feat(gic): add support for local chip addressing

This patch adds support for Local Chip Addressing (LCA). In a multi-chip
system, enablig LCA allows each GIC Distributor to maintain its own
version of routing table. This feature is activated when the
GICD_CFGID.LCA bit is set to 1.

The existing `gic600_multichip_data` data structure did not account for
the LCA feature. To support LCA:
- `rt_owner_base` is replaced by `base_addrs[]`. This is required
  because each GICD in the system needs to be configured independently,
  and their base addresses must be passed to the driver.
- `chip_addrs` is changed from 1D to 2D array to store the routing table
  for each chip's GICD. The entries in `chip_addrs` are configuration
  dependent, as the GIC specification does not enforce this.

On a multi-chip platform with chip count N where LCA is enabled by
default, the `gic600_multichip_data` structure should contain all copies
of the routing table (N*N entries). On platforms where LCA is not
supported, only the first sub-array with N entries is required. The
function signature of `gic600_multichip_init` remains unchanged, but if
the LCA feature is enabled, the driver will expect the routing table
configuration in the described format.

Change-Id: I8830c2cf90db6a0cae78e99914cd32c637284a2b
Signed-off-by: Jerry Wang <Jerry.Wang4@arm.com>
This commit is contained in:
Jerry Wang 2024-09-17 00:38:52 +01:00 committed by Jerry.Wang4
parent fffde230ba
commit c89438bcea
8 changed files with 134 additions and 50 deletions

View file

