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 */
26volatile 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 */
33volatile 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
37word_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 */
43BOOT_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
62BOOT_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
110BOOT_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
150void 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
165BOOT_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
172BOOT_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*/
191void 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 */
207void 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 */
227volatile 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
231unsigned int gic_vcpu_num_list_regs;
232
233#endif /* End of CONFIG_ARM_HYPERVISOR_SUPPORT */
234