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