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