GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -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
@@ -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));
}
@@ -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));
}
@@ -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 */
@@ -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;
}
@@ -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 */