diff --git a/drivers/interrupt_controller/intc_gicv3.c b/drivers/interrupt_controller/intc_gicv3.c index c84a42c7e363..50e36f1e87ae 100644 --- a/drivers/interrupt_controller/intc_gicv3.c +++ b/drivers/interrupt_controller/intc_gicv3.c @@ -1,6 +1,7 @@ /* * Copyright 2020 Broadcom * Copyright 2024 NXP + * Copyright 2025 Arm Limited and/or its affiliates * * SPDX-License-Identifier: Apache-2.0 */ @@ -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]; @@ -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; diff --git a/drivers/interrupt_controller/intc_gicv3_priv.h b/drivers/interrupt_controller/intc_gicv3_priv.h index 64fabe215376..30c7a6fa84dd 100644 --- a/drivers/interrupt_controller/intc_gicv3_priv.h +++ b/drivers/interrupt_controller/intc_gicv3_priv.h @@ -1,5 +1,6 @@ /* * Copyright 2020 Broadcom + * Copyright 2025 Arm Limited and/or its affiliates * * SPDX-License-Identifier: Apache-2.0 */ @@ -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 diff --git a/dts/bindings/interrupt-controller/arm,gic-v3.yaml b/dts/bindings/interrupt-controller/arm,gic-v3.yaml index 8fc5851d62cf..fed263f62733 100644 --- a/dts/bindings/interrupt-controller/arm,gic-v3.yaml +++ b/dts/bindings/interrupt-controller/arm,gic-v3.yaml @@ -1,7 +1,53 @@ +# +# Copyright 2025 Arm Limited and/or its affiliates +# # SPDX-License-Identifier: Apache-2.0 +# -description: ARM Generic Interrupt Controller v3 +description: | + ARM Generic Interrupt Controller v3 + + Examples for GICv3 devicetree nodes: + + 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"; + }; 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.