Merge pull request #708 from sandrine-bailleux-arm/sb/forward-decs
Add some missing forward declarations in plat_arm.h
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index f9f0715..4d936ad 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -273,6 +273,7 @@
DEFINE_SYSREG_RW_FUNCS(vpidr_el2)
DEFINE_SYSREG_RW_FUNCS(vmpidr_el2)
+DEFINE_SYSREG_RW_FUNCS(cntp_ctl_el0)
DEFINE_SYSREG_READ_FUNC(isr_el1)
diff --git a/lib/psci/psci_setup.c b/lib/psci/psci_setup.c
index 20d0635..aa2ed51 100644
--- a/lib/psci/psci_setup.c
+++ b/lib/psci/psci_setup.c
@@ -238,6 +238,13 @@
plat_setup_psci_ops(mailbox_ep, &psci_plat_pm_ops);
assert(psci_plat_pm_ops);
+ /*
+ * Flush `psci_plat_pm_ops` as it will be accessed by secondary CPUs
+ * during warm boot before data cache is enabled.
+ */
+ flush_dcache_range((uintptr_t)&psci_plat_pm_ops,
+ sizeof(psci_plat_pm_ops));
+
/* Initialize the psci capability */
psci_caps = PSCI_GENERIC_CAP;
diff --git a/plat/mediatek/mt8173/drivers/uart/8250_console.S b/plat/mediatek/common/drivers/uart/8250_console.S
similarity index 100%
rename from plat/mediatek/mt8173/drivers/uart/8250_console.S
rename to plat/mediatek/common/drivers/uart/8250_console.S
diff --git a/plat/mediatek/mt8173/drivers/uart/uart8250.h b/plat/mediatek/common/drivers/uart/uart8250.h
similarity index 100%
rename from plat/mediatek/mt8173/drivers/uart/uart8250.h
rename to plat/mediatek/common/drivers/uart/uart8250.h
diff --git a/plat/mediatek/mt6795/aarch64/plat_helpers.S b/plat/mediatek/mt6795/aarch64/plat_helpers.S
new file mode 100644
index 0000000..eb0611a
--- /dev/null
+++ b/plat/mediatek/mt6795/aarch64/plat_helpers.S
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_report_exception
+ .globl platform_is_primary_cpu
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl platform_mem_init
+
+
+ .macro crash_ram_log
+ /*
+ * Check teearg->atf_log_buf_size.
+ * Exit if atf_log_buf_size equals 0
+ */
+ adr x2, ptr_atf_crash_flag
+ ldr x2, [x2]
+ /* exit if ptr_atf_crash_flag equals NULL */
+ cbz x2, exit_putc
+
+ /*
+ * set atf crash magic number
+ */
+1:
+ adr x2, ptr_atf_crash_flag
+ ldr x2, [x2]
+ mov_imm x1, 0xdead1abf
+ /* p_atf_log_ctrl->atf_crash_flag = 0xdead1abf */
+ str w1, [x2]
+ /* can't use w3 return addr, w4, start of buffer addr */
+ ldr w2, [x2]
+ cmp w2, w1
+ b.ne 1b
+
+ /*
+ * get cpu id
+ */
+ mrs x1, mpidr_el1
+ /* refer to platform_get_core_pos */
+ and x2, x1, #MPIDR_CPU_MASK
+ and x1, x1, #MPIDR_CLUSTER_MASK
+ /* x1 = cpu id (cpu id = aff0 + aff1*4 ) */
+ add x1, x2, x1, LSR #6
+
+ adr x2, ptr_atf_except_write_pos_per_cpu
+ ldr x2, [x2]
+ /*
+ * plus (cpu_id * 8)-->
+ * &p_atf_log_ctrl->atf_except_write_pos_per_cpu[cpu_id]
+ * x2 = &p_atf_log_ctrl->atf_except_write_pos_per_cpu[cpu_id];
+ */
+ add x2, x2, x1, LSL # 3
+ /* log write */
+ /* w1 = p_atf_log_ctrl->atf_except_write_pos_per_cpu[cpu_id] */
+ ldr x1, [x2]
+ /* *x1 = w0-->
+ * *(p_atf_log_ctrl->atf_except_write_pos_per_cpu[cpu_id]) = c)
+ */
+ strb w0, [x1]
+ /* w1++ */
+ add x1, x1, #1
+ /* p_atf_log_ctrl->atf_except_write_pos_per_cpu[cpu_id] = w1 */
+ str x1, [x2]
+exit_putc:
+ .endm
+
+ /* -----------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * -----------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ /* Do not do cold boot for secondary CPU */
+cb_panic:
+ b cb_panic
+endfunc plat_secondary_cold_boot_setup
+
+func platform_is_primary_cpu
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, #PLAT_PRIMARY_CPU
+ cset x0, eq
+ ret
+endfunc platform_is_primary_cpu
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0, x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+ mov_imm x0, UART0_BASE
+ mov_imm x1, UART_CLOCK
+ mov_imm x2, UART_BAUDRATE
+ b console_init
+ ret
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(void)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ mov_imm x1, UART0_BASE
+ b console_core_putc
+ ret
+endfunc plat_crash_console_putc
+
+ /* --------------------------------------------------------
+ * void platform_mem_init (void);
+ *
+ * Any memory init, relocation to be done before the
+ * platform boots. Called very early in the boot process.
+ * --------------------------------------------------------
+ */
+func platform_mem_init
+ ret
+endfunc platform_mem_init
+
diff --git a/plat/mediatek/mt6795/bl31.ld.S b/plat/mediatek/mt6795/bl31.ld.S
new file mode 100644
index 0000000..44510a7
--- /dev/null
+++ b/plat/mediatek/mt6795/bl31.ld.S
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <platform_def.h>
+
+OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
+OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
+ENTRY(bl31_entrypoint)
+
+
+MEMORY {
+ RAM (rwx): ORIGIN = BL31_BASE, LENGTH = BL31_TZRAM_SIZE
+ RAM2 (rwx): ORIGIN = TZRAM2_BASE, LENGTH = TZRAM2_SIZE
+}
+
+
+SECTIONS
+{
+ . = BL31_BASE;
+
+ ASSERT(. == ALIGN(2048),
+ "vector base is not aligned on a 2K boundary.")
+
+ __RO_START__ = .;
+ vector . : {
+ *(.vectors)
+ } >RAM
+
+ ASSERT(. == ALIGN(4096),
+ "BL31_BASE address is not aligned on a page boundary.")
+
+ ro . : {
+ *bl31_entrypoint.o(.text*)
+ *(.text*)
+ *(.rodata*)
+
+ /* Ensure 8-byte alignment for descriptors and ensure inclusion */
+ . = ALIGN(8);
+ __RT_SVC_DESCS_START__ = .;
+ KEEP(*(rt_svc_descs))
+ __RT_SVC_DESCS_END__ = .;
+
+ /*
+ * Ensure 8-byte alignment for cpu_ops so that its fields are also
+ * aligned. Also ensure cpu_ops inclusion.
+ */
+ . = ALIGN(8);
+ __CPU_OPS_START__ = .;
+ KEEP(*(cpu_ops))
+ __CPU_OPS_END__ = .;
+
+ __RO_END_UNALIGNED__ = .;
+ /*
+ * Memory page(s) mapped to this section will be marked as read-only,
+ * executable. No RW data from the next section must creep in.
+ * Ensure the rest of the current memory page is unused.
+ */
+ . = NEXT(4096);
+ __RO_END__ = .;
+ } >RAM
+
+ ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__,
+ "cpu_ops not defined for this platform.")
+
+ /*
+ * Define a linker symbol to mark start of the RW memory area for this
+ * image.
+ */
+ __RW_START__ = . ;
+
+ .data . : {
+ __DATA_START__ = .;
+ *(.data*)
+ __DATA_END__ = .;
+ } >RAM
+
+#ifdef BL31_PROGBITS_LIMIT
+ ASSERT(. <= BL31_PROGBITS_LIMIT, "BL3-1 progbits has exceeded its limit.")
+#endif
+
+ stacks (NOLOAD) : {
+ __STACKS_START__ = .;
+ *(tzfw_normal_stacks)
+ __STACKS_END__ = .;
+ } >RAM
+
+ /*
+ * The .bss section gets initialised to 0 at runtime.
+ * Its base address must be 16-byte aligned.
+ */
+ .bss (NOLOAD) : ALIGN(16) {
+ __BSS_START__ = .;
+ *(.bss*)
+ *(COMMON)
+#if !USE_COHERENT_MEM
+ /*
+ * Bakery locks are stored in normal .bss memory
+ *
+ * Each lock's data is spread across multiple cache lines, one per CPU,
+ * but multiple locks can share the same cache line.
+ * The compiler will allocate enough memory for one CPU's bakery locks,
+ * the remaining cache lines are allocated by the linker script
+ */
+ . = ALIGN(CACHE_WRITEBACK_GRANULE);
+ __BAKERY_LOCK_START__ = .;
+ *(bakery_lock)
+ . = ALIGN(CACHE_WRITEBACK_GRANULE);
+ __PERCPU_BAKERY_LOCK_SIZE__ = ABSOLUTE(. - __BAKERY_LOCK_START__);
+ . = . + (__PERCPU_BAKERY_LOCK_SIZE__ * (PLATFORM_CORE_COUNT - 1));
+ __BAKERY_LOCK_END__ = .;
+#ifdef PLAT_PERCPU_BAKERY_LOCK_SIZE
+ ASSERT(__PERCPU_BAKERY_LOCK_SIZE__ == PLAT_PERCPU_BAKERY_LOCK_SIZE,
+ "PLAT_PERCPU_BAKERY_LOCK_SIZE does not match bakery lock requirements");
+#endif
+#endif
+ __BSS_END__ = .;
+ __RW_END__ = .;
+ } >RAM
+
+ ASSERT(. <= BL31_LIMIT, "BL3-1 image has exceeded its limit.")
+
+ /*
+ * The xlat_table section is for full, aligned page tables (4K).
+ * Removing them from .bss avoids forcing 4K alignment on
+ * the .bss section and eliminates the unecessary zero init
+ */
+ xlat_table (NOLOAD) : {
+ *(xlat_table)
+ } >RAM2
+
+#if USE_COHERENT_MEM
+ /*
+ * The base address of the coherent memory section must be page-aligned (4K)
+ * to guarantee that the coherent data are stored on their own pages and
+ * are not mixed with normal data. This is required to set up the correct
+ * memory attributes for the coherent data page tables.
+ */
+ coherent_ram (NOLOAD) : ALIGN(4096) {
+ __COHERENT_RAM_START__ = .;
+ /*
+ * Bakery locks are stored in coherent memory
+ *
+ * Each lock's data is contiguous and fully allocated by the compiler
+ */
+ *(bakery_lock)
+ *(tzfw_coherent_mem)
+ __COHERENT_RAM_END_UNALIGNED__ = .;
+ /*
+ * Memory page(s) mapped to this section will be marked
+ * as device memory. No other unexpected data must creep in.
+ * Ensure the rest of the current memory page is unused.
+ */
+ . = NEXT(4096);
+ __COHERENT_RAM_END__ = .;
+ } >RAM2
+#endif
+
+ /*
+ * Define a linker symbol to mark end of the RW memory area for this
+ * image.
+ */
+ __BL31_END__ = .;
+
+ __BSS_SIZE__ = SIZEOF(.bss);
+#if USE_COHERENT_MEM
+ __COHERENT_RAM_UNALIGNED_SIZE__ =
+ __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__;
+#endif
+
+ ASSERT(. <= TZRAM2_LIMIT, "TZRAM2 image has exceeded its limit.")
+}
diff --git a/plat/mediatek/mt6795/bl31_plat_setup.c b/plat/mediatek/mt6795/bl31_plat_setup.c
new file mode 100644
index 0000000..3a8612d
--- /dev/null
+++ b/plat/mediatek/mt6795/bl31_plat_setup.c
@@ -0,0 +1,492 @@
+/*
+ * Copyright (c) 2016, 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 <arm_gic.h>
+#include <assert.h>
+#include <arch_helpers.h>
+#include <bl_common.h>
+#include <cci.h>
+#include <console.h>
+#include <context_mgmt.h>
+#include <debug.h>
+#include <generic_delay_timer.h>
+#include <mcucfg.h>
+#include <mmio.h>
+#include <mtk_sip_svc.h>
+#include <mtk_plat_common.h>
+#include <mt_cpuxgpt.h>
+#include <platform.h>
+#include <plat_private.h>
+#include <string.h>
+#include <xlat_tables.h>
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted SRAM
+ ******************************************************************************/
+unsigned long __RO_START__;
+unsigned long __RO_END__;
+
+unsigned long __COHERENT_RAM_START__;
+unsigned long __COHERENT_RAM_END__;
+
+/*
+ * The next 2 constants identify the extents of the code & RO data region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned. It is the responsibility of the linker script to ensure that
+ * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
+ */
+#define BL31_RO_BASE (unsigned long)(&__RO_START__)
+#define BL31_RO_LIMIT (unsigned long)(&__RO_END__)
+
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned. It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols
+ * refer to page-aligned addresses.
+ */
+#define BL31_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL31_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+
+/*
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL3-1 from BL2.
+ */
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+static const int cci_map[] = {
+ PLAT_MT_CCI_CLUSTER0_SL_IFACE_IX,
+ PLAT_MT_CCI_CLUSTER1_SL_IFACE_IX
+};
+
+static uint32_t cci_map_length = ARRAY_SIZE(cci_map);
+
+/* Table of regions to map using the MMU. */
+static const mmap_region_t plat_mmap[] = {
+ /* for TF text, RO, RW */
+ MAP_REGION_FLAT(MTK_DEV_RNG0_BASE, MTK_DEV_RNG0_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MTK_DEV_RNG1_BASE, MTK_DEV_RNG1_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(RAM_CONSOLE_BASE & ~(PAGE_SIZE_MASK), RAM_CONSOLE_SIZE,
+ MT_DEVICE | MT_RW | MT_NS),
+ { 0 }
+
+};
+
+/*******************************************************************************
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ ******************************************************************************/
+#define DEFINE_CONFIGURE_MMU_EL(_el) \
+ void plat_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(plat_mmap); \
+ init_xlat_tables(); \
+ \
+ enable_mmu_el ## _el(0); \
+ }
+
+/* Define EL3 variants of the function initialising the MMU */
+DEFINE_CONFIGURE_MMU_EL(3)
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return SYS_COUNTER_FREQ_IN_TICKS;
+}
+
+void plat_cci_init(void)
+{
+ /* Initialize CCI driver */
+ cci_init(PLAT_MT_CCI_BASE, cci_map, cci_map_length);
+}
+
+void plat_cci_enable(void)
+{
+ /*
+ * Enable CCI coherency for this cluster.
+ * No need for locks as no other cpu is active at the moment.
+ */
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+}
+
+void plat_cci_disable(void)
+{
+ cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+}
+
+
+static void platform_setup_cpu(void)
+{
+ /* setup big cores */
+ mmio_write_32((uintptr_t)&mt6795_mcucfg->mp1_config_res,
+ MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK |
+ MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK |
+ MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK |
+ MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK |
+ MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK);
+ mmio_setbits_32((uintptr_t)&mt6795_mcucfg->mp1_miscdbg, MP1_AINACTS);
+ mmio_setbits_32((uintptr_t)&mt6795_mcucfg->mp1_clkenm_div,
+ MP1_SW_CG_GEN);
+ mmio_clrbits_32((uintptr_t)&mt6795_mcucfg->mp1_rst_ctl,
+ MP1_L2RSTDISABLE);
+
+ /* set big cores arm64 boot mode */
+ mmio_setbits_32((uintptr_t)&mt6795_mcucfg->mp1_cpucfg,
+ MP1_CPUCFG_64BIT);
+
+ /* set LITTLE cores arm64 boot mode */
+ mmio_setbits_32((uintptr_t)&mt6795_mcucfg->mp0_rv_addr[0].rv_addr_hw,
+ MP0_CPUCFG_64BIT);
+}
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ next_image_info = (type == NON_SECURE) ?
+ &bl33_image_ep_info : &bl32_image_ep_info;
+
+ /* None of the images on this platform can have 0x0 as the entrypoint */
+ if (next_image_info->pc)
+ return next_image_info;
+ else
+ return NULL;
+}
+
+/*******************************************************************************
+ * Perform any BL3-1 early platform setup. 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.
+ * 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)
+{
+ struct mtk_bl_param_t *pmtk_bl_param =
+ (struct mtk_bl_param_t *)from_bl2;
+ struct atf_arg_t *teearg;
+ unsigned long long normal_base;
+ unsigned long long atf_base;
+
+ assert(from_bl2 != NULL);
+ /*
+ * Mediatek preloader(i.e, BL2) is in 32 bit state, high 32bits
+ * of 64 bit GP registers are UNKNOWN if CPU warm reset from 32 bit
+ * to 64 bit state. So we need to clear high 32bit,
+ * which may be random value.
+ */
+ pmtk_bl_param =
+ (struct mtk_bl_param_t *)((uint64_t)pmtk_bl_param & 0x00000000ffffffff);
+ plat_params_from_bl2 =
+ (void *)((uint64_t)plat_params_from_bl2 & 0x00000000ffffffff);
+
+ teearg = (struct atf_arg_t *)pmtk_bl_param->tee_info_addr;
+
+ console_init(teearg->atf_log_port, UART_CLOCK, UART_BAUDRATE);
+ memcpy((void *)>eearg, (void *)teearg, sizeof(struct atf_arg_t));
+
+ normal_base = 0;
+ /* in ATF boot time, timer for cntpct_el0 is not initialized
+ * so it will not count now.
+ */
+ atf_base = read_cntpct_el0();
+ sched_clock_init(normal_base, atf_base);
+
+ VERBOSE("bl31_setup\n");
+
+ /* 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;
+
+ SET_PARAM_HEAD(&bl33_image_ep_info,
+ PARAM_EP,
+ VERSION_1,
+ 0);
+ /*
+ * Tell BL3-1 where the non-trusted software image
+ * is located and the entry state information
+ */
+ /* BL33_START_ADDRESS */
+ bl33_image_ep_info.pc = pmtk_bl_param->bl33_start_addr;
+ bl33_image_ep_info.spsr = plat_get_spsr_for_bl33_entry();
+ bl33_image_ep_info.args.arg4 = pmtk_bl_param->bootarg_loc;
+ bl33_image_ep_info.args.arg5 = pmtk_bl_param->bootarg_size;
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+}
+/*******************************************************************************
+ * Perform any BL3-1 platform setup code
+ ******************************************************************************/
+
+void bl31_platform_setup(void)
+{
+ platform_setup_cpu();
+
+ generic_delay_timer_init();
+
+ plat_mt_gic_driver_init();
+ /* Initialize the gic cpu and distributor interfaces */
+ plat_mt_gic_init();
+
+ /* Topologies are best known to the platform. */
+ mt_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.
+ * Init MTK propiartary log buffer control field.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+ /* Enable non-secure access to CCI-400 registers */
+ mmio_write_32(CCI400_BASE + CCI_SEC_ACCESS_OFFSET, 0x1);
+
+ plat_cci_init();
+ plat_cci_enable();
+
+ if (gteearg.atf_log_buf_size != 0) {
+ INFO("mmap atf buffer : 0x%x, 0x%x\n\r",
+ gteearg.atf_log_buf_start,
+ gteearg.atf_log_buf_size);
+
+ mmap_add_region(
+ gteearg.atf_log_buf_start &
+ ~(PAGE_SIZE_2MB_MASK),
+ gteearg.atf_log_buf_start &
+ ~(PAGE_SIZE_2MB_MASK),
+ PAGE_SIZE_2MB,
+ MT_DEVICE | MT_RW | MT_NS);
+
+ INFO("mmap atf buffer (force 2MB aligned):0x%x, 0x%x\n",
+ (gteearg.atf_log_buf_start & ~(PAGE_SIZE_2MB_MASK)),
+ PAGE_SIZE_2MB);
+ }
+ /*
+ * add TZRAM_BASE to memory map
+ * then set RO and COHERENT to different attribute
+ */
+ plat_configure_mmu_el3(
+ (TZRAM_BASE & ~(PAGE_SIZE_MASK)),
+ (TZRAM_SIZE & ~(PAGE_SIZE_MASK)),
+ (BL31_RO_BASE & ~(PAGE_SIZE_MASK)),
+ BL31_RO_LIMIT,
+ BL31_COHERENT_RAM_BASE,
+ BL31_COHERENT_RAM_LIMIT);
+ /* Initialize for ATF log buffer */
+ if (gteearg.atf_log_buf_size != 0) {
+ gteearg.atf_aee_debug_buf_size = ATF_AEE_BUFFER_SIZE;
+ gteearg.atf_aee_debug_buf_start =
+ gteearg.atf_log_buf_start +
+ gteearg.atf_log_buf_size - ATF_AEE_BUFFER_SIZE;
+ INFO("ATF log service is registered (0x%x, aee:0x%x)\n",
+ gteearg.atf_log_buf_start,
+ gteearg.atf_aee_debug_buf_start);
+ } else{
+ gteearg.atf_aee_debug_buf_size = 0;
+ gteearg.atf_aee_debug_buf_start = 0;
+ }
+
+ /* Platform code before bl31_main */
+ /* compatible to the earlier chipset */
+
+ /* Show to ATF log buffer & UART */
+ INFO("BL3-1: %s\n", version_string);
+ INFO("BL3-1: %s\n", build_message);
+
+}
+#if 0
+/* MTK Define */
+#define ACTLR_CPUECTLR_BIT (1 << 1)
+
+void enable_ns_access_to_cpuectlr(void)
+{
+ unsigned int next_actlr;
+
+
+ /* ACTLR_EL1 do not implement CUPECTLR */
+ next_actlr = read_actlr_el2();
+ next_actlr |= ACTLR_CPUECTLR_BIT;
+ write_actlr_el2(next_actlr);
+
+ next_actlr = read_actlr_el3();
+ next_actlr |= ACTLR_CPUECTLR_BIT;
+ write_actlr_el3(next_actlr);
+}
+#endif
+/*******************************************************************************
+ * This function prepare boot argument for 64 bit kernel entry
+ ******************************************************************************/
+static entry_point_info_t *bl31_plat_get_next_kernel64_ep_info(void)
+{
+ entry_point_info_t *next_image_info;
+ unsigned long el_status;
+ unsigned int mode;
+
+ el_status = 0;
+ mode = 0;
+
+ /* Kernel image is always non-secured */
+ next_image_info = &bl33_image_ep_info;
+
+ /* 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) {
+ INFO("Kernel_EL2\n");
+ mode = MODE_EL2;
+ } else{
+ INFO("Kernel_EL1\n");
+ mode = MODE_EL1;
+ }
+
+ INFO("Kernel is 64Bit\n");
+ next_image_info->spsr =
+ SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ next_image_info->pc = get_kernel_info_pc();
+ next_image_info->args.arg0 = get_kernel_info_r0();
+ next_image_info->args.arg1 = get_kernel_info_r1();
+
+ INFO("pc=0x%lx, r0=0x%lx, r1=0x%lx\n",
+ next_image_info->pc,
+ next_image_info->args.arg0,
+ next_image_info->args.arg1);
+
+
+ SET_SECURITY_STATE(next_image_info->h.attr, NON_SECURE);
+
+ /* 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;
+}
+
+/*******************************************************************************
+ * This function prepare boot argument for 32 bit kernel entry
+ ******************************************************************************/
+static entry_point_info_t *bl31_plat_get_next_kernel32_ep_info(void)
+{
+ entry_point_info_t *next_image_info;
+ unsigned int mode;
+
+ mode = 0;
+
+ /* Kernel image is always non-secured */
+ next_image_info = &bl33_image_ep_info;
+
+ /* Figure out what mode we enter the non-secure world in */
+ mode = MODE32_hyp;
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+
+ INFO("Kernel is 32Bit\n");
+ next_image_info->spsr =
+ SPSR_MODE32(mode, SPSR_T_ARM, SPSR_E_LITTLE,
+ (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT));
+ next_image_info->pc = get_kernel_info_pc();
+ next_image_info->args.arg0 = get_kernel_info_r0();
+ next_image_info->args.arg1 = get_kernel_info_r1();
+ next_image_info->args.arg2 = get_kernel_info_r2();
+
+ INFO("pc=0x%lx, r0=0x%lx, r1=0x%lx, r2=0x%lx\n",
+ next_image_info->pc,
+ next_image_info->args.arg0,
+ next_image_info->args.arg1,
+ next_image_info->args.arg2);
+
+
+ SET_SECURITY_STATE(next_image_info->h.attr, NON_SECURE);
+
+ /* 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;
+}
+
+/*******************************************************************************
+ * This function prepare boot argument for kernel entrypoint
+ ******************************************************************************/
+void bl31_prepare_kernel_entry(uint64_t k32_64)
+{
+ entry_point_info_t *next_image_info;
+ uint32_t image_type;
+
+ /* Determine which image to execute next */
+ /* image_type = bl31_get_next_image_type(); */
+ image_type = NON_SECURE;
+
+ /* Program EL3 registers to enable entry into the next EL */
+ if (k32_64 == 0)
+ next_image_info = bl31_plat_get_next_kernel32_ep_info();
+ else
+ next_image_info = bl31_plat_get_next_kernel64_ep_info();
+
+ assert(next_image_info);
+ assert(image_type == GET_SECURITY_STATE(next_image_info->h.attr));
+
+ INFO("BL3-1: Preparing for EL3 exit to %s world, Kernel\n",
+ (image_type == SECURE) ? "secure" : "normal");
+ INFO("BL3-1: Next image address = 0x%llx\n",
+ (unsigned long long) next_image_info->pc);
+ INFO("BL3-1: Next image spsr = 0x%x\n", next_image_info->spsr);
+ cm_init_context(read_mpidr_el1(), next_image_info);
+ cm_prepare_el3_exit(image_type);
+}
diff --git a/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.c b/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.c
new file mode 100644
index 0000000..2430c47
--- /dev/null
+++ b/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <arch_helpers.h>
+#include <mmio.h>
+#include <mt_cpuxgpt.h>
+#include <stdint.h>
+#include <platform.h>
+#include <debug.h>
+#define CPUXGPT_BASE 0x10200000
+#define INDEX_BASE (CPUXGPT_BASE+0x0674)
+#define CTL_BASE (CPUXGPT_BASE+0x0670)
+
+uint64_t normal_time_base;
+uint64_t atf_time_base;
+
+void sched_clock_init(uint64_t normal_base, uint64_t atf_base)
+{
+ normal_time_base = normal_base;
+ atf_time_base = atf_base;
+}
+
+uint64_t sched_clock(void)
+{
+ uint64_t cval;
+
+ cval = (((read_cntpct_el0() - atf_time_base)*1000)/
+ SYS_COUNTER_FREQ_IN_MHZ) + normal_time_base;
+ return cval;
+}
+
+/*
+ * Return: 0 - Trying to disable the CPUXGPT control bit,
+ * and not allowed to disable it.
+ * Return: 1 - reg_addr is not realted to disable the control bit.
+ */
+unsigned char check_cpuxgpt_write_permission(unsigned int reg_addr,
+ unsigned int reg_value)
+{
+ unsigned int idx;
+ unsigned int ctl_val;
+
+ if (reg_addr == CTL_BASE) {
+ idx = mmio_read_32(INDEX_BASE);
+
+ /* idx 0: CPUXGPT system control */
+ if (idx == 0) {
+ ctl_val = mmio_read_32(CTL_BASE);
+ if (ctl_val & 1) {
+ /*
+ * if enable bit already set,
+ * then bit 0 is not allow to set as 0
+ */
+ if (!(reg_value & 1))
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+
diff --git a/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.h b/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.h
new file mode 100644
index 0000000..edd045c
--- /dev/null
+++ b/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016, 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 __MT_CPUXGPT_H__
+#define __MT_CPUXGPT_H__
+
+/* REG */
+#define INDEX_CTL_REG 0x000
+#define INDEX_STA_REG 0x004
+#define INDEX_CNT_L_INIT 0x008
+#define INDEX_CNT_H_INIT 0x00C
+
+/* CTL_REG SET */
+#define EN_CPUXGPT 0x01
+#define EN_AHLT_DEBUG 0x02
+#define CLK_DIV1 (0x1 << 8)
+#define CLK_DIV2 (0x2 << 8)
+#define CLK_DIV4 (0x4 << 8)
+#define CLK_DIV_MASK (~(0x7<<8))
+
+void generic_timer_backup(void);
+void sched_clock_init(uint64_t normal_base, uint64_t atf_base);
+uint64_t sched_clock(void);
+
+#endif /* __MT_CPUXGPT_H__ */
diff --git a/plat/mediatek/mt6795/include/mcucfg.h b/plat/mediatek/mt6795/include/mcucfg.h
new file mode 100644
index 0000000..879e7fa
--- /dev/null
+++ b/plat/mediatek/mt6795/include/mcucfg.h
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2016, 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 __MCUCFG_H__
+#define __MCUCFG_H__
+
+#include <platform_def.h>
+#include <stdint.h>
+
+struct mt6795_mcucfg_regs {
+ uint32_t mp0_ca7l_cache_config;
+ struct {
+ uint32_t mem_delsel0;
+ uint32_t mem_delsel1;
+ } mp0_cpu[4];
+ uint32_t mp0_cache_mem_delsel0;
+ uint32_t mp0_cache_mem_delsel1;
+ uint32_t mp0_axi_config;
+ uint32_t mp0_misc_config[2];
+ struct {
+ uint32_t rv_addr_lw;
+ uint32_t rv_addr_hw;
+ } mp0_rv_addr[4];
+ uint32_t mp0_ca7l_cfg_dis;
+ uint32_t mp0_ca7l_clken_ctrl;
+ uint32_t mp0_ca7l_rst_ctrl;
+ uint32_t mp0_ca7l_misc_config;
+ uint32_t mp0_ca7l_dbg_pwr_ctrl;
+ uint32_t mp0_rw_rsvd0;
+ uint32_t mp0_rw_rsvd1;
+ uint32_t mp0_ro_rsvd;
+ uint32_t reserved0_0[100];
+ uint32_t mp1_cpucfg;
+ uint32_t mp1_miscdbg;
+ uint32_t reserved0_1[13];
+ uint32_t mp1_rst_ctl;
+ uint32_t mp1_clkenm_div;
+ uint32_t reserved0_2[7];
+ uint32_t mp1_config_res;
+ uint32_t reserved0_3[13];
+ struct {
+ uint32_t rv_addr_lw;
+ uint32_t rv_addr_hw;
+ } mp1_rv_addr[2];
+ uint32_t reserved0_4[84];
+ uint32_t mp0_rst_status; /* 0x400 */
+ uint32_t mp0_dbg_ctrl;
+ uint32_t mp0_dbg_flag;
+ uint32_t mp0_ca7l_ir_mon;
+ struct {
+ uint32_t pc_lw;
+ uint32_t pc_hw;
+ uint32_t fp_arch32;
+ uint32_t sp_arch32;
+ uint32_t fp_arch64_lw;
+ uint32_t fp_arch64_hw;
+ uint32_t sp_arch64_lw;
+ uint32_t sp_arch64_hw;
+ } mp0_dbg_core[4];
+ uint32_t dfd_ctrl;
+ uint32_t dfd_cnt_l;
+ uint32_t dfd_cnt_h;
+ uint32_t misccfg_mp0_rw_rsvd;
+ uint32_t misccfg_sec_vio_status0;
+ uint32_t misccfg_sec_vio_status1;
+ uint32_t reserved1[22];
+ uint32_t misccfg_rw_rsvd; /* 0x500 */
+ uint32_t mcusys_dbg_mon_sel_a;
+ uint32_t mcusys_dbg_mon;
+ uint32_t reserved2[61];
+ uint32_t mcusys_config_a; /* 0x600 */
+ uint32_t mcusys_config1_a;
+ uint32_t mcusys_gic_peribase_a;
+ uint32_t reserved3;
+ uint32_t sec_range0_start; /* 0x610 */
+ uint32_t sec_range0_end;
+ uint32_t sec_range_enable;
+ uint32_t reserved4;
+ uint32_t int_pol_ctl[8]; /* 0x620 */
+ uint32_t aclken_div; /* 0x640 */
+ uint32_t pclken_div;
+ uint32_t l2c_sram_ctrl;
+ uint32_t armpll_jit_ctrl;
+ uint32_t cci_addrmap; /* 0x650 */
+ uint32_t cci_config;
+ uint32_t cci_periphbase;
+ uint32_t cci_nevntcntovfl;
+ uint32_t cci_clk_ctrl; /* 0x660 */
+ uint32_t cci_acel_s1_ctrl;
+ uint32_t bus_fabric_dcm_ctrl;
+ uint32_t reserved5;
+ uint32_t xgpt_ctl; /* 0x670 */
+ uint32_t xgpt_idx;
+ uint32_t ptpod2_ctl0;
+ uint32_t ptpod2_ctl1;
+ uint32_t mcusys_revid;
+ uint32_t mcusys_rw_rsvd0;
+ uint32_t mcusys_rw_rsvd1;
+};
+
+static struct mt6795_mcucfg_regs *const mt6795_mcucfg = (void *)MCUCFG_BASE;
+
+/* cpu boot mode */
+enum {
+ MP0_CPUCFG_64BIT_SHIFT = 12,
+ MP1_CPUCFG_64BIT_SHIFT = 28,
+ MP0_CPUCFG_64BIT = 0xf << MP0_CPUCFG_64BIT_SHIFT,
+ MP1_CPUCFG_64BIT = 0xf << MP1_CPUCFG_64BIT_SHIFT
+};
+
+/* scu related */
+enum {
+ MP0_ACINACTM_SHIFT = 4,
+ MP1_ACINACTM_SHIFT = 0,
+ MP0_ACINACTM = 1 << MP0_ACINACTM_SHIFT,
+ MP1_ACINACTM = 1 << MP1_ACINACTM_SHIFT
+};
+
+enum {
+ MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0,
+ MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4,
+ MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8,
+ MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12,
+ MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16,
+
+ MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK =
+ 0xf << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK =
+ 0xf << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK =
+ 0xf << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK =
+ 0xf << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK =
+ 0xf << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT
+};
+
+enum {
+ MP1_AINACTS_SHIFT = 4,
+ MP1_AINACTS = 1 << MP1_AINACTS_SHIFT
+};
+
+enum {
+ MP1_SW_CG_GEN_SHIFT = 12,
+ MP1_SW_CG_GEN = 1 << MP1_SW_CG_GEN_SHIFT
+};
+
+enum {
+ MP1_L2RSTDISABLE_SHIFT = 14,
+ MP1_L2RSTDISABLE = 1 << MP1_L2RSTDISABLE_SHIFT
+};
+
+#endif /* __MCUCFG_H__ */
diff --git a/plat/mediatek/mt6795/include/plat_macros.S b/plat/mediatek/mt6795/include/plat_macros.S
new file mode 100644
index 0000000..ef9d1d8
--- /dev/null
+++ b/plat/mediatek/mt6795/include/plat_macros.S
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2016, 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 <cci.h>
+#include <gic_v2.h>
+#include <platform_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+gicc_regs:
+ .asciz "gicc_hppir", "gicc_ahppir", "gicc_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, x17, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ mov_imm x16, BASE_GICD_BASE
+ mov_imm x17, BASE_GICC_BASE
+ /* Load the gicc reg list to x6 */
+ adr x6, gicc_regs
+ /* Load the gicc regs to gp regs used by str_in_crash_buf_print */
+ ldr w8, [x17, #GICC_HPPIR]
+ ldr w9, [x17, #GICC_AHPPIR]
+ ldr w10, [x17, #GICC_CTLR]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+
+ /* Print the GICD_ISPENDR regs */
+ add x7, x16, #GICD_ISPENDR
+ adr x4, gicd_pend_reg
+ bl asm_print_str
+gicd_ispendr_loop:
+ sub x4, x7, x16
+ cmp x4, #0x280
+ b.eq exit_print_gic_regs
+ bl asm_print_hex
+
+ adr x4, spacer
+ bl asm_print_str
+
+ ldr x4, [x7], #8
+ bl asm_print_hex
+
+ adr x4, newline
+ bl asm_print_str
+ b gicd_ispendr_loop
+exit_print_gic_regs:
+ .endm
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+ .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+ /* ------------------------------------------------
+ * The below macro prints out relevant interconnect
+ * registers whenever an unhandled exception is
+ * taken in BL3-1.
+ * Clobbers: x0 - x9, sp
+ * ------------------------------------------------
+ */
+ .macro plat_print_interconnect_regs
+ adr x6, cci_iface_regs
+ /* Store in x7 the base address of the first interface */
+ mov_imm x7, (PLAT_MT_CCI_BASE + SLAVE_IFACE_OFFSET( \
+ PLAT_MT_CCI_CLUSTER0_SL_IFACE_IX))
+ ldr w8, [x7, #SNOOP_CTRL_REG]
+ /* Store in x7 the base address of the second interface */
+ mov_imm x7, (PLAT_MT_CCI_BASE + SLAVE_IFACE_OFFSET( \
+ PLAT_MT_CCI_CLUSTER1_SL_IFACE_IX))
+ ldr w9, [x7, #SNOOP_CTRL_REG]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+ .endm
diff --git a/plat/mediatek/mt6795/include/plat_private.h b/plat/mediatek/mt6795/include/plat_private.h
new file mode 100644
index 0000000..7385c49
--- /dev/null
+++ b/plat/mediatek/mt6795/include/plat_private.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PLAT_PRIVATE_H__
+#define __PLAT_PRIVATE_H__
+#include <stdint.h>
+#include <xlat_tables.h>
+
+void plat_configure_mmu_el3(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long,
+ unsigned long,
+ unsigned long,
+ unsigned long);
+
+void plat_cci_init(void);
+void plat_cci_enable(void);
+void plat_cci_disable(void);
+
+/* Declarations for plat_mt_gic.c */
+void plat_mt_gic_init(void);
+
+/* Declarations for plat_topology.c */
+int mt_setup_topology(void);
+void plat_delay_timer_init(void);
+
+void plat_mt_gic_driver_init(void);
+void plat_mt_gic_init(void);
+void plat_mt_gic_cpuif_enable(void);
+void plat_mt_gic_cpuif_disable(void);
+void plat_mt_gic_pcpu_init(void);
+
+#endif /* __PLAT_PRIVATE_H__ */
diff --git a/plat/mediatek/mt6795/include/plat_sip_calls.h b/plat/mediatek/mt6795/include/plat_sip_calls.h
new file mode 100644
index 0000000..a4844f4
--- /dev/null
+++ b/plat/mediatek/mt6795/include/plat_sip_calls.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PLAT_SIP_CALLS_H__
+#define __PLAT_SIP_CALLS_H__
+
+/*******************************************************************************
+ * Plat SiP function constants
+ ******************************************************************************/
+#define MTK_PLAT_SIP_NUM_CALLS 0
+
+#endif /* __PLAT_SIP_CALLS_H__ */
diff --git a/plat/mediatek/mt6795/include/platform_def.h b/plat/mediatek/mt6795/include/platform_def.h
new file mode 100644
index 0000000..275333f
--- /dev/null
+++ b/plat/mediatek/mt6795/include/platform_def.h
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2016, 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__
+
+#define PLAT_PRIMARY_CPU 0x0
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define MT_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+
+#define IO_PHYS (0x10000000)
+#define INFRACFG_AO_BASE (IO_PHYS + 0x1000)
+#define MCUCFG_BASE (IO_PHYS + 0x200000)
+#define PERI_BASE (IO_PHYS + 0x1000000)
+
+
+#define GPIO_BASE (IO_PHYS + 0x370000)
+#define SPM_BASE (IO_PHYS + 0x6000)
+#define RGU_BASE (MCUCFG_BASE + 0x11000)
+#define PMIC_WRAP_BASE (IO_PHYS + 0x10000)
+
+#define TRNG_base (MCUCFG_BASE + 0x230000)
+#define MT_GIC_BASE (0x10220000)
+#define MCU_SYS_SIZE (0x700000)
+#define PLAT_MT_CCI_BASE (IO_PHYS + 0x390000)
+
+/* Aggregate of all devices in the first GB */
+#define MTK_DEV_RNG0_BASE IO_PHYS
+#define MTK_DEV_RNG0_SIZE 0x400000
+#define MTK_DEV_RNG1_BASE (PERI_BASE)
+#define MTK_DEV_RNG1_SIZE 0x4000000
+
+/*******************************************************************************
+ * UART related constants
+ ******************************************************************************/
+#define UART0_BASE (PERI_BASE + 0x2000)
+
+#define UART_BAUDRATE (921600)
+#define UART_CLOCK (26000000)
+
+/*******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS 13000000
+#define SYS_COUNTER_FREQ_IN_MHZ (SYS_COUNTER_FREQ_IN_TICKS/1000000)
+
+/*******************************************************************************
+ * GIC-400 & interrupt handling related constants
+ ******************************************************************************/
+
+/* Base MTK_platform compatible GIC memory map */
+#define BASE_GICD_BASE (MT_GIC_BASE+0x1000)
+#define BASE_GICC_BASE (MT_GIC_BASE + 0x2000)
+#define BASE_GICR_BASE (MT_GIC_BASE + 0x200000)
+#define BASE_GICH_BASE (MT_GIC_BASE + 0x4000)
+#define BASE_GICV_BASE (MT_GIC_BASE + 0x6000)
+
+#define INT_POL_CTL0 0x10200620
+#define GIC_PRIVATE_SIGNALS (32)
+
+/*******************************************************************************
+ * CCI-400 related constants
+ ******************************************************************************/
+#define PLAT_MT_CCI_CLUSTER0_SL_IFACE_IX 4
+#define PLAT_MT_CCI_CLUSTER1_SL_IFACE_IX 3
+
+/*******************************************************************************
+ * WDT Registers
+ ******************************************************************************/
+#define MTK_WDT_BASE (RGU_BASE)
+#define MTK_WDT_SIZE (0x1000)
+#define MTK_WDT_MODE (MTK_WDT_BASE+0x0000)
+#define MTK_WDT_LENGTH (MTK_WDT_BASE+0x0004)
+#define MTK_WDT_RESTART (MTK_WDT_BASE+0x0008)
+#define MTK_WDT_STATUS (MTK_WDT_BASE+0x000C)
+#define MTK_WDT_INTERVAL (MTK_WDT_BASE+0x0010)
+#define MTK_WDT_SWRST (MTK_WDT_BASE+0x0014)
+#define MTK_WDT_SWSYSRST (MTK_WDT_BASE+0x0018)
+#define MTK_WDT_NONRST_REG (MTK_WDT_BASE+0x0020)
+#define MTK_WDT_NONRST_REG2 (MTK_WDT_BASE+0x0024)
+#define MTK_WDT_REQ_MODE (MTK_WDT_BASE+0x0030)
+#define MTK_WDT_REQ_IRQ_EN (MTK_WDT_BASE+0x0034)
+#define MTK_WDT_DEBUG_CTL (MTK_WDT_BASE+0x0040)
+
+/*WDT_STATUS*/
+#define MTK_WDT_STATUS_HWWDT_RST (0x80000000)
+#define MTK_WDT_STATUS_SWWDT_RST (0x40000000)
+#define MTK_WDT_STATUS_IRQWDT_RST (0x20000000)
+#define MTK_WDT_STATUS_DEBUGWDT_RST (0x00080000)
+#define MTK_WDT_STATUS_SPMWDT_RST (0x0002)
+#define MTK_WDT_STATUS_SPM_THERMAL_RST (0x0001)
+#define MTK_WDT_STATUS_THERMAL_DIRECT_RST (1<<18)
+#define MTK_WDT_STATUS_SECURITY_RST (1<<28)
+
+#define MTK_WDT_MODE_DUAL_MODE 0x0040
+#define MTK_WDT_MODE_IRQ 0x0008
+#define MTK_WDT_MODE_KEY 0x22000000
+#define MTK_WDT_MODE_EXTEN 0x0004
+#define MTK_WDT_SWRST_KEY 0x1209
+#define MTK_WDT_RESTART_KEY (0x1971)
+
+/* FIQ platform related define */
+#define MT_IRQ_SEC_SGI_0 8
+#define MT_IRQ_SEC_SGI_1 9
+#define MT_IRQ_SEC_SGI_2 10
+#define MT_IRQ_SEC_SGI_3 11
+#define MT_IRQ_SEC_SGI_4 12
+#define MT_IRQ_SEC_SGI_5 13
+#define MT_IRQ_SEC_SGI_6 14
+#define MT_IRQ_SEC_SGI_7 15
+
+#define FIQ_SMP_CALL_SGI MT_IRQ_SEC_SGI_5
+
+#define PLAT_ARM_G0_IRQS FIQ_SMP_CALL_SGI
+
+#define DEBUG_XLAT_TABLE 0
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* 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 0x800
+#elif IMAGE_BL32
+#define PLATFORM_STACK_SIZE 0x440
+#endif
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+#if ENABLE_PLAT_COMPAT
+#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2
+#else
+#define PLAT_MAX_PWR_LVL 2 /* MPIDR_AFFLVL2 */
+#endif
+
+#define PLATFORM_CACHE_LINE_SIZE 64
+#define PLATFORM_SYSTEM_COUNT 1
+#define PLATFORM_CLUSTER_COUNT 2
+#define PLATFORM_CLUSTER0_CORE_COUNT 4
+#define PLATFORM_CLUSTER1_CORE_COUNT 4
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \
+ PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER 4
+#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \
+ PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+/* ATF Argument */
+#define ATF_ARG_SIZE (0x800)
+
+/* TF txet, ro, rw, internal SRAM, Size: release: 80KB, debug: 92KB */
+#define TZRAM_BASE (0x110000)
+#if DEBUG
+#define TZRAM_SIZE (0x1C400)
+#else
+#define TZRAM_SIZE (0x1C400)
+#endif
+#define TZRAM2_BASE 0x00100000
+#define TZRAM2_SIZE 0xDC00
+#define TZRAM2_LIMIT (TZRAM2_BASE + TZRAM2_SIZE)
+
+#define RAM_CONSOLE_BASE 0x0012D000
+#define RAM_CONSOLE_SIZE 0x00001000
+/*******************************************************************************
+ * 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 (TZRAM_BASE + 0x1000)
+#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE)
+#define BSS1_STACK_LIMIT (TZRAM_BASE + TZRAM_SIZE)
+#define BL31_TZRAM_SIZE (TZRAM_SIZE - ATF_ARG_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define ADDR_SPACE_SIZE (1ull << 32)
+#define MAX_XLAT_TABLES 7
+#define MAX_MMAP_REGIONS 16
+
+
+/*******************************************************************************
+ * CCI-400 related constants
+ ******************************************************************************/
+#define CCI400_BASE 0x10390000
+#define CCI400_SL_IFACE_CLUSTER0 4
+#define CCI400_SL_IFACE_CLUSTER1 3
+#define CCI400_SL_IFACE_INDEX(mpidr) (mpidr & MPIDR_CLUSTER_MASK ? \
+ CCI400_SL_IFACE_CLUSTER1 : \
+ CCI400_SL_IFACE_CLUSTER0)
+#define CCI_SEC_ACCESS_OFFSET (0x8)
+
+
+/*******************************************************************************
+ * 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)
+
+#define BL32_BASE (0x0)
+
+/*
+ * Load address of BL3-3 for this platform port
+ */
+#define LK_SIZE_LIMIT (0x100000)
+#define PLAT_MTK_NS_IMAGE_OFFSET (0x41E00000)
+/* 16KB */
+#define ATF_AEE_BUFFER_SIZE (0x4000)
+#define PAGE_SIZE_2MB_MASK (PAGE_SIZE_2MB - 1)
+#define IS_PAGE_2MB_ALIGNED(addr) (((addr) & PAGE_SIZE_2MB_MASK) == 0)
+#define PAGE_SIZE_2MB (1 << PAGE_SIZE_2MB_SHIFT)
+#define PAGE_SIZE_2MB_SHIFT TWO_MB_SHIFT
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/mediatek/mt6795/include/power_tracer.h b/plat/mediatek/mt6795/include/power_tracer.h
new file mode 100644
index 0000000..ab9390d
--- /dev/null
+++ b/plat/mediatek/mt6795/include/power_tracer.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016, 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 __POWER_TRACER_H__
+#define __POWER_TRACER_H__
+
+#define CPU_UP 0
+#define CPU_DOWN 1
+#define CPU_SUSPEND 2
+#define CLUSTER_UP 3
+#define CLUSTER_DOWN 4
+#define CLUSTER_SUSPEND 5
+
+void trace_power_flow(unsigned long mpidr, unsigned char mode);
+
+#endif
diff --git a/plat/mediatek/mt6795/include/scu.h b/plat/mediatek/mt6795/include/scu.h
new file mode 100644
index 0000000..e59fd43
--- /dev/null
+++ b/plat/mediatek/mt6795/include/scu.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, 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 __SCU_H__
+#define __SCU_H__
+
+void disable_scu(unsigned long mpidr);
+void enable_scu(unsigned long mpidr);
+
+#endif
diff --git a/plat/mediatek/mt6795/include/spm.h b/plat/mediatek/mt6795/include/spm.h
new file mode 100644
index 0000000..32f8d8f
--- /dev/null
+++ b/plat/mediatek/mt6795/include/spm.h
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2016, 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 __SPM_H__
+#define __SPM_H__
+
+#define SPM_POWERON_CONFIG_SET (SPM_BASE + 0x000)
+#define SPM_POWER_ON_VAL0 (SPM_BASE + 0x010)
+#define SPM_POWER_ON_VAL1 (SPM_BASE + 0x014)
+#define SPM_CLK_SETTLE (SPM_BASE + 0x100)
+#define SPM_CA7_CPU1_PWR_CON (SPM_BASE + 0x218)
+#define SPM_CA7_CPU2_PWR_CON (SPM_BASE + 0x21c)
+#define SPM_CA7_CPU3_PWR_CON (SPM_BASE + 0x220)
+#define SPM_CA7_CPU1_L1_PDN (SPM_BASE + 0x264)
+#define SPM_CA7_CPU2_L1_PDN (SPM_BASE + 0x26c)
+#define SPM_CA7_CPU3_L1_PDN (SPM_BASE + 0x274)
+#define SPM_MD32_SRAM_CON (SPM_BASE + 0x2c8)
+#define SPM_PCM_CON0 (SPM_BASE + 0x310)
+#define SPM_PCM_CON1 (SPM_BASE + 0x314)
+#define SPM_PCM_IM_PTR (SPM_BASE + 0x318)
+#define SPM_PCM_IM_LEN (SPM_BASE + 0x31c)
+#define SPM_PCM_REG_DATA_INI (SPM_BASE + 0x320)
+#define SPM_PCM_EVENT_VECTOR0 (SPM_BASE + 0x340)
+#define SPM_PCM_EVENT_VECTOR1 (SPM_BASE + 0x344)
+#define SPM_PCM_EVENT_VECTOR2 (SPM_BASE + 0x348)
+#define SPM_PCM_EVENT_VECTOR3 (SPM_BASE + 0x34c)
+#define SPM_PCM_MAS_PAUSE_MASK (SPM_BASE + 0x354)
+#define SPM_PCM_PWR_IO_EN (SPM_BASE + 0x358)
+#define SPM_PCM_TIMER_VAL (SPM_BASE + 0x35c)
+#define SPM_PCM_TIMER_OUT (SPM_BASE + 0x360)
+#define SPM_PCM_REG0_DATA (SPM_BASE + 0x380)
+#define SPM_PCM_REG1_DATA (SPM_BASE + 0x384)
+#define SPM_PCM_REG2_DATA (SPM_BASE + 0x388)
+#define SPM_PCM_REG3_DATA (SPM_BASE + 0x38c)
+#define SPM_PCM_REG4_DATA (SPM_BASE + 0x390)
+#define SPM_PCM_REG5_DATA (SPM_BASE + 0x394)
+#define SPM_PCM_REG6_DATA (SPM_BASE + 0x398)
+#define SPM_PCM_REG7_DATA (SPM_BASE + 0x39c)
+#define SPM_PCM_REG8_DATA (SPM_BASE + 0x3a0)
+#define SPM_PCM_REG9_DATA (SPM_BASE + 0x3a4)
+#define SPM_PCM_REG10_DATA (SPM_BASE + 0x3a8)
+#define SPM_PCM_REG11_DATA (SPM_BASE + 0x3ac)
+#define SPM_PCM_REG12_DATA (SPM_BASE + 0x3b0)
+#define SPM_PCM_REG13_DATA (SPM_BASE + 0x3b4)
+#define SPM_PCM_REG14_DATA (SPM_BASE + 0x3b8)
+#define SPM_PCM_REG15_DATA (SPM_BASE + 0x3bc)
+#define SPM_PCM_EVENT_REG_STA (SPM_BASE + 0x3c0)
+#define SPM_PCM_FSM_STA (SPM_BASE + 0x3c4)
+#define SPM_PCM_IM_HOST_RW_PTR (SPM_BASE + 0x3c8)
+#define SPM_PCM_IM_HOST_RW_DAT (SPM_BASE + 0x3cc)
+#define SPM_PCM_EVENT_VECTOR4 (SPM_BASE + 0x3d0)
+#define SPM_PCM_EVENT_VECTOR5 (SPM_BASE + 0x3d4)
+#define SPM_PCM_EVENT_VECTOR6 (SPM_BASE + 0x3d8)
+#define SPM_PCM_EVENT_VECTOR7 (SPM_BASE + 0x3dc)
+#define SPM_PCM_SW_INT_SET (SPM_BASE + 0x3e0)
+#define SPM_PCM_SW_INT_CLEAR (SPM_BASE + 0x3e4)
+#define SPM_CLK_CON (SPM_BASE + 0x400)
+#define SPM_SLEEP_PTPOD2_CON (SPM_BASE + 0x408)
+#define SPM_APMCU_PWRCTL (SPM_BASE + 0x600)
+#define SPM_AP_DVFS_CON_SET (SPM_BASE + 0x604)
+#define SPM_AP_STANBY_CON (SPM_BASE + 0x608)
+#define SPM_PWR_STATUS (SPM_BASE + 0x60c)
+#define SPM_PWR_STATUS_2ND (SPM_BASE + 0x610)
+#define SPM_AP_BSI_REQ (SPM_BASE + 0x614)
+#define SPM_SLEEP_TIMER_STA (SPM_BASE + 0x720)
+#define SPM_SLEEP_WAKEUP_EVENT_MASK (SPM_BASE + 0x810)
+#define SPM_SLEEP_CPU_WAKEUP_EVENT (SPM_BASE + 0x814)
+#define SPM_SLEEP_MD32_WAKEUP_EVENT_MASK (SPM_BASE + 0x818)
+#define SPM_PCM_WDT_TIMER_VAL (SPM_BASE + 0x824)
+#define SPM_PCM_WDT_TIMER_OUT (SPM_BASE + 0x828)
+#define SPM_PCM_MD32_MAILBOX (SPM_BASE + 0x830)
+#define SPM_PCM_MD32_IRQ (SPM_BASE + 0x834)
+#define SPM_SLEEP_ISR_MASK (SPM_BASE + 0x900)
+#define SPM_SLEEP_ISR_STATUS (SPM_BASE + 0x904)
+#define SPM_SLEEP_ISR_RAW_STA (SPM_BASE + 0x910)
+#define SPM_SLEEP_MD32_ISR_RAW_STA (SPM_BASE + 0x914)
+#define SPM_SLEEP_WAKEUP_MISC (SPM_BASE + 0x918)
+#define SPM_SLEEP_BUS_PROTECT_RDY (SPM_BASE + 0x91c)
+#define SPM_SLEEP_SUBSYS_IDLE_STA (SPM_BASE + 0x920)
+#define SPM_PCM_RESERVE (SPM_BASE + 0xb00)
+#define SPM_PCM_RESERVE2 (SPM_BASE + 0xb04)
+#define SPM_PCM_FLAGS (SPM_BASE + 0xb08)
+#define SPM_PCM_SRC_REQ (SPM_BASE + 0xb0c)
+#define SPM_PCM_DEBUG_CON (SPM_BASE + 0xb20)
+#define SPM_CA7_CPU0_IRQ_MASK (SPM_BASE + 0xb30)
+#define SPM_CA7_CPU1_IRQ_MASK (SPM_BASE + 0xb34)
+#define SPM_CA7_CPU2_IRQ_MASK (SPM_BASE + 0xb38)
+#define SPM_CA7_CPU3_IRQ_MASK (SPM_BASE + 0xb3c)
+#define SPM_CA15_CPU0_IRQ_MASK (SPM_BASE + 0xb40)
+#define SPM_CA15_CPU1_IRQ_MASK (SPM_BASE + 0xb44)
+#define SPM_CA15_CPU2_IRQ_MASK (SPM_BASE + 0xb48)
+#define SPM_CA15_CPU3_IRQ_MASK (SPM_BASE + 0xb4c)
+#define SPM_PCM_PASR_DPD_0 (SPM_BASE + 0xb60)
+#define SPM_PCM_PASR_DPD_1 (SPM_BASE + 0xb64)
+#define SPM_PCM_PASR_DPD_2 (SPM_BASE + 0xb68)
+#define SPM_PCM_PASR_DPD_3 (SPM_BASE + 0xb6c)
+#define SPM_SLEEP_CA7_WFI0_EN (SPM_BASE + 0xf00)
+#define SPM_SLEEP_CA7_WFI1_EN (SPM_BASE + 0xf04)
+#define SPM_SLEEP_CA7_WFI2_EN (SPM_BASE + 0xf08)
+#define SPM_SLEEP_CA7_WFI3_EN (SPM_BASE + 0xf0c)
+#define SPM_SLEEP_CA15_WFI0_EN (SPM_BASE + 0xf10)
+#define SPM_SLEEP_CA15_WFI1_EN (SPM_BASE + 0xf14)
+#define SPM_SLEEP_CA15_WFI2_EN (SPM_BASE + 0xf18)
+#define SPM_SLEEP_CA15_WFI3_EN (SPM_BASE + 0xf1c)
+
+#define SPM_PROJECT_CODE 0xb16
+
+#define SPM_REGWR_EN (1U << 0)
+#define SPM_REGWR_CFG_KEY (SPM_PROJECT_CODE << 16)
+
+#define SPM_CPU_PDN_DIS (1U << 0)
+#define SPM_INFRA_PDN_DIS (1U << 1)
+#define SPM_DDRPHY_PDN_DIS (1U << 2)
+#define SPM_DUALVCORE_PDN_DIS (1U << 3)
+#define SPM_PASR_DIS (1U << 4)
+#define SPM_DPD_DIS (1U << 5)
+#define SPM_SODI_DIS (1U << 6)
+#define SPM_MEMPLL_RESET (1U << 7)
+#define SPM_MAINPLL_PDN_DIS (1U << 8)
+#define SPM_CPU_DVS_DIS (1U << 9)
+#define SPM_CPU_DORMANT (1U << 10)
+#define SPM_EXT_VSEL_GPIO103 (1U << 11)
+#define SPM_DDR_HIGH_SPEED (1U << 12)
+#define SPM_OPT (1U << 13)
+
+#define POWER_ON_VAL1_DEF 0x01011820
+#define PCM_FSM_STA_DEF 0x48490
+#define PCM_END_FSM_STA_DEF 0x08490
+#define PCM_END_FSM_STA_MASK 0x3fff0
+#define PCM_HANDSHAKE_SEND1 0xbeefbeef
+
+#define PCM_WDT_TIMEOUT (30 * 32768)
+#define PCM_TIMER_MAX (0xffffffff - PCM_WDT_TIMEOUT)
+
+#define CON0_PCM_KICK (1U << 0)
+#define CON0_IM_KICK (1U << 1)
+#define CON0_IM_SLEEP_DVS (1U << 3)
+#define CON0_PCM_SW_RESET (1U << 15)
+#define CON0_CFG_KEY (SPM_PROJECT_CODE << 16)
+
+#define CON1_IM_SLAVE (1U << 0)
+#define CON1_MIF_APBEN (1U << 3)
+#define CON1_PCM_TIMER_EN (1U << 5)
+#define CON1_IM_NONRP_EN (1U << 6)
+#define CON1_PCM_WDT_EN (1U << 8)
+#define CON1_PCM_WDT_WAKE_MODE (1U << 9)
+#define CON1_SPM_SRAM_SLP_B (1U << 10)
+#define CON1_SPM_SRAM_ISO_B (1U << 11)
+#define CON1_EVENT_LOCK_EN (1U << 12)
+#define CON1_CFG_KEY (SPM_PROJECT_CODE << 16)
+
+#define PCM_PWRIO_EN_R0 (1U << 0)
+#define PCM_PWRIO_EN_R7 (1U << 7)
+#define PCM_RF_SYNC_R0 (1U << 16)
+#define PCM_RF_SYNC_R2 (1U << 18)
+#define PCM_RF_SYNC_R6 (1U << 22)
+#define PCM_RF_SYNC_R7 (1U << 23)
+
+#define CC_SYSCLK0_EN_0 (1U << 0)
+#define CC_SYSCLK0_EN_1 (1U << 1)
+#define CC_SYSCLK1_EN_0 (1U << 2)
+#define CC_SYSCLK1_EN_1 (1U << 3)
+#define CC_SYSSETTLE_SEL (1U << 4)
+#define CC_LOCK_INFRA_DCM (1U << 5)
+#define CC_SRCLKENA_MASK_0 (1U << 6)
+#define CC_CXO32K_RM_EN_MD1 (1U << 9)
+#define CC_CXO32K_RM_EN_MD2 (1U << 10)
+#define CC_CLKSQ1_SEL (1U << 12)
+#define CC_DISABLE_DORM_PWR (1U << 14)
+#define CC_MD32_DCM_EN (1U << 18)
+
+#define WFI_OP_AND 1
+#define WFI_OP_OR 0
+
+#define WAKE_MISC_PCM_TIMER (1U << 19)
+#define WAKE_MISC_CPU_WAKE (1U << 20)
+
+/* define WAKE_SRC_XXX */
+#define WAKE_SRC_SPM_MERGE (1 << 0)
+#define WAKE_SRC_KP (1 << 2)
+#define WAKE_SRC_WDT (1 << 3)
+#define WAKE_SRC_GPT (1 << 4)
+#define WAKE_SRC_EINT (1 << 6)
+#define WAKE_SRC_LOW_BAT (1 << 9)
+#define WAKE_SRC_MD32 (1 << 10)
+#define WAKE_SRC_USB_CD (1 << 14)
+#define WAKE_SRC_USB_PDN (1 << 15)
+#define WAKE_SRC_AFE (1 << 20)
+#define WAKE_SRC_THERM (1 << 21)
+#define WAKE_SRC_SYSPWREQ (1 << 24)
+#define WAKE_SRC_SEJ (1 << 27)
+#define WAKE_SRC_ALL_MD32 (1 << 28)
+#define WAKE_SRC_CPU_IRQ (1 << 29)
+
+#endif /* __SPM_H__ */
diff --git a/plat/mediatek/mt6795/plat_delay_timer.c b/plat/mediatek/mt6795/plat_delay_timer.c
new file mode 100644
index 0000000..797ce05
--- /dev/null
+++ b/plat/mediatek/mt6795/plat_delay_timer.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2016, 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 <delay_timer.h>
+#include <platform_def.h>
+
+static uint32_t plat_get_timer_value(void)
+{
+ /*
+ * Generic delay timer implementation expects the timer to be a down
+ * counter. We apply bitwise NOT operator to the tick values returned
+ * by read_cntpct_el0() to simulate the down counter.
+ */
+ return (uint32_t)(~read_cntpct_el0());
+}
+
+static const timer_ops_t plat_timer_ops = {
+ .get_timer_value = plat_get_timer_value,
+ .clk_mult = 1,
+ .clk_div = SYS_COUNTER_FREQ_IN_MHZ,
+};
+
+void plat_delay_timer_init(void)
+{
+ timer_init(&plat_timer_ops);
+}
diff --git a/plat/mediatek/mt6795/plat_mt_gic.c b/plat/mediatek/mt6795/plat_mt_gic.c
new file mode 100644
index 0000000..8679d07
--- /dev/null
+++ b/plat/mediatek/mt6795/plat_mt_gic.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2016, 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 <gicv2.h>
+#include <plat_arm.h>
+#include <platform.h>
+#include <platform_def.h>
+
+const unsigned int g0_interrupt_array[] = {
+ PLAT_ARM_G0_IRQS
+};
+
+gicv2_driver_data_t arm_gic_data = {
+ .gicd_base = BASE_GICD_BASE,
+ .gicc_base = BASE_GICC_BASE,
+ .g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array),
+ .g0_interrupt_array = g0_interrupt_array,
+};
+
+void plat_mt_gic_driver_init(void)
+{
+ gicv2_driver_init(&arm_gic_data);
+}
+
+void plat_mt_gic_init(void)
+{
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
+
+void plat_mt_gic_cpuif_enable(void)
+{
+ gicv2_cpuif_enable();
+}
+
+void plat_mt_gic_cpuif_disable(void)
+{
+ gicv2_cpuif_disable();
+}
+
+void plat_mt_gic_pcpu_init(void)
+{
+ gicv2_pcpu_distif_init();
+}
diff --git a/plat/mediatek/mt6795/plat_pm.c b/plat/mediatek/mt6795/plat_pm.c
new file mode 100644
index 0000000..96fdab0
--- /dev/null
+++ b/plat/mediatek/mt6795/plat_pm.c
@@ -0,0 +1,495 @@
+/*
+ * Copyright (c) 2016, 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 <arm_gic.h>
+#include <assert.h>
+#include <bakery_lock.h>
+#include <cci.h>
+#include <console.h>
+#include <debug.h>
+#include <errno.h>
+#include <mcucfg.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <plat_private.h>
+#include <power_tracer.h>
+#include <psci.h>
+#include <scu.h>
+
+struct core_context {
+ unsigned long timer_data[8];
+ unsigned int count;
+ unsigned int rst;
+ unsigned int abt;
+ unsigned int brk;
+};
+
+struct cluster_context {
+ struct core_context core[PLATFORM_MAX_CPUS_PER_CLUSTER];
+};
+
+/*
+ * Top level structure to hold the complete context of a multi cluster system
+ */
+struct system_context {
+ struct cluster_context cluster[PLATFORM_CLUSTER_COUNT];
+};
+
+/*
+ * Top level structure which encapsulates the context of the entire system
+ */
+static struct system_context dormant_data[1];
+
+static inline struct cluster_context *system_cluster(
+ struct system_context *system,
+ uint32_t clusterid)
+{
+ return &system->cluster[clusterid];
+}
+
+static inline struct core_context *cluster_core(struct cluster_context *cluster,
+ uint32_t cpuid)
+{
+ return &cluster->core[cpuid];
+}
+
+static struct cluster_context *get_cluster_data(unsigned long mpidr)
+{
+ uint32_t clusterid;
+
+ clusterid = (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
+
+ return system_cluster(dormant_data, clusterid);
+}
+
+static struct core_context *get_core_data(unsigned long mpidr)
+{
+ struct cluster_context *cluster;
+ uint32_t cpuid;
+
+ cluster = get_cluster_data(mpidr);
+ cpuid = mpidr & MPIDR_CPU_MASK;
+
+ return cluster_core(cluster, cpuid);
+}
+
+static void mt_save_generic_timer(unsigned long *container)
+{
+ uint64_t ctl;
+ uint64_t val;
+
+ __asm__ volatile("mrs %x0, cntkctl_el1\n\t"
+ "mrs %x1, cntp_cval_el0\n\t"
+ "stp %x0, %x1, [%2, #0]"
+ : "=&r" (ctl), "=&r" (val)
+ : "r" (container)
+ : "memory");
+
+ __asm__ volatile("mrs %x0, cntp_tval_el0\n\t"
+ "mrs %x1, cntp_ctl_el0\n\t"
+ "stp %x0, %x1, [%2, #16]"
+ : "=&r" (val), "=&r" (ctl)
+ : "r" (container)
+ : "memory");
+
+ __asm__ volatile("mrs %x0, cntv_tval_el0\n\t"
+ "mrs %x1, cntv_ctl_el0\n\t"
+ "stp %x0, %x1, [%2, #32]"
+ : "=&r" (val), "=&r" (ctl)
+ : "r" (container)
+ : "memory");
+}
+
+static void mt_restore_generic_timer(unsigned long *container)
+{
+ uint64_t ctl;
+ uint64_t val;
+
+ __asm__ volatile("ldp %x0, %x1, [%2, #0]\n\t"
+ "msr cntkctl_el1, %x0\n\t"
+ "msr cntp_cval_el0, %x1"
+ : "=&r" (ctl), "=&r" (val)
+ : "r" (container)
+ : "memory");
+
+ __asm__ volatile("ldp %x0, %x1, [%2, #16]\n\t"
+ "msr cntp_tval_el0, %x0\n\t"
+ "msr cntp_ctl_el0, %x1"
+ : "=&r" (val), "=&r" (ctl)
+ : "r" (container)
+ : "memory");
+
+ __asm__ volatile("ldp %x0, %x1, [%2, #32]\n\t"
+ "msr cntv_tval_el0, %x0\n\t"
+ "msr cntv_ctl_el0, %x1"
+ : "=&r" (val), "=&r" (ctl)
+ : "r" (container)
+ : "memory");
+}
+
+static void stop_generic_timer(void)
+{
+ /*
+ * Disable the timer and mask the irq to prevent
+ * suprious interrupts on this cpu interface. It
+ * will bite us when we come back if we don't. It
+ * will be replayed on the inbound cluster.
+ */
+ uint64_t cntpctl = read_cntp_ctl_el0();
+
+ write_cntp_ctl_el0(clr_cntp_ctl_enable(cntpctl));
+}
+
+static void mt_cpu_save(unsigned long mpidr)
+{
+ struct core_context *core;
+
+ core = get_core_data(mpidr);
+ mt_save_generic_timer(core->timer_data);
+
+ /* disable timer irq, and upper layer should enable it again. */
+ stop_generic_timer();
+}
+
+static void mt_cpu_restore(unsigned long mpidr)
+{
+ struct core_context *core;
+
+ core = get_core_data(mpidr);
+ mt_restore_generic_timer(core->timer_data);
+}
+
+static void mt_platform_save_context(unsigned long mpidr)
+{
+ /* mcusys_save_context: */
+ mt_cpu_save(mpidr);
+}
+
+static void mt_platform_restore_context(unsigned long mpidr)
+{
+ /* mcusys_restore_context: */
+ mt_cpu_restore(mpidr);
+}
+
+/*******************************************************************************
+* Private 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 plat_do_plat_actions(unsigned int afflvl, unsigned int state)
+{
+ unsigned int max_phys_off_afflvl;
+
+ assert(afflvl <= MPIDR_AFFLVL2);
+
+ 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);
+ if (afflvl != max_phys_off_afflvl)
+ return -EAGAIN;
+
+ return 0;
+}
+
+/*******************************************************************************
+ * MTK_platform handler called when an affinity instance is about to enter
+ * standby.
+ ******************************************************************************/
+static void plat_affinst_standby(unsigned int power_state)
+{
+ unsigned int target_afflvl;
+
+ /* Sanity check the requested state */
+ target_afflvl = psci_get_pstate_afflvl(power_state);
+
+ /*
+ * It's possible to enter standby only on affinity level 0 i.e. a cpu
+ * on the MTK_platform. Ignore any other affinity level.
+ */
+ if (target_afflvl == MPIDR_AFFLVL0) {
+ /*
+ * Enter standby state. dsb is good practice before using wfi
+ * to enter low power states.
+ */
+ dsb();
+ wfi();
+ }
+}
+
+/*******************************************************************************
+ * MTK_platform handler called when an affinity instance is about to be turned
+ * on. The level and mpidr determine the affinity instance.
+ ******************************************************************************/
+static int plat_affinst_on(unsigned long mpidr,
+ unsigned long sec_entrypoint,
+ unsigned int afflvl,
+ unsigned int state)
+{
+ int rc = PSCI_E_SUCCESS;
+ unsigned long cpu_id;
+ unsigned long cluster_id;
+ uintptr_t rv;
+
+ /*
+ * It's possible to turn on only affinity level 0 i.e. a cpu
+ * on the MTK_platform. Ignore any other affinity level.
+ */
+ if (afflvl != MPIDR_AFFLVL0)
+ return rc;
+
+ cpu_id = mpidr & MPIDR_CPU_MASK;
+ cluster_id = mpidr & MPIDR_CLUSTER_MASK;
+
+ if (cluster_id)
+ rv = (uintptr_t)&mt6795_mcucfg->mp1_rv_addr[cpu_id].rv_addr_lw;
+ else
+ rv = (uintptr_t)&mt6795_mcucfg->mp0_rv_addr[cpu_id].rv_addr_lw;
+
+ mmio_write_32(rv, sec_entrypoint);
+ INFO("mt_on[%ld:%ld], entry %x\n",
+ cluster_id, cpu_id, mmio_read_32(rv));
+
+ return rc;
+}
+
+/*******************************************************************************
+ * MTK_platform handler called when an affinity instance is about to be turned
+ * off. The level and mpidr determine the affinity instance. The 'state' arg.
+ * allows the platform to decide whether the cluster is being turned off and
+ * take apt actions.
+ *
+ * CAUTION: This function is called with coherent stacks so that caches can be
+ * turned off, flushed and coherency disabled. There is no guarantee that caches
+ * will remain turned on across calls to this function as each affinity level is
+ * dealt with. So do not write & read global variables across calls. It will be
+ * wise to do flush a write to the global to prevent unpredictable results.
+ ******************************************************************************/
+static void plat_affinst_off(unsigned int afflvl, unsigned int state)
+{
+ unsigned long mpidr = read_mpidr_el1();
+
+ /* Determine if any platform actions need to be executed. */
+ if (plat_do_plat_actions(afflvl, state) == -EAGAIN)
+ return;
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ plat_mt_gic_cpuif_disable();
+
+ trace_power_flow(mpidr, CPU_DOWN);
+
+ if (afflvl != MPIDR_AFFLVL0) {
+ /* Disable coherency if this cluster is to be turned off */
+ plat_cci_disable();
+
+ trace_power_flow(mpidr, CLUSTER_DOWN);
+ }
+}
+
+/*******************************************************************************
+ * MTK_platform handler called when an affinity instance is about to be
+ * suspended. The level and mpidr determine the affinity instance. The 'state'
+ * arg. allows the platform to decide whether the cluster is being turned off
+ * and take apt actions.
+ *
+ * CAUTION: This function is called with coherent stacks so that caches can be
+ * turned off, flushed and coherency disabled. There is no guarantee that caches
+ * will remain turned on across calls to this function as each affinity level is
+ * dealt with. So do not write & read global variables across calls. It will be
+ * wise to do flush a write to the global to prevent unpredictable results.
+ ******************************************************************************/
+static void plat_affinst_suspend(unsigned long sec_entrypoint,
+ unsigned int afflvl,
+ unsigned int state)
+{
+ unsigned long mpidr = read_mpidr_el1();
+ unsigned long cluster_id;
+ unsigned long cpu_id;
+ uintptr_t rv;
+
+ /* Determine if any platform actions need to be executed. */
+ if (plat_do_plat_actions(afflvl, state) == -EAGAIN)
+ return;
+
+ cpu_id = mpidr & MPIDR_CPU_MASK;
+ cluster_id = mpidr & MPIDR_CLUSTER_MASK;
+
+ if (cluster_id)
+ rv = (uintptr_t)&mt6795_mcucfg->mp1_rv_addr[cpu_id].rv_addr_lw;
+ else
+ rv = (uintptr_t)&mt6795_mcucfg->mp0_rv_addr[cpu_id].rv_addr_lw;
+
+ mmio_write_32(rv, sec_entrypoint);
+
+ if (afflvl >= MPIDR_AFFLVL0)
+ mt_platform_save_context(mpidr);
+
+ /* Perform the common cluster specific operations */
+ if (afflvl >= MPIDR_AFFLVL1) {
+ /* Disable coherency if this cluster is to be turned off */
+ plat_cci_disable();
+ disable_scu(mpidr);
+
+ trace_power_flow(mpidr, CLUSTER_SUSPEND);
+ }
+
+ if (afflvl >= MPIDR_AFFLVL2) {
+ /* Prevent interrupts from spuriously waking up this cpu */
+ plat_mt_gic_cpuif_disable();
+ }
+}
+
+/*******************************************************************************
+ * MTK_platform 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.
+ ******************************************************************************/
+static void plat_affinst_on_finish(unsigned int afflvl, unsigned int state)
+{
+ unsigned long mpidr = read_mpidr_el1();
+
+ /* Determine if any platform actions need to be executed. */
+ if (plat_do_plat_actions(afflvl, state) == -EAGAIN)
+ return;
+
+ /* Perform the common cluster specific operations */
+ if (afflvl >= MPIDR_AFFLVL1) {
+ enable_scu(mpidr);
+
+ /* Enable coherency if this cluster was off */
+ plat_cci_enable();
+ trace_power_flow(mpidr, CLUSTER_UP);
+ }
+
+ /* Enable the gic cpu interface */
+ plat_mt_gic_cpuif_enable();
+ plat_mt_gic_pcpu_init();
+ trace_power_flow(mpidr, CPU_UP);
+}
+
+/*******************************************************************************
+ * MTK_platform handler called when an affinity instance has just been powered
+ * on after having been suspended earlier. The level and mpidr determine the
+ * affinity instance.
+ ******************************************************************************/
+static void plat_affinst_suspend_finish(unsigned int afflvl, unsigned int state)
+{
+ unsigned long mpidr = read_mpidr_el1();
+
+ /* Determine if any platform actions need to be executed. */
+ if (plat_do_plat_actions(afflvl, state) == -EAGAIN)
+ return;
+
+ if (afflvl >= MPIDR_AFFLVL2) {
+ /* Enable the gic cpu interface */
+ plat_mt_gic_init();
+ plat_mt_gic_cpuif_enable();
+ }
+
+ /* Perform the common cluster specific operations */
+ if (afflvl >= MPIDR_AFFLVL1) {
+ enable_scu(mpidr);
+
+ /* Enable coherency if this cluster was off */
+ plat_cci_enable();
+ trace_power_flow(mpidr, CLUSTER_UP);
+ }
+
+ if (afflvl >= MPIDR_AFFLVL0)
+ mt_platform_restore_context(mpidr);
+
+ plat_mt_gic_pcpu_init();
+}
+
+static unsigned int plat_get_sys_suspend_power_state(void)
+{
+ /* StateID: 0, StateType: 1(power down), PowerLevel: 2(system) */
+ return psci_make_powerstate(0, 1, 2);
+}
+
+/*******************************************************************************
+ * MTK handlers to shutdown/reboot the system
+ ******************************************************************************/
+static void __dead2 plat_system_off(void)
+{
+ INFO("MTK System Off\n");
+ wfi();
+ ERROR("MTK System Off: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 plat_system_reset(void)
+{
+ /* Write the System Configuration Control Register */
+ INFO("MTK System Reset\n");
+
+ mmio_clrbits_32(MTK_WDT_BASE,
+ (MTK_WDT_MODE_DUAL_MODE | MTK_WDT_MODE_IRQ));
+ mmio_setbits_32(MTK_WDT_BASE, (MTK_WDT_MODE_KEY | MTK_WDT_MODE_EXTEN));
+ mmio_setbits_32(MTK_WDT_SWRST, MTK_WDT_SWRST_KEY);
+
+ wfi();
+ ERROR("MTK System Reset: operation not handled.\n");
+ panic();
+}
+
+/*******************************************************************************
+ * Export the platform handlers to enable psci to invoke them
+ ******************************************************************************/
+static const plat_pm_ops_t plat_plat_pm_ops = {
+ .affinst_standby = plat_affinst_standby,
+ .affinst_on = plat_affinst_on,
+ .affinst_off = plat_affinst_off,
+ .affinst_suspend = plat_affinst_suspend,
+ .affinst_on_finish = plat_affinst_on_finish,
+ .affinst_suspend_finish = plat_affinst_suspend_finish,
+ .system_off = plat_system_off,
+ .system_reset = plat_system_reset,
+ .get_sys_suspend_power_state = plat_get_sys_suspend_power_state,
+};
+
+/*******************************************************************************
+ * Export the platform specific power ops & initialize the mtk_platform power
+ * controller
+ ******************************************************************************/
+int platform_setup_pm(const plat_pm_ops_t **plat_ops)
+{
+ *plat_ops = &plat_plat_pm_ops;
+ return 0;
+}
diff --git a/plat/mediatek/mt6795/plat_sip_svc.c b/plat/mediatek/mt6795/plat_sip_svc.c
new file mode 100644
index 0000000..9bb0f34
--- /dev/null
+++ b/plat/mediatek/mt6795/plat_sip_svc.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <console.h>
+#include <debug.h>
+#include <mmio.h>
+#include <mt_cpuxgpt.h>
+#include <mtk_sip_svc.h>
+#include <plat_private.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <mtk_plat_common.h>
+#include <runtime_svc.h>
+#include <xlat_tables.h>
+
+/*******************************************************************************
+ * SIP top level handler for servicing SMCs.
+ ******************************************************************************/
+uint64_t mediatek_plat_sip_handler(uint32_t smc_fid,
+ uint64_t x1,
+ uint64_t x2,
+ uint64_t x3,
+ uint64_t x4,
+ void *cookie,
+ void *handle,
+ uint64_t flags)
+{
+ uint64_t rc = 0;
+ uint32_t ns;
+
+ /* Determine which security state this SMC originated from */
+ ns = is_caller_non_secure(flags);
+
+ VERBOSE("sip_smc_handler\n");
+ VERBOSE("id=0x%x\n", smc_fid);
+ VERBOSE("x1=0x%lx, x2=0x%lx, x3=0x%lx, x4=0x%lx\n", x1, x2, x3, x4);
+
+ if (!ns) {
+ /* SiP SMC service secure world's call */
+ switch (smc_fid) {
+ default:
+ rc = SMC_UNK;
+ }
+ } else {
+ /* SiP SMC service normal world's call */
+ switch (smc_fid) {
+ default:
+ rc = SMC_UNK;
+ }
+ }
+
+ if (rc == SMC_UNK) {
+ console_init(gteearg.atf_log_port,
+ UART_CLOCK, UART_BAUDRATE);
+ ERROR("%s: unhandled NS(%d) SMC (0x%x)\n",
+ __func__, ns, smc_fid);
+ console_uninit();
+ }
+ SMC_RET1(handle, rc);
+}
diff --git a/plat/mediatek/mt6795/plat_topology.c b/plat/mediatek/mt6795/plat_topology.c
new file mode 100644
index 0000000..b1feac0
--- /dev/null
+++ b/plat/mediatek/mt6795/plat_topology.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <platform_def.h>
+#include <psci.h>
+
+unsigned int plat_get_aff_count(unsigned int aff_lvl, unsigned long mpidr)
+{
+ /* Report 1 (absent) instance at levels higher that the cluster level */
+ if (aff_lvl > MPIDR_AFFLVL1)
+ return PLATFORM_SYSTEM_COUNT;
+
+ if (aff_lvl == MPIDR_AFFLVL1)
+ return PLATFORM_CLUSTER_COUNT;
+
+ return mpidr & 0x100 ? PLATFORM_CLUSTER1_CORE_COUNT :
+ PLATFORM_CLUSTER0_CORE_COUNT;
+}
+
+unsigned int plat_get_aff_state(unsigned int aff_lvl, unsigned long mpidr)
+{
+ return aff_lvl <= MPIDR_AFFLVL2 ? PSCI_AFF_PRESENT : PSCI_AFF_ABSENT;
+}
+
+int mt_setup_topology(void)
+{
+ /* [TODO] Make topology configurable via SCC */
+ return 0;
+}
diff --git a/plat/mediatek/mt6795/platform.mk b/plat/mediatek/mt6795/platform.mk
new file mode 100644
index 0000000..97f2e1c
--- /dev/null
+++ b/plat/mediatek/mt6795/platform.mk
@@ -0,0 +1,95 @@
+#
+# Copyright (c) 2016, 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.
+#
+
+MTK_PLAT := plat/mediatek
+MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT}
+
+# Add OEM customized codes
+OEMS := true
+MTK_SIP_KERNEL_BOOT_ENABLE := 1
+
+
+ifneq (${OEMS},none)
+ OEMS_INCLUDES := -I${MTK_PLAT}/common/custom/
+ OEMS_SOURCES := ${MTK_PLAT}/common/custom/oem_svc.c
+endif
+
+PLAT_INCLUDES := -I${MTK_PLAT}/common/ \
+ -I${MTK_PLAT}/common/drivers/uart \
+ -I${MTK_PLAT_SOC}/ \
+ -I${MTK_PLAT_SOC}/drivers/timer/ \
+ -I${MTK_PLAT_SOC}/include/ \
+ -Iinclude/plat/arm/common/ \
+ -Iinclude/common/tbbr/ \
+ ${OEMS_INCLUDES}
+
+PLAT_BL_COMMON_SOURCES := lib/aarch64/xlat_tables.c \
+ plat/common/aarch64/plat_common.c \
+ plat/common/plat_gic.c
+
+BL31_SOURCES += drivers/arm/cci/cci.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v2/gicv2_main.c \
+ drivers/arm/gic/v2/gicv2_helpers.c \
+ plat/common/plat_gicv2.c \
+ drivers/console/console.S \
+ drivers/delay_timer/delay_timer.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ plat/common/aarch64/platform_mp_stack.S \
+ ${MTK_PLAT_SOC}/bl31_plat_setup.c \
+ ${MTK_PLAT_SOC}/plat_mt_gic.c \
+ ${MTK_PLAT}/common/mtk_sip_svc.c \
+ ${MTK_PLAT}/common/mtk_plat_common.c \
+ ${MTK_PLAT}/common/drivers/uart/8250_console.S \
+ ${MTK_PLAT_SOC}/aarch64/plat_helpers.S \
+ ${MTK_PLAT_SOC}/drivers/timer/mt_cpuxgpt.c \
+ ${MTK_PLAT_SOC}/plat_sip_svc.c \
+ ${MTK_PLAT_SOC}/plat_delay_timer.c \
+ ${MTK_PLAT_SOC}/plat_pm.c \
+ ${MTK_PLAT_SOC}/plat_topology.c \
+ ${MTK_PLAT_SOC}/power_tracer.c \
+ ${MTK_PLAT_SOC}/scu.c \
+ ${OEMS_SOURCES}
+
+# Flag used by the MTK_platform port to determine the version of ARM GIC
+# architecture to use for interrupt management in EL3.
+ARM_GIC_ARCH := 2
+$(eval $(call add_define,ARM_GIC_ARCH))
+
+# Enable workarounds for selected Cortex-A53 erratas.
+ERRATA_A53_826319 := 1
+ERRATA_A53_836870 := 1
+
+# indicate the reset vector address can be programmed
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+$(eval $(call add_define,MTK_SIP_KERNEL_BOOT_ENABLE))
+
diff --git a/plat/mediatek/mt6795/power_tracer.c b/plat/mediatek/mt6795/power_tracer.c
new file mode 100644
index 0000000..e6ea434
--- /dev/null
+++ b/plat/mediatek/mt6795/power_tracer.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016, 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 <debug.h>
+#include <power_tracer.h>
+
+#define trace_log(...) INFO("psci: " __VA_ARGS__)
+
+void trace_power_flow(unsigned long mpidr, unsigned char mode)
+{
+ switch (mode) {
+ case CPU_UP:
+ trace_log("core %ld:%ld ON\n",
+ (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS,
+ (mpidr & MPIDR_CPU_MASK));
+ break;
+ case CPU_DOWN:
+ trace_log("core %ld:%ld OFF\n",
+ (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS,
+ (mpidr & MPIDR_CPU_MASK));
+ break;
+ case CPU_SUSPEND:
+ trace_log("core %ld:%ld SUSPEND\n",
+ (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS,
+ (mpidr & MPIDR_CPU_MASK));
+ break;
+ case CLUSTER_UP:
+ trace_log("cluster %ld ON\n",
+ (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS);
+ break;
+ case CLUSTER_DOWN:
+ trace_log("cluster %ld OFF\n",
+ (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS);
+ break;
+ case CLUSTER_SUSPEND:
+ trace_log("cluster %ld SUSPEND\n",
+ (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS);
+ break;
+ default:
+ trace_log("unknown power mode\n");
+ break;
+ }
+}
diff --git a/plat/mediatek/mt6795/scu.c b/plat/mediatek/mt6795/scu.c
new file mode 100644
index 0000000..1f4ae6e
--- /dev/null
+++ b/plat/mediatek/mt6795/scu.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016, 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 <mcucfg.h>
+#include <mmio.h>
+
+void disable_scu(unsigned long mpidr)
+{
+ if (mpidr & MPIDR_CLUSTER_MASK)
+ mmio_setbits_32((uintptr_t)&mt6795_mcucfg->mp1_miscdbg,
+ MP1_ACINACTM);
+ else
+ mmio_setbits_32((uintptr_t)&mt6795_mcucfg->mp0_axi_config,
+ MP0_ACINACTM);
+}
+
+void enable_scu(unsigned long mpidr)
+{
+ if (mpidr & MPIDR_CLUSTER_MASK)
+ mmio_clrbits_32((uintptr_t)&mt6795_mcucfg->mp1_miscdbg,
+ MP1_ACINACTM);
+ else
+ mmio_clrbits_32((uintptr_t)&mt6795_mcucfg->mp0_axi_config,
+ MP0_ACINACTM);
+}
diff --git a/plat/mediatek/mt8173/platform.mk b/plat/mediatek/mt8173/platform.mk
index c815110..54ca475 100644
--- a/plat/mediatek/mt8173/platform.mk
+++ b/plat/mediatek/mt8173/platform.mk
@@ -32,13 +32,13 @@
MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT}
PLAT_INCLUDES := -I${MTK_PLAT}/common/ \
+ -I${MTK_PLAT}/common/drivers/uart/ \
-I${MTK_PLAT_SOC}/drivers/crypt/ \
-I${MTK_PLAT_SOC}/drivers/mtcmos/ \
-I${MTK_PLAT_SOC}/drivers/pmic/ \
-I${MTK_PLAT_SOC}/drivers/rtc/ \
-I${MTK_PLAT_SOC}/drivers/spm/ \
-I${MTK_PLAT_SOC}/drivers/timer/ \
- -I${MTK_PLAT_SOC}/drivers/uart/ \
-I${MTK_PLAT_SOC}/include/
PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \
@@ -58,6 +58,7 @@
lib/cpus/aarch64/cortex_a57.S \
lib/cpus/aarch64/cortex_a72.S \
plat/common/aarch64/platform_mp_stack.S \
+ ${MTK_PLAT}/common/drivers/uart/8250_console.S \
${MTK_PLAT}/common/mtk_plat_common.c \
${MTK_PLAT}/common/mtk_sip_svc.c \
${MTK_PLAT_SOC}/aarch64/plat_helpers.S \
@@ -72,7 +73,6 @@
${MTK_PLAT_SOC}/drivers/spm/spm_mcdi.c \
${MTK_PLAT_SOC}/drivers/spm/spm_suspend.c \
${MTK_PLAT_SOC}/drivers/timer/mt_cpuxgpt.c \
- ${MTK_PLAT_SOC}/drivers/uart/8250_console.S \
${MTK_PLAT_SOC}/plat_mt_gic.c \
${MTK_PLAT_SOC}/plat_pm.c \
${MTK_PLAT_SOC}/plat_sip_calls.c \
diff --git a/plat/rockchip/common/include/plat_params.h b/plat/rockchip/common/include/plat_params.h
index cad4535..8c64796 100644
--- a/plat/rockchip/common/include/plat_params.h
+++ b/plat/rockchip/common/include/plat_params.h
@@ -63,11 +63,31 @@
* alignment fault will occur during accessing its data member.
*/
+#define BL31_GPIO_DIR_OUT 0
+#define BL31_GPIO_DIR_IN 1
+
+#define BL31_GPIO_LEVEL_LOW 0
+#define BL31_GPIO_LEVEL_HIGH 1
+
+#define BL31_GPIO_PULL_NONE 0
+#define BL31_GPIO_PULL_UP 1
+#define BL31_GPIO_PULL_DOWN 2
+
/* param type */
enum {
PARAM_NONE = 0,
PARAM_RESET,
PARAM_POWEROFF,
+ PARAM_SUSPEND_GPIO,
+ PARAM_SUSPEND_APIO,
+};
+
+struct apio_info {
+ uint8_t apio1 : 1;
+ uint8_t apio2 : 1;
+ uint8_t apio3 : 1;
+ uint8_t apio4 : 1;
+ uint8_t apio5 : 1;
};
struct gpio_info {
@@ -88,4 +108,9 @@
struct gpio_info gpio;
};
+struct bl31_apio_param {
+ struct bl31_plat_param h;
+ struct apio_info apio;
+};
+
#endif /* __PLAT_PARAMS_H__ */
diff --git a/plat/rockchip/common/include/plat_private.h b/plat/rockchip/common/include/plat_private.h
index b9b634e..ad01266 100644
--- a/plat/rockchip/common/include/plat_private.h
+++ b/plat/rockchip/common/include/plat_private.h
@@ -121,8 +121,10 @@
void platform_cpu_warmboot(void);
-void *plat_get_rockchip_gpio_reset(void);
-void *plat_get_rockchip_gpio_poweroff(void);
+struct gpio_info *plat_get_rockchip_gpio_reset(void);
+struct gpio_info *plat_get_rockchip_gpio_poweroff(void);
+struct gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count);
+struct apio_info *plat_get_rockchip_suspend_apio(void);
void plat_rockchip_gpio_init(void);
extern const unsigned char rockchip_power_domain_tree_desc[];
diff --git a/plat/rockchip/common/params_setup.c b/plat/rockchip/common/params_setup.c
index 2a49556..646c1e1 100644
--- a/plat/rockchip/common/params_setup.c
+++ b/plat/rockchip/common/params_setup.c
@@ -40,25 +40,39 @@
#include <plat_private.h>
#include <string.h>
-static struct bl31_plat_param *bl31_params_head;
-static struct bl31_gpio_param param_reset;
-static struct bl31_gpio_param param_poweroff;
+static struct gpio_info param_reset;
+static struct gpio_info param_poweroff;
+static struct bl31_apio_param param_apio;
static struct gpio_info *rst_gpio;
static struct gpio_info *poweroff_gpio;
+static struct gpio_info suspend_gpio[10];
+uint32_t suspend_gpio_cnt;
+static struct apio_info *suspend_apio;
-void *plat_get_rockchip_gpio_reset(void)
+struct gpio_info *plat_get_rockchip_gpio_reset(void)
{
return rst_gpio;
}
-void *plat_get_rockchip_gpio_poweroff(void)
+struct gpio_info *plat_get_rockchip_gpio_poweroff(void)
{
return poweroff_gpio;
}
+struct gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count)
+{
+ *count = suspend_gpio_cnt;
+
+ return &suspend_gpio[0];
+}
+
+struct apio_info *plat_get_rockchip_suspend_apio(void)
+{
+ return suspend_apio;
+}
+
void params_early_setup(void *plat_param_from_bl2)
{
- struct bl31_plat_param *param;
struct bl31_plat_param *bl2_param;
struct bl31_gpio_param *gpio_param;
@@ -67,25 +81,38 @@
while (bl2_param) {
switch (bl2_param->type) {
case PARAM_RESET:
- param = (struct bl31_plat_param *)¶m_reset;
- memcpy((void *)param, (void *)bl2_param,
- sizeof(struct bl31_gpio_param));
- gpio_param = (struct bl31_gpio_param *)param;
- rst_gpio = &gpio_param->gpio;
+ gpio_param = (struct bl31_gpio_param *)bl2_param;
+ memcpy(¶m_reset, &gpio_param->gpio,
+ sizeof(struct gpio_info));
+ rst_gpio = ¶m_reset;
break;
case PARAM_POWEROFF:
- param = (struct bl31_plat_param *)¶m_poweroff;
- memcpy((void *)param, (void *)bl2_param,
- sizeof(struct bl31_gpio_param));
- gpio_param = (struct bl31_gpio_param *)param;
- poweroff_gpio = &gpio_param->gpio;
+ gpio_param = (struct bl31_gpio_param *)bl2_param;
+ memcpy(¶m_poweroff, &gpio_param->gpio,
+ sizeof(struct gpio_info));
+ poweroff_gpio = ¶m_poweroff;
+ break;
+ case PARAM_SUSPEND_GPIO:
+ if (suspend_gpio_cnt >= ARRAY_SIZE(suspend_gpio)) {
+ ERROR("exceed support suspend gpio number\n");
+ break;
+ }
+ gpio_param = (struct bl31_gpio_param *)bl2_param;
+ memcpy(&suspend_gpio[suspend_gpio_cnt],
+ &gpio_param->gpio,
+ sizeof(struct gpio_info));
+ suspend_gpio_cnt++;
+ break;
+ case PARAM_SUSPEND_APIO:
+ memcpy(¶m_apio, bl2_param,
+ sizeof(struct bl31_apio_param));
+ suspend_apio = ¶m_apio.apio;
break;
default:
- NOTICE("not expected type found\n");
- return; /* don't continue if unexpected type found */
+ ERROR("not expected type found %ld\n",
+ bl2_param->type);
+ break;
}
- param->next = bl31_params_head;
- bl31_params_head = param;
bl2_param = bl2_param->next;
}
}
diff --git a/plat/rockchip/common/plat_pm.c b/plat/rockchip/common/plat_pm.c
old mode 100755
new mode 100644
index 3c2c79a..d28100d
--- a/plat/rockchip/common/plat_pm.c
+++ b/plat/rockchip/common/plat_pm.c
@@ -283,9 +283,10 @@
rockchip_ops->cores_pwr_dm_resume();
/*
* Program the gic per-cpu distributor or re-distributor interface.
- * For sys power domain operation, resuming of the gic needs to operate in
- * rockchip_ops->sys_pwr_dm_resume, according to the sys power mode implements.
- */
+ * For sys power domain operation, resuming of the gic needs to operate
+ * in rockchip_ops->sys_pwr_dm_resume, according to the sys power mode
+ * implements.
+ */
plat_rockchip_gic_cpuif_enable();
comm_finish:
diff --git a/plat/rockchip/rk3399/drivers/dram/dram.c b/plat/rockchip/rk3399/drivers/dram/dram.c
index ddae84d..94aa076 100644
--- a/plat/rockchip/rk3399/drivers/dram/dram.c
+++ b/plat/rockchip/rk3399/drivers/dram/dram.c
@@ -2147,7 +2147,7 @@
{
int pll_cnt, i;
- pll_cnt = sizeof(dpll_rates_table) / sizeof(struct pll_div);
+ pll_cnt = ARRAY_SIZE(dpll_rates_table);
/* Assumming rate_table is in descending order */
for (i = 0; i < pll_cnt; i++) {
@@ -2155,6 +2155,10 @@
break;
}
+ /* if mhz lower than lowest frequency in table, use lowest frequency */
+ if (i == pll_cnt)
+ i = pll_cnt - 1;
+
return i;
}
@@ -2174,7 +2178,7 @@
return (24 * fbdiv) / refdiv / postdiv1 / postdiv2;
}
-uint64_t ddr_get_rate(void)
+uint32_t ddr_get_rate(void)
{
uint32_t refdiv, postdiv1, fbdiv, postdiv2;
@@ -2464,7 +2468,6 @@
* target freq.
*/
dram_get_parameter(&rk3399_dram_status.timing_config, &dram_timing);
-
gen_rk3399_ctl_params(&rk3399_dram_status.timing_config,
&dram_timing, index);
gen_rk3399_pi_params(&rk3399_dram_status.timing_config,
@@ -2494,7 +2497,7 @@
tf_printf("%u\n", p[i]);
}
-uint64_t ddr_set_rate(uint64_t hz)
+uint32_t ddr_set_rate(uint32_t hz)
{
uint32_t low_power, index;
uint32_t mhz = hz / (1000 * 1000);
@@ -2503,13 +2506,13 @@
rk3399_dram_status.index_freq[rk3399_dram_status.current_index])
goto out;
+ index = to_get_clk_index(mhz);
+ mhz = dpll_rates_table[index].mhz;
+
low_power = exit_low_power();
index = prepare_ddr_timing(mhz);
- if (index > 1) {
- /* set timing error, quit */
- mhz = 0;
+ if (index > 1)
goto out;
- }
dcf_start(mhz, index);
wait_dcf_done();
@@ -2526,7 +2529,7 @@
return mhz;
}
-uint64_t ddr_round_rate(uint64_t hz)
+uint32_t ddr_round_rate(uint32_t hz)
{
int index;
uint32_t mhz = hz / (1000 * 1000);
@@ -2536,7 +2539,7 @@
return dpll_rates_table[index].mhz * 1000 * 1000;
}
-uint64_t dts_timing_receive(uint64_t timing, uint64_t index)
+uint32_t dts_timing_receive(uint32_t timing, uint32_t index)
{
uint32_t *p = (uint32_t *) &dts_parameter;
static uint32_t receive_nums;
diff --git a/plat/rockchip/rk3399/drivers/dram/dram.h b/plat/rockchip/rk3399/drivers/dram/dram.h
index 62c5170..4f99070 100644
--- a/plat/rockchip/rk3399/drivers/dram/dram.h
+++ b/plat/rockchip/rk3399/drivers/dram/dram.h
@@ -321,9 +321,9 @@
#define DDR_RESTORE_SP(save_sp) ddr_save_sp(save_sp)
void ddr_init(void);
-uint64_t ddr_set_rate(uint64_t hz);
-uint64_t ddr_round_rate(uint64_t hz);
-uint64_t ddr_get_rate(void);
+uint32_t ddr_set_rate(uint32_t hz);
+uint32_t ddr_round_rate(uint32_t hz);
+uint32_t ddr_get_rate(void);
void clr_dcf_irq(void);
-uint64_t dts_timing_receive(uint64_t timing, uint64_t index);
+uint32_t dts_timing_receive(uint32_t timing, uint32_t index);
#endif
diff --git a/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c b/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c
index eca9fbc..4995d56 100644
--- a/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c
+++ b/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c
@@ -52,48 +52,105 @@
#define PMU_GPIO_PORT0 0
#define PMU_GPIO_PORT1 1
+#define GPIO_PORT2 2
+#define GPIO_PORT3 3
+#define GPIO_PORT4 4
#define PMU_GRF_GPIO0A_P 0x40
#define GRF_GPIO2A_P 0xe040
#define GPIO_P_MASK 0x03
-/*
- * gpio clock disabled when not operate
- * so need to enable gpio clock before operate gpio
- * after setting, need to disable gpio clock
- * gate 1: disable clock; 0: enable clock
- */
-static void gpio_clk(int gpio, uint32_t gate)
+#define GET_GPIO_PORT(pin) (pin / 32)
+#define GET_GPIO_NUM(pin) (pin % 32)
+#define GET_GPIO_BANK(pin) ((pin % 32) / 8)
+#define GET_GPIO_ID(pin) ((pin % 32) % 8)
+
+/* returns old clock state, enables clock, in order to do GPIO access */
+static int gpio_get_clock(uint32_t gpio_number)
{
- uint32_t port = gpio / 32;
+ uint32_t port = GET_GPIO_PORT(gpio_number);
+ uint32_t clock_state = 0;
assert(port < 5);
switch (port) {
- case 0:
+ case PMU_GPIO_PORT0:
+ clock_state = (mmio_read_32(PMUCRU_BASE +
+ CRU_PMU_CLKGATE_CON(1)) >>
+ PCLK_GPIO0_GATE_SHIFT) & 0x01;
mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1),
- BITS_WITH_WMASK(gate, CLK_GATE_MASK,
+ BITS_WITH_WMASK(0, CLK_GATE_MASK,
PCLK_GPIO0_GATE_SHIFT));
break;
- case 1:
+ case PMU_GPIO_PORT1:
+ clock_state = (mmio_read_32(PMUCRU_BASE +
+ CRU_PMU_CLKGATE_CON(1)) >>
+ PCLK_GPIO1_GATE_SHIFT) & 0x01;
mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1),
- BITS_WITH_WMASK(gate, CLK_GATE_MASK,
+ BITS_WITH_WMASK(0, CLK_GATE_MASK,
PCLK_GPIO1_GATE_SHIFT));
break;
- case 2:
+ case GPIO_PORT2:
+ clock_state = (mmio_read_32(CRU_BASE +
+ CRU_CLKGATE_CON(31)) >>
+ PCLK_GPIO2_GATE_SHIFT) & 0x01;
mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
- BITS_WITH_WMASK(gate, CLK_GATE_MASK,
+ BITS_WITH_WMASK(0, CLK_GATE_MASK,
PCLK_GPIO2_GATE_SHIFT));
break;
- case 3:
+ case GPIO_PORT3:
+ clock_state = (mmio_read_32(CRU_BASE +
+ CRU_CLKGATE_CON(31)) >>
+ PCLK_GPIO3_GATE_SHIFT) & 0x01;
mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
- BITS_WITH_WMASK(gate, CLK_GATE_MASK,
+ BITS_WITH_WMASK(0, CLK_GATE_MASK,
PCLK_GPIO3_GATE_SHIFT));
+ break;
+ case GPIO_PORT4:
+ clock_state = (mmio_read_32(CRU_BASE +
+ CRU_CLKGATE_CON(31)) >>
+ PCLK_GPIO4_GATE_SHIFT) & 0x01;
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
+ BITS_WITH_WMASK(0, CLK_GATE_MASK,
+ PCLK_GPIO4_GATE_SHIFT));
+ break;
+ default:
+ break;
+ }
+
+ return clock_state;
+}
+
+/* restores old state of gpio clock */
+void gpio_put_clock(uint32_t gpio_number, uint32_t clock_state)
+{
+ uint32_t port = GET_GPIO_PORT(gpio_number);
+ switch (port) {
+ case PMU_GPIO_PORT0:
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1),
+ BITS_WITH_WMASK(clock_state, CLK_GATE_MASK,
+ PCLK_GPIO0_GATE_SHIFT));
+ break;
+ case PMU_GPIO_PORT1:
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1),
+ BITS_WITH_WMASK(clock_state, CLK_GATE_MASK,
+ PCLK_GPIO1_GATE_SHIFT));
break;
- case 4:
+ case GPIO_PORT2:
mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
- BITS_WITH_WMASK(gate, CLK_GATE_MASK,
+ BITS_WITH_WMASK(clock_state, CLK_GATE_MASK,
+ PCLK_GPIO2_GATE_SHIFT));
+ break;
+ case GPIO_PORT3:
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
+ BITS_WITH_WMASK(clock_state, CLK_GATE_MASK,
+ PCLK_GPIO3_GATE_SHIFT));
+
+ break;
+ case GPIO_PORT4:
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
+ BITS_WITH_WMASK(clock_state, CLK_GATE_MASK,
PCLK_GPIO4_GATE_SHIFT));
break;
default:
@@ -101,16 +158,58 @@
}
}
+static int get_pull(int gpio)
+{
+ uint32_t port = GET_GPIO_PORT(gpio);
+ uint32_t bank = GET_GPIO_BANK(gpio);
+ uint32_t id = GET_GPIO_ID(gpio);
+ uint32_t val, clock_state;
+
+ assert((port < 5) && (bank < 4));
+
+ clock_state = gpio_get_clock(gpio);
+
+ if (port == PMU_GPIO_PORT0 || port == PMU_GPIO_PORT1) {
+ val = mmio_read_32(PMUGRF_BASE + PMU_GRF_GPIO0A_P +
+ port * 16 + bank * 4);
+ val = (val >> (id * 2)) & GPIO_P_MASK;
+ } else {
+ val = mmio_read_32(GRF_BASE + GRF_GPIO2A_P +
+ (port - 2) * 16 + bank * 4);
+ val = (val >> (id * 2)) & GPIO_P_MASK;
+ }
+ gpio_put_clock(gpio, clock_state);
+
+ /*
+ * in gpio0a, gpio0b, gpio2c, gpio2d,
+ * 00: Z
+ * 01: pull down
+ * 10: Z
+ * 11: pull up
+ * different with other gpio, so need to correct it
+ */
+ if (((port == 0) && (bank < 2)) || ((port == 2) && (bank > 1))) {
+ if (val == 3)
+ val = GPIO_PULL_UP;
+ else if (val == 1)
+ val = GPIO_PULL_DOWN;
+ else
+ val = 0;
+ }
+
+ return val;
+}
+
static void set_pull(int gpio, int pull)
{
- uint32_t port = gpio / 32;
- uint32_t num = gpio % 32;
- uint32_t bank = num / 8;
- uint32_t id = num % 8;
+ uint32_t port = GET_GPIO_PORT(gpio);
+ uint32_t bank = GET_GPIO_BANK(gpio);
+ uint32_t id = GET_GPIO_ID(gpio);
+ uint32_t clock_state;
- assert((port < 5) && (num < 32));
+ assert((port < 5) && (bank < 4));
- gpio_clk(gpio, 0);
+ clock_state = gpio_get_clock(gpio);
/*
* in gpio0a, gpio0b, gpio2c, gpio2d,
@@ -120,7 +219,7 @@
* 11: pull up
* different with other gpio, so need to correct it
*/
- if (((port == 0) && (bank < 2)) || ((port == 2) && (bank > 2))) {
+ if (((port == 0) && (bank < 2)) || ((port == 2) && (bank > 1))) {
if (pull == GPIO_PULL_UP)
pull = 3;
else if (pull == GPIO_PULL_DOWN)
@@ -138,17 +237,18 @@
(port - 2) * 16 + bank * 4,
BITS_WITH_WMASK(pull, GPIO_P_MASK, id * 2));
}
- gpio_clk(gpio, 1);
+ gpio_put_clock(gpio, clock_state);
}
static void set_direction(int gpio, int direction)
{
- uint32_t port = gpio / 32;
- uint32_t num = gpio % 32;
+ uint32_t port = GET_GPIO_PORT(gpio);
+ uint32_t num = GET_GPIO_NUM(gpio);
+ uint32_t clock_state;
assert((port < 5) && (num < 32));
- gpio_clk(gpio, 0);
+ clock_state = gpio_get_clock(gpio);
/*
* in gpio.h
@@ -158,18 +258,18 @@
* so need to revert direction value
*/
mmio_setbits_32(gpio_port[port] + SWPORTA_DDR, !direction << num);
- gpio_clk(gpio, 1);
+ gpio_put_clock(gpio, clock_state);
}
static int get_direction(int gpio)
{
- uint32_t port = gpio / 32;
- uint32_t num = gpio % 32;
- int direction;
+ uint32_t port = GET_GPIO_PORT(gpio);
+ uint32_t num = GET_GPIO_NUM(gpio);
+ int direction, clock_state;
assert((port < 5) && (num < 32));
- gpio_clk(gpio, 0);
+ clock_state = gpio_get_clock(gpio);
/*
* in gpio.h
@@ -180,37 +280,38 @@
*/
direction = !((mmio_read_32(gpio_port[port] +
SWPORTA_DDR) >> num) & 0x1);
- gpio_clk(gpio, 1);
+ gpio_put_clock(gpio, clock_state);
return direction;
}
static int get_value(int gpio)
{
- uint32_t port = gpio / 32;
- uint32_t num = gpio % 32;
- int value;
+ uint32_t port = GET_GPIO_PORT(gpio);
+ uint32_t num = GET_GPIO_NUM(gpio);
+ int value, clock_state;
assert((port < 5) && (num < 32));
- gpio_clk(gpio, 0);
+ clock_state = gpio_get_clock(gpio);
value = (mmio_read_32(gpio_port[port] + EXT_PORTA) >> num) & 0x1;
- gpio_clk(gpio, 1);
+ gpio_put_clock(gpio, clock_state);
return value;
}
static void set_value(int gpio, int value)
{
- uint32_t port = gpio / 32;
- uint32_t num = gpio % 32;
+ uint32_t port = GET_GPIO_PORT(gpio);
+ uint32_t num = GET_GPIO_NUM(gpio);
+ uint32_t clock_state;
assert((port < 5) && (num < 32));
- gpio_clk(gpio, 0);
+ clock_state = gpio_get_clock(gpio);
mmio_clrsetbits_32(gpio_port[port] + SWPORTA_DR, 1 << num,
!!value << num);
- gpio_clk(gpio, 0);
+ gpio_put_clock(gpio, clock_state);
}
const gpio_ops_t rk3399_gpio_ops = {
@@ -219,6 +320,7 @@
.get_value = get_value,
.set_value = set_value,
.set_pull = set_pull,
+ .get_pull = get_pull,
};
void plat_rockchip_gpio_init(void)
diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.c b/plat/rockchip/rk3399/drivers/pmu/pmu.c
old mode 100755
new mode 100644
index 50953d8..07a5b1e
--- a/plat/rockchip/rk3399/drivers/pmu/pmu.c
+++ b/plat/rockchip/rk3399/drivers/pmu/pmu.c
@@ -874,6 +874,190 @@
mmio_clrbits_32(PMU_BASE + PMU_BUS_CLR, hw_idle);
}
+static uint32_t iomux_status[12];
+static uint32_t pull_mode_status[12];
+static uint32_t gpio_direction[3];
+static uint32_t gpio_2_4_clk_gate;
+
+static void suspend_apio(void)
+{
+ struct apio_info *suspend_apio;
+ int i;
+
+ suspend_apio = plat_get_rockchip_suspend_apio();
+
+ if (!suspend_apio)
+ return;
+
+ /* save gpio2 ~ gpio4 iomux and pull mode */
+ for (i = 0; i < 12; i++) {
+ iomux_status[i] = mmio_read_32(GRF_BASE +
+ GRF_GPIO2A_IOMUX + i * 4);
+ pull_mode_status[i] = mmio_read_32(GRF_BASE +
+ GRF_GPIO2A_P + i * 4);
+ }
+
+ /* store gpio2 ~ gpio4 clock gate state */
+ gpio_2_4_clk_gate = (mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(31)) >>
+ PCLK_GPIO2_GATE_SHIFT) & 0x07;
+
+ /* enable gpio2 ~ gpio4 clock gate */
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
+ BITS_WITH_WMASK(0, 0x07, PCLK_GPIO2_GATE_SHIFT));
+
+ /* save gpio2 ~ gpio4 direction */
+ gpio_direction[0] = mmio_read_32(GPIO2_BASE + 0x04);
+ gpio_direction[1] = mmio_read_32(GPIO3_BASE + 0x04);
+ gpio_direction[2] = mmio_read_32(GPIO4_BASE + 0x04);
+
+ /* apio1 charge gpio3a0 ~ gpio3c7 */
+ if (suspend_apio->apio1) {
+
+ /* set gpio3a0 ~ gpio3c7 iomux to gpio */
+ mmio_write_32(GRF_BASE + GRF_GPIO3A_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+ mmio_write_32(GRF_BASE + GRF_GPIO3B_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+ mmio_write_32(GRF_BASE + GRF_GPIO3C_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+
+ /* set gpio3a0 ~ gpio3c7 pull mode to pull none */
+ mmio_write_32(GRF_BASE + GRF_GPIO3A_P, REG_SOC_WMSK | 0);
+ mmio_write_32(GRF_BASE + GRF_GPIO3B_P, REG_SOC_WMSK | 0);
+ mmio_write_32(GRF_BASE + GRF_GPIO3C_P, REG_SOC_WMSK | 0);
+
+ /* set gpio3a0 ~ gpio3c7 to input */
+ mmio_clrbits_32(GPIO3_BASE + 0x04, 0x00ffffff);
+ }
+
+ /* apio2 charge gpio2a0 ~ gpio2b4 */
+ if (suspend_apio->apio2) {
+
+ /* set gpio2a0 ~ gpio2b4 iomux to gpio */
+ mmio_write_32(GRF_BASE + GRF_GPIO2A_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+ mmio_write_32(GRF_BASE + GRF_GPIO2B_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+
+ /* set gpio2a0 ~ gpio2b4 pull mode to pull none */
+ mmio_write_32(GRF_BASE + GRF_GPIO2A_P, REG_SOC_WMSK | 0);
+ mmio_write_32(GRF_BASE + GRF_GPIO2B_P, REG_SOC_WMSK | 0);
+
+ /* set gpio2a0 ~ gpio2b4 to input */
+ mmio_clrbits_32(GPIO2_BASE + 0x04, 0x00001fff);
+ }
+
+ /* apio3 charge gpio2c0 ~ gpio2d4*/
+ if (suspend_apio->apio3) {
+
+ /* set gpio2a0 ~ gpio2b4 iomux to gpio */
+ mmio_write_32(GRF_BASE + GRF_GPIO2C_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+ mmio_write_32(GRF_BASE + GRF_GPIO2D_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+
+ /* set gpio2c0 ~ gpio2d4 pull mode to pull none */
+ mmio_write_32(GRF_BASE + GRF_GPIO2C_P, REG_SOC_WMSK | 0);
+ mmio_write_32(GRF_BASE + GRF_GPIO2D_P, REG_SOC_WMSK | 0);
+
+ /* set gpio2c0 ~ gpio2d4 to input */
+ mmio_clrbits_32(GPIO2_BASE + 0x04, 0x1fff0000);
+ }
+
+ /* apio4 charge gpio4c0 ~ gpio4c7, gpio4d0 ~ gpio4d6 */
+ if (suspend_apio->apio4) {
+
+ /* set gpio4c0 ~ gpio4d6 iomux to gpio */
+ mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+ mmio_write_32(GRF_BASE + GRF_GPIO4D_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+
+ /* set gpio4c0 ~ gpio4d6 pull mode to pull none */
+ mmio_write_32(GRF_BASE + GRF_GPIO4C_P, REG_SOC_WMSK | 0);
+ mmio_write_32(GRF_BASE + GRF_GPIO4D_P, REG_SOC_WMSK | 0);
+
+ /* set gpio4c0 ~ gpio4d6 to input */
+ mmio_clrbits_32(GPIO4_BASE + 0x04, 0x7fff0000);
+ }
+
+ /* apio5 charge gpio3d0 ~ gpio3d7, gpio4a0 ~ gpio4a7*/
+ if (suspend_apio->apio5) {
+ /* set gpio3d0 ~ gpio4a7 iomux to gpio */
+ mmio_write_32(GRF_BASE + GRF_GPIO3D_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+ mmio_write_32(GRF_BASE + GRF_GPIO4A_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+
+ /* set gpio3d0 ~ gpio4a7 pull mode to pull none */
+ mmio_write_32(GRF_BASE + GRF_GPIO3D_P, REG_SOC_WMSK | 0);
+ mmio_write_32(GRF_BASE + GRF_GPIO4A_P, REG_SOC_WMSK | 0);
+
+ /* set gpio4c0 ~ gpio4d6 to input */
+ mmio_clrbits_32(GPIO3_BASE + 0x04, 0xff000000);
+ mmio_clrbits_32(GPIO4_BASE + 0x04, 0x000000ff);
+ }
+}
+
+static void resume_apio(void)
+{
+ struct apio_info *suspend_apio;
+ int i;
+
+ suspend_apio = plat_get_rockchip_suspend_apio();
+
+ if (!suspend_apio)
+ return;
+
+ for (i = 0; i < 12; i++) {
+ mmio_write_32(GRF_BASE + GRF_GPIO2A_P + i * 4,
+ REG_SOC_WMSK | pull_mode_status[i]);
+ mmio_write_32(GRF_BASE + GRF_GPIO2A_IOMUX + i * 4,
+ REG_SOC_WMSK | iomux_status[i]);
+ }
+
+ /* set gpio2 ~ gpio4 direction back to store value */
+ mmio_write_32(GPIO2_BASE + 0x04, gpio_direction[0]);
+ mmio_write_32(GPIO3_BASE + 0x04, gpio_direction[1]);
+ mmio_write_32(GPIO4_BASE + 0x04, gpio_direction[2]);
+
+ /* set gpio2 ~ gpio4 clock gate back to store value */
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
+ BITS_WITH_WMASK(gpio_2_4_clk_gate, 0x07,
+ PCLK_GPIO2_GATE_SHIFT));
+}
+
+static void suspend_gpio(void)
+{
+ struct gpio_info *suspend_gpio;
+ uint32_t count;
+ int i;
+
+ suspend_gpio = plat_get_rockchip_suspend_gpio(&count);
+
+ for (i = 0; i < count; i++) {
+ gpio_set_value(suspend_gpio[i].index, suspend_gpio[i].polarity);
+ gpio_set_direction(suspend_gpio[i].index, GPIO_DIR_OUT);
+ udelay(1);
+ }
+}
+
+static void resume_gpio(void)
+{
+ struct gpio_info *suspend_gpio;
+ uint32_t count;
+ int i;
+
+ suspend_gpio = plat_get_rockchip_suspend_gpio(&count);
+
+ for (i = count - 1; i >= 0; i--) {
+ gpio_set_value(suspend_gpio[i].index,
+ !suspend_gpio[i].polarity);
+ gpio_set_direction(suspend_gpio[i].index, GPIO_DIR_OUT);
+ udelay(1);
+ }
+}
+
static int sys_pwr_domain_suspend(void)
{
uint32_t wait_cnt = 0;
@@ -919,7 +1103,6 @@
}
}
mmio_setbits_32(PMU_BASE + PMU_PWRDN_CON, BIT(PMU_SCU_B_PWRDWN_EN));
-
/*
* Disabling PLLs/PWM/DVFS is approaching WFI which is
* the last steps in suspend.
@@ -928,6 +1111,8 @@
disable_dvfs_plls();
disable_pwms();
disable_nodvfs_plls();
+ suspend_apio();
+ suspend_gpio();
return 0;
}
@@ -937,6 +1122,8 @@
uint32_t wait_cnt = 0;
uint32_t status = 0;
+ resume_apio();
+ resume_gpio();
enable_nodvfs_plls();
enable_pwms();
/* PWM regulators take time to come up; give 300us to be safe. */
@@ -952,7 +1139,6 @@
* somewhere.
*/
mmio_write_32(PMU_BASE + PMU_WAKEUP_STATUS, 0xffffffff);
-
mmio_write_32(PMU_BASE + PMU_WKUP_CFG4, 0x00);
mmio_write_32(SGRF_BASE + SGRF_SOC_CON0_1(1),
@@ -1003,6 +1189,9 @@
BIT(PMU_CLR_PERILP) |
BIT(PMU_CLR_PMU) |
BIT(PMU_CLR_GIC));
+
+ plat_rockchip_gic_cpuif_enable();
+
return 0;
}
@@ -1010,7 +1199,7 @@
{
struct gpio_info *rst_gpio;
- rst_gpio = (struct gpio_info *)plat_get_rockchip_gpio_reset();
+ rst_gpio = plat_get_rockchip_gpio_reset();
if (rst_gpio) {
gpio_set_direction(rst_gpio->index, GPIO_DIR_OUT);
@@ -1027,7 +1216,7 @@
{
struct gpio_info *poweroff_gpio;
- poweroff_gpio = (struct gpio_info *)plat_get_rockchip_gpio_poweroff();
+ poweroff_gpio = plat_get_rockchip_gpio_poweroff();
if (poweroff_gpio) {
/*
diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.h b/plat/rockchip/rk3399/drivers/pmu/pmu.h
index 65fe7db..ab2896b 100644
--- a/plat/rockchip/rk3399/drivers/pmu/pmu.h
+++ b/plat/rockchip/rk3399/drivers/pmu/pmu.h
@@ -875,7 +875,32 @@
#define MAX_WAIT_COUNT 1000
#define GRF_SOC_CON4 0x0e210
-#define GRF_GPIO4C_IOMUX 0x0e028
+
+#define GRF_GPIO2A_IOMUX 0xe000
+#define GRF_GPIO2B_IOMUX 0xe004
+#define GRF_GPIO2C_IOMUX 0xe008
+#define GRF_GPIO2D_IOMUX 0xe00c
+#define GRF_GPIO3A_IOMUX 0xe010
+#define GRF_GPIO3B_IOMUX 0xe014
+#define GRF_GPIO3C_IOMUX 0xe018
+#define GRF_GPIO3D_IOMUX 0xe01c
+#define GRF_GPIO4A_IOMUX 0xe020
+#define GRF_GPIO4B_IOMUX 0xe024
+#define GRF_GPIO4C_IOMUX 0xe028
+#define GRF_GPIO4D_IOMUX 0xe02c
+
+#define GRF_GPIO2A_P 0xe040
+#define GRF_GPIO2B_P 0xe044
+#define GRF_GPIO2C_P 0xe048
+#define GRF_GPIO2D_P 0xe04C
+#define GRF_GPIO3A_P 0xe050
+#define GRF_GPIO3B_P 0xe054
+#define GRF_GPIO3C_P 0xe058
+#define GRF_GPIO3D_P 0xe05C
+#define GRF_GPIO4A_P 0xe060
+#define GRF_GPIO4B_P 0xe064
+#define GRF_GPIO4C_P 0xe068
+#define GRF_GPIO4D_P 0xe06C
#define PMUGRF_GPIO0A_SMT 0x0120
#define PMUGRF_SOC_CON0 0x0180
diff --git a/plat/rockchip/rk3399/plat_sip_calls.c b/plat/rockchip/rk3399/plat_sip_calls.c
index 6069be2..a20ee2d 100644
--- a/plat/rockchip/rk3399/plat_sip_calls.c
+++ b/plat/rockchip/rk3399/plat_sip_calls.c
@@ -31,33 +31,33 @@
#include <runtime_svc.h>
#include <dram.h>
-#define RK_SIP_DDR_CFG64 0x82000008
-#define CONFIG_DRAM_INIT 0x00
-#define CONFIG_DRAM_SET_RATE 0x01
-#define CONFIG_DRAM_ROUND_RATE 0x02
-#define CONFIG_DRAM_SET_AT_SR 0x03
-#define CONFIG_DRAM_GET_BW 0x04
-#define CONFIG_DRAM_GET_RATE 0x05
-#define CONFIG_DRAM_CLR_IRQ 0x06
-#define CONFIG_DRAM_SET_PARAM 0x07
+#define RK_SIP_DDR_CFG 0x82000008
+#define DRAM_INIT 0x00
+#define DRAM_SET_RATE 0x01
+#define DRAM_ROUND_RATE 0x02
+#define DRAM_SET_AT_SR 0x03
+#define DRAM_GET_BW 0x04
+#define DRAM_GET_RATE 0x05
+#define DRAM_CLR_IRQ 0x06
+#define DRAM_SET_PARAM 0x07
-uint64_t ddr_smc_handler(uint64_t arg0, uint64_t arg1, uint64_t id)
+uint32_t ddr_smc_handler(uint64_t arg0, uint64_t arg1, uint64_t id)
{
switch (id) {
- case CONFIG_DRAM_INIT:
+ case DRAM_INIT:
ddr_init();
break;
- case CONFIG_DRAM_SET_RATE:
- return ddr_set_rate(arg0);
- case CONFIG_DRAM_ROUND_RATE:
- return ddr_round_rate(arg0);
- case CONFIG_DRAM_GET_RATE:
+ case DRAM_SET_RATE:
+ return ddr_set_rate((uint32_t)arg0);
+ case DRAM_ROUND_RATE:
+ return ddr_round_rate((uint32_t)arg0);
+ case DRAM_GET_RATE:
return ddr_get_rate();
- case CONFIG_DRAM_CLR_IRQ:
+ case DRAM_CLR_IRQ:
clr_dcf_irq();
break;
- case CONFIG_DRAM_SET_PARAM:
- dts_timing_receive(arg0, arg1);
+ case DRAM_SET_PARAM:
+ dts_timing_receive((uint32_t)arg0, (uint32_t)arg1);
break;
default:
break;
@@ -76,7 +76,7 @@
uint64_t flags)
{
switch (smc_fid) {
- case RK_SIP_DDR_CFG64:
+ case RK_SIP_DDR_CFG:
SMC_RET1(handle, ddr_smc_handler(x1, x2, x3));
default:
ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);