1/* 2 * Copyright (c) 2016, ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Universitaetstr 6, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10#include <kernel.h> 11#include <sysreg.h> 12#include <dev/armv8_dev.h> 13#include <dev/gic_v3_dist_dev.h> 14#include <dev/gic_v2_cpu_dev.h> 15#include <paging_kernel_arch.h> 16#include <arch/arm/gic.h> 17#include <arch/arm/platform.h> 18#include <getopt/getopt.h> 19 20static gic_v3_dist_t gic_v3_dev; 21static gic_v2_cpu_t gic_v2_cpu_dev; 22 23extern lpaddr_t platform_gic_cpu_interface_base; 24extern lpaddr_t platform_gic_distributor_base; 25 26// Command line arguments 27static struct cmdarg cmdargs[] = { 28 {"gic", ArgType_ULong, { .ulonginteger = &platform_gic_cpu_interface_base }}, 29 {"gicdist", ArgType_ULong, { .ulonginteger = &platform_gic_distributor_base }} 30}; 31 32/* 33 * This should return 1<<my_core_id 34 */ 35static uint8_t gic_get_cpumask(void) 36{ 37 uint32_t mask = gic_v3_dist_GICD_ITARGETSR_rd(&gic_v3_dev , 0); 38 mask |= mask >> 16; 39 mask |= mask >> 8; 40 return mask; 41} 42 43/* 44 * Reads th STATUSR register, prints error on error condition 45 */ 46static void check_cpu_if_statusr(void) 47{ 48 // gic_v2_cpu_STATUSR_t raw = gic_v2_cpu_STATUSR_rawrd(&gic_v2_cpu_dev); 49 // if (raw) { 50 // char buf[512]; 51 // gic_v2_cpu_STATUSR_pr(buf,sizeof(buf),&gic_v2_cpu_dev); 52 // printk(LOG_NOTE, "gic_v2: Error condition! Status: %s\n", buf); 53 // } 54} 55 56/* 57 * Initialize the global interrupt controller 58 * 59 * There are three types of interrupts 60 * 1) Software generated Interrupts (SGI) - IDs 0-15 61 * 2) Private Peripheral Interrupts (PPI) - IDs 16-31 62 * 3) Shared Peripheral Interrups (SPI) - IDs 32... 63 */ 64void gic_init(void) 65{ 66 printk(LOG_NOTE, "GICv2: Initializing\n"); 67 parse_commandline(kernel_command_line, cmdargs); 68 69 lvaddr_t gic_dist = local_phys_to_mem(platform_gic_distributor_base); 70 gic_v3_dist_initialize(&gic_v3_dev, (char *)gic_dist); 71 72 lvaddr_t gic_cpu = local_phys_to_mem(platform_gic_cpu_interface_base); 73 gic_v2_cpu_initialize(&gic_v2_cpu_dev, (char *)gic_cpu); 74 75 if (gic_v3_dist_GICD_TYPER_SecurityExtn_rdf(&gic_v3_dev)) { 76 printk(LOG_NOTE, "gic_v2: In init. GIC supports secure mode\n"); 77 } else { 78 printk(LOG_NOTE, "gic_v2: In init. GIC does not support secure mode\n"); 79 } 80} 81 82/* 83 * Returns active interrupt of group 1 84 */ 85uint32_t platform_get_active_irq(void) 86{ 87 uint32_t res = gic_v2_cpu_IAR_intid_rdf(&gic_v2_cpu_dev); 88 check_cpu_if_statusr(); 89 return res; 90} 91 92/* 93 * ACKs group 1 interrupt 94 */ 95void platform_acknowledge_irq(uint32_t irq) 96{ 97 gic_v2_cpu_EOIR_t reg = 0; 98 reg = gic_v2_cpu_EOIR_intid_insert(reg, irq); 99 gic_v2_cpu_EOIR_rawwr(&gic_v2_cpu_dev, irq); 100 check_cpu_if_statusr(); 101} 102 103/* 104 * Raise an SGI on a core. 105 */ 106void gic_raise_softirq(coreid_t cpuid, uint8_t irq) 107{ 108 // assuming affinity routing DISABLED 109 assert(irq <= 15); 110 gic_v3_dist_GICD_SGIR_t reg = 0; 111 reg = gic_v3_dist_GICD_SGIR_INTID_insert(reg, irq); 112 reg = gic_v3_dist_GICD_SGIR_CPUTargetList_insert(reg, 1<<(cpuid)); 113 gic_v3_dist_GICD_SGIR_wr(&gic_v3_dev, reg); 114 check_cpu_if_statusr(); 115} 116 117/* 118 * Enable GIC CPU-IF and local distributor 119 */ 120void gic_cpu_interface_enable(void) 121{ 122 printk(LOG_NOTE, "gic_v2: GICC IIDR " 123 "implementer=0x%x, revision=0x%x, variant=0x%x, prodid=0x%x, raw=0x%x\n", 124 gic_v2_cpu_IIDR_Implementer_rdf(&gic_v2_cpu_dev), 125 gic_v2_cpu_IIDR_Revision_rdf(&gic_v2_cpu_dev), 126 gic_v2_cpu_IIDR_Variant_rdf(&gic_v2_cpu_dev), 127 gic_v2_cpu_IIDR_ProductID_rdf(&gic_v2_cpu_dev), 128 gic_v2_cpu_IIDR_rawrd(&gic_v2_cpu_dev) 129 ); 130 131 // Do as Linux does: 132 // set priority mode: PMR to 0xf0 133 gic_v2_cpu_PMR_wr(&gic_v2_cpu_dev, 0xf0); 134 check_cpu_if_statusr(); 135 // Set binary point to 1: 6 group priority bits, 2 subpriority bits 136 gic_v2_cpu_BPR_wr(&gic_v2_cpu_dev, 1); 137 check_cpu_if_statusr(); 138 139 //We enable both group 0 and 1, but let both trigger IRQs (and not FIQs) 140 gic_v2_cpu_CTLR_NS_rawwr(&gic_v2_cpu_dev, 3); // code for non-secure 141 gic_v2_cpu_CTLR_FIQEn_wrf(&gic_v2_cpu_dev, 0); // route both groups to IRQ 142 143 // Disable all GIC bypassing (no wake-up interrupts). This does not 144 // seem to have any effect? 145 gic_v2_cpu_CTLR_FIQBypDisGrp1_wrf(&gic_v2_cpu_dev, 1); 146 gic_v2_cpu_CTLR_FIQBypDisGrp0_wrf(&gic_v2_cpu_dev, 1); 147 gic_v2_cpu_CTLR_IRQBypDisGrp1_wrf(&gic_v2_cpu_dev, 1); 148 gic_v2_cpu_CTLR_IRQBypDisGrp0_wrf(&gic_v2_cpu_dev, 1); 149 check_cpu_if_statusr(); 150 151 gic_v3_dist_GICD_CTLR_secure_t ctrl = 0; 152 // Set affinity routing (redundant on CN88xx) 153 ctrl = gic_v3_dist_GICD_CTLR_secure_ARE_NS_insert(ctrl, 1); 154 // Enable group 1 interrupts 155 ctrl = gic_v3_dist_GICD_CTLR_secure_EnableGrp1NS_insert(ctrl, 1); 156 gic_v3_dist_GICD_CTLR_secure_wr(&gic_v3_dev, ctrl); 157 158 check_cpu_if_statusr(); 159 160 printk(LOG_NOTE, "gic_v2: GICD IIDR " 161 "implementer=0x%x, revision=0x%x, variant=0x%x, prodid=0x%x, raw=0x%x\n", 162 gic_v3_dist_GICD_IIDR_Implementer_rdf(&gic_v3_dev), 163 gic_v3_dist_GICD_IIDR_Revision_rdf(&gic_v3_dev), 164 gic_v3_dist_GICD_IIDR_Variant_rdf(&gic_v3_dev), 165 gic_v3_dist_GICD_IIDR_ProductID_rdf(&gic_v3_dev), 166 gic_v3_dist_GICD_IIDR_rawrd(&gic_v3_dev) 167 ); 168 169 170 uint32_t itlines = gic_v3_dist_GICD_TYPER_ITLinesNumber_rdf(&gic_v3_dev); 171 itlines = (itlines+1)*32; 172 if(itlines > 1020) 173 itlines = 1020; 174 printk(LOG_NOTE, "gic_v2: #INTIDs supported: %" PRIu32 "\n", itlines); 175 176 uint32_t lspi = gic_v3_dist_GICD_TYPER_LSPI_rdf(&gic_v3_dev); 177 printk(LOG_NOTE, "gic_v2: #LSPIs supported: %" PRIu32 "\n", lspi); 178 179 180 // Setup distributor so it forwards all interrupts to this CPU. 181 uint8_t my_cpumask = gic_get_cpumask(); 182 uint32_t dest_cpumask = my_cpumask; 183 dest_cpumask = dest_cpumask | dest_cpumask << 8 | dest_cpumask << 16 | dest_cpumask << 24; 184 for(int i=8; i*4 < itlines; i++) 185 gic_v3_dist_GICD_ITARGETSR_wr(&gic_v3_dev, i, dest_cpumask); 186 187 // Put all interrupts into Group 0 and enable them 188 #define MASK_32 0xffffffff 189 for (int i = 0; i * 32 < itlines; i++) { 190 // Clear 191 gic_v3_dist_GICD_ICACTIVER_wr(&gic_v3_dev, i, MASK_32); 192 // Enable 193 gic_v3_dist_GICD_ISENABLER_wr(&gic_v3_dev, i, MASK_32); 194 // And put in group 0 195 gic_v3_dist_GICD_IGROUPR_rawwr(&gic_v3_dev, i, 0); 196 } 197 198 // Disable interrupt FIQ Bypass interrupt 28 199 gic_v3_dist_GICD_ICENABLER_wr(&gic_v3_dev, 0, (1<<28)); 200 201 202 gic_v3_dist_GICD_CTLR_rawwr(&gic_v3_dev, 0x1); // Enable Distributor 203 check_cpu_if_statusr(); 204} 205 206errval_t platform_init_ic_bsp(void) { 207 gic_init(); 208 gic_cpu_interface_enable(); 209 return SYS_ERR_OK; 210} 211 212errval_t platform_init_ic_app(void) { 213 gic_cpu_interface_enable(); 214 return SYS_ERR_OK; 215} 216 217/** 218 * \brief Enable an interrupt 219 * 220 * \see ARM Generic Interrupt Controller Architecture Specification v1.0 221 * 222 * \param int_id 223 * \param cpu_targets 8 Bit mask. One bit for each core in the system. 224 * (chapter 4.3.11) 225 * \param prio Priority of the interrupt (lower is higher). We allow 0..15. 226 * The number of priority bits is implementation specific, but at least 16 227 * (using bits [7:4] of the priority field, chapter 3.3) 228 * \param 0 is level-sensitive, 1 is edge-triggered 229 * \param 0 is N-to-N, 1 is 1-N 230 */ 231errval_t platform_enable_interrupt(uint32_t int_id, uint16_t prio, 232 bool edge_triggered, bool one_to_n) 233{ 234 return SYS_ERR_OK; 235} 236