GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
+22
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (C) 2018 Marvell International Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://spdx.org/licenses
|
||||
#
|
||||
|
||||
PLAT_MARVELL := plat/marvell/armada
|
||||
A8K_MSS_SOURCE := $(PLAT_MARVELL)/a8k/common/mss
|
||||
|
||||
BL2_SOURCES += $(A8K_MSS_SOURCE)/mss_bl2_setup.c \
|
||||
$(MARVELL_MOCHI_DRV)
|
||||
|
||||
BL31_SOURCES += $(A8K_MSS_SOURCE)/mss_pm_ipc.c \
|
||||
$(A8K_MSS_SOURCE)/mss_bl31_setup.c
|
||||
|
||||
PLAT_INCLUDES += -I$(A8K_MSS_SOURCE)
|
||||
|
||||
ifneq (${SCP_BL2},)
|
||||
# This define is used to inidcate the SCP image is present
|
||||
$(eval $(call add_define,SCP_IMAGE))
|
||||
endif
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* 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_defs.h"
|
||||
#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) + MSS_CP_REGS_OFFSET;
|
||||
}
|
||||
|
||||
uintptr_t bl2_plat_get_cp_mss_sram(int ap_idx, int cp_idx)
|
||||
{
|
||||
return MVEBU_CP_REGS_BASE(cp_idx) + MSS_CP_SRAM_OFFSET;
|
||||
}
|
||||
|
||||
uintptr_t bl2_plat_get_ap_mss_regs(int ap_idx)
|
||||
{
|
||||
return MVEBU_REGS_BASE + MSS_AP_REGS_OFFSET;
|
||||
}
|
||||
|
||||
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 if (revision == MVEBU_CN9130_DEV_ID)
|
||||
return CP_COUNT;
|
||||
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));
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 <lib/mmio.h>
|
||||
|
||||
#include <armada_common.h>
|
||||
|
||||
#include "mss_defs.h"
|
||||
|
||||
void mss_start_cp_cm3(int cp)
|
||||
{
|
||||
uint32_t magic;
|
||||
uintptr_t sram = MVEBU_CP_REGS_BASE(cp) + MSS_CP_SRAM_OFFSET;
|
||||
uintptr_t regs = MVEBU_CP_REGS_BASE(cp) + MSS_CP_REGS_OFFSET;
|
||||
|
||||
magic = mmio_read_32(sram);
|
||||
|
||||
/* Make sure the FW was loaded */
|
||||
if (magic != MSS_FW_READY_MAGIC) {
|
||||
return;
|
||||
}
|
||||
|
||||
NOTICE("Starting CP%d MSS CPU\n", cp);
|
||||
/* remove the magic */
|
||||
mmio_write_32(sram, 0);
|
||||
/* Release M3 from reset */
|
||||
mmio_write_32(MSS_M3_RSTCR(regs),
|
||||
(MSS_M3_RSTCR_RST_OFF << MSS_M3_RSTCR_RST_OFFSET));
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef MSS_DEFS_H
|
||||
#define MSS_DEFS_H
|
||||
|
||||
#define MSS_DMA_SRCBR(base) (base + 0xC0)
|
||||
#define MSS_DMA_DSTBR(base) (base + 0xC4)
|
||||
#define MSS_DMA_CTRLR(base) (base + 0xC8)
|
||||
#define MSS_M3_RSTCR(base) (base + 0xFC)
|
||||
|
||||
#define MSS_DMA_CTRLR_SIZE_OFFSET (0)
|
||||
#define MSS_DMA_CTRLR_REQ_OFFSET (15)
|
||||
#define MSS_DMA_CTRLR_REQ_SET (1)
|
||||
#define MSS_DMA_CTRLR_ACK_OFFSET (12)
|
||||
#define MSS_DMA_CTRLR_ACK_MASK (0x1)
|
||||
#define MSS_DMA_CTRLR_ACK_READY (1)
|
||||
#define MSS_M3_RSTCR_RST_OFFSET (0)
|
||||
#define MSS_M3_RSTCR_RST_OFF (1)
|
||||
|
||||
#define MSS_FW_READY_MAGIC 0x46575144 /* FWRD */
|
||||
|
||||
#define MSS_AP_REGS_OFFSET 0x00580000
|
||||
#define MSS_CP_SRAM_OFFSET 0x00220000
|
||||
#define MSS_CP_REGS_OFFSET 0x00280000
|
||||
|
||||
void mss_start_cp_cm3(int cp);
|
||||
|
||||
#endif /* MSS_DEFS_H */
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <lib/psci/psci.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <mss_pm_ipc.h>
|
||||
|
||||
/*
|
||||
* SISR is 32 bit interrupt register representing 32 interrupts
|
||||
*
|
||||
* +======+=============+=============+
|
||||
* + Bits + 31 + 30 - 00 +
|
||||
* +======+=============+=============+
|
||||
* + Desc + MSS Msg Int + Reserved +
|
||||
* +======+=============+=============+
|
||||
*/
|
||||
#define MSS_SISR (MVEBU_REGS_BASE + 0x5800D0)
|
||||
#define MSS_SISTR (MVEBU_REGS_BASE + 0x5800D8)
|
||||
|
||||
#define MSS_MSG_INT_MASK (0x80000000)
|
||||
#define MSS_TIMER_BASE (MVEBU_REGS_BASE_MASK + 0x580110)
|
||||
#define MSS_TRIGGER_TIMEOUT (2000)
|
||||
|
||||
/*****************************************************************************
|
||||
* mss_pm_ipc_msg_send
|
||||
*
|
||||
* DESCRIPTION: create and transmit IPC message
|
||||
*****************************************************************************
|
||||
*/
|
||||
int mss_pm_ipc_msg_send(unsigned int channel_id, unsigned int msg_id,
|
||||
const psci_power_state_t *target_state)
|
||||
{
|
||||
/* Transmit IPC message */
|
||||
#ifndef DISABLE_CLUSTER_LEVEL
|
||||
mv_pm_ipc_msg_tx(channel_id, msg_id,
|
||||
(unsigned int)target_state->pwr_domain_state[
|
||||
MPIDR_AFFLVL1]);
|
||||
#else
|
||||
mv_pm_ipc_msg_tx(channel_id, msg_id, 0);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* mss_pm_ipc_msg_trigger
|
||||
*
|
||||
* DESCRIPTION: Trigger IPC message interrupt to MSS
|
||||
*****************************************************************************
|
||||
*/
|
||||
int mss_pm_ipc_msg_trigger(void)
|
||||
{
|
||||
unsigned int timeout;
|
||||
unsigned int t_end;
|
||||
unsigned int t_start = mmio_read_32(MSS_TIMER_BASE);
|
||||
|
||||
mmio_write_32(MSS_SISR, MSS_MSG_INT_MASK);
|
||||
|
||||
do {
|
||||
/* wait while SCP process incoming interrupt */
|
||||
if (mmio_read_32(MSS_SISTR) != MSS_MSG_INT_MASK)
|
||||
break;
|
||||
|
||||
/* check timeout */
|
||||
t_end = mmio_read_32(MSS_TIMER_BASE);
|
||||
|
||||
timeout = ((t_start > t_end) ?
|
||||
(t_start - t_end) : (t_end - t_start));
|
||||
if (timeout > MSS_TRIGGER_TIMEOUT) {
|
||||
ERROR("PM MSG Trigger Timeout\n");
|
||||
break;
|
||||
}
|
||||
|
||||
} while (1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef MSS_PM_IPC_H
|
||||
#define MSS_PM_IPC_H
|
||||
|
||||
#include <mss_ipc_drv.h>
|
||||
|
||||
/* Currently MSS does not support Cluster level Power Down */
|
||||
#define DISABLE_CLUSTER_LEVEL
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* mss_pm_ipc_msg_send
|
||||
*
|
||||
* DESCRIPTION: create and transmit IPC message
|
||||
*****************************************************************************
|
||||
*/
|
||||
int mss_pm_ipc_msg_send(unsigned int channel_id, unsigned int msg_id,
|
||||
const psci_power_state_t *target_state);
|
||||
|
||||
/*****************************************************************************
|
||||
* mss_pm_ipc_msg_trigger
|
||||
*
|
||||
* DESCRIPTION: Trigger IPC message interrupt to MSS
|
||||
*****************************************************************************
|
||||
*/
|
||||
int mss_pm_ipc_msg_trigger(void);
|
||||
|
||||
|
||||
#endif /* MSS_PM_IPC_H */
|
||||
Reference in New Issue
Block a user