xref: /arm-trusted-firmware/plat/ti/k3/common/k3_gicv3.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <platform_def.h>
8*91f16700Schasinglulu 
9*91f16700Schasinglulu #include <assert.h>
10*91f16700Schasinglulu #include <common/bl_common.h>
11*91f16700Schasinglulu #include <common/interrupt_props.h>
12*91f16700Schasinglulu #include <drivers/arm/gicv3.h>
13*91f16700Schasinglulu #include <lib/utils.h>
14*91f16700Schasinglulu #include <lib/mmio.h>
15*91f16700Schasinglulu #include <plat/common/platform.h>
16*91f16700Schasinglulu 
17*91f16700Schasinglulu #include <k3_gicv3.h>
18*91f16700Schasinglulu 
19*91f16700Schasinglulu /* The GICv3 driver only needs to be initialized in EL3 */
20*91f16700Schasinglulu uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
21*91f16700Schasinglulu 
22*91f16700Schasinglulu static gicv3_redist_ctx_t rdist_ctx[PLATFORM_CORE_COUNT];
23*91f16700Schasinglulu static gicv3_dist_ctx_t dist_ctx;
24*91f16700Schasinglulu 
25*91f16700Schasinglulu static const interrupt_prop_t k3_interrupt_props[] = {
26*91f16700Schasinglulu 	PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S),
27*91f16700Schasinglulu 	PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0)
28*91f16700Schasinglulu };
29*91f16700Schasinglulu 
30*91f16700Schasinglulu static unsigned int k3_mpidr_to_core_pos(unsigned long mpidr)
31*91f16700Schasinglulu {
32*91f16700Schasinglulu 	return (unsigned int)plat_core_pos_by_mpidr(mpidr);
33*91f16700Schasinglulu }
34*91f16700Schasinglulu 
35*91f16700Schasinglulu gicv3_driver_data_t k3_gic_data = {
36*91f16700Schasinglulu 	.rdistif_num = PLATFORM_CORE_COUNT,
37*91f16700Schasinglulu 	.rdistif_base_addrs = rdistif_base_addrs,
38*91f16700Schasinglulu 	.interrupt_props = k3_interrupt_props,
39*91f16700Schasinglulu 	.interrupt_props_num = ARRAY_SIZE(k3_interrupt_props),
40*91f16700Schasinglulu 	.mpidr_to_core_pos = k3_mpidr_to_core_pos,
41*91f16700Schasinglulu };
42*91f16700Schasinglulu 
43*91f16700Schasinglulu void k3_gic_driver_init(uintptr_t gic_base)
44*91f16700Schasinglulu {
45*91f16700Schasinglulu 	/* GIC Distributor is always at the base of the IP */
46*91f16700Schasinglulu 	uintptr_t gicd_base = gic_base;
47*91f16700Schasinglulu 	/* GIC Redistributor base is run-time detected */
48*91f16700Schasinglulu 	uintptr_t gicr_base = 0;
49*91f16700Schasinglulu 
50*91f16700Schasinglulu 	for (unsigned int gicr_shift = 18; gicr_shift < 21; gicr_shift++) {
51*91f16700Schasinglulu 		uintptr_t gicr_check = gic_base + BIT(gicr_shift);
52*91f16700Schasinglulu 		uint32_t iidr = mmio_read_32(gicr_check + GICR_IIDR);
53*91f16700Schasinglulu 		if (iidr != 0) {
54*91f16700Schasinglulu 			/* Found the GICR base */
55*91f16700Schasinglulu 			gicr_base = gicr_check;
56*91f16700Schasinglulu 			break;
57*91f16700Schasinglulu 		}
58*91f16700Schasinglulu 	}
59*91f16700Schasinglulu 	/* Assert if we have not found the GICR base */
60*91f16700Schasinglulu 	assert(gicr_base != 0);
61*91f16700Schasinglulu 
62*91f16700Schasinglulu 	/*
63*91f16700Schasinglulu 	 * The GICv3 driver is initialized in EL3 and does not need
64*91f16700Schasinglulu 	 * to be initialized again in SEL1. This is because the S-EL1
65*91f16700Schasinglulu 	 * can use GIC system registers to manage interrupts and does
66*91f16700Schasinglulu 	 * not need GIC interface base addresses to be configured.
67*91f16700Schasinglulu 	 */
68*91f16700Schasinglulu 	k3_gic_data.gicd_base = gicd_base;
69*91f16700Schasinglulu 	k3_gic_data.gicr_base = gicr_base;
70*91f16700Schasinglulu 	gicv3_driver_init(&k3_gic_data);
71*91f16700Schasinglulu }
72*91f16700Schasinglulu 
73*91f16700Schasinglulu void k3_gic_init(void)
74*91f16700Schasinglulu {
75*91f16700Schasinglulu 	gicv3_distif_init();
76*91f16700Schasinglulu 	gicv3_rdistif_init(plat_my_core_pos());
77*91f16700Schasinglulu 	gicv3_cpuif_enable(plat_my_core_pos());
78*91f16700Schasinglulu }
79*91f16700Schasinglulu 
80*91f16700Schasinglulu void k3_gic_cpuif_enable(void)
81*91f16700Schasinglulu {
82*91f16700Schasinglulu 	gicv3_cpuif_enable(plat_my_core_pos());
83*91f16700Schasinglulu }
84*91f16700Schasinglulu 
85*91f16700Schasinglulu void k3_gic_cpuif_disable(void)
86*91f16700Schasinglulu {
87*91f16700Schasinglulu 	gicv3_cpuif_disable(plat_my_core_pos());
88*91f16700Schasinglulu }
89*91f16700Schasinglulu 
90*91f16700Schasinglulu void k3_gic_pcpu_init(void)
91*91f16700Schasinglulu {
92*91f16700Schasinglulu 	gicv3_rdistif_init(plat_my_core_pos());
93*91f16700Schasinglulu }
94*91f16700Schasinglulu 
95*91f16700Schasinglulu void k3_gic_save_context(void)
96*91f16700Schasinglulu {
97*91f16700Schasinglulu 	for (unsigned int i = 0U; i < PLATFORM_CORE_COUNT; i++) {
98*91f16700Schasinglulu 		gicv3_rdistif_save(i, &rdist_ctx[i]);
99*91f16700Schasinglulu 	}
100*91f16700Schasinglulu 	gicv3_distif_save(&dist_ctx);
101*91f16700Schasinglulu }
102*91f16700Schasinglulu 
103*91f16700Schasinglulu void k3_gic_restore_context(void)
104*91f16700Schasinglulu {
105*91f16700Schasinglulu 	gicv3_distif_init_restore(&dist_ctx);
106*91f16700Schasinglulu 	for (unsigned int i = 0U; i < PLATFORM_CORE_COUNT; i++) {
107*91f16700Schasinglulu 		gicv3_rdistif_init_restore(i, &rdist_ctx[i]);
108*91f16700Schasinglulu 	}
109*91f16700Schasinglulu }
110