feat(s32g274a): add ncore support

Ncore is a cache-coherent interconnect module. It enables the
integration of heterogenous coherent agents and non-coherent
agents in a chip. TF-A boots with the first core in isolation
to avoid crashes due to cache invalidation operations. Later,
it will disable the isolation and reconfigure the module every
time a new core is added or removed through PSCI.

Change-Id: Ida42db91b10be1e66c3b9b73674d1e37a61844dd
Signed-off-by: Dan Nica <dan.nica@nxp.com>
Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>
Signed-off-by: Ghennadi Procopciuc <ghennadi.procopciuc@nxp.com>
This commit is contained in:
Ghennadi Procopciuc 2024-09-25 14:03:33 +03:00
parent 5765e0c95a
commit 5071f7c7ee
5 changed files with 216 additions and 8 deletions

View file

@ -0,0 +1,102 @@
/*
* Copyright 2019-2021, 2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef S32G2_NCORE_H
#define S32G2_NCORE_H
#include <stdbool.h>
#define NCORE_BASE_ADDR UL(0x50400000)
#define A53_CLUSTER0_CAIU U(0)
#define A53_CLUSTER1_CAIU U(1)
/**
* Directory Unit Registers
*
* The directory provides a point of serialization for establishing transaction
* ordering and sequences coherence operations and memory accesses.
*/
#define NCORE_DIRU(N) (NCORE_BASE_ADDR + UL(0x80000) + ((N) * UL(0x1000)))
/* DIRU Snoop Filtering Enable */
#define NCORE_DIRUSFE(N) (NCORE_DIRU(N) + UL(0x10))
#define NCORE_DIRUSFE_SFEN(SF) BIT_32(SF)
/* DIRU Caching Agent Snoop Enable */
#define NCORE_DIRUCASE(N) (NCORE_DIRU(N) + UL(0x40))
#define NCORE_DIRUCASE_CASNPEN(CAIU) BIT_32(CAIU)
/* DIRU Snoop Filter Maintenance Control */
#define NCORE_DIRUSFMC(N) (NCORE_DIRU(N) + UL(0x80))
#define NCORE_DIRUSFMC_SFID(SF) ((SF) << 16U)
#define NCORE_DIRUSFMC_SFMNTOP_ALL U(0x0)
/* DIRU Snoop Filter Maintenance Activity */
#define NCORE_DIRUSFMA(N) (NCORE_DIRU(N) + UL(0x84))
#define NCORE_DIRUSFMA_MNTOPACTV BIT_32(0)
/**
* Coherent Agent Interface Unit Registers
*
* CAI provides a means for a fully-coherent agent to be connected to the Ncore.
* The CAI behaves as a fully-coherent slave.
*/
#define NCORE_CAIU(N) (NCORE_BASE_ADDR + ((N) * UL(0x1000)))
#define NCORE_CAIU0_BASE_ADDR NCORE_BASE_ADDR
/* CAIU Transaction Control */
#define NCORE_CAIUTC_OFF UL(0x0)
#define NCORE_CAIUTC_ISOLEN_SHIFT U(1)
#define NCORE_CAIUTC_ISOLEN_MASK BIT_32(NCORE_CAIUTC_ISOLEN_SHIFT)
#define NCORE_CAIUTC(N) (NCORE_CAIU(N) + NCORE_CAIUTC_OFF)
/* CAIU Identification */
#define NCORE_CAIUID(n) (NCORE_CAIU(n) + UL(0xFFC))
#define NCORE_CAIUID_TYPE GENMASK_32(U(19), U(16))
#define NCORE_CAIUID_TYPE_ACE_DVM U(0x0)
/**
* Coherent Subsystem Registers
*/
#define NCORE_CSR (NCORE_BASE_ADDR + UL(0xFF000))
/* Coherent Subsystem ACE DVM Snoop Enable */
#define NCORE_CSADSE (NCORE_CSR + UL(0x40))
#define NCORE_CSADSE_DVMSNPEN(CAIU) BIT_32(CAIU)
/* Coherent Subsystem Identification */
#define NCORE_CSID (NCORE_CSR + UL(0xFFC))
#define NCORE_CSID_NUMSFS_SHIFT U(18)
#define NCORE_CSID_NUMSFS_MASK GENMASK_32(U(22), NCORE_CSID_NUMSFS_SHIFT)
#define NCORE_CSID_NUMSFS(CSIDR) (((CSIDR) & NCORE_CSID_NUMSFS_MASK) \
>> NCORE_CSID_NUMSFS_SHIFT)
/* Coherent Subsystem Unit Identification */
#define NCORE_CSUID (NCORE_CSR + UL(0xFF8))
#define NCORE_CSUID_NUMCMIUS_SHIFT U(24)
#define NCORE_CSUID_NUMCMIUS_MASK GENMASK_32(U(29), NCORE_CSUID_NUMCMIUS_SHIFT)
#define NCORE_CSUID_NUMCMIUS(CSUIDR) (((CSUIDR) & NCORE_CSUID_NUMCMIUS_MASK) \
>> NCORE_CSUID_NUMCMIUS_SHIFT)
#define NCORE_CSUID_NUMDIRUS_SHIFT U(16)
#define NCORE_CSUID_NUMDIRUS_MASK GENMASK_32(U(21), NCORE_CSUID_NUMDIRUS_SHIFT)
#define NCORE_CSUID_NUMDIRUS(CSUIDR) (((CSUIDR) & NCORE_CSUID_NUMDIRUS_MASK) \
>> NCORE_CSUID_NUMDIRUS_SHIFT)
#define NCORE_CSUID_NUMNCBUS_SHIFT U(8)
#define NCORE_CSUID_NUMNCBUS_MASK GENMASK_32(U(13), NCORE_CSUID_NUMNCBUS_SHIFT)
#define NCORE_CSUID_NUMNCBUS(CSUIDR) (((CSUIDR) & NCORE_CSUID_NUMNCBUS_MASK) \
>> NCORE_CSUID_NUMNCBUS_SHIFT)
#ifndef __ASSEMBLER__
void ncore_caiu_online(uint32_t caiu);
void ncore_caiu_offline(uint32_t caiu);
void ncore_init(void);
bool ncore_is_caiu_online(uint32_t caiu);
void ncore_disable_caiu_isolation(uint32_t caiu);
#endif /* __ASSEMBLER__ */
#endif /* S32G2_NCORE_H */

