diff options
Diffstat (limited to 'plat')
228 files changed, 9330 insertions, 2483 deletions
diff --git a/plat/allwinner/common/allwinner-common.mk b/plat/allwinner/common/allwinner-common.mk index 997aaa6f78..da83b5e17f 100644 --- a/plat/allwinner/common/allwinner-common.mk +++ b/plat/allwinner/common/allwinner-common.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -20,8 +20,6 @@ PLAT_BL_COMMON_SOURCES := drivers/ti/uart/${ARCH}/16550_console.S \ ${AW_PLAT}/common/sunxi_common.c BL31_SOURCES += drivers/allwinner/axp/common.c \ - drivers/allwinner/sunxi_msgbox.c \ - drivers/arm/css/scpi/css_scpi.c \ ${GICV2_SOURCES} \ drivers/delay_timer/delay_timer.c \ drivers/delay_timer/generic_delay_timer.c \ @@ -29,12 +27,40 @@ BL31_SOURCES += drivers/allwinner/axp/common.c \ plat/common/plat_gicv2.c \ plat/common/plat_psci_common.c \ ${AW_PLAT}/common/sunxi_bl31_setup.c \ - ${AW_PLAT}/common/sunxi_cpu_ops.c \ ${AW_PLAT}/common/sunxi_pm.c \ ${AW_PLAT}/${PLAT}/sunxi_power.c \ ${AW_PLAT}/common/sunxi_security.c \ ${AW_PLAT}/common/sunxi_topology.c +# By default, attempt to use SCPI to the ARISC management processor. If SCPI +# is not enabled or SCP firmware is not loaded, fall back to a simpler native +# implementation that does not support CPU or system suspend. +# +# If SCP firmware will always be present (or absent), the unused implementation +# can be compiled out. +SUNXI_PSCI_USE_NATIVE ?= 1 +SUNXI_PSCI_USE_SCPI ?= 1 + +$(eval $(call assert_boolean,SUNXI_PSCI_USE_NATIVE)) +$(eval $(call assert_boolean,SUNXI_PSCI_USE_SCPI)) +$(eval $(call add_define,SUNXI_PSCI_USE_NATIVE)) +$(eval $(call add_define,SUNXI_PSCI_USE_SCPI)) + +ifeq (${SUNXI_PSCI_USE_NATIVE}${SUNXI_PSCI_USE_SCPI},00) +$(error "At least one of SCPI or native PSCI ops must be enabled") +endif + +ifeq (${SUNXI_PSCI_USE_NATIVE},1) +BL31_SOURCES += ${AW_PLAT}/common/sunxi_cpu_ops.c \ + ${AW_PLAT}/common/sunxi_native_pm.c +endif + +ifeq (${SUNXI_PSCI_USE_SCPI},1) +BL31_SOURCES += drivers/allwinner/sunxi_msgbox.c \ + drivers/arm/css/scpi/css_scpi.c \ + ${AW_PLAT}/common/sunxi_scpi_pm.c +endif + # The bootloader is guaranteed to only run on CPU 0 by the boot ROM. COLD_BOOT_SINGLE_CPU := 1 @@ -48,6 +74,10 @@ ENABLE_SVE_FOR_NS := 0 ERRATA_A53_835769 := 1 ERRATA_A53_843419 := 1 ERRATA_A53_855873 := 1 +ERRATA_A53_1530924 := 1 + +# The traditional U-Boot load address is 160MB into DRAM. +PRELOADED_BL33_BASE ?= 0x4a000000 # The reset vector can be changed for each CPU. PROGRAMMABLE_RESET_ADDRESS := 1 diff --git a/plat/allwinner/common/include/platform_def.h b/plat/allwinner/common/include/platform_def.h index 975cc48d52..93720fff29 100644 --- a/plat/allwinner/common/include/platform_def.h +++ b/plat/allwinner/common/include/platform_def.h @@ -25,9 +25,6 @@ #define BL31_NOBITS_BASE (SUNXI_SRAM_A1_BASE + 0x1000) #define BL31_NOBITS_LIMIT (SUNXI_SRAM_A1_BASE + SUNXI_SRAM_A1_SIZE) -/* The traditional U-Boot load address is 160MB into DRAM, so at 0x4a000000 */ -#define PLAT_SUNXI_NS_IMAGE_OFFSET (SUNXI_DRAM_BASE + (160U << 20)) - /* How much memory to reserve as secure for BL32, if configured */ #define SUNXI_DRAM_SEC_SIZE (32U << 20) diff --git a/plat/allwinner/common/include/sunxi_private.h b/plat/allwinner/common/include/sunxi_private.h index dcf3dc965c..b68d23f3de 100644 --- a/plat/allwinner/common/include/sunxi_private.h +++ b/plat/allwinner/common/include/sunxi_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,13 +7,32 @@ #ifndef SUNXI_PRIVATE_H #define SUNXI_PRIVATE_H +#include <lib/psci/psci.h> + void sunxi_configure_mmu_el3(int flags); void sunxi_cpu_on(u_register_t mpidr); -void sunxi_cpu_off(u_register_t mpidr); -void sunxi_disable_secondary_cpus(u_register_t primary_mpidr); +void sunxi_cpu_power_off_others(void); +void sunxi_cpu_power_off_self(void); void sunxi_power_down(void); +#if SUNXI_PSCI_USE_NATIVE +void sunxi_set_native_psci_ops(const plat_psci_ops_t **psci_ops); +#else +static inline void sunxi_set_native_psci_ops(const plat_psci_ops_t **psci_ops) +{ +} +#endif +#if SUNXI_PSCI_USE_SCPI +int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops); +#else +static inline int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops) +{ + return -1; +} +#endif +int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint); + int sunxi_pmic_setup(uint16_t socid, const void *fdt); void sunxi_security_setup(void); diff --git a/plat/allwinner/common/sunxi_bl31_setup.c b/plat/allwinner/common/sunxi_bl31_setup.c index e836a345bf..b619b18eda 100644 --- a/plat/allwinner/common/sunxi_bl31_setup.c +++ b/plat/allwinner/common/sunxi_bl31_setup.c @@ -57,7 +57,7 @@ static void *sunxi_find_dtb(void) for (i = 0; i < 2048 / sizeof(uint64_t); i++) { uint32_t *dtb_base; - if (u_boot_base[i] != PLAT_SUNXI_NS_IMAGE_OFFSET) + if (u_boot_base[i] != PRELOADED_BL33_BASE) continue; /* Does the suspected U-Boot size look anyhow reasonable? */ @@ -96,13 +96,10 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, * Tell BL31 where the non-trusted software image * is located and the entry state information */ - bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); + bl33_image_ep_info.pc = PRELOADED_BL33_BASE; bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); - - /* Turn off all secondary CPUs */ - sunxi_disable_secondary_cpus(read_mpidr()); } void bl31_plat_arch_setup(void) diff --git a/plat/allwinner/common/sunxi_common.c b/plat/allwinner/common/sunxi_common.c index 0ca18adc33..5b536a0432 100644 --- a/plat/allwinner/common/sunxi_common.c +++ b/plat/allwinner/common/sunxi_common.c @@ -27,7 +27,7 @@ static const mmap_region_t sunxi_mmap[PLATFORM_MMAP_REGIONS + 1] = { MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER), MAP_REGION(SUNXI_DRAM_BASE, SUNXI_DRAM_VIRT_BASE, SUNXI_DRAM_SEC_SIZE, MT_RW_DATA | MT_SECURE), - MAP_REGION(PLAT_SUNXI_NS_IMAGE_OFFSET, + MAP_REGION(PRELOADED_BL33_BASE, SUNXI_DRAM_VIRT_BASE + SUNXI_DRAM_SEC_SIZE, SUNXI_DRAM_MAP_SIZE, MT_RO_DATA | MT_NS), @@ -39,15 +39,6 @@ unsigned int plat_get_syscnt_freq2(void) return SUNXI_OSC24M_CLK_IN_HZ; } -uintptr_t plat_get_ns_image_entrypoint(void) -{ -#ifdef PRELOADED_BL33_BASE - return PRELOADED_BL33_BASE; -#else - return PLAT_SUNXI_NS_IMAGE_OFFSET; -#endif -} - void sunxi_configure_mmu_el3(int flags) { mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, @@ -125,11 +116,9 @@ int sunxi_init_platform_r_twi(uint16_t socid, bool use_rsb) device_bit = BIT(6); break; case SUNXI_SOC_H6: - if (use_rsb) - return -ENODEV; - pin_func = 0x33; + pin_func = use_rsb ? 0x22 : 0x33; device_bit = BIT(16); - reset_offset = 0x19c; + reset_offset = use_rsb ? 0x1bc : 0x19c; break; case SUNXI_SOC_A64: pin_func = use_rsb ? 0x22 : 0x33; @@ -157,7 +146,7 @@ int sunxi_init_platform_r_twi(uint16_t socid, bool use_rsb) if (socid != SUNXI_SOC_H6) mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, device_bit); else - mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x19c, device_bit | BIT(0)); + mmio_setbits_32(SUNXI_R_PRCM_BASE + reset_offset, BIT(0)); /* assert, then de-assert reset of I2C/RSB controller */ mmio_clrbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit); diff --git a/plat/allwinner/common/sunxi_cpu_ops.c b/plat/allwinner/common/sunxi_cpu_ops.c index 6e29b69bfc..cbad720ff1 100644 --- a/plat/allwinner/common/sunxi_cpu_ops.c +++ b/plat/allwinner/common/sunxi_cpu_ops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -45,7 +45,8 @@ static void sunxi_cpu_enable_power(unsigned int cluster, unsigned int core) mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x00); } -void sunxi_cpu_off(u_register_t mpidr) +/* We can't turn ourself off like this, but it works for other cores. */ +static void sunxi_cpu_off(u_register_t mpidr) { unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr); unsigned int core = MPIDR_AFFLVL0_VAL(mpidr); @@ -54,23 +55,22 @@ void sunxi_cpu_off(u_register_t mpidr) /* Deassert DBGPWRDUP */ mmio_clrbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core)); + /* Activate the core output clamps, but not for core 0. */ + if (core != 0) + mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core)); + /* Assert CPU power-on reset */ + mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); + /* Remove power from the CPU */ + sunxi_cpu_disable_power(cluster, core); +} - /* We can't turn ourself off like this, but it works for other cores. */ - if (read_mpidr() != mpidr) { - /* Activate the core output clamps, but not for core 0. */ - if (core != 0) - mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster), - BIT(core)); - /* Assert CPU power-on reset */ - mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); - /* Remove power from the CPU */ - sunxi_cpu_disable_power(cluster, core); - - return; - } +void sunxi_cpu_power_off_self(void) +{ + u_register_t mpidr = read_mpidr(); + unsigned int core = MPIDR_AFFLVL0_VAL(mpidr); /* Simplifies assembly, all SoCs so far are single cluster anyway. */ - assert(cluster == 0); + assert(MPIDR_AFFLVL1_VAL(mpidr) == 0); /* * If we are supposed to turn ourself off, tell the arisc SCP @@ -106,8 +106,9 @@ void sunxi_cpu_on(u_register_t mpidr) mmio_setbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core)); } -void sunxi_disable_secondary_cpus(u_register_t primary_mpidr) +void sunxi_cpu_power_off_others(void) { + u_register_t self = read_mpidr(); unsigned int cluster; unsigned int core; @@ -116,7 +117,7 @@ void sunxi_disable_secondary_cpus(u_register_t primary_mpidr) u_register_t mpidr = (cluster << MPIDR_AFF1_SHIFT) | (core << MPIDR_AFF0_SHIFT) | BIT(31); - if (mpidr != primary_mpidr) + if (mpidr != self) sunxi_cpu_off(mpidr); } } diff --git a/plat/allwinner/common/sunxi_native_pm.c b/plat/allwinner/common/sunxi_native_pm.c new file mode 100644 index 0000000000..148f50e2af --- /dev/null +++ b/plat/allwinner/common/sunxi_native_pm.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/arm/gicv2.h> +#include <drivers/delay_timer.h> +#include <lib/mmio.h> +#include <lib/psci/psci.h> + +#include <sunxi_mmap.h> +#include <sunxi_private.h> + +#define SUNXI_WDOG0_CTRL_REG (SUNXI_R_WDOG_BASE + 0x0010) +#define SUNXI_WDOG0_CFG_REG (SUNXI_R_WDOG_BASE + 0x0014) +#define SUNXI_WDOG0_MODE_REG (SUNXI_R_WDOG_BASE + 0x0018) + +static int sunxi_pwr_domain_on(u_register_t mpidr) +{ + sunxi_cpu_on(mpidr); + + return PSCI_E_SUCCESS; +} + +static void sunxi_pwr_domain_off(const psci_power_state_t *target_state) +{ + gicv2_cpuif_disable(); + + sunxi_cpu_power_off_self(); +} + +static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +static void __dead2 sunxi_system_off(void) +{ + gicv2_cpuif_disable(); + + /* Attempt to power down the board (may not return) */ + sunxi_power_down(); + + /* Turn off all CPUs */ + sunxi_cpu_power_off_others(); + sunxi_cpu_power_off_self(); + psci_power_down_wfi(); +} + +static void __dead2 sunxi_system_reset(void) +{ + gicv2_cpuif_disable(); + + /* Reset the whole system when the watchdog times out */ + mmio_write_32(SUNXI_WDOG0_CFG_REG, 1); + /* Enable the watchdog with the shortest timeout (0.5 seconds) */ + mmio_write_32(SUNXI_WDOG0_MODE_REG, (0 << 4) | 1); + /* Wait for twice the watchdog timeout before panicking */ + mdelay(1000); + + ERROR("PSCI: System reset failed\n"); + panic(); +} + +static const plat_psci_ops_t sunxi_native_psci_ops = { + .pwr_domain_on = sunxi_pwr_domain_on, + .pwr_domain_off = sunxi_pwr_domain_off, + .pwr_domain_on_finish = sunxi_pwr_domain_on_finish, + .system_off = sunxi_system_off, + .system_reset = sunxi_system_reset, + .validate_ns_entrypoint = sunxi_validate_ns_entrypoint, +}; + +void sunxi_set_native_psci_ops(const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &sunxi_native_psci_ops; +} diff --git a/plat/allwinner/common/sunxi_pm.c b/plat/allwinner/common/sunxi_pm.c index e0fa5b3ec9..eb1b7e7b85 100644 --- a/plat/allwinner/common/sunxi_pm.c +++ b/plat/allwinner/common/sunxi_pm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -8,258 +8,23 @@ #include <platform_def.h> -#include <arch_helpers.h> #include <common/debug.h> -#include <drivers/arm/css/css_scpi.h> -#include <drivers/arm/gicv2.h> -#include <drivers/delay_timer.h> #include <lib/mmio.h> #include <lib/psci/psci.h> -#include <plat/common/platform.h> #include <sunxi_cpucfg.h> -#include <sunxi_def.h> -#include <sunxi_mmap.h> #include <sunxi_private.h> -#define SUNXI_WDOG0_CTRL_REG (SUNXI_R_WDOG_BASE + 0x0010) -#define SUNXI_WDOG0_CFG_REG (SUNXI_R_WDOG_BASE + 0x0014) -#define SUNXI_WDOG0_MODE_REG (SUNXI_R_WDOG_BASE + 0x0018) - -#define CPU_PWR_LVL MPIDR_AFFLVL0 -#define CLUSTER_PWR_LVL MPIDR_AFFLVL1 -#define SYSTEM_PWR_LVL MPIDR_AFFLVL2 - -#define CPU_PWR_STATE(state) \ - ((state)->pwr_domain_state[CPU_PWR_LVL]) -#define CLUSTER_PWR_STATE(state) \ - ((state)->pwr_domain_state[CLUSTER_PWR_LVL]) -#define SYSTEM_PWR_STATE(state) \ - ((state)->pwr_domain_state[SYSTEM_PWR_LVL]) - -#define mpidr_is_valid(mpidr) (plat_core_pos_by_mpidr(mpidr) >= 0) - -/* - * The addresses for the SCP exception vectors are defined in the or1k - * architecture specification. - */ -#define OR1K_VEC_FIRST 0x01 -#define OR1K_VEC_LAST 0x0e -#define OR1K_VEC_ADDR(n) (0x100 * (n)) - -/* - * This magic value is the little-endian representation of the or1k - * instruction "l.mfspr r2, r0, 0x12", which is guaranteed to be the - * first instruction in the SCP firmware. - */ -#define SCP_FIRMWARE_MAGIC 0xb4400012 - -static bool scpi_available; - -static inline scpi_power_state_t scpi_map_state(plat_local_state_t psci_state) -{ - if (is_local_state_run(psci_state)) - return scpi_power_on; - if (is_local_state_retn(psci_state)) - return scpi_power_retention; - return scpi_power_off; -} - -static void sunxi_cpu_standby(plat_local_state_t cpu_state) -{ - u_register_t scr = read_scr_el3(); - - assert(is_local_state_retn(cpu_state)); - - write_scr_el3(scr | SCR_IRQ_BIT); - wfi(); - write_scr_el3(scr); -} - -static int sunxi_pwr_domain_on(u_register_t mpidr) -{ - if (mpidr_is_valid(mpidr) == 0) - return PSCI_E_INTERN_FAIL; - - if (scpi_available) { - scpi_set_css_power_state(mpidr, - scpi_power_on, - scpi_power_on, - scpi_power_on); - } else { - sunxi_cpu_on(mpidr); - } - - return PSCI_E_SUCCESS; -} - -static void sunxi_pwr_domain_off(const psci_power_state_t *target_state) -{ - plat_local_state_t cpu_pwr_state = CPU_PWR_STATE(target_state); - plat_local_state_t cluster_pwr_state = CLUSTER_PWR_STATE(target_state); - plat_local_state_t system_pwr_state = SYSTEM_PWR_STATE(target_state); - - if (is_local_state_off(cpu_pwr_state)) - gicv2_cpuif_disable(); - - if (scpi_available) { - scpi_set_css_power_state(read_mpidr(), - scpi_map_state(cpu_pwr_state), - scpi_map_state(cluster_pwr_state), - scpi_map_state(system_pwr_state)); - } -} - -static void __dead2 sunxi_pwr_down_wfi(const psci_power_state_t *target_state) -{ - sunxi_cpu_off(read_mpidr()); - - while (1) - wfi(); -} - -static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state) -{ - if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) - gicv2_distif_init(); - if (is_local_state_off(CPU_PWR_STATE(target_state))) { - gicv2_pcpu_distif_init(); - gicv2_cpuif_enable(); - } -} - -static void __dead2 sunxi_system_off(void) +int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint) { - gicv2_cpuif_disable(); - - if (scpi_available) { - /* Send the power down request to the SCP */ - uint32_t ret = scpi_sys_power_state(scpi_system_shutdown); - - if (ret != SCP_OK) - ERROR("PSCI: SCPI %s failed: %d\n", "shutdown", ret); - } - - /* Turn off all secondary CPUs */ - sunxi_disable_secondary_cpus(read_mpidr()); - - sunxi_power_down(); - - udelay(1000); - ERROR("PSCI: Cannot turn off system, halting\n"); - wfi(); - panic(); -} - -static void __dead2 sunxi_system_reset(void) -{ - gicv2_cpuif_disable(); - - if (scpi_available) { - /* Send the system reset request to the SCP */ - uint32_t ret = scpi_sys_power_state(scpi_system_reboot); - - if (ret != SCP_OK) - ERROR("PSCI: SCPI %s failed: %d\n", "reboot", ret); - } - - /* Reset the whole system when the watchdog times out */ - mmio_write_32(SUNXI_WDOG0_CFG_REG, 1); - /* Enable the watchdog with the shortest timeout (0.5 seconds) */ - mmio_write_32(SUNXI_WDOG0_MODE_REG, (0 << 4) | 1); - /* Wait for twice the watchdog timeout before panicking */ - mdelay(1000); - - ERROR("PSCI: System reset failed\n"); - wfi(); - panic(); -} - -static int sunxi_validate_power_state(unsigned int power_state, - psci_power_state_t *req_state) -{ - unsigned int power_level = psci_get_pstate_pwrlvl(power_state); - unsigned int type = psci_get_pstate_type(power_state); - - assert(req_state != NULL); - - if (power_level > PLAT_MAX_PWR_LVL) - return PSCI_E_INVALID_PARAMS; - - if (type == PSTATE_TYPE_STANDBY) { - /* Only one retention power state is supported. */ - if (psci_get_pstate_id(power_state) > 0) - return PSCI_E_INVALID_PARAMS; - /* The SoC cannot be suspended without losing state */ - if (power_level == SYSTEM_PWR_LVL) - return PSCI_E_INVALID_PARAMS; - for (unsigned int i = 0; i <= power_level; ++i) - req_state->pwr_domain_state[i] = PLAT_MAX_RET_STATE; - } else { - /* Only one off power state is supported. */ - if (psci_get_pstate_id(power_state) > 0) - return PSCI_E_INVALID_PARAMS; - for (unsigned int i = 0; i <= power_level; ++i) - req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; + /* The non-secure entry point must be in DRAM */ + if (ns_entrypoint < SUNXI_DRAM_BASE) { + return PSCI_E_INVALID_ADDRESS; } - /* Higher power domain levels should all remain running */ - for (unsigned int i = power_level + 1; i <= PLAT_MAX_PWR_LVL; ++i) - req_state->pwr_domain_state[i] = PSCI_LOCAL_STATE_RUN; return PSCI_E_SUCCESS; } -static int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint) -{ - /* The non-secure entry point must be in DRAM */ - if (ns_entrypoint >= SUNXI_DRAM_BASE) - return PSCI_E_SUCCESS; - - return PSCI_E_INVALID_ADDRESS; -} - -static void sunxi_get_sys_suspend_power_state(psci_power_state_t *req_state) -{ - assert(req_state); - - for (unsigned int i = 0; i <= PLAT_MAX_PWR_LVL; ++i) - req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; -} - -static int sunxi_get_node_hw_state(u_register_t mpidr, - unsigned int power_level) -{ - unsigned int cluster_state, cpu_state; - unsigned int cpu = MPIDR_AFFLVL0_VAL(mpidr); - - /* SoC power level (always on if PSCI works). */ - if (power_level == SYSTEM_PWR_LVL) - return HW_ON; - if (scpi_get_css_power_state(mpidr, &cpu_state, &cluster_state)) - return PSCI_E_NOT_SUPPORTED; - /* Cluster power level (full power state available). */ - if (power_level == CLUSTER_PWR_LVL) { - if (cluster_state == scpi_power_on) - return HW_ON; - if (cluster_state == scpi_power_retention) - return HW_STANDBY; - return HW_OFF; - } - /* CPU power level (one bit boolean for on or off). */ - return ((cpu_state & BIT(cpu)) != 0) ? HW_ON : HW_OFF; -} - -static plat_psci_ops_t sunxi_psci_ops = { - .cpu_standby = sunxi_cpu_standby, - .pwr_domain_on = sunxi_pwr_domain_on, - .pwr_domain_off = sunxi_pwr_domain_off, - .pwr_domain_on_finish = sunxi_pwr_domain_on_finish, - .system_off = sunxi_system_off, - .system_reset = sunxi_system_reset, - .validate_power_state = sunxi_validate_power_state, - .validate_ns_entrypoint = sunxi_validate_ns_entrypoint, -}; - int plat_setup_psci_ops(uintptr_t sec_entrypoint, const plat_psci_ops_t **psci_ops) { @@ -273,37 +38,12 @@ int plat_setup_psci_ops(uintptr_t sec_entrypoint, sec_entrypoint >> 32); } - /* Check for a valid SCP firmware, and boot the SCP if found. */ - if (mmio_read_32(SUNXI_SCP_BASE) == SCP_FIRMWARE_MAGIC) { - /* Program SCP exception vectors to the firmware entrypoint. */ - for (unsigned int i = OR1K_VEC_FIRST; i <= OR1K_VEC_LAST; ++i) { - uint32_t vector = SUNXI_SRAM_A2_BASE + OR1K_VEC_ADDR(i); - uint32_t offset = SUNXI_SCP_BASE - vector; - - mmio_write_32(vector, offset >> 2); - clean_dcache_range(vector, sizeof(uint32_t)); - } - /* Take the SCP out of reset. */ - mmio_setbits_32(SUNXI_R_CPUCFG_BASE, BIT(0)); - /* Wait for the SCP firmware to boot. */ - if (scpi_wait_ready() == 0) - scpi_available = true; - } - - NOTICE("PSCI: System suspend is %s\n", - scpi_available ? "available via SCPI" : "unavailable"); - if (scpi_available) { - /* Suspend is only available via SCPI. */ - sunxi_psci_ops.pwr_domain_suspend = sunxi_pwr_domain_off; - sunxi_psci_ops.pwr_domain_suspend_finish = sunxi_pwr_domain_on_finish; - sunxi_psci_ops.get_sys_suspend_power_state = sunxi_get_sys_suspend_power_state; - sunxi_psci_ops.get_node_hw_state = sunxi_get_node_hw_state; + if (sunxi_set_scpi_psci_ops(psci_ops) == 0) { + INFO("PSCI: Suspend is available via SCPI\n"); } else { - /* This is only needed when SCPI is unavailable. */ - sunxi_psci_ops.pwr_domain_pwr_down_wfi = sunxi_pwr_down_wfi; + INFO("PSCI: Suspend is unavailable\n"); + sunxi_set_native_psci_ops(psci_ops); } - *psci_ops = &sunxi_psci_ops; - return 0; } diff --git a/plat/allwinner/common/sunxi_scpi_pm.c b/plat/allwinner/common/sunxi_scpi_pm.c new file mode 100644 index 0000000000..74763ef7ed --- /dev/null +++ b/plat/allwinner/common/sunxi_scpi_pm.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/arm/css/css_scpi.h> +#include <drivers/arm/gicv2.h> +#include <lib/mmio.h> +#include <lib/psci/psci.h> + +#include <sunxi_mmap.h> +#include <sunxi_private.h> + +/* + * The addresses for the SCP exception vectors are defined in the or1k + * architecture specification. + */ +#define OR1K_VEC_FIRST 0x01 +#define OR1K_VEC_LAST 0x0e +#define OR1K_VEC_ADDR(n) (0x100 * (n)) + +/* + * This magic value is the little-endian representation of the or1k + * instruction "l.mfspr r2, r0, 0x12", which is guaranteed to be the + * first instruction in the SCP firmware. + */ +#define SCP_FIRMWARE_MAGIC 0xb4400012 + +#define CPU_PWR_LVL MPIDR_AFFLVL0 +#define CLUSTER_PWR_LVL MPIDR_AFFLVL1 +#define SYSTEM_PWR_LVL MPIDR_AFFLVL2 + +#define CPU_PWR_STATE(state) \ + ((state)->pwr_domain_state[CPU_PWR_LVL]) +#define CLUSTER_PWR_STATE(state) \ + ((state)->pwr_domain_state[CLUSTER_PWR_LVL]) +#define SYSTEM_PWR_STATE(state) \ + ((state)->pwr_domain_state[SYSTEM_PWR_LVL]) + +static inline scpi_power_state_t scpi_map_state(plat_local_state_t psci_state) +{ + if (is_local_state_run(psci_state)) { + return scpi_power_on; + } + if (is_local_state_retn(psci_state)) { + return scpi_power_retention; + } + return scpi_power_off; +} + +static void sunxi_cpu_standby(plat_local_state_t cpu_state) +{ + u_register_t scr = read_scr_el3(); + + assert(is_local_state_retn(cpu_state)); + + write_scr_el3(scr | SCR_IRQ_BIT); + wfi(); + write_scr_el3(scr); +} + +static int sunxi_pwr_domain_on(u_register_t mpidr) +{ + scpi_set_css_power_state(mpidr, + scpi_power_on, + scpi_power_on, + scpi_power_on); + + return PSCI_E_SUCCESS; +} + +static void sunxi_pwr_domain_off(const psci_power_state_t *target_state) +{ + plat_local_state_t cpu_pwr_state = CPU_PWR_STATE(target_state); + plat_local_state_t cluster_pwr_state = CLUSTER_PWR_STATE(target_state); + plat_local_state_t system_pwr_state = SYSTEM_PWR_STATE(target_state); + + if (is_local_state_off(cpu_pwr_state)) { + gicv2_cpuif_disable(); + } + + scpi_set_css_power_state(read_mpidr(), + scpi_map_state(cpu_pwr_state), + scpi_map_state(cluster_pwr_state), + scpi_map_state(system_pwr_state)); +} + +static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) { + gicv2_distif_init(); + } + if (is_local_state_off(CPU_PWR_STATE(target_state))) { + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + } +} + +static void __dead2 sunxi_system_off(void) +{ + uint32_t ret; + + gicv2_cpuif_disable(); + + /* Send the power down request to the SCP. */ + ret = scpi_sys_power_state(scpi_system_shutdown); + if (ret != SCP_OK) { + ERROR("PSCI: SCPI %s failed: %d\n", "shutdown", ret); + } + + psci_power_down_wfi(); +} + +static void __dead2 sunxi_system_reset(void) +{ + uint32_t ret; + + gicv2_cpuif_disable(); + + /* Send the system reset request to the SCP. */ + ret = scpi_sys_power_state(scpi_system_reboot); + if (ret != SCP_OK) { + ERROR("PSCI: SCPI %s failed: %d\n", "reboot", ret); + } + + psci_power_down_wfi(); +} + +static int sunxi_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int power_level = psci_get_pstate_pwrlvl(power_state); + unsigned int type = psci_get_pstate_type(power_state); + + assert(req_state != NULL); + + if (power_level > PLAT_MAX_PWR_LVL) { + return PSCI_E_INVALID_PARAMS; + } + + if (type == PSTATE_TYPE_STANDBY) { + /* Only one retention power state is supported. */ + if (psci_get_pstate_id(power_state) > 0) { + return PSCI_E_INVALID_PARAMS; + } + /* The SoC cannot be suspended without losing state */ + if (power_level == SYSTEM_PWR_LVL) { + return PSCI_E_INVALID_PARAMS; + } + for (unsigned int i = 0; i <= power_level; ++i) { + req_state->pwr_domain_state[i] = PLAT_MAX_RET_STATE; + } + } else { + /* Only one off power state is supported. */ + if (psci_get_pstate_id(power_state) > 0) { + return PSCI_E_INVALID_PARAMS; + } + for (unsigned int i = 0; i <= power_level; ++i) { + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; + } + } + /* Higher power domain levels should all remain running */ + for (unsigned int i = power_level + 1; i <= PLAT_MAX_PWR_LVL; ++i) { + req_state->pwr_domain_state[i] = PSCI_LOCAL_STATE_RUN; + } + + return PSCI_E_SUCCESS; +} + +static void sunxi_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + assert(req_state != NULL); + + for (unsigned int i = 0; i <= PLAT_MAX_PWR_LVL; ++i) { + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; + } +} + +static const plat_psci_ops_t sunxi_scpi_psci_ops = { + .cpu_standby = sunxi_cpu_standby, + .pwr_domain_on = sunxi_pwr_domain_on, + .pwr_domain_off = sunxi_pwr_domain_off, + .pwr_domain_suspend = sunxi_pwr_domain_off, + .pwr_domain_on_finish = sunxi_pwr_domain_on_finish, + .pwr_domain_suspend_finish = sunxi_pwr_domain_on_finish, + .system_off = sunxi_system_off, + .system_reset = sunxi_system_reset, + .validate_power_state = sunxi_validate_power_state, + .validate_ns_entrypoint = sunxi_validate_ns_entrypoint, + .get_sys_suspend_power_state = sunxi_get_sys_suspend_power_state, +}; + +int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &sunxi_scpi_psci_ops; + + /* Check for a valid SCP firmware. */ + if (mmio_read_32(SUNXI_SCP_BASE) != SCP_FIRMWARE_MAGIC) { + return -1; + } + + /* Program SCP exception vectors to the firmware entrypoint. */ + for (unsigned int i = OR1K_VEC_FIRST; i <= OR1K_VEC_LAST; ++i) { + uint32_t vector = SUNXI_SRAM_A2_BASE + OR1K_VEC_ADDR(i); + uint32_t offset = SUNXI_SCP_BASE - vector; + + mmio_write_32(vector, offset >> 2); + clean_dcache_range(vector, sizeof(uint32_t)); + } + + /* Take the SCP out of reset. */ + mmio_setbits_32(SUNXI_R_CPUCFG_BASE, BIT(0)); + + /* Wait for the SCP firmware to boot. */ + return scpi_wait_ready(); +} diff --git a/plat/allwinner/common/sunxi_security.c b/plat/allwinner/common/sunxi_security.c index 92c83b06ec..98b91c39f6 100644 --- a/plat/allwinner/common/sunxi_security.c +++ b/plat/allwinner/common/sunxi_security.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,16 +7,11 @@ #include <common/debug.h> #include <lib/mmio.h> +#include <sunxi_ccu.h> #include <sunxi_mmap.h> #include <sunxi_private.h> +#include <sunxi_spc.h> -#ifdef SUNXI_SPC_BASE -#define SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + ((p) * 0x0c) + 0x4) -#define SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + ((p) * 0x0c) + 0x8) -#define SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + ((p) * 0x0c) + 0xc) -#endif - -#define R_PRCM_SEC_SWITCH_REG 0x1d0 #define DMA_SEC_REG 0x20 /* @@ -27,20 +22,18 @@ */ void sunxi_security_setup(void) { -#ifdef SUNXI_SPC_BASE int i; INFO("Configuring SPC Controller\n"); /* SPC setup: set all devices to non-secure */ - for (i = 0; i < 6; i++) - mmio_write_32(SPC_DECPORT_SET_REG(i), 0xff); -#endif + for (i = 0; i < SUNXI_SPC_NUM_PORTS; i++) + mmio_write_32(SUNXI_SPC_DECPORT_SET_REG(i), 0xffffffff); /* set MBUS clocks, bus clocks (AXI/AHB/APB) and PLLs to non-secure */ mmio_write_32(SUNXI_CCU_SEC_SWITCH_REG, 0x7); /* Set R_PRCM bus clocks to non-secure */ - mmio_write_32(SUNXI_R_PRCM_BASE + R_PRCM_SEC_SWITCH_REG, 0x1); + mmio_write_32(SUNXI_R_PRCM_SEC_SWITCH_REG, 0x1); /* Set all DMA channels (16 max.) to non-secure */ mmio_write_32(SUNXI_DMA_BASE + DMA_SEC_REG, 0xffff); diff --git a/plat/allwinner/sun50i_a64/include/sunxi_ccu.h b/plat/allwinner/sun50i_a64/include/sunxi_ccu.h new file mode 100644 index 0000000000..2a24886217 --- /dev/null +++ b/plat/allwinner/sun50i_a64/include/sunxi_ccu.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_CCU_H +#define SUNXI_CCU_H + +#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x02f0) + +#define SUNXI_R_PRCM_SEC_SWITCH_REG (SUNXI_R_PRCM_BASE + 0x01d0) + +#endif /* SUNXI_CCU_H */ diff --git a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h index 9d2542fce0..6c847d39ba 100644 --- a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h +++ b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h @@ -36,7 +36,6 @@ #define SUNXI_MSGBOX_BASE 0x01c17000 #define SUNXI_SPINLOCK_BASE 0x01c18000 #define SUNXI_CCU_BASE 0x01c20000 -#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x2f0) #define SUNXI_PIO_BASE 0x01c20800 #define SUNXI_TIMER_BASE 0x01c20c00 #define SUNXI_WDOG_BASE 0x01c20ca0 diff --git a/plat/allwinner/sun50i_a64/include/sunxi_spc.h b/plat/allwinner/sun50i_a64/include/sunxi_spc.h new file mode 100644 index 0000000000..5ba7e18fef --- /dev/null +++ b/plat/allwinner/sun50i_a64/include/sunxi_spc.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_SPC_H +#define SUNXI_SPC_H + +#define SUNXI_SPC_NUM_PORTS 6 + +#define SUNXI_SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + 0x0004 + 0x0c * (p)) +#define SUNXI_SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + 0x0008 + 0x0c * (p)) +#define SUNXI_SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + 0x000c + 0x0c * (p)) + +#endif /* SUNXI_SPC_H */ diff --git a/plat/allwinner/sun50i_a64/sunxi_power.c b/plat/allwinner/sun50i_a64/sunxi_power.c index 5b7d76ae91..80a69c3404 100644 --- a/plat/allwinner/sun50i_a64/sunxi_power.c +++ b/plat/allwinner/sun50i_a64/sunxi_power.c @@ -92,21 +92,13 @@ static int rsb_init(void) if (ret) return ret; - /* Start with 400 KHz to issue the I2C->RSB switch command. */ - ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 400000); - if (ret) - return ret; - - /* - * Initiate an I2C transaction to write 0x7c into register 0x3e, - * switching the PMIC to RSB mode. - */ - ret = rsb_set_device_mode(0x7c3e00); + /* Switch to the recommended 3 MHz bus clock. */ + ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000); if (ret) return ret; - /* Now in RSB mode, switch to the recommended 3 MHz. */ - ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000); + /* Initiate an I2C transaction to switch the PMIC to RSB mode. */ + ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8); if (ret) return ret; @@ -156,6 +148,11 @@ int sunxi_pmic_setup(uint16_t socid, const void *fdt) pmic = AXP803_RSB; axp_setup_regulators(fdt); + /* Switch the PMIC back to I2C mode. */ + ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C); + if (ret) + return ret; + break; default: return -ENODEV; diff --git a/plat/allwinner/sun50i_h6/include/sunxi_ccu.h b/plat/allwinner/sun50i_h6/include/sunxi_ccu.h new file mode 100644 index 0000000000..85fbb90802 --- /dev/null +++ b/plat/allwinner/sun50i_h6/include/sunxi_ccu.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_CCU_H +#define SUNXI_CCU_H + +#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x0f00) + +#define SUNXI_R_PRCM_SEC_SWITCH_REG (SUNXI_R_PRCM_BASE + 0x0290) + +#endif /* SUNXI_CCU_H */ diff --git a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h index 702db770f2..2d7b098377 100644 --- a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h +++ b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h @@ -30,8 +30,8 @@ #define SUNXI_DMA_BASE 0x03002000 #define SUNXI_MSGBOX_BASE 0x03003000 #define SUNXI_CCU_BASE 0x03001000 -#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0xf00) #define SUNXI_PIO_BASE 0x0300b000 +#define SUNXI_SPC_BASE 0x03008000 #define SUNXI_TIMER_BASE 0x03009000 #define SUNXI_WDOG_BASE 0x030090a0 #define SUNXI_THS_BASE 0x05070400 @@ -55,6 +55,7 @@ #define SUNXI_R_TWD_BASE 0x07020800 #define SUNXI_R_CPUCFG_BASE 0x07000400 #define SUNXI_R_I2C_BASE 0x07081400 +#define SUNXI_R_RSB_BASE 0x07083000 #define SUNXI_R_UART_BASE 0x07080000 #define SUNXI_R_PIO_BASE 0x07022000 diff --git a/plat/allwinner/sun50i_h6/include/sunxi_spc.h b/plat/allwinner/sun50i_h6/include/sunxi_spc.h new file mode 100644 index 0000000000..0f5965bee5 --- /dev/null +++ b/plat/allwinner/sun50i_h6/include/sunxi_spc.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_SPC_H +#define SUNXI_SPC_H + +#define SUNXI_SPC_NUM_PORTS 14 + +#define SUNXI_SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + 0x0000 + 0x10 * (p)) +#define SUNXI_SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + 0x0004 + 0x10 * (p)) +#define SUNXI_SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + 0x0008 + 0x10 * (p)) + +#endif /* SUNXI_SPC_H */ diff --git a/plat/allwinner/sun50i_h6/platform.mk b/plat/allwinner/sun50i_h6/platform.mk index 4ecc57cf07..1c98919b1c 100644 --- a/plat/allwinner/sun50i_h6/platform.mk +++ b/plat/allwinner/sun50i_h6/platform.mk @@ -8,4 +8,4 @@ include plat/allwinner/common/allwinner-common.mk BL31_SOURCES += drivers/allwinner/axp/axp805.c \ - drivers/mentor/i2c/mi2cv.c + drivers/allwinner/sunxi_rsb.c diff --git a/plat/allwinner/sun50i_h6/sunxi_power.c b/plat/allwinner/sun50i_h6/sunxi_power.c index 443015bacf..a7865a5d4d 100644 --- a/plat/allwinner/sun50i_h6/sunxi_power.c +++ b/plat/allwinner/sun50i_h6/sunxi_power.c @@ -6,20 +6,17 @@ */ #include <errno.h> -#include <string.h> -#include <arch_helpers.h> #include <common/debug.h> #include <drivers/allwinner/axp.h> -#include <drivers/delay_timer.h> -#include <drivers/mentor/mi2cv.h> -#include <lib/mmio.h> +#include <drivers/allwinner/sunxi_rsb.h> #include <sunxi_def.h> #include <sunxi_mmap.h> #include <sunxi_private.h> -#define AXP805_ADDR 0x36 +#define AXP805_HW_ADDR 0x745 +#define AXP805_RT_ADDR 0x3a static enum pmic_type { UNKNOWN, @@ -28,67 +25,67 @@ static enum pmic_type { int axp_read(uint8_t reg) { - uint8_t val; - int ret; - - ret = i2c_write(AXP805_ADDR, 0, 0, ®, 1); - if (ret == 0) - ret = i2c_read(AXP805_ADDR, 0, 0, &val, 1); - if (ret) { - ERROR("PMIC: Cannot read AXP805 register %02x\n", reg); - return ret; - } - - return val; + return rsb_read(AXP805_RT_ADDR, reg); } int axp_write(uint8_t reg, uint8_t val) { - int ret; - - ret = i2c_write(AXP805_ADDR, reg, 1, &val, 1); - if (ret) - ERROR("PMIC: Cannot write AXP805 register %02x\n", reg); - - return ret; + return rsb_write(AXP805_RT_ADDR, reg, val); } -static int axp805_probe(void) +static int rsb_init(void) { int ret; - /* Switch the AXP805 to master/single-PMIC mode. */ - ret = axp_write(0xff, 0x0); + ret = rsb_init_controller(); if (ret) return ret; - ret = axp_check_id(); + /* Switch to the recommended 3 MHz bus clock. */ + ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000); if (ret) return ret; - return 0; + /* Initiate an I2C transaction to switch the PMIC to RSB mode. */ + ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8); + if (ret) + return ret; + + /* Associate the 8-bit runtime address with the 12-bit bus address. */ + ret = rsb_assign_runtime_address(AXP805_HW_ADDR, AXP805_RT_ADDR); + if (ret) + return ret; + + return axp_check_id(); } int sunxi_pmic_setup(uint16_t socid, const void *fdt) { int ret; - INFO("PMIC: Probing AXP805 on I2C\n"); + INFO("PMIC: Probing AXP805 on RSB\n"); - ret = sunxi_init_platform_r_twi(SUNXI_SOC_H6, false); + ret = sunxi_init_platform_r_twi(socid, true); if (ret) return ret; - /* initialise mi2cv driver */ - i2c_init((void *)SUNXI_R_I2C_BASE); + ret = rsb_init(); + if (ret) + return ret; - ret = axp805_probe(); + /* Switch the AXP805 to master/single-PMIC mode. */ + ret = axp_write(0xff, 0x0); if (ret) return ret; pmic = AXP805; axp_setup_regulators(fdt); + /* Switch the PMIC back to I2C mode. */ + ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C); + if (ret) + return ret; + return 0; } @@ -96,10 +93,9 @@ void sunxi_power_down(void) { switch (pmic) { case AXP805: - /* Re-initialise after rich OS might have used it. */ - sunxi_init_platform_r_twi(SUNXI_SOC_H6, false); - /* initialise mi2cv driver */ - i2c_init((void *)SUNXI_R_I2C_BASE); + /* (Re-)init RSB in case the rich OS has disabled it. */ + sunxi_init_platform_r_twi(SUNXI_SOC_H6, true); + rsb_init(); axp_power_off(); break; default: diff --git a/plat/amlogic/axg/include/platform_def.h b/plat/amlogic/axg/include/platform_def.h index a47cf7348e..c97687e363 100644 --- a/plat/amlogic/axg/include/platform_def.h +++ b/plat/amlogic/axg/include/platform_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -24,7 +24,7 @@ #define AML_PRIMARY_CPU U(0) -#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1 +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 #define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ PLATFORM_CORE_COUNT) diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk index 4b751fb20f..3ac1c01ab9 100644 --- a/plat/arm/board/arm_fpga/platform.mk +++ b/plat/arm/board/arm_fpga/platform.mk @@ -59,7 +59,9 @@ else lib/cpus/aarch64/cortex_a76ae.S \ lib/cpus/aarch64/cortex_a77.S \ lib/cpus/aarch64/cortex_a78.S \ + lib/cpus/aarch64/neoverse_n_common.S \ lib/cpus/aarch64/neoverse_n1.S \ + lib/cpus/aarch64/neoverse_n2.S \ lib/cpus/aarch64/neoverse_e1.S \ lib/cpus/aarch64/neoverse_v1.S \ lib/cpus/aarch64/cortex_a78_ae.S \ diff --git a/plat/arm/board/common/board_common.mk b/plat/arm/board/common/board_common.mk index 1885a600a7..6db0c00312 100644 --- a/plat/arm/board/common/board_common.mk +++ b/plat/arm/board/common/board_common.mk @@ -41,7 +41,6 @@ $(eval $(call add_define,ARM_ROTPK_LOCATION_ID)) # Force generation of the new hash if ROT_KEY is specified ifdef ROT_KEY HASH_PREREQUISITES = $(ROT_KEY) FORCE -FORCE: else HASH_PREREQUISITES = $(ROT_KEY) endif diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts index 8b9c281e2c..f4805db692 100644 --- a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts +++ b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts @@ -27,17 +27,14 @@ binary_size = <0x80000>; }; - chosen { - linux,initrd-start = <0>; - linux,initrd-end = <0>; - }; - hypervisor { compatible = "hafnium,hafnium"; vm1 { is_ffa_partition; debug_name = "cactus-primary"; load_address = <0x7000000>; + vcpu_count = <8>; + mem_size = <1048576>; }; vm2 { is_ffa_partition; @@ -74,11 +71,6 @@ CPU_1 }; - device-memory@0 { - device_type = "device-memory"; - reg = <0x0 0x0 0x6000000 0x0 0x8000000 0x78000000>; - }; - memory@6000000 { device_type = "memory"; reg = <0x0 0x6000000 0x2000000>; /* Trusted DRAM */ diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts index 266adfc2bb..57d6792e12 100644 --- a/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts +++ b/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts @@ -27,11 +27,6 @@ binary_size = <0x80000>; }; - chosen { - linux,initrd-start = <0>; - linux,initrd-end = <0>; - }; - hypervisor { compatible = "hafnium,hafnium"; vm1 { @@ -39,6 +34,8 @@ debug_name = "op-tee"; load_address = <0x6280000>; smc_whitelist = <0xbe000000>; + vcpu_count = <8>; + mem_size = <1048576>; }; }; @@ -61,11 +58,6 @@ CPU_1 }; - device-memory@0 { - device_type = "device-memory"; - reg = <0x0 0x0 0x6000000 0x0 0x8000000 0x78000000>; - }; - memory@6000000 { device_type = "memory"; reg = <0x0 0x6000000 0x2000000>; /* Trusted DRAM */ diff --git a/plat/arm/board/fvp/fdts/optee_sp_manifest.dts b/plat/arm/board/fvp/fdts/optee_sp_manifest.dts new file mode 100644 index 0000000000..928d0d3bf5 --- /dev/null +++ b/plat/arm/board/fvp/fdts/optee_sp_manifest.dts @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * This file is a Partition Manifest (PM) for a minimal Secure Partition (SP) + * that has additional optional properties defined. + * + */ + +/dts-v1/; + +/ { + compatible = "arm,ffa-manifest-1.0"; + + /* Properties */ + description = "op-tee"; + ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */ + uuid = <0x486178e0 0xe7f811e3 0xbc5e0002 0xa5d5c51b>; + id = <1>; + execution-ctx-count = <8>; + exception-level = <2>; /* S-EL1 */ + execution-state = <0>; /* AARCH64 */ + load-address = <0x6280000>; + entrypoint-offset = <0x1000>; + xlat-granule = <0>; /* 4KiB */ + boot-order = <0>; + messaging-method = <0>; /* Direct messaging only */ + run-time-model = <1>; /* Run to completion */ + + /* Boot protocol */ + gp-register-num = <0x0>; + + device-regions { + compatible = "arm,ffa-manifest-device-regions"; + + uart1 { + base-address = <0x00000000 0x1c0a0000>; + pages-count = <1>; + attributes = <0x3>; /* read-write */ + }; + + gicd { + base-address = <0x00000000 0x2f000000>; + pages-count = <16>; + attributes = <0x3>; /* read-write */ + }; + }; +}; diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c index 6e479ac4fc..52686facad 100644 --- a/plat/arm/board/fvp/fvp_common.c +++ b/plat/arm/board/fvp/fvp_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -48,6 +48,18 @@ arm_config_t arm_config; DEVICE1_SIZE, \ MT_DEVICE | MT_RW | MT_SECURE) +#if FVP_GICR_REGION_PROTECTION +#define MAP_GICD_MEM MAP_REGION_FLAT(BASE_GICD_BASE, \ + BASE_GICD_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* Map all core's redistributor memory as read-only. After boots up, + * per-core map its redistributor memory as read-write */ +#define MAP_GICR_MEM MAP_REGION_FLAT(BASE_GICR_BASE, \ + (BASE_GICR_SIZE * PLATFORM_CORE_COUNT),\ + MT_DEVICE | MT_RO | MT_SECURE) +#endif /* FVP_GICR_REGION_PROTECTION */ + /* * Need to be mapped with write permissions in order to set a new non-volatile * counter value. @@ -70,7 +82,9 @@ const mmap_region_t plat_arm_mmap[] = { V2M_MAP_FLASH0_RW, V2M_MAP_IOFPGA, MAP_DEVICE0, +#if FVP_INTERCONNECT_DRIVER == FVP_CCN MAP_DEVICE1, +#endif #if TRUSTED_BOARD_BOOT /* To access the Root of Trust Public Key registers. */ MAP_DEVICE2, @@ -86,7 +100,9 @@ const mmap_region_t plat_arm_mmap[] = { V2M_MAP_FLASH0_RW, V2M_MAP_IOFPGA, MAP_DEVICE0, +#if FVP_INTERCONNECT_DRIVER == FVP_CCN MAP_DEVICE1, +#endif ARM_MAP_NS_DRAM1, #ifdef __aarch64__ ARM_MAP_DRAM2, @@ -134,7 +150,12 @@ const mmap_region_t plat_arm_mmap[] = { ARM_MAP_EL3_TZC_DRAM, V2M_MAP_IOFPGA, MAP_DEVICE0, +#if FVP_GICR_REGION_PROTECTION + MAP_GICD_MEM, + MAP_GICR_MEM, +#else MAP_DEVICE1, +#endif /* FVP_GICR_REGION_PROTECTION */ ARM_V2M_MAP_MEM_PROTECT, #if SPM_MM ARM_SPM_BUF_EL3_MMAP, diff --git a/plat/arm/board/fvp/fvp_def.h b/plat/arm/board/fvp/fvp_def.h index 4efe69258c..831eb35b77 100644 --- a/plat/arm/board/fvp/fvp_def.h +++ b/plat/arm/board/fvp/fvp_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -135,7 +135,16 @@ /* Base FVP compatible GIC memory map */ #define BASE_GICD_BASE UL(0x2f000000) +#define BASE_GICD_SIZE UL(0x10000) #define BASE_GICR_BASE UL(0x2f100000) + +#if GIC_ENABLE_V4_EXTN +/* GICv4 redistributor size: 256KB */ +#define BASE_GICR_SIZE UL(0x40000) +#else +#define BASE_GICR_SIZE UL(0x20000) +#endif /* GIC_ENABLE_V4_EXTN */ + #define BASE_GICC_BASE UL(0x2c000000) #define BASE_GICH_BASE UL(0x2c010000) #define BASE_GICV_BASE UL(0x2c02f000) diff --git a/plat/arm/board/fvp/fvp_gicv3.c b/plat/arm/board/fvp/fvp_gicv3.c index 3e04d6b67c..8f3e7b702e 100644 --- a/plat/arm/board/fvp/fvp_gicv3.c +++ b/plat/arm/board/fvp/fvp_gicv3.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -15,6 +15,11 @@ #include <plat/arm/common/fconf_sec_intr_config.h> #include <plat/common/platform.h> +#if FVP_GICR_REGION_PROTECTION +/* To indicate GICR region of the core initialized as Read-Write */ +static bool fvp_gicr_rw_region_init[PLATFORM_CORE_COUNT] = {false}; +#endif /* FVP_GICR_REGION_PROTECTION */ + /* The GICv3 driver only needs to be initialized in EL3 */ static uintptr_t fvp_rdistif_base_addrs[PLATFORM_CORE_COUNT]; @@ -61,8 +66,39 @@ static gicv3_driver_data_t fvp_gic_data = { .mpidr_to_core_pos = fvp_gicv3_mpidr_hash }; +/****************************************************************************** + * This function gets called per core to make its redistributor frame rw + *****************************************************************************/ +static void fvp_gicv3_make_rdistrif_rw(void) +{ +#if FVP_GICR_REGION_PROTECTION + unsigned int core_pos = plat_my_core_pos(); + + /* Make the redistributor frame RW if it is not done previously */ + if (fvp_gicr_rw_region_init[core_pos] != true) { + int ret = xlat_change_mem_attributes(BASE_GICR_BASE + + (core_pos * BASE_GICR_SIZE), + BASE_GICR_SIZE, + MT_EXECUTE_NEVER | + MT_DEVICE | MT_RW | + MT_SECURE); + + if (ret != 0) { + ERROR("Failed to make redistributor frame \ + read write = %d\n", ret); + panic(); + } else { + fvp_gicr_rw_region_init[core_pos] = true; + } + } +#else + return; +#endif /* FVP_GICR_REGION_PROTECTION */ +} + void plat_arm_gic_driver_init(void) { + fvp_gicv3_make_rdistrif_rw(); /* * Get GICD and GICR base addressed through FCONF APIs. * FCONF is not supported in BL32 for FVP. @@ -117,6 +153,8 @@ void plat_arm_gic_pcpu_init(void) int result; const uint64_t *plat_gicr_frames = fvp_gicr_frames; + fvp_gicv3_make_rdistrif_rw(); + do { result = gicv3_rdistif_probe(*plat_gicr_frames); diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 4da0d76437..6c09d72683 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -16,6 +16,10 @@ FVP_MAX_CPUS_PER_CLUSTER := 4 # Default number of threads per CPU on FVP FVP_MAX_PE_PER_CPU := 1 +# Disable redistributor frame of inactive/fused CPU cores by marking it as read +# only; enable redistributor frames of all CPU cores by default. +FVP_GICR_REGION_PROTECTION := 0 + FVP_DT_PREFIX := fvp-base-gicv3-psci # The FVP platform depends on this macro to build with correct GIC driver. @@ -30,6 +34,9 @@ $(eval $(call add_define,FVP_MAX_CPUS_PER_CLUSTER)) # Pass FVP_MAX_PE_PER_CPU to the build system. $(eval $(call add_define,FVP_MAX_PE_PER_CPU)) +# Pass FVP_GICR_REGION_PROTECTION to the build system. +$(eval $(call add_define,FVP_GICR_REGION_PROTECTION)) + # Sanity check the cluster count and if FVP_CLUSTER_COUNT <= 2, # choose the CCI driver , else the CCN driver ifeq ($(FVP_CLUSTER_COUNT), 0) @@ -118,7 +125,9 @@ else lib/cpus/aarch64/cortex_a76ae.S \ lib/cpus/aarch64/cortex_a77.S \ lib/cpus/aarch64/cortex_a78.S \ + lib/cpus/aarch64/neoverse_n_common.S \ lib/cpus/aarch64/neoverse_n1.S \ + lib/cpus/aarch64/neoverse_n2.S \ lib/cpus/aarch64/neoverse_e1.S \ lib/cpus/aarch64/neoverse_v1.S \ lib/cpus/aarch64/cortex_a78_ae.S \ diff --git a/plat/arm/board/juno/juno_decl.h b/plat/arm/board/juno/juno_decl.h index cd87c3b776..21e56c051a 100644 --- a/plat/arm/board/juno/juno_decl.h +++ b/plat/arm/board/juno/juno_decl.h @@ -7,6 +7,6 @@ #ifndef JUNO_DECL_H #define JUNO_DECL_H -int juno_getentropy(void *buf, size_t len); +bool juno_getentropy(uint64_t *buf); #endif /* JUNO_DECL_H */ diff --git a/plat/arm/board/juno/juno_stack_protector.c b/plat/arm/board/juno/juno_stack_protector.c index 236eb5ba37..8c51f574cf 100644 --- a/plat/arm/board/juno/juno_stack_protector.c +++ b/plat/arm/board/juno/juno_stack_protector.c @@ -13,20 +13,16 @@ u_register_t plat_get_stack_protector_canary(void) { - u_register_t c[TRNG_NBYTES / sizeof(u_register_t)]; - u_register_t ret = 0; - size_t i; + uint64_t entropy; - if (juno_getentropy(c, sizeof(c)) != 0) { + if (!juno_getentropy(&entropy)) { ERROR("Not enough entropy to initialize canary value\n"); panic(); } - /* - * On Juno we get 128-bits of entropy in one round. - * Fuse the values together to form the canary. - */ - for (i = 0; i < ARRAY_SIZE(c); i++) - ret ^= c[i]; - return ret; + if (sizeof(entropy) == sizeof(u_register_t)) { + return entropy; + } + + return (entropy & 0xffffffffULL) ^ (entropy >> 32); } diff --git a/plat/arm/board/juno/juno_trng.c b/plat/arm/board/juno/juno_trng.c index 7869d3e335..b38e49f453 100644 --- a/plat/arm/board/juno/juno_trng.c +++ b/plat/arm/board/juno/juno_trng.c @@ -5,6 +5,8 @@ */ #include <assert.h> +#include <stdbool.h> +#include <stdint.h> #include <string.h> #include <lib/mmio.h> @@ -16,7 +18,10 @@ #define NSAMPLE_CLOCKS 1 /* min 1 cycle, max 231 cycles */ #define NRETRIES 5 -static inline int output_valid(void) +/* initialised to false */ +static bool juno_trng_initialized; + +static bool output_valid(void) { int i; @@ -25,59 +30,58 @@ static inline int output_valid(void) val = mmio_read_32(TRNG_BASE + TRNG_STATUS); if (val & 1U) - break; + return true; } - if (i >= NRETRIES) - return 0; /* No output data available. */ - return 1; + return false; /* No output data available. */ } /* - * This function fills `buf` with `len` bytes of entropy. + * This function fills `buf` with 8 bytes of entropy. * It uses the Trusted Entropy Source peripheral on Juno. - * Returns 0 when the buffer has been filled with entropy - * successfully and -1 otherwise. + * Returns 'true' when the buffer has been filled with entropy + * successfully, or 'false' otherwise. */ -int juno_getentropy(void *buf, size_t len) +bool juno_getentropy(uint64_t *buf) { - uint8_t *bp = buf; + uint64_t ret; assert(buf); - assert(len); - assert(!check_uptr_overflow((uintptr_t)bp, len)); - - /* Disable interrupt mode. */ - mmio_write_32(TRNG_BASE + TRNG_INTMASK, 0); - /* Program TRNG to sample for `NSAMPLE_CLOCKS`. */ - mmio_write_32(TRNG_BASE + TRNG_CONFIG, NSAMPLE_CLOCKS); + assert(!check_uptr_overflow((uintptr_t)buf, sizeof(*buf))); + + if (!juno_trng_initialized) { + /* Disable interrupt mode. */ + mmio_write_32(TRNG_BASE + TRNG_INTMASK, 0); + /* Program TRNG to sample for `NSAMPLE_CLOCKS`. */ + mmio_write_32(TRNG_BASE + TRNG_CONFIG, NSAMPLE_CLOCKS); + /* Abort any potentially pending sampling. */ + mmio_write_32(TRNG_BASE + TRNG_CONTROL, 2); + /* Reset TRNG outputs. */ + mmio_write_32(TRNG_BASE + TRNG_STATUS, 1); - while (len > 0) { - int i; + juno_trng_initialized = true; + } + if (!output_valid()) { /* Start TRNG. */ mmio_write_32(TRNG_BASE + TRNG_CONTROL, 1); - /* Check if output is valid. */ if (!output_valid()) - return -1; - - /* Fill entropy buffer. */ - for (i = 0; i < TRNG_NOUTPUTS; i++) { - size_t n; - uint32_t val; - - val = mmio_read_32(TRNG_BASE + i * sizeof(uint32_t)); - n = MIN(len, sizeof(uint32_t)); - memcpy(bp, &val, n); - bp += n; - len -= n; - if (len == 0) - break; - } - - /* Reset TRNG outputs. */ - mmio_write_32(TRNG_BASE + TRNG_STATUS, 1); + return false; } - return 0; + /* XOR each two 32-bit registers together, combine the pairs */ + ret = mmio_read_32(TRNG_BASE + 0); + ret ^= mmio_read_32(TRNG_BASE + 4); + ret <<= 32; + + ret |= mmio_read_32(TRNG_BASE + 8); + ret ^= mmio_read_32(TRNG_BASE + 12); + *buf = ret; + + /* Acknowledge current cycle, clear output registers. */ + mmio_write_32(TRNG_BASE + TRNG_STATUS, 1); + /* Trigger next TRNG cycle. */ + mmio_write_32(TRNG_BASE + TRNG_CONTROL, 1); + + return true; } diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk index 78704b583e..61cfb610c4 100644 --- a/plat/arm/board/juno/platform.mk +++ b/plat/arm/board/juno/platform.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -108,7 +108,7 @@ ifeq ($(USE_ROMLIB),1) all : bl1_romlib.bin endif -bl1_romlib.bin : $(BUILD_PLAT)/bl1.bin $(BUILD_PLAT)/romlib/romlib.bin +bl1_romlib.bin : $(BUILD_PLAT)/bl1.bin romlib.bin @echo "Building combined BL1 and ROMLIB binary for Juno $@" ./lib/romlib/gen_combined_bl1_romlib.sh -o bl1_romlib.bin $(BUILD_PLAT) diff --git a/plat/arm/board/morello/morello_bl31_setup.c b/plat/arm/board/morello/morello_bl31_setup.c index 5b91e87e1b..59dd37b170 100644 --- a/plat/arm/board/morello/morello_bl31_setup.c +++ b/plat/arm/board/morello/morello_bl31_setup.c @@ -8,6 +8,7 @@ #include <drivers/arm/css/css_mhu_doorbell.h> #include <drivers/arm/css/scmi.h> #include <drivers/arm/css/sds.h> +#include <lib/cassert.h> #include <plat/arm/common/plat_arm.h> #include "morello_def.h" @@ -17,18 +18,21 @@ * Platform information structure stored in SDS. * This structure holds information about platform's DDR * size which is an information about multichip setup - * - multichip mode - * - slave_count - * - Local DDR size in GB, DDR memory in master board - * - Remote DDR size in GB, DDR memory in slave board + * - Local DDR size in bytes, DDR memory in master board + * - Remote DDR size in bytes, DDR memory in slave board + * - slave_count + * - multichip mode */ struct morello_plat_info { - bool multichip_mode; + uint64_t local_ddr_size; + uint64_t remote_ddr_size; uint8_t slave_count; - uint8_t local_ddr_size; - uint8_t remote_ddr_size; + bool multichip_mode; } __packed; +/* Compile time assertion to ensure the size of structure is 18 bytes */ +CASSERT(sizeof(struct morello_plat_info) == MORELLO_SDS_PLATFORM_INFO_SIZE, + assert_invalid_plat_info_size); /* * BL33 image information structure stored in SDS. * This structure holds the source & destination addresses and @@ -80,6 +84,7 @@ void bl31_platform_setup(void) int ret; struct morello_plat_info plat_info; struct morello_bl33_info bl33_info; + struct morello_plat_info *copy_dest; ret = sds_init(); if (ret != SDS_OK) { @@ -99,8 +104,8 @@ void bl31_platform_setup(void) /* Validate plat_info SDS */ if ((plat_info.local_ddr_size == 0U) - || (plat_info.local_ddr_size > MORELLO_MAX_DDR_CAPACITY_GB) - || (plat_info.remote_ddr_size > MORELLO_MAX_DDR_CAPACITY_GB) + || (plat_info.local_ddr_size > MORELLO_MAX_DDR_CAPACITY) + || (plat_info.remote_ddr_size > MORELLO_MAX_DDR_CAPACITY) || (plat_info.slave_count > MORELLO_MAX_SLAVE_COUNT)) { ERROR("platform info SDS is corrupted\n"); panic(); @@ -127,5 +132,6 @@ void bl31_platform_setup(void) * and platform information should be passed to BL33 using NT_FW_CONFIG * passing mechanism. */ - mmio_write_32(MORELLO_PLATFORM_INFO_BASE, *(uint32_t *)&plat_info); + copy_dest = (struct morello_plat_info *)MORELLO_PLATFORM_INFO_BASE; + *copy_dest = plat_info; } diff --git a/plat/arm/board/morello/morello_def.h b/plat/arm/board/morello/morello_def.h index 09db3032b3..793729b99f 100644 --- a/plat/arm/board/morello/morello_def.h +++ b/plat/arm/board/morello/morello_def.h @@ -18,8 +18,8 @@ /* SDS Platform information defines */ #define MORELLO_SDS_PLATFORM_INFO_STRUCT_ID U(8) #define MORELLO_SDS_PLATFORM_INFO_OFFSET U(0) -#define MORELLO_SDS_PLATFORM_INFO_SIZE U(4) -#define MORELLO_MAX_DDR_CAPACITY_GB U(64) +#define MORELLO_SDS_PLATFORM_INFO_SIZE U(18) +#define MORELLO_MAX_DDR_CAPACITY U(0x1000000000) #define MORELLO_MAX_SLAVE_COUNT U(16) /* SDS BL33 image information defines */ @@ -28,6 +28,6 @@ #define MORELLO_SDS_BL33_INFO_SIZE U(12) /* Base address of non-secure SRAM where Platform information will be filled */ -#define MORELLO_PLATFORM_INFO_BASE UL(0x06008000) +#define MORELLO_PLATFORM_INFO_BASE UL(0x06000000) #endif /* MORELLO_DEF_H */ diff --git a/plat/arm/board/morello/platform.mk b/plat/arm/board/morello/platform.mk index 2a23bc60fe..fc7d4d3637 100644 --- a/plat/arm/board/morello/platform.mk +++ b/plat/arm/board/morello/platform.mk @@ -65,5 +65,3 @@ USE_COHERENT_MEM := 0 include plat/arm/common/arm_common.mk include plat/arm/css/common/css_common.mk include plat/arm/board/common/board_common.mk - -override ERRATA_N1_1542419 := 1 diff --git a/plat/arm/board/n1sdp/platform.mk b/plat/arm/board/n1sdp/platform.mk index 4b621e3c02..f20397acde 100644 --- a/plat/arm/board/n1sdp/platform.mk +++ b/plat/arm/board/n1sdp/platform.mk @@ -69,7 +69,7 @@ HW_ASSISTED_COHERENCY := 1 USE_COHERENT_MEM := 0 # Enable the flag since N1SDP has a system level cache -NEOVERSE_N1_EXTERNAL_LLC := 1 +NEOVERSE_Nx_EXTERNAL_LLC := 1 include plat/arm/common/arm_common.mk include plat/arm/css/common/css_common.mk include plat/arm/board/common/board_common.mk diff --git a/plat/arm/board/rde1edge/include/platform_def.h b/plat/arm/board/rde1edge/include/platform_def.h index 3fb640972a..c39fe2b69b 100644 --- a/plat/arm/board/rde1edge/include/platform_def.h +++ b/plat/arm/board/rde1edge/include/platform_def.h @@ -9,7 +9,7 @@ #include <lib/utils_def.h> -#include <sgi_base_platform_def.h> +#include <sgi_soc_platform_def.h> #define PLAT_ARM_CLUSTER_COUNT U(2) #define CSS_SGI_MAX_CPUS_PER_CLUSTER U(8) diff --git a/plat/arm/board/rde1edge/platform.mk b/plat/arm/board/rde1edge/platform.mk index a7c043413a..53074f495e 100644 --- a/plat/arm/board/rde1edge/platform.mk +++ b/plat/arm/board/rde1edge/platform.mk @@ -12,6 +12,8 @@ PLAT_INCLUDES += -I${RDE1EDGE_BASE}/include/ SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_e1.S +PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c + BL1_SOURCES += ${SGI_CPU_SOURCES} \ ${RDE1EDGE_BASE}/rde1edge_err.c diff --git a/plat/arm/board/rdn1edge/include/platform_def.h b/plat/arm/board/rdn1edge/include/platform_def.h index ab63e23ece..b167c46e0d 100644 --- a/plat/arm/board/rdn1edge/include/platform_def.h +++ b/plat/arm/board/rdn1edge/include/platform_def.h @@ -9,7 +9,7 @@ #include <lib/utils_def.h> -#include <sgi_base_platform_def.h> +#include <sgi_soc_platform_def.h> #define PLAT_ARM_CLUSTER_COUNT U(2) #define CSS_SGI_MAX_CPUS_PER_CLUSTER U(4) diff --git a/plat/arm/board/rdn1edge/platform.mk b/plat/arm/board/rdn1edge/platform.mk index b3134262ea..d65854f8d0 100644 --- a/plat/arm/board/rdn1edge/platform.mk +++ b/plat/arm/board/rdn1edge/platform.mk @@ -15,6 +15,8 @@ PLAT_INCLUDES += -I${RDN1EDGE_BASE}/include/ SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_n1.S +PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c + BL1_SOURCES += ${SGI_CPU_SOURCES} \ ${RDN1EDGE_BASE}/rdn1edge_err.c diff --git a/plat/arm/board/rdn1edge/rdn1edge_plat.c b/plat/arm/board/rdn1edge/rdn1edge_plat.c index f62c6f402b..1dbbf26da2 100644 --- a/plat/arm/board/rdn1edge/rdn1edge_plat.c +++ b/plat/arm/board/rdn1edge/rdn1edge_plat.c @@ -8,7 +8,7 @@ #include <drivers/arm/gic600_multichip.h> #include <plat/arm/common/plat_arm.h> #include <plat/common/platform.h> -#include <sgi_base_platform_def.h> +#include <sgi_soc_platform_def.h> #include <sgi_plat.h> #if defined(IMAGE_BL31) diff --git a/plat/arm/board/rddaniel/fdts/rddaniel_fw_config.dts b/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts index 9c9cefe87f..9c9cefe87f 100644 --- a/plat/arm/board/rddaniel/fdts/rddaniel_fw_config.dts +++ b/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts diff --git a/plat/arm/board/rddaniel/fdts/rddaniel_nt_fw_config.dts b/plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts index 4d4580d68b..bbc36fc149 100644 --- a/plat/arm/board/rddaniel/fdts/rddaniel_nt_fw_config.dts +++ b/plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts @@ -7,7 +7,7 @@ /dts-v1/; / { /* compatible string */ - compatible = "arm,rd-daniel"; + compatible = "arm,rd-n2"; /* * Place holder for system-id node with default values. The diff --git a/plat/arm/board/rddaniel/fdts/rddaniel_tb_fw_config.dts b/plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts index 49eda2735f..49eda2735f 100644 --- a/plat/arm/board/rddaniel/fdts/rddaniel_tb_fw_config.dts +++ b/plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts diff --git a/plat/arm/board/rdn2/include/platform_def.h b/plat/arm/board/rdn2/include/platform_def.h new file mode 100644 index 0000000000..3f753f73fe --- /dev/null +++ b/plat/arm/board/rdn2/include/platform_def.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <lib/utils_def.h> + +#include <sgi_soc_platform_def_v2.h> + +#define PLAT_ARM_CLUSTER_COUNT U(16) +#define CSS_SGI_MAX_CPUS_PER_CLUSTER U(1) +#define CSS_SGI_MAX_PE_PER_CPU U(1) + +#define PLAT_CSS_MHU_BASE UL(0x2A920000) +#define PLAT_MHUV2_BASE PLAT_CSS_MHU_BASE + +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2 +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1 + +/* TZC Related Constants */ +#define PLAT_ARM_TZC_BASE UL(0x10720000) +#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0) + +#define TZC400_OFFSET UL(0x1000000) +#define TZC400_COUNT U(8) + +#define TZC400_BASE(n) (PLAT_ARM_TZC_BASE + \ + (n * TZC400_OFFSET)) + +#define TZC_NSAID_ALL_AP U(0) +#define TZC_NSAID_PCI U(1) +#define TZC_NSAID_HDLCD0 U(2) +#define TZC_NSAID_CLCD U(7) +#define TZC_NSAID_AP U(9) +#define TZC_NSAID_VIRTIO U(15) + +#define PLAT_ARM_TZC_NS_DEV_ACCESS \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_ALL_AP)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_HDLCD0)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_PCI)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_AP)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_CLCD)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_VIRTIO)) + +/* + * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes + */ +#ifdef __aarch64__ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 42) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 42) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#endif + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE UL(0x30000000) +#define PLAT_ARM_GICC_BASE UL(0x2C000000) +#define PLAT_ARM_GICR_BASE UL(0x301C0000) + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/arm/board/rdn2/platform.mk b/plat/arm/board/rdn2/platform.mk new file mode 100644 index 0000000000..03771dc3d1 --- /dev/null +++ b/plat/arm/board/rdn2/platform.mk @@ -0,0 +1,60 @@ +# Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# RD-N2 platform uses GIC-Clayton which is based on GICv4.1 +GIC_ENABLE_V4_EXTN := 1 + +include plat/arm/css/sgi/sgi-common.mk + +RDN2_BASE = plat/arm/board/rdn2 + +PLAT_INCLUDES += -I${RDN2_BASE}/include/ + +SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_n2.S + +PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat_v2.c + +BL1_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDN2_BASE}/rdn2_err.c + +BL2_SOURCES += ${RDN2_BASE}/rdn2_plat.c \ + ${RDN2_BASE}/rdn2_security.c \ + ${RDN2_BASE}/rdn2_err.c \ + lib/utils/mem_region.c \ + drivers/arm/tzc/tzc400.c \ + plat/arm/common/arm_tzc400.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +BL31_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDN2_BASE}/rdn2_plat.c \ + ${RDN2_BASE}/rdn2_topology.c \ + drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +BL1_SOURCES += ${RDN2_BASE}/rdn2_trusted_boot.c +BL2_SOURCES += ${RDN2_BASE}/rdn2_trusted_boot.c +endif + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += ${RDN2_BASE}/fdts/${PLAT}_fw_config.dts \ + ${RDN2_BASE}/fdts/${PLAT}_tb_fw_config.dts +FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) + +FDT_SOURCES += ${RDN2_BASE}/fdts/${PLAT}_nt_fw_config.dts +NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb + +# Add the NT_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config)) + +override CTX_INCLUDE_AARCH32_REGS := 0 +override ENABLE_AMU := 1 diff --git a/plat/arm/board/rddaniel/rddaniel_err.c b/plat/arm/board/rdn2/rdn2_err.c index 5e10942199..802ac21f6f 100644 --- a/plat/arm/board/rddaniel/rddaniel_err.c +++ b/plat/arm/board/rdn2/rdn2_err.c @@ -7,7 +7,7 @@ #include <plat/arm/common/plat_arm.h> /* - * rddaniel error handler + * rdn2 error handler */ void __dead2 plat_arm_error_handler(int err) { diff --git a/plat/arm/board/rdn2/rdn2_plat.c b/plat/arm/board/rdn2/rdn2_plat.c new file mode 100644 index 0000000000..5bf14e3a16 --- /dev/null +++ b/plat/arm/board/rdn2/rdn2_plat.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/common/platform.h> +#include <sgi_plat.h> + +unsigned int plat_arm_sgi_get_platform_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET) + & SID_SYSTEM_ID_PART_NUM_MASK; +} + +unsigned int plat_arm_sgi_get_config_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET); +} + +unsigned int plat_arm_sgi_get_multi_chip_mode(void) +{ + return (mmio_read_32(SID_REG_BASE + SID_NODE_ID_OFFSET) & + SID_MULTI_CHIP_MODE_MASK) >> + SID_MULTI_CHIP_MODE_SHIFT; +} + +void bl31_platform_setup(void) +{ + sgi_bl31_common_platform_setup(); +} diff --git a/plat/arm/board/rdn2/rdn2_security.c b/plat/arm/board/rdn2/rdn2_security.c new file mode 100644 index 0000000000..9568b60cd4 --- /dev/null +++ b/plat/arm/board/rdn2/rdn2_security.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> +#include <platform_def.h> + + +static const arm_tzc_regions_info_t tzc_regions[] = { + ARM_TZC_REGIONS_DEF, + {} +}; + +/* Initialize the secure environment */ +void plat_arm_security_setup(void) +{ + + int i; + + for (i = 0; i < TZC400_COUNT; i++) + arm_tzc400_setup(TZC400_BASE(i), tzc_regions); + +} diff --git a/plat/arm/board/rdn2/rdn2_topology.c b/plat/arm/board/rdn2/rdn2_topology.c new file mode 100644 index 0000000000..5c2e287cbe --- /dev/null +++ b/plat/arm/board/rdn2/rdn2_topology.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> +#include <plat/arm/css/common/css_pm.h> + +/****************************************************************************** + * The power domain tree descriptor. + ******************************************************************************/ +const unsigned char rd_n2_pd_tree_desc[] = { + PLAT_ARM_CLUSTER_COUNT, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, +}; + +/******************************************************************************* + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return rd_n2_pd_tree_desc; +} + +/******************************************************************************* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + ******************************************************************************/ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = { + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x4)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x8)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x9)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xA)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xB)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xC)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xD)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xE)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xF)), +}; diff --git a/plat/arm/board/rddaniel/rddaniel_trusted_boot.c b/plat/arm/board/rdn2/rdn2_trusted_boot.c index 4592b8fbaf..4592b8fbaf 100644 --- a/plat/arm/board/rddaniel/rddaniel_trusted_boot.c +++ b/plat/arm/board/rdn2/rdn2_trusted_boot.c diff --git a/plat/arm/board/rddanielxlr/fdts/rddanielxlr_fw_config.dts b/plat/arm/board/rdv1/fdts/rdv1_fw_config.dts index 9c9cefe87f..9c9cefe87f 100644 --- a/plat/arm/board/rddanielxlr/fdts/rddanielxlr_fw_config.dts +++ b/plat/arm/board/rdv1/fdts/rdv1_fw_config.dts diff --git a/plat/arm/board/rddanielxlr/fdts/rddanielxlr_nt_fw_config.dts b/plat/arm/board/rdv1/fdts/rdv1_nt_fw_config.dts index 42d07a4504..62ba2c3f2f 100644 --- a/plat/arm/board/rddanielxlr/fdts/rddanielxlr_nt_fw_config.dts +++ b/plat/arm/board/rdv1/fdts/rdv1_nt_fw_config.dts @@ -7,7 +7,7 @@ /dts-v1/; / { /* compatible string */ - compatible = "arm,rd-daniel-xlr"; + compatible = "arm,rd-v1"; /* * Place holder for system-id node with default values. The diff --git a/plat/arm/board/rddanielxlr/fdts/rddanielxlr_tb_fw_config.dts b/plat/arm/board/rdv1/fdts/rdv1_tb_fw_config.dts index 49eda2735f..49eda2735f 100644 --- a/plat/arm/board/rddanielxlr/fdts/rddanielxlr_tb_fw_config.dts +++ b/plat/arm/board/rdv1/fdts/rdv1_tb_fw_config.dts diff --git a/plat/arm/board/rddaniel/include/platform_def.h b/plat/arm/board/rdv1/include/platform_def.h index a118ca38af..5b98b4e8c4 100644 --- a/plat/arm/board/rddaniel/include/platform_def.h +++ b/plat/arm/board/rdv1/include/platform_def.h @@ -9,7 +9,7 @@ #include <lib/utils_def.h> -#include <sgi_base_platform_def.h> +#include <sgi_soc_platform_def.h> #define PLAT_ARM_CLUSTER_COUNT U(16) #define CSS_SGI_MAX_CPUS_PER_CLUSTER U(1) diff --git a/plat/arm/board/rddaniel/platform.mk b/plat/arm/board/rdv1/platform.mk index 7422d638a8..2ffd139c96 100644 --- a/plat/arm/board/rddaniel/platform.mk +++ b/plat/arm/board/rdv1/platform.mk @@ -1,45 +1,47 @@ -# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # -# RD-Daniel platform uses GIC-Clayton which is based on GICv4.1 +# RD-V1 platform uses GIC-Clayton which is based on GICv4.1 GIC_ENABLE_V4_EXTN := 1 include plat/arm/css/sgi/sgi-common.mk -RDDANIEL_BASE = plat/arm/board/rddaniel +RDV1_BASE = plat/arm/board/rdv1 -PLAT_INCLUDES += -I${RDDANIEL_BASE}/include/ +PLAT_INCLUDES += -I${RDV1_BASE}/include/ SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_v1.S +PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c + BL1_SOURCES += ${SGI_CPU_SOURCES} \ - ${RDDANIEL_BASE}/rddaniel_err.c + ${RDV1_BASE}/rdv1_err.c -BL2_SOURCES += ${RDDANIEL_BASE}/rddaniel_plat.c \ - ${RDDANIEL_BASE}/rddaniel_security.c \ - ${RDDANIEL_BASE}/rddaniel_err.c \ +BL2_SOURCES += ${RDV1_BASE}/rdv1_plat.c \ + ${RDV1_BASE}/rdv1_security.c \ + ${RDV1_BASE}/rdv1_err.c \ lib/utils/mem_region.c \ drivers/arm/tzc/tzc400.c \ plat/arm/common/arm_tzc400.c \ plat/arm/common/arm_nor_psci_mem_protect.c BL31_SOURCES += ${SGI_CPU_SOURCES} \ - ${RDDANIEL_BASE}/rddaniel_plat.c \ - ${RDDANIEL_BASE}/rddaniel_topology.c \ + ${RDV1_BASE}/rdv1_plat.c \ + ${RDV1_BASE}/rdv1_topology.c \ drivers/cfi/v2m/v2m_flash.c \ lib/utils/mem_region.c \ plat/arm/common/arm_nor_psci_mem_protect.c ifeq (${TRUSTED_BOARD_BOOT}, 1) -BL1_SOURCES += ${RDDANIEL_BASE}/rddaniel_trusted_boot.c -BL2_SOURCES += ${RDDANIEL_BASE}/rddaniel_trusted_boot.c +BL1_SOURCES += ${RDV1_BASE}/rdv1_trusted_boot.c +BL2_SOURCES += ${RDV1_BASE}/rdv1_trusted_boot.c endif # Add the FDT_SOURCES and options for Dynamic Config -FDT_SOURCES += ${RDDANIEL_BASE}/fdts/${PLAT}_fw_config.dts \ - ${RDDANIEL_BASE}/fdts/${PLAT}_tb_fw_config.dts +FDT_SOURCES += ${RDV1_BASE}/fdts/${PLAT}_fw_config.dts \ + ${RDV1_BASE}/fdts/${PLAT}_tb_fw_config.dts FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb @@ -48,10 +50,11 @@ $(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) # Add the TB_FW_CONFIG to FIP and specify the same to certtool $(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) -FDT_SOURCES += ${RDDANIEL_BASE}/fdts/${PLAT}_nt_fw_config.dts +FDT_SOURCES += ${RDV1_BASE}/fdts/${PLAT}_nt_fw_config.dts NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb # Add the NT_FW_CONFIG to FIP and specify the same to certtool $(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG})) override CTX_INCLUDE_AARCH32_REGS := 0 +override ENABLE_AMU := 1 diff --git a/plat/arm/board/rdv1/rdv1_err.c b/plat/arm/board/rdv1/rdv1_err.c new file mode 100644 index 0000000000..68f9a3ef67 --- /dev/null +++ b/plat/arm/board/rdv1/rdv1_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * rdv1 error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (1) { + wfi(); + } +} diff --git a/plat/arm/board/rddaniel/rddaniel_plat.c b/plat/arm/board/rdv1/rdv1_plat.c index ab5251e511..ab5251e511 100644 --- a/plat/arm/board/rddaniel/rddaniel_plat.c +++ b/plat/arm/board/rdv1/rdv1_plat.c diff --git a/plat/arm/board/rddaniel/rddaniel_security.c b/plat/arm/board/rdv1/rdv1_security.c index 1247db8605..1247db8605 100644 --- a/plat/arm/board/rddaniel/rddaniel_security.c +++ b/plat/arm/board/rdv1/rdv1_security.c diff --git a/plat/arm/board/rddaniel/rddaniel_topology.c b/plat/arm/board/rdv1/rdv1_topology.c index 55f5e04da5..ab64fd8d00 100644 --- a/plat/arm/board/rddaniel/rddaniel_topology.c +++ b/plat/arm/board/rdv1/rdv1_topology.c @@ -10,7 +10,7 @@ /****************************************************************************** * The power domain tree descriptor. ******************************************************************************/ -const unsigned char rd_daniel_pd_tree_desc[] = { +const unsigned char rd_v1_pd_tree_desc[] = { PLAT_ARM_CLUSTER_COUNT, CSS_SGI_MAX_CPUS_PER_CLUSTER, CSS_SGI_MAX_CPUS_PER_CLUSTER, @@ -35,7 +35,7 @@ const unsigned char rd_daniel_pd_tree_desc[] = { ******************************************************************************/ const unsigned char *plat_get_power_domain_tree_desc(void) { - return rd_daniel_pd_tree_desc; + return rd_v1_pd_tree_desc; } /******************************************************************************* diff --git a/plat/arm/board/rddanielxlr/rddanielxlr_trusted_boot.c b/plat/arm/board/rdv1/rdv1_trusted_boot.c index 4592b8fbaf..4592b8fbaf 100644 --- a/plat/arm/board/rddanielxlr/rddanielxlr_trusted_boot.c +++ b/plat/arm/board/rdv1/rdv1_trusted_boot.c diff --git a/plat/arm/board/rdv1mc/fdts/rdv1mc_fw_config.dts b/plat/arm/board/rdv1mc/fdts/rdv1mc_fw_config.dts new file mode 100644 index 0000000000..9c9cefe87f --- /dev/null +++ b/plat/arm/board/rdv1mc/fdts/rdv1mc_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/tbbr/tbbr_img_def.h> + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = <TB_FW_CONFIG_ID>; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = <NT_FW_CONFIG_ID>; + }; + }; +}; diff --git a/plat/arm/board/rdv1mc/fdts/rdv1mc_nt_fw_config.dts b/plat/arm/board/rdv1mc/fdts/rdv1mc_nt_fw_config.dts new file mode 100644 index 0000000000..71c7db3cbd --- /dev/null +++ b/plat/arm/board/rdv1mc/fdts/rdv1mc_nt_fw_config.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + /* compatible string */ + compatible = "arm,rd-v1-mc"; + + /* + * Place holder for system-id node with default values. The + * value of platform-id and config-id will be set to the + * correct values during the BL2 stage of boot. + */ + system-id { + platform-id = <0x0>; + config-id = <0x0>; + multi-chip-mode = <0x0>; + }; +}; diff --git a/plat/arm/board/rdv1mc/fdts/rdv1mc_tb_fw_config.dts b/plat/arm/board/rdv1mc/fdts/rdv1mc_tb_fw_config.dts new file mode 100644 index 0000000000..49eda2735f --- /dev/null +++ b/plat/arm/board/rdv1mc/fdts/rdv1mc_tb_fw_config.dts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; +}; diff --git a/plat/arm/board/rddanielxlr/include/platform_def.h b/plat/arm/board/rdv1mc/include/platform_def.h index b1376b85d6..112b2102ba 100644 --- a/plat/arm/board/rddanielxlr/include/platform_def.h +++ b/plat/arm/board/rdv1mc/include/platform_def.h @@ -8,7 +8,7 @@ #define PLATFORM_DEF_H #include <lib/utils_def.h> -#include <sgi_base_platform_def.h> +#include <sgi_soc_platform_def.h> #define PLAT_ARM_CLUSTER_COUNT U(4) #define CSS_SGI_MAX_CPUS_PER_CLUSTER U(1) diff --git a/plat/arm/board/rddanielxlr/platform.mk b/plat/arm/board/rdv1mc/platform.mk index 8cbad525c9..50728416ae 100644 --- a/plat/arm/board/rddanielxlr/platform.mk +++ b/plat/arm/board/rdv1mc/platform.mk @@ -9,40 +9,42 @@ GICV3_IMPL_GIC600_MULTICHIP := 1 include plat/arm/css/sgi/sgi-common.mk -RDDANIELXLR_BASE = plat/arm/board/rddanielxlr +RDV1MC_BASE = plat/arm/board/rdv1mc -PLAT_INCLUDES += -I${RDDANIELXLR_BASE}/include/ +PLAT_INCLUDES += -I${RDV1MC_BASE}/include/ SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_v1.S +PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c + BL1_SOURCES += ${SGI_CPU_SOURCES} \ - ${RDDANIELXLR_BASE}/rddanielxlr_err.c + ${RDV1MC_BASE}/rdv1mc_err.c -BL2_SOURCES += ${RDDANIELXLR_BASE}/rddanielxlr_plat.c \ - ${RDDANIELXLR_BASE}/rddanielxlr_security.c \ - ${RDDANIELXLR_BASE}/rddanielxlr_err.c \ +BL2_SOURCES += ${RDV1MC_BASE}/rdv1mc_plat.c \ + ${RDV1MC_BASE}/rdv1mc_security.c \ + ${RDV1MC_BASE}/rdv1mc_err.c \ lib/utils/mem_region.c \ plat/arm/common/arm_nor_psci_mem_protect.c BL31_SOURCES += ${SGI_CPU_SOURCES} \ - ${RDDANIELXLR_BASE}/rddanielxlr_plat.c \ - ${RDDANIELXLR_BASE}/rddanielxlr_topology.c \ + ${RDV1MC_BASE}/rdv1mc_plat.c \ + ${RDV1MC_BASE}/rdv1mc_topology.c \ drivers/cfi/v2m/v2m_flash.c \ drivers/arm/gic/v3/gic600_multichip.c \ lib/utils/mem_region.c \ plat/arm/common/arm_nor_psci_mem_protect.c ifeq (${TRUSTED_BOARD_BOOT}, 1) -BL1_SOURCES += ${RDDANIELXLR_BASE}/rddanielxlr_trusted_boot.c -BL2_SOURCES += ${RDDANIELXLR_BASE}/rddanielxlr_trusted_boot.c +BL1_SOURCES += ${RDV1MC_BASE}/rdv1mc_trusted_boot.c +BL2_SOURCES += ${RDV1MC_BASE}/rdv1mc_trusted_boot.c endif # Enable dynamic addition of MMAP regions in BL31 BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC # Add the FDT_SOURCES and options for Dynamic Config -FDT_SOURCES += ${RDDANIELXLR_BASE}/fdts/${PLAT}_fw_config.dts \ - ${RDDANIELXLR_BASE}/fdts/${PLAT}_tb_fw_config.dts +FDT_SOURCES += ${RDV1MC_BASE}/fdts/${PLAT}_fw_config.dts \ + ${RDV1MC_BASE}/fdts/${PLAT}_tb_fw_config.dts FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb @@ -53,11 +55,11 @@ $(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) $(eval $(call CREATE_SEQ,SEQ,4)) ifneq ($(CSS_SGI_CHIP_COUNT),$(filter $(CSS_SGI_CHIP_COUNT),$(SEQ))) - $(error "Chip count for RD-Daniel Config-XLR should be either $(SEQ) \ + $(error "Chip count for RD-V1-MC should be either $(SEQ) \ currently it is set to ${CSS_SGI_CHIP_COUNT}.") endif -FDT_SOURCES += ${RDDANIELXLR_BASE}/fdts/${PLAT}_nt_fw_config.dts +FDT_SOURCES += ${RDV1MC_BASE}/fdts/${PLAT}_nt_fw_config.dts NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb # Add the NT_FW_CONFIG to FIP and specify the same to certtool diff --git a/plat/arm/board/rddanielxlr/rddanielxlr_err.c b/plat/arm/board/rdv1mc/rdv1mc_err.c index bff57cdae4..755a5034e2 100644 --- a/plat/arm/board/rddanielxlr/rddanielxlr_err.c +++ b/plat/arm/board/rdv1mc/rdv1mc_err.c @@ -7,7 +7,7 @@ #include <plat/arm/common/plat_arm.h> /* - * rddanielxlr error handler + * rdv1mc error handler */ void __dead2 plat_arm_error_handler(int err) { diff --git a/plat/arm/board/rddanielxlr/rddanielxlr_plat.c b/plat/arm/board/rdv1mc/rdv1mc_plat.c index 4b5f16a4f7..d859400667 100644 --- a/plat/arm/board/rddanielxlr/rddanielxlr_plat.c +++ b/plat/arm/board/rdv1mc/rdv1mc_plat.c @@ -8,11 +8,11 @@ #include <drivers/arm/gic600_multichip.h> #include <plat/arm/common/plat_arm.h> #include <plat/common/platform.h> -#include <sgi_base_platform_def.h> +#include <sgi_soc_platform_def.h> #include <sgi_plat.h> #if defined(IMAGE_BL31) -static const mmap_region_t rddanielxlr_dynamic_mmap[] = { +static const mmap_region_t rdv1mc_dynamic_mmap[] = { ARM_MAP_SHARED_RAM_REMOTE_CHIP(1), CSS_SGI_MAP_DEVICE_REMOTE_CHIP(1), SOC_CSS_MAP_DEVICE_REMOTE_CHIP(1), @@ -28,7 +28,7 @@ static const mmap_region_t rddanielxlr_dynamic_mmap[] = { #endif }; -static struct gic600_multichip_data rddanielxlr_multichip_data __init = { +static struct gic600_multichip_data rdv1mc_multichip_data __init = { .rt_owner_base = PLAT_ARM_GICD_BASE, .rt_owner = 0, .chip_count = CSS_SGI_CHIP_COUNT, @@ -54,7 +54,7 @@ static struct gic600_multichip_data rddanielxlr_multichip_data __init = { } }; -static uintptr_t rddanielxlr_multichip_gicr_frames[] = { +static uintptr_t rdv1mc_multichip_gicr_frames[] = { /* Chip 0's GICR Base */ PLAT_ARM_GICR_BASE, /* Chip 1's GICR BASE */ @@ -106,14 +106,14 @@ void bl31_platform_setup(void) panic(); } else if ((plat_arm_sgi_get_multi_chip_mode() == 1) && (CSS_SGI_CHIP_COUNT > 1)) { - INFO("Enabling support for multi-chip in RD-Daniel Cfg-XLR\n"); + INFO("Enabling support for multi-chip in RD-V1-MC\n"); - for (i = 0; i < ARRAY_SIZE(rddanielxlr_dynamic_mmap); i++) { + for (i = 0; i < ARRAY_SIZE(rdv1mc_dynamic_mmap); i++) { ret = mmap_add_dynamic_region( - rddanielxlr_dynamic_mmap[i].base_pa, - rddanielxlr_dynamic_mmap[i].base_va, - rddanielxlr_dynamic_mmap[i].size, - rddanielxlr_dynamic_mmap[i].attr); + rdv1mc_dynamic_mmap[i].base_pa, + rdv1mc_dynamic_mmap[i].base_va, + rdv1mc_dynamic_mmap[i].size, + rdv1mc_dynamic_mmap[i].attr); if (ret != 0) { ERROR("Failed to add dynamic mmap entry " "(ret=%d)\n", ret); @@ -122,8 +122,8 @@ void bl31_platform_setup(void) } plat_arm_override_gicr_frames( - rddanielxlr_multichip_gicr_frames); - gic600_multichip_init(&rddanielxlr_multichip_data); + rdv1mc_multichip_gicr_frames); + gic600_multichip_init(&rdv1mc_multichip_data); } sgi_bl31_common_platform_setup(); diff --git a/plat/arm/board/rddanielxlr/rddanielxlr_security.c b/plat/arm/board/rdv1mc/rdv1mc_security.c index 541f800a84..541f800a84 100644 --- a/plat/arm/board/rddanielxlr/rddanielxlr_security.c +++ b/plat/arm/board/rdv1mc/rdv1mc_security.c diff --git a/plat/arm/board/rddanielxlr/rddanielxlr_topology.c b/plat/arm/board/rdv1mc/rdv1mc_topology.c index 610e667cee..4486e5cfa3 100644 --- a/plat/arm/board/rddanielxlr/rddanielxlr_topology.c +++ b/plat/arm/board/rdv1mc/rdv1mc_topology.c @@ -12,7 +12,7 @@ /****************************************************************************** * The power domain tree descriptor. ******************************************************************************/ -const unsigned char rd_daniel_xlr_pd_tree_desc_multi_chip[] = { +const unsigned char rd_v1_mc_pd_tree_desc_multi_chip[] = { ((PLAT_ARM_CLUSTER_COUNT) * (CSS_SGI_CHIP_COUNT)), CSS_SGI_MAX_CPUS_PER_CLUSTER, CSS_SGI_MAX_CPUS_PER_CLUSTER, @@ -44,7 +44,7 @@ const unsigned char rd_daniel_xlr_pd_tree_desc_multi_chip[] = { const unsigned char *plat_get_power_domain_tree_desc(void) { if (plat_arm_sgi_get_multi_chip_mode() == 1) - return rd_daniel_xlr_pd_tree_desc_multi_chip; + return rd_v1_mc_pd_tree_desc_multi_chip; panic(); } diff --git a/plat/arm/board/rdv1mc/rdv1mc_trusted_boot.c b/plat/arm/board/rdv1mc/rdv1mc_trusted_boot.c new file mode 100644 index 0000000000..4592b8fbaf --- /dev/null +++ b/plat/arm/board/rdv1mc/rdv1mc_trusted_boot.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} diff --git a/plat/arm/board/sgi575/include/platform_def.h b/plat/arm/board/sgi575/include/platform_def.h index 95986cf4a3..c929334cdf 100644 --- a/plat/arm/board/sgi575/include/platform_def.h +++ b/plat/arm/board/sgi575/include/platform_def.h @@ -9,7 +9,7 @@ #include <lib/utils_def.h> -#include <sgi_base_platform_def.h> +#include <sgi_soc_platform_def.h> #define PLAT_ARM_CLUSTER_COUNT U(2) #define CSS_SGI_MAX_CPUS_PER_CLUSTER U(4) diff --git a/plat/arm/board/sgi575/platform.mk b/plat/arm/board/sgi575/platform.mk index 56f5733f17..89abcfe8ee 100644 --- a/plat/arm/board/sgi575/platform.mk +++ b/plat/arm/board/sgi575/platform.mk @@ -12,6 +12,8 @@ PLAT_INCLUDES += -I${SGI575_BASE}/include/ SGI_CPU_SOURCES := lib/cpus/aarch64/cortex_a75.S +PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c + BL1_SOURCES += ${SGI_CPU_SOURCES} \ ${SGI575_BASE}/sgi575_err.c diff --git a/plat/arm/board/tc0/fdts/tc0_spmc_manifest.dts b/plat/arm/board/tc0/fdts/tc0_spmc_manifest.dts index b6c543ade2..2f459b0139 100644 --- a/plat/arm/board/tc0/fdts/tc0_spmc_manifest.dts +++ b/plat/arm/board/tc0/fdts/tc0_spmc_manifest.dts @@ -20,30 +20,27 @@ binary_size = <0x80000>; }; - chosen { - linux,initrd-start = <0>; - linux,initrd-end = <0>; - }; - hypervisor { compatible = "hafnium,hafnium"; vm1 { is_ffa_partition; debug_name = "cactus-primary"; load_address = <0xfe000000>; + vcpu_count = <8>; + mem_size = <1048576>; }; vm2 { is_ffa_partition; debug_name = "cactus-secondary"; load_address = <0xfe100000>; - vcpu_count = <4>; + vcpu_count = <8>; mem_size = <1048576>; }; vm3 { is_ffa_partition; debug_name = "cactus-tertiary"; load_address = <0xfe200000>; - vcpu_count = <4>; + vcpu_count = <8>; mem_size = <1048576>; }; }; @@ -60,9 +57,37 @@ }; /* - * SPM(Hafnium) requires secondary cpu nodes are declared in + * SPMC (Hafnium) requires secondary cpu nodes are declared in * descending order */ + CPU7:cpu@700 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x700>; + enable-method = "psci"; + }; + + CPU6:cpu@600 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x600>; + enable-method = "psci"; + }; + + CPU5:cpu@500 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x500>; + enable-method = "psci"; + }; + + CPU4:cpu@400 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x400>; + enable-method = "psci"; + }; + CPU3:cpu@300 { device_type = "cpu"; compatible = "arm,armv8"; diff --git a/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts b/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts new file mode 100644 index 0000000000..221039c431 --- /dev/null +++ b/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/dts-v1/; + +/ { + compatible = "arm,ffa-core-manifest-1.0"; + #address-cells = <2>; + #size-cells = <1>; + + attribute { + spmc_id = <0x8000>; + maj_ver = <0x1>; + min_ver = <0x0>; + exec_state = <0x0>; + load_address = <0x0 0xfd000000>; + entrypoint = <0x0 0xfd000000>; + binary_size = <0x80000>; + }; + + hypervisor { + compatible = "hafnium,hafnium"; + vm1 { + is_ffa_partition; + debug_name = "op-tee"; + load_address = <0xfd280000>; + vcpu_count = <8>; + mem_size = <30928896>; /* 32MB TZC DRAM - SPMC region */ + }; + }; + + cpus { + #address-cells = <0x2>; + #size-cells = <0x0>; + + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x0>; + enable-method = "psci"; + }; + + /* + * SPMC (Hafnium) requires secondary cpu nodes are declared in + * descending order + */ + CPU7:cpu@700 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x700>; + enable-method = "psci"; + }; + + CPU6:cpu@600 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x600>; + enable-method = "psci"; + }; + + CPU5:cpu@500 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x500>; + enable-method = "psci"; + }; + + CPU4:cpu@400 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x400>; + enable-method = "psci"; + }; + + CPU3:cpu@300 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x300>; + enable-method = "psci"; + }; + + CPU2:cpu@200 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x200>; + enable-method = "psci"; + }; + + CPU1:cpu@100 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x100>; + enable-method = "psci"; + }; + }; + + /* 32MB of TC0_TZC_DRAM1_BASE */ + memory@fd000000 { + device_type = "memory"; + reg = <0x0 0xfd000000 0x2000000>; + }; +}; diff --git a/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts b/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts index 3df94bf92b..de5f95d5e2 100644 --- a/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts +++ b/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts @@ -27,6 +27,12 @@ secure-partitions { compatible = "arm,sp"; +#if OPTEE_SP_FW_CONFIG + op-tee { + uuid = <0x486178e0 0xe7f811e3 0xbc5e0002 0xa5d5c51b>; + load-address = <0xfd280000>; + }; +#else cactus-primary { uuid = <0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>; load-address = <0xfe000000>; @@ -43,5 +49,6 @@ uuid = <0x79b55c73 0x1d8c44b9 0x859361e1 0x770ad8d2>; load-address = <0xfe200000>; }; +#endif }; }; diff --git a/plat/arm/board/tc0/include/platform_def.h b/plat/arm/board/tc0/include/platform_def.h index 72a035f0ab..30b5ab7164 100644 --- a/plat/arm/board/tc0/include/platform_def.h +++ b/plat/arm/board/tc0/include/platform_def.h @@ -17,7 +17,7 @@ #include <plat/arm/soc/common/soc_css_def.h> #include <plat/common/common_def.h> -#define PLATFORM_CORE_COUNT 4 +#define PLATFORM_CORE_COUNT 8 #define PLAT_ARM_TRUSTED_SRAM_SIZE 0x00080000 /* 512 KB */ @@ -112,7 +112,7 @@ * little space for growth. */ #if TRUSTED_BOARD_BOOT -# define PLAT_ARM_MAX_BL2_SIZE 0x1E000 +# define PLAT_ARM_MAX_BL2_SIZE 0x20000 #else # define PLAT_ARM_MAX_BL2_SIZE 0x14000 #endif @@ -202,7 +202,7 @@ #define PLAT_ARM_SCMI_CHANNEL_COUNT 1 #define PLAT_ARM_CLUSTER_COUNT U(1) -#define PLAT_MAX_CPUS_PER_CLUSTER U(4) +#define PLAT_MAX_CPUS_PER_CLUSTER U(8) #define PLAT_MAX_PE_PER_CPU U(1) #define PLAT_CSS_MHU_BASE UL(0x45400000) diff --git a/plat/arm/board/tc0/platform.mk b/plat/arm/board/tc0/platform.mk index 5d2cc38c46..393d09cffa 100644 --- a/plat/arm/board/tc0/platform.mk +++ b/plat/arm/board/tc0/platform.mk @@ -43,7 +43,8 @@ TC0_BASE = plat/arm/board/tc0 PLAT_INCLUDES += -I${TC0_BASE}/include/ -TC0_CPU_SOURCES := lib/cpus/aarch64/cortex_matterhorn.S +TC0_CPU_SOURCES := lib/cpus/aarch64/cortex_klein.S \ + lib/cpus/aarch64/cortex_matterhorn.S INTERCONNECT_SOURCES := ${TC0_BASE}/tc0_interconnect.c @@ -86,8 +87,12 @@ $(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) $(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) ifeq (${SPD},spmd) -FDT_SOURCES += ${TC0_BASE}/fdts/${PLAT}_spmc_manifest.dts -TC0_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_spmc_manifest.dtb +ifeq ($(ARM_SPMC_MANIFEST_DTS),) +ARM_SPMC_MANIFEST_DTS := ${TC0_BASE}/fdts/${PLAT}_spmc_manifest.dts +endif + +FDT_SOURCES += ${ARM_SPMC_MANIFEST_DTS} +TC0_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/$(notdir $(basename ${ARM_SPMC_MANIFEST_DTS})).dtb # Add the TOS_FW_CONFIG to FIP and specify the same to certtool $(eval $(call TOOL_ADD_PAYLOAD,${TC0_TOS_FW_CONFIG},--tos-fw-config,${TC0_TOS_FW_CONFIG})) diff --git a/plat/arm/board/tc0/tc0_plat.c b/plat/arm/board/tc0/tc0_plat.c index e12ad56d81..b5698c0984 100644 --- a/plat/arm/board/tc0/tc0_plat.c +++ b/plat/arm/board/tc0/tc0_plat.c @@ -51,6 +51,10 @@ const mmap_region_t plat_arm_mmap[] = { #if TRUSTED_BOARD_BOOT && !BL2_AT_EL3 ARM_MAP_BL1_RW, #endif +#ifdef SPD_opteed + ARM_MAP_OPTEE_CORE_MEM, + ARM_OPTEE_PAGEABLE_LOAD_MEM, +#endif {0} }; #endif diff --git a/plat/arm/board/tc0/tc0_topology.c b/plat/arm/board/tc0/tc0_topology.c index 5478fbc329..8cfc3b50ee 100644 --- a/plat/arm/board/tc0/tc0_topology.c +++ b/plat/arm/board/tc0/tc0_topology.c @@ -33,6 +33,9 @@ const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = { (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)), (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)), (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x4)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)), }; /******************************************************************************* diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c index 8e74526346..926b8ec7cd 100644 --- a/plat/arm/css/common/css_pm.c +++ b/plat/arm/css/common/css_pm.c @@ -123,6 +123,9 @@ static void css_power_down_common(const psci_power_state_t *target_state) /* Prevent interrupts from spuriously waking up this cpu */ plat_arm_gic_cpuif_disable(); + /* Turn redistributor off */ + plat_arm_gic_redistif_off(); + /* Cluster is to be turned off, so disable coherency */ if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) { plat_arm_interconnect_exit_coherency(); diff --git a/plat/arm/css/sgi/include/sgi_base_platform_def.h b/plat/arm/css/sgi/include/sgi_base_platform_def.h index 159084f958..b805746de6 100644 --- a/plat/arm/css/sgi/include/sgi_base_platform_def.h +++ b/plat/arm/css/sgi/include/sgi_base_platform_def.h @@ -9,12 +9,9 @@ #include <lib/utils_def.h> #include <lib/xlat_tables/xlat_tables_defs.h> -#include <plat/arm/board/common/board_css_def.h> -#include <plat/arm/board/common/v2m_def.h> #include <plat/arm/common/arm_def.h> #include <plat/arm/common/arm_spm_def.h> #include <plat/arm/css/common/css_def.h> -#include <plat/arm/soc/common/soc_css_def.h> #include <plat/common/common_def.h> #define PLATFORM_CORE_COUNT (CSS_SGI_CHIP_COUNT * \ diff --git a/plat/arm/css/sgi/include/sgi_soc_css_def_v2.h b/plat/arm/css/sgi/include/sgi_soc_css_def_v2.h new file mode 100644 index 0000000000..03f107367f --- /dev/null +++ b/plat/arm/css/sgi/include/sgi_soc_css_def_v2.h @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGI_SOC_CSS_DEF_V2_H +#define SGI_SOC_CSS_DEF_V2_H + +#include <lib/utils_def.h> +#include <plat/common/common_def.h> + +/* + * Definitions common to all ARM CSS SoCs + */ + +/* Following covers ARM CSS SoC Peripherals */ + +#define SOC_SYSTEM_PERIPH_BASE UL(0x0C000000) +#define SOC_SYSTEM_PERIPH_SIZE UL(0x02000000) + +#define SOC_PLATFORM_PERIPH_BASE UL(0x0E000000) +#define SOC_PLATFORM_PERIPH_SIZE UL(0x02000000) + +#define SOC_CSS_PCIE_CONTROL_BASE UL(0x0ef20000) + +/* PL011 UART related constants */ +#define SOC_CSS_UART1_BASE UL(0x0ef80000) +#define SOC_CSS_UART0_BASE UL(0x0ef70000) + +/* Memory controller */ +#define SOC_MEMCNTRL_BASE UL(0x10000000) +#define SOC_MEMCNTRL_SIZE UL(0x10000000) + +#define SOC_CSS_UART0_CLK_IN_HZ UL(7372800) +#define SOC_CSS_UART1_CLK_IN_HZ UL(7372800) + +/* SoC NIC-400 Global Programmers View (GPV) */ +#define SOC_CSS_NIC400_BASE UL(0x0ED00000) + +#define SOC_CSS_NIC400_USB_EHCI U(0) +#define SOC_CSS_NIC400_TLX_MASTER U(1) +#define SOC_CSS_NIC400_USB_OHCI U(2) +#define SOC_CSS_NIC400_PL354_SMC U(3) +/* + * The apb4_bridge controls access to: + * - the PCIe configuration registers + * - the MMU units for USB, HDLCD and DMA + */ +#define SOC_CSS_NIC400_APB4_BRIDGE U(4) + +/* Non-volatile counters */ +#define SOC_TRUSTED_NVCTR_BASE UL(0x0EE70000) +#define TFW_NVCTR_BASE (SOC_TRUSTED_NVCTR_BASE + 0x0000) +#define TFW_NVCTR_SIZE U(4) +#define NTFW_CTR_BASE (SOC_TRUSTED_NVCTR_BASE + 0x0004) +#define NTFW_CTR_SIZE U(4) + +/* Keys */ +#define SOC_KEYS_BASE UL(0x0EE80000) +#define TZ_PUB_KEY_HASH_BASE (SOC_KEYS_BASE + 0x0000) +#define TZ_PUB_KEY_HASH_SIZE U(32) +#define HU_KEY_BASE (SOC_KEYS_BASE + 0x0020) +#define HU_KEY_SIZE U(16) +#define END_KEY_BASE (SOC_KEYS_BASE + 0x0044) +#define END_KEY_SIZE U(32) + +#define SOC_PLATFORM_PERIPH_MAP_DEVICE MAP_REGION_FLAT( \ + SOC_PLATFORM_PERIPH_BASE, \ + SOC_PLATFORM_PERIPH_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define SOC_SYSTEM_PERIPH_MAP_DEVICE MAP_REGION_FLAT( \ + SOC_SYSTEM_PERIPH_BASE, \ + SOC_SYSTEM_PERIPH_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define SOC_MEMCNTRL_MAP_DEVICE MAP_REGION_FLAT( \ + SOC_MEMCNTRL_BASE, \ + SOC_MEMCNTRL_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* + * The bootsec_bridge controls access to a bunch of peripherals, e.g. the UARTs. + */ +#define SOC_CSS_NIC400_BOOTSEC_BRIDGE U(5) +#define SOC_CSS_NIC400_BOOTSEC_BRIDGE_UART1 UL(1 << 12) + +/* + * Required platform porting definitions common to all ARM CSS SoCs + */ +/* 2MB used for SCP DDR retraining */ +#define PLAT_ARM_SCP_TZC_DRAM1_SIZE UL(0x00200000) + +/* V2M motherboard system registers & offsets */ +#define V2M_SYSREGS_BASE UL(0x0C010000) +#define V2M_SYS_LED U(0x8) + +/* + * V2M sysled bit definitions. The values written to this + * register are defined in arch.h & runtime_svc.h. Only + * used by the primary cpu to diagnose any cold boot issues. + * + * SYS_LED[0] - Security state (S=0/NS=1) + * SYS_LED[2:1] - Exception Level (EL3-EL0) + * SYS_LED[7:3] - Exception Class (Sync/Async & origin) + * + */ +#define V2M_SYS_LED_SS_SHIFT U(0) +#define V2M_SYS_LED_EL_SHIFT U(1) +#define V2M_SYS_LED_EC_SHIFT U(3) + +#define V2M_SYS_LED_SS_MASK U(0x01) +#define V2M_SYS_LED_EL_MASK U(0x03) +#define V2M_SYS_LED_EC_MASK U(0x1f) + +/* NOR Flash */ +#define V2M_FLASH0_BASE UL(0x08000000) +#define V2M_FLASH0_SIZE UL(0x04000000) +#define V2M_FLASH_BLOCK_SIZE UL(0x00040000) /* 256 KB */ + +/* + * The flash can be mapped either as read-only or read-write. + * + * If it is read-write then it should also be mapped as device memory because + * NOR flash programming involves sending a fixed, ordered sequence of commands. + * + * If it is read-only then it should also be mapped as: + * - Normal memory, because reading from NOR flash is transparent, it is like + * reading from RAM. + * - Non-executable by default. If some parts of the flash need to be executable + * then platform code is responsible for re-mapping the appropriate portion + * of it as executable. + */ +#define V2M_MAP_FLASH0_RW MAP_REGION_FLAT(V2M_FLASH0_BASE,\ + V2M_FLASH0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define V2M_MAP_FLASH0_RO MAP_REGION_FLAT(V2M_FLASH0_BASE,\ + V2M_FLASH0_SIZE, \ + MT_RO_DATA | MT_SECURE) + +#define SGI_MAP_FLASH0_RO MAP_REGION_FLAT(V2M_FLASH0_BASE,\ + V2M_FLASH0_SIZE, \ + MT_DEVICE | MT_RO | MT_SECURE) + +/* Platform ID address */ +#define BOARD_CSS_PLAT_ID_REG_ADDR UL(0x0EFE00E0) + +/* Platform ID related accessors */ +#define BOARD_CSS_PLAT_ID_REG_ID_MASK U(0x0F) +#define BOARD_CSS_PLAT_ID_REG_ID_SHIFT U(0x00) +#define BOARD_CSS_PLAT_ID_REG_VERSION_MASK U(0xF00) +#define BOARD_CSS_PLAT_ID_REG_VERSION_SHIFT U(0x08) +#define BOARD_CSS_PLAT_TYPE_RTL U(0x00) +#define BOARD_CSS_PLAT_TYPE_FPGA U(0x01) +#define BOARD_CSS_PLAT_TYPE_EMULATOR U(0x02) +#define BOARD_CSS_PLAT_TYPE_FVP U(0x03) + +#ifndef __ASSEMBLER__ + +#include <lib/mmio.h> + +#define BOARD_CSS_GET_PLAT_TYPE(addr) \ + ((mmio_read_32(addr) & BOARD_CSS_PLAT_ID_REG_ID_MASK) \ + >> BOARD_CSS_PLAT_ID_REG_ID_SHIFT) + +#endif /* __ASSEMBLER__ */ + + +#define MAX_IO_DEVICES U(3) +#define MAX_IO_HANDLES U(4) + +/* Reserve the last block of flash for PSCI MEM PROTECT flag */ +#define PLAT_ARM_FIP_BASE V2M_FLASH0_BASE +#define PLAT_ARM_FIP_MAX_SIZE (V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE) + +#define PLAT_ARM_NVM_BASE V2M_FLASH0_BASE +#define PLAT_ARM_NVM_SIZE (V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE) + +/* UART related constants */ +#define PLAT_ARM_BOOT_UART_BASE SOC_CSS_UART0_BASE +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ SOC_CSS_UART0_CLK_IN_HZ + +#define PLAT_ARM_RUN_UART_BASE SOC_CSS_UART1_BASE +#define PLAT_ARM_RUN_UART_CLK_IN_HZ SOC_CSS_UART1_CLK_IN_HZ + +#define PLAT_ARM_SP_MIN_RUN_UART_BASE SOC_CSS_UART1_BASE +#define PLAT_ARM_SP_MIN_RUN_UART_CLK_IN_HZ SOC_CSS_UART1_CLK_IN_HZ + +#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE +#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ + +#endif /* SGI_SOC_CSS_DEF_V2_H */ diff --git a/plat/arm/css/sgi/include/sgi_soc_platform_def.h b/plat/arm/css/sgi/include/sgi_soc_platform_def.h new file mode 100644 index 0000000000..d7a839a524 --- /dev/null +++ b/plat/arm/css/sgi/include/sgi_soc_platform_def.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGI_SOC_PLATFORM_DEF_H +#define SGI_SOC_PLATFORM_DEF_H + +#include <sgi_base_platform_def.h> +#include <plat/arm/board/common/board_css_def.h> +#include <plat/arm/board/common/v2m_def.h> +#include <plat/arm/soc/common/soc_css_def.h> + +#endif /* SGI_SOC_PLATFORM_DEF_H */ diff --git a/plat/arm/css/sgi/include/sgi_soc_platform_def_v2.h b/plat/arm/css/sgi/include/sgi_soc_platform_def_v2.h new file mode 100644 index 0000000000..cb747c34a8 --- /dev/null +++ b/plat/arm/css/sgi/include/sgi_soc_platform_def_v2.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGI_SOC_PLATFORM_DEF_V2_H +#define SGI_SOC_PLATFORM_DEF_V2_H + +#include <sgi_base_platform_def.h> +#include <sgi_soc_css_def_v2.h> + +#endif /* SGI_SOC_PLATFORM_DEF_V2_H */ diff --git a/plat/arm/css/sgi/include/sgi_variant.h b/plat/arm/css/sgi/include/sgi_variant.h index f4c5300d09..ecf6d93d6f 100644 --- a/plat/arm/css/sgi/include/sgi_variant.h +++ b/plat/arm/css/sgi/include/sgi_variant.h @@ -14,8 +14,11 @@ #define RD_N1E1_EDGE_SID_VER_PART_NUM 0x0786 #define RD_E1_EDGE_CONFIG_ID 0x2 -/* SID Version values for RD-Daniel */ -#define RD_DANIEL_SID_VER_PART_NUM 0x078a +/* SID Version values for RD-V1 */ +#define RD_V1_SID_VER_PART_NUM 0x078a + +/* SID Version values for RD-N2 */ +#define RD_N2_SID_VER_PART_NUM 0x07B7 /* Structure containing SGI platform variant information */ typedef struct sgi_platform_info { diff --git a/plat/arm/css/sgi/sgi-common.mk b/plat/arm/css/sgi/sgi-common.mk index 6b9e0cda6d..615f53dc97 100644 --- a/plat/arm/css/sgi/sgi-common.mk +++ b/plat/arm/css/sgi/sgi-common.mk @@ -32,8 +32,7 @@ ENT_GIC_SOURCES := ${GICV3_SOURCES} \ plat/common/plat_gicv3.c \ plat/arm/common/arm_gicv3.c -PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c \ - ${CSS_ENT_BASE}/aarch64/sgi_helper.S +PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/aarch64/sgi_helper.S BL1_SOURCES += ${INTERCONNECT_SOURCES} \ drivers/arm/sbsa/sbsa.c diff --git a/plat/arm/css/sgi/sgi_bl31_setup.c b/plat/arm/css/sgi/sgi_bl31_setup.c index a4aed004dc..e8238ba7c6 100644 --- a/plat/arm/css/sgi/sgi_bl31_setup.c +++ b/plat/arm/css/sgi/sgi_bl31_setup.c @@ -28,7 +28,7 @@ static scmi_channel_plat_info_t sgi575_scmi_plat_info = { .ring_doorbell = &mhu_ring_doorbell, }; -static scmi_channel_plat_info_t rd_n1e1_edge_scmi_plat_info[] = { +static scmi_channel_plat_info_t plat_rd_scmi_info[] = { { .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE, .db_reg_addr = PLAT_CSS_MHU_BASE + SENDER_REG_SET(0), @@ -74,10 +74,11 @@ static scmi_channel_plat_info_t rd_n1e1_edge_scmi_plat_info[] = { scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id) { if (sgi_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM || - sgi_plat_info.platform_id == RD_DANIEL_SID_VER_PART_NUM) { - if (channel_id >= ARRAY_SIZE(rd_n1e1_edge_scmi_plat_info)) + sgi_plat_info.platform_id == RD_V1_SID_VER_PART_NUM || + sgi_plat_info.platform_id == RD_N2_SID_VER_PART_NUM) { + if (channel_id >= ARRAY_SIZE(plat_rd_scmi_info)) panic(); - return &rd_n1e1_edge_scmi_plat_info[channel_id]; + return &plat_rd_scmi_info[channel_id]; } else if (sgi_plat_info.platform_id == SGI575_SSC_VER_PART_NUM) return &sgi575_scmi_plat_info; @@ -107,12 +108,11 @@ void sgi_bl31_common_platform_setup(void) const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) { /* - * For RD-E1-Edge and RD-Daniel platforms, only CPU power ON/OFF - * PSCI platform callbacks are supported. + * For RD-E1-Edge, only CPU power ON/OFF, PSCI platform callbacks are + * supported. */ if (((sgi_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM) && - (sgi_plat_info.config_id == RD_E1_EDGE_CONFIG_ID)) || - (sgi_plat_info.platform_id == RD_DANIEL_SID_VER_PART_NUM)) { + (sgi_plat_info.config_id == RD_E1_EDGE_CONFIG_ID))) { ops->cpu_standby = NULL; ops->system_off = NULL; ops->system_reset = NULL; diff --git a/plat/arm/css/sgi/sgi_plat_v2.c b/plat/arm/css/sgi/sgi_plat_v2.c new file mode 100644 index 0000000000..a770255fc6 --- /dev/null +++ b/plat/arm/css/sgi/sgi_plat_v2.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <platform_def.h> + +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> +#include <drivers/arm/sbsa.h> + +/* + * Table of regions for different BL stages to map using the MMU. + */ +#if IMAGE_BL1 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + SGI_MAP_FLASH0_RO, + CSS_SGI_MAP_DEVICE, + SOC_PLATFORM_PERIPH_MAP_DEVICE, + SOC_SYSTEM_PERIPH_MAP_DEVICE, + {0} +}; +#endif + +#if IMAGE_BL2 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + SGI_MAP_FLASH0_RO, +#ifdef PLAT_ARM_MEM_PROT_ADDR + ARM_V2M_MAP_MEM_PROTECT, +#endif + CSS_SGI_MAP_DEVICE, + SOC_MEMCNTRL_MAP_DEVICE, + SOC_PLATFORM_PERIPH_MAP_DEVICE, + SOC_SYSTEM_PERIPH_MAP_DEVICE, + ARM_MAP_NS_DRAM1, +#if ARM_BL31_IN_DRAM + ARM_MAP_BL31_SEC_DRAM, +#endif +#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3 + ARM_MAP_BL1_RW, +#endif + {0} +}; +#endif + +#if IMAGE_BL31 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, +#ifdef PLAT_ARM_MEM_PROT_ADDR + ARM_V2M_MAP_MEM_PROTECT, +#endif + CSS_SGI_MAP_DEVICE, + SOC_PLATFORM_PERIPH_MAP_DEVICE, + SOC_SYSTEM_PERIPH_MAP_DEVICE, + {0} +}; + +#endif + +ARM_CASSERT_MMAP + +#if TRUSTED_BOARD_BOOT +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + assert(heap_addr != NULL); + assert(heap_size != NULL); + + return arm_get_mbedtls_heap(heap_addr, heap_size); +} +#endif + +void plat_arm_secure_wdt_start(void) +{ + sbsa_wdog_start(SBSA_SECURE_WDOG_BASE, SBSA_SECURE_WDOG_TIMEOUT); +} + +void plat_arm_secure_wdt_stop(void) +{ + sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE); +} diff --git a/plat/arm/css/sgi/sgi_ras.c b/plat/arm/css/sgi/sgi_ras.c index f56544e72a..a04972d706 100644 --- a/plat/arm/css/sgi/sgi_ras.c +++ b/plat/arm/css/sgi/sgi_ras.c @@ -111,6 +111,7 @@ static int sgi_ras_intr_handler(const struct err_record_info *err_rec, struct sgi_ras_ev_map *ras_map; mm_communicate_header_t *header; uint32_t intr; + int ret; cm_el1_sysregs_context_save(NON_SECURE); intr = data->interrupt; @@ -120,7 +121,7 @@ static int sgi_ras_intr_handler(const struct err_record_info *err_rec, * this interrupt */ ras_map = find_ras_event_map_by_intr(intr); - assert(ras_map); + assert(ras_map != NULL); /* * Populate the MM_COMMUNICATE payload to share the @@ -152,9 +153,20 @@ static int sgi_ras_intr_handler(const struct err_record_info *err_rec, plat_ic_end_of_interrupt(intr); /* Dispatch the event to the SDEI client */ - sdei_dispatch_event(ras_map->sdei_ev_num); + ret = sdei_dispatch_event(ras_map->sdei_ev_num); + if (ret != 0) { + /* + * sdei_dispatch_event() may return failing result in some cases, + * for example kernel may not have registered a handler or RAS event + * may happen early during boot. We restore the NS context when + * sdei_dispatch_event() returns failing result. + */ + ERROR("SDEI dispatch failed: %d", ret); + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + } - return 0; + return ret; } int sgi_ras_intr_handler_setup(void) diff --git a/plat/marvell/armada/a3k/common/a3700_common.mk b/plat/marvell/armada/a3k/common/a3700_common.mk index 5e2f8e299b..8775e89342 100644 --- a/plat/marvell/armada/a3k/common/a3700_common.mk +++ b/plat/marvell/armada/a3k/common/a3700_common.mk @@ -1,5 +1,5 @@ # -# Copyright (C) 2018 Marvell International Ltd. +# Copyright (C) 2018-2021 Marvell International Ltd. # # SPDX-License-Identifier: BSD-3-Clause # https://spdx.org/licenses @@ -38,7 +38,6 @@ PLAT_INCLUDES := -I$(PLAT_FAMILY_BASE)/$(PLAT) \ -I$/drivers/arm/gic/common/ PLAT_BL_COMMON_SOURCES := $(PLAT_COMMON_BASE)/aarch64/a3700_common.c \ - $(MARVELL_COMMON_BASE)/marvell_cci.c \ $(MARVELL_DRV_BASE)/uart/a3700_console.S BL1_SOURCES += $(PLAT_COMMON_BASE)/aarch64/plat_helpers.S \ @@ -50,12 +49,14 @@ MARVELL_DRV := $(MARVELL_DRV_BASE)/comphy/phy-comphy-3700.c BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ $(PLAT_COMMON_BASE)/aarch64/plat_helpers.S \ + $(PLAT_COMMON_BASE)/plat_cci.c \ $(PLAT_COMMON_BASE)/plat_pm.c \ $(PLAT_COMMON_BASE)/dram_win.c \ $(PLAT_COMMON_BASE)/io_addr_dec.c \ $(PLAT_COMMON_BASE)/marvell_plat_config.c \ $(PLAT_COMMON_BASE)/a3700_ea.c \ $(PLAT_FAMILY_BASE)/$(PLAT)/plat_bl31_setup.c \ + $(MARVELL_COMMON_BASE)/marvell_cci.c \ $(MARVELL_COMMON_BASE)/marvell_ddr_info.c \ $(MARVELL_COMMON_BASE)/marvell_gicv3.c \ $(MARVELL_GIC_SOURCES) \ @@ -64,45 +65,53 @@ BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ $(PLAT_COMMON_BASE)/a3700_sip_svc.c \ $(MARVELL_DRV) -ifneq (${WTP},) +ifeq ($(CM3_SYSTEM_RESET),1) +BL31_SOURCES += $(PLAT_COMMON_BASE)/cm3_system_reset.c +endif + +ifdef WTP + +$(if $(wildcard $(value WTP)/*),,$(error "'WTP=$(value WTP)' was specified, but '$(value WTP)' directory does not exist")) +$(if $(shell test -s "$(value WTP)/branch.txt" || git -C $(value WTP) rev-parse --show-cdup 2>&1),$(error "'WTP=$(value WTP)' was specified, but '$(value WTP)' does not contain valid Marvell a3700_utils release tarball nor git repository")) DOIMAGEPATH := $(WTP) DOIMAGETOOL := $(DOIMAGEPATH)/wtptp/src/TBB_Linux/release/TBB_linux +BUILD_UART := uart-images +UART_IMAGE := $(BUILD_UART).tgz.bin + ifeq ($(MARVELL_SECURE_BOOT),1) -DOIMAGE_CFG := $(DOIMAGEPATH)/atf-tim.txt +DOIMAGE_CFG := $(BUILD_PLAT)/atf-tim.txt +DOIMAGEUART_CFG := $(BUILD_PLAT)/$(BUILD_UART)/atf-tim.txt IMAGESPATH := $(DOIMAGEPATH)/tim/trusted - -TIMNCFG := $(DOIMAGEPATH)/atf-timN.txt +TIMNCFG := $(BUILD_PLAT)/atf-timN.txt +TIMNUARTCFG := $(BUILD_PLAT)/$(BUILD_UART)/atf-timN.txt TIMNSIG := $(IMAGESPATH)/timnsign.txt TIM2IMGARGS := -i $(DOIMAGE_CFG) -n $(TIMNCFG) TIMN_IMAGE := $$(grep "Image Filename:" -m 1 $(TIMNCFG) | cut -c 17-) else #MARVELL_SECURE_BOOT -DOIMAGE_CFG := $(DOIMAGEPATH)/atf-ntim.txt +DOIMAGE_CFG := $(BUILD_PLAT)/atf-ntim.txt +DOIMAGEUART_CFG := $(BUILD_PLAT)/$(BUILD_UART)/atf-ntim.txt IMAGESPATH := $(DOIMAGEPATH)/tim/untrusted TIM2IMGARGS := -i $(DOIMAGE_CFG) endif #MARVELL_SECURE_BOOT TIMBUILD := $(DOIMAGEPATH)/script/buildtim.sh TIM2IMG := $(DOIMAGEPATH)/script/tim2img.pl +TIMDDRTOOL := $(DOIMAGEPATH)/tim/ddr/ddr_tool + +$(TIMBUILD): $(TIMDDRTOOL) # WTMI_IMG is used to specify the customized RTOS image running over # Service CPU (CM3 processor). By the default, it points to a # baremetal binary of fuse programming in A3700_utils. WTMI_IMG := $(DOIMAGEPATH)/wtmi/fuse/build/fuse.bin -# WTMI_SYSINIT_IMG is used for the system early initialization, -# such as AVS settings, clock-tree setup and dynamic DDR PHY training. -# After the initialization is done, this image will be wiped out -# from the memory and CM3 will continue with RTOS image or other application. -WTMI_SYSINIT_IMG := $(DOIMAGEPATH)/wtmi/sys_init/build/sys_init.bin - # WTMI_MULTI_IMG is composed of CM3 RTOS image (WTMI_IMG) -# and sys-init image (WTMI_SYSINIT_IMG). +# and sys-init image. WTMI_MULTI_IMG := $(DOIMAGEPATH)/wtmi/build/wtmi.bin -WTMI_ENC_IMG := $(DOIMAGEPATH)/wtmi/build/wtmi-enc.bin -BUILD_UART := uart-images +WTMI_ENC_IMG := wtmi-enc.bin SRCPATH := $(dir $(BL33)) @@ -117,68 +126,108 @@ TIM_IMAGE := $$(grep "Image Filename:" -m 1 $(DOIMAGE_CFG) | cut -c 17-) TIMBLDARGS := $(MARVELL_SECURE_BOOT) $(BOOTDEV) $(IMAGESPATH) $(DOIMAGEPATH) $(CLOCKSPRESET) \ $(DDR_TOPOLOGY) $(PARTNUM) $(DEBUG) $(DOIMAGE_CFG) $(TIMNCFG) $(TIMNSIG) 1 TIMBLDUARTARGS := $(MARVELL_SECURE_BOOT) UART $(IMAGESPATH) $(DOIMAGEPATH) $(CLOCKSPRESET) \ - $(DDR_TOPOLOGY) 0 0 $(DOIMAGE_CFG) $(TIMNCFG) $(TIMNSIG) 0 -DOIMAGE_FLAGS := -r $(DOIMAGE_CFG) -v -D + $(DDR_TOPOLOGY) 0 0 $(DOIMAGEUART_CFG) $(TIMNUARTCFG) $(TIMNSIG) 0 + +CRYPTOPP_LIBDIR ?= $(CRYPTOPP_PATH) +CRYPTOPP_INCDIR ?= $(CRYPTOPP_PATH) -$(DOIMAGETOOL): - $(if $(value CRYPTOPP_PATH),,$(error "Platform '${PLAT}' for WTP image tool requires CRYPTOPP_PATH. Please set CRYPTOPP_PATH to point to the right directory")) +$(DOIMAGETOOL): FORCE + $(if $(CRYPTOPP_LIBDIR),,$(error "Platform '$(PLAT)' for WTP image tool requires CRYPTOPP_PATH or CRYPTOPP_LIBDIR. Please set CRYPTOPP_PATH or CRYPTOPP_LIBDIR to point to the right directory")) + $(if $(CRYPTOPP_INCDIR),,$(error "Platform '$(PLAT)' for WTP image tool requires CRYPTOPP_PATH or CRYPTOPP_INCDIR. Please set CRYPTOPP_PATH or CRYPTOPP_INCDIR to point to the right directory")) + $(if $(wildcard $(CRYPTOPP_LIBDIR)/*),,$(error "Either 'CRYPTOPP_PATH' or 'CRYPTOPP_LIB' was set to '$(CRYPTOPP_LIBDIR)', but '$(CRYPTOPP_LIBDIR)' does not exist")) + $(if $(wildcard $(CRYPTOPP_INCDIR)/*),,$(error "Either 'CRYPTOPP_PATH' or 'CRYPTOPP_INCDIR' was set to '$(CRYPTOPP_INCDIR)', but '$(CRYPTOPP_INCDIR)' does not exist")) +ifdef CRYPTOPP_PATH $(Q)$(MAKE) --no-print-directory -C $(CRYPTOPP_PATH) -f GNUmakefile - $(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH)/wtptp/src/TBB_Linux -f TBB_linux.mak LIBDIR=$(CRYPTOPP_PATH) +endif + $(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH)/wtptp/src/TBB_Linux -f TBB_linux.mak LIBDIR=$(CRYPTOPP_LIBDIR) INCDIR=$(CRYPTOPP_INCDIR) + +$(WTMI_MULTI_IMG): FORCE + $(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH) WTMI_IMG=$(WTMI_IMG) DDR_TOPOLOGY=$(DDR_TOPOLOGY) CLOCKSPRESET=$(CLOCKSPRESET) WTMI -mrvl_flash: ${BUILD_PLAT}/${BOOT_IMAGE} ${DOIMAGETOOL} - $(if $(value MV_DDR_PATH),,$(error "Platform '${PLAT}' for target '$@' requires MV_DDR_PATH. Please set MV_DDR_PATH to point to the right directory")) - ${Q}${MAKE} --no-print-directory -C ${DOIMAGEPATH} WTMI_IMG=$(WTMI_IMG) MV_DDR_PATH=$(MV_DDR_PATH) - $(shell truncate -s %4 $(WTMI_IMG)) - @echo +$(BUILD_PLAT)/wtmi.bin: $(WTMI_MULTI_IMG) + $(Q)cp -a $(WTMI_MULTI_IMG) $(BUILD_PLAT)/wtmi.bin + +$(TIMDDRTOOL): FORCE + $(if $(value MV_DDR_PATH),,$(error "Platform '${PLAT}' for ddr tool requires MV_DDR_PATH. Please set MV_DDR_PATH to point to the right directory")) + $(if $(wildcard $(value MV_DDR_PATH)/*),,$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' directory does not exist")) + $(if $(shell test -s "$(value MV_DDR_PATH)/branch.txt" || git -C $(value MV_DDR_PATH) rev-parse --show-cdup 2>&1),$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' does not contain valid Marvell mv_ddr release tarball nor git repository")) + $(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH) MV_DDR_PATH=$(MV_DDR_PATH) DDR_TOPOLOGY=$(DDR_TOPOLOGY) mv_ddr + +$(BUILD_PLAT)/$(UART_IMAGE): $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/wtmi.bin $(DOIMAGETOOL) $(TIMBUILD) $(TIMDDRTOOL) + @$(ECHO_BLANK_LINE) @echo "Building uart images" - $(TIMBUILD) $(TIMBLDUARTARGS) - @sed -i 's|WTMI_IMG|$(WTMI_MULTI_IMG)|1' $(DOIMAGE_CFG) - @sed -i 's|BOOT_IMAGE|$(BUILD_PLAT)/$(BOOT_IMAGE)|1' $(DOIMAGE_CFG) + $(Q)mkdir -p $(BUILD_PLAT)/$(BUILD_UART) + $(Q)cp -a $(BUILD_PLAT)/wtmi.bin $(BUILD_PLAT)/$(BUILD_UART)/wtmi.bin + $(Q)cp -a $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/$(BUILD_UART)/$(BOOT_IMAGE) + $(Q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(TIMBUILD) $(TIMBLDUARTARGS) + $(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(DOIMAGEUART_CFG) + $(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(DOIMAGEUART_CFG) ifeq ($(MARVELL_SECURE_BOOT),1) - @sed -i 's|WTMI_IMG|$(WTMI_MULTI_IMG)|1' $(TIMNCFG) - @sed -i 's|BOOT_IMAGE|$(BUILD_PLAT)/$(BOOT_IMAGE)|1' $(TIMNCFG) + $(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIMNUARTCFG) + $(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIMNUARTCFG) endif - $(DOIMAGETOOL) $(DOIMAGE_FLAGS) - @if [ -e "$(TIMNCFG)" ]; then $(DOIMAGETOOL) -r $(TIMNCFG); fi - @rm -rf $(BUILD_PLAT)/$(BUILD_UART)* - @mkdir $(BUILD_PLAT)/$(BUILD_UART) - @mv -t $(BUILD_PLAT)/$(BUILD_UART) $(TIM_IMAGE) $(DOIMAGE_CFG) $(TIMN_IMAGE) $(TIMNCFG) - @find . -name "*_h.*" |xargs cp -ut $(BUILD_PLAT)/$(BUILD_UART) - @mv $(subst .bin,_h.bin,$(WTMI_MULTI_IMG)) $(BUILD_PLAT)/$(BUILD_UART)/wtmi_h.bin - @tar czf $(BUILD_PLAT)/$(BUILD_UART).tgz.bin -C $(BUILD_PLAT) ./$(BUILD_UART) - @echo + $(Q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(DOIMAGETOOL) -r $(DOIMAGEUART_CFG) -v -D +ifeq ($(MARVELL_SECURE_BOOT),1) + $(Q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(DOIMAGETOOL) -r $(TIMNUARTCFG) +endif + $(Q)tar czf $(BUILD_PLAT)/$(UART_IMAGE) -C $(BUILD_PLAT) $(BUILD_UART)/$(TIM_IMAGE) $(BUILD_UART)/wtmi_h.bin $(BUILD_UART)/boot-image_h.bin + @$(ECHO_BLANK_LINE) + @echo "Built $@ successfully" + @$(ECHO_BLANK_LINE) + +$(BUILD_PLAT)/$(FLASH_IMAGE): $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/wtmi.bin $(DOIMAGETOOL) $(TIMBUILD) $(TIMDDRTOOL) $(TIM2IMG) + @$(ECHO_BLANK_LINE) @echo "Building flash image" - $(TIMBUILD) $(TIMBLDARGS) - sed -i 's|WTMI_IMG|$(WTMI_MULTI_IMG)|1' $(DOIMAGE_CFG) - sed -i 's|BOOT_IMAGE|$(BUILD_PLAT)/$(BOOT_IMAGE)|1' $(DOIMAGE_CFG) + $(Q)cd $(BUILD_PLAT) && $(TIMBUILD) $(TIMBLDARGS) + $(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(DOIMAGE_CFG) + $(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(DOIMAGE_CFG) ifeq ($(MARVELL_SECURE_BOOT),1) - @sed -i 's|WTMI_IMG|$(WTMI_MULTI_IMG)|1' $(TIMNCFG) - @sed -i 's|BOOT_IMAGE|$(BUILD_PLAT)/$(BOOT_IMAGE)|1' $(TIMNCFG) - @echo -e "\n\t=======================================================\n"; - @echo -e "\t Secure boot. Encrypting wtmi and boot-image \n"; - @echo -e "\t=======================================================\n"; - @truncate -s %16 $(WTMI_MULTI_IMG) - @openssl enc -aes-256-cbc -e -in $(WTMI_MULTI_IMG) \ - -out $(WTMI_ENC_IMG) \ + $(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIMNCFG) + $(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIMNCFG) + @$(ECHO_BLANK_LINE) + @echo "======================================================="; + @echo " Secure boot. Encrypting wtmi and boot-image"; + @echo "======================================================="; + @$(ECHO_BLANK_LINE) + $(Q)cp $(BUILD_PLAT)/wtmi.bin $(BUILD_PLAT)/wtmi-align.bin + $(Q)truncate -s %16 $(BUILD_PLAT)/wtmi-align.bin + $(Q)openssl enc -aes-256-cbc -e -in $(BUILD_PLAT)/wtmi-align.bin \ + -out $(BUILD_PLAT)/$(WTMI_ENC_IMG) \ -K `cat $(IMAGESPATH)/aes-256.txt` -nosalt \ -iv `cat $(IMAGESPATH)/iv.txt` -p - @truncate -s %16 $(BUILD_PLAT)/$(BOOT_IMAGE); - @openssl enc -aes-256-cbc -e -in $(BUILD_PLAT)/$(BOOT_IMAGE) \ + $(Q)truncate -s %16 $(BUILD_PLAT)/$(BOOT_IMAGE); + $(Q)openssl enc -aes-256-cbc -e -in $(BUILD_PLAT)/$(BOOT_IMAGE) \ -out $(BUILD_PLAT)/$(BOOT_ENC_IMAGE) \ -K `cat $(IMAGESPATH)/aes-256.txt` -nosalt \ -iv `cat $(IMAGESPATH)/iv.txt` -p endif - $(DOIMAGETOOL) $(DOIMAGE_FLAGS) - @if [ -e "$(TIMNCFG)" ]; then $(DOIMAGETOOL) -r $(TIMNCFG); fi - @if [ "$(MARVELL_SECURE_BOOT)" = "1" ]; then sed -i 's|$(WTMI_MULTI_IMG)|$(WTMI_ENC_IMG)|1;s|$(BOOT_IMAGE)|$(BOOT_ENC_IMAGE)|1;' $(TIMNCFG); fi - $(TIM2IMG) $(TIM2IMGARGS) -o $(BUILD_PLAT)/$(FLASH_IMAGE) - @mv -t $(BUILD_PLAT) $(TIM_IMAGE) $(DOIMAGE_CFG) $(TIMN_IMAGE) $(TIMNCFG) $(WTMI_IMG) $(WTMI_SYSINIT_IMG) $(WTMI_MULTI_IMG) - @if [ "$(MARVELL_SECURE_BOOT)" = "1" ]; then mv -t $(BUILD_PLAT) $(WTMI_ENC_IMG) OtpHash.txt; fi - @find . -name "*.txt" | grep -E "CSK[[:alnum:]]_KeyHash.txt|Tim_msg.txt|TIMHash.txt" | xargs rm -f + $(Q)cd $(BUILD_PLAT) && $(DOIMAGETOOL) -r $(DOIMAGE_CFG) -v -D +ifeq ($(MARVELL_SECURE_BOOT),1) + $(Q)cd $(BUILD_PLAT) && $(DOIMAGETOOL) -r $(TIMNCFG) + $(Q)sed -i 's|wtmi.bin|$(WTMI_ENC_IMG)|1' $(TIMNCFG) + $(Q)sed -i 's|$(BOOT_IMAGE)|$(BOOT_ENC_IMAGE)|1' $(TIMNCFG) +endif + $(Q)cd $(BUILD_PLAT) && $(TIM2IMG) $(TIM2IMGARGS) -o $(BUILD_PLAT)/$(FLASH_IMAGE) + @$(ECHO_BLANK_LINE) + @echo "Built $@ successfully" + @$(ECHO_BLANK_LINE) + +clean realclean distclean: mrvl_clean + +.PHONY: mrvl_clean +mrvl_clean: + -$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH) MV_DDR_PATH=$(MV_DDR_PATH) clean + -$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH)/wtptp/src/TBB_Linux -f TBB_linux.mak clean +ifdef CRYPTOPP_PATH + -$(Q)$(MAKE) --no-print-directory -C $(CRYPTOPP_PATH) -f GNUmakefile clean +endif -else # ${WTP} +else # WTP -mrvl_flash: +$(BUILD_PLAT)/$(UART_IMAGE) $(BUILD_PLAT)/$(FLASH_IMAGE): $(error "Platform '${PLAT}' for target '$@' requires WTP. Please set WTP to point to the right directory") -endif # ${WTP} +endif # WTP + +.PHONY: mrvl_uart +mrvl_uart: $(BUILD_PLAT)/$(UART_IMAGE) diff --git a/plat/marvell/armada/a3k/common/cm3_system_reset.c b/plat/marvell/armada/a3k/common/cm3_system_reset.c new file mode 100644 index 0000000000..548ff51686 --- /dev/null +++ b/plat/marvell/armada/a3k/common/cm3_system_reset.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2020 Marek Behun, CZ.NIC + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include <stdbool.h> + +#include <common/debug.h> +#include <drivers/delay_timer.h> +#include <lib/mmio.h> + +#include <mvebu_def.h> + +/* Cortex-M3 Secure Processor Mailbox Registers */ +#define MVEBU_RWTM_PARAM0_REG (MVEBU_RWTM_REG_BASE) +#define MVEBU_RWTM_CMD_REG (MVEBU_RWTM_REG_BASE + 0x40) +#define MVEBU_RWTM_HOST_INT_RESET_REG (MVEBU_RWTM_REG_BASE + 0xC8) +#define MVEBU_RWTM_HOST_INT_MASK_REG (MVEBU_RWTM_REG_BASE + 0xCC) +#define MVEBU_RWTM_HOST_INT_SP_COMPLETE BIT(0) + +#define MVEBU_RWTM_REBOOT_CMD 0x0009 +#define MVEBU_RWTM_REBOOT_MAGIC 0xDEADBEEF + +static inline bool rwtm_completed(void) +{ + return (mmio_read_32(MVEBU_RWTM_HOST_INT_RESET_REG) & + MVEBU_RWTM_HOST_INT_SP_COMPLETE) != 0; +} + +static bool rwtm_wait(int ms) +{ + while (ms && !rwtm_completed()) { + mdelay(1); + --ms; + } + + return rwtm_completed(); +} + +void cm3_system_reset(void) +{ + int tries = 5; + + for (; tries > 0; --tries) { + mmio_clrbits_32(MVEBU_RWTM_HOST_INT_RESET_REG, + MVEBU_RWTM_HOST_INT_SP_COMPLETE); + + mmio_write_32(MVEBU_RWTM_PARAM0_REG, MVEBU_RWTM_REBOOT_MAGIC); + mmio_write_32(MVEBU_RWTM_CMD_REG, MVEBU_RWTM_REBOOT_CMD); + + if (rwtm_wait(10)) { + break; + } + + mdelay(100); + } + + /* If we reach here, the command is not implemented. */ + ERROR("System reset command not implemented in WTMI firmware!\n"); +} diff --git a/plat/marvell/armada/a3k/common/dram_win.c b/plat/marvell/armada/a3k/common/dram_win.c index 694f6d480e..e89f295045 100644 --- a/plat/marvell/armada/a3k/common/dram_win.c +++ b/plat/marvell/armada/a3k/common/dram_win.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Marvell International Ltd. + * Copyright (C) 2018-2021 Marvell International Ltd. * * SPDX-License-Identifier: BSD-3-Clause * https://spdx.org/licenses @@ -92,33 +92,35 @@ struct cpu_win_configuration mv_cpu_wins[CPU_WIN_CONFIG_MAX][MV_CPU_WIN_NUM] = { }, /* - * If total dram size is more than 2GB, now there is only one case - 4GB - * dram; we will use below cpu windows configurations: - * - Internal Regs, CCI-400, Boot Rom and PCIe windows are kept as - * default; - * - Use 4 CPU decode windows for DRAM, which cover 3.375GB DRAM; - * DDR window 0 is configured in tim header with 2GB size, no need to - * configure it again here; + * If total DRAM size is more than 2GB, now there is only one case: + * 4GB of DRAM; to better utilize address space (for maximization of + * DRAM usage), we will use the configuration of CPU windows below: + * - Internal Regs and Boot ROM windows are kept as default; + * - CCI-400 is moved from its default address to another address + * (this is actually done even if DRAM size is not more than 2 GB, + * because the firmware is compiled with that address as a + * constant); + * - PCIe window is moved to another address; + * - Use 4 CPU decode windows for DRAM, which cover 3.75GB DRAM; + * DDR window 0 is configured in tim header with 2G B size, no need + * to configure it again here; * - * 0xFFFFFFFF ---> |-----------------------| - * | Boot ROM | 64KB + * 0xFFFFFFFF ---> +-----------------------+ + * | Boot ROM | 64 KB * 0xFFF00000 ---> +-----------------------+ * : : - * 0xF0000000 ---> |-----------------------| - * | PCIE | 128 MB - * 0xE8000000 ---> |-----------------------| - * | DDR window 3 | 128 MB - * 0xE0000000 ---> +-----------------------+ - * : : - * 0xD8010000 ---> |-----------------------| - * | CCI Regs | 64 KB - * 0xD8000000 ---> +-----------------------+ - * : : + * 0xFE010000 ---> +-----------------------+ + * | CCI Regs | 64 KB + * 0xFE000000 ---> +-----------------------+ * : : + * 0xFA000000 ---> +-----------------------+ + * | PCIE | 128 MB + * 0xF2000000 ---> +-----------------------+ + * | DDR window 3 | 512 MB * 0xD2000000 ---> +-----------------------+ - * | Internal Regs | 32MB + * | Internal Regs | 32 MB * 0xD0000000 ---> |-----------------------| - * | DDR window 2 | 256 MB + * | DDR window 2 | 256 MB * 0xC0000000 ---> |-----------------------| * | | * | DDR window 1 | 1 GB @@ -155,14 +157,14 @@ struct cpu_win_configuration mv_cpu_wins[CPU_WIN_CONFIG_MAX][MV_CPU_WIN_NUM] = { 0xc0000000}, {CPU_WIN_ENABLED, CPU_WIN_TARGET_DRAM, - 0xe0000000, - 0x08000000, - 0xe0000000}, + 0xd2000000, + 0x20000000, + 0xd2000000}, {CPU_WIN_ENABLED, CPU_WIN_TARGET_PCIE, - 0xe8000000, + 0xf2000000, 0x08000000, - 0xe8000000}, + 0xf2000000}, }, }; diff --git a/plat/marvell/armada/a3k/common/include/a3700_plat_def.h b/plat/marvell/armada/a3k/common/include/a3700_plat_def.h index c7f40adc3e..83d95616b9 100644 --- a/plat/marvell/armada/a3k/common/include/a3700_plat_def.h +++ b/plat/marvell/armada/a3k/common/include/a3700_plat_def.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Marvell International Ltd. + * Copyright (C) 2018-2021 Marvell International Ltd. * * SPDX-License-Identifier: BSD-3-Clause * https://spdx.org/licenses @@ -41,8 +41,14 @@ #define MVEBU_GICR_BASE 0x1D40000 #define MVEBU_GICC_BASE 0x1D80000 -/* CCI-400 */ -#define MVEBU_CCI_BASE 0x8000000 +/* + * CCI-400 base address + * This address is absolute, not relative to MVEBU_REGS_BASE. + * This is not the default CCI base address (that would be 0xD8000000). + * Rather we remap CCI to this address to better utilize the address space. + * (The remapping is done in plat/marvell/armada/a3k/common/plat_cci.c) + */ +#define MVEBU_CCI_BASE 0xFE000000 /***************************************************************************** * North and south bridge register base @@ -119,4 +125,10 @@ */ #define MVEBU_COMPHY_REG_BASE (MVEBU_REGS_BASE + 0x18300) +/***************************************************************************** + * Cortex-M3 Secure Processor Mailbox constants + ***************************************************************************** + */ +#define MVEBU_RWTM_REG_BASE (MVEBU_REGS_BASE + 0xB0000) + #endif /* A3700_PLAT_DEF_H */ diff --git a/plat/marvell/armada/a3k/common/include/a3700_pm.h b/plat/marvell/armada/a3k/common/include/a3700_pm.h index cc6cf436ab..44dbb9f7d2 100644 --- a/plat/marvell/armada/a3k/common/include/a3700_pm.h +++ b/plat/marvell/armada/a3k/common/include/a3700_pm.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Marvell International Ltd. + * Copyright (C) 2016-2020 Marvell International Ltd. * * SPDX-License-Identifier: BSD-3-Clause * https://spdx.org/licenses @@ -48,4 +48,6 @@ struct pm_wake_up_src_config { struct pm_wake_up_src_config *mv_wake_up_src_config_get(void); +void cm3_system_reset(void); + #endif /* A3700_PM_H */ diff --git a/plat/marvell/armada/a3k/common/include/platform_def.h b/plat/marvell/armada/a3k/common/include/platform_def.h index 3d839f8201..057ee2eb9b 100644 --- a/plat/marvell/armada/a3k/common/include/platform_def.h +++ b/plat/marvell/armada/a3k/common/include/platform_def.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2019 Marvell International Ltd. + * Copyright (C) 2016-2021 Marvell International Ltd. * * SPDX-License-Identifier: BSD-3-Clause * https://spdx.org/licenses @@ -148,7 +148,7 @@ #define PLAT_MARVELL_SHARED_RAM_CACHED 1 /* CCI related constants */ -#define PLAT_MARVELL_CCI_BASE (MVEBU_REGS_BASE + MVEBU_CCI_BASE) +#define PLAT_MARVELL_CCI_BASE MVEBU_CCI_BASE #define PLAT_MARVELL_CCI_CLUSTER0_SL_IFACE_IX 3 #define PLAT_MARVELL_CCI_CLUSTER1_SL_IFACE_IX 4 @@ -227,6 +227,8 @@ #define CPU_DEC_RLR_REMAP_LOW_MASK \ (0xffff << CPU_DEC_BR_BASE_OFFS) +#define CPU_DEC_CCI_BASE_REG (MVEBU_CPU_DEC_WIN_REG_BASE + 0xe0) + /* Securities */ #define IRQ_SEC_OS_TICK_INT MARVELL_IRQ_SEC_PHY_TIMER diff --git a/plat/marvell/armada/a3k/common/plat_cci.c b/plat/marvell/armada/a3k/common/plat_cci.c new file mode 100644 index 0000000000..56f091fef4 --- /dev/null +++ b/plat/marvell/armada/a3k/common/plat_cci.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2021 Marek Behun <marek.behun@nic.cz> + * + * Based on plat/marvell/armada/common/marvell_cci.c + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include <drivers/arm/cci.h> +#include <lib/mmio.h> + +#include <plat_marvell.h> + +static const int cci_map[] = { + PLAT_MARVELL_CCI_CLUSTER0_SL_IFACE_IX, + PLAT_MARVELL_CCI_CLUSTER1_SL_IFACE_IX +}; + +/* + * This redefines the weak definition in + * plat/marvell/armada/common/marvell_cci.c + */ +void plat_marvell_interconnect_init(void) +{ + /* + * To better utilize the address space, we remap CCI base address from + * the default (0xD8000000) to MVEBU_CCI_BASE. + * This has to be done here, rather than in cpu_wins_init(), because + * cpu_wins_init() is called later. + */ + mmio_write_32(CPU_DEC_CCI_BASE_REG, MVEBU_CCI_BASE >> 20); + + cci_init(PLAT_MARVELL_CCI_BASE, cci_map, ARRAY_SIZE(cci_map)); +} diff --git a/plat/marvell/armada/a3k/common/plat_pm.c b/plat/marvell/armada/a3k/common/plat_pm.c index f8ce6fe29e..2bae37e3f9 100644 --- a/plat/marvell/armada/a3k/common/plat_pm.c +++ b/plat/marvell/armada/a3k/common/plat_pm.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Marvell International Ltd. + * Copyright (C) 2018-2020 Marvell International Ltd. * * SPDX-License-Identifier: BSD-3-Clause * https://spdx.org/licenses @@ -763,6 +763,11 @@ static void __dead2 a3700_system_off(void) panic(); } +#pragma weak cm3_system_reset +void cm3_system_reset(void) +{ +} + /***************************************************************************** * A3700 handlers to reset the system ***************************************************************************** @@ -780,6 +785,9 @@ static void __dead2 a3700_system_reset(void) 2 * sizeof(uint64_t)); #endif + /* Use Cortex-M3 secure coprocessor for system reset */ + cm3_system_reset(); + /* Trigger the warm reset */ mmio_write_32(MVEBU_WARM_RESET_REG, MVEBU_WARM_RESET_MAGIC); diff --git a/plat/marvell/armada/a8k/common/a8k_common.mk b/plat/marvell/armada/a8k/common/a8k_common.mk index 58394a46f1..63cfce22c2 100644 --- a/plat/marvell/armada/a8k/common/a8k_common.mk +++ b/plat/marvell/armada/a8k/common/a8k_common.mk @@ -152,14 +152,21 @@ BLE_PATH ?= $(PLAT_COMMON_BASE)/ble include ${BLE_PATH}/ble.mk $(eval $(call MAKE_BL,e)) +clean realclean distclean: mrvl_clean + +.PHONY: mrvl_clean mrvl_clean: @echo " Doimage CLEAN" ${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${DOIMAGEPATH} clean -${DOIMAGETOOL}: mrvl_clean +${DOIMAGETOOL}: FORCE @$(DOIMAGE_LIBS_CHECK) ${Q}${MAKE} --no-print-directory -C ${DOIMAGEPATH} -mrvl_flash: ${BUILD_PLAT}/${BOOT_IMAGE} ${DOIMAGETOOL} - ${DOIMAGETOOL} ${DOIMAGE_FLAGS} ${BUILD_PLAT}/${BOOT_IMAGE} ${BUILD_PLAT}/${FLASH_IMAGE} - +${BUILD_PLAT}/${FLASH_IMAGE}: ${ROM_BIN_EXT} ${BUILD_PLAT}/${BOOT_IMAGE} ${DOIMAGETOOL} + @${ECHO_BLANK_LINE} + @echo "Building flash image" + ${Q}${DOIMAGETOOL} ${DOIMAGE_FLAGS} ${BUILD_PLAT}/${BOOT_IMAGE} ${BUILD_PLAT}/${FLASH_IMAGE} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} diff --git a/plat/marvell/armada/a8k/common/ble/ble.mk b/plat/marvell/armada/a8k/common/ble/ble.mk index 60fbf5f1d2..78c62a0103 100644 --- a/plat/marvell/armada/a8k/common/ble/ble.mk +++ b/plat/marvell/armada/a8k/common/ble/ble.mk @@ -26,7 +26,5 @@ PLAT_INCLUDES += -I$(MV_DDR_PATH) \ BLE_LINKERFILE := $(BLE_PATH)/ble.ld.S -FORCE: - $(MV_DDR_LIB): FORCE @+make -C $(MV_DDR_PATH) --no-print-directory PLAT_INCLUDES="$(PLAT_INCLUDES)" PLATFORM=$(PLAT) ARCH=AARCH64 OBJ_DIR=$(BUILD_PLAT)/ble diff --git a/plat/marvell/armada/common/marvell_common.mk b/plat/marvell/armada/common/marvell_common.mk index 7f8dffa00d..04eb51c48d 100644 --- a/plat/marvell/armada/common/marvell_common.mk +++ b/plat/marvell/armada/common/marvell_common.mk @@ -87,10 +87,17 @@ include $(MARVELL_PLAT_BASE)/common/mss/mss_common.mk endif $(BUILD_PLAT)/$(BOOT_IMAGE): $(BUILD_PLAT)/bl1.bin $(BUILD_PLAT)/$(FIP_NAME) + $(if $(shell find $(BUILD_PLAT)/bl1.bin -type f -size +128k),$(error "Image '$(BUILD_PLAT)/bl1.bin' is bigger than 128kB")) @cp $(BUILD_PLAT)/bl1.bin $(BUILD_PLAT)/$(BOOT_IMAGE) || { rm -f $(BUILD_PLAT)/$(BOOT_IMAGE); false; } @truncate -s %128K $(BUILD_PLAT)/$(BOOT_IMAGE) || { rm -f $(BUILD_PLAT)/$(BOOT_IMAGE); false; } @cat $(BUILD_PLAT)/$(FIP_NAME) >> $(BUILD_PLAT)/$(BOOT_IMAGE) || { rm -f $(BUILD_PLAT)/$(BOOT_IMAGE); false; } @truncate -s %4 $(BUILD_PLAT)/$(BOOT_IMAGE) || { rm -f $(BUILD_PLAT)/$(BOOT_IMAGE); false; } + @$(ECHO_BLANK_LINE) @echo "Built $@ successfully" + @$(ECHO_BLANK_LINE) +.PHONY: mrvl_bootimage mrvl_bootimage: $(BUILD_PLAT)/$(BOOT_IMAGE) + +.PHONY: mrvl_flash +mrvl_flash: $(BUILD_PLAT)/$(FLASH_IMAGE) diff --git a/plat/marvell/version.mk b/plat/marvell/version.mk index e072e12d5a..bb22255372 100644 --- a/plat/marvell/version.mk +++ b/plat/marvell/version.mk @@ -1 +1 @@ -SUBVERSION = devel-18.12.0 +SUBVERSION = devel-18.12.2 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 0000000000..fca69130a4 --- /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/mt8183/drivers/uart/uart.c b/plat/mediatek/common/drivers/uart/uart.c index 3c6a980368..b940eb3396 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/mt8183/bl31_plat_setup.c b/plat/mediatek/mt8183/bl31_plat_setup.c index e96b4ad0c5..7dac8a49b9 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> @@ -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/timer/mt_timer.c b/plat/mediatek/mt8183/drivers/timer/mt_timer.c new file mode 100644 index 0000000000..0da4815b1e --- /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 0000000000..0b8edc5178 --- /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 be04c35091..062ce3adc3 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/platform.mk b/plat/mediatek/mt8183/platform.mk index 3ccc928ac4..07da1afac3 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/ \ @@ -44,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 \ @@ -57,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/bl31_plat_setup.c b/plat/mediatek/mt8192/bl31_plat_setup.c index 9a01bef65e..9de4a2e629 100644 --- a/plat/mediatek/mt8192/bl31_plat_setup.c +++ b/plat/mediatek/mt8192/bl31_plat_setup.c @@ -11,12 +11,16 @@ #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> @@ -81,10 +85,21 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, ******************************************************************************/ 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(); } /******************************************************************************* 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 0000000000..dd8bf4eed7 --- /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 0000000000..ee98d0e384 --- /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 0000000000..15a700c2b7 --- /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 0000000000..1cf78345e1 --- /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 0000000000..d5d7e2e293 --- /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(®ion_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(®ion_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 0000000000..0b1543197f --- /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/mcdi/mt_cpu_pm.c b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c new file mode 100644 index 0000000000..d6d4af742a --- /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 0000000000..f8c51a1995 --- /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 0000000000..19dd6a2837 --- /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 0000000000..df741221d3 --- /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 0000000000..f3545aabff --- /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 0000000000..cca4413973 --- /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 0000000000..aac22afa39 --- /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 0000000000..ae892ed5a8 --- /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 0000000000..92c71bcdd3 --- /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 0000000000..f1d8493863 --- /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 0000000000..124bc8fbee --- /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 0000000000..419bfe42c2 --- /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 0000000000..7ccebd6abe --- /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 0000000000..7ed2e62209 --- /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 0000000000..ad782955d6 --- /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 index 781f940b69..08608854a7 100644 --- a/plat/mediatek/mt8192/drivers/timer/mt_timer.c +++ b/plat/mediatek/mt8192/drivers/timer/mt_timer.c @@ -5,6 +5,7 @@ */ #include <arch_helpers.h> +#include <lib/mmio.h> #include <mt_timer.h> #include <platform_def.h> @@ -28,3 +29,10 @@ uint64_t sched_clock(void) - 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 index 7aca4a3bf9..b35317715f 100644 --- a/plat/mediatek/mt8192/drivers/timer/mt_timer.h +++ b/plat/mediatek/mt8192/drivers/timer/mt_timer.h @@ -12,6 +12,8 @@ #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) @@ -23,8 +25,11 @@ #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 0000000000..ac8b94dd1a --- /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 0000000000..046cf7314f --- /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/plat_mt_cirq.h b/plat/mediatek/mt8192/include/plat_mt_cirq.h index 581860109e..bb8b4577f8 100644 --- a/plat/mediatek/mt8192/include/plat_mt_cirq.h +++ b/plat/mediatek/mt8192/include/plat_mt_cirq.h @@ -7,24 +7,53 @@ #ifndef PLAT_MT_CIRQ_H #define PLAT_MT_CIRQ_H -#define SYS_CIRQ_BASE U(0x10204000) -#define CIRQ_IRQ_NUM U(439) -#define CIRQ_SPI_START U(96) +#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 CIRQ_STA_BASE U(0x000) -#define CIRQ_ACK_BASE U(0x080) -#define CIRQ_MASK_BASE U(0x100) -#define CIRQ_MASK_SET_BASE U(0x180) -#define CIRQ_MASK_CLR_BASE U(0x200) -#define CIRQ_SENS_BASE U(0x280) -#define CIRQ_SENS_SET_BASE U(0x300) -#define CIRQ_SENS_CLR_BASE U(0x380) -#define CIRQ_POL_BASE U(0x400) -#define CIRQ_POL_SET_BASE U(0x480) -#define CIRQ_POL_CLR_BASE U(0x500) -#define CIRQ_CON U(0x600) + +#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 @@ -32,8 +61,8 @@ #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_EVENT_BITS U(31) #define CIRQ_CON_SW_RST_BITS U(20) +#define CIRQ_CON_EVENT_BITS U(31) #define CIRQ_CON_BITS_MASK U(0x7) /* @@ -41,42 +70,59 @@ */ #define CIRQ_CON_EN U(0x1) #define CIRQ_CON_EDGE_ONLY U(0x1) -#define CIRQ_SW_RESET 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 MT_CIRQ_EDGE_SENSITIVE U(0) -#define MT_CIRQ_LEVEL_SENSITIVE U(1) -/* - * Define macro - */ -#define IRQ_TO_CIRQ_NUM(irq) ((irq) - (CIRQ_SPI_START)) -#define CIRQ_TO_IRQ_NUM(cirq) ((cirq) + (CIRQ_SPI_START)) +#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 cirq events - */ -struct cirq_events { - uint32_t spi_start; - uint32_t num_of_events; - uint32_t *wakeup_events; -}; /* * Define function prototypes. */ -void mt_cirq_enable(void); -void mt_cirq_disable(void); +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_sw_reset(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_dump_reg(void); +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 */ +#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 0000000000..8ba8b93a8c --- /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 0000000000..a2881cef64 --- /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_sip_calls.h b/plat/mediatek/mt8192/include/plat_sip_calls.h new file mode 100644 index 0000000000..0e423225ce --- /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 index 768e7cf826..3e44414242 100644 --- a/plat/mediatek/mt8192/include/platform_def.h +++ b/plat/mediatek/mt8192/include/platform_def.h @@ -23,8 +23,15 @@ #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) @@ -67,11 +74,12 @@ ******************************************************************************/ #define PLATFORM_STACK_SIZE 0x800 -#define PLAT_MAX_PWR_LVL U(2) +#define PLAT_MAX_PWR_LVL U(3) #define PLAT_MAX_RET_STATE U(1) -#define PLAT_MAX_OFF_STATE U(2) +#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) diff --git a/plat/mediatek/mt8192/plat_mt_cirq.c b/plat/mediatek/mt8192/plat_mt_cirq.c index 7fc060799a..9002b7ee1d 100644 --- a/plat/mediatek/mt8192/plat_mt_cirq.c +++ b/plat/mediatek/mt8192/plat_mt_cirq.c @@ -7,137 +7,255 @@ #include <arch_helpers.h> #include <common/debug.h> #include <drivers/arm/gic_common.h> -#include <drivers/console.h> #include <lib/mmio.h> #include <mt_gic_v3.h> -#include <mtk_plat_common.h> #include <plat_mt_cirq.h> #include <platform_def.h> static struct cirq_events cirq_all_events = { - .spi_start = CIRQ_SPI_START + .spi_start = CIRQ_SPI_START, }; - -static inline void mt_cirq_write32(uint32_t val, uint32_t addr) -{ - mmio_write_32(addr + SYS_CIRQ_BASE, val); -} - -static inline uint32_t mt_cirq_read32(uint32_t addr) -{ - return mmio_read_32(addr + SYS_CIRQ_BASE); -} - +static uint32_t already_cloned; /* - * cirq_clone_flush_check_store: - * set 1 if we need to enable clone/flush value's check + * 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.) */ -static int32_t cirq_clone_flush_check_val; +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; + } -/* - * cirq_pattern_clone_flush_check_show: set 1 if we need to do pattern test. - */ -static int32_t cirq_pattern_clone_flush_check_val; + 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(); -/* - * cirq_pattern_clone_flush_check_show: set 1 if we need to do pattern test. - */ -static int32_t cirq_pattern_list; + return 0; +} /* - * mt_cirq_ack_all: Ack all the interrupt on SYS_CIRQ + * 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.) */ -void mt_cirq_ack_all(void) +int mt_irq_mask_all(struct mtk_irq_mask *mask) { - unsigned int i; - - for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) { - mt_cirq_write32(0xFFFFFFFF, CIRQ_ACK_BASE + (i * 4U)); + 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; } - /* make sure all cirq setting take effect before doing other things */ - dmbsy(); } -/* - * mt_cirq_enable: Enable SYS_CIRQ - */ -void mt_cirq_enable(void) +static uint32_t mt_irq_get_pol(uint32_t irq) { - uint32_t st; +#ifdef CIRQ_WITH_POLARITY + uint32_t reg; + uint32_t base = INT_POL_CTL0; - mt_cirq_ack_all(); + if (irq < 32U) { + return 0; + } - st = mt_cirq_read32(CIRQ_CON); - st |= (CIRQ_CON_EN << CIRQ_CON_EN_BITS) | - (CIRQ_CON_EDGE_ONLY << CIRQ_CON_EDGE_ONLY_BITS); + reg = ((irq - 32U) / 32U); - mt_cirq_write32((st & CIRQ_CON_BITS_MASK), CIRQ_CON); + return mmio_read_32(base + reg * 4U); +#else + return 0; +#endif } -/* - * mt_cirq_disable: Disable SYS_CIRQ - */ -void mt_cirq_disable(void) +unsigned int mt_irq_get_sens(unsigned int irq) { - uint32_t st; + unsigned int config; - st = mt_cirq_read32(CIRQ_CON); - st &= ~(CIRQ_CON_EN << CIRQ_CON_EN_BITS); + /* + * 2'b10 edge + * 2'b01 level + */ + config = mmio_read_32(MT_GIC_BASE + GICD_ICFGR + (irq / 16U) * 4U); + config = (config >> (irq % 16U) * 2U) & 0x3; - mt_cirq_write32((st & CIRQ_CON_BITS_MASK), CIRQ_CON); + return config; } -/* - * mt_cirq_get_mask: Get the specified SYS_CIRQ mask - * @cirq_num: the SYS_CIRQ number to get - * @return: - * 1: this cirq is masked - * 0: this cirq is umasked - * 2: cirq num is out of range - */ -__attribute__((weak)) unsigned int mt_cirq_get_mask(uint32_t cirq_num) +static void collect_all_wakeup_events(void) { - uint32_t st; - unsigned int val; - - if (cirq_num >= CIRQ_IRQ_NUM) { - ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num); - return 2; + 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; } - st = mt_cirq_read32((cirq_num / 32U) * 4U + CIRQ_MASK_BASE); - val = (st >> (cirq_num % 32U)) & 1U; - return val; -} - -/* - * mt_cirq_mask_all: Mask all interrupts on SYS_CIRQ. - */ -void mt_cirq_mask_all(void) -{ - unsigned int i; + 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; + } - for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) { - mt_cirq_write32(0xFFFFFFFF, CIRQ_MASK_SET_BASE + (i * 4U)); + cirq_all_events.table[cirq_reg].used = 1U; + cirq_all_events.table[cirq_reg].reg_num = cirq_reg; + } } - /* make sure all cirq setting take effect before doing other things */ - dmbsy(); } /* - * mt_cirq_unmask_all: Unmask all interrupts on SYS_CIRQ. + * 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 */ -void mt_cirq_unmask_all(void) +#ifdef CIRQ_WITH_POLARITY +static int mt_cirq_set_pol(uint32_t cirq_num, uint32_t pol) { - unsigned int i; + uint32_t base; + uint32_t bit = 1U << (cirq_num % 32U); - for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) { - mt_cirq_write32(0xFFFFFFFF, CIRQ_MASK_CLR_BASE + (i * 4U)); + 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; } - /* make sure all cirq setting take effect before doing other things */ - dmbsy(); + + mmio_write_32(base, bit); + return 0; } +#endif /* * mt_cirq_mask: Mask the specified SYS_CIRQ. @@ -151,11 +269,11 @@ static int mt_cirq_mask(uint32_t cirq_num) uint32_t bit = 1U << (cirq_num % 32U); if (cirq_num >= CIRQ_IRQ_NUM) { - ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num); return -1; } - mt_cirq_write32(bit, (cirq_num / 32U) * 4U + CIRQ_MASK_SET_BASE); + mmio_write_32((cirq_num / 32U) * 4U + CIRQ_MASK_SET_BASE, bit); + return 0; } @@ -171,324 +289,264 @@ static int mt_cirq_unmask(uint32_t cirq_num) uint32_t bit = 1U << (cirq_num % 32U); if (cirq_num >= CIRQ_IRQ_NUM) { - ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num); return -1; } - mt_cirq_write32(bit, (cirq_num / 32U) * 4U + CIRQ_MASK_CLR_BASE); + mmio_write_32((cirq_num / 32U) * 4U + CIRQ_MASK_CLR_BASE, bit); + return 0; } -/* - * mt_cirq_set_sens: Set the sensitivity for the specified SYS_CIRQ number. - * @cirq_num: the SYS_CIRQ number to set - * @sens: sensitivity to set - * @return: - * 0: set sens success - * -1: cirq num is out of range - */ -static int mt_cirq_set_sens(uint32_t cirq_num, uint32_t sens) +uint32_t mt_irq_get_en(uint32_t irq) { - uint32_t base; - uint32_t bit = 1U << (cirq_num % 32U); + uint32_t addr, st, val; - if (cirq_num >= CIRQ_IRQ_NUM) { - ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num); - return -1; - } + addr = BASE_GICD_BASE + GICD_ISENABLER + (irq / 32U) * 4U; + st = mmio_read_32(addr); - if (sens == MT_CIRQ_EDGE_SENSITIVE) { - base = (cirq_num / 32U) * 4U + CIRQ_SENS_CLR_BASE; - } else if (sens == MT_CIRQ_LEVEL_SENSITIVE) { - base = (cirq_num / 32U) * 4U + CIRQ_SENS_SET_BASE; - } else { - ERROR("[CIRQ] set_sens invalid sen value %u\n", sens); - return -1; - } + val = (st >> (irq % 32U)) & 1U; - mt_cirq_write32(bit, base); - return 0; + return val; } -/* - * mt_cirq_get_sens: Get the specified SYS_CIRQ sensitivity - * @cirq_num: the SYS_CIRQ number to get - * @return: - * 1: this cirq is MT_LEVEL_SENSITIVE - * 0: this cirq is MT_EDGE_SENSITIVE - * 2: cirq num is out of range - */ -__attribute__((weak)) unsigned int mt_cirq_get_sens(uint32_t cirq_num) +static void __cirq_fast_clone(void) { - uint32_t st; - unsigned int val; + struct cirq_reg *reg; + unsigned int i; - if (cirq_num >= CIRQ_IRQ_NUM) { - ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num); - return 2; - } + for (i = 0U; i < CIRQ_REG_NUM ; ++i) { + uint32_t cirq_bit; - st = mt_cirq_read32((cirq_num / 32U) * 4U + CIRQ_SENS_BASE); - val = (st >> (cirq_num % 32U)) & 1U; - return val; -} + reg = &cirq_all_events.table[i]; -/* - * 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 - */ -static int mt_cirq_set_pol(uint32_t cirq_num, uint32_t pol) -{ - uint32_t base; - uint32_t bit = 1U << (cirq_num % 32U); + if (reg->used == 0U) { + continue; + } - if (cirq_num >= CIRQ_IRQ_NUM) { - ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num); - return -1; - } + mmio_write_32(CIRQ_SENS_CLR_BASE + (reg->reg_num * 4U), + reg->sen); - 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 { - ERROR("[CIRQ] set_pol invalid polarity value %u\n", pol); - return -1; - } + 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; - mt_cirq_write32(bit, base); - return 0; -} + val = ((1U << cirq_bit) & reg->mask); -/* - * mt_cirq_get_pol: Get the specified SYS_CIRQ polarity - * @cirq_num: the SYS_CIRQ number to get - * @return: - * 1: this cirq is MT_CIRQ_POL_POS - * 0: this cirq is MT_CIRQ_POL_NEG - * 2: cirq num is out of range - */ -__attribute__((weak)) unsigned int mt_cirq_get_pol(uint32_t cirq_num) -{ - uint32_t st; - unsigned int val; + if (val == 0U) { + continue; + } - if (cirq_num >= CIRQ_IRQ_NUM) { - ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num); - return 2; + 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); + } + } } +} - st = mt_cirq_read32((cirq_num / 32U) * 4U + CIRQ_POL_BASE); - val = (st >> (cirq_num % 32U)) & 1U; - return val; +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_get_pending: Get the specified SYS_CIRQ pending - * @cirq_num: the SYS_CIRQ number to get - * @return: - * 1: this cirq is pending - * 0: this cirq is not pending - * 2: cirq num is out of range + * mt_cirq_clone_gic: Copy the setting from GIC to SYS_CIRQ */ -static unsigned int mt_cirq_get_pending(uint32_t cirq_num) +void mt_cirq_clone_gic(void) { - uint32_t st; - unsigned int val; + cirq_fast_clone(); +} - if (cirq_num >= CIRQ_IRQ_NUM) { - ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num); - return 2; +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); } - st = mt_cirq_read32((cirq_num / 32U) * 4U + CIRQ_STA_BASE); - val = (st >> (cirq_num % 32U)) & 1U; - return val; + return pending_vec; +} + +static int mt_cirq_get_mask_vec(unsigned int i) +{ + return mmio_read_32((i * 4U) + CIRQ_MASK_BASE); } /* - * mt_cirq_clone_pol: Copy the polarity setting from GIC to SYS_CIRQ + * mt_cirq_ack_all: Ack all the interrupt on SYS_CIRQ */ -void mt_cirq_clone_pol(void) +void mt_cirq_ack_all(void) { - uint32_t cirq_num; + uint32_t ack_vec, pend_vec, mask_vec; + unsigned int i; - for (cirq_num = 0U; cirq_num < CIRQ_IRQ_NUM; cirq_num++) { - mt_cirq_set_pol(cirq_num, MT_CIRQ_POL_POS); + 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_clone_sens: Copy the sensitivity setting from GIC to SYS_CIRQ + * mt_cirq_enable: Enable SYS_CIRQ */ -void mt_cirq_clone_sens(void) +void mt_cirq_enable(void) { - uint32_t cirq_num, irq_num; - uint32_t st, val; - - for (cirq_num = 0U; cirq_num < CIRQ_IRQ_NUM; cirq_num++) { - irq_num = CIRQ_TO_IRQ_NUM(cirq_num); + uint32_t st; - if ((cirq_num == 0U) || (irq_num % 16U == 0U)) { - st = mmio_read_32(BASE_GICD_BASE + GICD_ICFGR + - (irq_num / 16U * 4U)); - } + /* level only */ + mt_cirq_ack_all(); - val = (st >> ((irq_num % 16U) * 2U)) & 0x2U; + st = mmio_read_32(CIRQ_CON); + /* + * CIRQ could monitor edge/level trigger + */ + st |= (CIRQ_CON_EN << CIRQ_CON_EN_BITS); - if (val) { - mt_cirq_set_sens(cirq_num, MT_CIRQ_EDGE_SENSITIVE); - } else { - mt_cirq_set_sens(cirq_num, MT_CIRQ_LEVEL_SENSITIVE); - } - } + mmio_write_32(CIRQ_CON, (st & CIRQ_CON_BITS_MASK)); } /* - * mt_cirq_clone_mask: Copy the mask setting from GIC to SYS_CIRQ + * mt_cirq_disable: Disable SYS_CIRQ */ -void mt_cirq_clone_mask(void) +void mt_cirq_disable(void) { - uint32_t cirq_num, irq_num; - uint32_t st, val; + uint32_t st; - for (cirq_num = 0U; cirq_num < CIRQ_IRQ_NUM; cirq_num++) { - irq_num = CIRQ_TO_IRQ_NUM(cirq_num); + st = mmio_read_32(CIRQ_CON); + st &= ~(CIRQ_CON_EN << CIRQ_CON_EN_BITS); + mmio_write_32(CIRQ_CON, (st & CIRQ_CON_BITS_MASK)); +} - if ((cirq_num == 0U) || (irq_num % 32U == 0U)) { - st = mmio_read_32(BASE_GICD_BASE + - GICD_ISENABLER + (irq_num / 32U * 4U)); - } +void mt_irq_unmask_for_sleep_ex(uint32_t irq) +{ + uint32_t mask; - val = (st >> (irq_num % 32)) & 1U; + mask = 1U << (irq % 32U); - if (val) { - mt_cirq_unmask(cirq_num); - } else { - mt_cirq_mask(cirq_num); - } - } + mmio_write_32(BASE_GICD_BASE + GICD_ISENABLER + + ((irq / 32U) * 4U), mask); } -/* - * mt_cirq_clone_gic: Copy the setting from GIC to SYS_CIRQ - */ -void mt_cirq_clone_gic(void) +void mt_cirq_mask_all(void) { - mt_cirq_clone_sens(); - mt_cirq_clone_mask(); + unsigned int i; + + for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) { + mmio_write_32(CIRQ_MASK_SET_BASE + (i * 4U), 0xFFFFFFFF); + } + dsb(); } -/* - * mt_cirq_disable: Flush interrupt from SYS_CIRQ to GIC - */ -void mt_cirq_flush(void) +static void cirq_fast_sw_flush(void) { + struct cirq_reg *reg; unsigned int i; - unsigned char cirq_p_val = 0U; - unsigned char irq_p_val = 0U; - uint32_t irq_p = 0U; - unsigned char pass = 1U; - uint32_t first_cirq_found = 0U; - uint32_t first_flushed_cirq; - uint32_t first_irq_flushedto; - uint32_t last_fluashed_cirq; - uint32_t last_irq_flushedto; - - if (cirq_pattern_clone_flush_check_val == 1U) { - if (cirq_pattern_list < CIRQ_IRQ_NUM) { - mt_cirq_unmask(cirq_pattern_list); - mt_cirq_set_sens(cirq_pattern_list, - MT_CIRQ_EDGE_SENSITIVE); - mt_cirq_set_pol(cirq_pattern_list, MT_CIRQ_POL_NEG); - mt_cirq_set_pol(cirq_pattern_list, MT_CIRQ_POL_POS); - mt_cirq_set_pol(cirq_pattern_list, MT_CIRQ_POL_NEG); - } else { - ERROR("[CIRQ] no pattern to test,"); - ERROR("input pattern first\n"); - } - ERROR("[CIRQ] cirq_pattern %u, cirq_p %u,", - cirq_pattern_list, - mt_cirq_get_pending(cirq_pattern_list)); - ERROR("cirq_s %u, cirq_con 0x%x\n", - mt_cirq_get_sens(cirq_pattern_list), - mt_cirq_read32(CIRQ_CON)); - } - mt_cirq_unmask_all(); + for (i = 0U; i < CIRQ_REG_NUM ; ++i) { + uint32_t cirq_bit; - for (i = 0U; i < CIRQ_IRQ_NUM; i++) { - cirq_p_val = mt_cirq_get_pending(i); - if (cirq_p_val) { - mt_irq_set_pending(CIRQ_TO_IRQ_NUM(i)); + reg = &cirq_all_events.table[i]; + + if (reg->used == 0U) { + continue; } - if (cirq_clone_flush_check_val == 1U) { - if (cirq_p_val == 0U) { + 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; - } - irq_p = CIRQ_TO_IRQ_NUM(i); - irq_p_val = mt_irq_get_pending(irq_p); - if (cirq_p_val != irq_p_val) { - ERROR("[CIRQ] CIRQ Flush Failed "); - ERROR("%u(cirq %d)!= %u(gic %d)\n", - cirq_p_val, i, irq_p_val, - CIRQ_TO_IRQ_NUM(i)); - pass = 0; - } else { - ERROR("[CIRQ] CIRQ Flush Pass "); - ERROR("%u(cirq %d) = %u(gic %d)\n", - cirq_p_val, i, irq_p_val, - CIRQ_TO_IRQ_NUM(i)); } - if (!first_cirq_found) { - first_flushed_cirq = i; - first_irq_flushedto = irq_p; - first_cirq_found = 1U; + + 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__); } - last_fluashed_cirq = i; - last_irq_flushedto = irq_p; } } +} - if (cirq_clone_flush_check_val == 1U) { - if (first_cirq_found) { - ERROR("[CIRQ] The first flush : CIRQ%u to IRQ%u\n", - first_flushed_cirq, first_irq_flushedto); - ERROR("[CIRQ] The last flush : CIRQ%u to IRQ%u\n", - last_fluashed_cirq, last_irq_flushedto); - } else { - ERROR("[CIRQ] There are no pending "); - ERROR("interrupt in CIRQ\n"); - ERROR("[CIRQ] so no flush operation happened\n"); - } - ERROR("[CIRQ] The Flush Max Range : CIRQ"); - ERROR("%d to IRQ%d ~ CIRQ%d to IRQ%d\n", 0U, - CIRQ_TO_IRQ_NUM(0U), CIRQ_IRQ_NUM - 1U, - CIRQ_TO_IRQ_NUM(CIRQ_IRQ_NUM - 1U)); - ERROR("[CIRQ] Flush Check %s, Confirm:SPI_START_OFFSET:%d\n", - pass == 1 ? "Pass" : "Failed", CIRQ_SPI_START); - } +/* + * 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 = mt_cirq_read32(CIRQ_CON); + st = mmio_read_32(CIRQ_CON); st |= (CIRQ_SW_RESET << CIRQ_CON_SW_RST_BITS); - - mt_cirq_write32(st, CIRQ_CON); -} - -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; + mmio_write_32(CIRQ_CON, st); +#endif } diff --git a/plat/mediatek/mt8192/plat_pm.c b/plat/mediatek/mt8192/plat_pm.c index becf5d311a..6a74c02dd1 100644 --- a/plat/mediatek/mt8192/plat_pm.c +++ b/plat/mediatek/mt8192/plat_pm.c @@ -5,17 +5,351 @@ */ /* common headers */ +#include <assert.h> + #include <arch_helpers.h> #include <common/debug.h> #include <drivers/gpio.h> #include <lib/psci/psci.h> -/* mediatek platform specific headers */ +/* 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(); +} -/******************************************************************************* - * MTK handlers to shutdown/reboot the system - ******************************************************************************/ static void __dead2 plat_mtk_system_reset(void) { struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset(); @@ -29,18 +363,35 @@ static void __dead2 plat_mtk_system_reset(void) panic(); } -/******************************************************************************* - * MTK_platform handler called when an affinity instance is about to be turned - * on. The level and mpidr determine the affinity instance. - ******************************************************************************/ -static const plat_psci_ops_t plat_plat_pm_ops = { - .system_reset = plat_mtk_system_reset, +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_plat_pm_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 0000000000..f97684f772 --- /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 index aa4975e80a..8c1231a6eb 100644 --- a/plat/mediatek/mt8192/plat_topology.c +++ b/plat/mediatek/mt8192/plat_topology.c @@ -17,6 +17,8 @@ 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, diff --git a/plat/mediatek/mt8192/platform.mk b/plat/mediatek/mt8192/platform.mk index 7544b26583..a5e7ee26a5 100644 --- a/plat/mediatek/mt8192/platform.mk +++ b/plat/mediatek/mt8192/platform.mk @@ -10,8 +10,16 @@ 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/timer/ + -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 @@ -23,25 +31,41 @@ PLAT_BL_COMMON_SOURCES := ${GICV3_SOURCES} \ 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 diff --git a/plat/nxp/common/plat_make_helper/plat_build_macros.mk b/plat/nxp/common/plat_make_helper/plat_build_macros.mk new file mode 100644 index 0000000000..bba5e36fff --- /dev/null +++ b/plat/nxp/common/plat_make_helper/plat_build_macros.mk @@ -0,0 +1,11 @@ +# +# Copyright (c) 2020, NXP. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +define SET_NXP_MAKE_FLAG +$1 := yes +$2_$1 := yes +endef diff --git a/plat/qemu/common/aarch64/plat_helpers.S b/plat/qemu/common/aarch64/plat_helpers.S index b54617385b..08b2817351 100644 --- a/plat/qemu/common/aarch64/plat_helpers.S +++ b/plat/qemu/common/aarch64/plat_helpers.S @@ -32,7 +32,8 @@ endfunc plat_my_core_pos func plat_qemu_calc_core_pos and x1, x0, #MPIDR_CPU_MASK and x0, x0, #MPIDR_CLUSTER_MASK - add x0, x1, x0, LSR #6 + add x0, x1, x0, LSR #(MPIDR_AFFINITY_BITS -\ + PLATFORM_CPU_PER_CLUSTER_SHIFT) ret endfunc plat_qemu_calc_core_pos diff --git a/plat/qemu/common/qemu_common.c b/plat/qemu/common/qemu_common.c index 7f8e4c4940..47ec79114e 100644 --- a/plat/qemu/common/qemu_common.c +++ b/plat/qemu/common/qemu_common.c @@ -26,7 +26,7 @@ #ifdef DEVICE2_BASE #define MAP_DEVICE2 MAP_REGION_FLAT(DEVICE2_BASE, \ DEVICE2_SIZE, \ - MT_DEVICE | MT_RO | MT_SECURE) + MT_DEVICE | MT_RW | MT_SECURE) #endif #define MAP_SHARED_RAM MAP_REGION_FLAT(SHARED_RAM_BASE, \ @@ -93,7 +93,11 @@ static const mmap_region_t plat_qemu_mmap[] = { #ifdef MAP_DEVICE1 MAP_DEVICE1, #endif +#ifdef MAP_DEVICE2 + MAP_DEVICE2, +#endif #if SPM_MM + MAP_NS_DRAM0, QEMU_SPM_BUF_EL3_MMAP, #else MAP_BL32_MEM, @@ -108,6 +112,9 @@ static const mmap_region_t plat_qemu_mmap[] = { #ifdef MAP_DEVICE1 MAP_DEVICE1, #endif +#ifdef MAP_DEVICE2 + MAP_DEVICE2, +#endif {0} }; #endif diff --git a/plat/qemu/common/qemu_spm.c b/plat/qemu/common/qemu_spm.c index e9ab1a5c37..93dd2b37d7 100644 --- a/plat/qemu/common/qemu_spm.c +++ b/plat/qemu/common/qemu_spm.c @@ -3,7 +3,12 @@ * Copyright (c) 2020, Linaro Limited and Contributors. All rights reserved. */ +#include <libfdt.h> + #include <bl31/ehf.h> +#include <common/debug.h> +#include <common/fdt_fixup.h> +#include <common/fdt_wrappers.h> #include <lib/xlat_tables/xlat_tables_compat.h> #include <services/spm_mm_partition.h> @@ -14,12 +19,13 @@ DEVICE1_SIZE, \ MT_DEVICE | MT_RW | MT_SECURE | MT_USER) -const mmap_region_t plat_qemu_secure_partition_mmap[] = { - MAP_DEVICE1_EL0, /* for the UART */ +mmap_region_t plat_qemu_secure_partition_mmap[] = { + QEMU_SP_IMAGE_NS_BUF_MMAP, /* must be placed at first entry */ + MAP_DEVICE1_EL0, /* for the UART */ QEMU_SP_IMAGE_MMAP, QEMU_SPM_BUF_EL0_MMAP, - QEMU_SP_IMAGE_NS_BUF_MMAP, QEMU_SP_IMAGE_RW_MMAP, + MAP_SECURE_VARSTORE, {0} }; @@ -38,7 +44,7 @@ static spm_mm_mp_info_t sp_mp_info[] = { [7] = {0x80000007, 0} }; -const spm_mm_boot_info_t plat_qemu_secure_partition_boot_info = { +spm_mm_boot_info_t plat_qemu_secure_partition_boot_info = { .h.type = PARAM_SP_IMAGE_BOOT_INFO, .h.version = VERSION_1, .h.size = sizeof(spm_mm_boot_info_t), @@ -65,12 +71,63 @@ ehf_pri_desc_t qemu_exceptions[] = { EHF_PRI_DESC(QEMU_PRI_BITS, PLAT_SP_PRI) }; +int dt_add_ns_buf_node(uintptr_t *base) +{ + uintptr_t addr; + size_t size; + uintptr_t ns_buf_addr; + int node; + int err; + void *fdt = (void *)ARM_PRELOADED_DTB_BASE; + + err = fdt_open_into(fdt, fdt, PLAT_QEMU_DT_MAX_SIZE); + if (err < 0) { + ERROR("Invalid Device Tree at %p: error %d\n", fdt, err); + return err; + } + + /* + * reserved-memory for standaloneMM non-secure buffer + * is allocated at the top of the first system memory region. + */ + node = fdt_path_offset(fdt, "/memory"); + + err = fdt_get_reg_props_by_index(fdt, node, 0, &addr, &size); + if (err < 0) { + ERROR("Failed to get the memory node information\n"); + return err; + } + INFO("System RAM @ 0x%lx - 0x%lx\n", addr, addr + size - 1); + + ns_buf_addr = addr + (size - PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE); + INFO("reserved-memory for spm-mm @ 0x%lx - 0x%llx\n", ns_buf_addr, + ns_buf_addr + PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE - 1); + + err = fdt_add_reserved_memory(fdt, "ns-buf-spm-mm", ns_buf_addr, + PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE); + if (err < 0) { + ERROR("Failed to add the reserved-memory node\n"); + return err; + } + + *base = ns_buf_addr; + return 0; +} + /* Plug in QEMU exceptions to Exception Handling Framework. */ EHF_REGISTER_PRIORITIES(qemu_exceptions, ARRAY_SIZE(qemu_exceptions), QEMU_PRI_BITS); const mmap_region_t *plat_get_secure_partition_mmap(void *cookie) { + uintptr_t ns_buf_base; + + dt_add_ns_buf_node(&ns_buf_base); + + plat_qemu_secure_partition_mmap[0].base_pa = ns_buf_base; + plat_qemu_secure_partition_mmap[0].base_va = ns_buf_base; + plat_qemu_secure_partition_boot_info.sp_ns_comm_buf_base = ns_buf_base; + return plat_qemu_secure_partition_mmap; } diff --git a/plat/qemu/common/qemu_stack_protector.c b/plat/qemu/common/qemu_stack_protector.c index c226158ad6..15ce3d6d2c 100644 --- a/plat/qemu/common/qemu_stack_protector.c +++ b/plat/qemu/common/qemu_stack_protector.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,17 +7,25 @@ #include <stdint.h> #include <arch_helpers.h> +#include <arch_features.h> #include <plat/common/platform.h> #define RANDOM_CANARY_VALUE ((u_register_t) 3288484550995823360ULL) u_register_t plat_get_stack_protector_canary(void) { +#if ENABLE_FEAT_RNG + /* Use the RNDR instruction if the CPU supports it */ + if (is_armv8_5_rng_present()) { + return read_rndr(); + } +#endif + /* - * Ideally, a random number should be returned instead of the + * Ideally, a random number should be returned above. If a random + * number generator is not supported, return instead a * combination of a timer's value and a compile-time constant. - * As the virt platform does not have any random number generator, - * this is better than nothing but not necessarily really secure. + * This is better than nothing but not necessarily really secure. */ return RANDOM_CANARY_VALUE ^ read_cntpct_el0(); } diff --git a/plat/qemu/qemu/include/platform_def.h b/plat/qemu/qemu/include/platform_def.h index ed4b748aff..e6bb1e6a9b 100644 --- a/plat/qemu/qemu/include/platform_def.h +++ b/plat/qemu/qemu/include/platform_def.h @@ -24,6 +24,14 @@ #define PLATFORM_CLUSTER1_CORE_COUNT U(0) #else #define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +/* + * Define the number of cores per cluster used in calculating core position. + * The cluster number is shifted by this value and added to the core ID, + * so its value represents log2(cores/cluster). + * Default is 2**(2) = 4 cores per cluster. + */ +#define PLATFORM_CPU_PER_CLUSTER_SHIFT U(2) + #define PLATFORM_CLUSTER_COUNT U(2) #define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER #define PLATFORM_CLUSTER1_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER diff --git a/plat/qemu/qemu_sbsa/include/platform_def.h b/plat/qemu/qemu_sbsa/include/platform_def.h index 76340051a3..b69c2ebefa 100644 --- a/plat/qemu/qemu_sbsa/include/platform_def.h +++ b/plat/qemu/qemu_sbsa/include/platform_def.h @@ -16,13 +16,17 @@ #define PLATFORM_STACK_SIZE 0x1000 -#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) -#define PLATFORM_CLUSTER_COUNT U(2) -#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER -#define PLATFORM_CLUSTER1_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER -#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT + \ - PLATFORM_CLUSTER1_CORE_COUNT) - +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(8) +/* + * Define the number of cores per cluster used in calculating core position. + * The cluster number is shifted by this value and added to the core ID, + * so its value represents log2(cores/cluster). + * Default is 2**(3) = 8 cores per cluster. + */ +#define PLATFORM_CPU_PER_CLUSTER_SHIFT U(3) +#define PLATFORM_CLUSTER_COUNT U(64) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \ + PLATFORM_MAX_CPUS_PER_CLUSTER) #define QEMU_PRIMARY_CPU U(0) #define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ @@ -85,7 +89,7 @@ */ #define SHARED_RAM_BASE SEC_SRAM_BASE -#define SHARED_RAM_SIZE 0x00001000 +#define SHARED_RAM_SIZE 0x00002000 #define PLAT_QEMU_TRUSTED_MAILBOX_BASE SHARED_RAM_BASE #define PLAT_QEMU_TRUSTED_MAILBOX_SIZE (8 + PLAT_QEMU_HOLD_SIZE) @@ -130,7 +134,7 @@ * Put BL3-1 at the top of the Trusted SRAM. BL31_BASE is calculated using the * current BL3-1 debug size plus a little space for growth. */ -#define BL31_SIZE 0x50000 +#define BL31_SIZE 0x300000 #define BL31_BASE (BL31_LIMIT - BL31_SIZE) #define BL31_LIMIT (BL1_RW_BASE) #define BL31_PROGBITS_LIMIT BL1_RW_BASE @@ -157,10 +161,10 @@ #define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 42) #if SPM_MM #define MAX_MMAP_REGIONS 12 -#define MAX_XLAT_TABLES 11 +#define MAX_XLAT_TABLES 12 #else #define MAX_MMAP_REGIONS 11 -#define MAX_XLAT_TABLES 10 +#define MAX_XLAT_TABLES 11 #endif #define MAX_IO_DEVICES 3 #define MAX_IO_HANDLES 4 @@ -203,7 +207,10 @@ #define DEVICE0_SIZE 0x04080000 /* This is map from NORMAL_UART up to SECURE_UART_MM */ #define DEVICE1_BASE 0x60000000 -#define DEVICE1_SIZE 0x00041000 +#define DEVICE1_SIZE 0x10041000 +/* This is a map for SECURE_EC */ +#define DEVICE2_BASE 0x50000000 +#define DEVICE2_SIZE 0x00001000 /* * GIC related constants @@ -300,10 +307,13 @@ /* * Shared memory between Normal world and S-EL0 for * passing data during service requests. It will be marked as RW and NS. + * This buffer is allocated at the top of NS_DRAM, the base address is + * overridden in SPM initialization. */ #define PLAT_QEMU_SP_IMAGE_NS_BUF_BASE (PLAT_QEMU_DT_BASE + \ PLAT_QEMU_DT_MAX_SIZE) -#define PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE ULL(0x10000) +#define PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE ULL(0x200000) + #define QEMU_SP_IMAGE_NS_BUF_MMAP MAP_REGION2( \ PLAT_QEMU_SP_IMAGE_NS_BUF_BASE, \ PLAT_QEMU_SP_IMAGE_NS_BUF_BASE, \ @@ -334,6 +344,19 @@ MT_USER, \ PAGE_SIZE) +/* + * Secure variable storage is located at Secure Flash. + */ +#if SPM_MM +#define QEMU_SECURE_VARSTORE_BASE 0x01000000 +#define QEMU_SECURE_VARSTORE_SIZE 0x00100000 +#define MAP_SECURE_VARSTORE MAP_REGION_FLAT( \ + QEMU_SECURE_VARSTORE_BASE, \ + QEMU_SECURE_VARSTORE_SIZE, \ + MT_MEMORY | MT_RW | \ + MT_SECURE | MT_USER) +#endif + /* Total number of memory regions with distinct properties */ #define PLAT_QEMU_SP_IMAGE_NUM_MEM_REGIONS 6 diff --git a/plat/qemu/qemu_sbsa/platform.mk b/plat/qemu/qemu_sbsa/platform.mk index acaa43f9ec..d45f3f156b 100644 --- a/plat/qemu/qemu_sbsa/platform.mk +++ b/plat/qemu/qemu_sbsa/platform.mk @@ -79,10 +79,12 @@ BL31_SOURCES += lib/cpus/aarch64/cortex_a57.S \ lib/semihosting/semihosting.c \ lib/semihosting/${ARCH}/semihosting_call.S \ plat/common/plat_psci_common.c \ - ${PLAT_QEMU_COMMON_PATH}/qemu_pm.c \ - ${PLAT_QEMU_COMMON_PATH}/topology.c \ + ${PLAT_QEMU_PATH}/sbsa_pm.c \ + ${PLAT_QEMU_PATH}/sbsa_topology.c \ ${PLAT_QEMU_COMMON_PATH}/aarch64/plat_helpers.S \ ${PLAT_QEMU_COMMON_PATH}/qemu_bl31_setup.c \ + common/fdt_fixup.c \ + common/fdt_wrappers.c \ ${QEMU_GIC_SOURCES} ifeq (${SPM_MM},1) BL31_SOURCES += ${PLAT_QEMU_COMMON_PATH}/qemu_spm.c diff --git a/plat/qemu/qemu_sbsa/sbsa_pm.c b/plat/qemu/qemu_sbsa/sbsa_pm.c new file mode 100644 index 0000000000..8d1e1d48c8 --- /dev/null +++ b/plat/qemu/qemu_sbsa/sbsa_pm.c @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2020, Nuvia Inc + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#include <arch_helpers.h> +#include <assert.h> +#include <lib/mmio.h> +#include <lib/psci/psci.h> +#include <plat/common/platform.h> + +#include <platform_def.h> +#include "sbsa_private.h" + +#define ADP_STOPPED_APPLICATION_EXIT 0x20026 + +/* + * Define offset and commands for the fake EC device + */ +#define SBSA_SECURE_EC_OFFSET 0x50000000 + +#define SBSA_SECURE_EC_CMD_SHUTDOWN 0x01 +#define SBSA_SECURE_EC_CMD_REBOOT 0x02 + +/* + * The secure entry point to be used on warm reset. + */ +static unsigned long secure_entrypoint; + +/* Make composite power state parameter till power level 0 */ +#if PSCI_EXTENDED_STATE_ID + +#define qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ + (((lvl0_state) << PSTATE_ID_SHIFT) | \ + ((type) << PSTATE_TYPE_SHIFT)) +#else +#define qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ + (((lvl0_state) << PSTATE_ID_SHIFT) | \ + ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \ + ((type) << PSTATE_TYPE_SHIFT)) +#endif /* PSCI_EXTENDED_STATE_ID */ + + +#define qemu_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \ + (((lvl1_state) << PLAT_LOCAL_PSTATE_WIDTH) | \ + qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type)) + + + +/* + * The table storing the valid idle power states. Ensure that the + * array entries are populated in ascending order of state-id to + * enable us to use binary search during power state validation. + * The table must be terminated by a NULL entry. + */ +static const unsigned int qemu_pm_idle_states[] = { + /* State-id - 0x01 */ + qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_RET, + MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY), + /* State-id - 0x02 */ + qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_OFF, + MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN), + /* State-id - 0x22 */ + qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_OFF, PLAT_LOCAL_STATE_OFF, + MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN), + 0 +}; + +/******************************************************************************* + * Platform handler called to check the validity of the power state + * parameter. The power state parameter has to be a composite power state. + ******************************************************************************/ +static int qemu_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int state_id; + unsigned int i; + + assert(req_state != NULL); + + /* + * Currently we are using a linear search for finding the matching + * entry in the idle power state array. This can be made a binary + * search if the number of entries justifies the additional complexity. + */ + for (i = 0U; qemu_pm_idle_states[i] != 0U; i++) { + if (power_state == qemu_pm_idle_states[i]) { + break; + } + } + + /* Return error if entry not found in the idle state array */ + if (qemu_pm_idle_states[i] == 0U) { + return PSCI_E_INVALID_PARAMS; + } + + i = 0U; + state_id = psci_get_pstate_id(power_state); + + /* Parse the State ID and populate the state info parameter */ + while (state_id != 0U) { + req_state->pwr_domain_state[i++] = state_id & + PLAT_LOCAL_PSTATE_MASK; + state_id >>= PLAT_LOCAL_PSTATE_WIDTH; + } + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Platform handler called when a CPU is about to enter standby. + ******************************************************************************/ +static void qemu_cpu_standby(plat_local_state_t cpu_state) +{ + + assert(cpu_state == PLAT_LOCAL_STATE_RET); + + /* + * Enter standby state + * dsb is good practice before using wfi to enter low power states + */ + dsb(); + wfi(); +} + +/******************************************************************************* + * Platform handler called when a power domain is about to be turned on. The + * mpidr determines the CPU to be turned on. + ******************************************************************************/ +static int qemu_pwr_domain_on(u_register_t mpidr) +{ + int pos = plat_core_pos_by_mpidr(mpidr); + uint64_t *hold_base = (uint64_t *)PLAT_QEMU_HOLD_BASE; + + if (pos < 0) { + return PSCI_E_INVALID_PARAMS; + } + + hold_base[pos] = PLAT_QEMU_HOLD_STATE_GO; + dsb(); + sev(); + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Platform handler called when a power domain is about to be turned off. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +static void qemu_pwr_domain_off(const psci_power_state_t *target_state) +{ + qemu_pwr_gic_off(); +} + +void __dead2 plat_secondary_cold_boot_setup(void); + +static void __dead2 +qemu_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state) +{ + disable_mmu_el3(); + plat_secondary_cold_boot_setup(); +} + +/******************************************************************************* + * Platform handler called when a power domain is about to be suspended. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +void qemu_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + assert(false); +} + +/******************************************************************************* + * Platform handler called when a power domain has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. + ******************************************************************************/ +void qemu_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == + PLAT_LOCAL_STATE_OFF); + + qemu_pwr_gic_on_finish(); +} + +/******************************************************************************* + * Platform handler called when a power domain has just been powered on after + * having been suspended earlier. The target_state encodes the low power state + * that each level has woken up from. + ******************************************************************************/ +void qemu_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +{ + assert(false); +} + +/******************************************************************************* + * Platform handlers to shutdown/reboot the system + ******************************************************************************/ +static void __dead2 qemu_system_off(void) +{ + mmio_write_32(SBSA_SECURE_EC_OFFSET, SBSA_SECURE_EC_CMD_SHUTDOWN); + panic(); +} + +static void __dead2 qemu_system_reset(void) +{ + mmio_write_32(SBSA_SECURE_EC_OFFSET, SBSA_SECURE_EC_CMD_REBOOT); + panic(); +} + +static const plat_psci_ops_t plat_qemu_psci_pm_ops = { + .cpu_standby = qemu_cpu_standby, + .pwr_domain_on = qemu_pwr_domain_on, + .pwr_domain_off = qemu_pwr_domain_off, + .pwr_domain_pwr_down_wfi = qemu_pwr_domain_pwr_down_wfi, + .pwr_domain_suspend = qemu_pwr_domain_suspend, + .pwr_domain_on_finish = qemu_pwr_domain_on_finish, + .pwr_domain_suspend_finish = qemu_pwr_domain_suspend_finish, + .system_off = qemu_system_off, + .system_reset = qemu_system_reset, + .validate_power_state = qemu_validate_power_state +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + uintptr_t *mailbox = (uintptr_t *)PLAT_QEMU_TRUSTED_MAILBOX_BASE; + + *mailbox = sec_entrypoint; + secure_entrypoint = (unsigned long)sec_entrypoint; + *psci_ops = &plat_qemu_psci_pm_ops; + + return 0; +} diff --git a/plat/qemu/qemu_sbsa/sbsa_private.h b/plat/qemu/qemu_sbsa/sbsa_private.h new file mode 100644 index 0000000000..a9f4601de8 --- /dev/null +++ b/plat/qemu/qemu_sbsa/sbsa_private.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020, Nuvia Inc + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SBSA_PRIVATE_H +#define SBSA_PRIVATE_H + +#include <stdint.h> + +unsigned int plat_qemu_calc_core_pos(u_register_t mpidr); + +void qemu_pwr_gic_on_finish(void); +void qemu_pwr_gic_off(void); + +#endif /* SBSA_PRIVATE_H */ diff --git a/plat/qemu/qemu_sbsa/sbsa_topology.c b/plat/qemu/qemu_sbsa/sbsa_topology.c new file mode 100644 index 0000000000..bd8d16b9ab --- /dev/null +++ b/plat/qemu/qemu_sbsa/sbsa_topology.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020, Nuvia Inc + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <common/debug.h> + +#include <platform_def.h> +#include "sbsa_private.h" + +/* The power domain tree descriptor */ +static unsigned char power_domain_tree_desc[PLATFORM_CLUSTER_COUNT + 1]; + +/******************************************************************************* + * This function returns the sbsa-ref default topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + unsigned int i; + + power_domain_tree_desc[0] = PLATFORM_CLUSTER_COUNT; + + for (i = 0U; i < PLATFORM_CLUSTER_COUNT; i++) { + power_domain_tree_desc[i + 1] = PLATFORM_MAX_CPUS_PER_CLUSTER; + } + + return 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; + + mpidr &= MPIDR_AFFINITY_MASK; + if ((mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0U) { + ERROR("Invalid MPIDR\n"); + 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) { + ERROR("cluster_id >= PLATFORM_CLUSTER_COUNT define\n"); + return -1; + } + + if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) { + ERROR("cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER define\n"); + return -1; + } + + return plat_qemu_calc_core_pos(mpidr); +} diff --git a/plat/qti/common/src/spmi_arb.c b/plat/qti/common/src/spmi_arb.c index 16e85a6fc4..4213ed1b33 100644 --- a/plat/qti/common/src/spmi_arb.c +++ b/plat/qti/common/src/spmi_arb.c @@ -10,8 +10,8 @@ #include <spmi_arb.h> -#define REG_APID_MAP(apid) (0x0C440900U + 4U * i) -#define NUM_APID 0x80 +#define REG_APID_MAP(apid) (0x0C440900U + sizeof(uint32_t) * apid) +#define NUM_APID ((0x1100U - 0x900U) / sizeof(uint32_t)) #define PPID_MASK (0xfffU << 8) diff --git a/plat/renesas/rcar/aarch64/plat_helpers.S b/plat/renesas/common/aarch64/plat_helpers.S index ec21f2510c..ec21f2510c 100644 --- a/plat/renesas/rcar/aarch64/plat_helpers.S +++ b/plat/renesas/common/aarch64/plat_helpers.S diff --git a/plat/renesas/rcar/aarch64/platform_common.c b/plat/renesas/common/aarch64/platform_common.c index b0a88cb6b1..b0a88cb6b1 100644 --- a/plat/renesas/rcar/aarch64/platform_common.c +++ b/plat/renesas/common/aarch64/platform_common.c diff --git a/plat/renesas/rcar/bl2_cpg_init.c b/plat/renesas/common/bl2_cpg_init.c index c3ca9ea16f..677a57d04a 100644 --- a/plat/renesas/rcar/bl2_cpg_init.c +++ b/plat/renesas/common/bl2_cpg_init.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,8 +7,8 @@ #include <common/debug.h> #include <lib/mmio.h> -#include "rcar_def.h" #include "cpg_registers.h" +#include "rcar_def.h" #include "rcar_private.h" static void bl2_secure_cpg_init(void); @@ -18,7 +18,7 @@ static void bl2_realtime_cpg_init_h3(void); static void bl2_system_cpg_init_h3(void); #endif -#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3) +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3) || (RCAR_LSI == RZ_G2M) static void bl2_realtime_cpg_init_m3(void); static void bl2_system_cpg_init_m3(void); #endif @@ -77,7 +77,7 @@ static void bl2_secure_cpg_init(void) stop_cr5 = 0xBFFFFFFFU; #endif - /** Secure Module Stop Control Registers */ + /* Secure Module Stop Control Registers */ cpg_write(SCMSTPCR0, 0xFFFFFFFFU); cpg_write(SCMSTPCR1, 0xFFFFFFFFU); cpg_write(SCMSTPCR2, stop_cr2); @@ -91,7 +91,7 @@ static void bl2_secure_cpg_init(void) cpg_write(SCMSTPCR10, 0xFFFFFFFFU); cpg_write(SCMSTPCR11, 0xFFFFFFFFU); - /** Secure Software Reset Access Enable Control Registers */ + /* Secure Software Reset Access Enable Control Registers */ cpg_write(SCSRSTECR0, 0x00000000U); cpg_write(SCSRSTECR1, 0x00000000U); cpg_write(SCSRSTECR2, reset_cr2); @@ -149,10 +149,10 @@ static void bl2_system_cpg_init_h3(void) } #endif -#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3) +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3) || (RCAR_LSI == RZ_G2M) static void bl2_realtime_cpg_init_m3(void) { - /** Realtime Module Stop Control Registers */ + /* Realtime Module Stop Control Registers */ cpg_write(RMSTPCR0, 0x00200000U); cpg_write(RMSTPCR1, 0xFFFFFFFFU); cpg_write(RMSTPCR2, 0x040E0FDCU); @@ -169,7 +169,7 @@ static void bl2_realtime_cpg_init_m3(void) static void bl2_system_cpg_init_m3(void) { - /** System Module Stop Control Registers */ + /* System Module Stop Control Registers */ cpg_write(SMSTPCR0, 0x00200000U); cpg_write(SMSTPCR1, 0xFFFFFFFFU); cpg_write(SMSTPCR2, 0x040E2FDCU); @@ -188,7 +188,7 @@ static void bl2_system_cpg_init_m3(void) #if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3N) static void bl2_realtime_cpg_init_m3n(void) { - /** Realtime Module Stop Control Registers */ + /* Realtime Module Stop Control Registers */ cpg_write(RMSTPCR0, 0x00210000U); cpg_write(RMSTPCR1, 0xFFFFFFFFU); cpg_write(RMSTPCR2, 0x040E0FDCU); @@ -362,7 +362,7 @@ void bl2_cpg_init(void) } #elif (RCAR_LSI == RCAR_H3) || (RCAR_LSI == RCAR_H3N) bl2_realtime_cpg_init_h3(); -#elif RCAR_LSI == RCAR_M3 +#elif (RCAR_LSI == RCAR_M3) || (RCAR_LSI == RZ_G2M) bl2_realtime_cpg_init_m3(); #elif RCAR_LSI == RCAR_M3N bl2_realtime_cpg_init_m3n(); @@ -408,7 +408,7 @@ void bl2_system_cpg_init(void) } #elif (RCAR_LSI == RCAR_H3) || (RCAR_LSI == RCAR_H3N) bl2_system_cpg_init_h3(); -#elif RCAR_LSI == RCAR_M3 +#elif (RCAR_LSI == RCAR_M3) || (RCAR_LSI == RZ_G2M) bl2_system_cpg_init_m3(); #elif RCAR_LSI == RCAR_M3N bl2_system_cpg_init_m3n(); diff --git a/plat/renesas/rcar/bl2_interrupt_error.c b/plat/renesas/common/bl2_interrupt_error.c index d9a4b8e628..d9a4b8e628 100644 --- a/plat/renesas/rcar/bl2_interrupt_error.c +++ b/plat/renesas/common/bl2_interrupt_error.c diff --git a/plat/renesas/rcar/bl2_plat_mem_params_desc.c b/plat/renesas/common/bl2_plat_mem_params_desc.c index bf2706d53f..bf2706d53f 100644 --- a/plat/renesas/rcar/bl2_plat_mem_params_desc.c +++ b/plat/renesas/common/bl2_plat_mem_params_desc.c diff --git a/plat/renesas/common/bl2_secure_setting.c b/plat/renesas/common/bl2_secure_setting.c new file mode 100644 index 0000000000..095d1f62a8 --- /dev/null +++ b/plat/renesas/common/bl2_secure_setting.c @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <lib/mmio.h> +#include <lib/utils_def.h> + +#include "axi_registers.h" +#include "lifec_registers.h" +#include "micro_delay.h" + +static void lifec_security_setting(void); +static void axi_security_setting(void); + +static const struct { + uint32_t reg; + uint32_t val; +} lifec[] = { + /* + * LIFEC0 (SECURITY) settings + * Security attribute setting for master ports + * Bit 0: ARM realtime core (Cortex-R7) master port + * 0: Non-Secure + */ + { SEC_SRC, 0x0000001EU }, + /* + * Security attribute setting for slave ports 0 to 15 + * {SEC_SEL0, 0xFFFFFFFFU}, + * {SEC_SEL1, 0xFFFFFFFFU}, + * {SEC_SEL2, 0xFFFFFFFFU}, + * Bit19: AXI-Bus (Main Memory domain AXI) slave ports + * 0: registers accessed from secure resource only + * Bit 9: DBSC4 register access slave ports. + * 0: registers accessed from secure resource only. + */ +#if (LIFEC_DBSC_PROTECT_ENABLE == 1) + { SEC_SEL3, 0xFFF7FDFFU }, +#else /* LIFEC_DBSC_PROTECT_ENABLE == 1 */ + { SEC_SEL3, 0xFFFFFFFFU }, +#endif /* LIFEC_DBSC_PROTECT_ENABLE == 1 */ + /* + * {SEC_SEL4, 0xFFFFFFFFU}, + * Bit 6: Boot ROM slave ports. + * 0: registers accessed from secure resource only + */ + { SEC_SEL5, 0xFFFFFFBFU }, + /* + * Bit13: SCEG PKA (secure APB) slave ports + * 0: registers accessed from secure resource only + * 1: Reserved[R-Car E3] + * Bit12: SCEG PKA (public APB) slave ports + * 0: registers accessed from secure resource only + * 1: Reserved[R-Car E3] + * Bit10: SCEG Secure Core slave ports + * 0: registers accessed from secure resource only + */ +#if (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RCAR_D3) + { SEC_SEL6, 0xFFFFFBFFU }, +#else /* (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RCAR_D3) */ + { SEC_SEL6, 0xFFFFCBFFU }, +#endif /* (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RCAR_D3) */ + /* + * {SEC_SEL7, 0xFFFFFFFFU}, + * {SEC_SEL8, 0xFFFFFFFFU}, + * {SEC_SEL9, 0xFFFFFFFFU}, + * {SEC_SEL10, 0xFFFFFFFFU}, + * {SEC_SEL11, 0xFFFFFFFFU}, + * {SEC_SEL12, 0xFFFFFFFFU}, + * Bit22: RPC slave ports. + * 0: registers accessed from secure resource only. + */ +#if (RCAR_RPC_HYPERFLASH_LOCKED == 1) + { SEC_SEL13, 0xFFBFFFFFU }, +#endif /* (RCAR_RPC_HYPERFLASH_LOCKED == 1) */ + /* + * Bit27: System Timer (SCMT) slave ports + * 0: registers accessed from secure resource only + * Bit26: System Watchdog Timer (SWDT) slave ports + * 0: registers accessed from secure resource only + */ + { SEC_SEL14, 0xF3FFFFFFU }, + /* + * Bit13: RST slave ports. + * 0: registers accessed from secure resource only + * Bit 7: Life Cycle 0 slave ports + * 0: registers accessed from secure resource only + */ + { SEC_SEL15, 0xFFFFFF3FU }, + /* + * Security group 0 attribute setting for master ports 0 + * Security group 1 attribute setting for master ports 0 + * {SEC_GRP0CR0, 0x00000000U}, + * {SEC_GRP1CR0, 0x00000000U}, + * Security group 0 attribute setting for master ports 1 + * Security group 1 attribute setting for master ports 1 + * {SEC_GRP0CR1, 0x00000000U}, + * {SEC_GRP1CR1, 0x00000000U}, + * Security group 0 attribute setting for master ports 2 + * Security group 1 attribute setting for master ports 2 + * Bit17: SCEG Secure Core master ports. + * SecurityGroup3 + */ + { SEC_GRP0CR2, 0x00020000U }, + { SEC_GRP1CR2, 0x00020000U }, + /* + * Security group 0 attribute setting for master ports 3 + * Security group 1 attribute setting for master ports 3 + * {SEC_GRP0CR3, 0x00000000U}, + * {SEC_GRP1CR3, 0x00000000U}, + * Security group 0 attribute setting for slave ports 0 + * Security group 1 attribute setting for slave ports 0 + * {SEC_GRP0COND0, 0x00000000U}, + * {SEC_GRP1COND0, 0x00000000U}, + * Security group 0 attribute setting for slave ports 1 + * Security group 1 attribute setting for slave ports 1 + * {SEC_GRP0COND1, 0x00000000U}, + * {SEC_GRP1COND1, 0x00000000U}, + * Security group 0 attribute setting for slave ports 2 + * Security group 1 attribute setting for slave ports 2 + * {SEC_GRP0COND2, 0x00000000U}, + * {SEC_GRP1COND2, 0x00000000U}, + * Security group 0 attribute setting for slave ports 3 + * Security group 1 attribute setting for slave ports 3 + * Bit19: AXI-Bus (Main Memory domain AXI) slave ports. + * SecurityGroup3 + * Bit 9: DBSC4 register access slave ports. + * SecurityGroup3 + */ +#if (LIFEC_DBSC_PROTECT_ENABLE == 1) + { SEC_GRP0COND3, 0x00080200U }, + { SEC_GRP1COND3, 0x00080200U }, +#else /* (LIFEC_DBSC_PROTECT_ENABLE == 1) */ + { SEC_GRP0COND3, 0x00000000U }, + { SEC_GRP1COND3, 0x00000000U }, +#endif /* (LIFEC_DBSC_PROTECT_ENABLE == 1) */ + /* + * Security group 0 attribute setting for slave ports 4 + * Security group 1 attribute setting for slave ports 4 + * {SEC_GRP0COND4, 0x00000000U}, + * {SEC_GRP1COND4, 0x00000000U}, + * Security group 0 attribute setting for slave ports 5 + * Security group 1 attribute setting for slave ports 5 + * Bit 6: Boot ROM slave ports + * SecurityGroup3 + */ + { SEC_GRP0COND5, 0x00000040U }, + { SEC_GRP1COND5, 0x00000040U }, + /* + * Security group 0 attribute setting for slave ports 6 + * Security group 1 attribute setting for slave ports 6 + * Bit13: SCEG PKA (secure APB) slave ports + * SecurityGroup3 + * Reserved[R-Car E3] + * Bit12: SCEG PKA (public APB) slave ports + * SecurityGroup3 + * Reserved[R-Car E3] + * Bit10: SCEG Secure Core slave ports + * SecurityGroup3 + */ +#if RCAR_LSI == RCAR_E3 + { SEC_GRP0COND6, 0x00000400U }, + { SEC_GRP1COND6, 0x00000400U }, +#else /* RCAR_LSI == RCAR_E3 */ + { SEC_GRP0COND6, 0x00003400U }, + { SEC_GRP1COND6, 0x00003400U }, +#endif /* RCAR_LSI == RCAR_E3 */ + /* + * Security group 0 attribute setting for slave ports 7 + * Security group 1 attribute setting for slave ports 7 + * {SEC_GRP0COND7, 0x00000000U}, + * {SEC_GRP1COND7, 0x00000000U}, + * Security group 0 attribute setting for slave ports 8 + * Security group 1 attribute setting for slave ports 8 + * {SEC_GRP0COND8, 0x00000000U}, + * {SEC_GRP1COND8, 0x00000000U}, + * Security group 0 attribute setting for slave ports 9 + * Security group 1 attribute setting for slave ports 9 + * {SEC_GRP0COND9, 0x00000000U}, + * {SEC_GRP1COND9, 0x00000000U}, + * Security group 0 attribute setting for slave ports 10 + * Security group 1 attribute setting for slave ports 10 + * {SEC_GRP0COND10, 0x00000000U}, + * {SEC_GRP1COND10, 0x00000000U}, + * Security group 0 attribute setting for slave ports 11 + * Security group 1 attribute setting for slave ports 11 + * {SEC_GRP0COND11, 0x00000000U}, + * {SEC_GRP1COND11, 0x00000000U}, + * Security group 0 attribute setting for slave ports 12 + * Security group 1 attribute setting for slave ports 12 + * {SEC_GRP0COND12, 0x00000000U}, + * {SEC_GRP1COND12, 0x00000000U}, + * Security group 0 attribute setting for slave ports 13 + * Security group 1 attribute setting for slave ports 13 + * Bit22: RPC slave ports. + * SecurityGroup3 + */ +#if (RCAR_RPC_HYPERFLASH_LOCKED == 1) + { SEC_GRP0COND13, 0x00400000U }, + { SEC_GRP1COND13, 0x00400000U }, +#endif /* (RCAR_RPC_HYPERFLASH_LOCKED == 1) */ + /* + * Security group 0 attribute setting for slave ports 14 + * Security group 1 attribute setting for slave ports 14 + * Bit26: System Timer (SCMT) slave ports + * SecurityGroup3 + * Bit27: System Watchdog Timer (SWDT) slave ports + * SecurityGroup3 + */ + { SEC_GRP0COND14, 0x0C000000U }, + { SEC_GRP1COND14, 0x0C000000U }, + /* + * Security group 0 attribute setting for slave ports 15 + * Security group 1 attribute setting for slave ports 15 + * Bit13: RST slave ports + * SecurityGroup3 + * Bit 7: Life Cycle 0 slave ports + * SecurityGroup3 + * Bit 6: TDBG slave ports + * SecurityGroup3 + */ + { SEC_GRP0COND15, 0x000000C0U }, + { SEC_GRP1COND15, 0x000000C0U }, + /* + * Security write protection attribute setting slave ports 0 + * {SEC_READONLY0, 0x00000000U}, + * Security write protection attribute setting slave ports 1 + * {SEC_READONLY1, 0x00000000U}, + * Security write protection attribute setting slave ports 2 + * {SEC_READONLY2, 0x00000000U}, + * Security write protection attribute setting slave ports 3 + * {SEC_READONLY3, 0x00000000U}, + * Security write protection attribute setting slave ports 4 + * {SEC_READONLY4, 0x00000000U}, + * Security write protection attribute setting slave ports 5 + * {SEC_READONLY5, 0x00000000U}, + * Security write protection attribute setting slave ports 6 + * {SEC_READONLY6, 0x00000000U}, + * Security write protection attribute setting slave ports 7 + * {SEC_READONLY7, 0x00000000U}, + * Security write protection attribute setting slave ports 8 + * {SEC_READONLY8, 0x00000000U}, + * Security write protection attribute setting slave ports 9 + * {SEC_READONLY9, 0x00000000U}, + * Security write protection attribute setting slave ports 10 + * {SEC_READONLY10, 0x00000000U}, + * Security write protection attribute setting slave ports 11 + * {SEC_READONLY11, 0x00000000U}, + * Security write protection attribute setting slave ports 12 + * {SEC_READONLY12, 0x00000000U}, + * Security write protection attribute setting slave ports 13 + * {SEC_READONLY13, 0x00000000U}, + * Security write protection attribute setting slave ports 14 + * {SEC_READONLY14, 0x00000000U}, + * Security write protection attribute setting slave ports 15 + * {SEC_READONLY15, 0x00000000U} + */ +}; + +/* AXI settings */ +static const struct { + uint32_t reg; + uint32_t val; +} axi[] = { + /* + * DRAM protection + * AXI dram protected area division + */ + {AXI_DPTDIVCR0, 0x0E0403F0U}, + {AXI_DPTDIVCR1, 0x0E0407E0U}, + {AXI_DPTDIVCR2, 0x0E080000U}, + {AXI_DPTDIVCR3, 0x0E080000U}, + {AXI_DPTDIVCR4, 0x0E080000U}, + {AXI_DPTDIVCR5, 0x0E080000U}, + {AXI_DPTDIVCR6, 0x0E080000U}, + {AXI_DPTDIVCR7, 0x0E080000U}, + {AXI_DPTDIVCR8, 0x0E080000U}, + {AXI_DPTDIVCR9, 0x0E080000U}, + {AXI_DPTDIVCR10, 0x0E080000U}, + {AXI_DPTDIVCR11, 0x0E080000U}, + {AXI_DPTDIVCR12, 0x0E080000U}, + {AXI_DPTDIVCR13, 0x0E080000U}, + {AXI_DPTDIVCR14, 0x0E080000U}, + /* AXI dram protected area setting */ + {AXI_DPTCR0, 0x0E000000U}, + {AXI_DPTCR1, 0x0E000E0EU}, + {AXI_DPTCR2, 0x0E000000U}, + {AXI_DPTCR3, 0x0E000000U}, + {AXI_DPTCR4, 0x0E000000U}, + {AXI_DPTCR5, 0x0E000000U}, + {AXI_DPTCR6, 0x0E000000U}, + {AXI_DPTCR7, 0x0E000000U}, + {AXI_DPTCR8, 0x0E000000U}, + {AXI_DPTCR9, 0x0E000000U}, + {AXI_DPTCR10, 0x0E000000U}, + {AXI_DPTCR11, 0x0E000000U}, + {AXI_DPTCR12, 0x0E000000U}, + {AXI_DPTCR13, 0x0E000000U}, + {AXI_DPTCR14, 0x0E000000U}, + {AXI_DPTCR15, 0x0E000000U}, + /* + * SRAM ptotection + * AXI sram protected area division + */ + {AXI_SPTDIVCR0, 0x0E0E6304U}, + {AXI_SPTDIVCR1, 0x0E0E6360U}, + {AXI_SPTDIVCR2, 0x0E0E6360U}, + {AXI_SPTDIVCR3, 0x0E0E6360U}, + {AXI_SPTDIVCR4, 0x0E0E6360U}, + {AXI_SPTDIVCR5, 0x0E0E6360U}, + {AXI_SPTDIVCR6, 0x0E0E6360U}, + {AXI_SPTDIVCR7, 0x0E0E6360U}, + {AXI_SPTDIVCR8, 0x0E0E6360U}, + {AXI_SPTDIVCR9, 0x0E0E6360U}, + {AXI_SPTDIVCR10, 0x0E0E6360U}, + {AXI_SPTDIVCR11, 0x0E0E6360U}, + {AXI_SPTDIVCR12, 0x0E0E6360U}, + {AXI_SPTDIVCR13, 0x0E0E6360U}, + {AXI_SPTDIVCR14, 0x0E0E6360U}, + /* AXI sram protected area setting */ + {AXI_SPTCR0, 0x0E000E0EU}, + {AXI_SPTCR1, 0x0E000000U}, + {AXI_SPTCR2, 0x0E000000U}, + {AXI_SPTCR3, 0x0E000000U}, + {AXI_SPTCR4, 0x0E000000U}, + {AXI_SPTCR5, 0x0E000000U}, + {AXI_SPTCR6, 0x0E000000U}, + {AXI_SPTCR7, 0x0E000000U}, + {AXI_SPTCR8, 0x0E000000U}, + {AXI_SPTCR9, 0x0E000000U}, + {AXI_SPTCR10, 0x0E000000U}, + {AXI_SPTCR11, 0x0E000000U}, + {AXI_SPTCR12, 0x0E000000U}, + {AXI_SPTCR13, 0x0E000000U}, + {AXI_SPTCR14, 0x0E000000U}, + {AXI_SPTCR15, 0x0E000000U} +}; + +static void lifec_security_setting(void) +{ + uint32_t i; + + for (i = 0; i < ARRAY_SIZE(lifec); i++) + mmio_write_32(lifec[i].reg, lifec[i].val); +} + +/* SRAM/DRAM protection setting */ +static void axi_security_setting(void) +{ + uint32_t i; + + for (i = 0; i < ARRAY_SIZE(axi); i++) + mmio_write_32(axi[i].reg, axi[i].val); +} + +void bl2_secure_setting(void) +{ + lifec_security_setting(); + axi_security_setting(); + rcar_micro_delay(10U); +} diff --git a/plat/renesas/rcar/bl31_plat_setup.c b/plat/renesas/common/bl31_plat_setup.c index 7bc0d8e27b..93798acfbc 100644 --- a/plat/renesas/rcar/bl31_plat_setup.c +++ b/plat/renesas/common/bl31_plat_setup.c @@ -28,7 +28,7 @@ static const uint64_t BL31_RO_LIMIT = BL_CODE_END; #if USE_COHERENT_MEM static const uint64_t BL31_COHERENT_RAM_BASE = BL_COHERENT_RAM_BASE; static const uint64_t BL31_COHERENT_RAM_LIMIT = BL_COHERENT_RAM_END; -#endif +#endif /* USE_COHERENT_MEM */ extern void plat_rcar_gic_driver_init(void); extern void plat_rcar_gic_init(void); @@ -84,11 +84,11 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, NOTICE("BL3-1 : Rev.%s\n", version_of_renesas); #if RCAR_LSI != RCAR_D3 - if (RCAR_CLUSTER_A53A57 == rcar_pwrc_get_cluster()) { + if (rcar_pwrc_get_cluster() == RCAR_CLUSTER_A53A57) { plat_cci_init(); plat_cci_enable(); } -#endif +#endif /* RCAR_LSI != RCAR_D3 */ } void bl31_plat_arch_setup(void) @@ -98,7 +98,7 @@ void bl31_plat_arch_setup(void) BL31_RO_BASE, BL31_RO_LIMIT #if USE_COHERENT_MEM , BL31_COHERENT_RAM_BASE, BL31_COHERENT_RAM_LIMIT -#endif +#endif /* USE_COHERENT_MEM */ ); rcar_pwrc_code_copy_to_system_ram(); } @@ -113,17 +113,20 @@ void bl31_platform_setup(void) rcar_pwrc_setup(); #if 0 - /* TODO: there is a broad number of rcar-gen3 SoC configurations; to - support all of them, Renesas use the pwrc driver to discover what - cores are on/off before announcing the topology. - This code hasnt been ported yet - */ + /* + * TODO: there is a broad number of rcar-gen3 SoC configurations; to + * support all of them, Renesas use the pwrc driver to discover what + * cores are on/off before announcing the topology. + * This code hasnt been ported yet + */ rcar_setup_topology(); #endif - /* mask should match the kernel's MPIDR_HWID_BITMASK so the core can be - identified during cpuhotplug (check the kernel's psci migrate set of - functions */ + /* + * mask should match the kernel's MPIDR_HWID_BITMASK so the core can be + * identified during cpuhotplug (check the kernel's psci migrate set of + * functions + */ rcar_boot_mpidr = read_mpidr_el1() & 0x0000ffffU; } diff --git a/plat/renesas/common/common.mk b/plat/renesas/common/common.mk new file mode 100644 index 0000000000..984ab5bace --- /dev/null +++ b/plat/renesas/common/common.mk @@ -0,0 +1,132 @@ +# +# Copyright (c) 2018-2020, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PROGRAMMABLE_RESET_ADDRESS := 0 +COLD_BOOT_SINGLE_CPU := 1 +ARM_CCI_PRODUCT_ID := 500 +TRUSTED_BOARD_BOOT := 1 +RESET_TO_BL31 := 1 +GENERATE_COT := 1 +BL2_AT_EL3 := 1 +ENABLE_SVE_FOR_NS := 0 +MULTI_CONSOLE_API := 1 + +CRASH_REPORTING := 1 +HANDLE_EA_EL3_FIRST := 1 + +$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) + +ifeq (${SPD},none) + SPD_NONE:=1 + $(eval $(call add_define,SPD_NONE)) +endif + +# LSI setting common define +RCAR_H3:=0 +RCAR_M3:=1 +RCAR_M3N:=2 +RCAR_E3:=3 +RCAR_H3N:=4 +RCAR_D3:=5 +RCAR_V3M:=6 +RCAR_AUTO:=99 +RZ_G2M:=100 +$(eval $(call add_define,RCAR_H3)) +$(eval $(call add_define,RCAR_M3)) +$(eval $(call add_define,RCAR_M3N)) +$(eval $(call add_define,RCAR_E3)) +$(eval $(call add_define,RCAR_H3N)) +$(eval $(call add_define,RCAR_D3)) +$(eval $(call add_define,RCAR_V3M)) +$(eval $(call add_define,RCAR_AUTO)) +$(eval $(call add_define,RZ_G2M)) + +RCAR_CUT_10:=0 +RCAR_CUT_11:=1 +RCAR_CUT_13:=3 +RCAR_CUT_20:=10 +RCAR_CUT_30:=20 +$(eval $(call add_define,RCAR_CUT_10)) +$(eval $(call add_define,RCAR_CUT_11)) +$(eval $(call add_define,RCAR_CUT_13)) +$(eval $(call add_define,RCAR_CUT_20)) +$(eval $(call add_define,RCAR_CUT_30)) + +# Enable workarounds for selected Cortex-A53 erratas. +ERRATA_A53_835769 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 + +# Enable workarounds for selected Cortex-A57 erratas. +ERRATA_A57_859972 := 1 +ERRATA_A57_813419 := 1 + +PLAT_INCLUDES := -Iplat/renesas/common/include/registers \ + -Iplat/renesas/common/include \ + -Iplat/renesas/common + +PLAT_BL_COMMON_SOURCES := drivers/renesas/common/iic_dvfs/iic_dvfs.c \ + plat/renesas/common/rcar_common.c + +RCAR_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + plat/common/plat_gicv2.c + +BL2_SOURCES += ${RCAR_GIC_SOURCES} \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S \ + ${LIBFDT_SRCS} \ + common/desc_image_load.c \ + plat/renesas/common/aarch64/platform_common.c \ + plat/renesas/common/aarch64/plat_helpers.S \ + plat/renesas/common/bl2_interrupt_error.c \ + plat/renesas/common/bl2_secure_setting.c \ + plat/renesas/common/plat_storage.c \ + plat/renesas/common/bl2_plat_mem_params_desc.c \ + plat/renesas/common/plat_image_load.c \ + plat/renesas/common/bl2_cpg_init.c \ + drivers/renesas/common/console/rcar_printf.c \ + drivers/renesas/common/scif/scif.S \ + drivers/renesas/common/common.c \ + drivers/renesas/common/io/io_emmcdrv.c \ + drivers/renesas/common/io/io_memdrv.c \ + drivers/renesas/common/io/io_rcar.c \ + drivers/renesas/common/auth/auth_mod.c \ + drivers/renesas/common/rpc/rpc_driver.c \ + drivers/renesas/common/dma/dma_driver.c \ + drivers/renesas/common/avs/avs_driver.c \ + drivers/renesas/common/delay/micro_delay.c \ + drivers/renesas/common/emmc/emmc_interrupt.c \ + drivers/renesas/common/emmc/emmc_utility.c \ + drivers/renesas/common/emmc/emmc_mount.c \ + drivers/renesas/common/emmc/emmc_init.c \ + drivers/renesas/common/emmc/emmc_read.c \ + drivers/renesas/common/emmc/emmc_cmd.c \ + drivers/renesas/common/watchdog/swdt.c \ + drivers/renesas/common/rom/rom_api.c \ + drivers/io/io_storage.c + +BL31_SOURCES += ${RCAR_GIC_SOURCES} \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S \ + plat/common/plat_psci_common.c \ + plat/renesas/common/plat_topology.c \ + plat/renesas/common/aarch64/plat_helpers.S \ + plat/renesas/common/aarch64/platform_common.c \ + plat/renesas/common/bl31_plat_setup.c \ + plat/renesas/common/plat_pm.c \ + drivers/renesas/common/console/rcar_console.S \ + drivers/renesas/common/console/rcar_printf.c \ + drivers/renesas/common/delay/micro_delay.c \ + drivers/renesas/common/pwrc/call_sram.S \ + drivers/renesas/common/pwrc/pwrc.c \ + drivers/renesas/common/common.c \ + drivers/arm/cci/cci.c + +include lib/xlat_tables_v2/xlat_tables.mk +include drivers/auth/mbedtls/mbedtls_crypto.mk +PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} diff --git a/plat/renesas/rcar/include/plat.ld.S b/plat/renesas/common/include/plat.ld.S index 7aef324c4f..7aef324c4f 100644 --- a/plat/renesas/rcar/include/plat.ld.S +++ b/plat/renesas/common/include/plat.ld.S diff --git a/plat/renesas/rcar/include/plat_macros.S b/plat/renesas/common/include/plat_macros.S index 927cd39e8f..927cd39e8f 100644 --- a/plat/renesas/rcar/include/plat_macros.S +++ b/plat/renesas/common/include/plat_macros.S diff --git a/plat/renesas/rcar/include/platform_def.h b/plat/renesas/common/include/platform_def.h index b7f0ca113e..73787140b5 100644 --- a/plat/renesas/rcar/include/platform_def.h +++ b/plat/renesas/common/include/platform_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved. + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -29,20 +29,20 @@ /* Size of cacheable stacks */ #if IMAGE_BL1 #if TRUSTED_BOARD_BOOT -#define PLATFORM_STACK_SIZE U(0x1000) +#define PLATFORM_STACK_SIZE U(0x1000) #else -#define PLATFORM_STACK_SIZE U(0x440) +#define PLATFORM_STACK_SIZE U(0x440) #endif #elif IMAGE_BL2 #if TRUSTED_BOARD_BOOT -#define PLATFORM_STACK_SIZE U(0x1000) +#define PLATFORM_STACK_SIZE U(0x1000) #else -#define PLATFORM_STACK_SIZE U(0x400) +#define PLATFORM_STACK_SIZE U(0x400) #endif #elif IMAGE_BL31 -#define PLATFORM_STACK_SIZE U(0x400) +#define PLATFORM_STACK_SIZE U(0x400) #elif IMAGE_BL32 -#define PLATFORM_STACK_SIZE U(0x440) +#define PLATFORM_STACK_SIZE U(0x440) #endif #define BL332_IMAGE_ID (NS_BL2U_IMAGE_ID + 1) @@ -97,11 +97,13 @@ #define MAX_IO_DEVICES U(3) #define MAX_IO_HANDLES U(4) -/******************************************************************************* +/* + ****************************************************************************** * BL2 specific defines. - ******************************************************************************/ -/* Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug - * size plus a little space for growth. */ + ****************************************************************************** + * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug + * size plus a little space for growth. + */ #define RCAR_SYSRAM_BASE U(0xE6300000) #if (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RCAR_D3) #define BL2_LIMIT U(0xE6320000) @@ -121,17 +123,19 @@ #endif #define RCAR_SYSRAM_SIZE (BL2_BASE - RCAR_SYSRAM_BASE) -/******************************************************************************* +/* + ****************************************************************************** * BL31 specific defines. - ******************************************************************************/ -/* Put BL3-1 at the top of the Trusted SRAM. BL31_BASE is calculated using the - * current BL3-1 debug size plus a little space for growth. */ + ****************************************************************************** + * Put BL3-1 at the top of the Trusted SRAM. BL31_BASE is calculated using the + * current BL3-1 debug size plus a little space for growth. + */ #define BL31_BASE (RCAR_TRUSTED_SRAM_BASE) #define BL31_LIMIT (RCAR_TRUSTED_SRAM_BASE + \ RCAR_TRUSTED_SRAM_SIZE) -#define RCAR_BL31_LOG_BASE (0x44040000) -#define RCAR_BL31_SDRAM_BTM (RCAR_BL31_LOG_BASE + 0x14000) -#define RCAR_BL31_LOG_SIZE (RCAR_BL31_SDRAM_BTM - RCAR_BL31_LOG_BASE) +#define RCAR_BL31_LOG_BASE (0x44040000) +#define RCAR_BL31_SDRAM_BTM (RCAR_BL31_LOG_BASE + 0x14000) +#define RCAR_BL31_LOG_SIZE (RCAR_BL31_SDRAM_BTM - RCAR_BL31_LOG_BASE) #define BL31_SRAM_BASE (DEVICE_SRAM_BASE) #define BL31_SRAM_LIMIT (DEVICE_SRAM_BASE + DEVICE_SRAM_SIZE) @@ -176,7 +180,7 @@ * 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 + * caches. Such alignment ensures that two mailboxes 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. diff --git a/plat/renesas/rcar/include/rcar_def.h b/plat/renesas/common/include/rcar_def.h index 0ffbfe979d..6c5b295615 100644 --- a/plat/renesas/rcar/include/rcar_def.h +++ b/plat/renesas/common/include/rcar_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -33,13 +33,13 @@ #define DRAM1_SIZE U(0x80000000) #define DRAM1_NS_BASE (DRAM1_BASE + U(0x10000000)) #define DRAM1_NS_SIZE (DRAM1_SIZE - DRAM1_NS_BASE) -#define DRAM_40BIT_BASE ULL(0x0400000000) -#define DRAM_40BIT_SIZE ULL(0x0400000000) -#define DRAM_PROTECTED_BASE ULL(0x43F00000) -#define DRAM_40BIT_PROTECTED_BASE ULL(0x0403F00000) -#define DRAM_PROTECTED_SIZE ULL(0x03F00000) -#define RCAR_BL31_CRASH_BASE U(0x4403F000) -#define RCAR_BL31_CRASH_SIZE U(0x00001000) +#define DRAM_40BIT_BASE ULL(0x0400000000) +#define DRAM_40BIT_SIZE ULL(0x0400000000) +#define DRAM_PROTECTED_BASE ULL(0x43F00000) +#define DRAM_40BIT_PROTECTED_BASE ULL(0x0403F00000) +#define DRAM_PROTECTED_SIZE ULL(0x03F00000) +#define RCAR_BL31_CRASH_BASE U(0x4403F000) +#define RCAR_BL31_CRASH_SIZE U(0x00001000) /* Entrypoint mailboxes */ #define MBOX_BASE RCAR_SHARED_MEM_BASE #define MBOX_SIZE 0x200 @@ -47,15 +47,19 @@ #define PARAMS_BASE (MBOX_BASE + MBOX_SIZE) #define BOOT_KIND_BASE (RCAR_SHARED_MEM_BASE + \ RCAR_SHARED_MEM_SIZE - 0x100) -/* The number of regions like RO(code), coherent and data required by - * different BL stages which need to be mapped in the MMU */ +/* + * The number of regions like RO(code), coherent and data required by + * different BL stages which need to be mapped in the MMU + */ #if USE_COHERENT_MEM #define RCAR_BL_REGIONS (3) #else #define RCAR_BL_REGIONS (2) #endif -/* The RCAR_MAX_MMAP_REGIONS depend on the number of entries in rcar_mmap[] - * defined for each BL stage in rcar_common.c. */ +/* + * The RCAR_MAX_MMAP_REGIONS depends on the number of entries in rcar_mmap[] + * defined for each BL stage in rcar_common.c. + */ #if IMAGE_BL2 #define RCAR_MMAP_ENTRIES (9) #endif @@ -73,24 +77,24 @@ /* BL33 */ #define NS_IMAGE_OFFSET (DRAM1_BASE + U(0x09000000)) /* BL31 */ -#define RCAR_DEVICE_BASE DEVICE_RCAR_BASE -#define RCAR_DEVICE_SIZE (0x1A000000) -#define RCAR_LOG_RES_SIZE (512/8) -#define RCAR_LOG_HEADER_SIZE (16) -#define RCAR_LOG_OTHER_SIZE (RCAR_LOG_HEADER_SIZE + \ +#define RCAR_DEVICE_BASE DEVICE_RCAR_BASE +#define RCAR_DEVICE_SIZE (0x1A000000) +#define RCAR_LOG_RES_SIZE (64) +#define RCAR_LOG_HEADER_SIZE (16) +#define RCAR_LOG_OTHER_SIZE (RCAR_LOG_HEADER_SIZE + \ RCAR_LOG_RES_SIZE) -#define RCAR_BL31_LOG_MAX (RCAR_BL31_LOG_SIZE - \ +#define RCAR_BL31_LOG_MAX (RCAR_BL31_LOG_SIZE - \ RCAR_LOG_OTHER_SIZE) -#define RCAR_CRASH_STACK RCAR_BL31_CRASH_BASE -#define AARCH64_SPACE_BASE ULL(0x00000000000) -#define AARCH64_SPACE_SIZE ULL(0x10000000000) +#define RCAR_CRASH_STACK RCAR_BL31_CRASH_BASE +#define AARCH64_SPACE_BASE ULL(0x00000000000) +#define AARCH64_SPACE_SIZE ULL(0x10000000000) /* CCI related constants */ #define CCI500_BASE U(0xF1200000) #define CCI500_CLUSTER0_SL_IFACE_IX (2) #define CCI500_CLUSTER1_SL_IFACE_IX (3) #define CCI500_CLUSTER0_SL_IFACE_IX_FOR_M3 (1) #define CCI500_CLUSTER1_SL_IFACE_IX_FOR_M3 (2) -#define RCAR_CCI_BASE CCI500_BASE +#define RCAR_CCI_BASE CCI500_BASE /* GIC */ #define RCAR_GICD_BASE U(0xF1010000) #define RCAR_GICR_BASE U(0xF1010000) @@ -106,47 +110,47 @@ #define ARM_IRQ_SEC_SGI_5 U(13) #define ARM_IRQ_SEC_SGI_6 U(14) #define ARM_IRQ_SEC_SGI_7 U(15) -#define ARM_IRQ_SEC_RPC U(70) -#define ARM_IRQ_SEC_TIMER U(166) -#define ARM_IRQ_SEC_TIMER_UP U(171) -#define ARM_IRQ_SEC_WDT U(173) -#define ARM_IRQ_SEC_CRYPT U(102) -#define ARM_IRQ_SEC_CRYPT_SecPKA U(97) -#define ARM_IRQ_SEC_CRYPT_PubPKA U(98) +#define ARM_IRQ_SEC_RPC U(70) +#define ARM_IRQ_SEC_TIMER U(166) +#define ARM_IRQ_SEC_TIMER_UP U(171) +#define ARM_IRQ_SEC_WDT U(173) +#define ARM_IRQ_SEC_CRYPT U(102) +#define ARM_IRQ_SEC_CRYPT_SecPKA U(97) +#define ARM_IRQ_SEC_CRYPT_PubPKA U(98) /* Timer control */ -#define RCAR_CNTC_BASE U(0xE6080000) +#define RCAR_CNTC_BASE U(0xE6080000) /* Reset */ -#define RCAR_CPGWPR U(0xE6150900) /* CPG write protect */ -#define RCAR_MODEMR U(0xE6160060) /* Mode pin */ -#define RCAR_CA57RESCNT U(0xE6160040) /* Reset control A57 */ -#define RCAR_CA53RESCNT U(0xE6160044) /* Reset control A53 */ -#define RCAR_SRESCR U(0xE6160110) /* Soft Power On Reset */ -#define RCAR_CA53WUPCR U(0xE6151010) /* Wake-up control A53 */ -#define RCAR_CA57WUPCR U(0xE6152010) /* Wake-up control A57 */ -#define RCAR_CA53PSTR U(0xE6151040) /* Power status A53 */ -#define RCAR_CA57PSTR U(0xE6152040) /* Power status A57 */ -#define RCAR_CA53CPU0CR U(0xE6151100) /* CPU control A53 */ -#define RCAR_CA57CPU0CR U(0xE6152100) /* CPU control A57 */ -#define RCAR_CA53CPUCMCR U(0xE6151184) /* Common power A53 */ -#define RCAR_CA57CPUCMCR U(0xE6152184) /* Common power A57 */ -#define RCAR_WUPMSKCA57 U(0xE6180014) /* Wake-up mask A57 */ -#define RCAR_WUPMSKCA53 U(0xE6180018) /* Wake-up mask A53 */ +#define RCAR_CPGWPR U(0xE6150900) /* CPG write protect */ +#define RCAR_MODEMR U(0xE6160060) /* Mode pin */ +#define RCAR_CA57RESCNT U(0xE6160040) /* Reset control A57 */ +#define RCAR_CA53RESCNT U(0xE6160044) /* Reset control A53 */ +#define RCAR_SRESCR U(0xE6160110) /* Soft Power On Reset */ +#define RCAR_CA53WUPCR U(0xE6151010) /* Wake-up control A53 */ +#define RCAR_CA57WUPCR U(0xE6152010) /* Wake-up control A57 */ +#define RCAR_CA53PSTR U(0xE6151040) /* Power status A53 */ +#define RCAR_CA57PSTR U(0xE6152040) /* Power status A57 */ +#define RCAR_CA53CPU0CR U(0xE6151100) /* CPU control A53 */ +#define RCAR_CA57CPU0CR U(0xE6152100) /* CPU control A57 */ +#define RCAR_CA53CPUCMCR U(0xE6151184) /* Common power A53 */ +#define RCAR_CA57CPUCMCR U(0xE6152184) /* Common power A57 */ +#define RCAR_WUPMSKCA57 U(0xE6180014) /* Wake-up mask A57 */ +#define RCAR_WUPMSKCA53 U(0xE6180018) /* Wake-up mask A53 */ /* SYSC */ -#define RCAR_PWRSR3 U(0xE6180140) /* Power stat A53-SCU */ -#define RCAR_PWRSR5 U(0xE61801C0) /* Power stat A57-SCU */ -#define RCAR_SYSCIER U(0xE618000C) /* Interrupt enable */ -#define RCAR_SYSCIMR U(0xE6180010) /* Interrupt mask */ -#define RCAR_SYSCSR U(0xE6180000) /* SYSC status */ -#define RCAR_PWRONCR3 U(0xE618014C) /* Power resume A53-SCU */ -#define RCAR_PWRONCR5 U(0xE61801CC) /* Power resume A57-SCU */ -#define RCAR_PWROFFCR3 U(0xE6180144) /* Power shutof A53-SCU */ -#define RCAR_PWROFFCR5 U(0xE61801C4) /* Power shutof A57-SCU */ -#define RCAR_PWRER3 U(0xE6180154) /* shutoff/resume error */ -#define RCAR_PWRER5 U(0xE61801D4) /* shutoff/resume error */ -#define RCAR_SYSCISR U(0xE6180004) /* Interrupt status */ -#define RCAR_SYSCISCR U(0xE6180008) /* Interrupt stat clear */ +#define RCAR_PWRSR3 U(0xE6180140) /* Power stat A53-SCU */ +#define RCAR_PWRSR5 U(0xE61801C0) /* Power stat A57-SCU */ +#define RCAR_SYSCIER U(0xE618000C) /* Interrupt enable */ +#define RCAR_SYSCIMR U(0xE6180010) /* Interrupt mask */ +#define RCAR_SYSCSR U(0xE6180000) /* SYSC status */ +#define RCAR_PWRONCR3 U(0xE618014C) /* Power resume A53-SCU */ +#define RCAR_PWRONCR5 U(0xE61801CC) /* Power resume A57-SCU */ +#define RCAR_PWROFFCR3 U(0xE6180144) /* Power shutoff A53-SCU */ +#define RCAR_PWROFFCR5 U(0xE61801C4) /* Power shutoff A57-SCU */ +#define RCAR_PWRER3 U(0xE6180154) /* shutoff/resume error */ +#define RCAR_PWRER5 U(0xE61801D4) /* shutoff/resume error */ +#define RCAR_SYSCISR U(0xE6180004) /* Interrupt status */ +#define RCAR_SYSCISCR U(0xE6180008) /* Interrupt stat clear */ /* Product register */ -#define RCAR_PRR U(0xFFF00044) +#define RCAR_PRR U(0xFFF00044) #define RCAR_M3_CUT_VER11 U(0x00000010) /* M3 Ver.1.1/Ver.1.2 */ #define RCAR_MAJOR_MASK U(0x000000F0) #define RCAR_MINOR_MASK U(0x0000000F) @@ -198,39 +202,39 @@ /* Memory mapped Generic timer interfaces */ #define ARM_SYS_CNTCTL_BASE RCAR_CNTC_BASE /* MODEMR PLL masks and bitfield values */ -#define CHECK_MD13_MD14 U(0x6000) -#define MD14_MD13_TYPE_0 U(0x0000) /* MD14=0 MD13=0 */ -#define MD14_MD13_TYPE_1 U(0x2000) /* MD14=0 MD13=1 */ -#define MD14_MD13_TYPE_2 U(0x4000) /* MD14=1 MD13=0 */ -#define MD14_MD13_TYPE_3 U(0x6000) /* MD14=1 MD13=1 */ +#define CHECK_MD13_MD14 U(0x6000) +#define MD14_MD13_TYPE_0 U(0x0000) /* MD14=0 MD13=0 */ +#define MD14_MD13_TYPE_1 U(0x2000) /* MD14=0 MD13=1 */ +#define MD14_MD13_TYPE_2 U(0x4000) /* MD14=1 MD13=0 */ +#define MD14_MD13_TYPE_3 U(0x6000) /* MD14=1 MD13=1 */ /* Frequency of EXTAL(Hz) */ -#define EXTAL_MD14_MD13_TYPE_0 U(8333300) /* MD14=0 MD13=0 */ -#define EXTAL_MD14_MD13_TYPE_1 U(10000000) /* MD14=0 MD13=1 */ -#define EXTAL_MD14_MD13_TYPE_2 U(12500000) /* MD14=1 MD13=0 */ -#define EXTAL_MD14_MD13_TYPE_3 U(16666600) /* MD14=1 MD13=1 */ -#define EXTAL_SALVATOR_XS U(8320000) /* Salvator-XS */ +#define EXTAL_MD14_MD13_TYPE_0 U(8333300) /* MD14=0 MD13=0 */ +#define EXTAL_MD14_MD13_TYPE_1 U(10000000) /* MD14=0 MD13=1 */ +#define EXTAL_MD14_MD13_TYPE_2 U(12500000) /* MD14=1 MD13=0 */ +#define EXTAL_MD14_MD13_TYPE_3 U(16666600) /* MD14=1 MD13=1 */ +#define EXTAL_SALVATOR_XS U(8320000) /* Salvator-XS */ #define EXTAL_EBISU U(24000000) /* Ebisu */ #define EXTAL_DRAAK U(24000000) /* Draak */ -/* CPG write protect registers */ -#define CPGWPR_PASSWORD (0x5A5AFFFFU) -#define CPGWPCR_PASSWORD (0xA5A50000U) +/* CPG write protect registers */ +#define CPGWPR_PASSWORD (0x5A5AFFFFU) +#define CPGWPCR_PASSWORD (0xA5A50000U) /* CA5x Debug Resource control registers */ -#define CPG_CA57DBGRCR (CPG_BASE + 0x2180U) -#define CPG_CA53DBGRCR (CPG_BASE + 0x1180U) -#define DBGCPUPREN ((uint32_t)1U << 19U) -#define CPG_PLL0CR (CPG_BASE + 0x00D8U) -#define CPG_PLL2CR (CPG_BASE + 0x002CU) -#define CPG_PLL4CR (CPG_BASE + 0x01F4U) +#define CPG_CA57DBGRCR (CPG_BASE + 0x2180U) +#define CPG_CA53DBGRCR (CPG_BASE + 0x1180U) +#define DBGCPUPREN ((uint32_t)1U << 19U) +#define CPG_PLL0CR (CPG_BASE + 0x00D8U) +#define CPG_PLL2CR (CPG_BASE + 0x002CU) +#define CPG_PLL4CR (CPG_BASE + 0x01F4U) #define CPG_CPGWPCR (CPG_BASE + 0x0904U) /* RST Registers */ -#define RST_BASE (0xE6160000U) -#define RST_WDTRSTCR (RST_BASE + 0x0054U) +#define RST_BASE (0xE6160000U) +#define RST_WDTRSTCR (RST_BASE + 0x0054U) #define RST_MODEMR (RST_BASE + 0x0060U) -#define WDTRSTCR_PASSWORD (0xA55A0000U) -#define WDTRSTCR_RWDT_RSTMSK ((uint32_t)1U << 0U) +#define WDTRSTCR_PASSWORD (0xA55A0000U) +#define WDTRSTCR_RWDT_RSTMSK ((uint32_t)1U << 0U) /* MFIS Registers */ -#define MFISWPCNTR_PASSWORD (0xACCE0000U) -#define MFISWPCNTR (0xE6260900U) +#define MFISWPCNTR_PASSWORD (0xACCE0000U) +#define MFISWPCNTR (0xE6260900U) /* IPMMU registers */ #define IPMMU_MM_BASE (0xE67B0000U) #define IPMMUMM_IMSCTLR (IPMMU_MM_BASE + 0x0500U) @@ -263,8 +267,8 @@ #define IPMMU_DS1_BASE (0xE7740000U) #define IPMMUDS1_IMSCTLR (IPMMU_DS1_BASE + 0x0500U) /* ARMREG registers */ -#define P_ARMREG_SEC_CTRL (0xE62711F0U) -#define P_ARMREG_SEC_CTRL_PROT (0x00000001U) +#define P_ARMREG_SEC_CTRL (0xE62711F0U) +#define P_ARMREG_SEC_CTRL_PROT (0x00000001U) /* MIDR */ #define MIDR_CA57 (0x0D07U << MIDR_PN_SHIFT) #define MIDR_CA53 (0x0D03U << MIDR_PN_SHIFT) @@ -279,28 +283,28 @@ #define RCAR_COLD_BOOT (0x00U) #define RCAR_WARM_BOOT (0x01U) #if PMIC_ROHM_BD9571 && RCAR_SYSTEM_RESET_KEEPON_DDR -#define KEEP10_MAGIC (0x55U) +#define KEEP10_MAGIC (0x55U) #endif /* lossy registers */ -#define LOSSY_PARAMS_BASE (0x47FD7000U) -#define AXI_DCMPAREACRA0 (0xE6784100U) -#define AXI_DCMPAREACRB0 (0xE6784104U) +#define LOSSY_PARAMS_BASE (0x47FD7000U) +#define AXI_DCMPAREACRA0 (0xE6784100U) +#define AXI_DCMPAREACRB0 (0xE6784104U) #define LOSSY_ENABLE (0x80000000U) #define LOSSY_DISABLE (0x00000000U) #define LOSSY_FMT_YUVPLANAR (0x00000000U) #define LOSSY_FMT_YUV422INTLV (0x20000000U) #define LOSSY_FMT_ARGB8888 (0x40000000U) -#define LOSSY_ST_ADDR0 (0x54000000U) -#define LOSSY_END_ADDR0 (0x57000000U) -#define LOSSY_FMT0 LOSSY_FMT_YUVPLANAR -#define LOSSY_ENA_DIS0 LOSSY_ENABLE -#define LOSSY_ST_ADDR1 0x0U -#define LOSSY_END_ADDR1 0x0U -#define LOSSY_FMT1 LOSSY_FMT_ARGB8888 -#define LOSSY_ENA_DIS1 LOSSY_DISABLE -#define LOSSY_ST_ADDR2 0x0U -#define LOSSY_END_ADDR2 0x0U -#define LOSSY_FMT2 LOSSY_FMT_YUV422INTLV -#define LOSSY_ENA_DIS2 LOSSY_DISABLE +#define LOSSY_ST_ADDR0 (0x54000000U) +#define LOSSY_END_ADDR0 (0x57000000U) +#define LOSSY_FMT0 LOSSY_FMT_YUVPLANAR +#define LOSSY_ENA_DIS0 LOSSY_ENABLE +#define LOSSY_ST_ADDR1 0x0U +#define LOSSY_END_ADDR1 0x0U +#define LOSSY_FMT1 LOSSY_FMT_ARGB8888 +#define LOSSY_ENA_DIS1 LOSSY_DISABLE +#define LOSSY_ST_ADDR2 0x0U +#define LOSSY_END_ADDR2 0x0U +#define LOSSY_FMT2 LOSSY_FMT_YUV422INTLV +#define LOSSY_ENA_DIS2 LOSSY_DISABLE #endif /* RCAR_DEF_H */ diff --git a/plat/renesas/rcar/include/rcar_private.h b/plat/renesas/common/include/rcar_private.h index a76c0238b4..36f4ca540e 100644 --- a/plat/renesas/rcar/include/rcar_private.h +++ b/plat/renesas/common/include/rcar_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,12 +7,12 @@ #ifndef RCAR_PRIVATE_H #define RCAR_PRIVATE_H -#include <platform_def.h> - #include <common/bl_common.h> #include <lib/bakery_lock.h> #include <lib/el3_runtime/cpu_data.h> +#include <platform_def.h> + typedef volatile struct mailbox { unsigned long value __aligned(CACHE_WRITEBACK_GRANULE); } mailbox_t; @@ -62,17 +62,18 @@ typedef struct rcar_cpu_data { */ #define rcar_lock_init(_lock_arg) -#define rcar_lock_get(_lock_arg) \ - bakery_lock_get(_lock_arg, \ +#define rcar_lock_get(_lock_arg) \ + bakery_lock_get(_lock_arg, \ CPU_DATA_PLAT_PCPU_OFFSET + RCAR_CPU_DATA_LOCK_OFFSET) #define rcar_lock_release(_lock_arg) \ - bakery_lock_release(_lock_arg, \ + bakery_lock_release(_lock_arg, \ CPU_DATA_PLAT_PCPU_OFFSET + RCAR_CPU_DATA_LOCK_OFFSET) -/* Ensure that the size of the RCAR specific per-cpu data structure and the size +/* + * Ensure that the size of the RCAR specific per-cpu data structure and the size * of the memory allocated in generic per-cpu data for the platform are the same */ -CASSERT(PLAT_PCPU_DATA_SIZE == sizeof(rcar_cpu_data_t), +CASSERT(sizeof(rcar_cpu_data_t) == PLAT_PCPU_DATA_SIZE, rcar_pcpu_data_size_mismatch); #endif /* @@ -84,7 +85,7 @@ void rcar_configure_mmu_el3(unsigned long total_base, #if USE_COHERENT_MEM , unsigned long coh_start, unsigned long coh_limit #endif - ); + ); void rcar_setup_topology(void); void rcar_cci_disable(void); diff --git a/plat/renesas/rcar/include/rcar_version.h b/plat/renesas/common/include/rcar_version.h index 67cbd71abc..67cbd71abc 100644 --- a/plat/renesas/rcar/include/rcar_version.h +++ b/plat/renesas/common/include/rcar_version.h diff --git a/plat/renesas/rcar/include/registers/axi_registers.h b/plat/renesas/common/include/registers/axi_registers.h index 36cd58bd9e..36cd58bd9e 100644 --- a/plat/renesas/rcar/include/registers/axi_registers.h +++ b/plat/renesas/common/include/registers/axi_registers.h diff --git a/plat/renesas/rcar/include/registers/cpg_registers.h b/plat/renesas/common/include/registers/cpg_registers.h index 0d698d9c1b..0d698d9c1b 100644 --- a/plat/renesas/rcar/include/registers/cpg_registers.h +++ b/plat/renesas/common/include/registers/cpg_registers.h diff --git a/plat/renesas/common/include/registers/lifec_registers.h b/plat/renesas/common/include/registers/lifec_registers.h new file mode 100644 index 0000000000..5f49e52c0f --- /dev/null +++ b/plat/renesas/common/include/registers/lifec_registers.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef LIFEC_REGISTERS_H +#define LIFEC_REGISTERS_H + +#define LIFEC_SEC_BASE (0xE6110000U) + +#define SEC_SRC (LIFEC_SEC_BASE + 0x0008U) +#define SEC_SEL0 (LIFEC_SEC_BASE + 0x0030U) +#define SEC_SEL1 (LIFEC_SEC_BASE + 0x0034U) +#define SEC_SEL2 (LIFEC_SEC_BASE + 0x0038U) +#define SEC_SEL3 (LIFEC_SEC_BASE + 0x003CU) +#define SEC_SEL4 (LIFEC_SEC_BASE + 0x0058U) +#define SEC_SEL5 (LIFEC_SEC_BASE + 0x005CU) +#define SEC_SEL6 (LIFEC_SEC_BASE + 0x0060U) +#define SEC_SEL7 (LIFEC_SEC_BASE + 0x0064U) +#define SEC_SEL8 (LIFEC_SEC_BASE + 0x0068U) +#define SEC_SEL9 (LIFEC_SEC_BASE + 0x006CU) +#define SEC_SEL10 (LIFEC_SEC_BASE + 0x0070U) +#define SEC_SEL11 (LIFEC_SEC_BASE + 0x0074U) +#define SEC_SEL12 (LIFEC_SEC_BASE + 0x0078U) +#define SEC_SEL13 (LIFEC_SEC_BASE + 0x007CU) +#define SEC_SEL14 (LIFEC_SEC_BASE + 0x0080U) +#define SEC_SEL15 (LIFEC_SEC_BASE + 0x0084U) +#define SEC_GRP0CR0 (LIFEC_SEC_BASE + 0x0138U) +#define SEC_GRP1CR0 (LIFEC_SEC_BASE + 0x013CU) +#define SEC_GRP0CR1 (LIFEC_SEC_BASE + 0x0140U) +#define SEC_GRP1CR1 (LIFEC_SEC_BASE + 0x0144U) +#define SEC_GRP0CR2 (LIFEC_SEC_BASE + 0x0148U) +#define SEC_GRP1CR2 (LIFEC_SEC_BASE + 0x014CU) +#define SEC_GRP0CR3 (LIFEC_SEC_BASE + 0x0150U) +#define SEC_GRP1CR3 (LIFEC_SEC_BASE + 0x0154U) +#define SEC_GRP0COND0 (LIFEC_SEC_BASE + 0x0158U) +#define SEC_GRP1COND0 (LIFEC_SEC_BASE + 0x015CU) +#define SEC_GRP0COND1 (LIFEC_SEC_BASE + 0x0160U) +#define SEC_GRP1COND1 (LIFEC_SEC_BASE + 0x0164U) +#define SEC_GRP0COND2 (LIFEC_SEC_BASE + 0x0168U) +#define SEC_GRP1COND2 (LIFEC_SEC_BASE + 0x016CU) +#define SEC_GRP0COND3 (LIFEC_SEC_BASE + 0x0170U) +#define SEC_GRP1COND3 (LIFEC_SEC_BASE + 0x0174U) +#define SEC_GRP0COND4 (LIFEC_SEC_BASE + 0x0178U) +#define SEC_GRP1COND4 (LIFEC_SEC_BASE + 0x017CU) +#define SEC_GRP0COND5 (LIFEC_SEC_BASE + 0x0180U) +#define SEC_GRP1COND5 (LIFEC_SEC_BASE + 0x0184U) +#define SEC_GRP0COND6 (LIFEC_SEC_BASE + 0x0188U) +#define SEC_GRP1COND6 (LIFEC_SEC_BASE + 0x018CU) +#define SEC_GRP0COND7 (LIFEC_SEC_BASE + 0x0190U) +#define SEC_GRP1COND7 (LIFEC_SEC_BASE + 0x0194U) +#define SEC_GRP0COND8 (LIFEC_SEC_BASE + 0x0198U) +#define SEC_GRP1COND8 (LIFEC_SEC_BASE + 0x019CU) +#define SEC_GRP0COND9 (LIFEC_SEC_BASE + 0x01A0U) +#define SEC_GRP1COND9 (LIFEC_SEC_BASE + 0x01A4U) +#define SEC_GRP0COND10 (LIFEC_SEC_BASE + 0x01A8U) +#define SEC_GRP1COND10 (LIFEC_SEC_BASE + 0x01ACU) +#define SEC_GRP0COND11 (LIFEC_SEC_BASE + 0x01B0U) +#define SEC_GRP1COND11 (LIFEC_SEC_BASE + 0x01B4U) +#define SEC_GRP0COND12 (LIFEC_SEC_BASE + 0x01B8U) +#define SEC_GRP1COND12 (LIFEC_SEC_BASE + 0x01BCU) +#define SEC_GRP0COND13 (LIFEC_SEC_BASE + 0x01C0U) +#define SEC_GRP1COND13 (LIFEC_SEC_BASE + 0x01C4U) +#define SEC_GRP0COND14 (LIFEC_SEC_BASE + 0x01C8U) +#define SEC_GRP1COND14 (LIFEC_SEC_BASE + 0x01CCU) +#define SEC_GRP0COND15 (LIFEC_SEC_BASE + 0x01D0U) +#define SEC_GRP1COND15 (LIFEC_SEC_BASE + 0x01D4U) +#define SEC_READONLY0 (LIFEC_SEC_BASE + 0x01D8U) +#define SEC_READONLY1 (LIFEC_SEC_BASE + 0x01DCU) +#define SEC_READONLY2 (LIFEC_SEC_BASE + 0x01E0U) +#define SEC_READONLY3 (LIFEC_SEC_BASE + 0x01E4U) +#define SEC_READONLY4 (LIFEC_SEC_BASE + 0x01E8U) +#define SEC_READONLY5 (LIFEC_SEC_BASE + 0x01ECU) +#define SEC_READONLY6 (LIFEC_SEC_BASE + 0x01F0U) +#define SEC_READONLY7 (LIFEC_SEC_BASE + 0x01F4U) +#define SEC_READONLY8 (LIFEC_SEC_BASE + 0x01F8U) +#define SEC_READONLY9 (LIFEC_SEC_BASE + 0x01FCU) +#define SEC_READONLY10 (LIFEC_SEC_BASE + 0x0200U) +#define SEC_READONLY11 (LIFEC_SEC_BASE + 0x0204U) +#define SEC_READONLY12 (LIFEC_SEC_BASE + 0x0208U) +#define SEC_READONLY13 (LIFEC_SEC_BASE + 0x020CU) +#define SEC_READONLY14 (LIFEC_SEC_BASE + 0x0210U) +#define SEC_READONLY15 (LIFEC_SEC_BASE + 0x0214U) + +#define LIFEC_SAFE_BASE (0xE6120000U) +#define SAFE_GRP0CR0 (LIFEC_SAFE_BASE + 0x0138U) +#define SAFE_GRP1CR0 (LIFEC_SAFE_BASE + 0x013CU) +#define SAFE_GRP0CR1 (LIFEC_SAFE_BASE + 0x0140U) +#define SAFE_GRP1CR1 (LIFEC_SAFE_BASE + 0x0144U) +#define SAFE_GRP0CR2 (LIFEC_SAFE_BASE + 0x0148U) +#define SAFE_GRP1CR2 (LIFEC_SAFE_BASE + 0x014CU) +#define SAFE_GRP0CR3 (LIFEC_SAFE_BASE + 0x0150U) +#define SAFE_GRP1CR3 (LIFEC_SAFE_BASE + 0x0154U) +#define SAFE_GRP0COND0 (LIFEC_SAFE_BASE + 0x0158U) +#define SAFE_GRP1COND0 (LIFEC_SAFE_BASE + 0x015CU) +#define SAFE_GRP0COND1 (LIFEC_SAFE_BASE + 0x0160U) +#define SAFE_GRP1COND1 (LIFEC_SAFE_BASE + 0x0164U) +#define SAFE_GRP0COND2 (LIFEC_SAFE_BASE + 0x0168U) +#define SAFE_GRP1COND2 (LIFEC_SAFE_BASE + 0x016CU) +#define SAFE_GRP0COND3 (LIFEC_SAFE_BASE + 0x0170U) +#define SAFE_GRP1COND3 (LIFEC_SAFE_BASE + 0x0174U) +#define SAFE_GRP0COND4 (LIFEC_SAFE_BASE + 0x0178U) +#define SAFE_GRP1COND4 (LIFEC_SAFE_BASE + 0x017CU) +#define SAFE_GRP0COND5 (LIFEC_SAFE_BASE + 0x0180U) +#define SAFE_GRP1COND5 (LIFEC_SAFE_BASE + 0x0184U) +#define SAFE_GRP0COND6 (LIFEC_SAFE_BASE + 0x0188U) +#define SAFE_GRP1COND6 (LIFEC_SAFE_BASE + 0x018CU) +#define SAFE_GRP0COND7 (LIFEC_SAFE_BASE + 0x0190U) +#define SAFE_GRP1COND7 (LIFEC_SAFE_BASE + 0x0194U) +#define SAFE_GRP0COND8 (LIFEC_SAFE_BASE + 0x0198U) +#define SAFE_GRP1COND8 (LIFEC_SAFE_BASE + 0x019CU) +#define SAFE_GRP0COND9 (LIFEC_SAFE_BASE + 0x01A0U) +#define SAFE_GRP1COND9 (LIFEC_SAFE_BASE + 0x01A4U) +#define SAFE_GRP0COND10 (LIFEC_SAFE_BASE + 0x01A8U) +#define SAFE_GRP1COND10 (LIFEC_SAFE_BASE + 0x01ACU) +#define SAFE_GRP0COND11 (LIFEC_SAFE_BASE + 0x01B0U) +#define SAFE_GRP1COND11 (LIFEC_SAFE_BASE + 0x01B4U) +#define SAFE_GRP0COND12 (LIFEC_SAFE_BASE + 0x01B8U) +#define SAFE_GRP1COND12 (LIFEC_SAFE_BASE + 0x01BCU) +#define SAFE_GRP0COND13 (LIFEC_SAFE_BASE + 0x01C0U) +#define SAFE_GRP1COND13 (LIFEC_SAFE_BASE + 0x01C4U) +#define SAFE_GRP0COND14 (LIFEC_SAFE_BASE + 0x01C8U) +#define SAFE_GRP1COND14 (LIFEC_SAFE_BASE + 0x01CCU) +#define SAFE_GRP0COND15 (LIFEC_SAFE_BASE + 0x01D0U) +#define SAFE_GRP1COND15 (LIFEC_SAFE_BASE + 0x01D4U) +#define SAFE_READONLY0 (LIFEC_SAFE_BASE + 0x01D8U) +#define SAFE_READONLY1 (LIFEC_SAFE_BASE + 0x01DCU) +#define SAFE_READONLY2 (LIFEC_SAFE_BASE + 0x01E0U) +#define SAFE_READONLY3 (LIFEC_SAFE_BASE + 0x01E4U) +#define SAFE_READONLY4 (LIFEC_SAFE_BASE + 0x01E8U) +#define SAFE_READONLY5 (LIFEC_SAFE_BASE + 0x01ECU) +#define SAFE_READONLY6 (LIFEC_SAFE_BASE + 0x01F0U) +#define SAFE_READONLY7 (LIFEC_SAFE_BASE + 0x01F4U) +#define SAFE_READONLY8 (LIFEC_SAFE_BASE + 0x01F8U) +#define SAFE_READONLY9 (LIFEC_SAFE_BASE + 0x01FCU) +#define SAFE_READONLY10 (LIFEC_SAFE_BASE + 0x0200U) +#define SAFE_READONLY11 (LIFEC_SAFE_BASE + 0x0204U) +#define SAFE_READONLY12 (LIFEC_SAFE_BASE + 0x0208U) +#define SAFE_READONLY13 (LIFEC_SAFE_BASE + 0x020CU) +#define SAFE_READONLY14 (LIFEC_SAFE_BASE + 0x0210U) +#define SAFE_READONLY15 (LIFEC_SAFE_BASE + 0x0214U) + +#endif /* LIFEC_REGISTERS_H */ diff --git a/plat/renesas/rcar/plat_image_load.c b/plat/renesas/common/plat_image_load.c index 9d814a6e59..9d814a6e59 100644 --- a/plat/renesas/rcar/plat_image_load.c +++ b/plat/renesas/common/plat_image_load.c diff --git a/plat/renesas/rcar/plat_pm.c b/plat/renesas/common/plat_pm.c index 6fc47b95c4..6a9ad450d5 100644 --- a/plat/renesas/rcar/plat_pm.c +++ b/plat/renesas/common/plat_pm.c @@ -6,8 +6,6 @@ #include <errno.h> -#include <platform_def.h> - #include <arch_helpers.h> #include <common/bl_common.h> #include <common/debug.h> @@ -19,17 +17,20 @@ #include <plat/common/platform.h> #include "iic_dvfs.h" +#include "platform_def.h" #include "pwrc.h" #include "rcar_def.h" #include "rcar_private.h" +#if RCAR_GEN3_ULCB #include "ulcb_cpld.h" +#endif /* RCAR_GEN3_ULCB */ -#define DVFS_SET_VID_0V (0x00) -#define P_ALL_OFF (0x80) -#define KEEPON_DDR1C (0x08) -#define KEEPON_DDR0C (0x04) -#define KEEPON_DDR1 (0x02) -#define KEEPON_DDR0 (0x01) +#define DVFS_SET_VID_0V (0x00) +#define P_ALL_OFF (0x80) +#define KEEPON_DDR1C (0x08) +#define KEEPON_DDR0C (0x04) +#define KEEPON_DDR1 (0x02) +#define KEEPON_DDR0 (0x01) #define SYSTEM_PWR_STATE(s) ((s)->pwr_domain_state[PLAT_MAX_PWR_LVL]) #define CLUSTER_PWR_STATE(s) ((s)->pwr_domain_state[MPIDR_AFFLVL1]) @@ -200,20 +201,20 @@ static void __dead2 rcar_system_reset(void) error = rcar_iic_dvfs_send(PMIC, REG_KEEP10, KEEP10_MAGIC); if (error) { - ERROR("Failed send KEEP10 magic ret=%d \n", error); + ERROR("Failed send KEEP10 magic ret=%d\n", error); goto done; } error = rcar_iic_dvfs_receive(PMIC, BKUP_MODE_CNT, &mode); if (error) { - ERROR("Failed recieve BKUP_Mode_Cnt ret=%d \n", error); + ERROR("Failed receive BKUP_Mode_Cnt ret=%d\n", error); goto done; } mode |= KEEPON_DDR1C | KEEPON_DDR0C | KEEPON_DDR1 | KEEPON_DDR0; error = rcar_iic_dvfs_send(PMIC, BKUP_MODE_CNT, mode); if (error) { - ERROR("Failed send KEEPON_DDRx ret=%d \n", error); + ERROR("Failed send KEEPON_DDRx ret=%d\n", error); goto done; } @@ -292,7 +293,7 @@ static const plat_psci_ops_t rcar_plat_psci_ops = { .system_reset = rcar_system_reset, .validate_power_state = rcar_validate_power_state, #if RCAR_SYSTEM_SUSPEND - .get_sys_suspend_power_state = rcar_get_sys_suspend_power_state, + .get_sys_suspend_power_state = rcar_get_sys_suspend_power_state, #endif }; diff --git a/plat/renesas/rcar/plat_storage.c b/plat/renesas/common/plat_storage.c index 05e3d9f0dd..6524561031 100644 --- a/plat/renesas/rcar/plat_storage.c +++ b/plat/renesas/common/plat_storage.c @@ -1,23 +1,22 @@ /* - * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include <string.h> -#include <platform_def.h> - #include <common/debug.h> #include <drivers/io/io_driver.h> #include <drivers/io/io_storage.h> #include <drivers/io/io_semihosting.h> #include "io_common.h" -#include "io_rcar.h" #include "io_memdrv.h" #include "io_emmcdrv.h" #include "io_private.h" +#include "io_rcar.h" +#include <platform_def.h> static uintptr_t emmcdrv_dev_handle; static uintptr_t memdrv_dev_handle; @@ -167,7 +166,7 @@ static int32_t open_rcar(const uintptr_t spec); struct plat_io_policy { uintptr_t *dev_handle; uintptr_t image_spec; - int32_t(*check) (const uintptr_t spec); + int32_t (*check)(const uintptr_t spec); }; static const struct plat_io_policy policies[] = { @@ -305,7 +304,7 @@ static const struct plat_io_policy policies[] = { (uintptr_t) &bl338_cert_file_spec, &open_rcar}, { #else - { + { #endif 0, 0, 0} }; @@ -322,16 +321,11 @@ static io_drv_spec_t io_drv_spec_emmcdrv = { 0, }; -static struct plat_io_policy drv_policies[] - __attribute__ ((section(".data"))) = { +static struct plat_io_policy drv_policies[] __attribute__ ((section(".data"))) = { /* FLASH_DEV_ID */ - { - &memdrv_dev_handle, - (uintptr_t) &io_drv_spec_memdrv, &open_memmap,}, - /* EMMC_DEV_ID */ - { - &emmcdrv_dev_handle, - (uintptr_t) &io_drv_spec_emmcdrv, &open_emmcdrv,} + { &memdrv_dev_handle, (uintptr_t) &io_drv_spec_memdrv, &open_memmap, }, + /* EMMC_DEV_ID */ + { &emmcdrv_dev_handle, (uintptr_t) &io_drv_spec_emmcdrv, &open_emmcdrv, } }; static int32_t open_rcar(const uintptr_t spec) diff --git a/plat/renesas/rcar/plat_topology.c b/plat/renesas/common/plat_topology.c index 0d5880d7a2..0d5880d7a2 100644 --- a/plat/renesas/rcar/plat_topology.c +++ b/plat/renesas/common/plat_topology.c diff --git a/plat/renesas/rcar/rcar_common.c b/plat/renesas/common/rcar_common.c index dec7229b30..dec7229b30 100644 --- a/plat/renesas/rcar/rcar_common.c +++ b/plat/renesas/common/rcar_common.c diff --git a/plat/renesas/rcar/bl2_secure_setting.c b/plat/renesas/rcar/bl2_secure_setting.c deleted file mode 100644 index 7473df5a21..0000000000 --- a/plat/renesas/rcar/bl2_secure_setting.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include <lib/mmio.h> -#include <lib/utils_def.h> - -#include "axi_registers.h" -#include "lifec_registers.h" -#include "micro_delay.h" - -static void lifec_security_setting(void); -static void axi_security_setting(void); - -static const struct { - uint32_t reg; - uint32_t val; -} lifec[] = { - /** LIFEC0 (SECURITY) settings */ - /* Security attribute setting for master ports */ - /* Bit 0: ARM realtime core (Cortex-R7) master port */ - /* 0: Non-Secure */ - { - SEC_SRC, 0x0000001EU}, - /** Security attribute setting for slave ports 0 to 15 */ - /* {SEC_SEL0, 0xFFFFFFFFU}, */ - /* {SEC_SEL1, 0xFFFFFFFFU}, */ - /* {SEC_SEL2, 0xFFFFFFFFU}, */ - /* Bit19: AXI-Bus (Main Memory domain AXI) slave ports */ - /* 0: registers accessed from secure resource only */ - /* Bit 9: DBSC4 register access slave ports. */ - /* 0: registers accessed from secure resource only. */ -#if (LIFEC_DBSC_PROTECT_ENABLE == 1) - { - SEC_SEL3, 0xFFF7FDFFU}, -#else - { - SEC_SEL3, 0xFFFFFFFFU}, -#endif - /* {SEC_SEL4, 0xFFFFFFFFU}, */ - /* Bit 6: Boot ROM slave ports. */ - /* 0: registers accessed from secure resource only */ - { - SEC_SEL5, 0xFFFFFFBFU}, - /* Bit13: SCEG PKA (secure APB) slave ports */ - /* 0: registers accessed from secure resource only */ - /* 1: Reserved[R-Car E3] */ - /* Bit12: SCEG PKA (public APB) slave ports */ - /* 0: registers accessed from secure resource only */ - /* 1: Reserved[R-Car E3] */ - /* Bit10: SCEG Secure Core slave ports */ - /* 0: registers accessed from secure resource only */ -#if (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RCAR_D3) - { - SEC_SEL6, 0xFFFFFBFFU}, -#else - { - SEC_SEL6, 0xFFFFCBFFU}, -#endif - /* {SEC_SEL7, 0xFFFFFFFFU}, */ - /* {SEC_SEL8, 0xFFFFFFFFU}, */ - /* {SEC_SEL9, 0xFFFFFFFFU}, */ - /* {SEC_SEL10, 0xFFFFFFFFU}, */ - /* {SEC_SEL11, 0xFFFFFFFFU}, */ - /* {SEC_SEL12, 0xFFFFFFFFU}, */ - /* Bit22: RPC slave ports. */ - /* 0: registers accessed from secure resource only. */ -#if (RCAR_RPC_HYPERFLASH_LOCKED == 1) - {SEC_SEL13, 0xFFBFFFFFU}, -#endif - /* Bit27: System Timer (SCMT) slave ports */ - /* 0: registers accessed from secure resource only */ - /* Bit26: System Watchdog Timer (SWDT) slave ports */ - /* 0: registers accessed from secure resource only */ - { - SEC_SEL14, 0xF3FFFFFFU}, - /* Bit13: RST slave ports. */ - /* 0: registers accessed from secure resource only */ - /* Bit 7: Life Cycle 0 slave ports */ - /* 0: registers accessed from secure resource only */ - { - SEC_SEL15, 0xFFFFFF3FU}, - /** Security group 0 attribute setting for master ports 0 */ - /** Security group 1 attribute setting for master ports 0 */ - /* {SEC_GRP0CR0, 0x00000000U}, */ - /* {SEC_GRP1CR0, 0x00000000U}, */ - /** Security group 0 attribute setting for master ports 1 */ - /** Security group 1 attribute setting for master ports 1 */ - /* {SEC_GRP0CR1, 0x00000000U}, */ - /* {SEC_GRP1CR1, 0x00000000U}, */ - /** Security group 0 attribute setting for master ports 2 */ - /** Security group 1 attribute setting for master ports 2 */ - /* Bit17: SCEG Secure Core master ports. */ - /* SecurityGroup3 */ - { - SEC_GRP0CR2, 0x00020000U}, { - SEC_GRP1CR2, 0x00020000U}, - /** Security group 0 attribute setting for master ports 3 */ - /** Security group 1 attribute setting for master ports 3 */ - /* {SEC_GRP0CR3, 0x00000000U}, */ - /* {SEC_GRP1CR3, 0x00000000U}, */ - /** Security group 0 attribute setting for slave ports 0 */ - /** Security group 1 attribute setting for slave ports 0 */ - /* {SEC_GRP0COND0, 0x00000000U}, */ - /* {SEC_GRP1COND0, 0x00000000U}, */ - /** Security group 0 attribute setting for slave ports 1 */ - /** Security group 1 attribute setting for slave ports 1 */ - /* {SEC_GRP0COND1, 0x00000000U}, */ - /* {SEC_GRP1COND1, 0x00000000U}, */ - /** Security group 0 attribute setting for slave ports 2 */ - /** Security group 1 attribute setting for slave ports 2 */ - /* {SEC_GRP0COND2, 0x00000000U}, */ - /* {SEC_GRP1COND2, 0x00000000U}, */ - /** Security group 0 attribute setting for slave ports 3 */ - /** Security group 1 attribute setting for slave ports 3 */ - /* Bit19: AXI-Bus (Main Memory domain AXI) slave ports. */ - /* SecurityGroup3 */ - /* Bit 9: DBSC4 register access slave ports. */ - /* SecurityGroup3 */ -#if (LIFEC_DBSC_PROTECT_ENABLE == 1) - { - SEC_GRP0COND3, 0x00080200U}, { - SEC_GRP1COND3, 0x00080200U}, -#else - { - SEC_GRP0COND3, 0x00000000U}, { - SEC_GRP1COND3, 0x00000000U}, -#endif - /** Security group 0 attribute setting for slave ports 4 */ - /** Security group 1 attribute setting for slave ports 4 */ - /* {SEC_GRP0COND4, 0x00000000U}, */ - /* {SEC_GRP1COND4, 0x00000000U}, */ - /** Security group 0 attribute setting for slave ports 5 */ - /** Security group 1 attribute setting for slave ports 5 */ - /* Bit 6: Boot ROM slave ports */ - /* SecurityGroup3 */ - { - SEC_GRP0COND5, 0x00000040U}, { - SEC_GRP1COND5, 0x00000040U}, - /** Security group 0 attribute setting for slave ports 6 */ - /** Security group 1 attribute setting for slave ports 6 */ - /* Bit13: SCEG PKA (secure APB) slave ports */ - /* SecurityGroup3 */ - /* Reserved[R-Car E3] */ - /* Bit12: SCEG PKA (public APB) slave ports */ - /* SecurityGroup3 */ - /* Reserved[R-Car E3] */ - /* Bit10: SCEG Secure Core slave ports */ - /* SecurityGroup3 */ -#if RCAR_LSI == RCAR_E3 - { - SEC_GRP0COND6, 0x00000400U}, { - SEC_GRP1COND6, 0x00000400U}, -#else - { - SEC_GRP0COND6, 0x00003400U}, { - SEC_GRP1COND6, 0x00003400U}, -#endif - /** Security group 0 attribute setting for slave ports 7 */ - /** Security group 1 attribute setting for slave ports 7 */ - /* {SEC_GRP0COND7, 0x00000000U}, */ - /* {SEC_GRP1COND7, 0x00000000U}, */ - /** Security group 0 attribute setting for slave ports 8 */ - /** Security group 1 attribute setting for slave ports 8 */ - /* {SEC_GRP0COND8, 0x00000000U}, */ - /* {SEC_GRP1COND8, 0x00000000U}, */ - /** Security group 0 attribute setting for slave ports 9 */ - /** Security group 1 attribute setting for slave ports 9 */ - /* {SEC_GRP0COND9, 0x00000000U}, */ - /* {SEC_GRP1COND9, 0x00000000U}, */ - /** Security group 0 attribute setting for slave ports 10 */ - /** Security group 1 attribute setting for slave ports 10 */ - /* {SEC_GRP0COND10, 0x00000000U}, */ - /* {SEC_GRP1COND10, 0x00000000U}, */ - /** Security group 0 attribute setting for slave ports 11 */ - /** Security group 1 attribute setting for slave ports 11 */ - /* {SEC_GRP0COND11, 0x00000000U}, */ - /* {SEC_GRP1COND11, 0x00000000U}, */ - /** Security group 0 attribute setting for slave ports 12 */ - /** Security group 1 attribute setting for slave ports 12 */ - /* {SEC_GRP0COND12, 0x00000000U}, */ - /* {SEC_GRP1COND12, 0x00000000U}, */ - /** Security group 0 attribute setting for slave ports 13 */ - /** Security group 1 attribute setting for slave ports 13 */ - /* Bit22: RPC slave ports. */ - /* SecurityGroup3 */ -#if (RCAR_RPC_HYPERFLASH_LOCKED == 1) - {SEC_GRP0COND13, 0x00400000U}, - {SEC_GRP1COND13, 0x00400000U}, -#endif - /** Security group 0 attribute setting for slave ports 14 */ - /** Security group 1 attribute setting for slave ports 14 */ - /* Bit26: System Timer (SCMT) slave ports */ - /* SecurityGroup3 */ - /* Bit27: System Watchdog Timer (SWDT) slave ports */ - /* SecurityGroup3 */ - { - SEC_GRP0COND14, 0x0C000000U}, { - SEC_GRP1COND14, 0x0C000000U}, - /** Security group 0 attribute setting for slave ports 15 */ - /** Security group 1 attribute setting for slave ports 15 */ - /* Bit13: RST slave ports */ - /* SecurityGroup3 */ - /* Bit 7: Life Cycle 0 slave ports */ - /* SecurityGroup3 */ - /* Bit 6: TDBG slave ports */ - /* SecurityGroup3 */ - { - SEC_GRP0COND15, 0x000000C0U}, { - SEC_GRP1COND15, 0x000000C0U}, - /** Security write protection attribute setting slave ports 0 */ - /* {SEC_READONLY0, 0x00000000U}, */ - /** Security write protection attribute setting slave ports 1 */ - /* {SEC_READONLY1, 0x00000000U}, */ - /** Security write protection attribute setting slave ports 2 */ - /* {SEC_READONLY2, 0x00000000U}, */ - /** Security write protection attribute setting slave ports 3 */ - /* {SEC_READONLY3, 0x00000000U}, */ - /** Security write protection attribute setting slave ports 4 */ - /* {SEC_READONLY4, 0x00000000U}, */ - /** Security write protection attribute setting slave ports 5 */ - /* {SEC_READONLY5, 0x00000000U}, */ - /** Security write protection attribute setting slave ports 6 */ - /* {SEC_READONLY6, 0x00000000U}, */ - /** Security write protection attribute setting slave ports 7 */ - /* {SEC_READONLY7, 0x00000000U}, */ - /** Security write protection attribute setting slave ports 8 */ - /* {SEC_READONLY8, 0x00000000U}, */ - /** Security write protection attribute setting slave ports 9 */ - /* {SEC_READONLY9, 0x00000000U}, */ - /** Security write protection attribute setting slave ports 10 */ - /* {SEC_READONLY10, 0x00000000U}, */ - /** Security write protection attribute setting slave ports 11 */ - /* {SEC_READONLY11, 0x00000000U}, */ - /** Security write protection attribute setting slave ports 12 */ - /* {SEC_READONLY12, 0x00000000U}, */ - /** Security write protection attribute setting slave ports 13 */ - /* {SEC_READONLY13, 0x00000000U}, */ - /** Security write protection attribute setting slave ports 14 */ - /* {SEC_READONLY14, 0x00000000U}, */ - /** Security write protection attribute setting slave ports 15 */ - /* {SEC_READONLY15, 0x00000000U} */ -}; - -/* AXI settings */ -static const struct { - uint32_t reg; - uint32_t val; -} axi[] = { - /* DRAM protection */ - /* AXI dram protected area division */ - { - AXI_DPTDIVCR0, 0x0E0403F0U}, { - AXI_DPTDIVCR1, 0x0E0407E0U}, { - AXI_DPTDIVCR2, 0x0E080000U}, { - AXI_DPTDIVCR3, 0x0E080000U}, { - AXI_DPTDIVCR4, 0x0E080000U}, { - AXI_DPTDIVCR5, 0x0E080000U}, { - AXI_DPTDIVCR6, 0x0E080000U}, { - AXI_DPTDIVCR7, 0x0E080000U}, { - AXI_DPTDIVCR8, 0x0E080000U}, { - AXI_DPTDIVCR9, 0x0E080000U}, { - AXI_DPTDIVCR10, 0x0E080000U}, { - AXI_DPTDIVCR11, 0x0E080000U}, { - AXI_DPTDIVCR12, 0x0E080000U}, { - AXI_DPTDIVCR13, 0x0E080000U}, { - AXI_DPTDIVCR14, 0x0E080000U}, - /* AXI dram protected area setting */ - { - AXI_DPTCR0, 0x0E000000U}, { - AXI_DPTCR1, 0x0E000E0EU}, { - AXI_DPTCR2, 0x0E000000U}, { - AXI_DPTCR3, 0x0E000000U}, { - AXI_DPTCR4, 0x0E000000U}, { - AXI_DPTCR5, 0x0E000000U}, { - AXI_DPTCR6, 0x0E000000U}, { - AXI_DPTCR7, 0x0E000000U}, { - AXI_DPTCR8, 0x0E000000U}, { - AXI_DPTCR9, 0x0E000000U}, { - AXI_DPTCR10, 0x0E000000U}, { - AXI_DPTCR11, 0x0E000000U}, { - AXI_DPTCR12, 0x0E000000U}, { - AXI_DPTCR13, 0x0E000000U}, { - AXI_DPTCR14, 0x0E000000U}, { - AXI_DPTCR15, 0x0E000000U}, - /* SRAM ptotection */ - /* AXI sram protected area division */ - { - AXI_SPTDIVCR0, 0x0E0E6304U}, { - AXI_SPTDIVCR1, 0x0E0E6360U}, { - AXI_SPTDIVCR2, 0x0E0E6360U}, { - AXI_SPTDIVCR3, 0x0E0E6360U}, { - AXI_SPTDIVCR4, 0x0E0E6360U}, { - AXI_SPTDIVCR5, 0x0E0E6360U}, { - AXI_SPTDIVCR6, 0x0E0E6360U}, { - AXI_SPTDIVCR7, 0x0E0E6360U}, { - AXI_SPTDIVCR8, 0x0E0E6360U}, { - AXI_SPTDIVCR9, 0x0E0E6360U}, { - AXI_SPTDIVCR10, 0x0E0E6360U}, { - AXI_SPTDIVCR11, 0x0E0E6360U}, { - AXI_SPTDIVCR12, 0x0E0E6360U}, { - AXI_SPTDIVCR13, 0x0E0E6360U}, { - AXI_SPTDIVCR14, 0x0E0E6360U}, - /* AXI sram protected area setting */ - { - AXI_SPTCR0, 0x0E000E0EU}, { - AXI_SPTCR1, 0x0E000000U}, { - AXI_SPTCR2, 0x0E000000U}, { - AXI_SPTCR3, 0x0E000000U}, { - AXI_SPTCR4, 0x0E000000U}, { - AXI_SPTCR5, 0x0E000000U}, { - AXI_SPTCR6, 0x0E000000U}, { - AXI_SPTCR7, 0x0E000000U}, { - AXI_SPTCR8, 0x0E000000U}, { - AXI_SPTCR9, 0x0E000000U}, { - AXI_SPTCR10, 0x0E000000U}, { - AXI_SPTCR11, 0x0E000000U}, { - AXI_SPTCR12, 0x0E000000U}, { - AXI_SPTCR13, 0x0E000000U}, { - AXI_SPTCR14, 0x0E000000U}, { - AXI_SPTCR15, 0x0E000000U} -}; - -static void lifec_security_setting(void) -{ - uint32_t i; - - for (i = 0; i < ARRAY_SIZE(lifec); i++) - mmio_write_32(lifec[i].reg, lifec[i].val); -} - -/* SRAM/DRAM protection setting */ -static void axi_security_setting(void) -{ - uint32_t i; - - for (i = 0; i < ARRAY_SIZE(axi); i++) - mmio_write_32(axi[i].reg, axi[i].val); -} - -void bl2_secure_setting(void) -{ - const uint32_t delay = 10; - - lifec_security_setting(); - axi_security_setting(); - rcar_micro_delay(delay); - - return; -} diff --git a/plat/renesas/rcar/include/registers/lifec_registers.h b/plat/renesas/rcar/include/registers/lifec_registers.h deleted file mode 100644 index de78760ae5..0000000000 --- a/plat/renesas/rcar/include/registers/lifec_registers.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifndef LIFEC_REGISTERS_H -#define LIFEC_REGISTERS_H - -#define LIFEC_SEC_BASE (0xE6110000U) - -#define SEC_SRC (LIFEC_SEC_BASE + 0x0008U) -#define SEC_SEL0 (LIFEC_SEC_BASE + 0x0030U) -#define SEC_SEL1 (LIFEC_SEC_BASE + 0x0034U) -#define SEC_SEL2 (LIFEC_SEC_BASE + 0x0038U) -#define SEC_SEL3 (LIFEC_SEC_BASE + 0x003CU) -#define SEC_SEL4 (LIFEC_SEC_BASE + 0x0058U) -#define SEC_SEL5 (LIFEC_SEC_BASE + 0x005CU) -#define SEC_SEL6 (LIFEC_SEC_BASE + 0x0060U) -#define SEC_SEL7 (LIFEC_SEC_BASE + 0x0064U) -#define SEC_SEL8 (LIFEC_SEC_BASE + 0x0068U) -#define SEC_SEL9 (LIFEC_SEC_BASE + 0x006CU) -#define SEC_SEL10 (LIFEC_SEC_BASE + 0x0070U) -#define SEC_SEL11 (LIFEC_SEC_BASE + 0x0074U) -#define SEC_SEL12 (LIFEC_SEC_BASE + 0x0078U) -#define SEC_SEL13 (LIFEC_SEC_BASE + 0x007CU) -#define SEC_SEL14 (LIFEC_SEC_BASE + 0x0080U) -#define SEC_SEL15 (LIFEC_SEC_BASE + 0x0084U) -#define SEC_GRP0CR0 (LIFEC_SEC_BASE + 0x0138U) -#define SEC_GRP1CR0 (LIFEC_SEC_BASE + 0x013CU) -#define SEC_GRP0CR1 (LIFEC_SEC_BASE + 0x0140U) -#define SEC_GRP1CR1 (LIFEC_SEC_BASE + 0x0144U) -#define SEC_GRP0CR2 (LIFEC_SEC_BASE + 0x0148U) -#define SEC_GRP1CR2 (LIFEC_SEC_BASE + 0x014CU) -#define SEC_GRP0CR3 (LIFEC_SEC_BASE + 0x0150U) -#define SEC_GRP1CR3 (LIFEC_SEC_BASE + 0x0154U) -#define SEC_GRP0COND0 (LIFEC_SEC_BASE + 0x0158U) -#define SEC_GRP1COND0 (LIFEC_SEC_BASE + 0x015CU) -#define SEC_GRP0COND1 (LIFEC_SEC_BASE + 0x0160U) -#define SEC_GRP1COND1 (LIFEC_SEC_BASE + 0x0164U) -#define SEC_GRP0COND2 (LIFEC_SEC_BASE + 0x0168U) -#define SEC_GRP1COND2 (LIFEC_SEC_BASE + 0x016CU) -#define SEC_GRP0COND3 (LIFEC_SEC_BASE + 0x0170U) -#define SEC_GRP1COND3 (LIFEC_SEC_BASE + 0x0174U) -#define SEC_GRP0COND4 (LIFEC_SEC_BASE + 0x0178U) -#define SEC_GRP1COND4 (LIFEC_SEC_BASE + 0x017CU) -#define SEC_GRP0COND5 (LIFEC_SEC_BASE + 0x0180U) -#define SEC_GRP1COND5 (LIFEC_SEC_BASE + 0x0184U) -#define SEC_GRP0COND6 (LIFEC_SEC_BASE + 0x0188U) -#define SEC_GRP1COND6 (LIFEC_SEC_BASE + 0x018CU) -#define SEC_GRP0COND7 (LIFEC_SEC_BASE + 0x0190U) -#define SEC_GRP1COND7 (LIFEC_SEC_BASE + 0x0194U) -#define SEC_GRP0COND8 (LIFEC_SEC_BASE + 0x0198U) -#define SEC_GRP1COND8 (LIFEC_SEC_BASE + 0x019CU) -#define SEC_GRP0COND9 (LIFEC_SEC_BASE + 0x01A0U) -#define SEC_GRP1COND9 (LIFEC_SEC_BASE + 0x01A4U) -#define SEC_GRP0COND10 (LIFEC_SEC_BASE + 0x01A8U) -#define SEC_GRP1COND10 (LIFEC_SEC_BASE + 0x01ACU) -#define SEC_GRP0COND11 (LIFEC_SEC_BASE + 0x01B0U) -#define SEC_GRP1COND11 (LIFEC_SEC_BASE + 0x01B4U) -#define SEC_GRP0COND12 (LIFEC_SEC_BASE + 0x01B8U) -#define SEC_GRP1COND12 (LIFEC_SEC_BASE + 0x01BCU) -#define SEC_GRP0COND13 (LIFEC_SEC_BASE + 0x01C0U) -#define SEC_GRP1COND13 (LIFEC_SEC_BASE + 0x01C4U) -#define SEC_GRP0COND14 (LIFEC_SEC_BASE + 0x01C8U) -#define SEC_GRP1COND14 (LIFEC_SEC_BASE + 0x01CCU) -#define SEC_GRP0COND15 (LIFEC_SEC_BASE + 0x01D0U) -#define SEC_GRP1COND15 (LIFEC_SEC_BASE + 0x01D4U) -#define SEC_READONLY0 (LIFEC_SEC_BASE + 0x01D8U) -#define SEC_READONLY1 (LIFEC_SEC_BASE + 0x01DCU) -#define SEC_READONLY2 (LIFEC_SEC_BASE + 0x01E0U) -#define SEC_READONLY3 (LIFEC_SEC_BASE + 0x01E4U) -#define SEC_READONLY4 (LIFEC_SEC_BASE + 0x01E8U) -#define SEC_READONLY5 (LIFEC_SEC_BASE + 0x01ECU) -#define SEC_READONLY6 (LIFEC_SEC_BASE + 0x01F0U) -#define SEC_READONLY7 (LIFEC_SEC_BASE + 0x01F4U) -#define SEC_READONLY8 (LIFEC_SEC_BASE + 0x01F8U) -#define SEC_READONLY9 (LIFEC_SEC_BASE + 0x01FCU) -#define SEC_READONLY10 (LIFEC_SEC_BASE + 0x0200U) -#define SEC_READONLY11 (LIFEC_SEC_BASE + 0x0204U) -#define SEC_READONLY12 (LIFEC_SEC_BASE + 0x0208U) -#define SEC_READONLY13 (LIFEC_SEC_BASE + 0x020CU) -#define SEC_READONLY14 (LIFEC_SEC_BASE + 0x0210U) -#define SEC_READONLY15 (LIFEC_SEC_BASE + 0x0214U) - -#define LIFEC_SAFE_BASE (0xE6120000U) -#define SAFE_GRP0CR0 (LIFEC_SAFE_BASE + 0x0138U) -#define SAFE_GRP1CR0 (LIFEC_SAFE_BASE + 0x013CU) -#define SAFE_GRP0CR1 (LIFEC_SAFE_BASE + 0x0140U) -#define SAFE_GRP1CR1 (LIFEC_SAFE_BASE + 0x0144U) -#define SAFE_GRP0CR2 (LIFEC_SAFE_BASE + 0x0148U) -#define SAFE_GRP1CR2 (LIFEC_SAFE_BASE + 0x014CU) -#define SAFE_GRP0CR3 (LIFEC_SAFE_BASE + 0x0150U) -#define SAFE_GRP1CR3 (LIFEC_SAFE_BASE + 0x0154U) -#define SAFE_GRP0COND0 (LIFEC_SAFE_BASE + 0x0158U) -#define SAFE_GRP1COND0 (LIFEC_SAFE_BASE + 0x015CU) -#define SAFE_GRP0COND1 (LIFEC_SAFE_BASE + 0x0160U) -#define SAFE_GRP1COND1 (LIFEC_SAFE_BASE + 0x0164U) -#define SAFE_GRP0COND2 (LIFEC_SAFE_BASE + 0x0168U) -#define SAFE_GRP1COND2 (LIFEC_SAFE_BASE + 0x016CU) -#define SAFE_GRP0COND3 (LIFEC_SAFE_BASE + 0x0170U) -#define SAFE_GRP1COND3 (LIFEC_SAFE_BASE + 0x0174U) -#define SAFE_GRP0COND4 (LIFEC_SAFE_BASE + 0x0178U) -#define SAFE_GRP1COND4 (LIFEC_SAFE_BASE + 0x017CU) -#define SAFE_GRP0COND5 (LIFEC_SAFE_BASE + 0x0180U) -#define SAFE_GRP1COND5 (LIFEC_SAFE_BASE + 0x0184U) -#define SAFE_GRP0COND6 (LIFEC_SAFE_BASE + 0x0188U) -#define SAFE_GRP1COND6 (LIFEC_SAFE_BASE + 0x018CU) -#define SAFE_GRP0COND7 (LIFEC_SAFE_BASE + 0x0190U) -#define SAFE_GRP1COND7 (LIFEC_SAFE_BASE + 0x0194U) -#define SAFE_GRP0COND8 (LIFEC_SAFE_BASE + 0x0198U) -#define SAFE_GRP1COND8 (LIFEC_SAFE_BASE + 0x019CU) -#define SAFE_GRP0COND9 (LIFEC_SAFE_BASE + 0x01A0U) -#define SAFE_GRP1COND9 (LIFEC_SAFE_BASE + 0x01A4U) -#define SAFE_GRP0COND10 (LIFEC_SAFE_BASE + 0x01A8U) -#define SAFE_GRP1COND10 (LIFEC_SAFE_BASE + 0x01ACU) -#define SAFE_GRP0COND11 (LIFEC_SAFE_BASE + 0x01B0U) -#define SAFE_GRP1COND11 (LIFEC_SAFE_BASE + 0x01B4U) -#define SAFE_GRP0COND12 (LIFEC_SAFE_BASE + 0x01B8U) -#define SAFE_GRP1COND12 (LIFEC_SAFE_BASE + 0x01BCU) -#define SAFE_GRP0COND13 (LIFEC_SAFE_BASE + 0x01C0U) -#define SAFE_GRP1COND13 (LIFEC_SAFE_BASE + 0x01C4U) -#define SAFE_GRP0COND14 (LIFEC_SAFE_BASE + 0x01C8U) -#define SAFE_GRP1COND14 (LIFEC_SAFE_BASE + 0x01CCU) -#define SAFE_GRP0COND15 (LIFEC_SAFE_BASE + 0x01D0U) -#define SAFE_GRP1COND15 (LIFEC_SAFE_BASE + 0x01D4U) -#define SAFE_READONLY0 (LIFEC_SAFE_BASE + 0x01D8U) -#define SAFE_READONLY1 (LIFEC_SAFE_BASE + 0x01DCU) -#define SAFE_READONLY2 (LIFEC_SAFE_BASE + 0x01E0U) -#define SAFE_READONLY3 (LIFEC_SAFE_BASE + 0x01E4U) -#define SAFE_READONLY4 (LIFEC_SAFE_BASE + 0x01E8U) -#define SAFE_READONLY5 (LIFEC_SAFE_BASE + 0x01ECU) -#define SAFE_READONLY6 (LIFEC_SAFE_BASE + 0x01F0U) -#define SAFE_READONLY7 (LIFEC_SAFE_BASE + 0x01F4U) -#define SAFE_READONLY8 (LIFEC_SAFE_BASE + 0x01F8U) -#define SAFE_READONLY9 (LIFEC_SAFE_BASE + 0x01FCU) -#define SAFE_READONLY10 (LIFEC_SAFE_BASE + 0x0200U) -#define SAFE_READONLY11 (LIFEC_SAFE_BASE + 0x0204U) -#define SAFE_READONLY12 (LIFEC_SAFE_BASE + 0x0208U) -#define SAFE_READONLY13 (LIFEC_SAFE_BASE + 0x020CU) -#define SAFE_READONLY14 (LIFEC_SAFE_BASE + 0x0210U) -#define SAFE_READONLY15 (LIFEC_SAFE_BASE + 0x0214U) - -#endif /* LIFEC_REGISTERS_H */ diff --git a/plat/renesas/rcar/platform.mk b/plat/renesas/rcar/platform.mk index 4c41dd341c..5e4978c0a0 100644 --- a/plat/renesas/rcar/platform.mk +++ b/plat/renesas/rcar/platform.mk @@ -1,56 +1,10 @@ # -# Copyright (c) 2018-2019, Renesas Electronics Corporation. All rights reserved. +# Copyright (c) 2018-2020, Renesas Electronics Corporation. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # -PROGRAMMABLE_RESET_ADDRESS := 0 -COLD_BOOT_SINGLE_CPU := 1 -ARM_CCI_PRODUCT_ID := 500 -TRUSTED_BOARD_BOOT := 1 -RESET_TO_BL31 := 1 -GENERATE_COT := 1 -BL2_AT_EL3 := 1 -ENABLE_SVE_FOR_NS := 0 -MULTI_CONSOLE_API := 1 - -CRASH_REPORTING := 1 -HANDLE_EA_EL3_FIRST := 1 - -$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) - -ifeq (${SPD},none) - SPD_NONE:=1 - $(eval $(call add_define,SPD_NONE)) -endif - -# LSI setting common define -RCAR_H3:=0 -RCAR_M3:=1 -RCAR_M3N:=2 -RCAR_E3:=3 -RCAR_H3N:=4 -RCAR_D3:=5 -RCAR_V3M:=6 -RCAR_AUTO:=99 -$(eval $(call add_define,RCAR_H3)) -$(eval $(call add_define,RCAR_M3)) -$(eval $(call add_define,RCAR_M3N)) -$(eval $(call add_define,RCAR_E3)) -$(eval $(call add_define,RCAR_H3N)) -$(eval $(call add_define,RCAR_D3)) -$(eval $(call add_define,RCAR_V3M)) -$(eval $(call add_define,RCAR_AUTO)) -RCAR_CUT_10:=0 -RCAR_CUT_11:=1 -RCAR_CUT_13:=3 -RCAR_CUT_20:=10 -RCAR_CUT_30:=20 -$(eval $(call add_define,RCAR_CUT_10)) -$(eval $(call add_define,RCAR_CUT_11)) -$(eval $(call add_define,RCAR_CUT_13)) -$(eval $(call add_define,RCAR_CUT_20)) -$(eval $(call add_define,RCAR_CUT_30)) +include plat/renesas/common/common.mk ifndef LSI $(error "Error: Unknown LSI. Please use LSI=<LSI name> to specify the LSI") @@ -339,105 +293,32 @@ ifeq (${RCAR_SYSTEM_RESET_KEEPON_DDR},1) endif endif -# Enable workarounds for selected Cortex-A53 erratas. -ERRATA_A53_835769 := 1 -ERRATA_A53_843419 := 1 -ERRATA_A53_855873 := 1 - -# Enable workarounds for selected Cortex-A57 erratas. -ERRATA_A57_859972 := 1 -ERRATA_A57_813419 := 1 - include drivers/renesas/rcar/ddr/ddr.mk include drivers/renesas/rcar/qos/qos.mk include drivers/renesas/rcar/pfc/pfc.mk include lib/libfdt/libfdt.mk -PLAT_INCLUDES := -Idrivers/renesas/rcar/ddr \ +PLAT_INCLUDES += -Idrivers/renesas/rcar/ddr \ -Idrivers/renesas/rcar/qos \ - -Idrivers/renesas/rcar/iic_dvfs \ -Idrivers/renesas/rcar/board \ -Idrivers/renesas/rcar/cpld/ \ - -Idrivers/renesas/rcar/avs \ - -Idrivers/renesas/rcar/delay \ - -Idrivers/renesas/rcar/rom \ - -Idrivers/renesas/rcar/scif \ - -Idrivers/renesas/rcar/emmc \ - -Idrivers/renesas/rcar/pwrc \ - -Idrivers/renesas/rcar/io \ - -Iplat/renesas/rcar/include/registers \ - -Iplat/renesas/rcar/include \ - -Iplat/renesas/rcar - -PLAT_BL_COMMON_SOURCES := drivers/renesas/rcar/iic_dvfs/iic_dvfs.c \ - plat/renesas/rcar/rcar_common.c - -RCAR_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ - drivers/arm/gic/v2/gicv2_main.c \ - drivers/arm/gic/v2/gicv2_helpers.c \ - plat/common/plat_gicv2.c - -BL2_SOURCES += ${RCAR_GIC_SOURCES} \ - lib/cpus/aarch64/cortex_a53.S \ - lib/cpus/aarch64/cortex_a57.S \ - ${LIBFDT_SRCS} \ - common/desc_image_load.c \ - plat/renesas/rcar/aarch64/platform_common.c \ - plat/renesas/rcar/aarch64/plat_helpers.S \ - plat/renesas/rcar/bl2_interrupt_error.c \ - plat/renesas/rcar/bl2_secure_setting.c \ - plat/renesas/rcar/bl2_plat_setup.c \ - plat/renesas/rcar/plat_storage.c \ - plat/renesas/rcar/bl2_plat_mem_params_desc.c \ - plat/renesas/rcar/plat_image_load.c \ - plat/renesas/rcar/bl2_cpg_init.c \ - drivers/renesas/rcar/console/rcar_printf.c \ - drivers/renesas/rcar/scif/scif.S \ - drivers/renesas/rcar/common.c \ - drivers/renesas/rcar/io/io_emmcdrv.c \ - drivers/renesas/rcar/io/io_memdrv.c \ - drivers/renesas/rcar/io/io_rcar.c \ - drivers/renesas/rcar/auth/auth_mod.c \ - drivers/renesas/rcar/rpc/rpc_driver.c \ - drivers/renesas/rcar/dma/dma_driver.c \ - drivers/renesas/rcar/avs/avs_driver.c \ - drivers/renesas/rcar/delay/micro_delay.c \ - drivers/renesas/rcar/emmc/emmc_interrupt.c \ - drivers/renesas/rcar/emmc/emmc_utility.c \ - drivers/renesas/rcar/emmc/emmc_mount.c \ - drivers/renesas/rcar/emmc/emmc_init.c \ - drivers/renesas/rcar/emmc/emmc_read.c \ - drivers/renesas/rcar/emmc/emmc_cmd.c \ - drivers/renesas/rcar/watchdog/swdt.c \ - drivers/renesas/rcar/rom/rom_api.c \ - drivers/renesas/rcar/board/board.c \ - drivers/io/io_storage.c - -BL31_SOURCES += ${RCAR_GIC_SOURCES} \ - lib/cpus/aarch64/cortex_a53.S \ - lib/cpus/aarch64/cortex_a57.S \ - plat/common/plat_psci_common.c \ - plat/renesas/rcar/plat_topology.c \ - plat/renesas/rcar/aarch64/plat_helpers.S \ - plat/renesas/rcar/aarch64/platform_common.c \ - plat/renesas/rcar/bl31_plat_setup.c \ - plat/renesas/rcar/plat_pm.c \ - drivers/renesas/rcar/console/rcar_console.S \ - drivers/renesas/rcar/console/rcar_printf.c \ - drivers/renesas/rcar/delay/micro_delay.c \ - drivers/renesas/rcar/pwrc/call_sram.S \ - drivers/renesas/rcar/pwrc/pwrc.c \ - drivers/renesas/rcar/common.c \ - drivers/arm/cci/cci.c + -Idrivers/renesas/common \ + -Idrivers/renesas/common/iic_dvfs \ + -Idrivers/renesas/common/avs \ + -Idrivers/renesas/common/delay \ + -Idrivers/renesas/common/rom \ + -Idrivers/renesas/common/scif \ + -Idrivers/renesas/common/emmc \ + -Idrivers/renesas/common/pwrc \ + -Idrivers/renesas/common/io + +BL2_SOURCES += plat/renesas/rcar/bl2_plat_setup.c \ + drivers/renesas/rcar/board/board.c ifeq (${RCAR_GEN3_ULCB},1) BL31_SOURCES += drivers/renesas/rcar/cpld/ulcb_cpld.c endif -include lib/xlat_tables_v2/xlat_tables.mk -include drivers/auth/mbedtls/mbedtls_crypto.mk -PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} - # build the layout images for the bootrom and the necessary srecords rcar: rcar_layout_tool rcar_srecord distclean realclean clean: clean_layout_tool clean_srecord diff --git a/plat/renesas/rzg/bl2_plat_setup.c b/plat/renesas/rzg/bl2_plat_setup.c new file mode 100644 index 0000000000..13f413b556 --- /dev/null +++ b/plat/renesas/rzg/bl2_plat_setup.c @@ -0,0 +1,909 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <string.h> + +#include <arch_helpers.h> +#include <bl1/bl1.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <common/desc_image_load.h> +#include <drivers/console.h> +#include <drivers/io/io_driver.h> +#include <drivers/io/io_storage.h> +#include <libfdt.h> +#include <lib/mmio.h> +#include <lib/xlat_tables/xlat_tables_defs.h> +#include <platform_def.h> +#include <plat/common/platform.h> + +#include "avs_driver.h" +#include "board.h" +#include "boot_init_dram.h" +#include "cpg_registers.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_std.h" +#include "io_common.h" +#include "io_rcar.h" +#include "qos_init.h" +#include "rcar_def.h" +#include "rcar_private.h" +#include "rcar_version.h" +#include "rom_api.h" + +#define MAX_DRAM_CHANNELS 4 +/* + * DDR ch0 has a shadow area mapped in 32bit address space. + * Physical address 0x4_0000_0000 - 0x4_7fff_ffff in 64bit space + * is mapped to 0x4000_0000 - 0xbfff_ffff in 32bit space. + */ +#define MAX_DRAM_SIZE_CH0_32BIT_ADDR_SPACE 0x80000000ULL + +#if RCAR_BL2_DCACHE == 1 +/* + * Following symbols are only used during plat_arch_setup() only + * when RCAR_BL2_DCACHE is enabled. + */ +static const uint64_t BL2_RO_BASE = BL_CODE_BASE; +static const uint64_t BL2_RO_LIMIT = BL_CODE_END; + +#if USE_COHERENT_MEM +static const uint64_t BL2_COHERENT_RAM_BASE = BL_COHERENT_RAM_BASE; +static const uint64_t BL2_COHERENT_RAM_LIMIT = BL_COHERENT_RAM_END; +#endif /* USE_COHERENT_MEM */ + +#endif /* RCAR_BL2_DCACHE */ + +extern void plat_rcar_gic_driver_init(void); +extern void plat_rcar_gic_init(void); +extern void bl2_enter_bl31(const struct entry_point_info *bl_ep_info); +extern void bl2_system_cpg_init(void); +extern void bl2_secure_setting(void); +extern void bl2_cpg_init(void); +extern void rcar_io_emmc_setup(void); +extern void rcar_io_setup(void); +extern void rcar_swdt_release(void); +extern void rcar_swdt_init(void); +extern void rcar_rpc_init(void); +extern void rcar_dma_init(void); +extern void rzg_pfc_init(void); + +static void bl2_init_generic_timer(void); + +/* RZ/G2 product check */ +#if RCAR_LSI == RZ_G2M +#define TARGET_PRODUCT PRR_PRODUCT_M3 +#define TARGET_NAME "RZ/G2M" +#elif RCAR_LSI == RCAR_AUTO +#define TARGET_NAME "RZ/G2M" +#endif /* RCAR_LSI == RZ_G2M */ + +#define GPIO_INDT (GPIO_INDT1) +#define GPIO_BKUP_TRG_SHIFT (1U << 8U) + +CASSERT((PARAMS_BASE + sizeof(bl2_to_bl31_params_mem_t) + 0x100) + < (RCAR_SHARED_MEM_BASE + RCAR_SHARED_MEM_SIZE), + assert_bl31_params_do_not_fit_in_shared_memory); + +static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE); + +/* FDT with DRAM configuration */ +uint64_t fdt_blob[PAGE_SIZE_4KB / sizeof(uint64_t)]; +static void *fdt = (void *)fdt_blob; + +static void unsigned_num_print(uint64_t unum, unsigned int radix, char *string) +{ + /* Just need enough space to store 64 bit decimal integer */ + char num_buf[20]; + int i = 0; + unsigned int rem; + + do { + rem = unum % radix; + if (rem < 0xaU) { + num_buf[i] = '0' + rem; + } else { + num_buf[i] = 'a' + (rem - 0xaU); + } + i++; + unum /= radix; + } while (unum > 0U); + + while (--i >= 0) { + *string++ = num_buf[i]; + } + *string = 0; +} + +#if RCAR_LOSSY_ENABLE == 1 +typedef struct bl2_lossy_info { + uint32_t magic; + uint32_t a0; + uint32_t b0; +} bl2_lossy_info_t; + +static void bl2_lossy_gen_fdt(uint32_t no, uint64_t start_addr, + uint64_t end_addr, uint32_t format, + uint32_t enable, int fcnlnode) +{ + const uint64_t fcnlsize = cpu_to_fdt64(end_addr - start_addr); + char nodename[40] = { 0 }; + int ret, node; + + /* Ignore undefined addresses */ + if (start_addr == 0UL && end_addr == 0UL) { + return; + } + + snprintf(nodename, sizeof(nodename), "lossy-decompression@"); + unsigned_num_print(start_addr, 16, nodename + strlen(nodename)); + + node = ret = fdt_add_subnode(fdt, fcnlnode, nodename); + if (ret < 0) { + NOTICE("BL2: Cannot create FCNL node (ret=%i)\n", ret); + panic(); + } + + ret = fdt_setprop_string(fdt, node, "compatible", + "renesas,lossy-decompression"); + if (ret < 0) { + NOTICE("BL2: Cannot add FCNL compat string %s (ret=%i)\n", + "renesas,lossy-decompression", ret); + panic(); + } + + ret = fdt_appendprop_string(fdt, node, "compatible", + "shared-dma-pool"); + if (ret < 0) { + NOTICE("BL2: Cannot append FCNL compat string %s (ret=%i)\n", + "shared-dma-pool", ret); + panic(); + } + + ret = fdt_setprop_u64(fdt, node, "reg", start_addr); + if (ret < 0) { + NOTICE("BL2: Cannot add FCNL reg prop (ret=%i)\n", ret); + panic(); + } + + ret = fdt_appendprop(fdt, node, "reg", &fcnlsize, sizeof(fcnlsize)); + if (ret < 0) { + NOTICE("BL2: Cannot append FCNL reg size prop (ret=%i)\n", ret); + panic(); + } + + ret = fdt_setprop(fdt, node, "no-map", NULL, 0); + if (ret < 0) { + NOTICE("BL2: Cannot add FCNL no-map prop (ret=%i)\n", ret); + panic(); + } + + ret = fdt_setprop_u32(fdt, node, "renesas,formats", format); + if (ret < 0) { + NOTICE("BL2: Cannot add FCNL formats prop (ret=%i)\n", ret); + panic(); + } +} + +static void bl2_lossy_setting(uint32_t no, uint64_t start_addr, + uint64_t end_addr, uint32_t format, + uint32_t enable, int fcnlnode) +{ + bl2_lossy_info_t info; + uint32_t reg; + + bl2_lossy_gen_fdt(no, start_addr, end_addr, format, enable, fcnlnode); + + reg = format | (start_addr >> 20); + mmio_write_32(AXI_DCMPAREACRA0 + 0x8U * no, reg); + mmio_write_32(AXI_DCMPAREACRB0 + 0x8U * no, end_addr >> 20); + mmio_write_32(AXI_DCMPAREACRA0 + 0x8U * no, reg | enable); + + info.magic = 0x12345678U; + info.a0 = mmio_read_32(AXI_DCMPAREACRA0 + 0x8U * no); + info.b0 = mmio_read_32(AXI_DCMPAREACRB0 + 0x8U * no); + + mmio_write_32(LOSSY_PARAMS_BASE + sizeof(info) * no, info.magic); + mmio_write_32(LOSSY_PARAMS_BASE + sizeof(info) * no + 0x4U, info.a0); + mmio_write_32(LOSSY_PARAMS_BASE + sizeof(info) * no + 0x8U, info.b0); + + NOTICE(" Entry %d: DCMPAREACRAx:0x%x DCMPAREACRBx:0x%x\n", no, + mmio_read_32(AXI_DCMPAREACRA0 + 0x8U * no), + mmio_read_32(AXI_DCMPAREACRB0 + 0x8U * no)); +} +#endif /* RCAR_LOSSY_ENABLE == 1 */ + +void bl2_plat_flush_bl31_params(void) +{ + uint32_t product_cut, product, cut; + uint32_t boot_dev, boot_cpu; + uint32_t reg; + + reg = mmio_read_32(RCAR_MODEMR); + boot_dev = reg & MODEMR_BOOT_DEV_MASK; + + if (boot_dev == MODEMR_BOOT_DEV_EMMC_25X1 || + boot_dev == MODEMR_BOOT_DEV_EMMC_50X8) { + emmc_terminate(); + } + + if ((reg & MODEMR_BOOT_CPU_MASK) != MODEMR_BOOT_CPU_CR7) { + bl2_secure_setting(); + } + + reg = mmio_read_32(RCAR_PRR); + product_cut = reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK); + product = reg & PRR_PRODUCT_MASK; + cut = reg & PRR_CUT_MASK; + + if (!((product == PRR_PRODUCT_M3 && cut < PRR_PRODUCT_30) || + (product == PRR_PRODUCT_H3 && cut < PRR_PRODUCT_20))) { + /* Disable MFIS write protection */ + mmio_write_32(MFISWPCNTR, MFISWPCNTR_PASSWORD | 1U); + } + + reg = mmio_read_32(RCAR_MODEMR); + boot_cpu = reg & MODEMR_BOOT_CPU_MASK; + if (boot_cpu == MODEMR_BOOT_CPU_CA57 || + boot_cpu == MODEMR_BOOT_CPU_CA53) { + if (product_cut == PRR_PRODUCT_H3_CUT20) { + mmio_write_32(IPMMUVI0_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUVI1_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUPV0_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUPV1_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUPV2_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUPV3_IMSCTLR, IMSCTLR_DISCACHE); + } else if (product_cut == (PRR_PRODUCT_M3N | PRR_PRODUCT_10) || + product_cut == (PRR_PRODUCT_M3N | PRR_PRODUCT_11)) { + mmio_write_32(IPMMUVI0_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUPV0_IMSCTLR, IMSCTLR_DISCACHE); + } else if ((product_cut == (PRR_PRODUCT_E3 | PRR_PRODUCT_10)) || + (product_cut == (PRR_PRODUCT_E3 | PRR_PRODUCT_11))) { + mmio_write_32(IPMMUVI0_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUVP0_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUPV0_IMSCTLR, IMSCTLR_DISCACHE); + } + + if (product_cut == (PRR_PRODUCT_H3_CUT20) || + product_cut == (PRR_PRODUCT_M3N | PRR_PRODUCT_10) || + product_cut == (PRR_PRODUCT_M3N | PRR_PRODUCT_11) || + product_cut == (PRR_PRODUCT_E3 | PRR_PRODUCT_10)) { + mmio_write_32(IPMMUHC_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMURT_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUMP_IMSCTLR, IMSCTLR_DISCACHE); + + mmio_write_32(IPMMUDS0_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUDS1_IMSCTLR, IMSCTLR_DISCACHE); + } + } + + mmio_write_32(IPMMUMM_IMSCTLR, IPMMUMM_IMSCTLR_ENABLE); + mmio_write_32(IPMMUMM_IMAUXCTLR, IPMMUMM_IMAUXCTLR_NMERGE40_BIT); + + rcar_swdt_release(); + bl2_system_cpg_init(); + +#if RCAR_BL2_DCACHE == 1 + /* Disable data cache (clean and invalidate) */ + disable_mmu_el3(); +#endif /* RCAR_BL2_DCACHE == 1 */ +} + +static uint32_t is_ddr_backup_mode(void) +{ +#if RCAR_SYSTEM_SUSPEND + static uint32_t reason = RCAR_COLD_BOOT; + static uint32_t once; + + if (once != 0U) { + return reason; + } + + once = 1; + if ((mmio_read_32(GPIO_INDT) & GPIO_BKUP_TRG_SHIFT) == 0U) { + return reason; + } + + reason = RCAR_WARM_BOOT; + return reason; +#else /* RCAR_SYSTEM_SUSPEND */ + return RCAR_COLD_BOOT; +#endif /* RCAR_SYSTEM_SUSPEND */ +} + +int bl2_plat_handle_pre_image_load(unsigned int image_id) +{ + u_register_t *boot_kind = (void *)BOOT_KIND_BASE; + bl_mem_params_node_t *bl_mem_params; + + if (image_id != BL31_IMAGE_ID) { + return 0; + } + + bl_mem_params = get_bl_mem_params_node(image_id); + + if (is_ddr_backup_mode() != RCAR_COLD_BOOT) { + *boot_kind = RCAR_WARM_BOOT; + flush_dcache_range(BOOT_KIND_BASE, sizeof(*boot_kind)); + + console_flush(); + bl2_plat_flush_bl31_params(); + + /* will not return */ + bl2_enter_bl31(&bl_mem_params->ep_info); + } + + *boot_kind = RCAR_COLD_BOOT; + flush_dcache_range(BOOT_KIND_BASE, sizeof(*boot_kind)); + + return 0; +} + +static uint64_t rzg_get_dest_addr_from_cert(uint32_t certid, uintptr_t *dest) +{ + uint32_t cert, len; + int err; + + err = rcar_get_certificate(certid, &cert); + if (err != 0) { + ERROR("%s : cert file load error", __func__); + return 1U; + } + + rcar_read_certificate((uint64_t)cert, &len, dest); + + return 0U; +} + +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + static bl2_to_bl31_params_mem_t *params; + bl_mem_params_node_t *bl_mem_params; + uintptr_t dest; + uint64_t ret; + + if (params == NULL) { + params = (bl2_to_bl31_params_mem_t *)PARAMS_BASE; + memset((void *)PARAMS_BASE, 0, sizeof(*params)); + } + + bl_mem_params = get_bl_mem_params_node(image_id); + + switch (image_id) { + case BL31_IMAGE_ID: + ret = rzg_get_dest_addr_from_cert(SOC_FW_CONTENT_CERT_ID, + &dest); + if (ret == 0U) { + bl_mem_params->image_info.image_base = dest; + } + break; + case BL32_IMAGE_ID: + ret = rzg_get_dest_addr_from_cert(TRUSTED_OS_FW_CONTENT_CERT_ID, + &dest); + if (ret == 0U) { + bl_mem_params->image_info.image_base = dest; + } + + memcpy(¶ms->bl32_ep_info, &bl_mem_params->ep_info, + sizeof(entry_point_info_t)); + break; + case BL33_IMAGE_ID: + memcpy(¶ms->bl33_ep_info, &bl_mem_params->ep_info, + sizeof(entry_point_info_t)); + break; + default: + break; + } + + return 0; +} + +struct meminfo *bl2_plat_sec_mem_layout(void) +{ + return &bl2_tzram_layout; +} + +static void bl2_populate_compatible_string(void *dt) +{ + uint32_t board_type; + uint32_t board_rev; + uint32_t reg; + int ret; + + fdt_setprop_u32(dt, 0, "#address-cells", 2); + fdt_setprop_u32(dt, 0, "#size-cells", 2); + + /* Populate compatible string */ + rzg_get_board_type(&board_type, &board_rev); + switch (board_type) { + case BOARD_HIHOPE_RZ_G2M: + ret = fdt_setprop_string(dt, 0, "compatible", + "hoperun,hihope-rzg2m"); + break; + default: + NOTICE("BL2: Cannot set compatible string, board unsupported\n"); + panic(); + break; + } + + if (ret < 0) { + NOTICE("BL2: Cannot set compatible string (ret=%i)\n", ret); + panic(); + } + + reg = mmio_read_32(RCAR_PRR); + switch (reg & PRR_PRODUCT_MASK) { + case PRR_PRODUCT_M3: + ret = fdt_appendprop_string(dt, 0, "compatible", + "renesas,r8a774a1"); + break; + default: + NOTICE("BL2: Cannot set compatible string, SoC unsupported\n"); + panic(); + break; + } + + if (ret < 0) { + NOTICE("BL2: Cannot set compatible string (ret=%i)\n", ret); + panic(); + } +} + +static int bl2_add_memory_node(uint64_t start, uint64_t size) +{ + char nodename[32] = { 0 }; + uint64_t fdtsize; + int ret, node; + + fdtsize = cpu_to_fdt64(size); + + snprintf(nodename, sizeof(nodename), "memory@"); + unsigned_num_print(start, 16, nodename + strlen(nodename)); + node = ret = fdt_add_subnode(fdt, 0, nodename); + if (ret < 0) { + return ret; + } + + ret = fdt_setprop_string(fdt, node, "device_type", "memory"); + if (ret < 0) { + return ret; + } + + ret = fdt_setprop_u64(fdt, node, "reg", start); + if (ret < 0) { + return ret; + } + + return fdt_appendprop(fdt, node, "reg", &fdtsize, sizeof(fdtsize)); +} + +static void bl2_advertise_dram_entries(uint64_t dram_config[8]) +{ + uint64_t start, size; + int ret, chan; + + for (chan = 0; chan < MAX_DRAM_CHANNELS; chan++) { + start = dram_config[2 * chan]; + size = dram_config[2 * chan + 1]; + if (size == 0U) { + continue; + } + + NOTICE("BL2: CH%d: %llx - %llx, %lld %siB\n", + chan, start, start + size - 1U, + (size >> 30) ? : size >> 20, + (size >> 30) ? "G" : "M"); + } + + /* + * We add the DT nodes in reverse order here. The fdt_add_subnode() + * adds the DT node before the first existing DT node, so we have + * to add them in reverse order to get nodes sorted by address in + * the resulting DT. + */ + for (chan = MAX_DRAM_CHANNELS - 1; chan >= 0; chan--) { + start = dram_config[2 * chan]; + size = dram_config[2 * chan + 1]; + if (size == 0U) { + continue; + } + + /* + * Channel 0 is mapped in 32bit space and the first + * 128 MiB are reserved + */ + if (chan == 0) { + /* + * Maximum DDR size in Channel 0 for 32 bit space is 2GB, Add DT node + * for remaining region in 64 bit address space + */ + if (size > MAX_DRAM_SIZE_CH0_32BIT_ADDR_SPACE) { + start = dram_config[chan] + MAX_DRAM_SIZE_CH0_32BIT_ADDR_SPACE; + size -= MAX_DRAM_SIZE_CH0_32BIT_ADDR_SPACE; + ret = bl2_add_memory_node(start, size); + if (ret < 0) { + goto err; + } + } + start = 0x48000000U; + size -= 0x8000000U; + } + + ret = bl2_add_memory_node(start, size); + if (ret < 0) { + goto err; + } + } + + return; +err: + NOTICE("BL2: Cannot add memory node to FDT (ret=%i)\n", ret); + panic(); +} + +static void bl2_advertise_dram_size(uint32_t product) +{ + uint64_t dram_config[8] = { + [0] = 0x400000000ULL, + [2] = 0x500000000ULL, + [4] = 0x600000000ULL, + [6] = 0x700000000ULL, + }; + + switch (product) { + case PRR_PRODUCT_M3: + /* 4GB(2GBx2 2ch split) */ + dram_config[1] = 0x80000000ULL; + dram_config[5] = 0x80000000ULL; + break; + default: + NOTICE("BL2: Detected invalid DRAM entries\n"); + break; + } + + bl2_advertise_dram_entries(dram_config); +} + +void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2, + u_register_t arg3, u_register_t arg4) +{ + uint32_t reg, midr, boot_dev, boot_cpu, type, rev; + uint32_t product, product_cut, major, minor; + int32_t ret; + const char *str; + const char *unknown = "unknown"; + const char *cpu_ca57 = "CA57"; + const char *cpu_ca53 = "CA53"; + const char *product_g2m = "G2M"; + const char *boot_hyper80 = "HyperFlash(80MHz)"; + const char *boot_qspi40 = "QSPI Flash(40MHz)"; + const char *boot_qspi80 = "QSPI Flash(80MHz)"; + const char *boot_emmc25x1 = "eMMC(25MHz x1)"; + const char *boot_emmc50x8 = "eMMC(50MHz x8)"; + const char *boot_hyper160 = "HyperFlash(160MHz)"; +#if RZG_LCS_STATE_DETECTION_ENABLE + uint32_t lcs; + const char *lcs_secure = "SE"; + const char *lcs_cm = "CM"; + const char *lcs_dm = "DM"; + const char *lcs_sd = "SD"; + const char *lcs_fa = "FA"; +#endif /* RZG_LCS_STATE_DETECTION_ENABLE */ + +#if (RCAR_LOSSY_ENABLE == 1) + int fcnlnode; +#endif /* (RCAR_LOSSY_ENABLE == 1) */ + + bl2_init_generic_timer(); + + reg = mmio_read_32(RCAR_MODEMR); + boot_dev = reg & MODEMR_BOOT_DEV_MASK; + boot_cpu = reg & MODEMR_BOOT_CPU_MASK; + + bl2_cpg_init(); + + if (boot_cpu == MODEMR_BOOT_CPU_CA57 || + boot_cpu == MODEMR_BOOT_CPU_CA53) { + rzg_pfc_init(); + rcar_console_boot_init(); + } + + plat_rcar_gic_driver_init(); + plat_rcar_gic_init(); + rcar_swdt_init(); + + /* FIQ interrupts are taken to EL3 */ + write_scr_el3(read_scr_el3() | SCR_FIQ_BIT); + + write_daifclr(DAIF_FIQ_BIT); + + reg = read_midr(); + midr = reg & (MIDR_PN_MASK << MIDR_PN_SHIFT); + switch (midr) { + case MIDR_CA57: + str = cpu_ca57; + break; + case MIDR_CA53: + str = cpu_ca53; + break; + default: + str = unknown; + break; + } + + NOTICE("BL2: RZ/G2 Initial Program Loader(%s) Rev.%s\n", str, + version_of_renesas); + + reg = mmio_read_32(RCAR_PRR); + product_cut = reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK); + product = reg & PRR_PRODUCT_MASK; + + switch (product) { + case PRR_PRODUCT_M3: + str = product_g2m; + break; + default: + str = unknown; + break; + } + + if ((product == PRR_PRODUCT_M3) && + ((reg & RCAR_MAJOR_MASK) == PRR_PRODUCT_20)) { + if ((reg & PRR_CUT_MASK) == RCAR_M3_CUT_VER11) { + /* M3 Ver.1.1 or Ver.1.2 */ + NOTICE("BL2: PRR is RZ/%s Ver.1.1 / Ver.1.2\n", str); + } else { + NOTICE("BL2: PRR is RZ/%s Ver.1.%d\n", str, + (reg & RCAR_MINOR_MASK) + RCAR_M3_MINOR_OFFSET); + } + } else { + major = (reg & RCAR_MAJOR_MASK) >> RCAR_MAJOR_SHIFT; + major = major + RCAR_MAJOR_OFFSET; + minor = reg & RCAR_MINOR_MASK; + NOTICE("BL2: PRR is RZ/%s Ver.%d.%d\n", str, major, minor); + } + + rzg_get_board_type(&type, &rev); + + switch (type) { + case BOARD_HIHOPE_RZ_G2M: + break; + default: + type = BOARD_UNKNOWN; + break; + } + + if (type == BOARD_UNKNOWN || rev == BOARD_REV_UNKNOWN) { + NOTICE("BL2: Board is %s Rev.---\n", GET_BOARD_NAME(type)); + } else { + NOTICE("BL2: Board is %s Rev.%d.%d\n", + GET_BOARD_NAME(type), + GET_BOARD_MAJOR(rev), GET_BOARD_MINOR(rev)); + } + +#if RCAR_LSI != RCAR_AUTO + if (product != TARGET_PRODUCT) { + ERROR("BL2: IPL was been built for the %s.\n", TARGET_NAME); + ERROR("BL2: Please write the correct IPL to flash memory.\n"); + panic(); + } +#endif /* RCAR_LSI != RCAR_AUTO */ + rcar_avs_init(); + rcar_avs_setting(); + + switch (boot_dev) { + case MODEMR_BOOT_DEV_HYPERFLASH160: + str = boot_hyper160; + break; + case MODEMR_BOOT_DEV_HYPERFLASH80: + str = boot_hyper80; + break; + case MODEMR_BOOT_DEV_QSPI_FLASH40: + str = boot_qspi40; + break; + case MODEMR_BOOT_DEV_QSPI_FLASH80: + str = boot_qspi80; + break; + case MODEMR_BOOT_DEV_EMMC_25X1: + str = boot_emmc25x1; + break; + case MODEMR_BOOT_DEV_EMMC_50X8: + str = boot_emmc50x8; + break; + default: + str = unknown; + break; + } + NOTICE("BL2: Boot device is %s\n", str); + + rcar_avs_setting(); + +#if RZG_LCS_STATE_DETECTION_ENABLE + reg = rcar_rom_get_lcs(&lcs); + if (reg != 0U) { + str = unknown; + goto lcm_state; + } + + switch (lcs) { + case LCS_CM: + str = lcs_cm; + break; + case LCS_DM: + str = lcs_dm; + break; + case LCS_SD: + str = lcs_sd; + break; + case LCS_SE: + str = lcs_secure; + break; + case LCS_FA: + str = lcs_fa; + break; + default: + str = unknown; + break; + } + +lcm_state: + NOTICE("BL2: LCM state is %s\n", str); +#endif /* RZG_LCS_STATE_DETECTION_ENABLE */ + + rcar_avs_end(); + is_ddr_backup_mode(); + + bl2_tzram_layout.total_base = BL31_BASE; + bl2_tzram_layout.total_size = BL31_LIMIT - BL31_BASE; + + if (boot_cpu == MODEMR_BOOT_CPU_CA57 || + boot_cpu == MODEMR_BOOT_CPU_CA53) { + ret = rzg_dram_init(); + if (ret != 0) { + NOTICE("BL2: Failed to DRAM initialize (%d).\n", ret); + panic(); + } + rzg_qos_init(); + } + + /* Set up FDT */ + ret = fdt_create_empty_tree(fdt, sizeof(fdt_blob)); + if (ret != 0) { + NOTICE("BL2: Cannot allocate FDT for U-Boot (ret=%i)\n", ret); + panic(); + } + + /* Add platform compatible string */ + bl2_populate_compatible_string(fdt); + + /* Print DRAM layout */ + bl2_advertise_dram_size(product); + + if (boot_dev == MODEMR_BOOT_DEV_EMMC_25X1 || + boot_dev == MODEMR_BOOT_DEV_EMMC_50X8) { + if (rcar_emmc_init() != EMMC_SUCCESS) { + NOTICE("BL2: Failed to eMMC driver initialize.\n"); + panic(); + } + rcar_emmc_memcard_power(EMMC_POWER_ON); + if (rcar_emmc_mount() != EMMC_SUCCESS) { + NOTICE("BL2: Failed to eMMC mount operation.\n"); + panic(); + } + } else { + rcar_rpc_init(); + rcar_dma_init(); + } + + reg = mmio_read_32(RST_WDTRSTCR); + reg &= ~WDTRSTCR_RWDT_RSTMSK; + reg |= WDTRSTCR_PASSWORD; + mmio_write_32(RST_WDTRSTCR, reg); + + mmio_write_32(CPG_CPGWPR, CPGWPR_PASSWORD); + mmio_write_32(CPG_CPGWPCR, CPGWPCR_PASSWORD); + + reg = mmio_read_32(RCAR_PRR); + if ((reg & RCAR_CPU_MASK_CA57) == RCAR_CPU_HAVE_CA57) { + mmio_write_32(CPG_CA57DBGRCR, + DBGCPUPREN | mmio_read_32(CPG_CA57DBGRCR)); + } + + if ((reg & RCAR_CPU_MASK_CA53) == RCAR_CPU_HAVE_CA53) { + mmio_write_32(CPG_CA53DBGRCR, + DBGCPUPREN | mmio_read_32(CPG_CA53DBGRCR)); + } + + if (product_cut == PRR_PRODUCT_H3_CUT10) { + reg = mmio_read_32(CPG_PLL2CR); + reg &= ~((uint32_t)1 << 5); + mmio_write_32(CPG_PLL2CR, reg); + + reg = mmio_read_32(CPG_PLL4CR); + reg &= ~((uint32_t)1 << 5); + mmio_write_32(CPG_PLL4CR, reg); + + reg = mmio_read_32(CPG_PLL0CR); + reg &= ~((uint32_t)1 << 12); + mmio_write_32(CPG_PLL0CR, reg); + } +#if (RCAR_LOSSY_ENABLE == 1) + NOTICE("BL2: Lossy Decomp areas\n"); + + fcnlnode = fdt_add_subnode(fdt, 0, "reserved-memory"); + if (fcnlnode < 0) { + NOTICE("BL2: Cannot create reserved mem node (ret=%i)\n", + fcnlnode); + panic(); + } + + bl2_lossy_setting(0, LOSSY_ST_ADDR0, LOSSY_END_ADDR0, + LOSSY_FMT0, LOSSY_ENA_DIS0, fcnlnode); + bl2_lossy_setting(1, LOSSY_ST_ADDR1, LOSSY_END_ADDR1, + LOSSY_FMT1, LOSSY_ENA_DIS1, fcnlnode); + bl2_lossy_setting(2, LOSSY_ST_ADDR2, LOSSY_END_ADDR2, + LOSSY_FMT2, LOSSY_ENA_DIS2, fcnlnode); +#endif /* RCAR_LOSSY_ENABLE */ + + fdt_pack(fdt); + NOTICE("BL2: FDT at %p\n", fdt); + + if (boot_dev == MODEMR_BOOT_DEV_EMMC_25X1 || + boot_dev == MODEMR_BOOT_DEV_EMMC_50X8) { + rcar_io_emmc_setup(); + } else { + rcar_io_setup(); + } +} + +void bl2_el3_plat_arch_setup(void) +{ +#if RCAR_BL2_DCACHE == 1 + NOTICE("BL2: D-Cache enable\n"); + rcar_configure_mmu_el3(BL2_BASE, + BL2_END - BL2_BASE, + BL2_RO_BASE, BL2_RO_LIMIT +#if USE_COHERENT_MEM + , BL2_COHERENT_RAM_BASE, BL2_COHERENT_RAM_LIMIT +#endif /* USE_COHERENT_MEM */ + ); +#endif /* RCAR_BL2_DCACHE == 1 */ +} + +void bl2_platform_setup(void) +{ + /* + * Place holder for performing any platform initialization specific + * to BL2. + */ +} + +static void bl2_init_generic_timer(void) +{ + uint32_t reg_cntfid; + uint32_t modemr; + uint32_t modemr_pll; + uint32_t pll_table[] = { + EXTAL_MD14_MD13_TYPE_0, /* MD14/MD13 : 0b00 */ + EXTAL_MD14_MD13_TYPE_1, /* MD14/MD13 : 0b01 */ + EXTAL_MD14_MD13_TYPE_2, /* MD14/MD13 : 0b10 */ + EXTAL_MD14_MD13_TYPE_3 /* MD14/MD13 : 0b11 */ + }; + + modemr = mmio_read_32(RCAR_MODEMR); + modemr_pll = (modemr & MODEMR_BOOT_PLL_MASK); + + /* Set frequency data in CNTFID0 */ + reg_cntfid = pll_table[modemr_pll >> MODEMR_BOOT_PLL_SHIFT]; + + /* Update memory mapped and register based frequency */ + write_cntfrq_el0((u_register_t)reg_cntfid); + mmio_write_32(ARM_SYS_CNTCTL_BASE + (uintptr_t)CNTFID_OFF, reg_cntfid); + /* Enable counter */ + mmio_setbits_32(RCAR_CNTC_BASE + (uintptr_t)CNTCR_OFF, + (uint32_t)CNTCR_EN); +} diff --git a/plat/renesas/rzg/platform.mk b/plat/renesas/rzg/platform.mk new file mode 100644 index 0000000000..421cbbe641 --- /dev/null +++ b/plat/renesas/rzg/platform.mk @@ -0,0 +1,222 @@ +# +# Copyright (c) 2018-2020, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include plat/renesas/common/common.mk + +ifndef LSI + $(error "Error: Unknown LSI. Please use LSI=<LSI name> to specify the LSI") +else + ifeq (${LSI},AUTO) + RCAR_LSI:=${RCAR_AUTO} + else ifeq (${LSI},G2M) + RCAR_LSI:=${RZ_G2M} + ifndef LSI_CUT + # enable compatible function. + RCAR_LSI_CUT_COMPAT := 1 + $(eval $(call add_define,RCAR_LSI_CUT_COMPAT)) + else + # disable compatible function. + ifeq (${LSI_CUT},10) + RCAR_LSI_CUT:=0 + else ifeq (${LSI_CUT},11) + RCAR_LSI_CUT:=1 + else ifeq (${LSI_CUT},13) + RCAR_LSI_CUT:=3 + else ifeq (${LSI_CUT},30) + RCAR_LSI_CUT:=20 + else + $(error "Error: ${LSI_CUT} is not supported.") + endif + $(eval $(call add_define,RCAR_LSI_CUT)) + endif + else + $(error "Error: ${LSI} is not supported.") + endif + $(eval $(call add_define,RCAR_LSI)) +endif + +# Process RZG_LCS_STATE_DETECTION_ENABLE flag +# Enable to get LCS state information +ifndef RZG_LCS_STATE_DETECTION_ENABLE +RZG_LCS_STATE_DETECTION_ENABLE := 0 +endif +$(eval $(call add_define,RZG_LCS_STATE_DETECTION_ENABLE)) + +# Process RCAR_SECURE_BOOT flag +ifndef RCAR_SECURE_BOOT +RCAR_SECURE_BOOT := 0 +endif +$(eval $(call add_define,RCAR_SECURE_BOOT)) + +# LCS state of RZ/G2 Chip is all CM. +# However certain chips(RZ/G2M and RZ/G2E) have incorrect factory Fuse settings +# which results in getting incorrect LCS states +# if need to enable RCAR_SECURE_BOOT, make sure the chip has proper factory Fuse settings. +ifeq (${RCAR_SECURE_BOOT},1) + ifeq (${RZG_LCS_STATE_DETECTION_ENABLE},0) + $(error "Error: Please check the chip has proper factory Fuse settings and set RZG_LCS_STATE_DETECTION_ENABLE to enable.") + endif +endif + +# lock RPC HYPERFLASH access by default +# unlock to repogram the ATF firmware from u-boot +ifndef RCAR_RPC_HYPERFLASH_LOCKED +RCAR_RPC_HYPERFLASH_LOCKED := 1 +endif +$(eval $(call add_define,RCAR_RPC_HYPERFLASH_LOCKED)) + +# Process RCAR_QOS_TYPE flag +ifndef RCAR_QOS_TYPE +RCAR_QOS_TYPE := 0 +endif +$(eval $(call add_define,RCAR_QOS_TYPE)) + +# Process RCAR_DRAM_SPLIT flag +ifndef RCAR_DRAM_SPLIT +RCAR_DRAM_SPLIT := 0 +endif +$(eval $(call add_define,RCAR_DRAM_SPLIT)) + +# Process RCAR_BL33_EXECUTION_EL flag +ifndef RCAR_BL33_EXECUTION_EL +RCAR_BL33_EXECUTION_EL := 0 +endif +$(eval $(call add_define,RCAR_BL33_EXECUTION_EL)) + +# Process RCAR_AVS_SETTING_ENABLE flag +ifndef AVS_SETTING_ENABLE +AVS_SETTING_ENABLE := 0 +endif +$(eval $(call add_define,AVS_SETTING_ENABLE)) + +# Process RCAR_LOSSY_ENABLE flag +ifndef RCAR_LOSSY_ENABLE +RCAR_LOSSY_ENABLE := 0 +endif +$(eval $(call add_define,RCAR_LOSSY_ENABLE)) + +# Process LIFEC_DBSC_PROTECT_ENABLE flag +ifndef LIFEC_DBSC_PROTECT_ENABLE +LIFEC_DBSC_PROTECT_ENABLE := 1 +endif +$(eval $(call add_define,LIFEC_DBSC_PROTECT_ENABLE)) + +# Process RCAR_GEN3_ULCB flag +ifndef RCAR_GEN3_ULCB +RCAR_GEN3_ULCB := 0 +endif + +# Process RCAR_REF_INT flag +ifndef RCAR_REF_INT +RCAR_REF_INT :=0 +endif +$(eval $(call add_define,RCAR_REF_INT)) + +# Process RCAR_REWT_TRAINING flag +ifndef RCAR_REWT_TRAINING +RCAR_REWT_TRAINING := 1 +endif +$(eval $(call add_define,RCAR_REWT_TRAINING)) + +# Process RCAR_SYSTEM_SUSPEND flag +ifndef RCAR_SYSTEM_SUSPEND +RCAR_SYSTEM_SUSPEND := 0 +endif +$(eval $(call add_define,RCAR_SYSTEM_SUSPEND)) + +# Process RCAR_DRAM_LPDDR4_MEMCONF flag +ifndef RCAR_DRAM_LPDDR4_MEMCONF +RCAR_DRAM_LPDDR4_MEMCONF :=1 +endif +$(eval $(call add_define,RCAR_DRAM_LPDDR4_MEMCONF)) + +# Process RCAR_DRAM_DDR3L_MEMCONF flag +ifndef RCAR_DRAM_DDR3L_MEMCONF +RCAR_DRAM_DDR3L_MEMCONF :=1 +endif +$(eval $(call add_define,RCAR_DRAM_DDR3L_MEMCONF)) + +# Process RCAR_DRAM_DDR3L_MEMDUAL flag +ifndef RCAR_DRAM_DDR3L_MEMDUAL +RCAR_DRAM_DDR3L_MEMDUAL :=1 +endif +$(eval $(call add_define,RCAR_DRAM_DDR3L_MEMDUAL)) + +# Process RCAR_BL33_ARG0 flag +ifdef RCAR_BL33_ARG0 +$(eval $(call add_define,RCAR_BL33_ARG0)) +endif + +#Process RCAR_BL2_DCACHE flag +ifndef RCAR_BL2_DCACHE +RCAR_BL2_DCACHE := 0 +endif +$(eval $(call add_define,RCAR_BL2_DCACHE)) + +# Process RCAR_DRAM_CHANNEL flag +ifndef RCAR_DRAM_CHANNEL +RCAR_DRAM_CHANNEL :=15 +endif +$(eval $(call add_define,RCAR_DRAM_CHANNEL)) + +#Process RCAR_SYSTEM_RESET_KEEPON_DDR flag +ifndef RCAR_SYSTEM_RESET_KEEPON_DDR +RCAR_SYSTEM_RESET_KEEPON_DDR := 0 +endif +$(eval $(call add_define,RCAR_SYSTEM_RESET_KEEPON_DDR)) + +include drivers/renesas/rzg/ddr/ddr.mk +include drivers/renesas/rzg/qos/qos.mk +include drivers/renesas/rzg/pfc/pfc.mk +include lib/libfdt/libfdt.mk + +PLAT_INCLUDES += -Idrivers/renesas/rzg/ddr \ + -Idrivers/renesas/rzg/qos \ + -Idrivers/renesas/rzg/board \ + -Idrivers/renesas/common \ + -Idrivers/renesas/common/iic_dvfs \ + -Idrivers/renesas/common/avs \ + -Idrivers/renesas/common/delay \ + -Idrivers/renesas/common/rom \ + -Idrivers/renesas/common/scif \ + -Idrivers/renesas/common/emmc \ + -Idrivers/renesas/common/pwrc \ + -Idrivers/renesas/common/io + +BL2_SOURCES += plat/renesas/rzg/bl2_plat_setup.c \ + drivers/renesas/rzg/board/board.c + +# build the layout images for the bootrom and the necessary srecords +rzg: rzg_layout_create rzg_srecord +distclean realclean clean: clean_layout_tool clean_srecord + +# layout images +LAYOUT_TOOLPATH ?= tools/renesas/rzg_layout_create + +clean_layout_tool: + @echo "clean layout tool" + ${Q}${MAKE} -C ${LAYOUT_TOOLPATH} clean + +.PHONY: rzg_layout_create +rzg_layout_create: + @echo "generating layout srecs" + ${Q}${MAKE} CPPFLAGS="-D=AARCH64" --no-print-directory -C ${LAYOUT_TOOLPATH} + +# srecords +SREC_PATH = ${BUILD_PLAT} +BL2_ELF_SRC = ${SREC_PATH}/bl2/bl2.elf +BL31_ELF_SRC = ${SREC_PATH}/bl31/bl31.elf + +clean_srecord: + @echo "clean bl2 and bl31 srecs" + rm -f ${SREC_PATH}/bl2.srec ${SREC_PATH}/bl31.srec + +.PHONY: rzg_srecord +rzg_srecord: $(BL2_ELF_SRC) $(BL31_ELF_SRC) + @echo "generating srec: ${SREC_PATH}/bl2.srec" + $(Q)$(OC) -O srec --srec-forceS3 ${BL2_ELF_SRC} ${SREC_PATH}/bl2.srec + @echo "generating srec: ${SREC_PATH}/bl31.srec" + $(Q)$(OC) -O srec --srec-forceS3 ${BL31_ELF_SRC} ${SREC_PATH}/bl31.srec diff --git a/plat/rockchip/common/rockchip_stack_protector.c b/plat/rockchip/common/rockchip_stack_protector.c new file mode 100644 index 0000000000..18989779ee --- /dev/null +++ b/plat/rockchip/common/rockchip_stack_protector.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include <arch_helpers.h> +#include <plat/common/platform.h> + +#define RANDOM_CANARY_VALUE ((u_register_t) 3288484550995823360ULL) + +u_register_t plat_get_stack_protector_canary(void) +{ + /* + * Ideally, a random number should be returned instead of the + * combination of a timer's value and a compile-time constant. + * As the virt platform does not have any random number generator, + * this is better than nothing but not necessarily really secure. + */ + return RANDOM_CANARY_VALUE ^ read_cntpct_el0(); +} + diff --git a/plat/rockchip/px30/platform.mk b/plat/rockchip/px30/platform.mk index 87cf18704a..b1bb80701f 100644 --- a/plat/rockchip/px30/platform.mk +++ b/plat/rockchip/px30/platform.mk @@ -36,6 +36,10 @@ PLAT_BL_COMMON_SOURCES := lib/bl_aux_params/bl_aux_params.c \ lib/xlat_tables/aarch64/xlat_tables.c \ plat/common/plat_psci_common.c +ifneq (${ENABLE_STACK_PROTECTOR},0) +PLAT_BL_COMMON_SOURCES += ${RK_PLAT_COMMON}/rockchip_stack_protector.c +endif + BL31_SOURCES += ${RK_GIC_SOURCES} \ common/desc_image_load.c \ drivers/arm/cci/cci.c \ diff --git a/plat/rockchip/rk3328/platform.mk b/plat/rockchip/rk3328/platform.mk index 0219422f93..5a307e4915 100644 --- a/plat/rockchip/rk3328/platform.mk +++ b/plat/rockchip/rk3328/platform.mk @@ -35,6 +35,10 @@ PLAT_BL_COMMON_SOURCES := common/desc_image_load.c \ plat/common/aarch64/crash_console_helpers.S \ plat/common/plat_psci_common.c +ifneq (${ENABLE_STACK_PROTECTOR},0) +PLAT_BL_COMMON_SOURCES += ${RK_PLAT_COMMON}/rockchip_stack_protector.c +endif + BL31_SOURCES += ${RK_GIC_SOURCES} \ drivers/arm/cci/cci.c \ drivers/ti/uart/aarch64/16550_console.S \ diff --git a/plat/rockchip/rk3368/platform.mk b/plat/rockchip/rk3368/platform.mk index cb0cb89625..e78729357b 100644 --- a/plat/rockchip/rk3368/platform.mk +++ b/plat/rockchip/rk3368/platform.mk @@ -33,6 +33,10 @@ PLAT_BL_COMMON_SOURCES := common/desc_image_load.c \ plat/common/aarch64/crash_console_helpers.S \ plat/common/plat_psci_common.c +ifneq (${ENABLE_STACK_PROTECTOR},0) +PLAT_BL_COMMON_SOURCES += ${RK_PLAT_COMMON}/rockchip_stack_protector.c +endif + BL31_SOURCES += ${RK_GIC_SOURCES} \ drivers/arm/cci/cci.c \ drivers/ti/uart/aarch64/16550_console.S \ diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk index a658fb2868..aba67c2fe3 100644 --- a/plat/rockchip/rk3399/platform.mk +++ b/plat/rockchip/rk3399/platform.mk @@ -38,6 +38,10 @@ PLAT_BL_COMMON_SOURCES := common/desc_image_load.c \ plat/common/aarch64/crash_console_helpers.S \ plat/common/plat_psci_common.c +ifneq (${ENABLE_STACK_PROTECTOR},0) +PLAT_BL_COMMON_SOURCES += ${RK_PLAT_COMMON}/rockchip_stack_protector.c +endif + BL31_SOURCES += ${RK_GIC_SOURCES} \ drivers/arm/cci/cci.c \ drivers/ti/uart/aarch64/16550_console.S \ diff --git a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c index 49375a62d0..d4ed445258 100644 --- a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c +++ b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c @@ -9,7 +9,7 @@ #include <common/debug.h> #include <common/runtime_svc.h> -#include <drivers/st/scmi-msg.h> +#include <drivers/scmi-msg.h> #include <lib/psci/psci.h> #include <tools_share/uuid.h> diff --git a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk index 8866fb556c..4d4820afa0 100644 --- a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk +++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk @@ -26,11 +26,11 @@ BL32_SOURCES += ${GICV2_SOURCES} \ BL32_SOURCES += plat/common/plat_psci_common.c # SCMI server drivers -BL32_SOURCES += drivers/st/scmi-msg/base.c \ - drivers/st/scmi-msg/clock.c \ - drivers/st/scmi-msg/entry.c \ - drivers/st/scmi-msg/reset_domain.c \ - drivers/st/scmi-msg/smt.c +BL32_SOURCES += drivers/scmi-msg/base.c \ + drivers/scmi-msg/clock.c \ + drivers/scmi-msg/entry.c \ + drivers/scmi-msg/reset_domain.c \ + drivers/scmi-msg/smt.c # stm32mp1 specific services BL32_SOURCES += plat/st/stm32mp1/services/bsec_svc.c \ diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S index 3021362365..84e9e8d432 100644 --- a/plat/st/stm32mp1/stm32mp1_helper.S +++ b/plat/st/stm32mp1/stm32mp1_helper.S @@ -204,7 +204,7 @@ endfunc plat_crash_console_init * --------------------------------------------- */ func plat_crash_console_flush - ldr r1, =STM32MP_DEBUG_USART_BASE + ldr r0, =STM32MP_DEBUG_USART_BASE b console_stm32_core_flush endfunc plat_crash_console_flush diff --git a/plat/st/stm32mp1/stm32mp1_scmi.c b/plat/st/stm32mp1/stm32mp1_scmi.c index 80faf0c6e0..6d60bd4de1 100644 --- a/plat/st/stm32mp1/stm32mp1_scmi.c +++ b/plat/st/stm32mp1/stm32mp1_scmi.c @@ -8,8 +8,8 @@ #include <platform_def.h> -#include <drivers/st/scmi-msg.h> -#include <drivers/st/scmi.h> +#include <drivers/scmi-msg.h> +#include <drivers/scmi.h> #include <drivers/st/stm32mp1_clk.h> #include <drivers/st/stm32mp_reset.h> #include <dt-bindings/clock/stm32mp1-clks.h> diff --git a/plat/ti/k3/board/generic/board.mk b/plat/ti/k3/board/generic/board.mk index a342214540..ef74cd64ca 100644 --- a/plat/ti/k3/board/generic/board.mk +++ b/plat/ti/k3/board/generic/board.mk @@ -13,5 +13,12 @@ $(eval $(call add_define,PRELOADED_BL33_BASE)) K3_HW_CONFIG_BASE ?= 0x82000000 $(eval $(call add_define,K3_HW_CONFIG_BASE)) +# Define sec_proxy usage as the full prioritized communication scheme +K3_SEC_PROXY_LITE := 0 +$(eval $(call add_define,K3_SEC_PROXY_LITE)) + +# System coherency is managed in hardware +USE_COHERENT_MEM := 1 + PLAT_INCLUDES += \ -Iplat/ti/k3/board/generic/include \ diff --git a/plat/ti/k3/board/lite/board.mk b/plat/ti/k3/board/lite/board.mk new file mode 100644 index 0000000000..76246be47c --- /dev/null +++ b/plat/ti/k3/board/lite/board.mk @@ -0,0 +1,24 @@ +# +# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL32_BASE ?= 0x9e800000 +$(eval $(call add_define,BL32_BASE)) + +PRELOADED_BL33_BASE ?= 0x80080000 +$(eval $(call add_define,PRELOADED_BL33_BASE)) + +K3_HW_CONFIG_BASE ?= 0x82000000 +$(eval $(call add_define,K3_HW_CONFIG_BASE)) + +# Define sec_proxy usage as the lite version +K3_SEC_PROXY_LITE := 1 +$(eval $(call add_define,K3_SEC_PROXY_LITE)) + +# We dont have system level coherency capability +USE_COHERENT_MEM := 0 + +PLAT_INCLUDES += \ + -Iplat/ti/k3/board/lite/include \ diff --git a/plat/ti/k3/board/lite/include/board_def.h b/plat/ti/k3/board/lite/include/board_def.h new file mode 100644 index 0000000000..7c7ea62c10 --- /dev/null +++ b/plat/ti/k3/board/lite/include/board_def.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BOARD_DEF_H +#define BOARD_DEF_H + +#include <lib/utils_def.h> + +/* The ports must be in order and contiguous */ +#define K3_CLUSTER0_CORE_COUNT U(4) +#define K3_CLUSTER1_CORE_COUNT U(0) +#define K3_CLUSTER2_CORE_COUNT U(0) +#define K3_CLUSTER3_CORE_COUNT U(0) + +/* + * This RAM will be used for the bootloader including code, bss, and stacks. + * It may need to be increased if BL31 grows in size. + * Current computation assumes data structures necessary for GIC and ARM for + * a single cluster of 4 processor. + */ +#define SEC_SRAM_BASE 0x70000000 /* Base of SRAM */ +#define SEC_SRAM_SIZE 0x0001a000 /* 104k */ + +#define PLAT_MAX_OFF_STATE U(2) +#define PLAT_MAX_RET_STATE U(1) + +#define PLAT_PROC_START_ID 32 +#define PLAT_PROC_DEVICE_START_ID 135 +#define PLAT_CLUSTER_DEVICE_START_ID 134 + +#endif /* BOARD_DEF_H */ diff --git a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c index ee1eecf789..a0bfdee367 100644 --- a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c +++ b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c @@ -97,11 +97,16 @@ static struct k3_sec_proxy_mbox spm = { .data_end_offset = 0x3C, }, .threads = { +#if !K3_SEC_PROXY_LITE SP_THREAD(SP_NOTIFY), SP_THREAD(SP_RESPONSE), SP_THREAD(SP_HIGH_PRIORITY), SP_THREAD(SP_LOW_PRIORITY), SP_THREAD(SP_NOTIFY_RESP), +#else + SP_THREAD(SP_RESPONSE), + SP_THREAD(SP_HIGH_PRIORITY), +#endif /* K3_SEC_PROXY_LITE */ }, }; @@ -261,9 +266,14 @@ int k3_sec_proxy_send(enum k3_sec_proxy_chan_id id, const struct k3_sec_proxy_ms /* * 'data_reg' indicates next register to write. If we did not already * write on tx complete reg(last reg), we must do so for transmit + * In addition, we also need to make sure all intermediate data + * registers(if any required), are reset to 0 for TISCI backward + * compatibility to be maintained. */ - if (data_reg <= spm.desc.data_end_offset) - mmio_write_32(spt->data + spm.desc.data_end_offset, 0); + while (data_reg <= spm.desc.data_end_offset) { + mmio_write_32(spt->data + data_reg, 0); + data_reg += sizeof(uint32_t); + } VERBOSE("Message successfully sent on thread %s\n", spt->name); diff --git a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h index 6c4f5dfffa..f4b0b4bace 100644 --- a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h +++ b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h @@ -16,13 +16,28 @@ * enum k3_sec_proxy_chan_id - Secure Proxy thread IDs * * These the available IDs used in k3_sec_proxy_{send,recv}() + * There are two schemes we use: + * * if K3_SEC_PROXY_LITE = 1, we just have two threads to talk + * * if K3_SEC_PROXY_LITE = 0, we have the full fledged + * communication scheme available. */ enum k3_sec_proxy_chan_id { +#if !K3_SEC_PROXY_LITE SP_NOTIFY = 0, SP_RESPONSE, SP_HIGH_PRIORITY, SP_LOW_PRIORITY, SP_NOTIFY_RESP, +#else + SP_RESPONSE = 8, + /* + * Note: TISCI documentation indicates "low priority", but in reality + * with a single thread, there is no low or high priority.. This usage + * is more appropriate for TF-A since we can reduce the churn as a + * result. + */ + SP_HIGH_PRIORITY, +#endif /* K3_SEC_PROXY_LITE */ }; /** diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c index e390efee6c..2c3313c43e 100644 --- a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c +++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c @@ -1163,6 +1163,7 @@ int ti_sci_core_reboot(void) ERROR("Message alloc failed (%d)\n", ret); return ret; } + req.domain = TI_SCI_DOMAIN_FULL_SOC_RESET; ret = ti_sci_do_xfer(&xfer); if (ret) { diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h b/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h index 2d23f9a9cf..310bf459d2 100644 --- a/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h +++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h @@ -95,12 +95,15 @@ struct ti_sci_msg_resp_version { /** * struct ti_sci_msg_req_reboot - Reboot the SoC * @hdr: Generic Header + * @domain: Domain to be reset, 0 for full SoC reboot * * Request type is TI_SCI_MSG_SYS_RESET, responded with a generic * ACK/NACK message. */ struct ti_sci_msg_req_reboot { struct ti_sci_msg_hdr hdr; +#define TI_SCI_DOMAIN_FULL_SOC_RESET 0x0 + uint8_t domain; } __packed; /** diff --git a/plat/ti/k3/common/k3_bl31_setup.c b/plat/ti/k3/common/k3_bl31_setup.c index 8bd7362923..ac4e60e4d1 100644 --- a/plat/ti/k3/common/k3_bl31_setup.c +++ b/plat/ti/k3/common/k3_bl31_setup.c @@ -13,6 +13,7 @@ #include <arch_helpers.h> #include <common/bl_common.h> #include <common/debug.h> +#include <lib/mmio.h> #include <lib/xlat_tables/xlat_tables_v2.h> #include <k3_console.h> @@ -23,6 +24,7 @@ const mmap_region_t plat_k3_mmap[] = { MAP_REGION_FLAT(K3_USART_BASE, K3_USART_SIZE, MT_DEVICE | MT_RW | MT_SECURE), MAP_REGION_FLAT(K3_GIC_BASE, K3_GIC_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(K3_GTC_BASE, K3_GTC_SIZE, MT_DEVICE | MT_RW | MT_SECURE), MAP_REGION_FLAT(SEC_PROXY_RT_BASE, SEC_PROXY_RT_SIZE, MT_DEVICE | MT_RW | MT_SECURE), MAP_REGION_FLAT(SEC_PROXY_SCFG_BASE, SEC_PROXY_SCFG_SIZE, MT_DEVICE | MT_RW | MT_SECURE), MAP_REGION_FLAT(SEC_PROXY_DATA_BASE, SEC_PROXY_DATA_SIZE, MT_DEVICE | MT_RW | MT_SECURE), @@ -127,6 +129,38 @@ void platform_mem_init(void) unsigned int plat_get_syscnt_freq2(void) { + uint32_t gtc_freq; + uint32_t gtc_ctrl; + + /* Lets try and provide basic diagnostics - cost is low */ + gtc_ctrl = mmio_read_32(K3_GTC_BASE + K3_GTC_CNTCR_OFFSET); + /* Did the bootloader fail to enable timer and OS guys are confused? */ + if ((gtc_ctrl & K3_GTC_CNTCR_EN_MASK) == 0U) { + ERROR("GTC is disabled! Timekeeping broken. Fix Bootloader\n"); + } + /* + * If debug will not pause time, we will have issues like + * drivers timing out while debugging, in cases of OS like Linux, + * RCU stall errors, which can be hard to differentiate vs real issues. + */ + if ((gtc_ctrl & K3_GTC_CNTCR_HDBG_MASK) == 0U) { + WARN("GTC: Debug access doesn't stop time. Fix Bootloader\n"); + } + + gtc_freq = mmio_read_32(K3_GTC_BASE + K3_GTC_CNTFID0_OFFSET); + /* Many older bootloaders may have missed programming FID0 register */ + if (gtc_freq != 0U) { + return gtc_freq; + } + + /* + * We could have just warned about this, but this can have serious + * hard to debug side effects if we are NOT sure what the actual + * frequency is. Lets make sure people don't miss this. + */ + ERROR("GTC_CNTFID0 is 0! Assuming %d Hz. Fix Bootloader\n", + SYS_COUNTER_FREQ_IN_TICKS); + return SYS_COUNTER_FREQ_IN_TICKS; } diff --git a/plat/ti/k3/common/plat_common.mk b/plat/ti/k3/common/plat_common.mk index c00262bcff..ab7366b7e2 100644 --- a/plat/ti/k3/common/plat_common.mk +++ b/plat/ti/k3/common/plat_common.mk @@ -11,9 +11,8 @@ COLD_BOOT_SINGLE_CPU := 1 # We can choose where a core starts executing PROGRAMMABLE_RESET_ADDRESS:= 1 -# System coherency is managed in hardware +# ARM coherency is managed in hardware WARMBOOT_ENABLE_DCACHE_EARLY := 1 -USE_COHERENT_MEM := 1 # A53 erratum for SoC. (enable them all) ERRATA_A53_826319 := 1 @@ -21,9 +20,11 @@ ERRATA_A53_835769 := 1 ERRATA_A53_836870 := 1 ERRATA_A53_843419 := 1 ERRATA_A53_855873 := 1 +ERRATA_A53_1530924 := 1 # A72 Erratum for SoC ERRATA_A72_859971 := 1 +ERRATA_A72_1319367 := 1 CRASH_REPORTING := 1 HANDLE_EA_EL3_FIRST := 1 diff --git a/plat/ti/k3/include/platform_def.h b/plat/ti/k3/include/platform_def.h index 98db626e24..f12fb0b211 100644 --- a/plat/ti/k3/include/platform_def.h +++ b/plat/ti/k3/include/platform_def.h @@ -150,15 +150,33 @@ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \ GIC_INTR_CFG_EDGE) + +#define K3_GTC_BASE 0x00A90000 +/* We just need 20 byte offset, but simpler to just remap the 64K page in */ +#define K3_GTC_SIZE 0x10000 +#define K3_GTC_CNTCR_OFFSET 0x00 +#define K3_GTC_CNTCR_EN_MASK 0x01 +#define K3_GTC_CNTCR_HDBG_MASK 0x02 +#define K3_GTC_CNTFID0_OFFSET 0x20 + #define K3_GIC_BASE 0x01800000 #define K3_GIC_SIZE 0x200000 +#if !K3_SEC_PROXY_LITE #define SEC_PROXY_DATA_BASE 0x32C00000 #define SEC_PROXY_DATA_SIZE 0x80000 #define SEC_PROXY_SCFG_BASE 0x32800000 #define SEC_PROXY_SCFG_SIZE 0x80000 #define SEC_PROXY_RT_BASE 0x32400000 #define SEC_PROXY_RT_SIZE 0x80000 +#else +#define SEC_PROXY_DATA_BASE 0x4D000000 +#define SEC_PROXY_DATA_SIZE 0x80000 +#define SEC_PROXY_SCFG_BASE 0x4A400000 +#define SEC_PROXY_SCFG_SIZE 0x80000 +#define SEC_PROXY_RT_BASE 0x4A600000 +#define SEC_PROXY_RT_SIZE 0x80000 +#endif /* K3_SEC_PROXY_LITE */ #define SEC_PROXY_TIMEOUT_US 1000000 #define SEC_PROXY_MAX_MESSAGE_SIZE 56 diff --git a/plat/xilinx/common/pm_service/pm_ipi.c b/plat/xilinx/common/pm_service/pm_ipi.c index c83d25b0d9..5dcceaea25 100644 --- a/plat/xilinx/common/pm_service/pm_ipi.c +++ b/plat/xilinx/common/pm_service/pm_ipi.c @@ -18,6 +18,8 @@ #include "pm_ipi.h" +#define ERROR_CODE_MASK 0xFFFFU + DEFINE_BAKERY_LOCK(pm_secure_lock); /** @@ -230,7 +232,7 @@ enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc, if (ret != PM_RET_SUCCESS) goto unlock; - ret = pm_ipi_buff_read(proc, value, count); + ret = ERROR_CODE_MASK & (pm_ipi_buff_read(proc, value, count)); unlock: bakery_lock_release(&pm_secure_lock); diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c index 03b7fbbb47..5e870ff5f2 100644 --- a/plat/xilinx/versal/bl31_versal_setup.c +++ b/plat/xilinx/versal/bl31_versal_setup.c @@ -34,8 +34,9 @@ entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) { assert(sec_state_is_valid(type)); - if (type == NON_SECURE) + if (type == NON_SECURE) { return &bl33_image_ep_info; + } return &bl32_image_ep_info; } @@ -68,8 +69,9 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, VERSAL_UART_CLOCK, VERSAL_UART_BAUDRATE, &versal_runtime_console); - if (rc == 0) + if (rc == 0) { panic(); + } console_set_scope(&versal_runtime_console, CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME); @@ -97,7 +99,7 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, enum fsbl_handoff ret = fsbl_atf_handover(&bl32_image_ep_info, &bl33_image_ep_info, atf_handoff_addr); - if (ret == FSBL_HANDOFF_NO_STRUCT) { + if (ret == FSBL_HANDOFF_NO_STRUCT || ret == FSBL_HANDOFF_INVAL_STRUCT) { bl31_set_default_config(); } else if (ret != FSBL_HANDOFF_SUCCESS) { panic(); diff --git a/plat/xilinx/versal/plat_psci.c b/plat/xilinx/versal/plat_psci.c index 39550858ad..fda42dfda8 100644 --- a/plat/xilinx/versal/plat_psci.c +++ b/plat/xilinx/versal/plat_psci.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -59,7 +59,9 @@ static void versal_pwr_domain_suspend(const psci_power_state_t *target_state) plat_versal_gic_cpuif_disable(); - plat_versal_gic_save(); + if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) { + plat_versal_gic_save(); + } state = target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE ? PM_STATE_SUSPEND_TO_RAM : PM_STATE_CPU_IDLE; @@ -99,11 +101,9 @@ static void versal_pwr_domain_suspend_finish( /* APU was turned off, so restore GIC context */ if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) { plat_versal_gic_resume(); - plat_versal_gic_cpuif_enable(); - } else { - plat_versal_gic_cpuif_enable(); - plat_versal_gic_pcpu_init(); } + + plat_versal_gic_cpuif_enable(); } void versal_pwr_domain_on_finish(const psci_power_state_t *target_state) diff --git a/plat/xilinx/versal/plat_versal.c b/plat/xilinx/versal/plat_versal.c index a080a76a95..107eae66b1 100644 --- a/plat/xilinx/versal/plat_versal.c +++ b/plat/xilinx/versal/plat_versal.c @@ -9,11 +9,13 @@ int plat_core_pos_by_mpidr(u_register_t mpidr) { - if (mpidr & MPIDR_CLUSTER_MASK) + if (mpidr & MPIDR_CLUSTER_MASK) { return -1; + } - if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT) + if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT) { return -1; + } return versal_calc_core_pos(mpidr); } diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index dbe94e6249..3cdd9d051c 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Xilinx, Inc. All rights reserved. + * Copyright (c) 2019-2020, Xilinx, Inc. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -14,6 +14,7 @@ #include <plat/common/platform.h> #include "pm_api_sys.h" #include "pm_client.h" +#include "pm_defs.h" /********************************************************************* * Target module IDs macros @@ -84,6 +85,22 @@ enum pm_ret_status pm_get_api_version(unsigned int *version) } /** + * pm_init_finalize() - Call to notify PMC PM firmware that master has power + * management enabled and that it has finished its + * initialization + * + * @return Status returned by the PMU firmware + */ +enum pm_ret_status pm_init_finalize(void) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, PM_INIT_FINALIZE); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** * pm_self_suspend() - PM call for processor to suspend itself * @nid Node id of the processor or subsystem * @latency Requested maximum wakeup latency (not supported) @@ -554,6 +571,22 @@ enum pm_ret_status pm_clock_get_parent(uint32_t clk_id, uint32_t *parent) return pm_ipi_send_sync(primary_proc, payload, parent, 1); } +/** + * pm_clock_get_rate() - Get the rate value for the clock + * @clk_id Clock ID + * @rate: Buffer to store clock rate value + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_clock_get_rate(uint32_t clk_id, uint32_t *clk_rate) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_CLOCK_GETRATE, clk_id); + + return pm_ipi_send_sync(primary_proc, payload, clk_rate, 2); +} /** * pm_pll_set_param() - Set PLL parameter @@ -689,12 +722,31 @@ enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype) enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t *data) { + uint32_t ret; + uint32_t version; uint32_t payload[PAYLOAD_ARG_CNT]; + uint32_t fw_api_version; /* Send request to the PMC */ PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, PM_QUERY_DATA, qid, arg1, arg2, arg3); - return pm_ipi_send_sync(primary_proc, payload, data, 4); + + ret = pm_feature_check(PM_QUERY_DATA, &version); + if (PM_RET_SUCCESS == ret) { + fw_api_version = version & 0xFFFF ; + if ((2U == fw_api_version) && + ((XPM_QID_CLOCK_GET_NAME == qid) || + (XPM_QID_PINCTRL_GET_FUNCTION_NAME == qid))) { + ret = pm_ipi_send_sync(primary_proc, payload, data, 8); + ret = data[0]; + data[0] = data[1]; + data[1] = data[2]; + data[2] = data[3]; + } else { + ret = pm_ipi_send_sync(primary_proc, payload, data, 4); + } + } + return ret; } /** * pm_api_ioctl() - PM IOCTL API for device control and configs @@ -780,7 +832,7 @@ enum pm_ret_status pm_feature_check(uint32_t api_id, unsigned int *version) switch (api_id) { case PM_GET_CALLBACK_DATA: case PM_GET_TRUSTZONE_VERSION: - case PM_INIT_FINALIZE: + case PM_LOAD_PDI: *version = (PM_API_BASE_VERSION << 16); return PM_RET_SUCCESS; case PM_GET_API_VERSION: @@ -798,6 +850,7 @@ enum pm_ret_status pm_feature_check(uint32_t api_id, unsigned int *version) case PM_SET_REQUIREMENT: case PM_RESET_ASSERT: case PM_RESET_GET_STATUS: + case PM_GET_CHIPID: case PM_PINCTRL_REQUEST: case PM_PINCTRL_RELEASE: case PM_PINCTRL_GET_FUNCTION: @@ -805,7 +858,6 @@ enum pm_ret_status pm_feature_check(uint32_t api_id, unsigned int *version) case PM_PINCTRL_CONFIG_PARAM_GET: case PM_PINCTRL_CONFIG_PARAM_SET: case PM_IOCTL: - case PM_QUERY_DATA: case PM_CLOCK_ENABLE: case PM_CLOCK_DISABLE: case PM_CLOCK_GETSTATE: @@ -813,16 +865,20 @@ enum pm_ret_status pm_feature_check(uint32_t api_id, unsigned int *version) case PM_CLOCK_GETDIVIDER: case PM_CLOCK_SETPARENT: case PM_CLOCK_GETPARENT: + case PM_CLOCK_GETRATE: case PM_PLL_SET_PARAMETER: case PM_PLL_GET_PARAMETER: case PM_PLL_SET_MODE: case PM_PLL_GET_MODE: case PM_FEATURE_CHECK: + case PM_INIT_FINALIZE: + case PM_SET_MAX_LATENCY: + case PM_REGISTER_NOTIFIER: *version = (PM_API_BASE_VERSION << 16); break; - case PM_LOAD_PDI: - *version = (PM_API_BASE_VERSION << 16); - return PM_RET_SUCCESS; + case PM_QUERY_DATA: + *version = (PM_API_QUERY_DATA_VERSION << 16); + break; default: *version = 0U; return PM_RET_ERROR_NOFEATURE; @@ -883,3 +939,45 @@ enum pm_ret_status pm_get_op_characteristic(uint32_t device_id, device_id, type); return pm_ipi_send_sync(primary_proc, payload, result, 1); } + +/** + * pm_set_max_latency() - PM call to change in the maximum wake-up latency + * requirements for a specific device currently + * used by that CPU. + * @device_id Device ID + * @latency Latency value + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_set_max_latency(uint32_t device_id, uint32_t latency) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_SET_MAX_LATENCY, + device_id, latency); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_register_notifier() - PM call to register a subsystem to be notified + * about the device event + * @device_id Device ID for the Node to which the event is related + * @event Event in question + * @wake Wake subsystem upon capturing the event if value 1 + * @enable Enable the registration for value 1, disable for value 0 + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_register_notifier(uint32_t device_id, uint32_t event, + uint32_t wake, uint32_t enable) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, PM_REGISTER_NOTIFIER, + device_id, event, wake, enable); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h index 4de592a2f4..84867b638c 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.h +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Xilinx, Inc. All rights reserved. + * Copyright (c) 2019-2020, Xilinx, Inc. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -15,6 +15,7 @@ **********************************************************/ enum pm_ret_status pm_get_api_version(unsigned int *version); +enum pm_ret_status pm_init_finalize(void); enum pm_ret_status pm_self_suspend(uint32_t nid, unsigned int latency, unsigned int state, @@ -52,6 +53,7 @@ enum pm_ret_status pm_clock_set_divider(uint32_t clk_id, uint32_t divider); enum pm_ret_status pm_clock_get_divider(uint32_t clk_id, uint32_t *divider); enum pm_ret_status pm_clock_set_parent(uint32_t clk_id, uint32_t parent); enum pm_ret_status pm_clock_get_parent(uint32_t clk_id, uint32_t *parent); +enum pm_ret_status pm_clock_get_rate(uint32_t clk_id, uint32_t *clk_rate); enum pm_ret_status pm_pll_set_param(uint32_t clk_id, uint32_t param, uint32_t value); enum pm_ret_status pm_pll_get_param(uint32_t clk_id, uint32_t param, @@ -72,4 +74,7 @@ enum pm_ret_status pm_load_pdi(uint32_t src, uint32_t address_low, enum pm_ret_status pm_get_op_characteristic(uint32_t device_id, enum pm_opchar_type type, uint32_t *result); +enum pm_ret_status pm_set_max_latency(uint32_t device_id, uint32_t latency); +enum pm_ret_status pm_register_notifier(uint32_t device_id, uint32_t event, + uint32_t wake, uint32_t enable); #endif /* PM_API_SYS_H */ diff --git a/plat/xilinx/versal/pm_service/pm_client.c b/plat/xilinx/versal/pm_service/pm_client.c index 5b47838e90..9ab921ee7c 100644 --- a/plat/xilinx/versal/pm_service/pm_client.c +++ b/plat/xilinx/versal/pm_service/pm_client.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Xilinx, Inc. All rights reserved. + * Copyright (c) 2019-2020, Xilinx, Inc. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -113,8 +113,9 @@ static enum pm_device_node_idx irq_to_pm_node_idx(unsigned int irq) /** * pm_client_set_wakeup_sources - Set all devices with enabled interrupts as * wake sources in the LibPM. + * @node_id: Node id of processor */ -static void pm_client_set_wakeup_sources(void) +static void pm_client_set_wakeup_sources(uint32_t node_id) { uint32_t reg_num; uint32_t device_id; @@ -147,7 +148,7 @@ static void pm_client_set_wakeup_sources(void) (!pm_wakeup_nodes_set[node_idx])) { /* Get device ID from node index */ device_id = PERIPH_DEVID(node_idx); - ret = pm_set_wakeup_source(XPM_DEVID_ACPU_0, + ret = pm_set_wakeup_source(node_id, device_id, 1); pm_wakeup_nodes_set[node_idx] = !ret; } @@ -167,7 +168,7 @@ void pm_client_suspend(const struct pm_proc *proc, unsigned int state) bakery_lock_get(&pm_client_secure_lock); if (state == PM_STATE_SUSPEND_TO_RAM) - pm_client_set_wakeup_sources(); + pm_client_set_wakeup_sources(proc->node_id); /* Set powerdown request */ mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) | diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index 966b00bb50..793f750091 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Xilinx, Inc. All rights reserved. + * Copyright (c) 2019-2020, Xilinx, Inc. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -39,10 +39,13 @@ /* PM API Versions */ #define PM_API_BASE_VERSION 1U +#define PM_API_QUERY_DATA_VERSION 2U + /* PM API ids */ #define PM_GET_API_VERSION 1U #define PM_GET_DEVICE_STATUS 3U #define PM_GET_OP_CHARACTERISTIC 4U +#define PM_REGISTER_NOTIFIER 5U #define PM_REQ_SUSPEND 6U #define PM_SELF_SUSPEND 7U #define PM_FORCE_POWERDOWN 8U @@ -53,6 +56,7 @@ #define PM_REQUEST_DEVICE 13U #define PM_RELEASE_DEVICE 14U #define PM_SET_REQUIREMENT 15U +#define PM_SET_MAX_LATENCY 16U #define PM_RESET_ASSERT 17U #define PM_RESET_GET_STATUS 18U #define PM_INIT_FINALIZE 21U @@ -163,4 +167,25 @@ enum pm_ret_status { PM_RET_ERROR_TIMEOUT = 2006, PM_RET_ERROR_NODE_USED = 2007 }; + +/** + * Qids + */ +enum pm_query_id { + XPM_QID_INVALID, + XPM_QID_CLOCK_GET_NAME, + XPM_QID_CLOCK_GET_TOPOLOGY, + XPM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS, + XPM_QID_CLOCK_GET_MUXSOURCES, + XPM_QID_CLOCK_GET_ATTRIBUTES, + XPM_QID_PINCTRL_GET_NUM_PINS, + XPM_QID_PINCTRL_GET_NUM_FUNCTIONS, + XPM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS, + XPM_QID_PINCTRL_GET_FUNCTION_NAME, + XPM_QID_PINCTRL_GET_FUNCTION_GROUPS, + XPM_QID_PINCTRL_GET_PIN_GROUPS, + XPM_QID_CLOCK_GET_NUM_CLOCKS, + XPM_QID_CLOCK_GET_MAX_DIVISOR, + XPM_QID_PLD_GET_PARENT, +}; #endif /* PM_DEFS_H */ diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c index 45b2803704..2ed6d27015 100644 --- a/plat/xilinx/versal/pm_service/pm_svc_main.c +++ b/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -159,7 +159,8 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, } case PM_INIT_FINALIZE: - SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS); + ret = pm_init_finalize(); + SMC_RET1(handle, (uint64_t)ret); case PM_GET_CALLBACK_DATA: { @@ -214,14 +215,15 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, case PM_QUERY_DATA: { - uint32_t data[4] = { 0 }; + uint32_t data[8] = { 0 }; ret = pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2], - pm_arg[3], data); + pm_arg[3], data); + SMC_RET2(handle, (uint64_t)ret | ((uint64_t)data[0] << 32), - (uint64_t)data[1] | ((uint64_t)data[2] << 32)); - } + (uint64_t)data[1] | ((uint64_t)data[2] << 32)); + } case PM_CLOCK_ENABLE: ret = pm_clock_enable(pm_arg[0]); SMC_RET1(handle, (uint64_t)ret); @@ -262,6 +264,15 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); } + case PM_CLOCK_GETRATE: + { + uint32_t rate[2] = { 0 }; + + ret = pm_clock_get_rate(pm_arg[0], rate); + SMC_RET2(handle, (uint64_t)ret | ((uint64_t)rate[0] << 32), + rate[1]); + } + case PM_PLL_SET_PARAMETER: ret = pm_pll_set_param(pm_arg[0], pm_arg[1], pm_arg[2]); SMC_RET1(handle, (uint64_t)ret); @@ -321,6 +332,18 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, SMC_RET1(handle, (uint64_t)ret | ((uint64_t)result << 32)); } + case PM_SET_MAX_LATENCY: + { + ret = pm_set_max_latency(pm_arg[0], pm_arg[1]); + SMC_RET1(handle, (uint64_t)ret); + } + + case PM_REGISTER_NOTIFIER: + { + ret = pm_register_notifier(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]); + SMC_RET1(handle, (uint64_t)ret); + } + default: WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid); SMC_RET1(handle, SMC_UNK); diff --git a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c index b6d8770cc9..d4cd7f65b8 100644 --- a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c +++ b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c @@ -32,8 +32,9 @@ entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) { assert(sec_state_is_valid(type)); - if (type == NON_SECURE) + if (type == NON_SECURE) { return &bl33_image_ep_info; + } return &bl32_image_ep_info; } @@ -99,14 +100,18 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, enum fsbl_handoff ret = fsbl_atf_handover(&bl32_image_ep_info, &bl33_image_ep_info, atf_handoff_addr); - if (ret == FSBL_HANDOFF_NO_STRUCT) + if (ret == FSBL_HANDOFF_NO_STRUCT) { bl31_set_default_config(); - else if (ret != FSBL_HANDOFF_SUCCESS) + } else if (ret != FSBL_HANDOFF_SUCCESS) { panic(); + } + } + if (bl32_image_ep_info.pc) { + VERBOSE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc); + } + if (bl33_image_ep_info.pc) { + VERBOSE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc); } - - NOTICE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc); - NOTICE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc); } /* Enable the test setup */ @@ -134,12 +139,14 @@ static interrupt_type_handler_t type_el3_interrupt_table[MAX_INTR_EL3]; int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler) { /* Validate 'handler' and 'id' parameters */ - if (!handler || id >= MAX_INTR_EL3) + if (!handler || id >= MAX_INTR_EL3) { return -EINVAL; + } /* Check if a handler has already been registered */ - if (type_el3_interrupt_table[id]) + if (type_el3_interrupt_table[id]) { return -EALREADY; + } type_el3_interrupt_table[id] = handler; @@ -154,8 +161,9 @@ static uint64_t rdo_el3_interrupt_handler(uint32_t id, uint32_t flags, intr_id = plat_ic_get_pending_interrupt_id(); handler = type_el3_interrupt_table[intr_id]; - if (handler != NULL) + if (handler != NULL) { handler(intr_id, flags, handle, cookie); + } return 0; } @@ -178,8 +186,9 @@ void bl31_plat_runtime_setup(void) set_interrupt_rm_flag(flags, NON_SECURE); rc = register_interrupt_type_handler(INTR_TYPE_EL3, rdo_el3_interrupt_handler, flags); - if (rc) + if (rc) { panic(); + } #endif } diff --git a/plat/xilinx/zynqmp/include/zynqmp_def.h b/plat/xilinx/zynqmp/include/zynqmp_def.h index 5e7254e5c5..f47463000d 100644 --- a/plat/xilinx/zynqmp/include/zynqmp_def.h +++ b/plat/xilinx/zynqmp/include/zynqmp_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -341,12 +341,22 @@ #define PGGS_BASEADDR (0xFFD80050U) #define PGGS_NUM_REGS U(4) -/* Warm restart boot health status register and mask */ -#define PM_BOOT_HEALTH_STATUS_REG (GGS_BASEADDR + U(0x10)) +/* PMU GGS4 register 4 is used for warm restart boot health status */ +#define PMU_GLOBAL_GEN_STORAGE4 (GGS_BASEADDR + 0x10) +/* Warm restart boot health status mask */ #define PM_BOOT_HEALTH_STATUS_MASK U(0x01) +/* WDT restart scope shift and mask */ +#define RESTART_SCOPE_SHIFT (3) +#define RESTART_SCOPE_MASK (0x3U << RESTART_SCOPE_SHIFT) /*AFI registers */ #define AFIFM6_WRCTRL U(13) #define FABRIC_WIDTH U(3) +/* CSUDMA Module Base Address*/ +#define CSUDMA_BASE 0xFFC80000 + +/* RSA-CORE Module Base Address*/ +#define RSA_CORE_BASE 0xFFCE0000 + #endif /* ZYNQMP_DEF_H */ diff --git a/plat/xilinx/zynqmp/plat_zynqmp.c b/plat/xilinx/zynqmp/plat_zynqmp.c index 906ce1b7fe..58a52a3bf1 100644 --- a/plat/xilinx/zynqmp/plat_zynqmp.c +++ b/plat/xilinx/zynqmp/plat_zynqmp.c @@ -9,11 +9,13 @@ int plat_core_pos_by_mpidr(u_register_t mpidr) { - if (mpidr & MPIDR_CLUSTER_MASK) + if (mpidr & MPIDR_CLUSTER_MASK) { return -1; + } - if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT) + if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT) { return -1; + } return zynqmp_calc_core_pos(mpidr); } diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk index 44f20f69f6..1cd168f7dd 100644 --- a/plat/xilinx/zynqmp/platform.mk +++ b/plat/xilinx/zynqmp/platform.mk @@ -59,13 +59,14 @@ PLAT_INCLUDES := -Iinclude/plat/arm/common/ \ -Iplat/xilinx/zynqmp/include/ \ -Iplat/xilinx/zynqmp/pm_service/ \ +# Include GICv2 driver files +include drivers/arm/gic/v2/gicv2.mk + PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \ lib/xlat_tables/aarch64/xlat_tables.c \ drivers/delay_timer/delay_timer.c \ drivers/delay_timer/generic_delay_timer.c \ - drivers/arm/gic/common/gic_common.c \ - drivers/arm/gic/v2/gicv2_main.c \ - drivers/arm/gic/v2/gicv2_helpers.c \ + ${GICV2_SOURCES} \ drivers/cadence/uart/aarch64/cdns_console.S \ plat/arm/common/arm_cci.c \ plat/arm/common/arm_common.c \ @@ -95,6 +96,8 @@ BL31_SOURCES += drivers/arm/cci/cci.c \ plat/xilinx/zynqmp/pm_service/pm_api_clock.c \ plat/xilinx/zynqmp/pm_service/pm_client.c +BL31_CPPFLAGS += -fno-jump-tables + ifneq (${RESET_TO_BL31},1) $(error "Using BL31 as the reset vector is only one option supported on ZynqMP. Please set RESET_TO_BL31 to 1.") endif diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c index 852f92763c..0cc517ec9e 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -129,12 +129,26 @@ .div = NA_DIV, \ } -#define GENERIC_DIV(id) \ +#define GENERIC_DIV1 \ { \ - .type = TYPE_DIV##id, \ - .offset = PERIPH_DIV##id##_SHIFT, \ - .width = PERIPH_DIV##id##_WIDTH, \ + .type = TYPE_DIV1, \ + .offset = PERIPH_DIV1_SHIFT, \ + .width = PERIPH_DIV1_WIDTH, \ + .clkflags = CLK_SET_RATE_NO_REPARENT | \ + CLK_IS_BASIC, \ + .typeflags = CLK_DIVIDER_ONE_BASED | \ + CLK_DIVIDER_ALLOW_ZERO, \ + .mult = NA_MULT, \ + .div = NA_DIV, \ + } + +#define GENERIC_DIV2 \ + { \ + .type = TYPE_DIV2, \ + .offset = PERIPH_DIV2_SHIFT, \ + .width = PERIPH_DIV2_WIDTH, \ .clkflags = CLK_SET_RATE_NO_REPARENT | \ + CLK_SET_RATE_PARENT | \ CLK_IS_BASIC, \ .typeflags = CLK_DIVIDER_ONE_BASED | \ CLK_DIVIDER_ALLOW_ZERO, \ @@ -340,25 +354,25 @@ static struct pm_clock_node acpu_nodes[] = { static struct pm_clock_node generic_mux_div_nodes[] = { GENERIC_MUX, - GENERIC_DIV(1), + GENERIC_DIV1, }; static struct pm_clock_node generic_mux_div_gate_nodes[] = { GENERIC_MUX, - GENERIC_DIV(1), + GENERIC_DIV1, GENERIC_GATE, }; static struct pm_clock_node generic_mux_div_unused_gate_nodes[] = { GENERIC_MUX, - GENERIC_DIV(1), + GENERIC_DIV1, IGNORE_UNUSED_GATE, }; static struct pm_clock_node generic_mux_div_div_gate_nodes[] = { GENERIC_MUX, - GENERIC_DIV(1), - GENERIC_DIV(2), + GENERIC_DIV1, + GENERIC_DIV2, GENERIC_GATE, }; @@ -410,8 +424,8 @@ static struct pm_clock_node dp_audio_video_ref_nodes[] = { static struct pm_clock_node usb_nodes[] = { GENERIC_MUX, - GENERIC_DIV(1), - GENERIC_DIV(2), + GENERIC_DIV1, + GENERIC_DIV2, { .type = TYPE_GATE, .offset = USB_GATE_SHIFT, @@ -2432,10 +2446,11 @@ enum pm_ret_status pm_api_clock_get_num_clocks(unsigned int *nclocks) * * @return Returns success. In case of error, name data is 0. */ -enum pm_ret_status pm_api_clock_get_name(unsigned int clock_id, char *name) +void pm_api_clock_get_name(unsigned int clock_id, char *name) { if (clock_id == CLK_MAX) - memcpy(name, END_OF_CLK, CLK_NAME_LEN); + memcpy(name, END_OF_CLK, sizeof(END_OF_CLK) > CLK_NAME_LEN ? + CLK_NAME_LEN : sizeof(END_OF_CLK)); else if (!pm_clock_valid(clock_id)) memset(name, 0, CLK_NAME_LEN); else if (clock_id < CLK_MAX_OUTPUT_CLK) @@ -2443,8 +2458,6 @@ enum pm_ret_status pm_api_clock_get_name(unsigned int clock_id, char *name) else memcpy(name, ext_clocks[clock_id - CLK_MAX_OUTPUT_CLK].name, CLK_NAME_LEN); - - return PM_RET_SUCCESS; } /** diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.h b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h index 301ed24b65..5efd63ff57 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.h +++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -294,7 +294,7 @@ struct pm_pll *pm_clock_get_pll(enum clock_id clock_id); struct pm_pll *pm_clock_get_pll_by_related_clk(enum clock_id clock_id); uint8_t pm_clock_has_div(unsigned int clock_id, enum pm_clock_div_id div_id); -enum pm_ret_status pm_api_clock_get_name(unsigned int clock_id, char *name); +void pm_api_clock_get_name(unsigned int clock_id, char *name); enum pm_ret_status pm_api_clock_get_num_clocks(unsigned int *nclocks); enum pm_ret_status pm_api_clock_get_topology(unsigned int clock_id, unsigned int index, diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c index 60e80d907c..f165fb0226 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -282,17 +282,29 @@ static enum pm_ret_status pm_ioctl_sd_set_tapdelay(enum pm_node_id nid, { unsigned int shift; enum pm_ret_status ret; + unsigned int val, mask; - if (nid == NODE_SD_0) + if (nid == NODE_SD_0) { shift = 0; - else if (nid == NODE_SD_1) + mask = ZYNQMP_SD0_DLL_RST_MASK; + } else if (nid == NODE_SD_1) { shift = ZYNQMP_SD_TAP_OFFSET; - else + mask = ZYNQMP_SD1_DLL_RST_MASK; + } else { return PM_RET_ERROR_ARGS; + } - ret = pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_ASSERT); - if (ret != PM_RET_SUCCESS) + ret = pm_mmio_read(ZYNQMP_SD_DLL_CTRL, &val); + if (ret != PM_RET_SUCCESS) { return ret; + } + + if ((val & mask) == 0) { + ret = pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_ASSERT); + if (ret != PM_RET_SUCCESS) { + return ret; + } + } if (type == PM_TAPDELAY_INPUT) { ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY, @@ -300,9 +312,15 @@ static enum pm_ret_status pm_ioctl_sd_set_tapdelay(enum pm_node_id nid, (ZYNQMP_SD_ITAPCHGWIN << shift)); if (ret != PM_RET_SUCCESS) goto reset_release; - ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY, - (ZYNQMP_SD_ITAPDLYENA_MASK << shift), - (ZYNQMP_SD_ITAPDLYENA << shift)); + if (value == 0) + ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY, + (ZYNQMP_SD_ITAPDLYENA_MASK << + shift), 0); + else + ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY, + (ZYNQMP_SD_ITAPDLYENA_MASK << + shift), (ZYNQMP_SD_ITAPDLYENA << + shift)); if (ret != PM_RET_SUCCESS) goto reset_release; ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY, @@ -314,8 +332,7 @@ static enum pm_ret_status pm_ioctl_sd_set_tapdelay(enum pm_node_id nid, (ZYNQMP_SD_ITAPCHGWIN_MASK << shift), 0); } else if (type == PM_TAPDELAY_OUTPUT) { ret = pm_mmio_write(ZYNQMP_SD_OTAP_DLY, - (ZYNQMP_SD_OTAPDLYENA_MASK << shift), - (ZYNQMP_SD_OTAPDLYENA << shift)); + (ZYNQMP_SD_OTAPDLYENA_MASK << shift), 0); if (ret != PM_RET_SUCCESS) goto reset_release; ret = pm_mmio_write(ZYNQMP_SD_OTAP_DLY, @@ -326,7 +343,10 @@ static enum pm_ret_status pm_ioctl_sd_set_tapdelay(enum pm_node_id nid, } reset_release: - pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_RELEASE); + if ((val & mask) == 0) { + (void)pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_RELEASE); + } + return ret; } @@ -575,7 +595,7 @@ static enum pm_ret_status pm_ioctl_ulpi_reset(void) */ static enum pm_ret_status pm_ioctl_set_boot_health_status(unsigned int value) { - return pm_mmio_write(PM_BOOT_HEALTH_STATUS_REG, + return pm_mmio_write(PMU_GLOBAL_GEN_STORAGE4, PM_BOOT_HEALTH_STATUS_MASK, value); } diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c index 4b8dfb6144..9a6b497f33 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c @@ -19,39 +19,6 @@ #include "pm_common.h" #include "pm_ipi.h" -#define PINCTRL_FUNCTION_MASK U(0xFE) -#define PINCTRL_VOLTAGE_STATUS_MASK U(0x01) -#define NFUNCS_PER_PIN U(13) -#define PINCTRL_NUM_MIOS U(78) -#define MAX_PIN_PER_REG U(26) -#define PINCTRL_BANK_ADDR_STEP U(28) - -#define PINCTRL_DRVSTRN0_REG_OFFSET U(0) -#define PINCTRL_DRVSTRN1_REG_OFFSET U(4) -#define PINCTRL_SCHCMOS_REG_OFFSET U(8) -#define PINCTRL_PULLCTRL_REG_OFFSET U(12) -#define PINCTRL_PULLSTAT_REG_OFFSET U(16) -#define PINCTRL_SLEWCTRL_REG_OFFSET U(20) -#define PINCTRL_VOLTAGE_STAT_REG_OFFSET U(24) - -#define IOU_SLCR_BANK1_CTRL5 U(0XFF180164) - -#define PINCTRL_CFG_ADDR_OFFSET(addr, reg, miopin) \ - ((addr) + 4 * PINCTRL_NUM_MIOS + PINCTRL_BANK_ADDR_STEP * \ - ((miopin) / MAX_PIN_PER_REG) + (reg)) - -#define PINCTRL_PIN_OFFSET(_miopin) \ - ((_miopin) - (MAX_PIN_PER_REG * ((_miopin) / MAX_PIN_PER_REG))) - -#define PINCTRL_REGVAL_TO_PIN_CONFIG(_pin, _val) \ - (((_val) >> PINCTRL_PIN_OFFSET(_pin)) & 0x1) - -static uint8_t pm_pinctrl_mux[NFUNCS_PER_PIN] = { - 0x02, 0x04, 0x08, 0x10, 0x18, - 0x00, 0x20, 0x40, 0x60, 0x80, - 0xA0, 0xC0, 0xE0 -}; - struct pinctrl_function { char name[FUNCTION_NAME_LEN]; uint16_t (*groups)[]; @@ -2604,18 +2571,13 @@ enum pm_ret_status pm_api_pinctrl_get_num_func_groups(unsigned int fid, * * This function is used by master to get name of function specified * by given function ID. - * - * @return Returns success. In case of error, name data is 0. */ -enum pm_ret_status pm_api_pinctrl_get_function_name(unsigned int fid, - char *name) +void pm_api_pinctrl_get_function_name(unsigned int fid, char *name) { if (fid >= MAX_FUNCTION) memcpy(name, END_OF_FUNCTION, FUNCTION_NAME_LEN); else memcpy(name, pinctrl_functions[fid].name, FUNCTION_NAME_LEN); - - return PM_RET_SUCCESS; } /** @@ -2713,330 +2675,3 @@ enum pm_ret_status pm_api_pinctrl_get_pin_groups(unsigned int pin, return PM_RET_SUCCESS; } - -/** - * pm_api_pinctrl_get_function() - Read function id set for the given pin - * @pin Pin number - * @nid Node ID of function currently set for given pin - * - * This function provides the function currently set for the given pin. - * - * @return Returns status, either success or error+reason - */ -enum pm_ret_status pm_api_pinctrl_get_function(unsigned int pin, - unsigned int *id) -{ - unsigned int i = 0, j = 0; - enum pm_ret_status ret = PM_RET_SUCCESS; - unsigned int ctrlreg, val, gid; - uint16_t *grps; - - ctrlreg = IOU_SLCR_BASEADDR + 4U * pin; - ret = pm_mmio_read(ctrlreg, &val); - if (ret != PM_RET_SUCCESS) - return ret; - - val &= PINCTRL_FUNCTION_MASK; - - for (i = 0; i < NFUNCS_PER_PIN; i++) - if (val == pm_pinctrl_mux[i]) - break; - - if (i == NFUNCS_PER_PIN) - return PM_RET_ERROR_NOTSUPPORTED; - - gid = *(*zynqmp_pin_groups[pin].groups + i); - - for (i = 0; i < MAX_FUNCTION; i++) { - grps = *pinctrl_functions[i].groups; - if (grps == NULL) - continue; - if (val != pinctrl_functions[i].regval) - continue; - - for (j = 0; grps[j] != (uint16_t)END_OF_GROUPS; j++) { - if (gid == grps[j]) { - *id = i; - goto done; - } - } - } - if (i == MAX_FUNCTION) - ret = PM_RET_ERROR_ARGS; -done: - return ret; -} - -/** - * pm_api_pinctrl_set_function() - Set function id set for the given pin - * @pin Pin number - * @nid Node ID of function to set for given pin - * - * This function provides the function currently set for the given pin. - * - * @return Returns status, either success or error+reason - */ -enum pm_ret_status pm_api_pinctrl_set_function(unsigned int pin, - unsigned int fid) -{ - int i, j; - unsigned int ctrlreg, val; - uint16_t *pgrps, *fgrps; - - ctrlreg = IOU_SLCR_BASEADDR + 4U * pin; - val = pinctrl_functions[fid].regval; - - for (i = 0; i < NFUNCS_PER_PIN; i++) - if (val == pm_pinctrl_mux[i]) - break; - - if (i == NFUNCS_PER_PIN) - return PM_RET_ERROR_NOTSUPPORTED; - - pgrps = *zynqmp_pin_groups[pin].groups; - if (!pgrps) - return PM_RET_ERROR_NOTSUPPORTED; - - fgrps = *pinctrl_functions[fid].groups; - if (!fgrps) - return PM_RET_ERROR_NOTSUPPORTED; - - for (i = 0; fgrps[i] != (uint16_t)END_OF_GROUPS; i++) - for (j = 0; pgrps[j] != (uint16_t)END_OF_GROUPS; j++) - if (fgrps[i] == pgrps[j]) - goto match; - - return PM_RET_ERROR_NOTSUPPORTED; - -match: - return pm_mmio_write(ctrlreg, PINCTRL_FUNCTION_MASK, val); -} - -/** - * pm_api_pinctrl_set_config() - Set configuration parameter for given pin - * @pin: Pin for which configuration is to be set - * @param: Configuration parameter to be set - * @value: Value to be set for configuration parameter - * - * This function sets value of requested configuration parameter for given pin. - * - * @return Returns status, either success or error+reason - */ -enum pm_ret_status pm_api_pinctrl_set_config(unsigned int pin, - unsigned int param, - unsigned int value) -{ - enum pm_ret_status ret; - unsigned int ctrlreg, mask, val, offset; - - if (param >= PINCTRL_CONFIG_MAX) - return PM_RET_ERROR_NOTSUPPORTED; - - if (pin >= PINCTRL_NUM_MIOS) - return PM_RET_ERROR_ARGS; - - mask = 1 << PINCTRL_PIN_OFFSET(pin); - - switch (param) { - case PINCTRL_CONFIG_SLEW_RATE: - if (value != PINCTRL_SLEW_RATE_FAST && - value != PINCTRL_SLEW_RATE_SLOW) - return PM_RET_ERROR_ARGS; - - ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR, - PINCTRL_SLEWCTRL_REG_OFFSET, - pin); - val = value << PINCTRL_PIN_OFFSET(pin); - ret = pm_mmio_write(ctrlreg, mask, val); - break; - case PINCTRL_CONFIG_BIAS_STATUS: - if (value != PINCTRL_BIAS_ENABLE && - value != PINCTRL_BIAS_DISABLE) - return PM_RET_ERROR_ARGS; - - ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR, - PINCTRL_PULLSTAT_REG_OFFSET, - pin); - - offset = PINCTRL_PIN_OFFSET(pin); - if (ctrlreg == IOU_SLCR_BANK1_CTRL5) - offset = (offset < 12U) ? - (offset + 14U) : (offset - 12U); - - val = value << offset; - mask = 1 << offset; - ret = pm_mmio_write(ctrlreg, mask, val); - break; - case PINCTRL_CONFIG_PULL_CTRL: - - if (value != PINCTRL_BIAS_PULL_DOWN && - value != PINCTRL_BIAS_PULL_UP) - return PM_RET_ERROR_ARGS; - - ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR, - PINCTRL_PULLSTAT_REG_OFFSET, - pin); - - offset = PINCTRL_PIN_OFFSET(pin); - if (ctrlreg == IOU_SLCR_BANK1_CTRL5) - offset = (offset < 12U) ? - (offset + 14U) : (offset - 12U); - - val = PINCTRL_BIAS_ENABLE << offset; - ret = pm_mmio_write(ctrlreg, 1 << offset, val); - if (ret != PM_RET_SUCCESS) - return ret; - - ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR, - PINCTRL_PULLCTRL_REG_OFFSET, - pin); - val = value << PINCTRL_PIN_OFFSET(pin); - ret = pm_mmio_write(ctrlreg, mask, val); - break; - case PINCTRL_CONFIG_SCHMITT_CMOS: - if (value != PINCTRL_INPUT_TYPE_CMOS && - value != PINCTRL_INPUT_TYPE_SCHMITT) - return PM_RET_ERROR_ARGS; - - ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR, - PINCTRL_SCHCMOS_REG_OFFSET, - pin); - - val = value << PINCTRL_PIN_OFFSET(pin); - ret = pm_mmio_write(ctrlreg, mask, val); - break; - case PINCTRL_CONFIG_DRIVE_STRENGTH: - if (value > PINCTRL_DRIVE_STRENGTH_12MA) - return PM_RET_ERROR_ARGS; - - ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR, - PINCTRL_DRVSTRN0_REG_OFFSET, - pin); - val = (value >> 1) << PINCTRL_PIN_OFFSET(pin); - ret = pm_mmio_write(ctrlreg, mask, val); - if (ret) - return ret; - - ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR, - PINCTRL_DRVSTRN1_REG_OFFSET, - pin); - val = (value & 0x01U) << PINCTRL_PIN_OFFSET(pin); - ret = pm_mmio_write(ctrlreg, mask, val); - break; - default: - ERROR("Invalid parameter %u\n", param); - ret = PM_RET_ERROR_NOTSUPPORTED; - break; - } - - return ret; -} - -/** - * pm_api_pinctrl_get_config() - Get configuration parameter value for given pin - * @pin: Pin for which configuration is to be read - * @param: Configuration parameter to be read - * @value: buffer to store value of configuration parameter - * - * This function reads value of requested configuration parameter for given pin. - * - * @return Returns status, either success or error+reason - */ -enum pm_ret_status pm_api_pinctrl_get_config(unsigned int pin, - unsigned int param, - unsigned int *value) -{ - enum pm_ret_status ret; - unsigned int ctrlreg, val; - - if (param >= PINCTRL_CONFIG_MAX) - return PM_RET_ERROR_NOTSUPPORTED; - - if (pin >= PINCTRL_NUM_MIOS) - return PM_RET_ERROR_ARGS; - - switch (param) { - case PINCTRL_CONFIG_SLEW_RATE: - ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR, - PINCTRL_SLEWCTRL_REG_OFFSET, - pin); - - ret = pm_mmio_read(ctrlreg, &val); - if (ret != PM_RET_SUCCESS) - return ret; - - *value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val); - break; - case PINCTRL_CONFIG_BIAS_STATUS: - ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR, - PINCTRL_PULLSTAT_REG_OFFSET, - pin); - - ret = pm_mmio_read(ctrlreg, &val); - if (ret) - return ret; - - if (ctrlreg == IOU_SLCR_BANK1_CTRL5) - val = ((val & 0x3FFF) << 12) | ((val >> 14) & 0xFFF); - - *value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val); - break; - case PINCTRL_CONFIG_PULL_CTRL: - - ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR, - PINCTRL_PULLCTRL_REG_OFFSET, - pin); - - ret = pm_mmio_read(ctrlreg, &val); - if (ret) - return ret; - - *value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val); - break; - case PINCTRL_CONFIG_SCHMITT_CMOS: - ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR, - PINCTRL_SCHCMOS_REG_OFFSET, - pin); - - ret = pm_mmio_read(ctrlreg, &val); - if (ret) - return ret; - - *value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val); - break; - case PINCTRL_CONFIG_DRIVE_STRENGTH: - ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR, - PINCTRL_DRVSTRN0_REG_OFFSET, - pin); - ret = pm_mmio_read(ctrlreg, &val); - if (ret) - return ret; - - *value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val) << 1; - - ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR, - PINCTRL_DRVSTRN1_REG_OFFSET, - pin); - ret = pm_mmio_read(ctrlreg, &val); - if (ret) - return ret; - - *value |= PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val); - break; - case PINCTRL_CONFIG_VOLTAGE_STATUS: - ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR, - PINCTRL_VOLTAGE_STAT_REG_OFFSET, - pin); - - ret = pm_mmio_read(ctrlreg, &val); - if (ret) - return ret; - - *value = val & PINCTRL_VOLTAGE_STATUS_MASK; - break; - default: - return PM_RET_ERROR_NOTSUPPORTED; - } - - return PM_RET_SUCCESS; -} diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h index 9923c00ba9..2b8fca3cda 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h +++ b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -709,18 +709,7 @@ enum { #define PINCTRL_DRIVE_STRENGTH_8MA 2U #define PINCTRL_DRIVE_STRENGTH_12MA 3U -enum pm_ret_status pm_api_pinctrl_set_function(unsigned int pin, - unsigned int fid); -enum pm_ret_status pm_api_pinctrl_get_function(unsigned int pin, - unsigned int *id); -enum pm_ret_status pm_api_pinctrl_set_config(unsigned int pin, - unsigned int param, - unsigned int value); -enum pm_ret_status pm_api_pinctrl_get_config(unsigned int pin, - unsigned int param, - unsigned int *value); -enum pm_ret_status pm_api_pinctrl_get_function_name(unsigned int fid, - char *name); +void pm_api_pinctrl_get_function_name(unsigned int fid, char *name); enum pm_ret_status pm_api_pinctrl_get_function_groups(unsigned int fid, unsigned int index, uint16_t *groups); diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c index b1720d9f6c..9a53408fd2 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c @@ -65,6 +65,10 @@ unsigned int pm_get_shutdown_scope(void) PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4); \ } +#define EM_PACK_PAYLOAD1(pl, arg0) { \ + pl[0] = (uint16_t)(0xE) << 16 | (uint16_t)arg0; \ +} + /** * pm_self_suspend() - PM call for processor to suspend itself * @nid Node id of the processor or subsystem @@ -655,7 +659,11 @@ void pm_get_callbackdata(uint32_t *data, size_t count) */ enum pm_ret_status pm_pinctrl_request(unsigned int pin) { - return PM_RET_SUCCESS; + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD2(payload, PM_PINCTRL_REQUEST, pin); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); } /** @@ -668,37 +676,44 @@ enum pm_ret_status pm_pinctrl_request(unsigned int pin) */ enum pm_ret_status pm_pinctrl_release(unsigned int pin) { - return PM_RET_SUCCESS; + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD2(payload, PM_PINCTRL_RELEASE, pin); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); } /** * pm_pinctrl_get_function() - Read function id set for the given pin * @pin Pin number - * @nid Node ID of function currently set for given pin + * @fid ID of function currently set for given pin * * This function provides the function currently set for the given pin. * * @return Returns status, either success or error+reason */ -enum pm_ret_status pm_pinctrl_get_function(unsigned int pin, - enum pm_node_id *nid) +enum pm_ret_status pm_pinctrl_get_function(unsigned int pin, unsigned int *fid) { - return pm_api_pinctrl_get_function(pin, nid); + uint32_t payload[PAYLOAD_ARG_CNT]; + + PM_PACK_PAYLOAD2(payload, PM_PINCTRL_GET_FUNCTION, pin); + return pm_ipi_send_sync(primary_proc, payload, fid, 1); } /** * pm_pinctrl_set_function() - Set function id set for the given pin * @pin Pin number - * @nid Node ID of function to set for given pin - * - * This function provides the function currently set for the given pin. + * @fid ID of function to set for given pin * * @return Returns status, either success or error+reason */ -enum pm_ret_status pm_pinctrl_set_function(unsigned int pin, - enum pm_node_id nid) +enum pm_ret_status pm_pinctrl_set_function(unsigned int pin, unsigned int fid) { - return pm_api_pinctrl_set_function(pin, (unsigned int)nid); + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD3(payload, PM_PINCTRL_SET_FUNCTION, pin, fid); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); } /** @@ -715,24 +730,30 @@ enum pm_ret_status pm_pinctrl_get_config(unsigned int pin, unsigned int param, unsigned int *value) { - return pm_api_pinctrl_get_config(pin, param, value); + uint32_t payload[PAYLOAD_ARG_CNT]; + + PM_PACK_PAYLOAD3(payload, PM_PINCTRL_CONFIG_PARAM_GET, pin, param); + return pm_ipi_send_sync(primary_proc, payload, value, 1); } /** - * pm_pinctrl_set_config() - Read value of requested config param for given pin + * pm_pinctrl_set_config() - Set value of requested config param for given pin * @pin Pin number * @param Parameter to set * @value Parameter value to set * - * This function provides the configuration parameter value for the given pin. - * * @return Returns status, either success or error+reason */ enum pm_ret_status pm_pinctrl_set_config(unsigned int pin, unsigned int param, unsigned int value) { - return pm_api_pinctrl_set_config(pin, param, value); + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD4(payload, PM_PINCTRL_CONFIG_PARAM_SET, pin, param, + value); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); } /** @@ -793,12 +814,10 @@ static enum pm_ret_status pm_clock_get_num_clocks(uint32_t *nclocks) * * This function is used by master to get nmae of clock specified * by given clock ID. - * - * @return Returns status, either success or error+reason */ -static enum pm_ret_status pm_clock_get_name(unsigned int clock_id, char *name) +static void pm_clock_get_name(unsigned int clock_id, char *name) { - return pm_api_clock_get_name(clock_id, name); + pm_api_clock_get_name(clock_id, name); } /** @@ -907,7 +926,13 @@ static enum pm_ret_status pm_clock_gate(unsigned int clock_id, /* Send request to the PMU */ PM_PACK_PAYLOAD2(payload, api_id, clock_id); - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); + status = pm_ipi_send_sync(primary_proc, payload, NULL, 0); + + /* If action fails due to the lack of permissions filter the error */ + if (status == PM_RET_ERROR_ACCESS) + status = PM_RET_SUCCESS; + + return status; } /** @@ -1229,13 +1254,10 @@ static enum pm_ret_status pm_pinctrl_get_num_function_groups(unsigned int fid, * * This function is used by master to get name of function specified * by given function Id - * - * Return: Returns status, either success or error+reason. */ -static enum pm_ret_status pm_pinctrl_get_function_name(unsigned int fid, - char *name) +static void pm_pinctrl_get_function_name(unsigned int fid, char *name) { - return pm_api_pinctrl_get_function_name(fid, name); + pm_api_pinctrl_get_function_name(fid, name); } /** @@ -1295,78 +1317,58 @@ static enum pm_ret_status pm_pinctrl_get_pin_groups(unsigned int pin_id, * @data Returned output data * * This function returns requested data. - * - * @return Returns status, either success or error+reason */ -enum pm_ret_status pm_query_data(enum pm_query_id qid, - unsigned int arg1, - unsigned int arg2, - unsigned int arg3, - unsigned int *data) +void pm_query_data(enum pm_query_id qid, unsigned int arg1, unsigned int arg2, + unsigned int arg3, unsigned int *data) { - enum pm_ret_status ret; - switch (qid) { case PM_QID_CLOCK_GET_NAME: - ret = pm_clock_get_name(arg1, (char *)data); + pm_clock_get_name(arg1, (char *)data); break; case PM_QID_CLOCK_GET_TOPOLOGY: - ret = pm_clock_get_topology(arg1, arg2, &data[1]); - data[0] = (unsigned int)ret; + data[0] = pm_clock_get_topology(arg1, arg2, &data[1]); break; case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS: - ret = pm_clock_get_fixedfactor_params(arg1, &data[1], &data[2]); - data[0] = (unsigned int)ret; + data[0] = pm_clock_get_fixedfactor_params(arg1, &data[1], + &data[2]); break; case PM_QID_CLOCK_GET_PARENTS: - ret = pm_clock_get_parents(arg1, arg2, &data[1]); - data[0] = (unsigned int)ret; + data[0] = pm_clock_get_parents(arg1, arg2, &data[1]); break; case PM_QID_CLOCK_GET_ATTRIBUTES: - ret = pm_clock_get_attributes(arg1, &data[1]); - data[0] = (unsigned int)ret; + data[0] = pm_clock_get_attributes(arg1, &data[1]); break; case PM_QID_PINCTRL_GET_NUM_PINS: - ret = pm_pinctrl_get_num_pins(&data[1]); - data[0] = (unsigned int)ret; + data[0] = pm_pinctrl_get_num_pins(&data[1]); break; case PM_QID_PINCTRL_GET_NUM_FUNCTIONS: - ret = pm_pinctrl_get_num_functions(&data[1]); - data[0] = (unsigned int)ret; + data[0] = pm_pinctrl_get_num_functions(&data[1]); break; case PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS: - ret = pm_pinctrl_get_num_function_groups(arg1, &data[1]); - data[0] = (unsigned int)ret; + data[0] = pm_pinctrl_get_num_function_groups(arg1, &data[1]); break; case PM_QID_PINCTRL_GET_FUNCTION_NAME: - ret = pm_pinctrl_get_function_name(arg1, (char *)data); + pm_pinctrl_get_function_name(arg1, (char *)data); break; case PM_QID_PINCTRL_GET_FUNCTION_GROUPS: - ret = pm_pinctrl_get_function_groups(arg1, arg2, - (uint16_t *)&data[1]); - data[0] = (unsigned int)ret; + data[0] = pm_pinctrl_get_function_groups(arg1, arg2, + (uint16_t *)&data[1]); break; case PM_QID_PINCTRL_GET_PIN_GROUPS: - ret = pm_pinctrl_get_pin_groups(arg1, arg2, - (uint16_t *)&data[1]); - data[0] = (unsigned int)ret; + data[0] = pm_pinctrl_get_pin_groups(arg1, arg2, + (uint16_t *)&data[1]); break; case PM_QID_CLOCK_GET_NUM_CLOCKS: - ret = pm_clock_get_num_clocks(&data[1]); - data[0] = (unsigned int)ret; + data[0] = pm_clock_get_num_clocks(&data[1]); break; case PM_QID_CLOCK_GET_MAX_DIVISOR: - ret = pm_clock_get_max_divisor(arg1, arg2, &data[1]); - data[0] = (unsigned int)ret; + data[0] = pm_clock_get_max_divisor(arg1, arg2, &data[1]); break; default: - ret = PM_RET_ERROR_ARGS; + data[0] = PM_RET_ERROR_ARGS; WARN("Unimplemented query service call: 0x%x\n", qid); - break; } - - return ret; } enum pm_ret_status pm_sha_hash(uint32_t address_high, @@ -1548,3 +1550,101 @@ enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode) PM_PACK_PAYLOAD2(payload, PM_PLL_GET_MODE, nid); return pm_ipi_send_sync(primary_proc, payload, mode, 1); } + +/** + * pm_register_access() - PM API for register read/write access data + * + * @register_access_id Register_access_id which says register read/write + * + * @address Address of the register to be accessed + * + * @mask Mask value to be used while writing value + * + * @value Value to be written to register + * + * @out Returned output data + * + * This function returns requested data. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_register_access(unsigned int register_access_id, + unsigned int address, + unsigned int mask, + unsigned int value, + unsigned int *out) +{ + enum pm_ret_status ret; + + if (((ZYNQMP_CSU_BASEADDR & address) != ZYNQMP_CSU_BASEADDR) && + ((CSUDMA_BASE & address) != CSUDMA_BASE) && + ((RSA_CORE_BASE & address) != RSA_CORE_BASE) && + ((PMU_GLOBAL_BASE & address) != PMU_GLOBAL_BASE)) + return PM_RET_ERROR_ACCESS; + + switch (register_access_id) { + case CONFIG_REG_WRITE: + ret = pm_mmio_write(address, mask, value); + break; + case CONFIG_REG_READ: + ret = pm_mmio_read(address, out); + break; + default: + ret = PM_RET_ERROR_ARGS; + WARN("Unimplemented register_access call\n\r"); + } + return ret; +} + +/** + * pm_efuse_access() - To program or read efuse bits. + * + * This function provides access to the xilskey library to program/read + * efuse bits. + * + * address_low: lower 32-bit Linear memory space address + * address_high: higher 32-bit Linear memory space address + * + * value: Returned output value + * + * @return Returns status, either success or error+reason + * + */ +enum pm_ret_status pm_efuse_access(uint32_t address_high, + uint32_t address_low, + uint32_t *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD3(payload, PM_EFUSE_ACCESS, address_high, address_low); + + return pm_ipi_send_sync(primary_proc, payload, value, 1); +} + +enum pm_ret_status em_set_action(unsigned int *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + EM_PACK_PAYLOAD1(payload, EM_SET_ACTION); + return pm_ipi_send_sync(primary_proc, payload, value, 1); +} + +enum pm_ret_status em_remove_action(unsigned int *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + EM_PACK_PAYLOAD1(payload, EM_REMOVE_ACTION); + return pm_ipi_send_sync(primary_proc, payload, value, 1); +} + +enum pm_ret_status em_send_errors(unsigned int *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + EM_PACK_PAYLOAD1(payload, EM_SEND_ERRORS); + return pm_ipi_send_sync(primary_proc, payload, value, 1); +} diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h index ff66d3f024..b0c26529d3 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h @@ -28,6 +28,11 @@ enum pm_query_id { PM_QID_CLOCK_GET_MAX_DIVISOR, }; +enum pm_register_access_id { + CONFIG_REG_WRITE, + CONFIG_REG_READ, +}; + /********************************************************** * System-level API function declarations **********************************************************/ @@ -151,11 +156,8 @@ enum pm_ret_status pm_clock_setparent(unsigned int clock_id, unsigned int parent_id); enum pm_ret_status pm_clock_getparent(unsigned int clock_id, unsigned int *parent_id); -enum pm_ret_status pm_query_data(enum pm_query_id qid, - unsigned int arg1, - unsigned int arg2, - unsigned int arg3, - unsigned int *data); +void pm_query_data(enum pm_query_id qid, unsigned int arg1, unsigned int arg2, + unsigned int arg3, unsigned int *data); enum pm_ret_status pm_sha_hash(uint32_t address_high, uint32_t address_low, uint32_t size, @@ -178,6 +180,11 @@ enum pm_ret_status pm_fpga_read(uint32_t reg_numframes, enum pm_ret_status pm_aes_engine(uint32_t address_high, uint32_t address_low, uint32_t *value); +enum pm_ret_status pm_register_access(unsigned int register_access_id, + unsigned int address, + unsigned int mask, + unsigned int value, + unsigned int *out); enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid, enum pm_pll_param param_id, @@ -189,5 +196,10 @@ enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid, enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode); enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode); +enum pm_ret_status pm_efuse_access(uint32_t address_high, + uint32_t address_low, uint32_t *value); +enum pm_ret_status em_set_action(unsigned int *value); +enum pm_ret_status em_remove_action(unsigned int *value); +enum pm_ret_status em_send_errors(unsigned int *value); #endif /* PM_API_SYS_H */ diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h index cae36c9d8f..3324431ddd 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_defs.h +++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -18,7 +18,7 @@ * (PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR */ #define PM_VERSION_MAJOR 1 -#define PM_VERSION_MINOR 0 +#define PM_VERSION_MINOR 1 #define PM_VERSION ((PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR) @@ -33,6 +33,7 @@ #define PM_STATE_CPU_IDLE 0x0U #define PM_STATE_SUSPEND_TO_RAM 0xFU +#define EM_FUNID_NUM_MASK 0xF0000U /********************************************************************* * Enum definitions ********************************************************************/ @@ -97,6 +98,9 @@ enum pm_api_id { PM_PLL_GET_PARAMETER, PM_PLL_SET_MODE, PM_PLL_GET_MODE, + /* PM Register Access API */ + PM_REGISTER_ACCESS, + PM_EFUSE_ACCESS, PM_API_MAX }; @@ -215,26 +219,29 @@ enum pm_opchar_type { /** * @PM_RET_SUCCESS: success - * @PM_RET_ERROR_ARGS: illegal arguments provided + * @PM_RET_ERROR_ARGS: illegal arguments provided (deprecated) + * @PM_RET_ERROR_NOTSUPPORTED: feature not supported (deprecated) + * @PM_RET_ERROR_INTERNAL: internal error + * @PM_RET_ERROR_CONFLICT: conflict * @PM_RET_ERROR_ACCESS: access rights violation + * @PM_RET_ERROR_INVALID_NODE: invalid node + * @PM_RET_ERROR_DOUBLE_REQ: duplicate request for same node + * @PM_RET_ERROR_ABORT_SUSPEND: suspend procedure has been aborted * @PM_RET_ERROR_TIMEOUT: timeout in communication with PMU - * @PM_RET_ERROR_NOTSUPPORTED: feature not supported - * @PM_RET_ERROR_PROC: node is not a processor node - * @PM_RET_ERROR_API_ID: illegal API ID - * @PM_RET_ERROR_OTHER: other error + * @PM_RET_ERROR_NODE_USED: node is already in use */ enum pm_ret_status { PM_RET_SUCCESS, - PM_RET_ERROR_ARGS, - PM_RET_ERROR_ACCESS, - PM_RET_ERROR_TIMEOUT, - PM_RET_ERROR_NOTSUPPORTED, - PM_RET_ERROR_PROC, - PM_RET_ERROR_API_ID, - PM_RET_ERROR_FAILURE, - PM_RET_ERROR_COMMUNIC, - PM_RET_ERROR_DOUBLEREQ, - PM_RET_ERROR_OTHER, + PM_RET_ERROR_ARGS = 1, + PM_RET_ERROR_NOTSUPPORTED = 4, + PM_RET_ERROR_INTERNAL = 2000, + PM_RET_ERROR_CONFLICT = 2001, + PM_RET_ERROR_ACCESS = 2002, + PM_RET_ERROR_INVALID_NODE = 2003, + PM_RET_ERROR_DOUBLE_REQ = 2004, + PM_RET_ERROR_ABORT_SUSPEND = 2005, + PM_RET_ERROR_TIMEOUT = 2006, + PM_RET_ERROR_NODE_USED = 2007 }; /** @@ -317,4 +324,13 @@ enum pm_clock_div_id { PM_CLOCK_DIV1_ID, }; +/** + * EM API IDs + */ +enum em_api_id { + EM_SET_ACTION = 1, + EM_REMOVE_ACTION, + EM_SEND_ERRORS, +}; + #endif /* PM_DEFS_H */ diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c index 3f4f0691e5..a49bda8d29 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c +++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c @@ -29,8 +29,8 @@ #define PM_SET_SUSPEND_MODE 0xa02 #define PM_GET_TRUSTZONE_VERSION 0xa03 -/* !0 - UP, 0 - DOWN */ -static int32_t pm_up = 0; +/* pm_up = !0 - UP, pm_up = 0 - DOWN */ +static int32_t pm_up, ipi_irq_flag; #if ZYNQMP_WDT_RESTART static spinlock_t inc_lock; @@ -142,6 +142,8 @@ static uint64_t __unused __dead2 zynqmp_sgi7_irq(uint32_t id, uint32_t flags, void *handle, void *cookie) { int i; + uint32_t value; + /* enter wfi and stay there */ INFO("Entering wfi\n"); @@ -156,8 +158,9 @@ static uint64_t __unused __dead2 zynqmp_sgi7_irq(uint32_t id, uint32_t flags, spin_unlock(&inc_lock); if (active_cores == 0) { - pm_system_shutdown(PMF_SHUTDOWN_TYPE_RESET, - PMF_SHUTDOWN_SUBTYPE_SUBSYSTEM); + pm_mmio_read(PMU_GLOBAL_GEN_STORAGE4, &value); + value = (value & RESTART_SCOPE_MASK) >> RESTART_SCOPE_SHIFT; + pm_system_shutdown(PMF_SHUTDOWN_TYPE_RESET, value); } /* enter wfi and stay there */ @@ -210,6 +213,15 @@ int pm_setup(void) status = pm_ipi_init(primary_proc); + ret = pm_get_api_version(&pm_ctx.api_version); + if (pm_ctx.api_version < PM_VERSION) { + ERROR("BL31: Platform Management API version error. Expected: " + "v%d.%d - Found: v%d.%d\n", PM_VERSION_MAJOR, + PM_VERSION_MINOR, pm_ctx.api_version >> 16, + pm_ctx.api_version & 0xFFFF); + return -EINVAL; + } + #if ZYNQMP_WDT_RESTART status = pm_wdt_restart_setup(); if (status) @@ -321,22 +333,21 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, case PM_GET_API_VERSION: /* Check is PM API version already verified */ - if (pm_ctx.api_version == PM_VERSION) { + if (pm_ctx.api_version >= PM_VERSION) { + if (!ipi_irq_flag) { + /* + * Enable IPI IRQ + * assume the rich OS is OK to handle callback IRQs now. + * Even if we were wrong, it would not enable the IRQ in + * the GIC. + */ + pm_ipi_irq_enable(primary_proc); + ipi_irq_flag = 1; + } SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS | - ((uint64_t)PM_VERSION << 32)); + ((uint64_t)pm_ctx.api_version << 32)); } - ret = pm_get_api_version(&pm_ctx.api_version); - /* - * Enable IPI IRQ - * assume the rich OS is OK to handle callback IRQs now. - * Even if we were wrong, it would not enable the IRQ in - * the GIC. - */ - pm_ipi_irq_enable(primary_proc); - SMC_RET1(handle, (uint64_t)ret | - ((uint64_t)pm_ctx.api_version << 32)); - case PM_SET_CONFIGURATION: ret = pm_set_configuration(pm_arg[0]); SMC_RET1(handle, (uint64_t)ret); @@ -474,8 +485,8 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, { uint32_t data[4] = { 0 }; - ret = pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2], - pm_arg[3], data); + pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], data); SMC_RET2(handle, (uint64_t)data[0] | ((uint64_t)data[1] << 32), (uint64_t)data[2] | ((uint64_t)data[3] << 32)); } @@ -606,8 +617,78 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, SMC_RET1(handle, (uint64_t)ret | ((uint64_t)mode << 32)); } + case PM_REGISTER_ACCESS: + { + uint32_t value; + + ret = pm_register_access(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case PM_EFUSE_ACCESS: + { + uint32_t value; + + ret = pm_efuse_access(pm_arg[0], pm_arg[1], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + default: WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid); SMC_RET1(handle, SMC_UNK); } } + +/** + * em_smc_handler() - SMC handler for EM-API calls coming from EL1/EL2. + * @smc_fid - Function Identifier + * @x1 - x4 - Arguments + * @cookie - Unused + * @handler - Pointer to caller's context structure + * + * @return - Unused + * + * Determines that smc_fid is valid and supported EM SMC Function ID from the + * list of em_api_ids, otherwise completes the request with + * the unknown SMC Function ID + * + * The SMC calls for EM service are forwarded from SIP Service SMC handler + * function with rt_svc_handle signature + */ +uint64_t em_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, + uint64_t x4, void *cookie, void *handle, uint64_t flags) +{ + enum pm_ret_status ret; + + switch (smc_fid & FUNCID_NUM_MASK) { + /* EM API Functions */ + case EM_SET_ACTION: + { + uint32_t value; + + ret = em_set_action(&value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case EM_REMOVE_ACTION: + { + uint32_t value; + + ret = em_remove_action(&value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case EM_SEND_ERRORS: + { + uint32_t value; + + ret = em_send_errors(&value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + default: + WARN("Unimplemented EM Service Call: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.h b/plat/xilinx/zynqmp/pm_service/pm_svc_main.h index 0968f64cba..abadd40653 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.h +++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -14,4 +14,7 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, void *cookie, void *handle, uint64_t flags); +uint64_t em_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, + uint64_t x4, void *cookie, void *handle, + uint64_t flags); #endif /* PM_SVC_MAIN_H */ diff --git a/plat/xilinx/zynqmp/sip_svc_setup.c b/plat/xilinx/zynqmp/sip_svc_setup.c index 9b182749cb..114da33d63 100644 --- a/plat/xilinx/zynqmp/sip_svc_setup.c +++ b/plat/xilinx/zynqmp/sip_svc_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -25,6 +25,9 @@ #define PM_FID_MASK 0xf000u #define PM_FID_VALUE 0u #define IPI_FID_VALUE 0x1000u +#define EM_FID_MASK 0xf0000u +#define EM_FID_VALUE 0xE0000u +#define is_em_fid(_fid) (((_fid) & EM_FID_MASK) == EM_FID_VALUE) #define is_pm_fid(_fid) (((_fid) & PM_FID_MASK) == PM_FID_VALUE) #define is_ipi_fid(_fid) (((_fid) & PM_FID_MASK) == IPI_FID_VALUE) @@ -41,9 +44,7 @@ DEFINE_SVC_UUID2(zynqmp_sip_uuid, static int32_t sip_svc_setup(void) { /* PM implementation as SiP Service */ - pm_setup(); - - return 0; + return pm_setup(); } /** @@ -61,8 +62,12 @@ uintptr_t sip_svc_smc_handler(uint32_t smc_fid, void *handle, u_register_t flags) { + /* Let EM SMC handler deal with EM-related requests */ + if (is_em_fid(smc_fid)) { + return em_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, + flags); + } else if (is_pm_fid(smc_fid)) { /* Let PM SMC handler deal with PM-related requests */ - if (is_pm_fid(smc_fid)) { return pm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags); } |