|
1 | 1 | /* |
2 | 2 | * Copyright 2020 Broadcom |
3 | 3 | * Copyright 2024 NXP |
| 4 | + * Copyright 2025 Arm Limited and/or its affiliates <[email protected]> |
4 | 5 | * |
5 | 6 | * SPDX-License-Identifier: Apache-2.0 |
6 | 7 | */ |
|
20 | 21 |
|
21 | 22 | #define DT_DRV_COMPAT arm_gic_v3 |
22 | 23 |
|
| 24 | +#define GIC_V3_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(DT_DRV_COMPAT) |
| 25 | + |
| 26 | +#define GIC_REDISTRIBUTOR_STRIDE DT_PROP_OR(GIC_V3_NODE, redistributor_stride, 0) |
| 27 | +#define GIC_NUM_REDISTRIBUTOR_REGIONS DT_PROP_OR(GIC_V3_NODE, redistributor_regions, 1) |
| 28 | + |
| 29 | +#define GIC_REG_REGION(idx, node_id) \ |
| 30 | + { \ |
| 31 | + .base = DT_REG_ADDR_BY_IDX(node_id, idx), \ |
| 32 | + .size = DT_REG_SIZE_BY_IDX(node_id, idx), \ |
| 33 | + } |
| 34 | + |
| 35 | +/* |
| 36 | + * Structure to save GIC register region info |
| 37 | + */ |
| 38 | +struct gic_reg_region { |
| 39 | + mem_addr_t base; |
| 40 | + mem_addr_t size; |
| 41 | +}; |
| 42 | + |
| 43 | +/* |
| 44 | + * GIC register regions info table |
| 45 | + */ |
| 46 | +static struct gic_reg_region gic_reg_regions[] = { |
| 47 | + LISTIFY(DT_NUM_REGS(GIC_V3_NODE), GIC_REG_REGION, (,), GIC_V3_NODE) |
| 48 | +}; |
| 49 | + |
| 50 | + |
23 | 51 | /* Redistributor base addresses for each core */ |
24 | 52 | mem_addr_t gic_rdists[CONFIG_MP_MAX_NUM_CPUS]; |
25 | 53 |
|
@@ -578,20 +606,34 @@ static inline uint64_t arm_gic_get_typer(mem_addr_t addr) |
578 | 606 | static mem_addr_t arm_gic_iterate_rdists(void) |
579 | 607 | { |
580 | 608 | uint64_t aff = arm_gic_mpidr_to_affinity(GET_MPIDR()); |
| 609 | + uint32_t idx; |
581 | 610 |
|
582 | | - for (mem_addr_t rdist_addr = GIC_RDIST_BASE; |
583 | | - rdist_addr < GIC_RDIST_BASE + GIC_RDIST_SIZE; |
584 | | - rdist_addr += 0x20000) { |
585 | | - uint64_t val = arm_gic_get_typer(rdist_addr + GICR_TYPER); |
586 | | - uint64_t gicr_aff = GICR_TYPER_AFFINITY_VALUE_GET(val); |
| 611 | + /* Skip the first array entry as it refers to the GIC distributor */ |
| 612 | + for (idx = 1; idx < GIC_NUM_REDISTRIBUTOR_REGIONS + 1; idx++) { |
| 613 | + uint64_t val; |
| 614 | + mem_addr_t rdist_addr = gic_reg_regions[idx].base; |
| 615 | + mem_addr_t rdist_end = rdist_addr + gic_reg_regions[idx].size; |
587 | 616 |
|
588 | | - if (arm_gic_aff_matching(gicr_aff, aff)) { |
589 | | - return rdist_addr; |
590 | | - } |
| 617 | + do { |
| 618 | + val = arm_gic_get_typer(rdist_addr + GICR_TYPER); |
| 619 | + uint64_t gicr_aff = GICR_TYPER_AFFINITY_VALUE_GET(val); |
591 | 620 |
|
592 | | - if (GICR_TYPER_LAST_GET(val) == 1) { |
593 | | - return (mem_addr_t)NULL; |
594 | | - } |
| 621 | + if (arm_gic_aff_matching(gicr_aff, aff)) { |
| 622 | + return rdist_addr; |
| 623 | + } |
| 624 | + |
| 625 | + if (GIC_REDISTRIBUTOR_STRIDE > 0) { |
| 626 | + rdist_addr += GIC_REDISTRIBUTOR_STRIDE; |
| 627 | + } else { |
| 628 | + /* |
| 629 | + * Skip RD_base and SGI_base |
| 630 | + * In GICv3, GICR_TYPER.VLPIS bit is RES0 and can can be ignored |
| 631 | + * as there are no VLPI and reserved pages. |
| 632 | + */ |
| 633 | + rdist_addr += KB(64) * 2; |
| 634 | + } |
| 635 | + |
| 636 | + } while ((!GICR_TYPER_LAST_GET(val)) && (rdist_addr < rdist_end)); |
595 | 637 | } |
596 | 638 |
|
597 | 639 | return (mem_addr_t)NULL; |
|
0 commit comments