1
1
/*
2
2
* Copyright 2021 BayLibre, SAS
3
+ * Copyright 2025 NXP
3
4
*
4
5
* SPDX-License-Identifier: Apache-2.0
5
6
*/
6
7
7
8
#include <zephyr/logging/log.h>
8
9
LOG_MODULE_REGISTER (intc_gicv3_its , LOG_LEVEL_ERR );
9
10
11
+ #include <zephyr/cache.h>
10
12
#include <zephyr/kernel.h>
11
13
#include <zephyr/device.h>
12
14
#include <zephyr/drivers/interrupt_controller/gicv3_its.h>
@@ -39,6 +41,9 @@ struct its_cmd_block {
39
41
#define ITS_CMD_QUEUE_SIZE SIZE_64K
40
42
#define ITS_CMD_QUEUE_NR_ENTRIES (ITS_CMD_QUEUE_SIZE / sizeof(struct its_cmd_block))
41
43
44
+ /* The level 1 entry size is a 64bit pointer */
45
+ #define GITS_LVL1_ENTRY_SIZE (8UL)
46
+
42
47
struct gicv3_its_data {
43
48
mm_reg_t base ;
44
49
struct its_cmd_block * cmd_base ;
@@ -190,8 +195,7 @@ static int its_alloc_tables(struct gicv3_its_data *data)
190
195
lvl2_width = fls_z (page_size / entry_size ) - 1 ;
191
196
device_ids -= lvl2_width + 1 ;
192
197
193
- /* The level 1 entry size is a 64bit pointer */
194
- entry_size = sizeof (uint64_t );
198
+ entry_size = GITS_LVL1_ENTRY_SIZE ;
195
199
196
200
indirect = true;
197
201
}
@@ -229,13 +233,22 @@ static int its_alloc_tables(struct gicv3_its_data *data)
229
233
}
230
234
231
235
reg |= MASK_SET (page_cnt - 1 , GITS_BASER_SIZE );
232
- reg |= MASK_SET (GIC_BASER_SHARE_INNER , GITS_BASER_SHAREABILITY );
233
236
reg |= MASK_SET ((uintptr_t )alloc_addr >> GITS_BASER_ADDR_SHIFT , GITS_BASER_ADDR );
234
237
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 );
235
243
reg |= MASK_SET (GIC_BASER_CACHE_RAWAWB , GITS_BASER_INNER_CACHE );
244
+ #endif
236
245
reg |= MASK_SET (indirect ? 1 : 0 , GITS_BASER_INDIRECT );
237
246
reg |= MASK_SET (1 , GITS_BASER_VALID );
238
247
248
+ #ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT
249
+ arch_dcache_flush_and_invd_range (alloc_addr , page_size * page_cnt );
250
+ #endif
251
+
239
252
sys_write64 (reg , data -> base + GITS_BASER (i ));
240
253
241
254
/* 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
300
313
uint64_t wr_idx , rd_idx , idx ;
301
314
unsigned int count = 1000000 ; /* 1s! */
302
315
316
+ #ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT
317
+ arch_dcache_flush_and_invd_range (cmd , sizeof (* cmd ));
318
+ #endif
319
+
303
320
wr_idx = (data -> cmd_write - data -> cmd_base ) * sizeof (* cmd );
304
321
rd_idx = sys_read32 (data -> base + GITS_CREADR );
305
322
@@ -426,7 +443,6 @@ static int its_send_invall_cmd(struct gicv3_its_data *data, uint32_t icid)
426
443
static int gicv3_its_send_int (const struct device * dev , uint32_t device_id , uint32_t event_id )
427
444
{
428
445
struct gicv3_its_data * data = dev -> data ;
429
-
430
446
/* TOFIX check device_id & event_id bounds */
431
447
432
448
return its_send_int_cmd (data , device_id , event_id );
@@ -436,7 +452,7 @@ static void its_setup_cmd_queue(const struct device *dev)
436
452
{
437
453
const struct gicv3_its_config * cfg = dev -> config ;
438
454
struct gicv3_its_data * data = dev -> data ;
439
- uint64_t reg = 0 ;
455
+ uint64_t reg = 0 , tmp ;
440
456
441
457
/* Zero out cmd table */
442
458
memset (cfg -> cmd_queue , 0 , cfg -> cmd_queue_size );
@@ -450,6 +466,17 @@ static void its_setup_cmd_queue(const struct device *dev)
450
466
451
467
sys_write64 (reg , data -> base + GITS_CBASER );
452
468
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
+
453
480
data -> cmd_base = (struct its_cmd_block * )cfg -> cmd_queue ;
454
481
data -> cmd_write = data -> cmd_base ;
455
482
@@ -529,9 +556,18 @@ static int gicv3_its_init_device_id(const struct device *dev, uint32_t device_id
529
556
530
557
memset (alloc_addr , 0 , data -> indirect_dev_page_size );
531
558
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
+
532
563
data -> indirect_dev_lvl1_table [offset ] = (uintptr_t )alloc_addr |
533
564
MASK_SET (1 , GITS_BASER_VALID );
534
565
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
+
535
571
barrier_dsync_fence_full ();
536
572
}
537
573
}
@@ -547,6 +583,10 @@ static int gicv3_its_init_device_id(const struct device *dev, uint32_t device_id
547
583
if (!itt ) {
548
584
return - ENOMEM ;
549
585
}
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
550
590
551
591
/* size is log2(ites) - 1, equivalent to (fls(ites) - 1) - 1 */
552
592
ret = its_send_mapd_cmd (data , device_id , fls_z (nr_ites ) - 2 , (uintptr_t )itt , true);
0 commit comments