summaryrefslogtreecommitdiff
path: root/plat
diff options
context:
space:
mode:
authorAndre Przywara <andre.przywara@arm.com>2016-02-03 23:44:36 +0000
committerAndre Przywara <andre.przywara@arm.com>2016-02-04 09:00:42 +0000
commit90fc243e9256775c85f8763e8fa1b2b59e67d0ce (patch)
tree4293050433bd6237830ec824e8334a90bf400af4 /plat
parent14b6608c9a2eba27ef36cc3e0806c9fa6d5555b0 (diff)
Merge in files from Allwinners lichee BSP tarball
The Pine64 Wiki[1] links to a BSP tarball, among other things containing a dump of an ARM Trusted Firmware source tree with Allwinner changes on top. Since the tarball does not contain any version history information about the changes, this commit is just the diff between the ATF 1.0 release and the files from the Allwinner provided tarball. The executable flag from many source has been removed. [1] http://wiki.pine64.org/index.php/Pine_A64_Software_Release#Linux_BSP_Related
Diffstat (limited to 'plat')
-rw-r--r--plat/fvp/platform.mk3
-rw-r--r--plat/sun50iw1p1/aarch64/plat_helpers.S144
-rw-r--r--plat/sun50iw1p1/aarch64/sunxi_common.c246
-rw-r--r--plat/sun50iw1p1/bl1_sunxi_setup.c136
-rw-r--r--plat/sun50iw1p1/bl2_sunxi_setup.c285
-rw-r--r--plat/sun50iw1p1/bl31_sunxi_setup.c275
-rw-r--r--plat/sun50iw1p1/drivers/gpio/gpio.c228
-rw-r--r--plat/sun50iw1p1/drivers/uart/uart.c149
-rw-r--r--plat/sun50iw1p1/gic_sunxi.h344
-rw-r--r--plat/sun50iw1p1/include/arisc.h789
-rw-r--r--plat/sun50iw1p1/include/ccmu.h81
-rw-r--r--plat/sun50iw1p1/include/gpio.h69
-rw-r--r--plat/sun50iw1p1/include/plat_macros.S106
-rw-r--r--plat/sun50iw1p1/include/platform_def.h135
-rw-r--r--plat/sun50iw1p1/include/uart.h43
-rw-r--r--plat/sun50iw1p1/mhu.c136
-rw-r--r--plat/sun50iw1p1/mhu.h43
-rw-r--r--plat/sun50iw1p1/plat_gic.c402
-rw-r--r--plat/sun50iw1p1/plat_pm.c335
-rw-r--r--plat/sun50iw1p1/plat_topology.c253
-rw-r--r--plat/sun50iw1p1/platform.mk91
-rw-r--r--plat/sun50iw1p1/scp/arisc.c248
-rw-r--r--plat/sun50iw1p1/scp/arisc.mk35
-rw-r--r--plat/sun50iw1p1/scp/arisc_i.h84
-rw-r--r--plat/sun50iw1p1/scp/hwmsgbox/hwmsgbox.c291
-rw-r--r--plat/sun50iw1p1/scp/hwmsgbox/hwmsgbox.mk31
-rw-r--r--plat/sun50iw1p1/scp/hwmsgbox/hwmsgbox_i.h46
-rw-r--r--plat/sun50iw1p1/scp/hwspinlock/hwspinlock.c109
-rw-r--r--plat/sun50iw1p1/scp/hwspinlock/hwspinlock.mk31
-rw-r--r--plat/sun50iw1p1/scp/hwspinlock/hwspinlock_i.h48
-rw-r--r--plat/sun50iw1p1/scp/include/arisc_cfgs.h74
-rw-r--r--plat/sun50iw1p1/scp/include/arisc_dbgs.h66
-rw-r--r--plat/sun50iw1p1/scp/include/arisc_hwmsgbox.h77
-rw-r--r--plat/sun50iw1p1/scp/include/arisc_hwspinlock.h63
-rw-r--r--plat/sun50iw1p1/scp/include/arisc_includes.h92
-rw-r--r--plat/sun50iw1p1/scp/include/arisc_message_manager.h73
-rw-r--r--plat/sun50iw1p1/scp/include/arisc_messages.h81
-rw-r--r--plat/sun50iw1p1/scp/include/arisc_para.h192
-rw-r--r--plat/sun50iw1p1/scp/interfaces/arisc_axp.c402
-rw-r--r--plat/sun50iw1p1/scp/interfaces/arisc_debug_level.c137
-rw-r--r--plat/sun50iw1p1/scp/interfaces/arisc_dram_crc.c57
-rw-r--r--plat/sun50iw1p1/scp/interfaces/arisc_dvfs.c81
-rw-r--r--plat/sun50iw1p1/scp/interfaces/arisc_loopback.c51
-rw-r--r--plat/sun50iw1p1/scp/interfaces/arisc_rsb.c329
-rw-r--r--plat/sun50iw1p1/scp/interfaces/arisc_standby.c286
-rw-r--r--plat/sun50iw1p1/scp/interfaces/interfaces.mk37
-rw-r--r--plat/sun50iw1p1/scp/message_manager/message_manager.c282
-rw-r--r--plat/sun50iw1p1/scp/message_manager/message_manager.mk31
-rw-r--r--plat/sun50iw1p1/scp/message_manager/message_manager_i.h40
-rw-r--r--plat/sun50iw1p1/scpi.c140
-rw-r--r--plat/sun50iw1p1/scpi.h82
-rw-r--r--plat/sun50iw1p1/sun50iw1p1.h127
-rw-r--r--plat/sun50iw1p1/sunxi_cpu_ops.c245
-rw-r--r--plat/sun50iw1p1/sunxi_cpu_ops.h39
-rw-r--r--plat/sun50iw1p1/sunxi_def.h124
-rw-r--r--plat/sun50iw1p1/sunxi_private.h107
-rw-r--r--plat/sun50iw1p1/sunxi_security.c110
-rw-r--r--plat/sun50iw1p1/tsp/tsp-wine.mk38
-rw-r--r--plat/sun50iw1p1/tsp/tsp_sunxi_setup.c101
59 files changed, 8779 insertions, 1 deletions
diff --git a/plat/fvp/platform.mk b/plat/fvp/platform.mk
index e7c06a8..73d6052 100644
--- a/plat/fvp/platform.mk
+++ b/plat/fvp/platform.mk
@@ -71,7 +71,8 @@ PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/pl011_console.S \
lib/semihosting/semihosting.c \
lib/semihosting/aarch64/semihosting_call.S \
plat/common/aarch64/plat_common.c \
- plat/fvp/fvp_io_storage.c
+ plat/fvp/fvp_io_storage.c
+
BL1_SOURCES += drivers/arm/cci400/cci400.c \
lib/cpus/aarch64/aem_generic.S \
diff --git a/plat/sun50iw1p1/aarch64/plat_helpers.S b/plat/sun50iw1p1/aarch64/plat_helpers.S
new file mode 100644
index 0000000..1bb225f
--- /dev/null
+++ b/plat/sun50iw1p1/aarch64/plat_helpers.S
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl_common.h>
+#include <cortex_a57.h>
+#include <cpu_macros.S>
+#include <platform_def.h>
+#include "../sunxi_def.h"
+
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_report_exception
+ .globl plat_reset_handler
+ .globl platform_get_core_pos
+ .globl platform_mem_init
+ .globl platform_smp_init
+
+ /* Define a crash console for the plaform */
+#define JUNO_CRASH_CONSOLE_BASE 0
+
+ /* ---------------------------------------------
+ * void plat_report_exception(unsigned int type)
+ * Function to report an unhandled exception
+ * with platform-specific means.
+ * On Juno platform, it updates the LEDs
+ * to indicate where we are
+ * ---------------------------------------------
+ */
+func plat_report_exception
+
+ ret
+
+ /*
+ * Return 0 to 3 for the A53s and 4 or 5 for the A57s
+ */
+func platform_get_core_pos
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+
+
+ /* -----------------------------------------------------
+ * void platform_mem_init(void);
+ *
+ * We don't need to carry out any memory initialization
+ * on Juno. The Secure RAM is accessible straight away.
+ * -----------------------------------------------------
+ */
+func platform_mem_init
+ ret
+
+ /* -----------------------------------------------------
+ * void plat_reset_handler(void);
+ *
+ * Implement workaround for defect id 831273 by enabling
+ * an event stream every 65536 cycles and set the L2 RAM
+ * latencies for Cortex-A57.
+ * -----------------------------------------------------
+ */
+func plat_reset_handler
+ /* Read the MIDR_EL1 */
+ mrs x0, midr_el1
+ ubfx x1, x0, MIDR_PN_SHIFT, #12
+ cmp w1, #((CORTEX_A57_MIDR >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
+ b.ne 1f
+
+ /* Change the L2 Data and Tag Ram latency to 3 cycles */
+ mov x0, #(L2_DATA_RAM_LATENCY_3_CYCLES | \
+ (L2_TAG_RAM_LATENCY_3_CYCLES << \
+ L2CTLR_TAG_RAM_LATENCY_SHIFT))
+ msr L2CTLR_EL1, x0
+
+1:
+ /* ---------------------------------------------
+ * Enable the event stream every 65536 cycles
+ * ---------------------------------------------
+ */
+ mov x0, #(0xf << EVNTI_SHIFT)
+ orr x0, x0, #EVNTEN_BIT
+ msr CNTKCTL_EL1, x0
+ isb
+ ret
+
+func platform_smp_init
+ mrs x0, ACTLR_EL3 // Read ACTLR_EL3
+ orr x0, x0, #(1 << 1) // Set CPUECTLR_EL1 access control bit
+ msr ACTLR_EL3, x0 // Write ACTLR_EL3
+ mrs x0, ACTLR_EL2 // Read ACTLR_EL2
+ orr x0, x0, #(1 << 1) // Set CPUECTLR_EL1 access control bit
+ msr ACTLR_EL2, x0 // Write ACTLR_EL2
+ mrs x0, S3_1_c15_c2_1 // Read CPUECTLR_EL1
+ orr x0, x0, #(1 << 6) // Set the SMPEN bit
+ msr S3_1_c15_c2_1, x0 // Write CPUECTLR_EL1
+ mov x0, #0x0
+ msr cntvoff_el2, x0
+ ret
+
+func console_core_putc
+ ldr x1, =0x01c28000
+1:
+ ldr w2, [x1,#20]
+ tbz w2, #6, 1b
+ str w0, [x1,#0]
+ ret
+
+func plat_crash_console_init
+ mov w0, #1
+ ret
+
+func plat_crash_console_putc
+ b console_core_putc
+
+
+
diff --git a/plat/sun50iw1p1/aarch64/sunxi_common.c b/plat/sun50iw1p1/aarch64/sunxi_common.c
new file mode 100644
index 0000000..b7de9d0
--- /dev/null
+++ b/plat/sun50iw1p1/aarch64/sunxi_common.c
@@ -0,0 +1,246 @@
+/*
+ * 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 <arm_gic.h>
+#include <bl_common.h>
+#include <cci400.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform.h>
+#include <plat_config.h>
+#include <xlat_tables.h>
+#include "../sunxi_def.h"
+#include "../sunxi_private.h"
+
+/*******************************************************************************
+ * plat_config 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.
+ ******************************************************************************/
+plat_config_t plat_config;
+
+/*
+ * 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 sunxi_mmap[] = {
+
+ //1G
+ { 0, 0, DRAM1_BASE, MT_DEVICE | MT_RW | MT_SECURE },
+ //2G
+ { DRAM1_BASE, DRAM1_BASE, SUNXI_MAX_DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS},
+ //TRUSTED dram for secure os and shared memory
+ { SUNXI_TRUSTED_DRAM_BASE, SUNXI_TRUSTED_DRAM_BASE, SUNXI_TRUSTED_DRAM_SIZE, MT_MEMORY | MT_RW | MT_SECURE },
+ { MEMRES_BASE, MEMRES_BASE, MEMRES_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 sunxi_configure_mmu_el##_el(unsigned long total_base, \
+ unsigned long total_size, \
+ unsigned long ro_start, \
+ unsigned long ro_limit, \
+ unsigned long coh_start, \
+ unsigned long coh_limit) \
+ { \
+ mmap_add_region(total_base, total_base, \
+ total_size, \
+ MT_MEMORY | MT_RW | MT_SECURE); \
+ mmap_add_region(ro_start, ro_start, \
+ ro_limit - ro_start, \
+ MT_MEMORY | MT_RO | MT_SECURE); \
+ mmap_add_region(coh_start, coh_start, \
+ coh_limit - coh_start, \
+ MT_DEVICE | MT_RW | MT_SECURE); \
+ mmap_add(sunxi_mmap); \
+ init_xlat_tables(); \
+ \
+ enable_mmu_el##_el(0); \
+ }
+
+void sunxi_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)
+{
+ mmap_add_region(total_base, total_base,
+ total_size,
+ MT_MEMORY | MT_RW | MT_SECURE);
+ mmap_add_region(ro_start, ro_start,
+ ro_limit - ro_start,
+ MT_MEMORY | MT_RO | MT_SECURE);
+ mmap_add_region(coh_start, coh_start,
+ coh_limit - coh_start,
+ MT_DEVICE | MT_RW | MT_SECURE);
+ mmap_add(sunxi_mmap);
+ init_xlat_tables();
+
+ enable_mmu_el3(0);
+}
+
+void sunxi_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)
+{
+ mmap_add_region(total_base, total_base,
+ total_size,
+ MT_MEMORY | MT_RW | MT_SECURE);
+ mmap_add_region(ro_start, ro_start,
+ ro_limit - ro_start,
+ MT_MEMORY | MT_RO | MT_SECURE);
+ mmap_add_region(coh_start, coh_start,
+ coh_limit - coh_start,
+ MT_DEVICE | MT_RW | MT_SECURE);
+ mmap_add(sunxi_mmap);
+ init_xlat_tables();
+
+ enable_mmu_el1(0);
+}
+
+
+/* Define EL1 and EL3 variants of the function initialising the MMU */
+//DEFINE_CONFIGURE_MMU_EL(1)
+//DEFINE_CONFIGURE_MMU_EL(3)
+
+/*******************************************************************************
+ * 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 sunxi_config_setup(void)
+{
+
+ 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 = 24<<20;//mmio_read_32(SYS_CNTCTL_BASE + CNTFID_OFF);
+
+ /* The first entry of the frequency modes table must not be 0 */
+ if (counter_base_frequency == 0)
+ panic();
+
+ return counter_base_frequency;
+}
+
+void sunxi_cci_init(void)
+{
+ /*
+ * Initialize CCI-400 driver
+ */
+
+}
+
+void sunxi_cci_enable(void)
+{
+ /*
+ * Enable CCI-400 coherency for this cluster. No need
+ * for locks as no other cpu is active at the
+ * moment
+ */
+
+}
+
+
+void sunxi_gic_init(void)
+{
+ gic_setup();
+}
+
+
+/*******************************************************************************
+ * Gets SPSR for BL32 entry
+ ******************************************************************************/
+uint32_t sunxi_get_spsr_for_bl32_entry(void)
+{
+ /*
+ * The Secure Payload Dispatcher service is responsible for
+ * setting the SPSR prior to entry into the BL32 image.
+ */
+ return 0;
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+uint32_t sunxi_get_spsr_for_bl33_entry(void)
+{
+ #if 0
+ unsigned long el_status;
+ unsigned int mode;
+ uint32_t spsr;
+
+ /* 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.
+ */
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+ #endif
+ return SPSR_MODE32(MODE32_svc,SPSR_T_ARM,SPSR_E_LITTLE,DISABLE_ALL_EXCEPTIONS);
+}
diff --git a/plat/sun50iw1p1/bl1_sunxi_setup.c b/plat/sun50iw1p1/bl1_sunxi_setup.c
new file mode 100644
index 0000000..b1205d4
--- /dev/null
+++ b/plat/sun50iw1p1/bl1_sunxi_setup.c
@@ -0,0 +1,136 @@
+/*
+ * 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 <console.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include "../../bl1/bl1_private.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__;
+
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned. It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
+ * page-aligned addresses.
+ */
+#define BL1_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL1_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+
+/* Data structure which holds the extents of the trusted 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 size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE;
+
+ /* Initialize the console to provide early debug support */
+ console_init(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE);
+
+ /* Allow BL1 to see the whole Trusted RAM */
+ bl1_tzram_layout.total_base = FVP_TRUSTED_SRAM_BASE;
+ bl1_tzram_layout.total_size = FVP_TRUSTED_SRAM_SIZE;
+
+ /* Calculate how much RAM BL1 is using and how much remains free */
+ bl1_tzram_layout.free_base = FVP_TRUSTED_SRAM_BASE;
+ bl1_tzram_layout.free_size = FVP_TRUSTED_SRAM_SIZE;
+ reserve_mem(&bl1_tzram_layout.free_base,
+ &bl1_tzram_layout.free_size,
+ BL1_RAM_BASE,
+ bl1_size);
+
+ /* 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_init();
+ fvp_cci_enable();
+
+ fvp_configure_mmu_el3(bl1_tzram_layout.total_base,
+ bl1_tzram_layout.total_size,
+ BL1_RO_BASE,
+ BL1_RO_LIMIT,
+ 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/sun50iw1p1/bl2_sunxi_setup.c b/plat/sun50iw1p1/bl2_sunxi_setup.c
new file mode 100644
index 0000000..d4fa4cb
--- /dev/null
+++ b/plat/sun50iw1p1/bl2_sunxi_setup.c
@@ -0,0 +1,285 @@
+/*
+ * 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__)
+
+/* 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")));
+
+/* Assert that BL3-1 parameters fit in shared memory */
+CASSERT((PARAMS_BASE + sizeof(bl2_to_bl31_params_mem_t)) <
+ (FVP_SHARED_RAM_BASE + FVP_SHARED_RAM_SIZE),
+ assert_bl31_params_do_not_fit_in_shared_memory);
+
+/*******************************************************************************
+ * 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;
+
+ /*
+ * 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, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE);
+
+ /* Setup the BL2 memory layout */
+ bl2_tzram_layout = *mem_layout;
+
+ /* 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(void)
+{
+ 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)
+{
+ SET_SECURITY_STATE(bl32_ep_info->h.attr, SECURE);
+ bl32_ep_info->spsr = fvp_get_spsr_for_bl32_entry();
+}
+
+/*******************************************************************************
+ * 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)
+{
+ SET_SECURITY_STATE(bl33_ep_info->h.attr, NON_SECURE);
+ bl33_ep_info->spsr = fvp_get_spsr_for_bl33_entry();
+}
+
+
+/*******************************************************************************
+ * 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_SIZE;
+ //(TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
+ bl32_meminfo->free_size =TSP_SEC_MEM_SIZE;
+ //(TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
+}
+
+
+/*******************************************************************************
+ * 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;
+}
diff --git a/plat/sun50iw1p1/bl31_sunxi_setup.c b/plat/sun50iw1p1/bl31_sunxi_setup.c
new file mode 100644
index 0000000..4237a25
--- /dev/null
+++ b/plat/sun50iw1p1/bl31_sunxi_setup.c
@@ -0,0 +1,275 @@
+/*
+ * 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 <arm_gic.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <bl31.h>
+#include <console.h>
+#include <mmio.h>
+#include <platform.h>
+#include <stddef.h>
+#include "sunxi_def.h"
+#include "sunxi_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 0
+#if RESET_TO_BL31
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_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
+#else
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+#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)
+{
+//#if RESET_TO_BL31
+#if 1
+
+ assert(sec_state_is_valid(type));
+
+ if (type == NON_SECURE)
+ return &bl33_image_ep_info;
+ else
+ return &bl32_image_ep_info;
+#else
+ entry_point_info_t *next_image_info;
+
+ assert(sec_state_is_valid(type));
+
+ next_image_info = (type == NON_SECURE) ?
+ bl2_to_bl31_params->bl33_ep_info :
+ bl2_to_bl31_params->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;
+#endif
+}
+
+/*******************************************************************************
+ * 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(SUNXI_UART0_BASE, UART0_CLK_IN_HZ, UART0_BAUDRATE);
+
+ /* Initialize the platform config for future decision making */
+ sunxi_config_setup();
+
+#if 0
+#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.
+ */
+ sunxi_security_setup();
+
+ /* Populate entry point information for BL3-2 and BL3-3 */
+ SET_PARAM_HEAD(&bl32_image_ep_info,
+ PARAM_EP,
+ VERSION_1,
+ 0);
+ SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+ bl32_image_ep_info.pc = BL32_BASE;
+ bl32_image_ep_info.spsr = sunxi_get_spsr_for_bl32_entry();
+
+ SET_PARAM_HEAD(&bl33_image_ep_info,
+ PARAM_EP,
+ VERSION_1,
+ 0);
+ /*
+ * Tell BL31 where the non-trusted software image
+ * is located and the entry state information
+ */
+ bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+ bl33_image_ep_info.spsr = sunxi_get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#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);
+ sunxi_security_setup();
+ bl2_to_bl31_params = from_bl2;
+ assert(((unsigned long)plat_params_from_bl2) == SUNXI_BL31_PLAT_PARAM_VAL);
+#endif
+#endif
+ /*
+ * 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.
+ */
+ sunxi_security_setup();
+ /*
+ * Tell BL31 where the non-trusted software image
+ * is located and the entry state information
+ */
+ bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+ bl33_image_ep_info.spsr = sunxi_get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+
+
+}
+
+/*******************************************************************************
+ * Initialize the gic, configure the CLCD and zero out variables needed by the
+ * secondaries to boot up correctly.
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+
+ //unsigned int reg_val;
+
+ /* Initialize the gic cpu and distributor interfaces */
+ sunxi_gic_init();
+#if 0
+
+ /*
+ * 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);
+#endif
+
+ /* Intialize the power controller */
+ //sunxi_pwrc_setup();
+
+ /* Topologies are best known to the platform. */
+ sunxi_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(void)
+{
+ //set smp bit before cache enable
+ platform_smp_init();
+#if 1
+ sunxi_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);
+#endif
+
+}
diff --git a/plat/sun50iw1p1/drivers/gpio/gpio.c b/plat/sun50iw1p1/drivers/gpio/gpio.c
new file mode 100644
index 0000000..f741041
--- /dev/null
+++ b/plat/sun50iw1p1/drivers/gpio/gpio.c
@@ -0,0 +1,228 @@
+/*
+**********************************************************************************************************************
+*
+* the Embedded Secure Bootloader System
+*
+*
+* Copyright(C), 2006-2014, Allwinnertech Co., Ltd.
+* All Rights Reserved
+*
+* File :
+*
+* By :
+*
+* Version : V2.00
+*
+* Date :
+*
+* Descript:
+**********************************************************************************************************************
+*/
+
+
+#include "../../sunxi_def.h"
+#include <gpio.h>
+
+#define GPIO_REG_READ(reg) mmio_read_32((reg))
+#define GPIO_REG_WRITE(reg, value) mmio_write_32((reg),(value))
+
+/*
+************************************************************************************************************
+*
+* normal_gpio_cfg
+*
+* 函数名称:
+*
+* 参数列表:
+*
+*
+*
+* 返回值 :
+*
+* 说明 :
+*
+*
+************************************************************************************************************
+*/
+int32_t boot_set_gpio(void *user_gpio_list, uint32_t group_count_max, int32_t set_gpio)
+{
+ normal_gpio_set_t *tmp_user_gpio_data, *gpio_list;
+ uint32_t first_port; //保存真正有效的GPIO的个数
+ uint32_t tmp_group_func_data;
+ uint32_t tmp_group_pull_data;
+ uint32_t tmp_group_dlevel_data;
+ uint32_t tmp_group_data_data;
+ uint32_t data_change = 0;
+ uint32_t tmp_group_func_addr, tmp_group_pull_addr;
+ uint32_t tmp_group_dlevel_addr, tmp_group_data_addr;
+ uint32_t port, port_num, port_num_func, port_num_pull;
+ uint32_t pre_port, pre_port_num_func;
+ uint32_t pre_port_num_pull;
+ int32_t i, tmp_val;
+
+
+ gpio_list = (normal_gpio_set_t *)user_gpio_list;
+
+ for(first_port = 0; first_port < group_count_max; first_port++)
+ {
+ tmp_user_gpio_data = gpio_list + first_port;
+ port = tmp_user_gpio_data->port; //读出端口数值
+ port_num = tmp_user_gpio_data->port_num; //读出端口中的某一个GPIO
+ if(!port)
+ {
+ continue;
+ }
+ port_num_func = (port_num >> 3);
+ port_num_pull = (port_num >> 4);
+
+ tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); //更新功能寄存器地址
+ tmp_group_pull_addr = PIO_REG_PULL(port, port_num_pull); //更新pull寄存器
+ tmp_group_dlevel_addr = PIO_REG_DLEVEL(port, port_num_pull);//更新level寄存器
+ tmp_group_data_addr = PIO_REG_DATA(port); //更新data寄存器
+
+ tmp_group_func_data = GPIO_REG_READ(tmp_group_func_addr);
+ tmp_group_pull_data = GPIO_REG_READ(tmp_group_pull_addr);
+ tmp_group_dlevel_data = GPIO_REG_READ(tmp_group_dlevel_addr);
+ tmp_group_data_data = GPIO_REG_READ(tmp_group_data_addr);
+
+ pre_port = port;
+ pre_port_num_func = port_num_func;
+ pre_port_num_pull = port_num_pull;
+ //更新功能寄存器
+ tmp_val = (port_num - (port_num_func << 3)) << 2;
+ tmp_group_func_data &= ~(0x07 << tmp_val);
+ if(set_gpio)
+ {
+ tmp_group_func_data |= (tmp_user_gpio_data->mul_sel & 0x07) << tmp_val;
+ }
+ //根据pull的值决定是否更新pull寄存器
+ tmp_val = (port_num - (port_num_pull << 4)) << 1;
+ if(tmp_user_gpio_data->pull >= 0)
+ {
+ tmp_group_pull_data &= ~( 0x03 << tmp_val);
+ tmp_group_pull_data |= (tmp_user_gpio_data->pull & 0x03) << tmp_val;
+ }
+ //根据driver level的值决定是否更新driver level寄存器
+ if(tmp_user_gpio_data->drv_level >= 0)
+ {
+ tmp_group_dlevel_data &= ~( 0x03 << tmp_val);
+ tmp_group_dlevel_data |= (tmp_user_gpio_data->drv_level & 0x03) << tmp_val;
+ }
+ //根据用户输入,以及功能分配决定是否更新data寄存器
+ if(tmp_user_gpio_data->mul_sel == 1)
+ {
+ if(tmp_user_gpio_data->data >= 0)
+ {
+ tmp_val = tmp_user_gpio_data->data & 1;
+ tmp_group_data_data &= ~(1 << port_num);
+ tmp_group_data_data |= tmp_val << port_num;
+ data_change = 1;
+ }
+ }
+
+ break;
+ }
+ //检查是否有数据存在
+ if(first_port >= group_count_max)
+ {
+ return -1;
+ }
+ //保存用户数据
+ for(i = first_port + 1; i < group_count_max; i++)
+ {
+ tmp_user_gpio_data = gpio_list + i; //gpio_set依次指向用户的每个GPIO数组成员
+ port = tmp_user_gpio_data->port; //读出端口数值
+ port_num = tmp_user_gpio_data->port_num; //读出端口中的某一个GPIO
+ if(!port)
+ {
+ break;
+ }
+ port_num_func = (port_num >> 3);
+ port_num_pull = (port_num >> 4);
+
+ if((port_num_pull != pre_port_num_pull) || (port != pre_port)) //如果发现当前引脚的端口不一致,或者所在的pull寄存器不一致
+ {
+ GPIO_REG_WRITE(tmp_group_func_addr, tmp_group_func_data); //回写功能寄存器
+ GPIO_REG_WRITE(tmp_group_pull_addr, tmp_group_pull_data); //回写pull寄存器
+ GPIO_REG_WRITE(tmp_group_dlevel_addr, tmp_group_dlevel_data); //回写driver level寄存器
+ if(data_change)
+ {
+ data_change = 0;
+ GPIO_REG_WRITE(tmp_group_data_addr, tmp_group_data_data); //回写data寄存器
+ }
+
+ tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); //更新功能寄存器地址
+ tmp_group_pull_addr = PIO_REG_PULL(port, port_num_pull); //更新pull寄存器
+ tmp_group_dlevel_addr = PIO_REG_DLEVEL(port, port_num_pull);//更新level寄存器
+ tmp_group_data_addr = PIO_REG_DATA(port); //更新data寄存器
+
+ tmp_group_func_data = GPIO_REG_READ(tmp_group_func_addr);
+ tmp_group_pull_data = GPIO_REG_READ(tmp_group_pull_addr);
+ tmp_group_dlevel_data = GPIO_REG_READ(tmp_group_dlevel_addr);
+ tmp_group_data_data = GPIO_REG_READ(tmp_group_data_addr);
+ }
+ else if(pre_port_num_func != port_num_func) //如果发现当前引脚的功能寄存器不一致
+ {
+ GPIO_REG_WRITE(tmp_group_func_addr, tmp_group_func_data); //则只回写功能寄存器
+ tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); //更新功能寄存器地址
+
+ tmp_group_func_data = GPIO_REG_READ(tmp_group_func_addr);
+ }
+ //保存当前硬件寄存器数据
+ pre_port_num_pull = port_num_pull; //设置当前GPIO成为前一个GPIO
+ pre_port_num_func = port_num_func;
+ pre_port = port;
+
+ //更新功能寄存器
+ tmp_val = (port_num - (port_num_func << 3)) << 2;
+ if(tmp_user_gpio_data->mul_sel >= 0)
+ {
+ tmp_group_func_data &= ~( 0x07 << tmp_val);
+ if(set_gpio)
+ {
+ tmp_group_func_data |= (tmp_user_gpio_data->mul_sel & 0x07) << tmp_val;
+ }
+ }
+ //根据pull的值决定是否更新pull寄存器
+ tmp_val = (port_num - (port_num_pull << 4)) << 1;
+ if(tmp_user_gpio_data->pull >= 0)
+ {
+ tmp_group_pull_data &= ~( 0x03 << tmp_val);
+ tmp_group_pull_data |= (tmp_user_gpio_data->pull & 0x03) << tmp_val;
+ }
+ //根据driver level的值决定是否更新driver level寄存器
+ if(tmp_user_gpio_data->drv_level >= 0)
+ {
+ tmp_group_dlevel_data &= ~( 0x03 << tmp_val);
+ tmp_group_dlevel_data |= (tmp_user_gpio_data->drv_level & 0x03) << tmp_val;
+ }
+ //根据用户输入,以及功能分配决定是否更新data寄存器
+ if(tmp_user_gpio_data->mul_sel == 1)
+ {
+ if(tmp_user_gpio_data->data >= 0)
+ {
+ tmp_val = tmp_user_gpio_data->data & 1;
+ tmp_group_data_data &= ~(1 << port_num);
+ tmp_group_data_data |= tmp_val << port_num;
+ data_change = 1;
+ }
+ }
+ }
+ //for循环结束,如果存在还没有回写的寄存器,这里写回到硬件当中
+ if(tmp_group_func_addr) //只要更新过寄存器地址,就可以对硬件赋值
+ { //那么把所有的值全部回写到硬件寄存器
+ GPIO_REG_WRITE(tmp_group_func_addr, tmp_group_func_data); //回写功能寄存器
+ GPIO_REG_WRITE(tmp_group_pull_addr, tmp_group_pull_data); //回写pull寄存器
+ GPIO_REG_WRITE(tmp_group_dlevel_addr, tmp_group_dlevel_data); //回写driver level寄存器
+ if(data_change)
+ {
+ GPIO_REG_WRITE(tmp_group_data_addr, tmp_group_data_data); //回写data寄存器
+ }
+ }
+
+ return 0;
+}
+
+
+
+
diff --git a/plat/sun50iw1p1/drivers/uart/uart.c b/plat/sun50iw1p1/drivers/uart/uart.c
new file mode 100644
index 0000000..710957c
--- /dev/null
+++ b/plat/sun50iw1p1/drivers/uart/uart.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <mmio.h>
+#include <uart.h>
+#include <gpio.h>
+#include <ccmu.h>
+#if DEBUG
+#define thr rbr
+#define dll rbr
+#define dlh ier
+#define iir fcr
+
+static serial_hw_t *serial_ctrl_base = NULL;
+static uint32_t uart_lock = 1;
+#if 0
+normal_gpio_set_t uart_ctrl[2] =
+{
+ { 2, 8, 4, 1, 1, 0, {0}},//PB8: 4--RX
+ { 2, 9, 4, 1, 1, 0, {0}},//PB9: 4--TX
+};
+#endif
+
+void sunxi_serial_init(int uart_port, void *gpio_cfg, int gpio_max)
+{
+ uint32_t reg, i;
+ uint32_t uart_clk;
+
+ if( (uart_port < 0) ||(uart_port > 0) )
+ {
+ return ;
+ }
+ //reset
+ reg = mmio_read_32(CCMU_BUS_SOFT_RST_REG4);
+ reg &= ~(1<<(CCM_UART_PORT_OFFSET + uart_port));
+ mmio_write_32(CCMU_BUS_SOFT_RST_REG4,reg);
+ for( i = 0; i < 100; i++ );
+ reg |= (1<<(CCM_UART_PORT_OFFSET + uart_port));
+ mmio_write_32(CCMU_BUS_SOFT_RST_REG4,reg);
+ //gate
+ reg = mmio_read_32(CCMU_BUS_CLK_GATING_REG3);
+ reg &= ~(1<<(CCM_UART_PORT_OFFSET + uart_port));
+ mmio_write_32(CCMU_BUS_CLK_GATING_REG3,reg);
+ for( i = 0; i < 100; i++ );
+ reg |= (1<<(CCM_UART_PORT_OFFSET + uart_port));
+ mmio_write_32(CCMU_BUS_CLK_GATING_REG3,reg);
+
+ //gpio
+ //boot_set_gpio(gpio_cfg, gpio_max, 1); //boot set,so not need to set again
+ //uart init
+ serial_ctrl_base = (serial_hw_t *)(SUNXI_UART0_BASE + uart_port * CCM_UART_ADDR_OFFSET);
+ serial_ctrl_base->mcr = 0x3;
+ uart_clk = (24000000 + 8 * UART_BAUD)/(16 * UART_BAUD);
+ serial_ctrl_base->lcr |= 0x80;
+ serial_ctrl_base->dlh = uart_clk>>8;
+ serial_ctrl_base->dll = uart_clk&0xff;
+ serial_ctrl_base->lcr &= ~0x80;
+ serial_ctrl_base->lcr = ((PARITY&0x03)<<3) | ((STOP&0x01)<<2) | (DLEN&0x03);
+ serial_ctrl_base->fcr = 0x7;
+
+ uart_lock = 0;
+
+ return;
+}
+
+
+void sunxi_serial_exit(void)
+{
+ uart_lock = 1;
+}
+
+void sunxi_serial_putc (char c)
+{
+ if (uart_lock)
+ return;
+
+ while((serial_ctrl_base->lsr & ( 1 << 6 )) == 0);
+ serial_ctrl_base->thr = c;
+}
+
+
+char sunxi_serial_getc (void)
+{
+ if (uart_lock)
+ return 0;
+
+ while((serial_ctrl_base->lsr & 1) == 0);
+ return serial_ctrl_base->rbr;
+
+}
+
+int sunxi_serial_tstc (void)
+{
+ return serial_ctrl_base->lsr & 1;
+}
+#endif /* DEBUG */
+
+int console_init(unsigned long base_addr,
+ unsigned int uart_clk, unsigned int baud_rate)
+{
+ sunxi_serial_init(0,NULL,0);
+ return 0;
+}
+
+int console_exit()
+{
+ sunxi_serial_exit();
+ return 0;
+}
+
+int console_putc(int c)
+{
+ sunxi_serial_putc(c);
+ return 0;
+}
+
+int console_getc(void)
+{
+ return sunxi_serial_getc();
+}
+
diff --git a/plat/sun50iw1p1/gic_sunxi.h b/plat/sun50iw1p1/gic_sunxi.h
new file mode 100644
index 0000000..f52bde4
--- /dev/null
+++ b/plat/sun50iw1p1/gic_sunxi.h
@@ -0,0 +1,344 @@
+/*
+ * 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 __GIC_SUNXI_H_
+#define __GIC_SUNXI_H_
+
+
+#include "sunxi_def.h"
+/*irq num*/
+#define GIC_SRC_SPI(_n) (32 + (_n))
+#define AW_IRQ_UART0 GIC_SRC_SPI(0) /* 32 */
+#define AW_IRQ_UART1 GIC_SRC_SPI(1) /* 33 */
+#define AW_IRQ_UART2 GIC_SRC_SPI(2) /* 34 */
+#define AW_IRQ_UART3 GIC_SRC_SPI(3) /* 35 */
+#define AW_IRQ_UART4 GIC_SRC_SPI(4) /* 36 */
+
+#define AW_IRQ_TWI0 GIC_SRC_SPI(6) /* 38 */
+#define AW_IRQ_TWI1 GIC_SRC_SPI(7) /* 39 */
+#define AW_IRQ_TWI2 GIC_SRC_SPI(8) /* 40 */
+
+#define AW_IRQ_PBEINT GIC_SRC_SPI(11) /* 43 */
+#define AW_IRQ_OWA GIC_SRC_SPI(12) /* 44*/
+#define AW_IRQ_DAUDIO0 GIC_SRC_SPI(13) /* 45 */
+#define AW_IRQ_DAUDIO1 GIC_SRC_SPI(14) /* 46 */
+#define AW_IRQ_DAUDIO2 GIC_SRC_SPI(15) /* 47 */
+
+#define AW_IRQ_PG_EINT GIC_SRC_SPI(17) /* 49 */
+#define AW_IRQ_TIMER0 GIC_SRC_SPI(18) /* 50 */
+#define AW_IRQ_TIMER1 GIC_SRC_SPI(19) /* 51 */
+#define AW_IRQ_PH_EINT GIC_SRC_SPI(21) /* 53 */
+
+#define AW_IRQ_WATCHDOG GIC_SRC_SPI(25) /* 57*/
+#define AW_IRQ_NMI GIC_SRC_SPI(32) /* 64*/
+
+
+#define AW_IRQ_DMA GIC_SRC_SPI(50) /* 82 */
+#define AW_IRQ_HSTIMER GIC_SRC_SPI(51) /* 83 */
+#define AW_IRQ_SMC GIC_SRC_SPI(56) /* 88 */
+#define AW_IRQ_MMC0 GIC_SRC_SPI(60) /* 92 */
+#define AW_IRQ_MMC1 GIC_SRC_SPI(61) /* 93 */
+#define AW_IRQ_MMC2 GIC_SRC_SPI(62) /* 94 */
+#define AW_IRQ_SPI0 GIC_SRC_SPI(65) /* 97 */
+#define AW_IRQ_SPI1 GIC_SRC_SPI(66) /* 98 */
+#define AW_IRQ_NAND GIC_SRC_SPI(70) /* 102 */
+#define AW_IRQ_USB_OTG GIC_SRC_SPI(71) /* 103 */
+#define AW_IRQ_USB_EHCI0 GIC_SRC_SPI(72) /* 104*/
+#define AW_IRQ_USB_OHCI0 GIC_SRC_SPI(73) /* 105 */
+#define AW_IRQ_USB_EHCI1 GIC_SRC_SPI(74) /* 106 */
+#define AW_IRQ_USB_OHCI1 GIC_SRC_SPI(75) /* 107 */
+
+#define AW_IRQ_CE0 GIC_SRC_SPI(80) /* 112 */
+#define AW_IRQ_TS GIC_SRC_SPI(81) /* 113 */
+#define AW_IRQ_EMC GIC_SRC_SPI(82) /* 114 */
+#define AW_IRQ_SCR GIC_SRC_SPI(83) /* 115 */
+#define AW_IRQ_CSI GIC_SRC_SPI(84) /* 116 */
+#define AW_IRQ_CSI_CCI GIC_SRC_SPI(85) /* 117 */
+#define AW_IRQ_TCON0 GIC_SRC_SPI(86) /* 118 */
+#define AW_IRQ_TCON1 GIC_SRC_SPI(87) /* 119 */
+#define AW_IRQ_HDMI GIC_SRC_SPI(88) /* 120 */
+#define AW_IRQ_MIPI_DSI GIC_SRC_SPI(89) /* 121 */
+
+#define AW_IRQ_DIT GIC_SRC_SPI(93) /* 125 */
+#define AW_IRQ_CE1 GIC_SRC_SPI(94) /* 126 */
+#define AW_IRQ_DE GIC_SRC_SPI(95) /* 127 */
+#define AW_IRQ_ROT GIC_SRC_SPI(96) /* 128 */
+#define AW_IRQ_GPU_GP GIC_SRC_SPI(97) /* 129 */
+#define AW_IRQ_GPU_GPMMU GIC_SRC_SPI(98) /* 130 */
+#define AW_IRQ_GPU_PP0 GIC_SRC_SPI(99) /* 131 */
+#define AW_IRQ_GPU_PP0MMU GIC_SRC_SPI(100) /* 132 */
+#define AW_IRQ_GPU_PMU GIC_SRC_SPI(101) /* 133 */
+#define AW_IRQ_GPU_PP1 GIC_SRC_SPI(102) /* 134 */
+#define AW_IRQ_GPU_PPMMU1 GIC_SRC_SPI(103) /* 135 */
+
+#define AW_IRQ_CTI0 GIC_SRC_SPI(108) /* 140 */
+#define AW_IRQ_CTI1 GIC_SRC_SPI(109) /* 141 */
+#define AW_IRQ_CTI2 GIC_SRC_SPI(110) /* 142 */
+#define AW_IRQ_CTI3 GIC_SRC_SPI(111) /* 143 */
+#define AW_IRQ_COMMTX0 GIC_SRC_SPI(112) /* 144 */
+#define AW_IRQ_COMMTX1 GIC_SRC_SPI(113) /* 145 */
+#define AW_IRQ_COMMTX2 GIC_SRC_SPI(114) /* 146 */
+#define AW_IRQ_COMMTX3 GIC_SRC_SPI(115) /* 147 */
+#define AW_IRQ_COMMRX0 GIC_SRC_SPI(116) /* 148 */
+#define AW_IRQ_COMMRX1 GIC_SRC_SPI(117) /* 149 */
+#define AW_IRQ_COMMRX2 GIC_SRC_SPI(118) /* 150 */
+#define AW_IRQ_COMMRX3 GIC_SRC_SPI(119) /* 151 */
+#define AW_IRQ_PMU0 GIC_SRC_SPI(120) /* 152 */
+#define AW_IRQ_PMU1 GIC_SRC_SPI(121) /* 153 */
+#define AW_IRQ_PMU2 GIC_SRC_SPI(122) /* 154 */
+#define AW_IRQ_PMU3 GIC_SRC_SPI(123) /* 155 */
+#define AW_IRQ_AXI_ERROR GIC_SRC_SPI(124) /*156*/
+#define GIC_IRQ_NUM (AW_IRQ_AXI_ERROR + 1)
+/*irq num end*/
+
+
+
+/* GIC registers */
+#define GIC_DIST_CON (ARMA9_GIC_BASE + 0x0000)
+#define GIC_CON_TYPE (ARMA9_GIC_BASE + 0x0004)
+#define GIC_CON_IIDR (ARMA9_GIC_BASE + 0x0008)
+
+#define GIC_CON_IGRP(n) (ARMA9_GIC_BASE + 0x0080 + (n)*4)
+
+#define GIC_SET_EN(_n) (ARMA9_GIC_BASE + 0x100 + 4 * (_n))
+#define GIC_SET_EN0 GIC_SET_EN(0) // 0x100
+#define GIC_SET_EN1 GIC_SET_EN(1) // 0x104
+#define GIC_SET_EN2 GIC_SET_EN(2) // 0x108
+#define GIC_SET_EN3 GIC_SET_EN(3) // 0x10c
+#define GIC_SET_EN4 GIC_SET_EN(4) // 0x110
+
+#define GIC_CLR_EN(_n) (ARMA9_GIC_BASE + 0x180 + 4 * (_n))
+#define GIC_CLR_EN0 GIC_CLR_EN(0) // 0x180
+#define GIC_CLR_EN1 GIC_CLR_EN(1) // 0x184
+#define GIC_CLR_EN2 GIC_CLR_EN(2) // 0x188
+#define GIC_CLR_EN3 GIC_CLR_EN(3) // 0x18c
+#define GIC_CLR_EN4 GIC_CLR_EN(4) // 0x190
+
+#define GIC_PEND_SET(_n) (ARMA9_GIC_BASE + 0x200 + 4 * (_n))
+#define GIC_PEND_SET0 GIC_PEND_SET(0) // 0x200
+#define GIC_PEND_SET1 GIC_PEND_SET(1) // 0x204
+#define GIC_PEND_SET2 GIC_PEND_SET(2) // 0x208
+#define GIC_PEND_SET3 GIC_PEND_SET(3) // 0x20c
+#define GIC_PEND_SET4 GIC_PEND_SET(4) // 0x210
+
+#define GIC_PEND_CLR(_n) (ARMA9_GIC_BASE + 0x280 + 4 * (_n))
+#define GIC_PEND_CLR0 GIC_PEND_CLR(0) // 0x280
+#define GIC_PEND_CLR1 GIC_PEND_CLR(1) // 0x284
+#define GIC_PEND_CLR2 GIC_PEND_CLR(2) // 0x288
+#define GIC_PEND_CLR3 GIC_PEND_CLR(3) // 0x28c
+#define GIC_PEND_CLR4 GIC_PEND_CLR(4) // 0x290
+
+#define GIC_ACT_SET(_n) (ARMA9_GIC_BASE + 0x300 + 4 * (_n))
+#define GIC_ACT_SET0 GIC_ACT_SET(0) // 0x300
+#define GIC_ACT_SET1 GIC_ACT_SET(1) // 0x304
+#define GIC_ACT_SET2 GIC_ACT_SET(2) // 0x308
+#define GIC_ACT_SET3 GIC_ACT_SET(3) // 0x30c
+#define GIC_ACT_SET4 GIC_ACT_SET(4) // 0x310
+
+#define GIC_ACT_CLR(_n) (ARMA9_GIC_BASE + 0x380 + 4 * (_n))
+#define GIC_ACT_CLR0 GIC_ACT_CLR(0) // 0x380
+#define GIC_ACT_CLR1 GIC_ACT_CLR(1) // 0x384
+#define GIC_ACT_CLR2 GIC_ACT_CLR(2) // 0x388
+#define GIC_ACT_CLR3 GIC_ACT_CLR(3) // 0x38c
+#define GIC_ACT_CLR4 GIC_ACT_CLR(4) // 0x390
+
+#define GIC_SGI_PRIO(_n) (ARMA9_GIC_BASE + 0x400 + 4 * (_n))
+#define GIC_SGI_PRIO0 GIC_SGI_PRIO(0) // 0x400
+#define GIC_SGI_PRIO1 GIC_SGI_PRIO(1) // 0x404
+#define GIC_SGI_PRIO2 GIC_SGI_PRIO(2) // 0x408
+#define GIC_SGI_PRIO3 GIC_SGI_PRIO(3) // 0x40C
+
+#define GIC_PPI_PRIO(_n) (ARMA9_GIC_BASE + 0x410 + 4 * (_n))
+#define GIC_PPI_PRIO0 GIC_PPI_PRIO(0) // 0x410
+#define GIC_PPI_PRIO1 GIC_PPI_PRIO(1) // 0x414
+#define GIC_PPI_PRIO2 GIC_PPI_PRIO(2) // 0x418
+#define GIC_PPI_PRIO3 GIC_PPI_PRIO(3) // 0x41C
+
+#define GIC_SPI_PRIO(_n) (ARMA9_GIC_BASE + 0x420 + 4 * (_n))
+#define GIC_SPI_PRIO0 GIC_SPI_PRIO(0 ) // 0x420
+#define GIC_SPI_PRIO1 GIC_SPI_PRIO(1 ) // 0x424
+#define GIC_SPI_PRIO2 GIC_SPI_PRIO(2 ) // 0x428
+#define GIC_SPI_PRIO3 GIC_SPI_PRIO(3 ) // 0x42C
+#define GIC_SPI_PRIO4 GIC_SPI_PRIO(4 ) // 0x430
+#define GIC_SPI_PRIO5 GIC_SPI_PRIO(5 ) // 0x434
+#define GIC_SPI_PRIO6 GIC_SPI_PRIO(6 ) // 0x438
+#define GIC_SPI_PRIO7 GIC_SPI_PRIO(7 ) // 0x43C
+#define GIC_SPI_PRIO8 GIC_SPI_PRIO(8 ) // 0x440
+#define GIC_SPI_PRIO9 GIC_SPI_PRIO(9 ) // 0x444
+#define GIC_SPI_PRIO10 GIC_SPI_PRIO(10) // 0x448
+#define GIC_SPI_PRIO11 GIC_SPI_PRIO(11) // 0x44C
+#define GIC_SPI_PRIO12 GIC_SPI_PRIO(12) // 0x450
+#define GIC_SPI_PRIO13 GIC_SPI_PRIO(13) // 0x454
+#define GIC_SPI_PRIO14 GIC_SPI_PRIO(14) // 0x458
+#define GIC_SPI_PRIO15 GIC_SPI_PRIO(15) // 0x45C
+#define GIC_SPI_PRIO16 GIC_SPI_PRIO(16) // 0x460
+#define GIC_SPI_PRIO17 GIC_SPI_PRIO(17) // 0x464
+#define GIC_SPI_PRIO18 GIC_SPI_PRIO(18) // 0x468
+#define GIC_SPI_PRIO19 GIC_SPI_PRIO(19) // 0x46C
+#define GIC_SPI_PRIO20 GIC_SPI_PRIO(20) // 0x470
+#define GIC_SPI_PRIO21 GIC_SPI_PRIO(21) // 0x474
+#define GIC_SPI_PRIO22 GIC_SPI_PRIO(22) // 0x478
+#define GIC_SPI_PRIO23 GIC_SPI_PRIO(23) // 0x47C
+#define GIC_SPI_PRIO24 GIC_SPI_PRIO(24) // 0x480
+#define GIC_SPI_PRIO25 GIC_SPI_PRIO(25) // 0x484
+#define GIC_SPI_PRIO26 GIC_SPI_PRIO(26) // 0x488
+#define GIC_SPI_PRIO27 GIC_SPI_PRIO(27) // 0x48C
+#define GIC_SPI_PRIO28 GIC_SPI_PRIO(28) // 0x490
+#define GIC_SPI_PRIO29 GIC_SPI_PRIO(29) // 0x494
+#define GIC_SPI_PRIO30 GIC_SPI_PRIO(30) // 0x498
+#define GIC_SPI_PRIO31 GIC_SPI_PRIO(31) // 0x49C
+
+#define GIC_SGI_PROC_TARG(_n) (ARMA9_GIC_BASE + 0x800 + 4 * (_n))
+#define GIC_SGI_PROC_TARG0 GIC_SGI_PROC_TARG(0) // 0x800
+#define GIC_SGI_PROC_TARG1 GIC_SGI_PROC_TARG(1) // 0x804
+#define GIC_SGI_PROC_TARG2 GIC_SGI_PROC_TARG(2) // 0x808
+#define GIC_SGI_PROC_TARG3 GIC_SGI_PROC_TARG(3) // 0x80C
+
+#define GIC_PPI_PROC_TARG(_n) (ARMA9_GIC_BASE + 0x810 + 4 * (_n))
+#define GIC_PPI_PROC_TARG0 GIC_PPI_PROC_TARG(0) // 0x810
+#define GIC_PPI_PROC_TARG1 GIC_PPI_PROC_TARG(1) // 0x814
+#define GIC_PPI_PROC_TARG2 GIC_PPI_PROC_TARG(2) // 0x818
+#define GIC_PPI_PROC_TARG3 GIC_PPI_PROC_TARG(3) // 0x81C
+
+#define GIC_SPI_PROC_TARG(_n) (ARMA9_GIC_BASE + 0x820 + 4 * (_n))
+#define GIC_SPI_PROC_TARG0 GIC_SPI_PROC_TARG(0 ) // 0x820
+#define GIC_SPI_PROC_TARG1 GIC_SPI_PROC_TARG(1 ) // 0x824
+#define GIC_SPI_PROC_TARG2 GIC_SPI_PROC_TARG(2 ) // 0x828
+#define GIC_SPI_PROC_TARG3 GIC_SPI_PROC_TARG(3 ) // 0x82C
+#define GIC_SPI_PROC_TARG4 GIC_SPI_PROC_TARG(4 ) // 0x830
+#define GIC_SPI_PROC_TARG5 GIC_SPI_PROC_TARG(5 ) // 0x834
+#define GIC_SPI_PROC_TARG6 GIC_SPI_PROC_TARG(6 ) // 0x838
+#define GIC_SPI_PROC_TARG7 GIC_SPI_PROC_TARG(7 ) // 0x83C
+#define GIC_SPI_PROC_TARG8 GIC_SPI_PROC_TARG(8 ) // 0x840
+#define GIC_SPI_PROC_TARG9 GIC_SPI_PROC_TARG(9 ) // 0x844
+#define GIC_SPI_PROC_TARG10 GIC_SPI_PROC_TARG(10) // 0x848
+#define GIC_SPI_PROC_TARG11 GIC_SPI_PROC_TARG(11) // 0x84C
+#define GIC_SPI_PROC_TARG12 GIC_SPI_PROC_TARG(12) // 0x850
+#define GIC_SPI_PROC_TARG13 GIC_SPI_PROC_TARG(13) // 0x854
+#define GIC_SPI_PROC_TARG14 GIC_SPI_PROC_TARG(14) // 0x858
+#define GIC_SPI_PROC_TARG15 GIC_SPI_PROC_TARG(15) // 0x85C
+#define GIC_SPI_PROC_TARG16 GIC_SPI_PROC_TARG(16) // 0x860
+#define GIC_SPI_PROC_TARG17 GIC_SPI_PROC_TARG(17) // 0x864
+#define GIC_SPI_PROC_TARG18 GIC_SPI_PROC_TARG(18) // 0x868
+#define GIC_SPI_PROC_TARG19 GIC_SPI_PROC_TARG(19) // 0x86C
+#define GIC_SPI_PROC_TARG20 GIC_SPI_PROC_TARG(20) // 0x870
+#define GIC_SPI_PROC_TARG21 GIC_SPI_PROC_TARG(21) // 0x874
+#define GIC_SPI_PROC_TARG22 GIC_SPI_PROC_TARG(22) // 0x878
+#define GIC_SPI_PROC_TARG23 GIC_SPI_PROC_TARG(23) // 0x87C
+#define GIC_SPI_PROC_TARG24 GIC_SPI_PROC_TARG(24) // 0x880
+#define GIC_SPI_PROC_TARG25 GIC_SPI_PROC_TARG(25) // 0x884
+#define GIC_SPI_PROC_TARG26 GIC_SPI_PROC_TARG(26) // 0x888
+#define GIC_SPI_PROC_TARG27 GIC_SPI_PROC_TARG(27) // 0x88C
+#define GIC_SPI_PROC_TARG28 GIC_SPI_PROC_TARG(28) // 0x890
+#define GIC_SPI_PROC_TARG29 GIC_SPI_PROC_TARG(29) // 0x894
+#define GIC_SPI_PROC_TARG30 GIC_SPI_PROC_TARG(30) // 0x898
+#define GIC_SPI_PROC_TARG31 GIC_SPI_PROC_TARG(31) // 0x89C
+
+#define GIC_IRQ_MOD_CFG(_n) (ARMA9_GIC_BASE + 0xc00 + 4 * (_n))
+#define GIC_IRQ_MOD_CFG0 GIC_IRQ_MOD_CFG(0) // 0xc00 - SGI
+#define GIC_IRQ_MOD_CFG1 GIC_IRQ_MOD_CFG(1) // 0xc04 - PPI
+#define GIC_IRQ_MOD_CFG2 GIC_IRQ_MOD_CFG(2) // 0xc08 - SPI0 ~ 15
+#define GIC_IRQ_MOD_CFG3 GIC_IRQ_MOD_CFG(3) // 0xc0C - SPI16 ~ 31
+#define GIC_IRQ_MOD_CFG4 GIC_IRQ_MOD_CFG(4) // 0xc10 - SPI32 ~ 47
+#define GIC_IRQ_MOD_CFG5 GIC_IRQ_MOD_CFG(5) // 0xc14 - SPI48 ~ 63
+#define GIC_IRQ_MOD_CFG6 GIC_IRQ_MOD_CFG(6) // 0xc18 - SPI64 ~ 79
+#define GIC_IRQ_MOD_CFG7 GIC_IRQ_MOD_CFG(7) // 0xc1C - SPI80 ~ 95
+#define GIC_IRQ_MOD_CFG8 GIC_IRQ_MOD_CFG(8) // 0xc20 - SPI96 ~ 111
+#define GIC_IRQ_MOD_CFG9 GIC_IRQ_MOD_CFG(9) // 0xc24 - SPI112 ~ 127
+
+#define GIC_SOFT_IRQ_GEN (ARMA9_GIC_BASE + 0xf00) // 0xf00
+#define GIC_SGI_PEND_SET(_n) (ARMA9_GIC_BASE + 0xf10 + 4 * (_n))
+#define GIC_SGI_PEND_SET0 GIC_SGI_PEND_SET(0) // 0xf10
+#define GIC_SGI_PEND_SET1 GIC_SGI_PEND_SET(1) // 0xf14
+#define GIC_SGI_PEND_SET2 GIC_SGI_PEND_SET(2) // 0xf18
+#define GIC_SGI_PEND_SET3 GIC_SGI_PEND_SET(3) // 0xf1C
+#define GIC_SGI_PEND_CLR(_n) (ARMA9_GIC_BASE + 0xf10 + 4 * (_n))
+#define GIC_SGI_PEND_CLR0 GIC_SGI_PEND_CLR(0) // 0xf20
+#define GIC_SGI_PEND_CLR1 GIC_SGI_PEND_CLR(1) // 0xf24
+#define GIC_SGI_PEND_CLR2 GIC_SGI_PEND_CLR(2) // 0xf28
+#define GIC_SGI_PEND_CLR3 GIC_SGI_PEND_CLR(3) // 0xf2C
+
+
+#define GIC_CPU_IF_CTRL (ARMA9_CPUIF_BASE + 0x000) // 0x8000
+#define GIC_INT_PRIO_MASK (ARMA9_CPUIF_BASE + 0x004) // 0x8004
+#define GIC_BINARY_POINT (ARMA9_CPUIF_BASE + 0x008) // 0x8008
+#define GIC_INT_ACK_REG (ARMA9_CPUIF_BASE + 0x00c) // 0x800c
+#define GIC_END_INT_REG (ARMA9_CPUIF_BASE + 0x010) // 0x8010
+#define GIC_RUNNING_PRIO (ARMA9_CPUIF_BASE + 0x014) // 0x8014
+#define GIC_HIGHEST_PENDINT (ARMA9_CPUIF_BASE + 0x018) // 0x8018
+#define GIC_DEACT_INT_REG (ARMA9_CPUIF_BASE + 0x1000)// 0x1000
+#define GIC_AIAR_REG (ARMA9_CPUIF_BASE + 0x020) // 0x8020
+#define GIC_AEOI_REG (ARMA9_CPUIF_BASE + 0x024) // 0x8024
+#define GIC_AHIGHEST_PENDINT (ARMA9_CPUIF_BASE + 0x028) // 0x8028
+
+
+/* gic source list */
+/* software generated interrupt */
+#define GIC_SRC_SGI(_n) (_n)
+#define GIC_SRC_SGI0 GIC_SRC_SGI(0 ) // (0 )
+#define GIC_SRC_SGI1 GIC_SRC_SGI(1 ) // (1 )
+#define GIC_SRC_SGI2 GIC_SRC_SGI(2 ) // (2 )
+#define GIC_SRC_SGI3 GIC_SRC_SGI(3 ) // (3 )
+#define GIC_SRC_SGI4 GIC_SRC_SGI(4 ) // (4 )
+#define GIC_SRC_SGI5 GIC_SRC_SGI(5 ) // (5 )
+#define GIC_SRC_SGI6 GIC_SRC_SGI(6 ) // (6 )
+#define GIC_SRC_SGI7 GIC_SRC_SGI(7 ) // (7 )
+#define GIC_SRC_SGI8 GIC_SRC_SGI(8 ) // (8 )
+#define GIC_SRC_SGI9 GIC_SRC_SGI(9 ) // (9 )
+#define GIC_SRC_SGI10 GIC_SRC_SGI(10) // (10)
+#define GIC_SRC_SGI11 GIC_SRC_SGI(11) // (11)
+#define GIC_SRC_SGI12 GIC_SRC_SGI(12) // (12)
+#define GIC_SRC_SGI13 GIC_SRC_SGI(13) // (13)
+#define GIC_SRC_SGI14 GIC_SRC_SGI(14) // (14)
+#define GIC_SRC_SGI15 GIC_SRC_SGI(15) // (15)
+/* private peripheral interrupt */
+#define GIC_SRC_PPI(_n) (16 + (_n))
+#define GIC_SRC_PPI0 GIC_SRC_PPI(0 ) // (16)
+#define GIC_SRC_PPI1 GIC_SRC_PPI(1 ) // (17)
+#define GIC_SRC_PPI2 GIC_SRC_PPI(2 ) // (18)
+#define GIC_SRC_PPI3 GIC_SRC_PPI(3 ) // (19)
+#define GIC_SRC_PPI4 GIC_SRC_PPI(4 ) // (20)
+#define GIC_SRC_PPI5 GIC_SRC_PPI(5 ) // (21)
+#define GIC_SRC_PPI6 GIC_SRC_PPI(6 ) // (22)
+#define GIC_SRC_PPI7 GIC_SRC_PPI(7 ) // (23)
+#define GIC_SRC_PPI8 GIC_SRC_PPI(8 ) // (24)
+#define GIC_SRC_PPI9 GIC_SRC_PPI(9 ) // (25)
+#define GIC_SRC_PPI10 GIC_SRC_PPI(10) // (26)
+#define GIC_SRC_PPI11 GIC_SRC_PPI(11) // (27)
+#define GIC_SRC_PPI12 GIC_SRC_PPI(12) // (28)
+#define GIC_SRC_PPI13 GIC_SRC_PPI(13) // (29)
+#define GIC_SRC_PPI14 GIC_SRC_PPI(14) // (30)
+#define GIC_SRC_PPI15 GIC_SRC_PPI(15) // (31)
+/* external peripheral interrupt */
+#define GIC_SRC_SPI(_n) (32 + (_n))
+
+
+#endif
+
diff --git a/plat/sun50iw1p1/include/arisc.h b/plat/sun50iw1p1/include/arisc.h
new file mode 100644
index 0000000..00384f5
--- /dev/null
+++ b/plat/sun50iw1p1/include/arisc.h
@@ -0,0 +1,789 @@
+/*
+ * include/linux/arisc/arisc.h
+ *
+ * Copyright 2012 (c) Allwinner.
+ * superm (superm@allwinnertech.com)
+ *
+ * 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.
+ *
+ */
+
+#ifndef __ASM_ARCH_ARISC_H
+#define __ASM_ARCH_ARISC_H
+
+/* the base of messages */
+#define ARISC_MESSAGE_BASE (0x10)
+
+/* standby commands */
+#define ARISC_SSTANDBY_ENTER_REQ (ARISC_MESSAGE_BASE + 0x00) /* request to enter (ac327 to arisc) */
+#define ARISC_SSTANDBY_RESTORE_NOTIFY (ARISC_MESSAGE_BASE + 0x01) /* restore finished (ac327 to arisc) */
+#define ARISC_NSTANDBY_ENTER_REQ (ARISC_MESSAGE_BASE + 0x02) /* request to enter (ac327 to arisc) */
+#define ARISC_NSTANDBY_WAKEUP_NOTIFY (ARISC_MESSAGE_BASE + 0x03) /* wakeup notify (arisc to ac327) */
+#define ARISC_NSTANDBY_RESTORE_REQ (ARISC_MESSAGE_BASE + 0x04) /* request to restore (ac327 to arisc) */
+#define ARISC_NSTANDBY_RESTORE_COMPLETE (ARISC_MESSAGE_BASE + 0x05) /* arisc restore complete (arisc to ac327) */
+#define ARISC_ESSTANDBY_ENTER_REQ (ARISC_MESSAGE_BASE + 0x06) /* request to enter (ac327 to arisc) */
+#define ARISC_TSTANDBY_ENTER_REQ (ARISC_MESSAGE_BASE + 0x07) /* request to enter (ac327 to arisc) */
+#define ARISC_TSTANDBY_RESTORE_NOTIFY (ARISC_MESSAGE_BASE + 0x08) /* restore finished (ac327 to arisc) */
+#define ARISC_FAKE_POWER_OFF_REQ (ARISC_MESSAGE_BASE + 0x09) /* request to enter (ac327 to arisc) */
+#define ARISC_CPUIDLE_ENTER_REQ (ARISC_MESSAGE_BASE + 0x0a) /* request to enter (ac327 to arisc) */
+#define ARISC_STANDBY_INFO_REQ (ARISC_MESSAGE_BASE + 0x10) /* request sst info (ac327 to arisc) */
+#define ARISC_CPUIDLE_CFG_REQ (ARISC_MESSAGE_BASE + 0x11) /* request to config (ac327 to arisc) */
+#define ARISC_CPU_OP_REQ (ARISC_MESSAGE_BASE + 0x12) /* cpu operations (ac327 to arisc) */
+#define ARISC_QUERY_WAKEUP_SRC_REQ (ARISC_MESSAGE_BASE + 0x13) /* query wakeup source (ac327 to arisc) */
+#define ARISC_SYS_OP_REQ (ARISC_MESSAGE_BASE + 0x14) /* system operations (ac327 to arisc) */
+
+/* dvfs commands */
+#define ARISC_CPUX_DVFS_REQ (ARISC_MESSAGE_BASE + 0x20) /* request dvfs (ac327 to arisc) */
+#define ARISC_CPUX_DVFS_CFG_VF_REQ (ARISC_MESSAGE_BASE + 0x21) /* request config dvfs v-f table(ac327 to arisc) */
+
+/* pmu commands */
+#define ARISC_AXP_INT_COMING_NOTIFY (ARISC_MESSAGE_BASE + 0x40) /* interrupt coming notify(arisc to ac327) */
+#define ARISC_AXP_DISABLE_IRQ (ARISC_MESSAGE_BASE + 0x41) /* disable axp irq of arisc */
+#define ARISC_AXP_ENABLE_IRQ (ARISC_MESSAGE_BASE + 0x42) /* enable axp irq of arisc */
+#define ARISC_AXP_GET_CHIP_ID (ARISC_MESSAGE_BASE + 0x43) /* axp get chip id */
+#define ARISC_AXP_SET_PARAS (ARISC_MESSAGE_BASE + 0x44) /* config axp parameters (ac327 to arisc) */
+#define ARISC_SET_PMU_VOLT (ARISC_MESSAGE_BASE + 0x45) /* set pmu volt (ac327 to arisc) */
+#define ARISC_GET_PMU_VOLT (ARISC_MESSAGE_BASE + 0x46) /* get pmu volt (ac327 to arisc) */
+#define ARISC_SET_LED_BLN (ARISC_MESSAGE_BASE + 0x47) /* set led bln (ac327 to arisc) */
+#define ARISC_AXP_REBOOT (ARISC_MESSAGE_BASE + 0x48) /* reboot system for no pmu protocols */
+#define ARISC_SET_PWR_TREE (ARISC_MESSAGE_BASE + 0x49) /* set power tree (ac327 to arisc) */
+#define ARISC_CLR_NMI_STATUS (ARISC_MESSAGE_BASE + 0x4a) /* clear nmi status (ac327 to arisc) */
+#define ARISC_SET_NMI_TRIGGER (ARISC_MESSAGE_BASE + 0x4b) /* set nmi tigger (ac327 to arisc) */
+
+/* set arisc debug commands */
+#define ARISC_SET_DEBUG_LEVEL (ARISC_MESSAGE_BASE + 0x50) /* set arisc debug level (ac327 to arisc) */
+#define ARISC_MESSAGE_LOOPBACK (ARISC_MESSAGE_BASE + 0x51) /* loopback message (ac327 to arisc) */
+#define ARISC_SET_UART_BAUDRATE (ARISC_MESSAGE_BASE + 0x52) /* set uart baudrate (ac327 to arisc) */
+#define ARISC_SET_DRAM_PARAS (ARISC_MESSAGE_BASE + 0x53) /* config dram parameter (ac327 to arisc) */
+#define ARISC_SET_DEBUG_DRAM_CRC_PARAS (ARISC_MESSAGE_BASE + 0x54) /* config dram crc parameters (ac327 to arisc) */
+#define ARISC_SET_IR_PARAS (ARISC_MESSAGE_BASE + 0x55) /* config ir parameter (ac327 to arisc) */
+#define ARISC_REPORT_ERR_INFO (ARISC_MESSAGE_BASE + 0x56) /* report arisc error info (arisc to ac327) */
+#define ARISC_SET_PARAS (ARISC_MESSAGE_BASE + 0x57) /* set paras (arisc to ac327) */
+
+/* audio commands */
+#define ARISC_AUDIO_START (ARISC_MESSAGE_BASE + 0x60) /* audio start play/capture(ac327 to arisc) */
+#define ARISC_AUDIO_STOP (ARISC_MESSAGE_BASE + 0x61) /* audio stop play/capture(ac327 to arisc) */
+#define ARISC_AUDIO_SET_BUF_PER_PARAS (ARISC_MESSAGE_BASE + 0x62) /* set audio buffer and peroid paras(ac327 to arisc) */
+#define ARISC_AUDIO_GET_POSITION (ARISC_MESSAGE_BASE + 0x63) /* get audio buffer position(ac327 to arisc) */
+#define ARISC_AUDIO_SET_TDM_PARAS (ARISC_MESSAGE_BASE + 0x64) /* set audio tdm parameters(ac327 to arisc) */
+#define ARISC_AUDIO_PERDONE_NOTIFY (ARISC_MESSAGE_BASE + 0x65) /* audio period done notify(arisc to ac327) */
+#define ARISC_AUDIO_ADD_PERIOD (ARISC_MESSAGE_BASE + 0x66) /* audio period done notify(arisc to ac327) */
+
+/* rsb commands */
+#define ARISC_RSB_READ_BLOCK_DATA (ARISC_MESSAGE_BASE + 0x70) /* rsb read block data (ac327 to arisc) */
+#define ARISC_RSB_WRITE_BLOCK_DATA (ARISC_MESSAGE_BASE + 0x71) /* rsb write block data (ac327 to arisc) */
+#define ARISC_RSB_BITS_OPS_SYNC (ARISC_MESSAGE_BASE + 0x72) /* rsb clear bits sync (ac327 to arisc) */
+#define ARISC_RSB_SET_INTERFACE_MODE (ARISC_MESSAGE_BASE + 0x73) /* rsb set interface mode (ac327 to arisc) */
+#define ARISC_RSB_SET_RTSADDR (ARISC_MESSAGE_BASE + 0x74) /* rsb set runtime slave addr (ac327 to arisc) */
+
+/* arisc initialize state notify commands */
+#define ARISC_STARTUP_NOTIFY (ARISC_MESSAGE_BASE + 0x80) /* arisc init state notify(arisc to ac327) */
+
+
+/* the base of ARM SVC ARISC */
+#define ARM_SVC_ARISC_BASE (0xc0000000)
+
+/* standby commands */
+#define ARM_SVC_ARISC_SSTANDBY_ENTER_REQ (ARM_SVC_ARISC_BASE + ARISC_SSTANDBY_ENTER_REQ) /* request to enter (ac327 to arisc) */
+#define ARM_SVC_ARISC_SSTANDBY_RESTORE_NOTIFY (ARM_SVC_ARISC_BASE + ARISC_SSTANDBY_RESTORE_NOTIFY) /* restore finished (ac327 to arisc) */
+#define ARM_SVC_ARISC_NSTANDBY_ENTER_REQ (ARM_SVC_ARISC_BASE + ARISC_NSTANDBY_ENTER_REQ) /* request to enter (ac327 to arisc) */
+#define ARM_SVC_ARISC_NSTANDBY_WAKEUP_NOTIFY (ARM_SVC_ARISC_BASE + ARISC_NSTANDBY_WAKEUP_NOTIFY) /* wakeup notify (arisc to ac327) */
+#define ARM_SVC_ARISC_NSTANDBY_RESTORE_REQ (ARM_SVC_ARISC_BASE + ARISC_NSTANDBY_RESTORE_REQ) /* request to restore (ac327 to arisc) */
+#define ARM_SVC_ARISC_NSTANDBY_RESTORE_COMPLETE (ARM_SVC_ARISC_BASE + ARISC_NSTANDBY_RESTORE_COMPLETE) /* arisc restore complete (arisc to ac327) */
+#define ARM_SVC_ARISC_ESSTANDBY_ENTER_REQ (ARM_SVC_ARISC_BASE + ARISC_ESSTANDBY_ENTER_REQ) /* request to enter (ac327 to arisc) */
+#define ARM_SVC_ARISC_TSTANDBY_ENTER_REQ (ARM_SVC_ARISC_BASE + ARISC_TSTANDBY_ENTER_REQ) /* request to enter (ac327 to arisc) */
+#define ARM_SVC_ARISC_TSTANDBY_RESTORE_NOTIFY (ARM_SVC_ARISC_BASE + ARISC_TSTANDBY_RESTORE_NOTIFY) /* restore finished (ac327 to arisc) */
+#define ARM_SVC_ARISC_FAKE_POWER_OFF_REQ (ARM_SVC_ARISC_BASE + ARISC_FAKE_POWER_OFF_REQ) /* request to enter (ac327 to arisc) */
+#define ARM_SVC_ARISC_CPUIDLE_ENTER_REQ (ARM_SVC_ARISC_BASE + ARISC_CPUIDLE_ENTER_REQ) /* request to enter (ac327 to arisc) */
+#define ARM_SVC_ARISC_STANDBY_INFO_REQ (ARM_SVC_ARISC_BASE + ARISC_STANDBY_INFO_REQ) /* request sst info (ac327 to arisc) */
+#define ARM_SVC_ARISC_CPUIDLE_CFG_REQ (ARM_SVC_ARISC_BASE + ARISC_CPUIDLE_CFG_REQ) /* request to config (ac327 to arisc) */
+#define ARM_SVC_ARISC_CPU_OP_REQ (ARM_SVC_ARISC_BASE + ARISC_CPU_OP_REQ) /* cpu operations (ac327 to arisc) */
+#define ARM_SVC_ARISC_QUERY_WAKEUP_SRC_REQ (ARM_SVC_ARISC_BASE + ARISC_QUERY_WAKEUP_SRC_REQ) /* query wakeup source (ac327 to arisc) */
+#define ARM_SVC_ARISC_SYS_OP_REQ (ARM_SVC_ARISC_BASE + ARISC_SYS_OP_REQ) /* system operations (ac327 to arisc) */
+
+/* dvfs commands */
+#define ARM_SVC_ARISC_CPUX_DVFS_REQ (ARM_SVC_ARISC_BASE + ARISC_CPUX_DVFS_REQ) /* request dvfs (ac327 to arisc) */
+#define ARM_SVC_ARISC_CPUX_DVFS_CFG_VF_REQ (ARM_SVC_ARISC_BASE + ARISC_CPUX_DVFS_CFG_VF_REQ) /* request config dvfs v-f table(ac327 to arisc) */
+
+/* pmu commands */
+#define ARM_SVC_ARISC_AXP_INT_COMING_NOTIFY (ARM_SVC_ARISC_BASE + ARISC_AXP_INT_COMING_NOTIFY) /* interrupt coming notify(arisc to ac327) */
+#define ARM_SVC_ARISC_AXP_DISABLE_IRQ (ARM_SVC_ARISC_BASE + ARISC_AXP_DISABLE_IRQ) /* disable axp irq of arisc */
+#define ARM_SVC_ARISC_AXP_ENABLE_IRQ (ARM_SVC_ARISC_BASE + ARISC_AXP_ENABLE_IRQ) /* enable axp irq of arisc */
+#define ARM_SVC_ARISC_AXP_GET_CHIP_ID (ARM_SVC_ARISC_BASE + ARISC_AXP_GET_CHIP_ID) /* axp get chip id */
+#define ARM_SVC_ARISC_AXP_SET_PARAS (ARM_SVC_ARISC_BASE + ARISC_AXP_SET_PARAS) /* config axp parameters (ac327 to arisc) */
+#define ARM_SVC_ARISC_SET_PMU_VOLT (ARM_SVC_ARISC_BASE + ARISC_SET_PMU_VOLT) /* set pmu volt (ac327 to arisc) */
+#define ARM_SVC_ARISC_GET_PMU_VOLT (ARM_SVC_ARISC_BASE + ARISC_GET_PMU_VOLT) /* get pmu volt (ac327 to arisc) */
+#define ARM_SVC_ARISC_SET_LED_BLN (ARM_SVC_ARISC_BASE + ARISC_SET_LED_BLN) /* set led bln (ac327 to arisc) */
+#define ARM_SVC_ARISC_AXP_REBOOT (ARM_SVC_ARISC_BASE + ARISC_AXP_REBOOT) /* reboot system for no pmu protocols */
+#define ARM_SVC_ARISC_SET_PWR_TREE (ARM_SVC_ARISC_BASE + ARISC_SET_PWR_TREE) /* set power tree (ac327 to arisc) */
+#define ARM_SVC_ARISC_CLR_NMI_STATUS (ARM_SVC_ARISC_BASE + ARISC_CLR_NMI_STATUS) /* clear nmi status (ac327 to arisc) */
+#define ARM_SVC_ARISC_SET_NMI_TRIGGER (ARM_SVC_ARISC_BASE + ARISC_SET_NMI_TRIGGER) /* set nmi tigger (ac327 to arisc) */
+
+/* set arisc debug commands */
+#define ARM_SVC_ARISC_SET_DEBUG_LEVEL (ARM_SVC_ARISC_BASE + ARISC_SET_DEBUG_LEVEL) /* set arisc debug level (ac327 to arisc) */
+#define ARM_SVC_ARISC_MESSAGE_LOOPBACK (ARM_SVC_ARISC_BASE + ARISC_MESSAGE_LOOPBACK) /* loopback message (ac327 to arisc) */
+#define ARM_SVC_ARISC_SET_UART_BAUDRATE (ARM_SVC_ARISC_BASE + ARISC_SET_UART_BAUDRATE) /* set uart baudrate (ac327 to arisc) */
+#define ARM_SVC_ARISC_SET_DRAM_PARAS (ARM_SVC_ARISC_BASE + ARISC_SET_DRAM_PARAS) /* config dram parameter (ac327 to arisc) */
+#define ARM_SVC_ARISC_SET_DEBUG_DRAM_CRC_PARAS (ARM_SVC_ARISC_BASE + ARISC_SET_DEBUG_DRAM_CRC_PARAS) /* config dram crc parameters (ac327 to arisc) */
+#define ARM_SVC_ARISC_SET_IR_PARAS (ARM_SVC_ARISC_BASE + ARISC_SET_IR_PARAS) /* config ir parameter (ac327 to arisc) */
+#define ARM_SVC_ARISC_REPORT_ERR_INFO (ARM_SVC_ARISC_BASE + ARISC_REPORT_ERR_INFO) /* report arisc error info (arisc to ac327) */
+#define ARM_SVC_ARISC_SET_PARAS (ARM_SVC_ARISC_BASE + ARISC_SET_PARAS) /* set paras (arisc to ac327) */
+
+/* audio commands */
+#define ARM_SVC_ARISC_AUDIO_START (ARM_SVC_ARISC_BASE + ARISC_AUDIO_START) /* audio start play/capture(ac327 to arisc) */
+#define ARM_SVC_ARISC_AUDIO_STOP (ARM_SVC_ARISC_BASE + ARISC_AUDIO_STOP) /* audio stop play/capture(ac327 to arisc) */
+#define ARM_SVC_ARISC_AUDIO_SET_BUF_PER_PARAS (ARM_SVC_ARISC_BASE + ARISC_AUDIO_SET_BUF_PER_PARAS) /* set audio buffer and peroid paras(ac327 to arisc) */
+#define ARM_SVC_ARISC_AUDIO_GET_POSITION (ARM_SVC_ARISC_BASE + ARISC_AUDIO_GET_POSITION) /* get audio buffer position(ac327 to arisc) */
+#define ARM_SVC_ARISC_AUDIO_SET_TDM_PARAS (ARM_SVC_ARISC_BASE + ARISC_AUDIO_SET_TDM_PARAS) /* set audio tdm parameters(ac327 to arisc) */
+#define ARM_SVC_ARISC_AUDIO_PERDONE_NOTIFY (ARM_SVC_ARISC_BASE + ARISC_AUDIO_PERDONE_NOTIFY) /* audio period done notify(arisc to ac327) */
+#define ARM_SVC_ARISC_AUDIO_ADD_PERIOD (ARM_SVC_ARISC_BASE + ARISC_AUDIO_ADD_PERIOD) /* audio period done notify(arisc to ac327) */
+
+/* rsb commands */
+#define ARM_SVC_ARISC_RSB_READ_BLOCK_DATA (ARM_SVC_ARISC_BASE + ARISC_RSB_READ_BLOCK_DATA) /* rsb read block data (ac327 to arisc) */
+#define ARM_SVC_ARISC_RSB_WRITE_BLOCK_DATA (ARM_SVC_ARISC_BASE + ARISC_RSB_WRITE_BLOCK_DATA) /* rsb write block data (ac327 to arisc) */
+#define ARM_SVC_ARISC_RSB_BITS_OPS_SYNC (ARM_SVC_ARISC_BASE + ARISC_RSB_BITS_OPS_SYNC) /* rsb clear bits sync (ac327 to arisc) */
+#define ARM_SVC_ARISC_RSB_SET_INTERFACE_MODE (ARM_SVC_ARISC_BASE + ARISC_RSB_SET_INTERFACE_MODE) /* rsb set interface mode (ac327 to arisc) */
+#define ARM_SVC_ARISC_RSB_SET_RTSADDR (ARM_SVC_ARISC_BASE + ARISC_RSB_SET_RTSADDR) /* rsb set runtime slave addr (ac327 to arisc) */
+
+/* arisc initialize state notify commands */
+#define ARM_SVC_ARISC_STARTUP_NOTIFY (ARM_SVC_ARISC_BASE + ARISC_STARTUP_NOTIFY) /* arisc init state notify(arisc to ac327) */
+
+#define AW_MSG_HWSPINLOCK (0)
+#define AW_AUDIO_HWSPINLOCK (1)
+#define AW_RTC_REG_HWSPINLOCK (2)
+
+#define NMI_INT_TYPE_PMU (0)
+#define NMI_INT_TYPE_RTC (1)
+#define NMI_INT_TYPE_PMU_OFFSET (0x1 << NMI_INT_TYPE_PMU)
+#define NMI_INT_TYPE_RTC_OFFSET (0x1 << NMI_INT_TYPE_RTC)
+
+/* the modes of arisc dvfs */
+#define ARISC_DVFS_SYN (1<<0)
+
+/* message attributes(only use 8bit) */
+#define ARISC_MESSAGE_ATTR_ASYN (0<<0) /* need asyn with another cpu */
+#define ARISC_MESSAGE_ATTR_SOFTSYN (1<<0) /* need soft syn with another cpu */
+#define ARISC_MESSAGE_ATTR_HARDSYN (1<<1) /* need hard syn with another cpu */
+
+/* axp driver interfaces */
+#define AXP_TRANS_BYTE_MAX (4)
+#define RSB_TRANS_BYTE_MAX (4)
+#define P2WI_TRANS_BYTE_MAX (8)
+
+/* RSB devices' address */
+#define RSB_DEVICE_SADDR1 (0x3A3) /* (0x01d1)AXP22x(AW1669) */
+#define RSB_DEVICE_SADDR3 (0x745) /* (0x03a2)AXP15x(AW1657) */
+#define RSB_DEVICE_SADDR7 (0xE89) /* (0x0744)Audio codec, AC100 */
+
+/* RSB run time address */
+#define RSB_RTSADDR_AXP809 (0x2d)
+#define RSB_RTSADDR_AXP806 (0x3a)
+#define RSB_RTSADDR_AC100 (0x4e)
+
+/* audio sram base address */
+#define AUDIO_SRAM_BASE_PALY (0x08117000)
+#define AUDIO_SRAM_BASE_CAPTURE (0x0811f000)
+
+#define AUDIO_SRAM_BUF_SIZE_02K (2048) /* buffer size 2k = 0x800 = 2048 */
+#define AUDIO_SRAM_BUF_SIZE_04K (4096) /* buffer size 4k = 0x1000 = 4096 */
+#define AUDIO_SRAM_BUF_SIZE_08K (8192) /* buffer size 8k = 0x2000 = 8192 */
+#define AUDIO_SRAM_BUF_SIZE_16K (16384) /* buffer size 16k = 0x4000 = 16384 */
+#define AUDIO_SRAM_BUF_SIZE_32K (32768) /* buffer size 32k = 0x8000 = 32768 */
+
+#define AUDIO_SRAM_PER_SIZE_02K (2048) /* period size 2k = 0x800 = 2048 */
+#define AUDIO_SRAM_PER_SIZE_04K (4096) /* period size 4k = 0x1000 = 4096 */
+#define AUDIO_SRAM_PER_SIZE_08K (8192) /* period size 8k = 0x2000 = 8192 */
+#define AUDIO_SRAM_PER_SIZE_16K (16384) /* period size 16k = 0x4000 = 16384 */
+#define AUDIO_SRAM_PER_SIZE_32K (32768) /* period size 32k = 0x8000 = 32768 */
+
+typedef enum {
+ arisc_power_on = 0,
+ arisc_power_retention = 1,
+ arisc_power_off = 3,
+} arisc_power_state_t;
+
+typedef enum {
+ arisc_system_shutdown = 0,
+ arisc_system_reboot = 1,
+ arisc_system_reset = 2
+} arisc_system_state_t;
+
+//pmu voltage types
+typedef enum power_voltage_type
+{
+ AXP809_POWER_VOL_DCDC1 = 0x0,
+ AXP809_POWER_VOL_DCDC2,
+ AXP809_POWER_VOL_DCDC3,
+ AXP809_POWER_VOL_DCDC4,
+ AXP809_POWER_VOL_DCDC5,
+ AXP809_POWER_VOL_DC5LDO,
+ AXP809_POWER_VOL_ALDO1,
+ AXP809_POWER_VOL_ALDO2,
+ AXP809_POWER_VOL_ALDO3,
+ AXP809_POWER_VOL_DLDO1,
+ AXP809_POWER_VOL_DLDO2,
+ AXP809_POWER_VOL_ELDO1,
+ AXP809_POWER_VOL_ELDO2,
+ AXP809_POWER_VOL_ELDO3,
+
+ AXP806_POWER_VOL_DCDCA,
+ AXP806_POWER_VOL_DCDCB,
+ AXP806_POWER_VOL_DCDCC,
+ AXP806_POWER_VOL_DCDCD,
+ AXP806_POWER_VOL_DCDCE,
+ AXP806_POWER_VOL_ALDO1,
+ AXP806_POWER_VOL_ALDO2,
+ AXP806_POWER_VOL_ALDO3,
+ AXP806_POWER_VOL_BLDO1,
+ AXP806_POWER_VOL_BLDO2,
+ AXP806_POWER_VOL_BLDO3,
+ AXP806_POWER_VOL_BLDO4,
+ AXP806_POWER_VOL_CLDO1,
+ AXP806_POWER_VOL_CLDO2,
+ AXP806_POWER_VOL_CLDO3,
+
+ OZ80120_POWER_VOL_DCDC,
+
+ POWER_VOL_MAX,
+} power_voltage_type_e;
+
+/* the pll of arisc dvfs */
+typedef enum arisc_pll_no {
+ ARISC_DVFS_PLL1 = 1,
+ ARISC_DVFS_PLL2 = 2
+} arisc_pll_no_e;
+
+/* rsb transfer data type */
+typedef enum arisc_rsb_datatype {
+ RSB_DATA_TYPE_BYTE = 1,
+ RSB_DATA_TYPE_HWORD = 2,
+ RSB_DATA_TYPE_WORD = 4
+} arisc_rsb_datatype_e;
+
+#if defined CONFIG_ARCH_SUN8IW1P1
+typedef enum arisc_p2wi_bits_ops {
+ P2WI_CLR_BITS,
+ P2WI_SET_BITS
+} arisc_p2wi_bits_ops_e;
+#elif (defined CONFIG_ARCH_SUN8IW3P1) || (defined CONFIG_ARCH_SUN8IW5P1) || (defined CONFIG_ARCH_SUN8IW6P1) || \
+ (defined CONFIG_ARCH_SUN8IW7P1) || (defined CONFIG_ARCH_SUN8IW9P1) || (defined CONFIG_ARCH_SUN9IW1P1) || \
+ (defined CONFIG_ARCH_SUN50IW1P1)
+/* rsb transfer data type */
+typedef enum arisc_rsb_bits_ops {
+ RSB_CLR_BITS,
+ RSB_SET_BITS
+} arisc_rsb_bits_ops_e;
+#endif
+
+typedef enum arisc_audio_mode {
+ AUDIO_PLAY, /* play mode */
+ AUDIO_CAPTURE /* capture mode */
+} arisc_audio_mode_e;
+
+typedef struct arisc_audio_mem
+{
+ uint32_t mode;
+ uint32_t sram_base_addr;
+ uint32_t buffer_size;
+ uint32_t period_size;
+}arisc_audio_mem_t;
+
+typedef struct arisc_audio_tdm
+{
+ uint32_t mode;
+ uint32_t samplerate;
+ uint32_t channum;
+}arisc_audio_tdm_t;
+
+/* arisc call-back */
+typedef int (*arisc_cb_t)(void *arg);
+
+/* sunxi_perdone_cbfn
+ *
+ * period done callback routine type
+*/
+/* audio callback struct */
+typedef struct audio_cb {
+ arisc_cb_t handler; /* dma callback fuction */
+ void *arg; /* args of func */
+}audio_cb_t;
+
+/*
+ * @len : number of read registers, max len:4;
+ * @datatype: type of the data, 0:byte(8bits), 1:halfword(16bits), 2:word(32bits)
+ * @msgattr: message attribute, 0:async, 1:soft sync, 2:hard aync
+ * @devaddr: devices address;
+ * @regaddr: array of registers address;
+ * @data: array of registers data;
+ */
+typedef struct arisc_rsb_block_cfg
+{
+ uint32_t len;
+ uint32_t datatype;
+ uint32_t msgattr;
+ uint32_t devaddr;
+ unsigned char *regaddr;
+ uint32_t *data;
+}arisc_rsb_block_cfg_t;
+
+/*
+ * @len : number of operate registers, max len:4;
+ * @datatype: type of the data, 0:byte(8bits), 1:halfword(16bits), 2:word(32bits)
+ * @msgattr: message attribute, 0:async, 1:soft sync, 2:hard aync
+ * @ops: bits operation, 0:clear bits, 1:set bits
+ * @devaddr : devices address;
+ * @regaddr : point of registers address;
+ * @mask : point of mask bits data;
+ * @delay: point of delay times;
+ */
+typedef struct arisc_rsb_bits_cfg
+{
+ uint32_t len;
+ uint32_t datatype;
+ uint32_t msgattr;
+ uint32_t ops;
+ uint32_t devaddr;
+ unsigned char *regaddr;
+ unsigned char *delay;
+ uint32_t *mask;
+}arisc_rsb_bits_cfg_t;
+
+typedef enum arisc_rw_type
+{
+ ARISC_READ = 0x0,
+ ARISC_WRITE = 0x1,
+} arisc_rw_type_e;
+
+typedef struct nmi_isr
+{
+ arisc_cb_t handler;
+ void *arg;
+} nmi_isr_t;
+
+extern nmi_isr_t nmi_isr_node[2];
+
+/*
+ * @flags: 0x01-clean pendings, 0x10-enter cupidle.
+ * @resume_addr: resume address for cpu0 out of idle.
+ */
+typedef struct sunxi_enter_idle_para{
+ unsigned long flags;
+ void *resume_addr;
+}sunxi_enter_idle_para_t;
+
+typedef struct sst_power_info_para
+{
+ /*
+ * define for sun9iw1p1
+ * power_reg bit0 ~ 7 AXP_main REG10, bit 8~15 AXP_main REG12
+ * power_reg bit16~23 AXP_slav REG10, bit24~31 AXP_slav REG11
+ *
+ * AXP_main REG10: 0-off, 1-on
+ * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
+ * aldo2 aldo1 dcdc5 dcdc4 dcdc3 dcdc2 dcdc1 dc5ldo
+ *
+ * REG12: bit0~5:0-off, 1-on, bit6~7: 0-on, 1-off, dc1sw's power come from dcdc1
+ * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
+ * dc1sw swout aldo3 dldo2 dldo1 eldo3 eldo2 eldo1
+ *
+ * AXP_slave REG10: 0-off, 1-on. dcdc b&c is not used, ignore them.
+ * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
+ * aldo3 aldo2 aldo1 dcdce dcdcd dcdcc dcdcb dcdca
+ *
+ * AXP_slave REG11: 0-off, 1-on
+ * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
+ * swout cldo3 cldo2 cldo1 bldo4 bldo3 bldo2 bldo1
+ */
+ /*
+ * define for sun8iw5p1
+ * power_reg0 ~ 7 AXP_main REG10, 8~15 AXP_main REG12
+ * power_reg16~32 null
+ *
+ * AXP_main REG10: 0-off, 1-on
+ * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
+ * aldo2 aldo1 dcdc5 dcdc4 dcdc3 dcdc2 dcdc1 dc5ldo
+ *
+ * REG12: 0-off, 1-on
+ * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
+ * dc1sw dldo4 dldo3 dldo2 dldo1 eldo3 eldo2 eldo1
+ *
+ * REG13: bit16 aldo3, 0-off, 1-on
+ * REG90: bit17 gpio0/ldo, 0-off, 1-on
+ * REG92: bit18 gpio1/ldo, 0-off, 1-on
+ */
+ unsigned int enable; /* enable bit */
+ unsigned int power_reg; /* registers of power state should be */
+ signed int system_power; /* the max power of system, signed, power mabe negative when charge */
+} sst_power_info_para_t;
+
+typedef struct sst_dram_info
+{
+ unsigned int dram_crc_enable;
+ unsigned int dram_crc_src;
+ unsigned int dram_crc_len;
+ unsigned int dram_crc_error;
+ unsigned int dram_crc_total_count;
+ unsigned int dram_crc_error_count;
+} sst_dram_info_t;
+
+typedef struct standby_info_para
+{
+ sst_power_info_para_t power_state; /* size 3W=12B */
+ sst_dram_info_t dram_state; /*size 6W=24B */
+} standby_info_para_t;
+
+int sunxi_arisc_probe(void *cfg);
+int sunxi_arisc_wait_ready(void);
+
+
+/* ====================================dvfs interface==================================== */
+/*
+ * set specific pll target frequency.
+ * @freq: target frequency to be set, based on KHZ;
+ * @pll: which pll will be set
+ * @mode: the attribute of message, whether syn or asyn;
+ * @cb: callback handler;
+ * @cb_arg: callback handler arguments;
+ *
+ * return: result, 0 - set frequency successed,
+ * !0 - set frequency failed;
+ */
+int arisc_dvfs_set_cpufreq(uint32_t freq, uint32_t pll, uint32_t mode);
+
+/*
+ * enter cpu idle.
+ * @cb: callback function.
+ * @cb_arg: arg for callback function.
+ * @pars: arg for enter cpuidle.
+ *
+ * return: result, 0 - enter cpuidle successed, !0 - failed;
+ */
+int arisc_enter_cpuidle(arisc_cb_t cb, void *cb_arg, struct sunxi_enter_idle_para *para);
+
+/**
+ * cpu operations.
+ * @mpidr: cpu id;
+ * @entrypoint: cpu resume entrypoint;
+ * @cpu_state: cpu state;
+ * @cluster_state: cluster state;
+ *
+ * return: result, 0 - super standby successed,
+ * !0 - super standby failed;
+ */
+int arisc_cpu_op(uint32_t mpidr, uint32_t entrypoint, arisc_power_state_t cpu_state,
+ arisc_power_state_t cluster_state);
+
+ /**
+ * system operations.
+ * @state: system state;
+ *
+ * return: result, 0 - system operations successed,
+ * !0 - system operations failed;
+ */
+int arisc_system_op(arisc_system_state_t state);
+
+/* ====================================standby interface==================================== */
+/**
+ * query super-standby wakeup source.
+ * @para: point of buffer to store wakeup event informations.
+ *
+ * return: result, 0 - query successed, !0 - query failed;
+ */
+int arisc_query_wakeup_source(uint32_t *event);
+
+int arisc_query_set_standby_info(struct standby_info_para *para, arisc_rw_type_e op);
+
+/*
+ * query config of standby power state and consumer.
+ * @para: point of buffer to store power informations.
+ *
+ * return: result, 0 - query successed, !0 - query failed;
+ */
+int arisc_query_standby_power_cfg(struct standby_info_para *para);
+
+/*
+ * set config of standby power state and consumer.
+ * @para: point of buffer to store power informations.
+ *
+ * return: result, 0 - set successed, !0 - set failed;
+ */
+#define arisc_set_standby_power_cfg(para) \
+ arisc_query_set_standby_info(para, ARISC_WRITE)
+
+/*
+ * query standby power state and consumer.
+ * @para: point of buffer to store power informations.
+ *
+ * return: result, 0 - query successed, !0 - query failed;
+ */
+#define arisc_query_standby_power(para) \
+ arisc_query_set_standby_info(para, ARISC_READ)
+
+/**
+ * query super-standby dram crc result.
+ * @perror: pointer of dram crc result.
+ * @ptotal_count: pointer of dram crc total count
+ * @perror_count: pointer of dram crc error count
+ *
+ * return: result, 0 - query successed,
+ * !0 - query failed;
+ */
+int arisc_query_dram_crc_result(unsigned long *perror, unsigned long *ptotal_count,
+ unsigned long *perror_count);
+
+int arisc_set_dram_crc_result(unsigned long error, unsigned long total_count,
+ unsigned long error_count);
+
+/**
+ * notify arisc cpux restored.
+ * @para: none.
+ *
+ * return: result, 0 - notify successed, !0 - notify failed;
+ */
+int arisc_cpux_ready_notify(void);
+
+#if defined CONFIG_ARCH_SUN8IW1P1
+void arisc_fake_power_off(void);
+#endif
+
+/* ====================================axp interface==================================== */
+/**
+ * register call-back function, call-back function is for arisc notify some event to ac327,
+ * axp/rtc interrupt for external interrupt NMI.
+ * @type: nmi type, pmu/rtc;
+ * @func: call-back function;
+ * @para: parameter for call-back function;
+ *
+ * @return: result, 0 - register call-back function successed;
+ * !0 - register call-back function failed;
+ * NOTE: the function is like "int callback(void *para)";
+ * this function will execute in system ISR.
+ */
+int arisc_nmi_cb_register(uint32_t type, arisc_cb_t func, void *para);
+
+/**
+ * unregister call-back function.
+ * @type: nmi type, pmu/rtc;
+ * @func: call-back function which need be unregister;
+ */
+void arisc_nmi_cb_unregister(uint32_t type, arisc_cb_t func);
+
+int arisc_disable_nmi_irq(void);
+int arisc_enable_nmi_irq(void);
+int arisc_clear_nmi_status(void);
+int arisc_set_nmi_trigger(uint32_t type);
+
+int arisc_axp_get_chip_id(unsigned char *chip_id);
+int arisc_adjust_pmu_chgcur(uint32_t max_chgcur, uint32_t chg_ic_temp, uint32_t flag);
+int arisc_set_pwr_tree(uint32_t *pwr_tree);
+
+int arisc_set_led_bln(uint32_t *paras);
+
+/* ====================================audio interface==================================== */
+/**
+ * start audio play or capture.
+ * @mode: start audio in which mode ; 0:play, 1;capture.
+ *
+ * return: result, 0 - start audio play or capture successed,
+ * !0 - start audio play or capture failed.
+ */
+int arisc_audio_start(int mode);
+
+/**
+ * stop audio play or capture.
+ * @mode: stop audio in which mode ; 0:play, 1;capture.
+ *
+ * return: result, 0 - stop audio play or capture successed,
+ * !0 - stop audio play or capture failed.
+ */
+int arisc_audio_stop(int mode);
+
+/**
+ * set audio buffer and period parameters.
+ * @audio_mem:
+ * mode :which mode be set; 0:paly, 1:capture;
+ * sram_base_addr:sram base addr of buffer;
+ * buffer_size :the size of buffer;
+ * period_size :the size of period;
+ *
+ * |period|period|period|period|...|period|period|period|period|...|
+ * | paly buffer | capture buffer |
+ * | |
+ * 1 2
+ * 1:paly sram_base_addr, 2:capture sram_base_addr;
+ * buffer size = capture sram_base_addr - paly sram_base_addr.
+ *
+ * return: result, 0 - set buffer and period parameters successed,
+ * !0 - set buffer and period parameters failed.
+ *
+ */
+int arisc_buffer_period_paras(struct arisc_audio_mem audio_mem);
+
+/**
+ * get audio play or capture real-time address.
+ * @mode: in which mode; 0:play, 1;capture;
+ * @addr: real-time address in which mode.
+ *
+ * return: result, 0 - get real-time address successed,
+ * !0 - get real-time address failed.
+ */
+int arisc_get_position(int mode, uint32_t *addr);
+
+/**
+ * register audio callback function.
+ * @mode: in which mode; 0:play, 1;capture;
+ * @handler: audio callback handler which need be register;
+ * @arg : the pointer of audio callback arguments.
+ *
+ * return: result, 0 - register audio callback function successed,
+ * !0 - register audio callback function failed.
+ */
+int arisc_audio_cb_register(int mode, arisc_cb_t handler, void *arg);
+
+/**
+ * unregister audio callback function.
+ * @mode: in which mode; 0:play, 1;capture;
+ * @handler: audio callback handler which need be register;
+ * @arg : the pointer of audio callback arguments.
+ *
+ * return: result, 0 - unregister audio callback function successed,
+ * !0 - unregister audio callback function failed.
+ */
+int arisc_audio_cb_unregister(int mode, arisc_cb_t handler);
+
+/**
+ * set audio tdm parameters.
+ * @tdm_cfg: audio tdm struct
+ * mode :in which mode; 0:play, 1;capture;
+ * samplerate:tdm samplerate depend on audio data;
+ * channel :audio channel number, 1 or 2.
+
+ * return: result, 0 - set buffer and period parameters successed,
+ * !0 - set buffer and period parameters failed.
+ *
+ */
+int arisc_tdm_paras(struct arisc_audio_tdm tdm_cfg);
+
+/**
+ * add audio period.
+ * @mode: start audio in which mode ; 0:play, 1;capture.
+ * @addr: period address which will be add in buffer
+ *
+ * return: result, 0 - add audio period successed,
+ * !0 - add audio period failed.
+ *
+ */
+int arisc_add_period(uint32_t mode, uint32_t addr);
+
+/* ====================================rsb interface==================================== */
+/**
+ * rsb read block data.
+ * @cfg: point of arisc_rsb_block_cfg struct;
+ *
+ * return: result, 0 - read register successed,
+ * !0 - read register failed or the len more then max len;
+ */
+int arisc_rsb_read_block_data(uint32_t *paras);
+
+/**
+ * rsb write block data.
+ * @cfg: point of arisc_rsb_block_cfg struct;
+ *
+ * return: result, 0 - write register successed,
+ * !0 - write register failedor the len more then max len;
+ */
+int arisc_rsb_write_block_data(uint32_t *paras);
+
+
+/**
+ * rsb read pmu reg.
+ * @addr: pmu reg addr;
+ *
+ * return: if read pmu reg successed, return data of pmu reg;
+ * if read pmu reg failed, return -1.
+ */
+uint8_t arisc_rsb_read_pmu_reg(uint32_t addr);
+
+/**
+ * rsb write pmu reg.
+ * @addr: pmu reg addr;
+ * @data: pmu reg data;
+ *
+ * return: result, 0 - write register successed,
+ * !0 - write register failedor the len more then max len;
+ */
+int arisc_rsb_write_pmu_reg(uint32_t addr, uint32_t data);
+
+
+/**
+ * rsb bits operation sync.
+ * @cfg: point of arisc_rsb_bits_cfg struct;
+ *
+ * return: result, 0 - bits operation successed,
+ * !0 - bits operation failed, or the len more then max len;
+ *
+ * rsb clear bits internal:
+ * data = rsb_read(regaddr);
+ * data = data & (~mask);
+ * rsb_write(regaddr, data);
+ *
+ * rsb set bits internal:
+ * data = rsb_read(addr);
+ * data = data | mask;
+ * rsb_write(addr, data);
+ *
+ */
+int rsb_bits_ops_sync(uint32_t *paras);
+
+/**
+ * rsb set interface mode.
+ * @devaddr: rsb slave device address;
+ * @regaddr: register address of rsb slave device;
+ * @data: data which to init rsb slave device interface mode;
+ *
+ * return: result, 0 - set interface mode successed,
+ * !0 - set interface mode failed;
+ */
+int arisc_rsb_set_interface_mode(uint32_t devaddr, uint32_t regaddr, uint32_t data);
+
+/**
+ * rsb set runtime slave address.
+ * @devaddr: rsb slave device address;
+ * @rtsaddr: rsb slave device's runtime slave address;
+ *
+ * return: result, 0 - set rsb runtime address successed,
+ * !0 - set rsb runtime address failed;
+ */
+int arisc_rsb_set_rtsaddr(uint32_t devaddr, uint32_t rtsaddr);
+
+/**
+ * set pmu voltage.
+ * @type: pmu regulator type;
+ * @voltage: pmu regulator voltage;
+ *
+ * return: result, 0 - set pmu voltage successed,
+ * !0 - set pmu voltage failed;
+ */
+int arisc_pmu_set_voltage(uint32_t type, uint32_t voltage);
+
+/**
+ * get pmu voltage.
+ * @type: pmu regulator type;
+ *
+ * return: pmu regulator voltage;
+ */
+int arisc_pmu_get_voltage(uint32_t type, uint32_t *voltage);
+
+/* ====================================debug interface==================================== */
+int arisc_message_loopback(void);
+int arisc_config_ir_paras(uint32_t ir_code, uint32_t ir_addr);
+int arisc_set_debug_level(unsigned int level);
+int arisc_set_uart_baudrate(uint32_t baudrate);
+int arisc_set_dram_crc_paras(unsigned int dram_crc_en, unsigned int dram_crc_srcaddr, unsigned int dram_crc_len);
+int arisc_set_paras(void);
+
+#endif /* __ASM_ARCH_A100_H */
+
diff --git a/plat/sun50iw1p1/include/ccmu.h b/plat/sun50iw1p1/include/ccmu.h
new file mode 100644
index 0000000..a1e817f
--- /dev/null
+++ b/plat/sun50iw1p1/include/ccmu.h
@@ -0,0 +1,81 @@
+/*
+ * (C) Copyright 2007-2015
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Jerry Wang <wangflord@allwinnertech.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef __CCMU_H
+#define __CCMU_H
+
+
+#include "../sunxi_def.h"
+
+/* pll list */
+#define CCMU_PLL_CPUX_CTRL_REG (SUNXI_CCM_BASE + 0x00)
+#define CCMU_PLL_AUDIO_CTRL_REG (SUNXI_CCM_BASE + 0x08)
+#define CCMU_PLL_VIDEO0_CTRL_REG (SUNXI_CCM_BASE + 0x10)
+#define CCMU_PLL_VE_CTRL_REG (SUNXI_CCM_BASE + 0x18)
+#define CCMU_PLL_DDR0_CTRL_REG (SUNXI_CCM_BASE + 0x20)
+#define CCMU_PLL_PERIPH0_CTRL_REG (SUNXI_CCM_BASE + 0x28)
+#define CCMU_PLL_PERIPH1_CTRL_REG (SUNXI_CCM_BASE + 0x2C)
+#define CCMU_PLL_VIDEO1_CTRL_REG (SUNXI_CCM_BASE + 0x30)
+#define CCMU_PLL_GPU_CTRL_REG (SUNXI_CCM_BASE + 0x38)
+#define CCMU_PLL_MIPI_CTRL_REG (SUNXI_CCM_BASE + 0x40)
+#define CCMU_PLL_HSIC_CTRL_REG (SUNXI_CCM_BASE + 0x44)
+#define CCMU_PLL_DE_CTRL_REG (SUNXI_CCM_BASE + 0x48)
+#define CCMU_PLL_DDR1_CTRL_REG (SUNXI_CCM_BASE + 0x4C)
+
+/* cfg list */
+#define CCMU_CPUX_AXI_CFG_REG (SUNXI_CCM_BASE + 0x50)
+#define CCMU_AHB1_APB1_CFG_REG (SUNXI_CCM_BASE + 0x54)
+#define CCMU_APB2_CFG_GREG (SUNXI_CCM_BASE + 0x58)
+#define CCMU_AHB2_CFG_GREG (SUNXI_CCM_BASE + 0x5C)
+
+/* gate list */
+#define CCMU_BUS_CLK_GATING_REG0 (SUNXI_CCM_BASE + 0x60)
+#define CCMU_BUS_CLK_GATING_REG1 (SUNXI_CCM_BASE + 0x64)
+#define CCMU_BUS_CLK_GATING_REG2 (SUNXI_CCM_BASE + 0x68)
+#define CCMU_BUS_CLK_GATING_REG3 (SUNXI_CCM_BASE + 0x6C)
+#define CCMU_BUS_CLK_GATING_REG4 (SUNXI_CCM_BASE + 0x70)
+
+/* module list */
+#define CCMU_NAND0_CLK_REG (SUNXI_CCM_BASE + 0x80)
+#define CCMU_SDMMC0_CLK_REG (SUNXI_CCM_BASE + 0x88)
+#define CCMU_SDMMC1_CLK_REG (SUNXI_CCM_BASE + 0x8C)
+#define CCMU_SDMMC2_CLK_REG (SUNXI_CCM_BASE + 0x90)
+
+#define CCMU_CE_CLK_REG (SUNXI_CCM_BASE + 0x9C)
+
+#define CCMU_USBPHY_CLK_REG (SUNXI_CCM_BASE + 0xCC)
+#define CCMU_DRAM_CLK_REG (SUNXI_CCM_BASE + 0xF4)
+#define CCMU_PLL_DDR_CFG_REG (SUNXI_CCM_BASE + 0xF8)
+#define CCMU_MBUS_RST_REG (SUNXI_CCM_BASE + 0xFC)
+#define CCMU_DRAM_CLK_GATING_REG (SUNXI_CCM_BASE + 0x100)
+
+#define CCMU_AVS_CLK_REG (SUNXI_CCM_BASE + 0x144)
+#define CCMU_MBUS_CLK_REG (SUNXI_CCM_BASE + 0x15C)
+
+/*gate rst list*/
+#define CCMU_BUS_SOFT_RST_REG0 (SUNXI_CCM_BASE + 0x2C0)
+#define CCMU_BUS_SOFT_RST_REG1 (SUNXI_CCM_BASE + 0x2C4)
+#define CCMU_BUS_SOFT_RST_REG2 (SUNXI_CCM_BASE + 0x2C8)
+#define CCMU_BUS_SOFT_RST_REG3 (SUNXI_CCM_BASE + 0x2D0)
+#define CCMU_BUS_SOFT_RST_REG4 (SUNXI_CCM_BASE + 0x2D8)
+
+#endif
+
diff --git a/plat/sun50iw1p1/include/gpio.h b/plat/sun50iw1p1/include/gpio.h
new file mode 100644
index 0000000..7cab9c9
--- /dev/null
+++ b/plat/sun50iw1p1/include/gpio.h
@@ -0,0 +1,69 @@
+/*
+ * (C) Copyright 2007-2013
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Jerry Wang <wangflord@allwinnertech.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _SUNXI_GPIO_H
+#define _SUNXI_GPIO_H
+
+#include <mmio.h>
+
+
+#define PIOC_REG_o_CFG0 0x00
+#define PIOC_REG_o_CFG1 0x04
+#define PIOC_REG_o_CFG2 0x08
+#define PIOC_REG_o_CFG3 0x0C
+#define PIOC_REG_o_DATA 0x10
+#define PIOC_REG_o_DRV0 0x14
+#define PIOC_REG_o_DRV1 0x18
+#define PIOC_REG_o_PUL0 0x1C
+#define PIOC_REG_o_PUL1 0x20
+
+
+
+/**#############################################################################################################
+ *
+ * GPIO(PIN) Operations
+ *
+-##############################################################################################################*/
+#define PIO_REG_CFG(n, i) (( SUNXI_PIO_BASE + ((n)-1)*0x24 + ((i)<<2) + 0x00))
+#define PIO_REG_DLEVEL(n, i) (( SUNXI_PIO_BASE + ((n)-1)*0x24 + ((i)<<2) + 0x14))
+#define PIO_REG_PULL(n, i) (( SUNXI_PIO_BASE + ((n)-1)*0x24 + ((i)<<2) + 0x1C))
+#define PIO_REG_DATA(n) (( SUNXI_PIO_BASE + ((n)-1)*0x24 + 0x10))
+
+
+//struct for gpio
+typedef struct
+{
+ unsigned char port; //端口号
+ unsigned char port_num; //端口内编号
+ char mul_sel; //功能编号
+ char pull; //电阻状态
+ char drv_level; //驱动驱动能力
+ char data; //输出电平
+ unsigned char reserved[2]; //保留位,保证对齐
+}
+normal_gpio_set_t;
+
+int32_t boot_set_gpio(void *user_gpio_list, uint32_t group_count_max, int32_t set_gpio);
+
+#endif /* _SUNXI_GPIO_H */
diff --git a/plat/sun50iw1p1/include/plat_macros.S b/plat/sun50iw1p1/include/plat_macros.S
new file mode 100644
index 0000000..4e35541
--- /dev/null
+++ b/plat/sun50iw1p1/include/plat_macros.S
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <cci400.h>
+#include <gic_v2.h>
+#include <plat_config.h>
+#include "../sunxi_def.h"
+
+.section .rodata.gic_reg_name, "aS"
+gic_regs:
+ .asciz "gic_hppir", "gic_ahppir", "gic_ctlr", ""
+gicd_pend_reg:
+ .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
+newline:
+ .asciz "\n"
+spacer:
+ .asciz ":\t\t0x"
+
+ /* ---------------------------------------------
+ * The below macro prints out relevant GIC
+ * registers whenever an unhandled exception is
+ * taken in BL3-1.
+ * Clobbers: x0 - x10, x16, sp
+ * ---------------------------------------------
+ */
+ .macro plat_print_gic_regs
+ adr x0, plat_config
+ ldr w16, [x0, #CONFIG_GICC_BASE_OFFSET]
+ cbz x16, exit_print_gic_regs
+ /* gic base address is now in x16 */
+ adr x6, gic_regs /* Load the gic reg list to x6 */
+ /* Load the gic regs to gp regs used by str_in_crash_buf_print */
+ ldr w8, [x16, #GICC_HPPIR]
+ ldr w9, [x16, #GICC_AHPPIR]
+ ldr w10, [x16, #GICC_CTLR]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+
+ /* Print the GICD_ISPENDR regs */
+ add x7, x16, #GICD_ISPENDR
+ adr x4, gicd_pend_reg
+ bl asm_print_str
+gicd_ispendr_loop:
+ sub x4, x7, x16
+ cmp x4, #0x280
+ b.eq exit_print_gic_regs
+ bl asm_print_hex
+ adr x4, spacer
+ bl asm_print_str
+ ldr x4, [x7], #8
+ bl asm_print_hex
+ adr x4, newline
+ bl asm_print_str
+ b gicd_ispendr_loop
+exit_print_gic_regs:
+ .endm
+#if 0
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+ .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+ /* ------------------------------------------------
+ * The below macro prints out relevant interconnect
+ * registers whenever an unhandled exception is
+ * taken in BL3-1.
+ * Clobbers: x0 - x9, sp
+ * ------------------------------------------------
+ */
+ .macro plat_print_interconnect_regs
+ adr x6, cci_iface_regs
+ /* Store in x7 the base address of the first interface */
+ mov_imm x7, (CCI400_BASE + SLAVE_IFACE3_OFFSET)
+ ldr w8, [x7, #SNOOP_CTRL_REG]
+ /* Store in x7 the base address of the second interface */
+ mov_imm x7, (CCI400_BASE + SLAVE_IFACE4_OFFSET)
+ ldr w9, [x7, #SNOOP_CTRL_REG]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+ .endm
+#endif
diff --git a/plat/sun50iw1p1/include/platform_def.h b/plat/sun50iw1p1/include/platform_def.h
new file mode 100644
index 0000000..70b8b79
--- /dev/null
+++ b/plat/sun50iw1p1/include/platform_def.h
@@ -0,0 +1,135 @@
+/*
+ * 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>
+#include "../sunxi_def.h"
+
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+#define DEBUG_XLAT_TABLE 0
+
+/* Size of cacheable stacks */
+#if DEBUG_XLAT_TABLE
+#define PLATFORM_STACK_SIZE 0x800
+#elif IMAGE_BL1
+#define PLATFORM_STACK_SIZE 0x440
+#elif IMAGE_BL2
+#define PLATFORM_STACK_SIZE 0x400
+#elif IMAGE_BL31
+#define PLATFORM_STACK_SIZE 0x400
+#elif IMAGE_BL32
+#define PLATFORM_STACK_SIZE 0x440
+#endif
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+
+/* 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 1
+#define PLATFORM_CORE_COUNT 4
+#define PLATFORM_NUM_AFFS (PLATFORM_CLUSTER_COUNT + PLATFORM_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER 4
+
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL3-1 at the top of the Trusted SRAM (just below the shared memory, if
+ * present). BL31_BASE is calculated using the current BL3-1 debug size plus a
+ * little space for growth.
+ */
+#define BL31_BASE (SUNXI_TRUSTED_MONITOR_BASE)
+#define BL31_PROGBITS_LIMIT (SUNXI_TRUSTED_MONITOR_LIMIT - 0x6000)
+#define BL31_LIMIT SUNXI_TRUSTED_MONITOR_LIMIT
+
+/*******************************************************************************
+ * BL32 specific defines.
+ ******************************************************************************/
+/*
+ * On sun50iw1p1, the TSP can execute either from Trusted SRAM or Trusted DRAM.
+ */
+
+#define TSP_SEC_MEM_BASE SUNXI_TRUSTED_DRAM_BASE
+#define TSP_SEC_MEM_SIZE SUNXI_TRUSTED_DRAM_SIZE
+#define BL32_BASE (SUNXI_TRUSTED_DRAM_BASE + SUNXI_SHARED_RAM_SIZE)
+#define BL32_LIMIT (SUNXI_TRUSTED_DRAM_BASE + (1 << 21))
+
+
+/*
+ * ID of the secure physical generic timer interrupt used by the TSP.
+ */
+#define TSP_IRQ_SEC_PHY_TIMER IRQ_SEC_PHY_TIMER
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define ADDR_SPACE_SIZE (1ull << 32)
+#define MAX_XLAT_TABLES 2
+#define MAX_MMAP_REGIONS 16
+
+/*******************************************************************************
+ * 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/sun50iw1p1/include/uart.h b/plat/sun50iw1p1/include/uart.h
new file mode 100644
index 0000000..af26c0b
--- /dev/null
+++ b/plat/sun50iw1p1/include/uart.h
@@ -0,0 +1,43 @@
+#ifndef _UART_H_
+#define _UART_H_
+
+#define NULL ((void*)0)
+#define CCM_UART_PORT_OFFSET 16
+#define CCM_UART_ADDR_OFFSET 0x400
+
+typedef struct serial_hw
+{
+ volatile unsigned int rbr; /* 0 */
+ volatile unsigned int ier; /* 1 */
+ volatile unsigned int fcr; /* 2 */
+ volatile unsigned int lcr; /* 3 */
+ volatile unsigned int mcr; /* 4 */
+ volatile unsigned int lsr; /* 5 */
+ volatile unsigned int msr; /* 6 */
+ volatile unsigned int sch; /* 7 */
+}serial_hw_t;
+
+
+#define UART_BAUD 115200 // Baud rate for UART
+ // Compute the divisor factor
+// UART Line Control Parameter
+#define PARITY 0 // Parity: 0,2 - no parity; 1 - odd parity; 3 - even parity
+#define STOP 0 // Number of Stop Bit: 0 - 1bit; 1 - 2(or 1.5)bits
+#define DLEN 3 // Data Length: 0 - 5bits; 1 - 6bits; 2 - 7bits; 3 - 8bits
+
+#if DEBUG
+void sunxi_serial_init(int uart_port, void *gpio_cfg, int gpio_max);
+void sunxi_serial_exit(void);
+void sunxi_serial_putc (char c);
+char sunxi_serial_getc (void);
+int sunxi_serial_tstc (void);
+#else
+static inline void sunxi_serial_init(int uart_port, void *gpio_cfg, int gpio_max) {}
+static inline void sunxi_serial_exit(void) {}
+static inline void sunxi_serial_putc(char c) {}
+static inline char sunxi_serial_getc(void) { return 0;}
+static inline int sunxi_serial_tstc(void) { return 0;}
+#endif
+
+
+#endif /* #ifndef _UART_H_ */
diff --git a/plat/sun50iw1p1/mhu.c b/plat/sun50iw1p1/mhu.c
new file mode 100644
index 0000000..a817b4d
--- /dev/null
+++ b/plat/sun50iw1p1/mhu.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 <arch_helpers.h>
+#include <bakery_lock.h>
+#include <mmio.h>
+#include <debug.h>
+#include "sunxi_def.h"
+#include "mhu.h"
+#include "scpi.h"
+
+#if 1
+void mhu_secure_message_start(void)
+{
+
+}
+
+void mhu_secure_message_send(uint32_t command)
+{
+ switch(command&0xf)
+ {
+ case SCPI_CMD_SCP_READY:
+ NOTICE("send cmd to scp: SCPI_CMD_SCP_READY\n");
+ break;
+ case SCPI_CMD_SET_CSS_POWER_STATE:
+ NOTICE("send cmd to scp: SCPI_CMD_SET_CSS_POWER_STATE\n");
+ break;
+ case SCPI_CMD_SYS_POWER_STATE:
+ NOTICE("send cmd to scp: SCPI_CMD_SYS_POWER_STATE\n");
+ break;
+ }
+}
+
+uint32_t mhu_secure_message_wait(void)
+{
+ /* Wait for response from SCP */
+
+ return 1;
+}
+
+void mhu_secure_message_end(void)
+{
+
+}
+
+void mhu_secure_init(void)
+{
+
+}
+#else
+/* SCP MHU secure channel registers */
+#define SCP_INTR_S_STAT 0x200
+#define SCP_INTR_S_SET 0x208
+#define SCP_INTR_S_CLEAR 0x210
+
+/* CPU MHU secure channel registers */
+#define CPU_INTR_S_STAT 0x300
+#define CPU_INTR_S_SET 0x308
+#define CPU_INTR_S_CLEAR 0x310
+
+
+static bakery_lock_t mhu_secure_lock __attribute__ ((section("tzfw_coherent_mem")));
+
+void mhu_secure_message_start(void)
+{
+ bakery_lock_get(&mhu_secure_lock);
+
+ /* Make sure any previous command has finished */
+ while (mmio_read_32(MHU_BASE + CPU_INTR_S_STAT) != 0)
+ ;
+}
+
+void mhu_secure_message_send(uint32_t command)
+{
+ /* Send command to SCP and wait for it to pick it up */
+ mmio_write_32(MHU_BASE + CPU_INTR_S_SET, command);
+ while (mmio_read_32(MHU_BASE + CPU_INTR_S_STAT) != 0)
+ ;
+}
+
+uint32_t mhu_secure_message_wait(void)
+{
+ /* Wait for response from SCP */
+ uint32_t response;
+ while (!(response = mmio_read_32(MHU_BASE + SCP_INTR_S_STAT)))
+ ;
+
+ return response;
+}
+
+void mhu_secure_message_end(void)
+{
+ /* Clear any response we got by writing all ones to the CLEAR register */
+ mmio_write_32(MHU_BASE + SCP_INTR_S_CLEAR, 0xffffffffu);
+
+ bakery_lock_release(&mhu_secure_lock);
+}
+
+void mhu_secure_init(void)
+{
+ bakery_lock_init(&mhu_secure_lock);
+
+ /*
+ * Clear the CPU's INTR register to make sure we don't see a stale
+ * or garbage value and think it's a message we've already sent.
+ */
+ mmio_write_32(MHU_BASE + CPU_INTR_S_CLEAR, 0xffffffffu);
+}
+#endif
diff --git a/plat/sun50iw1p1/mhu.h b/plat/sun50iw1p1/mhu.h
new file mode 100644
index 0000000..5149c82
--- /dev/null
+++ b/plat/sun50iw1p1/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/sun50iw1p1/plat_gic.c b/plat/sun50iw1p1/plat_gic.c
new file mode 100644
index 0000000..78e1a81
--- /dev/null
+++ b/plat/sun50iw1p1/plat_gic.c
@@ -0,0 +1,402 @@
+/*
+ * 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 <debug.h>
+#include "sunxi_def.h"
+#include "sunxi_private.h"
+#include "gic_sunxi.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);
+}
+
+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);
+}
+
+#if 0
+/*******************************************************************************
+ * 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);
+}
+#endif
+
+#define writel(v,a) mmio_write_32((a),(v))
+
+void gic_distributor_init(uint32_t addr)
+{
+ uint32_t cpumask = 0x01010101;
+ uint32_t gic_irqs;
+ uint32_t i;
+
+ writel(0, GIC_DIST_CON);
+ /* check GIC hardware configutation */
+ gic_irqs = ((mmio_read_32(GIC_CON_TYPE) & 0x1f) + 1) * 32;
+ if (gic_irqs > 1020)
+ {
+ gic_irqs = 1020;
+ }
+ if (gic_irqs < GIC_IRQ_NUM)
+ {
+ NOTICE("GIC parameter config error, only support %d"
+ " irqs < %d(spec define)!!\n", gic_irqs, GIC_IRQ_NUM);
+ return ;
+ }
+
+ /* Set ALL interrupts as group1(non-secure) interrupts */
+ for (i=1; i<GIC_IRQ_NUM; i+=16)
+ {
+ writel(0xffffffff, GIC_CON_IGRP(i>>4));
+ }
+
+
+ /* set trigger type to be level-triggered, active low */
+ for (i=0; i<GIC_IRQ_NUM; i+=16)
+ {
+ writel(0, GIC_IRQ_MOD_CFG(i>>4));
+ }
+ /* set priority */
+ for (i=GIC_SRC_SPI(0); i<GIC_IRQ_NUM; i+=4)
+ {
+ writel(0xa0a0a0a0, GIC_SPI_PRIO((i-32)>>2));
+ }
+ /* set processor target */
+ for (i=32; i<GIC_IRQ_NUM; i+=4)
+ {
+ writel(cpumask, GIC_SPI_PROC_TARG((i-32)>>2));
+ }
+ /* disable all interrupts */
+ for (i=32; i<GIC_IRQ_NUM; i+=32)
+ {
+ writel(0xffffffff, GIC_CLR_EN(i>>5));
+ }
+ /* clear all interrupt active state */
+ for (i=32; i<GIC_IRQ_NUM; i+=32)
+ {
+ writel(0xffffffff, GIC_ACT_CLR(i>>5));
+ }
+
+ writel(3, GIC_DIST_CON);
+
+
+ return ;
+}
+/*
+************************************************************************************************************
+*
+* function
+*
+* name :
+*
+* parmeters :
+*
+* return :
+*
+* note :
+*
+*
+************************************************************************************************************
+*/
+void gic_cpuif_init(uint32_t addr)
+{
+ uint32_t i;
+
+ writel(0, GIC_CPU_IF_CTRL);
+ /*
+ * Deal with the banked PPI and SGI interrupts - disable all
+ * PPI interrupts, ensure all SGI interrupts are enabled.
+ */
+ writel(0xffff0000, GIC_CLR_EN(0));
+ writel(0x0000ffff, GIC_SET_EN(0));
+ /* Set priority on PPI and SGI interrupts */
+ for (i=0; i<16; i+=4)
+ {
+ writel(0xa0a0a0a0, GIC_SGI_PRIO(i>>2));
+ }
+ for (i=16; i<32; i+=4)
+ {
+ writel(0xa0a0a0a0, GIC_PPI_PRIO((i-16)>>2));
+ }
+
+ writel(0xf0, GIC_INT_PRIO_MASK);
+
+ writel(0xb, GIC_CPU_IF_CTRL);
+
+ return ;
+}
+
+void gic_pcpu_distif_setup(unsigned int gicd_base)
+{
+ int 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, 0xa0a0a0a0);
+}
+
+void gic_setup(void)
+{
+ gic_cpuif_init(GICC_BASE);
+ gic_distributor_init(GICD_BASE);
+}
+
+/*******************************************************************************
+ * An ARM processor signals interrupt exceptions through the IRQ and FIQ pins.
+ * The interrupt controller knows which pin/line it uses to signal a type of
+ * interrupt. The platform knows which interrupt controller type is being used
+ * in a particular security state e.g. with an ARM GIC, normal world could use
+ * the GICv2 features while the secure world could use GICv3 features and vice
+ * versa.
+ * This function is exported by the platform to let the interrupt management
+ * framework determine for a type of interrupt and security state, which line
+ * should be used in the SCR_EL3 to control its routing to EL3. The interrupt
+ * line is represented as the bit position of the IRQ or FIQ bit in the SCR_EL3.
+ ******************************************************************************/
+uint32_t plat_interrupt_type_to_line(uint32_t type, uint32_t security_state)
+{
+ assert(type == INTR_TYPE_S_EL1 ||
+ type == INTR_TYPE_EL3 ||
+ type == INTR_TYPE_NS);
+
+ assert(sec_state_is_valid(security_state));
+
+ /*
+ * We ignore the security state parameter because Juno is GICv2 only
+ * so both normal and secure worlds are using ARM GICv2.
+ */
+ return gicv2_interrupt_type_to_line(GICC_BASE, type);
+}
+
+/*******************************************************************************
+ * This function returns the type of the highest priority pending interrupt at
+ * the GIC cpu interface. INTR_TYPE_INVAL is returned when there is no
+ * interrupt pending.
+ ******************************************************************************/
+uint32_t plat_ic_get_pending_interrupt_type(void)
+{
+ uint32_t id;
+
+ id = gicc_read_hppir(GICC_BASE);
+
+ /* Assume that all secure interrupts are S-EL1 interrupts */
+ if (id < 1022)
+ return INTR_TYPE_S_EL1;
+
+ if (id == GIC_SPURIOUS_INTERRUPT)
+ return INTR_TYPE_INVAL;
+
+ return INTR_TYPE_NS;
+}
+
+/*******************************************************************************
+ * This function returns the id of the highest priority pending interrupt at
+ * the GIC cpu interface. INTR_ID_UNAVAILABLE is returned when there is no
+ * interrupt pending.
+ ******************************************************************************/
+uint32_t plat_ic_get_pending_interrupt_id(void)
+{
+ uint32_t id;
+
+ id = gicc_read_hppir(GICC_BASE);
+
+ if (id < 1022)
+ return id;
+
+ if (id == 1023)
+ return INTR_ID_UNAVAILABLE;
+
+ /*
+ * Find out which non-secure interrupt it is under the assumption that
+ * the GICC_CTLR.AckCtl bit is 0.
+ */
+ return gicc_read_ahppir(GICC_BASE);
+}
+
+/*******************************************************************************
+ * This functions reads the GIC cpu interface Interrupt Acknowledge register
+ * to start handling the pending interrupt. It returns the contents of the IAR.
+ ******************************************************************************/
+uint32_t plat_ic_acknowledge_interrupt(void)
+{
+ return gicc_read_IAR(GICC_BASE);
+}
+
+/*******************************************************************************
+ * This functions writes the GIC cpu interface End Of Interrupt register with
+ * the passed value to finish handling the active interrupt
+ ******************************************************************************/
+void plat_ic_end_of_interrupt(uint32_t id)
+{
+ gicc_write_EOIR(GICC_BASE, id);
+}
+
+/*******************************************************************************
+ * This function returns the type of the interrupt id depending upon the group
+ * this interrupt has been configured under by the interrupt controller i.e.
+ * group0 or group1.
+ ******************************************************************************/
+uint32_t plat_ic_get_interrupt_type(uint32_t id)
+{
+ uint32_t group;
+
+ group = gicd_get_igroupr(GICD_BASE, id);
+
+ /* Assume that all secure interrupts are S-EL1 interrupts */
+ if (group == GRP0)
+ return INTR_TYPE_S_EL1;
+ else
+ return INTR_TYPE_NS;
+}
diff --git a/plat/sun50iw1p1/plat_pm.c b/plat/sun50iw1p1/plat_pm.c
new file mode 100644
index 0000000..f4f4e29
--- /dev/null
+++ b/plat/sun50iw1p1/plat_pm.c
@@ -0,0 +1,335 @@
+/*
+ * 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 <debug.h>
+#include <errno.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <psci.h>
+#include <mmio.h>
+#include <bakery_lock.h>
+#include "sunxi_def.h"
+#include "sunxi_private.h"
+#include "scpi.h"
+#include "sunxi_cpu_ops.h"
+#include <arisc.h>
+#include <cci400.h>
+#include <console.h>
+#include <psci.h>
+
+bakery_lock_t plat_console_lock __attribute__ ((section("tzfw_coherent_mem")));
+
+/*******************************************************************************
+ * Private Sunxi function to program the mailbox for a cpu before it is released
+ * from reset.
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Private Sunxi function which is used to determine if any platform actions
+ * should be performed for the specified affinity instance given its
+ * state. Nothing needs to be done if the 'state' is not off or if this is not
+ * the highest affinity level which will enter the 'state'.
+ ******************************************************************************/
+static int32_t sunxi_do_plat_actions(uint32_t afflvl, uint32_t state)
+{
+ uint32_t max_phys_off_afflvl;
+
+ assert(afflvl <= MPIDR_MAX_AFFLVL);
+
+ if (state != PSCI_STATE_OFF)
+ return -EAGAIN;
+
+ /*
+ * Find the highest affinity level which will be suspended and postpone
+ * all the platform specific actions until that level is hit.
+ */
+ max_phys_off_afflvl = psci_get_max_phys_off_afflvl();
+ assert(max_phys_off_afflvl != PSCI_INVALID_DATA);
+ assert(psci_get_suspend_afflvl() >= max_phys_off_afflvl);
+ if (afflvl != max_phys_off_afflvl)
+ return -EAGAIN;
+
+ return 0;
+}
+
+/*******************************************************************************
+ * Sunxi handler called when an affinity instance is about to be turned on. The
+ * level and mpidr determine the affinity instance.
+ ******************************************************************************/
+int32_t sunxi_affinst_on(uint64_t mpidr,
+ uint64_t sec_entrypoint,
+ uint64_t ns_entrypoint,
+ uint32_t afflvl,
+ uint32_t state)
+{
+ /*
+ * SCP takes care of powering up higher affinity levels so we
+ * only need to care about level 0
+ */
+ if (afflvl != MPIDR_AFFLVL0)
+ return PSCI_E_SUCCESS;
+
+ //INFO("mpidr:0x%llx, sec_entrypoint:0x%lx, ns_entrypoint:0x%lx, afflvl:0x%x, state:0x%x\n",
+ //mpidr, sec_entrypoint, ns_entrypoint, afflvl, state);
+ arisc_cpu_op(mpidr&0xff, sec_entrypoint, arisc_power_on, arisc_power_on);
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Sunxi handler called when an affinity instance has just been powered on after
+ * being turned off earlier. The level and mpidr determine the affinity
+ * instance. The 'state' arg. allows the platform to decide whether the cluster
+ * was turned off prior to wakeup and do what's necessary to setup it up
+ * correctly.
+ ******************************************************************************/
+int32_t sunxi_affinst_on_finish(uint64_t mpidr, uint32_t afflvl, uint32_t state)
+{
+ /* Determine if any platform actions need to be executed. */
+ if (sunxi_do_plat_actions(afflvl, state) == -EAGAIN)
+ return PSCI_E_SUCCESS;
+
+
+ /*
+ * Perform the common cluster specific operations i.e enable coherency
+ * if this cluster was off.
+ */
+ if (afflvl != MPIDR_AFFLVL0)
+ {
+ //cci_enable_cluster_coherency(mpidr);
+ }
+
+ // set smp bit before cache enable
+ platform_smp_init();
+
+ /* Enable the gic cpu interface */
+ gic_cpuif_setup(GICC_BASE);
+
+ /* Sunxi todo: Is this setup only needed after a cold boot? */
+ gic_pcpu_distif_setup(GICD_BASE);
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * sunxi handler called when an affinity instance is about to enter standby.
+ ******************************************************************************/
+int sunxi_affinst_standby(unsigned int power_state)
+{
+ unsigned int target_afflvl;
+ uint64_t scr = 0;
+
+ /* 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;
+
+ scr = read_scr_el3();
+ /* enable physical IRQ bit for NS world to wakeup the CPU */
+ write_scr_el3(scr | SCR_IRQ_BIT);
+ isb();
+
+ /*
+ * * Enter standby state
+ * * dsb is good practice before using wfi to enter low power states
+ * */
+ dsb();
+ wfi();
+
+ /*
+ * * Restore SCR to the original value, sync of scr_el3 is done
+ * * by eret while el3_exit to save some execution cycles.
+ * * */
+ write_scr_el3(scr);
+
+ return PSCI_E_SUCCESS;
+
+}
+
+/*******************************************************************************
+ * Common function called while turning a cpu off or suspending it. It is called
+ * from sunxi_off() or sunxi_suspend() when these functions in turn are called for
+ * the highest affinity level which will be powered down. It performs the
+ * actions common to the OFF and SUSPEND calls.
+ ******************************************************************************/
+static int32_t sunxi_power_down_common(uint32_t afflvl, uint64_t mpidr, uint64_t sec_entrypoint)
+{
+ uint32_t cluster_state = arisc_power_on;
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ gic_cpuif_deactivate(GICC_BASE);
+
+ /* Cluster is to be turned off, so disable coherency */
+ if (afflvl > MPIDR_AFFLVL0) {
+ //cci_disable_cluster_coherency(read_mpidr_el1());
+ cluster_state = arisc_power_off;
+ }
+
+ //INFO("afflvl:0x%x, mpidr:0x%lx, sec_entrypoint: %lx\n",
+ //afflvl, mpidr, sec_entrypoint);
+ arisc_cpu_op(mpidr&0xff, sec_entrypoint, scpi_power_off, cluster_state);
+
+ 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
+ * appropriate actions.
+ *
+ * CAUTION: 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 int32_t sunxi_affinst_off(uint64_t mpidr, uint32_t afflvl, uint32_t state)
+{
+ /* Determine if any platform actions need to be executed */
+ if (sunxi_do_plat_actions(afflvl, state) == -EAGAIN)
+ return PSCI_E_SUCCESS;
+
+ return sunxi_power_down_common(afflvl, mpidr, 0);
+}
+
+/*******************************************************************************
+ * 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: 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 int32_t sunxi_affinst_suspend(uint64_t mpidr,
+ uint64_t sec_entrypoint,
+ uint64_t ns_entrypoint,
+ uint32_t afflvl,
+ uint32_t state)
+{
+ /* Determine if any platform actions need to be executed */
+ if (sunxi_do_plat_actions(afflvl, state) == -EAGAIN)
+ return PSCI_E_SUCCESS;
+
+ if (afflvl == psci_get_suspend_afflvl())
+ console_exit();
+
+ return sunxi_power_down_common(afflvl, mpidr, sec_entrypoint);
+}
+
+/*******************************************************************************
+ * Sunxi 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.
+ ******************************************************************************/
+static int32_t sunxi_affinst_suspend_finish(uint64_t mpidr,
+ uint32_t afflvl,
+ uint32_t state)
+{
+ if ((afflvl == psci_get_suspend_afflvl()) && ((mpidr & 0xff) == 0x0)) {
+ gic_setup();
+ console_init(SUNXI_UART0_BASE, UART0_CLK_IN_HZ, UART0_BAUDRATE);
+ arisc_cpux_ready_notify();
+
+ }
+
+ return sunxi_affinst_on_finish(mpidr, afflvl, state);
+}
+
+/*******************************************************************************
+ * Sunxi handlers to shutdown/reboot the system
+ ******************************************************************************/
+static void __dead2 sunxi_system_off(void)
+{
+ uint32_t response;
+
+ /* Send the power down request to the SCP */
+ response = arisc_system_op(arisc_system_shutdown);
+
+ if (response != SCP_OK) {
+ ERROR("Sunxi System Off: SCP error %u.\n", response);
+ panic();
+ }
+ wfi();
+ ERROR("Sunxi System Off: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 sunxi_system_reset(void)
+{
+ uint32_t response;
+
+ /* Send the system reset request to the SCP */
+ response = arisc_system_op(scpi_system_reboot);
+
+ if (response != SCP_OK) {
+ ERROR("Sunxi System Reset: SCP error %u.\n", response);
+ panic();
+ }
+ wfi();
+ ERROR("Sunxi System Reset: operation not handled.\n");
+ panic();
+}
+
+/*******************************************************************************
+ * Export the platform handlers to enable psci to invoke them
+ ******************************************************************************/
+static const plat_pm_ops_t sunxi_ops = {
+ .affinst_standby = sunxi_affinst_standby,
+ .affinst_on = sunxi_affinst_on,
+ .affinst_on_finish = sunxi_affinst_on_finish,
+ .affinst_off = sunxi_affinst_off,
+ .affinst_suspend = sunxi_affinst_suspend,
+ .affinst_suspend_finish = sunxi_affinst_suspend_finish,
+ .system_off = sunxi_system_off,
+ .system_reset = sunxi_system_reset
+};
+
+/*******************************************************************************
+ * Export the platform specific power ops.
+ ******************************************************************************/
+int32_t platform_setup_pm(const plat_pm_ops_t **plat_ops)
+{
+ *plat_ops = &sunxi_ops;
+ bakery_lock_init(&plat_console_lock);
+ return 0;
+}
diff --git a/plat/sun50iw1p1/plat_topology.c b/plat/sun50iw1p1/plat_topology.c
new file mode 100644
index 0000000..7b2426a
--- /dev/null
+++ b/plat/sun50iw1p1/plat_topology.c
@@ -0,0 +1,253 @@
+/*
+ * 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>
+
+/* 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 sunxi_aff2_topology_map[1];
+static affinity_info_t sunxi_aff1_topology_map[PLATFORM_CLUSTER_COUNT];
+static affinity_info_t sunxi_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);
+
+ /* Fetch the starting index in the aff1 array */
+ for (ctr = 0;
+ sunxi_aff2_topology_map[ctr].sibling != AFFINST_INVAL;
+ ctr = sunxi_aff2_topology_map[ctr].sibling) {
+ aff_count++;
+ }
+
+ /*
+ * 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;
+ sunxi_aff1_topology_map[ctr].sibling != AFFINST_INVAL;
+ ctr = sunxi_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 = sunxi_aff1_topology_map[parent_aff_id].child;
+ sunxi_aff0_topology_map[ctr].sibling != AFFINST_INVAL;
+ ctr = sunxi_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:
+ aff_state = sunxi_aff2_topology_map[0].state;
+ /* Report affinity levels 2 & 3 as absent */
+ break;
+ case 1:
+ aff_state = sunxi_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 = sunxi_aff1_topology_map[idx].child;
+ idx += (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+ aff_state = sunxi_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(void)
+{
+ return MPIDR_MAX_AFFLVL;
+}
+
+/*******************************************************************************
+ * 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 sunxi_setup_topology(void)
+{
+ unsigned char aff0, aff1, aff_state, aff0_offset = 0;
+ unsigned long mpidr;
+
+ topology_setup_done = 0;
+
+ sunxi_aff2_topology_map[0].child = 0;
+ sunxi_aff2_topology_map[0].sibling = AFFINST_INVAL;
+ sunxi_aff2_topology_map[0].state = PSCI_AFF_PRESENT;
+
+
+ for (aff1 = 0; aff1 < PLATFORM_CLUSTER_COUNT; aff1++) {
+
+ sunxi_aff1_topology_map[aff1].child = aff0_offset;
+ sunxi_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 (1) {
+ /*
+ * Presence of even a single aff0 indicates
+ * presence of parent aff1 on the FVP.
+ */
+ aff_state = PSCI_AFF_PRESENT;
+ sunxi_aff1_topology_map[aff1].state =
+ PSCI_AFF_PRESENT;
+ } else {
+ aff_state = PSCI_AFF_ABSENT;
+ }
+
+ sunxi_aff0_topology_map[aff0_offset].child = AFFINST_INVAL;
+ sunxi_aff0_topology_map[aff0_offset].state = aff_state;
+ sunxi_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 */
+ sunxi_aff0_topology_map[aff0_offset - 1].sibling = AFFINST_INVAL;
+ }
+
+ /* Tie-off the last aff1 sibling to AFFINST_INVAL to avoid overflow */
+ sunxi_aff1_topology_map[aff1 - 1].sibling = AFFINST_INVAL;
+
+ topology_setup_done = 1;
+ return 0;
+}
diff --git a/plat/sun50iw1p1/platform.mk b/plat/sun50iw1p1/platform.mk
new file mode 100644
index 0000000..b250d20
--- /dev/null
+++ b/plat/sun50iw1p1/platform.mk
@@ -0,0 +1,91 @@
+#
+# 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.
+#
+
+# Shared memory may be allocated at the top of Trusted SRAM (tsram) or at the
+# base of Trusted SRAM (tdram)
+SUNXI_SHARED_DATA_LOCATION := tdram
+ifeq (${SUNXI_SHARED_DATA_LOCATION}, tsram)
+ SUNXI_SHARED_DATA_LOCATION_ID := SUNXI_IN_TRUSTED_SRAM
+else ifeq (${SUNXI_SHARED_DATA_LOCATION}, tdram)
+ SUNXI_SHARED_DATA_LOCATION_ID := SUNXI_IN_TRUSTED_DRAM
+else
+ $(error "Unsupported SUNXI_SHARED_DATA_LOCATION value")
+endif
+
+# On FVP, the TSP can execute either from Trusted SRAM or Trusted DRAM.
+# Trusted SRAM is the default.
+SUNXI_TSP_RAM_LOCATION := tdram
+ifeq (${SUNXI_TSP_RAM_LOCATION}, tsram)
+ SUNXI_TSP_RAM_LOCATION_ID := SUNXI_IN_TRUSTED_SRAM
+else ifeq (${SUNXI_TSP_RAM_LOCATION}, tdram)
+ SUNXI_TSP_RAM_LOCATION_ID := SUNXI_IN_TRUSTED_DRAM
+else
+ $(error "Unsupported SUNXI_TSP_RAM_LOCATION value")
+endif
+
+ifeq (${SUNXI_SHARED_DATA_LOCATION}, tsram)
+ ifeq (${SUNXI_TSP_RAM_LOCATION}, tdram)
+ $(error Shared data in Trusted SRAM and TSP in Trusted DRAM is not supported)
+ endif
+endif
+
+# Process flags
+$(eval $(call add_define,SUNXI_SHARED_DATA_LOCATION_ID))
+$(eval $(call add_define,SUNXI_TSP_RAM_LOCATION_ID))
+
+PLAT_INCLUDES := -Iplat/sun50iw1p1/include/
+
+
+PLAT_BL_COMMON_SOURCES := lib/aarch64/xlat_tables.c \
+ plat/common/aarch64/plat_common.c \
+ plat/sun50iw1p1/drivers/uart/uart.c \
+ plat/sun50iw1p1/drivers/gpio/gpio.c
+
+
+
+BL31_SOURCES += drivers/arm/cci400/cci400.c \
+ drivers/arm/gic/gic_v2.c \
+ lib/cpus/aarch64/aem_generic.S \
+ lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a57.S \
+ plat/common/aarch64/platform_mp_stack.S \
+ plat/sun50iw1p1/bl31_sunxi_setup.c \
+ plat/sun50iw1p1/plat_pm.c \
+ plat/sun50iw1p1/plat_gic.c \
+ plat/sun50iw1p1/mhu.c \
+ plat/sun50iw1p1/scpi.c \
+ plat/sun50iw1p1/sunxi_security.c \
+ plat/sun50iw1p1/sunxi_cpu_ops.c \
+ plat/sun50iw1p1/plat_topology.c \
+ plat/sun50iw1p1/aarch64/plat_helpers.S \
+ plat/sun50iw1p1/aarch64/sunxi_common.c \
+ services/arm/arm_svc_setup.c
+
+include plat/${PLAT}/scp/arisc.mk
diff --git a/plat/sun50iw1p1/scp/arisc.c b/plat/sun50iw1p1/scp/arisc.c
new file mode 100644
index 0000000..1430b7e
--- /dev/null
+++ b/plat/sun50iw1p1/scp/arisc.c
@@ -0,0 +1,248 @@
+/*
+ * drivers/arisc/arisc.c
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "arisc_i.h"
+
+/* local functions */
+static int arisc_wait_ready(unsigned int timeout);
+
+struct dts_cfg dts_cfg;
+unsigned int arisc_debug_dram_crc_en = 0;
+unsigned int arisc_debug_dram_crc_srcaddr = 0x40000000;
+unsigned int arisc_debug_dram_crc_len = (1024 * 1024);
+unsigned int arisc_debug_dram_crc_error = 0;
+unsigned int arisc_debug_dram_crc_total_count = 0;
+unsigned int arisc_debug_dram_crc_error_count = 0;
+volatile const unsigned int arisc_debug_level = 2;
+static unsigned char arisc_version[40] = "arisc defualt version";
+
+static int arisc_wait_ready(unsigned int timeout)
+{
+ /* wait arisc startup ready */
+ while (1) {
+ /*
+ * linux cpu interrupt is disable now,
+ * we should query message by hand.
+ */
+ struct arisc_message *pmessage = arisc_hwmsgbox_query_message();
+ if (pmessage == NULL) {
+ /* try to query again */
+ continue;
+ }
+ /* query valid message */
+ if (pmessage->type == ARISC_STARTUP_NOTIFY) {
+ /* check arisc software and driver version match or not */
+ if (pmessage->paras[0] != ARISC_VERSIONS) {
+ ARISC_ERR("arisc firmware:%d and driver version:%u not matched\n", pmessage->paras[0], ARISC_VERSIONS);
+ return -EINVAL;
+ } else {
+ /* printf the main and sub version string */
+ memcpy((void *)arisc_version, (const void*)(&(pmessage->paras[1])), 40);
+ ARISC_LOG("arisc version: [%s]\n", arisc_version);
+ }
+
+ /* received arisc startup ready message */
+ ARISC_INF("arisc startup ready\n");
+ if ((pmessage->attr & ARISC_MESSAGE_ATTR_SOFTSYN) ||
+ (pmessage->attr & ARISC_MESSAGE_ATTR_HARDSYN)) {
+ /* synchronous message, just feedback it */
+ ARISC_INF("arisc startup notify message feedback\n");
+ pmessage->paras[0] = (uint32_t)dts_cfg.image.base;
+ arisc_hwmsgbox_feedback_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+ } else {
+ /* asyn message, free message directly */
+ ARISC_INF("arisc startup notify message free directly\n");
+ arisc_message_free(pmessage);
+ }
+ break;
+ }
+ /*
+ * invalid message detected, ignore it.
+ * by superm at 2012-7-6 18:34:38.
+ */
+ ARISC_WRN("arisc startup waiting ignore message\n");
+ if ((pmessage->attr & ARISC_MESSAGE_ATTR_SOFTSYN) ||
+ (pmessage->attr & ARISC_MESSAGE_ATTR_HARDSYN)) {
+ /* synchronous message, just feedback it */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+ } else {
+ /* asyn message, free message directly */
+ arisc_message_free(pmessage);
+ }
+ /* we need waiting continue */
+ }
+
+ return 0;
+}
+
+int sunxi_deassert_arisc(void)
+{
+ ARISC_INF("set arisc reset to de-assert state\n");
+ {
+ volatile unsigned long value;
+ value = readl(dts_cfg.cpuscfg.base + 0x0);
+ value &= ~1;
+ writel(value, dts_cfg.cpuscfg.base + 0x0);
+ value = readl(dts_cfg.cpuscfg.base + 0x0);
+ value |= 1;
+ writel(value, dts_cfg.cpuscfg.base + 0x0);
+ }
+
+ return 0;
+}
+
+static int sunxi_arisc_para_init(struct arisc_para *para)
+{
+ /* init para */
+ memset(para, 0, sizeof(struct arisc_para));
+ para->message_pool_phys = (uint32_t)dts_cfg.space.msgpool_dst;
+ para->message_pool_size = (uint32_t)dts_cfg.space.msgpool_size;
+ para->standby_base = (uint32_t)dts_cfg.space.standby_dst;
+ para->standby_size = (uint32_t)dts_cfg.space.standby_size;
+ memcpy((void *)&para->vf, (void *)dts_cfg.vf, sizeof(para->vf));
+ memcpy((void *)&para->dram_para, (void *)&dts_cfg.dram_para, sizeof(para->dram_para));
+ para->power_key_code = dts_cfg.s_cir.power_key_code;
+ para->addr_code = dts_cfg.s_cir.addr_code;
+ para->suart_status = dts_cfg.s_uart.status;
+ para->pmu_bat_shutdown_ltf = dts_cfg.pmu.pmu_bat_shutdown_ltf;
+ para->pmu_bat_shutdown_htf = dts_cfg.pmu.pmu_bat_shutdown_htf;
+ para->pmu_pwroff_vol = dts_cfg.pmu.pmu_pwroff_vol;
+ para->power_start = dts_cfg.pmu.power_start;
+ para->powchk_used = dts_cfg.power.powchk_used;
+ para->power_reg = dts_cfg.power.power_reg;
+ para->system_power = dts_cfg.power.system_power;
+
+ ARISC_LOG("arisc_para size:%llx\n", sizeof(struct arisc_para));
+ ARISC_INF("msgpool base:%x, size:%u\n", para->message_pool_phys,
+ para->message_pool_size);
+
+ return 0;
+}
+
+uint32_t sunxi_load_arisc(uintptr_t image_addr, size_t image_size, void *para, size_t para_size)
+{
+ void *dst;
+ void *src;
+ size_t size;
+
+#if 0
+ /*
+ * phys addr to virt addr
+ * io space: ioremap
+ * kernel space: phys_to_virt
+ */
+ /* sram code space */
+ dst = (void *)dts_cfg.space.sram_dst;
+ src = (void *)((ptrdiff_t)image_addr + (ptrdiff_t)dts_cfg.space.sram_offset);
+ size = dts_cfg.space.sram_size;
+ memset(dst, 0, size);
+ memcpy(dst, src, size);
+ flush_dcache_range((uint64_t)dst, (uint64_t)size);
+
+ /* dram code space */
+ dst = (void *)dts_cfg.space.dram_dst;
+ src = (void *)((ptrdiff_t)image_addr + (ptrdiff_t)dts_cfg.space.dram_offset);
+ size = dts_cfg.space.dram_size;
+ memset(dst, 0, size);
+ memcpy(dst, src, size);
+ flush_dcache_range((uint64_t)dst, (uint64_t)size);
+
+ ARISC_INF("load arisc image finish\n");
+#endif
+ /* para space */
+ dst = (void *)dts_cfg.space.para_dst;
+ src = para;
+ size = dts_cfg.space.para_size;
+ memset(dst, 0, size);
+ memcpy(dst, src, size);
+ ARISC_INF("setup arisc para finish\n");
+ //dcsw_op_all(DCCISW);
+ flush_dcache_range((uint64_t)dst, (uint64_t)size);
+ isb();
+
+#if 0
+ /* relese arisc reset */
+ sunxi_deassert_arisc();
+ ARISC_INF("release arisc reset finish\n");
+
+ ARISC_INF("load arisc finish\n");
+#endif
+
+ return 0;
+}
+
+int sunxi_arisc_probe(void *cfg)
+{
+ struct arisc_para para;
+
+ ARISC_LOG("sunxi-arisc driver begin startup %d\n", arisc_debug_level);
+ memcpy((void *)&dts_cfg, (const void *)cfg, sizeof(struct dts_cfg));
+
+ /* init arisc parameter */
+ sunxi_arisc_para_init(&para);
+
+ /* load arisc */
+ sunxi_load_arisc(dts_cfg.image.base, dts_cfg.image.size,
+ (void *)(&para), sizeof(struct arisc_para));
+
+ /* initialize hwspinlock */
+ ARISC_INF("hwspinlock initialize\n");
+ arisc_hwspinlock_init();
+
+ /* initialize hwmsgbox */
+ ARISC_INF("hwmsgbox initialize\n");
+ arisc_hwmsgbox_init();
+
+ /* initialize message manager */
+ ARISC_INF("message manager initialize start:0x%llx, size:0x%llx\n", dts_cfg.space.msgpool_dst, dts_cfg.space.msgpool_size);
+ arisc_message_manager_init((void *)dts_cfg.space.msgpool_dst, dts_cfg.space.msgpool_size);
+
+ /* wait arisc ready */
+ ARISC_INF("wait arisc ready....\n");
+ if (arisc_wait_ready(10000)) {
+ ARISC_LOG("arisc startup failed\n");
+ }
+
+ arisc_set_paras();
+
+ /* enable arisc asyn tx interrupt */
+ //arisc_hwmsgbox_enable_receiver_int(ARISC_HWMSGBOX_ARISC_ASYN_TX_CH, AW_HWMSG_QUEUE_USER_AC327);
+
+ /* enable arisc syn tx interrupt */
+ //arisc_hwmsgbox_enable_receiver_int(ARISC_HWMSGBOX_ARISC_SYN_TX_CH, AW_HWMSG_QUEUE_USER_AC327);
+
+ /* arisc initialize succeeded */
+ ARISC_LOG("sunxi-arisc driver v%s is starting\n", DRV_VERSION);
+
+ return 0;
+}
+
+int sunxi_arisc_wait_ready(void)
+{
+ ARISC_INF("wait arisc ready....\n");
+ if (arisc_wait_ready(10000)) {
+ ARISC_LOG("arisc startup failed\n");
+ }
+ arisc_set_paras();
+ ARISC_LOG("sunxi-arisc driver v%s startup ok\n", DRV_VERSION);
+ return 0;
+}
+
diff --git a/plat/sun50iw1p1/scp/arisc.mk b/plat/sun50iw1p1/scp/arisc.mk
new file mode 100644
index 0000000..f75311c
--- /dev/null
+++ b/plat/sun50iw1p1/scp/arisc.mk
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+BL31_SOURCES += plat/sun50iw1p1/scp/arisc.c
+
+include plat/sun50iw1p1/scp/hwmsgbox/hwmsgbox.mk
+include plat/sun50iw1p1/scp/hwspinlock/hwspinlock.mk
+include plat/sun50iw1p1/scp/message_manager/message_manager.mk
+include plat/sun50iw1p1/scp/interfaces/interfaces.mk
diff --git a/plat/sun50iw1p1/scp/arisc_i.h b/plat/sun50iw1p1/scp/arisc_i.h
new file mode 100644
index 0000000..f44ffc1
--- /dev/null
+++ b/plat/sun50iw1p1/scp/arisc_i.h
@@ -0,0 +1,84 @@
+/*
+ * arch/arm/mach-sun6i/arisc/arisc_i.h
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ARISC_I_H__
+#define __ARISC_I_H__
+
+//#include <asm/atomic.h>
+//#include <asm/barrier.h>
+//#include <asm/memory.h>
+//#include <linux/arisc/arisc.h>
+//#include <linux/sysfs.h>
+//#include <linux/device.h>
+//#include <linux/gpio.h>
+//#include <linux/pinctrl/consumer.h>
+//#include <linux/module.h>
+//#include <linux/platform_device.h>
+//#include <linux/delay.h>
+//#include <linux/clk.h>
+//#include <linux/arisc/arisc-notifier.h>
+//#include <linux/of_address.h>
+//#include <linux/of_irq.h>
+//#include <linux/of_platform.h>
+
+#include "./include/arisc_includes.h"
+
+#define DRV_NAME "sunxi-arisc"
+#define DEV_NAME "sunxi-arisc"
+
+#if defined CONFIG_ARCH_SUN8IW1P1
+#define DRV_VERSION "1.00"
+#elif defined CONFIG_ARCH_SUN8IW3P1
+#define DRV_VERSION "1.01"
+#elif defined CONFIG_ARCH_SUN8IW5P1
+#define DRV_VERSION "1.02"
+#elif defined CONFIG_ARCH_SUN8IW6P1
+#define DRV_VERSION "1.03"
+#elif defined CONFIG_ARCH_SUN8IW7P1
+#define DRV_VERSION "1.04"
+#elif defined CONFIG_ARCH_SUN8IW9P1
+#define DRV_VERSION "1.05"
+#elif defined CONFIG_ARCH_SUN50IW1P1
+#define DRV_VERSION "1.10"
+#elif defined CONFIG_ARCH_SUN9IW1P1
+#define DRV_VERSION "2.00"
+#else
+#error "please select a platform\n"
+#endif
+
+extern unsigned int arisc_debug_dram_crc_en;
+extern unsigned int arisc_debug_dram_crc_srcaddr;
+extern unsigned int arisc_debug_dram_crc_len;
+extern unsigned int arisc_debug_dram_crc_error;
+extern unsigned int arisc_debug_dram_crc_total_count;
+extern unsigned int arisc_debug_dram_crc_error_count;
+extern volatile const unsigned int arisc_debug_level;
+extern struct standby_info_para arisc_powchk_back;
+
+//local functions
+extern int arisc_config_dram_paras(void);
+extern int arisc_sysconfig_ir_paras(void);
+extern int arisc_config_pmu_paras(void);
+extern int arisc_suspend_flag_query(void);
+#if (defined CONFIG_ARCH_SUN8IW7P1)
+extern void arisc_power_off(void);
+#endif
+#endif //__ARISC_I_H__
diff --git a/plat/sun50iw1p1/scp/hwmsgbox/hwmsgbox.c b/plat/sun50iw1p1/scp/hwmsgbox/hwmsgbox.c
new file mode 100644
index 0000000..f1bc032
--- /dev/null
+++ b/plat/sun50iw1p1/scp/hwmsgbox/hwmsgbox.c
@@ -0,0 +1,291 @@
+/*
+ * arch/arm/mach-sunxi/arisc/hwmsgbox/hwmsgbox.c
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "hwmsgbox_i.h"
+
+/* spinlock for syn and asyn channel */
+static spinlock_t syn_channel_lock;
+static spinlock_t asyn_channel_lock;
+static uintptr_t base;
+
+/**
+ * initialize hwmsgbox.
+ * @para: none.
+ *
+ * returns: 0 if initialize hwmsgbox succeeded, others if failed.
+ */
+int arisc_hwmsgbox_init(void)
+{
+ base = dts_cfg.msgbox.base;
+
+ /* initialize syn and asyn spinlock */
+ //writel(0xffffffff, base + AW_MSGBOX_IRQ_STATUS_REG(AW_HWMSG_QUEUE_USER_AC327));
+ //writel(0x0, base + AW_MSGBOX_IRQ_EN_REG(AW_HWMSG_QUEUE_USER_AC327));
+
+ return 0;
+}
+
+/**
+ * exit hwmsgbox.
+ * @para: none.
+ *
+ * returns: 0 if exit hwmsgbox succeeded, others if failed.
+ */
+int arisc_hwmsgbox_exit(void)
+{
+ return 0;
+}
+
+/**
+ * send one message to another processor by hwmsgbox.
+ * @pmessage: the pointer of sended message frame.
+ * @timeout: the wait time limit when message fifo is full, it is valid only when parameter mode = HWMSG_SEND_WAIT_TIMEOUT.
+ *
+ * returns: 0 if send message succeeded, other if failed.
+ */
+int arisc_hwmsgbox_send_message(struct arisc_message *pmessage, unsigned int timeout)
+{
+ volatile uint32_t value;
+
+ if (pmessage == NULL) {
+ return -EINVAL;
+ }
+ if (pmessage->attr & ARISC_MESSAGE_ATTR_HARDSYN) {
+ /* use ac327 hwsyn transmit channel */
+ spin_lock(&syn_channel_lock);
+ while (readl(base + AW_MSGBOX_FIFO_STATUS_REG(ARISC_HWMSGBOX_AC327_SYN_TX_CH)) == 1);
+
+ value = arisc_message_map_to_cpus(pmessage);
+ ARISC_INF("ac327 send hard syn message : %x\n", (unsigned int)value);
+ writel(value, base + AW_MSGBOX_MSG_REG(ARISC_HWMSGBOX_AC327_SYN_TX_CH));
+
+ /* hwsyn messsage must feedback use syn rx channel */
+ while (readl(base + AW_MSGBOX_MSG_STATUS_REG(ARISC_HWMSGBOX_AC327_SYN_RX_CH)) == 0);
+
+ /* check message valid */
+ if (value != (readl(base + AW_MSGBOX_MSG_REG(ARISC_HWMSGBOX_AC327_SYN_RX_CH)))) {
+ ARISC_ERR("hard syn message error [%x, %x]\n", (uint32_t)value, (uint32_t)(readl(base + AW_MSGBOX_MSG_REG(ARISC_HWMSGBOX_AC327_SYN_RX_CH))));
+ spin_unlock(&syn_channel_lock);
+ return -EINVAL;
+ }
+ ARISC_INF("ac327 hard syn message [%x, %x] feedback\n", (unsigned int)value, (unsigned int)pmessage->type);
+ /* if error call the callback function. by superm */
+ if(pmessage->result != 0) {
+ ARISC_ERR("message process error\n");
+ ARISC_ERR("message addr : %llx\n", pmessage);
+ ARISC_ERR("message state : %x\n", pmessage->state);
+ ARISC_ERR("message attr : %x\n", pmessage->attr);
+ ARISC_ERR("message type : %x\n", pmessage->type);
+ ARISC_ERR("message result : %x\n", pmessage->result);
+ if (pmessage->cb.handler == NULL) {
+ ARISC_WRN("callback not install\n");
+ } else {
+ /* call callback function */
+ ARISC_WRN("call the callback function\n");
+ (*(pmessage->cb.handler))(pmessage->cb.arg);
+ }
+ }
+ spin_unlock(&syn_channel_lock);
+ return 0;
+ }
+
+ /* use ac327 asyn transmit channel */
+ spin_lock(&asyn_channel_lock);
+ while (readl(base + AW_MSGBOX_FIFO_STATUS_REG(ARISC_HWMSGBOX_ARISC_ASYN_RX_CH)) == 1);
+
+ /* write message to message-queue fifo */
+ value = arisc_message_map_to_cpus(pmessage);
+ ARISC_INF("ac327 send message : %x\n", (unsigned int)value);
+ writel(value, base + AW_MSGBOX_MSG_REG(ARISC_HWMSGBOX_ARISC_ASYN_RX_CH));
+ spin_unlock(&asyn_channel_lock);
+
+ return 0;
+}
+
+int arisc_hwmsgbox_feedback_message(struct arisc_message *pmessage, unsigned int timeout)
+{
+ volatile unsigned long value;
+
+ if (pmessage->attr & ARISC_MESSAGE_ATTR_HARDSYN) {
+ /* use ac327 hard syn receiver channel */
+ spin_lock(&syn_channel_lock);
+ while (readl(base + AW_MSGBOX_FIFO_STATUS_REG(ARISC_HWMSGBOX_ARISC_SYN_RX_CH)) == 1);
+
+ value = arisc_message_map_to_cpus(pmessage);
+ ARISC_INF("arisc feedback hard syn message : %x\n", (unsigned int)value);
+ writel(value, base + AW_MSGBOX_MSG_REG(ARISC_HWMSGBOX_ARISC_SYN_RX_CH));
+ spin_unlock(&syn_channel_lock);
+
+ return 0;
+ }
+
+ /* invalid syn message */
+ return -EINVAL;
+}
+
+/**
+ * enbale the receiver interrupt of message-queue.
+ * @queue: the number of message-queue which we want to enable interrupt.
+ * @user: the user which we want to enable interrupt.
+ *
+ * returns: 0 if enable interrupt succeeded, others if failed.
+ */
+int arisc_hwmsgbox_enable_receiver_int(int queue, int user)
+{
+ volatile unsigned int value;
+
+ value = readl(base + AW_MSGBOX_IRQ_EN_REG(user));
+ value &= ~(0x1 << (queue * 2));
+ value |= (0x1 << (queue * 2));
+ writel(value, base + AW_MSGBOX_IRQ_EN_REG(user));
+
+ return 0;
+}
+
+/**
+ * disbale the receiver interrupt of message-queue.
+ * @queue: the number of message-queue which we want to enable interrupt.
+ * @user: the user which we want to enable interrupt.
+ *
+ * returns: 0 if disable interrupt succeeded, others if failed.
+ */
+int arisc_hwmsgbox_disable_receiver_int(int queue, int user)
+{
+ volatile unsigned int value;
+
+ value = readl(base + AW_MSGBOX_IRQ_EN_REG(user));
+ value &= ~(0x1 << (queue * 2));
+ writel(value, base + AW_MSGBOX_IRQ_EN_REG(user));
+
+ return 0;
+}
+
+/**
+ * query the receiver interrupt pending of message-queue.
+ * @queue: the number of message-queue which we want to query.
+ * @user: the user which we want to query.
+ *
+ * returns: 0 if query pending succeeded, others if failed.
+ */
+int arisc_hwmsgbox_query_receiver_pending(int queue, int user)
+{
+ volatile unsigned long value;
+
+ value = readl(base + (AW_MSGBOX_IRQ_STATUS_REG(user)));
+
+ return value & (0x1 << (queue * 2));
+}
+
+/**
+ * clear the receiver interrupt pending of message-queue.
+ * @queue: the number of message-queue which we want to clear.
+ * @user: the user which we want to clear.
+ *
+ * returns: 0 if clear pending succeeded, others if failed.
+ */
+int arisc_hwmsgbox_clear_receiver_pending(int queue, int user)
+{
+ writel((0x1 << (queue * 2)), base + AW_MSGBOX_IRQ_STATUS_REG(user));
+
+ return 0;
+}
+
+/**
+ * query message of hwmsgbox by hand, mainly for.
+ * @para: none.
+ *
+ * returns: the point of message, NULL if timeout.
+ */
+struct arisc_message *arisc_hwmsgbox_query_message(void)
+{
+ struct arisc_message *pmessage = NULL;
+
+ /* query ac327 asyn received channel */
+ if (readl(base + AW_MSGBOX_MSG_STATUS_REG(ARISC_HWMSGBOX_ARISC_ASYN_TX_CH))) {
+ volatile unsigned long value;
+ value = readl(base + AW_MSGBOX_MSG_REG(ARISC_HWMSGBOX_ARISC_ASYN_TX_CH));
+ pmessage = arisc_message_map_to_cpux(value);
+
+ if (arisc_message_valid(pmessage)) {
+ /* message state switch */
+ if (pmessage->state == ARISC_MESSAGE_PROCESSED) {
+ /* ARISC_MESSAGE_PROCESSED->ARISC_MESSAGE_FEEDBACKED */
+ pmessage->state = ARISC_MESSAGE_FEEDBACKED;
+ } else {
+ /* ARISC_MESSAGE_INITIALIZED->ARISC_MESSAGE_RECEIVED */
+ pmessage->state = ARISC_MESSAGE_RECEIVED;
+ }
+ } else {
+ ARISC_ERR("invalid asyn message received: pmessage = 0x%llx. \n", pmessage);
+ return NULL;
+ }
+ /* clear pending */
+ arisc_hwmsgbox_clear_receiver_pending(ARISC_HWMSGBOX_ARISC_ASYN_TX_CH, AW_HWMSG_QUEUE_USER_AC327);
+ return pmessage;
+ }
+ /* query ac327 syn received channel */
+ if (readl(base + AW_MSGBOX_MSG_STATUS_REG(ARISC_HWMSGBOX_ARISC_SYN_TX_CH))) {
+ volatile unsigned long value;
+ value = readl(base + AW_MSGBOX_MSG_REG(ARISC_HWMSGBOX_ARISC_SYN_TX_CH));
+ pmessage = arisc_message_map_to_cpux(value);
+ if (arisc_message_valid(pmessage)) {
+ /* message state switch */
+ if (pmessage->state == ARISC_MESSAGE_PROCESSED) {
+ /* ARISC_MESSAGE_PROCESSED->ARISC_MESSAGE_FEEDBACKED */
+ pmessage->state = ARISC_MESSAGE_FEEDBACKED;
+ } else {
+ /* ARISC_MESSAGE_INITIALIZED->ARISC_MESSAGE_RECEIVED */
+ pmessage->state = ARISC_MESSAGE_RECEIVED;
+ }
+ } else {
+ ARISC_ERR("invalid syn message received: pmessage = 0x%llx. \n", pmessage);
+ arisc_hwmsgbox_clear_receiver_pending(ARISC_HWMSGBOX_ARISC_SYN_TX_CH, AW_HWMSG_QUEUE_USER_AC327);
+ return NULL;
+ }
+ arisc_hwmsgbox_clear_receiver_pending(ARISC_HWMSGBOX_ARISC_SYN_TX_CH, AW_HWMSG_QUEUE_USER_AC327);
+ return pmessage;
+ }
+
+ /* no valid message now */
+ return NULL;
+}
+
+int arisc_hwmsgbox_standby_suspend(void)
+{
+ /* enable arisc asyn tx interrupt */
+ //arisc_hwmsgbox_disable_receiver_int(ARISC_HWMSGBOX_ARISC_ASYN_TX_CH, AW_HWMSG_QUEUE_USER_AC327);
+
+ /* enable arisc syn tx interrupt */
+ //arisc_hwmsgbox_disable_receiver_int(ARISC_HWMSGBOX_ARISC_SYN_TX_CH, AW_HWMSG_QUEUE_USER_AC327);
+
+ return 0;
+}
+
+int arisc_hwmsgbox_standby_resume(void)
+{
+ /* enable arisc asyn tx interrupt */
+ //arisc_hwmsgbox_enable_receiver_int(ARISC_HWMSGBOX_ARISC_ASYN_TX_CH, AW_HWMSG_QUEUE_USER_AC327);
+
+ /* enable arisc syn tx interrupt */
+ //arisc_hwmsgbox_enable_receiver_int(ARISC_HWMSGBOX_ARISC_SYN_TX_CH, AW_HWMSG_QUEUE_USER_AC327);
+
+ return 0;
+}
diff --git a/plat/sun50iw1p1/scp/hwmsgbox/hwmsgbox.mk b/plat/sun50iw1p1/scp/hwmsgbox/hwmsgbox.mk
new file mode 100644
index 0000000..aebb5ec
--- /dev/null
+++ b/plat/sun50iw1p1/scp/hwmsgbox/hwmsgbox.mk
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+
+BL31_SOURCES += plat/sun50iw1p1/scp/hwmsgbox/hwmsgbox.c
diff --git a/plat/sun50iw1p1/scp/hwmsgbox/hwmsgbox_i.h b/plat/sun50iw1p1/scp/hwmsgbox/hwmsgbox_i.h
new file mode 100644
index 0000000..ffee2a9
--- /dev/null
+++ b/plat/sun50iw1p1/scp/hwmsgbox/hwmsgbox_i.h
@@ -0,0 +1,46 @@
+/*
+ * arch/arm/mach-sunxi/arisc/hwmsgbox/hwmsgbox_i.h
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ARISC_HWMSGBOX_I_H
+#define __ARISC_HWMSGBOX_I_H
+
+#include "../include/arisc_includes.h"
+
+//hardware message-box register list
+#define AW_MSGBOX_CTRL_REG(m) (0x0000 + (0x4 * (m>>2)))
+#define AW_MSGBOX_IRQ_EN_REG(u) (0x0040 + (0x20* u))
+#define AW_MSGBOX_IRQ_STATUS_REG(u) (0x0050 + (0x20* u))
+#define AW_MSGBOX_FIFO_STATUS_REG(m) (0x0100 + (0x4 * m))
+#define AW_MSGBOX_MSG_STATUS_REG(m) (0x0140 + (0x4 * m))
+#define AW_MSGBOX_MSG_REG(m) (0x0180 + (0x4 * m))
+#define AW_MSGBOX_DEBUG_REG (0x01c0)
+
+/* local functions */
+int arisc_hwmsgbox_clear_receiver_pending(int queue, int user);
+int arisc_hwmsgbox_query_receiver_pending(int queue, int user);
+int arisc_hwmsgbox_enable_receiver_int(int queue, int user);
+int arisc_hwmsgbox_set_receiver(int queue, int user);
+int arisc_hwmsgbox_set_transmitter(int queue, int user);
+int arisc_hwmsgbox_wait_message_feedback(struct arisc_message *pmessage);
+int arisc_hwmsgbox_message_feedback(struct arisc_message *pmessage);
+int arisc_message_valid(struct arisc_message *pmessage);
+
+#endif /* __ARISC_HWMSGBOX_I_H */
diff --git a/plat/sun50iw1p1/scp/hwspinlock/hwspinlock.c b/plat/sun50iw1p1/scp/hwspinlock/hwspinlock.c
new file mode 100644
index 0000000..863d457
--- /dev/null
+++ b/plat/sun50iw1p1/scp/hwspinlock/hwspinlock.c
@@ -0,0 +1,109 @@
+/*
+ * arch/arm/mach-sunxi/arisc/hwspinlock/hwspinlock.c
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "hwspinlock_i.h"
+
+static struct arisc_hwspinlock arisc_hwspinlocks[ARISC_HW_SPINLOCK_NUM];
+static uintptr_t base;
+
+/**
+ * initialize hwspinlock.
+ * @para: none.
+ *
+ * returns: 0 if initialize hwspinlock succeeded, others if failed.
+ */
+int arisc_hwspinlock_init(void)
+{
+ base = dts_cfg.hwspinlock.base;
+
+ return 0;
+}
+
+/**
+ * exit hwspinlock.
+ * @para:none.
+ *
+ * returns: 0 if exit hwspinlock succeeded, others if failed.
+ */
+int arisc_hwspinlock_exit(void)
+{
+ return 0;
+}
+
+/**
+ * lock an hwspinlock with timeout limit,
+ * and hwspinlock will be unlocked in arisc_hwspin_unlock().
+ * @hwid: an hwspinlock id which we want to lock.
+ *
+ * returns: 0 if lock hwspinlock succeeded, other if failed.
+ */
+int arisc_hwspin_lock(int hwid)
+{
+ arisc_hwspinlock_t *spinlock;
+
+ if (hwid >= ARISC_HW_SPINLOCK_NUM) {
+ ARISC_ERR("invalid hwspinlock id [%d] for trylock\n", hwid);
+ return -EINVAL;
+ }
+ spinlock = &(arisc_hwspinlocks[hwid]);
+
+ /* is lock already taken by another context on the local cpu ? */
+ spin_lock(&(spinlock->lock));
+
+ /* try to take spinlock */
+ while (readl(base + AW_SPINLOCK_LOCK_REG(hwid)) == AW_SPINLOCK_TAKEN);
+
+ return 0;
+}
+
+/**
+ * unlock a specific hwspinlock.
+ * hwid: an hwspinlock id which we want to unlock.
+ *
+ * returns: 0 if unlock hwspinlock succeeded, other if failed.
+ */
+int arisc_hwspin_unlock(int hwid)
+{
+ arisc_hwspinlock_t *spinlock;
+
+ if (hwid >= ARISC_HW_SPINLOCK_NUM) {
+ ARISC_ERR("invalid hwspinlock id [%d] for unlock\n", hwid);
+ return -EINVAL;
+ }
+ spinlock = &(arisc_hwspinlocks[hwid]);
+
+ /* untaken the spinlock */
+ writel(0x0, base + AW_SPINLOCK_LOCK_REG(hwid));
+
+ spin_unlock(&(spinlock->lock));
+
+ return 0;
+}
+
+int arisc_hwspinlock_standby_suspend(void)
+{
+ return 0;
+}
+
+int arisc_hwspinlock_standby_resume(void)
+{
+ return 0;
+}
diff --git a/plat/sun50iw1p1/scp/hwspinlock/hwspinlock.mk b/plat/sun50iw1p1/scp/hwspinlock/hwspinlock.mk
new file mode 100644
index 0000000..2c5ee59
--- /dev/null
+++ b/plat/sun50iw1p1/scp/hwspinlock/hwspinlock.mk
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+
+BL31_SOURCES += plat/sun50iw1p1/scp/hwspinlock/hwspinlock.c
diff --git a/plat/sun50iw1p1/scp/hwspinlock/hwspinlock_i.h b/plat/sun50iw1p1/scp/hwspinlock/hwspinlock_i.h
new file mode 100644
index 0000000..231d7ee
--- /dev/null
+++ b/plat/sun50iw1p1/scp/hwspinlock/hwspinlock_i.h
@@ -0,0 +1,48 @@
+/*
+ * arch/arm/mach-sunxi/arisc/hwspinlock/hwspinlock-i.h
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __HW_SPINLOCK_I_H
+#define __HW_SPINLOCK_I_H
+
+#include "../include/arisc_includes.h"
+
+/* the used state of spinlock */
+#define SPINLOCK_FREE (0)
+#define SPINLOCK_USED (1)
+
+//the taken ot not state of spinlock
+#define AW_SPINLOCK_NOTTAKEN (0)
+#define AW_SPINLOCK_TAKEN (1)
+
+//hardware spinlock register list
+#define AW_SPINLOCK_SYS_STATUS_REG (0x0000)
+#define AW_SPINLOCK_STATUS_REG (0x0010)
+#define AW_SPINLOCK_IRQ_EN_REG (0x0020)
+#define AW_SPINLOCK_IRQ_PEND_REG (0x0040)
+#define AW_SPINLOCK_LOCK_REG(id) (0x0100 + id * 4)
+
+typedef struct arisc_hwspinlock
+{
+ unsigned long flags;
+ spinlock_t lock;
+} arisc_hwspinlock_t;
+
+#endif /* __HW_SPINLOCK_I_H */
diff --git a/plat/sun50iw1p1/scp/include/arisc_cfgs.h b/plat/sun50iw1p1/scp/include/arisc_cfgs.h
new file mode 100644
index 0000000..32234ba
--- /dev/null
+++ b/plat/sun50iw1p1/scp/include/arisc_cfgs.h
@@ -0,0 +1,74 @@
+/*
+ * arch/arm/mach-sunxi/arisc/include/arisc_cfgs.h
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ARISC_CFGS_H
+#define __ARISC_CFGS_H
+
+/* arisc software version number */
+#if defined CONFIG_ARCH_SUN8IW1P1
+#define ARISC_VERSIONS (100)
+#elif defined CONFIG_ARCH_SUN8IW3P1
+#define ARISC_VERSIONS (101)
+#elif defined CONFIG_ARCH_SUN8IW5P1
+#define ARISC_VERSIONS (102)
+#elif defined CONFIG_ARCH_SUN8IW6P1
+#define ARISC_VERSIONS (103)
+#elif defined CONFIG_ARCH_SUN8IW7P1
+#define ARISC_VERSIONS (104)
+#elif defined CONFIG_ARCH_SUN8IW9P1
+#define ARISC_VERSIONS (105)
+#elif defined CONFIG_ARCH_SUN50IW1P1
+#define ARISC_VERSIONS (110)
+#elif defined CONFIG_ARCH_SUN9IW1P1
+#define ARISC_VERSIONS (200)
+#else
+#error "please select a platform\n"
+#endif
+
+/* debugger system */
+#define ARISC_DEBUG_ON
+#define ARISC_DEBUG_LEVEL (3) /* debug level */
+
+/* the max number of cached message frame */
+#define ARISC_MESSAGE_CACHED_MAX (4)
+
+/* spinlock max timeout, base on ms */
+#define ARISC_SPINLOCK_TIMEOUT (100)
+
+/* send message max timeout, base on ms */
+#define ARISC_SEND_MSG_TIMEOUT (4000)
+
+/* hwmsgbox channels configure */
+#define ARISC_HWMSGBOX_ARISC_ASYN_TX_CH (0)
+#define ARISC_HWMSGBOX_ARISC_ASYN_RX_CH (1)
+#define ARISC_HWMSGBOX_ARISC_SYN_TX_CH (2)
+#define ARISC_HWMSGBOX_ARISC_SYN_RX_CH (3)
+#define ARISC_HWMSGBOX_AC327_SYN_TX_CH (4)
+#define ARISC_HWMSGBOX_AC327_SYN_RX_CH (5)
+
+/* dvfs config */
+#define ARISC_DVFS_VF_TABLE_MAX (16)
+/* ir config */
+#define ARISC_IR_KEY_SUP_NUM (8) /* the number of IR remote support */
+
+#define ARISC_DEV_CLKSRC_NUM (4) /* the number of dev clocksource support */
+
+#endif /* __ARISC_CFGS_H */
diff --git a/plat/sun50iw1p1/scp/include/arisc_dbgs.h b/plat/sun50iw1p1/scp/include/arisc_dbgs.h
new file mode 100644
index 0000000..aef8f5e
--- /dev/null
+++ b/plat/sun50iw1p1/scp/include/arisc_dbgs.h
@@ -0,0 +1,66 @@
+/*
+ * arch/arm/mach-sunxi/arisc/include/arisc_dbgs.h
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ARISC_DBGS_H
+#define __ARISC_DBGS_H
+
+/*
+ * debug level define,
+ * level 0 : dump debug information--none;
+ * level 1 : dump debug information--error;
+ * level 2 : dump debug information--error+warning;
+ * level 3 : dump debug information--error+warning+information;
+ * extern void printk(const char *, ...);
+ */
+#ifdef ARISC_DEBUG_ON
+/* debug levels */
+#define DEBUG_LEVEL_INF ((uint32_t)1 << 0)
+#define DEBUG_LEVEL_LOG ((uint32_t)1 << 1)
+#define DEBUG_LEVEL_WRN ((uint32_t)1 << 2)
+#define DEBUG_LEVEL_ERR ((uint32_t)1 << 3)
+
+#define ARISC_INF(format, args...) \
+ if(DEBUG_LEVEL_INF & (0xf0 >> (arisc_debug_level +1))) \
+ tf_printf("[SCP] :"format, ##args);
+
+#define ARISC_LOG(format, args...) \
+ if(DEBUG_LEVEL_LOG & (0xf0 >> (arisc_debug_level +1))) \
+ tf_printf("[SCP] :"format, ##args);
+
+#define ARISC_WRN(format, args...) \
+ if(DEBUG_LEVEL_WRN & (0xf0 >> (arisc_debug_level +1))) \
+ tf_printf("[SCP WARING] :"format, ##args);
+
+#define ARISC_ERR(format, args...) \
+ if(DEBUG_LEVEL_ERR & (0xf0 >> (arisc_debug_level +1))) \
+ tf_printf("[SCP ERROR] :"format, ##args);
+
+#else /* ARISC_DEBUG_ON */
+#define ARISC_INF(...)
+#define ARISC_WRN(...)
+#define ARISC_ERR(...)
+#define ARISC_LOG(...)
+#endif /* ARISC_DEBUG_ON */
+
+/* report error information id */
+#define ERR_NMI_INT_TIMEOUT (0x1)
+
+#endif /* __ARISC_DBGS_H */
diff --git a/plat/sun50iw1p1/scp/include/arisc_hwmsgbox.h b/plat/sun50iw1p1/scp/include/arisc_hwmsgbox.h
new file mode 100644
index 0000000..4bab7bc
--- /dev/null
+++ b/plat/sun50iw1p1/scp/include/arisc_hwmsgbox.h
@@ -0,0 +1,77 @@
+/*
+ * arch/arm/mach-sunxi/arisc/include/arisc_hwmsgbox.h
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ARISC_HWMSGBOX_H
+#define __ARISC_HWMSGBOX_H
+
+//the number of hardware message queue.
+#define AW_HWMSG_QUEUE_NUMBER (8)
+
+//the user of hardware message queue.
+typedef enum aw_hwmsg_queue_user
+{
+ AW_HWMSG_QUEUE_USER_ARISC, //arisc
+ AW_HWMSG_QUEUE_USER_AC327, //cpu0
+} aw_hwmsg_queue_user_e;
+
+/**
+ * initialize hwmsgbox.
+ * @para: none.
+ *
+ * returns: OK if initialize hwmsgbox succeeded, others if failed.
+ */
+int arisc_hwmsgbox_init(void);
+
+/**
+ * exit hwmsgbox.
+ * @para: none.
+ *
+ * returns: OK if exit hwmsgbox succeeded, others if failed.
+ */
+int arisc_hwmsgbox_exit(void);
+
+/**
+ * send one message to another processor by hwmsgbox.
+ * @pmessage: the pointer of sended message frame.
+ * @timeout: the wait time limit when message fifo is full,
+ * it is valid only when parameter mode = SEND_MESSAGE_WAIT_TIMEOUT.
+ *
+ * returns: OK if send message succeeded, other if failed.
+ */
+int arisc_hwmsgbox_send_message(struct arisc_message *pmessage, unsigned int timeout);
+
+/**
+ * Description: query message of hwmsgbox by hand, mainly for.
+ * @para: none.
+ *
+ * returns: the point of message, NULL if timeout.
+ */
+struct arisc_message *arisc_hwmsgbox_query_message(void);
+
+int arisc_hwmsgbox_enable_receiver_int(int queue, int user);
+int arisc_hwmsgbox_disable_receiver_int(int queue, int user);
+
+int arisc_hwmsgbox_feedback_message(struct arisc_message *pmessage, unsigned int timeout);
+
+int arisc_hwmsgbox_standby_resume(void);
+int arisc_hwmsgbox_standby_suspend(void);
+
+#endif /* __ARISC_HWMSGBOX_H */
diff --git a/plat/sun50iw1p1/scp/include/arisc_hwspinlock.h b/plat/sun50iw1p1/scp/include/arisc_hwspinlock.h
new file mode 100644
index 0000000..2b34276
--- /dev/null
+++ b/plat/sun50iw1p1/scp/include/arisc_hwspinlock.h
@@ -0,0 +1,63 @@
+/*
+ * arch/arm/mach-sunxi/arisc/include/arisc_hwspinlock.h
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ARISC_HW_SPINLOCK_H
+#define __ARISC_HW_SPINLOCK_H
+
+/* the max number of hardware spinlock */
+#define ARISC_HW_SPINLOCK_NUM (32)
+
+/**
+ * initialize hwspinlock.
+ * @para: none.
+ *
+ * returns: OK if initialize hwspinlock succeeded, others if failed.
+ */
+int arisc_hwspinlock_init(void);
+
+/**
+ * exit hwspinlock.
+ * @para: none.
+ *
+ * returns: OK if exit hwspinlock succeeded, others if failed.
+ */
+int arisc_hwspinlock_exit(void);
+
+/**
+ * lock an hwspinlock with timeout limit.
+ * @hwid : an hwspinlock id which we want to lock.
+ *
+ * returns: OK if lock hwspinlock succeeded, other if failed.
+ */
+int arisc_hwspin_lock(int hwid);
+
+/**
+ * unlock a specific hwspinlock.
+ * @hwid : an hwspinlock id which we want to unlock.
+ *
+ * returns: OK if unlock hwspinlock succeeded, other if failed.
+ */
+int arisc_hwspin_unlock(int hwid);
+
+int arisc_hwspinlock_standby_suspend(void);
+int arisc_hwspinlock_standby_resume(void);
+
+#endif /* __ARISC_HW_SPINLOCK_H */
diff --git a/plat/sun50iw1p1/scp/include/arisc_includes.h b/plat/sun50iw1p1/scp/include/arisc_includes.h
new file mode 100644
index 0000000..571c90c
--- /dev/null
+++ b/plat/sun50iw1p1/scp/include/arisc_includes.h
@@ -0,0 +1,92 @@
+/*
+ * arch/arm/mach-sunxi/arisc/include/arisc_includes.h
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ARISC_INCLUDES_H
+#define __ARISC_INCLUDES_H
+
+//#include <linux/kernel.h>
+//#include <linux/module.h>
+//#include <linux/string.h>
+//#include <linux/spinlock.h>
+//#include <linux/err.h>
+//#include <linux/io.h>
+//#include <linux/slab.h>
+//#include <linux/semaphore.h>
+//#include <linux/interrupt.h>
+//#include <linux/jiffies.h>
+//#include <linux/delay.h>
+//#include <linux/arisc/hwmsgbox.h>
+//#include <linux/arisc/hwspinlock.h>
+#define CONFIG_ARCH_SUN50IW1P1
+
+#include <arch_helpers.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <bakery_lock.h>
+#include <mmio.h>
+#include <debug.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <psci.h>
+#include <bakery_lock.h>
+#include <spinlock.h>
+#include <arisc.h>
+
+#include "../../sunxi_private.h"
+#include "../../sunxi_cpu_ops.h"
+#include "../../sunxi_def.h"
+#include "../../mhu.h"
+#include "../../scpi.h"
+#include "../../sun50iw1p1.h"
+
+/* configure and debugger */
+#include "../arisc_i.h"
+#include "./arisc_cfgs.h"
+#include "./arisc_dbgs.h"
+#include "./arisc_para.h"
+
+/* messages define */
+#include "./arisc_messages.h"
+#include "./arisc_message_manager.h"
+
+/* driver headers */
+#include "./arisc_hwmsgbox.h"
+#include "./arisc_hwspinlock.h"
+
+#define readl(x) mmio_read_32((x))
+#define writel(v, a) mmio_write_32((a), (v))
+
+/* global functions */
+extern int arisc_axp_int_notify(struct arisc_message *pmessage);
+extern int arisc_audio_perdone_notify(struct arisc_message *pmessage);
+extern int arisc_dvfs_cfg_vf_table(void);
+extern int arisc_query_set_standby_info(struct standby_info_para *para, arisc_rw_type_e op);
+extern int arisc_sysconfig_sstpower_paras(void);
+extern int arisc_report_error_info(struct arisc_message *pmessage);
+
+/* global vars */
+extern unsigned long arisc_sram_a2_base;
+extern struct dts_cfg dts_cfg;
+
+#endif /* __ARISC_INCLUDES_H */
diff --git a/plat/sun50iw1p1/scp/include/arisc_message_manager.h b/plat/sun50iw1p1/scp/include/arisc_message_manager.h
new file mode 100644
index 0000000..5b80596
--- /dev/null
+++ b/plat/sun50iw1p1/scp/include/arisc_message_manager.h
@@ -0,0 +1,73 @@
+/*
+ * arch/arm/mach-sunxi/arisc/include/arisc_message_manager.h
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ARISC_MESSAGE_MANAGER_H
+#define __ARISC_MESSAGE_MANAGER_H
+
+/**
+ * initialize message manager.
+ * @para: none.
+ *
+ * returns: OK if initialize succeeded, others if failed.
+ */
+int arisc_message_manager_init(void *addr, uint32_t size);
+
+/**
+ * exit message manager.
+ * para: none.
+ *
+ * returns: OK if exit succeeded, others if failed.
+ */
+int arisc_message_manager_exit(void);
+
+/**
+ * allocate one message frame. mainly use for send message by message-box,
+ * the message frame allocate form messages pool shared memory area.
+ * @para: none.
+ *
+ * returns: the pointer of allocated message frame, NULL if failed;
+ */
+struct arisc_message *arisc_message_allocate(unsigned int msg_attr);
+
+/**
+ * free one message frame. mainly use for process message finished,
+ * free it to messages pool or add to free message queue.
+ * @pmessage: the pointer of free message frame.
+ *
+ * returns: none.
+ */
+void arisc_message_free(struct arisc_message *pmessage);
+
+/**
+ * notify system that one message coming.
+ * @pmessage : the pointer of coming message frame.
+ *
+ * returns: OK if notify succeeded, other if failed.
+ */
+int arisc_message_coming_notify(struct arisc_message *pmessage);
+
+int arisc_semaphore_used_num_query(void);
+
+struct arisc_message *arisc_message_map_to_cpux(uint32_t addr);
+uint32_t arisc_message_map_to_cpus(struct arisc_message *message);
+int arisc_message_valid(struct arisc_message *pmessage);
+
+#endif /* __MESSAGE_MANAGER_H */
diff --git a/plat/sun50iw1p1/scp/include/arisc_messages.h b/plat/sun50iw1p1/scp/include/arisc_messages.h
new file mode 100644
index 0000000..98c47b1
--- /dev/null
+++ b/plat/sun50iw1p1/scp/include/arisc_messages.h
@@ -0,0 +1,81 @@
+/*
+ * arch/arm/mach-sunxi/arisc/include/arisc_messages.h
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef __ARISC_MESSAGES_H__
+#define __ARISC_MESSAGES_H__
+
+#include <arisc.h>
+
+/* message states */
+#define ARISC_MESSAGE_FREED (0x0) /* freed state */
+#define ARISC_MESSAGE_ALLOCATED (0x1) /* allocated state */
+#define ARISC_MESSAGE_INITIALIZED (0x2) /* initialized state */
+#define ARISC_MESSAGE_RECEIVED (0x3) /* received state */
+#define ARISC_MESSAGE_PROCESSING (0x4) /* processing state */
+#define ARISC_MESSAGE_PROCESSED (0x5) /* processed state */
+#define ARISC_MESSAGE_FEEDBACKED (0x6) /* feedback state */
+
+/* call back struct */
+typedef struct arisc_msg_cb
+{
+ arisc_cb_t handler;
+ void *arg;
+} arisc_msg_cb_t;
+
+#ifdef CONFIG_ARCH_SUN50IW1P1
+/*
+ * the structure of message frame,
+ * this structure will transfer between arisc and ac327.
+ * sizeof(struct message) : 128Byte.
+ */
+typedef struct arisc_message
+{
+ volatile unsigned char state; /* identify the used status of message frame */
+ volatile unsigned char attr; /* message attribute : SYN OR ASYN */
+ volatile unsigned char type; /* message type : DVFS_REQ */
+ volatile unsigned char result; /* message process result */
+ volatile unsigned char reserved[4]; /* reserved for 8byte align */
+ volatile struct arisc_message *next; /* pointer of next message frame */
+ volatile struct arisc_msg_cb cb; /* the callback function and arg of message */
+ volatile void *private; /* message private data */
+ volatile unsigned int paras[22]; /* the parameters of message */
+} arisc_message_t;
+#else
+/*
+ * the structure of message frame,
+ * this structure will transfer between arisc and ac327.
+ * sizeof(struct message) : 64Byte.
+ */
+typedef struct arisc_message
+{
+ volatile unsigned char state; /* identify the used status of message frame */
+ volatile unsigned char attr; /* message attribute : SYN OR ASYN */
+ volatile unsigned char type; /* message type : DVFS_REQ */
+ volatile unsigned char result; /* message process result */
+ volatile struct arisc_message *next; /* pointer of next message frame */
+ volatile struct arisc_msg_cb cb; /* the callback function and arg of message */
+ volatile void *private; /* message private data */
+ volatile unsigned int paras[11]; /* the parameters of message */
+} arisc_message_t;
+#endif
+
+#endif /* __ARISC_MESSAGES_H */
diff --git a/plat/sun50iw1p1/scp/include/arisc_para.h b/plat/sun50iw1p1/scp/include/arisc_para.h
new file mode 100644
index 0000000..1943759
--- /dev/null
+++ b/plat/sun50iw1p1/scp/include/arisc_para.h
@@ -0,0 +1,192 @@
+#ifndef __ARISC_PARA_H__
+#define __ARISC_PARA_H__
+
+#define ARISC_MACHINE_PAD 0
+#define ARISC_MACHINE_HOMLET 1
+
+/* arisc parameter size: 128byte */
+/*
+ * machine: machine id, pad = 0, homlet = 1;
+ * message_pool_phys: message pool physical address;
+ * message_pool_size: message pool size;
+ */
+#define SERVICES_DVFS_USED (1<<0)
+
+/* FIXME: if you modify this struct, you should
+ * sync this change with linux source,
+ * by superm at 2015-05-15.
+ */
+typedef enum power_dm
+{
+ DM_CPUA = 0, /* 0 */
+ DM_CPUB, /* 1 */
+ DM_DRAM, /* 2 */
+ DM_GPU, /* 3 */
+ DM_SYS, /* 4 */
+ DM_VPU, /* 5 */
+ DM_CPUS, /* 6 */
+ DM_DRAMPLL, /* 7 */
+ DM_ADC, /* 8 */
+ DM_PL, /* 9 */
+ DM_PM, /* 10 */
+ DM_IO, /* 11 */
+ DM_CPVDD, /* 12 */
+ DM_LDOIN, /* 13 */
+ DM_PLL, /* 14 */
+ DM_LPDDR, /* 15 */
+ DM_TEST, /* 16 */
+ DM_RES1, /* 17 */
+ DM_RES2, /* 18 */
+ DM_RES3, /* 19 */
+ DM_MAX, /* 20 */
+} power_dm_e;
+
+typedef struct mem_cfg
+{
+ uintptr_t base;
+ size_t size;
+} mem_cfg_t;
+
+typedef struct dev_cfg
+{
+ uintptr_t base;
+ size_t size;
+ uint32_t irq;
+ int status;
+} dev_cfg_t;
+
+typedef struct cir_cfg
+{
+ uintptr_t base;
+ size_t size;
+ uint32_t irq;
+ uint32_t power_key_code;
+ uint32_t addr_code;
+ int status;
+} cir_cfg_t;
+
+typedef struct pmu_cfg
+{
+ uint32_t pmu_bat_shutdown_ltf;
+ uint32_t pmu_bat_shutdown_htf;
+ uint32_t pmu_pwroff_vol;
+ uint32_t power_start;
+} pmu_cfg_t;
+
+typedef struct power_cfg
+{
+ uint32_t powchk_used;
+ uint32_t power_reg;
+ uint32_t system_power;
+} power_cfg_t;
+
+typedef struct image_cfg
+{
+ uintptr_t base;
+ size_t size;
+} image_cfg_t;
+
+typedef struct space_cfg
+{
+ uintptr_t sram_dst;
+ uintptr_t sram_offset;
+ size_t sram_size;
+ uintptr_t dram_dst;
+ uintptr_t dram_offset;
+ size_t dram_size;
+ uintptr_t para_dst;
+ uintptr_t para_offset;
+ size_t para_size;
+ uintptr_t msgpool_dst;
+ uintptr_t msgpool_offset;
+ size_t msgpool_size;
+ uintptr_t standby_dst;
+ uintptr_t standby_offset;
+ size_t standby_size;
+} space_cfg_t;
+
+typedef struct dram_para
+{
+ //normal configuration
+ uint32_t dram_clk;
+ uint32_t dram_type; //dram_type DDR2: 2 DDR3: 3 LPDDR2: 6 DDR3L: 31
+ uint32_t dram_zq;
+ uint32_t dram_odt_en;
+
+ //control configuration
+ uint32_t dram_para1;
+ uint32_t dram_para2;
+
+ //timing configuration
+ uint32_t dram_mr0;
+ uint32_t dram_mr1;
+ uint32_t dram_mr2;
+ uint32_t dram_mr3;
+ uint32_t dram_tpr0;
+ uint32_t dram_tpr1;
+ uint32_t dram_tpr2;
+ uint32_t dram_tpr3;
+ uint32_t dram_tpr4;
+ uint32_t dram_tpr5;
+ uint32_t dram_tpr6;
+
+ //reserved for future use
+ uint32_t dram_tpr7;
+ uint32_t dram_tpr8;
+ uint32_t dram_tpr9;
+ uint32_t dram_tpr10;
+ uint32_t dram_tpr11;
+ uint32_t dram_tpr12;
+ uint32_t dram_tpr13;
+
+}dram_para_t;
+
+typedef struct arisc_freq_voltage
+{
+ uint32_t freq; //cpu frequency
+ uint32_t voltage; //voltage for the frequency
+ uint32_t axi_div; //the divide ratio of axi bus
+} arisc_freq_voltage_t;
+
+typedef struct dts_cfg
+{
+ struct dram_para dram_para;
+ struct arisc_freq_voltage vf[ARISC_DVFS_VF_TABLE_MAX];
+ struct space_cfg space;
+ struct image_cfg image;
+ struct mem_cfg prcm;
+ struct mem_cfg cpuscfg;
+ struct dev_cfg msgbox;
+ struct dev_cfg hwspinlock;
+ struct dev_cfg s_uart;
+ struct dev_cfg s_rsb;
+ struct dev_cfg s_jtag;
+ struct cir_cfg s_cir;
+ struct pmu_cfg pmu;
+ struct power_cfg power;
+} dts_cfg_t;
+
+typedef struct arisc_para
+{
+ uint32_t message_pool_phys;
+ uint32_t message_pool_size;
+ uint32_t standby_base;
+ uint32_t standby_size;
+ uint32_t power_key_code;
+ uint32_t addr_code;
+ uint32_t suart_status;
+ uint32_t pmu_bat_shutdown_ltf;
+ uint32_t pmu_bat_shutdown_htf;
+ uint32_t pmu_pwroff_vol;
+ uint32_t power_start;
+ uint32_t powchk_used;
+ uint32_t power_reg;
+ uint32_t system_power;
+ struct dram_para dram_para;
+ struct arisc_freq_voltage vf[ARISC_DVFS_VF_TABLE_MAX];
+ uint32_t power_regu_tree[DM_MAX];
+} arisc_para_t;
+
+#define ARISC_PARA_SIZE (sizeof(struct arisc_para))
+
+#endif /* __ARISC_PARA_H__ */
diff --git a/plat/sun50iw1p1/scp/interfaces/arisc_axp.c b/plat/sun50iw1p1/scp/interfaces/arisc_axp.c
new file mode 100644
index 0000000..a33cfe2
--- /dev/null
+++ b/plat/sun50iw1p1/scp/interfaces/arisc_axp.c
@@ -0,0 +1,402 @@
+/*
+ * drivers/arisc/interfaces/arisc_axp.c
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "../arisc_i.h"
+
+/* nmi isr node, record current nmi interrupt handler and argument */
+nmi_isr_t nmi_isr_node[2];
+
+/**
+ * register call-back function, call-back function is for arisc notify some event to ac327,
+ * axp/rtc interrupt for external interrupt NMI.
+ * @type: nmi type, pmu/rtc;
+ * @func: call-back function;
+ * @para: parameter for call-back function;
+ *
+ * @return: result, 0 - register call-back function successed;
+ * !0 - register call-back function failed;
+ * NOTE: the function is like "int callback(void *para)";
+ * this function will execute in system ISR.
+ */
+int arisc_nmi_cb_register(uint32_t type, arisc_cb_t func, void *para)
+{
+ if (nmi_isr_node[type].handler) {
+ if(func == nmi_isr_node[type].handler) {
+ ARISC_WRN("nmi interrupt handler register already\n");
+ return 0;
+ }
+ /* just output warning message, overlay handler */
+ ARISC_WRN("nmi interrupt handler register already\n");
+ return -EINVAL;
+ }
+ nmi_isr_node[type].handler = func;
+ nmi_isr_node[type].arg = para;
+
+ return 0;
+}
+
+
+/**
+ * unregister call-back function.
+ * @type: nmi type, pmu/rtc;
+ * @func: call-back function which need be unregister;
+ */
+void arisc_nmi_cb_unregister(uint32_t type, arisc_cb_t func)
+{
+ if ((nmi_isr_node[type].handler) != (func)) {
+ /* invalid handler */
+ ARISC_WRN("invalid handler for unreg\n\n");
+ return ;
+ }
+ nmi_isr_node[type].handler = NULL;
+ nmi_isr_node[type].arg = NULL;
+}
+
+int arisc_disable_nmi_irq(void)
+{
+ int result;
+ struct arisc_message *pmessage;
+
+ /* allocate a message frame */
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+ if (pmessage == NULL) {
+ ARISC_WRN("allocate message failed\n");
+ return -ENOMEM;
+ }
+
+ /* initialize message */
+ pmessage->type = ARISC_AXP_DISABLE_IRQ;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+ pmessage->cb.handler = NULL;
+ pmessage->cb.arg = NULL;
+
+ /* send message use hwmsgbox */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ /* free message */
+ result = pmessage->result;
+ arisc_message_free(pmessage);
+
+ return result;
+}
+
+int arisc_enable_nmi_irq(void)
+{
+ int result;
+ struct arisc_message *pmessage;
+
+ /* allocate a message frame */
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+ if (pmessage == NULL) {
+ ARISC_WRN("allocate message failed\n");
+ return -ENOMEM;
+ }
+
+ /* initialize message */
+ pmessage->type = ARISC_AXP_ENABLE_IRQ;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+ pmessage->cb.handler = NULL;
+ pmessage->cb.arg = NULL;
+
+ /* send message use hwmsgbox */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ /* free message */
+ result = pmessage->result;
+ arisc_message_free(pmessage);
+
+ return result;
+}
+
+int arisc_clear_nmi_status(void)
+{
+ int result;
+ struct arisc_message *pmessage;
+
+ /* allocate a message frame */
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+ if (pmessage == NULL) {
+ ARISC_WRN("allocate message failed\n");
+ return -ENOMEM;
+ }
+
+ /* initialize message */
+ pmessage->type = ARISC_CLR_NMI_STATUS;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+ pmessage->cb.handler = NULL;
+ pmessage->cb.arg = NULL;
+
+ /* send message use hwmsgbox */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ /* free message */
+ result = pmessage->result;
+ arisc_message_free(pmessage);
+
+ return result;
+}
+
+int arisc_set_nmi_trigger(uint32_t type)
+{
+ int result;
+ struct arisc_message *pmessage;
+
+ /* allocate a message frame */
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+ if (pmessage == NULL) {
+ ARISC_WRN("allocate message failed\n");
+ return -ENOMEM;
+ }
+
+ /* initialize message */
+ pmessage->type = ARISC_SET_NMI_TRIGGER;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+ pmessage->cb.handler = NULL;
+ pmessage->cb.arg = NULL;
+ pmessage->paras[0] = type;
+
+ /* send message use hwmsgbox */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ /* free message */
+ result = pmessage->result;
+ arisc_message_free(pmessage);
+
+ return result;
+}
+
+int arisc_axp_get_chip_id(unsigned char *chip_id)
+{
+ int i;
+ int result;
+ struct arisc_message *pmessage;
+
+ /* allocate a message frame */
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+ if (pmessage == NULL) {
+ ARISC_WRN("allocate message failed\n");
+ return -ENOMEM;
+ }
+
+ /* initialize message */
+ pmessage->type = ARISC_AXP_GET_CHIP_ID;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+ pmessage->cb.handler = NULL;
+ pmessage->cb.arg = NULL;
+
+ memset((void *)pmessage->paras, 0, 16);
+
+ /* send message use hwmsgbox */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ /* |paras[0] |paras[1] |paras[2] |paras[3] |
+ * |chip_id[0~3]|chip_id[4~7]|chip_id[8~11]|chip_id[12~15]|
+ */
+ /* copy message readout data to user data buffer */
+ for (i = 0; i < 4; i++) {
+ chip_id[i] = (pmessage->paras[0] >> (i * 8)) & 0xff;
+ chip_id[4 + i] = (pmessage->paras[1] >> (i * 8)) & 0xff;
+ chip_id[8 + i] = (pmessage->paras[2] >> (i * 8)) & 0xff;
+ chip_id[12 + i] = (pmessage->paras[3] >> (i * 8)) & 0xff;
+ }
+
+ /* free message */
+ result = pmessage->result;
+ arisc_message_free(pmessage);
+
+ return result;
+}
+
+int arisc_set_led_bln(uint32_t *paras)
+{
+ int result;
+ struct arisc_message *pmessage;
+
+ /* allocate a message frame */
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+ if (pmessage == NULL) {
+ ARISC_WRN("allocate message failed\n");
+ return -ENOMEM;
+ }
+
+ /* initialize message */
+ pmessage->type = ARISC_SET_LED_BLN;
+ pmessage->paras[0] = paras[0];
+ pmessage->paras[1] = paras[1];
+ pmessage->paras[2] = paras[2];
+ pmessage->paras[3] = paras[3];
+
+ /* send message use hwmsgbox */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ /* free message */
+ result = pmessage->result;
+ arisc_message_free(pmessage);
+
+ return result;
+
+}
+
+#if (defined CONFIG_ARCH_SUN8IW5P1) || (defined CONFIG_ARCH_SUN50IW1P1)
+int arisc_adjust_pmu_chgcur(uint32_t max_chgcur, uint32_t chg_ic_temp, uint32_t flag)
+{
+ int result;
+ struct arisc_message *pmessage;
+
+ /* allocate a message frame */
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+ if (pmessage == NULL) {
+ ARISC_WRN("allocate message failed\n");
+ return -ENOMEM;
+ }
+
+ /* initialize message */
+ pmessage->type = ARISC_AXP_SET_PARAS;
+ pmessage->paras[0] = chg_ic_temp;
+ pmessage->paras[1] = max_chgcur;
+ pmessage->paras[2] = flag;
+
+ /* send message use hwmsgbox */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ /* free message */
+ result = pmessage->result;
+ arisc_message_free(pmessage);
+
+ return result;
+}
+#endif
+
+int arisc_set_pwr_tree(uint32_t *pwr_tree)
+{
+ int result;
+ struct arisc_message *pmessage;
+
+ /* allocate a message frame */
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+ if (pmessage == NULL) {
+ ARISC_WRN("allocate message failed\n");
+ return -ENOMEM;
+ }
+
+ /* initialize message */
+ pmessage->type = ARISC_SET_PWR_TREE;
+ memcpy((void *)pmessage->paras, (void *)pwr_tree, sizeof(int)*DM_MAX);
+
+ /* send message use hwmsgbox */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ /* free message */
+ result = pmessage->result;
+ arisc_message_free(pmessage);
+
+ return result;
+}
+
+int arisc_axp_int_notify(struct arisc_message *pmessage)
+{
+ uint32_t type = pmessage->paras[0];
+ uint32_t ret = 0;
+
+ if (type & NMI_INT_TYPE_PMU_OFFSET) {
+ /* call pmu interrupt handler */
+ if (nmi_isr_node[NMI_INT_TYPE_PMU].handler == NULL) {
+ ARISC_WRN("pmu irq handler not install\n");
+ return 1;
+ }
+
+ ARISC_INF("call pmu interrupt handler\n");
+ ret |= (*(nmi_isr_node[NMI_INT_TYPE_PMU].handler))(nmi_isr_node[NMI_INT_TYPE_PMU].arg);
+ }
+ if (type & NMI_INT_TYPE_RTC_OFFSET)
+ {
+ /* call rtc interrupt handler */
+ if (nmi_isr_node[NMI_INT_TYPE_RTC].handler == NULL) {
+ ARISC_WRN("rtc irq handler not install\n");
+ return 1;
+ }
+
+ ARISC_INF("call rtc interrupt handler\n");
+ ret |= (*(nmi_isr_node[NMI_INT_TYPE_RTC].handler))(nmi_isr_node[NMI_INT_TYPE_RTC].arg);
+ }
+
+ return ret;
+}
+
+int arisc_pmu_set_voltage(uint32_t type, uint32_t voltage)
+{
+ int result;
+ struct arisc_message *pmessage;
+
+ /* allocate a message frame */
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+ if (pmessage == NULL) {
+ ARISC_WRN("allocate message failed\n");
+ return -ENOMEM;
+ }
+
+ /* initialize message */
+ pmessage->type = ARISC_SET_PMU_VOLT;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+ pmessage->cb.handler = NULL;
+ pmessage->cb.arg = NULL;
+ pmessage->paras[0] = type;
+ pmessage->paras[1] = voltage;
+
+ /* send message use hwmsgbox */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ /* free message */
+ result = pmessage->result;
+ arisc_message_free(pmessage);
+
+ return result;
+}
+
+int arisc_pmu_get_voltage(uint32_t type, uint32_t *voltage)
+{
+ int result;
+ struct arisc_message *pmessage;
+
+ /* allocate a message frame */
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+ if (pmessage == NULL) {
+ ARISC_WRN("allocate message failed\n");
+ return -ENOMEM;
+ }
+
+ /* initialize message */
+ pmessage->type = ARISC_GET_PMU_VOLT;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+ pmessage->cb.handler = NULL;
+ pmessage->cb.arg = NULL;
+ pmessage->paras[0] = type;
+
+ /* send message use hwmsgbox */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+ *voltage = pmessage->paras[1];
+
+ /* free message */
+ result = pmessage->result;
+ arisc_message_free(pmessage);
+
+ return result;
+}
diff --git a/plat/sun50iw1p1/scp/interfaces/arisc_debug_level.c b/plat/sun50iw1p1/scp/interfaces/arisc_debug_level.c
new file mode 100644
index 0000000..e1e5346
--- /dev/null
+++ b/plat/sun50iw1p1/scp/interfaces/arisc_debug_level.c
@@ -0,0 +1,137 @@
+/*
+ * drivers/arisc/interfaces/arisc_debug_level.c
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "../arisc_i.h"
+
+/**
+ * set arisc debug level.
+ * @level: arisc debug level;
+ *
+ * return: 0 - set arisc debug level successed, !0 - set arisc debug level failed;
+ */
+int arisc_set_debug_level(unsigned int level)
+{
+ int result;
+ struct arisc_message *pmessage;
+
+ /* allocate a message frame */
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+ if (pmessage == NULL) {
+ ARISC_ERR("allocate message for debug level request failed\n");
+ return -ENOMEM;
+ }
+
+ /* initialize message */
+ pmessage->type = ARISC_SET_DEBUG_LEVEL;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+ pmessage->paras[0] = level;
+ pmessage->cb.handler = NULL;
+ pmessage->cb.arg = NULL;
+
+ /* send set debug level request to arisc */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ /* free message */
+ result = pmessage->result;
+ arisc_message_free(pmessage);
+
+ return result;
+}
+
+int arisc_set_uart_baudrate(uint32_t baudrate)
+{
+ int result;
+ struct arisc_message *pmessage;
+
+ /* allocate a message frame */
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+ if (pmessage == NULL) {
+ ARISC_ERR("allocate message for set baudrate request failed\n");
+ return -ENOMEM;
+ }
+
+ /* initialize message */
+ pmessage->type = ARISC_SET_UART_BAUDRATE;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+ pmessage->paras[0] = baudrate;
+ pmessage->cb.handler = NULL;
+ pmessage->cb.arg = NULL;
+
+ /* send message use hwmsgbox */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ /* free message */
+ result = pmessage->result;
+ arisc_message_free(pmessage);
+
+ return result;
+}
+
+int arisc_report_error_info(struct arisc_message *pmessage)
+{
+ uint32_t id = pmessage->paras[0];
+
+ switch(id) {
+ case ERR_NMI_INT_TIMEOUT: {
+ ARISC_ERR("arisc report error info: nmi int response timeout\n");
+ break;
+ }
+ default: {
+ ARISC_ERR("invaid arisc report error infomation id:%u\n", id);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * set paras.
+ *
+ * return: 0 - set paras successed, !0 - set paras failed;
+ */
+int arisc_set_paras(void)
+{
+ int result;
+ struct arisc_message *pmessage;
+
+ /* allocate a message frame */
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+ if (pmessage == NULL) {
+ ARISC_ERR("allocate message for set paras request failed\n");
+ return -ENOMEM;
+ }
+
+ /* initialize message */
+ pmessage->type = ARISC_SET_PARAS;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+ pmessage->cb.handler = NULL;
+ pmessage->cb.arg = NULL;
+
+ /* send set debug level request to arisc */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ /* free message */
+ result = pmessage->result;
+ arisc_message_free(pmessage);
+
+ return result;
+} \ No newline at end of file
diff --git a/plat/sun50iw1p1/scp/interfaces/arisc_dram_crc.c b/plat/sun50iw1p1/scp/interfaces/arisc_dram_crc.c
new file mode 100644
index 0000000..fd82232
--- /dev/null
+++ b/plat/sun50iw1p1/scp/interfaces/arisc_dram_crc.c
@@ -0,0 +1,57 @@
+/*
+ * drivers/arisc/interfaces/arisc_dram_crc.c
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "../arisc_i.h"
+
+/**
+ * set arisc debug dram crc paras.
+ * @dram_crc_en: arisc debug dram crc enable or disable;
+ * @dram_crc_srcaddr: source address of dram crc area
+ * @dram_crc_len: lenght of dram crc area
+ *
+ * return: 0 - set arisc debug dram crc paras successed, !0 - set arisc debug dram crc paras failed;
+ */
+int arisc_set_dram_crc_paras(unsigned int dram_crc_en, unsigned int dram_crc_srcaddr, unsigned int dram_crc_len)
+{
+ struct arisc_message *pmessage;
+
+ ARISC_INF("en:%x, src:%x len:%x\n", dram_crc_en, dram_crc_srcaddr, dram_crc_len);
+
+ /* allocate a message frame */
+ pmessage = arisc_message_allocate(0);
+ if (pmessage == NULL) {
+ ARISC_ERR("allocate message for seting dram crc paras request failed\n");
+ return -ENOMEM;
+ }
+
+ /* initialize message */
+ pmessage->type = ARISC_SET_DEBUG_DRAM_CRC_PARAS;
+ pmessage->paras[0] = dram_crc_en;
+ pmessage->paras[1] = dram_crc_srcaddr;
+ pmessage->paras[2] = dram_crc_len;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+
+ /* send set debug level request to arisc */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ return 0;
+}
+
diff --git a/plat/sun50iw1p1/scp/interfaces/arisc_dvfs.c b/plat/sun50iw1p1/scp/interfaces/arisc_dvfs.c
new file mode 100644
index 0000000..c7c50cc
--- /dev/null
+++ b/plat/sun50iw1p1/scp/interfaces/arisc_dvfs.c
@@ -0,0 +1,81 @@
+/*
+ * drivers/arisc/interfaces/arisc_dvfs.c
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "../arisc_i.h"
+
+static int dvfs_err_cb(void *arg)
+{
+ ARISC_ERR("dvfs error\n");
+
+ return 0;
+}
+
+/*
+ * set specific pll target frequency.
+ * @freq: target frequency to be set, based on KHZ;
+ * @pll: which pll will be set
+ * @mode: the attribute of message, whether syn or asyn;
+ * @cb: callback handler;
+ * @cb_arg: callback handler arguments;
+ *
+ * return: result, 0 - set frequency successed,
+ * !0 - set frequency failed;
+ */
+int arisc_dvfs_set_cpufreq(uint32_t freq, uint32_t pll, uint32_t mode)
+{
+ unsigned int msg_attr = 0;
+ struct arisc_message *pmessage;
+ int result = 0;
+
+ if (mode & ARISC_DVFS_SYN) {
+ msg_attr |= ARISC_MESSAGE_ATTR_HARDSYN;
+ }
+
+ /* allocate a message frame */
+ pmessage = arisc_message_allocate(msg_attr);
+ if (pmessage == NULL) {
+ ARISC_WRN("allocate message failed\n");
+ return -ENOMEM;
+ }
+
+ /* initialize message
+ *
+ * |paras[0]|paras[1]|
+ * |freq |pll |
+ */
+ pmessage->type = ARISC_CPUX_DVFS_REQ;
+ pmessage->paras[0] = freq;
+ pmessage->paras[1] = pll;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+ pmessage->cb.handler = dvfs_err_cb;
+ pmessage->cb.arg = NULL;
+
+ ARISC_INF("arisc dvfs request : %d\n", freq);
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ /* dvfs mode : syn or not */
+ if (mode & ARISC_DVFS_SYN) {
+ result = pmessage->result;
+ arisc_message_free(pmessage);
+ }
+
+ return result;
+}
diff --git a/plat/sun50iw1p1/scp/interfaces/arisc_loopback.c b/plat/sun50iw1p1/scp/interfaces/arisc_loopback.c
new file mode 100644
index 0000000..029d4dc
--- /dev/null
+++ b/plat/sun50iw1p1/scp/interfaces/arisc_loopback.c
@@ -0,0 +1,51 @@
+/*
+ * drivers/arisc/interfaces/arisc_loopback.c
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "../arisc_i.h"
+
+int arisc_message_loopback(void)
+{
+ int result;
+ struct arisc_message *pmessage;
+
+ /* allocate a message frame */
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+ if (pmessage == NULL) {
+ ARISC_WRN("allocate message failed\n");
+ return -ENOMEM;
+ }
+
+ /* initialize message */
+ pmessage->type = ARISC_MESSAGE_LOOPBACK;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+ pmessage->paras[0] = 11;
+ pmessage->cb.handler = NULL;
+ pmessage->cb.arg = NULL;
+
+ /* send message use hwmsgbox */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ /* free message */
+ result = pmessage->result;
+ arisc_message_free(pmessage);
+
+ return result;
+}
diff --git a/plat/sun50iw1p1/scp/interfaces/arisc_rsb.c b/plat/sun50iw1p1/scp/interfaces/arisc_rsb.c
new file mode 100644
index 0000000..f3b685b
--- /dev/null
+++ b/plat/sun50iw1p1/scp/interfaces/arisc_rsb.c
@@ -0,0 +1,329 @@
+/*
+ * drivers/arisc/interfaces/arisc_rsb.c
+ *
+ * Copyright (c) 2013 Allwinner.
+ * 2013-07-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "../arisc_i.h"
+
+#if (defined CONFIG_ARCH_SUN8IW3P1) || (defined CONFIG_ARCH_SUN8IW5P1) || (defined CONFIG_ARCH_SUN8IW6P1) || \
+ (defined CONFIG_ARCH_SUN8IW7P1) || (defined CONFIG_ARCH_SUN8IW9P1) || (defined CONFIG_ARCH_SUN9IW1P1) || \
+ (defined CONFIG_ARCH_SUN50IW1P1)
+
+/*
+ * used for indicate aduio codec been initialized,
+ * modules like audio & trc mabye initialize,
+ * but audio codec only can be initialize once
+ */
+static int audio_codec_init = 0;
+
+/**
+ * rsb read block data.
+ * @cfg: point of arisc_rsb_block_cfg struct;
+ *
+ * return: result, 0 - read register successed,
+ * !0 - read register failed or the len more then max len;
+ */
+int arisc_rsb_read_block_data(uint32_t *paras)
+{
+ int result;
+ struct arisc_message *pmessage;
+
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+
+ if (pmessage == NULL) {
+ ARISC_WRN("allocate message failed\n");
+ return -ENOMEM;
+ }
+
+ /* initialize message */
+ pmessage->type = ARISC_RSB_READ_BLOCK_DATA;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+ pmessage->cb.handler = NULL;
+ pmessage->cb.arg = NULL;
+
+ memcpy((void *)pmessage->paras, (const void *)paras, sizeof(pmessage->paras));
+
+ /* send message use hwmsgbox */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ memcpy((void *)paras, (const void *)pmessage->paras, sizeof(pmessage->paras));
+
+ /* free message */
+ result = pmessage->result;
+ arisc_message_free(pmessage);
+
+ return result;
+}
+
+
+/**
+ * rsb write block data.
+ * @cfg: point of arisc_rsb_block_cfg struct;
+ *
+ * return: result, 0 - write register successed,
+ * !0 - write register failedor the len more then max len;
+ */
+int arisc_rsb_write_block_data(uint32_t *paras)
+{
+ int result;
+ struct arisc_message *pmessage;
+
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+
+ if (pmessage == NULL) {
+ ARISC_WRN("allocate message failed\n");
+ return -ENOMEM;
+ }
+ /* initialize message */
+ pmessage->type = ARISC_RSB_WRITE_BLOCK_DATA;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+ pmessage->cb.handler = NULL;
+ pmessage->cb.arg = NULL;
+
+ memcpy((void *)pmessage->paras, (const void *)paras, sizeof(pmessage->paras));
+
+ /* send message use hwmsgbox */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ /* free message */
+ result = pmessage->result;
+ arisc_message_free(pmessage);
+
+ return result;
+}
+
+
+/**
+ * rsb read pmu reg.
+ * @addr: pmu reg addr;
+ *
+ * return: if read pmu reg successed, return data of pmu reg;
+ * if read pmu reg failed, return -1.
+ */
+uint8_t arisc_rsb_read_pmu_reg(uint32_t addr)
+{
+ int result;
+ uint32_t paras[22];
+ uint32_t data = 0;
+
+ /*
+ * package address and data to message->paras,
+ * message->paras data layout:
+ * |para[0] |para[1]|para[2] |para[3]|para[4]|para[5]|para[6]|
+ * |(len|datatype)|devaddr|regaddr0~3|data0 |data1 |data2 |data3 |
+ */
+ memset((void *)paras, 0, sizeof(uint32_t) * 6);
+ paras[0] = ((1 & 0xffff) | ((RSB_DATA_TYPE_BYTE << 16) & 0xffff0000));
+ paras[1] = 0x2d;
+ paras[2] = addr&0xff;
+
+ result = arisc_rsb_read_block_data(paras);
+ if (!result) {
+ data = paras[3];
+ } else {
+ ARISC_ERR("arisc rsb read pmu reg 0x%x err\n", addr);
+ return -1;
+ }
+
+ ARISC_INF("read pmu reg 0x%x:0x%x\n", addr, data);
+
+ return data;
+}
+
+
+/**
+ * rsb write pmu reg.
+ * @addr: pmu reg addr;
+ * @data: pmu reg data;
+ *
+ * return: result, 0 - write register successed,
+ * !0 - write register failedor the len more then max len;
+ */
+int arisc_rsb_write_pmu_reg(uint32_t addr, uint32_t data)
+{
+ int result;
+ uint32_t paras[22];
+
+ /*
+ * package address and data to message->paras,
+ * message->paras data layout:
+ * |para[0] |para[1]|para[2] |para[3]|para[4]|para[5]|para[6]|
+ * |(len|datatype)|devaddr|regaddr0~3|data0 |data1 |data2 |data3 |
+ */
+ memset((void *)paras, 0, sizeof(uint32_t) * 6);
+ paras[0] = ((1 & 0xffff) | ((RSB_DATA_TYPE_BYTE << 16) & 0xffff0000));
+ paras[1] = 0x2d;
+ paras[2] = addr&0xff;
+ paras[3] = data&0xff;
+
+ result = arisc_rsb_write_block_data(paras);
+ if (result) {
+ ARISC_ERR("arisc rsb write pmu reg 0x%x:0x%x err\n", addr, data);
+ }
+ ARISC_INF("write pmu reg 0x%x:0x%x\n", addr, data);
+
+ return result;
+}
+
+
+/**
+ * rsb bits operation sync.
+ * @cfg: point of arisc_rsb_bits_cfg struct;
+ *
+ * return: result, 0 - bits operation successed,
+ * !0 - bits operation failed, or the len more then max len;
+ *
+ * rsb clear bits internal:
+ * data = rsb_read(regaddr);
+ * data = data & (~mask);
+ * rsb_write(regaddr, data);
+ *
+ * rsb set bits internal:
+ * data = rsb_read(addr);
+ * data = data | mask;
+ * rsb_write(addr, data);
+ *
+ */
+int rsb_bits_ops_sync(uint32_t *paras)
+{
+ int result;
+ struct arisc_message *pmessage;
+
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+
+ if (pmessage == NULL) {
+ ARISC_WRN("allocate message failed\n");
+ return -ENOMEM;
+ }
+ /* initialize message */
+ pmessage->type = ARISC_RSB_BITS_OPS_SYNC;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+ pmessage->cb.handler = NULL;
+ pmessage->cb.arg = NULL;
+
+ memcpy((void *)pmessage->paras, (const void *)paras, sizeof(pmessage->paras));
+
+ /* send message use hwmsgbox */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ /* free message */
+ result = pmessage->result;
+ arisc_message_free(pmessage);
+
+ return result;
+}
+
+/**
+ * rsb set interface mode.
+ * @devaddr: rsb slave device address;
+ * @regaddr: register address of rsb slave device;
+ * @data: data which to init rsb slave device interface mode;
+ *
+ * return: result, 0 - set interface mode successed,
+ * !0 - set interface mode failed;
+ */
+int arisc_rsb_set_interface_mode(uint32_t devaddr, uint32_t regaddr, uint32_t data)
+{
+ int result;
+ struct arisc_message *pmessage;
+
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+
+ if (pmessage == NULL) {
+ ARISC_WRN("allocate message failed\n");
+ return -ENOMEM;
+ }
+
+ /* initialize message */
+ pmessage->type = ARISC_RSB_SET_INTERFACE_MODE;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+ pmessage->cb.handler = NULL;
+ pmessage->cb.arg = NULL;
+
+ /*
+ * package address and data to message->paras,
+ * message->paras data layout:
+ * |para[0]|para[1]|para[2]|
+ * |devaddr|regaddr|data |
+ */
+ pmessage->paras[0] = devaddr;
+ pmessage->paras[1] = regaddr;
+ pmessage->paras[2] = data;
+ /* send message use hwmsgbox */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ /* free message */
+ result = pmessage->result;
+ arisc_message_free(pmessage);
+
+ return result;
+}
+
+/**
+ * rsb set runtime slave address.
+ * @devaddr: rsb slave device address;
+ * @rtsaddr: rsb slave device's runtime slave address;
+ *
+ * return: result, 0 - set rsb runtime address successed,
+ * !0 - set rsb runtime address failed;
+ */
+int arisc_rsb_set_rtsaddr(uint32_t devaddr, uint32_t rtsaddr)
+{
+ int result;
+ struct arisc_message *pmessage;
+
+ /* check audio codec has been initialized */
+ if (devaddr == RSB_DEVICE_SADDR7) {
+ if (audio_codec_init)
+ return 0;
+ else
+ audio_codec_init = 1;
+ }
+
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+
+ if (pmessage == NULL) {
+ ARISC_WRN("allocate message failed\n");
+ return -ENOMEM;
+ }
+
+ /* initialize message */
+ pmessage->type = ARISC_RSB_SET_RTSADDR;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+ pmessage->cb.handler = NULL;
+ pmessage->cb.arg = NULL;
+
+ /*
+ * package address and data to message->paras,
+ * message->paras data layout:
+ * |para[0]|para[1]|
+ * |devaddr|rtsaddr|
+ */
+ pmessage->paras[0] = devaddr;
+ pmessage->paras[1] = rtsaddr;
+ /* send message use hwmsgbox */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ /* free message */
+ result = pmessage->result;
+ arisc_message_free(pmessage);
+
+ return result;
+}
+#endif
diff --git a/plat/sun50iw1p1/scp/interfaces/arisc_standby.c b/plat/sun50iw1p1/scp/interfaces/arisc_standby.c
new file mode 100644
index 0000000..d570ddf
--- /dev/null
+++ b/plat/sun50iw1p1/scp/interfaces/arisc_standby.c
@@ -0,0 +1,286 @@
+/*
+ * drivers/arisc/interfaces/arisc_standby.c
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "../arisc_i.h"
+
+/* record super-standby wakeup event */
+static unsigned long wakeup_event = 0;
+static unsigned long dram_crc_error = 0;
+static unsigned long dram_crc_total_count = 0;
+static unsigned long dram_crc_error_count = 0;
+
+/**
+ * cpu operations.
+ * @mpidr: cpu id;
+ * @entrypoint: cpu resume entrypoint;
+ * @cpu_state: cpu state;
+ * @cluster_state: cluster state;
+ *
+ * return: result, 0 - cpu operations successed,
+ * !0 - cpu operations failed;
+ */
+int arisc_cpu_op(uint32_t mpidr, uint32_t entrypoint, arisc_power_state_t cpu_state,
+ arisc_power_state_t cluster_state)
+{
+ struct arisc_message *pmessage;
+
+ /* allocate a message frame */
+ pmessage = arisc_message_allocate(0);
+ if (pmessage == NULL) {
+ ARISC_ERR("allocate message for cpu op request failed\n");
+ return -ENOMEM;
+ }
+
+ pmessage->type = ARISC_CPU_OP_REQ;
+ pmessage->cb.handler = NULL;
+ pmessage->cb.arg = NULL;
+ pmessage->paras[0] = mpidr;
+ pmessage->paras[1] = entrypoint;
+ pmessage->paras[2] = cpu_state;
+ pmessage->paras[3] = cluster_state;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+
+ /* send enter cpu operations request to arisc */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ return 0;
+}
+
+ /**
+ * system operations.
+ * @state: system state;
+ *
+ * return: result, 0 - system operations successed,
+ * !0 - system operations failed;
+ */
+int arisc_system_op(arisc_system_state_t state)
+{
+ struct arisc_message *pmessage;
+
+ /* allocate a message frame */
+ pmessage = arisc_message_allocate(0);
+ if (pmessage == NULL) {
+ ARISC_ERR("allocate message for sys op request failed\n");
+ return -ENOMEM;
+ }
+
+ pmessage->type = ARISC_SYS_OP_REQ;
+ pmessage->cb.handler = NULL;
+ pmessage->cb.arg = NULL;
+ pmessage->paras[0] = state;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+
+ /* send enter sys operations request to arisc */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ return 0;
+}
+
+/*
+ * enter cpu idle.
+ * @para: parameter for enter cpu idle.
+ * para->flag: 0x01-clear pending, 0x10-enter cpuidle
+ * para->resume_addr: the address cpu0 will run when exit idle
+ *
+ * return: result, 0 - super standby successed,
+ * !0 - super standby failed;
+ */
+int arisc_enter_cpuidle(arisc_cb_t cb, void *cb_arg, struct sunxi_enter_idle_para *para)
+{
+ struct arisc_message *pmessage; /* allocate a message frame */
+ pmessage = arisc_message_allocate(0);
+ if (pmessage == NULL) {
+ ARISC_ERR("allocate message for super-standby request failed\n");
+ return -ENOMEM;
+ }
+ pmessage->type = ARISC_CPUIDLE_ENTER_REQ;
+ pmessage->cb.handler = cb;
+ pmessage->cb.arg = cb_arg;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+ pmessage->paras[0] = para->flags;
+ pmessage->paras[1] = (unsigned long)para->resume_addr;
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+ return 0;
+}
+
+/**
+ * query super-standby wakeup source.
+ * @para: point of buffer to store wakeup event informations.
+ *
+ * return: result, 0 - query successed,
+ * !0 - query failed;
+ */
+int arisc_query_wakeup_source(uint32_t *event)
+{
+ *event = wakeup_event;
+
+ return 0;
+}
+
+/*
+ * query super-standby infoation.
+ * @para: point of array to store power states informations during sst.
+ * @op: 0:read, 1:set
+ *
+ * return: result, 0 - query successed,
+ * !0 - query failed;
+ */
+int arisc_query_set_standby_info(struct standby_info_para *para, arisc_rw_type_e op)
+{
+ struct arisc_message *pmsg;
+ int result;
+
+ /* allocate a message frame */
+ pmsg = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+ if (pmsg == NULL) {
+ ARISC_ERR("allocate message for query standby info failed\n");
+ return -ENOMEM;
+ }
+
+ /* check standby_info_para size valid or not */
+ if (sizeof(struct standby_info_para) > sizeof(pmsg->paras)) {
+ ARISC_ERR("standby info parameters number too long\n");
+ return -EINVAL;
+ }
+
+ /* initialize message */
+ pmsg->type = ARISC_STANDBY_INFO_REQ;
+ pmsg->cb.handler = NULL;
+ pmsg->cb.arg = NULL;
+ pmsg->private = (void *)op;
+ if (ARISC_WRITE == op) {
+ memcpy((void *)pmsg->paras, (const void *)para, sizeof(struct standby_info_para));
+ }
+ pmsg->state = ARISC_MESSAGE_INITIALIZED;
+
+ /* send query sst info request to arisc */
+ arisc_hwmsgbox_send_message(pmsg, ARISC_SEND_MSG_TIMEOUT);
+ if (ARISC_READ == op)
+ memcpy((void *)para, (void *)pmsg->paras, sizeof(struct standby_info_para));
+
+ /* free message */
+ result = pmsg->result;
+ arisc_message_free(pmsg);
+
+ return result;
+}
+
+/*
+ * query super-standby dram crc result.
+ * @para: point of buffer to store dram crc result informations.
+ *
+ * return: result, 0 - query successed,
+ * !0 - query failed;
+ */
+int arisc_query_dram_crc_result(unsigned long *perror, unsigned long *ptotal_count,
+ unsigned long *perror_count)
+{
+ *perror = dram_crc_error;
+ *ptotal_count = dram_crc_total_count;
+ *perror_count = dram_crc_error_count;
+
+ return 0;
+}
+
+int arisc_set_dram_crc_result(unsigned long error, unsigned long total_count,
+ unsigned long error_count)
+{
+ dram_crc_error = error;
+ dram_crc_total_count = total_count;
+ dram_crc_error_count = error_count;
+
+ return 0;
+}
+
+/**
+ * notify arisc cpux restored.
+ * @para: none.
+ *
+ * return: result, 0 - notify successed, !0 - notify failed;
+ */
+int arisc_cpux_ready_notify(void)
+{
+ struct arisc_message *pmessage;
+
+ /* notify hwspinlock and hwmsgbox resume first */
+ arisc_hwmsgbox_standby_resume();
+ arisc_hwspinlock_standby_resume();
+
+ /* allocate a message frame */
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+ if (pmessage == NULL) {
+ ARISC_WRN("allocate message failed\n");
+ return -ENOMEM;
+ }
+
+ /* initialize message */
+ pmessage->type = ARISC_SSTANDBY_RESTORE_NOTIFY;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+
+ /* record wakeup event */
+ wakeup_event = pmessage->paras[0];
+ if (arisc_debug_dram_crc_en) {
+ dram_crc_error = pmessage->paras[1];
+ dram_crc_total_count++;
+ dram_crc_error_count += (dram_crc_error ? 1 : 0);
+ }
+
+ /* free message */
+ arisc_message_free(pmessage);
+
+ return 0;
+}
+
+int arisc_config_ir_paras(uint32_t ir_code, uint32_t ir_addr)
+{
+ int result = 0;
+ struct arisc_message *pmessage;
+
+ /* allocate a message frame */
+ pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
+ if (pmessage == NULL) {
+ ARISC_WRN("allocate message failed\n");
+ return -ENOMEM;
+ }
+ /* initialize message */
+ pmessage->type = ARISC_SET_IR_PARAS;
+ pmessage->paras[0] = ir_code;
+ pmessage->paras[1] = ir_addr;
+ pmessage->state = ARISC_MESSAGE_INITIALIZED;
+ pmessage->cb.handler = NULL;
+ pmessage->cb.arg = NULL;
+
+ ARISC_INF("ir power key:0x%x, addr:0x%x\n", ir_code, ir_addr);
+
+ /* send request message */
+ arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+ if (pmessage->result) {
+ ARISC_WRN("config ir power key code [%d] fail\n", pmessage->paras[0]);
+ result = -EINVAL;
+ }
+
+ /* free allocated message */
+ arisc_message_free(pmessage);
+
+ return result;
+}
diff --git a/plat/sun50iw1p1/scp/interfaces/interfaces.mk b/plat/sun50iw1p1/scp/interfaces/interfaces.mk
new file mode 100644
index 0000000..1571046
--- /dev/null
+++ b/plat/sun50iw1p1/scp/interfaces/interfaces.mk
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+
+BL31_SOURCES += plat/sun50iw1p1/scp/interfaces/arisc_loopback.c \
+ plat/sun50iw1p1/scp/interfaces/arisc_dvfs.c \
+ plat/sun50iw1p1/scp/interfaces/arisc_rsb.c\
+ plat/sun50iw1p1/scp/interfaces/arisc_axp.c \
+ plat/sun50iw1p1/scp/interfaces/arisc_standby.c \
+ plat/sun50iw1p1/scp/interfaces/arisc_dram_crc.c \
+ plat/sun50iw1p1/scp/interfaces/arisc_debug_level.c
diff --git a/plat/sun50iw1p1/scp/message_manager/message_manager.c b/plat/sun50iw1p1/scp/message_manager/message_manager.c
new file mode 100644
index 0000000..46b8969
--- /dev/null
+++ b/plat/sun50iw1p1/scp/message_manager/message_manager.c
@@ -0,0 +1,282 @@
+/*
+ * arch/arm/mach-sunxi/arisc/message_manager/message_manager.c
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "message_manager_i.h"
+
+/* the start and end of message pool */
+static struct arisc_message *message_start;
+static struct arisc_message *message_end;
+
+/* spinlock for this module */
+static spinlock_t msg_mgr_lock;
+
+/* message cache manager */
+static struct arisc_message_cache message_cache;
+
+static void *arisc_message_pool_base;
+static uint32_t arisc_message_pool_size;
+
+/**
+ * initialize message manager.
+ * @para: none.
+ *
+ * returns: 0 if initialize succeeded, others if failed.
+ */
+int arisc_message_manager_init(void *addr, uint32_t size)
+{
+ int i;
+
+ arisc_message_pool_base = addr;
+ arisc_message_pool_size = size;
+
+ /* initialize message pool start and end */
+ message_start = (struct arisc_message *)(arisc_message_pool_base);
+ message_end = (struct arisc_message *)((ptrdiff_t)arisc_message_pool_base + arisc_message_pool_size);
+
+ //memset((void *)message_start, 0, arisc_message_pool_size);
+
+ /* initialize message_cache */
+ for (i = 0; i < ARISC_MESSAGE_CACHED_MAX; i++) {
+ message_cache.cache[i] = NULL;
+ }
+ message_cache.number = 0;
+
+ return 0;
+}
+
+/**
+ * exit message manager.
+ * @para: none.
+ *
+ * returns: 0 if exit succeeded, others if failed.
+ */
+int arisc_message_manager_exit(void)
+{
+ return 0;
+}
+
+static int arisc_message_invalid(struct arisc_message *pmessage)
+{
+ if ((pmessage >= message_start) &&
+ (pmessage < message_end)) {
+ /* valid arisc message */
+ return 0;
+ }
+ /* invalid arisc message */
+ return 1;
+}
+
+/**
+ * allocate one message frame. mainly use for send message by message-box,
+ * the message frame allocate form messages pool shared memory area.
+ * @para: none.
+ *
+ * returns: the pointer of allocated message frame, NULL if failed;
+ */
+struct arisc_message *arisc_message_allocate(unsigned int msg_attr)
+{
+ struct arisc_message *pmessage = NULL;
+ struct arisc_message *palloc = NULL;
+
+ /* first find in message_cache */
+ spin_lock(&msg_mgr_lock);
+ if (message_cache.number) {
+ ARISC_INF("arisc message_cache.number = 0x%x.\n", message_cache.number);
+ message_cache.number--;
+ palloc = message_cache.cache[message_cache.number];
+ ARISC_INF("message [%llx] allocate from message_cache\n", palloc);
+ if (arisc_message_invalid(palloc)) {
+ ARISC_ERR("allocate cache message [%llx] invalid\n", palloc);
+ }
+ }
+ spin_unlock(&msg_mgr_lock);
+ if (arisc_message_invalid(palloc)) {
+ /*
+ * cached message_cache finded fail,
+ * use spinlock 0 to exclusive with arisc.
+ */
+ arisc_hwspin_lock(AW_MSG_HWSPINLOCK);
+
+ /* search from the start of message pool every time. */
+ pmessage = message_start;
+ while (pmessage < message_end) {
+ if (pmessage->state == ARISC_MESSAGE_FREED) {
+ /* find free message in message pool, allocate it */
+ palloc = pmessage;
+ palloc->state = ARISC_MESSAGE_ALLOCATED;
+ ARISC_INF("message [%llx] allocate from message pool\n", palloc);
+ break;
+ }
+ /* next message frame */
+ pmessage++;
+ }
+ /* unlock hwspinlock 0 */
+ arisc_hwspin_unlock(AW_MSG_HWSPINLOCK);
+ }
+ if (arisc_message_invalid(palloc)) {
+ ARISC_ERR("allocate message [%llx] frame is invalid\n", palloc);
+ return NULL;
+ }
+ /* initialize messgae frame */
+ palloc->next = NULL;
+ palloc->attr = msg_attr;
+ palloc->private = NULL;
+
+ return palloc;
+}
+
+/**
+ * free one message frame. mainly use for process message finished,
+ * free it to messages pool or add to free message queue.
+ * @pmessage: the pointer of free message frame.
+ *
+ * returns: none.
+ */
+void arisc_message_free(struct arisc_message *pmessage)
+{
+ struct arisc_message *free_message = pmessage;
+
+ /* check this message valid or not */
+ if (arisc_message_invalid(free_message)) {
+ ARISC_ERR("free invalid arisc message [%llx]\n", free_message);
+ return;
+ }
+
+ /* try to free to free_list first */
+ spin_lock(&msg_mgr_lock);
+ if (message_cache.number < ARISC_MESSAGE_CACHED_MAX) {
+ ARISC_INF("insert message [%llx] to message_cache\n", free_message);
+ ARISC_INF("message_cache number : %d\n", message_cache.number);
+ /* cached this message, message state: ALLOCATED */
+ message_cache.cache[message_cache.number] = free_message;
+ message_cache.number++;
+ free_message->next = NULL;
+ free_message->state = ARISC_MESSAGE_ALLOCATED;
+ free_message = NULL;
+ }
+ spin_unlock(&msg_mgr_lock);
+
+ /* try to free message to pool if free to cache fail */
+ if (free_message) {
+ /* free to message pool,set message state as FREED. */
+ arisc_hwspin_lock(AW_MSG_HWSPINLOCK);
+ ARISC_INF("insert message [%llx] to message pool\n", free_message);
+ free_message->state = ARISC_MESSAGE_FREED;
+ free_message->next = NULL;
+ arisc_hwspin_unlock(AW_MSG_HWSPINLOCK);
+ }
+}
+
+/**
+ * notify system that one message coming.
+ * @pmessage: the pointer of coming message frame.
+ *
+ * returns: 0 if notify succeeded, other if failed.
+ */
+int arisc_message_coming_notify(struct arisc_message *pmessage)
+{
+ int ret;
+
+ /* ac327 receive message to arisc */
+ ARISC_INF("-------------------------------------------------------------\n");
+ ARISC_INF(" MESSAGE FROM ARISC \n");
+ ARISC_INF("message addr : %llx\n", pmessage);
+ ARISC_INF("message type : %x\n", pmessage->type);
+ ARISC_INF("message attr : %x\n", pmessage->attr);
+ ARISC_INF("-------------------------------------------------------------\n");
+
+ /* message per-process */
+ pmessage->state = ARISC_MESSAGE_PROCESSING;
+
+ /* process message */
+ switch (pmessage->type) {
+ case ARISC_AXP_INT_COMING_NOTIFY: {
+ ARISC_INF("pmu interrupt coming notify\n");
+ ret = arisc_axp_int_notify(pmessage);
+ pmessage->result = ret;
+ break;
+ }
+ case ARISC_AUDIO_PERDONE_NOTIFY: {
+ ARISC_INF("audio perdone notify\n");
+ ret = arisc_audio_perdone_notify(pmessage);
+ pmessage->result = ret;
+ break;
+ }
+ case ARISC_REPORT_ERR_INFO: {
+ ARISC_INF("arisc report error info\n");
+ ret = arisc_report_error_info(pmessage);
+ pmessage->result = ret;
+ break;
+ }
+
+ default : {
+ ARISC_ERR("invalid message type for ac327 process\n");
+ ARISC_ERR("message addr : %llx\n", pmessage);
+ ARISC_ERR("message state : %x\n", pmessage->state);
+ ARISC_ERR("message attr : %x\n", pmessage->attr);
+ ARISC_ERR("message type : %x\n", pmessage->type);
+ ARISC_ERR("message result : %x\n", pmessage->result);
+ ret = -EINVAL;
+ break;
+ }
+ }
+ /* message post process */
+ pmessage->state = ARISC_MESSAGE_PROCESSED;
+ if (pmessage->attr & ARISC_MESSAGE_ATTR_HARDSYN) {
+ /* synchronous message, should feedback process result */
+ arisc_hwmsgbox_feedback_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
+ } else {
+ /*
+ * asyn message, no need feedback message result,
+ * free message directly.
+ */
+ arisc_message_free(pmessage);
+ }
+
+ return ret;
+}
+
+struct arisc_message *arisc_message_map_to_cpux(uint32_t addr)
+{
+ struct arisc_message *message;
+ message = (struct arisc_message *)((ptrdiff_t)addr + (ptrdiff_t)arisc_message_pool_base);
+
+ return message;
+}
+
+uint32_t arisc_message_map_to_cpus(struct arisc_message *message)
+{
+ uint32_t value = (uint32_t)((ptrdiff_t)message - (ptrdiff_t)arisc_message_pool_base);
+
+ return value;
+}
+
+int arisc_message_valid(struct arisc_message *pmessage)
+{
+ if ((pmessage >= message_start) && (pmessage < message_end)) {
+ /* valid message */
+ return 1;
+ }
+
+ return 0;
+}
+
diff --git a/plat/sun50iw1p1/scp/message_manager/message_manager.mk b/plat/sun50iw1p1/scp/message_manager/message_manager.mk
new file mode 100644
index 0000000..806f3ef
--- /dev/null
+++ b/plat/sun50iw1p1/scp/message_manager/message_manager.mk
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+
+BL31_SOURCES += plat/sun50iw1p1/scp/message_manager/message_manager.c
diff --git a/plat/sun50iw1p1/scp/message_manager/message_manager_i.h b/plat/sun50iw1p1/scp/message_manager/message_manager_i.h
new file mode 100644
index 0000000..54c5383
--- /dev/null
+++ b/plat/sun50iw1p1/scp/message_manager/message_manager_i.h
@@ -0,0 +1,40 @@
+/*
+ * arch/arm/mach-sunxi/arisc/message_manager/message_manager_i.h
+ *
+ * Copyright (c) 2012 Allwinner.
+ * 2012-10-01 Written by superm (superm@allwinnertech.com).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ARISC_MESSAGE_MANAGER_I_H
+#define __ARISC_MESSAGE_MANAGER_I_H
+
+#include "../include/arisc_includes.h"
+#include "../arisc_i.h"
+
+#define ARISC_SEM_CACHE_MAX (8)
+
+/*
+ *the strcuture of message cache,
+ *main for messages cache management.
+ */
+typedef struct arisc_message_cache
+{
+ uint32_t number; /* valid message number */
+ struct arisc_message *cache[ARISC_MESSAGE_CACHED_MAX]; /* message cache table */
+} arisc_message_cache_t;
+
+#endif /* __ARISC_MESSAGE_MANAGER_I_H */
diff --git a/plat/sun50iw1p1/scpi.c b/plat/sun50iw1p1/scpi.c
new file mode 100644
index 0000000..e09ed90
--- /dev/null
+++ b/plat/sun50iw1p1/scpi.c
@@ -0,0 +1,140 @@
+/*
+ * 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 "sunxi_def.h"
+#include "mhu.h"
+#include "scpi.h"
+
+#define MHU_SECURE_SCP_TO_AP_PAYLOAD (MHU_SECURE_BASE+0x0080)
+#define MHU_SECURE_AP_TO_SCP_PAYLOAD (MHU_SECURE_BASE+0x0280)
+
+#define SIZE_SHIFT 20 /* Bit position for size value in MHU header */
+#define SIZE_MASK 0x1ff /* Mask to extract size value in MHU header*/
+
+
+void *scpi_secure_message_start(void)
+{
+ mhu_secure_message_start();
+
+ /* Return address of payload area. */
+ return (void *)MHU_SECURE_AP_TO_SCP_PAYLOAD;
+}
+
+void scpi_secure_message_send(unsigned command, size_t size)
+{
+ /* Make sure payload can be seen by SCP */
+ if (MHU_PAYLOAD_CACHED)
+ flush_dcache_range(MHU_SECURE_AP_TO_SCP_PAYLOAD, size);
+
+ mhu_secure_message_send(command | (size << SIZE_SHIFT));
+}
+
+unsigned scpi_secure_message_receive(void **message_out, size_t *size_out)
+{
+ uint32_t response = mhu_secure_message_wait();
+
+ /* Get size of payload */
+ size_t size = (response >> SIZE_SHIFT) & SIZE_MASK;
+
+ /* Clear size from response */
+ response &= ~(SIZE_MASK << SIZE_SHIFT);
+
+ /* Make sure we don't read stale data */
+ if (MHU_PAYLOAD_CACHED)
+ inv_dcache_range(MHU_SECURE_SCP_TO_AP_PAYLOAD, size);
+
+ if (size_out)
+ *size_out = size;
+
+ if (message_out)
+ *message_out = (void *)MHU_SECURE_SCP_TO_AP_PAYLOAD;
+
+ return response;
+}
+
+void scpi_secure_message_end(void)
+{
+ mhu_secure_message_end();
+}
+
+static void scpi_secure_send32(unsigned command, uint32_t message)
+{
+ *(__typeof__(message) *)scpi_secure_message_start() = message;
+ scpi_secure_message_send(command, sizeof(message));
+ scpi_secure_message_end();
+}
+
+int scpi_wait_ready(void)
+{
+ /* Get a message from the SCP */
+ scpi_secure_message_start();
+ size_t size;
+ unsigned command = scpi_secure_message_receive(NULL, &size);
+ scpi_secure_message_end();
+
+ /* We are expecting 'SCP Ready', produce correct error if it's not */
+ scpi_status_t response = SCP_OK;
+ if (command != SCPI_CMD_SCP_READY)
+ response = SCP_E_SUPPORT;
+ else if (size != 0)
+ response = SCP_E_SIZE;
+
+ /* Send our response back to SCP */
+ scpi_secure_send32(command, response);
+
+ return response == SCP_OK ? 0 : -1;
+}
+
+void scpi_set_css_power_state(unsigned mpidr, scpi_power_state_t cpu_state,
+ scpi_power_state_t cluster_state, scpi_power_state_t css_state)
+{
+ uint32_t state = mpidr & 0x0f; /* CPU ID */
+ state |= (mpidr & 0xf00) >> 4; /* Cluster ID */
+ state |= cpu_state << 8;
+ state |= cluster_state << 12;
+ state |= css_state << 16;
+ scpi_secure_send32(SCPI_CMD_SET_CSS_POWER_STATE, state);
+}
+
+uint32_t scpi_sys_power_state(scpi_system_state_t system_state)
+{
+ uint32_t *response;
+ size_t size;
+ uint8_t state = system_state & 0xff;
+
+ /* Send the command */
+ *(__typeof__(state) *)scpi_secure_message_start() = state;
+ scpi_secure_message_send(SCPI_CMD_SYS_POWER_STATE, sizeof(state));
+ scpi_secure_message_receive((void *)&response, &size);
+ scpi_secure_message_end();
+ return *response;
+}
diff --git a/plat/sun50iw1p1/scpi.h b/plat/sun50iw1p1/scpi.h
new file mode 100644
index 0000000..8a5ef65
--- /dev/null
+++ b/plat/sun50iw1p1/scpi.h
@@ -0,0 +1,82 @@
+/*
+ * 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 scpi_status_t;
+
+typedef enum {
+ SCPI_CMD_SCP_READY = 0x01,
+ SCPI_CMD_SET_CSS_POWER_STATE = 0x04,
+ SCPI_CMD_SYS_POWER_STATE = 0x08
+} scpi_command_t;
+
+typedef enum {
+ scpi_power_on = 0,
+ scpi_power_retention = 1,
+ scpi_power_off = 3,
+} scpi_power_state_t;
+
+typedef enum {
+ scpi_system_shutdown = 0,
+ scpi_system_reboot = 1,
+ scpi_system_reset = 2
+} scpi_system_state_t;
+
+extern int scpi_wait_ready(void);
+extern void scpi_set_css_power_state(unsigned mpidr, scpi_power_state_t cpu_state,
+ scpi_power_state_t cluster_state, scpi_power_state_t css_state);
+uint32_t scpi_sys_power_state(scpi_system_state_t system_state);
+
+#endif /* __SCPI_H__ */
diff --git a/plat/sun50iw1p1/sun50iw1p1.h b/plat/sun50iw1p1/sun50iw1p1.h
new file mode 100644
index 0000000..2013b38
--- /dev/null
+++ b/plat/sun50iw1p1/sun50iw1p1.h
@@ -0,0 +1,127 @@
+/*
+ * (C) Copyright 2007-2015
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Jerry Wang <wangflord@allwinnertech.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef __PLATFORM_H
+#define __PLATFORM_H
+
+#define SUNXI_SRAM_D_BASE (0x00010000L)
+/* base address of modules */
+#define SUNXI_DE_BASE (0x01000000L)
+#define SUNXI_CORESIGHT_DEBUG_BASE (0x01400000L)
+#define SUNXI_CPU_MBIST_BASE (0x01502000L)
+#define SUNXI_CPUX_CFG_BASE (0x01700000L)
+
+
+#define SUNXI_SYSCRL_BASE (0x01c00000L)
+
+#define SUNXI_DMA_BASE (0x01c02000L)
+#define SUNXI_NFC_BASE (0x01c03000L)
+#define SUNXI_TSC_BASE (0x01c06000L)
+
+#define SUNXI_TCON0_BASE (0x01c0c000L)
+#define SUNXI_TCON1_BASE (0x01c0d000L)
+#define SUNXI_VE_BASE (0x01c0e000L)
+
+#define SUNXI_SMHC0_BASE (0x01c0f000L)
+#define SUNXI_SMHC1_BASE (0x01c10000L)
+#define SUNXI_SMHC2_BASE (0x01c11000L)
+
+#define SUNXI_SID_BASE (0x01c14000L)
+#define SUNXI_SS_BASE (0x01c15000L)
+
+#define SUNXI_MSGBOX_BASE (0x01c17000L)
+#define SUNXI_SPINLOCK_BASE (0x01c18000L)
+
+#define SUNXI_USBOTG_BASE (0x01c19000L)
+#define SUNXI_EHCI0_BASE (0x01c1a000L)
+#define SUNXI_EHCI1_BASE (0x01c1b000L)
+
+#define SUNXI_SMC_BASE (0x01c1e000L)
+
+#define SUNXI_CCM_BASE (0x01c20000L)
+#define SUNXI_PIO_BASE (0x01c20800L)
+#define SUNXI_TIMER_BASE (0x01c20c00L)
+#define SUNXI_SPDIF_BASE (0x01c21000L)
+#define SUNXI_PWM03_BASE (0x01c21400L)
+
+#define SUNXI_KEYADC_BASE (0x01c21800L)
+#define SUNXI_DAUDIO0_BASE (0x01c22000L)
+#define SUNXI_DAUDIO1_BASE (0x01c24000L)
+#define SUNXI_DAUDIO2_BASE (0x01c28000L)
+
+#define SUNXI_AC_BASE (0x01c22c00L)
+#define SUNXI_SPC_BASE (0x01c23400L)
+#define SUNXI_THC_BASE (0x01c25000L)
+
+#define SUNXI_UART0_BASE (0x01c28000L)
+#define SUNXI_UART1_BASE (0x01c28400L)
+#define SUNXI_UART2_BASE (0x01c28800L)
+#define SUNXI_UART3_BASE (0x01c28c00L)
+#define SUNXI_UART4_BASE (0x01c29000L)
+
+#define SUNXI_TWI0_BASE (0x01c2ac00L)
+#define SUNXI_TWI1_BASE (0x01c2b000L)
+#define SUNXI_TWI2_BASE (0x01c2b400L)
+#define SUNXI_SCR_BASE (0x01c2c400L)
+
+#define SUNXI_EMAC_BASE (0x01c30000L)
+#define SUNXI_GPU_BASE (0x01c40000L)
+#define SUNXI_HSTMR_BASE (0x01c60000L)
+
+#define SUNXI_DRAMCOM_BASE (0x01c62000L)
+#define SUNXI_DRAMCTL0_BASE (0x01c63000L)
+#define SUNXI_DRAMPHY0_BASE (0x01c65000L)
+
+#define SUNXI_SPI0_BASE (0x01c68000L)
+#define SUNXI_SPI1_BASE (0x01c69000L)
+
+#define ARMA9_SCU_BASE (0x01c80000L)
+#define ARMA9_GIC_BASE (0x01c81000L)
+#define ARMA9_CPUIF_BASE (0x01c82000L)
+
+/* Base sunxi compatible GIC memory map */
+#define GICD_BASE ARMA9_GIC_BASE
+#define GICC_BASE ARMA9_CPUIF_BASE
+
+
+#define SUNXI_MIPI_DSI0_BASE (0x01ca0000L)
+#define SUNXI_MIPI_DSIPHY_BASE (0x01ca1000L)
+
+#define SUNXI_CSI0_BASE (0x01cb0000L)
+#define SUNXI_DE_INTERLACED_BASE (0x01e00000L)
+#define SUNXI_HDMI_BASE (0x01ee0000L)
+#define HDMI_BASE SUNXI_HDMI_BASE
+
+#define SUNXI_RTC_BASE (0x01f00000L)
+#define SUNXI_RTMR01_BASE (0x01f00800L)
+#define SUNXI_RINTC_BASE (0x01f00C00L)
+#define SUNXI_RWDOG_BASE (0x01f01000L)
+#define SUNXI_RPRCM_BASE (0x01f01400L)
+#define SUNXI_RTWD_BASE (0x01f01800L)
+#define SUNXI_RCPUCFG_BASE (0x01f01C00L)
+#define SUNXI_RCIR_BASE (0x01f02000L)
+#define SUNXI_RTWI_BASE (0x01f02400L)
+#define SUNXI_RUART_BASE (0x01f02800L)
+#define SUNXI_RPIO_BASE (0x01f02c00L)
+#define SUNXI_RRSB_BASE (0x01f03400L)
+#define SUNXI_RPWM_BASE (0x01f03800L)
+
+#endif
diff --git a/plat/sun50iw1p1/sunxi_cpu_ops.c b/plat/sun50iw1p1/sunxi_cpu_ops.c
new file mode 100644
index 0000000..04978b1
--- /dev/null
+++ b/plat/sun50iw1p1/sunxi_cpu_ops.c
@@ -0,0 +1,245 @@
+/*
+ * 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 <arch_helpers.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <mmio.h>
+#include <debug.h>
+#include <bakery_lock.h>
+#include "sunxi_def.h"
+#include "sunxi_private.h"
+
+#define SUN50I_PRCM_PBASE (0x01F01400)
+#define SUN50I_CPUCFG_PBASE (0x01700000)
+#define SUN50I_RCPUCFG_PBASE (0x01F01C00)
+
+#define SUNXI_CPU_PWR_CLAMP(cluster, cpu) (0x140 + (cluster*4 + cpu)*0x04)
+#define SUNXI_CLUSTER_PWROFF_GATING(cluster) (0x100 + (cluster)*0x04)
+#define SUNXI_CLUSTER_PWRON_RESET(cluster) (0x30 + (cluster)*0x04)
+
+#define SUNXI_DBG_REG0 (0x20)
+#define SUNXI_CLUSTER_CPU_STATUS(cluster) (0x30 + (cluster)*0x4)
+#define SUNXI_CPU_RST_CTRL(cluster) (0x80 + (cluster)*0x4)
+#define SUNXI_CLUSTER_CTRL0(cluster) (0x00 + (cluster)*0x10)
+
+#define SUNXI_CPU_RVBA_L(cpu) (0xA0 + (cpu)*0x8)
+#define SUNXI_CPU_RVBA_H(cpu) (0xA4 + (cpu)*0x8)
+
+#define readl(x) mmio_read_32((x))
+#define writel(v, a) mmio_write_32((a), (v))
+ typedef unsigned int bool;
+
+ static unsigned int sun50i_cpucfg_base = SUN50I_CPUCFG_PBASE;
+ static unsigned int sun50i_prcm_base = SUN50I_PRCM_PBASE;
+ static unsigned int sun50i_r_cpucfg_base = SUN50I_RCPUCFG_PBASE;
+ extern bakery_lock_t plat_console_lock;
+ void udelay(unsigned int delay)
+ {
+ unsigned int i, j;
+
+ for (i=0; i<1000*delay; i++)
+ {
+ j+=i;
+ }
+ }
+
+ void sun50i_set_secondary_entry(unsigned long entry, unsigned int cpu)
+ {
+ mmio_write_32(sun50i_cpucfg_base + SUNXI_CPU_RVBA_L(cpu) ,entry);
+ mmio_write_32(sun50i_cpucfg_base + SUNXI_CPU_RVBA_H(cpu), 0);
+ }
+
+ void sun50i_set_AA32nAA64(unsigned int cluster, unsigned int cpu, bool is_aa64)
+ {
+ volatile unsigned int value;
+
+ value = readl(sun50i_cpucfg_base + SUNXI_CLUSTER_CTRL0(cluster));
+ value &= ~(1<<(cpu + 24));
+ value |= (is_aa64 <<(cpu + 24));
+ writel(value, sun50i_cpucfg_base + SUNXI_CLUSTER_CTRL0(cluster));
+ value = readl(sun50i_cpucfg_base + SUNXI_CLUSTER_CTRL0(cluster));
+ }
+
+ int sun50i_power_switch_set(unsigned int cluster, unsigned int cpu, bool enable)
+ {
+ if (enable) {
+ if (0x00 == readl(sun50i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu))) {
+ NOTICE("%s: power switch enable already\n", __func__);
+ return 0;
+ }
+
+ /* de-active cpu power clamp */
+ writel(0xFE, sun50i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu));
+ udelay(20);
+
+ writel(0xF8, sun50i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu));
+ udelay(10);
+
+ writel(0xE0, sun50i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu));
+ udelay(10);
+
+ writel(0x80, sun50i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu));
+ udelay(10);
+
+ writel(0x00, sun50i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu));
+ udelay(20);
+
+ while (0x00 != readl(sun50i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu)));
+ } else {
+ if (0xFF == readl(sun50i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu))) {
+ NOTICE("%s: power switch disable already\n", __func__);
+ return 0;
+ }
+
+ writel(0xFF, sun50i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu));
+ udelay(30);
+
+ while (0xFF != readl(sun50i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu)));
+ }
+ return 0;
+ }
+
+ void sun50i_cpu_power_up(unsigned int cluster, unsigned int cpu)
+ {
+ unsigned int value;
+
+ /* Assert nCPUPORESET LOW */
+ value = readl(sun50i_cpucfg_base + SUNXI_CPU_RST_CTRL(cluster));
+ value &= (~(1<<cpu));
+ writel(value, sun50i_cpucfg_base + SUNXI_CPU_RST_CTRL(cluster));
+ udelay(10);
+
+ /* Assert cpu power-on reset */
+ value = readl(sun50i_r_cpucfg_base + SUNXI_CLUSTER_PWRON_RESET(cluster));
+ value &= (~(1<<cpu));
+ writel(value, sun50i_r_cpucfg_base + SUNXI_CLUSTER_PWRON_RESET(cluster));
+ udelay(10);
+
+ /* set AA32nAA64 to AA64 */
+ sun50i_set_AA32nAA64(cluster, cpu, 1);
+
+ /* Apply power to the PDCPU power domain. */
+ sun50i_power_switch_set(cluster, cpu, 1);
+
+ /* Release the core output clamps */
+ value = readl(sun50i_prcm_base + SUNXI_CLUSTER_PWROFF_GATING(cluster));
+ value &= (~(0x1<<cpu));
+ writel(value, sun50i_prcm_base + SUNXI_CLUSTER_PWROFF_GATING(cluster));
+ udelay(20);
+
+ /* Deassert cpu power-on reset */
+ value = readl(sun50i_r_cpucfg_base + SUNXI_CLUSTER_PWRON_RESET(cluster));
+ value |= ((1<<cpu));
+ writel(value, sun50i_r_cpucfg_base + SUNXI_CLUSTER_PWRON_RESET(cluster));
+ udelay(10);
+
+ /* Deassert core reset */
+ value = readl(sun50i_cpucfg_base + SUNXI_CPU_RST_CTRL(cluster));
+ value |= (1<<cpu);
+ writel(value, sun50i_cpucfg_base + SUNXI_CPU_RST_CTRL(cluster));
+ udelay(10);
+
+ /* Assert DBGPWRDUP HIGH */
+ value = readl(sun50i_cpucfg_base + SUNXI_DBG_REG0);
+ value |= (1<<cpu);
+ writel(value, sun50i_cpucfg_base + SUNXI_DBG_REG0);
+ udelay(10);
+ bakery_lock_get(&plat_console_lock);
+ INFO("sun50i power-up cluster-%d cpu-%d ok\n", cluster, cpu);
+ bakery_lock_release(&plat_console_lock);
+ }
+
+void sun50i_cpu_power_down(unsigned int cluster, unsigned int cpu)
+{
+ unsigned int value;
+
+ /* step7: Deassert DBGPWRDUP LOW */
+ value = readl(sun50i_cpucfg_base + SUNXI_DBG_REG0);
+ value &= (~(1<<cpu));
+ writel(value, sun50i_cpucfg_base + SUNXI_DBG_REG0);
+ udelay(10);
+
+ /* step8: Activate the core output clamps */
+ value = readl(sun50i_prcm_base + SUNXI_CLUSTER_PWROFF_GATING(cluster));
+ value |= (1 << cpu);
+ writel(value, sun50i_prcm_base + SUNXI_CLUSTER_PWROFF_GATING(cluster));
+ udelay(20);
+
+ /* step9: Assert nCPUPORESET LOW */
+ value = readl(sun50i_cpucfg_base + SUNXI_CPU_RST_CTRL(cluster));
+ value &= (~(1<<cpu));
+ writel(value, sun50i_cpucfg_base + SUNXI_CPU_RST_CTRL(cluster));
+ udelay(10);
+
+ /* step10: Remove power from th e PDCPU power domain */
+ sun50i_power_switch_set(cluster, cpu, 0);
+ bakery_lock_get(&plat_console_lock);
+ INFO("sun50i power-down cluster-%d cpu-%d ok.\n", cluster, cpu);
+ bakery_lock_release(&plat_console_lock);
+
+}
+
+void sunxi_cpu_die(unsigned int cpu)
+{
+ #if 0
+ unsigned long sctlr, cpuectlr;
+
+ /* step1: Disable the data cache */
+ __asm("mrs %0, SCTLR_EL1\n" : "=r" (sctlr));
+ sctlr &= ~(0x1<<2);
+ __asm volatile("msr SCTLR_EL1, %0\n" : : "r" (sctlr));
+
+ /* step2: Clean and invalidate all data from the L1 Data cache */
+ //flush_cache_all();
+ dcsw_op_louis(DCCSW);
+
+ /* step3: Disable data coherency with other cores in the cluster */
+ __asm("mrs %0, S3_1_c15_c2_1\n" : "=r" (cpuectlr));
+ cpuectlr &= ~(0x1<<6);
+ __asm volatile("msr S3_1_c15_c2_1, %0\n" : : "r" (cpuectlr));
+
+ /*
+ * step4: Execute an ISB instruction to ensure that
+ * all of the register changes from the previous steps
+ * have been committed
+ */
+ isb();
+
+ /*
+ * step5: Execute a DSB SY instruction to ensure that all cache,
+ * TLB and branch predictor maintenance operations issued
+ * by any core in the cluster device before the SMPEN bit
+ * was cleared have completed
+ */
+ dsb();
+ #endif
+}
+
diff --git a/plat/sun50iw1p1/sunxi_cpu_ops.h b/plat/sun50iw1p1/sunxi_cpu_ops.h
new file mode 100644
index 0000000..ce49903
--- /dev/null
+++ b/plat/sun50iw1p1/sunxi_cpu_ops.h
@@ -0,0 +1,39 @@
+/*
+ * 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 __SUNXI_CPU_OPS_H__
+#define __SUNXI_CPU_OPS_H__
+
+void sun50i_set_secondary_entry(unsigned long entry, unsigned int cpu);
+void sun50i_cpu_power_up(unsigned int cluster, unsigned int cpu);
+void sun50i_cpu_power_down(unsigned int cluster, unsigned int cpu);
+void sunxi_cpu_die(unsigned int cpu);
+
+#endif
diff --git a/plat/sun50iw1p1/sunxi_def.h b/plat/sun50iw1p1/sunxi_def.h
new file mode 100644
index 0000000..f4db727
--- /dev/null
+++ b/plat/sun50iw1p1/sunxi_def.h
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+ /*-------------------------------------------------------------------------------
+| | | | |
+| ATF | (atf&scp)share | Trusted OS | Linux |
+| | | | |
+ ----------------------------------------------------------------------------------
+| | | | |
+| 1M | 1M | 14M | other |
+| | | | |
+----------------------------------------------------------------------------------*/
+
+#ifndef __SUNXI_DEF_H__
+#define __SUNXI_DEF_H__
+
+#include "sun50iw1p1.h"
+/* Firmware Image Package */
+#define FIP_IMAGE_NAME "fip.bin"
+#define SUNXI_PRIMARY_CPU 0x0
+
+/* Memory location options for Shared data and TSP in sunxi */
+#define SUNXI_IN_TRUSTED_SRAM 0
+#define SUNXI_IN_TRUSTED_DRAM 1
+
+/*******************************************************************************
+ * sunxi memory map related constants
+ ******************************************************************************/
+
+#define SUNXI_MAX_DRAM_SIZE (2ull<<30) /*2G*/
+
+//monitor area(atf+scp)
+#define SUNXI_TRUSTED_MONITOR_BASE 0x40000000
+#define SUNXI_TRUSTED_MONITOR_SIZE (2<<20) //2MB
+
+//sec os area
+#define SUNXI_TRUSTED_DRAM_BASE 0x40200000
+#define SUNXI_TRUSTED_DRAM_SIZE (14<<20) //14 MB
+
+//monitor area + sec os area
+#define SUNXI_TRUSTED_RAM_SIZE 0x01000000 //total 16M
+
+//atf code limit
+#define SUNXI_TRUSTED_MONITOR_LIMIT (SUNXI_TRUSTED_MONITOR_BASE + (1<<20)) //1M
+
+
+/* 4KB shared memory */
+#define SUNXI_SHARED_RAM_SIZE 0x1000
+
+/* Shared memory at the base of Trusted DRAM */
+#define SUNXI_SHARED_RAM_BASE SUNXI_TRUSTED_DRAM_BASE
+
+
+#define DRAM1_BASE 0x40000000ull
+#define DRAM1_SIZE 0x40000000ull //1G
+#define DRAM1_END (DRAM1_BASE + DRAM1_SIZE - 1)
+#define DRAM1_SEC_SIZE 0x01000000ull
+
+#define DRAM_BASE DRAM1_BASE
+#define DRAM_SIZE DRAM1_SIZE
+
+#define MEMRES_BASE SUNXI_TRUSTED_MONITOR_LIMIT //0x40100000
+#define MEMRES_SIZE 0x100000 //1M
+
+/* Load address of BL33 in the sunxi */
+#define NS_IMAGE_OFFSET (DRAM1_BASE + 0xA000000) /* DRAM + 128MB */
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define SUNXI_BL31_PLAT_PARAM_VAL 0x12345678 //0x0f1e2d3c4b5a6978ULL
+
+
+/*******************************************************************************
+ * PL011 related constants
+ ******************************************************************************/
+#define UART0_BAUDRATE 115200
+
+#define UART0_CLK_IN_HZ 24000000
+
+/*******************************************************************************
+ * Shared Data
+ ******************************************************************************/
+
+/* Entrypoint mailboxes */
+#define TRUSTED_MAILBOXES_BASE SUNXI_SHARED_RAM_BASE
+#define TRUSTED_MAILBOXES_SIZE 0x200
+#define TRUSTED_MAILBOX_SHIFT 4
+
+
+/* Base address where parameters to BL31 are stored */
+#define PARAMS_BASE (TRUSTED_MAILBOXES_BASE + TRUSTED_MAILBOXES_SIZE)
+
+#define MHU_SECURE_BASE 0x10000
+#define MHU_SECURE_SIZE 0x1000
+
+#define MHU_PAYLOAD_CACHED 0
+
+#endif /* __SUNXI_DEF_H__ */
diff --git a/plat/sun50iw1p1/sunxi_private.h b/plat/sun50iw1p1/sunxi_private.h
new file mode 100644
index 0000000..e2c548f
--- /dev/null
+++ b/plat/sun50iw1p1/sunxi_private.h
@@ -0,0 +1,107 @@
+/*
+ * 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 __SUNXI_PRIVATE_H__
+#define __SUNXI_PRIVATE_H__
+
+#include <bl_common.h>
+#include <platform_def.h>
+
+
+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);
+
+
+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 sunxi_configure_mmu_el1(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long,
+ unsigned long,
+ unsigned long,
+ unsigned long);
+void sunxi_configure_mmu_el3(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long,
+ unsigned long,
+ unsigned long,
+ unsigned long);
+int sunxi_config_setup(void);
+
+void sunxi_cci_init(void);
+void sunxi_cci_enable(void);
+
+void sunxi_gic_init(void);
+
+/* Declarations for sunxi_topology.c */
+int sunxi_setup_topology(void);
+
+/* Declarations for sunxi_io_storage.c */
+void sunxi_io_setup(void);
+
+/* Declarations for sunxi_security.c */
+void sunxi_security_setup(void);
+
+/* Gets the SPR for BL32 entry */
+uint32_t sunxi_get_spsr_for_bl32_entry(void);
+
+/* Gets the SPSR for BL33 entry */
+uint32_t sunxi_get_spsr_for_bl33_entry(void);
+
+
+#endif /* __FVP_PRIVATE_H__ */
diff --git a/plat/sun50iw1p1/sunxi_security.c b/plat/sun50iw1p1/sunxi_security.c
new file mode 100644
index 0000000..c0ccac0
--- /dev/null
+++ b/plat/sun50iw1p1/sunxi_security.c
@@ -0,0 +1,110 @@
+/*
+ * 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 <plat_config.h>
+#include <tzc400.h>
+#include <mmio.h>
+#include "sunxi_def.h"
+#include "sunxi_private.h"
+
+#define SPC_BASE (0x1c23400ull)
+
+#define SPC_DECPORT0_STA_REG (SPC_BASE+0x4)
+#define SPC_DECPORT0_SET_REG (SPC_BASE+0x8)
+#define SPC_DECPORT0_CLR_REG (SPC_BASE+0xc)
+
+#define SPC_DECPORT1_STA_REG (SPC_BASE+0x10)
+#define SPC_DECPORT1_SET_REG (SPC_BASE+0x14)
+#define SPC_DECPORT1_CLR_REG (SPC_BASE+0x18)
+
+#define SPC_DECPORT2_STA_REG (SPC_BASE+0x1c)
+#define SPC_DECPORT2_SET_REG (SPC_BASE+0x20)
+#define SPC_DECPORT2_CLR_REG (SPC_BASE+0x24)
+
+#define SPC_DECPORT3_STA_REG (SPC_BASE+0x28)
+#define SPC_DECPORT3_SET_REG (SPC_BASE+0x2c)
+#define SPC_DECPORT3_CLR_REG (SPC_BASE+0x30)
+
+#define SPC_DECPORT4_STA_REG (SPC_BASE+0x34)
+#define SPC_DECPORT4_SET_REG (SPC_BASE+0x38)
+#define SPC_DECPORT4_CLR_REG (SPC_BASE+0x3c)
+
+#define SPC_DECPORT5_STA_REG (SPC_BASE+0x40)
+#define SPC_DECPORT5_SET_REG (SPC_BASE+0x44)
+#define SPC_DECPORT5_CLR_REG (SPC_BASE+0x48)
+
+
+
+
+
+
+
+
+/* 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 sunxi_security_setup(void)
+{
+ /*
+ *
+ * If the platform had additional peripheral specific security
+ * configurations, those would be configured here.
+ */
+
+ //if (!(get_plat_config()->flags & CONFIG_HAS_TZC))
+ // return;
+
+ INFO("Configuring SPC Controller\n");
+ //set all peripherals to non-sec
+ mmio_write_32(SPC_DECPORT0_SET_REG,0xff);
+ mmio_write_32(SPC_DECPORT1_SET_REG,0xff);
+ mmio_write_32(SPC_DECPORT2_SET_REG,0xff);
+ mmio_write_32(SPC_DECPORT3_SET_REG,0xff);
+ mmio_write_32(SPC_DECPORT4_SET_REG,0xff);
+ mmio_write_32(SPC_DECPORT5_SET_REG,0xff);
+
+ //set ccmu security switch: set mbus_sec bus_sec pll_sec to non-sec
+ mmio_write_32(0x01c20000+0x2f0, 0x7);
+
+ //set R_PRCM security switch: set power_sec pll_sec cpus_clk to non-sec
+ mmio_write_32(0x01f01400+0x1d0, 0x7);
+
+ //set dma security switch: set DMA channel0-7 to non-sec
+ mmio_write_32(0x01c02000+0x20, 0xff);
+
+}
diff --git a/plat/sun50iw1p1/tsp/tsp-wine.mk b/plat/sun50iw1p1/tsp/tsp-wine.mk
new file mode 100644
index 0000000..3cbc6ec
--- /dev/null
+++ b/plat/sun50iw1p1/tsp/tsp-wine.mk
@@ -0,0 +1,38 @@
+#
+# 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.
+#
+
+# TSP source files specific to FVP platform
+BL32_SOURCES += drivers/arm/gic/arm_gic.c \
+ drivers/arm/gic/gic_v2.c \
+ plat/common/aarch64/platform_mp_stack.S \
+ plat/common/plat_gic.c \
+ plat/sun50iw1p1/aarch64/sunxi_common.c \
+ plat/sun50iw1p1/aarch64/sunxi_helpers.S \
+ plat/sun50iw1p1/tsp/tsp_sunxi_setup.c
diff --git a/plat/sun50iw1p1/tsp/tsp_sunxi_setup.c b/plat/sun50iw1p1/tsp/tsp_sunxi_setup.c
new file mode 100644
index 0000000..82c74af
--- /dev/null
+++ b/plat/sun50iw1p1/tsp/tsp_sunxi_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_tsp.h>
+#include "../sunxi_def.h"
+#include "../sunxi_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 tsp_early_platform_setup(void)
+{
+ /*
+ * Initialize a different console than already in use to display
+ * messages from TSP
+ */
+ console_init(SUNXI_UART0_BASE, UART0_CLK_IN_HZ, UART0_BAUDRATE);
+
+ /* Initialize the platform config for future decision making */
+ sunxi_config_setup();
+}
+
+/*******************************************************************************
+ * Perform platform specific setup placeholder
+ ******************************************************************************/
+void tsp_platform_setup(void)
+{
+ sunxi_gic_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the MMU
+ ******************************************************************************/
+void tsp_plat_arch_setup(void)
+{
+ sunxi_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);
+}