@ -321,13 +321,41 @@ static void gic700_multichip_validate_data(
}
}
/*******************************************************************************
* Initialize GIC-600 and GIC-700 Multichip operation in LCA mode by setting up
* the routing table first.
******************************************************************************/
static void gic600_multichip_lca_init(
struct gic600_multichip_data *multichip_data)
{
unsigned int i, j;
unsigned int rt_owner = multichip_data->rt_owner;
for (i = 0; i < multichip_data->chip_count; i++) {
for (j = 0; j < multichip_data->chip_count; j++) {
INFO("RT(LCA): CHIP%u -> CHIP%u 0x%lx\n", i, j,
multichip_data->chip_addrs[i][j]);
set_gicd_chipr_n(multichip_data->base_addrs[i], j,
multichip_data->chip_addrs[i][j],
multichip_data->spi_ids[j].spi_id_min,
multichip_data->spi_ids[j].spi_id_max);
}
}
/* Initialize the GICD which is marked as routing table owner last */
set_gicd_dchipr_rt_owner(multichip_data->base_addrs[rt_owner],
rt_owner);
}
/*******************************************************************************
* Initialize GIC-600 and GIC-700 Multichip operation.
******************************************************************************/
void gic600_multichip_init(struct gic600_multichip_data *multichip_data)
{
unsigned int i;
uint32_t gicd_iidr_val = gicd_read_iidr(multichip_data->rt_owner_base);
unsigned int rt_owner = multichip_data->rt_owner;
uint32_t gicd_iidr_val =
gicd_read_iidr(multichip_data->base_addrs[rt_owner]);
if ((gicd_iidr_val & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) {
gic600_multichip_validate_data(multichip_data);
@ -341,16 +369,16 @@ void gic600_multichip_init(struct gic600_multichip_data *multichip_data)
* Ensure that G0/G1S/G1NS interrupts are disabled. This also ensures
* that GIC-600 Multichip configuration is done first.
*/
if ((gicd_read_ctlr(multichip_data->rt_owner_base) &
(CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT |
CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) {
if ((gicd_read_ctlr(multichip_data->base_addrs[rt_owner]) &
(CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT |
CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) {
ERROR("GICD_CTLR group interrupts are either enabled or have "
"pending writes.\n");
panic();
}
/* Ensure that the routing table owner is in disconnected state */
if (((read_gicd_chipsr(multichip_data->rt_owner_base) &
if (((read_gicd_chipsr(multichip_data->base_addrs[rt_owner]) &
GICD_CHIPSR_RTS_MASK) >> GICD_CHIPSR_RTS_SHIFT) !=
GICD_CHIPSR_RTS_STATE_DISCONNECTED) {
ERROR("GIC-600 routing table owner is not in disconnected "
@ -358,25 +386,34 @@ void gic600_multichip_init(struct gic600_multichip_data *multichip_data)
panic();
}
/* Initialize the GICD which is marked as routing table owner first */
set_gicd_dchipr_rt_owner(multichip_data->rt_owner_base,
multichip_data->rt_owner);
/* If LCA is not enabled */
if ((read_gicd_cfgid(multichip_data->base_addrs[rt_owner]) &
GICD_CFGID_LCA_BIT) == 0) {
/*
* Initialize the GICD which is marked as routing table
* owner first.
*/
set_gicd_dchipr_rt_owner(multichip_data->base_addrs[rt_owner],
rt_owner);
set_gicd_chipr_n(multichip_data->rt_owner_base, multichip_data->rt_owner,
multichip_data->chip_addrs[multichip_data->rt_owner],
multichip_data->
spi_ids[multichip_data->rt_owner].spi_id_min,
multichip_data->
spi_ids[multichip_data->rt_owner].spi_id_max);
set_gicd_chipr_n(multichip_data->base_addrs[rt_owner], rt_owner,
multichip_data->chip_addrs[rt_owner][rt_owner],
multichip_data->spi_ids[rt_owner].spi_id_min,
multichip_data->spi_ids[rt_owner].spi_id_max);
for (i = 0; i < multichip_data->chip_count; i++) {
if (i == multichip_data->rt_owner)
continue;
set_gicd_chipr_n(multichip_data->rt_owner_base, i,
multichip_data->chip_addrs[i],
for (i = 0; i < multichip_data->chip_count; i++) {
if (i == rt_owner)
continue;
set_gicd_chipr_n(
multichip_data->base_addrs[rt_owner], i,
multichip_data->chip_addrs[rt_owner][i],
multichip_data->spi_ids[i].spi_id_min,
multichip_data->spi_ids[i].spi_id_max);
}
} else {
/* If LCA is enabled */
INFO("GIC Local chip addressing is enabled\n");
gic600_multichip_lca_init(multichip_data);
}
plat_gic_multichip_data = multichip_data;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2023, ARM Limited. All rights reserved.
* Copyright (c) 2019-2024, ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -15,12 +15,14 @@
#define GICD_CHIPSR U(0xC000)
#define GICD_DCHIPR U(0xC004)
#define GICD_CHIPR U(0xC008)
#define GICD_CFGID U(0xF000)
/* GIC600 GICD multichip related masks */
#define GICD_CHIPRx_PUP_BIT BIT_64(1)
#define GICD_CHIPRx_SOCKET_STATE BIT_64(0)
#define GICD_DCHIPR_PUP_BIT BIT_32(0)
#define GICD_CHIPSR_RTS_MASK (BIT_32(4) | BIT_32(5))
#define GICD_CFGID_LCA_BIT BIT_64(21)
/* GIC600 GICD multichip related shifts */
#define GICD_CHIPRx_ADDR_SHIFT 16
@ -98,6 +100,11 @@ static inline uint32_t read_gicd_chipsr(uintptr_t base)
return mmio_read_32(base + GICD_CHIPSR);
}
static inline uint64_t read_gicd_cfgid(uintptr_t base)
{
return mmio_read_64(base + GICD_CFGID);
}
static inline void write_gicd_dchipr(uintptr_t base, uint32_t val)
{
mmio_write_32(base + GICD_DCHIPR, val);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, ARM Limited. All rights reserved.
* Copyright (c) 2019-2024, ARM Limited. All rights reserved.
* Copyright (c) 2023, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@ -49,10 +49,10 @@ typedef struct multichip_spi_ids_desc {
* value of {0, 0, 0} should be passed.
******************************************************************************/
struct gic600_multichip_data {
uintptr_t rt_owner_base;
uintptr_t base_addrs[GIC600_MAX_MULTICHIP];
unsigned int rt_owner;
unsigned int chip_count;
uint64_t chip_addrs[GIC600_MAX_MULTICHIP];
uint64_t chip_addrs[GIC600_MAX_MULTICHIP][GIC600_MAX_MULTICHIP];
multichip_spi_ids_desc_t spi_ids[GIC600_MAX_MULTICHIP];
};

View file

@ -17,6 +17,8 @@
#include "n1sdp_private.h"
#include <platform_def.h>
#define RT_OWNER 0
/*
* Platform information structure stored in SDS.
* This structure holds information about platform's DDR
@ -44,12 +46,16 @@ static scmi_channel_plat_info_t n1sdp_scmi_plat_info = {
};
static struct gic600_multichip_data n1sdp_multichip_data __init = {
.rt_owner_base = PLAT_ARM_GICD_BASE,
.rt_owner = 0,
.base_addrs = {
PLAT_ARM_GICD_BASE
},
.rt_owner = RT_OWNER,
.chip_count = 1,
.chip_addrs = {
PLAT_ARM_GICD_BASE >> 16,
PLAT_ARM_GICD_BASE >> 16
[RT_OWNER] = {
PLAT_ARM_GICD_BASE >> 16,
PLAT_ARM_GICD_BASE >> 16
}
},
.spi_ids = {
{PLAT_ARM_GICD_BASE, 32, 511},

View file

@ -11,6 +11,8 @@
#include <nrd_plat.h>
#define RT_OWNER 0
#if defined(IMAGE_BL31)
static const mmap_region_t rdn1edge_dynamic_mmap[] = {
NRD_CSS_SHARED_RAM_MMAP(1),
@ -19,12 +21,17 @@ static const mmap_region_t rdn1edge_dynamic_mmap[] = {
};
static struct gic600_multichip_data rdn1e1_multichip_data __init = {
.rt_owner_base = PLAT_ARM_GICD_BASE,
.rt_owner = 0,
.base_addrs = {
PLAT_ARM_GICD_BASE
},
.rt_owner = RT_OWNER,
.chip_count = NRD_CHIP_COUNT,
.chip_addrs = {
PLAT_ARM_GICD_BASE >> 16,
(PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16
[RT_OWNER] = {
PLAT_ARM_GICD_BASE >> 16,
(PLAT_ARM_GICD_BASE
+ NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16
}
},
.spi_ids = {
{PLAT_ARM_GICD_BASE,

View file

@ -13,6 +13,8 @@
#include <nrd_plat.h>
#include <rdn2_ras.h>
#define RT_OWNER 0
#if defined(IMAGE_BL31)
#if (NRD_PLATFORM_VARIANT == 2)
static const mmap_region_t rdn2mc_dynamic_mmap[] = {
@ -33,20 +35,27 @@ static const mmap_region_t rdn2mc_dynamic_mmap[] = {
#if (NRD_PLATFORM_VARIANT == 2)
static struct gic600_multichip_data rdn2mc_multichip_data __init = {
.rt_owner_base = PLAT_ARM_GICD_BASE,
.rt_owner = 0,
.base_addrs = {
PLAT_ARM_GICD_BASE
},
.rt_owner = RT_OWNER,
.chip_count = NRD_CHIP_COUNT,
.chip_addrs = {
PLAT_ARM_GICD_BASE >> 16,
[RT_OWNER] = {
PLAT_ARM_GICD_BASE >> 16,
#if NRD_CHIP_COUNT > 1
(PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
(PLAT_ARM_GICD_BASE
+ NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
#endif
#if NRD_CHIP_COUNT > 2
(PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
(PLAT_ARM_GICD_BASE
+ NRD_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
#endif
#if NRD_CHIP_COUNT > 3
(PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
(PLAT_ARM_GICD_BASE
+ NRD_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
#endif
}
},
.spi_ids = {
{PLAT_ARM_GICD_BASE,

View file

@ -11,6 +11,8 @@
#include <nrd_plat.h>
#define RT_OWNER 0
#if defined(IMAGE_BL31)
static const mmap_region_t rdv1mc_dynamic_mmap[] = {
NRD_CSS_SHARED_RAM_MMAP(1),
@ -29,18 +31,25 @@ static const mmap_region_t rdv1mc_dynamic_mmap[] = {
};
static struct gic600_multichip_data rdv1mc_multichip_data __init = {
.rt_owner_base = PLAT_ARM_GICD_BASE,
.rt_owner = 0,
.base_addrs = {
PLAT_ARM_GICD_BASE
},
.rt_owner = RT_OWNER,
.chip_count = NRD_CHIP_COUNT,
.chip_addrs = {
PLAT_ARM_GICD_BASE >> 16,
(PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
[RT_OWNER] = {
PLAT_ARM_GICD_BASE >> 16,
(PLAT_ARM_GICD_BASE
+ NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
#if (NRD_CHIP_COUNT > 2)
(PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
(PLAT_ARM_GICD_BASE
+ NRD_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
#endif
#if (NRD_CHIP_COUNT > 3)
(PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
(PLAT_ARM_GICD_BASE
+ NRD_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
#endif
}
},
.spi_ids = {
{PLAT_ARM_GICD_BASE,

View file

@ -15,6 +15,8 @@
#include <nrd_variant.h>
#include <rdv3_rse_comms.h>
#define RT_OWNER 0
#if (NRD_PLATFORM_VARIANT == 2)
static const mmap_region_t rdv3mc_dynamic_mmap[] = {
#if NRD_CHIP_COUNT > 1
@ -32,20 +34,27 @@ static const mmap_region_t rdv3mc_dynamic_mmap[] = {
};
static struct gic600_multichip_data rdv3mc_multichip_data __init = {
.rt_owner_base = PLAT_ARM_GICD_BASE,
.rt_owner = 0,
.base_addrs = {
PLAT_ARM_GICD_BASE
},
.rt_owner = RT_OWNER,
.chip_count = NRD_CHIP_COUNT,
.chip_addrs = {
PLAT_ARM_GICD_BASE >> 16,
[RT_OWNER] = {
PLAT_ARM_GICD_BASE >> 16,
#if NRD_CHIP_COUNT > 1
(PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
(PLAT_ARM_GICD_BASE
+ NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
#endif
#if NRD_CHIP_COUNT > 2
(PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
(PLAT_ARM_GICD_BASE
+ NRD_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
#endif
#if NRD_CHIP_COUNT > 3
(PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
(PLAT_ARM_GICD_BASE
+ NRD_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
#endif
}
},
.spi_ids = {
{PLAT_ARM_GICD_BASE, 32, 511},