aboutsummaryrefslogtreecommitdiffstats
path: root/plat/mediatek
diff options
context:
space:
mode:
Diffstat (limited to 'plat/mediatek')
-rw-r--r--plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init_v2.c125
-rw-r--r--plat/mediatek/common/drivers/uart/8250_console.S7
-rw-r--r--plat/mediatek/common/drivers/uart/uart.c (renamed from plat/mediatek/mt8183/drivers/uart/uart.c)11
-rw-r--r--plat/mediatek/common/mtk_plat_common.c32
-rw-r--r--plat/mediatek/common/mtk_plat_common.h3
-rw-r--r--plat/mediatek/mt6795/aarch64/plat_helpers.S6
-rw-r--r--plat/mediatek/mt6795/bl31.ld.S84
-rw-r--r--plat/mediatek/mt8173/bl31_plat_setup.c2
-rw-r--r--plat/mediatek/mt8173/drivers/wdt/wdt.c115
-rw-r--r--plat/mediatek/mt8173/drivers/wdt/wdt.h20
-rw-r--r--plat/mediatek/mt8173/include/mt8173_def.h12
-rw-r--r--plat/mediatek/mt8173/include/plat_sip_calls.h3
-rw-r--r--plat/mediatek/mt8173/include/platform_def.h2
-rw-r--r--plat/mediatek/mt8173/plat_pm.c9
-rw-r--r--plat/mediatek/mt8173/plat_sip_calls.c4
-rw-r--r--plat/mediatek/mt8173/platform.mk2
-rw-r--r--plat/mediatek/mt8183/bl31_plat_setup.c5
-rw-r--r--plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c10
-rw-r--r--plat/mediatek/mt8183/drivers/timer/mt_timer.c29
-rw-r--r--plat/mediatek/mt8183/drivers/timer/mt_timer.h20
-rw-r--r--plat/mediatek/mt8183/drivers/uart/uart.h2
-rw-r--r--plat/mediatek/mt8183/include/platform_def.h2
-rw-r--r--plat/mediatek/mt8183/platform.mk13
-rw-r--r--plat/mediatek/mt8192/aarch64/plat_helpers.S49
-rw-r--r--plat/mediatek/mt8192/aarch64/platform_common.c46
-rw-r--r--plat/mediatek/mt8192/bl31_plat_setup.c115
-rw-r--r--plat/mediatek/mt8192/drivers/dcm/mtk_dcm.c63
-rw-r--r--plat/mediatek/mt8192/drivers/dcm/mtk_dcm.h14
-rw-r--r--plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.c562
-rw-r--r--plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.h68
-rw-r--r--plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c122
-rw-r--r--plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h102
-rw-r--r--plat/mediatek/mt8192/drivers/gpio/mtgpio.c340
-rw-r--r--plat/mediatek/mt8192/drivers/gpio/mtgpio.h384
-rw-r--r--plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c123
-rw-r--r--plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.c269
-rw-r--r--plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.h106
-rw-r--r--plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.c148
-rw-r--r--plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.h12
-rw-r--r--plat/mediatek/mt8192/drivers/pmic/pmic.c13
-rw-r--r--plat/mediatek/mt8192/drivers/pmic/pmic.h15
-rw-r--r--plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h76
-rw-r--r--plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_common.h48
-rw-r--r--plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c84
-rw-r--r--plat/mediatek/mt8192/drivers/rtc/rtc.c148
-rw-r--r--plat/mediatek/mt8192/drivers/rtc/rtc.h197
-rw-r--r--plat/mediatek/mt8192/drivers/spmc/mtspmc.c177
-rw-r--r--plat/mediatek/mt8192/drivers/spmc/mtspmc.h31
-rw-r--r--plat/mediatek/mt8192/drivers/spmc/mtspmc_private.h184
-rw-r--r--plat/mediatek/mt8192/drivers/timer/mt_timer.c38
-rw-r--r--plat/mediatek/mt8192/drivers/timer/mt_timer.h35
-rw-r--r--plat/mediatek/mt8192/drivers/uart/uart.h100
-rw-r--r--plat/mediatek/mt8192/include/mcucfg.h257
-rw-r--r--plat/mediatek/mt8192/include/mt_gic_v3.h27
-rw-r--r--plat/mediatek/mt8192/include/plat_helpers.h12
-rw-r--r--plat/mediatek/mt8192/include/plat_macros.S38
-rw-r--r--plat/mediatek/mt8192/include/plat_mt_cirq.h128
-rw-r--r--plat/mediatek/mt8192/include/plat_mtk_lpm.h48
-rw-r--r--plat/mediatek/mt8192/include/plat_pm.h38
-rw-r--r--plat/mediatek/mt8192/include/plat_private.h18
-rw-r--r--plat/mediatek/mt8192/include/plat_sip_calls.h15
-rw-r--r--plat/mediatek/mt8192/include/platform_def.h126
-rw-r--r--plat/mediatek/mt8192/plat_mt_cirq.c552
-rw-r--r--plat/mediatek/mt8192/plat_mt_gic.c196
-rw-r--r--plat/mediatek/mt8192/plat_pm.c397
-rw-r--r--plat/mediatek/mt8192/plat_sip_calls.c27
-rw-r--r--plat/mediatek/mt8192/plat_topology.c75
-rw-r--r--plat/mediatek/mt8192/platform.mk83
68 files changed, 6101 insertions, 123 deletions
diff --git a/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init_v2.c b/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init_v2.c
new file mode 100644
index 000000000..fca69130a
--- /dev/null
+++ b/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init_v2.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include "platform_def.h"
+#include "pmic_wrap_init.h"
+
+/* pmic wrap module wait_idle and read polling interval (in microseconds) */
+enum pwrap_polling_interval {
+ WAIT_IDLE_POLLING_DELAY_US = 1,
+ READ_POLLING_DELAY_US = 2
+};
+
+static uint32_t pwrap_check_idle(void *wacs_register, uint32_t timeout_us)
+{
+ uint32_t reg_rdata = 0U, retry;
+
+ retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) /
+ WAIT_IDLE_POLLING_DELAY_US;
+ while (retry != 0) {
+ udelay(WAIT_IDLE_POLLING_DELAY_US);
+ reg_rdata = mmio_read_32((uintptr_t)wacs_register);
+ if (GET_WACS_FSM(reg_rdata) == SWINF_FSM_IDLE) {
+ break;
+ }
+ retry--;
+ };
+
+ if (retry == 0) {
+ /* timeout */
+ return E_PWR_WAIT_IDLE_TIMEOUT;
+ }
+
+ return 0U;
+}
+
+static uint32_t pwrap_check_vldclr(void *wacs_register, uint32_t timeout_us)
+{
+ uint32_t reg_rdata = 0U, retry;
+
+ retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US;
+ while (retry != 0) {
+ udelay(READ_POLLING_DELAY_US);
+ reg_rdata = mmio_read_32((uintptr_t)wacs_register);
+ if (GET_WACS_FSM(reg_rdata) == SWINF_FSM_WFVLDCLR) {
+ break;
+ }
+ retry--;
+ };
+
+ if (retry == 0) {
+ /* timeout */
+ return E_PWR_WAIT_IDLE_TIMEOUT;
+ }
+
+ return 0U;
+}
+
+static int32_t pwrap_wacs2(uint32_t write, uint32_t adr, uint32_t wdata,
+ uint32_t *rdata, uint32_t init_check)
+{
+ uint32_t reg_rdata, return_value;
+
+ if (init_check != 0) {
+ if ((mmio_read_32((uintptr_t)&mtk_pwrap->init_done) & 0x1) == 0) {
+ ERROR("initialization isn't finished\n");
+ return E_PWR_NOT_INIT_DONE;
+ }
+ }
+
+ /* Wait for Software Interface FSM state to be IDLE. */
+ return_value = pwrap_check_idle(&mtk_pwrap->wacs2_sta,
+ PWRAP_WAIT_IDLE_US);
+ if (return_value != 0) {
+ return return_value;
+ }
+
+ /* Set the write data */
+ if (write == 1) {
+ /* Set the write data. */
+ mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_wdata, wdata);
+ }
+
+ /* Send the command. */
+ mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_cmd, (write << 29) | adr);
+
+ if (write == 0) {
+ /*
+ * Wait for Software Interface FSM state to be WFVLDCLR,
+ * read the data and clear the valid flag.
+ */
+ return_value = pwrap_check_vldclr(&mtk_pwrap->wacs2_sta,
+ PWRAP_READ_US);
+ if (return_value != 0) {
+ return return_value;
+ }
+
+ if (rdata == NULL) {
+ return E_PWR_INVALID_ARG;
+ }
+
+ reg_rdata = mmio_read_32((uintptr_t)&mtk_pwrap->wacs2_rdata);
+ *rdata = reg_rdata;
+ mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 0x1);
+ }
+
+ return return_value;
+}
+
+/* external API for pmic_wrap user */
+int32_t pwrap_read(uint32_t adr, uint32_t *rdata)
+{
+ return pwrap_wacs2(0, adr, 0, rdata, 1);
+}
+
+int32_t pwrap_write(uint32_t adr, uint32_t wdata)
+{
+ return pwrap_wacs2(1, adr, wdata, 0, 1);
+}
diff --git a/plat/mediatek/common/drivers/uart/8250_console.S b/plat/mediatek/common/drivers/uart/8250_console.S
index 94a6c02ab..7a946f9a3 100644
--- a/plat/mediatek/common/drivers/uart/8250_console.S
+++ b/plat/mediatek/common/drivers/uart/8250_console.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -149,16 +149,15 @@ getc_error:
endfunc console_core_getc
/* ---------------------------------------------
- * int console_core_flush(uintptr_t base_addr)
+ * void console_core_flush(uintptr_t base_addr)
* Function to force a write of all buffered
* data that hasn't been output.
* In : x0 - console base address
- * Out : return -1 on error else return 0.
+ * Out : void.
* Clobber list : x0, x1
* ---------------------------------------------
*/
func console_core_flush
/* Placeholder */
- mov w0, #0
ret
endfunc console_core_flush
diff --git a/plat/mediatek/mt8183/drivers/uart/uart.c b/plat/mediatek/common/drivers/uart/uart.c
index 3c6a98036..b940eb339 100644
--- a/plat/mediatek/mt8183/drivers/uart/uart.c
+++ b/plat/mediatek/common/drivers/uart/uart.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,7 +9,7 @@
static struct mt_uart uart_save_addr[DRV_SUPPORT_UART_PORTS];
-static const unsigned int uart_base_addr[DRV_SUPPORT_UART_PORTS] = {
+static const uint32_t uart_base_addr[DRV_SUPPORT_UART_PORTS] = {
UART0_BASE,
UART1_BASE
};
@@ -99,13 +99,14 @@ void mt_uart_save(void)
void mt_console_uart_cg(int on)
{
- if (on)
+ if (on == 1) {
mmio_write_32(UART_CLOCK_GATE_CLR, UART0_CLOCK_GATE_BIT);
- else
+ } else {
mmio_write_32(UART_CLOCK_GATE_SET, UART0_CLOCK_GATE_BIT);
+ }
}
-int mt_console_uart_cg_status(void)
+uint32_t mt_console_uart_cg_status(void)
{
return mmio_read_32(UART_CLOCK_GATE_STA) & UART0_CLOCK_GATE_BIT;
}
diff --git a/plat/mediatek/common/mtk_plat_common.c b/plat/mediatek/common/mtk_plat_common.c
index a07a2981a..f57e4357d 100644
--- a/plat/mediatek/common/mtk_plat_common.c
+++ b/plat/mediatek/common/mtk_plat_common.c
@@ -10,8 +10,10 @@
#include <drivers/arm/cci.h>
#include <drivers/console.h>
#include <lib/mmio.h>
+#include <lib/smccc.h>
#include <lib/xlat_tables/xlat_tables.h>
#include <plat/common/platform.h>
+#include <services/arm_arch_svc.h>
#include <mtk_plat_common.h>
#include <mtk_sip_svc.h>
@@ -116,3 +118,33 @@ uint32_t plat_get_spsr_for_bl33_entry(void)
spsr = SPSR_MODE32(mode, 0, ee, daif);
return spsr;
}
+
+/*****************************************************************************
+ * plat_is_smccc_feature_available() - This function checks whether SMCCC
+ * feature is availabile for platform.
+ * @fid: SMCCC function id
+ *
+ * Return SMC_OK if SMCCC feature is available and SMC_ARCH_CALL_NOT_SUPPORTED
+ * otherwise.
+ *****************************************************************************/
+int32_t plat_is_smccc_feature_available(u_register_t fid)
+{
+ switch (fid) {
+ case SMCCC_ARCH_SOC_ID:
+ return SMC_ARCH_CALL_SUCCESS;
+ default:
+ return SMC_ARCH_CALL_NOT_SUPPORTED;
+ }
+}
+
+int32_t plat_get_soc_version(void)
+{
+ uint32_t manfid = (JEDEC_MTK_BKID << 24U) | (JEDEC_MTK_MFID << 16U);
+
+ return (int32_t)(manfid | (SOC_CHIP_ID & 0xFFFFU));
+}
+
+int32_t plat_get_soc_revision(void)
+{
+ return 0;
+}
diff --git a/plat/mediatek/common/mtk_plat_common.h b/plat/mediatek/common/mtk_plat_common.h
index 55f4c516e..919c17358 100644
--- a/plat/mediatek/common/mtk_plat_common.h
+++ b/plat/mediatek/common/mtk_plat_common.h
@@ -18,6 +18,9 @@
#define LINUX_KERNEL_32 0
#define SMC32_PARAM_MASK (0xFFFFFFFF)
+#define JEDEC_MTK_BKID U(4)
+#define JEDEC_MTK_MFID U(0x26)
+
struct atf_arg_t {
unsigned int atf_magic;
unsigned int tee_support;
diff --git a/plat/mediatek/mt6795/aarch64/plat_helpers.S b/plat/mediatek/mt6795/aarch64/plat_helpers.S
index 94f9eaef9..aaddb2bba 100644
--- a/plat/mediatek/mt6795/aarch64/plat_helpers.S
+++ b/plat/mediatek/mt6795/aarch64/plat_helpers.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -123,10 +123,10 @@ func plat_crash_console_putc
endfunc plat_crash_console_putc
/* ---------------------------------------------
- * int plat_crash_console_flush(int c)
+ * void plat_crash_console_flush(int c)
* Function to force a write of all buffered
* data that hasn't been output.
- * Out : return -1 on error else return 0.
+ * Out : void.
* Clobber list : x0, x1
* ---------------------------------------------
*/
diff --git a/plat/mediatek/mt6795/bl31.ld.S b/plat/mediatek/mt6795/bl31.ld.S
index cf68b711e..3d881fc43 100644
--- a/plat/mediatek/mt6795/bl31.ld.S
+++ b/plat/mediatek/mt6795/bl31.ld.S
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <common/bl_common.ld.h>
#include <lib/xlat_tables/xlat_tables_defs.h>
-#include <platform_def.h>
OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
@@ -38,20 +38,7 @@ SECTIONS
*(.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__ = .;
+ RODATA_COMMON
__RO_END_UNALIGNED__ = .;
/*
@@ -72,74 +59,19 @@ SECTIONS
*/
__RW_START__ = . ;
- /*
- * .data must be placed at a lower address than the stacks if the stack
- * protector is enabled. Alternatively, the .data.stack_protector_canary
- * section can be placed independently of the main .data section.
- */
- .data . : {
- __DATA_START__ = .;
- *(.data*)
- __DATA_END__ = .;
- } >RAM
+ DATA_SECTION >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 should be 16-byte aligned for better performance of the
- * zero-initialization code.
- */
- .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__ = .;
- __PERCPU_BAKERY_LOCK_START__ = .;
- *(bakery_lock)
- . = ALIGN(CACHE_WRITEBACK_GRANULE);
- __PERCPU_BAKERY_LOCK_END__ = .;
- __PERCPU_BAKERY_LOCK_SIZE__ = ABSOLUTE(__PERCPU_BAKERY_LOCK_END__ - __PERCPU_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
+ STACK_SECTION >RAM
+ BSS_SECTION >RAM
+ __RW_END__ = __BSS_END__;
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. The tables are initialized to zero by the translation
- * tables library.
- */
- xlat_table (NOLOAD) : {
- *(xlat_table)
- } >RAM2
+ XLAT_TABLE_SECTION >RAM2
#if USE_COHERENT_MEM
/*
diff --git a/plat/mediatek/mt8173/bl31_plat_setup.c b/plat/mediatek/mt8173/bl31_plat_setup.c
index 73a479b50..bd7d0b0ee 100644
--- a/plat/mediatek/mt8173/bl31_plat_setup.c
+++ b/plat/mediatek/mt8173/bl31_plat_setup.c
@@ -100,7 +100,7 @@ entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
u_register_t arg2, u_register_t arg3)
{
- static console_16550_t console;
+ static console_t console;
console_16550_register(MT8173_UART0_BASE, MT8173_UART_CLOCK, MT8173_BAUDRATE, &console);
diff --git a/plat/mediatek/mt8173/drivers/wdt/wdt.c b/plat/mediatek/mt8173/drivers/wdt/wdt.c
new file mode 100644
index 000000000..40f57eed2
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/wdt/wdt.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2020, Google LLC. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mt8173_def.h>
+#include <plat_sip_calls.h>
+#include <lib/psci/psci.h>
+#include <smccc_helpers.h>
+#include <wdt.h>
+
+#define WDT_BASE (RGU_BASE + 0)
+#define WDT_MODE (WDT_BASE + 0x00)
+#define WDT_LENGTH (WDT_BASE + 0x04)
+#define WDT_RESTART (WDT_BASE + 0x08)
+#define WDT_SWRST (WDT_BASE + 0x14)
+
+#define WDT_MODE_DUAL_MODE 0x40
+#define WDT_MODE_IRQ 0x8
+#define WDT_MODE_KEY 0x22000000
+#define WDT_MODE_EXTEN 0x4
+#define WDT_MODE_EN 0x1
+#define WDT_LENGTH_KEY 0x8
+#define WDT_RESTART_KEY 0x1971
+#define WDT_SWRST_KEY 0x1209
+
+
+#define WDT_MIN_TIMEOUT 1
+#define WDT_MAX_TIMEOUT 31
+
+enum smcwd_call {
+ SMCWD_INFO = 0,
+ SMCWD_SET_TIMEOUT = 1,
+ SMCWD_ENABLE = 2,
+ SMCWD_PET = 3,
+};
+
+static int wdt_enabled_before_suspend;
+
+/*
+ * We expect the WDT registers to be correctly initialized by BL2 firmware
+ * (which may be board specific), so we do not reinitialize them here.
+ */
+
+void wdt_trigger_reset(void)
+{
+ mmio_write_32(WDT_SWRST, WDT_SWRST_KEY);
+}
+
+void wdt_pet(void)
+{
+ mmio_write_32(WDT_RESTART, WDT_RESTART_KEY);
+}
+
+int wdt_set_timeout(uint32_t timeout)
+{
+ /* One tick here equals 512 32KHz ticks. 512 / 32000 * 125 / 2 = 1 */
+ uint32_t ticks = timeout * 125 / 2;
+
+ if (timeout < WDT_MIN_TIMEOUT || timeout > WDT_MAX_TIMEOUT)
+ return PSCI_E_INVALID_PARAMS;
+
+ mmio_write_32(WDT_LENGTH, ticks << 5 | WDT_LENGTH_KEY);
+
+ return PSCI_E_SUCCESS;
+}
+
+void wdt_set_enable(int enable)
+{
+ if (enable)
+ wdt_pet();
+ mmio_clrsetbits_32(WDT_MODE, WDT_MODE_EN,
+ WDT_MODE_KEY | (enable ? WDT_MODE_EN : 0));
+}
+
+void wdt_suspend(void)
+{
+ wdt_enabled_before_suspend = mmio_read_32(WDT_MODE) & WDT_MODE_EN;
+ if (wdt_enabled_before_suspend)
+ wdt_set_enable(0);
+}
+
+void wdt_resume(void)
+{
+ if (wdt_enabled_before_suspend)
+ wdt_set_enable(1);
+}
+
+uint64_t wdt_smc_handler(uint32_t x1,
+ uint32_t x2,
+ void *handle)
+{
+ int ret;
+
+ switch (x1) {
+ case SMCWD_INFO:
+ SMC_RET3(handle, PSCI_E_SUCCESS,
+ WDT_MIN_TIMEOUT, WDT_MAX_TIMEOUT);
+ case SMCWD_SET_TIMEOUT:
+ ret = wdt_set_timeout(x2);
+ SMC_RET1(handle, ret);
+ case SMCWD_ENABLE:
+ wdt_set_enable(x2 > 0);
+ SMC_RET1(handle, PSCI_E_SUCCESS);
+ case SMCWD_PET:
+ wdt_pet();
+ SMC_RET1(handle, PSCI_E_SUCCESS);
+ default:
+ ERROR("Unimplemented SMCWD call (%d)\n", x1);
+ SMC_RET1(handle, PSCI_E_NOT_SUPPORTED);
+ }
+}
diff --git a/plat/mediatek/mt8173/drivers/wdt/wdt.h b/plat/mediatek/mt8173/drivers/wdt/wdt.h
new file mode 100644
index 000000000..7262a5717
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/wdt/wdt.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2020, Google LLC. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef WDT_H
+#define WDT_H
+
+#include "stdint.h"
+
+void wdt_pet(void);
+void wdt_resume(void);
+void wdt_set_enable(int enable);
+int wdt_set_timeout(uint32_t timeout);
+uint64_t wdt_smc_handler(uint32_t x1, uint32_t x2, void *handle);
+void wdt_suspend(void);
+void wdt_trigger_reset(void);
+
+#endif /* WDT_H */
diff --git a/plat/mediatek/mt8173/include/mt8173_def.h b/plat/mediatek/mt8173/include/mt8173_def.h
index 58962f03d..378b4da55 100644
--- a/plat/mediatek/mt8173/include/mt8173_def.h
+++ b/plat/mediatek/mt8173/include/mt8173_def.h
@@ -80,18 +80,6 @@
#define PLAT_MT_CCI_CLUSTER0_SL_IFACE_IX 4
#define PLAT_MT_CCI_CLUSTER1_SL_IFACE_IX 3
-/*******************************************************************************
- * WDT related constants
- ******************************************************************************/
-#define MTK_WDT_BASE (RGU_BASE + 0)
-#define MTK_WDT_SWRST (MTK_WDT_BASE + 0x0014)
-
-#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
-
/* FIQ platform related define */
#define MT_IRQ_SEC_SGI_0 8
#define MT_IRQ_SEC_SGI_1 9
diff --git a/plat/mediatek/mt8173/include/plat_sip_calls.h b/plat/mediatek/mt8173/include/plat_sip_calls.h
index 88202cc55..ce9951a67 100644
--- a/plat/mediatek/mt8173/include/plat_sip_calls.h
+++ b/plat/mediatek/mt8173/include/plat_sip_calls.h
@@ -10,7 +10,7 @@
/*******************************************************************************
* Plat SiP function constants
******************************************************************************/
-#define MTK_PLAT_SIP_NUM_CALLS 6
+#define MTK_PLAT_SIP_NUM_CALLS 7
#define MTK_SIP_PWR_ON_MTCMOS 0x82000402
#define MTK_SIP_PWR_OFF_MTCMOS 0x82000403
@@ -18,5 +18,6 @@
#define MTK_SIP_SET_HDCP_KEY_NUM 0x82000405
#define MTK_SIP_CLR_HDCP_KEY 0x82000406
#define MTK_SIP_SET_HDCP_KEY_EX 0x82000407
+#define MTK_SIP_SMC_WATCHDOG 0x82003D06
#endif /* PLAT_SIP_CALLS_H */
diff --git a/plat/mediatek/mt8173/include/platform_def.h b/plat/mediatek/mt8173/include/platform_def.h
index 22129db13..d34042218 100644
--- a/plat/mediatek/mt8173/include/platform_def.h
+++ b/plat/mediatek/mt8173/include/platform_def.h
@@ -51,6 +51,8 @@
PLATFORM_CLUSTER_COUNT + \
PLATFORM_CORE_COUNT)
+#define SOC_CHIP_ID U(0x8173)
+
/*******************************************************************************
* Platform memory map related constants
******************************************************************************/
diff --git a/plat/mediatek/mt8173/plat_pm.c b/plat/mediatek/mt8173/plat_pm.c
index 67f1c731b..e72a3434e 100644
--- a/plat/mediatek/mt8173/plat_pm.c
+++ b/plat/mediatek/mt8173/plat_pm.c
@@ -27,6 +27,7 @@
#include <spm_hotplug.h>
#include <spm_mcdi.h>
#include <spm_suspend.h>
+#include <wdt.h>
#define MTK_PWR_LVL0 0
#define MTK_PWR_LVL1 1
@@ -350,6 +351,7 @@ static void plat_power_domain_suspend(const psci_power_state_t *state)
}
if (MTK_SYSTEM_PWR_STATE(state) == MTK_LOCAL_STATE_OFF) {
+ wdt_suspend();
disable_scu(mpidr);
generic_timer_backup();
spm_system_suspend();
@@ -409,6 +411,7 @@ static void plat_power_domain_suspend_finish(const psci_power_state_t *state)
plat_arm_gic_init();
spm_system_suspend_finish();
enable_scu(mpidr);
+ wdt_resume();
}
/* Perform the common cluster specific operations */
@@ -455,11 +458,7 @@ static void __dead2 plat_system_reset(void)
/* Write the System Configuration Control Register */
INFO("MTK System Reset\n");
- mmio_clrsetbits_32(MTK_WDT_BASE,
- (MTK_WDT_MODE_DUAL_MODE | MTK_WDT_MODE_IRQ),
- MTK_WDT_MODE_KEY);
- mmio_setbits_32(MTK_WDT_BASE, (MTK_WDT_MODE_KEY | MTK_WDT_MODE_EXTEN));
- mmio_setbits_32(MTK_WDT_SWRST, MTK_WDT_SWRST_KEY);
+ wdt_trigger_reset();
wfi();
ERROR("MTK System Reset: operation not handled.\n");
diff --git a/plat/mediatek/mt8173/plat_sip_calls.c b/plat/mediatek/mt8173/plat_sip_calls.c
index 102feb22a..da9b91dd6 100644
--- a/plat/mediatek/mt8173/plat_sip_calls.c
+++ b/plat/mediatek/mt8173/plat_sip_calls.c
@@ -12,6 +12,7 @@
#include <mtcmos.h>
#include <mtk_sip_svc.h>
#include <plat_sip_calls.h>
+#include <wdt.h>
/* Authorized secure register list */
enum {
@@ -102,6 +103,9 @@ uint64_t mediatek_plat_sip_handler(uint32_t smc_fid,
ret = crypt_clear_hdcp_key();
SMC_RET1(handle, ret);
+ case MTK_SIP_SMC_WATCHDOG:
+ return wdt_smc_handler(x1, x2, handle);
+
default:
ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
break;
diff --git a/plat/mediatek/mt8173/platform.mk b/plat/mediatek/mt8173/platform.mk
index a66c49bb4..f62802cb9 100644
--- a/plat/mediatek/mt8173/platform.mk
+++ b/plat/mediatek/mt8173/platform.mk
@@ -15,6 +15,7 @@ PLAT_INCLUDES := -I${MTK_PLAT}/common/ \
-I${MTK_PLAT_SOC}/drivers/rtc/ \
-I${MTK_PLAT_SOC}/drivers/spm/ \
-I${MTK_PLAT_SOC}/drivers/timer/ \
+ -I${MTK_PLAT_SOC}/drivers/wdt/ \
-I${MTK_PLAT_SOC}/include/
PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \
@@ -50,6 +51,7 @@ BL31_SOURCES += common/desc_image_load.c \
${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/wdt/wdt.c \
${MTK_PLAT_SOC}/plat_pm.c \
${MTK_PLAT_SOC}/plat_sip_calls.c \
${MTK_PLAT_SOC}/plat_topology.c \
diff --git a/plat/mediatek/mt8183/bl31_plat_setup.c b/plat/mediatek/mt8183/bl31_plat_setup.c
index 8204d7717..7dac8a49b 100644
--- a/plat/mediatek/mt8183/bl31_plat_setup.c
+++ b/plat/mediatek/mt8183/bl31_plat_setup.c
@@ -16,6 +16,7 @@
#include <drivers/generic_delay_timer.h>
#include <mcucfg.h>
#include <mt_gic_v3.h>
+#include <mt_timer.h>
#include <lib/coreboot.h>
#include <lib/mmio.h>
#include <mtk_mcdi.h>
@@ -112,7 +113,7 @@ entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
u_register_t arg2, u_register_t arg3)
{
- static console_16550_t console;
+ static console_t console;
params_early_setup(arg1);
@@ -148,6 +149,8 @@ void bl31_platform_setup(void)
mt_gic_driver_init();
mt_gic_init();
+ mt_systimer_init();
+
/* Init mcsi SF */
plat_mtk_cci_init_sf();
diff --git a/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c b/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c
index 64d854885..56d2ce26c 100644
--- a/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c
+++ b/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c
@@ -138,15 +138,9 @@ void emi_mpu_init(void)
(FORBIDDEN << 6));
emi_mpu_set_region_protection(0x52900000UL, 0x5FFFFFFFUL, 2,
(FORBIDDEN << 3 | FORBIDDEN << 6));
- emi_mpu_set_region_protection(0x60000000UL, 0x7FFFFFFFUL, 3,
+ emi_mpu_set_region_protection(0x60000000UL, 0xFFFFFFFFUL, 3,
(FORBIDDEN << 3 | FORBIDDEN << 6));
- emi_mpu_set_region_protection(0x80000000UL, 0x9FFFFFFFUL, 4,
- (FORBIDDEN << 3 | FORBIDDEN << 6));
- emi_mpu_set_region_protection(0xA0000000UL, 0xBFFFFFFFUL, 5,
- (FORBIDDEN << 3 | FORBIDDEN << 6));
- emi_mpu_set_region_protection(0xC0000000UL, 0xDFFFFFFFUL, 6,
- (FORBIDDEN << 3 | FORBIDDEN << 6));
- emi_mpu_set_region_protection(0xE0000000UL, 0xFFFFFFFFUL, 7,
+ emi_mpu_set_region_protection(0x100000000UL, 0x23FFFFFFFUL, 4,
(FORBIDDEN << 3 | FORBIDDEN << 6));
dump_emi_mpu_regions();
}
diff --git a/plat/mediatek/mt8183/drivers/timer/mt_timer.c b/plat/mediatek/mt8183/drivers/timer/mt_timer.c
new file mode 100644
index 000000000..0da4815b1
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/timer/mt_timer.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mcucfg.h>
+#include <mt_timer.h>
+#include <platform_def.h>
+
+static void enable_systimer_compensation(void)
+{
+ unsigned int reg;
+
+ reg = mmio_read_32(CNTCR_REG);
+ reg &= ~COMP_15_EN;
+ reg |= COMP_20_EN;
+ mmio_write_32(CNTCR_REG, reg);
+
+ NOTICE("[systimer] CNTCR_REG(0x%x)\n", mmio_read_32(CNTCR_REG));
+}
+
+void mt_systimer_init(void)
+{
+ /* systimer is default on, so we only enable systimer compensation */
+ enable_systimer_compensation();
+}
diff --git a/plat/mediatek/mt8183/drivers/timer/mt_timer.h b/plat/mediatek/mt8183/drivers/timer/mt_timer.h
new file mode 100644
index 000000000..0b8edc517
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/timer/mt_timer.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_TIMER_H
+#define MT_TIMER_H
+
+
+#define SYSTIMER_BASE (0x10017000)
+#define CNTCR_REG (SYSTIMER_BASE + 0x0)
+#define CNTSR_REG (SYSTIMER_BASE + 0x4)
+
+#define COMP_15_EN (1 << 10)
+#define COMP_20_EN (1 << 11)
+
+void mt_systimer_init(void);
+
+#endif /* MT_TIMER_H */
diff --git a/plat/mediatek/mt8183/drivers/uart/uart.h b/plat/mediatek/mt8183/drivers/uart/uart.h
index be04c3509..062ce3adc 100644
--- a/plat/mediatek/mt8183/drivers/uart/uart.h
+++ b/plat/mediatek/mt8183/drivers/uart/uart.h
@@ -95,6 +95,6 @@ struct mt_uart {
void mt_uart_save(void);
void mt_uart_restore(void);
void mt_console_uart_cg(int on);
-int mt_console_uart_cg_status(void);
+uint32_t mt_console_uart_cg_status(void);
#endif /* __UART_H__ */
diff --git a/plat/mediatek/mt8183/include/platform_def.h b/plat/mediatek/mt8183/include/platform_def.h
index 49a0f805e..25ccfbc52 100644
--- a/plat/mediatek/mt8183/include/platform_def.h
+++ b/plat/mediatek/mt8183/include/platform_def.h
@@ -279,6 +279,8 @@ INTR_PROP_DESC(MT_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
PLATFORM_CLUSTER_COUNT + \
PLATFORM_CORE_COUNT)
+#define SOC_CHIP_ID U(0x8183)
+
/*******************************************************************************
* Platform memory map related constants
******************************************************************************/
diff --git a/plat/mediatek/mt8183/platform.mk b/plat/mediatek/mt8183/platform.mk
index 597e18b90..07da1afac 100644
--- a/plat/mediatek/mt8183/platform.mk
+++ b/plat/mediatek/mt8183/platform.mk
@@ -14,6 +14,7 @@ PLAT_INCLUDES := -I${MTK_PLAT}/common/ \
-I${MTK_PLAT_SOC}/drivers/mcdi/ \
-I${MTK_PLAT_SOC}/drivers/spmc/ \
-I${MTK_PLAT_SOC}/drivers/gpio/ \
+ -I${MTK_PLAT_SOC}/drivers/timer/ \
-I${MTK_PLAT_SOC}/drivers/pmic/ \
-I${MTK_PLAT_SOC}/drivers/spm/ \
-I${MTK_PLAT_SOC}/drivers/sspm/ \
@@ -26,13 +27,12 @@ PLAT_BL_COMMON_SOURCES := lib/xlat_tables/aarch64/xlat_tables.c \
plat/common/plat_psci_common.c \
plat/common/aarch64/crash_console_helpers.S
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
BL31_SOURCES += common/desc_image_load.c \
drivers/arm/cci/cci.c \
- drivers/arm/gic/common/gic_common.c \
- drivers/arm/gic/v3/arm_gicv3_common.c \
- drivers/arm/gic/v3/gicv3_helpers.c \
- drivers/arm/gic/v3/gic500.c \
- drivers/arm/gic/v3/gicv3_main.c \
+ ${GICV3_SOURCES} \
drivers/delay_timer/delay_timer.c \
drivers/delay_timer/generic_delay_timer.c \
drivers/gpio/gpio.c \
@@ -45,6 +45,7 @@ BL31_SOURCES += common/desc_image_load.c \
${MTK_PLAT}/common/mtk_plat_common.c \
${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init.c \
${MTK_PLAT}/common/drivers/rtc/rtc_common.c \
+ ${MTK_PLAT}/common/drivers/uart/uart.c \
${MTK_PLAT}/common/params_setup.c \
${MTK_PLAT_SOC}/aarch64/plat_helpers.S \
${MTK_PLAT_SOC}/aarch64/platform_common.c \
@@ -58,7 +59,7 @@ BL31_SOURCES += common/desc_image_load.c \
${MTK_PLAT_SOC}/drivers/spm/spm_pmic_wrap.c \
${MTK_PLAT_SOC}/drivers/spm/spm_suspend.c \
${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \
- ${MTK_PLAT_SOC}/drivers/uart/uart.c \
+ ${MTK_PLAT_SOC}/drivers/timer/mt_timer.c \
${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c \
${MTK_PLAT_SOC}/plat_pm.c \
${MTK_PLAT_SOC}/plat_topology.c \
diff --git a/plat/mediatek/mt8192/aarch64/plat_helpers.S b/plat/mediatek/mt8192/aarch64/plat_helpers.S
new file mode 100644
index 000000000..99274dec4
--- /dev/null
+++ b/plat/mediatek/mt8192/aarch64/plat_helpers.S
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .globl plat_is_my_cpu_primary
+ .globl plat_my_core_pos
+ .globl plat_mediatek_calc_core_pos
+
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, #PLAT_PRIMARY_CPU
+ cset x0, eq
+ ret
+endfunc plat_is_my_cpu_primary
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * This function uses the plat_mediatek_calc_core_pos()
+ * definition to get the index of the calling CPU.
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b plat_mediatek_calc_core_pos
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr);
+ *
+ * In ARMv8.2, AFF2 is cluster id, AFF1 is core id and
+ * AFF0 is thread id. There is only one cluster in ARMv8.2
+ * and one thread in current implementation.
+ *
+ * With this function: CorePos = CoreID (AFF1)
+ * we do it with x0 = (x0 >> 8) & 0xff
+ * -----------------------------------------------------
+ */
+func plat_mediatek_calc_core_pos
+ mov x1, #MPIDR_AFFLVL_MASK
+ and x0, x1, x0, lsr #MPIDR_AFF1_SHIFT
+ ret
+endfunc plat_mediatek_calc_core_pos
diff --git a/plat/mediatek/mt8192/aarch64/platform_common.c b/plat/mediatek/mt8192/aarch64/platform_common.c
new file mode 100644
index 000000000..eb1bb4486
--- /dev/null
+++ b/plat/mediatek/mt8192/aarch64/platform_common.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Project Includes */
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+/* Platform Includes */
+#include <platform_def.h>
+
+/* Table of regions to map using the MMU. */
+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(MTK_DEV_RNG2_BASE, MTK_DEV_RNG2_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ { 0 }
+};
+
+/*******************************************************************************
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ ******************************************************************************/
+void plat_configure_mmu_el3(uintptr_t total_base,
+ uintptr_t total_size,
+ uintptr_t ro_start,
+ uintptr_t ro_limit)
+{
+ mmap_add_region(total_base, total_base, total_size,
+ MT_RW_DATA | MT_SECURE);
+ mmap_add_region(ro_start, ro_start, ro_limit - ro_start,
+ MT_CODE | MT_SECURE);
+ mmap_add(plat_mmap);
+ init_xlat_tables();
+ enable_mmu_el3(0);
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return SYS_COUNTER_FREQ_IN_TICKS;
+}
diff --git a/plat/mediatek/mt8192/bl31_plat_setup.c b/plat/mediatek/mt8192/bl31_plat_setup.c
new file mode 100644
index 000000000..9de4a2e62
--- /dev/null
+++ b/plat/mediatek/mt8192/bl31_plat_setup.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* System Includes */
+#include <assert.h>
+
+/* Project Includes */
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/coreboot.h>
+
+/* Platform Includes */
+#include <emi_mpu/emi_mpu.h>
+#include <gpio/mtgpio.h>
+#include <mt_gic_v3.h>
+#include <mt_timer.h>
+#include <mtk_dcm.h>
+#include <plat_params.h>
+#include <plat_private.h>
+
+static entry_point_info_t bl32_ep_info;
+static entry_point_info_t bl33_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. 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_ep_info : &bl32_ep_info;
+ assert(next_image_info->h.type == PARAM_EP);
+
+ /* None of the images on this platform can have 0x0 as the entrypoint */
+ if (next_image_info->pc) {
+ return next_image_info;
+ } else {
+ return NULL;
+ }
+}
+
+/*******************************************************************************
+ * Perform any BL31 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_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ static console_t console;
+
+ params_early_setup(arg1);
+
+#if COREBOOT
+ if (coreboot_serial.type) {
+ console_16550_register(coreboot_serial.baseaddr,
+ coreboot_serial.input_hertz,
+ coreboot_serial.baud,
+ &console);
+ }
+#else
+ console_16550_register(UART0_BASE, UART_CLOCK, UART_BAUDRATE, &console);
+#endif
+
+ NOTICE("MT8192 bl31_setup\n");
+
+ bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info);
+}
+
+
+/*******************************************************************************
+ * Perform any BL31 platform setup code
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+ /* Set dcm on */
+ if (!dcm_set_default()) {
+ ERROR("Failed to set default dcm on!!\n");
+ }
+
+ /* MPU Init */
+ emi_mpu_init();
+
+ /* Initialize the GIC driver, CPU and distributor interfaces */
+ mt_gic_driver_init();
+ mt_gic_init();
+
+ plat_mt8192_gpio_init();
+ mt_systimer_init();
+ generic_delay_timer_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+ plat_configure_mmu_el3(BL31_START,
+ BL31_END - BL31_START,
+ BL_CODE_BASE,
+ BL_CODE_END);
+}
diff --git a/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.c b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.c
new file mode 100644
index 000000000..dd8bf4eed
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mtk_dcm.h>
+#include <mtk_dcm_utils.h>
+
+static void dcm_armcore(bool mode)
+{
+ dcm_mp_cpusys_top_bus_pll_div_dcm(mode);
+ dcm_mp_cpusys_top_cpu_pll_div_0_dcm(mode);
+ dcm_mp_cpusys_top_cpu_pll_div_1_dcm(mode);
+}
+
+static void dcm_mcusys(bool on)
+{
+ dcm_mp_cpusys_top_adb_dcm(on);
+ dcm_mp_cpusys_top_apb_dcm(on);
+ dcm_mp_cpusys_top_cpubiu_dcm(on);
+ dcm_mp_cpusys_top_misc_dcm(on);
+ dcm_mp_cpusys_top_mp0_qdcm(on);
+ dcm_cpccfg_reg_emi_wfifo(on);
+ dcm_mp_cpusys_top_last_cor_idle_dcm(on);
+}
+
+static void dcm_stall(bool on)
+{
+ dcm_mp_cpusys_top_core_stall_dcm(on);
+ dcm_mp_cpusys_top_fcm_stall_dcm(on);
+}
+
+static bool check_dcm_state(void)
+{
+ bool ret = true;
+
+ ret &= dcm_mp_cpusys_top_bus_pll_div_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on();
+
+ ret &= dcm_mp_cpusys_top_adb_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_apb_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_cpubiu_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_misc_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_mp0_qdcm_is_on();
+ ret &= dcm_cpccfg_reg_emi_wfifo_is_on();
+ ret &= dcm_mp_cpusys_top_last_cor_idle_dcm_is_on();
+
+ ret &= dcm_mp_cpusys_top_core_stall_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_fcm_stall_dcm_is_on();
+
+ return ret;
+}
+
+bool dcm_set_default(void)
+{
+ dcm_armcore(true);
+ dcm_mcusys(true);
+ dcm_stall(true);
+
+ return check_dcm_state();
+}
diff --git a/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.h b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.h
new file mode 100644
index 000000000..ee98d0e38
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_DCM_H
+#define MTK_DCM_H
+
+#include <stdbool.h>
+
+bool dcm_set_default(void);
+
+#endif /* #ifndef MTK_DCM_H */
diff --git a/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.c b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.c
new file mode 100644
index 000000000..15a700c2b
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.c
@@ -0,0 +1,562 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <mtk_dcm_utils.h>
+
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_MASK (BIT(17))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_MASK (BIT(15) | \
+ BIT(16) | \
+ BIT(17) | \
+ BIT(18) | \
+ BIT(21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG2_MASK (BIT(15) | \
+ BIT(16) | \
+ BIT(17) | \
+ BIT(18))
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_ON (BIT(17))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_ON (BIT(15) | \
+ BIT(16) | \
+ BIT(17) | \
+ BIT(18) | \
+ BIT(21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG2_ON (BIT(15) | \
+ BIT(16) | \
+ BIT(17) | \
+ BIT(18))
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_OFF ((0x0 << 17))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_OFF ((0x0 << 15) | \
+ (0x0 << 16) | \
+ (0x0 << 17) | \
+ (0x0 << 18) | \
+ (0x0 << 21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG2_OFF ((0x0 << 15) | \
+ (0x0 << 16) | \
+ (0x0 << 17) | \
+ (0x0 << 18))
+
+bool dcm_mp_cpusys_top_adb_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_ADB_DCM_CFG0) &
+ MP_CPUSYS_TOP_ADB_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG0_ON);
+ ret &= ((mmio_read_32(MP_ADB_DCM_CFG4) &
+ MP_CPUSYS_TOP_ADB_DCM_REG1_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG1_ON);
+ ret &= ((mmio_read_32(MCUSYS_DCM_CFG0) &
+ MP_CPUSYS_TOP_ADB_DCM_REG2_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG2_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_adb_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_adb_dcm'" */
+ mmio_clrsetbits_32(MP_ADB_DCM_CFG0,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_ON);
+ mmio_clrsetbits_32(MP_ADB_DCM_CFG4,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_ON);
+ mmio_clrsetbits_32(MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_ADB_DCM_REG2_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG2_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_adb_dcm'" */
+ mmio_clrsetbits_32(MP_ADB_DCM_CFG0,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_OFF);
+ mmio_clrsetbits_32(MP_ADB_DCM_CFG4,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_OFF);
+ mmio_clrsetbits_32(MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_ADB_DCM_REG2_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG2_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_APB_DCM_REG0_MASK (BIT(5))
+#define MP_CPUSYS_TOP_APB_DCM_REG1_MASK (BIT(8))
+#define MP_CPUSYS_TOP_APB_DCM_REG2_MASK (BIT(16))
+#define MP_CPUSYS_TOP_APB_DCM_REG0_ON (BIT(5))
+#define MP_CPUSYS_TOP_APB_DCM_REG1_ON (BIT(8))
+#define MP_CPUSYS_TOP_APB_DCM_REG2_ON (BIT(16))
+#define MP_CPUSYS_TOP_APB_DCM_REG0_OFF ((0x0 << 5))
+#define MP_CPUSYS_TOP_APB_DCM_REG1_OFF ((0x0 << 8))
+#define MP_CPUSYS_TOP_APB_DCM_REG2_OFF ((0x0 << 16))
+
+bool dcm_mp_cpusys_top_apb_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_MISC_DCM_CFG0) &
+ MP_CPUSYS_TOP_APB_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG0_ON);
+ ret &= ((mmio_read_32(MCUSYS_DCM_CFG0) &
+ MP_CPUSYS_TOP_APB_DCM_REG1_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG1_ON);
+ ret &= ((mmio_read_32(MP0_DCM_CFG0) &
+ MP_CPUSYS_TOP_APB_DCM_REG2_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG2_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_apb_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_apb_dcm'" */
+ mmio_clrsetbits_32(MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG0_ON);
+ mmio_clrsetbits_32(MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG1_ON);
+ mmio_clrsetbits_32(MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG2_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG2_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_apb_dcm'" */
+ mmio_clrsetbits_32(MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG0_OFF);
+ mmio_clrsetbits_32(MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG1_OFF);
+ mmio_clrsetbits_32(MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG2_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG2_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK (BIT(11))
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON (BIT(11))
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF ((0x0 << 11))
+
+bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(BUS_PLLDIV_CFG) &
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_bus_pll_div_dcm'" */
+ mmio_clrsetbits_32(BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_bus_pll_div_dcm'" */
+ mmio_clrsetbits_32(BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK (BIT(0))
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON (BIT(0))
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF ((0x0 << 0))
+
+bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP0_DCM_CFG7) &
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_core_stall_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_core_stall_dcm'" */
+ mmio_clrsetbits_32(MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_core_stall_dcm'" */
+ mmio_clrsetbits_32(MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK ((0xffff << 0))
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON ((0xffff << 0))
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF ((0x0 << 0))
+
+bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MCSI_DCM0) &
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_cpubiu_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpubiu_dcm'" */
+ mmio_clrsetbits_32(MCSI_DCM0,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpubiu_dcm'" */
+ mmio_clrsetbits_32(MCSI_DCM0,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF ((0x0 << 11))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(CPU_PLLDIV_CFG0) &
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */
+ mmio_clrsetbits_32(CPU_PLLDIV_CFG0,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */
+ mmio_clrsetbits_32(CPU_PLLDIV_CFG0,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF ((0x0 << 11))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(CPU_PLLDIV_CFG1) &
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */
+ mmio_clrsetbits_32(CPU_PLLDIV_CFG1,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */
+ mmio_clrsetbits_32(CPU_PLLDIV_CFG1,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_MASK (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_ON (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_OFF ((0x0 << 11))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_2_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(CPU_PLLDIV_CFG2) &
+ MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_2_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_2_dcm'" */
+ mmio_clrsetbits_32(CPU_PLLDIV_CFG2,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_2_dcm'" */
+ mmio_clrsetbits_32(CPU_PLLDIV_CFG2,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_MASK (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_ON (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_OFF ((0x0 << 11))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_3_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(CPU_PLLDIV_CFG3) &
+ MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_3_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_3_dcm'" */
+ mmio_clrsetbits_32(CPU_PLLDIV_CFG3,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_3_dcm'" */
+ mmio_clrsetbits_32(CPU_PLLDIV_CFG3,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_MASK (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_ON (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_OFF ((0x0 << 11))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_4_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(CPU_PLLDIV_CFG4) &
+ MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_4_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_4_dcm'" */
+ mmio_clrsetbits_32(CPU_PLLDIV_CFG4,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_4_dcm'" */
+ mmio_clrsetbits_32(CPU_PLLDIV_CFG4,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK (BIT(4))
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON (BIT(4))
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF ((0x0 << 4))
+
+bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP0_DCM_CFG7) &
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_fcm_stall_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_fcm_stall_dcm'" */
+ mmio_clrsetbits_32(MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_fcm_stall_dcm'" */
+ mmio_clrsetbits_32(MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK ((0x1U << 31))
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON ((0x1U << 31))
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF ((0x0U << 31))
+
+bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(BUS_PLLDIV_CFG) &
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_last_cor_idle_dcm'" */
+ mmio_clrsetbits_32(BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_last_cor_idle_dcm'" */
+ mmio_clrsetbits_32(BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_MASK (BIT(1) | \
+ BIT(4))
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_ON (BIT(1) | \
+ BIT(4))
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_OFF ((0x0 << 1) | \
+ (0x0 << 4))
+
+bool dcm_mp_cpusys_top_misc_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_MISC_DCM_CFG0) &
+ MP_CPUSYS_TOP_MISC_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_MISC_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_misc_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_misc_dcm'" */
+ mmio_clrsetbits_32(MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_misc_dcm'" */
+ mmio_clrsetbits_32(MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK (BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK (BIT(0) | \
+ BIT(1) | \
+ BIT(2) | \
+ BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_ON (BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG1_ON (BIT(0) | \
+ BIT(1) | \
+ BIT(2) | \
+ BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF ((0x0 << 3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG1_OFF ((0x0 << 0) | \
+ (0x0 << 1) | \
+ (0x0 << 2) | \
+ (0x0 << 3))
+
+bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_MISC_DCM_CFG0) &
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_MP0_QDCM_REG0_ON);
+ ret &= ((mmio_read_32(MP0_DCM_CFG0) &
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_MP0_QDCM_REG1_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_mp0_qdcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_mp0_qdcm'" */
+ mmio_clrsetbits_32(MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_ON);
+ mmio_clrsetbits_32(MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK,
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_mp0_qdcm'" */
+ mmio_clrsetbits_32(MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF);
+ mmio_clrsetbits_32(MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK,
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_OFF);
+ }
+}
+
+#define CPCCFG_REG_EMI_WFIFO_REG0_MASK (BIT(0) | \
+ BIT(1) | \
+ BIT(2) | \
+ BIT(3))
+#define CPCCFG_REG_EMI_WFIFO_REG0_ON (BIT(0) | \
+ BIT(1) | \
+ BIT(2) | \
+ BIT(3))
+#define CPCCFG_REG_EMI_WFIFO_REG0_OFF ((0x0 << 0) | \
+ (0x0 << 1) | \
+ (0x0 << 2) | \
+ (0x0 << 3))
+
+bool dcm_cpccfg_reg_emi_wfifo_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(EMI_WFIFO) &
+ CPCCFG_REG_EMI_WFIFO_REG0_MASK) ==
+ (unsigned int) CPCCFG_REG_EMI_WFIFO_REG0_ON);
+
+ return ret;
+}
+
+void dcm_cpccfg_reg_emi_wfifo(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'cpccfg_reg_emi_wfifo'" */
+ mmio_clrsetbits_32(EMI_WFIFO,
+ CPCCFG_REG_EMI_WFIFO_REG0_MASK,
+ CPCCFG_REG_EMI_WFIFO_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'cpccfg_reg_emi_wfifo'" */
+ mmio_clrsetbits_32(EMI_WFIFO,
+ CPCCFG_REG_EMI_WFIFO_REG0_MASK,
+ CPCCFG_REG_EMI_WFIFO_REG0_OFF);
+ }
+}
+
diff --git a/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.h b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.h
new file mode 100644
index 000000000..1cf78345e
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_DCM_UTILS_H
+#define MTK_DCM_UTILS_H
+
+#include <stdbool.h>
+
+#include <mtk_dcm.h>
+#include <platform_def.h>
+
+/* Base */
+#define MP_CPUSYS_TOP_BASE (MCUCFG_BASE + 0x8000)
+#define CPCCFG_REG_BASE (MCUCFG_BASE + 0xA800)
+
+/* Register Definition */
+#define CPU_PLLDIV_CFG0 (MP_CPUSYS_TOP_BASE + 0x22a0)
+#define CPU_PLLDIV_CFG1 (MP_CPUSYS_TOP_BASE + 0x22a4)
+#define CPU_PLLDIV_CFG2 (MP_CPUSYS_TOP_BASE + 0x22a8)
+#define CPU_PLLDIV_CFG3 (MP_CPUSYS_TOP_BASE + 0x22ac)
+#define CPU_PLLDIV_CFG4 (MP_CPUSYS_TOP_BASE + 0x22b0)
+#define BUS_PLLDIV_CFG (MP_CPUSYS_TOP_BASE + 0x22e0)
+#define MCSI_DCM0 (MP_CPUSYS_TOP_BASE + 0x2440)
+#define MP_ADB_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x2500)
+#define MP_ADB_DCM_CFG4 (MP_CPUSYS_TOP_BASE + 0x2510)
+#define MP_MISC_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x2518)
+#define MCUSYS_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x25c0)
+#define EMI_WFIFO (CPCCFG_REG_BASE + 0x100)
+#define MP0_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x4880)
+#define MP0_DCM_CFG7 (MP_CPUSYS_TOP_BASE + 0x489c)
+
+/* MP_CPUSYS_TOP */
+bool dcm_mp_cpusys_top_adb_dcm_is_on(void);
+void dcm_mp_cpusys_top_adb_dcm(bool on);
+bool dcm_mp_cpusys_top_apb_dcm_is_on(void);
+void dcm_mp_cpusys_top_apb_dcm(bool on);
+bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void);
+void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on);
+bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void);
+void dcm_mp_cpusys_top_core_stall_dcm(bool on);
+bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpubiu_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_2_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_2_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_3_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_3_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_4_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_4_dcm(bool on);
+bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void);
+void dcm_mp_cpusys_top_fcm_stall_dcm(bool on);
+bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void);
+void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on);
+bool dcm_mp_cpusys_top_misc_dcm_is_on(void);
+void dcm_mp_cpusys_top_misc_dcm(bool on);
+bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void);
+void dcm_mp_cpusys_top_mp0_qdcm(bool on);
+/* CPCCFG_REG */
+bool dcm_cpccfg_reg_emi_wfifo_is_on(void);
+void dcm_cpccfg_reg_emi_wfifo(bool on);
+
+#endif
diff --git a/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c b/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c
new file mode 100644
index 000000000..d5d7e2e29
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <emi_mpu.h>
+#include <lib/mmio.h>
+
+/*
+ * emi_mpu_set_region_protection: protect a region.
+ * @start: start address of the region
+ * @end: end address of the region
+ * @access_permission: EMI MPU access permission
+ * Return 0 for success, otherwise negative status code.
+ */
+static int _emi_mpu_set_protection(
+ unsigned long start, unsigned long end,
+ unsigned int apc)
+{
+ unsigned int dgroup;
+ unsigned int region;
+
+ region = (start >> 24) & 0xFF;
+ start &= 0x00FFFFFF;
+ dgroup = (end >> 24) & 0xFF;
+ end &= 0x00FFFFFF;
+
+ if ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) {
+ WARN("Region:%u or dgroup:%u is wrong!\n", region, dgroup);
+ return -1;
+ }
+
+ apc &= 0x80FFFFFF;
+
+ if ((start >= DRAM_OFFSET) && (end >= start)) {
+ start -= DRAM_OFFSET;
+ end -= DRAM_OFFSET;
+ } else {
+ WARN("start:0x%lx or end:0x%lx address is wrong!\n",
+ start, end);
+ return -2;
+ }
+
+ mmio_write_32(EMI_MPU_SA(region), start);
+ mmio_write_32(EMI_MPU_EA(region), end);
+ mmio_write_32(EMI_MPU_APC(region, dgroup), apc);
+
+ return 0;
+}
+
+void dump_emi_mpu_regions(void)
+{
+ unsigned long apc[EMI_MPU_DGROUP_NUM], sa, ea;
+
+ int region, i;
+
+ /* Only dump 8 regions(max: EMI_MPU_REGION_NUM --> 32) */
+ for (region = 0; region < 8; ++region) {
+ for (i = 0; i < EMI_MPU_DGROUP_NUM; ++i)
+ apc[i] = mmio_read_32(EMI_MPU_APC(region, i));
+ sa = mmio_read_32(EMI_MPU_SA(region));
+ ea = mmio_read_32(EMI_MPU_EA(region));
+
+ WARN("region %d:\n", region);
+ WARN("\tsa:0x%lx, ea:0x%lx, apc0: 0x%lx apc1: 0x%lx\n",
+ sa, ea, apc[0], apc[1]);
+ }
+}
+
+int emi_mpu_set_protection(struct emi_region_info_t *region_info)
+{
+ unsigned long start, end;
+ int i;
+
+ if (region_info->region >= EMI_MPU_REGION_NUM)
+ return -1;
+
+ start = (unsigned long)(region_info->start >> EMI_MPU_ALIGN_BITS) |
+ (region_info->region << 24);
+
+ for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) {
+ end = (unsigned long)(region_info->end >> EMI_MPU_ALIGN_BITS) |
+ (i << 24);
+ _emi_mpu_set_protection(start, end, region_info->apc[i]);
+ }
+
+ return 0;
+}
+
+void emi_mpu_init(void)
+{
+ /* Set permission */
+ struct emi_region_info_t region_info;
+
+ /* PCE-e protect address(TODO) */
+ region_info.start = 0x80000000ULL;
+ region_info.end = 0x83FF0000ULL;
+ region_info.region = 1;
+ SET_ACCESS_PERMISSION(region_info.apc, 1,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, NO_PROT,
+ NO_PROT /*FORBIDDEN*/);
+ emi_mpu_set_protection(&region_info);
+
+ /* Forbidden All */
+ region_info.start = 0x40000000ULL; /* dram base addr */
+ region_info.end = 0x1FFFF0000ULL;
+ region_info.region = 2;
+ SET_ACCESS_PERMISSION(region_info.apc, 1,
+ NO_PROT, NO_PROT, NO_PROT, NO_PROT,
+ NO_PROT, NO_PROT, NO_PROT, NO_PROT,
+ NO_PROT, NO_PROT, NO_PROT, NO_PROT,
+ NO_PROT, FORBIDDEN, NO_PROT, NO_PROT);
+ emi_mpu_set_protection(&region_info);
+
+ dump_emi_mpu_regions();
+}
+
diff --git a/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h b/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h
new file mode 100644
index 000000000..0b1543197
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EMI_MPU_H
+#define EMI_MPU_H
+
+#include <platform_def.h>
+
+#define EMI_MPUP (EMI_BASE + 0x01D8)
+#define EMI_MPUQ (EMI_BASE + 0x01E0)
+#define EMI_MPUR (EMI_BASE + 0x01E8)
+#define EMI_MPUS (EMI_BASE + 0x01F0)
+#define EMI_MPUT (EMI_BASE + 0x01F8)
+#define EMI_MPUY (EMI_BASE + 0x0220)
+#define EMI_MPU_CTRL (EMI_MPU_BASE + 0x0000)
+#define EMI_MPUD0_ST (EMI_BASE + 0x0160)
+#define EMI_MPUD1_ST (EMI_BASE + 0x0164)
+#define EMI_MPUD2_ST (EMI_BASE + 0x0168)
+#define EMI_MPUD3_ST (EMI_BASE + 0x016C)
+#define EMI_MPUD0_ST2 (EMI_BASE + 0x0200)
+#define EMI_MPUD1_ST2 (EMI_BASE + 0x0204)
+#define EMI_MPUD2_ST2 (EMI_BASE + 0x0208)
+#define EMI_MPUD3_ST2 (EMI_BASE + 0x020C)
+
+#define EMI_PHY_OFFSET (0x40000000UL)
+
+#define NO_PROT (0)
+#define SEC_RW (1)
+#define SEC_RW_NSEC_R (2)
+#define SEC_RW_NSEC_W (3)
+#define SEC_R_NSEC_R (4)
+#define FORBIDDEN (5)
+#define SEC_R_NSEC_RW (6)
+
+#define SECURE_OS_MPU_REGION_ID (0)
+#define ATF_MPU_REGION_ID (1)
+
+#define EMI_MPU_SA0 (EMI_MPU_BASE + 0x100)
+#define EMI_MPU_EA0 (EMI_MPU_BASE + 0x200)
+#define EMI_MPU_SA(region) (EMI_MPU_SA0 + (region) * 4)
+#define EMI_MPU_EA(region) (EMI_MPU_EA0 + (region) * 4)
+
+#define EMI_MPU_APC0 (EMI_MPU_BASE + 0x300)
+#define EMI_MPU_APC(region, dgroup) (EMI_MPU_APC0 + (region) * 4 + \
+ (dgroup) * 0x100)
+
+#define EMI_MPU_CTRL_D0 (EMI_MPU_BASE + 0x800)
+#define EMI_MPU_CTRL_D(domain) (EMI_MPU_CTRL_D0 + domain * 4)
+#define EMI_RG_MASK_D0 (EMI_MPU_BASE + 0x900)
+#define EMI_RG_MASK_D(domain) (EMI_RG_MASK_D0 + domain * 4)
+
+#define EMI_MPU_DOMAIN_NUM 16
+#define EMI_MPU_REGION_NUM 32
+#define EMI_MPU_ALIGN_BITS 16
+#define DRAM_OFFSET (0x40000000 >> EMI_MPU_ALIGN_BITS)
+
+#define EMI_MPU_DGROUP_NUM (EMI_MPU_DOMAIN_NUM / 8)
+
+#if (EMI_MPU_DGROUP_NUM == 1)
+#define SET_ACCESS_PERMISSION(apc_ary, lock, d7, d6, d5, d4, d3, d2, d1, d0) \
+do { \
+ apc_ary[0] = 0; \
+ apc_ary[0] = \
+ (((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) \
+ | (((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) \
+ | (((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) \
+ | (((unsigned int) d1) << 3) | ((unsigned int) d0) \
+ | (((unsigned int) lock) << 31); \
+} while (0)
+#elif (EMI_MPU_DGROUP_NUM == 2)
+#define SET_ACCESS_PERMISSION(apc_ary, lock, d15, d14, d13, d12, d11, d10, \
+ d9, d8, d7, d6, d5, d4, d3, d2, d1, d0) \
+do { \
+ apc_ary[1] = \
+ (((unsigned int) d15) << 21) | (((unsigned int) d14) << 18) \
+ | (((unsigned int) d13) << 15) | (((unsigned int) d12) << 12) \
+ | (((unsigned int) d11) << 9) | (((unsigned int) d10) << 6) \
+ | (((unsigned int) d9) << 3) | ((unsigned int) d8); \
+ apc_ary[0] = \
+ (((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) \
+ | (((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) \
+ | (((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) \
+ | (((unsigned int) d1) << 3) | ((unsigned int) d0) \
+ | (((unsigned int) lock) << 31); \
+} while (0)
+#endif
+
+struct emi_region_info_t {
+ unsigned long long start;
+ unsigned long long end;
+ unsigned int region;
+ unsigned long apc[EMI_MPU_DGROUP_NUM];
+};
+
+void emi_mpu_init(void);
+int emi_mpu_set_protection(struct emi_region_info_t *region_info);
+void dump_emi_mpu_regions(void);
+
+#endif /* __EMI_MPU_H */
diff --git a/plat/mediatek/mt8192/drivers/gpio/mtgpio.c b/plat/mediatek/mt8192/drivers/gpio/mtgpio.c
new file mode 100644
index 000000000..e07b75a47
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/gpio/mtgpio.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <drivers/gpio.h>
+#include <lib/mmio.h>
+#include <mtgpio.h>
+#include <platform_def.h>
+
+/******************************************************************************
+ *Macro Definition
+ ******************************************************************************/
+#define GPIO_MODE_BITS 4
+#define MAX_GPIO_MODE_PER_REG 8
+#define MAX_GPIO_REG_BITS 32
+#define DIR_BASE (GPIO_BASE + 0x000)
+#define DOUT_BASE (GPIO_BASE + 0x100)
+#define DIN_BASE (GPIO_BASE + 0x200)
+#define MODE_BASE (GPIO_BASE + 0x300)
+#define SET 0x4
+#define CLR 0x8
+
+static void mt_set_gpio_dir_chip(uint32_t pin, int dir)
+{
+ uint32_t pos, bit;
+
+ assert(pin < MAX_GPIO_PIN);
+ assert(dir < MT_GPIO_DIR_MAX);
+
+ pos = pin / MAX_GPIO_REG_BITS;
+ bit = pin % MAX_GPIO_REG_BITS;
+
+ if (dir == MT_GPIO_DIR_IN) {
+ mmio_write_32(DIR_BASE + 0x10U * pos + CLR, 1U << bit);
+ } else {
+ mmio_write_32(DIR_BASE + 0x10U * pos + SET, 1U << bit);
+ }
+}
+
+static int mt_get_gpio_dir_chip(uint32_t pin)
+{
+ uint32_t pos, bit;
+ uint32_t reg;
+
+ assert(pin < MAX_GPIO_PIN);
+
+ pos = pin / MAX_GPIO_REG_BITS;
+ bit = pin % MAX_GPIO_REG_BITS;
+
+ reg = mmio_read_32(DIR_BASE + 0x10U * pos);
+ return (((reg & (1U << bit)) != 0U) ? MT_GPIO_DIR_OUT : MT_GPIO_DIR_IN);
+}
+
+static void mt_set_gpio_out_chip(uint32_t pin, int output)
+{
+ uint32_t pos, bit;
+
+ assert(pin < MAX_GPIO_PIN);
+ assert(output < MT_GPIO_OUT_MAX);
+
+ pos = pin / MAX_GPIO_REG_BITS;
+ bit = pin % MAX_GPIO_REG_BITS;
+
+ if (output == MT_GPIO_OUT_ZERO) {
+ mmio_write_32(DOUT_BASE + 0x10U * pos + CLR, 1U << bit);
+ } else {
+ mmio_write_32(DOUT_BASE + 0x10U * pos + SET, 1U << bit);
+ }
+}
+
+static int mt_get_gpio_in_chip(uint32_t pin)
+{
+ uint32_t pos, bit;
+ uint32_t reg;
+
+ assert(pin < MAX_GPIO_PIN);
+
+ pos = pin / MAX_GPIO_REG_BITS;
+ bit = pin % MAX_GPIO_REG_BITS;
+
+ reg = mmio_read_32(DIN_BASE + 0x10U * pos);
+ return (((reg & (1U << bit)) != 0U) ? 1 : 0);
+}
+
+static uintptr_t mt_gpio_find_reg_addr(uint32_t pin)
+{
+ uintptr_t reg_addr = 0U;
+ struct mt_pin_info gpio_info;
+
+ gpio_info = mt8192_pin_infos[pin];
+
+ switch (gpio_info.base & 0x0f) {
+ case 0:
+ reg_addr = IOCFG_RM_BASE;
+ break;
+ case 1:
+ reg_addr = IOCFG_BM_BASE;
+ break;
+ case 2:
+ reg_addr = IOCFG_BL_BASE;
+ break;
+ case 3:
+ reg_addr = IOCFG_BR_BASE;
+ break;
+ case 4:
+ reg_addr = IOCFG_LM_BASE;
+ break;
+ case 5:
+ reg_addr = IOCFG_LB_BASE;
+ break;
+ case 6:
+ reg_addr = IOCFG_RT_BASE;
+ break;
+ case 7:
+ reg_addr = IOCFG_LT_BASE;
+ break;
+ case 8:
+ reg_addr = IOCFG_TL_BASE;
+ break;
+ default:
+ break;
+ }
+
+ return reg_addr;
+}
+
+static void mt_gpio_set_spec_pull_pupd(uint32_t pin, int enable,
+ int select)
+{
+ uintptr_t reg1;
+ uintptr_t reg2;
+ struct mt_pin_info gpio_info;
+
+ gpio_info = mt8192_pin_infos[pin];
+ uint32_t bit = gpio_info.bit;
+
+ reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
+ reg2 = reg1 + (gpio_info.base & 0xf0);
+ if (enable == MT_GPIO_PULL_ENABLE) {
+ mmio_write_32(reg2 + SET, (1U << bit));
+ if (select == MT_GPIO_PULL_DOWN) {
+ mmio_write_32(reg1 + SET, (1U << bit));
+ } else {
+ mmio_write_32(reg1 + CLR, (1U << bit));
+ }
+ } else {
+ mmio_write_32(reg2 + CLR, (1U << bit));
+ mmio_write_32((reg2 + 0x010U) + CLR, (1U << bit));
+ }
+}
+
+static void mt_gpio_set_pull_pu_pd(uint32_t pin, int enable,
+ int select)
+{
+ uintptr_t reg1;
+ uintptr_t reg2;
+ struct mt_pin_info gpio_info;
+
+ gpio_info = mt8192_pin_infos[pin];
+ uint32_t bit = gpio_info.bit;
+
+ reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
+ reg2 = reg1 - (gpio_info.base & 0xf0);
+
+ if (enable == MT_GPIO_PULL_ENABLE) {
+ if (select == MT_GPIO_PULL_DOWN) {
+ mmio_write_32(reg1 + CLR, (1U << bit));
+ mmio_write_32(reg2 + SET, (1U << bit));
+ } else {
+ mmio_write_32(reg2 + CLR, (1U << bit));
+ mmio_write_32(reg1 + SET, (1U << bit));
+ }
+ } else {
+ mmio_write_32(reg1 + CLR, (1U << bit));
+ mmio_write_32(reg2 + CLR, (1U << bit));
+ }
+}
+
+static void mt_gpio_set_pull_chip(uint32_t pin, int enable,
+ int select)
+{
+ struct mt_pin_info gpio_info;
+
+ gpio_info = mt8192_pin_infos[pin];
+ if (gpio_info.flag) {
+ mt_gpio_set_spec_pull_pupd(pin, enable, select);
+ } else {
+ mt_gpio_set_pull_pu_pd(pin, enable, select);
+ }
+}
+
+static int mt_gpio_get_spec_pull_pupd(uint32_t pin)
+{
+ uintptr_t reg1;
+ uintptr_t reg2;
+ uint32_t r0;
+ uint32_t r1;
+
+ struct mt_pin_info gpio_info;
+
+ gpio_info = mt8192_pin_infos[pin];
+ uint32_t bit = gpio_info.bit;
+
+ reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
+ reg2 = reg1 + (gpio_info.base & 0xf0);
+
+ r0 = (mmio_read_32(reg2) >> bit) & 1U;
+ r1 = (mmio_read_32(reg2 + 0x010) >> bit) & 1U;
+ if (r0 == 0U && r1 == 0U) {
+ return MT_GPIO_PULL_NONE;
+ } else {
+ if (mmio_read_32(reg1) & (1U << bit)) {
+ return MT_GPIO_PULL_DOWN;
+ } else {
+ return MT_GPIO_PULL_UP;
+ }
+ }
+}
+
+static int mt_gpio_get_pull_pu_pd(uint32_t pin)
+{
+ uintptr_t reg1;
+ uintptr_t reg2;
+ uint32_t pu;
+ uint32_t pd;
+
+ struct mt_pin_info gpio_info;
+
+ gpio_info = mt8192_pin_infos[pin];
+ uint32_t bit = gpio_info.bit;
+
+ reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
+ reg2 = reg1 - (gpio_info.base & 0xf0);
+ pu = (mmio_read_32(reg1) >> bit) & 1U;
+ pd = (mmio_read_32(reg2) >> bit) & 1U;
+ if (pu == 1U) {
+ return MT_GPIO_PULL_UP;
+ } else if (pd == 1U) {
+ return MT_GPIO_PULL_DOWN;
+ } else {
+ return MT_GPIO_PULL_NONE;
+ }
+}
+
+static int mt_gpio_get_pull_chip(uint32_t pin)
+{
+ struct mt_pin_info gpio_info;
+
+ gpio_info = mt8192_pin_infos[pin];
+ if (gpio_info.flag) {
+ return mt_gpio_get_spec_pull_pupd(pin);
+ } else {
+ return mt_gpio_get_pull_pu_pd(pin);
+ }
+}
+
+static void mt_set_gpio_pull_select_chip(uint32_t pin, int sel)
+{
+ assert(pin < MAX_GPIO_PIN);
+
+ if (sel == MT_GPIO_PULL_NONE) {
+ mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_DISABLE, MT_GPIO_PULL_DOWN);
+ } else if (sel == MT_GPIO_PULL_UP) {
+ mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_UP);
+ } else if (sel == MT_GPIO_PULL_DOWN) {
+ mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_DOWN);
+ }
+}
+
+/* get pull-up or pull-down, regardless of resistor value */
+static int mt_get_gpio_pull_select_chip(uint32_t pin)
+{
+ assert(pin < MAX_GPIO_PIN);
+
+ return mt_gpio_get_pull_chip(pin);
+}
+
+static void mt_set_gpio_dir(int gpio, int direction)
+{
+ mt_set_gpio_dir_chip((uint32_t)gpio, direction);
+}
+
+static int mt_get_gpio_dir(int gpio)
+{
+ uint32_t pin;
+
+ pin = (uint32_t)gpio;
+ return mt_get_gpio_dir_chip(pin);
+}
+
+static void mt_set_gpio_pull(int gpio, int pull)
+{
+ uint32_t pin;
+
+ pin = (uint32_t)gpio;
+ mt_set_gpio_pull_select_chip(pin, pull);
+}
+
+static int mt_get_gpio_pull(int gpio)
+{
+ uint32_t pin;
+
+ pin = (uint32_t)gpio;
+ return mt_get_gpio_pull_select_chip(pin);
+}
+
+static void mt_set_gpio_out(int gpio, int value)
+{
+ uint32_t pin;
+
+ pin = (uint32_t)gpio;
+ mt_set_gpio_out_chip(pin, value);
+}
+
+static int mt_get_gpio_in(int gpio)
+{
+ uint32_t pin;
+
+ pin = (uint32_t)gpio;
+ return mt_get_gpio_in_chip(pin);
+}
+
+const gpio_ops_t mtgpio_ops = {
+ .get_direction = mt_get_gpio_dir,
+ .set_direction = mt_set_gpio_dir,
+ .get_value = mt_get_gpio_in,
+ .set_value = mt_set_gpio_out,
+ .set_pull = mt_set_gpio_pull,
+ .get_pull = mt_get_gpio_pull,
+};
+
+void plat_mt8192_gpio_init(void)
+{
+ gpio_init(&mtgpio_ops);
+}
diff --git a/plat/mediatek/mt8192/drivers/gpio/mtgpio.h b/plat/mediatek/mt8192/drivers/gpio/mtgpio.h
new file mode 100644
index 000000000..ca0c964f6
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/gpio/mtgpio.h
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_GPIO_H
+#define MT_GPIO_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <plat/common/common_def.h>
+
+/* Error Code No. */
+#define RSUCCESS 0
+#define ERACCESS 1
+#define ERINVAL 2
+#define ERWRAPPER 3
+#define MAX_GPIO_PIN MT_GPIO_BASE_MAX
+
+/* Enumeration for GPIO pin */
+typedef enum GPIO_PIN {
+ GPIO_UNSUPPORTED = -1,
+
+ GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6, GPIO7,
+ GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13, GPIO14, GPIO15,
+ GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23,
+ GPIO24, GPIO25, GPIO26, GPIO27, GPIO28, GPIO29, GPIO30, GPIO31,
+ GPIO32, GPIO33, GPIO34, GPIO35, GPIO36, GPIO37, GPIO38, GPIO39,
+ GPIO40, GPIO41, GPIO42, GPIO43, GPIO44, GPIO45, GPIO46, GPIO47,
+ GPIO48, GPIO49, GPIO50, GPIO51, GPIO52, GPIO53, GPIO54, GPIO55,
+ GPIO56, GPIO57, GPIO58, GPIO59, GPIO60, GPIO61, GPIO62, GPIO63,
+ GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70, GPIO71,
+ GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78, GPIO79,
+ GPIO80, GPIO81, GPIO82, GPIO83, GPIO84, GPIO85, GPIO86, GPIO87,
+ GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94, GPIO95,
+ GPIO96, GPIO97, GPIO98, GPIO99, GPIO100, GPIO101, GPIO102, GPIO103,
+ GPIO104, GPIO105, GPIO106, GPIO107, GPIO108, GPIO109, GPIO110, GPIO111,
+ GPIO112, GPIO113, GPIO114, GPIO115, GPIO116, GPIO117, GPIO118, GPIO119,
+ GPIO120, GPIO121, GPIO122, GPIO123, GPIO124, GPIO125, GPIO126, GPIO127,
+ GPIO128, GPIO129, GPIO130, GPIO131, GPIO132, GPIO133, GPIO134, GPIO135,
+ GPIO136, GPIO137, GPIO138, GPIO139, GPIO140, GPIO141, GPIO142, GPIO143,
+ GPIO144, GPIO145, GPIO146, GPIO147, GPIO148, GPIO149, GPIO150, GPIO151,
+ GPIO152, GPIO153, GPIO154, GPIO155, GPIO156, GPIO157, GPIO158, GPIO159,
+ GPIO160, GPIO161, GPIO162, GPIO163, GPIO164, GPIO165, GPIO166, GPIO167,
+ GPIO168, GPIO169, GPIO170, GPIO171, GPIO172, GPIO173, GPIO174, GPIO175,
+ GPIO176, GPIO177, GPIO178, GPIO179, GPIO180, GPIO181, GPIO182, GPIO183,
+ GPIO184, GPIO185, GPIO186, GPIO187, GPIO188, GPIO189, GPIO190, GPIO191,
+ GPIO192, GPIO193, GPIO194, GPIO195, GPIO196, GPIO197, GPIO198, GPIO199,
+ GPIO200, GPIO201, GPIO202, GPIO203, GPIO204, GPIO205, GPIO206, GPIO207,
+ GPIO208, GPIO209, GPIO210, GPIO211, GPIO212, GPIO213, GPIO214, GPIO215,
+ GPIO216, GPIO217, GPIO218, GPIO219,
+ MT_GPIO_BASE_MAX
+} GPIO_PIN;
+
+/* GPIO MODE CONTROL VALUE*/
+typedef enum {
+ GPIO_MODE_UNSUPPORTED = -1,
+ GPIO_MODE_GPIO = 0,
+ GPIO_MODE_00 = 0,
+ GPIO_MODE_01,
+ GPIO_MODE_02,
+ GPIO_MODE_03,
+ GPIO_MODE_04,
+ GPIO_MODE_05,
+ GPIO_MODE_06,
+ GPIO_MODE_07,
+
+ GPIO_MODE_MAX,
+ GPIO_MODE_DEFAULT = GPIO_MODE_00,
+} GPIO_MODE;
+
+/* GPIO DIRECTION */
+typedef enum {
+ MT_GPIO_DIR_UNSUPPORTED = -1,
+ MT_GPIO_DIR_OUT = 0,
+ MT_GPIO_DIR_IN = 1,
+ MT_GPIO_DIR_MAX,
+ MT_GPIO_DIR_DEFAULT = MT_GPIO_DIR_IN,
+} GPIO_DIR;
+
+/* GPIO PULL ENABLE*/
+typedef enum {
+ MT_GPIO_PULL_EN_UNSUPPORTED = -1,
+ MT_GPIO_PULL_DISABLE = 0,
+ MT_GPIO_PULL_ENABLE = 1,
+ MT_GPIO_PULL_ENABLE_R0 = 2,
+ MT_GPIO_PULL_ENABLE_R1 = 3,
+ MT_GPIO_PULL_ENABLE_R0R1 = 4,
+
+ MT_GPIO_PULL_EN_MAX,
+ MT_GPIO_PULL_EN_DEFAULT = MT_GPIO_PULL_ENABLE,
+} GPIO_PULL_EN;
+
+/* GPIO PULL-UP/PULL-DOWN*/
+typedef enum {
+ MT_GPIO_PULL_UNSUPPORTED = -1,
+ MT_GPIO_PULL_NONE = 0,
+ MT_GPIO_PULL_UP = 1,
+ MT_GPIO_PULL_DOWN = 2,
+ MT_GPIO_PULL_MAX,
+ MT_GPIO_PULL_DEFAULT = MT_GPIO_PULL_DOWN
+} GPIO_PULL;
+
+/* GPIO OUTPUT */
+typedef enum {
+ MT_GPIO_OUT_UNSUPPORTED = -1,
+ MT_GPIO_OUT_ZERO = 0,
+ MT_GPIO_OUT_ONE = 1,
+
+ MT_GPIO_OUT_MAX,
+ MT_GPIO_OUT_DEFAULT = MT_GPIO_OUT_ZERO,
+ MT_GPIO_DATA_OUT_DEFAULT = MT_GPIO_OUT_ZERO, /*compatible with DCT*/
+} GPIO_OUT;
+
+/* GPIO INPUT */
+typedef enum {
+ MT_GPIO_IN_UNSUPPORTED = -1,
+ MT_GPIO_IN_ZERO = 0,
+ MT_GPIO_IN_ONE = 1,
+
+ MT_GPIO_IN_MAX,
+} GPIO_IN;
+
+typedef struct {
+ uint32_t val;
+ uint32_t set;
+ uint32_t rst;
+ uint32_t _align1;
+} VAL_REGS;
+
+typedef struct {
+ VAL_REGS dir[7];
+ uint8_t rsv00[144];
+ VAL_REGS dout[7];
+ uint8_t rsv01[144];
+ VAL_REGS din[7];
+ uint8_t rsv02[144];
+ VAL_REGS mode[28];
+} GPIO_REGS;
+
+
+#define PIN(_id, _flag, _bit, _base, _offset) { \
+ .id = _id, \
+ .flag = _flag, \
+ .bit = _bit, \
+ .base = _base, \
+ .offset = _offset, \
+ }
+
+struct mt_pin_info {
+ uint8_t id;
+ uint8_t flag;
+ uint8_t bit;
+ uint16_t base;
+ uint16_t offset;
+};
+
+static const struct mt_pin_info mt8192_pin_infos[] = {
+ PIN(0, 0, 9, 0x23, 0xb0),
+ PIN(1, 0, 10, 0x23, 0xb0),
+ PIN(2, 0, 11, 0x23, 0xb0),
+ PIN(3, 0, 12, 0x23, 0xb0),
+ PIN(4, 0, 13, 0x23, 0xb0),
+ PIN(5, 0, 14, 0x23, 0xb0),
+ PIN(6, 0, 15, 0x23, 0xb0),
+ PIN(7, 0, 16, 0x23, 0xb0),
+ PIN(8, 0, 17, 0x23, 0xb0),
+ PIN(9, 0, 18, 0x23, 0xb0),
+ PIN(10, 1, 0, 0x15, 0x20),
+ PIN(11, 1, 1, 0x15, 0x20),
+ PIN(12, 1, 2, 0x15, 0x20),
+ PIN(13, 1, 3, 0x15, 0x20),
+ PIN(14, 1, 4, 0x15, 0x20),
+ PIN(15, 1, 5, 0x15, 0x20),
+ PIN(16, 0, 2, 0x17, 0x50),
+ PIN(17, 0, 3, 0x17, 0x50),
+ PIN(18, 0, 21, 0x36, 0xa0),
+ PIN(19, 0, 22, 0x36, 0xa0),
+ PIN(20, 0, 23, 0x36, 0xa0),
+ PIN(21, 0, 24, 0x36, 0xa0),
+ PIN(22, 0, 3, 0x21, 0x90),
+ PIN(23, 0, 4, 0x21, 0x90),
+ PIN(24, 0, 5, 0x21, 0x90),
+ PIN(25, 0, 6, 0x21, 0x90),
+ PIN(26, 0, 5, 0x22, 0x80),
+ PIN(27, 0, 6, 0x22, 0x80),
+ PIN(28, 0, 7, 0x22, 0x80),
+ PIN(29, 0, 8, 0x22, 0x80),
+ PIN(30, 0, 9, 0x22, 0x80),
+ PIN(31, 0, 27, 0x22, 0x70),
+ PIN(32, 0, 24, 0x22, 0x70),
+ PIN(33, 0, 26, 0x22, 0x70),
+ PIN(34, 0, 23, 0x22, 0x70),
+ PIN(35, 0, 25, 0x22, 0x70),
+ PIN(36, 0, 20, 0x21, 0x90),
+ PIN(37, 0, 21, 0x21, 0x90),
+ PIN(38, 0, 22, 0x21, 0x90),
+ PIN(39, 0, 23, 0x21, 0x90),
+ PIN(40, 0, 0, 0x17, 0x50),
+ PIN(41, 0, 1, 0x17, 0x50),
+ PIN(42, 0, 4, 0x17, 0x50),
+ PIN(43, 0, 25, 0x36, 0xa0),
+ PIN(44, 0, 26, 0x36, 0xa0),
+ PIN(45, 1, 9, 0x20, 0x60),
+ PIN(46, 1, 11, 0x20, 0x60),
+ PIN(47, 1, 10, 0x20, 0x60),
+ PIN(48, 1, 7, 0x20, 0x60),
+ PIN(49, 1, 8, 0x20, 0x60),
+ PIN(50, 1, 6, 0x20, 0x60),
+ PIN(51, 1, 0, 0x20, 0x60),
+ PIN(52, 1, 1, 0x20, 0x60),
+ PIN(53, 1, 5, 0x20, 0x60),
+ PIN(54, 1, 2, 0x20, 0x60),
+ PIN(55, 1, 4, 0x20, 0x60),
+ PIN(56, 1, 3, 0x20, 0x60),
+ PIN(57, 0, 1, 0x22, 0x80),
+ PIN(58, 0, 2, 0x22, 0x80),
+ PIN(59, 0, 3, 0x22, 0x80),
+ PIN(60, 0, 4, 0x22, 0x80),
+ PIN(61, 0, 28, 0x22, 0x70),
+ PIN(62, 0, 22, 0x22, 0x70),
+ PIN(63, 0, 0, 0x22, 0x70),
+ PIN(64, 0, 1, 0x22, 0x70),
+ PIN(65, 0, 12, 0x22, 0x70),
+ PIN(66, 0, 15, 0x22, 0x70),
+ PIN(67, 0, 16, 0x22, 0x70),
+ PIN(68, 0, 17, 0x22, 0x70),
+ PIN(69, 0, 18, 0x22, 0x70),
+ PIN(70, 0, 19, 0x22, 0x70),
+ PIN(71, 0, 20, 0x22, 0x70),
+ PIN(72, 0, 21, 0x22, 0x70),
+ PIN(73, 0, 2, 0x22, 0x70),
+ PIN(74, 0, 3, 0x22, 0x70),
+ PIN(75, 0, 4, 0x22, 0x70),
+ PIN(76, 0, 5, 0x22, 0x70),
+ PIN(77, 0, 6, 0x22, 0x70),
+ PIN(78, 0, 7, 0x22, 0x70),
+ PIN(79, 0, 8, 0x22, 0x70),
+ PIN(80, 0, 9, 0x22, 0x70),
+ PIN(81, 0, 10, 0x22, 0x70),
+ PIN(82, 0, 11, 0x22, 0x70),
+ PIN(83, 0, 13, 0x22, 0x70),
+ PIN(84, 0, 14, 0x22, 0x70),
+ PIN(85, 0, 31, 0x22, 0x70),
+ PIN(86, 0, 0, 0x22, 0x80),
+ PIN(87, 0, 29, 0x22, 0x70),
+ PIN(88, 0, 30, 0x22, 0x70),
+ PIN(89, 0, 24, 0x21, 0x90),
+ PIN(90, 0, 25, 0x21, 0x90),
+ PIN(91, 0, 0, 0x21, 0x90),
+ PIN(92, 0, 2, 0x21, 0xa0),
+ PIN(93, 0, 4, 0x21, 0xa0),
+ PIN(94, 0, 3, 0x21, 0xa0),
+ PIN(95, 0, 5, 0x21, 0xa0),
+ PIN(96, 0, 31, 0x21, 0x90),
+ PIN(97, 0, 26, 0x21, 0x90),
+ PIN(98, 0, 0, 0x21, 0xa0),
+ PIN(99, 0, 27, 0x21, 0x90),
+ PIN(100, 0, 28, 0x21, 0x90),
+ PIN(101, 0, 29, 0x21, 0x90),
+ PIN(102, 0, 30, 0x21, 0x90),
+ PIN(103, 0, 18, 0x21, 0x90),
+ PIN(104, 0, 17, 0x21, 0x90),
+ PIN(105, 0, 19, 0x21, 0x90),
+ PIN(106, 0, 16, 0x21, 0x90),
+ PIN(107, 0, 1, 0x21, 0x90),
+ PIN(108, 0, 2, 0x21, 0x90),
+ PIN(109, 0, 10, 0x21, 0x90),
+ PIN(110, 0, 7, 0x21, 0x90),
+ PIN(111, 0, 9, 0x21, 0x90),
+ PIN(112, 0, 11, 0x21, 0x90),
+ PIN(113, 0, 8, 0x21, 0x90),
+ PIN(114, 0, 14, 0x21, 0x90),
+ PIN(115, 0, 13, 0x21, 0x90),
+ PIN(116, 0, 15, 0x21, 0x90),
+ PIN(117, 0, 12, 0x21, 0x90),
+ PIN(118, 0, 23, 0x23, 0xb0),
+ PIN(119, 0, 29, 0x23, 0xb0),
+ PIN(120, 0, 28, 0x23, 0xb0),
+ PIN(121, 0, 2, 0x23, 0xc0),
+ PIN(122, 0, 27, 0x23, 0xb0),
+ PIN(123, 0, 1, 0x23, 0xc0),
+ PIN(124, 0, 26, 0x23, 0xb0),
+ PIN(125, 0, 0, 0x23, 0xc0),
+ PIN(126, 0, 19, 0x23, 0xb0),
+ PIN(127, 0, 20, 0x23, 0xb0),
+ PIN(128, 0, 21, 0x23, 0xb0),
+ PIN(129, 0, 22, 0x23, 0xb0),
+ PIN(130, 0, 6, 0x23, 0xb0),
+ PIN(131, 0, 7, 0x23, 0xb0),
+ PIN(132, 0, 8, 0x23, 0xb0),
+ PIN(133, 0, 3, 0x23, 0xb0),
+ PIN(134, 0, 4, 0x23, 0xb0),
+ PIN(135, 0, 5, 0x23, 0xb0),
+ PIN(136, 0, 0, 0x23, 0xb0),
+ PIN(137, 0, 1, 0x23, 0xb0),
+ PIN(138, 0, 2, 0x23, 0xb0),
+ PIN(139, 0, 25, 0x23, 0xb0),
+ PIN(140, 0, 31, 0x23, 0xb0),
+ PIN(141, 0, 24, 0x23, 0xb0),
+ PIN(142, 0, 30, 0x23, 0xb0),
+ PIN(143, 0, 6, 0x20, 0x70),
+ PIN(144, 0, 7, 0x20, 0x70),
+ PIN(145, 0, 8, 0x20, 0x70),
+ PIN(146, 0, 3, 0x20, 0x70),
+ PIN(147, 0, 4, 0x20, 0x70),
+ PIN(148, 0, 5, 0x20, 0x70),
+ PIN(149, 0, 0, 0x20, 0x70),
+ PIN(150, 0, 1, 0x20, 0x70),
+ PIN(151, 0, 2, 0x20, 0x70),
+ PIN(152, 1, 3, 0x36, 0x90),
+ PIN(153, 1, 2, 0x36, 0x90),
+ PIN(154, 1, 0, 0x36, 0x906),
+ PIN(155, 1, 1, 0x36, 0x90),
+ PIN(156, 0, 29, 0x36, 0xa0),
+ PIN(157, 0, 30, 0x36, 0xa0),
+ PIN(158, 0, 31, 0x36, 0xa0),
+ PIN(159, 0, 0, 0x36, 0xb0),
+ PIN(160, 0, 27, 0x36, 0xa04),
+ PIN(161, 0, 28, 0x36, 0xa0),
+ PIN(162, 0, 0, 0x36, 0xa0),
+ PIN(163, 0, 1, 0x36, 0xa0),
+ PIN(164, 0, 2, 0x36, 0xa0),
+ PIN(165, 0, 3, 0x36, 0xa0),
+ PIN(166, 0, 4, 0x36, 0xa0),
+ PIN(167, 0, 5, 0x36, 0xa0),
+ PIN(168, 0, 6, 0x36, 0xa0),
+ PIN(169, 0, 7, 0x36, 0xa0),
+ PIN(170, 0, 8, 0x36, 0xa0),
+ PIN(171, 0, 9, 0x36, 0xa0),
+ PIN(172, 0, 13, 0x36, 0xa0),
+ PIN(173, 0, 14, 0x36, 0xa0),
+ PIN(174, 0, 12, 0x36, 0xa0),
+ PIN(175, 0, 15, 0x36, 0xa0),
+ PIN(176, 0, 10, 0x36, 0xa0),
+ PIN(177, 0, 11, 0x36, 0xa0),
+ PIN(178, 0, 16, 0x36, 0xa0),
+ PIN(179, 0, 17, 0x36, 0xa0),
+ PIN(180, 0, 18, 0x36, 0xa0),
+ PIN(181, 0, 19, 0x36, 0xa0),
+ PIN(182, 0, 20, 0x36, 0xa0),
+ PIN(183, 1, 1, 0x18, 0x30),
+ PIN(184, 1, 2, 0x18, 0x30),
+ PIN(185, 1, 4, 0x18, 0x30),
+ PIN(186, 1, 6, 0x18, 0x30),
+ PIN(187, 1, 8, 0x18, 0x30),
+ PIN(188, 1, 3, 0x18, 0x30),
+ PIN(189, 1, 7, 0x18, 0x30),
+ PIN(190, 1, 9, 0x18, 0x30),
+ PIN(191, 1, 10, 0x18, 0x30),
+ PIN(192, 1, 0, 0x18, 0x30),
+ PIN(193, 1, 5, 0x18, 0x30),
+ PIN(194, 1, 11, 0x18, 0x30),
+ PIN(195, 0, 16, 0x14, 0x50),
+ PIN(196, 0, 6, 0x14, 0x50),
+ PIN(197, 0, 8, 0x14, 0x50),
+ PIN(198, 0, 7, 0x14, 0x50),
+ PIN(199, 0, 3, 0x14, 0x50),
+ PIN(200, 0, 6, 0x17, 0x50),
+ PIN(201, 0, 8, 0x17, 0x50),
+ PIN(202, 0, 15, 0x14, 0x50),
+ PIN(203, 0, 17, 0x14, 0x50),
+ PIN(204, 0, 5, 0x17, 0x50),
+ PIN(205, 0, 7, 0x17, 0x50),
+ PIN(206, 0, 18, 0x14, 0x50),
+ PIN(207, 0, 19, 0x14, 0x50),
+ PIN(208, 0, 20, 0x14, 0x50),
+ PIN(209, 0, 12, 0x14, 0x50),
+ PIN(210, 0, 11, 0x14, 0x50),
+ PIN(211, 0, 13, 0x14, 0x50),
+ PIN(212, 0, 10, 0x14, 0x50),
+ PIN(213, 0, 14, 0x14, 0x50),
+ PIN(214, 0, 0, 0x14, 0x50),
+ PIN(215, 0, 9, 0x14, 0x50),
+ PIN(216, 0, 4, 0x14, 0x50),
+ PIN(217, 0, 5, 0x14, 0x50),
+ PIN(218, 0, 1, 0x14, 0x50),
+ PIN(219, 0, 2, 0x14, 0x50),
+};
+
+void plat_mt8192_gpio_init(void);
+#endif /* MT_GPIO_H */
diff --git a/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c
new file mode 100644
index 000000000..d6d4af742
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <lib/psci/psci.h>
+#include <lib/spinlock.h>
+
+#include <mt_cpu_pm_cpc.h>
+#include <mt_mcdi.h>
+#include <plat_mtk_lpm.h>
+#include <plat_pm.h>
+
+DEFINE_SYSREG_RW_FUNCS(dbgprcr_el1);
+
+static int plat_mt_lp_cpu_rc;
+
+static int pwr_state_prompt(unsigned int cpu, const psci_power_state_t *state)
+{
+ return 0;
+}
+
+static int pwr_state_reflect(unsigned int cpu, const psci_power_state_t *state)
+{
+ mtk_cpc_core_on_hint_clr(cpu);
+
+ if (IS_SYSTEM_SUSPEND_STATE(state)) {
+ mtk_cpc_time_sync();
+ }
+
+ return 0;
+}
+
+static int pwr_cpu_pwron(unsigned int cpu, const psci_power_state_t *state)
+{
+ return 0;
+}
+
+static int pwr_cpu_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
+{
+ /* clear DBGPRCR.CORENPDRQ to allow CPU power down */
+ write_dbgprcr_el1(0ULL);
+
+ return 0;
+}
+
+static int pwr_cluster_pwron(unsigned int cpu, const psci_power_state_t *state)
+{
+ return 0;
+}
+
+static int pwr_cluster_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
+{
+ return 0;
+}
+
+static int pwr_mcusys_pwron(unsigned int cpu, const psci_power_state_t *state)
+{
+ if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
+ return -1;
+ }
+
+ mtk_cpc_mcusys_off_reflect();
+
+ return 0;
+}
+
+static int pwr_mcusys_pwron_finished(unsigned int cpu,
+ const psci_power_state_t *state)
+{
+ if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int pwr_mcusys_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
+{
+ if (!IS_MCUSYS_OFF_STATE(state)) {
+ goto mt_pwr_mcusysoff_break;
+ }
+
+ if (mcdi_try_init() != 0) { /* not ready to process mcusys-off */
+ goto mt_pwr_mcusysoff_break;
+ }
+
+ return 0;
+
+mt_pwr_mcusysoff_break:
+
+ plat_mt_lp_cpu_rc = -1;
+
+ return -1;
+}
+
+static const struct mt_lpm_tz plat_pm = {
+ .pwr_prompt = pwr_state_prompt,
+ .pwr_reflect = pwr_state_reflect,
+ .pwr_cpu_on = pwr_cpu_pwron,
+ .pwr_cpu_dwn = pwr_cpu_pwrdwn,
+ .pwr_cluster_on = pwr_cluster_pwron,
+ .pwr_cluster_dwn = pwr_cluster_pwrdwn,
+ .pwr_mcusys_dwn = pwr_mcusys_pwrdwn,
+ .pwr_mcusys_on = pwr_mcusys_pwron,
+ .pwr_mcusys_on_finished = pwr_mcusys_pwron_finished
+};
+
+const struct mt_lpm_tz *mt_plat_cpu_pm_init(void)
+{
+ mtk_cpc_init();
+
+ if (mcdi_try_init() == 0) {
+ INFO("MCDI init done.\n");
+ }
+
+ return &plat_pm;
+}
diff --git a/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.c b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.c
new file mode 100644
index 000000000..f8c51a199
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <drivers/delay_timer.h>
+
+#include <mt_cpu_pm_cpc.h>
+#include <mt_timer.h>
+
+struct mtk_cpc_dev {
+ int auto_off;
+ unsigned int auto_thres_tick;
+};
+
+static struct mtk_cpc_dev cpc;
+
+static int mtk_cpc_last_core_prot(uint32_t prot_req,
+ uint32_t resp_reg, uint32_t resp_ofs)
+{
+ uint32_t sta, retry;
+
+ retry = 0U;
+
+ while (retry++ < RETRY_CNT_MAX) {
+
+ mmio_write_32(CPC_MCUSYS_LAST_CORE_REQ, prot_req);
+
+ udelay(1U);
+
+ sta = (mmio_read_32(resp_reg) >> resp_ofs) & CPC_PROT_RESP_MASK;
+
+ if (sta == PROT_SUCCESS) {
+ return CPC_SUCCESS;
+ } else if (sta == PROT_GIVEUP) {
+ return CPC_ERR_FAIL;
+ }
+ }
+
+ return CPC_ERR_TIMEOUT;
+}
+
+int mtk_cpu_pm_mcusys_prot_aquire(void)
+{
+ return mtk_cpc_last_core_prot(
+ MCUSYS_PROT_SET,
+ CPC_MCUSYS_LAST_CORE_RESP,
+ MCUSYS_RESP_OFS);
+}
+
+void mtk_cpu_pm_mcusys_prot_release(void)
+{
+ mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, MCUSYS_PROT_CLR);
+}
+
+int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster)
+{
+ return mtk_cpc_last_core_prot(
+ CPUSYS_PROT_SET,
+ CPC_MCUSYS_MP_LAST_CORE_RESP,
+ CPUSYS_RESP_OFS);
+}
+
+void mtk_cpu_pm_cluster_prot_release(unsigned int cluster)
+{
+ mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, CPUSYS_PROT_CLR);
+}
+
+static void mtk_cpc_cluster_cnt_backup(void)
+{
+ uint32_t backup_cnt;
+ uint32_t curr_cnt;
+ uint32_t cnt_mask = GENMASK(14, 0);
+ uint32_t clr_mask = GENMASK(1, 0);
+
+ /* Single Cluster */
+ backup_cnt = mmio_read_32(CPC_CLUSTER_CNT_BACKUP);
+ curr_cnt = mmio_read_32(CPC_MCUSYS_CLUSTER_COUNTER);
+
+ /* Get off count if dormant count is 0 */
+ if ((curr_cnt & cnt_mask) == 0U) {
+ curr_cnt = (curr_cnt >> 16) & cnt_mask;
+ } else {
+ curr_cnt = curr_cnt & cnt_mask;
+ }
+
+ mmio_write_32(CPC_CLUSTER_CNT_BACKUP, backup_cnt + curr_cnt);
+ mmio_write_32(CPC_MCUSYS_CLUSTER_COUNTER_CLR, clr_mask);
+}
+
+static inline void mtk_cpc_mcusys_off_en(void)
+{
+ mmio_write_32(CPC_MCUSYS_PWR_CTRL, 1U);
+}
+
+static inline void mtk_cpc_mcusys_off_dis(void)
+{
+ mmio_write_32(CPC_MCUSYS_PWR_CTRL, 0U);
+}
+
+void mtk_cpc_mcusys_off_reflect(void)
+{
+ mtk_cpc_mcusys_off_dis();
+ mtk_cpu_pm_mcusys_prot_release();
+}
+
+int mtk_cpc_mcusys_off_prepare(void)
+{
+ if (mtk_cpu_pm_mcusys_prot_aquire() != CPC_SUCCESS) {
+ return CPC_ERR_FAIL;
+ }
+
+ mtk_cpc_cluster_cnt_backup();
+ mtk_cpc_mcusys_off_en();
+
+ return CPC_SUCCESS;
+}
+
+void mtk_cpc_core_on_hint_set(unsigned int cpu)
+{
+ mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_SET, BIT(cpu));
+}
+
+void mtk_cpc_core_on_hint_clr(unsigned int cpu)
+{
+ mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
+}
+
+static void mtk_cpc_dump_timestamp(void)
+{
+ uint32_t id;
+
+ for (id = 0U; id < CPC_TRACE_ID_NUM; id++) {
+ mmio_write_32(CPC_MCUSYS_TRACE_SEL, id);
+
+ memcpy((void *)(uintptr_t)CPC_TRACE_SRAM(id),
+ (const void *)(uintptr_t)CPC_MCUSYS_TRACE_DATA,
+ CPC_TRACE_SIZE);
+ }
+}
+
+void mtk_cpc_time_sync(void)
+{
+ uint64_t kt;
+ uint32_t systime_l, systime_h;
+
+ kt = sched_clock();
+ systime_l = mmio_read_32(CNTSYS_L_REG);
+ systime_h = mmio_read_32(CNTSYS_H_REG);
+
+ /* sync kernel timer to cpc */
+ mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE, (uint32_t)kt);
+ mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE, (uint32_t)(kt >> 32));
+ /* sync system timer to cpc */
+ mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE, systime_l);
+ mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE, systime_h);
+}
+
+static void mtk_cpc_config(uint32_t cfg, uint32_t data)
+{
+ uint32_t val;
+ uint32_t reg = 0U;
+
+ switch (cfg) {
+ case CPC_SMC_CONFIG_PROF:
+ reg = CPC_MCUSYS_CPC_DBG_SETTING;
+ val = mmio_read_32(reg);
+ val = (data != 0U) ? (val | CPC_PROF_EN) : (val & ~CPC_PROF_EN);
+ break;
+ case CPC_SMC_CONFIG_AUTO_OFF:
+ reg = CPC_MCUSYS_CPC_FLOW_CTRL_CFG;
+ val = mmio_read_32(reg);
+ if (data != 0U) {
+ val |= CPC_AUTO_OFF_EN;
+ cpc.auto_off = 1;
+ } else {
+ val &= ~CPC_AUTO_OFF_EN;
+ cpc.auto_off = 0;
+ }
+ break;
+ case CPC_SMC_CONFIG_AUTO_OFF_THRES:
+ reg = CPC_MCUSYS_CPC_OFF_THRES;
+ cpc.auto_thres_tick = us_to_ticks(data);
+ val = cpc.auto_thres_tick;
+ break;
+ case CPC_SMC_CONFIG_CNT_CLR:
+ reg = CPC_MCUSYS_CLUSTER_COUNTER_CLR;
+ val = GENMASK(1, 0); /* clr_mask */
+ break;
+ case CPC_SMC_CONFIG_TIME_SYNC:
+ mtk_cpc_time_sync();
+ break;
+ default:
+ break;
+ }
+
+ if (reg != 0U) {
+ mmio_write_32(reg, val);
+ }
+}
+
+static uint32_t mtk_cpc_read_config(uint32_t cfg)
+{
+ uint32_t res = 0U;
+
+ switch (cfg) {
+ case CPC_SMC_CONFIG_PROF:
+ res = (mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING) & CPC_PROF_EN) ?
+ 1U : 0U;
+ break;
+ case CPC_SMC_CONFIG_AUTO_OFF:
+ res = cpc.auto_off;
+ break;
+ case CPC_SMC_CONFIG_AUTO_OFF_THRES:
+ res = ticks_to_us(cpc.auto_thres_tick);
+ break;
+ case CPC_SMC_CONFIG_CNT_CLR:
+ break;
+ default:
+ break;
+ }
+
+ return res;
+}
+
+uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2)
+{
+ uint64_t res = 0ULL;
+
+ switch (act) {
+ case CPC_SMC_EVENT_DUMP_TRACE_DATA:
+ mtk_cpc_dump_timestamp();
+ break;
+ case CPC_SMC_EVENT_GIC_DPG_SET:
+ /* isolated_status = x2; */
+ break;
+ case CPC_SMC_EVENT_CPC_CONFIG:
+ mtk_cpc_config((uint32_t)arg1, (uint32_t)arg2);
+ break;
+ case CPC_SMC_EVENT_READ_CONFIG:
+ res = mtk_cpc_read_config((uint32_t)arg1);
+ break;
+ default:
+ break;
+ }
+
+ return res;
+}
+
+void mtk_cpc_init(void)
+{
+ mmio_write_32(CPC_MCUSYS_CPC_DBG_SETTING,
+ mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING)
+ | CPC_DBG_EN
+ | CPC_CALC_EN);
+
+ cpc.auto_off = 1;
+ cpc.auto_thres_tick = us_to_ticks(8000);
+
+ mmio_write_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG,
+ mmio_read_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG)
+ | CPC_OFF_PRE_EN
+ | (cpc.auto_off ? CPC_AUTO_OFF_EN : 0U));
+
+ mmio_write_32(CPC_MCUSYS_CPC_OFF_THRES, cpc.auto_thres_tick);
+}
diff --git a/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.h b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.h
new file mode 100644
index 000000000..19dd6a283
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_CPU_PM_CPC_H
+#define MT_CPU_PM_CPC_H
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <mcucfg.h>
+#include <platform_def.h>
+
+#define NEED_CPUSYS_PROT_WORKAROUND 1
+
+/* system sram registers */
+#define CPUIDLE_SRAM_REG(r) (uint32_t)(MTK_MCDI_SRAM_BASE + (r))
+
+/* db dump */
+#define CPC_TRACE_SIZE U(0x20)
+#define CPC_TRACE_ID_NUM U(10)
+#define CPC_TRACE_SRAM(id) (CPUIDLE_SRAM_REG(0x10) + (id) * CPC_TRACE_SIZE)
+
+/* buckup off count */
+#define CPC_CLUSTER_CNT_BACKUP CPUIDLE_SRAM_REG(0x1F0)
+#define CPC_MCUSYS_CNT CPUIDLE_SRAM_REG(0x1F4)
+
+/* CPC_MCUSYS_CPC_FLOW_CTRL_CFG(0xA814): debug setting */
+#define CPC_PWR_ON_SEQ_DIS BIT(1)
+#define CPC_PWR_ON_PRIORITY BIT(2)
+#define CPC_AUTO_OFF_EN BIT(5)
+#define CPC_DORMANT_WAIT_EN BIT(14)
+#define CPC_CTRL_EN BIT(16)
+#define CPC_OFF_PRE_EN BIT(29)
+
+/* CPC_MCUSYS_LAST_CORE_REQ(0xA818) : last core protection */
+#define CPUSYS_PROT_SET BIT(0)
+#define MCUSYS_PROT_SET BIT(8)
+#define CPUSYS_PROT_CLR BIT(8)
+#define MCUSYS_PROT_CLR BIT(9)
+
+#define CPC_PROT_RESP_MASK U(0x3)
+#define CPUSYS_RESP_OFS U(16)
+#define MCUSYS_RESP_OFS U(30)
+
+#define cpusys_resp(r) (((r) >> CPUSYS_RESP_OFS) & CPC_PROT_RESP_MASK)
+#define mcusys_resp(r) (((r) >> MCUSYS_RESP_OFS) & CPC_PROT_RESP_MASK)
+
+#define RETRY_CNT_MAX U(1000)
+
+#define PROT_RETRY U(0)
+#define PROT_SUCCESS U(1)
+#define PROT_GIVEUP U(2)
+
+/* CPC_MCUSYS_CPC_DBG_SETTING(0xAB00): debug setting */
+#define CPC_PROF_EN BIT(0)
+#define CPC_DBG_EN BIT(1)
+#define CPC_FREEZE BIT(2)
+#define CPC_CALC_EN BIT(3)
+
+enum {
+ CPC_SUCCESS = 0,
+
+ CPC_ERR_FAIL,
+ CPC_ERR_TIMEOUT,
+
+ NF_CPC_ERR
+};
+
+enum {
+ CPC_SMC_EVENT_DUMP_TRACE_DATA,
+ CPC_SMC_EVENT_GIC_DPG_SET,
+ CPC_SMC_EVENT_CPC_CONFIG,
+ CPC_SMC_EVENT_READ_CONFIG,
+
+ NF_CPC_SMC_EVENT
+};
+
+enum {
+ CPC_SMC_CONFIG_PROF,
+ CPC_SMC_CONFIG_AUTO_OFF,
+ CPC_SMC_CONFIG_AUTO_OFF_THRES,
+ CPC_SMC_CONFIG_CNT_CLR,
+ CPC_SMC_CONFIG_TIME_SYNC,
+
+ NF_CPC_SMC_CONFIG
+};
+
+#define us_to_ticks(us) ((us) * 13)
+#define ticks_to_us(tick) ((tick) / 13)
+
+int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster);
+void mtk_cpu_pm_cluster_prot_release(unsigned int cluster);
+
+void mtk_cpc_mcusys_off_reflect(void);
+int mtk_cpc_mcusys_off_prepare(void);
+
+void mtk_cpc_core_on_hint_set(unsigned int cpu);
+void mtk_cpc_core_on_hint_clr(unsigned int cpu);
+void mtk_cpc_time_sync(void);
+
+uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2);
+void mtk_cpc_init(void);
+
+#endif /* MT_CPU_PM_CPC_H */
diff --git a/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.c b/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.c
new file mode 100644
index 000000000..df741221d
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <cdefs.h>
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <mt_mcdi.h>
+
+/* Read/Write */
+#define APMCU_MCUPM_MBOX_AP_READY U(0)
+#define APMCU_MCUPM_MBOX_RESERVED_1 U(1)
+#define APMCU_MCUPM_MBOX_RESERVED_2 U(2)
+#define APMCU_MCUPM_MBOX_RESERVED_3 U(3)
+#define APMCU_MCUPM_MBOX_PWR_CTRL_EN U(4)
+#define APMCU_MCUPM_MBOX_L3_CACHE_MODE U(5)
+#define APMCU_MCUPM_MBOX_BUCK_MODE U(6)
+#define APMCU_MCUPM_MBOX_ARMPLL_MODE U(7)
+/* Read only */
+#define APMCU_MCUPM_MBOX_TASK_STA U(8)
+#define APMCU_MCUPM_MBOX_RESERVED_9 U(9)
+#define APMCU_MCUPM_MBOX_RESERVED_10 U(10)
+#define APMCU_MCUPM_MBOX_RESERVED_11 U(11)
+
+/* CPC mode - Read/Write */
+#define APMCU_MCUPM_MBOX_WAKEUP_CPU U(12)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_PWR_CTRL_EN */
+#define MCUPM_MCUSYS_CTRL BIT(0)
+#define MCUPM_BUCK_CTRL BIT(1)
+#define MCUPM_ARMPLL_CTRL BIT(2)
+#define MCUPM_CM_CTRL BIT(3)
+#define MCUPM_PWR_CTRL_MASK GENMASK(3, 0)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_BUCK_MODE */
+#define MCUPM_BUCK_NORMAL_MODE U(0) /* default */
+#define MCUPM_BUCK_LP_MODE U(1)
+#define MCUPM_BUCK_OFF_MODE U(2)
+#define NF_MCUPM_BUCK_MODE U(3)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_ARMPLL_MODE */
+#define MCUPM_ARMPLL_ON U(0) /* default */
+#define MCUPM_ARMPLL_GATING U(1)
+#define MCUPM_ARMPLL_OFF U(2)
+#define NF_MCUPM_ARMPLL_MODE U(3)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_TASK_STA */
+#define MCUPM_TASK_UNINIT U(0)
+#define MCUPM_TASK_INIT U(1)
+#define MCUPM_TASK_INIT_FINISH U(2)
+#define MCUPM_TASK_WAIT U(3)
+#define MCUPM_TASK_RUN U(4)
+#define MCUPM_TASK_PAUSE U(5)
+
+#define SSPM_MBOX_3_BASE U(0x0c55fce0)
+
+#define MCDI_NOT_INIT 0
+#define MCDI_INIT_1 1
+#define MCDI_INIT_2 2
+#define MCDI_INIT_DONE 3
+
+static int mcdi_init_status __section("tzfw_coherent_mem");
+
+static inline uint32_t mcdi_mbox_read(uint32_t id)
+{
+ return mmio_read_32(SSPM_MBOX_3_BASE + (id << 2));
+}
+
+static inline void mcdi_mbox_write(uint32_t id, uint32_t val)
+{
+ mmio_write_32(SSPM_MBOX_3_BASE + (id << 2), val);
+}
+
+static void mtk_mcupm_pwr_ctrl_setting(uint32_t dev)
+{
+ mcdi_mbox_write(APMCU_MCUPM_MBOX_PWR_CTRL_EN, dev);
+}
+
+static void mtk_set_mcupm_pll_mode(uint32_t mode)
+{
+ if (mode < NF_MCUPM_ARMPLL_MODE) {
+ mcdi_mbox_write(APMCU_MCUPM_MBOX_ARMPLL_MODE, mode);
+ }
+}
+
+static void mtk_set_mcupm_buck_mode(uint32_t mode)
+{
+ if (mode < NF_MCUPM_BUCK_MODE) {
+ mcdi_mbox_write(APMCU_MCUPM_MBOX_BUCK_MODE, mode);
+ }
+}
+
+static int mtk_mcupm_is_ready(void)
+{
+ unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA);
+
+ return (sta == MCUPM_TASK_WAIT) || (sta == MCUPM_TASK_INIT_FINISH);
+}
+
+static int mcdi_init_1(void)
+{
+ unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA);
+
+ if (sta != MCUPM_TASK_INIT) {
+ return -1;
+ }
+
+ mtk_set_mcupm_pll_mode(MCUPM_ARMPLL_OFF);
+ mtk_set_mcupm_buck_mode(MCUPM_BUCK_OFF_MODE);
+
+ mtk_mcupm_pwr_ctrl_setting(
+ MCUPM_MCUSYS_CTRL |
+ MCUPM_BUCK_CTRL |
+ MCUPM_ARMPLL_CTRL);
+
+ mcdi_mbox_write(APMCU_MCUPM_MBOX_AP_READY, 1);
+
+ return 0;
+}
+
+static int mcdi_init_2(void)
+{
+ return mtk_mcupm_is_ready() ? 0 : -1;
+}
+
+int mcdi_try_init(void)
+{
+ if (mcdi_init_status == MCDI_INIT_DONE) {
+ return 0;
+ }
+
+ if (mcdi_init_status == MCDI_NOT_INIT) {
+ mcdi_init_status = MCDI_INIT_1;
+ }
+
+ if (mcdi_init_status == MCDI_INIT_1 && mcdi_init_1() == 0) {
+ mcdi_init_status = MCDI_INIT_2;
+ }
+
+ if (mcdi_init_status == MCDI_INIT_2 && mcdi_init_2() == 0) {
+ mcdi_init_status = MCDI_INIT_DONE;
+ }
+
+ return (mcdi_init_status == MCDI_INIT_DONE) ? 0 : mcdi_init_status;
+}
diff --git a/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.h b/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.h
new file mode 100644
index 000000000..f3545aabf
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_MCDI_H
+#define MT_MCDI_H
+
+int mcdi_try_init(void);
+
+#endif /* MT_MCDI_H */
diff --git a/plat/mediatek/mt8192/drivers/pmic/pmic.c b/plat/mediatek/mt8192/drivers/pmic/pmic.c
new file mode 100644
index 000000000..cca441397
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/pmic/pmic.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <pmic.h>
+#include <pmic_wrap_init.h>
+
+void pmic_power_off(void)
+{
+ pwrap_write(PMIC_PWRHOLD, 0x0);
+}
diff --git a/plat/mediatek/mt8192/drivers/pmic/pmic.h b/plat/mediatek/mt8192/drivers/pmic/pmic.h
new file mode 100644
index 000000000..aac22afa3
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/pmic/pmic.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMIC_H
+#define PMIC_H
+
+#define PMIC_PWRHOLD 0xa08
+
+/* external API */
+void pmic_power_off(void);
+
+#endif /* PMIC_H */
diff --git a/plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h b/plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h
new file mode 100644
index 000000000..ae892ed5a
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMIC_WRAP_INIT_H
+#define PMIC_WRAP_INIT_H
+
+#include <stdint.h>
+
+#include "platform_def.h"
+
+/* external API */
+int32_t pwrap_read(uint32_t adr, uint32_t *rdata);
+int32_t pwrap_write(uint32_t adr, uint32_t wdata);
+
+static struct mt8192_pmic_wrap_regs *const mtk_pwrap = (void *)PMIC_WRAP_BASE;
+
+/* PMIC_WRAP registers */
+struct mt8192_pmic_wrap_regs {
+ uint32_t init_done;
+ uint32_t reserved[799];
+ uint32_t wacs2_cmd;
+ uint32_t wacs2_wdata;
+ uint32_t reserved1[3];
+ uint32_t wacs2_rdata;
+ uint32_t reserved2[3];
+ uint32_t wacs2_vldclr;
+ uint32_t wacs2_sta;
+};
+
+#define GET_WACS_FSM(x) ((x >> 1) & 0x7)
+
+/* macro for SWINF_FSM */
+#define SWINF_FSM_IDLE (0x00)
+#define SWINF_FSM_REQ (0x02)
+#define SWINF_FSM_WFDLE (0x04)
+#define SWINF_FSM_WFVLDCLR (0x06)
+#define SWINF_INIT_DONE (0x01)
+
+/* timeout setting */
+#define PWRAP_READ_US 1000
+#define PWRAP_WAIT_IDLE_US 1000
+
+/* error information flag */
+enum pwrap_errno {
+ E_PWR_INVALID_ARG = 1,
+ E_PWR_INVALID_RW = 2,
+ E_PWR_INVALID_ADDR = 3,
+ E_PWR_INVALID_WDAT = 4,
+ E_PWR_INVALID_OP_MANUAL = 5,
+ E_PWR_NOT_IDLE_STATE = 6,
+ E_PWR_NOT_INIT_DONE = 7,
+ E_PWR_NOT_INIT_DONE_READ = 8,
+ E_PWR_WAIT_IDLE_TIMEOUT = 9,
+ E_PWR_WAIT_IDLE_TIMEOUT_READ = 10,
+ E_PWR_INIT_SIDLY_FAIL = 11,
+ E_PWR_RESET_TIMEOUT = 12,
+ E_PWR_TIMEOUT = 13,
+ E_PWR_INIT_RESET_SPI = 20,
+ E_PWR_INIT_SIDLY = 21,
+ E_PWR_INIT_REG_CLOCK = 22,
+ E_PWR_INIT_ENABLE_PMIC = 23,
+ E_PWR_INIT_DIO = 24,
+ E_PWR_INIT_CIPHER = 25,
+ E_PWR_INIT_WRITE_TEST = 26,
+ E_PWR_INIT_ENABLE_CRC = 27,
+ E_PWR_INIT_ENABLE_DEWRAP = 28,
+ E_PWR_INIT_ENABLE_EVENT = 29,
+ E_PWR_READ_TEST_FAIL = 30,
+ E_PWR_WRITE_TEST_FAIL = 31,
+ E_PWR_SWITCH_DIO = 32
+};
+
+#endif /* PMIC_WRAP_INIT_H */
diff --git a/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_common.h b/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_common.h
new file mode 100644
index 000000000..92c71bcdd
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_common.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_PTP3_H
+#define MTK_PTP3_H
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+
+/************************************************
+ * BIT Operation and REG r/w
+ ************************************************/
+#define ptp3_read(addr) mmio_read_32((uintptr_t)addr)
+#define ptp3_write(addr, val) mmio_write_32((uintptr_t)addr, val)
+
+/************************************************
+ * CPU info
+ ************************************************/
+#define NR_PTP3_CFG1_CPU U(8)
+#define PTP3_CFG1_CPU_START_ID U(0)
+#define PTP3_CFG1_MASK 0x00100000
+
+#define NR_PTP3_CFG2_CPU U(4)
+#define PTP3_CFG2_CPU_START_ID U(4)
+
+#define NR_PTP3_CFG3_CPU U(4)
+#define PTP3_CFG3_CPU_START_ID U(4)
+
+/************************************************
+ * config enum
+ ************************************************/
+enum PTP3_CFG {
+ PTP3_CFG_ADDR,
+ PTP3_CFG_VALUE,
+ NR_PTP3_CFG,
+};
+
+/************************************
+ * prototype
+ ************************************/
+/* init trigger for ptp3 feature */
+extern void ptp3_init(unsigned int core);
+extern void ptp3_deinit(unsigned int core);
+
+#endif /* MTK_PTP3_H */
diff --git a/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c b/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c
new file mode 100644
index 000000000..f1d849386
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved. \
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "mtk_ptp3_common.h"
+
+/************************************************
+ * Central control: turn on sysPi protection
+ ************************************************/
+static unsigned int ptp3_cfg1[NR_PTP3_CFG1_CPU][NR_PTP3_CFG] = {
+ {0x0C530610, 0x110842},
+ {0x0C530E10, 0x110842},
+ {0x0C531610, 0x110842},
+ {0x0C531E10, 0x110842},
+ {0x0C532610, 0x110842},
+ {0x0C532E10, 0x110842},
+ {0x0C533610, 0x110842},
+ {0x0C533E10, 0x110842}
+};
+static unsigned int ptp3_cfg2[NR_PTP3_CFG2_CPU][NR_PTP3_CFG] = {
+ {0x0C53B830, 0x68000},
+ {0x0C53BA30, 0x68000},
+ {0x0C53BC30, 0x68000},
+ {0x0C53BE30, 0x68000}
+};
+static unsigned int ptp3_cfg3[NR_PTP3_CFG3_CPU][NR_PTP3_CFG] = {
+ {0x0C532480, 0x7C607C6},
+ {0x0C532C80, 0x7C607C6},
+ {0x0C533480, 0x7C607C6},
+ {0x0C533C80, 0x7C607C6}
+};
+
+/************************************************
+ * API
+ ************************************************/
+void ptp3_init(unsigned int core)
+{
+ unsigned int _core;
+
+ /* Apply ptp3_cfg1 for core 0 to 7 */
+ if (core < NR_PTP3_CFG1_CPU) {
+ /* update ptp3_cfg1 */
+ ptp3_write(
+ ptp3_cfg1[core][PTP3_CFG_ADDR],
+ ptp3_cfg1[core][PTP3_CFG_VALUE]);
+ }
+
+ /* Apply ptp3_cfg2 for core 4 to 7 */
+ if (core >= PTP3_CFG2_CPU_START_ID) {
+ _core = core - PTP3_CFG2_CPU_START_ID;
+
+ if (_core < NR_PTP3_CFG2_CPU) {
+ /* update ptp3_cfg2 */
+ ptp3_write(
+ ptp3_cfg2[_core][PTP3_CFG_ADDR],
+ ptp3_cfg2[_core][PTP3_CFG_VALUE]);
+ }
+ }
+
+ /* Apply ptp3_cfg3 for core 4 to 7 */
+ if (core >= PTP3_CFG3_CPU_START_ID) {
+ _core = core - PTP3_CFG3_CPU_START_ID;
+
+ if (_core < NR_PTP3_CFG3_CPU) {
+ /* update ptp3_cfg3 */
+ ptp3_write(
+ ptp3_cfg3[_core][PTP3_CFG_ADDR],
+ ptp3_cfg3[_core][PTP3_CFG_VALUE]);
+ }
+ }
+}
+
+void ptp3_deinit(unsigned int core)
+{
+ if (core < NR_PTP3_CFG1_CPU) {
+ /* update ptp3_cfg1 */
+ ptp3_write(
+ ptp3_cfg1[core][PTP3_CFG_ADDR],
+ ptp3_cfg1[core][PTP3_CFG_VALUE] &
+ ~PTP3_CFG1_MASK);
+ }
+}
diff --git a/plat/mediatek/mt8192/drivers/rtc/rtc.c b/plat/mediatek/mt8192/drivers/rtc/rtc.c
new file mode 100644
index 000000000..124bc8fbe
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/rtc/rtc.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <rtc.h>
+
+
+static void RTC_Config_Interface(uint32_t addr, uint16_t data,
+ uint16_t mask, uint16_t shift)
+{
+ uint16_t pmic_reg;
+
+ pmic_reg = RTC_Read(addr);
+
+ pmic_reg &= ~(mask << shift);
+ pmic_reg |= (data << shift);
+
+ RTC_Write(addr, pmic_reg);
+}
+
+static int32_t rtc_disable_2sec_reboot(void)
+{
+ uint16_t reboot;
+
+ reboot = (RTC_Read(RTC_AL_SEC) & ~RTC_BBPU_2SEC_EN) &
+ ~RTC_BBPU_AUTO_PDN_SEL;
+ RTC_Write(RTC_AL_SEC, reboot);
+
+ return RTC_Write_Trigger();
+}
+
+static int32_t rtc_enable_k_eosc(void)
+{
+ uint16_t alm_dow, alm_sec;
+ int16_t ret;
+
+ /* Turning on eosc cali mode clock */
+ RTC_Config_Interface(PMIC_RG_SCK_TOP_CKPDN_CON0_CLR, 1,
+ PMIC_RG_RTC_EOSC32_CK_PDN_MASK,
+ PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT);
+
+ alm_sec = RTC_Read(RTC_AL_SEC) & (~RTC_LPD_OPT_MASK);
+ RTC_Write(RTC_AL_SEC, alm_sec);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ RTC_Write(RTC_CON, RTC_LPD_EN);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ RTC_Write(RTC_CON, RTC_LPD_RST);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ RTC_Write(RTC_CON, RTC_LPD_EN);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ RTC_Write(RTC_POWERKEY1, RTC_POWERKEY1_KEY);
+ RTC_Write(RTC_POWERKEY2, RTC_POWERKEY2_KEY);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ /* set RTC EOSC calibration period = 8sec */
+ alm_dow = (RTC_Read(RTC_AL_DOW) & (~RTC_RG_EOSC_CALI_TD_MASK)) |
+ RTC_RG_EOSC_CALI_TD_8SEC;
+ RTC_Write(RTC_AL_DOW, alm_dow);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ RTC_Write(RTC_BBPU,
+ RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ /* Enable K EOSC mode :use solution1 of eosc cali to fix mt6359p 32K*/
+ RTC_Write(RTC_AL_YEA, (((RTC_Read(RTC_AL_YEA) | RTC_K_EOSC_RSV_0)
+ & (~RTC_K_EOSC_RSV_1)) | (RTC_K_EOSC_RSV_2)));
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ INFO("[RTC] RTC_enable_k_eosc\n");
+
+ return 1;
+}
+
+void rtc_power_off_sequence(void)
+{
+ uint16_t bbpu;
+ int16_t ret;
+
+ ret = rtc_disable_2sec_reboot();
+ if (ret == 0) {
+ return;
+ }
+
+ ret = rtc_enable_k_eosc();
+ if (ret == 0) {
+ return;
+ }
+
+ bbpu = RTC_BBPU_KEY | RTC_BBPU_PWREN;
+
+ if (Writeif_unlock() != 0) {
+ RTC_Write(RTC_BBPU,
+ bbpu | RTC_BBPU_RESET_ALARM | RTC_BBPU_RESET_SPAR);
+ RTC_Write(RTC_AL_MASK, RTC_AL_MASK_DOW);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return;
+ }
+ mdelay(1);
+
+ bbpu = RTC_Read(RTC_BBPU);
+
+ if (((bbpu & RTC_BBPU_RESET_ALARM) > 0) ||
+ ((bbpu & RTC_BBPU_RESET_SPAR) > 0)) {
+ INFO("[RTC] timeout\n");
+ }
+
+ bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD;
+ RTC_Write(RTC_BBPU, bbpu);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return;
+ }
+ }
+}
diff --git a/plat/mediatek/mt8192/drivers/rtc/rtc.h b/plat/mediatek/mt8192/drivers/rtc/rtc.h
new file mode 100644
index 000000000..419bfe42c
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/rtc/rtc.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RTC_H
+#define RTC_H
+
+/* RTC registers */
+enum {
+ RTC_BBPU = 0x0588,
+ RTC_IRQ_STA = 0x058A,
+ RTC_IRQ_EN = 0x058C,
+ RTC_CII_EN = 0x058E
+};
+
+enum {
+ RTC_AL_SEC = 0x05A0,
+ RTC_AL_MIN = 0x05A2,
+ RTC_AL_HOU = 0x05A4,
+ RTC_AL_DOM = 0x05A6,
+ RTC_AL_DOW = 0x05A8,
+ RTC_AL_MTH = 0x05AA,
+ RTC_AL_YEA = 0x05AC,
+ RTC_AL_MASK = 0x0590
+};
+
+enum {
+ RTC_OSC32CON = 0x05AE,
+ RTC_CON = 0x05C4,
+ RTC_WRTGR = 0x05C2
+};
+
+enum {
+ RTC_POWERKEY1 = 0x05B0,
+ RTC_POWERKEY2 = 0x05B2
+};
+
+enum {
+ RTC_POWERKEY1_KEY = 0xA357,
+ RTC_POWERKEY2_KEY = 0x67D2
+};
+
+enum {
+ RTC_PDN1 = 0x05B4,
+ RTC_PDN2 = 0x05B6,
+ RTC_SPAR0 = 0x05B8,
+ RTC_SPAR1 = 0x05BA,
+ RTC_PROT = 0x05BC,
+ RTC_DIFF = 0x05BE,
+ RTC_CALI = 0x05C0
+};
+
+enum {
+ RTC_OSC32CON_UNLOCK1 = 0x1A57,
+ RTC_OSC32CON_UNLOCK2 = 0x2B68
+};
+
+enum {
+ RTC_LPD_EN = 0x0406,
+ RTC_LPD_RST = 0x040E
+};
+
+enum {
+ RTC_LPD_OPT_XOSC_AND_EOSC_LPD = 0U << 13,
+ RTC_LPD_OPT_EOSC_LPD = 1U << 13,
+ RTC_LPD_OPT_XOSC_LPD = 2U << 13,
+ RTC_LPD_OPT_F32K_CK_ALIVE = 3U << 13,
+};
+
+#define RTC_LPD_OPT_MASK (3U << 13)
+
+enum {
+ RTC_PROT_UNLOCK1 = 0x586A,
+ RTC_PROT_UNLOCK2 = 0x9136
+};
+
+enum {
+ RTC_BBPU_PWREN = 1U << 0,
+ RTC_BBPU_SPAR_SW = 1U << 1,
+ RTC_BBPU_RESET_SPAR = 1U << 2,
+ RTC_BBPU_RESET_ALARM = 1U << 3,
+ RTC_BBPU_CLRPKY = 1U << 4,
+ RTC_BBPU_RELOAD = 1U << 5,
+ RTC_BBPU_CBUSY = 1U << 6
+};
+
+enum {
+ RTC_AL_MASK_SEC = 1U << 0,
+ RTC_AL_MASK_MIN = 1U << 1,
+ RTC_AL_MASK_HOU = 1U << 2,
+ RTC_AL_MASK_DOM = 1U << 3,
+ RTC_AL_MASK_DOW = 1U << 4,
+ RTC_AL_MASK_MTH = 1U << 5,
+ RTC_AL_MASK_YEA = 1U << 6
+};
+
+enum {
+ RTC_BBPU_AUTO_PDN_SEL = 1U << 6,
+ RTC_BBPU_2SEC_CK_SEL = 1U << 7,
+ RTC_BBPU_2SEC_EN = 1U << 8,
+ RTC_BBPU_2SEC_MODE = 0x3 << 9,
+ RTC_BBPU_2SEC_STAT_CLEAR = 1U << 11,
+ RTC_BBPU_2SEC_STAT_STA = 1U << 12
+};
+
+enum {
+ RTC_BBPU_KEY = 0x43 << 8
+};
+
+enum {
+ RTC_EMBCK_SRC_SEL = 1 << 8,
+ RTC_EMBCK_SEL_MODE = 3 << 6,
+ RTC_XOSC32_ENB = 1 << 5,
+ RTC_REG_XOSC32_ENB = 1 << 15
+};
+
+enum {
+ RTC_K_EOSC_RSV_0 = 1 << 8,
+ RTC_K_EOSC_RSV_1 = 1 << 9,
+ RTC_K_EOSC_RSV_2 = 1 << 10
+};
+
+enum {
+ RTC_RG_EOSC_CALI_TD_1SEC = 3 << 5,
+ RTC_RG_EOSC_CALI_TD_2SEC = 4 << 5,
+ RTC_RG_EOSC_CALI_TD_4SEC = 5 << 5,
+ RTC_RG_EOSC_CALI_TD_8SEC = 6 << 5,
+ RTC_RG_EOSC_CALI_TD_16SEC = 7 << 5,
+ RTC_RG_EOSC_CALI_TD_MASK = 7 << 5
+};
+
+/* PMIC TOP Register Definition */
+enum {
+ PMIC_RG_TOP_CON = 0x0020,
+ PMIC_RG_TOP_CKPDN_CON1 = 0x0112,
+ PMIC_RG_TOP_CKPDN_CON1_SET = 0x0114,
+ PMIC_RG_TOP_CKPDN_CON1_CLR = 0x0116,
+ PMIC_RG_TOP_CKSEL_CON0 = 0x0118,
+ PMIC_RG_TOP_CKSEL_CON0_SET = 0x011A,
+ PMIC_RG_TOP_CKSEL_CON0_CLR = 0x011C
+};
+
+/* PMIC SCK Register Definition */
+enum {
+ PMIC_RG_SCK_TOP_CKPDN_CON0 = 0x0514,
+ PMIC_RG_SCK_TOP_CKPDN_CON0_SET = 0x0516,
+ PMIC_RG_SCK_TOP_CKPDN_CON0_CLR = 0x0518,
+ PMIC_RG_EOSC_CALI_CON0 = 0x53A
+};
+
+enum {
+ PMIC_EOSC_CALI_START_ADDR = 0x53A
+};
+
+enum {
+ PMIC_EOSC_CALI_START_MASK = 0x1,
+ PMIC_EOSC_CALI_START_SHIFT = 0
+};
+
+/* PMIC DCXO Register Definition */
+enum {
+ PMIC_RG_DCXO_CW00 = 0x0788,
+ PMIC_RG_DCXO_CW02 = 0x0790,
+ PMIC_RG_DCXO_CW08 = 0x079C,
+ PMIC_RG_DCXO_CW09 = 0x079E,
+ PMIC_RG_DCXO_CW09_CLR = 0x07A2,
+ PMIC_RG_DCXO_CW10 = 0x07A4,
+ PMIC_RG_DCXO_CW12 = 0x07A8,
+ PMIC_RG_DCXO_CW13 = 0x07AA,
+ PMIC_RG_DCXO_CW15 = 0x07AE,
+ PMIC_RG_DCXO_CW19 = 0x07B6,
+};
+
+enum {
+ PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK = 0x1,
+ PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT = 1,
+ PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK = 0x1,
+ PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT = 3,
+ PMIC_RG_RTC_EOSC32_CK_PDN_MASK = 0x1,
+ PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT = 2,
+ PMIC_RG_EOSC_CALI_TD_MASK = 0x7,
+ PMIC_RG_EOSC_CALI_TD_SHIFT = 5,
+ PMIC_RG_XO_EN32K_MAN_MASK = 0x1,
+ PMIC_RG_XO_EN32K_MAN_SHIFT = 0
+};
+
+/* external API */
+uint16_t RTC_Read(uint32_t addr);
+void RTC_Write(uint32_t addr, uint16_t data);
+int32_t rtc_busy_wait(void);
+int32_t RTC_Write_Trigger(void);
+int32_t Writeif_unlock(void);
+void rtc_power_off_sequence(void);
+
+#endif /* RTC_H */
diff --git a/plat/mediatek/mt8192/drivers/spmc/mtspmc.c b/plat/mediatek/mt8192/drivers/spmc/mtspmc.c
new file mode 100644
index 000000000..7ccebd6ab
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spmc/mtspmc.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <mcucfg.h>
+#include <mtspmc.h>
+#include <mtspmc_private.h>
+
+
+void mcucfg_disable_gic_wakeup(uint32_t cluster, uint32_t cpu)
+{
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
+}
+
+void mcucfg_enable_gic_wakeup(uint32_t cluster, uint32_t cpu)
+{
+ mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
+}
+
+void mcucfg_set_bootaddr(uint32_t cluster, uint32_t cpu, uintptr_t bootaddr)
+{
+ assert(cluster == 0U);
+
+ mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr);
+}
+
+uintptr_t mcucfg_get_bootaddr(uint32_t cluster, uint32_t cpu)
+{
+ assert(cluster == 0U);
+
+ return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR));
+}
+
+void mcucfg_init_archstate(uint32_t cluster, uint32_t cpu, bool arm64)
+{
+ uint32_t reg;
+
+ assert(cluster == 0U);
+
+ reg = per_cluster(cluster, MCUCFG_INITARCH);
+
+ if (arm64) {
+ mmio_setbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
+ } else {
+ mmio_clrbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
+ }
+}
+
+/**
+ * Return subsystem's power state.
+ *
+ * @mask: mask to SPM_CPU_PWR_STATUS to query the power state
+ * of one subsystem.
+ * RETURNS:
+ * 0 (the subsys was powered off)
+ * 1 (the subsys was powered on)
+ */
+bool spm_get_powerstate(uint32_t mask)
+{
+ return (mmio_read_32(SPM_CPU_PWR_STATUS) & mask) != 0U;
+}
+
+bool spm_get_cluster_powerstate(uint32_t cluster)
+{
+ assert(cluster == 0U);
+
+ return spm_get_powerstate(MP0_CPUTOP);
+}
+
+bool spm_get_cpu_powerstate(uint32_t cluster, uint32_t cpu)
+{
+ uint32_t mask = BIT(cpu);
+
+ assert(cluster == 0U);
+
+ return spm_get_powerstate(mask);
+}
+
+int spmc_init(void)
+{
+ INFO("SPM: enable CPC mode\n");
+
+ mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN);
+
+ mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 4, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 5, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 6, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 7, SPM_CPU_PWR), PWR_RST_B);
+
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(1));
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(2));
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(3));
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(4));
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(5));
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(6));
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(7));
+
+ mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG);
+ mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG);
+ mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG);
+
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE);
+
+ return 0;
+}
+
+/**
+ * Power on a core with specified cluster and core index
+ *
+ * @cluster: the cluster ID of the CPU which to be powered on
+ * @cpu: the CPU ID of the CPU which to be powered on
+ */
+void spm_poweron_cpu(uint32_t cluster, uint32_t cpu)
+{
+ /* set to 0 after BIG VPROC bulk on & before B-core power on seq. */
+ if (cpu >= 4U) {
+ mmio_write_32(DREQ20_BIG_VPROC_ISO, 0U);
+ }
+
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN);
+ mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
+
+ while (!spm_get_cpu_powerstate(cluster, cpu)) {
+ }
+
+ mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN);
+
+ /* Enable Big CPU Last PC */
+ if (cpu >= 4U) {
+ mmio_clrbits_32(LAST_PC_REG(cpu), BIT(3));
+ }
+}
+
+/**
+ * Power off a core with specified cluster and core index
+ *
+ * @cluster: the cluster ID of the CPU which to be powered off
+ * @cpu: the CPU ID of the CPU which to be powered off
+ */
+void spm_poweroff_cpu(uint32_t cluster, uint32_t cpu)
+{
+ /* Set mp0_spmc_pwr_on_cpuX = 0 */
+ mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
+}
+
+/**
+ * Power off a cluster with specified index
+ *
+ * @cluster: the cluster index which to be powered off
+ */
+void spm_poweroff_cluster(uint32_t cluster)
+{
+ /* No need to power on/off cluster on single cluster platform */
+ assert(false);
+}
+
+/**
+ * Power on a cluster with specified index
+ *
+ * @cluster: the cluster index which to be powered on
+ */
+void spm_poweron_cluster(uint32_t cluster)
+{
+ /* No need to power on/off cluster on single cluster platform */
+ assert(false);
+}
diff --git a/plat/mediatek/mt8192/drivers/spmc/mtspmc.h b/plat/mediatek/mt8192/drivers/spmc/mtspmc.h
new file mode 100644
index 000000000..7ed2e6220
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spmc/mtspmc.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTSPMC_H
+#define MTSPMC_H
+
+#include <stdint.h>
+
+int spmc_init(void);
+
+void spm_poweron_cpu(uint32_t cluster, uint32_t cpu);
+void spm_poweroff_cpu(uint32_t cluster, uint32_t cpu);
+
+void spm_poweroff_cluster(uint32_t cluster);
+void spm_poweron_cluster(uint32_t cluster);
+
+bool spm_get_cpu_powerstate(uint32_t cluster, uint32_t cpu);
+bool spm_get_cluster_powerstate(uint32_t cluster);
+bool spm_get_powerstate(uint32_t mask);
+
+void mcucfg_init_archstate(uint32_t cluster, uint32_t cpu, bool arm64);
+void mcucfg_set_bootaddr(uint32_t cluster, uint32_t cpu, uintptr_t bootaddr);
+uintptr_t mcucfg_get_bootaddr(uint32_t cluster, uint32_t cpu);
+
+void mcucfg_disable_gic_wakeup(uint32_t cluster, uint32_t cpu);
+void mcucfg_enable_gic_wakeup(uint32_t cluster, uint32_t cpu);
+
+#endif /* MTSPMC_H */
diff --git a/plat/mediatek/mt8192/drivers/spmc/mtspmc_private.h b/plat/mediatek/mt8192/drivers/spmc/mtspmc_private.h
new file mode 100644
index 000000000..ad782955d
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spmc/mtspmc_private.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTSPMC_PRIVATE_H
+#define MTSPMC_PRIVATE_H
+
+#include <lib/utils_def.h>
+#include <platform_def.h>
+
+unsigned long read_cpuectlr(void);
+void write_cpuectlr(unsigned long cpuectlr);
+
+unsigned long read_cpupwrctlr_el1(void);
+void write_cpupwrctlr_el1(unsigned long cpuectlr);
+
+/*
+ * per_cpu/cluster helper
+ */
+struct per_cpu_reg {
+ unsigned int cluster_addr;
+ unsigned int cpu_stride;
+};
+
+#define per_cpu(cluster, cpu, reg) \
+ (reg[cluster].cluster_addr + (cpu << reg[cluster].cpu_stride))
+
+#define per_cluster(cluster, reg) (reg[cluster].cluster_addr)
+
+#define SPM_REG(ofs) (uint32_t)(SPM_BASE + (ofs))
+#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs))
+#define INFRACFG_AO_REG(ofs) (uint32_t)(INFRACFG_AO_BASE + (ofs))
+
+/* === SPMC related registers */
+#define SPM_POWERON_CONFIG_EN SPM_REG(0x000)
+/* bit-fields of SPM_POWERON_CONFIG_EN */
+#define PROJECT_CODE (U(0xb16) << 16)
+#define BCLK_CG_EN BIT(0)
+
+#define SPM_PWR_STATUS SPM_REG(0x16c)
+#define SPM_PWR_STATUS_2ND SPM_REG(0x170)
+#define SPM_CPU_PWR_STATUS SPM_REG(0x174)
+
+/* bit-fields of SPM_PWR_STATUS */
+#define MD BIT(0)
+#define CONN BIT(1)
+#define DDRPHY BIT(2)
+#define DISP BIT(3)
+#define MFG BIT(4)
+#define ISP BIT(5)
+#define INFRA BIT(6)
+#define VDEC BIT(7)
+#define MP0_CPUTOP BIT(8)
+#define MP0_CPU0 BIT(9)
+#define MP0_CPU1 BIT(10)
+#define MP0_CPU2 BIT(11)
+#define MP0_CPU3 BIT(12)
+#define MCUSYS BIT(14)
+#define MP0_CPU4 BIT(15)
+#define MP0_CPU5 BIT(16)
+#define MP0_CPU6 BIT(17)
+#define MP0_CPU7 BIT(18)
+#define VEN BIT(21)
+
+/* === SPMC related registers */
+#define SPM_MCUSYS_PWR_CON MCUCFG_REG(0xd200)
+#define SPM_MP0_CPUTOP_PWR_CON MCUCFG_REG(0xd204)
+#define SPM_MP0_CPU0_PWR_CON MCUCFG_REG(0xd208)
+#define SPM_MP0_CPU1_PWR_CON MCUCFG_REG(0xd20c)
+#define SPM_MP0_CPU2_PWR_CON MCUCFG_REG(0xd210)
+#define SPM_MP0_CPU3_PWR_CON MCUCFG_REG(0xd214)
+#define SPM_MP0_CPU4_PWR_CON MCUCFG_REG(0xd218)
+#define SPM_MP0_CPU5_PWR_CON MCUCFG_REG(0xd21c)
+#define SPM_MP0_CPU6_PWR_CON MCUCFG_REG(0xd220)
+#define SPM_MP0_CPU7_PWR_CON MCUCFG_REG(0xd224)
+
+/* bit fields of SPM_*_PWR_CON */
+#define PWR_ON_ACK BIT(31)
+#define VPROC_EXT_OFF BIT(7)
+#define DORMANT_EN BIT(6)
+#define RESETPWRON_CONFIG BIT(5)
+#define PWR_CLK_DIS BIT(4)
+#define PWR_ON BIT(2)
+#define PWR_RST_B BIT(0)
+
+/**** per_cpu registers for SPM_MP0_CPU?_PWR_CON */
+static const struct per_cpu_reg SPM_CPU_PWR[] = {
+ { .cluster_addr = SPM_MP0_CPU0_PWR_CON, .cpu_stride = 2U }
+};
+
+/**** per_cluster registers for SPM_MP0_CPUTOP_PWR_CON */
+static const struct per_cpu_reg SPM_CLUSTER_PWR[] = {
+ { .cluster_addr = SPM_MP0_CPUTOP_PWR_CON, .cpu_stride = 0U }
+};
+
+/* === MCUCFG related registers */
+/* aa64naa32 */
+#define MCUCFG_MP0_CLUSTER_CFG5 MCUCFG_REG(0xc8e4)
+/* reset vectors */
+#define MCUCFG_MP0_CLUSTER_CFG8 MCUCFG_REG(0xc900)
+#define MCUCFG_MP0_CLUSTER_CFG10 MCUCFG_REG(0xc908)
+#define MCUCFG_MP0_CLUSTER_CFG12 MCUCFG_REG(0xc910)
+#define MCUCFG_MP0_CLUSTER_CFG14 MCUCFG_REG(0xc918)
+#define MCUCFG_MP0_CLUSTER_CFG16 MCUCFG_REG(0xc920)
+#define MCUCFG_MP0_CLUSTER_CFG18 MCUCFG_REG(0xc928)
+#define MCUCFG_MP0_CLUSTER_CFG20 MCUCFG_REG(0xc930)
+#define MCUCFG_MP0_CLUSTER_CFG22 MCUCFG_REG(0xc938)
+
+/* MCUSYS DREQ BIG VPROC ISO control */
+#define DREQ20_BIG_VPROC_ISO MCUCFG_REG(0xad8c)
+
+/**** per_cpu registers for MCUCFG_MP0_CLUSTER_CFG? */
+static const struct per_cpu_reg MCUCFG_BOOTADDR[] = {
+ { .cluster_addr = MCUCFG_MP0_CLUSTER_CFG8, .cpu_stride = 3U }
+};
+
+/**** per_cpu registers for MCUCFG_MP0_CLUSTER_CFG5 */
+static const struct per_cpu_reg MCUCFG_INITARCH[] = {
+ { .cluster_addr = MCUCFG_MP0_CLUSTER_CFG5, .cpu_stride = 0U }
+};
+
+#define MCUCFG_INITARCH_CPU_BIT(cpu) BIT(16U + cpu)
+#define LAST_PC_REG(cpu) (MCUCFG_REG(0x308) + (cpu * 0x800))
+
+/* === CPC control */
+#define MCUCFG_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814)
+#define MCUCFG_CPC_SPMC_PWR_STATUS MCUCFG_REG(0xa840)
+
+/* bit fields of CPC_FLOW_CTRL_CFG */
+#define CPC_CTRL_ENABLE BIT(16)
+#define SSPM_ALL_PWR_CTRL_EN BIT(13) /* for cpu-hotplug */
+#define GIC_WAKEUP_IGNORE(cpu) BIT(21 + cpu)
+
+/* bit fields of CPC_SPMC_PWR_STATUS */
+#define CORE_SPMC_PWR_ON_ACK GENMASK(15, 0)
+
+/* === APB Module infracfg_ao */
+#define INFRA_TOPAXI_PROTECTEN INFRACFG_AO_REG(0x0220)
+#define INFRA_TOPAXI_PROTECTEN_STA0 INFRACFG_AO_REG(0x0224)
+#define INFRA_TOPAXI_PROTECTEN_STA1 INFRACFG_AO_REG(0x0228)
+#define INFRA_TOPAXI_PROTECTEN_SET INFRACFG_AO_REG(0x02a0)
+#define INFRA_TOPAXI_PROTECTEN_CLR INFRACFG_AO_REG(0x02a4)
+#define INFRA_TOPAXI_PROTECTEN_1 INFRACFG_AO_REG(0x0250)
+#define INFRA_TOPAXI_PROTECTEN_STA0_1 INFRACFG_AO_REG(0x0254)
+#define INFRA_TOPAXI_PROTECTEN_STA1_1 INFRACFG_AO_REG(0x0258)
+#define INFRA_TOPAXI_PROTECTEN_1_SET INFRACFG_AO_REG(0x02a8)
+#define INFRA_TOPAXI_PROTECTEN_1_CLR INFRACFG_AO_REG(0x02ac)
+
+/* bit fields of INFRA_TOPAXI_PROTECTEN */
+#define MP0_SPMC_PROT_STEP1_0_MASK BIT(12)
+#define MP0_SPMC_PROT_STEP1_1_MASK (BIT(26) | BIT(12))
+
+/* === SPARK */
+#define VOLTAGE_04 U(0x40)
+#define VOLTAGE_05 U(0x60)
+
+#define PTP3_CPU0_SPMC_SW_CFG MCUCFG_REG(0x200)
+#define CPU0_ILDO_CONTROL5 MCUCFG_REG(0x334)
+#define CPU0_ILDO_CONTROL8 MCUCFG_REG(0x340)
+
+/* bit fields of CPU0_ILDO_CONTROL5 */
+#define ILDO_RET_VOSEL GENMASK(7, 0)
+
+/* bit fields of PTP3_CPU_SPMC_SW_CFG */
+#define SW_SPARK_EN BIT(0)
+
+/* bit fields of CPU0_ILDO_CONTROL8 */
+#define ILDO_BYPASS_B BIT(0)
+
+static const struct per_cpu_reg MCUCFG_SPARK[] = {
+ { .cluster_addr = PTP3_CPU0_SPMC_SW_CFG, .cpu_stride = 11U }
+};
+
+static const struct per_cpu_reg ILDO_CONTROL5[] = {
+ { .cluster_addr = CPU0_ILDO_CONTROL5, .cpu_stride = 11U }
+};
+
+static const struct per_cpu_reg ILDO_CONTROL8[] = {
+ { .cluster_addr = CPU0_ILDO_CONTROL8, .cpu_stride = 11U }
+};
+
+#endif /* MTSPMC_PRIVATE_H */
diff --git a/plat/mediatek/mt8192/drivers/timer/mt_timer.c b/plat/mediatek/mt8192/drivers/timer/mt_timer.c
new file mode 100644
index 000000000..08608854a
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/timer/mt_timer.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <lib/mmio.h>
+#include <mt_timer.h>
+#include <platform_def.h>
+
+
+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;
+ uint64_t rel_base;
+
+ rel_base = read_cntpct_el0() - atf_time_base;
+ cval = ((rel_base * 1000U) / SYS_COUNTER_FREQ_IN_MHZ)
+ - normal_time_base;
+ return cval;
+}
+
+void mt_systimer_init(void)
+{
+ /* Enable access in NS mode */
+ mmio_write_32(CNTWACR_REG, CNT_WRITE_ACCESS_CTL_MASK);
+ mmio_write_32(CNTRACR_REG, CNT_READ_ACCESS_CTL_MASK);
+}
diff --git a/plat/mediatek/mt8192/drivers/timer/mt_timer.h b/plat/mediatek/mt8192/drivers/timer/mt_timer.h
new file mode 100644
index 000000000..b35317715
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/timer/mt_timer.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_TIMER_H
+#define MT_TIMER_H
+
+#define SYSTIMER_BASE (0x10017000)
+#define CNTCR_REG (SYSTIMER_BASE + 0x0)
+#define CNTSR_REG (SYSTIMER_BASE + 0x4)
+#define CNTSYS_L_REG (SYSTIMER_BASE + 0x8)
+#define CNTSYS_H_REG (SYSTIMER_BASE + 0xc)
+#define CNTWACR_REG (SYSTIMER_BASE + 0x10)
+#define CNTRACR_REG (SYSTIMER_BASE + 0x14)
+
+#define TIEO_EN (1 << 3)
+#define COMP_15_EN (1 << 10)
+#define COMP_20_EN (1 << 11)
+#define COMP_25_EN (1 << 12)
+
+#define COMP_FEATURE_MASK (COMP_15_EN | COMP_20_EN | COMP_25_EN | TIEO_EN)
+#define COMP_15_MASK (COMP_15_EN)
+#define COMP_20_MASK (COMP_20_EN | TIEO_EN)
+#define COMP_25_MASK (COMP_20_EN | COMP_25_EN)
+
+#define CNT_WRITE_ACCESS_CTL_MASK (0x3FFFFF0U)
+#define CNT_READ_ACCESS_CTL_MASK (0x3FFFFFFU)
+
+void sched_clock_init(uint64_t normal_base, uint64_t atf_base);
+uint64_t sched_clock(void);
+void mt_systimer_init(void);
+
+#endif /* MT_TIMER_H */
diff --git a/plat/mediatek/mt8192/drivers/uart/uart.h b/plat/mediatek/mt8192/drivers/uart/uart.h
new file mode 100644
index 000000000..ac8b94dd1
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/uart/uart.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef UART_H
+#define UART_H
+
+#include <platform_def.h>
+
+/* UART HW information */
+#define HW_SUPPORT_UART_PORTS 2
+#define DRV_SUPPORT_UART_PORTS 2
+
+/* console UART clock cg */
+#define UART_CLOCK_GATE_SET (INFRACFG_AO_BASE + 0x80)
+#define UART_CLOCK_GATE_CLR (INFRACFG_AO_BASE + 0x84)
+#define UART_CLOCK_GATE_STA (INFRACFG_AO_BASE + 0x90)
+#define UART0_CLOCK_GATE_BIT (1U<<22)
+#define UART1_CLOCK_GATE_BIT (1U<<23)
+
+/* UART registers */
+#define UART_RBR(_baseaddr) (_baseaddr + 0x0)
+#define UART_THR(_baseaddr) (_baseaddr + 0x0)
+#define UART_IER(_baseaddr) (_baseaddr + 0x4)
+#define UART_IIR(_baseaddr) (_baseaddr + 0x8)
+#define UART_FCR(_baseaddr) (_baseaddr + 0x8)
+#define UART_LCR(_baseaddr) (_baseaddr + 0xc)
+#define UART_MCR(_baseaddr) (_baseaddr + 0x10)
+#define UART_LSR(_baseaddr) (_baseaddr + 0x14)
+#define UART_MSR(_baseaddr) (_baseaddr + 0x18)
+#define UART_SCR(_baseaddr) (_baseaddr + 0x1c)
+#define UART_DLL(_baseaddr) (_baseaddr + 0x0)
+#define UART_DLH(_baseaddr) (_baseaddr + 0x4)
+#define UART_EFR(_baseaddr) (_baseaddr + 0x8)
+#define UART_XON1(_baseaddr) (_baseaddr + 0x10)
+#define UART_XON2(_baseaddr) (_baseaddr + 0x14)
+#define UART_XOFF1(_baseaddr) (_baseaddr + 0x18)
+#define UART_XOFF2(_baseaddr) (_baseaddr + 0x1c)
+#define UART_AUTOBAUD(_baseaddr) (_baseaddr + 0x20)
+#define UART_HIGHSPEED(_baseaddr) (_baseaddr + 0x24)
+#define UART_SAMPLE_COUNT(_baseaddr) (_baseaddr + 0x28)
+#define UART_SAMPLE_POINT(_baseaddr) (_baseaddr + 0x2c)
+#define UART_AUTOBAUD_REG(_baseaddr) (_baseaddr + 0x30)
+#define UART_RATE_FIX_REG(_baseaddr) (_baseaddr + 0x34)
+#define UART_AUTO_BAUDSAMPLE(_baseaddr) (_baseaddr + 0x38)
+#define UART_GUARD(_baseaddr) (_baseaddr + 0x3c)
+#define UART_ESCAPE_DAT(_baseaddr) (_baseaddr + 0x40)
+#define UART_ESCAPE_EN(_baseaddr) (_baseaddr + 0x44)
+#define UART_SLEEP_EN(_baseaddr) (_baseaddr + 0x48)
+#define UART_DMA_EN(_baseaddr) (_baseaddr + 0x4c)
+#define UART_RXTRI_AD(_baseaddr) (_baseaddr + 0x50)
+#define UART_FRACDIV_L(_baseaddr) (_baseaddr + 0x54)
+#define UART_FRACDIV_M(_baseaddr) (_baseaddr + 0x58)
+#define UART_FCR_RD(_baseaddr) (_baseaddr + 0x5C)
+#define UART_USB_RX_SEL(_baseaddr) (_baseaddr + 0xB0)
+#define UART_SLEEP_REQ(_baseaddr) (_baseaddr + 0xB4)
+#define UART_SLEEP_ACK(_baseaddr) (_baseaddr + 0xB8)
+#define UART_SPM_SEL(_baseaddr) (_baseaddr + 0xBC)
+#define UART_LCR_DLAB 0x0080
+#define UART_LCR_MODE_B 0x00bf
+
+enum uart_port_ID {
+ UART_PORT0 = 0,
+ UART_PORT1
+};
+
+struct mt_uart_register {
+ uint32_t dll;
+ uint32_t dlh;
+ uint32_t ier;
+ uint32_t lcr;
+ uint32_t mcr;
+ uint32_t fcr;
+ uint32_t lsr;
+ uint32_t scr;
+ uint32_t efr;
+ uint32_t highspeed;
+ uint32_t sample_count;
+ uint32_t sample_point;
+ uint32_t fracdiv_l;
+ uint32_t fracdiv_m;
+ uint32_t escape_en;
+ uint32_t guard;
+ uint32_t rx_sel;
+};
+
+struct mt_uart {
+ unsigned long base;
+ struct mt_uart_register registers;
+};
+
+/* external API */
+void mt_uart_save(void);
+void mt_uart_restore(void);
+void mt_console_uart_cg(int on);
+uint32_t mt_console_uart_cg_status(void);
+
+#endif /* __UART_H__ */
diff --git a/plat/mediatek/mt8192/include/mcucfg.h b/plat/mediatek/mt8192/include/mcucfg.h
new file mode 100644
index 000000000..046cf7314
--- /dev/null
+++ b/plat/mediatek/mt8192/include/mcucfg.h
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MCUCFG_H
+#define MCUCFG_H
+
+#ifndef __ASSEMBLER__
+#include <stdint.h>
+#endif /* __ASSEMBLER__ */
+
+#include <platform_def.h>
+
+#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs))
+
+#define MP2_MISC_CONFIG_BOOT_ADDR_L(cpu) (MCUCFG_REG(0x2290) + ((cpu) * 8))
+#define MP2_MISC_CONFIG_BOOT_ADDR_H(cpu) (MCUCFG_REG(0x2294) + ((cpu) * 8))
+
+#define MP2_CPUCFG MCUCFG_REG(0x2208)
+
+#define MP2_CPU0_STANDBYWFE BIT(4)
+#define MP2_CPU1_STANDBYWFE BIT(5)
+
+#define MP0_CPUTOP_SPMC_CTL MCUCFG_REG(0x788)
+#define MP1_CPUTOP_SPMC_CTL MCUCFG_REG(0x78C)
+#define MP1_CPUTOP_SPMC_SRAM_CTL MCUCFG_REG(0x790)
+
+#define sw_spark_en BIT(0)
+#define sw_no_wait_for_q_channel BIT(1)
+#define sw_fsm_override BIT(2)
+#define sw_logic_pre1_pdb BIT(3)
+#define sw_logic_pre2_pdb BIT(4)
+#define sw_logic_pdb BIT(5)
+#define sw_iso BIT(6)
+#define sw_sram_sleepb (U(0x3F) << 7)
+#define sw_sram_isointb BIT(13)
+#define sw_clk_dis BIT(14)
+#define sw_ckiso BIT(15)
+#define sw_pd (U(0x3F) << 16)
+#define sw_hot_plug_reset BIT(22)
+#define sw_pwr_on_override_en BIT(23)
+#define sw_pwr_on BIT(24)
+#define sw_coq_dis BIT(25)
+#define logic_pdbo_all_off_ack BIT(26)
+#define logic_pdbo_all_on_ack BIT(27)
+#define logic_pre2_pdbo_all_on_ack BIT(28)
+#define logic_pre1_pdbo_all_on_ack BIT(29)
+
+
+#define CPUSYSx_CPUx_SPMC_CTL(cluster, cpu) \
+ (MCUCFG_REG(0x1c30) + cluster * 0x2000 + cpu * 4)
+
+#define CPUSYS0_CPU0_SPMC_CTL MCUCFG_REG(0x1c30)
+#define CPUSYS0_CPU1_SPMC_CTL MCUCFG_REG(0x1c34)
+#define CPUSYS0_CPU2_SPMC_CTL MCUCFG_REG(0x1c38)
+#define CPUSYS0_CPU3_SPMC_CTL MCUCFG_REG(0x1c3C)
+
+#define CPUSYS1_CPU0_SPMC_CTL MCUCFG_REG(0x3c30)
+#define CPUSYS1_CPU1_SPMC_CTL MCUCFG_REG(0x3c34)
+#define CPUSYS1_CPU2_SPMC_CTL MCUCFG_REG(0x3c38)
+#define CPUSYS1_CPU3_SPMC_CTL MCUCFG_REG(0x3c3C)
+
+#define cpu_sw_spark_en BIT(0)
+#define cpu_sw_no_wait_for_q_channel BIT(1)
+#define cpu_sw_fsm_override BIT(2)
+#define cpu_sw_logic_pre1_pdb BIT(3)
+#define cpu_sw_logic_pre2_pdb BIT(4)
+#define cpu_sw_logic_pdb BIT(5)
+#define cpu_sw_iso BIT(6)
+#define cpu_sw_sram_sleepb BIT(7)
+#define cpu_sw_sram_isointb BIT(8)
+#define cpu_sw_clk_dis BIT(9)
+#define cpu_sw_ckiso BIT(10)
+#define cpu_sw_pd (U(0x1F) << 11)
+#define cpu_sw_hot_plug_reset BIT(16)
+#define cpu_sw_powr_on_override_en BIT(17)
+#define cpu_sw_pwr_on BIT(18)
+#define cpu_spark2ldo_allswoff BIT(19)
+#define cpu_pdbo_all_on_ack BIT(20)
+#define cpu_pre2_pdbo_allon_ack BIT(21)
+#define cpu_pre1_pdbo_allon_ack BIT(22)
+
+/* CPC related registers */
+#define CPC_MCUSYS_CPC_OFF_THRES MCUCFG_REG(0xa714)
+#define CPC_MCUSYS_PWR_CTRL MCUCFG_REG(0xa804)
+#define CPC_MCUSYS_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814)
+#define CPC_MCUSYS_LAST_CORE_REQ MCUCFG_REG(0xa818)
+#define CPC_MCUSYS_MP_LAST_CORE_RESP MCUCFG_REG(0xa81c)
+#define CPC_MCUSYS_LAST_CORE_RESP MCUCFG_REG(0xa824)
+#define CPC_MCUSYS_PWR_ON_MASK MCUCFG_REG(0xa828)
+#define CPC_MCUSYS_CPU_ON_SW_HINT_SET MCUCFG_REG(0xa8a8)
+#define CPC_MCUSYS_CPU_ON_SW_HINT_CLR MCUCFG_REG(0xa8ac)
+#define CPC_MCUSYS_CPC_DBG_SETTING MCUCFG_REG(0xab00)
+#define CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE MCUCFG_REG(0xab04)
+#define CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE MCUCFG_REG(0xab08)
+#define CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE MCUCFG_REG(0xab0c)
+#define CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE MCUCFG_REG(0xab10)
+#define CPC_MCUSYS_TRACE_SEL MCUCFG_REG(0xab14)
+#define CPC_MCUSYS_TRACE_DATA MCUCFG_REG(0xab20)
+#define CPC_MCUSYS_CLUSTER_COUNTER MCUCFG_REG(0xab70)
+#define CPC_MCUSYS_CLUSTER_COUNTER_CLR MCUCFG_REG(0xab74)
+
+#define SPARK2LDO MCUCFG_REG(0x2700)
+/* APB Module mcucfg */
+#define MP0_CA7_CACHE_CONFIG MCUCFG_REG(0x000)
+#define MP0_AXI_CONFIG MCUCFG_REG(0x02C)
+#define MP0_MISC_CONFIG0 MCUCFG_REG(0x030)
+#define MP0_MISC_CONFIG1 MCUCFG_REG(0x034)
+#define MP0_MISC_CONFIG2 MCUCFG_REG(0x038)
+#define MP0_MISC_CONFIG_BOOT_ADDR(cpu) (MP0_MISC_CONFIG2 + ((cpu) * 8))
+#define MP0_MISC_CONFIG3 MCUCFG_REG(0x03C)
+#define MP0_MISC_CONFIG9 MCUCFG_REG(0x054)
+#define MP0_CA7_MISC_CONFIG MCUCFG_REG(0x064)
+
+#define MP0_RW_RSVD0 MCUCFG_REG(0x06C)
+
+
+#define MP1_CA7_CACHE_CONFIG MCUCFG_REG(0x200)
+#define MP1_AXI_CONFIG MCUCFG_REG(0x22C)
+#define MP1_MISC_CONFIG0 MCUCFG_REG(0x230)
+#define MP1_MISC_CONFIG1 MCUCFG_REG(0x234)
+#define MP1_MISC_CONFIG2 MCUCFG_REG(0x238)
+#define MP1_MISC_CONFIG_BOOT_ADDR(cpu) (MP1_MISC_CONFIG2 + ((cpu) * 8))
+#define MP1_MISC_CONFIG3 MCUCFG_REG(0x23C)
+#define MP1_MISC_CONFIG9 MCUCFG_REG(0x254)
+#define MP1_CA7_MISC_CONFIG MCUCFG_REG(0x264)
+
+#define CCI_ADB400_DCM_CONFIG MCUCFG_REG(0x740)
+#define SYNC_DCM_CONFIG MCUCFG_REG(0x744)
+
+#define MP0_CLUSTER_CFG0 MCUCFG_REG(0xC8D0)
+
+#define MP0_SPMC MCUCFG_REG(0x788)
+#define MP1_SPMC MCUCFG_REG(0x78C)
+#define MP2_AXI_CONFIG MCUCFG_REG(0x220C)
+#define MP2_AXI_CONFIG_ACINACTM BIT(0)
+#define MP2_AXI_CONFIG_AINACTS BIT(4)
+
+#define MPx_AXI_CONFIG_ACINACTM BIT(4)
+#define MPx_AXI_CONFIG_AINACTS BIT(5)
+
+#define MPx_CA7_MISC_CONFIG_standbywfil2 BIT(28)
+
+#define MP0_CPU0_STANDBYWFE BIT(20)
+#define MP0_CPU1_STANDBYWFE BIT(21)
+#define MP0_CPU2_STANDBYWFE BIT(22)
+#define MP0_CPU3_STANDBYWFE BIT(23)
+
+#define MP1_CPU0_STANDBYWFE BIT(20)
+#define MP1_CPU1_STANDBYWFE BIT(21)
+#define MP1_CPU2_STANDBYWFE BIT(22)
+#define MP1_CPU3_STANDBYWFE BIT(23)
+
+#define CPUSYS0_SPARKVRETCNTRL MCUCFG_REG(0x1c00)
+#define CPUSYS0_SPARKEN MCUCFG_REG(0x1c04)
+#define CPUSYS0_AMUXSEL MCUCFG_REG(0x1c08)
+#define CPUSYS1_SPARKVRETCNTRL MCUCFG_REG(0x3c00)
+#define CPUSYS1_SPARKEN MCUCFG_REG(0x3c04)
+#define CPUSYS1_AMUXSEL MCUCFG_REG(0x3c08)
+
+#define MP2_PWR_RST_CTL MCUCFG_REG(0x2008)
+#define MP2_PTP3_CPUTOP_SPMC0 MCUCFG_REG(0x22A0)
+#define MP2_PTP3_CPUTOP_SPMC1 MCUCFG_REG(0x22A4)
+
+#define MP2_COQ MCUCFG_REG(0x22BC)
+#define MP2_COQ_SW_DIS BIT(0)
+
+#define MP2_CA15M_MON_SEL MCUCFG_REG(0x2400)
+#define MP2_CA15M_MON_L MCUCFG_REG(0x2404)
+
+#define CPUSYS2_CPU0_SPMC_CTL MCUCFG_REG(0x2430)
+#define CPUSYS2_CPU1_SPMC_CTL MCUCFG_REG(0x2438)
+#define CPUSYS2_CPU0_SPMC_STA MCUCFG_REG(0x2434)
+#define CPUSYS2_CPU1_SPMC_STA MCUCFG_REG(0x243C)
+
+#define MP0_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x068)
+#define MP1_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x268)
+#define BIG_DBG_PWR_CTRL MCUCFG_REG(0x75C)
+
+#define MP2_SW_RST_B BIT(0)
+#define MP2_TOPAON_APB_MASK BIT(1)
+
+#define B_SW_HOT_PLUG_RESET BIT(30)
+
+#define B_SW_PD_OFFSET 18U
+#define B_SW_PD (U(0x3f) << B_SW_PD_OFFSET)
+
+#define B_SW_SRAM_SLEEPB_OFFSET 12U
+#define B_SW_SRAM_SLEEPB (U(0x3f) << B_SW_SRAM_SLEEPB_OFFSET)
+
+#define B_SW_SRAM_ISOINTB BIT(9)
+#define B_SW_ISO BIT(8)
+#define B_SW_LOGIC_PDB BIT(7)
+#define B_SW_LOGIC_PRE2_PDB BIT(6)
+#define B_SW_LOGIC_PRE1_PDB BIT(5)
+#define B_SW_FSM_OVERRIDE BIT(4)
+#define B_SW_PWR_ON BIT(3)
+#define B_SW_PWR_ON_OVERRIDE_EN BIT(2)
+
+#define B_FSM_STATE_OUT_OFFSET (6U)
+#define B_FSM_STATE_OUT_MASK (U(0x1f) << B_FSM_STATE_OUT_OFFSET)
+#define B_SW_LOGIC_PDBO_ALL_OFF_ACK BIT(5)
+#define B_SW_LOGIC_PDBO_ALL_ON_ACK BIT(4)
+#define B_SW_LOGIC_PRE2_PDBO_ALL_ON_ACK BIT(3)
+#define B_SW_LOGIC_PRE1_PDBO_ALL_ON_ACK BIT(2)
+
+#define B_FSM_OFF (0U << B_FSM_STATE_OUT_OFFSET)
+#define B_FSM_ON (1U << B_FSM_STATE_OUT_OFFSET)
+#define B_FSM_RET (2U << B_FSM_STATE_OUT_OFFSET)
+
+#ifndef __ASSEMBLER__
+/* cpu boot mode */
+enum {
+ MP0_CPUCFG_64BIT_SHIFT = 12U,
+ MP1_CPUCFG_64BIT_SHIFT = 28U,
+ MP0_CPUCFG_64BIT = U(0xf) << MP0_CPUCFG_64BIT_SHIFT,
+ MP1_CPUCFG_64BIT = U(0xf) << MP1_CPUCFG_64BIT_SHIFT
+};
+
+enum {
+ MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0U,
+ MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4U,
+ MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8U,
+ MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12U,
+ MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16U,
+
+ MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK =
+ U(0xf) << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK =
+ U(0xf) << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK =
+ U(0xf) << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK =
+ U(0xf) << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK =
+ U(0xf) << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT
+};
+
+enum {
+ MP1_AINACTS_SHIFT = 4U,
+ MP1_AINACTS = 1U << MP1_AINACTS_SHIFT
+};
+
+enum {
+ MP1_SW_CG_GEN_SHIFT = 12U,
+ MP1_SW_CG_GEN = 1U << MP1_SW_CG_GEN_SHIFT
+};
+
+enum {
+ MP1_L2RSTDISABLE_SHIFT = 14U,
+ MP1_L2RSTDISABLE = 1U << MP1_L2RSTDISABLE_SHIFT
+};
+#endif /* __ASSEMBLER__ */
+
+#endif /* MCUCFG_H */
diff --git a/plat/mediatek/mt8192/include/mt_gic_v3.h b/plat/mediatek/mt8192/include/mt_gic_v3.h
new file mode 100644
index 000000000..c4ab44fa3
--- /dev/null
+++ b/plat/mediatek/mt8192/include/mt_gic_v3.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_GIC_V3_H
+#define MT_GIC_V3_H
+
+#include <drivers/arm/gicv3.h>
+#include <lib/mmio.h>
+
+void mt_gic_driver_init(void);
+void mt_gic_init(void);
+void mt_gic_set_pending(uint32_t irq);
+void mt_gic_distif_save(void);
+void mt_gic_distif_restore(void);
+void mt_gic_rdistif_init(void);
+void mt_gic_rdistif_save(void);
+void mt_gic_rdistif_restore(void);
+void mt_gic_rdistif_restore_all(void);
+void gic_sgi_save_all(void);
+void gic_sgi_restore_all(void);
+uint32_t mt_irq_get_pending(uint32_t irq);
+void mt_irq_set_pending(uint32_t irq);
+
+#endif /* MT_GIC_V3_H */
diff --git a/plat/mediatek/mt8192/include/plat_helpers.h b/plat/mediatek/mt8192/include/plat_helpers.h
new file mode 100644
index 000000000..9b550ee25
--- /dev/null
+++ b/plat/mediatek/mt8192/include/plat_helpers.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_HELPERS_H__
+#define __PLAT_HELPERS_H__
+
+unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr);
+
+#endif /* __PLAT_HELPERS_H__ */
diff --git a/plat/mediatek/mt8192/include/plat_macros.S b/plat/mediatek/mt8192/include/plat_macros.S
new file mode 100644
index 000000000..7d17e360a
--- /dev/null
+++ b/plat/mediatek/mt8192/include/plat_macros.S
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#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"
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+ .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+ /* ---------------------------------------------
+ * The below macro prints out relevant GIC
+ * registers whenever an unhandled exception
+ * is taken in BL31.
+ * Clobbers: x0 - x10, x26, x27, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ /* To-do: GIC owner */
+ /* To-do: CCI owner */
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/mediatek/mt8192/include/plat_mt_cirq.h b/plat/mediatek/mt8192/include/plat_mt_cirq.h
new file mode 100644
index 000000000..bb8b4577f
--- /dev/null
+++ b/plat/mediatek/mt8192/include/plat_mt_cirq.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MT_CIRQ_H
+#define PLAT_MT_CIRQ_H
+
+#include <stdint.h>
+
+enum {
+ IRQ_MASK_HEADER = 0xF1F1F1F1,
+ IRQ_MASK_FOOTER = 0xF2F2F2F2
+};
+
+struct mtk_irq_mask {
+ uint32_t header; /* for error checking */
+ uint32_t mask0;
+ uint32_t mask1;
+ uint32_t mask2;
+ uint32_t mask3;
+ uint32_t mask4;
+ uint32_t mask5;
+ uint32_t mask6;
+ uint32_t mask7;
+ uint32_t mask8;
+ uint32_t mask9;
+ uint32_t mask10;
+ uint32_t mask11;
+ uint32_t mask12;
+ uint32_t footer; /* for error checking */
+};
+
+/*
+ * Define hardware register
+ */
+
+#define SYS_CIRQ_BASE U(0x10204000)
+#define CIRQ_REG_NUM U(14)
+#define CIRQ_IRQ_NUM U(439)
+#define CIRQ_SPI_START U(64)
+#define MD_WDT_IRQ_BIT_ID U(110)
+
+#define CIRQ_STA_BASE (SYS_CIRQ_BASE + U(0x000))
+#define CIRQ_ACK_BASE (SYS_CIRQ_BASE + U(0x080))
+#define CIRQ_MASK_BASE (SYS_CIRQ_BASE + U(0x100))
+#define CIRQ_MASK_SET_BASE (SYS_CIRQ_BASE + U(0x180))
+#define CIRQ_MASK_CLR_BASE (SYS_CIRQ_BASE + U(0x200))
+#define CIRQ_SENS_BASE (SYS_CIRQ_BASE + U(0x280))
+#define CIRQ_SENS_SET_BASE (SYS_CIRQ_BASE + U(0x300))
+#define CIRQ_SENS_CLR_BASE (SYS_CIRQ_BASE + U(0x380))
+#define CIRQ_POL_BASE (SYS_CIRQ_BASE + U(0x400))
+#define CIRQ_POL_SET_BASE (SYS_CIRQ_BASE + U(0x480))
+#define CIRQ_POL_CLR_BASE (SYS_CIRQ_BASE + U(0x500))
+#define CIRQ_CON (SYS_CIRQ_BASE + U(0x600))
+
+/*
+ * Register placement
+ */
+#define CIRQ_CON_EN_BITS U(0)
+#define CIRQ_CON_EDGE_ONLY_BITS U(1)
+#define CIRQ_CON_FLUSH_BITS U(2)
+#define CIRQ_CON_SW_RST_BITS U(20)
+#define CIRQ_CON_EVENT_BITS U(31)
+#define CIRQ_CON_BITS_MASK U(0x7)
+
+/*
+ * Register setting
+ */
+#define CIRQ_CON_EN U(0x1)
+#define CIRQ_CON_EDGE_ONLY U(0x1)
+#define CIRQ_CON_FLUSH U(0x1)
+#define CIRQ_SW_RESET U(0x1)
+
+/*
+ * Define constant
+ */
+#define CIRQ_CTRL_REG_NUM ((CIRQ_IRQ_NUM + 31U) / 32U)
+
+#define MT_CIRQ_POL_NEG U(0)
+#define MT_CIRQ_POL_POS U(1)
+
+#define IRQ_TO_CIRQ_NUM(irq) ((irq) - (32U + CIRQ_SPI_START))
+#define CIRQ_TO_IRQ_NUM(cirq) ((cirq) + (32U + CIRQ_SPI_START))
+
+/* GIC sensitive */
+#define SENS_EDGE U(0x2)
+#define SENS_LEVEL U(0x1)
+
+
+/*
+ * Define function prototypes.
+ */
+int mt_cirq_test(void);
+void mt_cirq_dump_reg(void);
+int mt_irq_mask_restore(struct mtk_irq_mask *mask);
+int mt_irq_mask_all(struct mtk_irq_mask *mask);
+void mt_cirq_clone_gic(void);
+void mt_cirq_enable(void);
+void mt_cirq_flush(void);
+void mt_cirq_disable(void);
+void mt_irq_unmask_for_sleep_ex(uint32_t irq);
+void set_wakeup_sources(uint32_t *list, uint32_t num_of_events);
+void mt_cirq_sw_reset(void);
+
+struct cirq_reg {
+ uint32_t reg_num;
+ uint32_t used;
+ uint32_t mask;
+ uint32_t pol;
+ uint32_t sen;
+ uint32_t pending;
+ uint32_t the_link;
+};
+
+struct cirq_events {
+ uint32_t num_reg;
+ uint32_t spi_start;
+ uint32_t num_of_events;
+ uint32_t *wakeup_events;
+ struct cirq_reg table[CIRQ_REG_NUM];
+ uint32_t dist_base;
+ uint32_t cirq_base;
+ uint32_t used_reg_head;
+};
+
+#endif /* PLAT_MT_CIRQ_H */
diff --git a/plat/mediatek/mt8192/include/plat_mtk_lpm.h b/plat/mediatek/mt8192/include/plat_mtk_lpm.h
new file mode 100644
index 000000000..8ba8b93a8
--- /dev/null
+++ b/plat/mediatek/mt8192/include/plat_mtk_lpm.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MTK_LPM_H
+#define PLAT_MTK_LPM_H
+
+#include <lib/psci/psci.h>
+#include <lib/utils_def.h>
+
+#define MT_IRQ_REMAIN_MAX U(8)
+#define MT_IRQ_REMAIN_CAT_LOG BIT(31)
+
+struct mt_irqremain {
+ unsigned int count;
+ unsigned int irqs[MT_IRQ_REMAIN_MAX];
+ unsigned int wakeupsrc_cat[MT_IRQ_REMAIN_MAX];
+ unsigned int wakeupsrc[MT_IRQ_REMAIN_MAX];
+};
+
+#define PLAT_RC_STATUS_READY BIT(0)
+#define PLAT_RC_STATUS_FEATURE_EN BIT(1)
+#define PLAT_RC_STATUS_UART_NONSLEEP BIT(31)
+
+struct mt_lpm_tz {
+ int (*pwr_prompt)(unsigned int cpu, const psci_power_state_t *state);
+ int (*pwr_reflect)(unsigned int cpu, const psci_power_state_t *state);
+
+ int (*pwr_cpu_on)(unsigned int cpu, const psci_power_state_t *state);
+ int (*pwr_cpu_dwn)(unsigned int cpu, const psci_power_state_t *state);
+
+ int (*pwr_cluster_on)(unsigned int cpu,
+ const psci_power_state_t *state);
+ int (*pwr_cluster_dwn)(unsigned int cpu,
+ const psci_power_state_t *state);
+
+ int (*pwr_mcusys_on)(unsigned int cpu, const psci_power_state_t *state);
+ int (*pwr_mcusys_on_finished)(unsigned int cpu,
+ const psci_power_state_t *state);
+ int (*pwr_mcusys_dwn)(unsigned int cpu,
+ const psci_power_state_t *state);
+};
+
+const struct mt_lpm_tz *mt_plat_cpu_pm_init(void);
+
+#endif /* PLAT_MTK_LPM_H */
diff --git a/plat/mediatek/mt8192/include/plat_pm.h b/plat/mediatek/mt8192/include/plat_pm.h
new file mode 100644
index 000000000..a2881cef6
--- /dev/null
+++ b/plat/mediatek/mt8192/include/plat_pm.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PM_H
+#define PLAT_PM_H
+
+#include <lib/utils_def.h>
+
+#define MT_PLAT_PWR_STATE_CPU U(1)
+#define MT_PLAT_PWR_STATE_CLUSTER U(2)
+#define MT_PLAT_PWR_STATE_MCUSYS U(3)
+#define MT_PLAT_PWR_STATE_SUSPEND2IDLE U(8)
+#define MT_PLAT_PWR_STATE_SYSTEM_SUSPEND U(9)
+
+#define MTK_LOCAL_STATE_RUN U(0)
+#define MTK_LOCAL_STATE_RET U(1)
+#define MTK_LOCAL_STATE_OFF U(2)
+
+#define MTK_AFFLVL_CPU U(0)
+#define MTK_AFFLVL_CLUSTER U(1)
+#define MTK_AFFLVL_MCUSYS U(2)
+#define MTK_AFFLVL_SYSTEM U(3)
+
+#define IS_CLUSTER_OFF_STATE(s) \
+ is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_CLUSTER])
+#define IS_MCUSYS_OFF_STATE(s) \
+ is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_MCUSYS])
+#define IS_SYSTEM_SUSPEND_STATE(s) \
+ is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_SYSTEM])
+
+#define IS_PLAT_SUSPEND_ID(stateid)\
+ ((stateid == MT_PLAT_PWR_STATE_SUSPEND2IDLE) \
+ || (stateid == MT_PLAT_PWR_STATE_SYSTEM_SUSPEND))
+
+#endif /* PLAT_PM_H */
diff --git a/plat/mediatek/mt8192/include/plat_private.h b/plat/mediatek/mt8192/include/plat_private.h
new file mode 100644
index 000000000..42ca415f9
--- /dev/null
+++ b/plat/mediatek/mt8192/include/plat_private.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PRIVATE_H
+#define PLAT_PRIVATE_H
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void plat_configure_mmu_el3(uintptr_t total_base,
+ uintptr_t total_size,
+ uintptr_t ro_start,
+ uintptr_t ro_limit);
+
+#endif /* PLAT_PRIVATE_H */
diff --git a/plat/mediatek/mt8192/include/plat_sip_calls.h b/plat/mediatek/mt8192/include/plat_sip_calls.h
new file mode 100644
index 000000000..0e423225c
--- /dev/null
+++ b/plat/mediatek/mt8192/include/plat_sip_calls.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#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/mt8192/include/platform_def.h b/plat/mediatek/mt8192/include/platform_def.h
new file mode 100644
index 000000000..3e4441424
--- /dev/null
+++ b/plat/mediatek/mt8192/include/platform_def.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+
+#define PLAT_PRIMARY_CPU 0x0
+
+#define MT_GIC_BASE 0x0c000000
+#define PLAT_MT_CCI_BASE 0x0c500000
+#define MCUCFG_BASE 0x0c530000
+
+#define IO_PHYS 0x10000000
+
+/* Aggregate of all devices for MMU mapping */
+#define MTK_DEV_RNG0_BASE IO_PHYS
+#define MTK_DEV_RNG0_SIZE 0x10000000
+#define MTK_DEV_RNG1_BASE (IO_PHYS + 0x10000000)
+#define MTK_DEV_RNG1_SIZE 0x10000000
+#define MTK_DEV_RNG2_BASE 0x0c000000
+#define MTK_DEV_RNG2_SIZE 0x600000
+#define MTK_MCDI_SRAM_BASE 0x11B000
+#define MTK_MCDI_SRAM_MAP_SIZE 0x1000
+
+#define INFRACFG_AO_BASE (IO_PHYS + 0x00001000)
+#define GPIO_BASE (IO_PHYS + 0x00005000)
+#define SPM_BASE (IO_PHYS + 0x00006000)
+#define PMIC_WRAP_BASE (IO_PHYS + 0x00026000)
+#define EMI_BASE (IO_PHYS + 0x00219000)
+#define EMI_MPU_BASE (IO_PHYS + 0x00226000)
+#define IOCFG_RM_BASE (IO_PHYS + 0x01C20000)
+#define IOCFG_BM_BASE (IO_PHYS + 0x01D10000)
+#define IOCFG_BL_BASE (IO_PHYS + 0x01D30000)
+#define IOCFG_BR_BASE (IO_PHYS + 0x01D40000)
+#define IOCFG_LM_BASE (IO_PHYS + 0x01E20000)
+#define IOCFG_LB_BASE (IO_PHYS + 0x01E70000)
+#define IOCFG_RT_BASE (IO_PHYS + 0x01EA0000)
+#define IOCFG_LT_BASE (IO_PHYS + 0x01F20000)
+#define IOCFG_TL_BASE (IO_PHYS + 0x01F30000)
+/*******************************************************************************
+ * UART related constants
+ ******************************************************************************/
+#define UART0_BASE (IO_PHYS + 0x01002000)
+#define UART1_BASE (IO_PHYS + 0x01003000)
+
+#define UART_BAUDRATE 115200
+
+/*******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS 13000000
+#define SYS_COUNTER_FREQ_IN_MHZ 13
+
+/*******************************************************************************
+ * GIC-400 & interrupt handling related constants
+ ******************************************************************************/
+
+/* Base MTK_platform compatible GIC memory map */
+#define BASE_GICD_BASE MT_GIC_BASE
+#define MT_GIC_RDIST_BASE (MT_GIC_BASE + 0x40000)
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+#define PLATFORM_STACK_SIZE 0x800
+
+#define PLAT_MAX_PWR_LVL U(3)
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(9)
+
+#define PLATFORM_SYSTEM_COUNT U(1)
+#define PLATFORM_MCUSYS_COUNT U(1)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(8)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(8)
+
+#define SOC_CHIP_ID U(0x8192)
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+#define TZRAM_BASE 0x54600000
+#define TZRAM_SIZE 0x00030000
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL31 at the top of the Trusted SRAM (just below the shared memory, if
+ * present). BL31_BASE is calculated using the current BL31 debug size plus a
+ * little space for growth.
+ */
+#define BL31_BASE (TZRAM_BASE + 0x1000)
+#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#define MAX_XLAT_TABLES 16
+#define MAX_MMAP_REGIONS 16
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/mediatek/mt8192/plat_mt_cirq.c b/plat/mediatek/mt8192/plat_mt_cirq.c
new file mode 100644
index 000000000..9002b7ee1
--- /dev/null
+++ b/plat/mediatek/mt8192/plat_mt_cirq.c
@@ -0,0 +1,552 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/gic_common.h>
+#include <lib/mmio.h>
+
+#include <mt_gic_v3.h>
+#include <plat_mt_cirq.h>
+#include <platform_def.h>
+
+static struct cirq_events cirq_all_events = {
+ .spi_start = CIRQ_SPI_START,
+};
+static uint32_t already_cloned;
+/*
+ * mt_irq_mask_restore: restore all interrupts
+ * @mask: pointer to struct mtk_irq_mask for storing the original mask value.
+ * Return 0 for success; return negative values for failure.
+ * (This is ONLY used for the idle current measurement by the factory mode.)
+ */
+int mt_irq_mask_restore(struct mtk_irq_mask *mask)
+{
+ if (mask == NULL) {
+ return -1;
+ }
+ if (mask->header != IRQ_MASK_HEADER) {
+ return -1;
+ }
+ if (mask->footer != IRQ_MASK_FOOTER) {
+ return -1;
+ }
+
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x4),
+ mask->mask1);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x8),
+ mask->mask2);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0xc),
+ mask->mask3);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x10),
+ mask->mask4);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x14),
+ mask->mask5);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x18),
+ mask->mask6);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x1c),
+ mask->mask7);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x20),
+ mask->mask8);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x24),
+ mask->mask9);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x28),
+ mask->mask10);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x2c),
+ mask->mask11);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x30),
+ mask->mask12);
+ /* make sure dist changes happen */
+ dsb();
+
+ return 0;
+}
+
+/*
+ * mt_irq_mask_all: disable all interrupts
+ * @mask: pointer to struct mtk_irq_mask for storing the original mask value.
+ * Return 0 for success; return negative values for failure.
+ * (This is ONLY used for the idle current measurement by the factory mode.)
+ */
+int mt_irq_mask_all(struct mtk_irq_mask *mask)
+{
+ if (mask != NULL) {
+ /* for SPI */
+ mask->mask1 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x4));
+ mask->mask2 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x8));
+ mask->mask3 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0xc));
+ mask->mask4 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x10));
+ mask->mask5 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x14));
+ mask->mask6 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x18));
+ mask->mask7 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x1c));
+ mask->mask8 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x20));
+ mask->mask9 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x24));
+ mask->mask10 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x28));
+ mask->mask11 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x2c));
+ mask->mask12 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x30));
+
+ /* for SPI */
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x4),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x8),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0xC),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x10),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x14),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x18),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x1C),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x20),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x24),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x28),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x2c),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x30),
+ 0xFFFFFFFF);
+ /* make sure distributor changes happen */
+ dsb();
+
+ mask->header = IRQ_MASK_HEADER;
+ mask->footer = IRQ_MASK_FOOTER;
+
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+static uint32_t mt_irq_get_pol(uint32_t irq)
+{
+#ifdef CIRQ_WITH_POLARITY
+ uint32_t reg;
+ uint32_t base = INT_POL_CTL0;
+
+ if (irq < 32U) {
+ return 0;
+ }
+
+ reg = ((irq - 32U) / 32U);
+
+ return mmio_read_32(base + reg * 4U);
+#else
+ return 0;
+#endif
+}
+
+unsigned int mt_irq_get_sens(unsigned int irq)
+{
+ unsigned int config;
+
+ /*
+ * 2'b10 edge
+ * 2'b01 level
+ */
+ config = mmio_read_32(MT_GIC_BASE + GICD_ICFGR + (irq / 16U) * 4U);
+ config = (config >> (irq % 16U) * 2U) & 0x3;
+
+ return config;
+}
+
+static void collect_all_wakeup_events(void)
+{
+ unsigned int i;
+ uint32_t gic_irq;
+ uint32_t cirq;
+ uint32_t cirq_reg;
+ uint32_t cirq_offset;
+ uint32_t mask;
+ uint32_t pol_mask;
+ uint32_t irq_offset;
+ uint32_t irq_mask;
+
+ if ((cirq_all_events.wakeup_events == NULL) ||
+ cirq_all_events.num_of_events == 0U) {
+ return;
+ }
+
+ for (i = 0U; i < cirq_all_events.num_of_events; i++) {
+ if (cirq_all_events.wakeup_events[i] > 0U) {
+ gic_irq = cirq_all_events.wakeup_events[i];
+ cirq = gic_irq - cirq_all_events.spi_start - 32U;
+ cirq_reg = cirq / 32U;
+ cirq_offset = cirq % 32U;
+ mask = 0x1 << cirq_offset;
+ irq_offset = gic_irq % 32U;
+ irq_mask = 0x1 << irq_offset;
+ /*
+ * CIRQ default masks all
+ */
+ cirq_all_events.table[cirq_reg].mask |= mask;
+ /*
+ * CIRQ default pol is low
+ */
+ pol_mask = mt_irq_get_pol(
+ cirq_all_events.wakeup_events[i])
+ & irq_mask;
+ /*
+ * 0 means rising
+ */
+ if (pol_mask == 0U) {
+ cirq_all_events.table[cirq_reg].pol |= mask;
+ }
+ /*
+ * CIRQ could monitor edge/level trigger
+ * cirq register (0: edge, 1: level)
+ */
+ if (mt_irq_get_sens(cirq_all_events.wakeup_events[i])
+ == SENS_EDGE) {
+ cirq_all_events.table[cirq_reg].sen |= mask;
+ }
+
+ cirq_all_events.table[cirq_reg].used = 1U;
+ cirq_all_events.table[cirq_reg].reg_num = cirq_reg;
+ }
+ }
+}
+
+/*
+ * mt_cirq_set_pol: Set the polarity for the specified SYS_CIRQ number.
+ * @cirq_num: the SYS_CIRQ number to set
+ * @pol: polarity to set
+ * @return:
+ * 0: set pol success
+ * -1: cirq num is out of range
+ */
+#ifdef CIRQ_WITH_POLARITY
+static int mt_cirq_set_pol(uint32_t cirq_num, uint32_t pol)
+{
+ uint32_t base;
+ uint32_t bit = 1U << (cirq_num % 32U);
+
+ if (cirq_num >= CIRQ_IRQ_NUM) {
+ return -1;
+ }
+
+ if (pol == MT_CIRQ_POL_NEG) {
+ base = (cirq_num / 32U) * 4U + CIRQ_POL_CLR_BASE;
+ } else if (pol == MT_CIRQ_POL_POS) {
+ base = (cirq_num / 32U) * 4U + CIRQ_POL_SET_BASE;
+ } else {
+ return -1;
+ }
+
+ mmio_write_32(base, bit);
+ return 0;
+}
+#endif
+
+/*
+ * mt_cirq_mask: Mask the specified SYS_CIRQ.
+ * @cirq_num: the SYS_CIRQ number to mask
+ * @return:
+ * 0: mask success
+ * -1: cirq num is out of range
+ */
+static int mt_cirq_mask(uint32_t cirq_num)
+{
+ uint32_t bit = 1U << (cirq_num % 32U);
+
+ if (cirq_num >= CIRQ_IRQ_NUM) {
+ return -1;
+ }
+
+ mmio_write_32((cirq_num / 32U) * 4U + CIRQ_MASK_SET_BASE, bit);
+
+ return 0;
+}
+
+/*
+ * mt_cirq_unmask: Unmask the specified SYS_CIRQ.
+ * @cirq_num: the SYS_CIRQ number to unmask
+ * @return:
+ * 0: umask success
+ * -1: cirq num is out of range
+ */
+static int mt_cirq_unmask(uint32_t cirq_num)
+{
+ uint32_t bit = 1U << (cirq_num % 32U);
+
+ if (cirq_num >= CIRQ_IRQ_NUM) {
+ return -1;
+ }
+
+ mmio_write_32((cirq_num / 32U) * 4U + CIRQ_MASK_CLR_BASE, bit);
+
+ return 0;
+}
+
+uint32_t mt_irq_get_en(uint32_t irq)
+{
+ uint32_t addr, st, val;
+
+ addr = BASE_GICD_BASE + GICD_ISENABLER + (irq / 32U) * 4U;
+ st = mmio_read_32(addr);
+
+ val = (st >> (irq % 32U)) & 1U;
+
+ return val;
+}
+
+static void __cirq_fast_clone(void)
+{
+ struct cirq_reg *reg;
+ unsigned int i;
+
+ for (i = 0U; i < CIRQ_REG_NUM ; ++i) {
+ uint32_t cirq_bit;
+
+ reg = &cirq_all_events.table[i];
+
+ if (reg->used == 0U) {
+ continue;
+ }
+
+ mmio_write_32(CIRQ_SENS_CLR_BASE + (reg->reg_num * 4U),
+ reg->sen);
+
+ for (cirq_bit = 0U; cirq_bit < 32U; ++cirq_bit) {
+ uint32_t val, cirq_id;
+ uint32_t gic_id;
+#ifdef CIRQ_WITH_POLARITY
+ uint32_t gic_bit, pol;
+#endif
+ uint32_t en;
+
+ val = ((1U << cirq_bit) & reg->mask);
+
+ if (val == 0U) {
+ continue;
+ }
+
+ cirq_id = (reg->reg_num << 5U) + cirq_bit;
+ gic_id = CIRQ_TO_IRQ_NUM(cirq_id);
+#ifdef CIRQ_WITH_POLARITY
+ gic_bit = (0x1U << ((gic_id - 32U) % 32U));
+ pol = mt_irq_get_pol(gic_id) & gic_bit;
+ if (pol != 0U) {
+ mt_cirq_set_pol(cirq_id, MT_CIRQ_POL_NEG);
+ } else {
+ mt_cirq_set_pol(cirq_id, MT_CIRQ_POL_POS);
+ }
+#endif
+ en = mt_irq_get_en(gic_id);
+ if (en == 1U) {
+ mt_cirq_unmask(cirq_id);
+ } else {
+ mt_cirq_mask(cirq_id);
+ }
+ }
+ }
+}
+
+static void cirq_fast_clone(void)
+{
+ if (already_cloned == 0U) {
+ collect_all_wakeup_events();
+ already_cloned = 1U;
+ }
+ __cirq_fast_clone();
+}
+
+void set_wakeup_sources(uint32_t *list, uint32_t num_of_events)
+{
+ cirq_all_events.num_of_events = num_of_events;
+ cirq_all_events.wakeup_events = list;
+}
+/*
+ * mt_cirq_clone_gic: Copy the setting from GIC to SYS_CIRQ
+ */
+void mt_cirq_clone_gic(void)
+{
+ cirq_fast_clone();
+}
+
+uint32_t mt_irq_get_pending_vec(uint32_t start_irq)
+{
+ uint32_t base = 0U;
+ uint32_t pending_vec = 0U;
+ uint32_t reg = start_irq / 32U;
+ uint32_t LSB_num, MSB_num;
+ uint32_t LSB_vec, MSB_vec;
+
+ base = BASE_GICD_BASE;
+
+ /* if start_irq is not aligned 32, do some assembling */
+ MSB_num = start_irq % 32U;
+ if (MSB_num != 0U) {
+ LSB_num = 32U - MSB_num;
+ LSB_vec = mmio_read_32(base + GICD_ISPENDR +
+ reg * 4U) >> MSB_num;
+ MSB_vec = mmio_read_32(base + GICD_ISPENDR +
+ (reg + 1U) * 4U) << LSB_num;
+ pending_vec = MSB_vec | LSB_vec;
+ } else {
+ pending_vec = mmio_read_32(base + GICD_ISPENDR + reg * 4);
+ }
+
+ return pending_vec;
+}
+
+static int mt_cirq_get_mask_vec(unsigned int i)
+{
+ return mmio_read_32((i * 4U) + CIRQ_MASK_BASE);
+}
+
+/*
+ * mt_cirq_ack_all: Ack all the interrupt on SYS_CIRQ
+ */
+void mt_cirq_ack_all(void)
+{
+ uint32_t ack_vec, pend_vec, mask_vec;
+ unsigned int i;
+
+ for (i = 0; i < CIRQ_CTRL_REG_NUM; i++) {
+ /*
+ * if a irq is pending & not masked, don't ack it
+ * , since cirq start irq might not be 32 aligned with gic,
+ * need an exotic API to get proper vector of pending irq
+ */
+ pend_vec = mt_irq_get_pending_vec(CIRQ_SPI_START
+ + (i + 1U) * 32U);
+ mask_vec = mt_cirq_get_mask_vec(i);
+ /* those should be acked are: "not (pending & not masked)",
+ */
+ ack_vec = (~pend_vec) | mask_vec;
+ mmio_write_32(CIRQ_ACK_BASE + (i * 4U), ack_vec);
+ }
+
+ /*
+ * make sure all cirq setting take effect
+ * before doing other things
+ */
+ dsb();
+}
+/*
+ * mt_cirq_enable: Enable SYS_CIRQ
+ */
+void mt_cirq_enable(void)
+{
+ uint32_t st;
+
+ /* level only */
+ mt_cirq_ack_all();
+
+ st = mmio_read_32(CIRQ_CON);
+ /*
+ * CIRQ could monitor edge/level trigger
+ */
+ st |= (CIRQ_CON_EN << CIRQ_CON_EN_BITS);
+
+ mmio_write_32(CIRQ_CON, (st & CIRQ_CON_BITS_MASK));
+}
+
+/*
+ * mt_cirq_disable: Disable SYS_CIRQ
+ */
+void mt_cirq_disable(void)
+{
+ uint32_t st;
+
+ st = mmio_read_32(CIRQ_CON);
+ st &= ~(CIRQ_CON_EN << CIRQ_CON_EN_BITS);
+ mmio_write_32(CIRQ_CON, (st & CIRQ_CON_BITS_MASK));
+}
+
+void mt_irq_unmask_for_sleep_ex(uint32_t irq)
+{
+ uint32_t mask;
+
+ mask = 1U << (irq % 32U);
+
+ mmio_write_32(BASE_GICD_BASE + GICD_ISENABLER +
+ ((irq / 32U) * 4U), mask);
+}
+
+void mt_cirq_mask_all(void)
+{
+ unsigned int i;
+
+ for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) {
+ mmio_write_32(CIRQ_MASK_SET_BASE + (i * 4U), 0xFFFFFFFF);
+ }
+ dsb();
+}
+
+static void cirq_fast_sw_flush(void)
+{
+ struct cirq_reg *reg;
+ unsigned int i;
+
+ for (i = 0U; i < CIRQ_REG_NUM ; ++i) {
+ uint32_t cirq_bit;
+
+ reg = &cirq_all_events.table[i];
+
+ if (reg->used == 0U) {
+ continue;
+ }
+
+ reg->pending = mmio_read_32(CIRQ_STA_BASE +
+ (reg->reg_num << 2U));
+ reg->pending &= reg->mask;
+
+ for (cirq_bit = 0U; cirq_bit < 32U; ++cirq_bit) {
+ uint32_t val, cirq_id;
+
+ val = (1U << cirq_bit) & reg->pending;
+ if (val == 0U) {
+ continue;
+ }
+
+ cirq_id = (reg->reg_num << 5U) + cirq_bit;
+ mt_irq_set_pending(CIRQ_TO_IRQ_NUM(cirq_id));
+ if (CIRQ_TO_IRQ_NUM(cirq_id) == MD_WDT_IRQ_BIT_ID) {
+ INFO("Set MD_WDT_IRQ pending in %s\n",
+ __func__);
+ }
+ }
+ }
+}
+
+/*
+ * mt_cirq_disable: Flush interrupt from SYS_CIRQ to GIC
+ */
+void mt_cirq_flush(void)
+{
+ cirq_fast_sw_flush();
+ mt_cirq_mask_all();
+ mt_cirq_ack_all();
+}
+
+void mt_cirq_sw_reset(void)
+{
+#ifdef CIRQ_NEED_SW_RESET
+ uint32_t st;
+
+ st = mmio_read_32(CIRQ_CON);
+ st |= (CIRQ_SW_RESET << CIRQ_CON_SW_RST_BITS);
+ mmio_write_32(CIRQ_CON, st);
+#endif
+}
diff --git a/plat/mediatek/mt8192/plat_mt_gic.c b/plat/mediatek/mt8192/plat_mt_gic.c
new file mode 100644
index 000000000..ae8d697a5
--- /dev/null
+++ b/plat/mediatek/mt8192/plat_mt_gic.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "../drivers/arm/gic/v3/gicv3_private.h"
+#include <bl31/interrupt_mgmt.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+
+#include <mt_gic_v3.h>
+#include <mtk_plat_common.h>
+#include <plat/common/platform.h>
+#include <plat_private.h>
+#include <platform_def.h>
+
+#define SGI_MASK 0xffff
+
+uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+static uint32_t rdist_has_saved[PLATFORM_CORE_COUNT];
+
+/* we save and restore the GICv3 context on system suspend */
+gicv3_dist_ctx_t dist_ctx;
+
+static unsigned int mt_mpidr_to_core_pos(u_register_t mpidr)
+{
+ return plat_core_pos_by_mpidr(mpidr);
+}
+
+gicv3_driver_data_t mt_gicv3_data = {
+ .gicd_base = MT_GIC_BASE,
+ .gicr_base = MT_GIC_RDIST_BASE,
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = rdistif_base_addrs,
+ .mpidr_to_core_pos = mt_mpidr_to_core_pos,
+};
+
+struct gic_chip_data {
+ /* All cores share the same configuration */
+ unsigned int saved_group;
+ unsigned int saved_enable;
+ unsigned int saved_conf0;
+ unsigned int saved_conf1;
+ unsigned int saved_grpmod;
+ /* Per-core sgi */
+ unsigned int saved_sgi[PLATFORM_CORE_COUNT];
+};
+
+static struct gic_chip_data gic_data;
+
+void mt_gic_driver_init(void)
+{
+ gicv3_driver_init(&mt_gicv3_data);
+}
+
+void mt_gic_set_pending(uint32_t irq)
+{
+ gicv3_set_interrupt_pending(irq, plat_my_core_pos());
+}
+
+void mt_gic_distif_save(void)
+{
+ gicv3_distif_save(&dist_ctx);
+}
+
+void mt_gic_distif_restore(void)
+{
+ gicv3_distif_init_restore(&dist_ctx);
+}
+
+void mt_gic_rdistif_init(void)
+{
+ unsigned int proc_num;
+ unsigned int index;
+ uintptr_t gicr_base;
+
+ proc_num = plat_my_core_pos();
+ gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+
+ /* set all SGI/PPI as non-secure GROUP1 by default */
+ mmio_write_32(gicr_base + GICR_IGROUPR0, ~0U);
+ mmio_write_32(gicr_base + GICR_IGRPMODR0, 0x0);
+
+ /* setup the default PPI/SGI priorities */
+ for (index = 0; index < TOTAL_PCPU_INTR_NUM; index += 4U)
+ gicr_write_ipriorityr(gicr_base, index,
+ GICD_IPRIORITYR_DEF_VAL);
+}
+
+void mt_gic_rdistif_save(void)
+{
+ unsigned int proc_num;
+ uintptr_t gicr_base;
+
+ proc_num = plat_my_core_pos();
+ gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+
+ gic_data.saved_group = mmio_read_32(gicr_base + GICR_IGROUPR0);
+ gic_data.saved_enable = mmio_read_32(gicr_base + GICR_ISENABLER0);
+ gic_data.saved_conf0 = mmio_read_32(gicr_base + GICR_ICFGR0);
+ gic_data.saved_conf1 = mmio_read_32(gicr_base + GICR_ICFGR1);
+ gic_data.saved_grpmod = mmio_read_32(gicr_base + GICR_IGRPMODR0);
+
+ rdist_has_saved[proc_num] = 1;
+}
+
+void mt_gic_rdistif_restore(void)
+{
+ unsigned int proc_num;
+ uintptr_t gicr_base;
+
+ proc_num = plat_my_core_pos();
+ if (rdist_has_saved[proc_num] == 1) {
+ gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+ mmio_write_32(gicr_base + GICR_IGROUPR0, gic_data.saved_group);
+ mmio_write_32(gicr_base + GICR_ISENABLER0,
+ gic_data.saved_enable);
+ mmio_write_32(gicr_base + GICR_ICFGR0, gic_data.saved_conf0);
+ mmio_write_32(gicr_base + GICR_ICFGR1, gic_data.saved_conf1);
+ mmio_write_32(gicr_base + GICR_IGRPMODR0,
+ gic_data.saved_grpmod);
+ }
+}
+
+void mt_gic_rdistif_restore_all(void)
+{
+ unsigned int proc_num;
+ uintptr_t gicr_base;
+
+ for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) {
+ gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+ mmio_write_32(gicr_base + GICR_IGROUPR0, gic_data.saved_group);
+ mmio_write_32(gicr_base + GICR_ISENABLER0,
+ gic_data.saved_enable);
+ mmio_write_32(gicr_base + GICR_ICFGR0, gic_data.saved_conf0);
+ mmio_write_32(gicr_base + GICR_ICFGR1, gic_data.saved_conf1);
+ mmio_write_32(gicr_base + GICR_IGRPMODR0,
+ gic_data.saved_grpmod);
+ }
+}
+
+void gic_sgi_save_all(void)
+{
+ unsigned int proc_num;
+ uintptr_t gicr_base;
+
+ for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) {
+ gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+ gic_data.saved_sgi[proc_num] =
+ mmio_read_32(gicr_base + GICR_ISPENDR0) & SGI_MASK;
+ }
+}
+
+void gic_sgi_restore_all(void)
+{
+ unsigned int proc_num;
+ uintptr_t gicr_base;
+
+ for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) {
+ gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+ mmio_write_32(gicr_base + GICR_ICPENDR0, SGI_MASK);
+ mmio_write_32(gicr_base + GICR_ISPENDR0,
+ gic_data.saved_sgi[proc_num] & SGI_MASK);
+ }
+}
+
+void mt_gic_init(void)
+{
+ gicv3_distif_init();
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+uint32_t mt_irq_get_pending(uint32_t irq)
+{
+ uint32_t val;
+
+ val = mmio_read_32(BASE_GICD_BASE + GICD_ISPENDR +
+ irq / 32 * 4);
+ val = (val >> (irq % 32)) & 1U;
+ return val;
+}
+
+
+void mt_irq_set_pending(uint32_t irq)
+{
+ uint32_t bit = 1U << (irq % 32);
+
+ mmio_write_32(BASE_GICD_BASE + GICD_ISPENDR +
+ irq / 32 * 4, bit);
+}
diff --git a/plat/mediatek/mt8192/plat_pm.c b/plat/mediatek/mt8192/plat_pm.c
new file mode 100644
index 000000000..6a74c02dd
--- /dev/null
+++ b/plat/mediatek/mt8192/plat_pm.c
@@ -0,0 +1,397 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* common headers */
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/gpio.h>
+#include <lib/psci/psci.h>
+
+/* platform specific headers */
+#include <mt_gic_v3.h>
+#include <mtk_ptp3_common.h>
+#include <mtspmc.h>
+#include <plat/common/platform.h>
+#include <plat_mtk_lpm.h>
+#include <plat_params.h>
+#include <plat_pm.h>
+#include <pmic.h>
+#include <rtc.h>
+
+/*
+ * Cluster state request:
+ * [0] : The CPU requires cluster power down
+ * [1] : The CPU requires cluster power on
+ */
+#define coordinate_cluster(onoff) write_clusterpwrdn_el1(onoff)
+#define coordinate_cluster_pwron() coordinate_cluster(1)
+#define coordinate_cluster_pwroff() coordinate_cluster(0)
+
+/* platform secure entry point */
+static uintptr_t secure_entrypoint;
+/* per-CPU power state */
+static unsigned int plat_power_state[PLATFORM_CORE_COUNT];
+
+/* platform CPU power domain - ops */
+static const struct mt_lpm_tz *plat_mt_pm;
+
+#define plat_mt_pm_invoke(_name, _cpu, _state) ({ \
+ int ret = -1; \
+ if (plat_mt_pm != NULL && plat_mt_pm->_name != NULL) { \
+ ret = plat_mt_pm->_name(_cpu, _state); \
+ } \
+ ret; })
+
+#define plat_mt_pm_invoke_no_check(_name, _cpu, _state) ({ \
+ if (plat_mt_pm != NULL && plat_mt_pm->_name != NULL) { \
+ (void) plat_mt_pm->_name(_cpu, _state); \
+ } \
+ })
+
+/*
+ * Common MTK_platform operations to power on/off a
+ * CPU in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
+ */
+
+static void plat_cpu_pwrdwn_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+
+ plat_mt_pm_invoke_no_check(pwr_cpu_dwn, cpu, state);
+
+ if ((psci_get_pstate_pwrlvl(req_pstate) >= MTK_AFFLVL_CLUSTER) ||
+ (req_pstate == 0U)) { /* hotplug off */
+ coordinate_cluster_pwroff();
+ }
+
+ /* Prevent interrupts from spuriously waking up this CPU */
+ mt_gic_rdistif_save();
+ gicv3_cpuif_disable(cpu);
+ gicv3_rdistif_off(cpu);
+ /* PTP3 config */
+ ptp3_deinit(cpu);
+}
+
+static void plat_cpu_pwron_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+
+ plat_mt_pm_invoke_no_check(pwr_cpu_on, cpu, state);
+
+ coordinate_cluster_pwron();
+
+ /* Enable the GIC CPU interface */
+ gicv3_rdistif_on(cpu);
+ gicv3_cpuif_enable(cpu);
+ mt_gic_rdistif_init();
+
+ /*
+ * If mcusys does power down before then restore
+ * all CPUs' GIC Redistributors
+ */
+ if (IS_MCUSYS_OFF_STATE(state)) {
+ mt_gic_rdistif_restore_all();
+ } else {
+ mt_gic_rdistif_restore();
+ }
+
+ /* PTP3 config */
+ ptp3_init(cpu);
+}
+
+/*
+ * Common MTK_platform operations to power on/off a
+ * cluster in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
+ */
+
+static void plat_cluster_pwrdwn_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+
+ if (plat_mt_pm_invoke(pwr_cluster_dwn, cpu, state) != 0) {
+ coordinate_cluster_pwron();
+
+ /* TODO: return on fail.
+ * Add a 'return' here before adding any code following
+ * the if-block.
+ */
+ }
+}
+
+static void plat_cluster_pwron_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+
+ if (plat_mt_pm_invoke(pwr_cluster_on, cpu, state) != 0) {
+ /* TODO: return on fail.
+ * Add a 'return' here before adding any code following
+ * the if-block.
+ */
+ }
+}
+
+/*
+ * Common MTK_platform operations to power on/off a
+ * mcusys in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
+ */
+
+static void plat_mcusys_pwrdwn_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+
+ if (plat_mt_pm_invoke(pwr_mcusys_dwn, cpu, state) != 0) {
+ return; /* return on fail */
+ }
+
+ mt_gic_distif_save();
+ gic_sgi_save_all();
+}
+
+static void plat_mcusys_pwron_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+
+ if (plat_mt_pm_invoke(pwr_mcusys_on, cpu, state) != 0) {
+ return; /* return on fail */
+ }
+
+ mt_gic_init();
+ mt_gic_distif_restore();
+ gic_sgi_restore_all();
+
+ plat_mt_pm_invoke_no_check(pwr_mcusys_on_finished, cpu, state);
+}
+
+/*
+ * plat_psci_ops implementation
+ */
+
+static void plat_cpu_standby(plat_local_state_t cpu_state)
+{
+ uint64_t scr;
+
+ scr = read_scr_el3();
+ write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
+
+ isb();
+ dsb();
+ wfi();
+
+ write_scr_el3(scr);
+}
+
+static int plat_power_domain_on(u_register_t mpidr)
+{
+ unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+ unsigned int cluster = 0U;
+
+ if (cpu >= PLATFORM_CORE_COUNT) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ if (!spm_get_cluster_powerstate(cluster)) {
+ spm_poweron_cluster(cluster);
+ }
+
+ /* init CPU reset arch as AARCH64 */
+ mcucfg_init_archstate(cluster, cpu, true);
+ mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
+ spm_poweron_cpu(cluster, cpu);
+
+ return PSCI_E_SUCCESS;
+}
+
+static void plat_power_domain_on_finish(const psci_power_state_t *state)
+{
+ unsigned long mpidr = read_mpidr_el1();
+ unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+
+ assert(cpu < PLATFORM_CORE_COUNT);
+
+ /* Allow IRQs to wakeup this core in IDLE flow */
+ mcucfg_enable_gic_wakeup(0U, cpu);
+
+ if (IS_CLUSTER_OFF_STATE(state)) {
+ plat_cluster_pwron_common(cpu, state, 0U);
+ }
+
+ plat_cpu_pwron_common(cpu, state, 0U);
+}
+
+static void plat_power_domain_off(const psci_power_state_t *state)
+{
+ unsigned long mpidr = read_mpidr_el1();
+ unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+
+ assert(cpu < PLATFORM_CORE_COUNT);
+
+ plat_cpu_pwrdwn_common(cpu, state, 0U);
+ spm_poweroff_cpu(0U, cpu);
+
+ /* prevent unintended IRQs from waking up the hot-unplugged core */
+ mcucfg_disable_gic_wakeup(0U, cpu);
+
+ if (IS_CLUSTER_OFF_STATE(state)) {
+ plat_cluster_pwrdwn_common(cpu, state, 0U);
+ }
+}
+
+static void plat_power_domain_suspend(const psci_power_state_t *state)
+{
+ unsigned int cpu = plat_my_core_pos();
+
+ assert(cpu < PLATFORM_CORE_COUNT);
+
+ plat_mt_pm_invoke_no_check(pwr_prompt, cpu, state);
+
+ /* Perform the common CPU specific operations */
+ plat_cpu_pwrdwn_common(cpu, state, plat_power_state[cpu]);
+
+ if (IS_CLUSTER_OFF_STATE(state)) {
+ /* Perform the common cluster specific operations */
+ plat_cluster_pwrdwn_common(cpu, state, plat_power_state[cpu]);
+ }
+
+ if (IS_MCUSYS_OFF_STATE(state)) {
+ /* Perform the common mcusys specific operations */
+ plat_mcusys_pwrdwn_common(cpu, state, plat_power_state[cpu]);
+ }
+}
+
+static void plat_power_domain_suspend_finish(const psci_power_state_t *state)
+{
+ unsigned int cpu = plat_my_core_pos();
+
+ assert(cpu < PLATFORM_CORE_COUNT);
+
+ if (IS_MCUSYS_OFF_STATE(state)) {
+ /* Perform the common mcusys specific operations */
+ plat_mcusys_pwron_common(cpu, state, plat_power_state[cpu]);
+ }
+
+ if (IS_CLUSTER_OFF_STATE(state)) {
+ /* Perform the common cluster specific operations */
+ plat_cluster_pwron_common(cpu, state, plat_power_state[cpu]);
+ }
+
+ /* Perform the common CPU specific operations */
+ plat_cpu_pwron_common(cpu, state, plat_power_state[cpu]);
+
+ plat_mt_pm_invoke_no_check(pwr_reflect, cpu, state);
+}
+
+static int plat_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ unsigned int pstate = psci_get_pstate_type(power_state);
+ unsigned int aff_lvl = psci_get_pstate_pwrlvl(power_state);
+ unsigned int cpu = plat_my_core_pos();
+
+ if (pstate == PSTATE_TYPE_STANDBY) {
+ req_state->pwr_domain_state[0] = PLAT_MAX_RET_STATE;
+ } else {
+ unsigned int i;
+ unsigned int pstate_id = psci_get_pstate_id(power_state);
+ plat_local_state_t s = MTK_LOCAL_STATE_OFF;
+
+ /* Use pstate_id to be power domain state */
+ if (pstate_id > s) {
+ s = (plat_local_state_t)pstate_id;
+ }
+
+ for (i = 0U; i <= aff_lvl; i++) {
+ req_state->pwr_domain_state[i] = s;
+ }
+ }
+
+ plat_power_state[cpu] = power_state;
+ return PSCI_E_SUCCESS;
+}
+
+static void plat_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ unsigned int lv;
+ unsigned int cpu = plat_my_core_pos();
+
+ for (lv = PSCI_CPU_PWR_LVL; lv <= PLAT_MAX_PWR_LVL; lv++) {
+ req_state->pwr_domain_state[lv] = PLAT_MAX_OFF_STATE;
+ }
+
+ plat_power_state[cpu] =
+ psci_make_powerstate(
+ MT_PLAT_PWR_STATE_SYSTEM_SUSPEND,
+ PSTATE_TYPE_POWERDOWN, PLAT_MAX_PWR_LVL);
+
+ flush_dcache_range((uintptr_t)
+ &plat_power_state[cpu],
+ sizeof(plat_power_state[cpu]));
+}
+
+static void __dead2 plat_mtk_system_off(void)
+{
+ INFO("MTK System Off\n");
+
+ rtc_power_off_sequence();
+ pmic_power_off();
+
+ wfi();
+ ERROR("MTK System Off: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 plat_mtk_system_reset(void)
+{
+ struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset();
+
+ INFO("MTK System Reset\n");
+
+ gpio_set_value(gpio_reset->index, gpio_reset->polarity);
+
+ wfi();
+ ERROR("MTK System Reset: operation not handled.\n");
+ panic();
+}
+
+static const plat_psci_ops_t plat_psci_ops = {
+ .system_reset = plat_mtk_system_reset,
+ .cpu_standby = plat_cpu_standby,
+ .pwr_domain_on = plat_power_domain_on,
+ .pwr_domain_on_finish = plat_power_domain_on_finish,
+ .pwr_domain_off = plat_power_domain_off,
+ .pwr_domain_suspend = plat_power_domain_suspend,
+ .pwr_domain_suspend_finish = plat_power_domain_suspend_finish,
+ .system_off = plat_mtk_system_off,
+ .validate_power_state = plat_validate_power_state,
+ .get_sys_suspend_power_state = plat_get_sys_suspend_power_state
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ *psci_ops = &plat_psci_ops;
+ secure_entrypoint = sec_entrypoint;
+
+ /*
+ * init the warm reset config for boot CPU
+ * reset arch as AARCH64
+ * reset addr as function bl31_warm_entrypoint()
+ */
+ mcucfg_init_archstate(0U, 0U, true);
+ mcucfg_set_bootaddr(0U, 0U, secure_entrypoint);
+
+ spmc_init();
+ plat_mt_pm = mt_plat_cpu_pm_init();
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8192/plat_sip_calls.c b/plat/mediatek/mt8192/plat_sip_calls.c
new file mode 100644
index 000000000..f97684f77
--- /dev/null
+++ b/plat/mediatek/mt8192/plat_sip_calls.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+
+uintptr_t mediatek_plat_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+
+ switch (smc_fid) {
+ default:
+ ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+ break;
+ }
+
+ SMC_RET1(handle, SMC_UNK);
+}
diff --git a/plat/mediatek/mt8192/plat_topology.c b/plat/mediatek/mt8192/plat_topology.c
new file mode 100644
index 000000000..8c1231a6e
--- /dev/null
+++ b/plat/mediatek/mt8192/plat_topology.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Project Includes */
+#include <arch.h>
+#include <arch_helpers.h>
+#include <lib/psci/psci.h>
+
+/* Platform Includes */
+#include <plat_helpers.h>
+#include <platform_def.h>
+
+const unsigned char mtk_power_domain_tree_desc[] = {
+ /* Number of root nodes */
+ PLATFORM_SYSTEM_COUNT,
+ /* Number of children for the root node */
+ PLATFORM_MCUSYS_COUNT,
+ /* Number of children for the mcusys node */
+ PLATFORM_CLUSTER_COUNT,
+ /* Number of children for the first cluster node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+};
+
+/*******************************************************************************
+ * This function returns the MT8192 default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return mtk_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ if (read_mpidr() & MPIDR_MT_MASK) {
+ /* ARMv8.2 arch */
+ if (mpidr & (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) {
+ return -1;
+ }
+ return plat_mediatek_calc_core_pos(mpidr);
+ }
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+
+ if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) {
+ return -1;
+ }
+
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
+ return -1;
+ }
+
+ /*
+ * Validate cpu_id by checking whether it represents a CPU in
+ * one of the two clusters present on the platform.
+ */
+ if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
+ return -1;
+ }
+
+ return (cpu_id + (cluster_id * 8));
+}
diff --git a/plat/mediatek/mt8192/platform.mk b/plat/mediatek/mt8192/platform.mk
new file mode 100644
index 000000000..a5e7ee26a
--- /dev/null
+++ b/plat/mediatek/mt8192/platform.mk
@@ -0,0 +1,83 @@
+#
+# Copyright (c) 2020, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+MTK_PLAT := plat/mediatek
+MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT}
+
+PLAT_INCLUDES := -I${MTK_PLAT}/common/ \
+ -I${MTK_PLAT_SOC}/include/ \
+ -I${MTK_PLAT_SOC}/drivers/ \
+ -I${MTK_PLAT_SOC}/drivers/dcm \
+ -I${MTK_PLAT_SOC}/drivers/emi_mpu/ \
+ -I${MTK_PLAT_SOC}/drivers/gpio/ \
+ -I${MTK_PLAT_SOC}/drivers/mcdi/ \
+ -I${MTK_PLAT_SOC}/drivers/pmic/ \
+ -I${MTK_PLAT_SOC}/drivers/ptp3/ \
+ -I${MTK_PLAT_SOC}/drivers/rtc/ \
+ -I${MTK_PLAT_SOC}/drivers/spmc/ \
+ -I${MTK_PLAT_SOC}/drivers/timer/ \
+ -I${MTK_PLAT_SOC}/drivers/uart/
+
+GICV3_SUPPORT_GIC600 := 1
+include drivers/arm/gic/v3/gicv3.mk
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_BL_COMMON_SOURCES := ${GICV3_SOURCES} \
+ ${XLAT_TABLES_LIB_SRCS} \
+ plat/common/aarch64/crash_console_helpers.S \
+ plat/common/plat_psci_common.c
+
+BL31_SOURCES += common/desc_image_load.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/ti/uart/aarch64/16550_console.S \
+ drivers/gpio/gpio.c \
+ lib/bl_aux_params/bl_aux_params.c \
+ lib/cpus/aarch64/cortex_a55.S \
+ lib/cpus/aarch64/cortex_a76.S \
+ plat/common/plat_gicv3.c \
+ ${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init_v2.c \
+ ${MTK_PLAT}/common/drivers/rtc/rtc_common.c \
+ ${MTK_PLAT}/common/drivers/uart/uart.c \
+ ${MTK_PLAT}/common/mtk_plat_common.c \
+ ${MTK_PLAT}/common/mtk_sip_svc.c \
+ ${MTK_PLAT}/common/params_setup.c \
+ ${MTK_PLAT_SOC}/aarch64/platform_common.c \
+ ${MTK_PLAT_SOC}/aarch64/plat_helpers.S \
+ ${MTK_PLAT_SOC}/bl31_plat_setup.c \
+ ${MTK_PLAT_SOC}/drivers/pmic/pmic.c \
+ ${MTK_PLAT_SOC}/drivers/rtc/rtc.c \
+ ${MTK_PLAT_SOC}/plat_pm.c \
+ ${MTK_PLAT_SOC}/plat_topology.c \
+ ${MTK_PLAT_SOC}/plat_mt_gic.c \
+ ${MTK_PLAT_SOC}/plat_mt_cirq.c \
+ ${MTK_PLAT_SOC}/plat_sip_calls.c \
+ ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c \
+ ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c \
+ ${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c \
+ ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \
+ ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm.c \
+ ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm_cpc.c \
+ ${MTK_PLAT_SOC}/drivers/mcdi/mt_mcdi.c \
+ ${MTK_PLAT_SOC}/drivers/ptp3/mtk_ptp3_main.c \
+ ${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c \
+ ${MTK_PLAT_SOC}/drivers/timer/mt_timer.c
+
+# Configs for A76 and A55
+HW_ASSISTED_COHERENCY := 1
+USE_COHERENT_MEM := 0
+CTX_INCLUDE_AARCH32_REGS := 0
+
+# indicate the reset vector address can be programmed
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+COLD_BOOT_SINGLE_CPU := 1
+
+MACH_MT8192 := 1
+$(eval $(call add_define,MACH_MT8192))
+
+include lib/coreboot/coreboot.mk
+