Skip to content

Commit 104a956

Browse files
committed
drivers: intc_gicv3: enable dma-noncoherent support
GIC redistributor on Some platform are connected to a non-coherent downstream interconnect, it need to use Non-cahable and Non-shareable access atttributes to access external memory. And also flush the data cache after CPU update related memory. Signed-off-by: Jiafei Pan <[email protected]>
1 parent 4852719 commit 104a956

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

drivers/interrupt_controller/Kconfig.gic

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,13 @@ config GIC_SAFE_CONFIG
7373
crash the OS has already been started. With this enabled, it will bypass
7474
GIC distributor configuration if it has been configured by other OS.
7575

76+
config GIC_V3_RDIST_DMA_NONCOHERENT
77+
bool "GIC redistributor is DMA noncoherent"
78+
depends on GIC_V3
79+
default n
80+
help
81+
GIC redistributor on Some platform are connected to a non-coherent
82+
downstream interconnect, it need to use Non-cahable and Non-shareable
83+
access atttributes to access external memory.
84+
7685
endif # CPU_CORTEX

drivers/interrupt_controller/intc_gicv3.c

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
/*
22
* Copyright 2020 Broadcom
3-
* Copyright 2024 NXP
3+
* Copyright 2024-2025 NXP
44
* Copyright 2025 Arm Limited and/or its affiliates <[email protected]>
55
*
66
* SPDX-License-Identifier: Apache-2.0
77
*/
88

9+
#include <zephyr/cache.h>
910
#include <zephyr/device.h>
1011
#include <zephyr/kernel.h>
1112
#include <zephyr/arch/cpu.h>
@@ -111,7 +112,11 @@ static void arm_gic_lpi_setup(unsigned int intid, bool enable)
111112
*cfg &= ~BIT(0);
112113
}
113114

115+
#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT
116+
arch_dcache_flush_and_invd_range(cfg, sizeof(*cfg));
117+
#else
114118
barrier_dsync_fence_full();
119+
#endif
115120

116121
its_rdist_invall();
117122
}
@@ -123,7 +128,11 @@ static void arm_gic_lpi_set_priority(unsigned int intid, unsigned int prio)
123128
*cfg &= 0xfc;
124129
*cfg |= prio & 0xfc;
125130

131+
#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT
132+
arch_dcache_flush_and_invd_range(cfg, sizeof(*cfg));
133+
#else
126134
barrier_dsync_fence_full();
135+
#endif
127136

128137
its_rdist_invall();
129138
}
@@ -406,7 +415,7 @@ static void gicv3_rdist_setup_lpis(mem_addr_t rdist)
406415
unsigned int lpi_id_bits =
407416
MIN(GICD_TYPER_IDBITS(sys_read32(GICD_TYPER)), ITS_MAX_LPI_NRBITS);
408417
uintptr_t lpi_pend_table;
409-
uint64_t reg;
418+
uint64_t reg, tmp;
410419
uint32_t ctlr;
411420

412421
/* If not, alloc a common prop table for all redistributors */
@@ -418,6 +427,11 @@ static void gicv3_rdist_setup_lpis(mem_addr_t rdist)
418427
lpi_pend_table = (uintptr_t)k_aligned_alloc(64 * 1024, LPI_PENDBASE_SZ(lpi_id_bits));
419428
memset((void *)lpi_pend_table, 0, LPI_PENDBASE_SZ(lpi_id_bits));
420429

430+
#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT
431+
arch_dcache_flush_and_invd_range((void *)lpi_prop_table, LPI_PROPBASE_SZ(lpi_id_bits));
432+
arch_dcache_flush_and_invd_range((void *)lpi_pend_table, LPI_PENDBASE_SZ(lpi_id_bits));
433+
#endif
434+
421435
ctlr = sys_read32(rdist + GICR_CTLR);
422436
ctlr &= ~GICR_CTLR_ENABLE_LPIS;
423437
sys_write32(ctlr, rdist + GICR_CTLR);
@@ -429,15 +443,33 @@ static void gicv3_rdist_setup_lpis(mem_addr_t rdist)
429443
(GIC_BASER_CACHE_INNERLIKE << GITR_PROPBASER_OUTER_CACHE_SHIFT) |
430444
((lpi_id_bits - 1) & GITR_PROPBASER_ID_BITS_MASK);
431445
sys_write64(reg, rdist + GICR_PROPBASER);
432-
/* TOFIX: check SHAREABILITY validity */
446+
/* Check SHAREABILITY validity */
447+
tmp = sys_read64(rdist + GICR_PROPBASER);
448+
#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT
449+
tmp &= ~MASK(GITR_PROPBASER_SHAREABILITY);
450+
#endif
451+
if (!(tmp & MASK(GITR_PROPBASER_SHAREABILITY))) {
452+
reg &= ~(MASK(GITR_PROPBASER_SHAREABILITY) | MASK(GITR_PROPBASER_INNER_CACHE));
453+
reg |= GIC_BASER_CACHE_NCACHEABLE << GITR_PROPBASER_INNER_CACHE_SHIFT;
454+
sys_write64(reg, rdist + GICR_PROPBASER);
455+
}
433456

434457
/* PENDBASE */
435458
reg = (GIC_BASER_SHARE_INNER << GITR_PENDBASER_SHAREABILITY_SHIFT) |
436459
(GIC_BASER_CACHE_RAWAWB << GITR_PENDBASER_INNER_CACHE_SHIFT) |
437460
(lpi_pend_table & (GITR_PENDBASER_ADDR_MASK << GITR_PENDBASER_ADDR_SHIFT)) |
438461
(GIC_BASER_CACHE_INNERLIKE << GITR_PENDBASER_OUTER_CACHE_SHIFT) | GITR_PENDBASER_PTZ;
439462
sys_write64(reg, rdist + GICR_PENDBASER);
440-
/* TOFIX: check SHAREABILITY validity */
463+
/* Check SHAREABILITY validity */
464+
tmp = sys_read64(rdist + GICR_PENDBASER);
465+
#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT
466+
tmp &= ~MASK(GITR_PENDBASER_SHAREABILITY);
467+
#endif
468+
if (!(tmp & MASK(GITR_PENDBASER_SHAREABILITY))) {
469+
reg &= ~(MASK(GITR_PENDBASER_SHAREABILITY) | MASK(GITR_PENDBASER_INNER_CACHE));
470+
reg |= GIC_BASER_CACHE_NCACHEABLE << GITR_PENDBASER_INNER_CACHE_SHIFT;
471+
sys_write64(reg, rdist + GICR_PENDBASER);
472+
}
441473

442474
ctlr = sys_read32(rdist + GICR_CTLR);
443475
ctlr |= GICR_CTLR_ENABLE_LPIS;

0 commit comments

Comments
 (0)