Skip to content

Commit

Permalink
drivers: gic: Add multiple GIC redistributors regions support
Browse files Browse the repository at this point in the history
For GIC multiple views feature support, all GIC Re-distributor's
GICR_TYPER.last will be set. Because configuration view-0 can
assign non-contiguous CPUs to views other than 0, in this case
the GIC Redistributors' registers won't seem contiguous.

So the GIC driver should cope with multiple sets of redistributors
like multi-chip scenarios. In this patch we add multiple GIC
redistributor regions support in GIC redistributor iteration.

For more information, refer to the Multi view subsection
in the GIC Technical Reference Manual.
For example:
https://developer.arm.com/documentation/101516/0400/Operation-of-GIC-700/Multi-view

Signed-off-by: Ziad Elhanafy <[email protected]>
  • Loading branch information
ZiadElhanafy committed Jan 14, 2025
1 parent b7b3449 commit 42c95ef
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 18 deletions.
64 changes: 53 additions & 11 deletions drivers/interrupt_controller/intc_gicv3.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
* Copyright 2020 Broadcom
* Copyright 2024 NXP
* Copyright 2025 Arm Limited and/or its affiliates <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -20,6 +21,33 @@

#define DT_DRV_COMPAT arm_gic_v3

#define GIC_V3_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(DT_DRV_COMPAT)

#define GIC_REDISTRIBUTOR_STRIDE DT_PROP_OR(GIC_V3_NODE, redistributor_stride, 0)
#define GIC_NUM_REDISTRIBUTOR_REGIONS DT_PROP_OR(GIC_V3_NODE, redistributor_regions, 1)

#define GIC_REG_REGION(idx, node_id) \
{ \
.base = DT_REG_ADDR_BY_IDX(node_id, idx), \
.size = DT_REG_SIZE_BY_IDX(node_id, idx), \
}

/*
* Structure to save GIC register region info
*/
struct gic_reg_region {
mem_addr_t base;
mem_addr_t size;
};

/*
* GIC register regions info table
*/
static struct gic_reg_region gic_reg_regions[] = {
LISTIFY(DT_NUM_REGS(GIC_V3_NODE), GIC_REG_REGION, (,), GIC_V3_NODE)
};


/* Redistributor base addresses for each core */
mem_addr_t gic_rdists[CONFIG_MP_MAX_NUM_CPUS];

Expand Down Expand Up @@ -578,20 +606,34 @@ static inline uint64_t arm_gic_get_typer(mem_addr_t addr)
static mem_addr_t arm_gic_iterate_rdists(void)
{
uint64_t aff = arm_gic_mpidr_to_affinity(GET_MPIDR());
uint32_t idx;

for (mem_addr_t rdist_addr = GIC_RDIST_BASE;
rdist_addr < GIC_RDIST_BASE + GIC_RDIST_SIZE;
rdist_addr += 0x20000) {
uint64_t val = arm_gic_get_typer(rdist_addr + GICR_TYPER);
uint64_t gicr_aff = GICR_TYPER_AFFINITY_VALUE_GET(val);
/* Skip the first array entry as it refers to the GIC distributor */
for (idx = 1; idx < GIC_NUM_REDISTRIBUTOR_REGIONS + 1; idx++) {
uint64_t val;
mem_addr_t rdist_addr = gic_reg_regions[idx].base;
mem_addr_t rdist_end = rdist_addr + gic_reg_regions[idx].size;

if (arm_gic_aff_matching(gicr_aff, aff)) {
return rdist_addr;
}
do {
val = arm_gic_get_typer(rdist_addr + GICR_TYPER);
uint64_t gicr_aff = GICR_TYPER_AFFINITY_VALUE_GET(val);

if (GICR_TYPER_LAST_GET(val) == 1) {
return (mem_addr_t)NULL;
}
if (arm_gic_aff_matching(gicr_aff, aff)) {
return rdist_addr;
}

if (GIC_REDISTRIBUTOR_STRIDE > 0) {
rdist_addr += GIC_REDISTRIBUTOR_STRIDE;
} else {
/*
* Skip RD_base and SGI_base
* In GICv3, GICR_TYPER.VLPIS bit is RES0 and can can be ignored
* as there are no VLPI and reserved pages.
*/
rdist_addr += KB(64) * 2;
}

} while ((!GICR_TYPER_LAST_GET(val)) && (rdist_addr < rdist_end));
}

return (mem_addr_t)NULL;
Expand Down
8 changes: 1 addition & 7 deletions drivers/interrupt_controller/intc_gicv3_priv.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright 2020 Broadcom
* Copyright 2025 Arm Limited and/or its affiliates <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -25,13 +26,6 @@
#define GIC_BASER_SHARE_INNER 0x1UL /* Inner Shareable */
#define GIC_BASER_SHARE_OUTER 0x2UL /* Outer Shareable */

/*
* GIC Register Interface Base Addresses
*/

#define GIC_RDIST_BASE DT_REG_ADDR_BY_IDX(DT_INST(0, arm_gic), 1)
#define GIC_RDIST_SIZE DT_REG_SIZE_BY_IDX(DT_INST(0, arm_gic), 1)

/* SGI base is at 64K offset from Redistributor */
#define GICR_SGI_BASE_OFF 0x10000

Expand Down
46 changes: 46 additions & 0 deletions dts/bindings/interrupt-controller/arm,gic-v3.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,53 @@
#
# Copyright 2025 Arm Limited and/or its affiliates <[email protected]>
#
# SPDX-License-Identifier: Apache-2.0
#

description: ARM Generic Interrupt Controller v3

compatible: arm,gic-v3

include: arm,gic.yaml

properties:
redistributor-stride:
type: int
description:
If using padding pages, specifies the stride of consecutive
redistributors which is the distance between consecutive redistributors in
memory. Must be a multiple of 64kB. Required if the distance between
redistributors is not the default 128kB.

redistributor-regions:
type: int
description:
The number of independent contiguous regions occupied by the redistributors.
The term "regions" refers to distinct memory segments or areas allocated
for redistributors within the system memory. The number of redistributor
regions and their sizes are hardware-specific. Required if more than one
such region is present.

examples:
- |
gic: interrupt-controller@2cf00000 {
compatible = "arm,gic-v3", "arm,gic";
reg = <0x2f000000 0x10000>, /* GICD */
<0x2f100000 0x200000>; /* GICR */
interrupt-controller;
#interrupt-cells = <3>;
status = "okay";
};
- |
gic: interrupt-controller@2c010000 {
compatible = "arm,gic-v3", "arm,gic";
redistributor-stride = <0x40000>; /* 256kB stride */
redistributor-regions = <2>;
reg = <0x2c010000 0x10000>, /* GICD */
<0x2d000000 0x800000>, /* GICR 1: CPUs 0-31 */
<0x2e000000 0x800000>; /* GICR 2: CPUs 32-63 */
interrupt-controller;
#interrupt-cells = <4>;
status = "okay";
};

0 comments on commit 42c95ef

Please sign in to comment.