diff options
author | Ferass El Hafidi <vitali64pmemail@protonmail.com> | 2023-05-08 19:03:10 +0200 |
---|---|---|
committer | Ferass El Hafidi <vitali64pmemail@protonmail.com> | 2023-05-08 19:03:10 +0200 |
commit | f9ed707f171c8069e99e24e24c3da73d8b6f5716 (patch) | |
tree | 4da9838d387c8bc260e83f3f51f5dfa83e0b48ae /plat | |
download | amlogic-bl2-master.tar.gz |
Diffstat (limited to 'plat')
106 files changed, 21423 insertions, 0 deletions
diff --git a/plat/common/aarch64/plat_common.c b/plat/common/aarch64/plat_common.c new file mode 100644 index 0000000..2abf29d --- /dev/null +++ b/plat/common/aarch64/plat_common.c @@ -0,0 +1,49 @@ +/* + * 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 <xlat_tables.h> + +/* + * The following 2 platform setup functions are weakly defined. They + * provide typical implementations that may be re-used by multiple + * platforms but may also be overridden by a platform if required. + */ +#pragma weak bl31_plat_enable_mmu +#pragma weak bl32_plat_enable_mmu + +void bl31_plat_enable_mmu() +{ + enable_mmu_el3(); +} + +void bl32_plat_enable_mmu() +{ + enable_mmu_el1(); +} diff --git a/plat/common/aarch64/platform_helpers.S b/plat/common/aarch64/platform_helpers.S new file mode 100644 index 0000000..f6ac13e --- /dev/null +++ b/plat/common/aarch64/platform_helpers.S @@ -0,0 +1,81 @@ +/* + * 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 <platform_def.h> + + + .weak platform_get_core_pos + .weak platform_is_primary_cpu + .weak platform_check_mpidr + .weak plat_report_exception + + /* ----------------------------------------------------- + * int platform_get_core_pos(int mpidr); + * With this function: CorePos = (ClusterId * 4) + + * CoreId + * ----------------------------------------------------- + */ +func platform_get_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret + + /* ----------------------------------------------------- + * void platform_is_primary_cpu (unsigned int mpid); + * + * Given the mpidr say whether this cpu is the primary + * cpu (applicable ony after a cold boot) + * ----------------------------------------------------- + */ +func platform_is_primary_cpu + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #PRIMARY_CPU + cset x0, eq + ret + + /* ----------------------------------------------------- + * Placeholder function which should be redefined by + * each platform. + * ----------------------------------------------------- + */ +func platform_check_mpidr + mov x0, xzr + ret + + /* ----------------------------------------------------- + * Placeholder function which should be redefined by + * each platform. + * ----------------------------------------------------- + */ +func plat_report_exception + ret diff --git a/plat/common/aarch64/platform_mp_stack.S b/plat/common/aarch64/platform_mp_stack.S new file mode 100644 index 0000000..801ec7f --- /dev/null +++ b/plat/common/aarch64/platform_mp_stack.S @@ -0,0 +1,102 @@ +/* + * 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.h> +#include <asm_macros.S> +#include <platform_def.h> + + + .local pcpu_dv_mem_stack + .local platform_normal_stacks + .weak platform_set_stack + .weak platform_get_stack + .weak platform_set_coherent_stack + + + /* ----------------------------------------------------- + * void platform_set_coherent_stack (unsigned long mpidr) + * + * For a given CPU, this function sets the stack pointer + * to a stack allocated in device memory. This stack can + * be used by C code which enables/disables the SCTLR.M + * SCTLR.C bit e.g. while powering down a cpu + * ----------------------------------------------------- + */ +func platform_set_coherent_stack + mov x5, x30 // lr + get_mp_stack pcpu_dv_mem_stack, PCPU_DV_MEM_STACK_SIZE + mov sp, x0 + ret x5 + + /* ----------------------------------------------------- + * unsigned long platform_get_stack (unsigned long mpidr) + * + * For a given CPU, this function returns the stack + * pointer for a stack allocated in device memory. + * ----------------------------------------------------- + */ +func platform_get_stack + mov x10, x30 // lr + get_mp_stack platform_normal_stacks, PLATFORM_STACK_SIZE + ret x10 + + /* ----------------------------------------------------- + * void platform_set_stack (unsigned long mpidr) + * + * For a given CPU, this function sets the stack pointer + * to a stack allocated in normal memory. + * ----------------------------------------------------- + */ +func platform_set_stack + mov x9, x30 // lr + bl platform_get_stack + mov sp, x0 + ret x9 + + /* ----------------------------------------------------- + * Per-cpu stacks in normal memory. + * Used for C code during runtime execution (when coherent + * stacks are not required). + * Each cpu gets a stack of PLATFORM_STACK_SIZE bytes. + * ----------------------------------------------------- + */ +declare_stack platform_normal_stacks, tzfw_normal_stacks, \ + PLATFORM_STACK_SIZE, PLATFORM_CORE_COUNT + + /* ----------------------------------------------------- + * Per-cpu stacks in device memory. + * Used for C code just before power down or right after + * power up when the MMU or caches need to be turned on + * or off. + * Each cpu gets a stack of PCPU_DV_MEM_STACK_SIZE bytes. + * ----------------------------------------------------- + */ +declare_stack pcpu_dv_mem_stack, tzfw_coherent_mem, \ + PCPU_DV_MEM_STACK_SIZE, PLATFORM_CORE_COUNT diff --git a/plat/common/aarch64/platform_up_stack.S b/plat/common/aarch64/platform_up_stack.S new file mode 100644 index 0000000..45a96a6 --- /dev/null +++ b/plat/common/aarch64/platform_up_stack.S @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <arch.h> +#include <asm_macros.S> +#include <platform_def.h> + + + .local pcpu_dv_mem_stack + .local platform_normal_stacks + .globl platform_set_stack + .globl platform_get_stack + .globl platform_set_coherent_stack + + + /* ----------------------------------------------------- + * void platform_set_coherent_stack (unsigned long) + * + * For cold-boot BL images, only the primary CPU needs a + * stack. This function sets the stack pointer to a stack + * allocated in device memory. + * ----------------------------------------------------- + */ +func platform_set_coherent_stack + get_up_stack pcpu_dv_mem_stack, PCPU_DV_MEM_STACK_SIZE + mov sp, x0 + ret + + + /* ----------------------------------------------------- + * unsigned long platform_get_stack (unsigned long) + * + * For cold-boot BL images, only the primary CPU needs a + * stack. This function returns the stack pointer for a + * stack allocated in device memory. + * ----------------------------------------------------- + */ +func platform_get_stack + get_up_stack platform_normal_stacks, PLATFORM_STACK_SIZE + ret + + /* ----------------------------------------------------- + * void platform_set_stack (unsigned long) + * + * For cold-boot BL images, only the primary CPU needs a + * stack. This function sets the stack pointer to a stack + * allocated in normal memory. + * ----------------------------------------------------- + */ +func platform_set_stack + get_up_stack platform_normal_stacks, PLATFORM_STACK_SIZE + mov sp, x0 + ret + + /* ----------------------------------------------------- + * Single cpu stack in normal memory. + * Used for C code during boot, PLATFORM_STACK_SIZE bytes + * are allocated + * ----------------------------------------------------- + */ +declare_stack platform_normal_stacks, tzfw_normal_stacks, \ + PLATFORM_STACK_SIZE, 1 + + /* ----------------------------------------------------- + * Single cpu stack in device/coherent memory. + * PCPU_DV_MEM_STACK_SIZE bytes are allocated. + * ----------------------------------------------------- + */ +declare_stack pcpu_dv_mem_stack, tzfw_coherent_mem, \ + PCPU_DV_MEM_STACK_SIZE, 1 diff --git a/plat/fvp/aarch64/fvp_common.c b/plat/fvp/aarch64/fvp_common.c new file mode 100644 index 0000000..3a07844 --- /dev/null +++ b/plat/fvp/aarch64/fvp_common.c @@ -0,0 +1,251 @@ +/* + * 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 <arch_helpers.h> +#include <assert.h> +#include <bl_common.h> +#include <cci400.h> +#include <debug.h> +#include <mmio.h> +#include <platform.h> +#include <xlat_tables.h> +#include "../fvp_def.h" + +/******************************************************************************* + * 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 fvp_config[CONFIG_LIMIT]; + +/* + * Table of regions to map using the MMU. + * This doesn't include TZRAM as the 'mem_layout' argument passed to + * configure_mmu_elx() will give the available subset of that, + */ +const mmap_region_t fvp_mmap[] = { + { TZROM_BASE, TZROM_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, + { TZDRAM_BASE, TZDRAM_SIZE, MT_MEMORY | MT_RW | MT_SECURE }, + { FLASH0_BASE, FLASH0_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, + { FLASH1_BASE, FLASH1_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, + { VRAM_BASE, VRAM_SIZE, MT_MEMORY | MT_RW | MT_SECURE }, + { DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + { NSRAM_BASE, NSRAM_SIZE, MT_MEMORY | MT_RW | MT_NS }, + { DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + /* 2nd GB as device for now...*/ + { 0x40000000, 0x40000000, MT_DEVICE | MT_RW | MT_SECURE }, + { DRAM1_BASE, DRAM1_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 fvp_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_size, \ + MT_MEMORY | MT_RW | MT_SECURE); \ + mmap_add_region(ro_start, ro_limit - ro_start, \ + MT_MEMORY | MT_RO | MT_SECURE); \ + mmap_add_region(coh_start, coh_limit - coh_start, \ + MT_DEVICE | MT_RW | MT_SECURE); \ + mmap_add(fvp_mmap); \ + init_xlat_tables(); \ + \ + enable_mmu_el##_el(); \ + } + +/* Define EL1 and EL3 variants of the function initialising the MMU */ +DEFINE_CONFIGURE_MMU_EL(1) +DEFINE_CONFIGURE_MMU_EL(3) + +/* Simple routine which returns a configuration variable value */ +unsigned long fvp_get_cfgvar(unsigned int var_id) +{ + assert(var_id < CONFIG_LIMIT); + return fvp_config[var_id]; +} + +/******************************************************************************* + * A single boot loader stack is expected to work on both the Foundation FVP + * models and the two flavours of the Base FVP models (AEMv8 & Cortex). The + * SYS_ID register provides a mechanism for detecting the differences between + * these platforms. This information is stored in a per-BL array to allow the + * code to take the correct path.Per BL platform configuration. + ******************************************************************************/ +int fvp_config_setup(void) +{ + unsigned int rev, hbi, bld, arch, sys_id, midr_pn; + + sys_id = mmio_read_32(VE_SYSREGS_BASE + V2M_SYS_ID); + rev = (sys_id >> SYS_ID_REV_SHIFT) & SYS_ID_REV_MASK; + hbi = (sys_id >> SYS_ID_HBI_SHIFT) & SYS_ID_HBI_MASK; + bld = (sys_id >> SYS_ID_BLD_SHIFT) & SYS_ID_BLD_MASK; + arch = (sys_id >> SYS_ID_ARCH_SHIFT) & SYS_ID_ARCH_MASK; + + if ((rev != REV_FVP) || (arch != ARCH_MODEL)) + panic(); + + /* + * The build field in the SYS_ID tells which variant of the GIC + * memory is implemented by the model. + */ + switch (bld) { + case BLD_GIC_VE_MMAP: + fvp_config[CONFIG_GICD_ADDR] = VE_GICD_BASE; + fvp_config[CONFIG_GICC_ADDR] = VE_GICC_BASE; + fvp_config[CONFIG_GICH_ADDR] = VE_GICH_BASE; + fvp_config[CONFIG_GICV_ADDR] = VE_GICV_BASE; + break; + case BLD_GIC_A53A57_MMAP: + fvp_config[CONFIG_GICD_ADDR] = BASE_GICD_BASE; + fvp_config[CONFIG_GICC_ADDR] = BASE_GICC_BASE; + fvp_config[CONFIG_GICH_ADDR] = BASE_GICH_BASE; + fvp_config[CONFIG_GICV_ADDR] = BASE_GICV_BASE; + break; + default: + assert(0); + } + + /* + * The hbi field in the SYS_ID is 0x020 for the Base FVP & 0x010 + * for the Foundation FVP. + */ + switch (hbi) { + case HBI_FOUNDATION: + fvp_config[CONFIG_MAX_AFF0] = 4; + fvp_config[CONFIG_MAX_AFF1] = 1; + fvp_config[CONFIG_CPU_SETUP] = 0; + fvp_config[CONFIG_BASE_MMAP] = 0; + fvp_config[CONFIG_HAS_CCI] = 0; + fvp_config[CONFIG_HAS_TZC] = 0; + break; + case HBI_FVP_BASE: + midr_pn = (read_midr() >> MIDR_PN_SHIFT) & MIDR_PN_MASK; + if ((midr_pn == MIDR_PN_A57) || (midr_pn == MIDR_PN_A53)) + fvp_config[CONFIG_CPU_SETUP] = 1; + else + fvp_config[CONFIG_CPU_SETUP] = 0; + + fvp_config[CONFIG_MAX_AFF0] = 4; + fvp_config[CONFIG_MAX_AFF1] = 2; + fvp_config[CONFIG_BASE_MMAP] = 1; + fvp_config[CONFIG_HAS_CCI] = 1; + fvp_config[CONFIG_HAS_TZC] = 1; + break; + default: + assert(0); + } + + return 0; +} + +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 */ + assert(counter_base_frequency != 0); + + return counter_base_frequency; +} + +void fvp_cci_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 = fvp_get_cfgvar(CONFIG_HAS_CCI); + if (cci_setup) + cci_enable_coherency(read_mpidr()); +} + + +/******************************************************************************* + * Set SPSR and secure state for BL32 image + ******************************************************************************/ +void fvp_set_bl32_ep_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; +} + +/******************************************************************************* + * Set SPSR and secure state for BL33 image + ******************************************************************************/ +void fvp_set_bl33_ep_info(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); +} diff --git a/plat/fvp/aarch64/fvp_helpers.S b/plat/fvp/aarch64/fvp_helpers.S new file mode 100644 index 0000000..f856f46 --- /dev/null +++ b/plat/fvp/aarch64/fvp_helpers.S @@ -0,0 +1,186 @@ +/* + * 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 <gic_v2.h> +#include "../drivers/pwrc/fvp_pwrc.h" +#include "../fvp_def.h" + + .globl platform_get_entrypoint + .globl plat_secondary_cold_boot_setup + .globl platform_mem_init + .globl plat_report_exception + + .macro fvp_choose_gicmmap param1, param2, x_tmp, w_tmp, res + ldr \x_tmp, =VE_SYSREGS_BASE + V2M_SYS_ID + ldr \w_tmp, [\x_tmp] + ubfx \w_tmp, \w_tmp, #SYS_ID_BLD_SHIFT, #SYS_ID_BLD_LENGTH + cmp \w_tmp, #BLD_GIC_VE_MMAP + csel \res, \param1, \param2, eq + .endm + + /* ----------------------------------------------------- + * 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. + * TODO: Should we read the PSYS register to make sure + * that the request has gone through. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + /* --------------------------------------------- + * Power down this cpu. + * TODO: Do we need to worry about powering the + * cluster down as well here. That will need + * locks which we won't have unless an elf- + * loader zeroes out the zi section. + * --------------------------------------------- + */ + mrs x0, mpidr_el1 + ldr x1, =PWRC_BASE + str w0, [x1, #PPOFFR_OFF] + + /* --------------------------------------------- + * Deactivate the gic cpu interface as well + * --------------------------------------------- + */ + ldr x0, =VE_GICC_BASE + ldr x1, =BASE_GICC_BASE + fvp_choose_gicmmap x0, x1, x2, w2, x1 + mov w0, #(IRQ_BYP_DIS_GRP1 | FIQ_BYP_DIS_GRP1) + orr w0, w0, #(IRQ_BYP_DIS_GRP0 | FIQ_BYP_DIS_GRP0) + str w0, [x1, #GICC_CTLR] + + /* --------------------------------------------- + * There is no sane reason to come out of this + * wfi so panic if we do. This cpu will be pow- + * ered on and reset by the cpu_on pm api + * --------------------------------------------- + */ + dsb sy + wfi +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 + * ----------------------------------------------------- + */ +func platform_get_entrypoint + 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 + * ----------------------------------------------------- + */ +func platform_mem_init + ldr x0, =TZDRAM_BASE + MBOX_OFF + mov w1, #PLATFORM_CORE_COUNT +loop: + str xzr, [x0], #CACHE_WRITEBACK_GRANULE + subs w1, w1, #1 + b.gt loop + ret + + /* --------------------------------------------- + * 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 + * --------------------------------------------- + */ +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 diff --git a/plat/fvp/bl1_fvp_setup.c b/plat/fvp/bl1_fvp_setup.c new file mode 100644 index 0000000..f758082 --- /dev/null +++ b/plat/fvp/bl1_fvp_setup.c @@ -0,0 +1,152 @@ +/* + * 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 <mmio.h> +#include <platform.h> +#include <platform_def.h> +#include "fvp_def.h" +#include "fvp_private.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_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 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; + + /* Initialize the console to provide early debug support */ + console_init(PL011_UART0_BASE); + + /* + * 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 platform config for future decision making */ + fvp_config_setup(); +} + +/******************************************************************************* + * 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 */ + fvp_io_setup(); +} + + +/******************************************************************************* + * 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) +{ + fvp_cci_setup(); + + fvp_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 FVP we are only setting the security state, entrypoint + ******************************************************************************/ +void bl1_plat_set_bl2_ep_info(image_info_t *bl2_image, + entry_point_info_t *bl2_ep) +{ + SET_SECURITY_STATE(bl2_ep->h.attr, SECURE); + bl2_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); +} diff --git a/plat/fvp/bl2_fvp_setup.c b/plat/fvp/bl2_fvp_setup.c new file mode 100644 index 0000000..72580f9 --- /dev/null +++ b/plat/fvp/bl2_fvp_setup.c @@ -0,0 +1,298 @@ +/* + * 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 <platform.h> +#include <platform_def.h> +#include <string.h> +#include "fvp_def.h" +#include "fvp_private.h" + +/******************************************************************************* + * Declarations of linker defined symbols which will help us find the layout + * of trusted SRAM + ******************************************************************************/ +extern unsigned long __RO_START__; +extern unsigned long __RO_END__; + +extern unsigned long __COHERENT_RAM_START__; +extern unsigned long __COHERENT_RAM_END__; + +/* + * The next 2 constants identify the extents of the code & RO data region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses. + */ +#define 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_t bl2_tzram_layout +__attribute__ ((aligned(PLATFORM_CACHE_LINE_SIZE), + section("tzfw_coherent_mem"))); + +/******************************************************************************* + * Reference to structures which holds the arguments which need to be passed + * to BL31 + ******************************************************************************/ +static bl31_params_t *bl2_to_bl31_params; +static entry_point_info_t *bl31_ep_info; + +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) +{ + bl2_to_bl31_params_mem_t *bl31_params_mem; + +#if TSP_RAM_LOCATION_ID == TSP_IN_TZDRAM + /* + * Ensure that the secure DRAM memory used for passing BL31 arguments + * does not overlap with the BL32_BASE. + */ + assert(BL32_BASE > PARAMS_BASE + sizeof(bl2_to_bl31_params_mem_t)); +#endif + + /* + * Allocate the memory for all the arguments that needs to + * be passed to BL31 + */ + bl31_params_mem = (bl2_to_bl31_params_mem_t *)PARAMS_BASE; + memset((void *)PARAMS_BASE, 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 BL31 related information */ + bl31_ep_info = &bl31_params_mem->bl31_ep_info; + 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 BL32 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); + } + + /* Fill BL33 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); + 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_ep_info->args.arg1 = FVP_BL31_PLAT_PARAM_VAL; +#endif + return bl31_ep_info; +} + + +/******************************************************************************* + * 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_t *mem_layout) +{ + /* Initialize the console to provide early debug support */ + console_init(PL011_UART0_BASE); + + /* 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; + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); +} + +/******************************************************************************* + * Perform platform specific setup. For now just initialize the memory location + * to use for passing arguments to BL31. + ******************************************************************************/ +void bl2_platform_setup(void) +{ + /* + * Do initial security configuration to allow DRAM/device access. On + * Base FVP only DRAM security is programmable (via TrustZone), but + * other platforms might have more programmable security devices + * present. + */ + fvp_security_setup(); + + /* Initialise the IO layer and register platform IO devices */ + fvp_io_setup(); +} + +/* Flush the TF params and the TF plat params */ +void bl2_plat_flush_bl31_params(void) +{ + flush_dcache_range((unsigned long)PARAMS_BASE, \ + 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() +{ + fvp_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); +} + +/******************************************************************************* + * 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 FVP 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 FVP 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) +{ + fvp_set_bl32_ep_info(bl32_ep_info); +} + +/******************************************************************************* + * 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 FVP 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) +{ + fvp_set_bl33_ep_info(bl33_ep_info); +} + + +/******************************************************************************* + * Populate the extents of memory available for loading BL32 + ******************************************************************************/ +void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo) +{ + /* + * Populate the extents of memory available for loading BL32. + */ + 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; + bl32_meminfo->attr = BOT_LOAD; + bl32_meminfo->next = 0; +} + + +/******************************************************************************* + * Populate the extents of memory available for loading BL33 + ******************************************************************************/ +void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo) +{ + bl33_meminfo->total_base = DRAM_BASE; + bl33_meminfo->total_size = DRAM_SIZE - DRAM1_SEC_SIZE; + bl33_meminfo->free_base = DRAM_BASE; + bl33_meminfo->free_size = DRAM_SIZE - DRAM1_SEC_SIZE; + bl33_meminfo->attr = 0; + bl33_meminfo->attr = 0; +} diff --git a/plat/fvp/bl31_fvp_setup.c b/plat/fvp/bl31_fvp_setup.c new file mode 100644 index 0000000..6554ec3 --- /dev/null +++ b/plat/fvp/bl31_fvp_setup.c @@ -0,0 +1,257 @@ +/* + * 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 <arch_helpers.h> +#include <assert.h> +#include <bl_common.h> +#include <bl31.h> +#include <console.h> +#include <mmio.h> +#include <platform.h> +#include <stddef.h> +#include "drivers/pwrc/fvp_pwrc.h" +#include "fvp_def.h" +#include "fvp_private.h" + +/******************************************************************************* + * Declarations of linker defined symbols which will help us find the layout + * of trusted SRAM + ******************************************************************************/ +extern unsigned long __RO_START__; +extern unsigned long __RO_END__; + +extern unsigned long __COHERENT_RAM_START__; +extern unsigned long __COHERENT_RAM_END__; + +/* + * The next 2 constants identify the extents of the code & RO data region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses. + */ +#define 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__) + + +#if RESET_TO_BL31 +static entry_point_info_t bl32_entrypoint_info; +static entry_point_info_t bl33_entrypoint_info; +#else +/******************************************************************************* + * Reference to structure which holds the arguments that have been passed to + * BL31 from BL2. + ******************************************************************************/ +static bl31_params_t *bl2_to_bl31_params; +#endif + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for the + * security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + +#if RESET_TO_BL31 + + if (type == NON_SECURE) + fvp_get_entry_point_info(NON_SECURE, &bl33_entrypoint_info); + else + fvp_get_entry_point_info(SECURE, &bl32_entrypoint_info); + + next_image_info = (type == NON_SECURE) ? + &bl33_entrypoint_info : + &bl32_entrypoint_info; +#else + next_image_info = (type == NON_SECURE) ? + bl2_to_bl31_params->bl33_ep_info : + bl2_to_bl31_params->bl32_ep_info; +#endif + + + /* 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 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_params_t *from_bl2, + void *plat_params_from_bl2) +{ + /* Initialize the console to provide early debug support */ + console_init(PL011_UART0_BASE); + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); + +#if RESET_TO_BL31 + /* There are no parameters from BL2 if BL31 is a reset vector */ + assert(from_bl2 == NULL); + assert(plat_params_from_bl2 == NULL); + + + /* + * Do initial security configuration to allow DRAM/device access. On + * Base FVP only DRAM security is programmable (via TrustZone), but + * other platforms might have more programmable security devices + * present. + */ + fvp_security_setup(); +#else + /* Check params passed from BL2 should not be NULL, + * We are not checking plat_params_from_bl2 as NULL as we are not + * using it on FVP + */ + assert(from_bl2 != NULL); + assert(from_bl2->h.type == PARAM_BL31); + assert(from_bl2->h.version >= VERSION_1); + + bl2_to_bl31_params = from_bl2; + assert(((unsigned long)plat_params_from_bl2) == FVP_BL31_PLAT_PARAM_VAL); +#endif +} + +/******************************************************************************* + * Initialize the gic, configure the CLCD and zero out variables needed by the + * secondaries to boot up correctly. + ******************************************************************************/ +void bl31_platform_setup() +{ + unsigned int reg_val; + + /* Initialize the gic cpu and distributor interfaces */ + gic_setup(); + + /* + * TODO: Configure the CLCD before handing control to + * linux. Need to see if a separate driver is needed + * instead. + */ + mmio_write_32(VE_SYSREGS_BASE + V2M_SYS_CFGDATA, 0); + mmio_write_32(VE_SYSREGS_BASE + V2M_SYS_CFGCTRL, + (1ull << 31) | (1 << 30) | (7 << 20) | (0 << 16)); + + /* 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(0), reg_val); + mmio_write_32(SYS_TIMCTL_BASE + CNTACR_BASE(1), reg_val); + + reg_val = (1 << CNTNSAR_NS_SHIFT(0)) | (1 << CNTNSAR_NS_SHIFT(1)); + mmio_write_32(SYS_TIMCTL_BASE + CNTNSAR, reg_val); + + /* Intialize the power controller */ + fvp_pwrc_setup(); + + /* Topologies are best known to the platform. */ + fvp_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() +{ +#if RESET_TO_BL31 + fvp_cci_setup(); + +#endif + fvp_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); +} + +#if RESET_TO_BL31 +/******************************************************************************* + * Generate the entry point info for Non Secure and Secure images + * for transferring control from BL31 + ******************************************************************************/ +void fvp_get_entry_point_info(unsigned long target_security, + entry_point_info_t *target_entry_info) +{ + if (target_security == NON_SECURE) { + SET_PARAM_HEAD(target_entry_info, + PARAM_EP, + VERSION_1, + 0); + /* + * Tell BL31 where the non-trusted software image + * is located and the entry state information + */ + target_entry_info->pc = plat_get_ns_image_entrypoint(); + + fvp_set_bl33_ep_info(target_entry_info); + + } else { + SET_PARAM_HEAD(target_entry_info, + PARAM_EP, + VERSION_1, + 0); + if (BL32_BASE != 0) { + /* Hard coding entry point to the base of the BL32 */ + target_entry_info->pc = BL32_BASE; + fvp_set_bl32_ep_info(target_entry_info); + } + } +} +#endif diff --git a/plat/fvp/bl32_fvp_setup.c b/plat/fvp/bl32_fvp_setup.c new file mode 100644 index 0000000..f8dc3c7 --- /dev/null +++ b/plat/fvp/bl32_fvp_setup.c @@ -0,0 +1,101 @@ +/* + * 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 <bl_common.h> +#include <console.h> +#include <platform.h> +#include "fvp_def.h" +#include "fvp_private.h" + +/******************************************************************************* + * Declarations of linker defined symbols which will help us find the layout + * of trusted SRAM + ******************************************************************************/ +extern unsigned long __RO_START__; +extern unsigned long __RO_END__; + +extern unsigned long __COHERENT_RAM_START__; +extern unsigned long __COHERENT_RAM_END__; + +/* + * The next 2 constants identify the extents of the code & RO data region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses. + */ +#define BL32_RO_BASE (unsigned long)(&__RO_START__) +#define BL32_RO_LIMIT (unsigned long)(&__RO_END__) + +/* + * The next 2 constants identify the extents of the coherent memory region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to + * page-aligned addresses. + */ +#define BL32_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) +#define BL32_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) + +/******************************************************************************* + * Initialize the UART + ******************************************************************************/ +void bl32_early_platform_setup(void) +{ + /* + * Initialize a different console than already in use to display + * messages from TSP + */ + console_init(PL011_UART1_BASE); + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); +} + +/******************************************************************************* + * Perform platform specific setup placeholder + ******************************************************************************/ +void bl32_platform_setup() +{ + +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the MMU + ******************************************************************************/ +void bl32_plat_arch_setup() +{ + fvp_configure_mmu_el1(BL32_RO_BASE, + (BL32_COHERENT_RAM_LIMIT - BL32_RO_BASE), + BL32_RO_BASE, + BL32_RO_LIMIT, + BL32_COHERENT_RAM_BASE, + BL32_COHERENT_RAM_LIMIT); +} diff --git a/plat/fvp/drivers/pwrc/fvp_pwrc.c b/plat/fvp/drivers/pwrc/fvp_pwrc.c new file mode 100644 index 0000000..d1feece --- /dev/null +++ b/plat/fvp/drivers/pwrc/fvp_pwrc.c @@ -0,0 +1,107 @@ +/* + * 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 <bakery_lock.h> +#include <mmio.h> +#include "../../fvp_def.h" +#include "fvp_pwrc.h" + +/* + * TODO: Someday there will be a generic power controller api. At the moment + * each platform has its own pwrc so just exporting functions is fine. + */ +static bakery_lock_t pwrc_lock __attribute__ ((section("tzfw_coherent_mem"))); + +unsigned int fvp_pwrc_get_cpu_wkr(unsigned long mpidr) +{ + unsigned int rc = 0; + bakery_lock_get(mpidr, &pwrc_lock); + mmio_write_32(PWRC_BASE + PSYSR_OFF, (unsigned int) mpidr); + rc = PSYSR_WK(mmio_read_32(PWRC_BASE + PSYSR_OFF)); + bakery_lock_release(mpidr, &pwrc_lock); + return rc; +} + +unsigned int fvp_pwrc_read_psysr(unsigned long mpidr) +{ + unsigned int rc = 0; + bakery_lock_get(mpidr, &pwrc_lock); + mmio_write_32(PWRC_BASE + PSYSR_OFF, (unsigned int) mpidr); + rc = mmio_read_32(PWRC_BASE + PSYSR_OFF); + bakery_lock_release(mpidr, &pwrc_lock); + return rc; +} + +void fvp_pwrc_write_pponr(unsigned long mpidr) +{ + bakery_lock_get(mpidr, &pwrc_lock); + mmio_write_32(PWRC_BASE + PPONR_OFF, (unsigned int) mpidr); + bakery_lock_release(mpidr, &pwrc_lock); +} + +void fvp_pwrc_write_ppoffr(unsigned long mpidr) +{ + bakery_lock_get(mpidr, &pwrc_lock); + mmio_write_32(PWRC_BASE + PPOFFR_OFF, (unsigned int) mpidr); + bakery_lock_release(mpidr, &pwrc_lock); +} + +void fvp_pwrc_set_wen(unsigned long mpidr) +{ + bakery_lock_get(mpidr, &pwrc_lock); + mmio_write_32(PWRC_BASE + PWKUPR_OFF, + (unsigned int) (PWKUPR_WEN | mpidr)); + bakery_lock_release(mpidr, &pwrc_lock); +} + +void fvp_pwrc_clr_wen(unsigned long mpidr) +{ + bakery_lock_get(mpidr, &pwrc_lock); + mmio_write_32(PWRC_BASE + PWKUPR_OFF, + (unsigned int) mpidr); + bakery_lock_release(mpidr, &pwrc_lock); +} + +void fvp_pwrc_write_pcoffr(unsigned long mpidr) +{ + bakery_lock_get(mpidr, &pwrc_lock); + mmio_write_32(PWRC_BASE + PCOFFR_OFF, (unsigned int) mpidr); + bakery_lock_release(mpidr, &pwrc_lock); +} + +/* Nothing else to do here apart from initializing the lock */ +int fvp_pwrc_setup(void) +{ + bakery_lock_init(&pwrc_lock); + return 0; +} + + + diff --git a/plat/fvp/drivers/pwrc/fvp_pwrc.h b/plat/fvp/drivers/pwrc/fvp_pwrc.h new file mode 100644 index 0000000..ad1ea85 --- /dev/null +++ b/plat/fvp/drivers/pwrc/fvp_pwrc.h @@ -0,0 +1,77 @@ +/* + * 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 __FVP_PWRC_H__ +#define __FVP_PWRC_H__ + +/* FVP Power controller register offset etc */ +#define PPOFFR_OFF 0x0 +#define PPONR_OFF 0x4 +#define PCOFFR_OFF 0x8 +#define PWKUPR_OFF 0xc +#define PSYSR_OFF 0x10 + +#define PWKUPR_WEN (1ull << 31) + +#define PSYSR_AFF_L2 (1 << 31) +#define PSYSR_AFF_L1 (1 << 30) +#define PSYSR_AFF_L0 (1 << 29) +#define PSYSR_WEN (1 << 28) +#define PSYSR_PC (1 << 27) +#define PSYSR_PP (1 << 26) + +#define PSYSR_WK_SHIFT 24 +#define PSYSR_WK_MASK 0x3 +#define PSYSR_WK(x) (x >> PSYSR_WK_SHIFT) & PSYSR_WK_MASK + +#define WKUP_COLD 0x0 +#define WKUP_RESET 0x1 +#define WKUP_PPONR 0x2 +#define WKUP_GICREQ 0x3 + +#define PSYSR_INVALID 0xffffffff + +#ifndef __ASSEMBLY__ + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ +int fvp_pwrc_setup(void); +void fvp_pwrc_write_pcoffr(unsigned long); +void fvp_pwrc_write_ppoffr(unsigned long); +void fvp_pwrc_write_pponr(unsigned long); +void fvp_pwrc_set_wen(unsigned long); +void fvp_pwrc_clr_wen(unsigned long); +unsigned int fvp_pwrc_read_psysr(unsigned long); +unsigned int fvp_pwrc_get_cpu_wkr(unsigned long); + +#endif /*__ASSEMBLY__*/ + +#endif /* __FVP_PWRC_H__ */ diff --git a/plat/fvp/fvp_def.h b/plat/fvp/fvp_def.h new file mode 100644 index 0000000..04ba611 --- /dev/null +++ b/plat/fvp/fvp_def.h @@ -0,0 +1,237 @@ +/* + * 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 __FVP_DEF_H__ +#define __FVP_DEF_H__ + +#include <platform_def.h> /* for TZROM_SIZE */ + + +/* Firmware Image Package */ +#define FIP_IMAGE_NAME "fip.bin" + +/* Constants for accessing platform configuration */ +#define CONFIG_GICD_ADDR 0 +#define CONFIG_GICC_ADDR 1 +#define CONFIG_GICH_ADDR 2 +#define CONFIG_GICV_ADDR 3 +#define CONFIG_MAX_AFF0 4 +#define CONFIG_MAX_AFF1 5 +/* Indicate whether the CPUECTLR SMP bit should be enabled. */ +#define CONFIG_CPU_SETUP 6 +#define CONFIG_BASE_MMAP 7 +/* Indicates whether CCI should be enabled on the platform. */ +#define CONFIG_HAS_CCI 8 +#define CONFIG_HAS_TZC 9 +#define CONFIG_LIMIT 10 + +/******************************************************************************* + * FVP memory map related constants + ******************************************************************************/ + +#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 + +#define MBOX_OFF 0x1000 + +/* Base address where parameters to BL31 are stored */ +#define PARAMS_BASE TZDRAM_BASE + +#define DRAM1_BASE 0x80000000ull +#define DRAM1_SIZE 0x80000000ull +#define DRAM1_END (DRAM1_BASE + DRAM1_SIZE - 1) +#define DRAM1_SEC_SIZE 0x01000000ull + +#define DRAM_BASE DRAM1_BASE +#define DRAM_SIZE DRAM1_SIZE + +#define DRAM2_BASE 0x880000000ull +#define DRAM2_SIZE 0x780000000ull +#define DRAM2_END (DRAM2_BASE + DRAM2_SIZE - 1) + +#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 +#define SYS_CNTREAD_BASE 0x2a800000 +#define SYS_TIMCTL_BASE 0x2a810000 + +/* V2M motherboard system registers & offsets */ +#define VE_SYSREGS_BASE 0x1c010000 +#define V2M_SYS_ID 0x0 +#define V2M_SYS_LED 0x8 +#define V2M_SYS_CFGDATA 0xa0 +#define V2M_SYS_CFGCTRL 0xa4 + +/* Load address of BL33 in the FVP port */ +#define NS_IMAGE_OFFSET (DRAM1_BASE + 0x8000000) /* DRAM + 128MB */ + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define FVP_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +/* + * 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 + +#define SYS_LED_SS_MASK 0x1 +#define SYS_LED_EL_MASK 0x3 +#define SYS_LED_EC_MASK 0x1f + +/* V2M sysid register bits */ +#define SYS_ID_REV_SHIFT 27 +#define SYS_ID_HBI_SHIFT 16 +#define SYS_ID_BLD_SHIFT 12 +#define SYS_ID_ARCH_SHIFT 8 +#define SYS_ID_FPGA_SHIFT 0 + +#define SYS_ID_REV_MASK 0xf +#define SYS_ID_HBI_MASK 0xfff +#define SYS_ID_BLD_MASK 0xf +#define SYS_ID_ARCH_MASK 0xf +#define SYS_ID_FPGA_MASK 0xff + +#define SYS_ID_BLD_LENGTH 4 + +#define REV_FVP 0x0 +#define HBI_FVP_BASE 0x020 +#define HBI_FOUNDATION 0x010 + +#define BLD_GIC_VE_MMAP 0x0 +#define BLD_GIC_A53A57_MMAP 0x1 + +#define ARCH_MODEL 0x1 + +/* FVP Power controller base address*/ +#define PWRC_BASE 0x1c100000 + + +/******************************************************************************* + * 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 + +/******************************************************************************* + * TrustZone address space controller related constants + ******************************************************************************/ +#define TZC400_BASE 0x2a4a0000 + +/* + * The NSAIDs for this platform as used to program the TZC400. + */ + +/* The FVP has 4 bits of NSAIDs. Used with TZC FAIL_ID (ACE Lite ID width) */ +#define FVP_AID_WIDTH 4 + +/* NSAIDs used by devices in TZC filter 0 on FVP */ +#define FVP_NSAID_DEFAULT 0 +#define FVP_NSAID_PCI 1 +#define FVP_NSAID_VIRTIO 8 /* from FVP v5.6 onwards */ +#define FVP_NSAID_AP 9 /* Application Processors */ +#define FVP_NSAID_VIRTIO_OLD 15 /* until FVP v5.5 */ + +/* NSAIDs used by devices in TZC filter 2 on FVP */ +#define FVP_NSAID_HDLCD0 2 +#define FVP_NSAID_CLCD 7 + + +#endif /* __FVP_DEF_H__ */ diff --git a/plat/fvp/fvp_gic.c b/plat/fvp/fvp_gic.c new file mode 100644 index 0000000..3156da9 --- /dev/null +++ b/plat/fvp/fvp_gic.c @@ -0,0 +1,408 @@ +/* + * 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 <gic_v2.h> +#include <gic_v3.h> +#include <interrupt_mgmt.h> +#include <platform.h> +#include <stdint.h> +#include "fvp_def.h" +#include "fvp_private.h" + +/******************************************************************************* + * 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); + isb(); /* ensure NS=1 takes effect before accessing ICC_SRE_EL2 */ + + /* + * 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); + isb(); /* commite ICC_* changes before setting NS=0 */ + + /* Restore SCR_EL3 */ + write_scr(scr_val); + isb(); /* ensure NS=0 takes effect immediately */ +} + +/******************************************************************************* + * 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 = fvp_get_cfgvar(CONFIG_GICD_ADDR); + gicc_base = fvp_get_cfgvar(CONFIG_GICC_ADDR); + + 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) +{ + uint32_t gicc_base = fvp_get_cfgvar(CONFIG_GICC_ADDR); + + assert(type == INTR_TYPE_S_EL1 || + type == INTR_TYPE_EL3 || + type == INTR_TYPE_NS); + + assert(security_state == NON_SECURE || security_state == SECURE); + + /* + * We ignore the security state parameter under the assumption that + * both normal and secure worlds are using ARM GICv2. This parameter + * will be used when the secure world starts using GICv3. + */ +#if FVP_GIC_ARCH == 2 + return gicv2_interrupt_type_to_line(gicc_base, type); +#else +#error "Invalid GIC architecture version specified for FVP port" +#endif +} + +#if FVP_GIC_ARCH == 2 +/******************************************************************************* + * 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() +{ + uint32_t id, gicc_base; + + gicc_base = fvp_get_cfgvar(CONFIG_GICC_ADDR); + 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() +{ + uint32_t id, gicc_base; + + gicc_base = fvp_get_cfgvar(CONFIG_GICC_ADDR); + 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() +{ + return gicc_read_IAR(fvp_get_cfgvar(CONFIG_GICC_ADDR)); +} + +/******************************************************************************* + * 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(fvp_get_cfgvar(CONFIG_GICC_ADDR), id); + return; +} + +/******************************************************************************* + * 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(fvp_get_cfgvar(CONFIG_GICD_ADDR), id); + + /* Assume that all secure interrupts are S-EL1 interrupts */ + if (group == GRP0) + return INTR_TYPE_S_EL1; + else + return INTR_TYPE_NS; +} + +#else +#error "Invalid GIC architecture version specified for FVP port" +#endif diff --git a/plat/fvp/fvp_io_storage.c b/plat/fvp/fvp_io_storage.c new file mode 100644 index 0000000..c32cca9 --- /dev/null +++ b/plat/fvp/fvp_io_storage.c @@ -0,0 +1,238 @@ +/* + * 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 <io_semihosting.h> +#include <semihosting.h> /* For FOPEN_MODE_... */ +#include <string.h> +#include "fvp_def.h" + +/* IO devices */ +static io_plat_data_t io_data; +static const io_dev_connector_t *sh_dev_con; +static uintptr_t sh_dev_spec; +static uintptr_t sh_init_params; +static uintptr_t sh_dev_handle; +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 = FLASH0_BASE, + .length = FLASH0_SIZE +}; + +static const io_file_spec_t bl2_file_spec = { + .path = BL2_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 bl32_file_spec = { + .path = BL32_IMAGE_NAME, + .mode = FOPEN_MODE_RB +}; + +static const io_file_spec_t bl33_file_spec = { + .path = BL33_IMAGE_NAME, + .mode = FOPEN_MODE_RB +}; + +static int open_fip(const uintptr_t spec); +static int open_memmap(const uintptr_t spec); + +struct plat_io_policy { + 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 + }, { + BL31_IMAGE_NAME, + &fip_dev_handle, + (uintptr_t)&bl31_file_spec, + open_fip + }, { + BL32_IMAGE_NAME, + &fip_dev_handle, + (uintptr_t)&bl32_file_spec, + open_fip + }, { + BL33_IMAGE_NAME, + &fip_dev_handle, + (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; +} + + +static int open_semihosting(const uintptr_t spec) +{ + int result = IO_FAIL; + uintptr_t 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 fvp_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, 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; + } else { + result = open_semihosting( + policy->image_spec); + if (result == IO_SUCCESS) { + *dev_handle = sh_dev_handle; + *image_spec = + policy->image_spec; + } + } + } + policy++; + } + } else { + result = IO_FAIL; + } + return result; +} diff --git a/plat/fvp/fvp_pm.c b/plat/fvp/fvp_pm.c new file mode 100644 index 0000000..d702643 --- /dev/null +++ b/plat/fvp/fvp_pm.c @@ -0,0 +1,411 @@ +/* + * 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 <bakery_lock.h> +#include <cci400.h> +#include <mmio.h> +#include <platform.h> +#include <platform_def.h> +#include <psci.h> +#include "drivers/pwrc/fvp_pwrc.h" +#include "fvp_def.h" +#include "fvp_private.h" + +/******************************************************************************* + * FVP handler called when an affinity instance is about to enter standby. + ******************************************************************************/ +int fvp_affinst_standby(unsigned int power_state) +{ + unsigned int target_afflvl; + + /* Sanity check the requested state */ + target_afflvl = psci_get_pstate_afflvl(power_state); + + /* + * It's possible to enter standby only on affinity level 0 i.e. a cpu + * on the FVP. Ignore any other affinity level. + */ + if (target_afflvl != MPIDR_AFFLVL0) + return PSCI_E_INVALID_PARAMS; + + /* + * Enter standby state + * dsb is good practice before using wfi to enter low power states + */ + dsb(); + wfi(); + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * FVP handler called when an affinity instance is about to be turned on. The + * level and mpidr determine the affinity instance. + ******************************************************************************/ +int fvp_affinst_on(unsigned long mpidr, + unsigned long sec_entrypoint, + unsigned long ns_entrypoint, + unsigned int afflvl, + unsigned int state) +{ + int rc = PSCI_E_SUCCESS; + unsigned long linear_id; + mailbox_t *fvp_mboxes; + unsigned int psysr; + + /* + * It's possible to turn on only affinity level 0 i.e. a cpu + * on the FVP. Ignore any other affinity level. + */ + if (afflvl != MPIDR_AFFLVL0) + goto exit; + + /* + * Ensure that we do not cancel an inflight power off request + * for the target cpu. That would leave it in a zombie wfi. + * Wait for it to power off, program the jump address for the + * target cpu and then program the power controller to turn + * that cpu on + */ + do { + psysr = fvp_pwrc_read_psysr(mpidr); + } while (psysr & PSYSR_AFF_L0); + + linear_id = platform_get_core_pos(mpidr); + fvp_mboxes = (mailbox_t *) (TZDRAM_BASE + MBOX_OFF); + fvp_mboxes[linear_id].value = sec_entrypoint; + flush_dcache_range((unsigned long) &fvp_mboxes[linear_id], + sizeof(unsigned long)); + + fvp_pwrc_write_pponr(mpidr); + +exit: + return rc; +} + +/******************************************************************************* + * FVP handler called when an affinity instance is about to be turned off. The + * level and mpidr determine the affinity instance. The 'state' arg. allows the + * platform to decide whether the cluster is being turned off and take apt + * actions. + * + * CAUTION: This function is called with coherent stacks so that caches can be + * turned off, flushed and coherency disabled. There is no guarantee that caches + * will remain turned on across calls to this function as each affinity level is + * dealt with. So do not write & read global variables across calls. It will be + * wise to do flush a write to the global to prevent unpredictable results. + ******************************************************************************/ +int fvp_affinst_off(unsigned long mpidr, + unsigned int afflvl, + unsigned int state) +{ + int rc = PSCI_E_SUCCESS; + unsigned int gicc_base, ectlr; + unsigned long cpu_setup, cci_setup; + + switch (afflvl) { + case MPIDR_AFFLVL1: + if (state == PSCI_STATE_OFF) { + /* + * Disable coherency if this cluster is to be + * turned off + */ + cci_setup = fvp_get_cfgvar(CONFIG_HAS_CCI); + if (cci_setup) { + cci_disable_coherency(mpidr); + } + + /* + * Program the power controller to turn the + * cluster off + */ + fvp_pwrc_write_pcoffr(mpidr); + + } + break; + + case MPIDR_AFFLVL0: + if (state == PSCI_STATE_OFF) { + + /* + * Take this cpu out of intra-cluster coherency if + * the FVP flavour supports the SMP bit. + */ + cpu_setup = fvp_get_cfgvar(CONFIG_CPU_SETUP); + if (cpu_setup) { + ectlr = read_cpuectlr(); + ectlr &= ~CPUECTLR_SMP_BIT; + write_cpuectlr(ectlr); + } + + /* + * Prevent interrupts from spuriously waking up + * this cpu + */ + gicc_base = fvp_get_cfgvar(CONFIG_GICC_ADDR); + gic_cpuif_deactivate(gicc_base); + + /* + * Program the power controller to power this + * cpu off + */ + fvp_pwrc_write_ppoffr(mpidr); + } + break; + + default: + assert(0); + } + + return rc; +} + +/******************************************************************************* + * FVP handler called when an affinity instance is about to be suspended. The + * level and mpidr determine the affinity instance. The 'state' arg. allows the + * platform to decide whether the cluster is being turned off and take apt + * actions. + * + * CAUTION: This function is called with coherent stacks so that caches can be + * turned off, flushed and coherency disabled. There is no guarantee that caches + * will remain turned on across calls to this function as each affinity level is + * dealt with. So do not write & read global variables across calls. It will be + * wise to do flush a write to the global to prevent unpredictable results. + ******************************************************************************/ +int fvp_affinst_suspend(unsigned long mpidr, + unsigned long sec_entrypoint, + unsigned long ns_entrypoint, + unsigned int afflvl, + unsigned int state) +{ + int rc = PSCI_E_SUCCESS; + unsigned int gicc_base, ectlr; + unsigned long cpu_setup, cci_setup, linear_id; + mailbox_t *fvp_mboxes; + + switch (afflvl) { + case MPIDR_AFFLVL1: + if (state == PSCI_STATE_OFF) { + /* + * Disable coherency if this cluster is to be + * turned off + */ + cci_setup = fvp_get_cfgvar(CONFIG_HAS_CCI); + if (cci_setup) { + cci_disable_coherency(mpidr); + } + + /* + * Program the power controller to turn the + * cluster off + */ + fvp_pwrc_write_pcoffr(mpidr); + + } + break; + + case MPIDR_AFFLVL0: + if (state == PSCI_STATE_OFF) { + /* + * Take this cpu out of intra-cluster coherency if + * the FVP flavour supports the SMP bit. + */ + cpu_setup = fvp_get_cfgvar(CONFIG_CPU_SETUP); + if (cpu_setup) { + ectlr = read_cpuectlr(); + ectlr &= ~CPUECTLR_SMP_BIT; + write_cpuectlr(ectlr); + } + + /* Program the jump address for the target cpu */ + linear_id = platform_get_core_pos(mpidr); + fvp_mboxes = (mailbox_t *) (TZDRAM_BASE + MBOX_OFF); + fvp_mboxes[linear_id].value = sec_entrypoint; + flush_dcache_range((unsigned long) &fvp_mboxes[linear_id], + sizeof(unsigned long)); + + /* + * Prevent interrupts from spuriously waking up + * this cpu + */ + gicc_base = fvp_get_cfgvar(CONFIG_GICC_ADDR); + gic_cpuif_deactivate(gicc_base); + + /* + * Program the power controller to power this + * cpu off and enable wakeup interrupts. + */ + fvp_pwrc_set_wen(mpidr); + fvp_pwrc_write_ppoffr(mpidr); + } + break; + + default: + assert(0); + } + + return rc; +} + +/******************************************************************************* + * FVP 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. + ******************************************************************************/ +int fvp_affinst_on_finish(unsigned long mpidr, + unsigned int afflvl, + unsigned int state) +{ + int rc = PSCI_E_SUCCESS; + unsigned long linear_id, cpu_setup; + mailbox_t *fvp_mboxes; + unsigned int gicd_base, gicc_base, reg_val, ectlr; + + switch (afflvl) { + + case MPIDR_AFFLVL1: + /* Enable coherency if this cluster was off */ + if (state == PSCI_STATE_OFF) { + + /* + * This CPU might have woken up whilst the + * cluster was attempting to power down. In + * this case the FVP power controller will + * have a pending cluster power off request + * which needs to be cleared by writing to the + * PPONR register. This prevents the power + * controller from interpreting a subsequent + * entry of this cpu into a simple wfi as a + * power down request. + */ + fvp_pwrc_write_pponr(mpidr); + + fvp_cci_setup(); + } + break; + + case MPIDR_AFFLVL0: + /* + * Ignore the state passed for a cpu. It could only have + * been off if we are here. + */ + + /* + * Turn on intra-cluster coherency if the FVP flavour supports + * it. + */ + cpu_setup = fvp_get_cfgvar(CONFIG_CPU_SETUP); + if (cpu_setup) { + ectlr = read_cpuectlr(); + ectlr |= CPUECTLR_SMP_BIT; + write_cpuectlr(ectlr); + } + + /* + * Clear PWKUPR.WEN bit to ensure interrupts do not interfere + * with a cpu power down unless the bit is set again + */ + fvp_pwrc_clr_wen(mpidr); + + /* Zero the jump address in the mailbox for this cpu */ + fvp_mboxes = (mailbox_t *) (TZDRAM_BASE + MBOX_OFF); + linear_id = platform_get_core_pos(mpidr); + fvp_mboxes[linear_id].value = 0; + flush_dcache_range((unsigned long) &fvp_mboxes[linear_id], + sizeof(unsigned long)); + + gicd_base = fvp_get_cfgvar(CONFIG_GICD_ADDR); + gicc_base = fvp_get_cfgvar(CONFIG_GICC_ADDR); + + /* Enable the gic cpu interface */ + gic_cpuif_setup(gicc_base); + + /* TODO: This setup is needed only after a cold boot */ + gic_pcpu_distif_setup(gicd_base); + + /* 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(0), reg_val); + mmio_write_32(SYS_TIMCTL_BASE + CNTACR_BASE(1), reg_val); + + reg_val = (1 << CNTNSAR_NS_SHIFT(0)) | + (1 << CNTNSAR_NS_SHIFT(1)); + mmio_write_32(SYS_TIMCTL_BASE + CNTNSAR, reg_val); + + break; + + default: + assert(0); + } + + return rc; +} + +/******************************************************************************* + * FVP handler called when an affinity instance has just been powered on after + * having been suspended earlier. The level and mpidr determine the affinity + * instance. + * TODO: At the moment we reuse the on finisher and reinitialize the secure + * context. Need to implement a separate suspend finisher. + ******************************************************************************/ +int fvp_affinst_suspend_finish(unsigned long mpidr, + unsigned int afflvl, + unsigned int state) +{ + return fvp_affinst_on_finish(mpidr, afflvl, state); +} + + +/******************************************************************************* + * Export the platform handlers to enable psci to invoke them + ******************************************************************************/ +static const plat_pm_ops_t fvp_plat_pm_ops = { + fvp_affinst_standby, + fvp_affinst_on, + fvp_affinst_off, + fvp_affinst_suspend, + fvp_affinst_on_finish, + fvp_affinst_suspend_finish, +}; + +/******************************************************************************* + * Export the platform specific power ops & initialize the fvp power controller + ******************************************************************************/ +int platform_setup_pm(const plat_pm_ops_t **plat_ops) +{ + *plat_ops = &fvp_plat_pm_ops; + return 0; +} diff --git a/plat/fvp/fvp_private.h b/plat/fvp/fvp_private.h new file mode 100644 index 0000000..2331bb7 --- /dev/null +++ b/plat/fvp/fvp_private.h @@ -0,0 +1,109 @@ +/* + * 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 __FVP_PRIVATE_H__ +#define __FVP_PRIVATE_H__ + +#include <bl_common.h> +#include <platform_def.h> + + +typedef volatile struct mailbox { + unsigned long value + __attribute__((__aligned__(CACHE_WRITEBACK_GRANULE))); +} mailbox_t; + +/******************************************************************************* + * This structure represents the superset of information that is passed to + * BL31 e.g. while passing control to it from BL2 which is bl31_params + * and bl31_plat_params and its elements + ******************************************************************************/ +typedef struct bl2_to_bl31_params_mem { + bl31_params_t bl31_params; + image_info_t bl31_image_info; + image_info_t bl32_image_info; + image_info_t bl33_image_info; + entry_point_info_t bl33_ep_info; + entry_point_info_t bl32_ep_info; + entry_point_info_t bl31_ep_info; +} bl2_to_bl31_params_mem_t; + +/******************************************************************************* + * Forward declarations + ******************************************************************************/ +struct meminfo; + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ +void fvp_configure_mmu_el1(unsigned long total_base, + unsigned long total_size, + unsigned long, + unsigned long, + unsigned long, + unsigned long); +void fvp_configure_mmu_el3(unsigned long total_base, + unsigned long total_size, + unsigned long, + unsigned long, + unsigned long, + unsigned long); +unsigned long fvp_get_cfgvar(unsigned int); +int fvp_config_setup(void); + +#if RESET_TO_BL31 +void fvp_get_entry_point_info(unsigned long target_security, + struct entry_point_info *target_entry_info); +#endif +void fvp_cci_setup(void); + +/* Declarations for fvp_gic.c */ +void gic_cpuif_deactivate(unsigned int); +void gic_cpuif_setup(unsigned int); +void gic_pcpu_distif_setup(unsigned int); +void gic_setup(void); + +/* Declarations for fvp_topology.c */ +int fvp_setup_topology(void); + +/* Declarations for fvp_io_storage.c */ +void fvp_io_setup(void); + +/* Declarations for fvp_security.c */ +void fvp_security_setup(void); + +/* Sets the entrypoint for BL32 */ +void fvp_set_bl32_ep_info(struct entry_point_info *bl32_ep); + +/* Sets the entrypoint for BL33 */ +void fvp_set_bl33_ep_info(struct entry_point_info *bl33_ep); + + +#endif /* __FVP_PRIVATE_H__ */ diff --git a/plat/fvp/fvp_security.c b/plat/fvp/fvp_security.c new file mode 100644 index 0000000..76c4541 --- /dev/null +++ b/plat/fvp/fvp_security.c @@ -0,0 +1,136 @@ +/* + * 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 <tzc400.h> +#include "fvp_def.h" +#include "fvp_private.h" + +/* Used to improve readability for configuring regions. */ +#define FILTER_SHIFT(filter) (1 << filter) + +/* + * For the moment we assume that all security programming is done by the + * primary core. + * TODO: + * Might want to enable interrupt on violations when supported? + */ +void fvp_security_setup(void) +{ + tzc_instance_t controller; + + /* + * The Base FVP has a TrustZone address space controller, the Foundation + * FVP does not. Trying to program the device on the foundation FVP will + * cause an abort. + * + * If the platform had additional peripheral specific security + * configurations, those would be configured here. + */ + + if (!fvp_get_cfgvar(CONFIG_HAS_TZC)) + return; + + /* + * The TrustZone controller controls access to main DRAM. Give + * full NS access for the moment to use with OS. + */ + INFO("Configuring TrustZone Controller\n"); + + /* + * The driver does some error checking and will assert. + * - Provide base address of device on platform. + * - Provide width of ACE-Lite IDs on platform. + */ + controller.base = TZC400_BASE; + controller.aid_width = FVP_AID_WIDTH; + tzc_init(&controller); + + /* + * Currently only filters 0 and 2 are connected on Base FVP. + * Filter 0 : CPU clusters (no access to DRAM by default) + * Filter 1 : not connected + * Filter 2 : LCDs (access to VRAM allowed by default) + * Filter 3 : not connected + * Programming unconnected filters will have no effect at the + * moment. These filter could, however, be connected in future. + * So care should be taken not to configure the unused filters. + */ + + /* Disable all filters before programming. */ + tzc_disable_filters(&controller); + + /* + * Allow only non-secure access to all DRAM to supported devices. + * Give access to the CPUs and Virtio. Some devices + * would normally use the default ID so allow that too. We use + * two regions to cover the blocks of physical memory in the FVPs. + * + * Software executing in the secure state, such as a secure + * boot-loader, can access the DRAM by using the NS attributes in + * the MMU translation tables and descriptors. + */ + + /* Set to cover the first block of DRAM */ + tzc_configure_region(&controller, FILTER_SHIFT(0), 1, + DRAM1_BASE, DRAM1_END - DRAM1_SEC_SIZE, + TZC_REGION_S_NONE, + TZC_REGION_ACCESS_RDWR(FVP_NSAID_DEFAULT) | + TZC_REGION_ACCESS_RDWR(FVP_NSAID_PCI) | + TZC_REGION_ACCESS_RDWR(FVP_NSAID_AP) | + TZC_REGION_ACCESS_RDWR(FVP_NSAID_VIRTIO) | + TZC_REGION_ACCESS_RDWR(FVP_NSAID_VIRTIO_OLD)); + + /* Set to cover the secure reserved region */ + tzc_configure_region(&controller, FILTER_SHIFT(0), 3, + (DRAM1_END - DRAM1_SEC_SIZE) + 1 , DRAM1_END, + TZC_REGION_S_RDWR, + 0x0); + + /* Set to cover the second block of DRAM */ + tzc_configure_region(&controller, FILTER_SHIFT(0), 2, + DRAM2_BASE, DRAM2_END, TZC_REGION_S_NONE, + TZC_REGION_ACCESS_RDWR(FVP_NSAID_DEFAULT) | + TZC_REGION_ACCESS_RDWR(FVP_NSAID_PCI) | + TZC_REGION_ACCESS_RDWR(FVP_NSAID_AP) | + TZC_REGION_ACCESS_RDWR(FVP_NSAID_VIRTIO) | + TZC_REGION_ACCESS_RDWR(FVP_NSAID_VIRTIO_OLD)); + + /* + * TODO: Interrupts are not currently supported. The only + * options we have are for access errors to occur quietly or to + * cause an exception. We choose to cause an exception. + */ + tzc_set_action(&controller, TZC_ACTION_ERR); + + /* Enable filters. */ + tzc_enable_filters(&controller); +} diff --git a/plat/fvp/fvp_topology.c b/plat/fvp/fvp_topology.c new file mode 100644 index 0000000..cf21503 --- /dev/null +++ b/plat/fvp/fvp_topology.c @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <assert.h> +#include <platform_def.h> +/* TODO: Reusing psci error codes & state information. Get our own! */ +#include <psci.h> +#include "drivers/pwrc/fvp_pwrc.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 affinity_info { + unsigned char sibling; + unsigned char child; + unsigned char state; + unsigned int data; +} affinity_info_t; + +/******************************************************************************* + * 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_t fvp_aff1_topology_map[PLATFORM_CLUSTER_COUNT]; +static affinity_info_t 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 fvp_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; +} diff --git a/plat/fvp/include/plat_macros.S b/plat/fvp/include/plat_macros.S new file mode 100644 index 0000000..bdd402d --- /dev/null +++ b/plat/fvp/include/plat_macros.S @@ -0,0 +1,57 @@ +/* + * 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 <gic_v2.h> +#include "../fvp_def.h" + +.section .rodata.gic_reg_name, "aS" +gic_regs: .asciz "gic_iar", "gic_ctlr", "" + +/* Currently we have only 2 GIC registers to report */ +#define GIC_REG_SIZE (2 * 8) + /* --------------------------------------------- + * The below macro prints out relevant GIC + * registers whenever an unhandled exception is + * taken in BL31. + * --------------------------------------------- + */ + .macro plat_print_gic_regs + mov x0, #CONFIG_GICC_ADDR + bl fvp_get_cfgvar + /* gic base address is now in x0 */ + ldr w1, [x0, #GICC_IAR] + ldr w2, [x0, #GICD_CTLR] + sub sp, sp, #GIC_REG_SIZE + stp x1, x2, [sp] /* we store the gic registers as 64 bit */ + adr x0, gic_regs + mov x1, sp + bl print_string_value + add sp, sp, #GIC_REG_SIZE + .endm diff --git a/plat/fvp/include/platform_def.h b/plat/fvp/include/platform_def.h new file mode 100644 index 0000000..46a9f24 --- /dev/null +++ b/plat/fvp/include/platform_def.h @@ -0,0 +1,180 @@ +/* + * 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 + +/* Size of coherent stacks for debug and release builds */ +#if DEBUG +#define PCPU_DV_MEM_STACK_SIZE 0x400 +#else +#define PCPU_DV_MEM_STACK_SIZE 0x300 +#endif + +#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 */ +#define BL33_IMAGE_NAME "bl33.bin" /* e.g. UEFI */ + +#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 + +/* Location of trusted dram on the base fvp */ +#define TZDRAM_BASE 0x06000000 +#define TZDRAM_SIZE 0x02000000 + +/******************************************************************************* + * BL1 specific defines. + * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of + * 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 - 0xc000) +#define BL2_LIMIT (TZRAM_BASE + TZRAM_SIZE) + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +#define BL31_BASE (TZRAM_BASE + 0x6000) +#if TSP_RAM_LOCATION_ID == TSP_IN_TZRAM +#define BL31_LIMIT BL32_BASE +#elif TSP_RAM_LOCATION_ID == TSP_IN_TZDRAM +#define BL31_LIMIT BL2_BASE +#endif + +/******************************************************************************* + * BL32 specific defines. + ******************************************************************************/ +/* + * On FVP, the TSP can execute either from Trusted SRAM or Trusted DRAM. + */ +#define TSP_IN_TZRAM 0 +#define TSP_IN_TZDRAM 1 + +#if TSP_RAM_LOCATION_ID == TSP_IN_TZRAM +# define TSP_SEC_MEM_BASE TZRAM_BASE +# define TSP_SEC_MEM_SIZE TZRAM_SIZE +# define BL32_BASE (TZRAM_BASE + TZRAM_SIZE - 0x1c000) +# define BL32_LIMIT BL2_BASE +#elif TSP_RAM_LOCATION_ID == TSP_IN_TZDRAM +# define TSP_SEC_MEM_BASE TZDRAM_BASE +# define TSP_SEC_MEM_SIZE TZDRAM_SIZE +# define BL32_BASE (TZDRAM_BASE + 0x2000) +# define BL32_LIMIT (TZDRAM_BASE + (1 << 21)) +#else +# error "Unsupported TSP_RAM_LOCATION_ID value" +#endif + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define ADDR_SPACE_SIZE (1ull << 32) +#define MAX_XLAT_TABLES 3 +#define MAX_MMAP_REGIONS 16 + +/******************************************************************************* + * ID of the secure physical generic timer interrupt. + ******************************************************************************/ +#define IRQ_SEC_PHY_TIMER 29 + +/******************************************************************************* + * 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) + + +/******************************************************************************* + * Declarations and constants to access the mailboxes safely. Each mailbox is + * aligned on the biggest cache line size in the platform. This is known only + * to the platform as it might have a combination of integrated and external + * caches. Such alignment ensures that two maiboxes do not sit on the same cache + * line at any cache level. They could belong to different cpus/clusters & + * get written while being protected by different locks causing corruption of + * a valid mailbox address. + ******************************************************************************/ +#define CACHE_WRITEBACK_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + + +#endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/fvp/platform.mk b/plat/fvp/platform.mk new file mode 100644 index 0000000..4cc4d1e --- /dev/null +++ b/plat/fvp/platform.mk @@ -0,0 +1,94 @@ +# +# 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. +# + +# On FVP, the TSP can execute either from Trusted SRAM or Trusted DRAM. +# Trusted SRAM is the default. +TSP_RAM_LOCATION := tsram + +ifeq (${TSP_RAM_LOCATION}, tsram) + TSP_RAM_LOCATION_ID := TSP_IN_TZRAM +else ifeq (${TSP_RAM_LOCATION}, tdram) + TSP_RAM_LOCATION_ID := TSP_IN_TZDRAM +else + $(error "Unsupported TSP_RAM_LOCATION value") +endif + +# Process TSP_RAM_LOCATION_ID flag +$(eval $(call add_define,TSP_RAM_LOCATION_ID)) + +PLAT_INCLUDES := -Iplat/fvp/include/ + +PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/pl011.c \ + drivers/arm/pl011/pl011_console.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_semihosting.c \ + lib/mmio.c \ + lib/aarch64/sysreg_helpers.S \ + lib/aarch64/xlat_tables.c \ + lib/semihosting/semihosting.c \ + lib/semihosting/aarch64/semihosting_call.S \ + plat/common/aarch64/plat_common.c \ + plat/fvp/fvp_io_storage.c + +BL1_SOURCES += drivers/arm/cci400/cci400.c \ + plat/common/aarch64/platform_up_stack.S \ + plat/fvp/bl1_fvp_setup.c \ + plat/fvp/aarch64/fvp_common.c \ + plat/fvp/aarch64/fvp_helpers.S + +BL2_SOURCES += drivers/arm/tzc400/tzc400.c \ + plat/common/aarch64/platform_up_stack.S \ + plat/fvp/bl2_fvp_setup.c \ + plat/fvp/fvp_security.c \ + plat/fvp/aarch64/fvp_common.c + +BL31_SOURCES += drivers/arm/gic/gic_v2.c \ + drivers/arm/gic/gic_v3.c \ + drivers/arm/gic/aarch64/gic_v3_sysregs.S \ + drivers/arm/cci400/cci400.c \ + plat/common/aarch64/platform_mp_stack.S \ + plat/fvp/bl31_fvp_setup.c \ + plat/fvp/fvp_gic.c \ + plat/fvp/fvp_pm.c \ + plat/fvp/fvp_topology.c \ + plat/fvp/aarch64/fvp_helpers.S \ + plat/fvp/aarch64/fvp_common.c \ + plat/fvp/drivers/pwrc/fvp_pwrc.c + +ifeq (${RESET_TO_BL31}, 1) +BL31_SOURCES += drivers/arm/tzc400/tzc400.c \ + plat/fvp/fvp_security.c +endif + +# Flag used by the FVP port to determine the version of ARM GIC architecture +# to use for interrupt management in EL3. +FVP_GIC_ARCH := 2 +$(eval $(call add_define,FVP_GIC_ARCH)) diff --git a/plat/gxb/aarch64/bl1_plat_helpers.S b/plat/gxb/aarch64/bl1_plat_helpers.S new file mode 100644 index 0000000..97d04c3 --- /dev/null +++ b/plat/gxb/aarch64/bl1_plat_helpers.S @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <arch.h> +#include <asm_macros.S> +#include "../plat_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 + /* PLAT todo: Implement secondary CPU cold boot setup on PLAT */ +cb_panic: + b cb_panic + + + /* ----------------------------------------------------- + * void platform_get_entrypoint (unsigned int mpid); + * + * Main job of this routine is to distinguish between + * a cold and warm boot. + * On a cold boot the secondaries first wait for the + * platform to be initialized after which they are + * hotplugged in. The primary proceeds to perform the + * platform initialization. + * On a warm boot, each cpu jumps to the address in its + * mailbox. + * + * TODO: Not a good idea to save lr in a temp reg + * ----------------------------------------------------- + */ +func platform_get_entrypoint + mov x9, x30 // lr + bl platform_get_core_pos + ldr x1, =TRUSTED_MAILBOXES_BASE + lsl x0, x0, #TRUSTED_MAILBOX_SHIFT + ldr x0, [x1, x0] + ret x9 + + + /* ----------------------------------------------------- + * void platform_cold_boot_init (bl1_main function); + * + * Routine called only by the primary cpu after a cold + * boot to perform early platform initialization + * ----------------------------------------------------- + */ +func platform_cold_boot_init + mov x20, x0 + + /* --------------------------------------------- + * Give ourselves a small coherent stack to + * ease the pain of initializing the MMU and + * CCI in assembler + * --------------------------------------------- + */ + mrs x0, mpidr_el1 + bl platform_set_coherent_stack + + /* --------------------------------------------- + * Architectural init. can be generic e.g. + * enabling stack alignment and platform spec- + * ific e.g. MMU & page table setup as per the + * platform memory map. Perform the latter here + * and the former in bl1_main. + * --------------------------------------------- + */ + bl bl1_early_platform_setup + bl bl1_plat_arch_setup + + /* --------------------------------------------- + * Give ourselves a stack allocated in Normal + * -IS-WBWA memory + * --------------------------------------------- + */ + mrs x0, mpidr_el1 + bl platform_set_stack + + /* --------------------------------------------- + * Jump to the main function. Returning from it + * is a terminal error. + * --------------------------------------------- + */ + blr x20 + +cb_init_panic: + b cb_init_panic diff --git a/plat/gxb/aarch64/cache.S b/plat/gxb/aarch64/cache.S new file mode 100644 index 0000000..d80c716 --- /dev/null +++ b/plat/gxb/aarch64/cache.S @@ -0,0 +1,38 @@ +/* + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + * + * This file is based on sample code from ARMv8 ARM. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <arch.h> +#include <asm_macros.S> + + .global disable_mmu_el1 + .global disable_mmu_icache_el1 + +/* + * void disable_mmu_el1(void) + * + * disable mmu and dcache. + */ +func disable_mmu_el1 + mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT) +do_disable_mmu: + mrs x0, sctlr_el1 + bic x0, x0, x1 + msr sctlr_el1, x0 + isb // ensure MMU is off + mov x0, #DCCISW // DCache clean and invalidate + b dcsw_op_all + +/* + * void disable_mmu_icache_el1(void) + * + * disable mmu and dcache. + */ +func disable_mmu_icache_el1 + mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT) + b do_disable_mmu
\ No newline at end of file diff --git a/plat/gxb/aarch64/common.c b/plat/gxb/aarch64/common.c new file mode 100644 index 0000000..2982880 --- /dev/null +++ b/plat/gxb/aarch64/common.c @@ -0,0 +1,119 @@ +/* + * 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 <mmio.h> +#include <platform.h> +#include <platform_def.h> +#include <xlat_tables.h> +#include "../plat_def.h" +#include <runtime_svc.h> +#include <arch_helpers.h> +#include <asm/arch/watchdog.h> +#include <stdio.h> + +extern int console_puts(const char *s); +extern void console_put_hex(unsigned long data,unsigned int bitlen); + +#ifdef BL2_ENABLE_MMU +/* + * 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 plat_mmap[] = { + { MAILBOX_START, MAILBOX_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + { TZROM_BASE, TZROM_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, + { DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS }, + { SPI_BASE, SPI_SIZE, MT_MEMORY | MT_RW | MT_SECURE }, + { DEVICEC_BASE, DEVICEC_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + { DEVICED_BASE, DEVICED_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + { DEVICEE_BASE, DEVICEE_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + {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_size, \ + MT_MEMORY | MT_RW | MT_SECURE); \ + mmap_add_region(ro_start, ro_limit - ro_start, \ + MT_MEMORY | MT_RO | MT_SECURE); \ + mmap_add_region(coh_start, coh_limit - coh_start,\ + MT_DEVICE | MT_RW | MT_SECURE); \ + mmap_add(plat_mmap); \ + init_xlat_tables(); \ + \ + enable_mmu_el##_el(); \ + } + +/* Define EL1 and EL3 variants of the function initialising the MMU */ +DEFINE_CONFIGURE_MMU_EL(1) +DEFINE_CONFIGURE_MMU_EL(3) +#endif + +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 */ + assert(counter_base_frequency != 0); + + return counter_base_frequency; +} + +void plat_report_exception(void){ + serial_puts("Enter exception!\nValue: 0x"); + serial_put_hex(read_esr_el1(), 32); + serial_puts("\n"); + reset_system(); + /*never return*/ + while (1) ; +}
\ No newline at end of file diff --git a/plat/gxb/aarch64/plat_helpers.S b/plat/gxb/aarch64/plat_helpers.S new file mode 100644 index 0000000..e69dd4b --- /dev/null +++ b/plat/gxb/aarch64/plat_helpers.S @@ -0,0 +1,85 @@ +/* + * 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 <platform_def.h> +#include "../plat_def.h" + + .globl platform_mem_init + + /* --------------------------------------------- + * void plat_report_exception(unsigned int type) + * Function to report an unhandled exception + * with platform-specific means. + * On ${PLAT} platform, it updates the LEDs + * to indicate where we are + * --------------------------------------------- + */ + + /* + * Return 0 to 3 for the A53s and 4 or 5 for the A57s + */ + .globl platform_get_core_pos +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 + + + /* ----------------------------------------------------- + * void platform_is_primary_cpu (unsigned int mpid); + * + * Given the mpidr say whether this cpu is the primary + * cpu (applicable ony after a cold boot) + * ----------------------------------------------------- + */ + .globl platform_is_primary_cpu +func platform_is_primary_cpu + /* Warning: this function is called without a valid stack */ + /* ${PLAT} todo: allow configuration of primary CPU using SCC */ + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #PRIMARY_CPU + cset x0, eq + ret + + + /* ----------------------------------------------------- + * void platform_mem_init(void); + * + * We don't need to carry out any memory initialization + * on ${PLAT}. The Secure RAM is accessible straight away. + * ----------------------------------------------------- + */ +func platform_mem_init + ret diff --git a/plat/gxb/bl2_plat_setup.c b/plat/gxb/bl2_plat_setup.c new file mode 100644 index 0000000..54b40f9 --- /dev/null +++ b/plat/gxb/bl2_plat_setup.c @@ -0,0 +1,303 @@ +/* + * 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 <serial.h> +#include <debug.h> +#include <platform.h> +#include <platform_def.h> +#include <string.h> +#include "plat_def.h" +#include "plat_private.h" +#include "scp_bootloader.h" +#include <xlat_tables.h> +#include <io.h> +#include "storage.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); + /* UEFI expects to receive the primary CPU MPID (through x0) */ + bl2_to_bl31_params->bl33_ep_info->args.arg0 = 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 = PLAT_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) +{ + //serial_init(52); //24M + + bl2_tzram_layout.total_base = TZRAM_BASE; + bl2_tzram_layout.total_size = TZRAM_SIZE; + bl2_tzram_layout.free_base = TZRAM_BL2_FREE_BASE; + bl2_tzram_layout.free_size = TZRAM_BL2_FREE_SIZE; + bl2_tzram_layout.attr = (unsigned long)0x0E939E2E8CF8EFFD; + bl2_tzram_layout.next = 0; +} + +/******************************************************************************* + * 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) +{ +#ifdef BL2_ENABLE_MMU + /* setup mmu */ + 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); +#endif + + /* storage init */ + storage_init(); +} + +/* 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) +{ + return; +} + +/******************************************************************************* + * 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 ${PLAT} 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 ${PLAT} 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 ${PLAT} 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 + ******************************************************************************/ +#ifdef BL32_BASE +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; + bl32_meminfo->attr = BOT_LOAD; + bl32_meminfo->next = 0; +} +#endif + +/******************************************************************************* + * 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; + bl33_meminfo->attr = 0; + bl33_meminfo->attr = 0; +} diff --git a/plat/gxb/crypto/bignum.c b/plat/gxb/crypto/bignum.c new file mode 100644 index 0000000..ac0c811 --- /dev/null +++ b/plat/gxb/crypto/bignum.c @@ -0,0 +1,1355 @@ +/* + * Multi-precision integer library + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * This MPI implementation is based on: + * + * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf + * http://www.stillhq.com/extracted/gnupg-api/mpi/ + * http://math.libtomcrypt.com/files/tommath.pdf + */ + +#include "common.h" +#include <string.h> +#include <rsa_config.h> +#include <stdio.h> + + +#if defined(POLARSSL_BIGNUM_C) + +#include "bignum.h" +#include "bn_mul.h" + +#define ciL (sizeof(t_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ +#define biH (ciL << 2) /* half limb size */ + +/* + * Convert between bits/chars and number of limbs + */ +#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL) +#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL) + + +#define CONFIG_MALLOC_MAX (128 * 1024) + +//char malloc_buffer[CONFIG_MALLOC_MAX]; +//static unsigned char * malloc_buffer = (unsigned char *)(0x10400000); +static int malloc_addr = 0; + +void *mymalloc(int size) +{ + void *p; + + if (malloc_addr + size > CONFIG_MALLOC_MAX) + p = NULL; + else + //p = (char *)&malloc_buffer[0] + malloc_addr; + p = (char *)(unsigned long)(0x1700000+ malloc_addr); + + if (p) + malloc_addr += size; + //ss_printf("malloc size %d/%d addr %p\n", size, malloc_addr, p); + + //printf("aml log : malloc_buffer=%p malloc_addr=0x%x p=%p size=%d\n", + // malloc_buffer,malloc_addr,p,size); + + return p; +} + +void myfree(void *ptr) +{ +} + +void mymallocreset() +{ + malloc_addr = 0; +} + + +/* + * Initialize one MPI + */ +void mpi_init( mpi *X ) +{ + if ( X == NULL ) + return; + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Unallocate one MPI + */ +void mpi_free( mpi *X ) +{ + if ( X == NULL ) + return; + + if ( X->p != NULL ) + { + memset( X->p, 0, X->n * ciL ); + myfree( X->p ); + } + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Enlarge to the specified number of limbs + */ +int mpi_grow( mpi *X, size_t nblimbs ) +{ + t_uint *p; + + if ( nblimbs > POLARSSL_MPI_MAX_LIMBS ) + return( POLARSSL_ERR_MPI_MALLOC_FAILED ); + + + if ( X->n < nblimbs ) + { + + if ( ( p = (t_uint *) mymalloc( nblimbs * ciL ) ) == NULL ) + return( POLARSSL_ERR_MPI_MALLOC_FAILED ); + + memset( p, 0, nblimbs * ciL ); + + if ( X->p != NULL ) + { + memcpy( p, X->p, X->n * ciL ); + memset( X->p, 0, X->n * ciL ); + myfree( X->p ); + } + + X->n = nblimbs; + X->p = p; + } + + return( 0 ); +} + +/* + * Copy the contents of Y into X + */ +int mpi_copy( mpi *X, const mpi *Y ) +{ + int ret; + size_t i; + + if ( X == Y ) + return( 0 ); + + for ( i = Y->n - 1; i > 0; i-- ) + if ( Y->p[i] != 0 ) + break; + i++; + + X->s = Y->s; + + MPI_CHK( mpi_grow( X, i ) ); + + memset( X->p, 0, X->n * ciL ); + memcpy( X->p, Y->p, i * ciL ); + +cleanup: + + return( ret ); +} + +/* + * Swap the contents of X and Y + */ +void mpi_swap( mpi *X, mpi *Y ) +{ + mpi T; + + memcpy( &T, X, sizeof( mpi ) ); + memcpy( X, Y, sizeof( mpi ) ); + memcpy( Y, &T, sizeof( mpi ) ); +} + +/* + * Set value from integer + */ +int mpi_lset( mpi *X, t_sint z ) +{ + int ret; + + MPI_CHK( mpi_grow( X, 1 ) ); + memset( X->p, 0, X->n * ciL ); + + X->p[0] = ( z < 0 ) ? -z : z; + X->s = ( z < 0 ) ? -1 : 1; + +cleanup: + + return( ret ); +} + +/* + * Get a specific bit + */ +int mpi_get_bit( const mpi *X, size_t pos ) +{ + if ( X->n * biL <= pos ) + return( 0 ); + + return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01; +} + +/* + * Set a bit to a specific value of 0 or 1 + */ +int mpi_set_bit( mpi *X, size_t pos, unsigned char val ) +{ + int ret = 0; + size_t off = pos / biL; + size_t idx = pos % biL; + + if ( val != 0 && val != 1 ) + return POLARSSL_ERR_MPI_BAD_INPUT_DATA; + + if ( X->n * biL <= pos ) + { + if ( val == 0 ) + return ( 0 ); + + MPI_CHK( mpi_grow( X, off + 1 ) ); + } + + X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx ); + +cleanup: + + return( ret ); +} + +/* + * Return the number of least significant bits + */ +size_t mpi_lsb( const mpi *X ) +{ + size_t i, j, count = 0; + + for ( i = 0; i < X->n; i++ ) + for ( j = 0; j < biL; j++, count++ ) + if ( ( ( X->p[i] >> j ) & 1 ) != 0 ) + return( count ); + + return( 0 ); +} + +/* + * Return the number of most significant bits + */ +size_t mpi_msb( const mpi *X ) +{ + size_t i, j; + + for ( i = X->n - 1; i > 0; i-- ) + if ( X->p[i] != 0 ) + break; + + for ( j = biL; j > 0; j-- ) + if ( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 ) + break; + + return( ( i * biL ) + j ); +} + +/* + * Return the total size in bytes + */ +size_t mpi_size( const mpi *X ) +{ + return( ( mpi_msb( X ) + 7 ) >> 3 ); +} + + +/* + * Import X from unsigned binary data, big endian + */ +int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t i, j, n; + + for ( n = 0; n < buflen; n++ ) + if ( buf[n] != 0 ) + break; + MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) ); + + MPI_CHK( mpi_lset( X, 0 ) ); + + + for ( i = buflen, j = 0; i > n; i--, j++ ) + X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3); + +cleanup: + + return( ret ); +} + +/* + * Export X into unsigned binary data, big endian + */ +int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen ) +{ + size_t i, j, n; + + n = mpi_size( X ); + + if ( buflen < n ) + return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL ); + + memset( buf, 0, buflen ); + + for ( i = buflen - 1, j = 0; n > 0; i--, j++, n-- ) + buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) ); + + return( 0 ); +} + +/* + * Left-shift: X <<= count + */ +int mpi_shift_l( mpi *X, size_t count ) +{ + int ret; + size_t i, v0, t1; + t_uint r0 = 0, r1; + + v0 = count / (biL ); + t1 = count & (biL - 1); + + i = mpi_msb( X ) + count; + + if ( X->n * biL < i ) + MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) ); + + ret = 0; + + /* + * shift by count / limb_size + */ + if ( v0 > 0 ) + { + for ( i = X->n; i > v0; i-- ) + X->p[i - 1] = X->p[i - v0 - 1]; + + for ( ; i > 0; i-- ) + X->p[i - 1] = 0; + } + + /* + * shift by count % limb_size + */ + if ( t1 > 0 ) + { + for ( i = v0; i < X->n; i++ ) + { + r1 = X->p[i] >> (biL - t1); + X->p[i] <<= t1; + X->p[i] |= r0; + r0 = r1; + } + } + +cleanup: + + return( ret ); +} + +/* + * Right-shift: X >>= count + */ +int mpi_shift_r( mpi *X, size_t count ) +{ + size_t i, v0, v1; + t_uint r0 = 0, r1; + + v0 = count / biL; + v1 = count & (biL - 1); + + if ( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) + return mpi_lset( X, 0 ); + + /* + * shift by count / limb_size + */ + if ( v0 > 0 ) + { + for ( i = 0; i < X->n - v0; i++ ) + X->p[i] = X->p[i + v0]; + + for ( ; i < X->n; i++ ) + X->p[i] = 0; + } + + /* + * shift by count % limb_size + */ + if ( v1 > 0 ) + { + for ( i = X->n; i > 0; i-- ) + { + r1 = X->p[i - 1] << (biL - v1); + X->p[i - 1] >>= v1; + X->p[i - 1] |= r0; + r0 = r1; + } + } + + return( 0 ); +} + +/* + * Compare unsigned values + */ +int mpi_cmp_abs( const mpi *X, const mpi *Y ) +{ + size_t i, j; + + for ( i = X->n; i > 0; i-- ) + if ( X->p[i - 1] != 0 ) + break; + + for ( j = Y->n; j > 0; j-- ) + if ( Y->p[j - 1] != 0 ) + break; + + if ( i == 0 && j == 0 ) + return( 0 ); + + if ( i > j ) return( 1 ) ; + if ( j > i ) return( -1 ) ; + + for ( ; i > 0; i-- ) + { + if ( X->p[i - 1] > Y->p[i - 1] ) return( 1 ) ; + if ( X->p[i - 1] < Y->p[i - 1] ) return( -1 ) ; + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mpi_cmp_mpi( const mpi *X, const mpi *Y ) +{ + size_t i, j; + + for ( i = X->n; i > 0; i-- ) + if ( X->p[i - 1] != 0 ) + break; + + for ( j = Y->n; j > 0; j-- ) + if ( Y->p[j - 1] != 0 ) + break; + + if ( i == 0 && j == 0 ) + return( 0 ); + + if ( i > j ) return( X->s ) ; + if ( j > i ) return( -Y->s ) ; + + if ( X->s > 0 && Y->s < 0 ) return( 1 ) ; + if ( Y->s > 0 && X->s < 0 ) return( -1 ) ; + + for ( ; i > 0; i-- ) + { + if ( X->p[i - 1] > Y->p[i - 1] ) return( X->s ) ; + if ( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ) ; + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mpi_cmp_int( const mpi *X, t_sint z ) +{ + mpi Y; + t_uint p[1]; + + *p = ( z < 0 ) ? -z : z; + Y.s = ( z < 0 ) ? -1 : 1; + Y.n = 1; + Y.p = p; + + return( mpi_cmp_mpi( X, &Y ) ); +} + +/* + * Unsigned addition: X = |A| + |B| (HAC 14.7) + */ +int mpi_add_abs( mpi *X, const mpi *A, const mpi *B ) +{ + int ret; + size_t i, j; + t_uint *o, *p, c; + + if ( X == B ) + { + const mpi *T = A; A = X; B = T; + } + + if ( X != A ) + MPI_CHK( mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned additions. + */ + X->s = 1; + + for ( j = B->n; j > 0; j-- ) + if ( B->p[j - 1] != 0 ) + break; + + MPI_CHK( mpi_grow( X, j ) ); + + o = B->p; p = X->p; c = 0; + + for ( i = 0; i < j; i++, o++, p++ ) + { + *p += c; c = ( *p < c ); + *p += *o; c += ( *p < *o ); + } + + while ( c != 0 ) + { + if ( i >= X->n ) + { + MPI_CHK( mpi_grow( X, i + 1 ) ); + p = X->p + i; + } + + *p += c; c = ( *p < c ); i++; p++; + } + +cleanup: + + return( ret ); +} + +/* + * Helper for mpi substraction + */ +static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d ) +{ + size_t i; + t_uint c, z; + + for ( i = c = 0; i < n; i++, s++, d++ ) + { + z = ( *d < c ); *d -= c; + c = ( *d < *s ) + z; *d -= *s; + } + + while ( c != 0 ) + { + z = ( *d < c ); *d -= c; + c = z; i++; d++; + } +} + +/* + * Unsigned substraction: X = |A| - |B| (HAC 14.9) + */ +int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B ) +{ + mpi TB; + int ret; + size_t n; + + if ( mpi_cmp_abs( A, B ) < 0 ) + return( POLARSSL_ERR_MPI_NEGATIVE_VALUE ); + + mpi_init( &TB ); + + if ( X == B ) + { + MPI_CHK( mpi_copy( &TB, B ) ); + B = &TB; + } + + if ( X != A ) + MPI_CHK( mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned substractions. + */ + X->s = 1; + + ret = 0; + + for ( n = B->n; n > 0; n-- ) + if ( B->p[n - 1] != 0 ) + break; + + mpi_sub_hlp( n, B->p, X->p ); + +cleanup: + + mpi_free( &TB ); + + return( ret ); +} + +/* + * Signed addition: X = A + B + */ +int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B ) +{ + int ret, s = A->s; + + if ( A->s * B->s < 0 ) + { + if ( mpi_cmp_abs( A, B ) >= 0 ) + { + MPI_CHK( mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MPI_CHK( mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MPI_CHK( mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed substraction: X = A - B + */ +int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B ) +{ + int ret, s = A->s; + + if ( A->s * B->s > 0 ) + { + if ( mpi_cmp_abs( A, B ) >= 0 ) + { + MPI_CHK( mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MPI_CHK( mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MPI_CHK( mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed addition: X = A + b + */ +int mpi_add_int( mpi *X, const mpi *A, t_sint b ) +{ + mpi _B; + t_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mpi_add_mpi( X, A, &_B ) ); +} + +/* + * Signed substraction: X = A - b + */ +int mpi_sub_int( mpi *X, const mpi *A, t_sint b ) +{ + mpi _B; + t_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mpi_sub_mpi( X, A, &_B ) ); +} + +/* + * Helper for mpi multiplication + */ +static void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b ) +{ + t_uint c = 0, t = 0; + +#if defined(MULADDC_HUIT) + for ( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_HUIT + MULADDC_STOP + } + + for ( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#else + for ( ; i >= 16; i -= 16 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for ( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for ( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#endif + + t++; + + do { + *d += c; c = ( *d < c ); d++; + } + while ( c != 0 ) ; +} + +/* + * Baseline multiplication: X = A * B (HAC 14.12) + */ +int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B ) +{ + int ret; + size_t i, j; + mpi TA, TB; + + mpi_init( &TA ); mpi_init( &TB ); + + if ( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ) ; A = &TA; } + if ( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ) ; B = &TB; } + + for ( i = A->n; i > 0; i-- ) + if ( A->p[i - 1] != 0 ) + break; + + for ( j = B->n; j > 0; j-- ) + if ( B->p[j - 1] != 0 ) + break; + + MPI_CHK( mpi_grow( X, i + j ) ); + MPI_CHK( mpi_lset( X, 0 ) ); + + for ( i++; j > 0; j-- ) + mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] ); + + X->s = A->s * B->s; + +cleanup: + + mpi_free( &TB ); mpi_free( &TA ); + + return( ret ); +} + +/* + * Baseline multiplication: X = A * b + */ +int mpi_mul_int( mpi *X, const mpi *A, t_sint b ) +{ + mpi _B; + t_uint p[1]; + + _B.s = 1; + _B.n = 1; + _B.p = p; + p[0] = b; + + return( mpi_mul_mpi( X, A, &_B ) ); +} + +/* + * Division by mpi: A = Q * B + R (HAC 14.20) + */ +int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B ) +{ + int ret; + size_t i, n, t, k; + mpi X, Y, Z, T1, T2; + + if ( mpi_cmp_int( B, 0 ) == 0 ) + return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO ); + + mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z ); + mpi_init( &T1 ); mpi_init( &T2 ); + + if ( mpi_cmp_abs( A, B ) < 0 ) + { + if ( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) ) ; + if ( R != NULL ) MPI_CHK( mpi_copy( R, A ) ) ; + return( 0 ); + } + + MPI_CHK( mpi_copy( &X, A ) ); + MPI_CHK( mpi_copy( &Y, B ) ); + X.s = Y.s = 1; + + MPI_CHK( mpi_grow( &Z, A->n + 2 ) ); + MPI_CHK( mpi_lset( &Z, 0 ) ); + MPI_CHK( mpi_grow( &T1, 2 ) ); + MPI_CHK( mpi_grow( &T2, 3 ) ); + + k = mpi_msb( &Y ) % biL; + if ( k < biL - 1 ) + { + k = biL - 1 - k; + MPI_CHK( mpi_shift_l( &X, k ) ); + MPI_CHK( mpi_shift_l( &Y, k ) ); + } + else k = 0; + + n = X.n - 1; + t = Y.n - 1; + MPI_CHK( mpi_shift_l( &Y, biL * (n - t) ) ); + + while ( mpi_cmp_mpi( &X, &Y ) >= 0 ) + { + Z.p[n - t]++; + mpi_sub_mpi( &X, &X, &Y ); + } + mpi_shift_r( &Y, biL * (n - t) ); + + for ( i = n; i > t ; i-- ) + { + if ( X.p[i] >= Y.p[t] ) + Z.p[i - t - 1] = ~0; + else + { +#if defined(POLARSSL_HAVE_UDBL) + t_udbl r; + + r = (t_udbl) X.p[i] << biL; + r |= (t_udbl) X.p[i - 1]; + r /= Y.p[t]; + if ( r > ((t_udbl) 1 << biL) - 1) + r = ((t_udbl) 1 << biL) - 1; + + Z.p[i - t - 1] = (t_uint) r; +#else + /* + * __udiv_qrnnd_c, from gmp/longlong.h + */ + t_uint q0, q1, r0, r1; + t_uint d0, d1, d, m; + + d = Y.p[t]; + d0 = ( d << biH ) >> biH; + d1 = ( d >> biH ); + + q1 = X.p[i] / d1; + r1 = X.p[i] - d1 * q1; + r1 <<= biH; + r1 |= ( X.p[i - 1] >> biH ); + + m = q1 * d0; + if ( r1 < m ) + { + q1--, r1 += d; + while ( r1 >= d && r1 < m ) + q1--, r1 += d; + } + r1 -= m; + + q0 = r1 / d1; + r0 = r1 - d1 * q0; + r0 <<= biH; + r0 |= ( X.p[i - 1] << biH ) >> biH; + + m = q0 * d0; + if ( r0 < m ) + { + q0--, r0 += d; + while ( r0 >= d && r0 < m ) + q0--, r0 += d; + } + r0 -= m; + + Z.p[i - t - 1] = ( q1 << biH ) | q0; +#endif + } + + Z.p[i - t - 1]++; + do + { + Z.p[i - t - 1]--; + + MPI_CHK( mpi_lset( &T1, 0 ) ); + T1.p[0] = (t < 1) ? 0 : Y.p[t - 1]; + T1.p[1] = Y.p[t]; + MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); + + MPI_CHK( mpi_lset( &T2, 0 ) ); + T2.p[0] = (i < 2) ? 0 : X.p[i - 2]; + T2.p[1] = (i < 1) ? 0 : X.p[i - 1]; + T2.p[2] = X.p[i]; + } + while ( mpi_cmp_mpi( &T1, &T2 ) > 0 ) ; + + MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); + MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) ); + MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) ); + + if ( mpi_cmp_int( &X, 0 ) < 0 ) + { + MPI_CHK( mpi_copy( &T1, &Y ) ); + MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) ); + MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) ); + Z.p[i - t - 1]--; + } + } + + if ( Q != NULL ) + { + mpi_copy( Q, &Z ); + Q->s = A->s * B->s; + } + + if ( R != NULL ) + { + mpi_shift_r( &X, k ); + X.s = A->s; + mpi_copy( R, &X ); + + if ( mpi_cmp_int( R, 0 ) == 0 ) + R->s = 1; + } + +cleanup: + + mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z ); + mpi_free( &T1 ); mpi_free( &T2 ); + + return( ret ); +} +/* + * Modulo: R = A mod B + */ +int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B ) +{ + int ret; + + if ( mpi_cmp_int( B, 0 ) < 0 ) + return POLARSSL_ERR_MPI_NEGATIVE_VALUE; + + MPI_CHK( mpi_div_mpi( NULL, R, A, B ) ); + + while ( mpi_cmp_int( R, 0 ) < 0 ) + MPI_CHK( mpi_add_mpi( R, R, B ) ); + + while ( mpi_cmp_mpi( R, B ) >= 0 ) + MPI_CHK( mpi_sub_mpi( R, R, B ) ); + +cleanup: + + return( ret ); +} + +/* + * Modulo: r = A mod b + */ +int mpi_mod_int( t_uint *r, const mpi *A, t_sint b ) +{ + size_t i; + t_uint x, y, z; + + if ( b == 0 ) + return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO ); + + if ( b < 0 ) + return POLARSSL_ERR_MPI_NEGATIVE_VALUE; + + /* + * handle trivial cases + */ + if ( b == 1 ) + { + *r = 0; + return( 0 ); + } + + if ( b == 2 ) + { + *r = A->p[0] & 1; + return( 0 ); + } + + /* + * general case + */ + for ( i = A->n, y = 0; i > 0; i-- ) + { + x = A->p[i - 1]; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + + x <<= biH; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + } + + /* + * If A is negative, then the current y represents a negative value. + * Flipping it to the positive side. + */ + if ( A->s < 0 && y != 0 ) + y = b - y; + + *r = y; + + return( 0 ); +} + +/* + * Fast Montgomery initialization (thanks to Tom St Denis) + */ +static void mpi_montg_init( t_uint *mm, const mpi *N ) +{ + t_uint x, m0 = N->p[0]; + + x = m0; + x += ( ( m0 + 2 ) & 4 ) << 1; + x *= ( 2 - ( m0 * x ) ); + + if ( biL >= 16 ) x *= ( 2 - ( m0 * x ) ) ; + if ( biL >= 32 ) x *= ( 2 - ( m0 * x ) ) ; + if ( biL >= 64 ) x *= ( 2 - ( m0 * x ) ) ; + + *mm = ~x + 1; +} + +/* + * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) + */ +static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T ) +{ + size_t i, n, m; + t_uint u0, u1, *d; + + memset( T->p, 0, T->n * ciL ); + + d = T->p; + n = N->n; + m = ( B->n < n ) ? B->n : n; + + for ( i = 0; i < n; i++ ) + { + /* + * T = (T + u0*B + u1*N) / 2^biL + */ + u0 = A->p[i]; + u1 = ( d[0] + u0 * B->p[0] ) * mm; + + mpi_mul_hlp( m, B->p, d, u0 ); + mpi_mul_hlp( n, N->p, d, u1 ); + + *d++ = u0; d[n + 1] = 0; + } + + memcpy( A->p, d, (n + 1) * ciL ); + + if ( mpi_cmp_abs( A, N ) >= 0 ) + mpi_sub_hlp( n, N->p, A->p ); + else + /* prevent timing attacks */ + mpi_sub_hlp( n, A->p, T->p ); +} + +/* + * Montgomery reduction: A = A * R^-1 mod N + */ +static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T ) +{ + t_uint z = 1; + mpi U; + + U.n = U.s = (int) z; + U.p = &z; + + mpi_montmul( A, &U, N, mm, T ); +} + +/* + * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) + */ +int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR ) +{ + int ret; + size_t wbits, wsize, one = 1; + size_t i, j, nblimbs; + size_t bufsize, nbits; + t_uint ei, mm, state; + mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos; + int neg; + + if ( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + if ( mpi_cmp_int( E, 0 ) < 0 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + /* + * Init temps and window size + */ + mpi_montg_init( &mm, N ); + mpi_init( &RR ); mpi_init( &T ); + memset( W, 0, sizeof( W ) ); + + i = mpi_msb( E ); + + wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : + ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; + + if ( wsize > POLARSSL_MPI_WINDOW_SIZE ) + wsize = POLARSSL_MPI_WINDOW_SIZE; + + j = N->n + 1; + MPI_CHK( mpi_grow( X, j ) ); + MPI_CHK( mpi_grow( &W[1], j ) ); + MPI_CHK( mpi_grow( &T, j * 2 ) ); + + /* + * Compensate for negative A (and correct at the end) + */ + neg = ( A->s == -1 ); + + mpi_init( &Apos ); + if ( neg ) + { + MPI_CHK( mpi_copy( &Apos, A ) ); + Apos.s = 1; + A = &Apos; + } + + /* + * If 1st call, pre-compute R^2 mod N + */ + if ( _RR == NULL || _RR->p == NULL ) + { + MPI_CHK( mpi_lset( &RR, 1 ) ); + MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) ); + MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) ); + + if ( _RR != NULL ) + memcpy( _RR, &RR, sizeof( mpi ) ); + } + else + memcpy( &RR, _RR, sizeof( mpi ) ); + + /* + * W[1] = A * R^2 * R^-1 mod N = A * R mod N + */ + if ( mpi_cmp_mpi( A, N ) >= 0 ) + mpi_mod_mpi( &W[1], A, N ); + else mpi_copy( &W[1], A ); + + mpi_montmul( &W[1], &RR, N, mm, &T ); + + /* + * X = R^2 * R^-1 mod N = R mod N + */ + MPI_CHK( mpi_copy( X, &RR ) ); + mpi_montred( X, N, mm, &T ); + + if ( wsize > 1 ) + { + /* + * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) + */ + j = one << (wsize - 1); + + MPI_CHK( mpi_grow( &W[j], N->n + 1 ) ); + MPI_CHK( mpi_copy( &W[j], &W[1] ) ); + + for ( i = 0; i < wsize - 1; i++ ) + mpi_montmul( &W[j], &W[j], N, mm, &T ); + + /* + * W[i] = W[i - 1] * W[1] + */ + for ( i = j + 1; i < (one << wsize); i++ ) + { + MPI_CHK( mpi_grow( &W[i], N->n + 1 ) ); + MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) ); + + mpi_montmul( &W[i], &W[1], N, mm, &T ); + } + } + + nblimbs = E->n; + bufsize = 0; + nbits = 0; + wbits = 0; + state = 0; + + while ( 1 ) + { + if ( bufsize == 0 ) + { + if ( nblimbs-- == 0 ) + break; + + bufsize = sizeof( t_uint ) << 3; + } + + bufsize--; + + ei = (E->p[nblimbs] >> bufsize) & 1; + + /* + * skip leading 0s + */ + if ( ei == 0 && state == 0 ) + continue; + + if ( ei == 0 && state == 1 ) + { + /* + * out of window, square X + */ + mpi_montmul( X, X, N, mm, &T ); + continue; + } + + /* + * add ei to current window + */ + state = 2; + + nbits++; + wbits |= (ei << (wsize - nbits)); + + if ( nbits == wsize ) + { + /* + * X = X^wsize R^-1 mod N + */ + for ( i = 0; i < wsize; i++ ) + mpi_montmul( X, X, N, mm, &T ); + + /* + * X = X * W[wbits] R^-1 mod N + */ + mpi_montmul( X, &W[wbits], N, mm, &T ); + + state--; + nbits = 0; + wbits = 0; + } + } + + /* + * process the remaining bits + */ + for ( i = 0; i < nbits; i++ ) + { + mpi_montmul( X, X, N, mm, &T ); + + wbits <<= 1; + + if ( (wbits & (one << wsize)) != 0 ) + mpi_montmul( X, &W[1], N, mm, &T ); + } + + /* + * X = A^E * R * R^-1 mod N = A^E mod N + */ + mpi_montred( X, N, mm, &T ); + + if ( neg ) + { + X->s = -1; + mpi_add_mpi( X, N, X ); + } + +cleanup: + + for ( i = (one << (wsize - 1)); i < (one << wsize); i++ ) + mpi_free( &W[i] ); + + mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos ); + + if ( _RR == NULL ) + mpi_free( &RR ); + + return( ret ); +} + +#endif diff --git a/plat/gxb/crypto/ndma_utils.c b/plat/gxb/crypto/ndma_utils.c new file mode 100644 index 0000000..29147e0 --- /dev/null +++ b/plat/gxb/crypto/ndma_utils.c @@ -0,0 +1,183 @@ +#include <stdint.h> +#include "ndma_utils.h" +#include <asm/arch/secure_apb.h> +#include <arch_helpers.h> + +uint32_t NDMA_table_ptr_start[4]; +uint32_t NDMA_table_ptr_curr[4]; +uint32_t NDMA_table_ptr_end[4]; + + +#define NDMA_Wr(addr, data) *(volatile uint32_t *)(addr)=(data) +#define NDMA_Rd(addr) *(volatile uint32_t *)(addr) +// -------------------------------------------- +// NDMA_set_table_position_secure +// -------------------------------------------- +void NDMA_set_table_position_secure( uint32_t thread_num, uint32_t table_start, uint32_t table_end ) +{ + NDMA_table_ptr_start[thread_num] = table_start; + NDMA_table_ptr_curr[thread_num] = table_start; + NDMA_table_ptr_end[thread_num] = table_end; + switch ( thread_num ) { + case 3: NDMA_Wr( SEC_SEC_BLKMV_THREAD_TABLE_START3, table_start ); + NDMA_Wr( SEC_SEC_BLKMV_THREAD_TABLE_END3, table_end ); + // Pulse thread init to register the new start/end locations + NDMA_Wr( NDMA_THREAD_REG, NDMA_Rd(NDMA_THREAD_REG) | (1 << 27) ); + break; + case 2: NDMA_Wr( SEC_SEC_BLKMV_THREAD_TABLE_START2, table_start ); + NDMA_Wr( SEC_SEC_BLKMV_THREAD_TABLE_END2, table_end ); + // Pulse thread init to register the new start/end locations + NDMA_Wr( NDMA_THREAD_REG, NDMA_Rd(NDMA_THREAD_REG) | (1 << 26) ); + break; + case 1: NDMA_Wr( SEC_SEC_BLKMV_THREAD_TABLE_START1, table_start ); + NDMA_Wr( SEC_SEC_BLKMV_THREAD_TABLE_END1, table_end ); + // Pulse thread init to register the new start/end locations + NDMA_Wr( NDMA_THREAD_REG, NDMA_Rd(NDMA_THREAD_REG) | (1 << 25) ); + break; + case 0: NDMA_Wr( SEC_SEC_BLKMV_THREAD_TABLE_START0, table_start ); + NDMA_Wr( SEC_SEC_BLKMV_THREAD_TABLE_END0, table_end ); + // Pulse thread init to register the new start/end locations + NDMA_Wr( SEC_NDMA_THREAD_REG, NDMA_Rd(NDMA_THREAD_REG) | (1 << 24) ); + break; + } +} + + +// -------------------------------------------- +// NDMA_start() +// -------------------------------------------- +// Start the block move procedure +// +void NDMA_start(uint32_t thread_num) +{ + NDMA_Wr(SEC_NDMA_CNTL_REG0,NDMA_Rd(SEC_NDMA_CNTL_REG0) | (1 << NDMA_ENABLE) ); + + // NDMA_Wr(NDMA_CNTL_REG0,0xf8634000 ); + NDMA_Wr(SEC_NDMA_THREAD_REG,NDMA_Rd(SEC_NDMA_THREAD_REG) | (1 << (thread_num + 8)) ); +} +// -------------------------------------------- +// NDMA_wait_for_completion() +// -------------------------------------------- +// Wait for all block moves to complete +// +void NDMA_wait_for_completion(uint32_t thread_num) +{ + if ( !NDMA_table_ptr_start[thread_num] ) { // there are no table entries + return; + } + + while ( (NDMA_Rd(SEC_NDMA_TABLE_ADD_REG) & (0xFF << (thread_num*8))) ) { } +} + +void NDMA_stop(uint32_t thread_num) +{ + NDMA_Wr(NDMA_THREAD_REG,NDMA_Rd(NDMA_THREAD_REG) & ~(1 << (thread_num + 8)) ); + // If no threads enabled, then shut down the DMA engine completely + if ( !(NDMA_Rd(NDMA_THREAD_REG) & (0xF << 8)) ) { + NDMA_Wr(NDMA_CNTL_REG0,NDMA_Rd(NDMA_CNTL_REG0) & ~(1 << NDMA_ENABLE) ); + } +} +// -------------------------------------------- +// NDMA_add_descriptor_aes +// -------------------------------------------- +// Simple add function for AES +void NDMA_add_descriptor_aes( +uint32_t thread_num, +uint32_t irq, +uint32_t cbc_enable, +uint32_t cbc_reset, +uint32_t encrypt, // 0 = decrypt, 1 = encrypt +uint32_t aes_type, // 00 = 128, 01 = 192, 10 = 256 +uint32_t pre_endian, +uint32_t post_endian, +uint32_t bytes_to_move, +uint32_t src_addr, +uint32_t dest_addr, +uint32_t ctr_endian, +uint32_t ctr_limit ) +{ + volatile uint32_t *p = (volatile uint32_t *)(unsigned long)NDMA_table_ptr_curr[thread_num]; + (*p++) = (0x01 << 30) | // owned by CPU + (0 << 27) | + (0 << 26) | + (0 << 25) | + (4 << 22) | // AES + (irq << 21)| (1<<8); + (*p++) = src_addr; + (*p++) = dest_addr; + (*p++) = bytes_to_move & 0x01FFFFFF; + (*p++) = 0x00000000; // no skip + (*p++) = 0x00000000; // no skip + // Prepare the pointer for the next descriptor boundary + // inline processing + bytes to move extension + (*p++) = + (ctr_endian << 16) | + (ctr_limit << 14) | + (cbc_enable << 12) | + (cbc_reset << 11) | + (encrypt << 10) | + (aes_type << 8) | + (post_endian << 4) | + (pre_endian << 0); + + #if 0 + _clean_dcache_addr(NDMA_table_ptr_curr[thread_num]); + _clean_invd_dcache_addr (NDMA_table_ptr_curr[thread_num]); + _clean_dcache_addr(NDMA_table_ptr_curr[thread_num]+32); + _clean_invd_dcache_addr (NDMA_table_ptr_curr[thread_num]+32); + #endif + + if ( NDMA_table_ptr_curr[thread_num] == NDMA_table_ptr_end[thread_num] ) { + NDMA_table_ptr_curr[thread_num] = NDMA_table_ptr_start[thread_num]; + } else { + NDMA_table_ptr_curr[thread_num] += 32; // point to the next location (8-4 byte table entries) + } + NDMA_Wr( NDMA_TABLE_ADD_REG, (thread_num << 8) | (1 << 0) ); +} + +// -------------------------------------------- +// NDMA_add_descriptor_sha +// -------------------------------------------- +// Simple add function for SHA +void NDMA_add_descriptor_sha( +uint32_t thread_num, +uint32_t irq, +uint32_t sha_mode, // 1:sha1;2:sha2-256;3:sha2_224 +uint32_t pre_endian, +uint32_t bytes_to_move, +uint32_t src_addr, +uint32_t last_block ) +{ + volatile uint32_t *p = (volatile uint32_t *)(unsigned long)NDMA_table_ptr_curr[thread_num]; + (*p++) = (0x01 << 30) | // owned by CPU + (0 << 27) | + (0 << 26) | + (0 << 25) | + (5 << 22) | // SHA + (irq << 21) ; + (*p++) = src_addr; + (*p++) = 0x00000000; + (*p++) = bytes_to_move & 0x01FFFFFF; + (*p++) = 0x00000000; // no skip + (*p++) = 0x00000000; // no skip + // Prepare the pointer for the next descriptor boundary + // inline processing + bytes to move extension + (*p++) = (sha_mode << 8) | + (last_block << 4) | + (pre_endian << 0); + + #if 0 + _clean_dcache_addr(NDMA_table_ptr_curr[thread_num]); + _clean_invd_dcache_addr (NDMA_table_ptr_curr[thread_num]); + _clean_dcache_addr(NDMA_table_ptr_curr[thread_num]+32); + _clean_invd_dcache_addr (NDMA_table_ptr_curr[thread_num]+32); + #endif + + if ( NDMA_table_ptr_curr[thread_num] == NDMA_table_ptr_end[thread_num] ) { + NDMA_table_ptr_curr[thread_num] = NDMA_table_ptr_start[thread_num]; + } else { + NDMA_table_ptr_curr[thread_num] += 32; // point to the next location (8-4 byte table entries) + } + NDMA_Wr( SEC_NDMA_TABLE_ADD_REG, (thread_num << 8) | (1 << 0) ); +} + diff --git a/plat/gxb/crypto/rsa.c b/plat/gxb/crypto/rsa.c new file mode 100644 index 0000000..988dec3 --- /dev/null +++ b/plat/gxb/crypto/rsa.c @@ -0,0 +1,240 @@ +/* + * The RSA public-key cryptosystem + * + * Copyright (C) 2006-2011, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * RSA was designed by Ron Rivest, Adi Shamir and Len Adleman. + * + * http://theory.lcs.mit.edu/~rivest/rsapaper.pdf + * http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf + */ + +#include <rsa_config.h> +#include <string.h> + +#if defined(POLARSSL_RSA_C) + +#include <rsa.h> + +#include <stdio.h> + +/* + * Initialize an RSA context + */ + +extern void mymallocreset(); + +void rsa_init( rsa_context *ctx, + int padding, + int hash_id ) +{ + memset( ctx, 0, sizeof( rsa_context ) ); + + ctx->padding = padding; + ctx->hash_id = hash_id; + + mymallocreset(); +} + +/* + * Do an RSA public key operation + */ +int rsa_public( rsa_context *ctx, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t olen; + mpi T; + mpi_init( &T ); + MPI_CHK( mpi_read_binary( &T, input, ctx->len ) ); + + if ( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + mpi_free( &T ); + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + olen = ctx->len; + MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); + MPI_CHK( mpi_write_binary( &T, output, olen ) ); + +cleanup: + + mpi_free( &T ); + + if ( ret != 0 ) + return( POLARSSL_ERR_RSA_PUBLIC_FAILED + ret ); + return( 0 ); +} + +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function + */ +int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + int ret; + size_t len, siglen; + unsigned char *p, c; + unsigned char buf[POLARSSL_MPI_MAX_SIZE]; + + if ( ctx->padding != RSA_PKCS_V15 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + siglen = ctx->len; + + if ( siglen < 16 || siglen > sizeof( buf ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + +#ifdef CONFIG_EMU_BUILD + ret = ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, sig, buf ) + : rsa_private( ctx, sig, buf ); +#else + if (mode != RSA_PUBLIC) + return ( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + ret = rsa_public( ctx, sig, buf ); +#endif /* CONFIG_EMU_BUILD */ + + if ( ret != 0 ) + return( ret ); + + p = buf; + + if ( *p++ != 0 || *p++ != RSA_SIGN ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + + while ( *p != 0 ) + { + if ( p >= buf + siglen - 1 || *p != 0xFF ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + p++; + } + p++; + + len = siglen - ( p - buf ); + + if ( len == 33 && hash_id == SIG_RSA_SHA1 ) + { + if ( memcmp( p, ASN1_HASH_SHA1_ALT, 13 ) == 0 && + memcmp( p + 13, hash, 20 ) == 0 ) + return( 0 ); + else + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + } + if ( len == 34 ) + { + c = p[13]; + p[13] = 0; + + if ( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if ( ( c == 2 && hash_id == SIG_RSA_MD2 ) || + ( c == 4 && hash_id == SIG_RSA_MD4 ) || + ( c == 5 && hash_id == SIG_RSA_MD5 ) ) + { + if ( memcmp( p + 18, hash, 16 ) == 0 ) + return( 0 ); + else + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + } + } + + if ( len == 35 && hash_id == SIG_RSA_SHA1 ) + { + if ( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 && + memcmp( p + 15, hash, 20 ) == 0 ) + return( 0 ); + else + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + } + if ( ( len == 19 + 28 && p[14] == 4 && hash_id == SIG_RSA_SHA224 ) || + ( len == 19 + 32 && p[14] == 1 && hash_id == SIG_RSA_SHA256 ) || + ( len == 19 + 48 && p[14] == 2 && hash_id == SIG_RSA_SHA384 ) || + ( len == 19 + 64 && p[14] == 3 && hash_id == SIG_RSA_SHA512 ) ) + { + c = p[1] - 17; + p[1] = 17; + p[14] = 0; + + if( p[18] == c && + memcmp( p, ASN1_HASH_SHA2X, 18 ) == 0 && + memcmp( p + 19, hash, c ) == 0 ) + return( 0 ); + else + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + } + + if ( len == hashlen && hash_id == SIG_RSA_RAW ) + { + if ( memcmp( p, hash, hashlen ) == 0 ) + return( 0 ); + else + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + } + + return( POLARSSL_ERR_RSA_INVALID_PADDING ); +} + +/* + * Do an RSA operation and check the message digest + */ +int rsa_pkcs1_verify( rsa_context *ctx, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + int ret; + switch ( ctx->padding ) + { + case RSA_PKCS_V15: + ret = rsa_rsassa_pkcs1_v15_verify( ctx, mode, hash_id, + hashlen, hash, sig ); + break; + default: + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } + + return ret; +} + +/* + * Free the components of an RSA key + */ +void rsa_free( rsa_context *ctx ) +{ + mpi_free( &ctx->RQ ); mpi_free( &ctx->RP ); mpi_free( &ctx->RN ); + mpi_free( &ctx->QP ); mpi_free( &ctx->DQ ); mpi_free( &ctx->DP ); + mpi_free( &ctx->Q ); mpi_free( &ctx->P ); mpi_free( &ctx->D ); + mpi_free( &ctx->E ); mpi_free( &ctx->N ); +} + +#endif diff --git a/plat/gxb/crypto/secureboot.c b/plat/gxb/crypto/secureboot.c new file mode 100644 index 0000000..fc36dd7 --- /dev/null +++ b/plat/gxb/crypto/secureboot.c @@ -0,0 +1,749 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/common/plat/gxb/crypto/secureboot.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +//for polarssl RSA +#include <rsa.h> +#include <string.h> +#include <stdio.h> +#include <sha2.h> +#include <asm/arch/secure_apb.h> +#include <arch_helpers.h> + +#include <ndma_utils.h> + +//#define AML_DEBUG_SHOW + +#if defined(AML_DEBUG_SHOW) + #define aml_printf printf +#else + #define aml_printf(...) +#endif + +////////////////////////////////////////////////////////////////////////////////////// +//following code will be used for romcode +//only signature check +// +////////////////////////////////////////////////////////////////////////////////////// +//following code will be used for romcode +//only signature check +//copy from here... +//return 0 for success, others for fail + +///////////////////////////////////////////////////////////////////////////////////////// +//amlogic secure boot solution +typedef enum{ + AML_SIG_TYPE_NONE=0, + AML_SIG_TYPE_RSA_PKCS_V15, + AML_SIG_TYPE_RSA_PKCS_V21, //?? + AML_SIG_TYPE_RSA_PKCS_V15_AES, +}e_aml_sig_type; + +typedef enum{ + AML_DATA_TYPE_NONE=0, + AML_DATA_TYPE_RSA_KEY, + AML_DATA_TYPE_AES_KEY, + AML_DATA_TYPE_PROGRAM_GO, //need this? + AML_DATA_TYPE_PROGRAM_CALL, //need this? +}e_aml_data_type; + + +#define AML_BLK_ID (0x4C4D4140) +#define AML_BLK_VER_MJR (1) +#define AML_BLK_VER_MIN (0) + + +typedef struct __st_aml_block_header{ + //16 + unsigned int dwMagic; //"@AML" + unsigned int nTotalSize; //total size: sizeof(hdr)+ + // nSigLen + nDataLen + unsigned char bySizeHdr; //sizeof(st_aml_block) + unsigned char byRootKeyIndex;//root key index; only romcode + // will use it, others just skip + unsigned char byVerMajor; //major version + unsigned char byVerMinor; //minor version + + unsigned char szPadding1[4]; //padding??? + + //16+16 + unsigned int nSigType; //e_aml_sig_type : AML_SIG_TYPE_NONE... + unsigned int nSigOffset; //sig data offset, include header + unsigned int nSigLen; //sig data length + //unsigned char szPadding2[4]; //padding??? + unsigned int nCHKStart; //begin to be protected with SHA2 + + //32+16 + unsigned int nPUKType; //e_aml_data_type : AML_DATA_TYPE_PROGRAM + unsigned int nPUKOffset; //raw data offset, include header + unsigned int nPUKDataLen; //raw data length + //unsigned char szPadding4[4]; //padding??? + unsigned int nCHKSize; //size to be protected with SHA2 + + //48+16 + unsigned int nDataType; //e_aml_data_type : AML_DATA_TYPE_PROGRAM + unsigned int nDataOffset; //raw data offset, include header + unsigned int nDataLen; //raw data length + unsigned char szPadding3[4]; //padding??? + + //64 +} st_aml_block_header; + +typedef enum{ + AML_ITEM_TYPE_NONE=0, + AML_ITEM_TYPE_RAW_RSA_N, + AML_ITEM_TYPE_RAW_RSA_E, + AML_ITEM_TYPE_RAW_RSA_D, +}e_aml_big_num_type; + + +typedef struct __stBigNumber{ + //8 + unsigned short nBigNMType; //e_aml_big_num_type + unsigned short nOffset; //offset for each data, after HDR + unsigned short nSize; //size of raw data + unsigned char szReserved[2]; //for future ? padding + //unsigned char szSHA2Item[32];//SHA2 of raw data ?? need this ?? + //8 +}st_BIG_NUMBER; + +typedef struct __stBigNumberStore{ + //8 + unsigned short nBigNMType; //e_aml_big_num_type + unsigned short nOffset; //offset for each data, after HDR + unsigned short nSize; //size of raw data + unsigned char szReserved[2]; //for future ? padding + unsigned char pBuffer[1024]; + //unsigned char szSHA2Item[32];//SHA2 of raw data ?? need this ?? + //8 +}st_BIG_NUMBER_store; + +typedef enum{ + AML_RSA_TYPE_NONE=0, + AML_RSA_TYPE_1024, + AML_RSA_TYPE_2048, + AML_RSA_TYPE_4096, + AML_RSA_TYPE_8192, + AML_RSA_TYPE_1024_SHA2, + AML_RSA_TYPE_2048_SHA2, + AML_RSA_TYPE_4096_SHA2, + AML_RSA_TYPE_8192_SHA2, + +}e_aml_rsa_type_t; + +typedef struct __stItemHeader{ + //4 + unsigned char byCount; //amount + unsigned char byUnitSize; //sizeof(st_BIG_NUMBER) + unsigned char szPad1[2]; //padding + + //4+12 + unsigned short nItemsOffset; //arrBNM[] + unsigned short nItemTotalSize; //(byCount X byUnitSize) + unsigned short nRAWOffset; //arrBNM[] + unsigned short nRAWSize; //sum(arrBNM[byCount].nSize) + unsigned char szPad2[4]; //padding + //16 +}st_ITEM_HDR; + +/* +typedef struct __stItemHeader{ + st_ITEM_HDR header; + //...... + //...... + st_BIG_NUMBER arrBNM[]; +}st_ITEM; +*/ + +#define AML_KEY_ID (0x59454B40) +#define AML_KEY_VER (1) + +#define AML_KEY_RSA1024 (0x41533152) +#define AML_KEY_RSA2048 (0x41533252) +#define AML_KEY_RSA4096 (0x41533452) +#define AML_KEY_RSA8192 (0x41533852) + +#define AML_KEY_RSA1024_SHA (0x41483152) +#define AML_KEY_RSA2048_SHA (0x41483252) +#define AML_KEY_RSA4096_SHA (0x41483452) +#define AML_KEY_RSA8192_SHA (0x41483852) + +typedef struct __stKeyHeader{ + //16 + unsigned int dwMagic; //"@KEY" 0x59454B40 + unsigned int nTotalSize; //total size + unsigned char byVersion; //version + unsigned char byKeyType; //e_aml_rsa_type_t + unsigned char byHeadSize; //sizeof(st_KEY_HDR) + unsigned char szPad1[1]; //padding + unsigned int dwTypeInfo; // + + //16+32 + union{ + unsigned char szKeySHA2[32]; + st_ITEM_HDR itemHdr; + }un; + + //48 +}st_KEY_HDR; + +#define AML_KEY_MATRIX_ID (0x584D4B40) +#define AML_KEY_MATRIX_VER (1) +#define AML_KEY_MAX_KEY_NUM (4) + +typedef struct __stKeyMaxHeader{ + //8 + unsigned int dwMagic; //"@KMX" 0x584D4B40 + unsigned char byVersion; //version + unsigned char szPad1; //padding + unsigned short nHeadSize; //sizeof(st_KEY_MAX_HDR) + + //8+8 + unsigned int nTotalSize; //nHeadSize + (byCount x byUnitSize) + // + sum(arrKeyHdr[byCount].itemHdr.nItemTotalSize) + unsigned char byCount; //key amount + unsigned char byUnitSize; //sizeof(st_KEY_HDR) + unsigned char szPad2[2]; //padding + + //16 +}st_KEY_MAX_HDR; + +//---------------------------------------------- +typedef struct __stKeyMax{ + st_KEY_MAX_HDR header; + st_KEY_HDR arrKeyHdr[4]; +}st_KEY_MAX; + + +#if defined(AML_DEBUG_SHOW) +void aml_u8_printf( unsigned char *p, int size ) +{ + int i; + for (i=0; i<size; i++) + printf("%02X%s", p[i], ((i+1) % 16==0) ? "\n" :" "); +} +#endif + +#if defined(CONFIG_AML_SECURE_UBOOT) +static int aml_key_match_check_tpl(unsigned char szKeySHA2[32]) +{ + int nReturn = -1; + int i = 0; + volatile st_KEY_MAX *pKeyMax = (volatile st_KEY_MAX *)(0xd9000808); + for (i = 0;i<pKeyMax->header.byCount;++i) + { + if (!memcmp(szKeySHA2,(void *)pKeyMax->arrKeyHdr[i].un.szKeySHA2,32)) + { + nReturn = 0; + break; + } + } + + return nReturn; +} +int aml_load_rsa_puk(rsa_context *prsa_ctx, + unsigned char *pBlock,unsigned char szSHA2[32]) +{ + int nRet = -1; + st_aml_block_header *pblkHdr = (st_aml_block_header *)pBlock; + st_KEY_HDR * pkeyHdr = (st_KEY_HDR *)(pBlock + pblkHdr->nPUKOffset); + st_ITEM_HDR * pHdr = (st_ITEM_HDR*)&pkeyHdr->un.itemHdr; + st_BIG_NUMBER *pBGN = (st_BIG_NUMBER *)(pBlock + pHdr->nItemsOffset); + unsigned char *pRAW = (unsigned char *)(pBlock + pHdr->nRAWOffset); + mpi *pMPI = 0; + int i =0; + + if (!prsa_ctx || !pBlock ) + goto exit; + + //following is just for this verison pollarssl code + //just disable them if use the standard copy + //begin + //extern int g_nMX_RSA_keyFormat; + //g_nMX_RSA_keyFormat = 1; + //end + + pblkHdr = (st_aml_block_header *)pBlock; + pkeyHdr = (st_KEY_HDR *)(pBlock + pblkHdr->nPUKOffset); + pHdr = (st_ITEM_HDR*)&pkeyHdr->un.itemHdr; + pBGN = (st_BIG_NUMBER *)(pBlock + pHdr->nItemsOffset); + pRAW = (unsigned char *)(pBlock + pHdr->nRAWOffset); + + + sha2(pRAW,pHdr->nRAWSize,szSHA2,0); + + //u8_printf(pBGN,32); + //u8_printf(pRAW,32); + + for ( i = 0;i< pHdr->byCount;++i) + { + switch (pBGN->nBigNMType) + { + case AML_ITEM_TYPE_RAW_RSA_N: pMPI = &prsa_ctx->N; break; + case AML_ITEM_TYPE_RAW_RSA_E: pMPI = &prsa_ctx->E; break; + case AML_ITEM_TYPE_RAW_RSA_D: pMPI = &prsa_ctx->D; break; + default: pMPI = 0; break; + } + + if (!pMPI) + while (1) ; + + mpi_read_binary(pMPI,pRAW,pBGN->nSize); + + pRAW += pBGN->nSize; + pBGN += 1; + } + + prsa_ctx->len = ( mpi_msb( &prsa_ctx->N ) + 7 ) >> 3; + + switch (prsa_ctx->len) + { + case 0x80: //R1024 + case 0x100: //R2048 + case 0x200: nRet = 0;break; //R4096 + } + +exit: + + return nRet; +} +#endif //CONFIG_AML_SECURE_UBOOT + +///////////////////////////////////////////////////////////////////////// +/** + * pBuffer : st_aml_block_header + signature data + st_aml_block_header(mirror) + [PUK] + raw data + * 1. st_aml_block_header will have offset, length, type for signature data, PUK and raw data + * 2. signature data is a PKCS #1 v1.5 RSA signature of SHA256 (st_aml_block_header(mirror) + [PUK] + raw data) + * signed with the PUK's corresponding private key. + * 3. st_aml_block_header(mirror) is a mirror copy of st_aml_block_header for data consistency + * 4. PUK is a RSA Public Key to be used for signature check (PKCSv15 format) + * 5. raw data: has two types for romcode + * 5.1 1st stage: two keymax : the first is for 4 root key SHA256 and the second is for 4 user key SHA256 + * 5.2 2nd stage: BL2 raw data + * pKeyMax : 4 SHA256 hashes of the keys (N+E) + * 1. for 1st stage: pKeyMax is 0 for the root keymax and user keymax check + * 2. for 2nd stage: pKeyMax is the user keymax to verify the PUK for BL2 signature + * pEntry : offset for BL2 start + * + * return 0 for success and pEntry is the BL2 start address and all others value for check fail +*/ +int aml_sig_check_buffer(unsigned long pBuffer,unsigned int *pEntry) +{ + + int nReturn = __LINE__; +#if defined(CONFIG_AML_SECURE_UBOOT) + rsa_context rsa_ctx; + unsigned char szPUKSHA2[32]; + unsigned char *pSig; +#endif + + int nTick; + +//#define AML_SECURE_LOG_TE 1 + +#if defined(AML_SECURE_LOG_TE) + #define AML_GET_TE(a) do{a = *((volatile unsigned int*)0xc1109988);}while(0); + unsigned nT1,nT2; +#else + #define AML_GET_TE(...) +#endif + + unsigned char *pData=0; + st_aml_block_header * pBlkHdr = 0; + int nBL3XSigFlag = 0; + unsigned char szSHA2[32]; + unsigned char *szAMLBLK= (unsigned char *)(unsigned long)(0x10800000); + sha2_ctx sha_ctx; + pBlkHdr = (st_aml_block_header *)pBuffer; + + aml_printf("aml log : Ln = %d\n",__LINE__); + + if (AML_BLK_ID != pBlkHdr->dwMagic) + goto exit; + + if (AML_BLK_VER_MJR != pBlkHdr->byVerMajor) + goto exit; + if (AML_BLK_VER_MIN != pBlkHdr->byVerMinor) + goto exit; + + if (sizeof(st_aml_block_header) != pBlkHdr->bySizeHdr) + goto exit; + + //more check + if (sizeof(st_aml_block_header) != pBlkHdr->nSigOffset) + goto exit; + + aml_printf("aml log : Ln = %d\n",__LINE__); + + nReturn = __LINE__; + +#if defined(CONFIG_AML_SECURE_UBOOT) + //RSA key load + rsa_init( &rsa_ctx, RSA_PKCS_V15, 0 ); +#endif //CONFIG_AML_SECURE_UBOOT + + switch (pBlkHdr->nSigType) + { +#if defined(CONFIG_AML_SECURE_UBOOT) + case AML_RSA_TYPE_1024: + case AML_RSA_TYPE_2048: + case AML_RSA_TYPE_4096: + { + switch (pBlkHdr->nSigLen) + { + case 0x80: //R1024 + case 0x100: //R2048 + case 0x200: //R4096 + { + nBL3XSigFlag = 1; + if (aml_load_rsa_puk(&rsa_ctx,(unsigned char *)pBuffer,szPUKSHA2)) + goto exit; + + aml_printf("aml log : PUK is RSA%d\n",(rsa_ctx.len<<3)); + + }break;//R4096 + default: goto exit; + } + }break; +#endif //CONFIG_AML_SECURE_UBOOT + case AML_RSA_TYPE_NONE:break; + default: goto exit; + } + + aml_printf("aml log : Ln = %d\n",__LINE__); + + nReturn = __LINE__; + //check chip is secure enabled or not + //if enabled just fail for next boot device + //if(aml_check_secure_set_match(nBL3XSigFlag)) + // goto exit; + + nTick = 64 - (pBlkHdr->nPUKDataLen & (63)); + //backup header + memcpy((void*)szAMLBLK,(void*)pBuffer,pBlkHdr->nDataOffset); + pBlkHdr = (st_aml_block_header *)szAMLBLK; + + flush_dcache_range((unsigned long )szAMLBLK, pBlkHdr->nDataOffset); + + //move original + memcpy((void*)pBuffer,(void *)(pBuffer + pBlkHdr->nDataLen),pBlkHdr->nDataOffset); + + flush_dcache_range((unsigned long )pBuffer, pBlkHdr->nDataOffset); + + memcpy((void*)(szAMLBLK+pBlkHdr->nDataOffset),(void*)pBuffer,nTick); + flush_dcache_range((unsigned long )(szAMLBLK+pBlkHdr->nDataOffset), nTick); + + aml_printf("aml log : Ln = %d\n",__LINE__); + + pData =(unsigned char *)(szAMLBLK + pBlkHdr->nCHKStart); + +#if defined(CONFIG_AML_SECURE_UBOOT) + pSig = (unsigned char *)(szAMLBLK + pBlkHdr->nSigOffset); +#endif //#if defined(CONFIG_AML_SECURE_UBOOT) + + AML_GET_TE(nT1); + + SHA2_init( &sha_ctx, 256); + //hash header + SHA2_update( &sha_ctx, szAMLBLK, pBlkHdr->bySizeHdr); + //skip signature + //hash PUK + SHA2_update( &sha_ctx, pData, pBlkHdr->nPUKDataLen+nTick); + SHA2_final( &sha_ctx, (unsigned char *)(pBuffer+nTick), pBlkHdr->nDataLen-nTick); + AML_GET_TE(nT2); + + //flush_dcache_range((unsigned long )sha_ctx.buf,32); + +#if defined(AML_SECURE_LOG_TE) + printf("aml log : SHA %d (bytes) used %d(us)\n",pBlkHdr->nDataLen+ pBlkHdr->nPUKDataLen +pBlkHdr->bySizeHdr, + nT2 - nT1); +#endif + + memcpy(szSHA2,sha_ctx.buf,32); + + flush_dcache_range((unsigned long )szSHA2,32); + +#if defined(AML_DEBUG_SHOW) + aml_printf("\naml log : dump cal SHA2 :\n"); + aml_u8_printf((unsigned char *)szSHA2,32); +#endif + + if (!nBL3XSigFlag) + { + aml_printf("aml log : normal check Ln = %d\n",__LINE__); + nReturn = memcmp((const void*)szSHA2, + (const void*)(szAMLBLK+pBlkHdr->nSigOffset),sizeof(szSHA2)); + +#if defined(AML_DEBUG_SHOW) + aml_printf("\naml log : dump org SHA :\n"); + aml_u8_printf((unsigned char *)(szAMLBLK+pBlkHdr->nSigOffset),32); +#endif + //if(!nReturn && pEntry) + // *pEntry = 0; + //else + if (nReturn) + nReturn = __LINE__; + + goto exit; + } + +#if defined(CONFIG_AML_SECURE_UBOOT) + //verify PUK is valid or not + if (aml_key_match_check_tpl(szPUKSHA2)) + { + //error + aml_printf("aml log: PUK is not a valid key!\n"); + nReturn = __LINE__; + goto exit; + } + + nReturn = rsa_pkcs1_verify( &rsa_ctx, RSA_PUBLIC, SIG_RSA_SHA256,32, szSHA2, pSig ); + + if (nReturn) + { + aml_printf("aml log : Sig check fail! Return = %d\n",nReturn); + nReturn = __LINE__; + goto exit; + } + else + { + aml_printf("aml log : Sig check pass!\n"); + + if (pEntry) + *pEntry = 0; + + } + + //printf("aml log : RSA-%d check %s!\n",rsa_ctx.len<<3, nReturn ? "fail": "pass"); + serial_puts("aml log : RSA-"); + serial_put_dec(rsa_ctx.len<<3); + serial_puts(" check "); + serial_puts(nReturn ? "fail": "pass"); + serial_puts("!\n"); +#endif //CONFIG_AML_SECURE_UBOOT + +exit: + + return nReturn; +} + +#if defined(CONFIG_AML_SECURE_UBOOT) + +//#define CONFIG_AML_HW_AES_PIO + +#if defined(CONFIG_AML_HW_AES_PIO) +void aes_setkey( const uint8_t *key) +{ + uint32_t i; + uint32_t *key32 = (uint32_t *)key; + + // select aes + clrbits_le32(SEC_SEC_BLKMV_GEN_REG0, (3<<12)); + + // setup aes 256 cbc decrypto pio + writel((2<<18) | (1<<16), SEC_SEC_BLKMV_AES_REG0); + + // aes=4, request pio and wait for grant. + writel((1<<4) | 4, SEC_SEC_BLKMV_PIO_CNTL0); + while (((readl(SEC_SEC_BLKMV_PIO_CNTL0) >> 31) & 1) == 0); + + // Write the Key + for (i=0; i<8; i++) { + writel(key32[i], SEC_SEC_BLKMV_PIO_DATA0 + i*4); + } + + //set IV + for (i=0; i<4; i++) writel(0, SEC_SEC_BLKMV_PIO_DATA8 + i*4); + + // load iv + setbits_le32(SEC_SEC_BLKMV_AES_REG0, (1<<1)); + +} + +/** + * Perform AES 256 CBC decryption + * cpt: array of 16 bytes of cipher text and plain text output + */ +void aes_cbc_decrypt(uint32_t *cpt) +{ + uint32_t i; + + for (i=0; i<4; i++) writel(cpt[i], SEC_SEC_BLKMV_AES_PIO_W0 + i*4); + + // Wait for the AES process to complete + while ((readl(SEC_NDMA_CNTL_REG0) >> 12) & 1) ; + + for (i=0; i<4; i++) cpt[i] = readl(SEC_SEC_BLKMV_PIO_DATA0 + i*4); +} +#else +//HW AES DMA +#define AES_Wr(addr, data) *(volatile uint32_t *)(addr)=(data) +#define AES_Rd(addr) *(volatile uint32_t *)(addr) +#define THREAD0_TABLE_LOC 0x5500000 +int g_n_aes_thread_num = 0; +void aes_setkey( const uint8_t *key) +{ + uint32_t *key32 = (uint32_t *)key; + + g_n_aes_thread_num = 0; //fixed thread number to 0 + + AES_Wr( SEC_SEC_BLKMV_PIO_CNTL0, (AES_Rd(SEC_SEC_BLKMV_PIO_CNTL0)| (5<<0)) ); + + AES_Wr(SEC_SEC_BLKMV_GEN_REG0, ((AES_Rd(SEC_SEC_BLKMV_GEN_REG0) & ~(0xf << 8)) | (0xf << 8)) ); + AES_Wr(SEC_SEC_BLKMV_GEN_REG0, ((AES_Rd(SEC_SEC_BLKMV_GEN_REG0) & ~(0xf << 0)) | (0 << 0)) ); + + AES_Wr(SEC_SEC_BLKMV_GEN_REG0, ((AES_Rd(SEC_SEC_BLKMV_GEN_REG0) & ~(0xf << 4)) | (0x0<< 4)) ); // only thread 2 can issue Secure transfers + + AES_Wr( SEC_SEC_BLKMV_AES_REG0, (AES_Rd(SEC_SEC_BLKMV_AES_REG0) & ~(0x1 << 3)) ); + AES_Wr( NDMA_AES_REG0, (AES_Rd(NDMA_AES_REG0) & ~(0x3 << 8)) | (g_n_aes_thread_num << 8) ); + + //key + AES_Wr( NDMA_AES_KEY_0, (key32[0]) ); + AES_Wr( NDMA_AES_KEY_1, (key32[1]) ); + AES_Wr( NDMA_AES_KEY_2, (key32[2]) ); + AES_Wr( NDMA_AES_KEY_3, (key32[3]) ); + AES_Wr( NDMA_AES_KEY_4, (key32[4]) ); + AES_Wr( NDMA_AES_KEY_5, (key32[5]) ); + AES_Wr( NDMA_AES_KEY_6, (key32[6]) ); + AES_Wr( NDMA_AES_KEY_7, (key32[7]) ); + + //set IV + AES_Wr( NDMA_AES_IV_0, 0); + AES_Wr( NDMA_AES_IV_1, 0); + AES_Wr( NDMA_AES_IV_2, 0); + AES_Wr( NDMA_AES_IV_3, 0); + + NDMA_set_table_position_secure( g_n_aes_thread_num, THREAD0_TABLE_LOC, THREAD0_TABLE_LOC + (10*32) ); // 2 thread entries + +} + +void aes_cbc_decrypt(uint32_t *ct,uint32_t *pt,int nLen) +{ + NDMA_add_descriptor_aes( g_n_aes_thread_num, // uint32_t thread_num, + 1, // uint32_t irq, + 1, // uint32_t cbc_enable, + 1, // uint32_t cbc_reset, + 0, // uint32_t encrypt, // 0 = decrypt, 1 = encrypt + 2, // uint32_t aes_type, // 00 = 128, 01 = 192, 10 = 256 + 0, // uint32_t pre_endian, + 0, // uint32_t post_endian, + nLen, // uint32_t bytes_to_move, + (unsigned int)(long)ct, // uint32_t src_addr, + (unsigned int)(long)pt, // uint32_t dest_addr ) + 0xf, // uint32_t ctr_endian, + 0 ); // uint32_t ctr_limit ) + NDMA_start(g_n_aes_thread_num); + + NDMA_wait_for_completion(g_n_aes_thread_num); + + NDMA_stop(g_n_aes_thread_num); + +} + +#endif +#endif //CONFIG_AML_SECURE_UBOOT + +int aml_data_check(unsigned long pBuffer,unsigned long pBufferDST,unsigned int nLength,unsigned int nAESFlag) +{ + +#define TOC_HEADER_NAME (0xAA640001) +#define TOC_HEADER_SERIAL_NUMBER (0x12345678) + +#if defined(CONFIG_AML_SECURE_UBOOT) + unsigned char szAESKey[32]; + #if defined(CONFIG_AML_HW_AES_PIO) + unsigned int *ct32; + int i = 0; + #endif + unsigned char *pDST= (unsigned char *)(pBufferDST); +#endif //CONFIG_AML_SECURE_UBOOT + +#if defined(AML_DEBUG_SHOW) + int nBegin,nEnd; +#endif + + unsigned int *pCHK = (unsigned int *)pBuffer; + +#if defined(AML_DEBUG_SHOW) + nBegin = *((volatile unsigned int*)0xc1109988); +#endif + + if (TOC_HEADER_NAME == *pCHK && TOC_HEADER_SERIAL_NUMBER == *(pCHK+1)) + { + return 0; + } + + +#if defined(CONFIG_AML_SECURE_UBOOT) + +#if defined(AML_DEBUG_SHOW) + aml_printf("aml log : begin dump buffer before AES nTPLAESFlag = %d:\n",nAESFlag); + aml_u8_printf((unsigned char *)pBuffer,32); +#endif + + if (nAESFlag) + { + + if (nAESFlag) + pCHK = (unsigned int*)pDST; + + sha2((unsigned char *)0xd9000000,16,szAESKey,0); + aes_setkey(szAESKey); + +#if defined(CONFIG_AML_HW_AES_PIO) + //HW AES PIO + ct32 = (unsigned int *)pBuffer; + + for (i=0; i<nLength/16; i++) + aes_cbc_decrypt(&ct32[i*4]); + + memcpy(pDST,(void*)pBuffer,nLength); +#else + //HW AES DMA + aes_cbc_decrypt((unsigned int *)pBuffer,(unsigned int *)pDST,nLength); +#endif + pBuffer = (unsigned long)pDST; + + flush_dcache_range((unsigned long )pDST, nLength); + +#if defined(AML_DEBUG_SHOW) + nEnd = *((volatile unsigned int*)0xc1109988); + aml_printf("aml log : begin dump buffer after AES nTPLAESFlag=%d len=%d time=%dus\n", + nAESFlag,nLength,nEnd - nBegin); + aml_u8_printf((unsigned char *)pBuffer,32); +#endif + if (TOC_HEADER_NAME == *pCHK && TOC_HEADER_SERIAL_NUMBER == *(pCHK+1)) + return 0; + } + +#if defined(AML_DEBUG_SHOW) + aml_printf("aml log : begin dump buffer after AES nTPLAESFlag = %d:\n",nAESFlag); + aml_u8_printf((unsigned char *)pBuffer,32); +#endif + +#endif //CONFIG_AML_SECURE_UBOOT + + return aml_sig_check_buffer(pBuffer,0); + +} + + +////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////// diff --git a/plat/gxb/ddr/ddr.c b/plat/gxb/ddr/ddr.c new file mode 100644 index 0000000..68438c6 --- /dev/null +++ b/plat/gxb/ddr/ddr.c @@ -0,0 +1,863 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/ddr/ddr.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <stdio.h> +#include "ddr_pctl_define.h" +#include "ddr_pub_define.h" +#include "dmc_define.h" +#include "mmc_define.h" +#include "sec_mmc_define.h" +#include <timer.h> +#include <asm/arch/ddr.h> +#include <asm/arch/secure_apb.h> +#include <pll.h> +#include <config.h> +#include <asm/arch/cpu.h> +#include <asm/arch/timing.h> +#include <memtest.h> +#include <asm/arch/watchdog.h> +#include <cache.h> +#include "timing.c" +#include "ddr_detect.c" + +static ddr_set_t * p_ddr_set = &__ddr_setting; +static ddr_timing_t * p_ddr_timing = NULL; +static unsigned int ddr0_enabled; +static unsigned int ddr1_enabled; + +unsigned int ddr_init(void){ + /*detect hot boot or cold boot*/ + //if(hot_boot()){ + // serial_puts("hot boot, skip ddr init!\n"); + // return 0; + //} + + ddr_init_pll(); + ddr_pre_init(); + ddr_init_pctl(); + ddr_init_dmc(); + ddr_print_info(); +#ifndef CONFIG_PXP_EMULATOR +//can not enable ddr test on pxp, for kernel and dtb already load in ddr +#ifdef CONFIG_SPL_DDR_DUMP + if (CONFIG_SPL_DDR_DUMP_FLAG != readl(P_PREG_STICKY_REG0)) { + ddr_test(); + } +#else + ddr_test(); +#endif +#endif + return 0; +} + +unsigned int ddr_init_pll(void){ + wr_reg(P_AM_ANALOG_TOP_REG1, rd_reg(P_AM_ANALOG_TOP_REG1) | (1<<0)); + wr_reg(P_HHI_MPLL_CNTL5, rd_reg(P_HHI_MPLL_CNTL5) | (1<<0)); + + /* DDR PLL BANDGAP */ + wr_reg(AM_DDR_PLL_CNTL4, rd_reg(AM_DDR_PLL_CNTL4) & (~(1<<12))); + wr_reg(AM_DDR_PLL_CNTL4, rd_reg(AM_DDR_PLL_CNTL4)|(1<<12)); + _udelay(10); + + /* set ddr pll reg */ + if ((p_ddr_set->ddr_clk >= CONFIG_DDR_CLK_LOW) && (p_ddr_set->ddr_clk < 750)) { + // OD N M + p_ddr_set->ddr_pll_ctrl = (2 << 16) | (1 << 9) | ((((p_ddr_set->ddr_clk/6)*6)/12) << 0); + } + else if((p_ddr_set->ddr_clk >= 750) && (p_ddr_set->ddr_clk < CONFIG_DDR_CLK_HIGH)) { + // OD N M + p_ddr_set->ddr_pll_ctrl = (1 << 16) | (1 << 9) | ((((p_ddr_set->ddr_clk/12)*12)/24) << 0); + } + + /* if enabled, change ddr pll setting */ +#ifdef CONFIG_CMD_DDR_TEST + serial_puts("STICKY_REG0: 0x"); + serial_put_hex(rd_reg(P_PREG_STICKY_REG0), 32); + serial_puts("\n"); + serial_puts("STICKY_REG1: 0x"); + serial_put_hex(rd_reg(P_PREG_STICKY_REG1), 32); + serial_puts("\n"); + if ((rd_reg(P_PREG_STICKY_REG0)>>20) == 0xf13) { + unsigned zqcr = rd_reg(P_PREG_STICKY_REG0) & 0xfffff; + if (0 == zqcr) + zqcr = p_ddr_set->t_pub_zq0pr; + serial_puts("ZQCR: 0x"); + serial_put_hex(p_ddr_set->t_pub_zq0pr, 32); + serial_puts(" -> 0x"); + serial_put_hex(zqcr, 32); + serial_puts("\n"); + p_ddr_set->t_pub_zq0pr = zqcr; + p_ddr_set->t_pub_zq1pr = zqcr; + p_ddr_set->t_pub_zq2pr = zqcr; + p_ddr_set->t_pub_zq3pr = zqcr; + serial_puts("PLL : 0x"); + serial_put_hex(p_ddr_set->ddr_pll_ctrl, 32); + serial_puts(" -> 0x"); + serial_put_hex(rd_reg(P_PREG_STICKY_REG1), 32); + serial_puts("\n"); + p_ddr_set->ddr_pll_ctrl = rd_reg(P_PREG_STICKY_REG1); + wr_reg(P_PREG_STICKY_REG0,0); + wr_reg(P_PREG_STICKY_REG1,0); + } +#endif + + /* ddr pll init */ + do { + //wr_reg(AM_DDR_PLL_CNTL1, 0x1); + wr_reg(AM_DDR_PLL_CNTL, (1<<29)); + wr_reg(AM_DDR_PLL_CNTL1, CFG_DDR_PLL_CNTL_1); + wr_reg(AM_DDR_PLL_CNTL2, CFG_DDR_PLL_CNTL_2); + wr_reg(AM_DDR_PLL_CNTL3, CFG_DDR_PLL_CNTL_3); + wr_reg(AM_DDR_PLL_CNTL4, CFG_DDR_PLL_CNTL_4); + wr_reg(AM_DDR_PLL_CNTL, ((1<<29) | (p_ddr_set->ddr_pll_ctrl))); + wr_reg(AM_DDR_PLL_CNTL, rd_reg(AM_DDR_PLL_CNTL)&(~(1<<29))); + _udelay(200); + }while(pll_lock_check(AM_DDR_PLL_CNTL, "DDR PLL")); + + /* Enable the DDR DLL clock input from PLL */ + wr_reg(DDR_CLK_CNTL, 0xb0000000); + wr_reg(DDR_CLK_CNTL, 0xb0000000); + + /* update ddr_clk */ + unsigned int ddr_pll = rd_reg(AM_DDR_PLL_CNTL)&(~(1<<29)); + unsigned int ddr_clk = 2*(((24 * (ddr_pll&0x1ff))/((ddr_pll>>9)&0x1f))>>((ddr_pll>>16)&0x3)); + p_ddr_set->ddr_clk = ddr_clk; + + return 0; +} + +void ddr_print_info(void){ + if (p_ddr_set->ddr_size_detect) + ddr_size_detect(p_ddr_set); + + unsigned int dmc_reg = rd_reg(DMC_DDR_CTRL); + unsigned char ddr_2t_mode = 0; + unsigned char ddr_chl = DDR_USE_2_CHANNEL(p_ddr_set->ddr_channel_set); + + /* 0:1t, 1:2t, 2:f2t(force) */ + ddr_2t_mode = ((rd_reg(DDR0_PCTL_MCFG) >> 3) & 0x1); + if (p_ddr_set->ddr_channel_set == CONFIG_DDR01_SHARE_AC) + ddr_2t_mode = 2; + + for (int i=0; i<=ddr_chl; i++) { + /* ddr info */ + serial_puts("DDR"); + serial_put_dec(i); + serial_puts(": "); + serial_put_dec(1 << (((dmc_reg>>(3*i)) & 0x7)+7)); + serial_puts("MB"); + if (p_ddr_set->ddr_size_detect) + serial_puts("(auto)"); + serial_puts(" @ "); + serial_put_dec(p_ddr_set->ddr_clk); + serial_puts("MHz("); + serial_puts(((ddr_2t_mode==2)?"F1T":((ddr_2t_mode==1)?"2T":"1T"))); + serial_puts(")-"); + serial_put_dec(p_ddr_set->ddr_timing_ind); + serial_puts("\n"); + } + + /* write ddr size to reg */ + wr_reg(SEC_AO_SEC_GP_CFG0, ((rd_reg(SEC_AO_SEC_GP_CFG0) & 0x0000ffff) | ((p_ddr_set->ddr_size) << 16))); +} + +unsigned int ddr_init_dmc(void){ + unsigned int ddr0_size = 0, ddr1_size = 0; + unsigned int ddr0_size_reg = 0, ddr1_size_reg = 0; +// unsigned int i=0, j=0, convert_reg_size = 6; + + /* transfer correct dmc ctrl setting */ + unsigned int ddr_one_chl = DDR_USE_1_CHANNEL(p_ddr_set->ddr_channel_set); + ddr0_size = (p_ddr_set->ddr_size)>>(7-ddr_one_chl); + ddr1_size = ddr_one_chl?0x7:((p_ddr_set->ddr_size)>>7); + ddr1_size_reg=ddr_one_chl?0x5:0x0; + while (!((ddr0_size>>=1)&0x1)) + ddr0_size_reg++; + while (!((ddr1_size>>=1)&0x1)) + ddr1_size_reg++; + + p_ddr_set->ddr_dmc_ctrl &= (~0x3f); //clear ddr capacity reg bits + p_ddr_set->ddr_dmc_ctrl |= ((ddr0_size_reg)|(ddr1_size_reg<<3)); + + wr_reg(DMC_DDR_CTRL, p_ddr_set->ddr_dmc_ctrl); + if ((p_ddr_set->ddr_channel_set == CONFIG_DDR01_SHARE_AC)|| + (p_ddr_set->ddr_channel_set == CONFIG_DDR0_ONLY_16BIT))//jiaxing find use 16bit channel 0 only must write map0-4? + { + //CONIFG DDR PHY comamnd address map to 32bits linear address. + //DDR0 ROW 14:0. DDR1 ROW 13:0. COL 9:0. + wr_reg( DDR0_ADDRMAP_0, ( 0 | 5 << 5 | 6 << 10 | 7 << 15 | 8 << 20 | 9 << 25 )); + wr_reg( DDR0_ADDRMAP_1, ( 13| 30<< 5 | 0 << 10 | 10 << 15 | 11 << 20 | 12 << 25 )); + //wr_reg( DDR0_ADDRMAP_1, ( 0| 0 << 5 | 0 << 10 | 10 << 15 | 11 << 20 | 12 << 25 )); + wr_reg( DDR0_ADDRMAP_2, ( 16| 17 << 5 | 18 << 10 | 19 << 15 | 20 << 20 | 21 << 25 )); + wr_reg( DDR0_ADDRMAP_3, ( 22| 23 << 5 | 24 << 10 | 25 << 15 | 26 << 20 | 27 << 25 )); + wr_reg( DDR0_ADDRMAP_4, ( 29| 14 << 5 | 15 << 10 | 28 << 15 | 0 << 20 | 0 << 25 )); + + wr_reg( DDR1_ADDRMAP_0, ( 0 | 5 << 5 | 6 << 10 | 7 << 15 | 8 << 20 | 9 << 25 )); + wr_reg( DDR1_ADDRMAP_1, ( 13| 30<< 5 | 0 << 10 | 10 << 15 | 11 << 20 | 12 << 25 )); + //wr_reg( DDR1_ADDRMAP_1, ( 13| 0 << 5 | 0 << 10 | 10 << 15 | 11 << 20 | 12 << 25 )); + wr_reg( DDR1_ADDRMAP_2, ( 16| 17 << 5 | 18 << 10 | 19 << 15 | 20 << 20 | 21 << 25 )); + wr_reg( DDR1_ADDRMAP_3, ( 22| 23 << 5 | 24 << 10 | 25 << 15 | 26 << 20 | 27 << 25 )); + wr_reg( DDR1_ADDRMAP_4, ( 29| 14 << 5 | 15 << 10 | 28 << 15 | 0 << 20 | 0 << 25 )); + } + else if(p_ddr_set->ddr_channel_set == CONFIG_DDR0_RANK01_SAME){ + //wr_reg( DDR0_ADDRMAP_1, ( 11| 0 << 5 | 0 << 10 | 0 << 15 | 15 << 20 | 16 << 25 )); + wr_reg( DDR0_ADDRMAP_1, ( 11| 31 << 5 | 0 << 10 | 14 << 15 | 15 << 20 | 16 << 25 )); + wr_reg( DDR0_ADDRMAP_4, ( 30| 12 << 5 | 13 << 10 | 29 << 15 | 0 << 20 | 0 << 25 )); + } + else if(p_ddr_set->ddr_channel_set == CONFIG_DDR0_RANK01_DIFF){ + //wr_reg( DDR0_ADDRMAP_1, ( 11| 0 << 5 | 0 << 10 | 0 << 15 | 15 << 20 | 16 << 25 )); + wr_reg( DDR0_ADDRMAP_1, ( 11| 31 << 5 | 0 << 10 | 14 << 15 | 15 << 20 | 16 << 25 )); + wr_reg( DDR0_ADDRMAP_4, ( 0| 12 << 5 | 13 << 10 | 29 << 15 | 0 << 20 | 30 << 25 )); + } + + wr_reg(DMC_PCTL_LP_CTRL, 0x440620); + //wr_reg(DDR0_APD_CTRL, 0x45); + wr_reg(DDR0_APD_CTRL, (0x20<<8)|(0x20)); + wr_reg(DDR0_CLK_CTRL, 0x5); + + // disable AXI port0 (CPU) IRQ/FIQ security control. + wr_reg(DMC_AXI0_QOS_CTRL1, 0x11); + + //CONFIG DMC security register to enable the all reqeust can access all DDR region. + wr_reg(DMC_SEC_RANGE_CTRL, 0x0 ); + wr_reg(DMC_SEC_CTRL, 0x80000000 ); + wr_reg(DMC_SEC_AXI_PORT_CTRL, 0x55555555); + wr_reg(DMC_DEV_SEC_READ_CTRL, 0x55555555 ); + wr_reg(DMC_DEV_SEC_WRITE_CTRL, 0x55555555 ); + wr_reg(DMC_GE2D_SEC_CTRL, 0x15); + wr_reg(DMC_PARSER_SEC_CTRL, 0x5); + wr_reg(DMC_VPU_SEC_CFG, 0xffffffff); + wr_reg(DMC_VPU_SEC_WRITE_CTRL, 0x55555555 ); + wr_reg(DMC_VPU_SEC_READ_CTRL, 0x55555555 ); + wr_reg(DMC_VDEC_SEC_CFG, 0xffffffff); + wr_reg(DMC_VDEC_SEC_WRITE_CTRL, 0x55555555 ); + wr_reg(DMC_VDEC_SEC_READ_CTRL, 0x55555555 ); + wr_reg(DMC_HCODEC_SEC_CFG, 0xffffffff); + wr_reg(DMC_HCODEC_SEC_WRITE_CTRL, 0x55555555 ); + wr_reg(DMC_HCODEC_SEC_READ_CTRL, 0x55555555 ); + wr_reg(DMC_HEVC_SEC_CFG, 0xffffffff); + wr_reg(DMC_HEVC_SEC_WRITE_CTRL, 0x55555555 ); + wr_reg(DMC_HEVC_SEC_READ_CTRL, 0x55555555 ); + + //// ENABLE THE DC_REQS. + wr_reg(DMC_REQ_CTRL, 0xFFFF); + + // SCRATCH1 + wr_reg(0xC1107d40, 0xbaadf00d); + + // PUT SOME CODE HERE TO TRY TO STOP BUS TRAFFIC + __asm__ volatile("NOP"); + __asm__ volatile("DMB SY"); + __asm__ volatile("ISB"); + + // REMAP THE ADDRESS SPACE BY WRITING TO NIC400 REMAP REGISTER + //wr_reg(0xC1300000, 0x00000001); + //__asm__ volatile("ISB"); + //__asm__ volatile("DMB SY"); + + return 0; +} + +unsigned int ddr_init_pctl(void){ + ddr0_enabled = !(((p_ddr_set->ddr_dmc_ctrl) >> 7) & 0x1); //check if ddr1 only enabled + ddr1_enabled = !(((p_ddr_set->ddr_dmc_ctrl) >> 6) & 0x1); //check if ddr0 only enabled + + // RELEASE THE DDR DLL RESET PIN. + wr_reg(DMC_SOFT_RST, 0xFFFFFFFF); + wr_reg(DMC_SOFT_RST1, 0xFFFFFFFF); + + // ENABLE UPCTL AND PUB CLOCK AND RESET. + //@@@ enable UPCTL and PUB clock and reset. + wr_reg(DMC_PCTL_LP_CTRL, 0x550620); + wr_reg(DDR0_SOFT_RESET, 0xf); + + // INITIALIZATION PHY. + // FOR SIMULATION TO REDUCE THE INIT TIME. + //wr_reg(DDR0_PUB_PTR0, p_ddr_set->t_pub_ptr[0]); + //wr_reg(DDR0_PUB_PTR1, p_ddr_set->t_pub_ptr[1]); + //wr_reg(DDR0_PUB_PTR3, p_ddr_set->t_pub_ptr[3]); + //wr_reg(DDR0_PUB_PTR4, p_ddr_set->t_pub_ptr[4]); + + wr_reg(DDR0_PUB_IOVCR0, 0x49494949); + wr_reg(DDR0_PUB_IOVCR1, 0x49494949); + + // CONFIGURE DDR PHY PUBL REGISTERS. + wr_reg(DDR0_PUB_ODTCR, p_ddr_set->t_pub_odtcr); + + // PROGRAM PUB MRX REGISTERS. + wr_reg(DDR0_PUB_MR0, p_ddr_set->t_pub_mr[0]); + wr_reg(DDR0_PUB_MR1, p_ddr_set->t_pub_mr[1]); + wr_reg(DDR0_PUB_MR2, p_ddr_set->t_pub_mr[2]); + wr_reg(DDR0_PUB_MR3, p_ddr_set->t_pub_mr[3]); + + // PROGRAM DDR SDRAM TIMING PARAMETER. + wr_reg(DDR0_PUB_DTPR0, p_ddr_set->t_pub_dtpr[0]); + wr_reg(DDR0_PUB_DTPR1, p_ddr_set->t_pub_dtpr[1]); + //wr_reg(DDR0_PUB_PGCR0, p_ddr_set->t_pub_pgcr0); //Jiaxing debug low freq issue + wr_reg(DDR0_PUB_PGCR1, p_ddr_set->t_pub_pgcr1); + wr_reg(DDR0_PUB_PGCR2, p_ddr_set->t_pub_pgcr2); + //wr_reg(DDR0_PUB_PGCR2, 0x00f05f97); + wr_reg(DDR0_PUB_PGCR3, p_ddr_set->t_pub_pgcr3); + wr_reg(DDR0_PUB_DXCCR, p_ddr_set->t_pub_dxccr); + + wr_reg(DDR0_PUB_DTPR2, p_ddr_set->t_pub_dtpr[2]); + wr_reg(DDR0_PUB_DTPR3, p_ddr_set->t_pub_dtpr[3]); + wr_reg(DDR0_PUB_DTCR, p_ddr_set->t_pub_dtcr); //use mpr |(1<<6) + + //DDR0_DLL_LOCK_WAIT + wait_set(DDR0_PUB_PGSR0, 0); + + //wr_reg(DDR0_PUB_DTCR, 0x430030c7); + //wr_reg(DDR0_PUB_DTPR3, 0x2010a902); //tmp disable + wr_reg(DDR0_PUB_ACIOCR1, 0); + wr_reg(DDR0_PUB_ACIOCR2, 0); + wr_reg(DDR0_PUB_ACIOCR3, 0); + wr_reg(DDR0_PUB_ACIOCR4, 0); + wr_reg(DDR0_PUB_ACIOCR5, 0); + wr_reg(DDR0_PUB_DX0GCR1, 0); + wr_reg(DDR0_PUB_DX0GCR2, 0); + wr_reg(DDR0_PUB_DX0GCR3, (0x1<<10)|(0x2<<12)); //power down dm recevier + wr_reg(DDR0_PUB_DX1GCR1, 0); + wr_reg(DDR0_PUB_DX1GCR2, 0); + wr_reg(DDR0_PUB_DX1GCR3, (0x1<<10)|(0x2<<12));//power down dm recevier + wr_reg(DDR0_PUB_DX2GCR1, 0); + wr_reg(DDR0_PUB_DX2GCR2, 0); + wr_reg(DDR0_PUB_DX2GCR3, (0x1<<10)|(0x2<<12));//power down dm recevier + wr_reg(DDR0_PUB_DX3GCR1, 0); + wr_reg(DDR0_PUB_DX3GCR2, 0); + wr_reg(DDR0_PUB_DX3GCR3, (0x1<<10)|(0x2<<12));//power down dm recevier + + // 2:0 011: DDR0_ MODE. 100: LPDDR2 MODE. + // 3: 8 BANK. + // 7; MPR FOR DATA TRAINING. + wr_reg(DDR0_PUB_DCR, p_ddr_set->t_pub_dcr); //use mpr |(1<<7) + + wr_reg(DDR0_PUB_DTAR0, p_ddr_set->t_pub_dtar); + wr_reg(DDR0_PUB_DTAR1, (0X8 | p_ddr_set->t_pub_dtar)); + wr_reg(DDR0_PUB_DTAR2, (0X10 | p_ddr_set->t_pub_dtar)); + wr_reg(DDR0_PUB_DTAR3, (0X18 | p_ddr_set->t_pub_dtar)); + + //// DDR PHY INITIALIZATION +#ifdef CONFIG_PXP_EMULATOR + wr_reg(DDR0_PUB_PIR, 0X581); +#endif + wr_reg(DDR0_PUB_DSGCR, p_ddr_set->t_pub_dsgcr); + + //DDR0_SDRAM_INIT_WAIT : + wait_set(DDR0_PUB_PGSR0, 0); + + if (ddr0_enabled) { + // configure DDR0 IP. + wr_reg(DDR0_PCTL_TOGCNT1U, p_ddr_set->t_pctl0_1us_pck); + wr_reg(DDR0_PCTL_TOGCNT100N, p_ddr_set->t_pctl0_100ns_pck); + wr_reg(DDR0_PCTL_TINIT, p_ddr_set->t_pctl0_init_us); //20 + wr_reg(DDR0_PCTL_TRSTH, p_ddr_set->t_pctl0_rsth_us); //50 + wr_reg(DDR0_PCTL_MCFG, (p_ddr_set->t_pctl0_mcfg)|((p_ddr_set->ddr_2t_mode)?(1<<3):(0<<3))); + if (p_ddr_set->ddr_channel_set == CONFIG_DDR01_SHARE_AC) + wr_reg(DDR0_PCTL_MCFG1, ((p_ddr_set->t_pctl0_mcfg1)&0xFFFFFF00)); + else + wr_reg(DDR0_PCTL_MCFG1, p_ddr_set->t_pctl0_mcfg1); + } + + if (ddr1_enabled) { + // configure DDR1 IP. + wr_reg(DDR1_PCTL_TOGCNT1U, p_ddr_set->t_pctl0_1us_pck); + wr_reg(DDR1_PCTL_TOGCNT100N, p_ddr_set->t_pctl0_100ns_pck); + wr_reg(DDR1_PCTL_TINIT, p_ddr_set->t_pctl0_init_us); //20 + wr_reg(DDR1_PCTL_TRSTH, p_ddr_set->t_pctl0_rsth_us); //50 + wr_reg(DDR1_PCTL_MCFG, (p_ddr_set->t_pctl0_mcfg)|((p_ddr_set->ddr_2t_mode)?(1<<3):(0<<3))); + //wr_reg(DDR1_PCTL_MCFG1, p_ddr_set->t_pctl0_mcfg1); + if (p_ddr_set->ddr_channel_set == CONFIG_DDR01_SHARE_AC) + wr_reg(DDR1_PCTL_MCFG1, ((p_ddr_set->t_pctl0_mcfg1)&0xFFFFFF00)); + else + wr_reg(DDR1_PCTL_MCFG1, p_ddr_set->t_pctl0_mcfg1); + } + + _udelay(500); + + // MONITOR DFI INITIALIZATION STATUS. + if (ddr0_enabled) { + wait_set(DDR0_PCTL_DFISTSTAT0, 0); + wr_reg(DDR0_PCTL_POWCTL, 1); + //DDR0_POWER_UP_WAIT + wait_set(DDR0_PCTL_POWSTAT, 0); + } + if (ddr1_enabled) { + wait_set(DDR1_PCTL_DFISTSTAT0, 0); + wr_reg(DDR1_PCTL_POWCTL, 1); + //DDR0_POWER_UP_WAIT + wait_set(DDR1_PCTL_POWSTAT, 0); + } + + if (ddr0_enabled) { + wr_reg(DDR0_PCTL_TRFC, p_ddr_timing->cfg_ddr_rfc); + wr_reg(DDR0_PCTL_TREFI_MEM_DDR3, p_ddr_timing->cfg_ddr_refi_mddr3); + wr_reg(DDR0_PCTL_TMRD, p_ddr_timing->cfg_ddr_mrd); + wr_reg(DDR0_PCTL_TRP, p_ddr_timing->cfg_ddr_rp); + wr_reg(DDR0_PCTL_TAL, p_ddr_timing->cfg_ddr_al); + wr_reg(DDR0_PCTL_TCWL, p_ddr_timing->cfg_ddr_cwl); + wr_reg(DDR0_PCTL_TCL, p_ddr_timing->cfg_ddr_cl); + wr_reg(DDR0_PCTL_TRAS, p_ddr_timing->cfg_ddr_ras); + wr_reg(DDR0_PCTL_TRC, p_ddr_timing->cfg_ddr_rc); + wr_reg(DDR0_PCTL_TRCD, p_ddr_timing->cfg_ddr_rcd); + wr_reg(DDR0_PCTL_TRRD, p_ddr_timing->cfg_ddr_rrd); + wr_reg(DDR0_PCTL_TRTP, p_ddr_timing->cfg_ddr_rtp); + wr_reg(DDR0_PCTL_TWR, p_ddr_timing->cfg_ddr_wr); + wr_reg(DDR0_PCTL_TWTR, p_ddr_timing->cfg_ddr_wtr); + wr_reg(DDR0_PCTL_TEXSR, p_ddr_timing->cfg_ddr_exsr); + wr_reg(DDR0_PCTL_TXP, p_ddr_timing->cfg_ddr_xp); + wr_reg(DDR0_PCTL_TDQS, p_ddr_timing->cfg_ddr_dqs); + wr_reg(DDR0_PCTL_TRTW, p_ddr_timing->cfg_ddr_rtw); + wr_reg(DDR0_PCTL_TCKSRE, p_ddr_timing->cfg_ddr_cksre); + wr_reg(DDR0_PCTL_TCKSRX, p_ddr_timing->cfg_ddr_cksrx); + wr_reg(DDR0_PCTL_TMOD, p_ddr_timing->cfg_ddr_mod); + wr_reg(DDR0_PCTL_TCKE, p_ddr_timing->cfg_ddr_cke); + wr_reg(DDR0_PCTL_TCKESR, p_ddr_timing->cfg_ddr_cke+1); + wr_reg(DDR0_PCTL_TZQCS, p_ddr_timing->cfg_ddr_zqcs); + wr_reg(DDR0_PCTL_TZQCL, p_ddr_timing->cfg_ddr_zqcl); + wr_reg(DDR0_PCTL_TXPDLL, p_ddr_timing->cfg_ddr_xpdll); + wr_reg(DDR0_PCTL_TZQCSI, p_ddr_timing->cfg_ddr_zqcsi); + } + + if (ddr1_enabled) { + wr_reg(DDR1_PCTL_TRFC, p_ddr_timing->cfg_ddr_rfc); + wr_reg(DDR1_PCTL_TREFI_MEM_DDR3, p_ddr_timing->cfg_ddr_refi_mddr3); + wr_reg(DDR1_PCTL_TMRD, p_ddr_timing->cfg_ddr_mrd); + wr_reg(DDR1_PCTL_TRP, p_ddr_timing->cfg_ddr_rp); + wr_reg(DDR1_PCTL_TAL, p_ddr_timing->cfg_ddr_al); + wr_reg(DDR1_PCTL_TCWL, p_ddr_timing->cfg_ddr_cwl); + wr_reg(DDR1_PCTL_TCL, p_ddr_timing->cfg_ddr_cl); + wr_reg(DDR1_PCTL_TRAS, p_ddr_timing->cfg_ddr_ras); + wr_reg(DDR1_PCTL_TRC, p_ddr_timing->cfg_ddr_rc); + wr_reg(DDR1_PCTL_TRCD, p_ddr_timing->cfg_ddr_rcd); + wr_reg(DDR1_PCTL_TRRD, p_ddr_timing->cfg_ddr_rrd); + wr_reg(DDR1_PCTL_TRTP, p_ddr_timing->cfg_ddr_rtp); + wr_reg(DDR1_PCTL_TWR, p_ddr_timing->cfg_ddr_wr); + wr_reg(DDR1_PCTL_TWTR, p_ddr_timing->cfg_ddr_wtr); + wr_reg(DDR1_PCTL_TEXSR, p_ddr_timing->cfg_ddr_exsr); + wr_reg(DDR1_PCTL_TXP, p_ddr_timing->cfg_ddr_xp); + wr_reg(DDR1_PCTL_TDQS, p_ddr_timing->cfg_ddr_dqs); + wr_reg(DDR1_PCTL_TRTW, p_ddr_timing->cfg_ddr_rtw); + wr_reg(DDR1_PCTL_TCKSRE, p_ddr_timing->cfg_ddr_cksre); + wr_reg(DDR1_PCTL_TCKSRX, p_ddr_timing->cfg_ddr_cksrx); + wr_reg(DDR1_PCTL_TMOD, p_ddr_timing->cfg_ddr_mod); + wr_reg(DDR1_PCTL_TCKE, p_ddr_timing->cfg_ddr_cke); + wr_reg(DDR1_PCTL_TCKESR, p_ddr_timing->cfg_ddr_cke+1); + wr_reg(DDR1_PCTL_TZQCS, p_ddr_timing->cfg_ddr_zqcs); + wr_reg(DDR1_PCTL_TZQCL, p_ddr_timing->cfg_ddr_zqcl); + wr_reg(DDR1_PCTL_TXPDLL, p_ddr_timing->cfg_ddr_xpdll); + wr_reg(DDR1_PCTL_TZQCSI, p_ddr_timing->cfg_ddr_zqcsi); + } + + if (ddr0_enabled) { + wr_reg(DDR0_PCTL_SCFG, p_ddr_set->t_pctl0_scfg); + wr_reg(DDR0_PCTL_SCTL, p_ddr_set->t_pctl0_sctl); + } + + if (ddr1_enabled) { + wr_reg(DDR1_PCTL_SCFG, p_ddr_set->t_pctl0_scfg); + wr_reg(DDR1_PCTL_SCTL, p_ddr_set->t_pctl0_sctl); + } + + // SCRATCH1 + wr_reg(0xC1107d40, 0xdeadbeef); + + // NEW HIU + wr_reg(0xC883c010, 0x88776655); + + //DDR0_STAT_CONFIG_WAIT + if (ddr0_enabled) + wait_set(DDR0_PCTL_STAT, 0); + if (ddr1_enabled) + wait_set(DDR1_PCTL_STAT, 0); + + if (ddr0_enabled) { + wr_reg(DDR0_PCTL_PPCFG, p_ddr_set->t_pctl0_ppcfg); /* 16bit or 32bit mode */ + wr_reg(DDR0_PCTL_DFISTCFG0, p_ddr_set->t_pctl0_dfistcfg0); + wr_reg(DDR0_PCTL_DFISTCFG1, p_ddr_set->t_pctl0_dfistcfg1); + wr_reg(DDR0_PCTL_DFITCTRLDELAY, p_ddr_set->t_pctl0_dfitctrldelay); + wr_reg(DDR0_PCTL_DFITPHYWRDATA, p_ddr_set->t_pctl0_dfitphywrdata); + wr_reg(DDR0_PCTL_DFITPHYWRLAT, p_ddr_set->t_pctl0_dfitphywrlta); + wr_reg(DDR0_PCTL_DFITRDDATAEN, p_ddr_set->t_pctl0_dfitrddataen); + wr_reg(DDR0_PCTL_DFITPHYRDLAT, p_ddr_set->t_pctl0_dfitphyrdlat); + wr_reg(DDR0_PCTL_DFITDRAMCLKDIS, p_ddr_set->t_pctl0_dfitdramclkdis); + wr_reg(DDR0_PCTL_DFITDRAMCLKEN, p_ddr_set->t_pctl0_dfitdramclken); + wr_reg(DDR0_PCTL_DFILPCFG0, p_ddr_set->t_pctl0_dfilpcfg0); + wr_reg(DDR0_PCTL_DFITPHYUPDTYPE1, p_ddr_set->t_pctl0_dfitphyupdtype1); + wr_reg(DDR0_PCTL_DFITCTRLUPDMIN, p_ddr_set->t_pctl0_dfitctrlupdmin); + wr_reg(DDR0_PCTL_DFIODTCFG, p_ddr_set->t_pctl0_dfiodtcfg); + wr_reg(DDR0_PCTL_DFIODTCFG1, p_ddr_set->t_pctl0_dfiodtcfg1); + wr_reg(DDR0_PCTL_CMDTSTATEN, p_ddr_set->t_pctl0_cmdtstaten); + } + + if (ddr1_enabled) { + wr_reg(DDR1_PCTL_PPCFG, p_ddr_set->t_pctl0_ppcfg); /* 16bit or 32bit mode */ + wr_reg(DDR1_PCTL_DFISTCFG0, p_ddr_set->t_pctl0_dfistcfg0); + wr_reg(DDR1_PCTL_DFISTCFG1, p_ddr_set->t_pctl0_dfistcfg1); + wr_reg(DDR1_PCTL_DFITCTRLDELAY, p_ddr_set->t_pctl0_dfitctrldelay); + wr_reg(DDR1_PCTL_DFITPHYWRDATA, p_ddr_set->t_pctl0_dfitphywrdata); + wr_reg(DDR1_PCTL_DFITPHYWRLAT, p_ddr_set->t_pctl0_dfitphywrlta); + wr_reg(DDR1_PCTL_DFITRDDATAEN, p_ddr_set->t_pctl0_dfitrddataen); + wr_reg(DDR1_PCTL_DFITPHYRDLAT, p_ddr_set->t_pctl0_dfitphyrdlat); + wr_reg(DDR1_PCTL_DFITDRAMCLKDIS, p_ddr_set->t_pctl0_dfitdramclkdis); + wr_reg(DDR1_PCTL_DFITDRAMCLKEN, p_ddr_set->t_pctl0_dfitdramclken); + wr_reg(DDR1_PCTL_DFILPCFG0, p_ddr_set->t_pctl0_dfilpcfg0); + wr_reg(DDR1_PCTL_DFITPHYUPDTYPE1, p_ddr_set->t_pctl0_dfitphyupdtype1); + wr_reg(DDR1_PCTL_DFITCTRLUPDMIN, p_ddr_set->t_pctl0_dfitctrlupdmin); + wr_reg(DDR1_PCTL_DFIODTCFG, p_ddr_set->t_pctl0_dfiodtcfg); + wr_reg(DDR1_PCTL_DFIODTCFG1, p_ddr_set->t_pctl0_dfiodtcfg1); + wr_reg(DDR1_PCTL_CMDTSTATEN, p_ddr_set->t_pctl0_cmdtstaten); + } + +#ifndef CONFIG_PXP_EMULATOR + wr_reg(DDR0_PUB_ZQ0PR, p_ddr_set->t_pub_zq0pr); + wr_reg(DDR0_PUB_ZQ1PR, p_ddr_set->t_pub_zq1pr); + wr_reg(DDR0_PUB_ZQ2PR, p_ddr_set->t_pub_zq2pr); + wr_reg(DDR0_PUB_ZQ3PR, p_ddr_set->t_pub_zq3pr); + + wr_reg(DDR0_PUB_PIR, 3); + wait_set(DDR0_PUB_PGSR0, 0); + wr_reg(DDR0_PUB_ZQCR,(rd_reg(DDR0_PUB_ZQCR))|(1<<2)|(1<<27)); //jiaxing debug must force update + _udelay(10); + wr_reg(DDR0_PUB_ZQCR,(rd_reg(DDR0_PUB_ZQCR))&(~((1<<2)|(1<<27)))); + _udelay(30); + if (p_ddr_set->ddr_channel_set == CONFIG_DDR0_ONLY_16BIT) + { + wr_reg(DDR0_PUB_DX2GCR0, (0xfffffffe&rd_reg(DDR0_PUB_DX2GCR0))); + wr_reg(DDR0_PUB_DX3GCR0, (0xfffffffe&rd_reg(DDR0_PUB_DX3GCR0))); + } + +#ifdef CONFIG_DDR_CMD_BDL_TUNE + wr_reg(DDR0_PUB_ACLCDLR, DDR_AC_LCDLR); //ck0 + wr_reg(DDR0_PUB_ACBDLR0, DDR_CK0_BDL); //ck0 + wr_reg(DDR0_PUB_ACBDLR1, (DDR_WE_BDL<<16)|(DDR_CAS_BDL<<8)|(DDR_RAS_BDL)); //ras cas we + wr_reg(DDR0_PUB_ACBDLR2, ((DDR_ACPDD_BDL<<24)|(DDR_BA2_BDL<<16)|(DDR_BA1_BDL<<8)|(DDR_BA0_BDL))); //ba0 ba1 ba2 + wr_reg(DDR0_PUB_ACBDLR3, ((DDR_CS1_BDL<<8)|(DDR_CS0_BDL))); //cs0 cs1 + wr_reg(DDR0_PUB_ACBDLR4, ((DDR_ODT1_BDL<<8)|(DDR_ODT0_BDL))); //odt0 odt1 + wr_reg(DDR0_PUB_ACBDLR5, ((DDR_CKE1_BDL<<8)|(DDR_CKE0_BDL))); //cke0 cke1 + wr_reg(DDR0_PUB_ACBDLR6, ((DDR_A3_BDL<<24)|(DDR_A2_BDL<<16)|(DDR_A1_BDL<<8)|(DDR_A0_BDL))); //a0 a1 a2 a3 + wr_reg(DDR0_PUB_ACBDLR7, ((DDR_A7_BDL<<24)|(DDR_A6_BDL<<16)|(DDR_A5_BDL<<8)|(DDR_A4_BDL))); //a4 a5 a6 a7 + wr_reg(DDR0_PUB_ACBDLR8, ((DDR_A11_BDL<<24)|(DDR_A10_BDL<<16)|(DDR_A9_BDL<<8)|(DDR_A8_BDL))); //a8 a9 a10 a11 + wr_reg(DDR0_PUB_ACBDLR9, ((DDR_A15_BDL<<24)|(DDR_A14_BDL<<16)|(DDR_A13_BDL<<8)|(DDR_A12_BDL))); //a12 a13 a14 a15 +#endif + + wr_reg(DDR0_PUB_PIR, (DDR_PIR | PUB_PIR_INIT)); + do { + _udelay(20); + } while(DDR_PGSR0_CHECK()); +#endif + + if ((p_ddr_set->ddr_channel_set == CONFIG_DDR0_RANK0_ONLY) || \ + (p_ddr_set->ddr_channel_set == CONFIG_DDR0_RANK01_SAME)) + { + unsigned int i=0, j=0; + i=(rd_reg(DDR0_PUB_DX2LCDLR0)); + wr_reg(DDR0_PUB_DX2LCDLR0,((i>>8)|(i&(0xffffff00)))); + i=(((rd_reg(DDR0_PUB_DX2GTR))>>3)&((7<<0))); + j=(((rd_reg(DDR0_PUB_DX2GTR))>>14)&((3<<0))); + wr_reg(DDR0_PUB_DX2GTR,i|(i<<3)|(j<<12)|(j<<14)); + i=(rd_reg(DDR0_PUB_DX2LCDLR2)); + wr_reg(DDR0_PUB_DX2LCDLR2,((i>>8)|(i&(0xffffff00)))); + i=(rd_reg(DDR0_PUB_DX3LCDLR0)); + wr_reg(DDR0_PUB_DX3LCDLR0,((i>>8)|(i&(0xffffff00)))); + i=(((rd_reg(DDR0_PUB_DX3GTR))>>3)&((7<<0))); + j=(((rd_reg(DDR0_PUB_DX3GTR))>>14)&((3<<0))); + wr_reg(DDR0_PUB_DX3GTR,i|(i<<3)|(j<<12)|(j<<14)); + i=(rd_reg(DDR0_PUB_DX3LCDLR2)); + wr_reg(DDR0_PUB_DX3LCDLR2,((i>>8)|(i&(0xffffff00)))); + i=(rd_reg(DDR0_PUB_DX0LCDLR0)); + wr_reg(DDR0_PUB_DX0LCDLR0,((i<<8)|(i&(0xffff00ff)))); + i=(((rd_reg(DDR0_PUB_DX0GTR))<<0)&((7<<0))); + j=(((rd_reg(DDR0_PUB_DX0GTR))>>12)&((3<<0))); + wr_reg(DDR0_PUB_DX0GTR,i|(i<<3)|(j<<12)|(j<<14)); + i=(rd_reg(DDR0_PUB_DX0LCDLR2)); + wr_reg(DDR0_PUB_DX0LCDLR2,((i<<8)|(i&(0xffff00ff)))); + i=(rd_reg(DDR0_PUB_DX1LCDLR0)); + wr_reg(DDR0_PUB_DX1LCDLR0,((i<<8)|(i&(0xffff00ff)))); + i=(((rd_reg(DDR0_PUB_DX1GTR))<<0)&((7<<0))); + j=(((rd_reg(DDR0_PUB_DX1GTR))>>12)&((3<<0))); + wr_reg(DDR0_PUB_DX1GTR,i|(i<<3)|(j<<12)|(j<<14)); + i=(rd_reg(DDR0_PUB_DX1LCDLR2)); + wr_reg(DDR0_PUB_DX1LCDLR2,((i<<8)|(i&(0xffff00ff)))); + } + if ((p_ddr_set->ddr_channel_set == CONFIG_DDR0_RANK0_ONLY) || \ + (p_ddr_set->ddr_channel_set == CONFIG_DDR0_RANK01_SAME) || \ + (p_ddr_set->ddr_channel_set == CONFIG_DDR0_RANK01_DIFF)) { + //wr_reg(DDR0_PUB_PGCR2,((((1<<28))|p_ddr_set->t_pub_pgcr2))); + wr_reg(DDR0_PUB_PGCR2,(((~(1<<28))&p_ddr_set->t_pub_pgcr2))); + } + + if ((p_ddr_set->ddr_2t_mode) && \ + (p_ddr_set->ddr_channel_set != CONFIG_DDR01_SHARE_AC) && \ + (((p_ddr_set->t_pub_dcr)&0x7)== 0x3)) { + //jiaxing mark----must place after training ,because training is 1t mode ,if delay too much training will not ok + wr_reg(DDR0_PUB_ACLCDLR, 0x1f); //delay cmd/address 2t signle not effect cs cke odt + //wr_reg(DDR0_PUB_ACBDLR0, 0x10); //ck0 + /* + wr_reg(DDR0_PUB_ACBDLR1, (0x18<<16)|(0x18<<8)|(0x18)); //ras cas we + wr_reg(DDR0_PUB_ACBDLR2, ((0x18<<16)|(0x18<<8)|(0x18))); //ba0 ba1 ba2 + //wr_reg(DDR0_PUB_ACBDLR3, ((0<<8)|(0))); //cs0 cs1 + //wr_reg(DDR0_PUB_ACBDLR4, ((0<<8)|(0))); //odt0 odt1 + //wr_reg(DDR0_PUB_ACBDLR5, ((0<<8)|(0))); //cke0 cke1 + wr_reg(DDR0_PUB_ACBDLR6, ((0x18<<24)|(0x18<<16)|(0x18<<8)|(0x18))); //a0 a1 a2 a3 + wr_reg(DDR0_PUB_ACBDLR7, ((0x18<<24)|(0x18<<16)|(0x18<<8)|(0x18))); //a4 a5 a6 a7 + wr_reg(DDR0_PUB_ACBDLR8, ((0x18<<24)|(0x18<<16)|(0x18<<8)|(0x18))); //a8 a9 a10 a11 + wr_reg(DDR0_PUB_ACBDLR9, ((0x18<<24)|(0x18<<16)|(0x18<<8)|(0x18))); //a12 a13 a14 a15 + */ + } + //DDR0_CMD_TIMER_WAIT + if (ddr0_enabled) + wait_set(DDR0_PCTL_CMDTSTAT, 0); + if (ddr1_enabled) + wait_set(DDR1_PCTL_CMDTSTAT, 0); + + ////APB_WR(PCTL_PCTL_SCTL, 2); // INIT: 0, CFG: 1, GO: 2, SLEEP: 3, WAKEUP: 4 + if (ddr0_enabled) + wr_reg(DDR0_PCTL_SCTL, UPCTL_CMD_GO); + if (ddr1_enabled) + wr_reg(DDR1_PCTL_SCTL, UPCTL_CMD_GO); + + ////WHILE ((APB_RD(DDR0_PCTL_STAT) & 0x7 ) != 3 ) {} + //DDR0_STAT_GO_WAIT: + if (ddr0_enabled) + wait_equal(DDR0_PCTL_STAT, UPCTL_STAT_ACCESS); + if (ddr1_enabled) + wait_equal(DDR1_PCTL_STAT, UPCTL_STAT_ACCESS); + + wr_reg( DDR0_PUB_ZQCR,(rd_reg(DDR0_PUB_ZQCR))|(1<<2)); + wr_reg( DDR0_PUB_ZQCR,(rd_reg(DDR0_PUB_ZQCR))&(~(1<<2))); + +/* power down zq for power saving */ +#ifdef CONFIG_DDR_ZQ_POWER_DOWN + wr_reg( DDR0_PUB_ZQCR,(rd_reg(DDR0_PUB_ZQCR))|(1<<2)); +#endif + +/* power down phy vref for power saving */ +#ifdef CONFIG_DDR_POWER_DOWN_PHY_VREF + wr_reg(DDR0_PUB_IOVCR0, 0); + wr_reg(DDR0_PUB_IOVCR1, 0); +#endif + + //// ENABLE THE DMC AUTO REFRESH FUNCTION + if (ddr0_enabled) { + wr_reg(DMC_REFR_CTRL1, 0X8800191|(0x3<<2)|(0x1<<0)); + rd_reg(DDR0_PCTL_MCFG); + } + if (ddr1_enabled) { + wr_reg(DMC_REFR_CTRL1, 0X8800191|(0x3<<2)|(0x1<<1)); + rd_reg(DDR1_PCTL_MCFG); + } + wr_reg(DMC_REFR_CTRL2, 0X20100000|(p_ddr_set->ddr_clk/20)|(39<<8)); + + return 0; +} + +void ddr_pre_init(void){ + /* find match ddr timing */ + if ((p_ddr_set->ddr_clk >= CONFIG_DDR_CLK_LOW) && (p_ddr_set->ddr_clk < 533)) { + p_ddr_set->ddr_timing_ind = CONFIG_DDR_TIMMING_DDR3_7; + } + else if ((p_ddr_set->ddr_clk >= 533) && (p_ddr_set->ddr_clk < 667)) { + p_ddr_set->ddr_timing_ind = CONFIG_DDR_TIMMING_DDR3_9; + } + else if ((p_ddr_set->ddr_clk >= 667) && (p_ddr_set->ddr_clk < 800)) { + p_ddr_set->ddr_timing_ind = CONFIG_DDR_TIMMING_DDR3_11; + } + else if ((p_ddr_set->ddr_clk >= 800) && (p_ddr_set->ddr_clk < 933)) { + p_ddr_set->ddr_timing_ind = CONFIG_DDR_TIMMING_DDR3_13; + } + else if ((p_ddr_set->ddr_clk >= 933) && (p_ddr_set->ddr_clk < CONFIG_DDR_CLK_HIGH)) { + p_ddr_set->ddr_timing_ind = CONFIG_DDR_TIMMING_DDR3_14; + } + else { + serial_puts("DDR clk setting error! Reset...\n"); + reset_system(); + } + + p_ddr_set->t_pctl0_1us_pck = (p_ddr_set->ddr_clk / 2); + p_ddr_set->t_pctl0_100ns_pck = (p_ddr_set->ddr_clk / 20); + + /* get match timing config */ + unsigned loop; + for (loop = 0; loop < (sizeof(__ddr_timming)/sizeof(ddr_timing_t)); loop++) { + if (__ddr_timming[loop].identifier == p_ddr_set->ddr_timing_ind) { + p_ddr_timing = &__ddr_timming[loop]; + break; + } + } + if (NULL == p_ddr_timing) { + serial_puts("Can't find ddr timing setting! Reset...\n"); + reset_system(); + } + + unsigned int ddr_dual_rank_sel = 0; + unsigned int ddr_chl_set = 0; + + //BIT22. 1:RANK1 IS SAME AS RANK0 + //BIT21. 0:SEC RANK DISABLE, 1:SEC RANK ENABLE + //BIT20. SHARE AC MODE, 0:DISABLE, 1:ENABLE + if (p_ddr_set->ddr_channel_set == CONFIG_DDR0_RANK0_ONLY) { + serial_puts("DDR channel setting: DDR0 Rank0 only\n"); + ddr_chl_set = ((0x2 << 20) | //b'010: BIT22, BIT21, BIT20 + (0 << 16) | //BIT[17:16], DDR0_DDR1 DATA WIDTH, 0:32BIT, 1:16BIT + (1 << 6)); //b'00:DDR0_DDR1, b'01: DDR0_ONLY, b'10:DDR1_ONLY + ddr_dual_rank_sel = 0; //SET PGCR2[28], RANK0 AND RANK1 USE SAME RANK SELECT SIGNAL + p_ddr_set->t_pctl0_ppcfg = (0xF0 << 1); + p_ddr_set->t_pctl0_dfiodtcfg = 0x0808; + } + else if (p_ddr_set->ddr_channel_set == CONFIG_DDR0_RANK01_SAME) { + serial_puts("DDR channel setting: DDR0 Rank0+1 same\n"); + ddr_chl_set = ((0x4 << 20) | (0 << 16) | (1 << 6)); + ddr_dual_rank_sel = 1; + p_ddr_set->t_pctl0_ppcfg = (0xF0 << 1); + p_ddr_set->t_pctl0_dfiodtcfg = 0x08; + } + else if (p_ddr_set->ddr_channel_set == CONFIG_DDR0_RANK01_DIFF) { + serial_puts("DDR channel setting: DDR0 Rank0+1 diff\n"); + ddr_chl_set = ((0x2 << 20) | (0 << 16) | (1 << 6)); + ddr_dual_rank_sel = 0; + p_ddr_set->t_pctl0_ppcfg = (0xF0 << 1); + p_ddr_set->t_pctl0_dfiodtcfg = 0x08; + } + else if (p_ddr_set->ddr_channel_set == CONFIG_DDR0_ONLY_16BIT) { + serial_puts("DDR channel setting: ONLY DDR0 16bit mode\n"); + ddr_chl_set = ((0x2 << 20) | (3 << 16) | (1 << 6)); + ddr_dual_rank_sel = 0; + //p_ddr_set->t_pctl0_ppcfg = (0xF0 << 1); + p_ddr_set->t_pctl0_ppcfg =(0x1fc | 1 ); + p_ddr_set->t_pctl0_dfiodtcfg = 0x08; + } + else if (p_ddr_set->ddr_channel_set == CONFIG_DDR01_SHARE_AC) { + serial_puts("DDR channel setting: DDR0+1 share ac\n"); + ddr_chl_set = ((0x1 << 20) | (3 << 16) | (0 << 6)); + ddr_dual_rank_sel = 1; + p_ddr_set->t_pctl0_ppcfg = (0x1fc | 1 ); + p_ddr_set->t_pctl0_dfiodtcfg = 0x08; + p_ddr_set->ddr_dmc_ctrl |= (5 << 8); + p_ddr_set->ddr_2t_mode = 1; + } + p_ddr_set->ddr_dmc_ctrl |= (ddr_chl_set | + (0x5 << 3) | //set to max size + (0x5 << 0)); //set to max size + /* config t_pub_pgcr2[28] share-ac-dual */ + p_ddr_set->t_pub_pgcr2 |= (ddr_dual_rank_sel << 28); + + /* update pctl timing */ + int tmp_val = 0; + tmp_val =( p_ddr_timing->cfg_ddr_cwl + p_ddr_timing->cfg_ddr_al); + tmp_val = (tmp_val - ((tmp_val%2) ? 3:4))/2; + p_ddr_set->t_pctl0_dfitphywrlta=tmp_val; + + tmp_val = p_ddr_timing->cfg_ddr_cl + p_ddr_timing->cfg_ddr_al; + tmp_val = (tmp_val - ((tmp_val%2) ? 3:4))/2; + p_ddr_set->t_pctl0_dfitrddataen=tmp_val; + + //p_ddr_set->t_pctl0_dfitphyrdlat=16; + if ((p_ddr_timing->cfg_ddr_cl+p_ddr_timing->cfg_ddr_al)%2) { + p_ddr_set->t_pctl0_dfitphyrdlat=14; + } + + /* update pub mr */ + p_ddr_set->t_pub_mr[0] = ((((p_ddr_timing->cfg_ddr_cl - 4) & 0x8)>>1) | + (((p_ddr_timing->cfg_ddr_cl - 4) & 0x7) << 4) | + ((((p_ddr_timing->cfg_ddr_wr <= 8)?(p_ddr_timing->cfg_ddr_wr - 4):(p_ddr_timing->cfg_ddr_wr>>1)) & 7) << 9) | + (0x0) | (0x0 << 3) | (0x0 << 7) | (0x0 << 8) | (0x6 << 9) | (1 << 12)), + p_ddr_set->t_pub_mr[1] = ( ((p_ddr_set->ddr_drv<<1)|((p_ddr_set->ddr_odt&1)<<2) | + (((p_ddr_set->ddr_odt&2)>>1)<<6) | + (((p_ddr_set->ddr_odt&4)>>2)<<9) | + (1<<7) | + ((p_ddr_timing->cfg_ddr_al ? ((p_ddr_timing->cfg_ddr_cl - p_ddr_timing->cfg_ddr_al)&3): 0) << 3 ))), + p_ddr_set->t_pub_mr[2] = ((1<<6) | + (((p_ddr_timing->cfg_ddr_cwl-5)&0x7)<<3)), + p_ddr_set->t_pub_mr[3] = 0x0, + /* update pub dtpr */ + p_ddr_set->t_pub_dtpr[0] = (p_ddr_timing->cfg_ddr_rtp | + (p_ddr_timing->cfg_ddr_wtr << 4) | + (p_ddr_timing->cfg_ddr_rp << 8) | + (p_ddr_timing->cfg_ddr_ras << 16) | + (p_ddr_timing->cfg_ddr_rrd << 22) | + (p_ddr_timing->cfg_ddr_rcd << 26)); + p_ddr_set->t_pub_dtpr[1] = ((p_ddr_timing->cfg_ddr_mod << 2) | + (p_ddr_timing->cfg_ddr_faw << 5) | + (p_ddr_timing->cfg_ddr_rfc << 11) | + (p_ddr_timing->cfg_ddr_wlmrd << 20) | + (p_ddr_timing->cfg_ddr_wlo << 26) | + (0 << 30) ); //TAOND + p_ddr_set->t_pub_dtpr[2] = (p_ddr_timing->cfg_ddr_xs | + (p_ddr_timing->cfg_ddr_xp << 10) | + (p_ddr_timing->cfg_ddr_dllk << 19) | + (0 << 29) | //TRTODT ADDITIONAL + (0 << 30) | //TRTW ADDITIONAL + (0 << 31 )); //TCCD ADDITIONAL + p_ddr_set->t_pub_dtpr[3] = (0 | (0 << 3) | + (p_ddr_timing->cfg_ddr_rc << 6) | + (p_ddr_timing->cfg_ddr_cke << 13) | + (p_ddr_timing->cfg_ddr_mrd << 18) | + (0 << 29)); //tAOFDx + p_ddr_set->t_pctl0_mcfg = ((p_ddr_set->t_pctl0_mcfg)&(~(0x3<<18))) | + (((((p_ddr_timing->cfg_ddr_faw+p_ddr_timing->cfg_ddr_rrd-1)/p_ddr_timing->cfg_ddr_rrd)-4)&0x3)<<18); + p_ddr_set->t_pctl0_mcfg1 |= ((((p_ddr_timing->cfg_ddr_faw%p_ddr_timing->cfg_ddr_rrd)?(p_ddr_timing->cfg_ddr_rrd-(p_ddr_timing->cfg_ddr_faw%p_ddr_timing->cfg_ddr_rrd)):0)&0x7)<<8); +} + +void ddr_test(void){ + if (memTestDataBus((volatile unsigned int *)(uint64_t) \ + (p_ddr_set->ddr_base_addr + p_ddr_set->ddr_start_offset))) { + serial_puts("DataBus test failed!!!\n"); + reset_system(); + } + else + serial_puts("DataBus test pass!\n"); + if (memTestAddressBus((volatile unsigned int *)(uint64_t) \ + (p_ddr_set->ddr_base_addr + p_ddr_set->ddr_start_offset), \ + ((p_ddr_set->ddr_size << 20) - p_ddr_set->ddr_start_offset))) { + serial_puts("AddrBus test failed!!!\n"); + reset_system(); + } + else + serial_puts("AddrBus test pass!\n"); +#if MEM_TEST_DEVICE + if (p_ddr_set->ddr_full_test) { + extern void watchdog_disable(void); + //disable_mmu_el1(); + watchdog_disable(); + if (memTestDevice((volatile unsigned int *)(uint64_t) \ + (p_ddr_set->ddr_base_addr + p_ddr_set->ddr_start_offset), \ + ((p_ddr_set->ddr_size << 20) - p_ddr_set->ddr_start_offset))) { + serial_puts("Device test failed!!!\n"); + reset_system(); + } + else + serial_puts("Device test pass!\n"); + } +#endif// #if MEM_TEST_DEVICE +} + +#if 0 +unsigned int hot_boot(void){ + if (((rd_reg(SCRATCH0) >> 24) & 0xFF) == 0x11) { + /*hot boot*/ + return 0; + } + else{ + return 1; + } +} +#endif diff --git a/plat/gxb/ddr/ddr_detect.c b/plat/gxb/ddr/ddr_detect.c new file mode 100644 index 0000000..a3b28d5 --- /dev/null +++ b/plat/gxb/ddr/ddr_detect.c @@ -0,0 +1,96 @@ + +#define SIZE_16MB 0x01000000 +#define DDR_SIZE_PATTERN 0xAABBCCDD +#define DDR_SIZE_VERI_ADDR SIZE_16MB + +#define DDR_VERI_PATTERN_256M 0 +#define DDR_VERI_PATTERN_512M 0 +#define DDR_VERI_PATTERN_1024M 0xAC7E5AC0 +#define DDR_VERI_PATTERN_2048M 0x1A182515 + +#define DDR_VERI_PATTERN_384M 0 +#define DDR_VERI_PATTERN_768M 0 +#define DDR_VERI_PATTERN_1536M 0 +#define DDR_VERI_PATTERN_3072M 0 + +#define DDR_SIZE_LOOP_MAX 29 + +#ifndef DDR_DETECT_DEBUG +#define DDR_DETECT_DEBUG 0 +#endif + +#if DDR_DETECT_DEBUG +#define debug_serial_puts(a) serial_puts(a) +#define debug_serial_put_hex(a, b) serial_put_hex(a, b) +#else +#define debug_serial_puts(a) +#define debug_serial_put_hex(a, b) +#endif + +#if (CONFIG_DDR_SIZE_AUTO_DETECT) +void ddr_size_detect(ddr_set_t * p_ddr_set) { + /* Set max col, row, bank size */ + debug_serial_puts("DMC_DDR_CTRL: 0x"); + debug_serial_put_hex(rd_reg(DMC_DDR_CTRL), 32); + debug_serial_puts("\n"); + wr_reg(DMC_DDR_CTRL, ((rd_reg(DMC_DDR_CTRL))&(~0x3F))|((5<<3)|5)); + debug_serial_puts("DMC_DDR_CTRL: 0x"); + debug_serial_put_hex(rd_reg(DMC_DDR_CTRL), 32); + debug_serial_puts("\n"); + + uint32_t size_loop=0; + uint64_t write_addr=0; + uint32_t ddr0_size=0; + uint32_t ddr1_size=0; + uint32_t ddr0_size_reg=0; + uint32_t ddr1_size_reg=0; + + //first detect aligned size + for (size_loop=0; size_loop<=DDR_SIZE_LOOP_MAX; size_loop++) { + write_addr = (uint32_t)((0x4<<size_loop)+DDR_SIZE_VERI_ADDR); + debug_serial_puts("size_loop1=0x"); + debug_serial_put_hex(size_loop, 32); + debug_serial_puts("\n"); + wr_reg((unsigned long)DDR_SIZE_VERI_ADDR, 0); + debug_serial_puts("write 0x"); + debug_serial_put_hex(write_addr, 32); + debug_serial_puts("\n"); + wr_reg(write_addr, DDR_SIZE_PATTERN); + _udelay(10); + debug_serial_puts("rd_reg(0):0x"); + debug_serial_put_hex(rd_reg(DDR_SIZE_VERI_ADDR), 32); + debug_serial_puts(", rd_reg(0x4<<size_loop):0x"); + debug_serial_put_hex(rd_reg(write_addr), 32); + debug_serial_puts("\n"); + if ((rd_reg(DDR_SIZE_VERI_ADDR) != 0) && (rd_reg(DDR_SIZE_VERI_ADDR) != DDR_SIZE_PATTERN)) { + debug_serial_puts("find match size1: 0x"); + debug_serial_put_hex(size_loop, 32); + debug_serial_puts("\n"); + /* get correct ddr size */ + p_ddr_set->ddr_size = 1<<(size_loop+2-20); //MB + /* set correct dmc cntl reg */ + unsigned int ddr_one_chl = DDR_USE_1_CHANNEL(p_ddr_set->ddr_channel_set); + ddr0_size = (p_ddr_set->ddr_size)>>(7-ddr_one_chl); + ddr1_size = ddr_one_chl?0x7:((p_ddr_set->ddr_size)>>7); + ddr1_size_reg=ddr_one_chl?0x5:0x0; + while (!((ddr0_size>>=1)&0x1)) + ddr0_size_reg++; + while (!((ddr1_size>>=1)&0x1)) + ddr1_size_reg++; + break; + } + } + debug_serial_puts("DMC_DDR_CTRL: 0x"); + debug_serial_put_hex(rd_reg(DMC_DDR_CTRL), 32); + debug_serial_puts("\n"); + wr_reg(DMC_DDR_CTRL, ((rd_reg(DMC_DDR_CTRL))&(~0x3F))|(ddr1_size_reg<<3|ddr0_size_reg)); + debug_serial_puts("DMC_DDR_CTRL: 0x"); + debug_serial_put_hex(rd_reg(DMC_DDR_CTRL), 32); + debug_serial_puts("\n"); + return; +} +#else +void ddr_size_detect(ddr_set_t * p_ddr_set) { + return; +} +#endif
\ No newline at end of file diff --git a/plat/gxb/ddr/ddr_pctl_define.h b/plat/gxb/ddr/ddr_pctl_define.h new file mode 100644 index 0000000..146391b --- /dev/null +++ b/plat/gxb/ddr/ddr_pctl_define.h @@ -0,0 +1,282 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/ddr/ddr_pctl_define.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#define DDR0_PCTL_SCFG 0xc8839000 +#define DDR0_PCTL_SCTL 0xc8839004 +#define DDR0_PCTL_STAT 0xc8839008 +#define DDR0_PCTL_INTRSTAT 0xc883900c +#define DDR0_PCTL_POWSTAT 0xc8839048 +#define DDR0_PCTL_MRRSTAT0 0xc8839064 +#define DDR0_PCTL_CMDTSTAT 0xc883904c +#define DDR0_PCTL_MCMD 0xc8839040 +#define DDR0_PCTL_MRRSTAT1 0xc8839068 +#define DDR0_PCTL_MRRCFG0 0xc8839060 +#define DDR0_PCTL_CMDTSTATEN 0xc8839050 +#define DDR0_PCTL_POWCTL 0xc8839044 +#define DDR0_PCTL_PPCFG 0xc8839084 +#define DDR0_PCTL_LPDDR23ZQCFG 0xc883908c +#define DDR0_PCTL_MCFG1 0xc883907c +#define DDR0_PCTL_MSTAT 0xc8839088 +#define DDR0_PCTL_MCFG 0xc8839080 +#define DDR0_PCTL_DTUAWDT 0xc88390b0 +#define DDR0_PCTL_DTUPRD2 0xc88390a8 +#define DDR0_PCTL_DTUPRD3 0xc88390ac +#define DDR0_PCTL_DTUNE 0xc883909c +#define DDR0_PCTL_DTUPDES 0xc8839094 +#define DDR0_PCTL_DTUNA 0xc8839098 +#define DDR0_PCTL_DTUPRD0 0xc88390a0 +#define DDR0_PCTL_DTUPRD1 0xc88390a4 +#define DDR0_PCTL_TCKSRE 0xc8839124 +#define DDR0_PCTL_TZQCSI 0xc883911c +#define DDR0_PCTL_TINIT 0xc88390c4 +#define DDR0_PCTL_TDPD 0xc8839144 +#define DDR0_PCTL_TOGCNT1U 0xc88390c0 +#define DDR0_PCTL_TCKE 0xc883912c +#define DDR0_PCTL_TMOD 0xc8839130 +#define DDR0_PCTL_TEXSR 0xc883910c +#define DDR0_PCTL_TAL 0xc88390e4 +#define DDR0_PCTL_TRTP 0xc8839100 +#define DDR0_PCTL_TCKSRX 0xc8839128 +#define DDR0_PCTL_TRTW 0xc88390e0 +#define DDR0_PCTL_TCWL 0xc88390ec +#define DDR0_PCTL_TWR 0xc8839104 +#define DDR0_PCTL_TCL 0xc88390e8 +#define DDR0_PCTL_TDQS 0xc8839120 +#define DDR0_PCTL_TRSTH 0xc88390c8 +#define DDR0_PCTL_TRCD 0xc88390f8 +#define DDR0_PCTL_TXP 0xc8839110 +#define DDR0_PCTL_TOGCNT100N 0xc88390cc +#define DDR0_PCTL_TMRD 0xc88390d4 +#define DDR0_PCTL_TRSTL 0xc8839134 +#define DDR0_PCTL_TREFI 0xc88390d0 +#define DDR0_PCTL_TRAS 0xc88390f0 +#define DDR0_PCTL_TREFI_MEM_DDR3 0xc8839148 +#define DDR0_PCTL_TWTR 0xc8839108 +#define DDR0_PCTL_TRC 0xc88390f4 +#define DDR0_PCTL_TRFC 0xc88390d8 +#define DDR0_PCTL_TMRR 0xc883913c +#define DDR0_PCTL_TCKESR 0xc8839140 +#define DDR0_PCTL_TZQCL 0xc8839138 +#define DDR0_PCTL_TRRD 0xc88390fc +#define DDR0_PCTL_TRP 0xc88390dc +#define DDR0_PCTL_TZQCS 0xc8839118 +#define DDR0_PCTL_TXPDLL 0xc8839114 +#define DDR0_PCTL_ECCCFG 0xc8839180 +#define DDR0_PCTL_ECCLOG 0xc883918c +#define DDR0_PCTL_ECCCLR 0xc8839188 +#define DDR0_PCTL_ECCTST 0xc8839184 +#define DDR0_PCTL_DTUWD0 0xc8839210 +#define DDR0_PCTL_DTUWD1 0xc8839214 +#define DDR0_PCTL_DTUWACTL 0xc8839200 +#define DDR0_PCTL_DTULFSRRD 0xc8839238 +#define DDR0_PCTL_DTUWD2 0xc8839218 +#define DDR0_PCTL_DTUWD3 0xc883921c +#define DDR0_PCTL_DTULFSRWD 0xc8839234 +#define DDR0_PCTL_DTURACTL 0xc8839204 +#define DDR0_PCTL_DTUWDM 0xc8839220 +#define DDR0_PCTL_DTURD0 0xc8839224 +#define DDR0_PCTL_DTURD1 0xc8839228 +#define DDR0_PCTL_DTURD2 0xc883922c +#define DDR0_PCTL_DTURD3 0xc8839230 +#define DDR0_PCTL_DTUCFG 0xc8839208 +#define DDR0_PCTL_DTUEAF 0xc883923c +#define DDR0_PCTL_DTUECTL 0xc883920c +#define DDR0_PCTL_DFIODTCFG1 0xc8839248 +#define DDR0_PCTL_DFITCTRLDELAY 0xc8839240 +#define DDR0_PCTL_DFIODTRANKMAP 0xc883924c +#define DDR0_PCTL_DFIODTCFG 0xc8839244 +#define DDR0_PCTL_DFITPHYWRLAT 0xc8839254 +#define DDR0_PCTL_DFITPHYWRDATA 0xc8839250 +#define DDR0_PCTL_DFITRDDATAEN 0xc8839260 +#define DDR0_PCTL_DFITPHYRDLAT 0xc8839264 +#define DDR0_PCTL_DFITREFMSKI 0xc8839294 +#define DDR0_PCTL_DFITPHYUPDTYPE0 0xc8839270 +#define DDR0_PCTL_DFITPHYUPDTYPE1 0xc8839274 +#define DDR0_PCTL_DFITCTRLUPDDLY 0xc8839288 +#define DDR0_PCTL_DFITPHYUPDTYPE2 0xc8839278 +#define DDR0_PCTL_DFITCTRLUPDMIN 0xc8839280 +#define DDR0_PCTL_DFITPHYUPDTYPE3 0xc883927c +#define DDR0_PCTL_DFIUPDCFG 0xc8839290 +#define DDR0_PCTL_DFITCTRLUPDMAX 0xc8839284 +#define DDR0_PCTL_DFITCTRLUPDI 0xc8839298 +#define DDR0_PCTL_DFITRRDLVLEN 0xc88392b8 +#define DDR0_PCTL_DFITRSTAT0 0xc88392b0 +#define DDR0_PCTL_DFITRWRLVLEN 0xc88392b4 +#define DDR0_PCTL_DFITRCFG0 0xc88392ac +#define DDR0_PCTL_DFITRRDLVLGATEEN 0xc88392bc +#define DDR0_PCTL_DFISTSTAT0 0xc88392c0 +#define DDR0_PCTL_DFISTPARLOG 0xc88392e0 +#define DDR0_PCTL_DFITDRAMCLKEN 0xc88392d0 +#define DDR0_PCTL_DFISTPARCLR 0xc88392dc +#define DDR0_PCTL_DFISTCFG0 0xc88392c4 +#define DDR0_PCTL_DFISTCFG1 0xc88392c8 +#define DDR0_PCTL_DFISTCFG2 0xc88392d8 +#define DDR0_PCTL_DFITDRAMCLKDIS 0xc88392d4 +#define DDR0_PCTL_DFILPCFG0 0xc88392f0 +#define DDR0_PCTL_DFITRWRLVLDELAY0 0xc8839318 +#define DDR0_PCTL_DFITRWRLVLDELAY1 0xc883931c +#define DDR0_PCTL_DFITRWRLVLDELAY2 0xc8839320 +#define DDR0_PCTL_DFITRRDLVLRESP0 0xc883930c +#define DDR0_PCTL_DFITRRDLVLRESP1 0xc8839310 +#define DDR0_PCTL_DFITRRDLVLRESP2 0xc8839314 +#define DDR0_PCTL_DFITRWRLVLRESP0 0xc8839300 +#define DDR0_PCTL_DFITRRDLVLDELAY0 0xc8839324 +#define DDR0_PCTL_DFITRRDLVLDELAY1 0xc8839328 +#define DDR0_PCTL_DFITRWRLVLRESP1 0xc8839304 +#define DDR0_PCTL_DFITRRDLVLDELAY2 0xc883932c +#define DDR0_PCTL_DFITRWRLVLRESP2 0xc8839308 +#define DDR0_PCTL_DFITRRDLVLGATEDELAY0 0xc8839330 +#define DDR0_PCTL_DFITRCMD 0xc883933c +#define DDR0_PCTL_DFITRRDLVLGATEDELAY1 0xc8839334 +#define DDR0_PCTL_DFITRRDLVLGATEDELAY2 0xc8839338 +#define DDR0_PCTL_IPTR 0xc88393fc +#define DDR0_PCTL_IPVR 0xc88393f8 + +#define DDR1_PCTL_SCFG 0xc8839400 +#define DDR1_PCTL_SCTL 0xc8839404 +#define DDR1_PCTL_STAT 0xc8839408 +#define DDR1_PCTL_INTRSTAT 0xc883940c +#define DDR1_PCTL_POWSTAT 0xc8839448 +#define DDR1_PCTL_MRRSTAT0 0xc8839464 +#define DDR1_PCTL_CMDTSTAT 0xc883944c +#define DDR1_PCTL_MCMD 0xc8839440 +#define DDR1_PCTL_MRRSTAT1 0xc8839468 +#define DDR1_PCTL_MRRCFG0 0xc8839460 +#define DDR1_PCTL_CMDTSTATEN 0xc8839450 +#define DDR1_PCTL_POWCTL 0xc8839444 +#define DDR1_PCTL_PPCFG 0xc8839484 +#define DDR1_PCTL_LPDDR23ZQCFG 0xc883948c +#define DDR1_PCTL_MCFG1 0xc883947c +#define DDR1_PCTL_MSTAT 0xc8839488 +#define DDR1_PCTL_MCFG 0xc8839480 +#define DDR1_PCTL_DTUAWDT 0xc88394b0 +#define DDR1_PCTL_DTUPRD2 0xc88394a8 +#define DDR1_PCTL_DTUPRD3 0xc88394ac +#define DDR1_PCTL_DTUNE 0xc883949c +#define DDR1_PCTL_DTUPDES 0xc8839494 +#define DDR1_PCTL_DTUNA 0xc8839498 +#define DDR1_PCTL_DTUPRD0 0xc88394a0 +#define DDR1_PCTL_DTUPRD1 0xc88394a4 +#define DDR1_PCTL_TCKSRE 0xc8839524 +#define DDR1_PCTL_TZQCSI 0xc883951c +#define DDR1_PCTL_TINIT 0xc88394c4 +#define DDR1_PCTL_TDPD 0xc8839544 +#define DDR1_PCTL_TOGCNT1U 0xc88394c0 +#define DDR1_PCTL_TCKE 0xc883952c +#define DDR1_PCTL_TMOD 0xc8839530 +#define DDR1_PCTL_TEXSR 0xc883950c +#define DDR1_PCTL_TAL 0xc88394e4 +#define DDR1_PCTL_TRTP 0xc8839500 +#define DDR1_PCTL_TCKSRX 0xc8839528 +#define DDR1_PCTL_TRTW 0xc88394e0 +#define DDR1_PCTL_TCWL 0xc88394ec +#define DDR1_PCTL_TWR 0xc8839504 +#define DDR1_PCTL_TCL 0xc88394e8 +#define DDR1_PCTL_TDQS 0xc8839520 +#define DDR1_PCTL_TRSTH 0xc88394c8 +#define DDR1_PCTL_TRCD 0xc88394f8 +#define DDR1_PCTL_TXP 0xc8839510 +#define DDR1_PCTL_TOGCNT100N 0xc88394cc +#define DDR1_PCTL_TMRD 0xc88394d4 +#define DDR1_PCTL_TRSTL 0xc8839534 +#define DDR1_PCTL_TREFI 0xc88394d0 +#define DDR1_PCTL_TRAS 0xc88394f0 +#define DDR1_PCTL_TREFI_MEM_DDR3 0xc8839548 +#define DDR1_PCTL_TWTR 0xc8839508 +#define DDR1_PCTL_TRC 0xc88394f4 +#define DDR1_PCTL_TRFC 0xc88394d8 +#define DDR1_PCTL_TMRR 0xc883953c +#define DDR1_PCTL_TCKESR 0xc8839540 +#define DDR1_PCTL_TZQCL 0xc8839538 +#define DDR1_PCTL_TRRD 0xc88394fc +#define DDR1_PCTL_TRP 0xc88394dc +#define DDR1_PCTL_TZQCS 0xc8839518 +#define DDR1_PCTL_TXPDLL 0xc8839514 +#define DDR1_PCTL_ECCCFG 0xc8839580 +#define DDR1_PCTL_ECCLOG 0xc883958c +#define DDR1_PCTL_ECCCLR 0xc8839588 +#define DDR1_PCTL_ECCTST 0xc8839584 +#define DDR1_PCTL_DTUWD0 0xc8839610 +#define DDR1_PCTL_DTUWD1 0xc8839614 +#define DDR1_PCTL_DTUWACTL 0xc8839600 +#define DDR1_PCTL_DTULFSRRD 0xc8839638 +#define DDR1_PCTL_DTUWD2 0xc8839618 +#define DDR1_PCTL_DTUWD3 0xc883961c +#define DDR1_PCTL_DTULFSRWD 0xc8839634 +#define DDR1_PCTL_DTURACTL 0xc8839604 +#define DDR1_PCTL_DTUWDM 0xc8839620 +#define DDR1_PCTL_DTURD0 0xc8839624 +#define DDR1_PCTL_DTURD1 0xc8839628 +#define DDR1_PCTL_DTURD2 0xc883962c +#define DDR1_PCTL_DTURD3 0xc8839630 +#define DDR1_PCTL_DTUCFG 0xc8839608 +#define DDR1_PCTL_DTUEAF 0xc883963c +#define DDR1_PCTL_DTUECTL 0xc883960c +#define DDR1_PCTL_DFIODTCFG1 0xc8839648 +#define DDR1_PCTL_DFITCTRLDELAY 0xc8839640 +#define DDR1_PCTL_DFIODTRANKMAP 0xc883964c +#define DDR1_PCTL_DFIODTCFG 0xc8839644 +#define DDR1_PCTL_DFITPHYWRLAT 0xc8839654 +#define DDR1_PCTL_DFITPHYWRDATA 0xc8839650 +#define DDR1_PCTL_DFITRDDATAEN 0xc8839660 +#define DDR1_PCTL_DFITPHYRDLAT 0xc8839664 +#define DDR1_PCTL_DFITREFMSKI 0xc8839694 +#define DDR1_PCTL_DFITPHYUPDTYPE0 0xc8839670 +#define DDR1_PCTL_DFITPHYUPDTYPE1 0xc8839674 +#define DDR1_PCTL_DFITCTRLUPDDLY 0xc8839688 +#define DDR1_PCTL_DFITPHYUPDTYPE2 0xc8839678 +#define DDR1_PCTL_DFITCTRLUPDMIN 0xc8839680 +#define DDR1_PCTL_DFITPHYUPDTYPE3 0xc883967c +#define DDR1_PCTL_DFIUPDCFG 0xc8839690 +#define DDR1_PCTL_DFITCTRLUPDMAX 0xc8839684 +#define DDR1_PCTL_DFITCTRLUPDI 0xc8839698 +#define DDR1_PCTL_DFITRRDLVLEN 0xc88396b8 +#define DDR1_PCTL_DFITRSTAT0 0xc88396b0 +#define DDR1_PCTL_DFITRWRLVLEN 0xc88396b4 +#define DDR1_PCTL_DFITRCFG0 0xc88396ac +#define DDR1_PCTL_DFITRRDLVLGATEEN 0xc88396bc +#define DDR1_PCTL_DFISTSTAT0 0xc88396c0 +#define DDR1_PCTL_DFISTPARLOG 0xc88396e0 +#define DDR1_PCTL_DFITDRAMCLKEN 0xc88396d0 +#define DDR1_PCTL_DFISTPARCLR 0xc88396dc +#define DDR1_PCTL_DFISTCFG0 0xc88396c4 +#define DDR1_PCTL_DFISTCFG1 0xc88396c8 +#define DDR1_PCTL_DFISTCFG2 0xc88396d8 +#define DDR1_PCTL_DFITDRAMCLKDIS 0xc88396d4 +#define DDR1_PCTL_DFILPCFG0 0xc88396f0 +#define DDR1_PCTL_DFITRWRLVLDELAY0 0xc8839718 +#define DDR1_PCTL_DFITRWRLVLDELAY1 0xc883971c +#define DDR1_PCTL_DFITRWRLVLDELAY2 0xc8839720 +#define DDR1_PCTL_DFITRRDLVLRESP0 0xc883970c +#define DDR1_PCTL_DFITRRDLVLRESP1 0xc8839710 +#define DDR1_PCTL_DFITRRDLVLRESP2 0xc8839714 +#define DDR1_PCTL_DFITRWRLVLRESP0 0xc8839700 +#define DDR1_PCTL_DFITRRDLVLDELAY0 0xc8839724 +#define DDR1_PCTL_DFITRRDLVLDELAY1 0xc8839728 +#define DDR1_PCTL_DFITRWRLVLRESP1 0xc8839704 +#define DDR1_PCTL_DFITRRDLVLDELAY2 0xc883972c +#define DDR1_PCTL_DFITRWRLVLRESP2 0xc8839708 +#define DDR1_PCTL_DFITRRDLVLGATEDELAY0 0xc8839730 +#define DDR1_PCTL_DFITRCMD 0xc883973c +#define DDR1_PCTL_DFITRRDLVLGATEDELAY1 0xc8839734 +#define DDR1_PCTL_DFITRRDLVLGATEDELAY2 0xc8839738 +#define DDR1_PCTL_IPTR 0xc88397fc +#define DDR1_PCTL_IPVR 0xc88397f8 diff --git a/plat/gxb/ddr/ddr_pub_define.h b/plat/gxb/ddr/ddr_pub_define.h new file mode 100644 index 0000000..471965d --- /dev/null +++ b/plat/gxb/ddr/ddr_pub_define.h @@ -0,0 +1,305 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/ddr/ddr_pub_define.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#define DDR0_PUB_REG_BASE 0xc8836000 + +#define DDR0_PUB_RIDR (DDR0_PUB_REG_BASE+(0x00<<2)) +#define DDR0_PUB_PIR (DDR0_PUB_REG_BASE+(0x01<<2)) +#define DDR0_PUB_PGCR0 (DDR0_PUB_REG_BASE+(0x02<<2)) +#define DDR0_PUB_PGCR1 (DDR0_PUB_REG_BASE+(0x03<<2)) +#define DDR0_PUB_PGCR2 (DDR0_PUB_REG_BASE+(0x04<<2)) +#define DDR0_PUB_PGCR3 (DDR0_PUB_REG_BASE+(0x05<<2)) +#define DDR0_PUB_PGSR0 (DDR0_PUB_REG_BASE+(0x06<<2)) +#define DDR0_PUB_PGSR1 (DDR0_PUB_REG_BASE+(0x07<<2)) +#define DDR0_PUB_PLLCR (DDR0_PUB_REG_BASE+(0x08<<2)) +#define DDR0_PUB_PTR0 (DDR0_PUB_REG_BASE+(0x09<<2)) +#define DDR0_PUB_PTR1 (DDR0_PUB_REG_BASE+(0x0A<<2)) +#define DDR0_PUB_PTR2 (DDR0_PUB_REG_BASE+(0x0B<<2)) +#define DDR0_PUB_PTR3 (DDR0_PUB_REG_BASE+(0x0C<<2)) +#define DDR0_PUB_PTR4 (DDR0_PUB_REG_BASE+(0x0D<<2)) +#define DDR0_PUB_ACMDLR (DDR0_PUB_REG_BASE+(0x0E<<2)) +#define DDR0_PUB_ACLCDLR (DDR0_PUB_REG_BASE+(0x0F<<2)) +#define DDR0_PUB_ACBDLR0 (DDR0_PUB_REG_BASE+(0x10<<2)) +#define DDR0_PUB_ACBDLR1 (DDR0_PUB_REG_BASE+(0x11<<2)) +#define DDR0_PUB_ACBDLR2 (DDR0_PUB_REG_BASE+(0x12<<2)) +#define DDR0_PUB_ACBDLR3 (DDR0_PUB_REG_BASE+(0x13<<2)) +#define DDR0_PUB_ACBDLR4 (DDR0_PUB_REG_BASE+(0x14<<2)) +#define DDR0_PUB_ACBDLR5 (DDR0_PUB_REG_BASE+(0x15<<2)) +#define DDR0_PUB_ACBDLR6 (DDR0_PUB_REG_BASE+(0x16<<2)) +#define DDR0_PUB_ACBDLR7 (DDR0_PUB_REG_BASE+(0x17<<2)) +#define DDR0_PUB_ACBDLR8 (DDR0_PUB_REG_BASE+(0x18<<2)) +#define DDR0_PUB_ACBDLR9 (DDR0_PUB_REG_BASE+(0x19<<2)) +#define DDR0_PUB_ACIOCR0 (DDR0_PUB_REG_BASE+(0x1A<<2)) +#define DDR0_PUB_ACIOCR1 (DDR0_PUB_REG_BASE+(0x1B<<2)) +#define DDR0_PUB_ACIOCR2 (DDR0_PUB_REG_BASE+(0x1C<<2)) +#define DDR0_PUB_ACIOCR3 (DDR0_PUB_REG_BASE+(0x1D<<2)) +#define DDR0_PUB_ACIOCR4 (DDR0_PUB_REG_BASE+(0x1E<<2)) +#define DDR0_PUB_ACIOCR5 (DDR0_PUB_REG_BASE+(0x1F<<2)) +#define DDR0_PUB_DXCCR (DDR0_PUB_REG_BASE+(0x20<<2)) +#define DDR0_PUB_DSGCR (DDR0_PUB_REG_BASE+(0x21<<2)) +#define DDR0_PUB_DCR (DDR0_PUB_REG_BASE+(0x22<<2)) +#define DDR0_PUB_DTPR0 (DDR0_PUB_REG_BASE+(0x23<<2)) +#define DDR0_PUB_DTPR1 (DDR0_PUB_REG_BASE+(0x24<<2)) +#define DDR0_PUB_DTPR2 (DDR0_PUB_REG_BASE+(0x25<<2)) +#define DDR0_PUB_DTPR3 (DDR0_PUB_REG_BASE+(0x26<<2)) +#define DDR0_PUB_MR0 (DDR0_PUB_REG_BASE+(0x27<<2)) +#define DDR0_PUB_MR1 (DDR0_PUB_REG_BASE+(0x28<<2)) +#define DDR0_PUB_MR2 (DDR0_PUB_REG_BASE+(0x29<<2)) +#define DDR0_PUB_MR3 (DDR0_PUB_REG_BASE+(0x2A<<2)) +#define DDR0_PUB_ODTCR (DDR0_PUB_REG_BASE+(0x2B<<2)) +#define DDR0_PUB_DTCR (DDR0_PUB_REG_BASE+(0x2C<<2)) +#define DDR0_PUB_DTAR0 (DDR0_PUB_REG_BASE+(0x2D<<2)) +#define DDR0_PUB_DTAR1 (DDR0_PUB_REG_BASE+(0x2E<<2)) +#define DDR0_PUB_DTAR2 (DDR0_PUB_REG_BASE+(0x2F<<2)) +#define DDR0_PUB_DTAR3 (DDR0_PUB_REG_BASE+(0x30<<2)) +#define DDR0_PUB_DTDR0 (DDR0_PUB_REG_BASE+(0x31<<2)) +#define DDR0_PUB_DTDR1 (DDR0_PUB_REG_BASE+(0x32<<2)) +#define DDR0_PUB_DTEDR0 (DDR0_PUB_REG_BASE+(0x33<<2)) +#define DDR0_PUB_DTEDR1 (DDR0_PUB_REG_BASE+(0x34<<2)) +#define DDR0_PUB_RDIMMGCR0 (DDR0_PUB_REG_BASE+(0x35<<2)) +#define DDR0_PUB_RDIMMGCR1 (DDR0_PUB_REG_BASE+(0x36<<2)) +#define DDR0_PUB_RDIMMCR0 (DDR0_PUB_REG_BASE+(0x37<<2)) +#define DDR0_PUB_RDIMMCR1 (DDR0_PUB_REG_BASE+(0x38<<2)) +#define DDR0_PUB_GPR0 (DDR0_PUB_REG_BASE+(0x39<<2)) +#define DDR0_PUB_GPR1 (DDR0_PUB_REG_BASE+(0x3A<<2)) +#define DDR0_PUB_CATR0 (DDR0_PUB_REG_BASE+(0x3B<<2)) +#define DDR0_PUB_CATR1 (DDR0_PUB_REG_BASE+(0x3C<<2)) +//0x3D-32'h5F reserved) +#define DDR0_PUB_DCUAR (DDR0_PUB_REG_BASE+(0x60<<2)) +#define DDR0_PUB_DCUDR (DDR0_PUB_REG_BASE+(0x61<<2)) +#define DDR0_PUB_DCURR (DDR0_PUB_REG_BASE+(0x62<<2)) +#define DDR0_PUB_DCULR (DDR0_PUB_REG_BASE+(0x63<<2)) +#define DDR0_PUB_DCUGCR (DDR0_PUB_REG_BASE+(0x64<<2)) +#define DDR0_PUB_DCUTPR (DDR0_PUB_REG_BASE+(0x65<<2)) +#define DDR0_PUB_DCUSR0 (DDR0_PUB_REG_BASE+(0x66<<2)) +#define DDR0_PUB_DCUSR1 (DDR0_PUB_REG_BASE+(0x67<<2)) +//0x68-32'h6F reserved) +#define DDR0_PUB_BISTRR (DDR0_PUB_REG_BASE+(0x70<<2)) +#define DDR0_PUB_BISTWCR (DDR0_PUB_REG_BASE+(0x71<<2)) +#define DDR0_PUB_BISTMSKR0 (DDR0_PUB_REG_BASE+(0x72<<2)) +#define DDR0_PUB_BISTMSKR1 (DDR0_PUB_REG_BASE+(0x73<<2)) +#define DDR0_PUB_BISTMSKR2 (DDR0_PUB_REG_BASE+(0x74<<2)) +#define DDR0_PUB_BISTLSR (DDR0_PUB_REG_BASE+(0x75<<2)) +#define DDR0_PUB_BISTAR0 (DDR0_PUB_REG_BASE+(0x76<<2)) +#define DDR0_PUB_BISTAR1 (DDR0_PUB_REG_BASE+(0x77<<2)) +#define DDR0_PUB_BISTAR2 (DDR0_PUB_REG_BASE+(0x78<<2)) +#define DDR0_PUB_BISTUDPR (DDR0_PUB_REG_BASE+(0x79<<2)) +#define DDR0_PUB_BISTGSR (DDR0_PUB_REG_BASE+(0x7A<<2)) +#define DDR0_PUB_BISTWER (DDR0_PUB_REG_BASE+(0x7B<<2)) +#define DDR0_PUB_BISTBER0 (DDR0_PUB_REG_BASE+(0x7C<<2)) +#define DDR0_PUB_BISTBER1 (DDR0_PUB_REG_BASE+(0x7D<<2)) +#define DDR0_PUB_BISTBER2 (DDR0_PUB_REG_BASE+(0x7E<<2)) +#define DDR0_PUB_BISTBER3 (DDR0_PUB_REG_BASE+(0x7F<<2)) +#define DDR0_PUB_BISTWCSR (DDR0_PUB_REG_BASE+(0x80<<2)) +#define DDR0_PUB_BISTFWR0 (DDR0_PUB_REG_BASE+(0x81<<2)) +#define DDR0_PUB_BISTFWR1 (DDR0_PUB_REG_BASE+(0x82<<2)) +#define DDR0_PUB_BISTFWR2 (DDR0_PUB_REG_BASE+(0x83<<2)) +//0x84-32'h8D reserved) +#define DDR0_PUB_IOVCR0 (DDR0_PUB_REG_BASE+(0x8E<<2)) +#define DDR0_PUB_IOVCR1 (DDR0_PUB_REG_BASE+(0x8F<<2)) +#define DDR0_PUB_ZQCR (DDR0_PUB_REG_BASE+(0x90<<2)) +#define DDR0_PUB_ZQ0PR (DDR0_PUB_REG_BASE+(0x91<<2)) +#define DDR0_PUB_ZQ0DR (DDR0_PUB_REG_BASE+(0x92<<2)) +#define DDR0_PUB_ZQ0SR (DDR0_PUB_REG_BASE+(0x93<<2)) +//0x94 reserved) +#define DDR0_PUB_ZQ1PR (DDR0_PUB_REG_BASE+(0x95<<2)) +#define DDR0_PUB_ZQ1DR (DDR0_PUB_REG_BASE+(0x96<<2)) +#define DDR0_PUB_ZQ1SR (DDR0_PUB_REG_BASE+(0x97<<2)) +//0x98 reserved) +#define DDR0_PUB_ZQ2PR (DDR0_PUB_REG_BASE+(0x99<<2)) +#define DDR0_PUB_ZQ2DR (DDR0_PUB_REG_BASE+(0x9A<<2)) +#define DDR0_PUB_ZQ2SR (DDR0_PUB_REG_BASE+(0x9B<<2)) +//0x9c reserved) +#define DDR0_PUB_ZQ3PR (DDR0_PUB_REG_BASE+(0x9D<<2)) +#define DDR0_PUB_ZQ3DR (DDR0_PUB_REG_BASE+(0x9E<<2)) +#define DDR0_PUB_ZQ3SR (DDR0_PUB_REG_BASE+(0x9F<<2)) +#define DDR0_PUB_DX0GCR0 (DDR0_PUB_REG_BASE+(0xA0<<2)) +#define DDR0_PUB_DX0GCR1 (DDR0_PUB_REG_BASE+(0xA1<<2)) +#define DDR0_PUB_DX0GCR2 (DDR0_PUB_REG_BASE+(0xA2<<2)) +#define DDR0_PUB_DX0GCR3 (DDR0_PUB_REG_BASE+(0xA3<<2)) +#define DDR0_PUB_DX0GSR0 (DDR0_PUB_REG_BASE+(0xA4<<2)) +#define DDR0_PUB_DX0GSR1 (DDR0_PUB_REG_BASE+(0xA5<<2)) +#define DDR0_PUB_DX0GSR2 (DDR0_PUB_REG_BASE+(0xA6<<2)) +#define DDR0_PUB_DX0BDLR0 (DDR0_PUB_REG_BASE+(0xA7<<2)) +#define DDR0_PUB_DX0BDLR1 (DDR0_PUB_REG_BASE+(0xA8<<2)) +#define DDR0_PUB_DX0BDLR2 (DDR0_PUB_REG_BASE+(0xA9<<2)) +#define DDR0_PUB_DX0BDLR3 (DDR0_PUB_REG_BASE+(0xAA<<2)) +#define DDR0_PUB_DX0BDLR4 (DDR0_PUB_REG_BASE+(0xAB<<2)) +#define DDR0_PUB_DX0BDLR5 (DDR0_PUB_REG_BASE+(0xAC<<2)) +#define DDR0_PUB_DX0BDLR6 (DDR0_PUB_REG_BASE+(0xAD<<2)) +#define DDR0_PUB_DX0LCDLR0 (DDR0_PUB_REG_BASE+(0xAE<<2)) +#define DDR0_PUB_DX0LCDLR1 (DDR0_PUB_REG_BASE+(0xAF<<2)) +#define DDR0_PUB_DX0LCDLR2 (DDR0_PUB_REG_BASE+(0xB0<<2)) +#define DDR0_PUB_DX0MDLR (DDR0_PUB_REG_BASE+(0xB1<<2)) +#define DDR0_PUB_DX0GTR (DDR0_PUB_REG_BASE+(0xB2<<2)) +//0xB4-32'hBF reserved) +#define DDR0_PUB_DX1GCR0 (DDR0_PUB_REG_BASE+(0xC0<<2)) +#define DDR0_PUB_DX1GCR1 (DDR0_PUB_REG_BASE+(0xC1<<2)) +#define DDR0_PUB_DX1GCR2 (DDR0_PUB_REG_BASE+(0xC2<<2)) +#define DDR0_PUB_DX1GCR3 (DDR0_PUB_REG_BASE+(0xC3<<2)) +#define DDR0_PUB_DX1GSR0 (DDR0_PUB_REG_BASE+(0xC4<<2)) +#define DDR0_PUB_DX1GSR1 (DDR0_PUB_REG_BASE+(0xC5<<2)) +#define DDR0_PUB_DX1GSR2 (DDR0_PUB_REG_BASE+(0xC6<<2)) +#define DDR0_PUB_DX1BDLR0 (DDR0_PUB_REG_BASE+(0xC7<<2)) +#define DDR0_PUB_DX1BDLR1 (DDR0_PUB_REG_BASE+(0xC8<<2)) +#define DDR0_PUB_DX1BDLR2 (DDR0_PUB_REG_BASE+(0xC9<<2)) +#define DDR0_PUB_DX1BDLR3 (DDR0_PUB_REG_BASE+(0xCA<<2)) +#define DDR0_PUB_DX1BDLR4 (DDR0_PUB_REG_BASE+(0xCB<<2)) +#define DDR0_PUB_DX1BDLR5 (DDR0_PUB_REG_BASE+(0xCC<<2)) +#define DDR0_PUB_DX1BDLR6 (DDR0_PUB_REG_BASE+(0xCD<<2)) +#define DDR0_PUB_DX1LCDLR0 (DDR0_PUB_REG_BASE+(0xCE<<2)) +#define DDR0_PUB_DX1LCDLR1 (DDR0_PUB_REG_BASE+(0xCF<<2)) +#define DDR0_PUB_DX1LCDLR2 (DDR0_PUB_REG_BASE+(0xD0<<2)) +#define DDR0_PUB_DX1MDLR (DDR0_PUB_REG_BASE+(0xD1<<2)) +#define DDR0_PUB_DX1GTR (DDR0_PUB_REG_BASE+(0xD2<<2)) +#define DDR0_PUB_DX2GCR0 (DDR0_PUB_REG_BASE+(0xE0<<2)) +#define DDR0_PUB_DX2GCR1 (DDR0_PUB_REG_BASE+(0xE1<<2)) +#define DDR0_PUB_DX2GCR2 (DDR0_PUB_REG_BASE+(0xE2<<2)) +#define DDR0_PUB_DX2GCR3 (DDR0_PUB_REG_BASE+(0xE3<<2)) +#define DDR0_PUB_DX2GSR0 (DDR0_PUB_REG_BASE+(0xE4<<2)) +#define DDR0_PUB_DX2GSR1 (DDR0_PUB_REG_BASE+(0xE5<<2)) +#define DDR0_PUB_DX2GSR2 (DDR0_PUB_REG_BASE+(0xE6<<2)) +#define DDR0_PUB_DX2BDLR0 (DDR0_PUB_REG_BASE+(0xE7<<2)) +#define DDR0_PUB_DX2BDLR1 (DDR0_PUB_REG_BASE+(0xE8<<2)) +#define DDR0_PUB_DX2BDLR2 (DDR0_PUB_REG_BASE+(0xE9<<2)) +#define DDR0_PUB_DX2BDLR3 (DDR0_PUB_REG_BASE+(0xEA<<2)) +#define DDR0_PUB_DX2BDLR4 (DDR0_PUB_REG_BASE+(0xEB<<2)) +#define DDR0_PUB_DX2BDLR5 (DDR0_PUB_REG_BASE+(0xEC<<2)) +#define DDR0_PUB_DX2BDLR6 (DDR0_PUB_REG_BASE+(0xED<<2)) +#define DDR0_PUB_DX2LCDLR0 (DDR0_PUB_REG_BASE+(0xEE<<2)) +#define DDR0_PUB_DX2LCDLR1 (DDR0_PUB_REG_BASE+(0xEF<<2)) +#define DDR0_PUB_DX2LCDLR2 (DDR0_PUB_REG_BASE+(0xF0<<2)) +#define DDR0_PUB_DX2MDLR (DDR0_PUB_REG_BASE+(0xF1<<2)) +#define DDR0_PUB_DX2GTR (DDR0_PUB_REG_BASE+(0xF2<<2)) +#define DDR0_PUB_DX3GCR0 (DDR0_PUB_REG_BASE+(0x100<<2)) +#define DDR0_PUB_DX3GCR1 (DDR0_PUB_REG_BASE+(0x101<<2)) +#define DDR0_PUB_DX3GCR2 (DDR0_PUB_REG_BASE+(0x102<<2)) +#define DDR0_PUB_DX3GCR3 (DDR0_PUB_REG_BASE+(0x103<<2)) +#define DDR0_PUB_DX3GSR0 (DDR0_PUB_REG_BASE+(0x104<<2)) +#define DDR0_PUB_DX3GSR1 (DDR0_PUB_REG_BASE+(0x105<<2)) +#define DDR0_PUB_DX3GSR2 (DDR0_PUB_REG_BASE+(0x106<<2)) +#define DDR0_PUB_DX3BDLR0 (DDR0_PUB_REG_BASE+(0x107<<2)) +#define DDR0_PUB_DX3BDLR1 (DDR0_PUB_REG_BASE+(0x108<<2)) +#define DDR0_PUB_DX3BDLR2 (DDR0_PUB_REG_BASE+(0x109<<2)) +#define DDR0_PUB_DX3BDLR3 (DDR0_PUB_REG_BASE+(0x10A<<2)) +#define DDR0_PUB_DX3BDLR4 (DDR0_PUB_REG_BASE+(0x10B<<2)) +#define DDR0_PUB_DX3BDLR5 (DDR0_PUB_REG_BASE+(0x10C<<2)) +#define DDR0_PUB_DX3BDLR6 (DDR0_PUB_REG_BASE+(0x10D<<2)) +#define DDR0_PUB_DX3LCDLR0 (DDR0_PUB_REG_BASE+(0x10E<<2)) +#define DDR0_PUB_DX3LCDLR1 (DDR0_PUB_REG_BASE+(0x10F<<2)) +#define DDR0_PUB_DX3LCDLR2 (DDR0_PUB_REG_BASE+(0x110<<2)) +#define DDR0_PUB_DX3MDLR (DDR0_PUB_REG_BASE+(0x111<<2)) +#define DDR0_PUB_DX3GTR (DDR0_PUB_REG_BASE+(0x112<<2)) +#define DDR0_PUB_DX4GCR0 (DDR0_PUB_REG_BASE+(0x120<<2)) +#define DDR0_PUB_DX4GCR1 (DDR0_PUB_REG_BASE+(0x121<<2)) +#define DDR0_PUB_DX4GCR2 (DDR0_PUB_REG_BASE+(0x122<<2)) +#define DDR0_PUB_DX4GCR3 (DDR0_PUB_REG_BASE+(0x123<<2)) +#define DDR0_PUB_DX4GSR0 (DDR0_PUB_REG_BASE+(0x124<<2)) +#define DDR0_PUB_DX4GSR1 (DDR0_PUB_REG_BASE+(0x125<<2)) +#define DDR0_PUB_DX4GSR2 (DDR0_PUB_REG_BASE+(0x126<<2)) +#define DDR0_PUB_DX4BDLR0 (DDR0_PUB_REG_BASE+(0x127<<2)) +#define DDR0_PUB_DX4BDLR1 (DDR0_PUB_REG_BASE+(0x128<<2)) +#define DDR0_PUB_DX4BDLR2 (DDR0_PUB_REG_BASE+(0x129<<2)) +#define DDR0_PUB_DX4BDLR3 (DDR0_PUB_REG_BASE+(0x12A<<2)) +#define DDR0_PUB_DX4BDLR4 (DDR0_PUB_REG_BASE+(0x12B<<2)) +#define DDR0_PUB_DX4BDLR5 (DDR0_PUB_REG_BASE+(0x12C<<2)) +#define DDR0_PUB_DX4BDLR6 (DDR0_PUB_REG_BASE+(0x12D<<2)) +#define DDR0_PUB_DX4LCDLR0 (DDR0_PUB_REG_BASE+(0x12E<<2)) +#define DDR0_PUB_DX4LCDLR1 (DDR0_PUB_REG_BASE+(0x12F<<2)) +#define DDR0_PUB_DX4LCDLR2 (DDR0_PUB_REG_BASE+(0x130<<2)) +#define DDR0_PUB_DX4MDLR (DDR0_PUB_REG_BASE+(0x131<<2)) +#define DDR0_PUB_DX4GTR (DDR0_PUB_REG_BASE+(0x132<<2)) +#define DDR0_PUB_DX5GCR0 (DDR0_PUB_REG_BASE+(0x140<<2)) +#define DDR0_PUB_DX5GCR1 (DDR0_PUB_REG_BASE+(0x141<<2)) +#define DDR0_PUB_DX5GCR2 (DDR0_PUB_REG_BASE+(0x142<<2)) +#define DDR0_PUB_DX5GCR3 (DDR0_PUB_REG_BASE+(0x143<<2)) +#define DDR0_PUB_DX5GSR0 (DDR0_PUB_REG_BASE+(0x144<<2)) +#define DDR0_PUB_DX5GSR1 (DDR0_PUB_REG_BASE+(0x145<<2)) +#define DDR0_PUB_DX5GSR2 (DDR0_PUB_REG_BASE+(0x146<<2)) +#define DDR0_PUB_DX5BDLR0 (DDR0_PUB_REG_BASE+(0x147<<2)) +#define DDR0_PUB_DX5BDLR1 (DDR0_PUB_REG_BASE+(0x148<<2)) +#define DDR0_PUB_DX5BDLR2 (DDR0_PUB_REG_BASE+(0x149<<2)) +#define DDR0_PUB_DX5BDLR3 (DDR0_PUB_REG_BASE+(0x14A<<2)) +#define DDR0_PUB_DX5BDLR4 (DDR0_PUB_REG_BASE+(0x14B<<2)) +#define DDR0_PUB_DX5BDLR5 (DDR0_PUB_REG_BASE+(0x14C<<2)) +#define DDR0_PUB_DX5BDLR6 (DDR0_PUB_REG_BASE+(0x14D<<2)) +#define DDR0_PUB_DX5LCDLR0 (DDR0_PUB_REG_BASE+(0x14E<<2)) +#define DDR0_PUB_DX5LCDLR1 (DDR0_PUB_REG_BASE+(0x14F<<2)) +#define DDR0_PUB_DX5LCDLR2 (DDR0_PUB_REG_BASE+(0x150<<2)) +#define DDR0_PUB_DX5MDLR (DDR0_PUB_REG_BASE+(0x151<<2)) +#define DDR0_PUB_DX5GTR (DDR0_PUB_REG_BASE+(0x152<<2)) +#define DDR0_PUB_DX6GCR0 (DDR0_PUB_REG_BASE+(0x160<<2)) +#define DDR0_PUB_DX6GCR1 (DDR0_PUB_REG_BASE+(0x161<<2)) +#define DDR0_PUB_DX6GCR2 (DDR0_PUB_REG_BASE+(0x162<<2)) +#define DDR0_PUB_DX6GCR3 (DDR0_PUB_REG_BASE+(0x163<<2)) +#define DDR0_PUB_DX6GSR0 (DDR0_PUB_REG_BASE+(0x164<<2)) +#define DDR0_PUB_DX6GSR1 (DDR0_PUB_REG_BASE+(0x165<<2)) +#define DDR0_PUB_DX6GSR2 (DDR0_PUB_REG_BASE+(0x166<<2)) +#define DDR0_PUB_DX6BDLR0 (DDR0_PUB_REG_BASE+(0x167<<2)) +#define DDR0_PUB_DX6BDLR1 (DDR0_PUB_REG_BASE+(0x168<<2)) +#define DDR0_PUB_DX6BDLR2 (DDR0_PUB_REG_BASE+(0x169<<2)) +#define DDR0_PUB_DX6BDLR3 (DDR0_PUB_REG_BASE+(0x16A<<2)) +#define DDR0_PUB_DX6BDLR4 (DDR0_PUB_REG_BASE+(0x16B<<2)) +#define DDR0_PUB_DX6BDLR5 (DDR0_PUB_REG_BASE+(0x16C<<2)) +#define DDR0_PUB_DX6BDLR6 (DDR0_PUB_REG_BASE+(0x16D<<2)) +#define DDR0_PUB_DX6LCDLR0 (DDR0_PUB_REG_BASE+(0x16E<<2)) +#define DDR0_PUB_DX6LCDLR1 (DDR0_PUB_REG_BASE+(0x16F<<2)) +#define DDR0_PUB_DX6LCDLR2 (DDR0_PUB_REG_BASE+(0x170<<2)) +#define DDR0_PUB_DX6MDLR (DDR0_PUB_REG_BASE+(0x171<<2)) +#define DDR0_PUB_DX6GTR (DDR0_PUB_REG_BASE+(0x172<<2)) +#define DDR0_PUB_DX7GCR0 (DDR0_PUB_REG_BASE+(0x180<<2)) +#define DDR0_PUB_DX7GCR1 (DDR0_PUB_REG_BASE+(0x181<<2)) +#define DDR0_PUB_DX7GCR2 (DDR0_PUB_REG_BASE+(0x182<<2)) +#define DDR0_PUB_DX7GCR3 (DDR0_PUB_REG_BASE+(0x183<<2)) +#define DDR0_PUB_DX7GSR0 (DDR0_PUB_REG_BASE+(0x184<<2)) +#define DDR0_PUB_DX7GSR1 (DDR0_PUB_REG_BASE+(0x185<<2)) +#define DDR0_PUB_DX7GSR2 (DDR0_PUB_REG_BASE+(0x186<<2)) +#define DDR0_PUB_DX7BDLR0 (DDR0_PUB_REG_BASE+(0x187<<2)) +#define DDR0_PUB_DX7BDLR1 (DDR0_PUB_REG_BASE+(0x188<<2)) +#define DDR0_PUB_DX7BDLR2 (DDR0_PUB_REG_BASE+(0x189<<2)) +#define DDR0_PUB_DX7BDLR3 (DDR0_PUB_REG_BASE+(0x18A<<2)) +#define DDR0_PUB_DX7BDLR4 (DDR0_PUB_REG_BASE+(0x18B<<2)) +#define DDR0_PUB_DX7BDLR5 (DDR0_PUB_REG_BASE+(0x18C<<2)) +#define DDR0_PUB_DX7BDLR6 (DDR0_PUB_REG_BASE+(0x18D<<2)) +#define DDR0_PUB_DX7LCDLR0 (DDR0_PUB_REG_BASE+(0x18E<<2)) +#define DDR0_PUB_DX7LCDLR1 (DDR0_PUB_REG_BASE+(0x18F<<2)) +#define DDR0_PUB_DX7LCDLR2 (DDR0_PUB_REG_BASE+(0x190<<2)) +#define DDR0_PUB_DX7MDLR (DDR0_PUB_REG_BASE+(0x191<<2)) +#define DDR0_PUB_DX7GTR (DDR0_PUB_REG_BASE+(0x192<<2)) +#define DDR0_PUB_DX8GCR0 (DDR0_PUB_REG_BASE+(0x1A0<<2)) +#define DDR0_PUB_DX8GCR1 (DDR0_PUB_REG_BASE+(0x1A1<<2)) +#define DDR0_PUB_DX8GCR2 (DDR0_PUB_REG_BASE+(0x1A2<<2)) +#define DDR0_PUB_DX8GCR3 (DDR0_PUB_REG_BASE+(0x1A3<<2)) +#define DDR0_PUB_DX8GSR0 (DDR0_PUB_REG_BASE+(0x1A4<<2)) +#define DDR0_PUB_DX8GSR1 (DDR0_PUB_REG_BASE+(0x1A5<<2)) +#define DDR0_PUB_DX8GSR2 (DDR0_PUB_REG_BASE+(0x1A6<<2)) +#define DDR0_PUB_DX8BDLR0 (DDR0_PUB_REG_BASE+(0x1A7<<2)) +#define DDR0_PUB_DX8BDLR1 (DDR0_PUB_REG_BASE+(0x1A8<<2)) +#define DDR0_PUB_DX8BDLR2 (DDR0_PUB_REG_BASE+(0x1A9<<2)) +#define DDR0_PUB_DX8BDLR3 (DDR0_PUB_REG_BASE+(0x1AA<<2)) +#define DDR0_PUB_DX8BDLR4 (DDR0_PUB_REG_BASE+(0x1AB<<2)) +#define DDR0_PUB_DX8BDLR5 (DDR0_PUB_REG_BASE+(0x1AC<<2)) +#define DDR0_PUB_DX8BDLR6 (DDR0_PUB_REG_BASE+(0x1AD<<2)) +#define DDR0_PUB_DX8LCDLR0 (DDR0_PUB_REG_BASE+(0x1AE<<2)) +#define DDR0_PUB_DX8LCDLR1 (DDR0_PUB_REG_BASE+(0x1AF<<2)) +#define DDR0_PUB_DX8LCDLR2 (DDR0_PUB_REG_BASE+(0x1B0<<2)) +#define DDR0_PUB_DX8MDLR (DDR0_PUB_REG_BASE+(0x1B1<<2)) +#define DDR0_PUB_DX8GTR (DDR0_PUB_REG_BASE+(0x1B2<<2)) diff --git a/plat/gxb/ddr/dmc_define.h b/plat/gxb/ddr/dmc_define.h new file mode 100644 index 0000000..20a607e --- /dev/null +++ b/plat/gxb/ddr/dmc_define.h @@ -0,0 +1,372 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/ddr/dmc_define.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#define DMC_REG_BASE 0xc8838000 + +#define DMC_REQ_CTRL (DMC_REG_BASE + (0x00 <<2 )) + //bit 11. enable dmc request of chan 11. Audio + //bit 10. enable dmc request of chan 10. Device. + //bit 9. enable dmc request of chan 9. VDEC2 + //bit 8. enable dmc request of chan 8. HCODEC + //bit 7. enable dmc request of chan 7. VDEC + //bit 6. enable dmc request of chan 6. VDIN + //bit 5. enable dmc request of chan 5. VDISP2 + //bit 4. enable dmc request of chan 4. VDISP + //bit 3. enable dmc request of chan 3. Mali + //bit 2. enable dmc request of chan 2. Mali + //bit 1. enable dmc request of chan 1. Mali + //bit 0. enable dmc request of chan 0. A9 +#define DMC_SOFT_RST (DMC_REG_BASE + (0x01 <<2 )) +#define DMC_SOFT_RST1 (DMC_REG_BASE + (0x02 <<2 )) +#define DMC_RST_STS (DMC_REG_BASE + (0x03 <<2 )) +#define DMC_RST_STS1 (DMC_REG_BASE + (0x04 <<2 )) +#define DMC_VERSION (DMC_REG_BASE + (0x05 <<2 )) + //read only default = 1. + +#define DMC_RAM_PD (DMC_REG_BASE + (0x11 <<2 )) + +#define DC_CAV_LUT_DATAL (DMC_REG_BASE + (0x12 <<2 )) + //low 32 bits of canvas data which need to be configured to canvas memory. +#define DC_CAV_LUT_DATAH (DMC_REG_BASE + (0x13 <<2 )) + //high 32bits of cavnas data which need to be configured to canvas memory. +#define DC_CAV_LUT_ADDR (DMC_REG_BASE + (0x14 <<2 )) + //bit 9:8. write 9:8 2'b10. the canvas data will saved in canvas memory with addres 7:0. + //bit 7:0. canvas address. +#define DC_CAV_LUT_RDATAL (DMC_REG_BASE + (0x15 <<2 )) +#define DC_CAV_LUT_RDATAH (DMC_REG_BASE + (0x16 <<2 )) +#define DMC_2ARB_CTRL (DMC_REG_BASE + (0x20 <<2 )) + +#define DMC_REFR_CTRL1 (DMC_REG_BASE + (0x23 <<2 )) + //bit23:16 tRFC waiting time, when hold nif command after refresh. + //bit 9 after refresh, hold nif command enable + //bit 8 when refresh req, hold nif command enable + //bit 7 dmc to control auto_refresh enable + //bit 6:4 refresh number per refresh cycle.. + //bit 3 pvt enable + //bit 2 zqc enable + //bit 1 ddr1 auto refresh dmc control select. + //bit 0 ddr0 auto refresh dmc control select. + +#define DMC_REFR_CTRL2 (DMC_REG_BASE + (0x24 <<2 )) + //bit 31:24 tZQCI + //bit 23:16 tPVTI + //bit 15:8 tREFI + //bit 7:0 t100ns + +#define DMC_PARB_CTRL (DMC_REG_BASE + (0x25 <<2 )) + //bit 17. default port1(MALI AXI port) urgent bit. + //bit 16 default port0(A9 AXI port ) urgent bit. + //bit 15:8 t_ugt_gap. when the consecutive urgent request granted over the t_ugt_wd times, we allow the number of non urgent request was granted by the port arbiter. + //bit 7:0. t_ugt_wd. + + +#define DMC_MON_CTRL2 (DMC_REG_BASE + (0x26 <<2 )) + //bit 31. qos_mon_en. write 1 to trigger the enable. polling this bit 0, means finished. or use interrupt to check finish. + //bit 30. qos_mon interrupt clear. clear the qos monitor result. read 1 = qos mon finish interrupt. + //bit 20. qos_mon_trig_sel. 1 = vsync. 0 = timer. + //bit 19:16. qos monitor channel select. select one at one time only. + //bit 15:0. port select for the selected channel. +#define DMC_MON_CTRL3 (DMC_REG_BASE + (0x27 <<2 )) + // qos_mon_clk_timer. How long to measure the bandwidth. + + +#define DMC_MON_ALL_REQ_CNT (DMC_REG_BASE + (0x28 <<2 )) + // at the test period, the whole MMC request time. +#define DMC_MON_ALL_GRANT_CNT (DMC_REG_BASE + (0x29 <<2 )) + // at the test period, the whole MMC granted data cycles. 64bits unit. +#define DMC_MON_ONE_GRANT_CNT (DMC_REG_BASE + (0x2a <<2 )) + // at the test period, the granted data cycles for the selected channel and ports. + +#define DMC_CLKG_CTRL0 (DMC_REG_BASE + (0x30 <<2 )) + //bit 29. enalbe auto clock gating for write rsp generation. + //bit 28. enalbe auto clock gating for read rsp generation. + //bit 27. enalbe auto clock gating for ddr1 read back data buffer. + //bit 26. enalbe auto clock gating for ddr0 read back data buffer. + //bit 25. enalbe auto clock gating for ddr1 command filter. + //bit 24. enalbe auto clock gating for ddr0 command filter. + //bit 23. enalbe auto clock gating for ddr1 write reorder buffer. + //bit 22. enalbe auto clock gating for ddr0 write reorder buffer. + //bit 21. enalbe auto clock gating for ddr1 write data buffer. + //bit 20. enalbe auto clock gating for ddr0 write data buffer. + //bit 19. enalbe auto clock gating for ddr1 read reorder buffer. + //bit 18. enalbe auto clock gating for ddr0 read reorder buffer. + //bit 17. enalbe auto clock gating for read canvas. + //bit 16. enalbe auto clock gating for write canvas. + //bit 15. enalbe auto clock gating for chan 15. + //bit 14. enalbe auto clock gating for chan 14. + //bit 13. enalbe auto clock gating for chan 13. + //bit 12. enalbe auto clock gating for chan 12. + //bit 11. enalbe auto clock gating for chan 11. + //bit 10. enalbe auto clock gating for chan 10. + //bit 9. enalbe auto clock gating for chan 9. + //bit 8. enalbe auto clock gating for chan 8. + //bit 7. enalbe auto clock gating for chan 7. + //bit 6. enalbe auto clock gating for chan 6. + //bit 5. enalbe auto clock gating for chan 5. + //bit 4. enalbe auto clock gating for chan 4. + //bit 3. enalbe auto clock gating for chan 3. + //bit 2. enalbe auto clock gating for chan 2. + //bit 1. enalbe auto clock gating for chan 1. + //bit 0. enalbe auto clock gating for chan 0. + +#define DMC_CLKG_CTRL1 (DMC_REG_BASE + (0x31 <<2 )) + //bit 29. force to disalbe the clock of write rsp generation. + //bit 28. force to disalbe the clock of read rsp generation. + //bit 27. force to disalbe the clock of ddr1 read back data buffer. + //bit 26. force to disalbe the clock of ddr0 read back data buffer. + //bit 25. force to disalbe the clock of ddr1 command filter. + //bit 24. force to disalbe the clock of ddr0 command filter. + //bit 23. force to disalbe the clock of ddr1 write reorder buffer. + //bit 22. force to disalbe the clock of ddr0 write reorder buffer. + //bit 21. force to disalbe the clock of ddr1 write data buffer. + //bit 20. force to disalbe the clock of ddr0 write data buffer. + //bit 19. force to disalbe the clock of ddr1 read reorder buffer. + //bit 18. force to disalbe the clock of ddr0 read reorder buffer. + //bit 17. force to disalbe the clock of read canvas. + //bit 16. force to disalbe the clock of write canvas. + //bit 15. force to disalbe the clock of chan 15. + //bit 14. force to disalbe the clock of chan 14. + //bit 13. force to disalbe the clock of chan 13. + //bit 12. force to disalbe the clock of chan 12. + //bit 11. force to disalbe the clock of chan 11. + //bit 10. force to disalbe the clock of chan 10. + //bit 9. force to disalbe the clock of chan 9. + //bit 8. force to disalbe the clock of chan 8. + //bit 7. force to disalbe the clock of chan 7. + //bit 6. force to disalbe the clock of chan 6. + //bit 5. force to disalbe the clock of chan 5. + //bit 4. force to disalbe the clock of chan 4. + //bit 3. force to disalbe the clock of chan 3. + //bit 2. force to disalbe the clock of chan 2. + //bit 1. force to disalbe the clock of chan 1. + //bit 0. force to disalbe the clock of chan 0. + + +#define DMC_CHAN_STS (DMC_REG_BASE + (0x32 <<2 )) + +#define DMC_CMD_FILTER_CTRL1 (DMC_REG_BASE + (0x40 <<2 )) + //bit 29:20 nugt read buf full access limit + //bit 19:10. ugt read access limit. + //bit 9:0 nugt read access limit + +#define DMC_CMD_FILTER_CTRL2 (DMC_REG_BASE + (0x41 <<2 )) + //bit 29:20 ugt read buf full access limit + //bit 9:0 nugt write access pending limit + //bit 19:10. ugt write access pending limit. + +#define DMC_CMD_FILTER_CTRL3 (DMC_REG_BASE + (0x42 <<2 )) + //bit 26:22 wbuf high level number + //bit 21:17 wbuf mid level number + //bit 16:12 wbuf low level number + //bit 11:8 rbuf high level number + //bit 7:4 rbuf middle level number + //bit 3:0 rbuf low level number + +#define DMC_CMD_FILTER_CTRL4 (DMC_REG_BASE + (0x43 <<2 )) + //bit 24:20. tHIT latency. page hit command latency for next same page not hit command. + //bit 19:15. tIDLE latency. page idle command latency for next same page not hit command. + //bit 14:10. tMISS latency. page miss command latency for next same page not hit command. + //bit 9:0. rbuf idle timer to let the wbuf output. +#define DMC_CMD_FILTER_CTRL5 (DMC_REG_BASE + ( 0x44 << 2)) + +#define DMC_CMD_BUFFER_CTRL (DMC_REG_BASE + (0x45 <<2 )) + //bit 30:25 total write buffer number. default 32. + //bit 24:20 total read buffer number. default 16. + //bit 19:10 ugt age limit. over this age limit, this read buffer would turn to super urgent. + //bit 9:0 nugt age limit. over this age limit, this read buffer would turn to super urgent. +#define DMC_PCTL_LP_CTRL (DMC_REG_BASE + ( 0x46 << 2)) + +#define DMC_AM0_CHAN_CTRL (DMC_REG_BASE + (0x60 <<2 )) +#define DMC_AM0_HOLD_CTRL (DMC_REG_BASE + (0x61 <<2 )) +#define DMC_AM0_QOS_INC (DMC_REG_BASE + (0x62 <<2 )) +#define DMC_AM0_QOS_INCBK (DMC_REG_BASE + (0x63 <<2 )) +#define DMC_AM0_QOS_DEC (DMC_REG_BASE + (0x64 <<2 )) +#define DMC_AM0_QOS_DECBK (DMC_REG_BASE + (0x65 <<2 )) +#define DMC_AM0_QOS_DIS (DMC_REG_BASE + (0x66 <<2 )) +#define DMC_AM0_QOS_DISBK (DMC_REG_BASE + (0x67 <<2 )) +#define DMC_AM0_QOS_CTRL0 (DMC_REG_BASE + (0x68 <<2 )) +#define DMC_AM0_QOS_CTRL1 (DMC_REG_BASE + (0x69 <<2 )) + +#define DMC_AM1_CHAN_CTRL (DMC_REG_BASE + (0x6a <<2 )) +#define DMC_AM1_HOLD_CTRL (DMC_REG_BASE + (0x6b <<2 )) +#define DMC_AM1_QOS_INC (DMC_REG_BASE + (0x6c <<2 )) +#define DMC_AM1_QOS_INCBK (DMC_REG_BASE + (0x6d <<2 )) +#define DMC_AM1_QOS_DEC (DMC_REG_BASE + (0x6e <<2 )) +#define DMC_AM1_QOS_DECBK (DMC_REG_BASE + (0x6f <<2 )) +#define DMC_AM1_QOS_DIS (DMC_REG_BASE + (0x70 <<2 )) +#define DMC_AM1_QOS_DISBK (DMC_REG_BASE + (0x71 <<2 )) +#define DMC_AM1_QOS_CTRL0 (DMC_REG_BASE + (0x72 <<2 )) +#define DMC_AM1_QOS_CTRL1 (DMC_REG_BASE + (0x73 <<2 )) + +#define DMC_AM2_CHAN_CTRL (DMC_REG_BASE + (0x74 <<2 )) +#define DMC_AM2_HOLD_CTRL (DMC_REG_BASE + (0x75 <<2 )) +#define DMC_AM2_QOS_INC (DMC_REG_BASE + (0x76 <<2 )) +#define DMC_AM2_QOS_INCBK (DMC_REG_BASE + (0x77 <<2 )) +#define DMC_AM2_QOS_DEC (DMC_REG_BASE + (0x78 <<2 )) +#define DMC_AM2_QOS_DECBK (DMC_REG_BASE + (0x79 <<2 )) +#define DMC_AM2_QOS_DIS (DMC_REG_BASE + (0x7a <<2 )) +#define DMC_AM2_QOS_DISBK (DMC_REG_BASE + (0x7b <<2 )) +#define DMC_AM2_QOS_CTRL0 (DMC_REG_BASE + (0x7c <<2 )) +#define DMC_AM2_QOS_CTRL1 (DMC_REG_BASE + (0x7d <<2 )) + +#define DMC_AM3_CHAN_CTRL (DMC_REG_BASE + (0x7e <<2 )) +#define DMC_AM3_HOLD_CTRL (DMC_REG_BASE + (0x7f <<2 )) +#define DMC_AM3_QOS_INC (DMC_REG_BASE + (0x80 <<2 )) +#define DMC_AM3_QOS_INCBK (DMC_REG_BASE + (0x81 <<2 )) +#define DMC_AM3_QOS_DEC (DMC_REG_BASE + (0x82 <<2 )) +#define DMC_AM3_QOS_DECBK (DMC_REG_BASE + (0x83 <<2 )) +#define DMC_AM3_QOS_DIS (DMC_REG_BASE + (0x84 <<2 )) +#define DMC_AM3_QOS_DISBK (DMC_REG_BASE + (0x85 <<2 )) +#define DMC_AM3_QOS_CTRL0 (DMC_REG_BASE + (0x86 <<2 )) +#define DMC_AM3_QOS_CTRL1 (DMC_REG_BASE + (0x87 <<2 )) + +#define DMC_AM4_CHAN_CTRL (DMC_REG_BASE + (0x88 <<2 )) +#define DMC_AM4_HOLD_CTRL (DMC_REG_BASE + (0x89 <<2 )) +#define DMC_AM4_QOS_INC (DMC_REG_BASE + (0x8a <<2 )) +#define DMC_AM4_QOS_INCBK (DMC_REG_BASE + (0x8b <<2 )) +#define DMC_AM4_QOS_DEC (DMC_REG_BASE + (0x8c <<2 )) +#define DMC_AM4_QOS_DECBK (DMC_REG_BASE + (0x8d <<2 )) +#define DMC_AM4_QOS_DIS (DMC_REG_BASE + (0x8e <<2 )) +#define DMC_AM4_QOS_DISBK (DMC_REG_BASE + (0x8f <<2 )) +#define DMC_AM4_QOS_CTRL0 (DMC_REG_BASE + (0x90 <<2 )) +#define DMC_AM4_QOS_CTRL1 (DMC_REG_BASE + (0x91 <<2 )) + +#define DMC_AM5_CHAN_CTRL (DMC_REG_BASE + (0x92 <<2 )) +#define DMC_AM5_HOLD_CTRL (DMC_REG_BASE + (0x93 <<2 )) +#define DMC_AM5_QOS_INC (DMC_REG_BASE + (0x94 <<2 )) +#define DMC_AM5_QOS_INCBK (DMC_REG_BASE + (0x95 <<2 )) +#define DMC_AM5_QOS_DEC (DMC_REG_BASE + (0x96 <<2 )) +#define DMC_AM5_QOS_DECBK (DMC_REG_BASE + (0x97 <<2 )) +#define DMC_AM5_QOS_DIS (DMC_REG_BASE + (0x98 <<2 )) +#define DMC_AM5_QOS_DISBK (DMC_REG_BASE + (0x99 <<2 )) +#define DMC_AM5_QOS_CTRL0 (DMC_REG_BASE + (0x9a <<2 )) +#define DMC_AM5_QOS_CTRL1 (DMC_REG_BASE + (0x9b <<2 )) + +#define DMC_AM6_CHAN_CTRL (DMC_REG_BASE + (0x9c <<2 )) +#define DMC_AM6_HOLD_CTRL (DMC_REG_BASE + (0x9d <<2 )) +#define DMC_AM6_QOS_INC (DMC_REG_BASE + (0x9e <<2 )) +#define DMC_AM6_QOS_INCBK (DMC_REG_BASE + (0x9f <<2 )) +#define DMC_AM6_QOS_DEC (DMC_REG_BASE + (0xa0 <<2 )) +#define DMC_AM6_QOS_DECBK (DMC_REG_BASE + (0xa1 <<2 )) +#define DMC_AM6_QOS_DIS (DMC_REG_BASE + (0xa2 <<2 )) +#define DMC_AM6_QOS_DISBK (DMC_REG_BASE + (0xa3 <<2 )) +#define DMC_AM6_QOS_CTRL0 (DMC_REG_BASE + (0xa4 <<2 )) +#define DMC_AM6_QOS_CTRL1 (DMC_REG_BASE + (0xa5 <<2 )) + +#define DMC_AM7_CHAN_CTRL (DMC_REG_BASE + (0xa6 <<2 )) +#define DMC_AM7_HOLD_CTRL (DMC_REG_BASE + (0xa7 <<2 )) +#define DMC_AM7_QOS_INC (DMC_REG_BASE + (0xa8 <<2 )) +#define DMC_AM7_QOS_INCBK (DMC_REG_BASE + (0xa9 <<2 )) +#define DMC_AM7_QOS_DEC (DMC_REG_BASE + (0xaa <<2 )) +#define DMC_AM7_QOS_DECBK (DMC_REG_BASE + (0xab <<2 )) +#define DMC_AM7_QOS_DIS (DMC_REG_BASE + (0xac <<2 )) +#define DMC_AM7_QOS_DISBK (DMC_REG_BASE + (0xad <<2 )) +#define DMC_AM7_QOS_CTRL0 (DMC_REG_BASE + (0xae <<2 )) +#define DMC_AM7_QOS_CTRL1 (DMC_REG_BASE + (0xaf <<2 )) + +#define DMC_AXI0_CHAN_CTRL (DMC_REG_BASE + (0xb0 <<2 )) +#define DMC_AXI0_HOLD_CTRL (DMC_REG_BASE + (0xb1 <<2 )) +#define DMC_AXI0_QOS_INC (DMC_REG_BASE + (0xb2 <<2 )) +#define DMC_AXI0_QOS_INCBK (DMC_REG_BASE + (0xb3 <<2 )) +#define DMC_AXI0_QOS_DEC (DMC_REG_BASE + (0xb4 <<2 )) +#define DMC_AXI0_QOS_DECBK (DMC_REG_BASE + (0xb5 <<2 )) +#define DMC_AXI0_QOS_DIS (DMC_REG_BASE + (0xb6 <<2 )) +#define DMC_AXI0_QOS_DISBK (DMC_REG_BASE + (0xb7 <<2 )) +#define DMC_AXI0_QOS_CTRL0 (DMC_REG_BASE + (0xb8 <<2 )) +#define DMC_AXI0_QOS_CTRL1 (DMC_REG_BASE + (0xb9 <<2 )) + +#define DMC_AXI1_CHAN_CTRL (DMC_REG_BASE + (0xba <<2 )) +#define DMC_AXI1_HOLD_CTRL (DMC_REG_BASE + (0xbb <<2 )) +#define DMC_AXI1_QOS_INC (DMC_REG_BASE + (0xbc <<2 )) +#define DMC_AXI1_QOS_INCBK (DMC_REG_BASE + (0xbd <<2 )) +#define DMC_AXI1_QOS_DEC (DMC_REG_BASE + (0xbe <<2 )) +#define DMC_AXI1_QOS_DECBK (DMC_REG_BASE + (0xbf <<2 )) +#define DMC_AXI1_QOS_DIS (DMC_REG_BASE + (0xc0 <<2 )) +#define DMC_AXI1_QOS_DISBK (DMC_REG_BASE + (0xc1 <<2 )) +#define DMC_AXI1_QOS_CTRL0 (DMC_REG_BASE + (0xc2 <<2 )) +#define DMC_AXI1_QOS_CTRL1 (DMC_REG_BASE + (0xc3 <<2 )) + +#define DMC_AXI2_CHAN_CTRL (DMC_REG_BASE + (0xc4 <<2 )) +#define DMC_AXI2_HOLD_CTRL (DMC_REG_BASE + (0xc5 <<2 )) +#define DMC_AXI2_QOS_INC (DMC_REG_BASE + (0xc6 <<2 )) +#define DMC_AXI2_QOS_INCBK (DMC_REG_BASE + (0xc7 <<2 )) +#define DMC_AXI2_QOS_DEC (DMC_REG_BASE + (0xc8 <<2 )) +#define DMC_AXI2_QOS_DECBK (DMC_REG_BASE + (0xc9 <<2 )) +#define DMC_AXI2_QOS_DIS (DMC_REG_BASE + (0xca <<2 )) +#define DMC_AXI2_QOS_DISBK (DMC_REG_BASE + (0xcb <<2 )) +#define DMC_AXI2_QOS_CTRL0 (DMC_REG_BASE + (0xcc <<2 )) +#define DMC_AXI2_QOS_CTRL1 (DMC_REG_BASE + (0xcd <<2 )) + +#define DMC_AXI3_CHAN_CTRL (DMC_REG_BASE + (0xce <<2 )) +#define DMC_AXI3_HOLD_CTRL (DMC_REG_BASE + (0xcf <<2 )) +#define DMC_AXI3_QOS_INC (DMC_REG_BASE + (0xd0 <<2 )) +#define DMC_AXI3_QOS_INCBK (DMC_REG_BASE + (0xd1 <<2 )) +#define DMC_AXI3_QOS_DEC (DMC_REG_BASE + (0xd2 <<2 )) +#define DMC_AXI3_QOS_DECBK (DMC_REG_BASE + (0xd3 <<2 )) +#define DMC_AXI3_QOS_DIS (DMC_REG_BASE + (0xd4 <<2 )) +#define DMC_AXI3_QOS_DISBK (DMC_REG_BASE + (0xd5 <<2 )) +#define DMC_AXI3_QOS_CTRL0 (DMC_REG_BASE + (0xd6 <<2 )) +#define DMC_AXI3_QOS_CTRL1 (DMC_REG_BASE + (0xd7 <<2 )) + +#define DMC_AXI4_CHAN_CTRL (DMC_REG_BASE + (0xd8 <<2 )) +#define DMC_AXI4_HOLD_CTRL (DMC_REG_BASE + (0xd9 <<2 )) +#define DMC_AXI4_QOS_INC (DMC_REG_BASE + (0xda <<2 )) +#define DMC_AXI4_QOS_INCBK (DMC_REG_BASE + (0xdb <<2 )) +#define DMC_AXI4_QOS_DEC (DMC_REG_BASE + (0xdc <<2 )) +#define DMC_AXI4_QOS_DECBK (DMC_REG_BASE + (0xdd <<2 )) +#define DMC_AXI4_QOS_DIS (DMC_REG_BASE + (0xde <<2 )) +#define DMC_AXI4_QOS_DISBK (DMC_REG_BASE + (0xdf <<2 )) +#define DMC_AXI4_QOS_CTRL0 (DMC_REG_BASE + (0xe0 <<2 )) +#define DMC_AXI4_QOS_CTRL1 (DMC_REG_BASE + (0xe1 <<2 )) + +#define DMC_AXI5_CHAN_CTRL (DMC_REG_BASE + (0xe2 <<2 )) +#define DMC_AXI5_HOLD_CTRL (DMC_REG_BASE + (0xe3 <<2 )) +#define DMC_AXI5_QOS_INC (DMC_REG_BASE + (0xe4 <<2 )) +#define DMC_AXI5_QOS_INCBK (DMC_REG_BASE + (0xe5 <<2 )) +#define DMC_AXI5_QOS_DEC (DMC_REG_BASE + (0xe6 <<2 )) +#define DMC_AXI5_QOS_DECBK (DMC_REG_BASE + (0xe7 <<2 )) +#define DMC_AXI5_QOS_DIS (DMC_REG_BASE + (0xe8 <<2 )) +#define DMC_AXI5_QOS_DISBK (DMC_REG_BASE + (0xe9 <<2 )) +#define DMC_AXI5_QOS_CTRL0 (DMC_REG_BASE + (0xea <<2 )) +#define DMC_AXI5_QOS_CTRL1 (DMC_REG_BASE + (0xeb <<2 )) + +#define DMC_AXI6_CHAN_CTRL (DMC_REG_BASE + (0xec <<2 )) +#define DMC_AXI6_HOLD_CTRL (DMC_REG_BASE + (0xed <<2 )) +#define DMC_AXI6_QOS_INC (DMC_REG_BASE + (0xee <<2 )) +#define DMC_AXI6_QOS_INCBK (DMC_REG_BASE + (0xef <<2 )) +#define DMC_AXI6_QOS_DEC (DMC_REG_BASE + (0xf0 <<2 )) +#define DMC_AXI6_QOS_DECBK (DMC_REG_BASE + (0xf1 <<2 )) +#define DMC_AXI6_QOS_DIS (DMC_REG_BASE + (0xf2 <<2 )) +#define DMC_AXI6_QOS_DISBK (DMC_REG_BASE + (0xf3 <<2 )) +#define DMC_AXI6_QOS_CTRL0 (DMC_REG_BASE + (0xf4 <<2 )) +#define DMC_AXI6_QOS_CTRL1 (DMC_REG_BASE + (0xf5 <<2 )) + +#define DMC_AXI7_CHAN_CTRL (DMC_REG_BASE + (0xf6 <<2 )) +#define DMC_AXI7_HOLD_CTRL (DMC_REG_BASE + (0xf7 <<2 )) +#define DMC_AXI7_QOS_INC (DMC_REG_BASE + (0xf8 <<2 )) +#define DMC_AXI7_QOS_INCBK (DMC_REG_BASE + (0xf9 <<2 )) +#define DMC_AXI7_QOS_DEC (DMC_REG_BASE + (0xfa <<2 )) +#define DMC_AXI7_QOS_DECBK (DMC_REG_BASE + (0xfb <<2 )) +#define DMC_AXI7_QOS_DIS (DMC_REG_BASE + (0xfc <<2 )) +#define DMC_AXI7_QOS_DISBK (DMC_REG_BASE + (0xfd <<2 )) +#define DMC_AXI7_QOS_CTRL0 (DMC_REG_BASE + (0xfe <<2 )) +#define DMC_AXI7_QOS_CTRL1 (DMC_REG_BASE + (0xff <<2 )) + diff --git a/plat/gxb/ddr/mmc_define.h b/plat/gxb/ddr/mmc_define.h new file mode 100644 index 0000000..7f738d8 --- /dev/null +++ b/plat/gxb/ddr/mmc_define.h @@ -0,0 +1,87 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/ddr/mmc_define.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#define AM_DDR_PLL_CNTL 0xc8836800 + //bit 31. PLL lock. read only + //bit 30. PLL power down. 1 = PLL powerdown. 0 = PLL enable. + //bit 29. PLL reset. + //bit 28. SSEN + //bit 27:24. SS_AMP + //bit 23:20. SS_CLK + //bit 17:16. OD. + //bit 15:14. OD1. + //bit 13:9. N. + //bit 8:0 M +#define AM_DDR_PLL_CNTL1 0xc8836804 + //bit 31:28. DPLL_LM_W + //bit 27:22. DPLL_LM_S. + //bit 21. DPFD_LMODE + //bit 20:19. DC_VC_IN. + //bit 18:17. DCO_SDMCK_SEL + //bit 16. DCO_M_EN. + //bit 15. SDM_PR_EN. + //bit 14 DIV_MODE. + //bit 13:2 DIV_FRAC + //bit 1 AFC_DSEL_BYPASS. + //bit 0. AFC_DSEL_IN. +#define AM_DDR_PLL_CNTL2 0xc8836808 + //bit 29:26. FILTER_PVT2. + //bit 25:22. FILTER PVT1. + //bit 21:11. FILTER ACQ2. + //bit 10:0. FILTER ACQ1. +#define AM_DDR_PLL_CNTL3 0xc883680c + //bit 31:20. DPLL REVE. + //bit 13:6. TDC_BUF. + //bit 5. PVT_FIX_EN. + //bit 4:3. DCO_IUP. + //bit 2. IIR_BYPASS_N. + //bit 1 TDC_EN +#define AM_DDR_PLL_CNTL4 0xc8836810 + //bit 21:20. DPLL_CLK_EN. + //bit 13. DCO_SDM_EN + //bit 12. BGP_EN. + //bit 11:8. GPB_C +#define AM_DDR_PLL_STS 0xc8836814 + //bit 31. DDR_PLL lock. + //bit 8:1. DPLL_OUT_RSV + //bit 0. AFC DONE. + +#define DDR_CLK_CNTL 0xc8836818 + //bit 31 ddr_pll_clk enable. enable the clock from DDR_PLL to clock generateion. + // whenever change the DDR_PLL frequency, disable the clock, after the DDR_PLL locked, then enable it again. + //bit 30. ddr_pll_prod_test_en. enable the clock to clock/32 which to clock frequency measurement and production test pin. + //bit 29. ddr_phy_ctl_clk enable. + //bit 28. clock generation logic soft reset. 0 = reset. + //bit 27. phy_4xclk phase inverter.. + //bit 26. pll_freq divide/2. 1: use pll div/2 clock as the n_clk. 0: use pll clock as n_clk. this setting is used for the synopsys DDR PHY PLL fast lock mode. + +#define DDR0_CLK_CTRL 0xc8836c00 +//bit 3. force to disable PUB PCLK. +//bit 2. PUB auto ctrl n_clk clock gating enable. when the DFI_LP_REQ and DFI_LP_ACK detected , auto gated PUB n_clk. +//bit 1. force to disable PUB PCLK. +//bit 0. PUB pclk auto clock gating enable. when the IP detected PCTL enter power down mode, use this bit to gating pub pclk. +#define DDR0_SOFT_RESET 0xc8836c04 +//bit 3. pub n_clk domain soft reset. 1 active. +//bit 2. pub p_clk domain soft reset. + +#define DDR0_APD_CTRL 0xc8836c08 +//bit 15:8. power down enter latency. when IP checked the dfi_lp_req && dfi_lp_ack, give PCTL and pub additional latency let them settle down, then gating the clock. +//bit 7:0. no active latency. after c_active_in become to low, wait additional latency to check the pctl low power state. diff --git a/plat/gxb/ddr/sec_mmc_define.h b/plat/gxb/ddr/sec_mmc_define.h new file mode 100644 index 0000000..2d4508c --- /dev/null +++ b/plat/gxb/ddr/sec_mmc_define.h @@ -0,0 +1,712 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/ddr/sec_mmc_define.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#define DMC_SEC_REG_BASE 0xda838400 +#define DMC_SEC_CTRL (DMC_SEC_REG_BASE + (0x00 <<2)) + + //security range defination have to be atom option. all the range controll register will be shadowed. + //write bit 31 to 1 to update the setting in shadow register to be used. +#define DMC_SEC_RANGE0_CTRL (DMC_SEC_REG_BASE + (0x01 <<2)) + //bit 31:16 : range 0 end address higher 16bits. + //bit 15:0 : range 0 start address higher 16bits. +#define DMC_SEC_RANGE1_CTRL (DMC_SEC_REG_BASE + (0x02 <<2)) + //bit 31:16 : range 1 end address higher 16bits. + //bit 15:0 : range 1 start address higher 16bits. +#define DMC_SEC_RANGE2_CTRL (DMC_SEC_REG_BASE + (0x03 <<2)) + //bit 31:16 : range 2 end address higher 16bits. + //bit 15:0 : range 2 start address higher 16bits. +#define DMC_SEC_RANGE3_CTRL (DMC_SEC_REG_BASE + (0x04 <<2)) + //bit 31:16 : range 3 end address higher 16bits. + //bit 15:0 : range 3 start address higher 16bits. +#define DMC_SEC_RANGE4_CTRL (DMC_SEC_REG_BASE + (0x05 <<2)) + //bit 31:16 : range 4 end address higher 16bits. + //bit 15:0 : range 4 start address higher 16bits. +#define DMC_SEC_RANGE5_CTRL (DMC_SEC_REG_BASE + (0x06 <<2)) + //bit 31:16 : range 5 end address higher 16bits. + //bit 15:0 : range 5 start address higher 16bits. +#define DMC_SEC_RANGE_CTRL (DMC_SEC_REG_BASE + (0x07 <<2)) + //bit 31:7 : not used + //bit 6 : default range security level. 1 : secure region. 0 : non secure region. + //bit 5 : range 5 security level. 1 : secure region. 0 : non secure region. + //bit 4 : range 4 security level. 1 : secure region. 0 : non secure region. + //bit 3 : range 3 security level. 1 : secure region. 0 : non secure region. + //bit 2 : range 2 security level. 1 : secure region. 0 : non secure region. + //bit 1 : range 1 security level. 1 : secure region. 0 : non secure region. + //bit 0 : range 0 security level. 1 : secure region. 0 : non secure region. + +#define DMC_SEC_AXI_PORT_CTRL (DMC_SEC_REG_BASE + (0x0e <<2)) + //bit 31~24. not used. + //bit 23. AXI port3 (HDCP ) secure region write access enable bit. 1: enable. 0 : disable. + //bit 22. AXI port3 (HDCP ) non secure region write access enable bit. 1: enable. 0 : disable. + //bit 21. AXI port2 (Mali 1) secure region write access enable bit. 1: enable. 0 : disable. + //bit 20. AXI port2 (Mali 1) non secure region write access enable bit. 1: enable. 0 : disable. + //bit 19. AXI port1 (Mali 0) secure region write access enable bit. 1: enable. 0 : disable. + //bit 18. AXI port1 (Mali 0) non secure region write access enable bit. 1: enable. 0 : disable. + //bit 17. AXI port0 (CPU) secure region write access enable bit. 1: enable. 0 : disable. + //bit 16. AXI port0 (CPU) non secure region write access enable bit. 1: enable. 0 : disable. + //bit 15~8. not used. + //bit 7. AXI port3 (HDCP ) secure region read access enable bit. 1: enable. 0 : disable. + //bit 6. AXI port3 (HDCP ) non secure region read access enable bit. 1: enable. 0 : disable. + //bit 5. AXI port2 (Mali 1) secure region read access enable bit. 1: enable. 0 : disable. + //bit 4. AXI port2 (Mali 1) non secure region read access enable bit. 1: enable. 0 : disable. + //bit 3. AXI port1 (Mali 0) secure region read access enable bit. 1: enable. 0 : disable. + //bit 2. AXI port1 (Mali 0) non secure region read access enable bit. 1: enable. 0 : disable. + //bit 1. AXI port0 (CPU) secure region read access enable bit. 1: enable. 0 : disable. + //bit 0. AXI port0 (CPU) non secure region read access enable bit. 1: enable. 0 : disable. + +#define DMC_VDEC_SEC_READ_CTRL (DMC_SEC_REG_BASE + (0x10 <<2)) + //bit 31. VDEC subID14 ( not used ) secure region read access enable bit. 1: enable. 0 : disable. + //bit 30. VDEC subID14 ( not used ) non secure region read access enable bit. 1: enable. 0 : disable. + //bit 29. VDEC subID14 ( not used ) secure region read access enable bit. 1: enable. 0 : disable. + //bit 28. VDEC subID14 ( not used ) non secure region read access enable bit. 1: enable. 0 : disable. + //bit 27. VDEC subID13 ( not used ) secure region read access enable bit. 1: enable. 0 : disable. + //bit 26. VDEC subID13 ( not used ) non secure region read access enable bit. 1: enable. 0 : disable. + //bit 25. VDEC subID12 ( not used ) secure region read access enable bit. 1: enable. 0 : disable. + //bit 24. VDEC subID12 ( not used ) non secure region read access enable bit. 1: enable. 0 : disable. + //bit 23. VDEC subID11 ( not used ) secure region read access enable bit. 1: enable. 0 : disable. + //bit 22. VDEC subID11 ( not used ) non secure region read access enable bit. 1: enable. 0 : disable. + //bit 21. VDEC subID10 ( mbbot ) secure region read access enable bit. 1: enable. 0 : disable. + //bit 20. VDEC subID10 ( mbbot ) non secure region read access enable bit. 1: enable. 0 : disable. + //bit 19. VDEC subID9 ( not used.) secure region read access enable bit. 1: enable. 0 : disable. + //bit 18. VDEC subID9 ( not used) non secure region read access enable bit. 1: enable. 0 : disable. + //bit 17. VDEC subID8 ( not used.) secure region read access enable bit. 1: enable. 0 : disable. + //bit 16. VDEC subID8 ( not used) non secure region read access enable bit. 1: enable. 0 : disable. + //bit 15. VDEC subID7 (dw) secure region read access enable bit. 1: enable. 0 : disable. + //bit 14. VDEC subID7 (dw) non secure region read access enable bit. 1: enable. 0 : disable. + //bit 13. VDEC subID6 (comb) secure region read access enable bit. 1: enable. 0 : disable. + //bit 12. VDEC subID6 (comb) non secure region read access enable bit. 1: enable. 0 : disable. + //bit 11. VDEC subID5 (lmem) secure region read access enable bit. 1: enable. 0 : disable. + //bit 10. VDEC subID5 (lmem) non secure region read access enable bit. 1: enable. 0 : disable. + //bit 9. VDEC subID4 (imem) secure region read access enable bit. 1: enable. 0 : disable. + //bit 8. VDEC subID4 (imem) non secure region read access enable bit. 1: enable. 0 : disable. + //bit 7. VDEC subID3 (picdc) secure region read access enable bit. 1: enable. 0 : disable. + //bit 6. VDEC subID3 (picdc) non secure region read access enable bit. 1: enable. 0 : disable. + //bit 5. VDEC subID2 (psc) secure region read access enable bit. 1: enable. 0 : disable. + //bit 4. VDEC subID2 (psc) non secure region read access enable bit. 1: enable. 0 : disable. + //bit 3. VDEC subID1 (dcac) secure region read access enable bit. 1: enable. 0 : disable. + //bit 2. VDEC subID1 (dcac) non secure region read access enable bit. 1: enable. 0 : disable. + //bit 1. VDEC subID0 (vld) secure region read access enable bit. 1: enable. 0 : disable. + //bit 0. VDEC subID0 (vld) non secure region read access enable bit. 1: enable. 0 : disable. +#define DMC_VDEC_SEC_WRITE_CTRL (DMC_SEC_REG_BASE + (0x11 <<2)) + //bit 31. VDEC subID14 ( not used ) secure region write access enable bit. 1: enable. 0 : disable. + //bit 30. VDEC subID14 ( not used ) non secure region write access enable bit. 1: enable. 0 : disable. + //bit 29. VDEC subID14 ( not used ) secure region write access enable bit. 1: enable. 0 : disable. + //bit 28. VDEC subID14 ( not used ) non secure region write access enable bit. 1: enable. 0 : disable. + //bit 27. VDEC subID13 ( not used ) secure region write access enable bit. 1: enable. 0 : disable. + //bit 26. VDEC subID13 ( not used ) non secure region write access enable bit. 1: enable. 0 : disable. + //bit 25. VDEC subID12 ( not used ) secure region write access enable bit. 1: enable. 0 : disable. + //bit 24. VDEC subID12 ( not used ) non secure region write access enable bit. 1: enable. 0 : disable. + //bit 23. VDEC subID11 ( not used ) secure region write access enable bit. 1: enable. 0 : disable. + //bit 22. VDEC subID11 ( not used ) non secure region write access enable bit. 1: enable. 0 : disable. + //bit 21. VDEC subID10 ( mbbot ) secure region write access enable bit. 1: enable. 0 : disable. + //bit 20. VDEC subID10 ( mbbot ) non secure region write access enable bit. 1: enable. 0 : disable. + //bit 19. VDEC subID9 ( not used.) secure region write access enable bit. 1: enable. 0 : disable. + //bit 18. VDEC subID9 ( not used) non secure region write access enable bit. 1: enable. 0 : disable. + //bit 17. VDEC subID8 ( not used.) secure region write access enable bit. 1: enable. 0 : disable. + //bit 16. VDEC subID8 ( not used) non secure region write access enable bit. 1: enable. 0 : disable. + //bit 15. VDEC subID7 (dw) secure region write access enable bit. 1: enable. 0 : disable. + //bit 14. VDEC subID7 (dw) non secure region write access enable bit. 1: enable. 0 : disable. + //bit 13. VDEC subID6 (comb) secure region write access enable bit. 1: enable. 0 : disable. + //bit 12. VDEC subID6 (comb) non secure region write access enable bit. 1: enable. 0 : disable. + //bit 11. VDEC subID5 (lmem) secure region write access enable bit. 1: enable. 0 : disable. + //bit 10. VDEC subID5 (lmem) non secure region write access enable bit. 1: enable. 0 : disable. + //bit 9. VDEC subID4 (imem) secure region write access enable bit. 1: enable. 0 : disable. + //bit 8. VDEC subID4 (imem) non secure region write access enable bit. 1: enable. 0 : disable. + //bit 7. VDEC subID3 (picdc) secure region write access enable bit. 1: enable. 0 : disable. + //bit 6. VDEC subID3 (picdc) non secure region write access enable bit. 1: enable. 0 : disable. + //bit 5. VDEC subID2 (psc) secure region write access enable bit. 1: enable. 0 : disable. + //bit 4. VDEC subID2 (psc) non secure region write access enable bit. 1: enable. 0 : disable. + //bit 3. VDEC subID1 (dcac) secure region write access enable bit. 1: enable. 0 : disable. + //bit 2. VDEC subID1 (dcac) non secure region write access enable bit. 1: enable. 0 : disable. + //bit 1. VDEC subID0 (vld) secure region write access enable bit. 1: enable. 0 : disable. + //bit 0. VDEC subID0 (vld) non secure region write access enable bit. 1: enable. 0 : disable. +#define DMC_VDEC_SEC_CFG (DMC_SEC_REG_BASE + (0x12 <<2)) + //DWC_VDEC_SEC_READ_CTRL and DMC_VDEC_SEC_WRITE_CTRL register APB bus configuation enable. 2 bit for each port. one for read, one for write. + //bit 31. VDEC subID15 () To enable APB bus modifiy the write security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 30. VDEC subID14 () To enable APB bus modifiy the write security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 29. VDEC subID13 () To enable APB bus modifiy the write security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 28. VDEC subID12 () To enable APB bus modifiy the write security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 27. VDEC subID11 () To enable APB bus modifiy the write security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 26. VDEC subID10 (mbbot) To enable APB bus modifiy the write security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 25. VDEC subID9 () To enable APB bus modifiy the write security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 24. VDEC subID8 () To enable APB bus modifiy the write security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 23. VDEC subID7 (dw) To enable APB bus modifiy the write security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 22. VDEC subID6 (comb) To enable APB bus modifiy the write security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 21. VDEC subID5 (lmem) To enable APB bus modifiy the write security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 20. VDEC subID4 (imem) To enable APB bus modifiy the write security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 19. VDEC subID3 (picdc) To enable APB bus modifiy the write security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 18. VDEC subID2 (psc) To enable APB bus modifiy the write security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 17. VDEC subID1 (dcac) To enable APB bus modifiy the write security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 16. VDEC subID0 (vld) To enable APB bus modifiy the write security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 15. VDEC subID15 () To enable APB bus modifiy the read security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 14. VDEC subID14 () To enable APB bus modifiy the read security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 13. VDEC subID13 () To enable APB bus modifiy the read security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 12. VDEC subID12 () To enable APB bus modifiy the read security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 11. VDEC subID11 () To enable APB bus modifiy the read security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 10. VDEC subID10 (mbbot) To enable APB bus modifiy the read security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 9. VDEC subID9 () To enable APB bus modifiy the read security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 8. VDEC subID8 () To enable APB bus modifiy the read security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 7. VDEC subID7 (dw) To enable APB bus modifiy the read security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 6. VDEC subID6 (comb) To enable APB bus modifiy the read security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 5. VDEC subID5 (lmem) To enable APB bus modifiy the read security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 4. VDEC subID4 (imem) To enable APB bus modifiy the read security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 3. VDEC subID3 (picdc) To enable APB bus modifiy the read security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 2. VDEC subID2 (psc) To enable APB bus modifiy the read security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 1. VDEC subID1 (dcac) To enable APB bus modifiy the read security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + //bit 0. VDEC subID0 (vld) To enable APB bus modifiy the read security control bits. 1 : eable the APB modify. 0 : disable APB bus modify. + +#define DMC_VDEC_EF_TRIG_CTRL (DMC_SEC_REG_BASE + (0x13 <<2)) + // VDEC Electronic fence trigger selection and trigger secure type. 1 bit for trigger select for one read port. 1 bit for trigger type for one read port. + //Electronic would be triggered by the read from defined secure level from selected subIDs. + //bit 31. trigger type selection for subID15 (). 1 = secure access. 0 : non secure access. + //bit 30. trigger type selection for subID14 (). 1 = secure access. 0 : non secure access. + //bit 29. trigger type selection for subID13 (). 1 = secure access. 0 : non secure access. + //bit 28. trigger type selection for subID12 (). 1 = secure access. 0 : non secure access. + //bit 27. trigger type selection for subID11 (). 1 = secure access. 0 : non secure access. + //bit 26. trigger type selection for subID10 (). 1 = secure access. 0 : non secure access. + //bit 25. trigger type selection for subID9 (). 1 = secure access. 0 : non secure access. + //bit 24. trigger type selection for subID8 (). 1 = secure access. 0 : non secure access. + //bit 23. trigger type selection for subID7 (dw). 1 = secure access. 0 : non secure access. + //bit 22. trigger type selection for subID6 (comb). 1 = secure access. 0 : non secure access. + //bit 21. trigger type selection for subID5 (lmem). 1 = secure access. 0 : non secure access. + //bit 20. trigger type selection for subID4 (imem). 1 = secure access. 0 : non secure access. + //bit 19. trigger type selection for subID3 (picdc). 1 = secure access. 0 : non secure access. + //bit 18. trigger type selection for subID2 (psc). 1 = secure access. 0 : non secure access. + //bit 17. trigger type selection for subID1 (dcac). 1 = secure access. 0 : non secure access. + //bit 16. trigger type selection for subID0 (vld). 1 = secure access. 0 : non secure access. + //bit 15. trigger source selection for subID15 (). 1 = selected. 0 : not selected. + //bit 14. trigger source selection for subID14 (). 1 = selected. 0 : not selected. + //bit 13. trigger source selection for subID13 (). 1 = selected. 0 : not selected. + //bit 12. trigger source selection for subID12 (). 1 = selected. 0 : not selected. + //bit 11. trigger source selection for subID11 (). 1 = selected. 0 : not selected. + //bit 10. trigger source selection for subID10 (). 1 = selected. 0 : not selected. + //bit 9. trigger source selection for subID9 (). 1 = selected. 0 : not selected. + //bit 8. trigger source selection for subID8 (). 1 = selected. 0 : not selected. + //bit 7. trigger source selection for subID7 (dw). 1 = selected. 0 : not selected. + //bit 6. trigger source selection for subID6 (comb). 1 = selected. 0 : not selected. + //bit 5. trigger source selection for subID5 (lmem). 1 = selected. 0 : not selected. + //bit 4. trigger source selection for subID4 (imem). 1 = selected. 0 : not selected. + //bit 3. trigger source selection for subID3 (picdc). 1 = selected. 0 : not selected. + //bit 2. trigger source selection for subID2 (psc). 1 = selected. 0 : not selected. + //bit 1. trigger source selection for subID1 (dcac). 1 = selected. 0 : not selected. + //bit 0. trigger source selection for subID0 (vld). 1 = selected. 0 : not selected. + +#define DMC_VDEC_EF_PROT (DMC_SEC_REG_BASE + (0x14 <<2)) + //to define which subID would be affected if the EF got triggered. + //bit 31. EF would affect subID15 () write access secure control. 1 = selected. 0 : not selected. + //bit 30. EF would affect subID14 () write access secure control. 1 = selected. 0 : not selected. + //bit 29. EF would affect subID13 () write access secure control. 1 = selected. 0 : not selected. + //bit 28. EF would affect subID12 () write access secure control. 1 = selected. 0 : not selected. + //bit 27. EF would affect subID11 () write access secure control. 1 = selected. 0 : not selected. + //bit 26. EF would affect subID10 () write access secure control. 1 = selected. 0 : not selected. + //bit 25. EF would affect subID9 () write access secure control. 1 = selected. 0 : not selected. + //bit 24. EF would affect subID8 () write access secure control. 1 = selected. 0 : not selected. + //bit 23. EF would affect subID7 (dw) write access secure control. 1 = selected. 0 : not selected. + //bit 22. EF would affect subID6 (comb) write access secure control. 1 = selected. 0 : not selected. + //bit 21. EF would affect subID5 (lmem) write access secure control. 1 = selected. 0 : not selected. + //bit 20. EF would affect subID4 (imem) write access secure control. 1 = selected. 0 : not selected. + //bit 19. EF would affect subID3 (picdc) write access secure control. 1 = selected. 0 : not selected. + //bit 18. EF would affect subID2 (psc) write access secure control. 1 = selected. 0 : not selected. + //bit 17. EF would affect subID1 (dcac) write access secure control. 1 = selected. 0 : not selected. + //bit 16. EF would affect subID0 (vld) write access secure control. 1 = selected. 0 : not selected. + //bit 15. EF would affect subID15 () read access secure control. 1 = selected. 0 : not selected. + //bit 14. EF would affect subID14 () read access secure control. 1 = selected. 0 : not selected. + //bit 13. EF would affect subID13 () read access secure control. 1 = selected. 0 : not selected. + //bit 12. EF would affect subID12 () read access secure control. 1 = selected. 0 : not selected. + //bit 11. EF would affect subID11 () read access secure control. 1 = selected. 0 : not selected. + //bit 10. EF would affect subID10 () read access secure control. 1 = selected. 0 : not selected. + //bit 9. EF would affect subID9 () read access secure control. 1 = selected. 0 : not selected. + //bit 8. EF would affect subID8 () read access secure control. 1 = selected. 0 : not selected. + //bit 7. EF would affect subID7 (dw) read access secure control. 1 = selected. 0 : not selected. + //bit 6. EF would affect subID6 (comb) read access secure control. 1 = selected. 0 : not selected. + //bit 5. EF would affect subID5 (lmem) read access secure control. 1 = selected. 0 : not selected. + //bit 4. EF would affect subID4 (imem) read access secure control. 1 = selected. 0 : not selected. + //bit 3. EF would affect subID3 (picdc) read access secure control. 1 = selected. 0 : not selected. + //bit 2. EF would affect subID2 (psc) read access secure control. 1 = selected. 0 : not selected. + //bit 1. EF would affect subID1 (dcac) read access secure control. 1 = selected. 0 : not selected. + //bit 0. EF would affect subID0 (vld) read access secure control. 1 = selected. 0 : not selected. +#define DMC_VDEC_EF_READ (DMC_SEC_REG_BASE + (0x15 <<2)) + //this register contains the vdec read security control bits after the EF got triggered. + //if the DMC_VDEC_EF_PROT register bit 15:0 related bit was enable, then the related secure control bits would be copied to DMC_VDEC_SEC_READ_CTRL related bits. + +#define DMC_VDEC_EF_WRITE (DMC_SEC_REG_BASE + (0x16 <<2)) + //this register contains the vdec write security control bits after the EF got triggered. + //if the DMC_VDEC_EF_PROT register bit 15:0 related bit was enable, then the related secure control bits would be copied to DMC_VDEC_SEC_READ_CTRL related bits. + + //HCODEC security and Electronic fence is same as VDEC with different SUBID define.. + //subID15:13 : not used. + //subID12 : ME. + //subID11 : mfdin + //subID10 : mcmbot + //subID9 : i_pred. + //subID8 : qdct + //subID7 : vlc + //subID6 : comb + //subID5 : LMEM + //subID4 : IMEM. + //subID3 : mcrcc + //subID2 : PSC + //subID1 : dcac + //subID0 : vld +#define DMC_HCODEC_SEC_READ_CTRL (DMC_SEC_REG_BASE + (0x17 <<2)) + //each subID with 2bits. one for secure region. one for unsecure region. + +#define DMC_HCODEC_SEC_WRITE_CTRL (DMC_SEC_REG_BASE + (0x18 <<2)) + //each subID with 2bits. one for secure region. one for unsecure region. + +#define DMC_HCODEC_SEC_CFG (DMC_SEC_REG_BASE + (0x19 <<2)) + //DWC_HCODEC_SEC_READ_CTRL and DMC_HCODEC_SEC_WRITE_CTRL register APB bus configuation enable. 2 bit for each port. one for read, one for write. + +#define DMC_HCODEC_EF_TRIG_CTRL (DMC_SEC_REG_BASE + (0x1a <<2)) + // HCODEC Electronic fence trigger selection and trigger secure type. 1 bit for trigger select for one read port. 1 bit for trigger type for one read port. + +#define DMC_HCODEC_EF_PROT (DMC_SEC_REG_BASE + (0x1b <<2)) + // HCODEC EF protected access control. each subID 2 bits. one for read one for write. +#define DMC_HCODEC_EF_READ (DMC_SEC_REG_BASE + (0x1c <<2)) + //the DWC_HCODEC_SEC_READ_CTRL value need to be changed after HCODEC EF fence triggered. once the trigger happens, the DMC_HCODEC_EF_PROT[15:0] bit enabled subIDs value will be copied to DWC_HCODEC_SEC_READ_CTRL register. +#define DMC_HCODEC_EF_WRITE (DMC_SEC_REG_BASE + (0x1d <<2)) + //the DWC_HCODEC_SEC_WRITE_CTRL value need to be changed after HCODEC EF fence triggered. once the trigger happens, the DMC_HCODEC_EF_PROT[31:16] bit enabled subIDs value will be copied to DWC_HCODEC_SEC_WRITE_CTRL register. + +//HEVC security and electronic fence control is similar with VDEC/HCODE. only difference is in HEVC, the LMEM/IMEM are shared in one SUBID. so we need to have seperate seting for them. + //subID 7 : mpred. + //subID 6 : dblk_d + //subID 5 : dblk_p + //subID 4 : ipp + //subID 3 : mpp + //subID 2 : SAO + //subID 1 : stream. + //subID 0 : AMRISC CPU. include IMEM and LMEM. AR/WID[3:0] == 0 IMEM. LMEM. + //HEVC ID 7. [6:4] for subID. +#define DMC_HEVC_SEC_READ_CTRL (DMC_SEC_REG_BASE + (0x1e <<2)) + //bit 31:18. not used. + //bit 17. READ secure area eable bit for HEVC subID0 CPU with IDbits 3:0 != 4'h0 read access. 1 : enable. 0 : disable. + //bit 16. READ non secure area eable bit for HEVC subID 0 CPU with IDbits 3:0 != 4'h0 read access. 1 : enable. 0 : disable. + //bit 15. READ secure area eable bit for HEVC subID 7 mpred read access. 1 : enable. 0 : disable. + //bit 14. READ non secure area eable bit for HEVC subID 7 mpred read access. 1 : enable. 0 : disable. + //bit 13. READ secure area eable bit for HEVC subID 6 dblk_d read access. 1 : enable. 0 : disable. + //bit 12. READ non secure area eable bit for HEVC subID 6 dblk_d read access. 1 : enable. 0 : disable. + //bit 11. READ secure area eable bit for HEVC subID 5 dblk_p read access. 1 : enable. 0 : disable. + //bit 10. READ non secure area eable bit for HEVC subID 5 dblk_p read access. 1 : enable. 0 : disable. + //bit 9. READ secure area eable bit for HEVC subID 4 ipp read access. 1 : enable. 0 : disable. + //bit 8. READ non secure area eable bit for HEVC subID 4 ipp read access. 1 : enable. 0 : disable. + //bit 7. READ secure area eable bit for HEVC subID 3 mpp read access. 1 : enable. 0 : disable. + //bit 6. READ non secure area eable bit for HEVC subID 3 mpp read access. 1 : enable. 0 : disable. + //bit 5. READ secure area eable bit for HEVC subID 2 SAO read access. 1 : enable. 0 : disable. + //bit 4. READ non secure area eable bit for HEVC subID 2 SAO read access. 1 : enable. 0 : disable. + //bit 3. READ secure area eable bit for HEVCsubID 1 stream read access. 1 : enable. 0 : disable. + //bit 2. READ non secure area eable bit for HEVC subID 1 stream read access. 1 : enable. 0 : disable. + //bit 1. READ secure area eable bit for HEVC CPU access with ID bit 3:0 = 4'h0. 1 : enable. 0 : disable. + //bit 0. READ non secure area eable bit for HEVC CPU access with ID bit 3:0 = 4'h0. 1 : enable. 0 : disable. + +#define DMC_HEVC_SEC_WRITE_CTRL (DMC_SEC_REG_BASE + (0x1f <<2)) + //bit 31:18. not used. + //bit 17. WRITE secure area eable bit for HEVC subID0 CPU with IDbits[7:4] == 4'h1 write access. 1 : enable. 0 : disable. + //bit 16. WRITE non secure area eable bit for HEVC subID 0 CPU IDbits[7:4] == 4'h1 write access. 1 : enable. 0 : disable. + //bit 15. WRITE secure area eable bit for HEVC subID [7:5] ==7 mpred write access. 1 : enable. 0 : disable. + //bit 14. WRITE non secure area eable bit for HEVC subID 7 mpred write access. 1 : enable. 0 : disable. + //bit 13. WRITE secure area eable bit for HEVC subID [7:5] == 6 dblk_d write access. 1 : enable. 0 : disable. + //bit 12. WRITE non secure area eable bit for HEVC subID [7:5] == 6 dblk_d write access. 1 : enable. 0 : disable. + //bit 11. WRITE secure area eable bit for HEVC subID [7:5] == 5 dblk_p write access. 1 : enable. 0 : disable. + //bit 10. WRITE non secure area eable bit for HEVC subID [7:5] == 5 dblk_p write access. 1 : enable. 0 : disable. + //bit 9. WRITE secure area eable bit for HEVC subID [7:5] == 4 ipp write access. 1 : enable. 0 : disable. + //bit 8. WRITE non secure area eable bit for HEVC subID [7:5] == 4 ipp write access. 1 : enable. 0 : disable. + //bit 7. WRITE secure area eable bit for HEVC subID [7:5] == 3 mpp write access. 1 : enable. 0 : disable. + //bit 6. WRITE non secure area eable bit for HEVC subID [7:5] == 3 mpp write access. 1 : enable. 0 : disable. + //bit 5. WRITE secure area eable bit for HEVC subID [7:5] == 2 SAO write access. 1 : enable. 0 : disable. + //bit 4. WRITE non secure area eable bit for HEVC subID 2 SAO write access. 1 : enable. 0 : disable. + //bit 3. WRITE secure area eable bit for HEVCsubID [7:5] == 1 stream write access. 1 : enable. 0 : disable. + //bit 2. WRITE non secure area eable bit for HEVC subID [7:5] == 1 stream write access. 1 : enable. 0 : disable. + //bit 1. WRITE secure area eable bit for HEVC CPU access with ID bit 7 :4 = 4'h0. 1 : enable. 0 : disable. + //bit 0. WRITE non secure area eable bit for HEVC CPU access with ID bit 7:4 = 4'h0. 1 : enable. 0 : disable. + +#define DMC_HEVC_SEC_CFG (DMC_SEC_REG_BASE + (0x20 <<2)) + //24:16 9 CBUS modfiy enable bit for 9 write secure cotnrol SUBIDs + // 8:0. 9 CBUS modify enable bit for 9 READ secure control SUBIDs. +#define DMC_HEVC_EF_TRIG_CTRL (DMC_SEC_REG_BASE + (0x21 <<2)) + //bit 24:16. 9 HEVC EF trigger selection type for 9 SUBID read access. + //bit 8:0. 9 HEVC EF trigger selection for 9 SUBID read acess. + +#define DMC_HEVC_EF_PROT (DMC_SEC_REG_BASE + (0x22 <<2)) + //bit 24:16. 9 HEVC EF controlled write subID selection. + //bit 8:0. 9 HEVC EF controlled read subIDs selection. + +#define DMC_HEVC_EF_READ (DMC_SEC_REG_BASE + (0x23 <<2)) + //bit 17:0. DWC_HEVC_SEC_READ_CTRL value need to be changed after HEVC EF fence triggered. +#define DMC_HEVC_EF_WRITE (DMC_SEC_REG_BASE + (0x24 <<2)) + //bit 17:0. DWC_HEVC_SEC_WRITE_CTRL value need to be changed after HEVC EF fence triggered. + + + +//there are upto 16 read subID inside VPU and dynamic allocated 3 VPU read ports. +//there are upto 16 write subIDs insdie VPU and dynamic allocated 2 VPU write ports +//there are 3 electronic fences for VPU domain. we can allocated any of those 16 read ports as the trigger of the 3 EF. +//the 3 EF also can control any of those read ports and write ports security levels. +//the Software should make sure there's no conflit setting between these 3 EFs. +#define DMC_VPU_SEC_READ_CTRL (DMC_SEC_REG_BASE + (0x32 <<2)) +//bit 31:0. each read subID have 2 bits securty control. one is for seucre area access. one is for unsecure aread access. + +#define DMC_VPU_SEC_WRITE_CTRL (DMC_SEC_REG_BASE + (0x33 <<2)) +//bit 31:0. each write subID have 2 bits securty control. one is for seucre area access. one is for unsecure aread access. + +#define DMC_VPU_SEC_CFG (DMC_SEC_REG_BASE + (0x25 <<2)) + //31:16 enable APB bus configure VPU write SubIDs security contrl register DMC_VPU_SEC_WRITE_CTRL. + //15:0 enable APB bus configure for VPU read SubIDs security control register. DMC_VPU_SEC_READ_CTRL +#define DMC_VPU_EF0_TRIG_CTRL (DMC_SEC_REG_BASE + (0x26 <<2)) + //31:16. VPU EF0 trigger selection read source type. + //15:0. VPU EF0 trigger selection read source select. +#define DMC_VPU_EF0_PROT (DMC_SEC_REG_BASE + (0x27 <<2)) + //bit 24:16. 16 VPU EF0 controlled write subIDs selection. + //bit 15:0. 16 VPU EF0 controlled read subIDs selection. +#define DMC_VPU_EF0_READ (DMC_SEC_REG_BASE + (0x28 <<2)) + //EF0 controlled DMC_VPU_SEC_READ_CTRL. +#define DMC_VPU_EF0_WRITE (DMC_SEC_REG_BASE + (0x29 <<2)) + //EF0 controlled DMC_VPU_SEC_WRITE_CTRL. + +#define DMC_VPU_EF1_TRIG_CTRL (DMC_SEC_REG_BASE + (0x2a <<2)) + //31:16. VPU EF1 trigger selection read source type. + //15:0. VPU EF1 trigger selection read source select. +#define DMC_VPU_EF1_PROT (DMC_SEC_REG_BASE + (0x2b <<2)) + //bit 24:16. 16 VPU EF1 controlled write subIDs selection. + //bit 15:0. 16 VPU EF1 controlled read subIDs selection. +#define DMC_VPU_EF1_READ (DMC_SEC_REG_BASE + (0x2c <<2)) + //EF1 controlled DMC_VPU_SEC_READ_CTRL. +#define DMC_VPU_EF1_WRITE (DMC_SEC_REG_BASE + (0x2d <<2)) + //EF1 controlled DMC_VPU_SEC_WRITE_CTRL. +#define DMC_VPU_EF2_TRIG_CTRL (DMC_SEC_REG_BASE + (0x2e <<2)) + //31:16. VPU EF2 trigger selection read source type. + //15:0. VPU EF2 trigger selection read source select. +#define DMC_VPU_EF2_PROT (DMC_SEC_REG_BASE + (0x2f <<2)) + //bit 24:16. 16 VPU EF2 controlled write subIDs selection. + //bit 15:0. 16 VPU EF2 controlled read subIDs selection. +#define DMC_VPU_EF2_READ (DMC_SEC_REG_BASE + (0x30 <<2)) + //EF2 controlled DMC_VPU_SEC_READ_CTRL. +#define DMC_VPU_EF2_WRITE (DMC_SEC_REG_BASE + (0x31 <<2)) + //EF2 controlled DMC_VPU_SEC_WRITE_CTRL. + + //GE2D is seperated port in GX. +#define DMC_GE2D_SEC_CTRL (DMC_SEC_REG_BASE + (0x34 <<2)) + //bit 31:22 NOT USED. + //bit 21:16. GE2D secure control after EF triggered. + //bit 14:12 GE2D EF proection selection after EF triggered.. + //bit 11:10 GE2D Electronic fence trigger read source secure type selection. + //bit 9:8 GE2D Electronic fence trigger read source selection. + //bit 5:4. GE2D write destination 2 secruity control bits. + //bit 3:2. GE2D read source 2 secruity control bits. + //bit 1:0. GE2D read source 1 secruity control bits. + +#define DMC_PARSER_SEC_CTRL (DMC_SEC_REG_BASE + (0x35 <<2)) + //bit 11:8. Pasrese write and read security contrl bits after EF triggered. + //bit 7:6. Parser EF trigger protection enable. + //bit 5. Parser EF trigger read source type. + //bit 4 Pasrer EF trigger read source enable. + //bit 3:2. Parser write security control bits. + //bit 1:0. Parser read security control bits. +#define DMC_DEV_SEC_READ_CTRL (DMC_SEC_REG_BASE + (0x36 <<2)) + //16 device subID read access security control bits. each subID 2 bits. +#define DMC_DEV_SEC_WRITE_CTRL (DMC_SEC_REG_BASE + (0x37 <<2)) + //16 device subID write access security control bits. each subID 2 bits. + + +//2 DES key one for secure region and one for non-secure region. +#define DMC_DES_KEY0_H (DMC_SEC_REG_BASE + (0x90 <<2)) +#define DMC_DES_KEY0_L (DMC_SEC_REG_BASE + (0x91 <<2)) + //64bits data descrable key for security level 0 ( DES key) + +#define DMC_DES_KEY1_H (DMC_SEC_REG_BASE + (0x92 <<2)) +#define DMC_DES_KEY1_L (DMC_SEC_REG_BASE + (0x93 <<2)) + //64bits data descrable key for security level 1( DES key) + +#define DMC_DES_PADDING (DMC_SEC_REG_BASE + (0x9a <<2)) + //32bits address padding used for DES data generation. + +#define DMC_CA_REMAP_L (DMC_SEC_REG_BASE + (0x9b <<2)) +#define DMC_CA_REMAP_H (DMC_SEC_REG_BASE + (0x9c <<2)) + //This is a 16x4 address remap look up table. + //the column address bit 7:4 would be the index input and be replace with the value stored in these register. + //{DMC_CA_REMAP_H, DMC_CA_REMAP_L} + //bit 63:60: new address for index 15 + //bit 59:56: new address for index 14 + //bit 55:52: new address for index 13 + //bit 51:48: new address for index 12 + //bit 47:44: new address for index 11 + //bit 43:40: new address for index 10 + //bit 39:36: new address for index 9 + //bit 35:32: new address for index 8 + //bit 31:28: new address for index 7 + //bit 27:24: new address for index 6 + //bit 23:20: new address for index 5 + //bit 19:16: new address for index 4 + //bit 15:12: new address for index 3 + //bit 11:8: new address for index 2 + //bit 7:4: new address for index 1 + //bit 3:0: new address for index 0 + + +// two range protection function. +#define DMC_PROT0_RANGE (DMC_SEC_REG_BASE + (0xa0 <<2)) + //protection 0 address range. the range define is 64Kbyte boundary. current address [31:16] >= start address && current address [31:16] <= end address. + //bit 31:16 : range end address. + //bit 15:0 : range start address +#define DMC_PROT0_CTRL (DMC_SEC_REG_BASE + (0xa1 <<2)) + //bit 19. protection 0 for write access enable bit. + //bit 18. protection 0 for read access enable bit. + //bit 17. protection 0 write access block function. if enabled, the access wouldn't write to the DDR SDRAM. if not enabled only generate a interrupt, but the access still wrote to DDR. + //bit 16. not used. + //bit 15:0 each bit to enable one of the 15 channel input for the protection function. + +#define DMC_PROT1_RANGE (DMC_SEC_REG_BASE + (0xa2 <<2)) + //protection 1 address range. the range define is 64Kbyte boundary. current address [31:16] >= start address && current address [31:16] <= end address. + //bit 31:16 : range end address. + //bit 15:0 : range start address +#define DMC_PROT1_CTRL (DMC_SEC_REG_BASE + (0xa3 <<2)) + //bit 19. protection 1 for write access enable bit. + //bit 18. protection 1 for read access enable bit. + //bit 17. protection 1 write access block function. if enabled, the access wouldn't write to the DDR SDRAM. if not enabled only generate a interrupt, but the access still wrote to DDR. +//two data point +#define DMC_WTCH0_D0 (DMC_SEC_REG_BASE + (0xa4 <<2)) + //WTCH0 will watch upto 128bits data access. +#define DMC_WTCH0_D1 (DMC_SEC_REG_BASE + (0xa5 <<2)) +#define DMC_WTCH0_D2 (DMC_SEC_REG_BASE + (0xa6 <<2)) +#define DMC_WTCH0_D3 (DMC_SEC_REG_BASE + (0xa7 <<2)) + // the watch point 0 data {d3, d2,d1,d0} +#define DMC_WTCH0_RANGE (DMC_SEC_REG_BASE + (0xa8 <<2)) + //address range. 64Kbyte boundary. + // 31:16 start address high 16. + // 15:0 start address high 16. +#define DMC_WTCH0_CTRL (DMC_SEC_REG_BASE + (0xa9 <<2)) + //bit 31:16. 16bits write data strb. + //bit 15:0. 16bits input channels select. +#define DMC_WTCH0_CTRL1 (DMC_SEC_REG_BASE + (0xaa <<2)) + //bit 2. watch point 0 enable. + //bit 1:0. watch point0 type. 2'b00 : double bytes. only watchpoint data 15:0 and data strb 1:0 is valid. 2'b01: 4 bytes. 2'b10: 8 bytes. 2'b11, all 16bytes. + +#define DMC_WTCH1_D0 (DMC_SEC_REG_BASE + (0xab <<2)) +#define DMC_WTCH1_D1 (DMC_SEC_REG_BASE + (0xac <<2)) +#define DMC_WTCH1_D2 (DMC_SEC_REG_BASE + (0xad <<2)) +#define DMC_WTCH1_D3 (DMC_SEC_REG_BASE + (0xae <<2)) + // the watch point 1 data {d3, d2,d1,d0} +#define DMC_WTCH1_RANGE (DMC_SEC_REG_BASE + (0xaf <<2)) + //address range. 64Kbyte boundary. + // 31:16 start address high 16. + // 15:0 start address high 16. +#define DMC_WTCH1_CTRL (DMC_SEC_REG_BASE + (0xb0 <<2)) + //bit 31:16. 16bits write data strb. + //bit 15:0. 16bits input channels select. +#define DMC_WTCH1_CTRL1 (DMC_SEC_REG_BASE + (0xb1 <<2)) + //bit 2. watch point 0 enable. + //bit 1:0. watch point0 type. 2'b00 : double bytes. only watchpoint data 15:0 and data strb 1:0 is valid. 2'b01: 4 bytes. 2'b10: 8 bytes. 2'b11, all 16bytes. + + +//trap function: all the enable the port ID read access or enable PORT ID and subID read access must be in the predefine range. otherwire the read access would be blocked. +// and an error will be generated. +#define DMC_TRAP0_RANGE (DMC_SEC_REG_BASE + (0xb2 <<2)) + // address trap0 range register. + //31:16. trap0 end address + //15:0 start0 address. +#define DMC_TRAP0_CTRL (DMC_SEC_REG_BASE + (0xb3 <<2)) + //bit 30 trap0 port ID 2 enable. + //bit 29 trap0 port ID 1 enable. + //bit 28 trap0 port ID 0 enable. + //bit 27 trap0 port ID 2 subid enable. + //bit 26 trap0 port ID 1 subid enable. + //bit 25 trap0 port ID 0 subid enable. + //bit 23:20. trap0 port port ID 2 channel ID number. + //bit 19:16. trap0 port port ID 2 subID ID number. + //bit 15:12. trap0 port ID 1 ID number. + //bit 11:8. trap0 port ID 1 subID ID number. + //bit 7:4. trap0 port ID 0 ID number. + //bit 3:0. trap0 port ID 0 subID ID number. + +#define DMC_TRAP1_RANGE (DMC_SEC_REG_BASE + (0xb4 <<2)) + //address trap range register. + //31:16. trap end address + //15:0 start address. +#define DMC_TRAP1_CTRL (DMC_SEC_REG_BASE + (0xb5 <<2)) + //bit 30 trap1 port ID 2 enable. + //bit 29 trap1 port ID 1 enable. + //bit 28 trap1 port ID 0 enable. + //bit 27 trap1 port ID 2 subid enable. + //bit 26 trap1 port ID 1 subid enable. + //bit 25 trap1 port ID 0 subid enable. + //bit 23:20. trap1 port port ID 2 channel ID number. + //bit 19:16. trap1 port port ID 2 subID ID number. + //bit 15:12. trap1 port ID 1 ID number. + //bit 11:8. trap1 port ID 1 subID ID number. + //bit 7:4. trap1 port ID 0 ID number. + //bit 3:0. trap1 port ID 0 subID ID number. + + + +//registers to check the security protection and watch point error information. +#define DMC_SEC_STATUS (DMC_SEC_REG_BASE + (0xb6 <<2)) + +#define DMC_VIO_ADDR0 (DMC_SEC_REG_BASE + (0xb7 <<2)) + //ddr0 write secure violation address. +#define DMC_VIO_ADDR1 (DMC_SEC_REG_BASE + (0xb8 <<2)) + //22 secure check violation. + //21 protection 1 vilation. + //20 protection 0 vilation. + //19:18. not use.d + //17 ddr0 write address overflow. write out of DDR size. + //16:14. ddr0 write violation AWPROT bits. + //13:0 ddr0_write violation ID. +#define DMC_VIO_ADDR2 (DMC_SEC_REG_BASE + (0xb9 <<2)) + //ddr1 write seure violation address +#define DMC_VIO_ADDR3 (DMC_SEC_REG_BASE + (0xba <<2)) + //22 ddr1 write secure check violation. + //21 ddr1 write protection 1 vilation. + //20 ddr1 write protection 0 vilation. + //19 ddr1 watch 1 catch + //18. ddr1 watch 0 catch. + //17 ddr1 write address overflow. write out of DDR size. + //16:14. ddr1 write violation AWPROT bits. + //13:0 ddr1_write violation ID. + +#define DMC_VIO_ADDR4 (DMC_SEC_REG_BASE + (0xbb <<2)) + //ddr0 read seure violation address +#define DMC_VIO_ADDR5 (DMC_SEC_REG_BASE + (0xbc <<2)) + //22 ddr0 read secure check violation. + //21 ddr0 read protection 1 violation. + //20 ddr0 read protection 0 violation. + //19 ddr0 read trap1 violation + //18 ddr0 read trap0 violation + //17 ddr 0 read address overflow. write out of DDR size. + //16:14. ddr 0 read violation ARPROT bits. + //13:0 ddr 0 read violation ID. + +#define DMC_VIO_ADDR6 (DMC_SEC_REG_BASE + (0xbd <<2)) + //ddr1 read seure violation address + +#define DMC_VIO_ADDR7 (DMC_SEC_REG_BASE + (0xbe <<2)) + //22 ddr1 read secure check violation. + //21 ddr1 read protection 1 violation. + //20 ddr1 read protection 0 violation. + //19 ddr1 read trap1 violation + //18 ddr1 read trap0 violation + //17 ddr 1 read address overflow. write out of DDR size. + //16:14. ddr 1 read violation ARPROT bits. + //13:0 ddr 1 read violation ID. + + +//each row bank and rank address can be selected from any address. +#define DDR0_ADDRMAP_4 (DMC_SEC_REG_BASE + (0xd4 <<2)) + //29:25 rank select. + //24:20 ba3 //for bank group or 16banks.. + //19:15 ba2. + //14:10 ba1. + //9:5 ba0. + //4:0 ra15. +#define DDR0_ADDRMAP_3 (DMC_SEC_REG_BASE + (0xd3 <<2)) + //29:25 ra14. + //24:20 ra13. + //19:15 ra12. + //14:10 ra11. + //9:5 ra10. + //4:0 ra9. +#define DDR0_ADDRMAP_2 (DMC_SEC_REG_BASE + (0xd2 <<2)) + //29:25 ra8. + //24:20 ra7. + //19:15 ra6. + //14:10 ra5. + //9:5 ra4. + //4:0 ra3. +#define DDR0_ADDRMAP_1 (DMC_SEC_REG_BASE + (0xd1 <<2)) + //29:25 ra2. + //24:20 ra1. + //19:15 ra0. + //14:10 ca11. + //9:5 ca10. + //4:0 ca9. + +#define DDR0_ADDRMAP_0 (DMC_SEC_REG_BASE + (0xd0 <<2)) + //29:25 ca8. + //24:20 ca7. + //19:15 ca6. + //14:10 ca5. + //9:5 ca4. + //4:0 ca3. + +#define DDR1_ADDRMAP_4 (DMC_SEC_REG_BASE + (0xd9 <<2)) + //29:25 rank select. + //24:20 ba3 //for bank group or 16banks.. + //19:15 ba2. + //14:10 ba1. + //9:5 ba0. + //4:0 ra15. +#define DDR1_ADDRMAP_3 (DMC_SEC_REG_BASE + (0xd8 <<2)) + //29:25 ra14. + //24:20 ra13. + //19:15 ra12. + //14:10 ra11. + //9:5 ra10. + //4:0 ra9. +#define DDR1_ADDRMAP_2 (DMC_SEC_REG_BASE + (0xd7 <<2)) + //29:25 ra8. + //24:20 ra7. + //19:15 ra6. + //14:10 ra5. + //9:5 ra4. + //4:0 ra3. +#define DDR1_ADDRMAP_1 (DMC_SEC_REG_BASE + (0xd6 <<2)) + //29:25 ra2. + //24:20 ra1. + //19:15 ra0. + //14:10 ca11. + //9:5 ca10. + //4:0 ca9. +#define DDR1_ADDRMAP_0 (DMC_SEC_REG_BASE + (0xd5 <<2)) + //29:25 ca8. + //24:20 ca7. + //19:15 ca6. + //14:10 ca5. + //9:5 ca4. + //4:0 ca3. + + +#define DMC_DDR_CTRL (DMC_SEC_REG_BASE + (0xda <<2)) + //bit 22. rank1 is same as rank0. only in not shared-AC mdoe. and chan0 second rank not selected. that's means still in rank0 32bits mode. + //bit 21. channel0 second rank selection enable. only in not shared-AC mode. + //bit 20. Shared AC mode. + //bit 19 :18 must be 0 always. becasue we'll use 32bits PHY data. + //bit 19: DDR channel 1 16bits data interface. 1 : 16bits data inteface. 0 : 32bits data interface + //bit 18: DDR channel 0 16bits data interface. 1 : 16bits data inteface. 0 : 32bits data interface + + //bit 17: for DDR channel 1. 1: only use 16bits data in a 32bits phy data interface. 0: normal 32bits data interface. + //bit 16. for DDR channel 0. 1: only use 16bits data in a 32bits phy data interface. 0: normal 32bits data interface. + //bit 10:8 channel bit selection in shared range. + //bit 7. DDR1_ONLY. 1: DDR channel 1 only. when both channel 0 and 1 in the design. 0 : normal. + //bit 6. DDR0_ONLY. 1: DDR channel 0 only. when both channel 0 and 1 in the design. 0 : normal. + //bit 5:3 : DDR channel 1 size. + //3'b000 : DDR channel 1 is 128MB. + //3'b001 : DDR channel 1 is 256MB. + //3'b010 : DDR channel 1 is 512MB. + //3'b011 : DDR channel 1 is 1GB. + //3'b100 : DDR channel 1 is 2GB. + //3'b101 : DDR channel 1 is 4GB. + //others : reserved. + //bit 2:0 : DDR channel 0 size. + //3'b000 : DDR channel 0 is 128MB. + //3'b001 : DDR channel 0 is 256MB. + //3'b010 : DDR channel 0 is 512MB. + //3'b011 : DDR channel 0 is 1GB. + //3'b100 : DDR channel 0 is 2GB. + //3'b101 : DDR channel 0 is 4GB. + //others : reserved.
\ No newline at end of file diff --git a/plat/gxb/efuse.c b/plat/gxb/efuse.c new file mode 100644 index 0000000..703c1d5 --- /dev/null +++ b/plat/gxb/efuse.c @@ -0,0 +1,48 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/efuse.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <io.h> +#include <asm/arch/cpu_config.h> +#include <stdio.h> +#include <string.h> +#include <efuse.h> + +#define EFUSE_READ_PRINT 0 + +void efuse_read(uint64_t offset, uint64_t length, const char * buffer){ + memcpy((void *)buffer, (void *)(P_SHARED_EFUSE_MIRROR+offset), length); +#if EFUSE_READ_PRINT + efuse_print(offset, length, buffer); +#endif +} + +void efuse_print(uint64_t offset, uint64_t length, const char * buffer){ + uint32_t loop = 0; + serial_puts("Efuse Read:"); + for (loop=0; loop<length; loop++) { + if (0 == (loop % 16)) + serial_puts("\n"); + serial_put_hex(buffer[loop], 8); + serial_puts(" "); + //printf("%2x ", buffer[loop]); + } + serial_puts("\n"); +}
\ No newline at end of file diff --git a/plat/gxb/include/arch.h b/plat/gxb/include/arch.h new file mode 100644 index 0000000..612ef63 --- /dev/null +++ b/plat/gxb/include/arch.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2015 Amlogic, Inc. All rights reserved. + * + * This source code is subject to the terms and conditions defined in the + * file 'LICENSE' which is part of this source code package. + * + * AArch64 specific register defines + */ +#ifndef __ARCH_H__ +#define __ARCH_H__ + +/* AArch64 SPSR */ +#define AARCH64_SPSR_EL1h 0x5 +#define AARCH64_SPSR_F (1 << 6) +#define AARCH64_SPSR_I (1 << 7) +#define AARCH64_SPSR_A (1 << 8) + +/* CPSR/SPSR definitions */ +#define DAIF_FIQ_BIT (1 << 0) +#define DAIF_IRQ_BIT (1 << 1) +#define DAIF_ABT_BIT (1 << 2) +#define DAIF_DBG_BIT (1 << 3) +#define SPSR_DAIF_SHIFT 6 +#define SPSR_DAIF_MASK 0xf + +#define SPSR_AIF_SHIFT 6 +#define SPSR_AIF_MASK 0x7 + +#define SPSR_E_SHIFT 9 +#define SPSR_E_MASK 0x1 +#define SPSR_E_LITTLE 0x0 +#define SPSR_E_BIG 0x1 + +#define SPSR_T_SHIFT 5 +#define SPSR_T_MASK 0x1 +#define SPSR_T_ARM 0x0 +#define SPSR_T_THUMB 0x1 + +#define DISABLE_ALL_EXCEPTIONS \ + (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT | DAIF_DBG_BIT) + + +#define MODE_EL_SHIFT 0x2 +#define MODE_EL_MASK 0x3 +#define MODE_EL3 0x3 +#define MODE_EL2 0x2 +#define MODE_EL1 0x1 +#define MODE_EL0 0x0 + +/* SCTLR definitions */ +#define SCTLR_EL2_RES1 ((1 << 29) | (1 << 28) | (1 << 23) | (1 << 22) | \ + (1 << 18) | (1 << 16) | (1 << 11) | (1 << 5) | \ + (1 << 4)) + +#define SCTLR_EL1_RES1 ((1 << 29) | (1 << 28) | (1 << 23) | (1 << 22) | \ + (1 << 11)) +#define SCTLR_AARCH32_EL1_RES1 \ + ((1 << 23) | (1 << 22) | (1 << 11) | (1 << 4) | \ + (1 << 3)) + +#define SCTLR_M_BIT (1 << 0) +#define SCTLR_A_BIT (1 << 1) +#define SCTLR_C_BIT (1 << 2) +#define SCTLR_SA_BIT (1 << 3) +#define SCTLR_I_BIT (1 << 12) +#define SCTLR_WXN_BIT (1 << 19) +#define SCTLR_EE_BIT (1 << 25) + + +/* Exception Syndrome register bits and bobs */ +#define ESR_EC_SHIFT 26 +#define ESR_EC_MASK 0x3f +#define ESR_EC_LENGTH 6 +#define EC_UNKNOWN 0x0 +#define EC_WFE_WFI 0x1 +#define EC_AARCH32_CP15_MRC_MCR 0x3 +#define EC_AARCH32_CP15_MRRC_MCRR 0x4 +#define EC_AARCH32_CP14_MRC_MCR 0x5 +#define EC_AARCH32_CP14_LDC_STC 0x6 +#define EC_FP_SIMD 0x7 +#define EC_AARCH32_CP10_MRC 0x8 +#define EC_AARCH32_CP14_MRRC_MCRR 0xc +#define EC_ILLEGAL 0xe +#define EC_AARCH32_SVC 0x11 +#define EC_AARCH32_HVC 0x12 +#define EC_AARCH32_SMC 0x13 +#define EC_AARCH64_SVC 0x15 +#define EC_AARCH64_HVC 0x16 +#define EC_AARCH64_SMC 0x17 +#define EC_AARCH64_SYS 0x18 +#define EC_IABORT_LOWER_EL 0x20 +#define EC_IABORT_CUR_EL 0x21 +#define EC_PC_ALIGN 0x22 +#define EC_DABORT_LOWER_EL 0x24 +#define EC_DABORT_CUR_EL 0x25 +#define EC_SP_ALIGN 0x26 +#define EC_AARCH32_FP 0x28 +#define EC_AARCH64_FP 0x2c +#define EC_SERROR 0x2f + +#define EC_BITS(x) ((x >> ESR_EC_SHIFT) & ESR_EC_MASK) + + +/****************************************************************************** + * Opcode passed in x0 to tell next EL that we want to run an image. + * Corresponds to the function ID of the only SMC that the BL1 exception + * handlers service. That's why the chosen value is the first function ID of + * the ARM SMC64 range. + *****************************************************************************/ +#define RUN_IMAGE 0xC0000000 + +/******************************************************************************* + * Constants that allow assembler code to access members of and the + * 'entry_point_info' structure at their correct offsets. + ******************************************************************************/ +#define ENTRY_POINT_INFO_PC_OFFSET 0x08 +#define ENTRY_POINT_INFO_ARGS_OFFSET 0x18 + +/* BL2 SMC parameter structre */ +#if 0 +/*************************************************************************** + * This structure provides version information and the size of the + * structure, attributes for the structure it represents + ***************************************************************************/ +/* typedef struct param_header { */ +/* uint8_t type; /* type of the structure */ */ +/* uint8_t version; /* version of this structure */ */ +/* uint16_t size; /* size of this structure in bytes */ */ +/* uint32_t attr; /* attributes: unused bits SBZ */ */ +/* } param_header_t; */ + +/***************************************************************************** + * This structure represents the superset of information needed while + * switching exception levels. The only two mechanisms to do so are + * ERET & SMC. Security state is indicated using bit zero of header + * attribute + * NOTE: BL1 expects entrypoint followed by spsr while processing + * SMC to jump to BL31 from the start of entry_point_info + *****************************************************************************/ +/* typedef struct entry_point_info { */ +/* param_header_t h; */ +/* uintptr_t pc; */ +/* uint32_t spsr; */ +/* aapcs64_params_t args; */ +/* } entry_point_info_t; */ + +/* BL2 SMC: MUST fill entry_point_info: +* pc, spsr(must be el3), arg0,..(BL2 pass to BL31 parameters) */ +#endif + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CPUECTLR_EL1 S3_1_C15_C2_1 /* Instruction def. */ +#define CPUECTLR_SMP_BIT (1 << 6) + +#endif diff --git a/plat/gxb/include/bignum.h b/plat/gxb/include/bignum.h new file mode 100644 index 0000000..0a84519 --- /dev/null +++ b/plat/gxb/include/bignum.h @@ -0,0 +1,640 @@ +/** + * \file bignum.h + * + * \brief Multi-precision integer library + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_BIGNUM_H +#define POLARSSL_BIGNUM_H + +#include "rsa_config.h" + +#ifdef _MSC_VER +#include <basetsd.h> +#if (_MSC_VER <= 1200) +typedef signed short int16_t; +typedef unsigned short uint16_t; +#else +typedef INT16 int16_t; +typedef UINT16 uint16_t; +#endif +typedef INT32 int32_t; +typedef INT64 int64_t; +typedef UINT32 uint32_t; +typedef UINT64 uint64_t; +#else +#ifdef CONFIG_EMU_BUILD +#include <inttypes.h> +#endif /* CONFIG_EMU_BUILD */ +#endif + +#define POLARSSL_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */ +#define POLARSSL_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */ +#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */ +#define POLARSSL_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */ +#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */ +#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */ +#define POLARSSL_ERR_MPI_MALLOC_FAILED -0x0010 /**< Memory allocation failed. */ + +#define MPI_CHK(f) if( ( ret = f ) != 0 ) goto cleanup + +/* + * Maximum size MPIs are allowed to grow to in number of limbs. + */ +#define POLARSSL_MPI_MAX_LIMBS 10000 + +/* + * Maximum window size used for modular exponentiation. Default: 6 + * Minimum value: 1. Maximum value: 6. + * + * Result is an array of ( 2 << POLARSSL_MPI_WINDOW_SIZE ) MPIs used + * for the sliding window calculation. (So 64 by default) + * + * Reduction in size, reduces speed. + */ +#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ + +/* + * Maximum size of MPIs allowed in bits and bytes for user-MPIs. + * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) + * + * Note: Calculations can results temporarily in larger MPIs. So the number + * of limbs required (POLARSSL_MPI_MAX_LIMBS) is higher. + */ +#define POLARSSL_MPI_MAX_SIZE 512 /**< Maximum number of bytes for usable MPIs. */ +#define POLARSSL_MPI_MAX_BITS ( 8 * POLARSSL_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ + +/* + * When reading from files with mpi_read_file() and writing to files with + * mpi_write_file() the buffer should have space + * for a (short) label, the MPI (in the provided radix), the newline + * characters and the '\0'. + * + * By default we assume at least a 10 char label, a minimum radix of 10 + * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). + * Autosized at compile time for at least a 10 char label, a minimum radix + * of 10 (decimal) for a number of POLARSSL_MPI_MAX_BITS size. + * + * This used to be statically sized to 1250 for a maximum of 4096 bit + * numbers (1234 decimal chars). + * + * Calculate using the formula: + * POLARSSL_MPI_RW_BUFFER_SIZE = ceil(POLARSSL_MPI_MAX_BITS / ln(10) * ln(2)) + + * LabelSize + 6 + */ +#define POLARSSL_MPI_MAX_BITS_SCALE100 ( 100 * POLARSSL_MPI_MAX_BITS ) +#define LN_2_DIV_LN_10_SCALE100 332 +#define POLARSSL_MPI_RW_BUFFER_SIZE ( ((POLARSSL_MPI_MAX_BITS_SCALE100 + LN_2_DIV_LN_10_SCALE100 - 1) / LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) + +/* + * Define the base integer type, architecture-wise + */ +typedef int64_t t_sint; +typedef uint64_t t_uint; + +/** + * \brief MPI structure + */ +typedef struct +{ + int s; /*!< integer sign */ + size_t n; /*!< total # of limbs */ + t_uint *p; /*!< pointer to limbs */ +} +mpi; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize one MPI + * + * \param X One MPI to initialize. + */ +void mpi_init( mpi *X ); + +/** + * \brief Unallocate one MPI + * + * \param X One MPI to unallocate. + */ +void mpi_free( mpi *X ); + +/** + * \brief Enlarge to the specified number of limbs + * + * \param X MPI to grow + * \param nblimbs The target number of limbs + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_grow( mpi *X, size_t nblimbs ); + +/** + * \brief Copy the contents of Y into X + * + * \param X Destination MPI + * \param Y Source MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_copy( mpi *X, const mpi *Y ); + +/** + * \brief Swap the contents of X and Y + * + * \param X First MPI value + * \param Y Second MPI value + */ +void mpi_swap( mpi *X, mpi *Y ); + +/** + * \brief Set value from integer + * + * \param X MPI to set + * \param z Value to use + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_lset( mpi *X, t_sint z ); + +/** + * \brief Get a specific bit from X + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * + * \return Either a 0 or a 1 + */ +int mpi_get_bit( const mpi *X, size_t pos ); + +/** + * \brief Set a bit of X to a specific value of 0 or 1 + * + * \note Will grow X if necessary to set a bit to 1 in a not yet + * existing limb. Will not grow if bit should be set to 0 + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * \param val The value to set the bit to (0 or 1) + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1 + */ +int mpi_set_bit( mpi *X, size_t pos, unsigned char val ); + +/** + * \brief Return the number of zero-bits before the least significant + * '1' bit + * + * Note: Thus also the zero-based index of the least significant '1' bit + * + * \param X MPI to use + */ +size_t mpi_lsb( const mpi *X ); + +/** + * \brief Return the number of bits up to and including the most + * significant '1' bit' + * + * Note: Thus also the one-based index of the most significant '1' bit + * + * \param X MPI to use + */ +size_t mpi_msb( const mpi *X ); + +/** + * \brief Return the total size in bytes + * + * \param X MPI to use + */ +size_t mpi_size( const mpi *X ); + +/** + * \brief Import from an ASCII string + * + * \param X Destination MPI + * \param radix Input numeric base + * \param s Null-terminated string buffer + * + * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code + */ +int mpi_read_string( mpi *X, int radix, const char *s ); + +/** + * \brief Export into an ASCII string + * + * \param X Source MPI + * \param radix Output numeric base + * \param s String buffer + * \param slen String buffer size + * + * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code. + * *slen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *slen = 0 to obtain the + * minimum required buffer size in *slen. + */ +int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen ); + +#if defined(POLARSSL_FS_IO) +/** + * \brief Read X from an opened file + * + * \param X Destination MPI + * \param radix Input numeric base + * \param fin Input file handle + * + * \return 0 if successful, POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if + * the file read buffer is too small or a + * POLARSSL_ERR_MPI_XXX error code + */ +int mpi_read_file( mpi *X, int radix, FILE *fin ); + +/** + * \brief Write X into an opened file, or stdout if fout is NULL + * + * \param p Prefix, can be NULL + * \param X Source MPI + * \param radix Output numeric base + * \param fout Output file handle (can be NULL) + * + * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code + * + * \note Set fout == NULL to print X on the console. + */ +int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout ); +#endif /* POLARSSL_FS_IO */ + +/** + * \brief Import X from unsigned binary data, big endian + * + * \param X Destination MPI + * \param buf Input buffer + * \param buflen Input buffer size + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen ); + +/** + * \brief Export X into unsigned binary data, big endian + * + * \param X Source MPI + * \param buf Output buffer + * \param buflen Output buffer size + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough + */ +int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen ); + +/** + * \brief Left-shift: X <<= count + * + * \param X MPI to shift + * \param count Amount to shift + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_shift_l( mpi *X, size_t count ); + +/** + * \brief Right-shift: X >>= count + * + * \param X MPI to shift + * \param count Amount to shift + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_shift_r( mpi *X, size_t count ); + +/** + * \brief Compare unsigned values + * + * \param X Left-hand MPI + * \param Y Right-hand MPI + * + * \return 1 if |X| is greater than |Y|, + * -1 if |X| is lesser than |Y| or + * 0 if |X| is equal to |Y| + */ +int mpi_cmp_abs( const mpi *X, const mpi *Y ); + +/** + * \brief Compare signed values + * + * \param X Left-hand MPI + * \param Y Right-hand MPI + * + * \return 1 if X is greater than Y, + * -1 if X is lesser than Y or + * 0 if X is equal to Y + */ +int mpi_cmp_mpi( const mpi *X, const mpi *Y ); + +/** + * \brief Compare signed values + * + * \param X Left-hand MPI + * \param z The integer value to compare to + * + * \return 1 if X is greater than z, + * -1 if X is lesser than z or + * 0 if X is equal to z + */ +int mpi_cmp_int( const mpi *X, t_sint z ); + +/** + * \brief Unsigned addition: X = |A| + |B| + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_add_abs( mpi *X, const mpi *A, const mpi *B ); + +/** + * \brief Unsigned substraction: X = |A| - |B| + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A + */ +int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B ); + +/** + * \brief Signed addition: X = A + B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B ); + +/** + * \brief Signed substraction: X = A - B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B ); + +/** + * \brief Signed addition: X = A + b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to add + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_add_int( mpi *X, const mpi *A, t_sint b ); + +/** + * \brief Signed substraction: X = A - b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to subtract + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_sub_int( mpi *X, const mpi *A, t_sint b ); + +/** + * \brief Baseline multiplication: X = A * B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B ); + +/** + * \brief Baseline multiplication: X = A * b + * Note: b is an unsigned integer type, thus + * Negative values of b are ignored. + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to multiply with + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_mul_int( mpi *X, const mpi *A, t_sint b ); + +/** + * \brief Division by mpi: A = Q * B + R + * + * \param Q Destination MPI for the quotient + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0 + * + * \note Either Q or R can be NULL. + */ +int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B ); + +/** + * \brief Division by int: A = Q * b + R + * + * \param Q Destination MPI for the quotient + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param b Integer to divide by + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0 + * + * \note Either Q or R can be NULL. + */ +int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b ); + +/** + * \brief Modulo: R = A mod B + * + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0, + * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B < 0 + */ +int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B ); + +/** + * \brief Modulo: r = A mod b + * + * \param r Destination t_uint + * \param A Left-hand MPI + * \param b Integer to divide by + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0, + * POLARSSL_ERR_MPI_NEGATIVE_VALUE if b < 0 + */ +int mpi_mod_int( t_uint *r, const mpi *A, t_sint b ); + +/** + * \brief Sliding-window exponentiation: X = A^E mod N + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param E Exponent MPI + * \param N Modular MPI + * \param _RR Speed-up MPI used for recalculations + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even or if + * E is negative + * + * \note _RR is used to avoid re-computing R*R mod N across + * multiple calls, which speeds up things a bit. It can + * be set to NULL if the extra performance is unneeded. + */ +int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR ); + +/** + * \brief Fill an MPI X with size bytes of random + * + * \param X Destination MPI + * \param size Size in bytes + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_fill_random( mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Greatest common divisor: G = gcd(A, B) + * + * \param G Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_gcd( mpi *G, const mpi *A, const mpi *B ); + +/** + * \brief Modular inverse: X = A^-1 mod N + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param N Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil + POLARSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N + */ +int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N ); + +/** + * \brief Miller-Rabin primality test + * + * \param X MPI to check + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime + */ +int mpi_is_prime( mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Prime number generation + * + * \param X Destination MPI + * \param nbits Required size of X in bits ( 3 <= nbits <= POLARSSL_MPI_MAX_BITS ) + * \param dh_flag If 1, then (X-1)/2 will be prime too + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 + */ +int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mpi_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* bignum.h */ diff --git a/plat/gxb/include/bn_mul.h b/plat/gxb/include/bn_mul.h new file mode 100644 index 0000000..400ca74 --- /dev/null +++ b/plat/gxb/include/bn_mul.h @@ -0,0 +1,865 @@ +/** + * \file bn_mul.h + * + * \brief Multi-precision integer library + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * Multiply source vector [s] with b, add result + * to destination vector [d] and set carry c. + * + * Currently supports: + * + * . IA-32 (386+) . AMD64 / EM64T + * . IA-32 (SSE2) . Motorola 68000 + * . PowerPC, 32-bit . MicroBlaze + * . PowerPC, 64-bit . TriCore + * . SPARC v8 . ARM v3+ + * . Alpha . MIPS32 + * . C, longlong . C, generic + */ +#ifndef POLARSSL_BN_MUL_H +#define POLARSSL_BN_MUL_H + +#include "bignum.h" + +#if defined(POLARSSL_HAVE_ASM) + +#if defined(__GNUC__) +#if defined(__i386__) + +#define MULADDC_INIT \ + asm( " \ + movl %%ebx, %0; \ + movl %5, %%esi; \ + movl %6, %%edi; \ + movl %7, %%ecx; \ + movl %8, %%ebx; \ + " + +#define MULADDC_CORE \ + " \ + lodsl; \ + mull %%ebx; \ + addl %%ecx, %%eax; \ + adcl $0, %%edx; \ + addl (%%edi), %%eax; \ + adcl $0, %%edx; \ + movl %%edx, %%ecx; \ + stosl; \ + " + +#if defined(POLARSSL_HAVE_SSE2) + +#define MULADDC_HUIT \ + " \ + movd %%ecx, %%mm1; \ + movd %%ebx, %%mm0; \ + movd (%%edi), %%mm3; \ + paddq %%mm3, %%mm1; \ + movd (%%esi), %%mm2; \ + pmuludq %%mm0, %%mm2; \ + movd 4(%%esi), %%mm4; \ + pmuludq %%mm0, %%mm4; \ + movd 8(%%esi), %%mm6; \ + pmuludq %%mm0, %%mm6; \ + movd 12(%%esi), %%mm7; \ + pmuludq %%mm0, %%mm7; \ + paddq %%mm2, %%mm1; \ + movd 4(%%edi), %%mm3; \ + paddq %%mm4, %%mm3; \ + movd 8(%%edi), %%mm5; \ + paddq %%mm6, %%mm5; \ + movd 12(%%edi), %%mm4; \ + paddq %%mm4, %%mm7; \ + movd %%mm1, (%%edi); \ + movd 16(%%esi), %%mm2; \ + pmuludq %%mm0, %%mm2; \ + psrlq $32, %%mm1; \ + movd 20(%%esi), %%mm4; \ + pmuludq %%mm0, %%mm4; \ + paddq %%mm3, %%mm1; \ + movd 24(%%esi), %%mm6; \ + pmuludq %%mm0, %%mm6; \ + movd %%mm1, 4(%%edi); \ + psrlq $32, %%mm1; \ + movd 28(%%esi), %%mm3; \ + pmuludq %%mm0, %%mm3; \ + paddq %%mm5, %%mm1; \ + movd 16(%%edi), %%mm5; \ + paddq %%mm5, %%mm2; \ + movd %%mm1, 8(%%edi); \ + psrlq $32, %%mm1; \ + paddq %%mm7, %%mm1; \ + movd 20(%%edi), %%mm5; \ + paddq %%mm5, %%mm4; \ + movd %%mm1, 12(%%edi); \ + psrlq $32, %%mm1; \ + paddq %%mm2, %%mm1; \ + movd 24(%%edi), %%mm5; \ + paddq %%mm5, %%mm6; \ + movd %%mm1, 16(%%edi); \ + psrlq $32, %%mm1; \ + paddq %%mm4, %%mm1; \ + movd 28(%%edi), %%mm5; \ + paddq %%mm5, %%mm3; \ + movd %%mm1, 20(%%edi); \ + psrlq $32, %%mm1; \ + paddq %%mm6, %%mm1; \ + movd %%mm1, 24(%%edi); \ + psrlq $32, %%mm1; \ + paddq %%mm3, %%mm1; \ + movd %%mm1, 28(%%edi); \ + addl $32, %%edi; \ + addl $32, %%esi; \ + psrlq $32, %%mm1; \ + movd %%mm1, %%ecx; \ + " + +#define MULADDC_STOP \ + " \ + emms; \ + movl %4, %%ebx; \ + movl %%ecx, %1; \ + movl %%edi, %2; \ + movl %%esi, %3; \ + " \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ecx", "edx", "esi", "edi" \ + ); + +#else + +#define MULADDC_STOP \ + " \ + movl %4, %%ebx; \ + movl %%ecx, %1; \ + movl %%edi, %2; \ + movl %%esi, %3; \ + " \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ecx", "edx", "esi", "edi" \ + ); +#endif /* SSE2 */ +#endif /* i386 */ + +#if defined(__amd64__) || defined (__x86_64__) + +#define MULADDC_INIT \ + asm( "movq %0, %%rsi " :: "m" (s)); \ + asm( "movq %0, %%rdi " :: "m" (d)); \ + asm( "movq %0, %%rcx " :: "m" (c)); \ + asm( "movq %0, %%rbx " :: "m" (b)); \ + asm( "xorq %r8, %r8 " ); + +#define MULADDC_CORE \ + asm( "movq (%rsi),%rax " ); \ + asm( "mulq %rbx " ); \ + asm( "addq $8, %rsi " ); \ + asm( "addq %rcx, %rax " ); \ + asm( "movq %r8, %rcx " ); \ + asm( "adcq $0, %rdx " ); \ + asm( "nop " ); \ + asm( "addq %rax, (%rdi) " ); \ + asm( "adcq %rdx, %rcx " ); \ + asm( "addq $8, %rdi " ); + +#define MULADDC_STOP \ + asm( "movq %%rcx, %0 " : "=m" (c)); \ + asm( "movq %%rdi, %0 " : "=m" (d)); \ + asm( "movq %%rsi, %0 " : "=m" (s) :: \ + "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" ); + +#endif /* AMD64 */ + +#if defined(__mc68020__) || defined(__mcpu32__) + +#define MULADDC_INIT \ + asm( "movl %0, %%a2 " :: "m" (s)); \ + asm( "movl %0, %%a3 " :: "m" (d)); \ + asm( "movl %0, %%d3 " :: "m" (c)); \ + asm( "movl %0, %%d2 " :: "m" (b)); \ + asm( "moveq #0, %d0 " ); + +#define MULADDC_CORE \ + asm( "movel %a2@+, %d1 " ); \ + asm( "mulul %d2, %d4:%d1 " ); \ + asm( "addl %d3, %d1 " ); \ + asm( "addxl %d0, %d4 " ); \ + asm( "moveq #0, %d3 " ); \ + asm( "addl %d1, %a3@+ " ); \ + asm( "addxl %d4, %d3 " ); + +#define MULADDC_STOP \ + asm( "movl %%d3, %0 " : "=m" (c)); \ + asm( "movl %%a3, %0 " : "=m" (d)); \ + asm( "movl %%a2, %0 " : "=m" (s) :: \ + "d0", "d1", "d2", "d3", "d4", "a2", "a3" ); + +#define MULADDC_HUIT \ + asm( "movel %a2@+, %d1 " ); \ + asm( "mulul %d2, %d4:%d1 " ); \ + asm( "addxl %d3, %d1 " ); \ + asm( "addxl %d0, %d4 " ); \ + asm( "addl %d1, %a3@+ " ); \ + asm( "movel %a2@+, %d1 " ); \ + asm( "mulul %d2, %d3:%d1 " ); \ + asm( "addxl %d4, %d1 " ); \ + asm( "addxl %d0, %d3 " ); \ + asm( "addl %d1, %a3@+ " ); \ + asm( "movel %a2@+, %d1 " ); \ + asm( "mulul %d2, %d4:%d1 " ); \ + asm( "addxl %d3, %d1 " ); \ + asm( "addxl %d0, %d4 " ); \ + asm( "addl %d1, %a3@+ " ); \ + asm( "movel %a2@+, %d1 " ); \ + asm( "mulul %d2, %d3:%d1 " ); \ + asm( "addxl %d4, %d1 " ); \ + asm( "addxl %d0, %d3 " ); \ + asm( "addl %d1, %a3@+ " ); \ + asm( "movel %a2@+, %d1 " ); \ + asm( "mulul %d2, %d4:%d1 " ); \ + asm( "addxl %d3, %d1 " ); \ + asm( "addxl %d0, %d4 " ); \ + asm( "addl %d1, %a3@+ " ); \ + asm( "movel %a2@+, %d1 " ); \ + asm( "mulul %d2, %d3:%d1 " ); \ + asm( "addxl %d4, %d1 " ); \ + asm( "addxl %d0, %d3 " ); \ + asm( "addl %d1, %a3@+ " ); \ + asm( "movel %a2@+, %d1 " ); \ + asm( "mulul %d2, %d4:%d1 " ); \ + asm( "addxl %d3, %d1 " ); \ + asm( "addxl %d0, %d4 " ); \ + asm( "addl %d1, %a3@+ " ); \ + asm( "movel %a2@+, %d1 " ); \ + asm( "mulul %d2, %d3:%d1 " ); \ + asm( "addxl %d4, %d1 " ); \ + asm( "addxl %d0, %d3 " ); \ + asm( "addl %d1, %a3@+ " ); \ + asm( "addxl %d0, %d3 " ); + +#endif /* MC68000 */ + +#if defined(__powerpc__) || defined(__ppc__) +#if defined(__powerpc64__) || defined(__ppc64__) + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( "ld r3, %0 " :: "m" (s)); \ + asm( "ld r4, %0 " :: "m" (d)); \ + asm( "ld r5, %0 " :: "m" (c)); \ + asm( "ld r6, %0 " :: "m" (b)); \ + asm( "addi r3, r3, -8 " ); \ + asm( "addi r4, r4, -8 " ); \ + asm( "addic r5, r5, 0 " ); + +#define MULADDC_CORE \ + asm( "ldu r7, 8(r3) " ); \ + asm( "mulld r8, r7, r6 " ); \ + asm( "mulhdu r9, r7, r6 " ); \ + asm( "adde r8, r8, r5 " ); \ + asm( "ld r7, 8(r4) " ); \ + asm( "addze r5, r9 " ); \ + asm( "addc r8, r8, r7 " ); \ + asm( "stdu r8, 8(r4) " ); + +#define MULADDC_STOP \ + asm( "addze r5, r5 " ); \ + asm( "addi r4, r4, 8 " ); \ + asm( "addi r3, r3, 8 " ); \ + asm( "std r5, %0 " : "=m" (c)); \ + asm( "std r4, %0 " : "=m" (d)); \ + asm( "std r3, %0 " : "=m" (s) :: \ + "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); + +#else + +#define MULADDC_INIT \ + asm( "ld %%r3, %0 " :: "m" (s)); \ + asm( "ld %%r4, %0 " :: "m" (d)); \ + asm( "ld %%r5, %0 " :: "m" (c)); \ + asm( "ld %%r6, %0 " :: "m" (b)); \ + asm( "addi %r3, %r3, -8 " ); \ + asm( "addi %r4, %r4, -8 " ); \ + asm( "addic %r5, %r5, 0 " ); + +#define MULADDC_CORE \ + asm( "ldu %r7, 8(%r3) " ); \ + asm( "mulld %r8, %r7, %r6 " ); \ + asm( "mulhdu %r9, %r7, %r6 " ); \ + asm( "adde %r8, %r8, %r5 " ); \ + asm( "ld %r7, 8(%r4) " ); \ + asm( "addze %r5, %r9 " ); \ + asm( "addc %r8, %r8, %r7 " ); \ + asm( "stdu %r8, 8(%r4) " ); + +#define MULADDC_STOP \ + asm( "addze %r5, %r5 " ); \ + asm( "addi %r4, %r4, 8 " ); \ + asm( "addi %r3, %r3, 8 " ); \ + asm( "std %%r5, %0 " : "=m" (c)); \ + asm( "std %%r4, %0 " : "=m" (d)); \ + asm( "std %%r3, %0 " : "=m" (s) :: \ + "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); + +#endif + +#else /* PPC32 */ + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( "lwz r3, %0 " :: "m" (s)); \ + asm( "lwz r4, %0 " :: "m" (d)); \ + asm( "lwz r5, %0 " :: "m" (c)); \ + asm( "lwz r6, %0 " :: "m" (b)); \ + asm( "addi r3, r3, -4 " ); \ + asm( "addi r4, r4, -4 " ); \ + asm( "addic r5, r5, 0 " ); + +#define MULADDC_CORE \ + asm( "lwzu r7, 4(r3) " ); \ + asm( "mullw r8, r7, r6 " ); \ + asm( "mulhwu r9, r7, r6 " ); \ + asm( "adde r8, r8, r5 " ); \ + asm( "lwz r7, 4(r4) " ); \ + asm( "addze r5, r9 " ); \ + asm( "addc r8, r8, r7 " ); \ + asm( "stwu r8, 4(r4) " ); + +#define MULADDC_STOP \ + asm( "addze r5, r5 " ); \ + asm( "addi r4, r4, 4 " ); \ + asm( "addi r3, r3, 4 " ); \ + asm( "stw r5, %0 " : "=m" (c)); \ + asm( "stw r4, %0 " : "=m" (d)); \ + asm( "stw r3, %0 " : "=m" (s) :: \ + "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); + +#else + +#define MULADDC_INIT \ + asm( "lwz %%r3, %0 " :: "m" (s)); \ + asm( "lwz %%r4, %0 " :: "m" (d)); \ + asm( "lwz %%r5, %0 " :: "m" (c)); \ + asm( "lwz %%r6, %0 " :: "m" (b)); \ + asm( "addi %r3, %r3, -4 " ); \ + asm( "addi %r4, %r4, -4 " ); \ + asm( "addic %r5, %r5, 0 " ); + +#define MULADDC_CORE \ + asm( "lwzu %r7, 4(%r3) " ); \ + asm( "mullw %r8, %r7, %r6 " ); \ + asm( "mulhwu %r9, %r7, %r6 " ); \ + asm( "adde %r8, %r8, %r5 " ); \ + asm( "lwz %r7, 4(%r4) " ); \ + asm( "addze %r5, %r9 " ); \ + asm( "addc %r8, %r8, %r7 " ); \ + asm( "stwu %r8, 4(%r4) " ); + +#define MULADDC_STOP \ + asm( "addze %r5, %r5 " ); \ + asm( "addi %r4, %r4, 4 " ); \ + asm( "addi %r3, %r3, 4 " ); \ + asm( "stw %%r5, %0 " : "=m" (c)); \ + asm( "stw %%r4, %0 " : "=m" (d)); \ + asm( "stw %%r3, %0 " : "=m" (s) :: \ + "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); + +#endif + +#endif /* PPC32 */ +#endif /* PPC64 */ + +#if defined(__sparc__) && defined(__sparc64__) + +#define MULADDC_INIT \ + asm( \ + " \ + ldx %3, %%o0; \ + ldx %4, %%o1; \ + ld %5, %%o2; \ + ld %6, %%o3; \ + " + +#define MULADDC_CORE \ + " \ + ld [%%o0], %%o4; \ + inc 4, %%o0; \ + ld [%%o1], %%o5; \ + umul %%o3, %%o4, %%o4; \ + addcc %%o4, %%o2, %%o4; \ + rd %%y, %%g1; \ + addx %%g1, 0, %%g1; \ + addcc %%o4, %%o5, %%o4; \ + st %%o4, [%%o1]; \ + addx %%g1, 0, %%o2; \ + inc 4, %%o1; \ + " + +#define MULADDC_STOP \ + " \ + st %%o2, %0; \ + stx %%o1, %1; \ + stx %%o0, %2; \ + " \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); +#endif /* SPARCv9 */ + +#if defined(__sparc__) && !defined(__sparc64__) + +#define MULADDC_INIT \ + asm( \ + " \ + ld %3, %%o0; \ + ld %4, %%o1; \ + ld %5, %%o2; \ + ld %6, %%o3; \ + " + +#define MULADDC_CORE \ + " \ + ld [%%o0], %%o4; \ + inc 4, %%o0; \ + ld [%%o1], %%o5; \ + umul %%o3, %%o4, %%o4; \ + addcc %%o4, %%o2, %%o4; \ + rd %%y, %%g1; \ + addx %%g1, 0, %%g1; \ + addcc %%o4, %%o5, %%o4; \ + st %%o4, [%%o1]; \ + addx %%g1, 0, %%o2; \ + inc 4, %%o1; \ + " + +#define MULADDC_STOP \ + " \ + st %%o2, %0; \ + st %%o1, %1; \ + st %%o0, %2; \ + " \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#endif /* SPARCv8 */ + +#if defined(__microblaze__) || defined(microblaze) + +#define MULADDC_INIT \ + asm( "lwi r3, %0 " :: "m" (s)); \ + asm( "lwi r4, %0 " :: "m" (d)); \ + asm( "lwi r5, %0 " :: "m" (c)); \ + asm( "lwi r6, %0 " :: "m" (b)); \ + asm( "andi r7, r6, 0xffff" ); \ + asm( "bsrli r6, r6, 16 " ); + +#define MULADDC_CORE \ + asm( "lhui r8, r3, 0 " ); \ + asm( "addi r3, r3, 2 " ); \ + asm( "lhui r9, r3, 0 " ); \ + asm( "addi r3, r3, 2 " ); \ + asm( "mul r10, r9, r6 " ); \ + asm( "mul r11, r8, r7 " ); \ + asm( "mul r12, r9, r7 " ); \ + asm( "mul r13, r8, r6 " ); \ + asm( "bsrli r8, r10, 16 " ); \ + asm( "bsrli r9, r11, 16 " ); \ + asm( "add r13, r13, r8 " ); \ + asm( "add r13, r13, r9 " ); \ + asm( "bslli r10, r10, 16 " ); \ + asm( "bslli r11, r11, 16 " ); \ + asm( "add r12, r12, r10 " ); \ + asm( "addc r13, r13, r0 " ); \ + asm( "add r12, r12, r11 " ); \ + asm( "addc r13, r13, r0 " ); \ + asm( "lwi r10, r4, 0 " ); \ + asm( "add r12, r12, r10 " ); \ + asm( "addc r13, r13, r0 " ); \ + asm( "add r12, r12, r5 " ); \ + asm( "addc r5, r13, r0 " ); \ + asm( "swi r12, r4, 0 " ); \ + asm( "addi r4, r4, 4 " ); + +#define MULADDC_STOP \ + asm( "swi r5, %0 " : "=m" (c)); \ + asm( "swi r4, %0 " : "=m" (d)); \ + asm( "swi r3, %0 " : "=m" (s) :: \ + "r3", "r4" , "r5" , "r6" , "r7" , "r8" , \ + "r9", "r10", "r11", "r12", "r13" ); + +#endif /* MicroBlaze */ + +#if defined(__tricore__) + +#define MULADDC_INIT \ + asm( "ld.a %%a2, %0 " :: "m" (s)); \ + asm( "ld.a %%a3, %0 " :: "m" (d)); \ + asm( "ld.w %%d4, %0 " :: "m" (c)); \ + asm( "ld.w %%d1, %0 " :: "m" (b)); \ + asm( "xor %d5, %d5 " ); + +#define MULADDC_CORE \ + asm( "ld.w %d0, [%a2+] " ); \ + asm( "madd.u %e2, %e4, %d0, %d1 " ); \ + asm( "ld.w %d0, [%a3] " ); \ + asm( "addx %d2, %d2, %d0 " ); \ + asm( "addc %d3, %d3, 0 " ); \ + asm( "mov %d4, %d3 " ); \ + asm( "st.w [%a3+], %d2 " ); + +#define MULADDC_STOP \ + asm( "st.w %0, %%d4 " : "=m" (c)); \ + asm( "st.a %0, %%a3 " : "=m" (d)); \ + asm( "st.a %0, %%a2 " : "=m" (s) :: \ + "d0", "d1", "e2", "d4", "a2", "a3" ); + +#endif /* TriCore */ + +#if defined(__arm__) + +#if defined(__thumb__) + +#define MULADDC_INIT \ + asm( \ + " \ + ldr r0, %3; \ + ldr r1, %4; \ + ldr r2, %5; \ + ldr r3, %6; \ + lsr r7, r3, #16; \ + mov r9, r7; \ + lsl r7, r3, #16; \ + lsr r7, r7, #16; \ + mov r8, r7; \ + " + +#define MULADDC_CORE \ + " \ + ldmia r0!, {r6}; \ + lsr r7, r6, #16; \ + lsl r6, r6, #16; \ + lsr r6, r6, #16; \ + mov r4, r8; \ + mul r4, r6; \ + mov r3, r9; \ + mul r6, r3; \ + mov r5, r9; \ + mul r5, r7; \ + mov r3, r8; \ + mul r7, r3; \ + lsr r3, r6, #16; \ + add r5, r5, r3; \ + lsr r3, r7, #16; \ + add r5, r5, r3; \ + add r4, r4, r2; \ + mov r2, #0; \ + adc r5, r2; \ + lsl r3, r6, #16; \ + add r4, r4, r3; \ + adc r5, r2; \ + lsl r3, r7, #16; \ + add r4, r4, r3; \ + adc r5, r2; \ + ldr r3, [r1]; \ + add r4, r4, r3; \ + adc r2, r5; \ + stmia r1!, {r4}; \ + " + +#define MULADDC_STOP \ + " \ + str r2, %0; \ + str r1, %1; \ + str r0, %2; \ + " \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "r8", "r9" \ + ); + +#else + +#define MULADDC_INIT \ + asm( \ + " \ + ldr r0, %3; \ + ldr r1, %4; \ + ldr r2, %5; \ + ldr r3, %6; \ + " + +#define MULADDC_CORE \ + " \ + ldr r4, [r0], #4; \ + mov r5, #0; \ + ldr r6, [r1]; \ + umlal r2, r5, r3, r4; \ + adds r7, r6, r2; \ + adc r2, r5, #0; \ + str r7, [r1], #4; \ + " + +#define MULADDC_STOP \ + " \ + str r2, %0; \ + str r1, %1; \ + str r0, %2; \ + " \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7" \ + ); + +#endif /* Thumb */ + +#endif /* ARMv3 */ + +#if defined(__alpha__) + +#define MULADDC_INIT \ + asm( "ldq $1, %0 " :: "m" (s)); \ + asm( "ldq $2, %0 " :: "m" (d)); \ + asm( "ldq $3, %0 " :: "m" (c)); \ + asm( "ldq $4, %0 " :: "m" (b)); + +#define MULADDC_CORE \ + asm( "ldq $6, 0($1) " ); \ + asm( "addq $1, 8, $1 " ); \ + asm( "mulq $6, $4, $7 " ); \ + asm( "umulh $6, $4, $6 " ); \ + asm( "addq $7, $3, $7 " ); \ + asm( "cmpult $7, $3, $3 " ); \ + asm( "ldq $5, 0($2) " ); \ + asm( "addq $7, $5, $7 " ); \ + asm( "cmpult $7, $5, $5 " ); \ + asm( "stq $7, 0($2) " ); \ + asm( "addq $2, 8, $2 " ); \ + asm( "addq $6, $3, $3 " ); \ + asm( "addq $5, $3, $3 " ); + +#define MULADDC_STOP \ + asm( "stq $3, %0 " : "=m" (c)); \ + asm( "stq $2, %0 " : "=m" (d)); \ + asm( "stq $1, %0 " : "=m" (s) :: \ + "$1", "$2", "$3", "$4", "$5", "$6", "$7" ); + +#endif /* Alpha */ + +#if defined(__mips__) + +#define MULADDC_INIT \ + asm( "lw $10, %0 " :: "m" (s)); \ + asm( "lw $11, %0 " :: "m" (d)); \ + asm( "lw $12, %0 " :: "m" (c)); \ + asm( "lw $13, %0 " :: "m" (b)); + +#define MULADDC_CORE \ + asm( "lw $14, 0($10) " ); \ + asm( "multu $13, $14 " ); \ + asm( "addi $10, $10, 4 " ); \ + asm( "mflo $14 " ); \ + asm( "mfhi $9 " ); \ + asm( "addu $14, $12, $14 " ); \ + asm( "lw $15, 0($11) " ); \ + asm( "sltu $12, $14, $12 " ); \ + asm( "addu $15, $14, $15 " ); \ + asm( "sltu $14, $15, $14 " ); \ + asm( "addu $12, $12, $9 " ); \ + asm( "sw $15, 0($11) " ); \ + asm( "addu $12, $12, $14 " ); \ + asm( "addi $11, $11, 4 " ); + +#define MULADDC_STOP \ + asm( "sw $12, %0 " : "=m" (c)); \ + asm( "sw $11, %0 " : "=m" (d)); \ + asm( "sw $10, %0 " : "=m" (s) :: \ + "$9", "$10", "$11", "$12", "$13", "$14", "$15" ); + +#endif /* MIPS */ +#endif /* GNUC */ + +#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + +#define MULADDC_INIT \ + __asm mov esi, s \ + __asm mov edi, d \ + __asm mov ecx, c \ + __asm mov ebx, b + +#define MULADDC_CORE \ + __asm lodsd \ + __asm mul ebx \ + __asm add eax, ecx \ + __asm adc edx, 0 \ + __asm add eax, [edi] \ + __asm adc edx, 0 \ + __asm mov ecx, edx \ + __asm stosd + +#if defined(POLARSSL_HAVE_SSE2) + +#define EMIT __asm _emit + +#define MULADDC_HUIT \ + EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ + EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ + EMIT 0x0F EMIT 0x6E EMIT 0x1F \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x16 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ + EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ + EMIT 0x0F EMIT 0x7E EMIT 0x0F \ + EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ + EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ + EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x7E EMIT 0xC9 + +#define MULADDC_STOP \ + EMIT 0x0F EMIT 0x77 \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#else + +#define MULADDC_STOP \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#endif /* SSE2 */ +#endif /* MSVC */ + +#endif /* POLARSSL_HAVE_ASM */ + +#if !defined(MULADDC_CORE) +#if defined(POLARSSL_HAVE_UDBL) + +#define MULADDC_INIT \ +{ \ + t_udbl r; \ + t_uint r0, r1; + +#define MULADDC_CORE \ + r = *(s++) * (t_udbl) b; \ + r0 = r; \ + r1 = r >> biL; \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#else + +#define MULADDC_INIT \ +{ \ + t_uint s0, s1, b0, b1; \ + t_uint r0, r1, rx, ry; \ + b0 = ( b << biH ) >> biH; \ + b1 = ( b >> biH ); + +#define MULADDC_CORE \ + s0 = ( *s << biH ) >> biH; \ + s1 = ( *s >> biH ); s++; \ + rx = s0 * b1; r0 = s0 * b0; \ + ry = s1 * b0; r1 = s1 * b1; \ + r1 += ( rx >> biH ); \ + r1 += ( ry >> biH ); \ + rx <<= biH; ry <<= biH; \ + r0 += rx; r1 += (r0 < rx); \ + r0 += ry; r1 += (r0 < ry); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#endif /* C (generic) */ +#endif /* C (longlong) */ + +#endif /* bn_mul.h */ diff --git a/plat/gxb/include/cache.h b/plat/gxb/include/cache.h new file mode 100644 index 0000000..9f186f5 --- /dev/null +++ b/plat/gxb/include/cache.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015 Amlogic, Inc. All rights reserved. + * + * This source code is subject to the terms and conditions defined in the + * file 'LICENSE' which is part of this source code package. + * + */ + +#ifndef __BL2_CACHE_H_ +#define __BL2_CACHE_H_ + +void disable_mmu_el1(void); /*disable mmu dcache*/ +void disable_mmu_icache_el1(void); /*disable mmu dcache icache*/ + +#endif /*__BL2_CACHE_H_*/
\ No newline at end of file diff --git a/plat/gxb/include/common.h b/plat/gxb/include/common.h new file mode 100644 index 0000000..68874ff --- /dev/null +++ b/plat/gxb/include/common.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015 Amlogic, Inc. All rights reserved. + * + * This source code is subject to the terms and conditions defined in the + * file 'LICENSE' which is part of this source code package. + * + * Common defines + */ + +#ifndef _BOOT_ROM_COMMON_H +#define _BOOT_ROM_COMMON_H + +#include <stdint.h> +#include <stddef.h> +#include "rsa_config.h" + +#ifdef CONFIG_EMU_BUILD +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#endif /* CONFIG_EMU_BUILD */ + +#define setbits_le32(reg, val) (*((volatile uint32_t *)((uintptr_t)(reg)))) |= (val) +#define clrbits_le32(reg, val) (*((volatile uint32_t *)((uintptr_t)(reg)))) &= (~(val)) +#define writel32(val, reg) (*((volatile uint32_t *)((uintptr_t)(reg)))) = (val) +#define readl32(reg) (*((volatile uint32_t *)((uintptr_t)(reg)))) + +#if 0 +static inline void writel32(uint32_t value, uintptr_t addr) +{ + *(volatile uint32_t*)addr = value; +} + +static inline uint32_t readl32(uintptr_t addr) +{ + return *(volatile uint32_t*)addr; +} +#endif + +#define writel writel32 +#define readl readl32 + +void print_str(const char *str); +void print_u32(unsigned int data); + +#undef DEBUG +#ifdef DEBUG +#define print_error print_str +#define print_out print_str +#define print_info print_str +#define print_dbg print_str +#define print_dbg_u32 print_u32 +#else +#define dummy_print(a) do{} while(0); +#define print_error print_str +#define print_out print_str +#define print_info(a) dummy_print(a) +#define print_dbg(a) dummy_print(a) +#define print_dbg_u32(a) dummy_print(a) +#endif + +#ifdef CONFIG_EMU_BUILD +#define ss_printf printf +#else +#define ss_printf(...) +#endif /* CONFIG_EMU_BUILD */ + +#endif /* _BOOT_ROM_COMMON_H */ diff --git a/plat/gxb/include/efuse.h b/plat/gxb/include/efuse.h new file mode 100644 index 0000000..bb32c23 --- /dev/null +++ b/plat/gxb/include/efuse.h @@ -0,0 +1,30 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/include/efuse.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __BL2_EFUSE_H__ +#define __BL2_EFUSE_H__ + +#include <stdint.h> + +void efuse_read(uint64_t offset, uint64_t length, const char * buffer); +void efuse_print(uint64_t offset, uint64_t length, const char * buffer); + +#endif /* __BL2_EFUSE_H__ */ diff --git a/plat/gxb/include/mailbox.h b/plat/gxb/include/mailbox.h new file mode 100644 index 0000000..7422e87 --- /dev/null +++ b/plat/gxb/include/mailbox.h @@ -0,0 +1,40 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/include/mailbox.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __BL2_MAILBOX_H_ +#define __BL2_MAILBOX_H_ + +#define MB_SRAM_BASE 0xd9013800 + +#define CMD_SHA 0xc0de0001 +#define CMD_OP_SHA 0xc0de0002 +#define CMD_DATA_LEN 0xc0dec0d0 +#define CMD_DATA 0xc0dec0de +#define CMD_END 0xe00de00d + +void *memcpy_t(void *dest, const void *src, size_t len); +void mb_send_data(uint32_t val, uint32_t port); +uint32_t mb_read_data(uint32_t port); +void mb_clear_data(uint32_t val, uint32_t port); +void send_bl30x(uint32_t addr, uint32_t size, const uint8_t * sha2, + uint32_t sha2_length, const char * name); + +#endif /*__BL2_MAILBOX_H_*/
\ No newline at end of file diff --git a/plat/gxb/include/ndma_utils.h b/plat/gxb/include/ndma_utils.h new file mode 100644 index 0000000..a0ff93a --- /dev/null +++ b/plat/gxb/include/ndma_utils.h @@ -0,0 +1,33 @@ + +#ifndef NDMA_UTILS_H +#define NDMA_UTILS_H +void NDMA_set_table_position( uint32_t thread_num, uint32_t table_start, uint32_t table_end ); +void NDMA_set_table_position_secure( uint32_t thread_num, uint32_t table_start, uint32_t table_end ); +void NDMA_start(uint32_t thread_num); +void NDMA_stop(uint32_t thread_num); +void NDMA_wait_for_completion(uint32_t thread_num); +void NDMA_add_descriptor_aes( + uint32_t thread_num, + uint32_t irq, + uint32_t cbc_enable, + uint32_t cbc_reset, + uint32_t encrypt, // 0 = decrypt, 1 = encrypt + uint32_t aes_type, // 00 = 128, 01 = 192, 10 = 256 + uint32_t pre_endian, + uint32_t post_endian, + uint32_t bytes_to_move, + uint32_t src_addr, + uint32_t dest_addr, + uint32_t ctr_endian, + uint32_t ctr_limit ); + + +void NDMA_add_descriptor_sha( + uint32_t thread_num, + uint32_t irq, + uint32_t sha_type, // 0 = sha1, 1 = sha2-224, 2 = sha2-256 + uint32_t pre_endian, + uint32_t bytes_to_move, + uint32_t src_addr, + uint32_t last_block ); +#endif diff --git a/plat/gxb/include/plat_init.h b/plat/gxb/include/plat_init.h new file mode 100644 index 0000000..a6ee99b --- /dev/null +++ b/plat/gxb/include/plat_init.h @@ -0,0 +1,27 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/include/plat_init.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __ARCH_INIT_H +#define __ARCH_INIT_H + +void pinmux_init(void); + +#endif /* __ARCH_INIT_H */ diff --git a/plat/gxb/include/plat_macros.S b/plat/gxb/include/plat_macros.S new file mode 100644 index 0000000..71f4264 --- /dev/null +++ b/plat/gxb/include/plat_macros.S @@ -0,0 +1,55 @@ +/* + * 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 <gic_v2.h> +#include "../plat_def.h" + +.section .rodata.gic_reg_name, "aS" +gic_regs: .asciz "gic_iar", "gic_ctlr", "" + +/* Currently we have only 2 GIC registers to report */ +#define GIC_REG_SIZE (2 * 8) + /* --------------------------------------------- + * The below macro prints out relevant GIC + * registers whenever an unhandled exception is + * taken in BL3-1. + * --------------------------------------------- + */ + .macro plat_print_gic_regs + ldr x0, =GICC_BASE + ldr w1, [x0, #GICC_IAR] + ldr w2, [x0, #GICC_CTLR] + sub sp, sp, #GIC_REG_SIZE + stp x1, x2, [sp] /* we store the gic registers as 64 bit */ + adr x0, gic_regs + mov x1, sp + bl print_string_value + add sp, sp, #GIC_REG_SIZE + .endm diff --git a/plat/gxb/include/platform_def.h b/plat/gxb/include/platform_def.h new file mode 100644 index 0000000..386baa3 --- /dev/null +++ b/plat/gxb/include/platform_def.h @@ -0,0 +1,188 @@ +/* + * 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 0xE00 + +/* Size of coherent stacks for debug and release builds */ +#if DEBUG +#define PCPU_DV_MEM_STACK_SIZE 0x400 +#else +#define PCPU_DV_MEM_STACK_SIZE 0x300 +#endif + +#define FIRMWARE_WELCOME_STR "Booting trusted firmware boot loader stage 1\n\r" + +/* Trusted Boot Firmware BL2 */ +#define BL2_IMAGE_NAME "bl2.bin" +#define BL2_IMAGE_SIZE 0xC000 /*48KB*/ +#define BL2_IMAGE_OFFSET 0x1000 /*4KB, header of bl2*/ + +/* 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_CORE_COUNT 6 +#define PRIMARY_CPU 0x0 +#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_BASE 0xD9040000 +#define TZROM_SIZE 0x00010000 + +//#define TZRAM_BASE 0x04001000 +//#define TZRAM_SIZE 0x0003F000 +#define TZRAM_BASE 0xD9000000 +#define TZRAM_SIZE 0x00020000 + +#define TZRAM_BL2_FREE_BASE TZRAM_BASE + BL2_IMAGE_SIZE +#define TZRAM_BL2_FREE_SIZE TZRAM_SIZE - BL2_IMAGE_SIZE + +/******************************************************************************* + * 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_BASE TZRAM_BASE + BL2_IMAGE_OFFSET +//#define BL2_LIMIT (TZRAM_BASE + TZRAM_SIZE) +#define BL2_LIMIT (TZRAM_BASE + 0XC000) //48KB + +#define BL2_ALIGN (16) //default 4K +//#define BL2_ENABLE_MMU + +/******************************************************************************* + * Load address of BL3-0 in the ${PLAT} 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 ${PLAT} port + ******************************************************************************/ +#define NS_IMAGE_OFFSET 0xE0000000 + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define ADDR_SPACE_SIZE (1ull << 32) +#define MAX_XLAT_TABLES 5 +#define MAX_MMAP_REGIONS 16 + +/******************************************************************************* + * ID of the secure physical generic timer interrupt. + ******************************************************************************/ +#define IRQ_SEC_PHY_TIMER 29 + +/******************************************************************************* + * CCI-400 related constants + ******************************************************************************/ +#define CCI400_BASE 0x2c090000 +#define CCI400_SL_IFACE_CLUSTER0 4 +#define CCI400_SL_IFACE_CLUSTER1 3 +#define CCI400_SL_IFACE_INDEX(mpidr) (mpidr & MPIDR_CLUSTER_MASK ? \ + CCI400_SL_IFACE_CLUSTER1 : \ + CCI400_SL_IFACE_CLUSTER0) +/******************************************************************************* + * Declarations and constants to access the mailboxes safely. Each mailbox is + * aligned on the biggest cache line size in the platform. This is known only + * to the platform as it might have a combination of integrated and external + * caches. Such alignment ensures that two maiboxes do not sit on the same cache + * line at any cache level. They could belong to different cpus/clusters & + * get written while being protected by different locks causing corruption of + * a valid mailbox address. + ******************************************************************************/ +#define CACHE_WRITEBACK_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +#endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/gxb/include/pll.h b/plat/gxb/include/pll.h new file mode 100644 index 0000000..1e71b7e --- /dev/null +++ b/plat/gxb/include/pll.h @@ -0,0 +1,61 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/include/pll.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <stdint.h> +#include <io.h> + +#ifndef __BL2_PLL_H_ +#define __BL2_PLL_H_ + +#define PLL_lOCK_CHECK_LOOP 10 +#define PLL_LOCK_BIT_OFFSET 31 + +#define Wr(reg, val) writel(val, reg) +#define Rd(reg) readl(reg) + +#define CFG_SYS_PLL_CNTL_2 (0x5ac80000) +#define CFG_SYS_PLL_CNTL_3 (0x8e452015) +#define CFG_SYS_PLL_CNTL_4 (0x0401d40c) +#define CFG_SYS_PLL_CNTL_5 (0x00000870) + +#define CFG_MPLL_CNTL_2 (0x59C80000) +#define CFG_MPLL_CNTL_3 (0xCA45B822) +#define CFG_MPLL_CNTL_4 (0x00010007) +#define CFG_MPLL_CNTL_5 (0xB5500E1A) +#define CFG_MPLL_CNTL_6 (0xFC454545) +#define CFG_MPLL_CNTL_7 (0) +#define CFG_MPLL_CNTL_8 (0) +#define CFG_MPLL_CNTL_9 (0) + +//DDR PLL +#define CFG_DDR_PLL_CNTL_1 (0x69c80000) +#define CFG_DDR_PLL_CNTL_2 (0xca463823) +#define CFG_DDR_PLL_CNTL_3 (0x00c00023) +#define CFG_DDR_PLL_CNTL_4 (0x00303500) + +unsigned int pll_init(void); +void clocks_set_sys_cpu_clk(uint32_t freq, \ + uint32_t pclk_ratio, \ + uint32_t aclkm_ratio, \ + uint32_t atclk_ratio ); +unsigned pll_lock_check(unsigned long pll_reg, const char *pll_name); + +#endif /*__BL2_PLL_H_*/
\ No newline at end of file diff --git a/plat/gxb/include/rsa.h b/plat/gxb/include/rsa.h new file mode 100644 index 0000000..c6c91c5 --- /dev/null +++ b/plat/gxb/include/rsa.h @@ -0,0 +1,598 @@ +/** + * \file rsa.h + * + * \brief The RSA public-key cryptosystem + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_RSA_H +#define POLARSSL_RSA_H + +#include "common.h" +#include "bignum.h" + +/* + * RSA Error codes + */ +#define POLARSSL_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */ +#define POLARSSL_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */ +#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the libraries validity check. */ +#define POLARSSL_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */ +#define POLARSSL_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */ +#define POLARSSL_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */ +#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */ +#define POLARSSL_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */ + +/* + * PKCS#1 constants + */ +#define SIG_RSA_RAW 0 +#define SIG_RSA_MD2 2 +#define SIG_RSA_MD4 3 +#define SIG_RSA_MD5 4 +#define SIG_RSA_SHA1 5 +#define SIG_RSA_SHA224 14 +#define SIG_RSA_SHA256 11 +#define SIG_RSA_SHA384 12 +#define SIG_RSA_SHA512 13 + +#define RSA_PUBLIC 0 +#define RSA_PRIVATE 1 + +#define RSA_PKCS_V15 0 +#define RSA_PKCS_V21 1 + +#define RSA_SIGN 1 +#define RSA_CRYPT 2 + +#define ASN1_STR_CONSTRUCTED_SEQUENCE "\x30" +#define ASN1_STR_NULL "\x05" +#define ASN1_STR_OID "\x06" +#define ASN1_STR_OCTET_STRING "\x04" + +#define OID_DIGEST_ALG_MDX "\x2A\x86\x48\x86\xF7\x0D\x02\x00" +#define OID_HASH_ALG_SHA1 "\x2b\x0e\x03\x02\x1a" +#define OID_HASH_ALG_SHA2X "\x60\x86\x48\x01\x65\x03\x04\x02\x00" + +#define OID_ISO_MEMBER_BODIES "\x2a" +#define OID_ISO_IDENTIFIED_ORG "\x2b" + +/* + * ISO Member bodies OID parts + */ +#define OID_COUNTRY_US "\x86\x48" +#define OID_RSA_DATA_SECURITY "\x86\xf7\x0d" + +/* + * ISO Identified organization OID parts + */ +#define OID_OIW_SECSIG_SHA1 "\x0e\x03\x02\x1a" + +/* + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * + * Digest ::= OCTET STRING + */ +#define ASN1_HASH_MDX \ +( \ + ASN1_STR_CONSTRUCTED_SEQUENCE "\x20" \ + ASN1_STR_CONSTRUCTED_SEQUENCE "\x0C" \ + ASN1_STR_OID "\x08" \ + OID_DIGEST_ALG_MDX \ + ASN1_STR_NULL "\x00" \ + ASN1_STR_OCTET_STRING "\x10" \ +) + +#define ASN1_HASH_SHA1 \ + ASN1_STR_CONSTRUCTED_SEQUENCE "\x21" \ + ASN1_STR_CONSTRUCTED_SEQUENCE "\x09" \ + ASN1_STR_OID "\x05" \ + OID_HASH_ALG_SHA1 \ + ASN1_STR_NULL "\x00" \ + ASN1_STR_OCTET_STRING "\x14" + +#define ASN1_HASH_SHA1_ALT \ + ASN1_STR_CONSTRUCTED_SEQUENCE "\x1F" \ + ASN1_STR_CONSTRUCTED_SEQUENCE "\x07" \ + ASN1_STR_OID "\x05" \ + OID_HASH_ALG_SHA1 \ + ASN1_STR_OCTET_STRING "\x14" + +#define ASN1_HASH_SHA2X \ + ASN1_STR_CONSTRUCTED_SEQUENCE "\x11" \ + ASN1_STR_CONSTRUCTED_SEQUENCE "\x0d" \ + ASN1_STR_OID "\x09" \ + OID_HASH_ALG_SHA2X \ + ASN1_STR_NULL "\x00" \ + ASN1_STR_OCTET_STRING "\x00" + +/** + * \brief RSA context structure + */ +typedef struct +{ + int ver; /*!< always 0 */ + size_t len; /*!< size(N) in chars */ + + mpi N; /*!< public modulus */ + mpi E; /*!< public exponent */ + + mpi D; /*!< private exponent */ + mpi P; /*!< 1st prime factor */ + mpi Q; /*!< 2nd prime factor */ + mpi DP; /*!< D % (P - 1) */ + mpi DQ; /*!< D % (Q - 1) */ + mpi QP; /*!< 1 / (Q % P) */ + + mpi RN; /*!< cached R^2 mod N */ + mpi RP; /*!< cached R^2 mod P */ + mpi RQ; /*!< cached R^2 mod Q */ + + int padding; /*!< RSA_PKCS_V15 for 1.5 padding and + RSA_PKCS_v21 for OAEP/PSS */ + int hash_id; /*!< Hash identifier of md_type_t as + specified in the md.h header file + for the EME-OAEP and EMSA-PSS + encoding */ +} +rsa_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize an RSA context + * + * Note: Set padding to RSA_PKCS_V21 for the RSAES-OAEP + * encryption scheme and the RSASSA-PSS signature scheme. + * + * \param ctx RSA context to be initialized + * \param padding RSA_PKCS_V15 or RSA_PKCS_V21 + * \param hash_id RSA_PKCS_V21 hash identifier + * + * \note The hash_id parameter is actually ignored + * when using RSA_PKCS_V15 padding. + */ +void rsa_init( rsa_context *ctx, + int padding, + int hash_id); + +/** + * \brief Generate an RSA keypair + * + * \param ctx RSA context that will hold the key + * \param f_rng RNG function + * \param p_rng RNG parameter + * \param nbits size of the public key in bits + * \param exponent public exponent (e.g., 65537) + * + * \note rsa_init() must be called beforehand to setup + * the RSA context. + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + */ +int rsa_gen_key( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ); + +/** + * \brief Check a public RSA key + * + * \param ctx RSA context to be checked + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + */ +int rsa_check_pubkey( const rsa_context *ctx ); + +/** + * \brief Check a private RSA key + * + * \param ctx RSA context to be checked + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + */ +int rsa_check_privkey( const rsa_context *ctx ); + +/** + * \brief Do an RSA public key operation + * + * \param ctx RSA context + * \param input input buffer + * \param output output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note This function does NOT take care of message + * padding. Also, be sure to set input[0] = 0 or assure that + * input is smaller than N. + * + * \note The input and output buffers must be large + * enough (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_public( rsa_context *ctx, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Do an RSA private key operation + * + * \param ctx RSA context + * \param input input buffer + * \param output output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The input and output buffers must be large + * enough (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_private( rsa_context *ctx, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Generic wrapper to perform a PKCS#1 encryption using the + * mode from the context. Add the message padding, then do an + * RSA operation. + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param ilen contains the plaintext length + * \param input buffer holding the data to be encrypted + * \param output buffer that will hold the ciphertext + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_pkcs1_encrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Perform a PKCS#1 v1.5 encryption (RSAES-PKCS1-v1_5-ENCRYPT) + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for padding) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param ilen contains the plaintext length + * \param input buffer holding the data to be encrypted + * \param output buffer that will hold the ciphertext + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_rsaes_pkcs1_v15_encrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Perform a PKCS#1 v2.1 OAEP encryption (RSAES-OAEP-ENCRYPT) + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param label buffer holding the custom label to use + * \param label_len contains the label length + * \param ilen contains the plaintext length + * \param input buffer holding the data to be encrypted + * \param output buffer that will hold the ciphertext + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_rsaes_oaep_encrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Generic wrapper to perform a PKCS#1 decryption using the + * mode from the context. Do an RSA operation, then remove + * the message padding + * + * \param ctx RSA context + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param olen will contain the plaintext length + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +int rsa_pkcs1_decrypt( rsa_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief Perform a PKCS#1 v1.5 decryption (RSAES-PKCS1-v1_5-DECRYPT) + * + * \param ctx RSA context + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param olen will contain the plaintext length + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +int rsa_rsaes_pkcs1_v15_decrypt( rsa_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief Perform a PKCS#1 v2.1 OAEP decryption (RSAES-OAEP-DECRYPT) + * + * \param ctx RSA context + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param label buffer holding the custom label to use + * \param label_len contains the label length + * \param olen will contain the plaintext length + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +int rsa_rsaes_oaep_decrypt( rsa_context *ctx, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief Generic wrapper to perform a PKCS#1 signature using the + * mode from the context. Do a private RSA operation to sign + * a message digest + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} + * \param hashlen message digest length (for SIG_RSA_RAW only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \note In case of PKCS#1 v2.1 encoding keep in mind that + * the hash_id in the RSA context is the one used for the + * encoding. hash_id in the function call is the type of hash + * that is encoded. According to RFC 3447 it is advised to + * keep both hashes the same. + */ +int rsa_pkcs1_sign( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief Perform a PKCS#1 v1.5 signature (RSASSA-PKCS1-v1_5-SIGN) + * + * \param ctx RSA context + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} + * \param hashlen message digest length (for SIG_RSA_RAW only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief Perform a PKCS#1 v2.1 PSS signature (RSASSA-PSS-SIGN) + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} + * \param hashlen message digest length (for SIG_RSA_RAW only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \note In case of PKCS#1 v2.1 encoding keep in mind that + * the hash_id in the RSA context is the one used for the + * encoding. hash_id in the function call is the type of hash + * that is encoded. According to RFC 3447 it is advised to + * keep both hashes the same. + */ +int rsa_rsassa_pss_sign( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief Generic wrapper to perform a PKCS#1 verification using the + * mode from the context. Do a public RSA operation and check + * the message digest + * + * \param ctx points to an RSA public key + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} + * \param hashlen message digest length (for SIG_RSA_RAW only) + * \param hash buffer holding the message digest + * \param sig buffer holding the ciphertext + * + * \return 0 if the verify operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \note In case of PKCS#1 v2.1 encoding keep in mind that + * the hash_id in the RSA context is the one used for the + * verification. hash_id in the function call is the type of hash + * that is verified. According to RFC 3447 it is advised to + * keep both hashes the same. + */ +int rsa_pkcs1_verify( rsa_context *ctx, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief Perform a PKCS#1 v1.5 verification (RSASSA-PKCS1-v1_5-VERIFY) + * + * \param ctx points to an RSA public key + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} + * \param hashlen message digest length (for SIG_RSA_RAW only) + * \param hash buffer holding the message digest + * \param sig buffer holding the ciphertext + * + * \return 0 if the verify operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY) + * \brief Do a public RSA and check the message digest + * + * \param ctx points to an RSA public key + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} + * \param hashlen message digest length (for SIG_RSA_RAW only) + * \param hash buffer holding the message digest + * \param sig buffer holding the ciphertext + * + * \return 0 if the verify operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \note In case of PKCS#1 v2.1 encoding keep in mind that + * the hash_id in the RSA context is the one used for the + * verification. hash_id in the function call is the type of hash + * that is verified. According to RFC 3447 it is advised to + * keep both hashes the same. + */ +int rsa_rsassa_pss_verify( rsa_context *ctx, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief Free the components of an RSA key + * + * \param ctx RSA Context to free + */ +void rsa_free( rsa_context *ctx ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int rsa_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* rsa.h */ diff --git a/plat/gxb/include/rsa_config.h b/plat/gxb/include/rsa_config.h new file mode 100644 index 0000000..6425e11 --- /dev/null +++ b/plat/gxb/include/rsa_config.h @@ -0,0 +1,892 @@ +/** + * \file config.h + * + * \brief Configuration options (set of defines) + * + * Copyright (C) 2006-2012, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + */ +#ifndef POLARSSL_CONFIG_H +#define POLARSSL_CONFIG_H + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def POLARSSL_HAVE_INT8 + * + * The system uses 8-bit wide native integers. + * + * Uncomment if native integers are 8-bit wide. +#define POLARSSL_HAVE_INT8 + */ + +/** + * \def POLARSSL_HAVE_INT16 + * + * The system uses 16-bit wide native integers. + * + * Uncomment if native integers are 16-bit wide. +#define POLARSSL_HAVE_INT16 + */ + +/** + * \def POLARSSL_HAVE_LONGLONG + * + * The compiler supports the 'long long' type. + * (Only used on 32-bit platforms) + */ +#define POLARSSL_HAVE_LONGLONG + +/** + * \def POLARSSL_HAVE_ASM + * + * The compiler has support for asm() + * + * Uncomment to enable the use of assembly code. + * + * Requires support for asm() in compiler. + * + * Used in: + * library/timing.c + * library/padlock.c + * include/polarssl/bn_mul.h + * + */ +#define POLARSSL_HAVE_ASM + +/** + * \def POLARSSL_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + * +#define POLARSSL_HAVE_SSE2 + */ +/* \} name */ + +/** + * \name SECTION: PolarSSL feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def POLARSSL_AES_ROM_TABLES + * + * Store the AES tables in ROM. + * + * Uncomment this macro to store the AES tables in ROM. + * +#define POLARSSL_AES_ROM_TABLES + */ + +/** + * \def POLARSSL_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +#define POLARSSL_CIPHER_MODE_CFB + +/** + * \def POLARSSL_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +#define POLARSSL_CIPHER_MODE_CTR + +/** + * \def POLARSSL_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires POLARSSL_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * TLS_RSA_WITH_NULL_MD5 + * TLS_RSA_WITH_NULL_SHA + * TLS_RSA_WITH_NULL_SHA256 + * + * Uncomment this macro to enable the NULL cipher and ciphersuites +#define POLARSSL_CIPHER_NULL_CIPHER + */ + +/** + * \def POLARSSL_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * TLS_RSA_WITH_DES_CBC_SHA + * TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to enable weak ciphersuites +#define POLARSSL_ENABLE_WEAK_CIPHERSUITES + */ + +/** + * \def POLARSSL_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of error_strerror() in + * third party libraries easier. + * + * Disable if you run into name conflicts and want to really remove the + * error_strerror() + */ +#define POLARSSL_ERROR_STRERROR_DUMMY + +/** + * \def POLARSSL_GENPRIME + * + * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C + * + * Enable the RSA prime-number generation code. +#define POLARSSL_GENPRIME + */ + +/** + * \def POLARSSL_FS_IO + * + * Enable functions that use the filesystem. +#define POLARSSL_FS_IO + */ + +/** + * \def POLARSSL_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. +#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES + */ + +/** + * \def POLARSSL_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. +#define POLARSSL_NO_PLATFORM_ENTROPY + */ + +/** + * \def POLARSSL_PKCS1_V21 + * + * Requires: POLARSSL_MD_C, POLARSSL_RSA_C + * + * Enable support for PKCS#1 v2.1 encoding. + * This enables support for RSAES-OAEP and RSASSA-PSS operations. +#define POLARSSL_PKCS1_V21 + */ + +/** + * \def POLARSSL_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * +#define POLARSSL_RSA_NO_CRT + */ + +/** + * \def POLARSSL_SELF_TEST + * + * Enable the checkup functions (*_self_test). +#define POLARSSL_SELF_TEST + */ + +/** + * \def POLARSSL_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, PolarSSL can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +#define POLARSSL_SSL_ALERT_MESSAGES + +/** + * \def POLARSSL_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * +#define POLARSSL_SSL_DEBUG_ALL + */ + +/** + * \def POLARSSL_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * Uncomment this macro to enable hooking functions. +#define POLARSSL_SSL_HW_RECORD_ACCEL + */ + +/** + * \def POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (POLARSSL_SSL_SRV_C) + * + * Comment this macro to disable support for SSLv2 Client Hello messages. + */ +#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + +/** + * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an unknown critical extension. + * + * Uncomment to prevent an error. + * +#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + */ + +/** + * \def POLARSSL_ZLIB_SUPPORT + * + * If set, the SSL/TLS module uses ZLIB to support compression and + * decompression of packet data. + * + * Used in: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB +#define POLARSSL_ZLIB_SUPPORT + */ +/* \} name */ + +/** + * \name SECTION: PolarSSL modules + * + * This section enables or disables entire modules in PolarSSL + * \{ + */ + +/** + * \def POLARSSL_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/ssl_tls.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_WITH_AES_128_CBC_SHA + * TLS_RSA_WITH_AES_256_CBC_SHA + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * TLS_RSA_WITH_AES_128_CBC_SHA256 + * TLS_RSA_WITH_AES_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * TLS_RSA_WITH_AES_128_GCM_SHA256 + * TLS_RSA_WITH_AES_256_GCM_SHA384 + * + * PEM uses AES for decrypting encrypted keys. +#define POLARSSL_AES_C + */ + +/** + * \def POLARSSL_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites: + * TLS_RSA_WITH_RC4_128_MD5 + * TLS_RSA_WITH_RC4_128_SHA +#define POLARSSL_ARC4_C + */ + +/** + * \def POLARSSL_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509parse.c + */ +#define POLARSSL_ASN1_PARSE_C + +/** + * \def POLARSSL_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + */ +#define POLARSSL_ASN1_WRITE_C + +/** + * \def POLARSSL_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +#define POLARSSL_BASE64_C + +/** + * \def POLARSSL_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/rsa.c + * library/ssl_tls.c + * library/x509parse.c + * + * This module is required for RSA and DHM support. + */ +#define POLARSSL_BIGNUM_C + +/** + * \def POLARSSL_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +#define POLARSSL_BLOWFISH_C + +/** + * \def POLARSSL_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + */ +#define POLARSSL_CAMELLIA_C + +/** + * \def POLARSSL_CERTS_C + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * This module is used for testing (ssl_client/server). + */ +#define POLARSSL_CERTS_C + +/** + * \def POLARSSL_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: + * + * Uncomment to enable generic cipher wrappers. + */ +#define POLARSSL_CIPHER_C + +/** + * \def POLARSSL_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-256-based random generator + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: POLARSSL_AES_C + * + * This module provides the CTR_DRBG AES-256 random number generator. + */ +#define POLARSSL_CTR_DRBG_C + +/** + * \def POLARSSL_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +#define POLARSSL_DEBUG_C + +/** + * \def POLARSSL_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * + * PEM uses DES/3DES for decrypting encrypted keys. + */ +#define POLARSSL_DES_C + +/** + * \def POLARSSL_DHM_C + * + * Enable the Diffie-Hellman-Merkle key exchange. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_DHE_RSA_WITH_DES_CBC_SHA + * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + */ +#define POLARSSL_DHM_C + +/** + * \def POLARSSL_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: POLARSSL_SHA4_C + * + * This module provides a generic entropy pool + */ +#define POLARSSL_ENTROPY_C + +/** + * \def POLARSSL_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables err_strerror(). + */ +#define POLARSSL_ERROR_C + +/** + * \def POLARSSL_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES + * + * Module: library/gcm.c + * + * Requires: POLARSSL_AES_C + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_WITH_AES_128_GCM_SHA256 + * TLS_RSA_WITH_AES_256_GCM_SHA384 + */ +#define POLARSSL_GCM_C + +/** + * \def POLARSSL_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Module: library/havege.c + * Caller: + * + * Requires: POLARSSL_TIMING_C + * + * This module enables the HAVEGE random number generator. + */ +#define POLARSSL_HAVEGE_C + +/** + * \def POLARSSL_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define POLARSSL_MD_C + +/** + * \def POLARSSL_MD2_C + * + * Enable the MD2 hash algorithm + * + * Module: library/md2.c + * Caller: library/x509parse.c + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + * +#define POLARSSL_MD2_C + */ + +/** + * \def POLARSSL_MD4_C + * + * Enable the MD4 hash algorithm + * + * Module: library/md4.c + * Caller: library/x509parse.c + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + * +#define POLARSSL_MD4_C + */ + +/** + * \def POLARSSL_MD5_C + * + * Enable the MD5 hash algorithm + * + * Module: library/md5.c + * Caller: library/pem.c + * library/ssl_tls.c + * library/x509parse.c + * + * This module is required for SSL/TLS and X.509. + * PEM uses MD5 for decrypting encrypted keys. + */ +#define POLARSSL_MD5_C + +/** + * \def POLARSSL_NET_C + * + * Enable the TCP/IP networking routines. + * + * Module: library/net.c + * Caller: + * + * This module provides TCP/IP networking routines. + */ +#define POLARSSL_NET_C + +/** + * \def POLARSSL_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * This modules adds support for the VIA PadLock on x86. +#define POLARSSL_PADLOCK_C + */ + +/** + * \def POLARSSL_PBKDF2_C + * + * Enable PKCS#5 PBKDF2 key derivation function + * + * Module: library/pbkdf2.c + * + * Requires: POLARSSL_MD_C + * + * This module adds support for the PKCS#5 PBKDF2 key derivation function. +#define POLARSSL_PBKDF2_C + */ + +/** + * \def POLARSSL_PEM_C + * + * Enable PEM decoding + * + * Module: library/pem.c + * Caller: library/x509parse.c + * + * Requires: POLARSSL_BASE64_C + * + * This modules adds support for decoding PEM files. + */ +#define POLARSSL_PEM_C + +/** + * \def POLARSSL_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/ssl_srv.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) +#define POLARSSL_PKCS11_C + */ + +/** + * \def POLARSSL_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * Requires: POLARSSL_BIGNUM_C + * + * This module is required for SSL/TLS and MD5-signed certificates. + */ +#define POLARSSL_RSA_C + +/** + * \def POLARSSL_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509parse.c + * + * This module is required for SSL/TLS and SHA1-signed certificates. +#define POLARSSL_SHA1_C + */ + +/** + * \def POLARSSL_SHA2_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * + * Module: library/sha2.c + * Caller: library/md_wrap.c + * library/x509parse.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define POLARSSL_SHA2_C + +/** + * \def POLARSSL_SHA4_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * + * Module: library/sha4.c + * Caller: library/md_wrap.c + * library/x509parse.c + * + * This module adds support for SHA-384 and SHA-512. + */ +#define POLARSSL_SHA4_C + +/** + * \def POLARSSL_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: POLARSSL_SSL_CACHE_C + */ +#define POLARSSL_SSL_CACHE_C + +/** + * \def POLARSSL_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#define POLARSSL_SSL_CLI_C + +/** + * \def POLARSSL_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +#define POLARSSL_SSL_SRV_C + +/** + * \def POLARSSL_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: POLARSSL_MD5_C, POLARSSL_SHA1_C, POLARSSL_X509_PARSE_C + * + * This module is required for SSL/TLS. + */ +#define POLARSSL_SSL_TLS_C + +/** + * \def POLARSSL_TIMING_C + * + * Enable the portable timing interface. + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +#define POLARSSL_TIMING_C + +/** + * \def POLARSSL_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +#define POLARSSL_VERSION_C + +/** + * \def POLARSSL_X509_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/x509parse.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_RSA_C + * + * This module is required for X.509 certificate parsing. + */ +#define POLARSSL_X509_PARSE_C + +/** + * \def POLARSSL_X509_WRITE_C + * + * Enable X.509 buffer writing. + * + * Module: library/x509write.c + * + * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C + * + * This module is required for X.509 certificate request writing. + */ +#define POLARSSL_X509_WRITE_C + +/** + * \def POLARSSL_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +#define POLARSSL_XTEA_C +/* \} name */ + +#endif /* config.h */ diff --git a/plat/gxb/include/saradc.h b/plat/gxb/include/saradc.h new file mode 100644 index 0000000..ca6becf --- /dev/null +++ b/plat/gxb/include/saradc.h @@ -0,0 +1,48 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/include/pll.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <stdint.h> +#include <io.h> + +#ifndef __SARADC_H_ +#define __SARADC_H_ + +#define Wr(reg, val) writel(val, reg) +#define Rd(reg) readl(reg) + +#define P_SAR_SAR_ADC_REG0 (volatile unsigned int *)0xc1108680 +#define P_SAR_ADC_CHAN_LIST (volatile unsigned int *)0xc1108684 +#define P_SAR_ADC_AVG_CNTL (volatile unsigned int *)0xc1108688 +#define P_SAR_ADC_REG3 (volatile unsigned int *)0xc110868c +#define P_SAR_ADC_DELAY (volatile unsigned int *)0xc1108690 +#define P_SAR_ADC_AUX_SW (volatile unsigned int *)0xc110869c +#define P_SAR_ADC_CHAN_10_SW (volatile unsigned int *)0xc11086a0 +#define P_SAR_ADC_DETECT_IDLE_SW (volatile unsigned int *)0xc11086a4 +#define P_SAR_ADC_DELTA_11 (volatile unsigned int *)0xc11086a8 +#define P_SAR_ADC_TEMP_SES (volatile unsigned int *)0xc11086ac +#define P_SAR_ADC_CLOCK (volatile unsigned int *)0xc883c3d8 +#define P_SAR_FIFO_READ (volatile unsigned int *)0xc1108698 + + +unsigned int saradc_ch1_get(void); + + +#endif /*__BL2_PLL_H_*/ diff --git a/plat/gxb/include/sha2.h b/plat/gxb/include/sha2.h new file mode 100644 index 0000000..f63f2c0 --- /dev/null +++ b/plat/gxb/include/sha2.h @@ -0,0 +1,48 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/include/sha2.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <stdint.h> + +#ifndef __PLAT_SHA2_H_ +#define __PLAT_SHA2_H_ + + +#define SHA224_DIGEST_SIZE 28 + +#define SHA256_DIGEST_SIZE 32 +#define SHA256_BLOCK_SIZE 64 + +/* SHA2 context */ +typedef struct { + uint32_t h[8]; + uint32_t tot_len; + uint32_t len; + uint32_t digest_len; + uint8_t block[2 * SHA256_BLOCK_SIZE]; + uint8_t buf[SHA256_DIGEST_SIZE]; /* Used to store the final digest. */ +}sha2_ctx ; + +void SHA2_init(sha2_ctx *, unsigned int ); +void SHA2_update(sha2_ctx *, const uint8_t *, unsigned int); +void SHA2_final(sha2_ctx *,const unsigned char *, unsigned int ); +void sha2(const unsigned char *, unsigned int , unsigned char output[32], unsigned int); +int aml_data_check(unsigned long ,unsigned long ,unsigned int ,unsigned int ); +#endif /*__PLAT_SHA2_H_*/
\ No newline at end of file diff --git a/plat/gxb/include/storage.h b/plat/gxb/include/storage.h new file mode 100644 index 0000000..ac01e44 --- /dev/null +++ b/plat/gxb/include/storage.h @@ -0,0 +1,77 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/include/storage.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __BL2_STORAGE_H_ +#define __BL2_STORAGE_H_ + +#include <asm/arch/cpu_sdio.h> + +/*boot device defines*/ +#define BOOT_DEVICE_RESERVED 0 +#define BOOT_DEVICE_EMMC 1 +#define BOOT_DEVICE_NAND 2 +#define BOOT_DEVICE_SPI 3 +#define BOOT_DEVICE_SD 4 +#define BOOT_DEVICE_USB 5 +#define BOOT_DEVICE_USB_FORCEMODE 6//force booting from usb mode + +/*sdio defines*/ +#define MAX_DESC_NUM 8 +#define MAX_BLOCK_COUNTS 128 +uint64_t storage_init(void); +uint64_t storage_load(uint64_t src, uint64_t des, uint64_t size, const char * image_name); +uint64_t get_boot_device(void); +uint64_t spi_read(uint64_t src, uint64_t des, uint64_t size); +uint64_t sdio_read_blocks(struct sd_emmc_global_regs *sd_emmc_regs, uint64_t src, uint64_t des, uint64_t size,uint64_t mode); +uint64_t sdio_read_data(uint64_t boot_device, uint64_t src, uint64_t des, uint64_t size); +uint64_t usb_boot(uint64_t src, uint64_t des, uint64_t size); +uint64_t get_boot_device(void); +uint64_t get_ddr_size(void); +void dump_ddr_data(void); +uint64_t sdio_write_data(uint64_t boot_device, uint64_t src, uint64_t des, uint64_t size); +uint64_t sdio_write_blocks(struct sd_emmc_global_regs *sd_emmc_regs, + uint64_t src, uint64_t des, uint64_t size, uint64_t mode); + +/*SIZE defines*/ +#define SIZE_1K 0x400 +#define SIZE_2K 0x800 +#define SIZE_4K 0x1000 +#define SIZE_8K 0x2000 +#define SIZE_16K 0x4000 +#define SIZE_32K 0x8000 +#define SIZE_64K 0x10000 +#define SIZE_128K 0x20000 +#define SIZE_256K 0x40000 +#define SIZE_512K 0x80000 +#define SIZE_1M 0x100000 +#define SIZE_2M 0x200000 +#define SIZE_4M 0x400000 +#define SIZE_8M 0x800000 +#define SIZE_16M 0x1000000 +#define SIZE_32M 0x2000000 +#define SIZE_64M 0x4000000 +#define SIZE_128M 0x8000000 +#define SIZE_256M 0x10000000 +#define SIZE_512M 0x20000000 +#define SIZE_1G 0x40000000 +#define SIZE_2G 0x80000000 + +#endif /*__BL2_STORAGE_H_*/ diff --git a/plat/gxb/include/timer.h b/plat/gxb/include/timer.h new file mode 100644 index 0000000..f477ce1 --- /dev/null +++ b/plat/gxb/include/timer.h @@ -0,0 +1,48 @@ + +/* + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __TIMER_H +#define __TIMER_H + +#include <stdint.h> + +/** + * Get the current timestamp from the system timer. + */ +uint32_t get_time(void); + +/** + * Busy-wait. + * + * @param us Number of microseconds to delay. + */ +void _udelay(unsigned int us); + +/** + * time counter + * usage: + * timer_start(); + * func(); //func that you want measure time consumption + * timer_end("func"); //will print "func Time: xxxx us" + */ +void timer_start(void); +void timer_end(const char * name); + +#endif /* __TIMER_H */ diff --git a/plat/gxb/mailbox.c b/plat/gxb/mailbox.c new file mode 100644 index 0000000..eadc2f1 --- /dev/null +++ b/plat/gxb/mailbox.c @@ -0,0 +1,135 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/mailbox.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <stdio.h> +#include <string.h> +#include <io.h> +#include <stdint.h> +#include <asm/arch/romboot.h> +#include <mailbox.h> +#include <asm/arch/secure_apb.h> + +void mb_send_data(uint32_t val, uint32_t port) +{ + unsigned long base_addr = SEC_HIU_MAILBOX_SET_0; + unsigned long set_addr; + + if (port > 5) { + serial_puts("Error: Use the error port num!\n"); + return; + } + + set_addr = base_addr + port*3*4; + + if (!val) { + serial_puts("Error: mailbox try to send zero val!\n"); + return; + } + + writel(val, set_addr); + + return; +} + +uint32_t mb_read_data(uint32_t port) +{ + unsigned long base_addr = SEC_HIU_MAILBOX_STAT_0; + uint32_t val; + + if (port > 5) { + serial_puts("Error: Use the error port num!\n"); + return 0; + } + + val = readl(base_addr + port*3*4); + + if (val) + return val; + else { +// print_out("Warning: read mailbox val=0.\n"); + return 0; + } +} + +void mb_clear_data(uint32_t val, uint32_t port) +{ + uint32_t base_addr = SEC_HIU_MAILBOX_CLR_0; + + unsigned long clean_addr = base_addr + port*3*4; + + if (port > 5) { + serial_puts("Error: Use the error port num!\n"); + return; + } + + if (!val) { + serial_puts("Warning: clean val=0.\n"); + return; + } + + writel(val,clean_addr); + + return; +} + +void send_bl30x(uint32_t addr, uint32_t size, const uint8_t * sha2, \ + uint32_t sha2_length, const char * name) +{ + int i; + *(unsigned int *)MB_SRAM_BASE = size; + + if (0 == strcmp("bl301", name)) { + /*bl301 must wait bl30 run*/ + serial_puts("Wait bl30..."); + while (0x3 != ((readl(AO_SEC_SD_CFG15) >> 20) & 0x3)) {} + serial_puts("Done\n"); + } + + serial_puts("Sending "); + serial_puts(name); + //serial_puts("time=0x%x size=0x%x\n", readl(0xc1109988),size); + + mb_send_data(CMD_DATA_LEN, 3); + do {} while(mb_read_data(3)); + memcpy((void *)MB_SRAM_BASE, (const void *)sha2, sha2_length); + mb_send_data(CMD_SHA, 3); + do {} while(mb_read_data(3)); + + for (i = 0; i < size; i+=1024) { + serial_puts("."); + if (size >= i + 1024) + memcpy((void *)MB_SRAM_BASE,(const void *)(unsigned long)(addr+i),1024); + else if(size > i) + memcpy((void *)MB_SRAM_BASE,(const void *)(unsigned long)(addr+i),(size-i)); + + mb_send_data(CMD_DATA, 3); + do {} while(mb_read_data(3)); + } + mb_send_data(CMD_OP_SHA, 3); + + do {} while(mb_read_data(3)); + serial_puts("OK. \nRun "); + serial_puts(name); + serial_puts("...\n"); + + /* The BL31 will run after this command */ + mb_send_data(CMD_END,3);//code transfer end. +} diff --git a/plat/gxb/mhu.c b/plat/gxb/mhu.c new file mode 100644 index 0000000..ba9baff --- /dev/null +++ b/plat/gxb/mhu.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <arch_helpers.h> +#include <bakery_lock.h> +#include <mmio.h> +#include "plat_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(read_mpidr(), &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(read_mpidr(), &mhu_secure_lock); +} + +void mhu_secure_init(void) +{ + bakery_lock_init(&mhu_secure_lock); + + /* + * Clear the CPU's INTR register to make sure we don't see a stale + * or garbage value and think it's a message we've already sent. + */ + mmio_write_32(MHU_BASE + CPU_INTR_S_CLEAR, 0xffffffffu); +} diff --git a/plat/gxb/mhu.h b/plat/gxb/mhu.h new file mode 100644 index 0000000..5149c82 --- /dev/null +++ b/plat/gxb/mhu.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MHU_H__ +#define __MHU_H__ + +#include <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__ */ diff --git a/plat/gxb/nand.c b/plat/gxb/nand.c new file mode 100644 index 0000000..5813c47 --- /dev/null +++ b/plat/gxb/nand.c @@ -0,0 +1,775 @@ +/* + * Copyright (c) 2015 Amlogic, Inc. All rights reserved. + * + * This source code is subject to the terms and conditions defined in the + * file 'LICENSE' which is part of this source code package. + * + * + * Amlogic nand spl module + * Author: nand team @amlogic.com + * Created time: 2015.04.28 + * + */ + +#include <config.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <io.h> +#include <platform_def.h> +#include <asm/arch/io.h> +#include <asm/arch/nand.h> +#include <efuse.h> +#include <asm/arch/secure_apb.h> +#include <asm/arch/romboot.h> +#include <arch_helpers.h> + +//#define NFIO_LINE do { printf("%s %d\n", __func__, __LINE__); } while(0); +#define NFIO_LINE + +/* global */ +nand_setup_t glb_setup; // 8 bytes + +ext_info_t glb_ext_info = { + .read_info = 0, + .new_type = 0, + .xlc = 0, +}; + +unsigned char page_list_hynix_1y[128] = { + 0x00, 0x01, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x0d, + 0x0f, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1b, 0x1d, + 0x1f, 0x21, 0x23, 0x25, 0x27, 0x29, 0x2b, 0x2d, + 0x2f, 0x31, 0x33, 0x35, 0x37, 0x39, 0x3b, 0x3d, + + 0x3f, 0x41, 0x43, 0x45, 0x47, 0x49, 0x4b, 0x4d, + 0x4f, 0x51, 0x53, 0x55, 0x57, 0x59, 0x5b, 0x5d, + 0x5f, 0x61, 0x63, 0x65, 0x67, 0x69, 0x6b, 0x6d, + 0x6f, 0x71, 0x73, 0x75, 0x77, 0x79, 0x7b, 0x7d, + + 0x7f, 0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d, + 0x8f, 0x91, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9d, + 0x9f, 0xa1, 0xA3, 0xA5, 0xA7, 0xA9, 0xAb, 0xAd, + 0xAf, 0xb1, 0xB3, 0xB5, 0xB7, 0xB9, 0xBb, 0xBd, + + 0xBf, 0xc1, 0xC3, 0xC5, 0xC7, 0xC9, 0xCb, 0xCd, + 0xCf, 0xd1, 0xD3, 0xD5, 0xD7, 0xD9, 0xDb, 0xDd, + 0xDf, 0xe1, 0xE3, 0xE5, 0xE7, 0xE9, 0xEb, 0xEd, + 0xEf, 0xf1, 0xF3, 0xF5, 0xF7, 0xF9, 0xFb, 0xFd, +}; + +unsigned char page_list_hynix_2x[128] = { + 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, + 0x0E, 0x0F, 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, + 0x1E, 0x1F, 0x22, 0x23, 0x26, 0x27, 0x2A, 0x2B, + 0x2E, 0x2F, 0x32, 0x33, 0x36, 0x37, 0x3A, 0x3B, + + 0x3E, 0x3F, 0x42, 0x43, 0x46, 0x47, 0x4A, 0x4B, + 0x4E, 0x4F, 0x52, 0x53, 0x56, 0x57, 0x5A, 0x5B, + 0x5E, 0x5F, 0x62, 0x63, 0x66, 0x67, 0x6A, 0x6B, + 0x6E, 0x6F, 0x72, 0x73, 0x76, 0x77, 0x7A, 0x7B, + + 0x7E, 0x7F, 0x82, 0x83, 0x86, 0x87, 0x8A, 0x8B, + 0x8E, 0x8F, 0x92, 0x93, 0x96, 0x97, 0x9A, 0x9B, + 0x9E, 0x9F, 0xA2, 0xA3, 0xA6, 0xA7, 0xAA, 0xAB, + 0xAE, 0xAF, 0xB2, 0xB3, 0xB6, 0xB7, 0xBA, 0xBB, + + 0xBE, 0xBF, 0xC2, 0xC3, 0xC6, 0xC7, 0xCA, 0xCB, + 0xCE, 0xCF, 0xD2, 0xD3, 0xD6, 0xD7, 0xDA, 0xDB, + 0xDE, 0xDF, 0xE2, 0xE3, 0xE6, 0xE7, 0xEA, 0xEB, + 0xEE, 0xEF, 0xF2, 0xF3, 0xF6, 0xF7, 0xFA, 0xFB, +}; + +//#define PRINT printf +#if 0 +static void _dump_mem_u8(uint8_t * buf, uint32_t len) +{ + uint32_t i; + PRINT("%s, %p, %d", __func__, buf, len); + for (i = 0; i < len/sizeof(uint8_t); i++) { + + if ( i % 16 == 0) + PRINT("\n0x%p: ", buf+i); + PRINT("%02x ", buf[i]); + } + PRINT("\n"); + return; +} +#endif //0 + +void nfio_pin_mux(void) +{ + *P_PAD_PULL_UP_EN_REG2 = 0xffff87ff; + *P_PAD_PULL_UP_REG2 = 0xffff8700; + *P_PERIPHS_PIN_MUX_4 = (1<<31) | (1<<30) | (0x3ff<<20); +} + +uint32_t nfio_reset(void) +{ + uint32_t tmp; + + // Reset NAND controller + (*P_NAND_CMD) = (1<<31); + + // Reset NAND + (*P_NAND_CMD) = (CE0 | IDLE); + (*P_NAND_CMD) = (CE0 | CLE | 0xff); + (*P_NAND_CMD) = (CE0 | IDLE | 10); + + // nand cycle = 200ns. + // Set time out 2^13* nand cycle, 1.7ms + if ( glb_setup.cfg.b.no_rb ) { // without RB + (*P_NAND_CMD) = (CE0 | CLE | 0x70); + (*P_NAND_CMD) = (CE0 | IDLE | 2); + (*P_NAND_CMD) = (IO6 | RB | 13); + } + else { // with RB + *P_NAND_CMD = (CE0 | RB | 13); + } + + (*P_NAND_CMD) = (CE0 | IDLE); + (*P_NAND_CMD) = (CE0 | IDLE); + + // if NAND is not installed or Reset failed, + // the RB time out is set. + while (((tmp = (*P_NAND_CMD))>>22&0x1f) > 0) { + if (tmp>>27&1) { // time out + (*P_NAND_CMD) = (1<<31); + return ERROR_NAND_TIMEOUT; + } + } + + return 0; +} + +/* + * read nand manufactor id into retry info. + */ +static uint16_t _read_id(void) +{ + uint16_t id; + + (*P_NAND_CMD) = (CE0 | IDLE); + (*P_NAND_CMD) = (CE0 | CLE | 0x90); + (*P_NAND_CMD) = (CE0 | IDLE | 3); + (*P_NAND_CMD) = (CE0 | ALE | 0); + (*P_NAND_CMD) = (CE0 | IDLE | 3); + (*P_NAND_CMD) = (CE0 | DRD | 3); + + (*P_NAND_CMD) = (CE0 | IDLE); + (*P_NAND_CMD) = (CE0 | IDLE); + while (((*P_NAND_CMD)>>22&0x1f) > 0); + + id = (*P_NAND_BUF)&0xff; + + return id; +} + +static void _set_retry(uint16_t id) +{ + switch (glb_setup.id) { + case NAND_MFR_MICRON : + glb_setup.max = 8; + break; + case NAND_MFR_TOSHIBA : + glb_setup.max = 8; + break; + case NAND_MFR_SAMSUNG : + glb_setup.max = 15; + break; + case NAND_MFR_SANDISK : + glb_setup.max = 22; + break; + case NAND_MFR_HYNIX : + case NAND_MFR_FUJITSU : + case NAND_MFR_NATIONAL : + case NAND_MFR_RENESAS : + case NAND_MFR_STMICRO : + case NAND_MFR_AMD : + case NAND_MFR_INTEL : + glb_setup.max = 0; + break; + default : + glb_setup.max = 0; + break; + } +} +// toshiba retry ------------------------------------------ +// 0 : pre condition + retry 0. +// 1~6 : valid retry, otherwise no action. +// 7, 0xff : exit, back to normal. +// loop from 0 to 7, total 8. +void read_retry_toshiba(uint32_t retry, uint32_t *cmd) +{ + unsigned char val[] = { + 0x04, 0x04, 0x7C, 0x7E, + 0x00, 0x7C, 0x78, 0x78, + 0x7C, 0x76, 0x74, 0x72, + 0x08, 0x08, 0x00, 0x00, + 0x0B, 0x7E, 0x76, 0x74, + 0x10, 0x76, 0x72, 0x70, + 0x02, 0x00, 0x7E, 0x7C, + 0x00, 0x00, 0x00, 0x00}; + uint32_t i, k, retry_val_idx; + + i = 0; + if (retry == 7) retry = 0xff; + retry_val_idx = retry == 0xff ? 7 : retry; + + if (retry_val_idx < 8) { + // pre condition, send before first. + if (retry == 0) { + cmd[i++] = (CE0 | CLE | 0x5c); + cmd[i++] = (CE0 | CLE | 0xc5); + cmd[i++] = (CE0 | IDLE); + } + + for (k=4; k<8; k++) { + cmd[i++] = (CE0 | CLE | 0x55); + cmd[i++] = (CE0 | IDLE | 2); //Tcalsv + cmd[i++] = (CE0 | ALE | k); + cmd[i++] = (CE0 | IDLE | 2); //Tcalsv + cmd[i++] = (CE0 | DWR | val[retry_val_idx*4 + k-4]); + cmd[i++] = (CE0 | IDLE); + } + + cmd[i++] = (CE0 | CLE | 0x55); + cmd[i++] = (CE0 | IDLE | 2); //Tcalsv + cmd[i++] = (CE0 | ALE | 0xd); + cmd[i++] = (CE0 | IDLE | 2); //Tcalsv + cmd[i++] = (CE0 | DWR | 0); + cmd[i++] = (CE0 | IDLE); + + if (retry == 6) { + cmd[i++] = (CE0 | CLE | 0xb3); + cmd[i++] = (CE0 | IDLE); + } + + if (retry != 0xff) { + cmd[i++] = (CE0 | CLE | 0x26); + cmd[i++] = (CE0 | CLE | 0x5d); + cmd[i++] = (CE0 | IDLE); + } + } + + // exit and check rb + if (retry == 0xff) { + cmd[i++] = (CE0 | CLE | 0xff); + cmd[i++] = (CE0 | IDLE | 2); //Twb + + if (glb_setup.cfg.b.no_rb) { + cmd[i++] = (CE0 | CLE | 0x70); + cmd[i++] = (CE0 | IDLE | 2); + cmd[i++] = (IO6 | RB | 13); + } + else{ + cmd[i++] = (CE0 | RB | 13); + } + } + + cmd[i] = 0; +} + +// sandisk retry ------------------------------------------ +// 0 : activation + retry 0. +// 1~20 : valid retry, otherwise no action. +// 21, 0xff : exit +// loop from 0 to 21, total 22. +void read_retry_sandisk(uint32_t retry, uint32_t *cmd) +{ + uint32_t i, k; + unsigned char val[] = { + 0x00, 0x00, 0x00, + 0xf0, 0xf0, 0xf0, + 0xef, 0xe0, 0xe0, + 0xdf, 0xd0, 0xd0, + 0x1e, 0xe0, 0x10, + 0x2e, 0xd0, 0x20, + 0x3d, 0xf0, 0x30, + 0xcd, 0xe0, 0xd0, + 0x0d, 0xd0, 0x10, + 0x01, 0x10, 0x20, + 0x12, 0x20, 0x20, + 0xb2, 0x10, 0xd0, + 0xa3, 0x20, 0xd0, + 0x9f, 0x00, 0xd0, + 0xbe, 0xf0, 0xc0, + 0xad, 0xc0, 0xc0, + 0x9f, 0xf0, 0xc0, + 0x01, 0x00, 0x00, + 0x02, 0x00, 0x00, + 0x0d, 0xb0, 0x00, + 0x0c, 0xa0, 0x00}; + + i = 0; + if (retry == 21) retry = 0xff; + + if (retry == 0) { // activation and init, entry 0. + cmd[i++] = (CE0 | CLE | 0x3b); + cmd[i++] = (CE0 | CLE | 0xb9); + for (k=4; k<13; k++) { + cmd[i++] = (CE0 | CLE | 0x54); + cmd[i++] = (CE0 | ALE | k); + cmd[i++] = (CE0 | DWR | 0); + } + cmd[i++] = (CE0 | CLE | 0xb6); + } + else if (retry < 21) { // entry: 1~20 + cmd[i++] = (CE0 | CLE | 0x3b); + cmd[i++] = (CE0 | CLE | 0xb9); + for (k=0; k<3; k++) { + cmd[i++] = (CE0 | CLE | 0x54); + cmd[i++] = (CE0 | ALE | (k==0?4:k==1?5:7)); + cmd[i++] = (CE0 | DWR | val[retry*3+k]); + } + cmd[i++] = (CE0 | CLE | 0xb6); + } + else if (retry == 255) { + cmd[i++] = (CE0 | CLE | 0x3b); + cmd[i++] = (CE0 | CLE | 0xb9); + for (k=0; k<3; k++) { + cmd[i++] = (CE0 | CLE | 0x54); + cmd[i++] = (CE0 | ALE | (k==0?4:k==1?5:7)); + cmd[i++] = (CE0 | DWR | 0); + } + cmd[i++] = (CE0 | CLE | 0xd6); + } + cmd[i] = 0; +} + +// micron retry ------------------------------------------ +// 0 : disable +// 1~7 : valid retry, otherwise no action. +// 0xff : same as 0. +// loop from 0 to 7, total 8. +void read_retry_micron(uint32_t retry, uint32_t *cmd) +{ + uint32_t i; + + i = 0; + if (retry == 0xff) retry = 0; + + if (retry < 8) { + cmd[i++] = (CE0 | CLE | 0xef); + cmd[i++] = (CE0 | ALE | 0x89); + cmd[i++] = (CE0 | IDLE | 3); //Tadl + cmd[i++] = (CE0 | DWR | retry); + cmd[i++] = (CE0 | DWR | 0); + cmd[i++] = (CE0 | DWR | 0); + cmd[i++] = (CE0 | DWR | 0); + cmd[i++] = (CE0 | IDLE | 2); //Twb + + //check rb for Tfeat + if (glb_setup.cfg.b.no_rb) { + cmd[i++] = (CE0 | CLE | 0x70); + cmd[i++] = (CE0 | IDLE | 2); + cmd[i++] = (IO6 | RB | 13); + } + else{ + cmd[i++] = (CE0 | RB | 13); + } + } + + cmd[i] = 0; +} + +void read_retry_hynix(uint32_t retry, uint32_t *cmd) +{ + // use SLC mode. +} + +// samsung retry ------------------------------------------ +// 0 : disable +// 1~14 : valid retry, otherwise no action. +// 0xff : same as 0. +// loop from 0 to 14, total 15. +void read_retry_samsung(uint32_t retry, uint32_t *cmd) +{ + uint32_t i, k; + unsigned char adr[] = { + 0xa7, 0xa4, 0xa5, 0xa6}; + unsigned char val[] = { + 0x00, 0x00, 0x00, 0x00, + 0x05, 0x0A, 0x00, 0x00, + 0x28, 0x00, 0xEC, 0xD8, + 0xED, 0xF5, 0xED, 0xE6, + 0x0A, 0x0F, 0x05, 0x00, + 0x0F, 0x0A, 0xFB, 0xEC, + 0xE8, 0xEF, 0xE8, 0xDC, + 0xF1, 0xFB, 0xFE, 0xF0, + 0x0A, 0x00, 0xFB, 0xEC, + 0xD0, 0xE2, 0xD0, 0xC2, + 0x14, 0x0F, 0xFB, 0xEC, + 0xE8, 0xFB, 0xE8, 0xDC, + 0x1E, 0x14, 0xFB, 0xEC, + 0xFB, 0xFF, 0xFB, 0xF8, + 0x07, 0x0C, 0x02, 0x00}; + + i = 0; + if (retry == 0xff) retry = 0; + if (retry < 15) { + for (k=0; k<4; k++) { + cmd[i++] = (CE0 | CLE | 0xa1); + cmd[i++] = (CE0 | ALE | 0); + cmd[i++] = (CE0 | ALE | adr[k]); + cmd[i++] = (CE0 | IDLE | 2); //Tadl + cmd[i++] = (CE0 | DWR | val[retry*4+k]); + cmd[i++] = (CE0 | IDLE | 8); //over 300ns before next cmd + } + } + cmd[i] = 0; +} + + +void nfio_read_retry(uint32_t mode) +{ + static uint32_t retry = 0; + uint32_t i, cmd[128]; + + if (glb_setup.max == 0) + return; + + switch (glb_setup.id) { + case NAND_MFR_MICRON: + NFIO_LINE + read_retry_micron(retry, cmd); + break; + + case NAND_MFR_TOSHIBA: + read_retry_toshiba(retry, cmd); + break; + + case NAND_MFR_HYNIX: + read_retry_hynix(retry, cmd); + break; + + case NAND_MFR_SAMSUNG: + read_retry_samsung(retry, cmd); + break; + + case NAND_MFR_SANDISK: + read_retry_sandisk(retry, cmd); + break; + + /* todo, add other read retry here! */ + } + + retry = retry+1 < glb_setup.max ? retry+1 : 0; + + i = 0; + while (((*P_NAND_CMD)>>22&0x1f)<0x1f && cmd[i] != 0) { + (*P_NAND_CMD) = cmd[i++]; + } +} + +// read one page +uint32_t nfio_page_read(uint32_t src, uint32_t mem) +{ + uint32_t k, ecc_pages; + uint32_t info; + uint64_t mem_addr; + + uint32_t info_adr = NAND_INFO_BUF; //use romboot's buffer. + uint64_t info_adr64; + uint64_t * p_info_buf; + volatile uint64_t dma_done; + + ecc_pages = glb_setup.cfg.b.cmd&0x3f; + + NFIO_LINE + info_adr64 = (uint64_t) info_adr; + p_info_buf = (uint64_t *)info_adr64; + + memset(p_info_buf, 0, ecc_pages * INFO_BYTE_PER_ECCPAGE); + flush_dcache_range((uint64_t)p_info_buf, (uint64_t)(ecc_pages * sizeof(uint64_t))); + + while (((*P_NAND_CMD)>>22&0x1f) > 0); + NFIO_LINE + + // add A2H command for SLC read + if ( glb_setup.cfg.b.a2 ) { + (*P_NAND_CMD) = (CE0 | IDLE); + (*P_NAND_CMD) = (CE0 | CLE | 0xa2); + (*P_NAND_CMD) = (CE0 | IDLE); + } + NFIO_LINE + // send cmds + (*P_NAND_CMD) = CE0 | IDLE; + (*P_NAND_CMD) = CE0 | CLE | 0; + (*P_NAND_CMD) = CE0 | ALE | 0; + if ( glb_setup.cfg.b.large_page ) { + NFIO_LINE + (*P_NAND_CMD) = CE0 | ALE | 0; + } + (*P_NAND_CMD) = CE0 | ALE | ((src)&0xff); + (*P_NAND_CMD) = CE0 | ALE | ((src>>8)&0xff); + (*P_NAND_CMD) = CE0 | ALE | 0; + if ( glb_setup.cfg.b.large_page ) { + NFIO_LINE + (*P_NAND_CMD) = CE0 | CLE | 0x30; + } + NFIO_LINE + if ( glb_setup.cfg.b.no_rb ) { // without RB + NFIO_LINE + (*P_NAND_CMD) = CE0 | IDLE; + (*P_NAND_CMD) = CE0 | CLE | 0x70; + (*P_NAND_CMD) = CE0 | IDLE | 2; + (*P_NAND_CMD) = IO6 | RB | 13; + (*P_NAND_CMD) = CE0 | IDLE | 2; + (*P_NAND_CMD) = CE0 | CLE | 0; //switch to read mode. + (*P_NAND_CMD) = CE0 | IDLE | 2; + }else{ // with RB + (*P_NAND_CMD) = CE0 | IDLE | 40; + (*P_NAND_CMD) = CE0 | RB | 13; + } + /* new way to set address. */ + (*P_NAND_CMD) = ADL | (mem & 0xFFFF); //data address. + (*P_NAND_CMD) = ADH | ((mem >> 16) & 0xFFFF); + (*P_NAND_CMD) = AIL | (info_adr & 0xFFFF); //set info address. + (*P_NAND_CMD) = AIH | ((info_adr >> 16) & 0xFFFF); + + + /* set seed, start dma*/ + (*P_NAND_CMD) = SEED | (0xc2 + (src&0x7fff)); + //printf("cmd 0x%x\n", glb_setup.cfg.b.cmd); + //printf("P_NAND_CFG 0x%x\n", (*P_NAND_CFG)); + (*P_NAND_CMD) = glb_setup.cfg.b.cmd; + + (*P_NAND_CMD) = (CE0 | IDLE); + (*P_NAND_CMD) = (CE0 | IDLE); + NFIO_LINE + /* wait I/F ready*/ + while (((*P_NAND_CMD)>>22&0x1f) > 0); + NFIO_LINE + /* wait info dma ready */ + do { + inv_dcache_range((uint64_t)p_info_buf, (uint64_t)(ecc_pages * sizeof(uint64_t))); + dma_done = p_info_buf[ecc_pages-1]; + } while (dma_done == 0); + NFIO_LINE + // random only, old oob! + // blank page: ecc uncorr, zero_cnt<10. + // ecc error: ecc uncorr, zero_cnt>10. + // no magic: ecc OK, no magic word. + // return the first error. + for (k=0; k<ecc_pages; k++) { + //printf("ecc page %d\n", k); + mem_addr = info_adr; + info = *(volatile uint32_t *)mem_addr; + if ((info>>24 & 0x3f) == 0x3f) { // uncorrectable + if ( glb_setup.cfg.b.a2 ) nfio_reset(); + + // check blank page + if ((info>>16&0x3f) < 0xa) { + //PRINT("blank @ page 0x%08x\n", src); + return ERROR_NAND_BLANK_PAGE; + } + else { + //PRINT("ecc fail @ page 0x%08x\n", src); + return ERROR_NAND_ECC; + } + } + + if (k == 0 && (info & 0xc000ffff) != 0xc000aa55) { //magic word error + //PRINT("magic fail @ page 0x%08x\n", src); + return ERROR_NAND_MAGIC_WORD; + } + info_adr += 8; + } + NFIO_LINE + return 0; +} + +static uint32_t page_2_addr(uint32_t page) +{ + uint32_t addr = page; + uint32_t new_type = glb_ext_info.new_type; + uint32_t page_per_blk = glb_ext_info.page_per_blk; + + if (new_type) { + uint32_t blk_addr; + blk_addr = (page / page_per_blk) * page_per_blk; + /* hynix */ + if (new_type < 10) { + if (new_type == 6) + addr = page_list_hynix_1y[page % page_per_blk] + blk_addr; + else + addr = page_list_hynix_2x[page % page_per_blk] + blk_addr; + } else if (new_type == 40) { + addr = (page % page_per_blk) * 2 + blk_addr; + } + } + return addr; +} + +// read multiple nand pages. fixme, may cause overflow... +uint32_t nfio_read(uint32_t src, uint32_t mem, uint32_t size) +{ + uint32_t ret; + uint32_t ecc_mode, short_mode, short_size, ecc_pages, page_size; + uint32_t page_base, page_addr, retry_cnt, read_size; + + // ecc page size, unit: 8 bytes + ecc_mode = glb_setup.cfg.b.cmd>>14&7; + short_mode = glb_setup.cfg.b.cmd>>13&1; + short_size = glb_setup.cfg.b.cmd>>6&0x7f; + ecc_pages = glb_setup.cfg.b.cmd&0x3f; + + page_size = (short_mode ? short_size : ecc_mode < 2 ? 64 : 128) * 8 * ecc_pages; + NFIO_LINE + flush_dcache_range((uint64_t)mem, (uint64_t)(size)); + // read one nand page per loop. + for (read_size=0; read_size<size; read_size+=page_size) { + page_addr = page_2_addr(src++); + //printf("page_addr 0x%x\n", page_addr); + retry_cnt = 0; + + do { + for (page_base=0; page_base<0x400; page_base+=0x100) { + NFIO_LINE + ret = nfio_page_read(page_base + page_addr, + mem + read_size); + if (ret != ERROR_NAND_ECC) { // good, blank, no magic + break; + } + } + + // read retry + if (ret == ERROR_NAND_ECC) { + if (retry_cnt < glb_setup.max) { + retry_cnt++; + nfio_read_retry(1); + } + else + break; + } + } while (ret == ERROR_NAND_ECC); + + if (ret) return ret; + } + + return 0; +} + +uint32_t nfio_init() +{ + uint32_t ret; + nand_page0_t *page0 = (nand_page0_t *)NAND_PAGE0_BUF; + nand_setup_t *nand_setup; + ext_info_t * p_ext_info; + char e_cfg[8]; + + nand_setup = &page0->nand_setup; + p_ext_info = &page0->ext_info; + + efuse_read(0, 8, e_cfg); + // from default + glb_setup.cfg.d32 = DEFAULT_ECC_MODE; + glb_setup.cfg.b.active = 1; + + // from efuse + glb_setup.cfg.b.no_rb = 1; //defaut + //glb_setup.cfg.b.sync_mode = efuse->tg_nd_bm_e ? 2 : 0; + glb_setup.cfg.b.sync_mode = 0; //fixme, + glb_setup.cfg.b.size = 0; + NFIO_LINE + // get pin + nfio_pin_mux(); + + // set clk to 24MHz + (*P_CLK_CNTL) = ( 1<< 31 | 1<<28 | 1 << 21 | 2 << 8 | 1); + + // nand cfg register: + // sync[11:10] : 0:aync, 1:micron(started from sync, don't need to set), + // 2: samsung/toshiba toggle, need to set when read. + // Nand cycle = 200ns, timing at 3rd clock. + (*P_NAND_CFG) = + 4 | (3<<5) // Please see main.c for detailed timing info + |(glb_setup.cfg.b.sync_mode<<10) // async mode + |(0<<12) // disable cmd_start + |(0<<13) // disable cmd_auto + |(0<<14) // disable apb_mode + |(1<<31);// disable NAND bus gated clock. + + if (e_cfg[6] & (1 << 5)) + (*P_NAND_CFG) = (*P_NAND_CFG) |(1<<17); // enable encrypt mode. + + // reset + ret = nfio_reset(); + if (ret) return ret; + NFIO_LINE + //read ID + glb_setup.id = _read_id(); + //printf("MID, %x\n", glb_setup.id); + // set retry parameter. + _set_retry(glb_setup.id); + NFIO_LINE + + //_dump_mem_u8((uint8_t *)page0, 384); + /* fixme, use the memory filled by romboot nfdrv.*/ + ret = nfio_read(0, NAND_PAGE0_BUF, 384); + if (ret == ERROR_NAND_ECC) { + if (glb_setup.id == NAND_MFR_SANDISK) { + glb_setup.cfg.b.a2 = 1; + glb_setup.max = 0; + ret = nfio_read(0, NAND_PAGE0_BUF, 384); + } + else if (glb_setup.cfg.b.sync_mode == 0 && (glb_setup.id == NAND_MFR_TOSHIBA || + glb_setup.id == NAND_MFR_SAMSUNG)) { + glb_setup.cfg.b.sync_mode = 2; + (*P_NAND_CFG) |= (glb_setup.cfg.b.sync_mode<<10); + *P_PAD_PULL_UP_REG2 &= ~(1<<15); + ret = nfio_read(0, NAND_PAGE0_BUF, 384); + } + } + // override + glb_setup.cfg.d32 = nand_setup->cfg.d32; //get cfg! + glb_setup.id = nand_setup->id; + glb_setup.max = nand_setup->max; + glb_setup.cfg.b.size = 0; // efuse size + + glb_ext_info.new_type = p_ext_info->new_type; + glb_ext_info.page_per_blk = p_ext_info->page_per_blk; + + //printf("cfg %x, new %x, pages %x\n", glb_setup.cfg.d32, glb_ext_info.new_type, glb_ext_info.page_per_blk); + NFIO_LINE + + return ret; +} + +/* + *interface for spl. + * + * src, offset bytes in storage + * dst, ram address + * size, reada bytes count. + **/ +uint32_t nf_read(uint32_t boot_device, uint32_t src, uint32_t des, uint32_t size) +{ + uint32_t _page_size, _page, _cnt; + uint32_t ecc_mode, ecc_pages; + uint32_t ret = 0; + + ecc_mode = glb_setup.cfg.b.cmd>>14&7; + ecc_pages = glb_setup.cfg.b.cmd&0x3f; + _page_size = (ecc_mode < 2 ? 64 : 128) * 8 * ecc_pages; + //printf("ecc_mode %d, ecc_pages %d, pagesize %d\n", ecc_mode, ecc_pages, _page_size); + if (src % SRC_ALIGN_SIZE) { + //PRINT("%s(), unaligned src 0x%08x\n", __func__, src); + ret = ERROR_NAND_UNALIGN_SRC; + goto _out; + } + NFIO_LINE + _page = src / _page_size; + _cnt = size; + ret = nfio_read(_page + 1, des, _cnt); /*skip page0 */ + // des64 = (uint64_t) des; + // _dump_mem_u8((uint8_t *)des64, size); +_out: + return ret; +} + + + + + diff --git a/plat/gxb/plat-tsp.ld.S b/plat/gxb/plat-tsp.ld.S new file mode 100644 index 0000000..16d6c17 --- /dev/null +++ b/plat/gxb/plat-tsp.ld.S @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + ASSERT(__BL32_END__ <= BL2_BASE, "BL3-2 image overlaps BL2 image.") diff --git a/plat/gxb/plat_def.h b/plat/gxb/plat_def.h new file mode 100644 index 0000000..13f0fdf --- /dev/null +++ b/plat/gxb/plat_def.h @@ -0,0 +1,198 @@ +/* + * 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 __PLAT_DEF_H__ +#define __PLAT_DEF_H__ + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define PLAT_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +/******************************************************************************* + * ${PLAT} 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 + +#define SPI_BASE 0xCC000000 +#define SPI_SIZE 0x00400000 + +#define MAILBOX_START 0xd9013000 +#define MAILBOX_SIZE 0x00001000 + +/* Following covers Columbus Peripherals excluding NSROM and NSRAM */ +#define DEVICE0_BASE 0x20000000 +#define DEVICE0_SIZE 0x0e000000 +#define MHU_BASE 0x2b1f0000 + +#define DEVICEC_BASE 0xC0000000 +#define DEVICEC_SIZE 0x0C000000 + +#define DEVICED_BASE 0xDA100000 +#define DEVICED_SIZE 0x02000000 + +#define DEVICEE_BASE 0xD0000000 +#define DEVICEE_SIZE 0x01000000 + +#define NSRAM_BASE 0x2e000000 +#define NSRAM_SIZE 0x00008000 + +/* Following covers ${PLAT} Peripherals and PCIe expansion area */ +#define DEVICE1_BASE 0x40000000 +#define DEVICE1_SIZE 0x40000000 +#define PCIE_CONTROL_BASE 0x7ff20000 + +//#define DRAM_ROM_SPACE 0x01000000 /*16MB*/ +#define DRAM_BASE 0x01000000 +#define DRAM_SIZE 0x7f000000 + +/* 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 + +/******************************************************************************* + * 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 + +#endif /* __FVP_DEF_H__ */ diff --git a/plat/gxb/plat_gic.c b/plat/gxb/plat_gic.c new file mode 100644 index 0000000..874077c --- /dev/null +++ b/plat/gxb/plat_gic.c @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <arch_helpers.h> +#include <assert.h> +#include <bl_common.h> +#include <gic_v2.h> +#include <interrupt_mgmt.h> +#include <platform.h> +#include "plat_def.h" +#include "plat_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(security_state == NON_SECURE || security_state == SECURE); + + /* + * We ignore the security state parameter because ${PLAT} is GICv2 only + * so both normal and secure worlds are using ARM GICv2. + */ + return gicv2_interrupt_type_to_line(GICC_BASE, type); +} + +/******************************************************************************* + * This function returns the type of the highest priority pending interrupt at + * the GIC cpu interface. INTR_TYPE_INVAL is returned when there is no + * interrupt pending. + ******************************************************************************/ +uint32_t plat_ic_get_pending_interrupt_type(void) +{ + uint32_t id; + + id = gicc_read_hppir(GICC_BASE); + + /* Assume that all secure interrupts are S-EL1 interrupts */ + if (id < 1022) + return INTR_TYPE_S_EL1; + + if (id == GIC_SPURIOUS_INTERRUPT) + return INTR_TYPE_INVAL; + + return INTR_TYPE_NS; +} + +/******************************************************************************* + * This function returns the id of the highest priority pending interrupt at + * the GIC cpu interface. INTR_ID_UNAVAILABLE is returned when there is no + * interrupt pending. + ******************************************************************************/ +uint32_t plat_ic_get_pending_interrupt_id(void) +{ + uint32_t id; + + id = gicc_read_hppir(GICC_BASE); + + if (id < 1022) + return id; + + if (id == 1023) + return INTR_ID_UNAVAILABLE; + + /* + * Find out which non-secure interrupt it is under the assumption that + * the GICC_CTLR.AckCtl bit is 0. + */ + return gicc_read_ahppir(GICC_BASE); +} + +/******************************************************************************* + * This functions reads the GIC cpu interface Interrupt Acknowledge register + * to start handling the pending interrupt. It returns the contents of the IAR. + ******************************************************************************/ +uint32_t plat_ic_acknowledge_interrupt(void) +{ + return gicc_read_IAR(GICC_BASE); +} + +/******************************************************************************* + * This functions writes the GIC cpu interface End Of Interrupt register with + * the passed value to finish handling the active interrupt + ******************************************************************************/ +void plat_ic_end_of_interrupt(uint32_t id) +{ + gicc_write_EOIR(GICC_BASE, id); +} + +/******************************************************************************* + * This function returns the type of the interrupt id depending upon the group + * this interrupt has been configured under by the interrupt controller i.e. + * group0 or group1. + ******************************************************************************/ +uint32_t plat_ic_get_interrupt_type(uint32_t id) +{ + uint32_t group; + + group = gicd_get_igroupr(GICD_BASE, id); + + /* Assume that all secure interrupts are S-EL1 interrupts */ + if (group == GRP0) + return INTR_TYPE_S_EL1; + else + return INTR_TYPE_NS; +} diff --git a/plat/gxb/plat_init.c b/plat/gxb/plat_init.c new file mode 100644 index 0000000..a19e1f7 --- /dev/null +++ b/plat/gxb/plat_init.c @@ -0,0 +1,44 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/plat_init.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <io.h> +#include <stdio.h> +#include <stdint.h> +#include <timer.h> +#include <asm/arch/secure_apb.h> + +void pinmux_init(void) { + //detect sdio debug board + unsigned pinmux_2 = readl(P_PERIPHS_PIN_MUX_2); + // clear sdio pinmux + setbits_le32(P_PREG_PAD_GPIO2_O,0x3f<<20); + setbits_le32(P_PREG_PAD_GPIO2_EN_N,0x3f<<20); + clrbits_le32(P_PERIPHS_PIN_MUX_2,7<<12); //clear sd d1~d3 pinmux + if (!(readl(P_PREG_PAD_GPIO2_I)&(1<<24))) { //sd_d3 low, debug board in + clrbits_le32(P_AO_RTI_PIN_MUX_REG,3<<11); //clear AO uart pinmux + setbits_le32(P_PERIPHS_PIN_MUX_8,3<<9); + serial_puts("\nsdio debug board detected "); + } + else{ + writel(pinmux_2,P_PERIPHS_PIN_MUX_2); + serial_puts("\nno sdio debug board detected "); + } +}
\ No newline at end of file diff --git a/plat/gxb/plat_io_storage.c b/plat/gxb/plat_io_storage.c new file mode 100644 index 0000000..b1b0532 --- /dev/null +++ b/plat/gxb/plat_io_storage.c @@ -0,0 +1,203 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/plat_io_storage.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <assert.h> +#include <string.h> +#include <platform.h> +#include <io_storage.h> +#include <io_driver.h> +#include <semihosting.h> /* For FOPEN_MODE_... */ +#include <io_fip.h> +#include <io_memmap.h> +#include <debug.h> +#include "plat_def.h" + +/* IO devices */ +static io_plat_data_t io_data; +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 bl32_file_spec = { + .path = BL32_IMAGE_NAME, + .mode = FOPEN_MODE_RB +}; + +static const io_file_spec_t bl33_file_spec = { + .path = BL33_IMAGE_NAME, + .mode = FOPEN_MODE_RB +}; + +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 + }, { + BL32_IMAGE_NAME, + &fip_dev_handle, + (uintptr_t)&bl32_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; + + /* Initialise the IO layer */ + io_init(&io_data); + + /* Register the IO devices on this platform */ + io_result = register_io_dev_fip(&fip_dev_con); + assert(io_result == IO_SUCCESS); + + io_result = register_io_dev_memmap(&memmap_dev_con); + assert(io_result == IO_SUCCESS); + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(fip_dev_con, fip_dev_spec, &fip_dev_handle); + assert(io_result == IO_SUCCESS); + + io_result = io_dev_open(memmap_dev_con, memmap_dev_spec, + &memmap_dev_handle); + assert(io_result == IO_SUCCESS); + + /* Ignore improbable errors in release builds */ + (void)io_result; +} + + +/* Return an IO device handle and specification which can be used to access + * an image. Use this to enforce platform load policy */ +int plat_get_image_source(const char *image_name, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result = IO_FAIL; + const struct plat_io_policy *policy; + + if ((image_name != NULL) && (dev_handle != NULL) && + (image_spec != NULL)) { + policy = policies; + while (policy->image_name != NULL) { + if (strcmp(policy->image_name, image_name) == 0) { + result = policy->check(policy->image_spec); + if (result == IO_SUCCESS) { + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + break; + } + } + policy++; + } + } else { + result = IO_FAIL; + } + return result; +} diff --git a/plat/gxb/plat_pm.c b/plat/gxb/plat_pm.c new file mode 100644 index 0000000..c3248eb --- /dev/null +++ b/plat/gxb/plat_pm.c @@ -0,0 +1,271 @@ +/* + * 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 <platform.h> +#include <platform_def.h> +#include <psci.h> +#include "plat_def.h" +#include "plat_private.h" +#include "scpi.h" + +typedef struct { + /* Align the suspend level to allow per-cpu lockless access */ + uint32_t state[MPIDR_MAX_AFFLVL] __aligned(CACHE_WRITEBACK_GRANULE); +} scp_pstate; + +static scp_pstate target_pstate[PLATFORM_CORE_COUNT]; + +int pm_on(unsigned long mpidr, + unsigned long sec_entrypoint, + unsigned long ns_entrypoint, + unsigned int afflvl, + unsigned int 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 + */ + unsigned long *mbox = (unsigned long *)(unsigned long)( + TRUSTED_MAILBOXES_BASE + + (platform_get_core_pos(mpidr) << TRUSTED_MAILBOX_SHIFT) + ); + *mbox = sec_entrypoint; + flush_dcache_range((unsigned long)mbox, sizeof(*mbox)); + + scpi_set_css_power_state(mpidr, scpi_power_on, scpi_power_on, + scpi_power_on); + + return PSCI_E_SUCCESS; +} + +int pm_on_finish(unsigned long mpidr, unsigned int afflvl, unsigned int state) +{ + switch (afflvl) { + + case MPIDR_AFFLVL1: + /* Enable coherency if this cluster was off */ + if (state == PSCI_STATE_OFF) + cci_enable_coherency(mpidr); + break; + + case MPIDR_AFFLVL0: + /* + * Ignore the state passed for a cpu. It could only have + * been off if we are here. + */ + + /* Turn on intra-cluster coherency. */ + write_cpuectlr(read_cpuectlr() | CPUECTLR_SMP_BIT); + + /* Enable the gic cpu interface */ + gic_cpuif_setup(GICC_BASE); + /* ${PLAT} todo: Is this setup only needed after a cold boot? */ + gic_pcpu_distif_setup(GICD_BASE); + + /* + * Clear the mailbox for each cpu + */ + unsigned long *mbox = (unsigned long *)(unsigned long)( + TRUSTED_MAILBOXES_BASE + + (platform_get_core_pos(mpidr) << TRUSTED_MAILBOX_SHIFT) + ); + *mbox = 0; + flush_dcache_range((unsigned long)mbox, sizeof(*mbox)); + + break; + } + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Common function called while turning a cpu off or suspending it. It is called + * for each affinity level until the target affinity level. It keeps track of + * the power state that needs to be programmed through the SCP firmware for each + * affinity level. Once the target affinity level is reached it uses the MHU + * channel to ask the SCP to perform the power operations for each affinity + * level accumulated so far. + * + * CAUTION: This function is called with coherent stacks so that caches can be + * turned off, flushed and coherency disabled. There is no guarantee that caches + * will remain turned on across calls to this function as each affinity level is + * dealt with. So do not write & read global variables across calls. It will be + * wise to do flush a write to the global to prevent unpredictable results. + ******************************************************************************/ +static int plat_power_down_common(unsigned long mpidr, + unsigned int linear_id, + unsigned int cur_afflvl, + unsigned int tgt_afflvl, + unsigned int state) +{ + /* Record which power state this affinity level is supposed to enter */ + if (state == PSCI_STATE_OFF) { + target_pstate[linear_id].state[cur_afflvl] = scpi_power_off; + } else { + assert(cur_afflvl != MPIDR_AFFLVL0); + target_pstate[linear_id].state[cur_afflvl] = scpi_power_on; + goto exit; + } + + switch (cur_afflvl) { + case MPIDR_AFFLVL1: + /* Cluster is to be turned off, so disable coherency */ + cci_disable_coherency(mpidr); + + break; + + case MPIDR_AFFLVL0: + /* Turn off intra-cluster coherency */ + write_cpuectlr(read_cpuectlr() & ~CPUECTLR_SMP_BIT); + + /* Prevent interrupts from spuriously waking up this cpu */ + gic_cpuif_deactivate(GICC_BASE); + + break; + } + +exit: + /* + * If this is the target affinity level then we need to ask the SCP + * to power down the appropriate components depending upon their state + */ + if (cur_afflvl == tgt_afflvl) { + scpi_set_css_power_state(mpidr, + target_pstate[linear_id].state[MPIDR_AFFLVL0], + target_pstate[linear_id].state[MPIDR_AFFLVL1], + scpi_power_on); + + /* Reset the states */ + target_pstate[linear_id].state[MPIDR_AFFLVL0] = scpi_power_on; + target_pstate[linear_id].state[MPIDR_AFFLVL1] = scpi_power_on; + } + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Handler called when an affinity instance is about to be turned off. The + * level and mpidr determine the affinity instance. The 'state' arg. allows the + * platform to decide whether the cluster is being turned off and take apt + * actions. + * + * CAUTION: This function is called with coherent stacks so that caches can be + * turned off, flushed and coherency disabled. There is no guarantee that caches + * will remain turned on across calls to this function as each affinity level is + * dealt with. So do not write & read global variables across calls. It will be + * wise to do flush a write to the global to prevent unpredictable results. + ******************************************************************************/ +int pm_off(unsigned long mpidr, unsigned int afflvl, unsigned int state) +{ + return plat_power_down_common(mpidr, + platform_get_core_pos(mpidr), + afflvl, + plat_get_max_afflvl(), + state); +} + +/******************************************************************************* + * Handler called when an affinity instance is about to be suspended. The + * level and mpidr determine the affinity instance. The 'state' arg. allows the + * platform to decide whether the cluster is being turned off and take apt + * actions. The 'sec_entrypoint' determines the address in BL3-1 from where + * execution should resume. + * + * CAUTION: This function is called with coherent stacks so that caches can be + * turned off, flushed and coherency disabled. There is no guarantee that caches + * will remain turned on across calls to this function as each affinity level is + * dealt with. So do not write & read global variables across calls. It will be + * wise to do flush a write to the global to prevent unpredictable results. + ******************************************************************************/ +int pm_suspend(unsigned long mpidr, + unsigned long sec_entrypoint, + unsigned long ns_entrypoint, + unsigned int afflvl, + unsigned int state) +{ + uint32_t tgt_afflvl; + + tgt_afflvl = psci_get_suspend_afflvl(mpidr); + assert(tgt_afflvl != PSCI_INVALID_DATA); + + /* + * Setup mailbox with address for CPU entrypoint when it next powers up + */ + if (afflvl == MPIDR_AFFLVL0) { + unsigned long *mbox = (unsigned long *)(unsigned long)( + TRUSTED_MAILBOXES_BASE + + (platform_get_core_pos(mpidr) << TRUSTED_MAILBOX_SHIFT) + ); + *mbox = sec_entrypoint; + flush_dcache_range((unsigned long)mbox, sizeof(*mbox)); + } + + return plat_power_down_common(mpidr, + platform_get_core_pos(mpidr), + afflvl, + tgt_afflvl, + state); +} + +int pm_suspend_finish(unsigned long mpidr, + unsigned int afflvl, + unsigned int state) +{ + return pm_on_finish(mpidr, afflvl, state); +} + +/******************************************************************************* + * Export the platform handlers to enable psci to invoke them + ******************************************************************************/ +static const plat_pm_ops_t pm_ops = { + .affinst_on = pm_on, + .affinst_on_finish = pm_on_finish, + .affinst_off = pm_off, + .affinst_suspend = pm_suspend, + .affinst_suspend_finish = pm_suspend_finish +}; + +/******************************************************************************* + * Export the platform specific power ops & initialize the fvp power controller + ******************************************************************************/ +int platform_setup_pm(const plat_pm_ops_t **plat_ops) +{ + *plat_ops = &pm_ops; + return 0; +} diff --git a/plat/gxb/plat_private.h b/plat/gxb/plat_private.h new file mode 100644 index 0000000..ec552e7 --- /dev/null +++ b/plat/gxb/plat_private.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __PLAT_PRIVATE_H__ +#define __PLAT_PRIVATE_H__ + +#include <bl_common.h> +#include <stdint.h> +#include <platform_def.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 ${PLAT} 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 ${PLAT} 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 ${PLAT} 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 ${PLAT} 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 /* __PLAT_PRIVATE_H__ */ diff --git a/plat/gxb/plat_topology.c b/plat/gxb/plat_topology.c new file mode 100644 index 0000000..b4b3711 --- /dev/null +++ b/plat/gxb/plat_topology.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <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() +{ + /* ${PLAT} todo: Make topology configurable via SCC */ + return 0; +} diff --git a/plat/gxb/platform.mk b/plat/gxb/platform.mk new file mode 100644 index 0000000..8caffd4 --- /dev/null +++ b/plat/gxb/platform.mk @@ -0,0 +1,97 @@ +# +# 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/${PLAT}/include/ + +PLAT_BL_COMMON_SOURCES := drivers/arm/serial/serial.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + lib/mmio.c \ + lib/aarch64/sysreg_helpers.S \ + plat/common/aarch64/plat_common.c \ + plat/${PLAT}/plat_io_storage.c + +BL1_SOURCES += drivers/arm/cci400/cci400.c \ + plat/common/aarch64/platform_up_stack.S \ + plat/${PLAT}/bl1_plat_setup.c \ + plat/${PLAT}/aarch64/bl1_plat_helpers.S \ + plat/${PLAT}/aarch64/plat_helpers.S \ + plat/${PLAT}/aarch64/common.c + +BL2_SOURCES += lib/locks/bakery/bakery_lock.c \ + plat/common/aarch64/platform_up_stack.S \ + plat/${PLAT}/bl2_plat_setup.c \ + plat/${PLAT}/mhu.c \ + plat/${PLAT}/aarch64/plat_helpers.S \ + plat/${PLAT}/aarch64/cache.S \ + plat/${PLAT}/aarch64/common.c \ + plat/${PLAT}/scp_bootloader.c \ + plat/${PLAT}/scpi.c \ + plat/${PLAT}/storage.c \ + plat/${PLAT}/sha2.c \ + plat/${PLAT}/mailbox.c \ + plat/${PLAT}/watchdog.c \ + plat/${PLAT}/efuse.c \ + plat/${PLAT}/pll.c \ + plat/${PLAT}/power_init.c \ + plat/${PLAT}/saradc.c \ + plat/${PLAT}/timer.c \ + plat/${PLAT}/crypto/secureboot.c \ + plat/${PLAT}/ddr/ddr.c \ + plat/${PLAT}/plat_init.c \ + plat/${PLAT}/crypto/ndma_utils.c + +BL31_SOURCES += drivers/arm/cci400/cci400.c \ + drivers/arm/gic/gic_v2.c \ + plat/common/aarch64/platform_mp_stack.S \ + plat/${PLAT}/bl31_plat_setup.c \ + plat/${PLAT}/mhu.c \ + plat/${PLAT}/aarch64/plat_helpers.S \ + plat/${PLAT}/aarch64/common.c \ + plat/${PLAT}/plat_pm.c \ + plat/${PLAT}/plat_topology.c \ + plat/${PLAT}/plat_gic.c \ + plat/${PLAT}/scpi.c \ + plat/${PLAT}/smc_arm.c + +ifeq ($(CONFIG_AML_SECURE_UBOOT),y) + BL2_SOURCES += plat/${PLAT}/crypto/rsa.c \ + plat/${PLAT}/crypto/bignum.c +endif + +ifeq ($(CONFIG_AML_NAND),y) + BL2_SOURCES += plat/${PLAT}/nand.c +endif + + +ifneq (${RESET_TO_BL31},0) + $(error "Using BL3-1 as the reset vector is not supported on PLAT. \ + Please set RESET_TO_BL31 to 0.") +endif diff --git a/plat/gxb/pll.c b/plat/gxb/pll.c new file mode 100644 index 0000000..5dd5bb8 --- /dev/null +++ b/plat/gxb/pll.c @@ -0,0 +1,271 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/pll.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <pll.h> +#include <string.h> +#include <asm/arch/watchdog.h> +#include <stdio.h> +#include <asm/arch/secure_apb.h> +#include <timer.h> +#include <stdio.h> +#include <asm/arch/timing.h> + +unsigned lock_check_loop = 0; +extern pll_set_t __pll_setting; +static pll_set_t * p_pll_set = &__pll_setting; + +unsigned int pll_init(void){ + // Switch clk81 to the oscillator input + // romcode might have already programmed clk81 to a PLL + Wr( HHI_MPEG_CLK_CNTL, Rd(HHI_MPEG_CLK_CNTL) & ~(1 << 8) ); + // Switch sys clk to oscillator, the SYS CPU might have already been programmed + clocks_set_sys_cpu_clk( 0, 0, 0, 0); + + //SYS PLL,FIX PLL bangap + Wr(HHI_MPLL_CNTL6, Rd(HHI_MPLL_CNTL6)|(1<<26)); + _udelay(100); + + unsigned int sys_pll_cntl = 0; + if ((p_pll_set->cpu_clk >= 600) && (p_pll_set->cpu_clk <= 1200)) { + sys_pll_cntl = (1<<16/*OD*/) | (1<<9/*N*/) | (p_pll_set->cpu_clk / 12/*M*/); + } + else if ((p_pll_set->cpu_clk > 1200) && (p_pll_set->cpu_clk <= 2000)) { + sys_pll_cntl = (0<<16/*OD*/) | (1<<9/*N*/) | (p_pll_set->cpu_clk / 24/*M*/); + } + //Init SYS pll + do { + Wr(HHI_SYS_PLL_CNTL, Rd(HHI_SYS_PLL_CNTL)|(1<<29)); + Wr(HHI_SYS_PLL_CNTL2, CFG_SYS_PLL_CNTL_2); + Wr(HHI_SYS_PLL_CNTL3, CFG_SYS_PLL_CNTL_3); + Wr(HHI_SYS_PLL_CNTL4, CFG_SYS_PLL_CNTL_4); + Wr(HHI_SYS_PLL_CNTL5, CFG_SYS_PLL_CNTL_5); + Wr(HHI_SYS_PLL_CNTL, ((1<<30)|(1<<29)|sys_pll_cntl)); // A9 clock + Wr(HHI_SYS_PLL_CNTL, Rd(HHI_SYS_PLL_CNTL)&(~(1<<29))); + _udelay(20); + } while(pll_lock_check(HHI_SYS_PLL_CNTL, "SYS PLL")); + clocks_set_sys_cpu_clk( 1, 0, 0, 0); // Connect SYS CPU to the PLL divider output + + sys_pll_cntl = Rd(HHI_SYS_PLL_CNTL); + unsigned cpu_clk = (24/ \ + ((sys_pll_cntl>>9)&0x1F)* \ + (sys_pll_cntl&0x1FF)/ \ + (1<<((sys_pll_cntl>>16)&0x3))); + /* cpu clk = 24/N*M/2^OD */ + serial_puts("CPU clk: "); + serial_put_dec(cpu_clk); + serial_puts("MHz\n"); + + //FIXED PLL + Wr(HHI_MPLL_CNTL4, CFG_MPLL_CNTL_4); + Wr(HHI_MPLL_CNTL, Rd(HHI_MPLL_CNTL)|(1<<29)); + _udelay(200); + Wr(HHI_MPLL_CNTL2, CFG_MPLL_CNTL_2); + Wr(HHI_MPLL_CNTL3, CFG_MPLL_CNTL_3); + //Wr(HHI_MPLL_CNTL4, CFG_MPLL_CNTL_4); + Wr(HHI_MPLL_CNTL5, CFG_MPLL_CNTL_5); + Wr(HHI_MPLL_CNTL6, CFG_MPLL_CNTL_6); + Wr(HHI_MPLL_CNTL, ((1 << 30) | (1<<29) | (3 << 9) | (250 << 0)) ); + Wr(HHI_MPLL_CNTL, Rd(HHI_MPLL_CNTL)&(~(1<<29))); //set reset bit to 0 + _udelay(800); + Wr(HHI_MPLL_CNTL4, Rd(HHI_MPLL_CNTL4)|(1<<14)); + do { + if ((Rd(HHI_MPLL_CNTL)&(1<<31)) != 0) + break; + Wr(HHI_MPLL_CNTL,Rd(HHI_MPLL_CNTL) | (1<<29)); + _udelay(1000); + Wr(HHI_MPLL_CNTL, Rd(HHI_MPLL_CNTL)&(~(1<<29))); + _udelay(1000); + }while(pll_lock_check(HHI_MPLL_CNTL, "FIX PLL")); + + // Enable the separate fclk_div2 and fclk_div3 + // .MPLL_CLK_OUT_DIV2_EN ( hi_mpll_cntl10[7:0] ), + // .MPLL_CLK_OUT_DIV3_EN ( hi_mpll_cntl10[11:8] ), + Wr( HHI_MPLL_CNTL10, (0xFFF << 16) ); + + // ------------------------------- + // Set Multi-Phase PLL0 = 350Mhz + // ------------------------------- + Wr( HHI_MPLL_CNTL7, ((7 << 16) | (1 << 15) | (1 << 14) | (4681 << 0)) ); + + // ------------------------- + // set CLK81 to 166.6Mhz Fixed + // ------------------------- + Wr( HHI_MPEG_CLK_CNTL, ((Rd(HHI_MPEG_CLK_CNTL) & (~((0x7 << 12) | (1 << 7) | (0x7F << 0)))) | ((5 << 12) | (1 << 7) | (2 << 0))) ); + // Connect clk81 to the PLL divider output + Wr( HHI_MPEG_CLK_CNTL, Rd(HHI_MPEG_CLK_CNTL) | (1 << 8) ); + + // ------------------------------- + // Set Multi-Phase PLL1 = 442.368 Mhz + // ------------------------------- + // +----------------------------------------+ + // | <<< Clock Reset Test >>> | + // +-------------------------------------+ +------+-----------+---------------------+ +------------ + // | Multi-Phase PLL | | CRT | Final | Ideal | | HIU Reg + // | FIn | N2 SDM_IN | CLKMP | | XD | Clock | Error Clock | | 0x10a7 + // +---------+--------------+------------| |------+-----------+---------------------+ +------------ + // | 24.0000 | 5 12524 | 442.3701 | | 1 | 442.3701 | 0.000% ( 442.368) | | 0x0005f0ec + // .MPLL_SDM_IN1 ( hi_mpll_cntl8[13:0] ), + // .MPLL_CH1_EN ( hi_mpll_cntl8[14] ), + // .MPLL_SDM_EN1 ( hi_mpll_cntl8[15] ), + // .MPLL_N_IN1 ( hi_mpll_cntl8[22:16] ), + // .MPLL_I160CTR1 ( hi_mpll_cntl8[25:24] ), + // .MPLL_R_SW1 ( hi_mpll_cntl8[27:26] ), + Wr( HHI_MPLL_CNTL8, ((5 << 16) | (1 << 15) | (1 << 14) | (12524 << 0)) ); + + return 0; +} + +// -------------------------------------------------- +// clocks_set_sys_cpu_clk +// -------------------------------------------------- +// This function sets the System CPU clock muxing and the +// sub-clocks related to the System CPU (AXI, PCLK,...) +// +// Parameters: +// freq: +// 0: 24Mhz Crystal +// 1: System PLL +// 1275, 850, 637,.... +// pclk_ratio: 0 = no change to the existing setting. 2,3,...8 = the clock ratio relative to the system CPU clock +// aclkm_ratio: 0 = no change to the existing setting. 2,3,...8 = the clock ratio relative to the system CPU clock +// atclk_ratio: 0 = no change to the existing setting. 2,3,...8 = the clock ratio relative to the system CPU clock +// -------------------------------- +// freq = 0: 24Mhz Crystal +// freq = 1: System PLL +// freq = 1000, 667, 500, 333, 250... +// Pass 0 to pclk_ratio or aclkm_ratio or atclk_ratio if nothing changes +void clocks_set_sys_cpu_clk(uint32_t freq, uint32_t pclk_ratio, uint32_t aclkm_ratio, uint32_t atclk_ratio ) +{ + uint32_t control = 0; + uint32_t dyn_pre_mux = 0; + uint32_t dyn_post_mux = 0; + uint32_t dyn_div = 0; + + // Make sure not busy from last setting and we currently match the last setting + do { + control = Rd(HHI_SYS_CPU_CLK_CNTL); + } while( (control & (1 << 28)) ); + + control = control | (1 << 26); // Enable + + // Switching to System PLL...just change the final mux + if ( freq == 1 ) { + // wire cntl_final_mux_sel = control[11]; + control = control | (1 << 11); + } else { + switch ( freq ) { + case 0: // If Crystal + dyn_pre_mux = 0; + dyn_post_mux = 0; + dyn_div = 0; // divide by 1 + break; + case 1000: // fclk_div2 + dyn_pre_mux = 1; + dyn_post_mux = 0; + dyn_div = 0; // divide by 1 + break; + case 667: // fclk_div3 + dyn_pre_mux = 2; + dyn_post_mux = 0; + dyn_div = 0; // divide by 1 + break; + case 500: // fclk_div2/2 + dyn_pre_mux = 1; + dyn_post_mux = 1; + dyn_div = 1; // Divide by 2 + break; + case 333: // fclk_div3/2 + dyn_pre_mux = 2; + dyn_post_mux = 1; + dyn_div = 1; // divide by 2 + break; + case 250: // fclk_div2/4 + dyn_pre_mux = 1; + dyn_post_mux = 1; + dyn_div = 3; // divide by 4 + break; + } + if ( control & (1 << 10) ) { // if using Dyn mux1, set dyn mux 0 + // Toggle bit[10] indicating a dynamic mux change + control = (control & ~((1 << 10) | (0x3f << 4) | (1 << 2) | (0x3 << 0))) + | ((0 << 10) + | (dyn_div << 4) + | (dyn_post_mux << 2) + | (dyn_pre_mux << 0)); + } else { + // Toggle bit[10] indicating a dynamic mux change + control = (control & ~((1 << 10) | (0x3f << 20) | (1 << 18) | (0x3 << 16))) + | ((1 << 10) + | (dyn_div << 20) + | (dyn_post_mux << 18) + | (dyn_pre_mux << 16)); + } + // Select Dynamic mux + control = control & ~(1 << 11); + } + Wr(HHI_SYS_CPU_CLK_CNTL,control); + // + // Now set the divided clocks related to the System CPU + // + // This function changes the clock ratios for the + // PCLK, ACLKM (AXI) and ATCLK + // .clk_clken0_i ( {clk_div2_en,clk_div2} ), + // .clk_clken1_i ( {clk_div3_en,clk_div3} ), + // .clk_clken2_i ( {clk_div4_en,clk_div4} ), + // .clk_clken3_i ( {clk_div5_en,clk_div5} ), + // .clk_clken4_i ( {clk_div6_en,clk_div6} ), + // .clk_clken5_i ( {clk_div7_en,clk_div7} ), + // .clk_clken6_i ( {clk_div8_en,clk_div8} ), + + uint32_t control1 = Rd(HHI_SYS_CPU_CLK_CNTL1); + + // .cntl_PCLK_mux ( hi_sys_cpu_clk_cntl1[5:3] ), + if ( (pclk_ratio >= 2) && (pclk_ratio <= 8) ) { control1 = (control1 & ~(0x7 << 3)) | ((pclk_ratio-2) << 3) ; } + // .cntl_ACLKM_clk_mux ( hi_sys_cpu_clk_cntl1[11:9] ), // AXI matrix + if ( (aclkm_ratio >= 2) && (aclkm_ratio <= 8) ) { control1 = (control1 & ~(0x7 << 9)) | ((aclkm_ratio-2) << 9) ; } + // .cntl_ATCLK_clk_mux ( hi_sys_cpu_clk_cntl1[8:6] ), + if ( (atclk_ratio >= 2) && (atclk_ratio <= 8) ) { control1 = (control1 & ~(0x7 << 6)) | ((atclk_ratio-2) << 6) ; } + Wr( HHI_SYS_CPU_CLK_CNTL1, control1 ); +} + +unsigned pll_lock_check(unsigned long pll_reg, const char *pll_name){ + /*locked: return 0, else return 1*/ + unsigned lock = ((Rd(pll_reg) >> PLL_LOCK_BIT_OFFSET) & 0x1); + if (lock) { + lock_check_loop = 0; + //serial_puts(pll_name); + //serial_puts("" lock ok!\n"); + } + else{ + lock_check_loop++; + serial_puts(pll_name); + serial_puts(" lock check "); + serial_put_dec(lock_check_loop); + serial_puts("\n"); + if (lock_check_loop >= PLL_lOCK_CHECK_LOOP) { + serial_puts(pll_name); + serial_puts(" lock failed! reset...\n"); + reset_system(); + while (1) ; + } + } + return !lock; +}
\ No newline at end of file diff --git a/plat/gxb/power_init.c b/plat/gxb/power_init.c new file mode 100644 index 0000000..2098361 --- /dev/null +++ b/plat/gxb/power_init.c @@ -0,0 +1,16 @@ + +#ifdef CONFIG_PLATFORM_POWER_INIT +#include "power.c" +#else +void __attribute__((weak)) power_init(int mode) +{ + /* + * fake function for platform without power init + */ +} +#endif + +void platform_power_init(int mode) +{ + power_init(mode); +} diff --git a/plat/gxb/saradc.c b/plat/gxb/saradc.c new file mode 100644 index 0000000..1e5bfd3 --- /dev/null +++ b/plat/gxb/saradc.c @@ -0,0 +1,73 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/saradc.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <string.h> +#include <stdio.h> +#include <saradc.h> +#include <asm/arch/secure_apb.h> +#include <timer.h> + +#define SAMP_COUNT 9 +const unsigned int sam_val[SAMP_COUNT] = {0, 0x80, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, 0x400}; + +unsigned int saradc_ch1_get(void) +{ + unsigned int val = 0; + unsigned int cnt=0; + unsigned int idx=0; + + Wr(P_SAR_ADC_CHAN_LIST, 0x00000001); // + Wr(P_SAR_ADC_AVG_CNTL, 0x00003000); + Wr(P_SAR_ADC_REG3, 0xc3a8500a); + Wr(P_SAR_ADC_DELAY, 0x010a000a); + Wr(P_SAR_ADC_AUX_SW, 0x03eb1a0c); + Wr(P_SAR_ADC_CHAN_10_SW, 0x008c000c); + Wr(P_SAR_ADC_DETECT_IDLE_SW, 0x008e038c); + Wr(P_SAR_ADC_DELTA_11, 0x0c00c400); + Wr(P_SAR_ADC_CLOCK, 0x00000114); + Wr(P_SAR_ADC_TEMP_SES, 0x00002000); + Wr(P_SAR_SAR_ADC_REG0, 0x84064040); + _udelay(20); + Wr(P_SAR_SAR_ADC_REG0, 0x84064041); + _udelay(20); + Wr(P_SAR_SAR_ADC_REG0, 0x84064045); + _udelay(20); + + while ( ( Rd(P_SAR_SAR_ADC_REG0)& 0x70000000) && (cnt++ <100)) ; + if (cnt >= 100) { + serial_puts(" Get saradc sample Error. Cnt_"); + serial_put_dec(cnt); + serial_puts("\n"); + } + val = Rd(P_SAR_FIFO_READ) & 0x3ff; + for (idx=0; idx<SAMP_COUNT; idx++) + { + if (val <= sam_val[idx]+0x3f) + break; + } + + Wr(SEC_AO_SEC_GP_CFG0, ((Rd(SEC_AO_SEC_GP_CFG0) & 0xFFFF00ff) | (idx << 8))); + serial_puts("Board ID = "); + serial_put_dec(idx); + serial_puts("\n"); + return idx; +} + diff --git a/plat/gxb/scp_bootloader.c b/plat/gxb/scp_bootloader.c new file mode 100644 index 0000000..305029f --- /dev/null +++ b/plat/gxb/scp_bootloader.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <arch_helpers.h> +#include <platform.h> +#include "plat_def.h" +#include "mhu.h" +#include "scp_bootloader.h" +#include "scpi.h" + +/* Boot commands sent from AP -> SCP */ +#define BOOT_CMD_START 0x01 +#define BOOT_CMD_DATA 0x02 + +typedef struct { + uint32_t image_size; +} cmd_start_payload; + +typedef struct { + uint32_t sequence_num; + uint32_t offset; + uint32_t size; +} cmd_data_payload; + +#define BOOT_DATA_MAX_SIZE 0x1000 + +/* Boot commands sent from SCP -> AP */ +#define BOOT_CMD_ACK 0x03 +#define BOOT_CMD_NACK 0x04 + +typedef struct { + uint32_t sequence_num; +} cmd_ack_payload; + +/* + * Unlike the runtime protocol, the boot protocol uses the same memory region + * for both AP -> SCP and SCP -> AP transfers; define the address of this... + */ +static void * const cmd_payload = (void *)(MHU_SECURE_BASE + 0x0080); + +static void *scp_boot_message_start(void) +{ + mhu_secure_message_start(); + + return cmd_payload; +} + +static void scp_boot_message_send(unsigned command, size_t size) +{ + /* Make sure payload can be seen by SCP */ + if (MHU_PAYLOAD_CACHED) + flush_dcache_range((unsigned long)cmd_payload, size); + + /* Send command to SCP */ + mhu_secure_message_send(command | (size << 8)); +} + +static uint32_t scp_boot_message_wait(size_t size) +{ + uint32_t response = mhu_secure_message_wait(); + + /* Make sure we see the reply from the SCP and not any stale data */ + if (MHU_PAYLOAD_CACHED) + inv_dcache_range((unsigned long)cmd_payload, size); + + return response & 0xff; +} + +static void scp_boot_message_end(void) +{ + mhu_secure_message_end(); +} + +static int transfer_block(uint32_t sequence_num, uint32_t offset, uint32_t size) +{ + cmd_data_payload *cmd_data = scp_boot_message_start(); + cmd_data->sequence_num = sequence_num; + cmd_data->offset = offset; + cmd_data->size = size; + + scp_boot_message_send(BOOT_CMD_DATA, sizeof(*cmd_data)); + + cmd_ack_payload *cmd_ack = cmd_payload; + int ok = scp_boot_message_wait(sizeof(*cmd_ack)) == BOOT_CMD_ACK + && cmd_ack->sequence_num == sequence_num; + + scp_boot_message_end(); + + return ok; +} + +int scp_bootloader_transfer(void *image, unsigned int image_size) +{ + uintptr_t offset = (uintptr_t)image - MHU_SECURE_BASE; + uintptr_t end = offset + image_size; + uint32_t response; + + mhu_secure_init(); + + /* Initiate communications with SCP */ + do { + cmd_start_payload *cmd_start = scp_boot_message_start(); + cmd_start->image_size = image_size; + + scp_boot_message_send(BOOT_CMD_START, sizeof(*cmd_start)); + + response = scp_boot_message_wait(0); + + scp_boot_message_end(); + } while (response != BOOT_CMD_ACK); + + /* Transfer image to SCP a block at a time */ + uint32_t sequence_num = 1; + size_t size; + while ((size = end - offset) != 0) { + if (size > BOOT_DATA_MAX_SIZE) + size = BOOT_DATA_MAX_SIZE; + while (!transfer_block(sequence_num, offset, size)) + ; /* Retry forever */ + offset += size; + sequence_num++; + } + + /* Wait for SCP to signal it's ready */ + return scpi_wait_ready(); +} diff --git a/plat/gxb/scp_bootloader.h b/plat/gxb/scp_bootloader.h new file mode 100644 index 0000000..e872513 --- /dev/null +++ b/plat/gxb/scp_bootloader.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SCP_BOOTLOADER_H__ +#define __SCP_BOOTLOADER_H__ + +int scp_bootloader_transfer(void *image, unsigned int image_size); + +#endif diff --git a/plat/gxb/scpi.c b/plat/gxb/scpi.c new file mode 100644 index 0000000..07f1f66 --- /dev/null +++ b/plat/gxb/scpi.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <arch_helpers.h> +#include <platform.h> +#include "plat_def.h" +#include "mhu.h" +#include "scpi.h" + +#define MHU_SECURE_SCP_TO_AP_PAYLOAD (MHU_SECURE_BASE+0x0080) +#define MHU_SECURE_AP_TO_SCP_PAYLOAD (MHU_SECURE_BASE+0x0280) + +#define SIZE_SHIFT 20 /* Bit position for size value in MHU header */ +#define SIZE_MASK 0x1ff /* Mask to extract size value in MHU header*/ + + +void *scpi_secure_message_start(void) +{ + mhu_secure_message_start(); + + /* Return address of payload area. */ + return (void *)MHU_SECURE_AP_TO_SCP_PAYLOAD; +} + +void scpi_secure_message_send(unsigned command, size_t size) +{ + /* Make sure payload can be seen by SCP */ + if (MHU_PAYLOAD_CACHED) + flush_dcache_range(MHU_SECURE_AP_TO_SCP_PAYLOAD, size); + + mhu_secure_message_send(command | (size << SIZE_SHIFT)); +} + +unsigned scpi_secure_message_receive(void **message_out, size_t *size_out) +{ + uint32_t response = mhu_secure_message_wait(); + + /* Get size of payload */ + size_t size = (response >> SIZE_SHIFT) & SIZE_MASK; + + /* Clear size from response */ + response &= ~(SIZE_MASK << SIZE_SHIFT); + + /* Make sure we don't read stale data */ + if (MHU_PAYLOAD_CACHED) + inv_dcache_range(MHU_SECURE_SCP_TO_AP_PAYLOAD, size); + + if (size_out) + *size_out = size; + + if (message_out) + *message_out = (void *)MHU_SECURE_SCP_TO_AP_PAYLOAD; + + return response; +} + +void scpi_secure_message_end(void) +{ + mhu_secure_message_end(); +} + +static void scpi_secure_send32(unsigned command, uint32_t message) +{ + *(__typeof__(message) *)scpi_secure_message_start() = message; + scpi_secure_message_send(command, sizeof(message)); + scpi_secure_message_end(); +} + +int scpi_wait_ready(void) + { + /* Get a message from the SCP */ + scpi_secure_message_start(); + size_t size; + unsigned command = scpi_secure_message_receive(NULL, &size); + scpi_secure_message_end(); + + /* We are expecting 'SCP Ready', produce correct error if it's not */ + spci_status response = SCP_OK; + if (command != SCPI_CMD_SCP_READY) + response = SCP_E_SUPPORT; + else if (size != 0) + response = SCP_E_SIZE; + + /* Send our response back to SCP */ + scpi_secure_send32(command, response); + + return response == SCP_OK ? 0 : -1; + } + +void scpi_set_css_power_state(unsigned mpidr, scpi_power_state cpu_state, + scpi_power_state cluster_state, scpi_power_state css_state) +{ + uint32_t state = mpidr & 0x0f; /* CPU ID */ + state |= (mpidr & 0xf00) >> 4; /* Cluster ID */ + state |= cpu_state << 8; + state |= cluster_state << 12; + state |= css_state << 16; + scpi_secure_send32(SCPI_CMD_SET_CSS_POWER_STATE, state); +} diff --git a/plat/gxb/scpi.h b/plat/gxb/scpi.h new file mode 100644 index 0000000..4ddbeea --- /dev/null +++ b/plat/gxb/scpi.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SCPI_H__ +#define __SCPI_H__ + +#include <stddef.h> +#include <stdint.h> + +extern void *scpi_secure_message_start(void); +extern void scpi_secure_message_send(unsigned command, size_t size); +extern unsigned scpi_secure_message_receive(void ** message_out, size_t *size_out); +extern void scpi_secure_message_end(void); + + +enum { + SCP_OK = 0, /* Success */ + SCP_E_PARAM, /* Invalid parameter(s) */ + SCP_E_ALIGN, /* Invalid alignment */ + SCP_E_SIZE, /* Invalid size */ + SCP_E_HANDLER, /* Invalid handler or callback */ + SCP_E_ACCESS, /* Invalid access or permission denied */ + SCP_E_RANGE, /* Value out of range */ + SCP_E_TIMEOUT, /* Time out has ocurred */ + SCP_E_NOMEM, /* Invalid memory area or pointer */ + SCP_E_PWRSTATE, /* Invalid power state */ + SCP_E_SUPPORT, /* Feature not supported or disabled */ +}; + +typedef uint32_t spci_status; + +typedef enum { + SCPI_CMD_SCP_READY = 0x01, + SCPI_CMD_SET_CSS_POWER_STATE = 0x04, +} spci_command; + +typedef enum { + scpi_power_on = 0, + scpi_power_retention = 1, + scpi_power_off = 3, +} scpi_power_state; + +extern int scpi_wait_ready(void); +extern void scpi_set_css_power_state(unsigned mpidr, scpi_power_state cpu_state, + scpi_power_state cluster_state, scpi_power_state css_state); + +#endif /* __SCPI_H__ */ diff --git a/plat/gxb/sha2.c b/plat/gxb/sha2.c new file mode 100644 index 0000000..0ccf5bd --- /dev/null +++ b/plat/gxb/sha2.c @@ -0,0 +1,416 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/sha2.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <stdio.h> +#include <asm/arch/romboot.h> +#include <string.h> +#include <io.h> +#include <platform_def.h> +#include <sha2.h> +#include <asm/arch/secure_apb.h> +#include <ndma_utils.h> + +#define CONFIG_AML_SHA2_HW_DMA + +static sha2_ctx *cur_ctx; +static void hw_init(uint32_t is224) +{ + uint32_t i, tmp; + uint32_t state[10]; + if (is224 == 0) { + /* SHA-256 */ + state[7] = 0x6A09E667; + state[6] = 0xBB67AE85; + state[5] = 0x3C6EF372; + state[4] = 0xA54FF53A; + state[3] = 0x510E527F; + state[2] = 0x9B05688C; + state[1] = 0x1F83D9AB; + state[0] = 0x5BE0CD19; + } + else { + /* SHA-224 */ + state[7] = 0xC1059ED8; + state[6] = 0x367CD507; + state[5] = 0x3070DD17; + state[4] = 0xF70E5939; + state[3] = 0xFFC00B31; + state[2] = 0x68581511; + state[1] = 0x64F98FA7; + state[0] = 0xBEFA4FA4; + } + + state[8] = 0; + state[9] = 0; + + tmp = readl(SEC_SEC_BLKMV_GEN_REG0); + tmp &= ~((3 << 12) | (0xf << 8) | (0xf << 4)); + tmp |= (1 << 12) | (0xa << 8) | (4 << 4); + writel(tmp, (int *)SEC_SEC_BLKMV_GEN_REG0); + + writel((0 << 21) | // last wdata + (0 << 20) | // last block + (3 << 18) | // byte transfer count + ((is224 ? 3 : 2) << 16) | // SHA mode + (0 << 12) | // out endian + (0 << 8) | // in endian + (0 << 4) | // + (0 << 4) | // + (1 << 3) | // enable + (0 << 2) | // + (0 << 1) | // + (1 << 0), // enable SHA PIO data engine + SEC_SEC_BLKMV_SHA_CONTROL); + + // sha=5 + writel((1 << 4) | 5, SEC_SEC_BLKMV_PIO_CNTL0); + while (((readl(SEC_SEC_BLKMV_PIO_CNTL0) >> 31) & 1) == 0) + ; + + // initial + for (i = 0; i < 10; i++) + writel(state[i], (long)(SEC_SEC_BLKMV_PIO_DATA0 + i * 4)); +} + +static void hw_update(const uint8_t *input, uint32_t ilen, uint8_t last_update) +{ + uint32_t bytes, left, tmp; + uint32_t *p; + + if (!last_update && (ilen % 64)) { + serial_puts("Err:sha\n"); + // sha2 usage problem + return; + } + + // block + p = (uint32_t *)input; + while (ilen > 0) { + if (ilen >= 64) { + bytes = 64; + ilen -= 64; + } + else { + bytes = ilen; + ilen = 0; + } + + while (bytes > 0) { + if (bytes >= 4) { + left = 4; + bytes -= 4; + } + else { + left = bytes; + bytes = 0; + } + + if (left < 4) { // last write, last block + tmp = readl(SEC_SEC_BLKMV_SHA_CONTROL); + tmp &= ~(0xf << 18); + tmp |= ((left - 1) << 18) | (3 << 20); + writel(tmp, SEC_SEC_BLKMV_SHA_CONTROL); + } + else if (bytes == 0) { // last write, + tmp = readl(SEC_SEC_BLKMV_SHA_CONTROL); + tmp &= ~(3 << 20); + tmp |= (1 << 21); + + if (last_update && ilen == 0) + tmp |= (1 << 20); // last block + + writel(tmp, SEC_SEC_BLKMV_SHA_CONTROL); + } + + writel(*p++, SEC_SEC_BLKMV_SHA_PIO_WDATA); + + if (bytes == 0) { + while ((readl(SEC_SEC_BLKMV_SHA_CONTROL) >> 31) & 1) + ; + + tmp = readl(SEC_SEC_BLKMV_SHA_CONTROL); + tmp &= ~(3 << 20); + tmp |= (1 << 22); + writel(tmp, SEC_SEC_BLKMV_SHA_CONTROL); + } + } + } +} + +static void hw_final(uint8_t output[32]) +{ + uint32_t *p; + uint32_t i; + setbits_le32(SEC_SEC_BLKMV_PIO_CNTL0, 1 << 6); + clrbits_le32(SEC_SEC_BLKMV_PIO_CNTL0, 1 << 6); + + for (p = (uint32_t *)(output), i = 0; i < 8; i++) + *p++ = readl((long)(SEC_SEC_BLKMV_PIO_DATA0 + i * 4)); +} + +/** + * SHA-2 Family Hash Init + * + * @param ctx context + * @param digest_len digest length in bits (224 or 256) + */ +void SHA2_HW_init(sha2_ctx *ctx, uint32_t digest_len) +{ + if (cur_ctx != NULL) { + serial_puts("Err:sha\n"); + // sha2 usage problem + return; + } + cur_ctx = ctx; + + hw_init(digest_len == 224); + + ctx->len = 0; +} + +/** + * SHA-2 Family Hash Update + */ +void SHA2_HW_update(sha2_ctx *ctx, const uint8_t *data, uint32_t len) +{ + unsigned int fill_len, data_len, rem_len,offset; + + if (cur_ctx != ctx) { + serial_puts("Err:sha\n"); + // sha2 usage problem + return; + } + /* This method updates the hash for the input data in blocks, except the last + * partial|full block, which is saved in ctx->block. The last partial|full + * block will be added to the hash in SHA2_final. + */ + data_len = len; + offset = 0; + /* fill saved block from beginning of input data */ + if (ctx->len) { + fill_len = SHA256_BLOCK_SIZE - ctx->len; + memcpy(&ctx->block[ctx->len], data, fill_len); + data_len -= fill_len; + offset = fill_len; + ctx->len += fill_len; + } + if (ctx->len == SHA256_BLOCK_SIZE && data_len > 0) { + /* saved block is full and is not last block, hash it */ + hw_update(ctx->block, SHA256_BLOCK_SIZE, 0); + ctx->len = 0; + } + if (data_len > SHA256_BLOCK_SIZE) { + /* still have more than 1 block. hash up until last [partial|full] block */ + rem_len = data_len % SHA256_BLOCK_SIZE; + if (rem_len == 0) { + rem_len = SHA256_BLOCK_SIZE; + } + + data_len -= rem_len; + hw_update(&data[offset], data_len, 0); + offset += data_len; + } else { + rem_len = data_len; + } + + if (rem_len) { + /* save the remaining data */ + memcpy(ctx->block, &data[offset], rem_len); + ctx->len = rem_len; + } +} + +/** + * SHA-2 Family Hash Update + * + * Returns pointer to ctx->buf containing hash. + */ +uint8_t *SHA2_HW_final(sha2_ctx *ctx) +{ + if (cur_ctx != ctx) { + serial_puts("Err:sha\n"); + // sha2 usage problem + return ctx->buf; + } + if (ctx->len == 0 || ctx->len > SHA256_BLOCK_SIZE) { + serial_puts("Err:sha\n"); + // internal sha2 problem + return ctx->buf; + } + hw_update(ctx->block, ctx->len, 1); + hw_final(ctx->buf); + cur_ctx = NULL; + return ctx->buf; +} + +#if defined(CONFIG_AML_SHA2_HW_DMA) +#define THREAD1_TABLE_LOC 0x5510000 +#define SHA_Wr(addr, data) *(volatile uint32_t *)(addr)=(data) +#define SHA_Rd(addr) *(volatile uint32_t *)(addr) +#define SEC_ALLOWED_MASK 0xa // thread 3 and thread 1 are allowed non-secure +int g_n_sha_Start_flag = 0; +int g_n_sha_thread_num = 0; +#endif + +void SHA2_init(sha2_ctx *ctx, unsigned int digest_len) +{ +#if defined(CONFIG_AML_SHA2_HW_DMA) + + unsigned int sha2_256_msg_in[8] = { + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; + + g_n_sha_thread_num = 0; //fixed SHA2 with thread 0 + + + // Setup secure and non-secure transfers + // Also set up the general readback of crypto outputs to the SHA engine + // assign sec_allowed_mask = sec_gen_reg0[11:8]; + // wire [1:0] sec_read_sel = sec_gen_reg0[13:12]; + SHA_Wr(SEC_SEC_BLKMV_GEN_REG0, ((SHA_Rd(SEC_SEC_BLKMV_GEN_REG0) & ~((0x3 << 12) | (0xf << 8))) | (1 << 12) | (SEC_ALLOWED_MASK << 8)) ); + // Allow secure DDR tranfers for the Secure domains + // wire [3:0] sec_ddr_sec_id_en = sec_gen_reg0[7:4]; // Even though a thread is secure, we may not want it to use the DDR secure ID (just in case); + SHA_Wr(SEC_SEC_BLKMV_GEN_REG0, ((SHA_Rd(SEC_SEC_BLKMV_GEN_REG0) & ~(0xf << 4)) | (0x4 << 4)) ); // only thread 2 can issue Secure transfers + + // Enable the SHA engine + // wire sec_sha_dma_enable = sec_sha_control[3]; + SHA_Wr( SEC_SEC_BLKMV_SHA_CONTROL, SHA_Rd(SEC_SEC_BLKMV_SHA_CONTROL) | (1 << 3) ); + + // For DMA modes, pretend there is a PIO request for the AES (not SHA) + // reg pio_granted; // pio_control[31]; + // wire pio_hold_all = pio_control[5]; // set to 1 to block all in-line processing regardless of the PIO being used + // wire pio_request = pio_control[4]; + // wire [2:0] pio_inline_type = pio_control[2:0]; + SHA_Wr( SEC_SEC_BLKMV_PIO_CNTL0, (SHA_Rd(SEC_SEC_BLKMV_PIO_CNTL0) & ~((1 << 4) | (0x7 << 0))) | ((1 << 4) | (4 << 0)) ); // Request for AES + + // + // Write the initial message and datatlen + // + // initial the internal CPU fifo write counter for the save/restore engine + // wire sec_sha_cpu_save_init = sec_sha_control[6]; // Pulsed + // wire [1:0] sec_sha_thread = sec_sha_control[5:4]; + SHA_Wr( SEC_SEC_BLKMV_SHA_CONTROL, (SHA_Rd(SEC_SEC_BLKMV_SHA_CONTROL) & ~(3 << 4)) | (1 << 6) | (g_n_sha_thread_num << 4) ); // pulse bit (init cpu counters) + SHA_Wr( SEC_SEC_BLKMV_SHA_DMA_MSG_IN, sha2_256_msg_in[7] ); + SHA_Wr( SEC_SEC_BLKMV_SHA_DMA_MSG_IN, sha2_256_msg_in[6] ); + SHA_Wr( SEC_SEC_BLKMV_SHA_DMA_MSG_IN, sha2_256_msg_in[5] ); + SHA_Wr( SEC_SEC_BLKMV_SHA_DMA_MSG_IN, sha2_256_msg_in[4] ); + SHA_Wr( SEC_SEC_BLKMV_SHA_DMA_MSG_IN, sha2_256_msg_in[3] ); + SHA_Wr( SEC_SEC_BLKMV_SHA_DMA_MSG_IN, sha2_256_msg_in[2] ); + SHA_Wr( SEC_SEC_BLKMV_SHA_DMA_MSG_IN, sha2_256_msg_in[1] ); + SHA_Wr( SEC_SEC_BLKMV_SHA_DMA_MSG_IN, sha2_256_msg_in[0] ); + SHA_Wr( SEC_SEC_BLKMV_SHA_DMA_DATALEN_IN, 0 ); + SHA_Wr( SEC_SEC_BLKMV_SHA_DMA_DATALEN_IN, 0 ); + + memset((void*)THREAD1_TABLE_LOC,0,10*32); + + NDMA_set_table_position_secure( g_n_sha_thread_num, THREAD1_TABLE_LOC, THREAD1_TABLE_LOC + (10*32) ); // 2 thread entries + g_n_sha_Start_flag = 0; +#else + SHA2_HW_init(ctx, digest_len); +#endif +} + +void SHA2_update(sha2_ctx *ctx, const unsigned char *data, unsigned int len) +{ + +#if defined(CONFIG_AML_SHA2_HW_DMA) + + if (!len) + return; + + NDMA_add_descriptor_sha( g_n_sha_thread_num, // uint32_t thread_num, + 1, // uint32_t irq, + 2, // uint32_t sha_mode, // 1:sha1;2:sha2-256;3:sha2_224 + 0, // uint32_t pre_endian, + len, // uint32_t bytes_to_move, + (uint32_t)(unsigned long)data, // uint32_t src_addr, + 0 ); // uint32_t last_block, + if (!g_n_sha_Start_flag) + { + NDMA_start(g_n_sha_thread_num); + g_n_sha_Start_flag = 1; + } +#else + SHA2_HW_update(ctx, data, len); +#endif +} + +void SHA2_final(sha2_ctx *ctx,const unsigned char *data, unsigned int len) +{ +#if defined(CONFIG_AML_SHA2_HW_DMA) + unsigned int *pOUT = (unsigned int *)(unsigned char *)ctx->buf; + + NDMA_add_descriptor_sha( g_n_sha_thread_num, // uint32_t thread_num, + 1, // uint32_t irq, + 2, // uint32_t sha_mode, // 1:sha1;2:sha2-256;3:sha2_224 + 0, // uint32_t pre_endian, + len, // uint32_t bytes_to_move, + (uint32_t)(unsigned long)data, // uint32_t src_addr, + 1 ); // uint32_t last_block, + + if (!g_n_sha_Start_flag) + { + NDMA_start(g_n_sha_thread_num); + g_n_sha_Start_flag = 1; + } + + NDMA_wait_for_completion(g_n_sha_thread_num); + NDMA_stop(g_n_sha_thread_num); + g_n_sha_Start_flag = 0; + + pOUT[0] = SHA_Rd(SEC_SEC_BLKMV_PIO_DATA0); + pOUT[1] = SHA_Rd(SEC_SEC_BLKMV_PIO_DATA1); + pOUT[2] = SHA_Rd(SEC_SEC_BLKMV_PIO_DATA2); + pOUT[3] = SHA_Rd(SEC_SEC_BLKMV_PIO_DATA3); + pOUT[4] = SHA_Rd(SEC_SEC_BLKMV_PIO_DATA4); + pOUT[5] = SHA_Rd(SEC_SEC_BLKMV_PIO_DATA5); + pOUT[6] = SHA_Rd(SEC_SEC_BLKMV_PIO_DATA6); + pOUT[7] = SHA_Rd(SEC_SEC_BLKMV_PIO_DATA7); + +#else + SHA2_HW_update(ctx, data, len); + SHA2_HW_final(ctx); +#endif + +} + + +void sha2(const uint8_t *input, unsigned int ilen, unsigned char output[32], unsigned int is224) +{ + sha2_ctx sha_ctx; + unsigned long nSRCAddr = (unsigned long)input; + + if (((nSRCAddr >> 24) & (0xFF)) == 0xD9) + { + //serial_puts("aml log : PIO SHA\n"); + SHA2_HW_init(&sha_ctx, is224 ? 224: 256); + SHA2_HW_update(&sha_ctx, input, ilen); + SHA2_HW_final(&sha_ctx); + + } + else + { + //serial_puts("aml log : DMA SHA\n"); + SHA2_init( &sha_ctx, is224 ? 224: 256); + SHA2_final( &sha_ctx, input,ilen); + } + memcpy(output,sha_ctx.buf,32); +} diff --git a/plat/gxb/smc_arm.c b/plat/gxb/smc_arm.c new file mode 100644 index 0000000..c6b3c9b --- /dev/null +++ b/plat/gxb/smc_arm.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <psci.h> +#include <runtime_svc.h> + +#define ARM_SMC_ARM_CPU_SUSPEND 0x80100001 +#define ARM_SMC_ARM_CPU_OFF 0x80100002 +#define ARM_SMC_ARM_CPU_ON 0x80100003 +#define ARM_SMC_ARM_MIGRATE 0x80100004 + +#define ARM_TRUSTZONE_ARM_FAST_SMC_ID_PRESENCE 0x80FFFF00 +#define ARM_TRUSTZONE_ARM_FAST_SMC_ID_UID 0x80FFFF10 + +#define ARM_TRUSTZONE_UID_4LETTERID 0x1 +#define ARM_TRUSTZONE_ARM_UID 0x40524d48 /* "ARMH" */ + + +static uint64_t smc_arm_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, + uint64_t x3, uint64_t x4, void *cookie, + void *handle, uint64_t flags) +{ + switch (smc_fid) { + + /* + * HACK WARNING: Below we use SMC_RET4 to return the original contents + * of x1-x3. We do this because UEFI is expecting these values to be + * preserved across the SMC call. + */ + + case ARM_TRUSTZONE_ARM_FAST_SMC_ID_PRESENCE: + SMC_RET4(handle, 1, x1, x2, x3); + break; + + case ARM_TRUSTZONE_ARM_FAST_SMC_ID_UID + 0: + SMC_RET4(handle, ARM_TRUSTZONE_UID_4LETTERID, x1, x2, x3); + break; + + case ARM_TRUSTZONE_ARM_FAST_SMC_ID_UID + 1: + SMC_RET4(handle, ARM_TRUSTZONE_ARM_UID, x1, x2, x3); + break; + + /* The following 3 cases translate functions into the PSCI equivalent */ + + case ARM_SMC_ARM_CPU_OFF: + smc_fid = PSCI_CPU_OFF; + break; + + case ARM_SMC_ARM_CPU_SUSPEND: + smc_fid = PSCI_CPU_SUSPEND_AARCH64; + break; + + case ARM_SMC_ARM_CPU_ON: + smc_fid = PSCI_CPU_ON_AARCH64; + break; + + } + + return psci_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags); +} + +static int32_t smc_arm_setup(void) +{ + return 0; +} + +DECLARE_RT_SVC(arm, OEN_ARM_START, OEN_ARM_END, SMC_TYPE_FAST, + smc_arm_setup, smc_arm_handler); diff --git a/plat/gxb/storage.c b/plat/gxb/storage.c new file mode 100644 index 0000000..2227b70 --- /dev/null +++ b/plat/gxb/storage.c @@ -0,0 +1,497 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/storage.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <arch_helpers.h> +#include <stdio.h> +#include <stdint.h> +#include <asm/arch/romboot.h> +#include <string.h> +#include <io.h> +#include <platform_def.h> +#include <storage.h> +#include <asm/arch/io.h> +#include <asm/arch/secure_apb.h> +#include <asm/arch/cpu_sdio.h> +#include <asm/arch/nand.h> +#include <fip.h> +#include <asm/arch/watchdog.h> + +void dump_ddr_data(void) +{ +#ifdef CONFIG_SPL_DDR_DUMP + if (CONFIG_SPL_DDR_DUMP_FLAG == readl(P_PREG_STICKY_REG0)) { + serial_puts("Dump ddr[0x"); + serial_put_hex(CONFIG_SPL_DDR_DUMP_ADDR, 32); + serial_puts("-0x"); + serial_put_hex((CONFIG_SPL_DDR_DUMP_ADDR+CONFIG_SPL_DDR_DUMP_SIZE), 32); + serial_puts("] to "); + serial_puts((CONFIG_SPL_DDR_DUMP_DEV_TYPE==BOOT_DEVICE_SD)?"External":"Internal"); + serial_puts(" device[0x"); + serial_put_hex(CONFIG_SPL_DDR_DUMP_DEV_OFFSET, 32); + serial_puts("-0x"); + serial_put_hex((CONFIG_SPL_DDR_DUMP_DEV_OFFSET+CONFIG_SPL_DDR_DUMP_SIZE), 32); + serial_puts("]\n\n"); + + writel(0, P_PREG_STICKY_REG0); + watchdog_disable(); + sdio_write_data(CONFIG_SPL_DDR_DUMP_DEV_TYPE, CONFIG_SPL_DDR_DUMP_ADDR, \ + CONFIG_SPL_DDR_DUMP_DEV_OFFSET, CONFIG_SPL_DDR_DUMP_SIZE); + reset_system(); + } +#endif + return; +} + +uint64_t storage_init(void) +{ + uint64_t boot_device = 0; + boot_device = get_boot_device(); + switch (boot_device) { +#if defined(CONFIG_AML_NAND) + case BOOT_DEVICE_NAND: + serial_puts( "NAND init\n"); + nfio_init(); + break; +#endif //CONFIG_AML_NAND + default: + //serial_puts("do nothing!\n"); + break; + } + return 0; +} +uint64_t storage_load(uint64_t src, uint64_t des, uint64_t size, const char * image_name) +{ + char * device_name = "UNKNOWN"; + uint64_t boot_device = 0; + + boot_device = get_boot_device(); + //boot_device = BOOT_DEVICE_SPI; + switch (boot_device) { + case BOOT_DEVICE_RESERVED: + device_name = "Rsv"; + break; + case BOOT_DEVICE_EMMC: + device_name = "eMMC"; + break; +#if defined(CONFIG_AML_NAND) + case BOOT_DEVICE_NAND: + device_name = "NAND"; + break; +#endif //CONFIG_AML_NAND + case BOOT_DEVICE_SPI: + device_name = "SPI"; + break; + case BOOT_DEVICE_SD: + device_name = "SD"; + src += 512; //sd boot must add 512 offset + break; + case BOOT_DEVICE_USB: + case BOOT_DEVICE_USB_FORCEMODE: + device_name = "USB"; + break; + default: + break; + } + //printf("Load %s from %s, src: 0x%x, dst: 0x%x, size: 0x%x\n", + // image_name, device_name, src, des, size); + serial_puts("Load "); + serial_puts(image_name); + serial_puts(" from "); + serial_puts(device_name); + serial_puts(", src: 0x"); + serial_put_hex(src, 32); + serial_puts(", des: 0x"); + serial_put_hex(des, 32); + serial_puts(", size: 0x"); + serial_put_hex(size, 32); + serial_puts("\n"); + switch (boot_device) { + case BOOT_DEVICE_RESERVED: + break; + case BOOT_DEVICE_EMMC: + sdio_read_data(boot_device,src, des, size); + break; +#if defined(CONFIG_AML_NAND) + case BOOT_DEVICE_NAND: + nf_read(boot_device, src, des, size); + break; +#endif //CONFIG_AML_NAND + case BOOT_DEVICE_SPI: + spi_read(src, des, size); + break; + case BOOT_DEVICE_SD: + sdio_read_data(boot_device, src, des, size); + break; + case BOOT_DEVICE_USB: + case BOOT_DEVICE_USB_FORCEMODE: + usb_boot(src, des, size); + break; + default: + break; + } +#ifdef BL2_ENABLE_MMU + inv_dcache_range(des, size); +#endif + return 0; +} + +uint64_t spi_read(uint64_t src, uint64_t des, uint64_t size) +{ + /*spi pin mux*/ + *P_PAD_PULL_UP_EN_REG2 = 0xffff87ff; + *P_PAD_PULL_UP_REG2 = 0xffff8700; + // deselect nand/emmc, select spi. + *P_PERIPHS_PIN_MUX_4 &= ~((1<<31) | (7<<22) | (1<<20)); + *P_PERIPHS_PIN_MUX_5 |= 0xf; + + /*spi init*/ + /* use sys_clock_freq: 0x002ab000 //24:0x002ab313 + * use sys_clock_freq/2: 0x002aa101 + * use sys_clock_freq/4: 0x002aa313 + * use sys_clock_freq/8: 0x002aa737 + * use sys_clock_freq/10: 0x002aa949 + * use sys_clock_freq/16: 0x002aaf7f + */ +#ifndef CONFIG_PXP_EMULATOR + writel(0x2aa949,P_SPI_FLASH_CTRL); +#else + writel(0x002ab000,P_SPI_FLASH_CTRL); +#endif + + /*load data*/ + uint64_t des64, src64; + des64 = des; + src64 = src; + memcpy((void *)des64, (void *)(src64 | (uint64_t)P_SPI_START_ADDR), size); + return 0; +} + +uint64_t sdio_read_blocks(struct sd_emmc_global_regs *sd_emmc_regs, + uint64_t src, uint64_t des, uint64_t size, uint64_t mode) +{ + unsigned ret = 0; + unsigned read_start; + unsigned vstart = 0; + unsigned status_irq = 0; + unsigned response[4]; + struct cmd_cfg *des_cmd_cur = NULL; + struct sd_emmc_desc_info desc[MAX_DESC_NUM]; + struct sd_emmc_desc_info *desc_cur; + struct sd_emmc_start *desc_start = (struct sd_emmc_start*)&vstart; + struct sd_emmc_status *status_irq_reg = (void *)&status_irq; + + memset(desc,0,MAX_DESC_NUM*sizeof(struct sd_emmc_desc_info)); + desc_cur = desc; + + if (mode) + read_start = src>>9; + else + read_start = src; + + des_cmd_cur = (struct cmd_cfg *)&(desc_cur->cmd_info); + //starting reading...... + des_cmd_cur->cmd_index = 18; //read data command + if (mode) { + des_cmd_cur->block_mode = 1; + des_cmd_cur->length = size; + }else{ + des_cmd_cur->block_mode = 0; + des_cmd_cur->length = size; + } + + des_cmd_cur->data_io = 1; + des_cmd_cur->data_wr = 0; + des_cmd_cur->data_num = 0; + des_cmd_cur->no_resp = 0; + des_cmd_cur->resp_num = 0; + des_cmd_cur->timeout = 7; + des_cmd_cur->owner = 1; + des_cmd_cur->end_of_chain = 1; + + desc_cur->cmd_arg = read_start; + desc_cur->data_addr = des; + desc_cur->data_addr &= ~(1<<0); //DDR + desc_cur->resp_addr = (unsigned long)response; + + desc_start->init = 0; + desc_start->busy = 1; + desc_start->addr = (unsigned long)desc >> 2; + sd_emmc_regs->gstatus = 0x3fff; + //sd_emmc_regs->gstart = vstart; + sd_emmc_regs->gcmd_cfg = desc_cur->cmd_info; + sd_emmc_regs->gcmd_dat = desc_cur->data_addr; + sd_emmc_regs->gcmd_arg = desc_cur->cmd_arg; + + + while (1) { + status_irq = sd_emmc_regs->gstatus; + if (status_irq_reg->end_of_chain) + break; + } + //send stop cmd + desc_cur = &desc[1]; + des_cmd_cur = (struct cmd_cfg *)&(desc_cur->cmd_info); + des_cmd_cur->cmd_index = 12; + des_cmd_cur->data_io = 0; + des_cmd_cur->no_resp = 0; + des_cmd_cur->r1b = 1; + des_cmd_cur->owner = 1; + des_cmd_cur->end_of_chain = 1; + + desc_start->init = 0; + desc_start->busy = 1; + desc_start->addr = (unsigned long)desc_cur >> 2; + sd_emmc_regs->gstatus = 0x3fff; + //sd_emmc_regs->gstart = vstart; + sd_emmc_regs->gcmd_cfg = desc_cur->cmd_info; + sd_emmc_regs->gcmd_dat = desc_cur->data_addr; + sd_emmc_regs->gcmd_arg = desc_cur->cmd_arg; + + while (1) { + status_irq = sd_emmc_regs->gstatus; + //printf("status_irq=0x%x\n",status_irq); + if (status_irq_reg->end_of_chain) + break; + } + + if (status_irq_reg->rxd_err) + ret |= SD_EMMC_RXD_ERROR; + if (status_irq_reg->txd_err) + ret |= SD_EMMC_TXD_ERROR; + if (status_irq_reg->desc_err) + ret |= SD_EMMC_DESC_ERROR; + if (status_irq_reg->resp_err) + ret |= SD_EMMC_RESP_CRC_ERROR; + if (status_irq_reg->resp_timeout) + ret |= SD_EMMC_RESP_TIMEOUT_ERROR; + if (status_irq_reg->desc_timeout) + ret |= SD_EMMC_DESC_TIMEOUT_ERROR; + if (ret) { + serial_puts("sd/emmc read data error: ret="); + serial_put_dec(ret); + serial_puts("\n"); + } + //else + //serial_puts("read data success!\n"); + return ret; +} + +#ifdef CONFIG_SPL_DDR_DUMP +uint64_t sdio_write_blocks(struct sd_emmc_global_regs *sd_emmc_regs, + uint64_t src, uint64_t des, uint64_t size, uint64_t mode) +{ + unsigned ret = 0; + unsigned write_start; + unsigned vstart = 0; + unsigned status_irq = 0; + unsigned response[4]; + struct cmd_cfg *des_cmd_cur = NULL; + struct sd_emmc_desc_info desc[MAX_DESC_NUM]; + struct sd_emmc_desc_info *desc_cur; + struct sd_emmc_start *desc_start = (struct sd_emmc_start*)&vstart; + struct sd_emmc_status *status_irq_reg = (void *)&status_irq; + + memset(desc,0,MAX_DESC_NUM*sizeof(struct sd_emmc_desc_info)); + desc_cur = desc; + + if (mode) + write_start = des>>9; + else + write_start = des; + + des_cmd_cur = (struct cmd_cfg *)&(desc_cur->cmd_info); + //starting reading...... + des_cmd_cur->cmd_index = 25; //muti write data command + if (mode) { + des_cmd_cur->block_mode = 1; + des_cmd_cur->length = size; + }else{ + des_cmd_cur->block_mode = 0; + des_cmd_cur->length = size; + } + + des_cmd_cur->data_io = 1; + des_cmd_cur->data_wr = 1; + des_cmd_cur->data_num = 0; + des_cmd_cur->no_resp = 0; + des_cmd_cur->resp_num = 0; + des_cmd_cur->timeout = 7; + des_cmd_cur->owner = 1; + des_cmd_cur->end_of_chain = 1; + + desc_cur->cmd_arg = write_start; + desc_cur->data_addr = src; + desc_cur->data_addr &= ~(1<<0); //DDR + desc_cur->resp_addr = (unsigned long)response; + + desc_start->init = 0; + desc_start->busy = 1; + desc_start->addr = (unsigned long)desc >> 2; + sd_emmc_regs->gstatus = 0x3fff; + //sd_emmc_regs->gstart = vstart; + sd_emmc_regs->gcmd_cfg = desc_cur->cmd_info; + sd_emmc_regs->gcmd_dat = desc_cur->data_addr; + sd_emmc_regs->gcmd_arg = desc_cur->cmd_arg; + + + while (1) { + status_irq = sd_emmc_regs->gstatus; + if (status_irq_reg->end_of_chain) + break; + } + //send stop cmd + desc_cur = &desc[1]; + des_cmd_cur = (struct cmd_cfg *)&(desc_cur->cmd_info); + des_cmd_cur->cmd_index = 12; + des_cmd_cur->data_io = 0; + des_cmd_cur->no_resp = 0; + des_cmd_cur->r1b = 1; + des_cmd_cur->owner = 1; + des_cmd_cur->end_of_chain = 1; + + desc_start->init = 0; + desc_start->busy = 1; + desc_start->addr = (unsigned long)desc_cur >> 2; + sd_emmc_regs->gstatus = 0x3fff; + //sd_emmc_regs->gstart = vstart; + sd_emmc_regs->gcmd_cfg = desc_cur->cmd_info; + sd_emmc_regs->gcmd_dat = desc_cur->data_addr; + sd_emmc_regs->gcmd_arg = desc_cur->cmd_arg; + + while (1) { + status_irq = sd_emmc_regs->gstatus; + //printf("status_irq=0x%x\n",status_irq); + if (status_irq_reg->end_of_chain) + break; + } + + if (status_irq_reg->rxd_err) + ret |= SD_EMMC_RXD_ERROR; + if (status_irq_reg->txd_err) + ret |= SD_EMMC_TXD_ERROR; + if (status_irq_reg->desc_err) + ret |= SD_EMMC_DESC_ERROR; + if (status_irq_reg->resp_err) + ret |= SD_EMMC_RESP_CRC_ERROR; + if (status_irq_reg->resp_timeout) + ret |= SD_EMMC_RESP_TIMEOUT_ERROR; + if (status_irq_reg->desc_timeout) + ret |= SD_EMMC_DESC_TIMEOUT_ERROR; + if (ret) { + serial_puts("sd/emmc write data error: ret="); + serial_put_dec(ret); + serial_puts("\n"); + } + //else + //serial_puts("write data success!\n"); + return ret; +} +#endif // #ifdef CONFIG_SPL_DDR_DUMP + +uint64_t sdio_read_data(uint64_t boot_device, uint64_t src, uint64_t des, uint64_t size) +{ + unsigned mode,blk_cnt,ret; + struct sd_emmc_global_regs *sd_emmc_regs=0; + union sd_emmc_setup *s_setup = (union sd_emmc_setup *)SEC_AO_SEC_GP_CFG1; + + if (boot_device == BOOT_DEVICE_EMMC) + sd_emmc_regs = (struct sd_emmc_global_regs *)SD_EMMC_BASE_C; + else if(boot_device == BOOT_DEVICE_SD) + sd_emmc_regs = (struct sd_emmc_global_regs *)SD_EMMC_BASE_B; + else + serial_puts("sd/emmc boot device error\n"); + + mode = s_setup->b.sdhc | s_setup->b.hcs ? 1 : 0; + +#if 0 + if (mode) + serial_puts("sd/emmc is lba mode\n"); + else + serial_puts("sd/emmc is byte mode\n"); +#endif + + blk_cnt = ((size+511)&(~(511)))>>9; + do { + ret = sdio_read_blocks(sd_emmc_regs,src,des,(blk_cnt>MAX_BLOCK_COUNTS)?MAX_BLOCK_COUNTS:blk_cnt,mode); + if (ret) + return ret; + if (blk_cnt>MAX_BLOCK_COUNTS) { + src += MAX_BLOCK_COUNTS<<9; + des += MAX_BLOCK_COUNTS<<9; + blk_cnt -= MAX_BLOCK_COUNTS; + }else + break; + }while(1); + + return ret; +} + +#ifdef CONFIG_SPL_DDR_DUMP +uint64_t sdio_write_data(uint64_t boot_device, uint64_t src, uint64_t des, uint64_t size) +{ + unsigned mode,blk_cnt,ret; + struct sd_emmc_global_regs *sd_emmc_regs=0; + union sd_emmc_setup *s_setup = (union sd_emmc_setup *)SEC_AO_SEC_GP_CFG1; + + if (boot_device == BOOT_DEVICE_EMMC) + sd_emmc_regs = (struct sd_emmc_global_regs *)SD_EMMC_BASE_C; + else if(boot_device == BOOT_DEVICE_SD) + sd_emmc_regs = (struct sd_emmc_global_regs *)SD_EMMC_BASE_B; + else + serial_puts("sd/emmc boot device error\n"); + + mode = s_setup->b.sdhc | s_setup->b.hcs ? 1 : 0; + +#if 0 + if (mode) + serial_puts("sd/emmc is lba mode\n"); + else + serial_puts("sd/emmc is byte mode\n"); +#endif + + blk_cnt = ((size+511)&(~(511)))>>9; + do { + ret = sdio_write_blocks(sd_emmc_regs,src,des,(blk_cnt>MAX_BLOCK_COUNTS)?MAX_BLOCK_COUNTS:blk_cnt,mode); + if (ret) + return ret; + if (blk_cnt>MAX_BLOCK_COUNTS) { + src += MAX_BLOCK_COUNTS<<9; + des += MAX_BLOCK_COUNTS<<9; + blk_cnt -= MAX_BLOCK_COUNTS; + }else + break; + }while(1); + + return ret; +} +#endif // #ifdef CONFIG_SPL_DDR_DUMP + +uint64_t get_boot_device(void) { + const unsigned forceUsbRegVal = readl(SEC_AO_RTI_STATUS_REG3); + const unsigned forceUsbBootFlag = ( forceUsbRegVal>>12 ) & 0xF; + if ( 2 == forceUsbBootFlag) return BOOT_DEVICE_USB_FORCEMODE; + + return (readl(SEC_AO_SEC_GP_CFG0) & 0xf); +} + +uint64_t get_ddr_size(void) { + return ((readl(SEC_AO_SEC_GP_CFG0) >> 16) & 0xffff); +} diff --git a/plat/gxb/timer.c b/plat/gxb/timer.c new file mode 100644 index 0000000..e8f076d --- /dev/null +++ b/plat/gxb/timer.c @@ -0,0 +1,59 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/timer.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <io.h> +#include <stdio.h> +#include <asm/arch/romboot.h> +#include <timer.h> + +#define P_EE_TIMER_E P_ISA_TIMERE + +uint32_t time_start = 0; +uint32_t time_end = 0; + +uint32_t get_time(void) +{ + return readl(P_EE_TIMER_E); +} + +void _udelay(unsigned int us) +{ +#ifndef CONFIG_PXP_EMULATOR + uint32_t t0 = get_time(); + + while (get_time() - t0 <= us) + ; +#endif +} + +void timer_start(void) +{ + time_start = get_time(); +} + +void timer_end(const char * name) +{ + time_end = get_time(); + serial_puts(name); + serial_puts(" Time: "); + serial_put_dec(time_end - time_start); + serial_puts(" us\n"); +}
\ No newline at end of file diff --git a/plat/gxb/watchdog.c b/plat/gxb/watchdog.c new file mode 100644 index 0000000..e77e358 --- /dev/null +++ b/plat/gxb/watchdog.c @@ -0,0 +1,72 @@ + +/* + * arch/arm/cpu/armv8/common/firmware/plat/gxb/watchdog.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <stdint.h> +#include <asm/arch/romboot.h> +#include <asm/arch/watchdog.h> +#include <io.h> +#include <asm/arch/io.h> +#include <timer.h> + +void watchdog_init(uint32_t msec) +{ + // src: 24MHz + // div: 24000 for 1ms + // reset ao-22 and ee-21 + *P_WATCHDOG_CNTL = (1<<24)|(1<<25)|(1<<22)|(1<<21)|(24000-1); + + // set timeout + *P_WATCHDOG_TCNT = msec; + *P_WATCHDOG_RESET = 0; + + // enable + *P_WATCHDOG_CNTL |= (1<<18); +} + +void watchdog_reset(void) +{ + *P_WATCHDOG_RESET = 0; +} + +void watchdog_disable(void) +{ + // turn off internal counter and disable + *P_WATCHDOG_CNTL &= ~((1<<18)|(1<<25)); +} +void reset_system(void) +{ + int i; + _udelay(10000); //wait print + while (1) { + writel( 0x3 | (1 << 21) // sys reset en + | (1 << 23) // interrupt en + | (1 << 24) // clk en + | (1 << 25) // clk div en + | (1 << 26) // sys reset now + , P_WATCHDOG_CNTL); + writel(0, P_WATCHDOG_RESET); + + writel(readl(P_WATCHDOG_CNTL) | (1<<18), // watchdog en + P_WATCHDOG_CNTL); + for (i=0; i<100; i++) + readl(P_WATCHDOG_CNTL);/*Deceive gcc for waiting some cycles */ + } +} diff --git a/plat/juno/aarch64/bl1_plat_helpers.S b/plat/juno/aarch64/bl1_plat_helpers.S new file mode 100644 index 0000000..785aa15 --- /dev/null +++ b/plat/juno/aarch64/bl1_plat_helpers.S @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <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 diff --git a/plat/juno/aarch64/juno_common.c b/plat/juno/aarch64/juno_common.c new file mode 100644 index 0000000..1aaf189 --- /dev/null +++ b/plat/juno/aarch64/juno_common.c @@ -0,0 +1,133 @@ +/* + * 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 <mmio.h> +#include <platform.h> +#include <platform_def.h> +#include <xlat_tables.h> +#include "../juno_def.h" +#include <runtime_svc.h> +#include <arch_helpers.h> + +extern int console_puts(const char *s); +extern void console_put_hex(unsigned long data,unsigned int bitlen); + +/* + * 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[] = { +#if 0 + { TZROM_BASE, TZROM_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, + { MHU_SECURE_BASE, MHU_SECURE_SIZE, (MHU_PAYLOAD_CACHED ? MT_MEMORY : MT_DEVICE) + | MT_RW | MT_SECURE }, +// { TZRAM_BASE, TZRAM_SIZE, MT_MEMORY | MT_RW | MT_SECURE }, /* configure_mmu() meminfo arg sets subset of this */ + { FLASH_BASE, FLASH_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, + { EMMC_BASE, EMMC_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, + { PSRAM_BASE, PSRAM_SIZE, MT_MEMORY | MT_RW | MT_SECURE }, /* Used for 'TZDRAM' */ + { IOFPGA_BASE, IOFPGA_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, +// { NSROM_BASE, NSROM_SIZE, MT_MEMORY | MT_RW | MT_NS }, /* Eats a page table so leave it out for now */ + { DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + { NSRAM_BASE, NSRAM_SIZE, MT_MEMORY | MT_RW | MT_NS }, + { DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + { DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS }, +#endif + + { TZROM_BASE, TZROM_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, + { DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS }, + { DEVICEG_BASE, DEVICEG_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + + {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_size, \ + MT_MEMORY | MT_RW | MT_SECURE); \ + mmap_add_region(ro_start, ro_limit - ro_start, \ + MT_MEMORY | MT_RO | MT_SECURE); \ + mmap_add_region(coh_start, coh_limit - coh_start,\ + MT_DEVICE | MT_RW | MT_SECURE); \ + mmap_add(juno_mmap); \ + init_xlat_tables(); \ + \ + enable_mmu_el##_el(); \ + } + +/* 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 */ + assert(counter_base_frequency != 0); + + return counter_base_frequency; +} + +void plat_report_exception(void){ + console_puts("Enter exception!\n"); + console_puts("Value: 0x"); + uint64_t esr_val = read_esr_el1(); + //__asm__ volatile("msr %0, esr_el1\n" : "=r"(esr_val)); + //__asm__ volatile("msr %0, esr_el1\n" :"=r"(esr_val)); + console_put_hex(esr_val, 32); + console_puts("\n"); + + /*never return*/ + while (1) ; +}
\ No newline at end of file diff --git a/plat/juno/aarch64/plat_helpers.S b/plat/juno/aarch64/plat_helpers.S new file mode 100644 index 0000000..c091b99 --- /dev/null +++ b/plat/juno/aarch64/plat_helpers.S @@ -0,0 +1,85 @@ +/* + * 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 <platform_def.h> +#include "../juno_def.h" + + .globl platform_mem_init + + /* --------------------------------------------- + * 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 + * --------------------------------------------- + */ + + /* + * Return 0 to 3 for the A53s and 4 or 5 for the A57s + */ + .globl platform_get_core_pos +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 + + + /* ----------------------------------------------------- + * void platform_is_primary_cpu (unsigned int mpid); + * + * Given the mpidr say whether this cpu is the primary + * cpu (applicable ony after a cold boot) + * ----------------------------------------------------- + */ + .globl platform_is_primary_cpu +func platform_is_primary_cpu + /* Warning: this function is called without a valid stack */ + /* Juno todo: allow configuration of primary CPU using SCC */ + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #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 diff --git a/plat/juno/bl1_plat_setup.c b/plat/juno/bl1_plat_setup.c new file mode 100644 index 0000000..9f9583d --- /dev/null +++ b/plat/juno/bl1_plat_setup.c @@ -0,0 +1,252 @@ +/* + * 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 <mmio.h> +#include <platform.h> +#include <platform_def.h> +#include <tzc400.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__; + +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 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 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; + + /* Initialize the console to provide early debug support */ + console_init(PL011_UART0_BASE); + + /* + * 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; + } +} + + +/* + * 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) +{ + /* + * Enable CCI-400 for this cluster. No need + * for locks as no other cpu is active at the + * moment + */ + cci_enable_coherency(read_mpidr()); + + configure_mmu_el3(bl1_tzram_layout.total_base, + bl1_tzram_layout.total_size, + TZROM_BASE, + TZROM_BASE + TZROM_SIZE, + BL1_COHERENT_RAM_BASE, + BL1_COHERENT_RAM_LIMIT); +} + +/******************************************************************************* + * Before calling this function BL2 is loaded in memory and its entrypoint + * is set by load_image. This is a placeholder for the platform to change + * the entrypoint of BL2 and set SPSR and security state. + * On Juno we are only setting the security state, entrypoint + ******************************************************************************/ +void bl1_plat_set_bl2_ep_info(image_info_t *bl2_image, + entry_point_info_t *bl2_ep) +{ + SET_SECURITY_STATE(bl2_ep->h.attr, SECURE); + bl2_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); +} diff --git a/plat/juno/bl2_plat_setup.c b/plat/juno/bl2_plat_setup.c new file mode 100644 index 0000000..1a26e43 --- /dev/null +++ b/plat/juno/bl2_plat_setup.c @@ -0,0 +1,437 @@ +/* + * 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" +#include <xlat_tables.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); + /* UEFI expects to receive the primary CPU MPID (through x0) */ + bl2_to_bl31_params->bl33_ep_info->args.arg0 = 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); + //char c; + console_init(52); //24M + +console_putc('h'); +console_putc('a'); +console_putc('h'); +console_putc('a'); + /* Setup the BL2 memory layout */ +#if 0 + 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; +#endif + bl2_tzram_layout.total_base = TZRAM_BASE; + bl2_tzram_layout.total_size = TZRAM_SIZE; + bl2_tzram_layout.free_base = TZRAM_BASE; + bl2_tzram_layout.free_size = TZRAM_SIZE; + bl2_tzram_layout.attr = (unsigned long)0x0E939E2E8CF8EFFD; + bl2_tzram_layout.next = 0; +console_putc('h'); +console_putc('e'); +console_putc('h'); +console_putc('e'); +} + +/******************************************************************************* + * Load BL3-0 into Trusted RAM, then transfer it using the SCP Download + * protocol. The image is loaded into RAM in the same place that BL3-1 will be + * loaded later so here, we copy the RAM layout structure and use it to load + * the image into. When this function exits, the RAM layout remains untouched + * so the BL2 can load BL3-1 as normal. + ******************************************************************************/ +static int load_bl30(void) +{ + meminfo_t *bl2_tzram_layout; + meminfo_t tmp_tzram_layout; + uintptr_t bl30_base; + uint32_t bl30_size; + unsigned int bl2_load, bl30_load; + int ret; + int e; + image_info_t bl30_image_info; + + /* Find out how much free trusted ram remains after BL2 load */ + bl2_tzram_layout = bl2_plat_sec_mem_layout(); + + /* copy the TZRAM layout and use it */ + memcpy(&tmp_tzram_layout, bl2_tzram_layout, sizeof(meminfo_t)); + + /* Work out where to load BL3-0 before transferring to SCP */ + bl2_load = tmp_tzram_layout.attr & LOAD_MASK; + assert((bl2_load == TOP_LOAD) || (bl2_load == BOT_LOAD)); + bl30_load = (bl2_load == TOP_LOAD) ? BOT_LOAD : TOP_LOAD; + + SET_PARAM_HEAD(&bl30_image_info, PARAM_IMAGE_BINARY, VERSION_1, 0); + + /* Load the BL3-0 image */ + e = load_image(&tmp_tzram_layout, + BL30_IMAGE_NAME, + bl30_load, + BL30_BASE, + &bl30_image_info, + NULL); + + /* Panic if it has not been possible to load BL3-0 */ + if (e) { + ERROR("Failed to load BL3-0 image.\n"); + panic(); + } + + bl30_base = bl30_image_info.image_base; + bl30_size = bl30_image_info.image_size; + assert(bl30_base != 0); + assert(bl30_size != 0); + + INFO("BL2: BL3-0 loaded at 0x%lx, len=%d (0x%x)\n\r", bl30_base, + bl30_size, bl30_size); + flush_dcache_range(bl30_base, bl30_size); + ret = scp_bootloader_transfer((void *)bl30_base, bl30_size); + + if (ret == 0) + INFO("BL2: BL3-0 loaded and transferred to SCP\n\r"); + else + ERROR("BL2: BL3-0 load and transfer failure\n\r"); + + return ret; +} + +/******************************************************************************* + * 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(); + + /* Load BL3-0 */ + if (load_bl30() != 0) + panic(); +} + +/* 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)); +} + +/* + * 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[] = { +#if 0 + { TZROM_BASE, TZROM_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, + { MHU_SECURE_BASE, MHU_SECURE_SIZE, (MHU_PAYLOAD_CACHED ? MT_MEMORY : MT_DEVICE) + | MT_RW | MT_SECURE }, +// { TZRAM_BASE, TZRAM_SIZE, MT_MEMORY | MT_RW | MT_SECURE }, /* configure_mmu() meminfo arg sets subset of this */ + { FLASH_BASE, FLASH_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, + { EMMC_BASE, EMMC_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, + { PSRAM_BASE, PSRAM_SIZE, MT_MEMORY | MT_RW | MT_SECURE }, /* Used for 'TZDRAM' */ + { IOFPGA_BASE, IOFPGA_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, +// { NSROM_BASE, NSROM_SIZE, MT_MEMORY | MT_RW | MT_NS }, /* Eats a page table so leave it out for now */ + { DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + { NSRAM_BASE, NSRAM_SIZE, MT_MEMORY | MT_RW | MT_NS }, + { DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + { DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS }, +#endif + + { TZROM_BASE, TZROM_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, + { DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS }, + { DEVICEG_BASE, DEVICEG_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + + {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(void) +{ +console_putc('a'); +console_putc('r'); +console_putc('c'); +console_putc('h'); +/* + 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); +*/ + +mmap_add_region(bl2_tzram_layout.total_base, + bl2_tzram_layout.total_size, + MT_MEMORY | MT_RW | MT_SECURE); +console_putc('1'); +mmap_add_region(BL2_RO_BASE, BL2_RO_LIMIT - BL2_RO_BASE, + MT_MEMORY | MT_RO | MT_SECURE); +console_putc('2'); +mmap_add_region(BL2_COHERENT_RAM_BASE, BL2_COHERENT_RAM_LIMIT - BL2_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE); +console_putc('3'); +mmap_add(juno_mmap); +console_putc('4'); +init_xlat_tables(); +console_putc('5'); +//enable_mmu_el1(); + + +console_putc('o'); +console_putc('v'); +console_putc('e'); +console_putc('r'); +} + +/******************************************************************************* + * 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; + bl32_meminfo->attr = BOT_LOAD; + bl32_meminfo->next = 0; +} + + +/******************************************************************************* + * 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; + bl33_meminfo->attr = 0; + bl33_meminfo->attr = 0; +} diff --git a/plat/juno/bl31_plat_setup.c b/plat/juno/bl31_plat_setup.c new file mode 100644 index 0000000..9489804 --- /dev/null +++ b/plat/juno/bl31_plat_setup.c @@ -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 <assert.h> +#include <bl31.h> +#include <bl_common.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); + + /* + * Check params passed from BL2 should not be NULL, + */ + assert(from_bl2 != NULL); + assert(from_bl2->h.type == PARAM_BL31); + assert(from_bl2->h.version >= VERSION_1); + /* + * In debug builds, we pass a special value in 'plat_params_from_bl2' + * to verify platform parameters from BL2 to BL3-1. + * In release builds, it's not used. + */ + assert(((unsigned long long)plat_params_from_bl2) == + JUNO_BL31_PLAT_PARAM_VAL); + + /* + * Copy BL3-2 and BL3-3 entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + bl32_ep_info = *from_bl2->bl32_ep_info; + bl33_ep_info = *from_bl2->bl33_ep_info; +} + +/******************************************************************************* + * Initialize the MHU and the GIC. + ******************************************************************************/ +void bl31_platform_setup(void) +{ + unsigned int reg_val; + + mhu_secure_init(); + + /* Initialize the gic cpu and distributor interfaces */ + gic_setup(); + + /* Enable and initialize the System level generic timer */ + mmio_write_32(SYS_CNTCTL_BASE + CNTCR_OFF, CNTCR_FCREQ(0) | CNTCR_EN); + + /* Allow access to the System counter timer module */ + reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT); + reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT); + reg_val |= (1 << CNTACR_RWVT_SHIFT) | (1 << CNTACR_RWPT_SHIFT); + mmio_write_32(SYS_TIMCTL_BASE + CNTACR_BASE(1), reg_val); + + reg_val = (1 << CNTNSAR_NS_SHIFT(1)); + mmio_write_32(SYS_TIMCTL_BASE + CNTNSAR, reg_val); + + /* Topologies are best known to the platform. */ + plat_setup_topology(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the mmu in a quick and dirty way. + ******************************************************************************/ +void bl31_plat_arch_setup() +{ + configure_mmu_el3(BL31_RO_BASE, + BL31_COHERENT_RAM_LIMIT - BL31_RO_BASE, + BL31_RO_BASE, + BL31_RO_LIMIT, + BL31_COHERENT_RAM_BASE, + BL31_COHERENT_RAM_LIMIT); +} diff --git a/plat/juno/bl32_plat_setup.c b/plat/juno/bl32_plat_setup.c new file mode 100644 index 0000000..d154add --- /dev/null +++ b/plat/juno/bl32_plat_setup.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <bl_common.h> +#include <console.h> +#include <platform.h> +#include "juno_def.h" +#include "juno_private.h" + +/******************************************************************************* + * Declarations of linker defined symbols which will help us find the layout + * of trusted SRAM + ******************************************************************************/ +extern unsigned long __RO_START__; +extern unsigned long __RO_END__; + +extern unsigned long __COHERENT_RAM_START__; +extern unsigned long __COHERENT_RAM_END__; + +/* + * The next 2 constants identify the extents of the code & RO data region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses. + */ +#define BL32_RO_BASE (unsigned long)(&__RO_START__) +#define BL32_RO_LIMIT (unsigned long)(&__RO_END__) + +/* + * The next 2 constants identify the extents of the coherent memory region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to + * page-aligned addresses. + */ +#define BL32_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) +#define BL32_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) + +/******************************************************************************* + * Initialize the UART + ******************************************************************************/ +void bl32_early_platform_setup(void) +{ + /* + * Initialize a different console than already in use to display + * messages from TSP + */ + console_init(PL011_UART1_BASE); +} + +/******************************************************************************* + * Perform platform specific setup placeholder + ******************************************************************************/ +void bl32_platform_setup(void) +{ +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this only intializes the MMU + ******************************************************************************/ +void bl32_plat_arch_setup(void) +{ + configure_mmu_el1(BL32_RO_BASE, + BL32_COHERENT_RAM_LIMIT - BL32_RO_BASE, + BL32_RO_BASE, + BL32_RO_LIMIT, + BL32_COHERENT_RAM_BASE, + BL32_COHERENT_RAM_LIMIT); +} diff --git a/plat/juno/include/plat_macros.S b/plat/juno/include/plat_macros.S new file mode 100644 index 0000000..30dc847 --- /dev/null +++ b/plat/juno/include/plat_macros.S @@ -0,0 +1,55 @@ +/* + * 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 <gic_v2.h> +#include "../juno_def.h" + +.section .rodata.gic_reg_name, "aS" +gic_regs: .asciz "gic_iar", "gic_ctlr", "" + +/* Currently we have only 2 GIC registers to report */ +#define GIC_REG_SIZE (2 * 8) + /* --------------------------------------------- + * The below macro prints out relevant GIC + * registers whenever an unhandled exception is + * taken in BL3-1. + * --------------------------------------------- + */ + .macro plat_print_gic_regs + ldr x0, =GICC_BASE + ldr w1, [x0, #GICC_IAR] + ldr w2, [x0, #GICC_CTLR] + sub sp, sp, #GIC_REG_SIZE + stp x1, x2, [sp] /* we store the gic registers as 64 bit */ + adr x0, gic_regs + mov x1, sp + bl print_string_value + add sp, sp, #GIC_REG_SIZE + .endm diff --git a/plat/juno/include/platform_def.h b/plat/juno/include/platform_def.h new file mode 100644 index 0000000..cb8a685 --- /dev/null +++ b/plat/juno/include/platform_def.h @@ -0,0 +1,179 @@ +/* + * 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 + +/* Size of coherent stacks for debug and release builds */ +#if DEBUG +#define PCPU_DV_MEM_STACK_SIZE 0x400 +#else +#define PCPU_DV_MEM_STACK_SIZE 0x300 +#endif + +#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 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_CORE_COUNT 6 +#define PRIMARY_CPU 0x0 +#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_BASE 0xD9040000 +#define TZROM_SIZE 0x00010000 + +//#define TZRAM_BASE 0x04001000 +//#define TZRAM_SIZE 0x0003F000 +#define TZRAM_BASE 0xD9000000 +#define TZRAM_SIZE 0x00020000 + +/******************************************************************************* + * 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_BASE TZRAM_BASE +#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 5 +#define MAX_MMAP_REGIONS 16 + +/******************************************************************************* + * ID of the secure physical generic timer interrupt. + ******************************************************************************/ +#define IRQ_SEC_PHY_TIMER 29 + +/******************************************************************************* + * CCI-400 related constants + ******************************************************************************/ +#define CCI400_BASE 0x2c090000 +#define CCI400_SL_IFACE_CLUSTER0 4 +#define CCI400_SL_IFACE_CLUSTER1 3 +#define CCI400_SL_IFACE_INDEX(mpidr) (mpidr & MPIDR_CLUSTER_MASK ? \ + CCI400_SL_IFACE_CLUSTER1 : \ + CCI400_SL_IFACE_CLUSTER0) +/******************************************************************************* + * Declarations and constants to access the mailboxes safely. Each mailbox is + * aligned on the biggest cache line size in the platform. This is known only + * to the platform as it might have a combination of integrated and external + * caches. Such alignment ensures that two maiboxes do not sit on the same cache + * line at any cache level. They could belong to different cpus/clusters & + * get written while being protected by different locks causing corruption of + * a valid mailbox address. + ******************************************************************************/ +#define CACHE_WRITEBACK_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +#endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/juno/juno_def.h b/plat/juno/juno_def.h new file mode 100644 index 0000000..bc9c8c1 --- /dev/null +++ b/plat/juno/juno_def.h @@ -0,0 +1,184 @@ +/* + * 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 + +/******************************************************************************* + * 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 DEVICEG_BASE 0xC0000000 +#define DEVICEG_SIZE 0x08008000 + +#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 0x00000000 +#define DRAM_SIZE 0xC0000000 + +/* 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 + +/******************************************************************************* + * 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 + +#endif /* __FVP_DEF_H__ */ diff --git a/plat/juno/juno_private.h b/plat/juno/juno_private.h new file mode 100644 index 0000000..924b679 --- /dev/null +++ b/plat/juno/juno_private.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __JUNO_PRIVATE_H__ +#define __JUNO_PRIVATE_H__ + +#include <bl_common.h> +#include <stdint.h> +#include <platform_def.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__ */ diff --git a/plat/juno/mhu.c b/plat/juno/mhu.c new file mode 100644 index 0000000..89b8d00 --- /dev/null +++ b/plat/juno/mhu.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <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(read_mpidr(), &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(read_mpidr(), &mhu_secure_lock); +} + +void mhu_secure_init(void) +{ + bakery_lock_init(&mhu_secure_lock); + + /* + * Clear the CPU's INTR register to make sure we don't see a stale + * or garbage value and think it's a message we've already sent. + */ + mmio_write_32(MHU_BASE + CPU_INTR_S_CLEAR, 0xffffffffu); +} diff --git a/plat/juno/mhu.h b/plat/juno/mhu.h new file mode 100644 index 0000000..5149c82 --- /dev/null +++ b/plat/juno/mhu.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MHU_H__ +#define __MHU_H__ + +#include <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__ */ diff --git a/plat/juno/plat-tsp.ld.S b/plat/juno/plat-tsp.ld.S new file mode 100644 index 0000000..16d6c17 --- /dev/null +++ b/plat/juno/plat-tsp.ld.S @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + ASSERT(__BL32_END__ <= BL2_BASE, "BL3-2 image overlaps BL2 image.") diff --git a/plat/juno/plat_gic.c b/plat/juno/plat_gic.c new file mode 100644 index 0000000..b18890b --- /dev/null +++ b/plat/juno/plat_gic.c @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <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(security_state == NON_SECURE || security_state == SECURE); + + /* + * We ignore the security state parameter because Juno is GICv2 only + * so both normal and secure worlds are using ARM GICv2. + */ + return gicv2_interrupt_type_to_line(GICC_BASE, type); +} + +/******************************************************************************* + * This function returns the type of the highest priority pending interrupt at + * the GIC cpu interface. INTR_TYPE_INVAL is returned when there is no + * interrupt pending. + ******************************************************************************/ +uint32_t plat_ic_get_pending_interrupt_type(void) +{ + uint32_t id; + + id = gicc_read_hppir(GICC_BASE); + + /* Assume that all secure interrupts are S-EL1 interrupts */ + if (id < 1022) + return INTR_TYPE_S_EL1; + + if (id == GIC_SPURIOUS_INTERRUPT) + return INTR_TYPE_INVAL; + + return INTR_TYPE_NS; +} + +/******************************************************************************* + * This function returns the id of the highest priority pending interrupt at + * the GIC cpu interface. INTR_ID_UNAVAILABLE is returned when there is no + * interrupt pending. + ******************************************************************************/ +uint32_t plat_ic_get_pending_interrupt_id(void) +{ + uint32_t id; + + id = gicc_read_hppir(GICC_BASE); + + if (id < 1022) + return id; + + if (id == 1023) + return INTR_ID_UNAVAILABLE; + + /* + * Find out which non-secure interrupt it is under the assumption that + * the GICC_CTLR.AckCtl bit is 0. + */ + return gicc_read_ahppir(GICC_BASE); +} + +/******************************************************************************* + * This functions reads the GIC cpu interface Interrupt Acknowledge register + * to start handling the pending interrupt. It returns the contents of the IAR. + ******************************************************************************/ +uint32_t plat_ic_acknowledge_interrupt(void) +{ + return gicc_read_IAR(GICC_BASE); +} + +/******************************************************************************* + * This functions writes the GIC cpu interface End Of Interrupt register with + * the passed value to finish handling the active interrupt + ******************************************************************************/ +void plat_ic_end_of_interrupt(uint32_t id) +{ + gicc_write_EOIR(GICC_BASE, id); +} + +/******************************************************************************* + * This function returns the type of the interrupt id depending upon the group + * this interrupt has been configured under by the interrupt controller i.e. + * group0 or group1. + ******************************************************************************/ +uint32_t plat_ic_get_interrupt_type(uint32_t id) +{ + uint32_t group; + + group = gicd_get_igroupr(GICD_BASE, id); + + /* Assume that all secure interrupts are S-EL1 interrupts */ + if (group == GRP0) + return INTR_TYPE_S_EL1; + else + return INTR_TYPE_NS; +} diff --git a/plat/juno/plat_io_storage.c b/plat/juno/plat_io_storage.c new file mode 100644 index 0000000..16259af --- /dev/null +++ b/plat/juno/plat_io_storage.c @@ -0,0 +1,212 @@ +/* + * 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 <semihosting.h> /* For FOPEN_MODE_... */ +#include <io_fip.h> +#include <io_memmap.h> +#include <debug.h> +#include "juno_def.h" + +/* IO devices */ +static io_plat_data_t io_data; +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 bl32_file_spec = { + .path = BL32_IMAGE_NAME, + .mode = FOPEN_MODE_RB +}; + +static const io_file_spec_t bl33_file_spec = { + .path = BL33_IMAGE_NAME, + .mode = FOPEN_MODE_RB +}; + +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 + }, { + BL32_IMAGE_NAME, + &fip_dev_handle, + (uintptr_t)&bl32_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; + + /* Initialise the IO layer */ + io_init(&io_data); + + /* Register the IO devices on this platform */ + io_result = register_io_dev_fip(&fip_dev_con); + assert(io_result == IO_SUCCESS); + + io_result = register_io_dev_memmap(&memmap_dev_con); + assert(io_result == IO_SUCCESS); + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(fip_dev_con, fip_dev_spec, &fip_dev_handle); + assert(io_result == IO_SUCCESS); + + io_result = io_dev_open(memmap_dev_con, memmap_dev_spec, + &memmap_dev_handle); + assert(io_result == IO_SUCCESS); + + /* Ignore improbable errors in release builds */ + (void)io_result; +} + + +/* Return an IO device handle and specification which can be used to access + * an image. Use this to enforce platform load policy */ +int plat_get_image_source(const char *image_name, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result = IO_FAIL; + const struct plat_io_policy *policy; + + if ((image_name != NULL) && (dev_handle != NULL) && + (image_spec != NULL)) { + policy = policies; + while (policy->image_name != NULL) { + if (strcmp(policy->image_name, image_name) == 0) { + result = policy->check(policy->image_spec); + if (result == IO_SUCCESS) { + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + break; + } + } + policy++; + } + } else { + result = IO_FAIL; + } + return result; +} diff --git a/plat/juno/plat_pm.c b/plat/juno/plat_pm.c new file mode 100644 index 0000000..4e85f7c --- /dev/null +++ b/plat/juno/plat_pm.c @@ -0,0 +1,271 @@ +/* + * 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 <platform.h> +#include <platform_def.h> +#include <psci.h> +#include "juno_def.h" +#include "juno_private.h" +#include "scpi.h" + +typedef struct { + /* Align the suspend level to allow per-cpu lockless access */ + uint32_t state[MPIDR_MAX_AFFLVL] __aligned(CACHE_WRITEBACK_GRANULE); +} scp_pstate; + +static scp_pstate target_pstate[PLATFORM_CORE_COUNT]; + +int pm_on(unsigned long mpidr, + unsigned long sec_entrypoint, + unsigned long ns_entrypoint, + unsigned int afflvl, + unsigned int 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 + */ + unsigned long *mbox = (unsigned long *)(unsigned long)( + TRUSTED_MAILBOXES_BASE + + (platform_get_core_pos(mpidr) << TRUSTED_MAILBOX_SHIFT) + ); + *mbox = sec_entrypoint; + flush_dcache_range((unsigned long)mbox, sizeof(*mbox)); + + scpi_set_css_power_state(mpidr, scpi_power_on, scpi_power_on, + scpi_power_on); + + return PSCI_E_SUCCESS; +} + +int pm_on_finish(unsigned long mpidr, unsigned int afflvl, unsigned int state) +{ + switch (afflvl) { + + case MPIDR_AFFLVL1: + /* Enable coherency if this cluster was off */ + if (state == PSCI_STATE_OFF) + cci_enable_coherency(mpidr); + break; + + case MPIDR_AFFLVL0: + /* + * Ignore the state passed for a cpu. It could only have + * been off if we are here. + */ + + /* Turn on intra-cluster coherency. */ + write_cpuectlr(read_cpuectlr() | CPUECTLR_SMP_BIT); + + /* 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 each cpu + */ + unsigned long *mbox = (unsigned long *)(unsigned long)( + TRUSTED_MAILBOXES_BASE + + (platform_get_core_pos(mpidr) << TRUSTED_MAILBOX_SHIFT) + ); + *mbox = 0; + flush_dcache_range((unsigned long)mbox, sizeof(*mbox)); + + break; + } + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Common function called while turning a cpu off or suspending it. It is called + * for each affinity level until the target affinity level. It keeps track of + * the power state that needs to be programmed through the SCP firmware for each + * affinity level. Once the target affinity level is reached it uses the MHU + * channel to ask the SCP to perform the power operations for each affinity + * level accumulated so far. + * + * CAUTION: This function is called with coherent stacks so that caches can be + * turned off, flushed and coherency disabled. There is no guarantee that caches + * will remain turned on across calls to this function as each affinity level is + * dealt with. So do not write & read global variables across calls. It will be + * wise to do flush a write to the global to prevent unpredictable results. + ******************************************************************************/ +static int juno_power_down_common(unsigned long mpidr, + unsigned int linear_id, + unsigned int cur_afflvl, + unsigned int tgt_afflvl, + unsigned int state) +{ + /* Record which power state this affinity level is supposed to enter */ + if (state == PSCI_STATE_OFF) { + target_pstate[linear_id].state[cur_afflvl] = scpi_power_off; + } else { + assert(cur_afflvl != MPIDR_AFFLVL0); + target_pstate[linear_id].state[cur_afflvl] = scpi_power_on; + goto exit; + } + + switch (cur_afflvl) { + case MPIDR_AFFLVL1: + /* Cluster is to be turned off, so disable coherency */ + cci_disable_coherency(mpidr); + + break; + + case MPIDR_AFFLVL0: + /* Turn off intra-cluster coherency */ + write_cpuectlr(read_cpuectlr() & ~CPUECTLR_SMP_BIT); + + /* Prevent interrupts from spuriously waking up this cpu */ + gic_cpuif_deactivate(GICC_BASE); + + break; + } + +exit: + /* + * If this is the target affinity level then we need to ask the SCP + * to power down the appropriate components depending upon their state + */ + if (cur_afflvl == tgt_afflvl) { + scpi_set_css_power_state(mpidr, + target_pstate[linear_id].state[MPIDR_AFFLVL0], + target_pstate[linear_id].state[MPIDR_AFFLVL1], + scpi_power_on); + + /* Reset the states */ + target_pstate[linear_id].state[MPIDR_AFFLVL0] = scpi_power_on; + target_pstate[linear_id].state[MPIDR_AFFLVL1] = scpi_power_on; + } + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Handler called when an affinity instance is about to be turned off. The + * level and mpidr determine the affinity instance. The 'state' arg. allows the + * platform to decide whether the cluster is being turned off and take apt + * actions. + * + * CAUTION: This function is called with coherent stacks so that caches can be + * turned off, flushed and coherency disabled. There is no guarantee that caches + * will remain turned on across calls to this function as each affinity level is + * dealt with. So do not write & read global variables across calls. It will be + * wise to do flush a write to the global to prevent unpredictable results. + ******************************************************************************/ +int pm_off(unsigned long mpidr, unsigned int afflvl, unsigned int state) +{ + return juno_power_down_common(mpidr, + platform_get_core_pos(mpidr), + afflvl, + plat_get_max_afflvl(), + state); +} + +/******************************************************************************* + * Handler called when an affinity instance is about to be suspended. The + * level and mpidr determine the affinity instance. The 'state' arg. allows the + * platform to decide whether the cluster is being turned off and take apt + * actions. The 'sec_entrypoint' determines the address in BL3-1 from where + * execution should resume. + * + * CAUTION: This function is called with coherent stacks so that caches can be + * turned off, flushed and coherency disabled. There is no guarantee that caches + * will remain turned on across calls to this function as each affinity level is + * dealt with. So do not write & read global variables across calls. It will be + * wise to do flush a write to the global to prevent unpredictable results. + ******************************************************************************/ +int pm_suspend(unsigned long mpidr, + unsigned long sec_entrypoint, + unsigned long ns_entrypoint, + unsigned int afflvl, + unsigned int state) +{ + uint32_t tgt_afflvl; + + tgt_afflvl = psci_get_suspend_afflvl(mpidr); + assert(tgt_afflvl != PSCI_INVALID_DATA); + + /* + * Setup mailbox with address for CPU entrypoint when it next powers up + */ + if (afflvl == MPIDR_AFFLVL0) { + unsigned long *mbox = (unsigned long *)(unsigned long)( + TRUSTED_MAILBOXES_BASE + + (platform_get_core_pos(mpidr) << TRUSTED_MAILBOX_SHIFT) + ); + *mbox = sec_entrypoint; + flush_dcache_range((unsigned long)mbox, sizeof(*mbox)); + } + + return juno_power_down_common(mpidr, + platform_get_core_pos(mpidr), + afflvl, + tgt_afflvl, + state); +} + +int pm_suspend_finish(unsigned long mpidr, + unsigned int afflvl, + unsigned int state) +{ + return pm_on_finish(mpidr, afflvl, state); +} + +/******************************************************************************* + * Export the platform handlers to enable psci to invoke them + ******************************************************************************/ +static const plat_pm_ops_t pm_ops = { + .affinst_on = pm_on, + .affinst_on_finish = pm_on_finish, + .affinst_off = pm_off, + .affinst_suspend = pm_suspend, + .affinst_suspend_finish = pm_suspend_finish +}; + +/******************************************************************************* + * Export the platform specific power ops & initialize the fvp power controller + ******************************************************************************/ +int platform_setup_pm(const plat_pm_ops_t **plat_ops) +{ + *plat_ops = &pm_ops; + return 0; +} diff --git a/plat/juno/plat_topology.c b/plat/juno/plat_topology.c new file mode 100644 index 0000000..39d4dab --- /dev/null +++ b/plat/juno/plat_topology.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <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; +} diff --git a/plat/juno/platform.mk b/plat/juno/platform.mk new file mode 100644 index 0000000..b1d0c77 --- /dev/null +++ b/plat/juno/platform.mk @@ -0,0 +1,74 @@ +# +# 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/serial/serial.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + lib/mmio.c \ + lib/aarch64/xlat_tables.c \ + lib/aarch64/sysreg_helpers.S \ + plat/common/aarch64/plat_common.c \ + plat/juno/plat_io_storage.c + +BL1_SOURCES += drivers/arm/cci400/cci400.c \ + 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 \ + 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 \ + plat/juno/smc_arm.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 diff --git a/plat/juno/scp_bootloader.c b/plat/juno/scp_bootloader.c new file mode 100644 index 0000000..a6d25d4 --- /dev/null +++ b/plat/juno/scp_bootloader.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <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(); +} diff --git a/plat/juno/scp_bootloader.h b/plat/juno/scp_bootloader.h new file mode 100644 index 0000000..e872513 --- /dev/null +++ b/plat/juno/scp_bootloader.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SCP_BOOTLOADER_H__ +#define __SCP_BOOTLOADER_H__ + +int scp_bootloader_transfer(void *image, unsigned int image_size); + +#endif diff --git a/plat/juno/scpi.c b/plat/juno/scpi.c new file mode 100644 index 0000000..cdfc1f2 --- /dev/null +++ b/plat/juno/scpi.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <arch_helpers.h> +#include <platform.h> +#include "juno_def.h" +#include "mhu.h" +#include "scpi.h" + +#define MHU_SECURE_SCP_TO_AP_PAYLOAD (MHU_SECURE_BASE+0x0080) +#define MHU_SECURE_AP_TO_SCP_PAYLOAD (MHU_SECURE_BASE+0x0280) + +#define SIZE_SHIFT 20 /* Bit position for size value in MHU header */ +#define SIZE_MASK 0x1ff /* Mask to extract size value in MHU header*/ + + +void *scpi_secure_message_start(void) +{ + mhu_secure_message_start(); + + /* Return address of payload area. */ + return (void *)MHU_SECURE_AP_TO_SCP_PAYLOAD; +} + +void scpi_secure_message_send(unsigned command, size_t size) +{ + /* Make sure payload can be seen by SCP */ + if (MHU_PAYLOAD_CACHED) + flush_dcache_range(MHU_SECURE_AP_TO_SCP_PAYLOAD, size); + + mhu_secure_message_send(command | (size << SIZE_SHIFT)); +} + +unsigned scpi_secure_message_receive(void **message_out, size_t *size_out) +{ + uint32_t response = mhu_secure_message_wait(); + + /* Get size of payload */ + size_t size = (response >> SIZE_SHIFT) & SIZE_MASK; + + /* Clear size from response */ + response &= ~(SIZE_MASK << SIZE_SHIFT); + + /* Make sure we don't read stale data */ + if (MHU_PAYLOAD_CACHED) + inv_dcache_range(MHU_SECURE_SCP_TO_AP_PAYLOAD, size); + + if (size_out) + *size_out = size; + + if (message_out) + *message_out = (void *)MHU_SECURE_SCP_TO_AP_PAYLOAD; + + return response; +} + +void scpi_secure_message_end(void) +{ + mhu_secure_message_end(); +} + +static void scpi_secure_send32(unsigned command, uint32_t message) +{ + *(__typeof__(message) *)scpi_secure_message_start() = message; + scpi_secure_message_send(command, sizeof(message)); + scpi_secure_message_end(); +} + +int scpi_wait_ready(void) + { + /* Get a message from the SCP */ + scpi_secure_message_start(); + size_t size; + unsigned command = scpi_secure_message_receive(NULL, &size); + scpi_secure_message_end(); + + /* We are expecting 'SCP Ready', produce correct error if it's not */ + spci_status response = SCP_OK; + if (command != SCPI_CMD_SCP_READY) + response = SCP_E_SUPPORT; + else if (size != 0) + response = SCP_E_SIZE; + + /* Send our response back to SCP */ + scpi_secure_send32(command, response); + + return response == SCP_OK ? 0 : -1; + } + +void scpi_set_css_power_state(unsigned mpidr, scpi_power_state cpu_state, + scpi_power_state cluster_state, scpi_power_state css_state) +{ + uint32_t state = mpidr & 0x0f; /* CPU ID */ + state |= (mpidr & 0xf00) >> 4; /* Cluster ID */ + state |= cpu_state << 8; + state |= cluster_state << 12; + state |= css_state << 16; + scpi_secure_send32(SCPI_CMD_SET_CSS_POWER_STATE, state); +} diff --git a/plat/juno/scpi.h b/plat/juno/scpi.h new file mode 100644 index 0000000..4ddbeea --- /dev/null +++ b/plat/juno/scpi.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SCPI_H__ +#define __SCPI_H__ + +#include <stddef.h> +#include <stdint.h> + +extern void *scpi_secure_message_start(void); +extern void scpi_secure_message_send(unsigned command, size_t size); +extern unsigned scpi_secure_message_receive(void ** message_out, size_t *size_out); +extern void scpi_secure_message_end(void); + + +enum { + SCP_OK = 0, /* Success */ + SCP_E_PARAM, /* Invalid parameter(s) */ + SCP_E_ALIGN, /* Invalid alignment */ + SCP_E_SIZE, /* Invalid size */ + SCP_E_HANDLER, /* Invalid handler or callback */ + SCP_E_ACCESS, /* Invalid access or permission denied */ + SCP_E_RANGE, /* Value out of range */ + SCP_E_TIMEOUT, /* Time out has ocurred */ + SCP_E_NOMEM, /* Invalid memory area or pointer */ + SCP_E_PWRSTATE, /* Invalid power state */ + SCP_E_SUPPORT, /* Feature not supported or disabled */ +}; + +typedef uint32_t spci_status; + +typedef enum { + SCPI_CMD_SCP_READY = 0x01, + SCPI_CMD_SET_CSS_POWER_STATE = 0x04, +} spci_command; + +typedef enum { + scpi_power_on = 0, + scpi_power_retention = 1, + scpi_power_off = 3, +} scpi_power_state; + +extern int scpi_wait_ready(void); +extern void scpi_set_css_power_state(unsigned mpidr, scpi_power_state cpu_state, + scpi_power_state cluster_state, scpi_power_state css_state); + +#endif /* __SCPI_H__ */ diff --git a/plat/juno/smc_arm.c b/plat/juno/smc_arm.c new file mode 100644 index 0000000..c6b3c9b --- /dev/null +++ b/plat/juno/smc_arm.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <psci.h> +#include <runtime_svc.h> + +#define ARM_SMC_ARM_CPU_SUSPEND 0x80100001 +#define ARM_SMC_ARM_CPU_OFF 0x80100002 +#define ARM_SMC_ARM_CPU_ON 0x80100003 +#define ARM_SMC_ARM_MIGRATE 0x80100004 + +#define ARM_TRUSTZONE_ARM_FAST_SMC_ID_PRESENCE 0x80FFFF00 +#define ARM_TRUSTZONE_ARM_FAST_SMC_ID_UID 0x80FFFF10 + +#define ARM_TRUSTZONE_UID_4LETTERID 0x1 +#define ARM_TRUSTZONE_ARM_UID 0x40524d48 /* "ARMH" */ + + +static uint64_t smc_arm_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, + uint64_t x3, uint64_t x4, void *cookie, + void *handle, uint64_t flags) +{ + switch (smc_fid) { + + /* + * HACK WARNING: Below we use SMC_RET4 to return the original contents + * of x1-x3. We do this because UEFI is expecting these values to be + * preserved across the SMC call. + */ + + case ARM_TRUSTZONE_ARM_FAST_SMC_ID_PRESENCE: + SMC_RET4(handle, 1, x1, x2, x3); + break; + + case ARM_TRUSTZONE_ARM_FAST_SMC_ID_UID + 0: + SMC_RET4(handle, ARM_TRUSTZONE_UID_4LETTERID, x1, x2, x3); + break; + + case ARM_TRUSTZONE_ARM_FAST_SMC_ID_UID + 1: + SMC_RET4(handle, ARM_TRUSTZONE_ARM_UID, x1, x2, x3); + break; + + /* The following 3 cases translate functions into the PSCI equivalent */ + + case ARM_SMC_ARM_CPU_OFF: + smc_fid = PSCI_CPU_OFF; + break; + + case ARM_SMC_ARM_CPU_SUSPEND: + smc_fid = PSCI_CPU_SUSPEND_AARCH64; + break; + + case ARM_SMC_ARM_CPU_ON: + smc_fid = PSCI_CPU_ON_AARCH64; + break; + + } + + return psci_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags); +} + +static int32_t smc_arm_setup(void) +{ + return 0; +} + +DECLARE_RT_SVC(arm, OEN_ARM_START, OEN_ARM_END, SMC_TYPE_FAST, + smc_arm_setup, smc_arm_handler); |