Skip to content

Commit 8f425d2

Browse files
committed
drivers: gicv3_its: enable dma noncoherent support
Add DMA noncoherent support on GICv3 ITS driver. Signed-off-by: Jiafei Pan <[email protected]>
1 parent 104a956 commit 8f425d2

File tree

1 file changed

+45
-5
lines changed

1 file changed

+45
-5
lines changed

drivers/interrupt_controller/intc_gicv3_its.c

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
/*
22
* Copyright 2021 BayLibre, SAS
3+
* Copyright 2025 NXP
34
*
45
* SPDX-License-Identifier: Apache-2.0
56
*/
67

78
#include <zephyr/logging/log.h>
89
LOG_MODULE_REGISTER(intc_gicv3_its, LOG_LEVEL_ERR);
910

11+
#include <zephyr/cache.h>
1012
#include <zephyr/kernel.h>
1113
#include <zephyr/device.h>
1214
#include <zephyr/drivers/interrupt_controller/gicv3_its.h>
@@ -39,6 +41,9 @@ struct its_cmd_block {
3941
#define ITS_CMD_QUEUE_SIZE SIZE_64K
4042
#define ITS_CMD_QUEUE_NR_ENTRIES (ITS_CMD_QUEUE_SIZE / sizeof(struct its_cmd_block))
4143

44+
/* The level 1 entry size is a 64bit pointer */
45+
#define GITS_LVL1_ENTRY_SIZE (8UL)
46+
4247
struct gicv3_its_data {
4348
mm_reg_t base;
4449
struct its_cmd_block *cmd_base;
@@ -190,8 +195,7 @@ static int its_alloc_tables(struct gicv3_its_data *data)
190195
lvl2_width = fls_z(page_size / entry_size) - 1;
191196
device_ids -= lvl2_width + 1;
192197

193-
/* The level 1 entry size is a 64bit pointer */
194-
entry_size = sizeof(uint64_t);
198+
entry_size = GITS_LVL1_ENTRY_SIZE;
195199

196200
indirect = true;
197201
}
@@ -229,13 +233,22 @@ static int its_alloc_tables(struct gicv3_its_data *data)
229233
}
230234

231235
reg |= MASK_SET(page_cnt - 1, GITS_BASER_SIZE);
232-
reg |= MASK_SET(GIC_BASER_SHARE_INNER, GITS_BASER_SHAREABILITY);
233236
reg |= MASK_SET((uintptr_t)alloc_addr >> GITS_BASER_ADDR_SHIFT, GITS_BASER_ADDR);
234237
reg |= MASK_SET(GIC_BASER_CACHE_INNERLIKE, GITS_BASER_OUTER_CACHE);
238+
#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT
239+
reg |= MASK_SET(GIC_BASER_SHARE_NO, GITS_BASER_SHAREABILITY);
240+
reg |= MASK_SET(GIC_BASER_CACHE_NCACHEABLE, GITS_BASER_INNER_CACHE);
241+
#else
242+
reg |= MASK_SET(GIC_BASER_SHARE_INNER, GITS_BASER_SHAREABILITY);
235243
reg |= MASK_SET(GIC_BASER_CACHE_RAWAWB, GITS_BASER_INNER_CACHE);
244+
#endif
236245
reg |= MASK_SET(indirect ? 1 : 0, GITS_BASER_INDIRECT);
237246
reg |= MASK_SET(1, GITS_BASER_VALID);
238247

248+
#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT
249+
arch_dcache_flush_and_invd_range(alloc_addr, page_size * page_cnt);
250+
#endif
251+
239252
sys_write64(reg, data->base + GITS_BASER(i));
240253

241254
/* TOFIX: check page size & SHAREABILITY validity after write */
@@ -300,6 +313,10 @@ static int its_post_command(struct gicv3_its_data *data, struct its_cmd_block *c
300313
uint64_t wr_idx, rd_idx, idx;
301314
unsigned int count = 1000000; /* 1s! */
302315

316+
#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT
317+
arch_dcache_flush_and_invd_range(cmd, sizeof(*cmd));
318+
#endif
319+
303320
wr_idx = (data->cmd_write - data->cmd_base) * sizeof(*cmd);
304321
rd_idx = sys_read32(data->base + GITS_CREADR);
305322

@@ -426,7 +443,6 @@ static int its_send_invall_cmd(struct gicv3_its_data *data, uint32_t icid)
426443
static int gicv3_its_send_int(const struct device *dev, uint32_t device_id, uint32_t event_id)
427444
{
428445
struct gicv3_its_data *data = dev->data;
429-
430446
/* TOFIX check device_id & event_id bounds */
431447

432448
return its_send_int_cmd(data, device_id, event_id);
@@ -436,7 +452,7 @@ static void its_setup_cmd_queue(const struct device *dev)
436452
{
437453
const struct gicv3_its_config *cfg = dev->config;
438454
struct gicv3_its_data *data = dev->data;
439-
uint64_t reg = 0;
455+
uint64_t reg = 0, tmp;
440456

441457
/* Zero out cmd table */
442458
memset(cfg->cmd_queue, 0, cfg->cmd_queue_size);
@@ -450,6 +466,17 @@ static void its_setup_cmd_queue(const struct device *dev)
450466

451467
sys_write64(reg, data->base + GITS_CBASER);
452468

469+
#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT
470+
reg &= ~(MASK(GITS_BASER_SHAREABILITY));
471+
#endif
472+
/* Check whether hardware supports sharable */
473+
tmp = sys_read64(data->base + GITS_CBASER);
474+
if (!(tmp & MASK(GITS_BASER_SHAREABILITY))) {
475+
reg &= ~(MASK(GITS_BASER_SHAREABILITY) | MASK(GITS_BASER_INNER_CACHE));
476+
reg |= MASK_SET(GIC_BASER_CACHE_NCACHEABLE, GITS_CBASER_INNER_CACHE);
477+
sys_write64(reg, data->base + GITS_CBASER);
478+
}
479+
453480
data->cmd_base = (struct its_cmd_block *)cfg->cmd_queue;
454481
data->cmd_write = data->cmd_base;
455482

@@ -529,9 +556,18 @@ static int gicv3_its_init_device_id(const struct device *dev, uint32_t device_id
529556

530557
memset(alloc_addr, 0, data->indirect_dev_page_size);
531558

559+
#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT
560+
arch_dcache_flush_and_invd_range(alloc_addr, data->indirect_dev_page_size);
561+
#endif
562+
532563
data->indirect_dev_lvl1_table[offset] = (uintptr_t)alloc_addr |
533564
MASK_SET(1, GITS_BASER_VALID);
534565

566+
#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT
567+
arch_dcache_flush_and_invd_range(data->indirect_dev_lvl1_table + offset,
568+
GITS_LVL1_ENTRY_SIZE);
569+
#endif
570+
535571
barrier_dsync_fence_full();
536572
}
537573
}
@@ -547,6 +583,10 @@ static int gicv3_its_init_device_id(const struct device *dev, uint32_t device_id
547583
if (!itt) {
548584
return -ENOMEM;
549585
}
586+
memset(itt, 0, alloc_size);
587+
#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT
588+
arch_dcache_flush_and_invd_range(itt, alloc_size);
589+
#endif
550590

551591
/* size is log2(ites) - 1, equivalent to (fls(ites) - 1) - 1 */
552592
ret = its_send_mapd_cmd(data, device_id, fls_z(nr_ites) - 2, (uintptr_t)itt, true);

0 commit comments

Comments
 (0)