View file

@ -11,6 +11,7 @@
#include <plat_console.h>
#include <s32cc-clk-drv.h>
#include <plat_io_storage.h>
#include <s32cc-ncore.h>
#define SIUL2_PC09_MSCR UL(0x4009C2E4)
#define SIUL2_PC10_MSCR UL(0x4009C2E8)
@ -62,6 +63,14 @@ void bl2_el3_early_platform_setup(u_register_t arg0, u_register_t arg1,
linflex_config_pinctrl();
console_s32g2_register();
/* Restore (clear) the CAIUTC[IsolEn] bit for the primary cluster, which
* we have manually set during early BL2 boot.
*/
ncore_disable_caiu_isolation(A53_CLUSTER0_CAIU);
ncore_init();
ncore_caiu_online(A53_CLUSTER0_CAIU);
plat_s32g2_io_setup();
}

View file

@ -6,10 +6,7 @@
#include <asm_macros.S>
#include <platform_def.h>
#define S32G_NCORE_CAIU0_BASE_ADDR UL(0x50400000)
#define S32G_NCORE_CAIUTC_OFF U(0x0)
#define S32G_NCORE_CAIUTC_ISOLEN_SHIFT U(1)
#include <s32cc-ncore.h>
.globl plat_crash_console_flush
.globl plat_crash_console_init
@ -104,12 +101,12 @@ endfunc plat_secondary_cold_boot_setup
* Clobber list: x0, x1, x2
*/
func plat_reset_handler
mov x0, #S32G_NCORE_CAIU0_BASE_ADDR
ldr w1, [x0, #S32G_NCORE_CAIUTC_OFF]
mov x0, #NCORE_CAIU0_BASE_ADDR
ldr w1, [x0, #NCORE_CAIUTC_OFF]
movz w2, #1
lsl w2, w2, #S32G_NCORE_CAIUTC_ISOLEN_SHIFT
lsl w2, w2, #NCORE_CAIUTC_ISOLEN_SHIFT
orr w1, w1, w2
str w1, [x0, #S32G_NCORE_CAIUTC_OFF]
str w1, [x0, #NCORE_CAIUTC_OFF]
ret
endfunc plat_reset_handler

View file

@ -53,6 +53,7 @@ BL2_SOURCES += \
${PLAT_S32G274ARDB2}/plat_bl2_el3_setup.c \
${PLAT_S32G274ARDB2}/plat_bl2_image_desc.c \
${PLAT_S32G274ARDB2}/plat_io_storage.c \
${PLAT_S32G274ARDB2}/s32cc_ncore.c \
common/desc_image_load.c \
drivers/io/io_fip.c \
drivers/io/io_memmap.c \

View file

@ -0,0 +1,99 @@
/*
* Copyright 2019-2021, 2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <lib/mmio.h>
#include <platform_def.h>
#include <s32cc-ncore.h>
static void ncore_diru_online(uint32_t diru)
{
uint32_t numsfs, sf;
numsfs = NCORE_CSID_NUMSFS(mmio_read_32(NCORE_CSID)) + 1U;
/* Initialize all entries maintenance operation for each snoop filter */
for (sf = 0U; sf < numsfs; sf++) {
mmio_write_32(NCORE_DIRUSFMC(diru), NCORE_DIRUSFMC_SFID(sf) |
NCORE_DIRUSFMC_SFMNTOP_ALL);
while ((mmio_read_32(NCORE_DIRUSFMA(diru)) & NCORE_DIRUSFMA_MNTOPACTV) != 0U) {
}
mmio_setbits_32(NCORE_DIRUSFE(diru), NCORE_DIRUSFE_SFEN(sf));
}
}
void ncore_disable_caiu_isolation(uint32_t caiu)
{
/* Exit from low-power state */
mmio_clrbits_32(NCORE_CAIUTC(caiu), NCORE_CAIUTC_ISOLEN_MASK);
}
static void set_caiu(uint32_t caiu, bool on)
{
uint32_t dirucase, csadser, caiuidr;
uint32_t numdirus, diru;
/* Enable or disable snoop messages to the CAI for each DIRU */
numdirus = NCORE_CSUID_NUMDIRUS(mmio_read_32(NCORE_CSUID));
for (diru = 0; diru < numdirus; diru++) {
dirucase = mmio_read_32(NCORE_DIRUCASE(diru));
if (on) {
dirucase |= NCORE_DIRUCASE_CASNPEN(caiu);
} else {
dirucase &= ~NCORE_DIRUCASE_CASNPEN(caiu);
}
mmio_write_32(NCORE_DIRUCASE(diru), dirucase);
}
/* Enable or disable DVM messages to the CAI */
caiuidr = mmio_read_32(NCORE_CAIUID(caiu));
if ((caiuidr & NCORE_CAIUID_TYPE) == NCORE_CAIUID_TYPE_ACE_DVM) {
csadser = mmio_read_32(NCORE_CSADSE);
if (on) {
csadser |= NCORE_CSADSE_DVMSNPEN(caiu);
} else {
csadser &= ~NCORE_CSADSE_DVMSNPEN(caiu);
}
mmio_write_32(NCORE_CSADSE, csadser);
}
}
void ncore_caiu_online(uint32_t caiu)
{
set_caiu(caiu, true);
}
void ncore_caiu_offline(uint32_t caiu)
{
set_caiu(caiu, false);
}
bool ncore_is_caiu_online(uint32_t caiu)
{
uint32_t stat = mmio_read_32(NCORE_CSADSE);
return ((stat & NCORE_CSADSE_DVMSNPEN(caiu)) != 0U);
}
void ncore_init(void)
{
uint32_t csuidr = mmio_read_32(NCORE_CSUID);
uint32_t numdirus, diru;
numdirus = NCORE_CSUID_NUMDIRUS(csuidr);
for (diru = 0U; diru < numdirus; diru++) {
/**
* Transition the directory to an online state by ensuring that
* all DIRUs within the interface are operational.
*/
ncore_diru_online(diru);
}
}