1 /*
2  * Copyright 2014, General Dynamics C4 Systems
3  *
4  * SPDX-License-Identifier: GPL-2.0-only
5  */
6 
7 #include <config.h>
8 #include <arch/machine/gic_v2.h>
9 
10 #define TARGET_CPU_ALLINT(CPU) ( \
11         ( ((CPU)&0xff)<<0u  ) |\
12         ( ((CPU)&0xff)<<8u  ) |\
13         ( ((CPU)&0xff)<<16u ) |\
14         ( ((CPU)&0xff)<<24u ) \
15     )
16 #define TARGET_CPU0_ALLINT   TARGET_CPU_ALLINT(BIT(0))
17 
18 /* Use this to forward interrupts to all CPUs when debugging */
19 #define TARGET_CPU_ALL_ALLINT   TARGET_CPU_ALLINT(0xff)
20 
21 #define IRQ_SET_ALL 0xffffffff;
22 
23 #ifndef GIC_V2_DISTRIBUTOR_PPTR
24 #error GIC_V2_DISTRIBUTOR_PPTR must be defined for virtual memory access to the gic distributer
25 #else  /* GIC_DISTRIBUTOR_PPTR */
26 volatile struct gic_dist_map *const gic_dist =
27     (volatile struct gic_dist_map *)(GIC_V2_DISTRIBUTOR_PPTR);
28 #endif /* GIC_DISTRIBUTOR_PPTR */
29 
30 #ifndef GIC_V2_CONTROLLER_PPTR
31 #error GIC_V2_CONTROLLER_PPTR must be defined for virtual memory access to the gic cpu interface
32 #else  /* GIC_CONTROLLER_PPTR */
33 volatile struct gic_cpu_iface_map *const gic_cpuiface =
34     (volatile struct gic_cpu_iface_map *)(GIC_V2_CONTROLLER_PPTR);
35 #endif /* GIC_CONTROLLER_PPTR */
36 
37 word_t active_irq[CONFIG_MAX_NUM_NODES] = {IRQ_NONE};
38 
39 /* Get the target id for this processor. We rely on the constraint that the registers
40  * for PPI are read only and return only the current processor as the target.
41  * If this doesn't lead to a valid ID, we emit a warning and default to core 0.
42  */
infer_cpu_gic_id(int nirqs)43 BOOT_CODE static uint8_t infer_cpu_gic_id(int nirqs)
44 {
45     word_t i;
46     uint32_t target = 0;
47     for (i = 0; i < nirqs; i += 4) {
48         target = gic_dist->targets[i >> 2];
49         target |= target >> 16;
50         target |= target >> 8;
51         if (target) {
52             break;
53         }
54     }
55     if (!target) {
56         printf("Warning: Could not infer GIC interrupt target ID, assuming 0.\n");
57         target = BIT(0);
58     }
59     return target & 0xff;
60 }
61 
dist_init(void)62 BOOT_CODE static void dist_init(void)
63 {
64     word_t i;
65     int nirqs = 32 * ((gic_dist->ic_type & 0x1f) + 1);
66     gic_dist->enable = 0;
67 
68     for (i = 0; i < nirqs; i += 32) {
69         /* disable */
70         gic_dist->enable_clr[i >> 5] = IRQ_SET_ALL;
71         /* clear pending */
72         gic_dist->pending_clr[i >> 5] = IRQ_SET_ALL;
73     }
74 
75     /* reset interrupts priority */
76     for (i = 32; i < nirqs; i += 4) {
77         if (config_set(CONFIG_ARM_HYPERVISOR_SUPPORT)) {
78             gic_dist->priority[i >> 2] = 0x80808080;
79         } else {
80             gic_dist->priority[i >> 2] = 0;
81         }
82     }
83 
84     /*
85      * reset int target to current cpu
86      * We query which id that the GIC uses for us and use that.
87      */
88     uint8_t target = infer_cpu_gic_id(nirqs);
89     for (i = 0; i < nirqs; i += 4) {
90         gic_dist->targets[i >> 2] = TARGET_CPU_ALLINT(target);
91     }
92 
93     /* level-triggered, 1-N */
94     for (i = 64; i < nirqs; i += 32) {
95         gic_dist->config[i >> 5] = 0x55555555;
96     }
97 
98     /* group 0 for secure; group 1 for non-secure */
99     for (i = 0; i < nirqs; i += 32) {
100         if (config_set(CONFIG_ARM_HYPERVISOR_SUPPORT) && !config_set(CONFIG_PLAT_QEMU_ARM_VIRT)) {
101             gic_dist->security[i >> 5] = 0xffffffff;
102         } else {
103             gic_dist->security[i >> 5] = 0;
104         }
105     }
106     /* enable the int controller */
107     gic_dist->enable = 1;
108 }
109 
cpu_iface_init(void)110 BOOT_CODE static void cpu_iface_init(void)
111 {
112     uint32_t i;
113 
114     /* For non-Exynos4, the registers are banked per CPU, need to clear them */
115     gic_dist->enable_clr[0] = IRQ_SET_ALL;
116     gic_dist->pending_clr[0] = IRQ_SET_ALL;
117 
118     /* put everything in group 0; group 1 if in hyp mode */
119     if (config_set(CONFIG_ARM_HYPERVISOR_SUPPORT) && !config_set(CONFIG_PLAT_QEMU_ARM_VIRT)) {
120         gic_dist->security[0] = 0xffffffff;
121         gic_dist->priority[0] = 0x80808080;
122     } else {
123         gic_dist->security[0] = 0;
124         gic_dist->priority[0] = 0x0;
125     }
126 
127     /* clear any software generated interrupts */
128     for (i = 0; i < 16; i += 4) {
129         gic_dist->sgi_pending_clr[i >> 2] = IRQ_SET_ALL;
130     }
131 
132     gic_cpuiface->icontrol = 0;
133     /* the write to priority mask is ignored if the kernel is
134      * in non-secure mode and the priority mask is already configured
135      * by secure mode software. the elfloader should config the
136      * interrupt routing properly to ensure that the hyp-mode kernel
137      * can get interrupts
138      */
139     gic_cpuiface->pri_msk_c = 0x000000f0;
140     gic_cpuiface->pb_c = 0x00000003;
141 
142     i = gic_cpuiface->int_ack;
143     while ((i & IRQ_MASK) != IRQ_NONE) {
144         gic_cpuiface->eoi = i;
145         i = gic_cpuiface->int_ack;
146     }
147     gic_cpuiface->icontrol = 1;
148 }
149 
setIRQTrigger(irq_t irq,bool_t trigger)150 void setIRQTrigger(irq_t irq, bool_t trigger)
151 {
152     /* in the gic_config, there is a 2 bit field for each irq,
153      * setting the most significant bit of this field makes the irq edge-triggered,
154      * while 0 indicates that it is level-triggered */
155     word_t index = IRQT_TO_IRQ(irq) / 16u;
156     word_t offset = (IRQT_TO_IRQ(irq) % 16u) * 2;
157     if (trigger) {
158         /* set the bit */
159         gic_dist->config[index] |= BIT(offset + 1);
160     } else {
161         gic_dist->config[index] &= ~BIT(offset + 1);
162     }
163 }
164 
initIRQController(void)165 BOOT_CODE void initIRQController(void)
166 {
167     /* irqInvalid cannot correspond to a valid IRQ index into the irq state array */
168     assert(INT_STATE_ARRAY_SIZE < IRQT_TO_IRQ(irqInvalid));
169     dist_init();
170 }
171 
cpu_initLocalIRQController(void)172 BOOT_CODE void cpu_initLocalIRQController(void)
173 {
174     cpu_iface_init();
175 }
176 
177 #ifdef ENABLE_SMP_SUPPORT
178 /*
179 * 25-24: target lister filter
180 * 0b00 - send the ipi to the CPU interfaces specified in the CPU target list
181 * 0b01 - send the ipi to all CPU interfaces except the cpu interface.
182 *        that requrested teh ipi
183 * 0b10 - send the ipi only to the CPU interface that requested the IPI.
184 * 0b11 - reserved
185 *.
186 * 23-16: CPU targets list
187 * each bit of CPU target list [7:0] refers to the corresponding CPU interface.
188 * 3-0:   SGIINTID
189 * software generated interrupt id, from 0 to 15...
190 */
ipi_send_target(irq_t irq,word_t cpuTargetList)191 void ipi_send_target(irq_t irq, word_t cpuTargetList)
192 {
193     if (config_set(CONFIG_PLAT_TX2)) {
194         /* We need to swap the top 4 bits and the bottom 4 bits of the
195          * cpuTargetList since the A57 cores with logical core ID 0-3 are
196          * in cluster 1 and the Denver2 cores with logical core ID 4-5 are
197          * in cluster 0. */
198         cpuTargetList = ((cpuTargetList & 0xf) << 4) | ((cpuTargetList & 0xf0) >> 4);
199     }
200     gic_dist->sgi_control = (cpuTargetList << (GICD_SGIR_CPUTARGETLIST_SHIFT)) | (IRQT_TO_IRQ(
201                                                                                       irq) << GICD_SGIR_SGIINTID_SHIFT);
202 }
203 
204 /*
205  * Set CPU target for the interrupt if it's not a PPI
206  */
setIRQTarget(irq_t irq,seL4_Word target)207 void setIRQTarget(irq_t irq, seL4_Word target)
208 {
209     uint8_t targetList = 1 << target;
210     uint8_t *targets = (void *)(gic_dist->targets);
211     word_t hwIRQ = IRQT_TO_IRQ(irq);
212 
213     /* Return early if PPI */
214     if (IRQ_IS_PPI(irq)) {
215         fail("PPI can't have designated target core\n");
216         return;
217     }
218     targets[hwIRQ] = targetList;
219 }
220 #endif /* ENABLE_SMP_SUPPORT */
221 
222 #ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
223 
224 #ifndef GIC_V2_VCPUCTRL_PPTR
225 #error GIC_V2_VCPUCTRL_PPTR must be defined for virtual memory access to the gic virtual cpu interface control
226 #else  /* GIC_PL400_GICVCPUCTRL_PPTR */
227 volatile struct gich_vcpu_ctrl_map *gic_vcpu_ctrl =
228     (volatile struct gich_vcpu_ctrl_map *)(GIC_V2_VCPUCTRL_PPTR);
229 #endif /* GIC_PL400_GICVCPUCTRL_PPTR */
230 
231 unsigned int gic_vcpu_num_list_regs;
232 
233 #endif /* End of CONFIG_ARM_HYPERVISOR_SUPPORT */
234