~funderscore blog cgit wiki get in touch
aboutsummaryrefslogtreecommitdiff
path: root/plat
diff options
context:
space:
mode:
authorFerass El Hafidi <vitali64pmemail@protonmail.com>2023-05-08 19:03:10 +0200
committerFerass El Hafidi <vitali64pmemail@protonmail.com>2023-05-08 19:03:10 +0200
commitf9ed707f171c8069e99e24e24c3da73d8b6f5716 (patch)
tree4da9838d387c8bc260e83f3f51f5dfa83e0b48ae /plat
downloadamlogic-bl2-master.tar.gz
Push old Amlogic BL2 sourcesHEADmaster
Diffstat (limited to 'plat')
-rw-r--r--plat/common/aarch64/plat_common.c49
-rw-r--r--plat/common/aarch64/platform_helpers.S81
-rw-r--r--plat/common/aarch64/platform_mp_stack.S102
-rw-r--r--plat/common/aarch64/platform_up_stack.S97
-rw-r--r--plat/fvp/aarch64/fvp_common.c251
-rw-r--r--plat/fvp/aarch64/fvp_helpers.S186
-rw-r--r--plat/fvp/bl1_fvp_setup.c152
-rw-r--r--plat/fvp/bl2_fvp_setup.c298
-rw-r--r--plat/fvp/bl31_fvp_setup.c257
-rw-r--r--plat/fvp/bl32_fvp_setup.c101
-rw-r--r--plat/fvp/drivers/pwrc/fvp_pwrc.c107
-rw-r--r--plat/fvp/drivers/pwrc/fvp_pwrc.h77
-rw-r--r--plat/fvp/fvp_def.h237
-rw-r--r--plat/fvp/fvp_gic.c408
-rw-r--r--plat/fvp/fvp_io_storage.c238
-rw-r--r--plat/fvp/fvp_pm.c411
-rw-r--r--plat/fvp/fvp_private.h109
-rw-r--r--plat/fvp/fvp_security.c136
-rw-r--r--plat/fvp/fvp_topology.c240
-rw-r--r--plat/fvp/include/plat_macros.S57
-rw-r--r--plat/fvp/include/platform_def.h180
-rw-r--r--plat/fvp/platform.mk94
-rw-r--r--plat/gxb/aarch64/bl1_plat_helpers.S125
-rw-r--r--plat/gxb/aarch64/cache.S38
-rw-r--r--plat/gxb/aarch64/common.c119
-rw-r--r--plat/gxb/aarch64/plat_helpers.S85
-rw-r--r--plat/gxb/bl2_plat_setup.c303
-rw-r--r--plat/gxb/crypto/bignum.c1355
-rw-r--r--plat/gxb/crypto/ndma_utils.c183
-rw-r--r--plat/gxb/crypto/rsa.c240
-rw-r--r--plat/gxb/crypto/secureboot.c749
-rw-r--r--plat/gxb/ddr/ddr.c863
-rw-r--r--plat/gxb/ddr/ddr_detect.c96
-rw-r--r--plat/gxb/ddr/ddr_pctl_define.h282
-rw-r--r--plat/gxb/ddr/ddr_pub_define.h305
-rw-r--r--plat/gxb/ddr/dmc_define.h372
-rw-r--r--plat/gxb/ddr/mmc_define.h87
-rw-r--r--plat/gxb/ddr/sec_mmc_define.h712
-rw-r--r--plat/gxb/efuse.c48
-rw-r--r--plat/gxb/include/arch.h157
-rw-r--r--plat/gxb/include/bignum.h640
-rw-r--r--plat/gxb/include/bn_mul.h865
-rw-r--r--plat/gxb/include/cache.h15
-rw-r--r--plat/gxb/include/common.h68
-rw-r--r--plat/gxb/include/efuse.h30
-rw-r--r--plat/gxb/include/mailbox.h40
-rw-r--r--plat/gxb/include/ndma_utils.h33
-rw-r--r--plat/gxb/include/plat_init.h27
-rw-r--r--plat/gxb/include/plat_macros.S55
-rw-r--r--plat/gxb/include/platform_def.h188
-rw-r--r--plat/gxb/include/pll.h61
-rw-r--r--plat/gxb/include/rsa.h598
-rw-r--r--plat/gxb/include/rsa_config.h892
-rw-r--r--plat/gxb/include/saradc.h48
-rw-r--r--plat/gxb/include/sha2.h48
-rw-r--r--plat/gxb/include/storage.h77
-rw-r--r--plat/gxb/include/timer.h48
-rw-r--r--plat/gxb/mailbox.c135
-rw-r--r--plat/gxb/mhu.c95
-rw-r--r--plat/gxb/mhu.h43
-rw-r--r--plat/gxb/nand.c775
-rw-r--r--plat/gxb/plat-tsp.ld.S31
-rw-r--r--plat/gxb/plat_def.h198
-rw-r--r--plat/gxb/plat_gic.c283
-rw-r--r--plat/gxb/plat_init.c44
-rw-r--r--plat/gxb/plat_io_storage.c203
-rw-r--r--plat/gxb/plat_pm.c271
-rw-r--r--plat/gxb/plat_private.h153
-rw-r--r--plat/gxb/plat_topology.c60
-rw-r--r--plat/gxb/platform.mk97
-rw-r--r--plat/gxb/pll.c271
-rw-r--r--plat/gxb/power_init.c16
-rw-r--r--plat/gxb/saradc.c73
-rw-r--r--plat/gxb/scp_bootloader.c153
-rw-r--r--plat/gxb/scp_bootloader.h36
-rw-r--r--plat/gxb/scpi.c126
-rw-r--r--plat/gxb/scpi.h74
-rw-r--r--plat/gxb/sha2.c416
-rw-r--r--plat/gxb/smc_arm.c95
-rw-r--r--plat/gxb/storage.c497
-rw-r--r--plat/gxb/timer.c59
-rw-r--r--plat/gxb/watchdog.c72
-rw-r--r--plat/juno/aarch64/bl1_plat_helpers.S125
-rw-r--r--plat/juno/aarch64/juno_common.c133
-rw-r--r--plat/juno/aarch64/plat_helpers.S85
-rw-r--r--plat/juno/bl1_plat_setup.c252
-rw-r--r--plat/juno/bl2_plat_setup.c437
-rw-r--r--plat/juno/bl31_plat_setup.c174
-rw-r--r--plat/juno/bl32_plat_setup.c97
-rw-r--r--plat/juno/include/plat_macros.S55
-rw-r--r--plat/juno/include/platform_def.h179
-rw-r--r--plat/juno/juno_def.h184
-rw-r--r--plat/juno/juno_private.h153
-rw-r--r--plat/juno/mhu.c95
-rw-r--r--plat/juno/mhu.h43
-rw-r--r--plat/juno/plat-tsp.ld.S31
-rw-r--r--plat/juno/plat_gic.c283
-rw-r--r--plat/juno/plat_io_storage.c212
-rw-r--r--plat/juno/plat_pm.c271
-rw-r--r--plat/juno/plat_topology.c60
-rw-r--r--plat/juno/platform.mk74
-rw-r--r--plat/juno/scp_bootloader.c153
-rw-r--r--plat/juno/scp_bootloader.h36
-rw-r--r--plat/juno/scpi.c126
-rw-r--r--plat/juno/scpi.h74
-rw-r--r--plat/juno/smc_arm.c95
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);