1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <common/debug.h> 8*91f16700Schasinglulu #include <common/fdt_wrappers.h> 9*91f16700Schasinglulu #include <drivers/arm/arm_gicv3_common.h> 10*91f16700Schasinglulu #include <drivers/arm/gic_common.h> 11*91f16700Schasinglulu #include <drivers/arm/gicv3.h> 12*91f16700Schasinglulu #include <lib/mmio.h> 13*91f16700Schasinglulu #include <libfdt.h> 14*91f16700Schasinglulu 15*91f16700Schasinglulu #include <platform_def.h> 16*91f16700Schasinglulu #include <plat/common/platform.h> 17*91f16700Schasinglulu #include <platform_def.h> 18*91f16700Schasinglulu 19*91f16700Schasinglulu static const interrupt_prop_t fpga_interrupt_props[] = { 20*91f16700Schasinglulu PLATFORM_G1S_PROPS(INTR_GROUP1S), 21*91f16700Schasinglulu PLATFORM_G0_PROPS(INTR_GROUP0) 22*91f16700Schasinglulu }; 23*91f16700Schasinglulu 24*91f16700Schasinglulu static uintptr_t fpga_rdistif_base_addrs[PLATFORM_CORE_COUNT]; 25*91f16700Schasinglulu static int nr_itses; 26*91f16700Schasinglulu 27*91f16700Schasinglulu static unsigned int fpga_mpidr_to_core_pos(unsigned long mpidr) 28*91f16700Schasinglulu { 29*91f16700Schasinglulu return (unsigned int)plat_core_pos_by_mpidr(mpidr); 30*91f16700Schasinglulu } 31*91f16700Schasinglulu 32*91f16700Schasinglulu static gicv3_driver_data_t fpga_gicv3_driver_data = { 33*91f16700Schasinglulu .interrupt_props = fpga_interrupt_props, 34*91f16700Schasinglulu .interrupt_props_num = ARRAY_SIZE(fpga_interrupt_props), 35*91f16700Schasinglulu .rdistif_num = PLATFORM_CORE_COUNT, 36*91f16700Schasinglulu .rdistif_base_addrs = fpga_rdistif_base_addrs, 37*91f16700Schasinglulu .mpidr_to_core_pos = fpga_mpidr_to_core_pos 38*91f16700Schasinglulu }; 39*91f16700Schasinglulu 40*91f16700Schasinglulu void plat_fpga_gic_init(void) 41*91f16700Schasinglulu { 42*91f16700Schasinglulu const void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE; 43*91f16700Schasinglulu uintptr_t gicr_base = 0U; 44*91f16700Schasinglulu uint32_t iidr; 45*91f16700Schasinglulu int node, ret; 46*91f16700Schasinglulu 47*91f16700Schasinglulu node = fdt_node_offset_by_compatible(fdt, 0, "arm,gic-v3"); 48*91f16700Schasinglulu if (node < 0) { 49*91f16700Schasinglulu WARN("No \"arm,gic-v3\" compatible node found in DT, no GIC support.\n"); 50*91f16700Schasinglulu return; 51*91f16700Schasinglulu } 52*91f16700Schasinglulu 53*91f16700Schasinglulu /* TODO: Assuming only empty "ranges;" properties up the bus path. */ 54*91f16700Schasinglulu ret = fdt_get_reg_props_by_index(fdt, node, 0, 55*91f16700Schasinglulu &fpga_gicv3_driver_data.gicd_base, NULL); 56*91f16700Schasinglulu if (ret < 0) { 57*91f16700Schasinglulu WARN("Could not read GIC distributor address from DT.\n"); 58*91f16700Schasinglulu return; 59*91f16700Schasinglulu } 60*91f16700Schasinglulu 61*91f16700Schasinglulu iidr = mmio_read_32(fpga_gicv3_driver_data.gicd_base + GICD_IIDR); 62*91f16700Schasinglulu if (((iidr & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) || 63*91f16700Schasinglulu ((iidr & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_700)) { 64*91f16700Schasinglulu unsigned int frame_id; 65*91f16700Schasinglulu 66*91f16700Schasinglulu /* 67*91f16700Schasinglulu * According to the GIC TRMs, if there are any ITSes, they 68*91f16700Schasinglulu * start four 64K pages after the distributor. After all 69*91f16700Schasinglulu * the ITSes then follow the redistributors. 70*91f16700Schasinglulu */ 71*91f16700Schasinglulu gicr_base = fpga_gicv3_driver_data.gicd_base + (4U << 16); 72*91f16700Schasinglulu 73*91f16700Schasinglulu do { 74*91f16700Schasinglulu uint64_t its_typer; 75*91f16700Schasinglulu 76*91f16700Schasinglulu /* Each GIC component can be identified by its ID. */ 77*91f16700Schasinglulu frame_id = gicv3_get_component_partnum(gicr_base); 78*91f16700Schasinglulu 79*91f16700Schasinglulu if (frame_id == PIDR_COMPONENT_ARM_REDIST) { 80*91f16700Schasinglulu INFO("Found %d ITSes, redistributors start at 0x%llx\n", 81*91f16700Schasinglulu nr_itses, (unsigned long long)gicr_base); 82*91f16700Schasinglulu break; 83*91f16700Schasinglulu } 84*91f16700Schasinglulu 85*91f16700Schasinglulu if (frame_id != PIDR_COMPONENT_ARM_ITS) { 86*91f16700Schasinglulu WARN("GICv3: found unexpected frame 0x%x\n", 87*91f16700Schasinglulu frame_id); 88*91f16700Schasinglulu gicr_base = 0U; 89*91f16700Schasinglulu break; 90*91f16700Schasinglulu } 91*91f16700Schasinglulu 92*91f16700Schasinglulu /* 93*91f16700Schasinglulu * Found an ITS, now work out if it supports virtual 94*91f16700Schasinglulu * SGIs (for direct guest injection). If yes, each 95*91f16700Schasinglulu * ITS occupies four 64K pages, otherwise just two. 96*91f16700Schasinglulu */ 97*91f16700Schasinglulu its_typer = mmio_read_64(gicr_base + GITS_TYPER); 98*91f16700Schasinglulu if ((its_typer & GITS_TYPER_VSGI) != 0U) { 99*91f16700Schasinglulu gicr_base += 4U << 16; 100*91f16700Schasinglulu } else { 101*91f16700Schasinglulu gicr_base += 2U << 16; 102*91f16700Schasinglulu } 103*91f16700Schasinglulu nr_itses++; 104*91f16700Schasinglulu } while (true); 105*91f16700Schasinglulu } 106*91f16700Schasinglulu 107*91f16700Schasinglulu /* 108*91f16700Schasinglulu * If this is not a GIC-600 or -700, or the autodetection above failed, 109*91f16700Schasinglulu * use the base address from the device tree. 110*91f16700Schasinglulu */ 111*91f16700Schasinglulu if (gicr_base == 0U) { 112*91f16700Schasinglulu ret = fdt_get_reg_props_by_index(fdt, node, 1, 113*91f16700Schasinglulu &fpga_gicv3_driver_data.gicr_base, 114*91f16700Schasinglulu NULL); 115*91f16700Schasinglulu if (ret < 0) { 116*91f16700Schasinglulu WARN("Could not read GIC redistributor address from DT.\n"); 117*91f16700Schasinglulu return; 118*91f16700Schasinglulu } 119*91f16700Schasinglulu } else { 120*91f16700Schasinglulu fpga_gicv3_driver_data.gicr_base = gicr_base; 121*91f16700Schasinglulu } 122*91f16700Schasinglulu 123*91f16700Schasinglulu gicv3_driver_init(&fpga_gicv3_driver_data); 124*91f16700Schasinglulu gicv3_distif_init(); 125*91f16700Schasinglulu gicv3_rdistif_init(plat_my_core_pos()); 126*91f16700Schasinglulu gicv3_cpuif_enable(plat_my_core_pos()); 127*91f16700Schasinglulu } 128*91f16700Schasinglulu 129*91f16700Schasinglulu void fpga_pwr_gic_on_finish(void) 130*91f16700Schasinglulu { 131*91f16700Schasinglulu gicv3_rdistif_init(plat_my_core_pos()); 132*91f16700Schasinglulu gicv3_cpuif_enable(plat_my_core_pos()); 133*91f16700Schasinglulu } 134*91f16700Schasinglulu 135*91f16700Schasinglulu void fpga_pwr_gic_off(void) 136*91f16700Schasinglulu { 137*91f16700Schasinglulu gicv3_cpuif_disable(plat_my_core_pos()); 138*91f16700Schasinglulu gicv3_rdistif_off(plat_my_core_pos()); 139*91f16700Schasinglulu } 140*91f16700Schasinglulu 141*91f16700Schasinglulu unsigned int fpga_get_nr_gic_cores(void) 142*91f16700Schasinglulu { 143*91f16700Schasinglulu return gicv3_rdistif_get_number_frames(fpga_gicv3_driver_data.gicr_base); 144*91f16700Schasinglulu } 145*91f16700Schasinglulu 146*91f16700Schasinglulu uintptr_t fpga_get_redist_size(void) 147*91f16700Schasinglulu { 148*91f16700Schasinglulu uint64_t typer_val = mmio_read_64(fpga_gicv3_driver_data.gicr_base + 149*91f16700Schasinglulu GICR_TYPER); 150*91f16700Schasinglulu 151*91f16700Schasinglulu return gicv3_redist_size(typer_val); 152*91f16700Schasinglulu } 153*91f16700Schasinglulu 154*91f16700Schasinglulu uintptr_t fpga_get_redist_base(void) 155*91f16700Schasinglulu { 156*91f16700Schasinglulu return fpga_gicv3_driver_data.gicr_base; 157*91f16700Schasinglulu } 158*91f16700Schasinglulu 159*91f16700Schasinglulu bool fpga_has_its(void) 160*91f16700Schasinglulu { 161*91f16700Schasinglulu return nr_itses > 0; 162*91f16700Schasinglulu } 163