summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrzegorz Jaszczyk <jaz@semihalf.com>2017-08-30 13:31:06 +0200
committerKostya Porotchkin <kostap@marvell.com>2017-08-31 16:23:05 +0300
commit72392ef6b448c80e68793586c9e7f1f46731c139 (patch)
tree6bd7221418343eac3f83e2026a5e813c0b0eb7dc
parente8fc2d5ebab5dfd07429709a2a3bc36985d610f2 (diff)
plat: marvell: a8k: allow to load scp_bl2 firmware that doesn't contain PM FW
Hitherto if the SCP_BL2 path was defined, Marvell platform code (plat/marvell/a8k/common/a8k_common.mk via plat/marvell/a8k/common/mss/mss_common.mk) was defining SCP_IMAGE, which was used in power management related code(mainly in plat_pm.c) for choosing proper PM related code. Therefore there were two different situation: 1) The SCP_BL2 was not defined, then the ATF used its own PM related code 2) The SCP_BL2 was defined and ATF assumed that during SCP_BL2 stage the firmware with PM support was loaded into MSS AP CM3 and PM was managed mainly via IPC messages between ATF and MSS AP CM3 firmware. Now in some cases the firmware for MSS AP CM3 does not support PM therefore it causes some issue: during Linux boot only one CPU was brought out from reset and all secondary CPUs remained down. After this change the Marvell platform code can verify if the firmware loaded to MSS AP CM3 has PM support at runtime and does not make assumption basing on SCP_BL2 definition anymore. In other words all preprocessor condition of SCP_IMAGE was replaced by runtime condition that allows to really distinguish between situation where we are running PM firmware or not, so three different scenario are possible and handled correctly now: 1) The SCP_BL2 is not used at all then the ATF uses its own PM related code. 2) The SCP_BL2 contains firmware for MSS AP CM3 and it supports PM, then ATF manage PM mainly via IPC messages between ATF and MSS AP CM3 firmware. 3) The SCP_BL2 does not contain firmware for MSS AP CM3 or it contain firmware that does not support PM, then ATF uses its own PM related code. Change-Id: I26da4db968966cb5e61714ff192fb645a3a57875 Signed-off-by: Grzegorz Jaszczyk <jaz@semihalf.com> Reviewed-on: http://vgitil04.il.marvell.com:8080/43573 Tested-by: iSoC Platform CI <ykjenk@marvell.com> Reviewed-by: Kostya Porotchkin <kostap@marvell.com> Reviewed-by: Omri Itach <omrii@marvell.com> Reviewed-by: Igal Liberman <igall@marvell.com>
-rw-r--r--include/plat/marvell/a8k/common/plat_marvell.h3
-rw-r--r--include/plat/marvell/a8k/common/plat_pm_trace.h2
-rw-r--r--lib/psci/psci_off.c23
-rw-r--r--plat/marvell/a8k/common/a8k_common.mk4
-rw-r--r--plat/marvell/a8k/common/mss/mss_scp_bootloader.c6
-rw-r--r--plat/marvell/a8k/common/plat_bl31_setup.c22
-rw-r--r--plat/marvell/a8k/common/plat_pm.c232
7 files changed, 150 insertions, 142 deletions
diff --git a/include/plat/marvell/a8k/common/plat_marvell.h b/include/plat/marvell/a8k/common/plat_marvell.h
index 1798563c..779c235b 100644
--- a/include/plat/marvell/a8k/common/plat_marvell.h
+++ b/include/plat/marvell/a8k/common/plat_marvell.h
@@ -102,6 +102,9 @@ void marvell_bl31_plat_arch_setup(void);
/* Power management config to power off the SoC */
void *plat_get_pm_cfg(void);
+/* Check if MSS AP CM3 firmware contains PM support */
+_Bool is_pm_fw_running(void);
+
/* Bootrom image recovery utility functions */
void *plat_get_skip_image_data(void);
diff --git a/include/plat/marvell/a8k/common/plat_pm_trace.h b/include/plat/marvell/a8k/common/plat_pm_trace.h
index 907fa5f8..c1b88707 100644
--- a/include/plat/marvell/a8k/common/plat_pm_trace.h
+++ b/include/plat/marvell/a8k/common/plat_pm_trace.h
@@ -96,7 +96,7 @@ struct pm_trace_ctrl {
#define TRACE_PWR_DOMAIN_ON_MASK (0xFF)
-#if defined(SCP_IMAGE) && defined(PM_TRACE_ENABLE)
+#ifdef PM_TRACE_ENABLE
/* trace API definition */
void pm_core_0_trace(unsigned int trace);
diff --git a/lib/psci/psci_off.c b/lib/psci/psci_off.c
index 7b6f90ed..23f6793c 100644
--- a/lib/psci/psci_off.c
+++ b/lib/psci/psci_off.c
@@ -35,6 +35,7 @@
#include <platform.h>
#include <string.h>
#include "psci_private.h"
+#include <plat_marvell.h>
/******************************************************************************
* Construct the psci_power_state to request power OFF at all power levels.
@@ -105,19 +106,23 @@ int psci_do_cpu_off(unsigned int end_pwrlvl)
psci_stats_update_pwr_down(end_pwrlvl, &state_info);
#endif
+#ifdef SCP_IMAGE
+ if (is_pm_fw_running()) {
+ /*
+ * MSS implementation does not support cluster power down
+ * in case of Hot plug, therefore we defined MPIDR_AFFLVL1
+ * state to PSCI_LOCAL_STATE_RUN. resulting in max off level
+ * set to CPU level
+ */
+ state_info.pwr_domain_state[MPIDR_AFFLVL1] =
+ PSCI_LOCAL_STATE_RUN;
+ }
+#endif
+
/*
* Arch. management. Perform the necessary steps to flush all
* cpu caches.
*/
-#ifdef SCP_IMAGE
- /*
- * MSS implementation does not support cluster power down
- * in case of Hot plug, therefore we defined MPIDR_AFFLVL1
- * state to PSCI_LOCAL_STATE_RUN. resulting in max off level
- * set to CPU level
- */
- state_info.pwr_domain_state[MPIDR_AFFLVL1] = PSCI_LOCAL_STATE_RUN;
-#endif
psci_do_pwrdown_cache_maintenance(psci_find_max_off_lvl(&state_info));
/*
diff --git a/plat/marvell/a8k/common/a8k_common.mk b/plat/marvell/a8k/common/a8k_common.mk
index 01ee84a6..0cb058ac 100644
--- a/plat/marvell/a8k/common/a8k_common.mk
+++ b/plat/marvell/a8k/common/a8k_common.mk
@@ -111,9 +111,7 @@ BL31_SOURCES += lib/cpus/aarch64/cortex_a72.S \
$(MARVELL_GIC_SOURCES)
# Add trace functionality for PM
-ifneq (${SCP_BL2},)
BL31_SOURCES += $(PLAT_COMMON_BASE)/plat_pm_trace.c
-endif
# Disable the PSCI platform compatibility layer (allows porting
# from Old Platform APIs to the new APIs).
@@ -121,6 +119,4 @@ endif
ENABLE_PLAT_COMPAT := 0
# MSS (SCP) build
-ifneq (${SCP_BL2},)
include $(PLAT_COMMON_BASE)/mss/mss_common.mk
-endif
diff --git a/plat/marvell/a8k/common/mss/mss_scp_bootloader.c b/plat/marvell/a8k/common/mss/mss_scp_bootloader.c
index 15961375..cad93c14 100644
--- a/plat/marvell/a8k/common/mss/mss_scp_bootloader.c
+++ b/plat/marvell/a8k/common/mss/mss_scp_bootloader.c
@@ -215,10 +215,8 @@ static int mss_ap_load_image(uintptr_t single_img, uint32_t image_size)
/* check that the image was loaded successfully */
ret = mss_check_image_ready(mss_pm_crtl);
- if (ret != 0) {
- ERROR("SCP Image check failed\n");
- return -1;
- }
+ if (ret != 0)
+ NOTICE("SCP Image doesn't contain PM firmware\n");
return 0;
}
diff --git a/plat/marvell/a8k/common/plat_bl31_setup.c b/plat/marvell/a8k/common/plat_bl31_setup.c
index 8083b398..e2e988fc 100644
--- a/plat/marvell/a8k/common/plat_bl31_setup.c
+++ b/plat/marvell/a8k/common/plat_bl31_setup.c
@@ -42,10 +42,10 @@
#include <mci.h>
#include <debug.h>
-#ifdef SCP_IMAGE
#include <mss_ipc_drv.h>
#include <mss_mem.h>
-#endif
+
+static _Bool pm_fw_running;
/* Set a weak stub for platforms that don't need to configure GPIO */
#pragma weak marvell_gpio_config
@@ -69,17 +69,27 @@ void marvell_bl31_mpp_init(void)
void marvell_bl31_mss_init(void)
{
-#ifdef SCP_IMAGE
struct mss_pm_ctrl_block *mss_pm_crtl =
(struct mss_pm_ctrl_block *)MSS_SRAM_PM_CONTROL_BASE;
+ /* Check that the image was loaded successfully */
+ if (mss_pm_crtl->handshake != HOST_ACKNOWLEDGEMENT) {
+ NOTICE("MSS PM is not supported in this build\n");
+ return;
+ }
+
+ /* If we got here it means that the PM firmware is running */
+ pm_fw_running = 1;
+
INFO("MSS IPC init\n");
if (mss_pm_crtl->ipc_state == IPC_INITIALIZED)
mv_pm_ipc_init(mss_pm_crtl->ipc_base_address | MVEBU_REGS_BASE);
-#else
- INFO("MSS is not supported in this build\n");
-#endif
+}
+
+_Bool is_pm_fw_running(void)
+{
+ return pm_fw_running;
}
/* This function overruns the same function in marvell_bl31_setup.c */
diff --git a/plat/marvell/a8k/common/plat_pm.c b/plat/marvell/a8k/common/plat_pm.c
index f038f4c0..3149f9b3 100644
--- a/plat/marvell/a8k/common/plat_pm.c
+++ b/plat/marvell/a8k/common/plat_pm.c
@@ -44,12 +44,10 @@
#include <marvell_pm.h>
#include <plat_config.h>
-#ifdef SCP_IMAGE
#include <bakery_lock.h>
#include <platform.h>
#include <mss_pm_ipc.h>
#include <plat_pm_trace.h>
-#endif
#define MVEBU_PRIVATE_UID_REG 0x30
#define MVEBU_RFU_GLOBL_SW_RST 0x84
@@ -84,10 +82,8 @@
#define MVEBU_MC_PHY_AUTO_OFF_MASK (1 << MVEBU_MC_PHY_AUTO_OFF_OFFSET)
#define MVEBU_MC_PHY_AUTO_OFF_EN (1 << MVEBU_MC_PHY_AUTO_OFF_OFFSET)
-#ifdef SCP_IMAGE
/* this lock synchronize AP multiple cores execution with MSS */
DEFINE_BAKERY_LOCK(pm_sys_lock);
-#endif
/* Weak definitions may be overridden in specific board */
#pragma weak plat_get_pm_cfg
@@ -294,7 +290,6 @@ cpu_poweron_error:
return -1;
}
-#ifndef SCP_IMAGE
static int plat_marvell_cpu_on(u_register_t mpidr)
{
int cpu_id;
@@ -320,7 +315,6 @@ static int plat_marvell_cpu_on(u_register_t mpidr)
return 0;
}
-#endif /* SCP_IMAGE */
/*******************************************************************************
* A8K handler called to check the validity of the power state
@@ -380,30 +374,30 @@ static int a8k_pwr_domain_on(u_register_t mpidr)
/* Power up CPU (CPUs 1-3 are powered off at start of BLE) */
plat_marvell_cpu_powerup(mpidr);
-#ifdef SCP_IMAGE
- unsigned int target = ((mpidr & 0xFF) + (((mpidr >> 8) & 0xFF) * 2));
+ if (is_pm_fw_running()) {
+ unsigned int target = ((mpidr & 0xFF) + (((mpidr >> 8) & 0xFF) * 2));
- /*
- * pm system synchronization - used to synchronize
- * multiple core access to MSS
- */
- bakery_lock_get(&pm_sys_lock);
+ /*
+ * pm system synchronization - used to synchronize
+ * multiple core access to MSS
+ */
+ bakery_lock_get(&pm_sys_lock);
- /* send CPU ON IPC Message to MSS */
- mss_pm_ipc_msg_send(target, PM_IPC_MSG_CPU_ON, 0);
+ /* send CPU ON IPC Message to MSS */
+ mss_pm_ipc_msg_send(target, PM_IPC_MSG_CPU_ON, 0);
- /* trigger IPC message to MSS */
- mss_pm_ipc_msg_trigger();
+ /* trigger IPC message to MSS */
+ mss_pm_ipc_msg_trigger();
- /* pm system synchronization */
- bakery_lock_release(&pm_sys_lock);
+ /* pm system synchronization */
+ bakery_lock_release(&pm_sys_lock);
- /* trace message */
- PM_TRACE(TRACE_PWR_DOMAIN_ON | target);
-#else
- /* proprietary CPU ON exection flow */
- plat_marvell_cpu_on(mpidr);
-#endif /* SCP_IMAGE */
+ /* trace message */
+ PM_TRACE(TRACE_PWR_DOMAIN_ON | target);
+ } else {
+ /* proprietary CPU ON exection flow */
+ plat_marvell_cpu_on(mpidr);
+ }
return 0;
}
@@ -422,30 +416,32 @@ static int a8k_validate_ns_entrypoint(uintptr_t entrypoint)
******************************************************************************/
static void a8k_pwr_domain_off(const psci_power_state_t *target_state)
{
-#ifdef SCP_IMAGE
- unsigned int idx = plat_my_core_pos();
+ if (is_pm_fw_running()) {
+ unsigned int idx = plat_my_core_pos();
- /* Prevent interrupts from spuriously waking up this cpu */
- gicv2_cpuif_disable();
+ /* Prevent interrupts from spuriously waking up this cpu */
+ gicv2_cpuif_disable();
- /* pm system synchronization - used to synchronize multiple core access to MSS */
- bakery_lock_get(&pm_sys_lock);
+ /* pm system synchronization - used to synchronize multiple
+ * core access to MSS
+ */
+ bakery_lock_get(&pm_sys_lock);
- /* send CPU OFF IPC Message to MSS */
- mss_pm_ipc_msg_send(idx, PM_IPC_MSG_CPU_OFF, target_state);
+ /* send CPU OFF IPC Message to MSS */
+ mss_pm_ipc_msg_send(idx, PM_IPC_MSG_CPU_OFF, target_state);
- /* trigger IPC message to MSS */
- mss_pm_ipc_msg_trigger();
+ /* trigger IPC message to MSS */
+ mss_pm_ipc_msg_trigger();
- /* pm system synchronization */
- bakery_lock_release(&pm_sys_lock);
+ /* pm system synchronization */
+ bakery_lock_release(&pm_sys_lock);
- /* trace message */
- PM_TRACE(TRACE_PWR_DOMAIN_OFF);
-#else
- INFO("%s: is not supported without SCP\n", __func__);
- return;
-#endif /* SCP_IMAGE */
+ /* trace message */
+ PM_TRACE(TRACE_PWR_DOMAIN_OFF);
+ } else {
+ INFO("%s: is not supported without SCP\n", __func__);
+ return;
+ }
}
/* Get PM config to power off the SoC */
@@ -454,7 +450,6 @@ void *plat_get_pm_cfg(void)
return NULL;
}
-#ifndef SCP_IMAGE
/*
* This function should be called on restore from
* "suspend to RAM" state when the execution flow
@@ -611,7 +606,6 @@ static void plat_marvell_system_power_off(void)
/* Issue the power off */
plat_marvell_power_off_trigger();
}
-#endif /* SCP_IMAGE */
/*******************************************************************************
* A8K handler called when a power domain is about to be suspended. The
@@ -619,63 +613,65 @@ static void plat_marvell_system_power_off(void)
******************************************************************************/
static void a8k_pwr_domain_suspend(const psci_power_state_t *target_state)
{
-#ifdef SCP_IMAGE
- unsigned int idx;
+ if (is_pm_fw_running()) {
+ unsigned int idx;
- /* Prevent interrupts from spuriously waking up this cpu */
- gicv2_cpuif_disable();
+ /* Prevent interrupts from spuriously waking up this cpu */
+ gicv2_cpuif_disable();
- idx = plat_my_core_pos();
+ idx = plat_my_core_pos();
- /* pm system synchronization -used to synchronize multiple core access to MSS */
- bakery_lock_get(&pm_sys_lock);
+ /* pm system synchronization - used to synchronize multiple
+ * core access to MSS
+ */
+ bakery_lock_get(&pm_sys_lock);
- /* send CPU Suspend IPC Message to MSS */
- mss_pm_ipc_msg_send(idx, PM_IPC_MSG_CPU_SUSPEND, target_state);
+ /* send CPU Suspend IPC Message to MSS */
+ mss_pm_ipc_msg_send(idx, PM_IPC_MSG_CPU_SUSPEND, target_state);
- /* trigger IPC message to MSS */
- mss_pm_ipc_msg_trigger();
+ /* trigger IPC message to MSS */
+ mss_pm_ipc_msg_trigger();
- /* pm system synchronization */
- bakery_lock_release(&pm_sys_lock);
+ /* pm system synchronization */
+ bakery_lock_release(&pm_sys_lock);
- /* trace message */
- PM_TRACE(TRACE_PWR_DOMAIN_SUSPEND);
-#else
- uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE;
+ /* trace message */
+ PM_TRACE(TRACE_PWR_DOMAIN_SUSPEND);
+ } else {
+ uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE;
- INFO("Suspending to RAM\n");
+ INFO("Suspending to RAM\n");
- /* Prevent interrupts from spuriously waking up this cpu */
- gicv2_cpuif_disable();
+ /* Prevent interrupts from spuriously waking up this cpu */
+ gicv2_cpuif_disable();
- mailbox[MBOX_IDX_SUSPEND_MAGIC] = MVEBU_MAILBOX_SUSPEND_STATE;
- mailbox[MBOX_IDX_ROM_EXIT_ADDR] = (uintptr_t)&plat_exit_bootrom;
+ mailbox[MBOX_IDX_SUSPEND_MAGIC] = MVEBU_MAILBOX_SUSPEND_STATE;
+ mailbox[MBOX_IDX_ROM_EXIT_ADDR] = (uintptr_t)&plat_exit_bootrom;
#if PLAT_MARVELL_SHARED_RAM_CACHED
- flush_dcache_range(PLAT_MARVELL_MAILBOX_BASE +
- MBOX_IDX_SUSPEND_MAGIC * sizeof(uintptr_t),
- 2 * sizeof(uintptr_t));
+ flush_dcache_range(PLAT_MARVELL_MAILBOX_BASE +
+ MBOX_IDX_SUSPEND_MAGIC * sizeof(uintptr_t),
+ 2 * sizeof(uintptr_t));
#endif
- /* Flush and disable LLC before going off-power */
- llc_disable(0);
-
- /*
- * Power off whole system, it should be guaranteed that CPU has enough time to finish
- * remained tasks before the power off takes effect.
- */
- plat_marvell_system_power_off();
+ /* Flush and disable LLC before going off-power */
+ llc_disable(0);
- isb();
- /*
- * Do not halt here!
- * The function must return for allowing the caller function
- * psci_power_up_finish() to do the proper context saving and
- * to release the CPU lock.
- */
+ /*
+ * Power off whole system, it should be guaranteed that CPU has
+ * enough time to finish remained tasks before the power off
+ * takes effect.
+ */
+ plat_marvell_system_power_off();
-#endif /* SCP_IMAGE */
+ isb();
+ /*
+ * Do not halt here!
+ * The function must return for allowing the caller function
+ * psci_power_up_finish() to do the proper context saving and
+ * to release the CPU lock.
+ */
+ }
}
/*******************************************************************************
@@ -692,10 +688,10 @@ static void a8k_pwr_domain_on_finish(const psci_power_state_t *target_state)
gicv2_pcpu_distif_init();
gicv2_cpuif_enable();
-#ifdef SCP_IMAGE
- /* trace message */
- PM_TRACE(TRACE_PWR_DOMAIN_ON_FINISH);
-#endif /* SCP_IMAGE */
+ if (is_pm_fw_running()) {
+ /* trace message */
+ PM_TRACE(TRACE_PWR_DOMAIN_ON_FINISH);
+ }
}
/*******************************************************************************
@@ -707,39 +703,39 @@ static void a8k_pwr_domain_on_finish(const psci_power_state_t *target_state)
******************************************************************************/
static void a8k_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
{
-#ifdef SCP_IMAGE
- /* arch specific configuration */
- psci_arch_init(0);
+ if (is_pm_fw_running()) {
+ /* arch specific configuration */
+ psci_arch_init(0);
- /* Interrupt initialization */
- gicv2_cpuif_enable();
+ /* Interrupt initialization */
+ gicv2_cpuif_enable();
- /* trace message */
- PM_TRACE(TRACE_PWR_DOMAIN_SUSPEND_FINISH);
-#else
- uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE;
-
- /* Only primary CPU requres platform init */
- if (!plat_my_core_pos()) {
- /* Initialize the console to provide early debug support */
- console_init(PLAT_MARVELL_BOOT_UART_BASE,
- PLAT_MARVELL_BOOT_UART_CLK_IN_HZ,
- MARVELL_CONSOLE_BAUDRATE);
- bl31_plat_arch_setup();
- marvell_bl31_platform_setup();
- /*
- * Remove suspend to RAM marker from the mailbox
- * for treating a regular reset as a cold boot
- */
- mailbox[MBOX_IDX_SUSPEND_MAGIC] = 0;
- mailbox[MBOX_IDX_ROM_EXIT_ADDR] = 0;
+ /* trace message */
+ PM_TRACE(TRACE_PWR_DOMAIN_SUSPEND_FINISH);
+ } else {
+ uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE;
+
+ /* Only primary CPU requres platform init */
+ if (!plat_my_core_pos()) {
+ /* Initialize the console to provide early debug support */
+ console_init(PLAT_MARVELL_BOOT_UART_BASE,
+ PLAT_MARVELL_BOOT_UART_CLK_IN_HZ,
+ MARVELL_CONSOLE_BAUDRATE);
+ bl31_plat_arch_setup();
+ marvell_bl31_platform_setup();
+ /*
+ * Remove suspend to RAM marker from the mailbox
+ * for treating a regular reset as a cold boot
+ */
+ mailbox[MBOX_IDX_SUSPEND_MAGIC] = 0;
+ mailbox[MBOX_IDX_ROM_EXIT_ADDR] = 0;
#if PLAT_MARVELL_SHARED_RAM_CACHED
- flush_dcache_range(PLAT_MARVELL_MAILBOX_BASE +
- MBOX_IDX_SUSPEND_MAGIC * sizeof(uintptr_t),
- 2 * sizeof(uintptr_t));
+ flush_dcache_range(PLAT_MARVELL_MAILBOX_BASE +
+ MBOX_IDX_SUSPEND_MAGIC * sizeof(uintptr_t),
+ 2 * sizeof(uintptr_t));
#endif
+ }
}
-#endif /* SCP_IMAGE */
}
/*******************************************************************************