mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-16 17:44:19 +00:00

Make sure the current CCU window is not in use before adding a new address map during MSS BL2 image load preparations. At BL2 stage the CCU Win-2 points to DRAM. If additional mapping is added to MSS BL2 stage initialization, the DDR entry will be destroyed and lead to the system hang. Change-Id: I215e83508acc37d54dab6954d791b9a74cc883ca Signed-off-by: Konstantin Porotchkin <kostap@marvell.com>
158 lines
4.3 KiB
C
158 lines
4.3 KiB
C
/*
|
|
* Copyright (C) 2018 Marvell International Ltd.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
* https://spdx.org/licenses
|
|
*/
|
|
|
|
#include <platform_def.h>
|
|
|
|
#include <common/bl_common.h>
|
|
#include <common/debug.h>
|
|
#include <drivers/marvell/ccu.h>
|
|
#include <drivers/marvell/mochi/ap_setup.h>
|
|
#include <drivers/marvell/mochi/cp110_setup.h>
|
|
#include <lib/mmio.h>
|
|
|
|
#include <armada_common.h>
|
|
#include <marvell_plat_priv.h> /* timer functionality */
|
|
|
|
#include "mss_scp_bootloader.h"
|
|
|
|
/* MSS windows configuration */
|
|
#define MSS_AEBR(base) (base + 0x160)
|
|
#define MSS_AIBR(base) (base + 0x164)
|
|
#define MSS_AEBR_MASK 0xFFF
|
|
#define MSS_AIBR_MASK 0xFFF
|
|
|
|
#define MSS_EXTERNAL_SPACE 0x50000000
|
|
#define MSS_EXTERNAL_ACCESS_BIT 28
|
|
#define MSS_EXTERNAL_ADDR_MASK 0xfffffff
|
|
#define MSS_INTERNAL_ACCESS_BIT 28
|
|
|
|
struct addr_map_win ccu_mem_map[] = {
|
|
{MVEBU_CP_REGS_BASE(0), 0x4000000, IO_0_TID}
|
|
};
|
|
|
|
/* Since the scp_bl2 image can contain firmware for cp1 and cp0 coprocessors,
|
|
* the access to cp0 and cp1 need to be provided. More precisely it is
|
|
* required to:
|
|
* - get the information about device id which is stored in CP0 registers
|
|
* (to distinguish between cases where we have cp0 and cp1 or standalone cp0)
|
|
* - get the access to cp which is needed for loading fw for cp0/cp1
|
|
* coprocessors
|
|
* This function configures ccu windows accordingly.
|
|
*
|
|
* Note: there is no need to restore previous ccu configuration, since in next
|
|
* phase (BL31) the init_ccu will be called (via apn806_init/
|
|
* bl31_plat_arch_setu) and therefore the ccu configuration will be overwritten.
|
|
*/
|
|
static int bl2_plat_mmap_init(void)
|
|
{
|
|
int cfg_num, win_id, cfg_idx, cp;
|
|
|
|
cfg_num = ARRAY_SIZE(ccu_mem_map);
|
|
|
|
/* CCU window-0 should not be counted - it's already used */
|
|
if (cfg_num > (MVEBU_CCU_MAX_WINS - 1)) {
|
|
ERROR("BL2: %s: trying to open too many windows\n", __func__);
|
|
return -1;
|
|
}
|
|
|
|
/* Enable required CCU windows
|
|
* Do not touch CCU window 0,
|
|
* it's used for the internal registers access
|
|
*/
|
|
for (cfg_idx = 0, win_id = 1;
|
|
(win_id < MVEBU_CCU_MAX_WINS) && (cfg_idx < cfg_num); win_id++) {
|
|
/* Skip already enabled CCU windows */
|
|
if (ccu_is_win_enabled(MVEBU_AP0, win_id))
|
|
continue;
|
|
/* Enable required CCU windows */
|
|
ccu_win_check(&ccu_mem_map[cfg_idx]);
|
|
ccu_enable_win(MVEBU_AP0, &ccu_mem_map[cfg_idx], win_id);
|
|
cfg_idx++;
|
|
}
|
|
|
|
/* Config address for each cp other than cp0 */
|
|
for (cp = 1; cp < CP_COUNT; cp++)
|
|
update_cp110_default_win(cp);
|
|
|
|
/* There is need to configure IO_WIN windows again to overwrite
|
|
* temporary configuration done during update_cp110_default_win
|
|
*/
|
|
init_io_win(MVEBU_AP0);
|
|
|
|
/* Open AMB bridge required for MG access */
|
|
for (cp = 0; cp < CP_COUNT; cp++)
|
|
cp110_amb_init(MVEBU_CP_REGS_BASE(cp));
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol.
|
|
* Return 0 on success, -1 otherwise.
|
|
*****************************************************************************
|
|
*/
|
|
int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info)
|
|
{
|
|
int ret;
|
|
|
|
INFO("BL2: Initiating SCP_BL2 transfer to SCP\n");
|
|
|
|
/* initialize time (for delay functionality) */
|
|
plat_delay_timer_init();
|
|
|
|
ret = bl2_plat_mmap_init();
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
ret = scp_bootloader_transfer((void *)scp_bl2_image_info->image_base,
|
|
scp_bl2_image_info->image_size);
|
|
|
|
if (ret == 0)
|
|
INFO("BL2: SCP_BL2 transferred to SCP\n");
|
|
else
|
|
ERROR("BL2: SCP_BL2 transfer failure\n");
|
|
|
|
return ret;
|
|
}
|
|
|
|
uintptr_t bl2_plat_get_cp_mss_regs(int ap_idx, int cp_idx)
|
|
{
|
|
return MVEBU_CP_REGS_BASE(cp_idx) + 0x280000;
|
|
}
|
|
|
|
uintptr_t bl2_plat_get_ap_mss_regs(int ap_idx)
|
|
{
|
|
return MVEBU_REGS_BASE + 0x580000;
|
|
}
|
|
|
|
uint32_t bl2_plat_get_cp_count(int ap_idx)
|
|
{
|
|
uint32_t revision = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
|
|
/* A8040: two CPs.
|
|
* A7040: one CP.
|
|
*/
|
|
if (revision == MVEBU_80X0_DEV_ID ||
|
|
revision == MVEBU_80X0_CP115_DEV_ID)
|
|
return 2;
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
uint32_t bl2_plat_get_ap_count(void)
|
|
{
|
|
/* A8040 and A7040 have only one AP */
|
|
return 1;
|
|
}
|
|
|
|
void bl2_plat_configure_mss_windows(uintptr_t mss_regs)
|
|
{
|
|
/* set AXI External and Internal Address Bus extension */
|
|
mmio_write_32(MSS_AEBR(mss_regs),
|
|
((0x0 >> MSS_EXTERNAL_ACCESS_BIT) & MSS_AEBR_MASK));
|
|
mmio_write_32(MSS_AIBR(mss_regs),
|
|
((mss_regs >> MSS_INTERNAL_ACCESS_BIT) & MSS_AIBR_MASK));
|
|
}
|