187762bceSOliver Swede /* 293b785f5SAndre Przywara * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. 387762bceSOliver Swede * 487762bceSOliver Swede * SPDX-License-Identifier: BSD-3-Clause 587762bceSOliver Swede */ 687762bceSOliver Swede 71a0f9366SAndre Przywara #include <common/debug.h> 81a0f9366SAndre Przywara #include <common/fdt_wrappers.h> 993b785f5SAndre Przywara #include <drivers/arm/arm_gicv3_common.h> 1087762bceSOliver Swede #include <drivers/arm/gic_common.h> 1193b785f5SAndre Przywara #include <drivers/arm/gicv3.h> 12c69f815bSAndre Przywara #include <lib/mmio.h> 131a0f9366SAndre Przywara #include <libfdt.h> 1487762bceSOliver Swede 151a0f9366SAndre Przywara #include <platform_def.h> 1687762bceSOliver Swede #include <plat/common/platform.h> 1787762bceSOliver Swede #include <platform_def.h> 1887762bceSOliver Swede 1987762bceSOliver Swede static const interrupt_prop_t fpga_interrupt_props[] = { 2087762bceSOliver Swede PLATFORM_G1S_PROPS(INTR_GROUP1S), 2187762bceSOliver Swede PLATFORM_G0_PROPS(INTR_GROUP0) 2287762bceSOliver Swede }; 2387762bceSOliver Swede 2487762bceSOliver Swede static uintptr_t fpga_rdistif_base_addrs[PLATFORM_CORE_COUNT]; 2593b785f5SAndre Przywara static int nr_itses; 2687762bceSOliver Swede 2787762bceSOliver Swede static unsigned int fpga_mpidr_to_core_pos(unsigned long mpidr) 2887762bceSOliver Swede { 2987762bceSOliver Swede return (unsigned int)plat_core_pos_by_mpidr(mpidr); 3087762bceSOliver Swede } 3187762bceSOliver Swede 321a0f9366SAndre Przywara static gicv3_driver_data_t fpga_gicv3_driver_data = { 3387762bceSOliver Swede .interrupt_props = fpga_interrupt_props, 3487762bceSOliver Swede .interrupt_props_num = ARRAY_SIZE(fpga_interrupt_props), 3587762bceSOliver Swede .rdistif_num = PLATFORM_CORE_COUNT, 3687762bceSOliver Swede .rdistif_base_addrs = fpga_rdistif_base_addrs, 3787762bceSOliver Swede .mpidr_to_core_pos = fpga_mpidr_to_core_pos 3887762bceSOliver Swede }; 3987762bceSOliver Swede 4087762bceSOliver Swede void plat_fpga_gic_init(void) 4187762bceSOliver Swede { 421a0f9366SAndre Przywara const void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE; 4393b785f5SAndre Przywara uintptr_t gicr_base = 0U; 4493b785f5SAndre Przywara uint32_t iidr; 451a0f9366SAndre Przywara int node, ret; 461a0f9366SAndre Przywara 471a0f9366SAndre Przywara node = fdt_node_offset_by_compatible(fdt, 0, "arm,gic-v3"); 481a0f9366SAndre Przywara if (node < 0) { 491a0f9366SAndre Przywara WARN("No \"arm,gic-v3\" compatible node found in DT, no GIC support.\n"); 501a0f9366SAndre Przywara return; 511a0f9366SAndre Przywara } 521a0f9366SAndre Przywara 531a0f9366SAndre Przywara /* TODO: Assuming only empty "ranges;" properties up the bus path. */ 541a0f9366SAndre Przywara ret = fdt_get_reg_props_by_index(fdt, node, 0, 551a0f9366SAndre Przywara &fpga_gicv3_driver_data.gicd_base, NULL); 561a0f9366SAndre Przywara if (ret < 0) { 571a0f9366SAndre Przywara WARN("Could not read GIC distributor address from DT.\n"); 581a0f9366SAndre Przywara return; 591a0f9366SAndre Przywara } 601a0f9366SAndre Przywara 6193b785f5SAndre Przywara iidr = mmio_read_32(fpga_gicv3_driver_data.gicd_base + GICD_IIDR); 6293b785f5SAndre Przywara if (((iidr & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) || 6393b785f5SAndre Przywara ((iidr & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_700)) { 6493b785f5SAndre Przywara unsigned int frame_id; 6593b785f5SAndre Przywara 6693b785f5SAndre Przywara /* 6793b785f5SAndre Przywara * According to the GIC TRMs, if there are any ITSes, they 6893b785f5SAndre Przywara * start four 64K pages after the distributor. After all 6993b785f5SAndre Przywara * the ITSes then follow the redistributors. 7093b785f5SAndre Przywara */ 7193b785f5SAndre Przywara gicr_base = fpga_gicv3_driver_data.gicd_base + (4U << 16); 7293b785f5SAndre Przywara 7393b785f5SAndre Przywara do { 7493b785f5SAndre Przywara uint64_t its_typer; 7593b785f5SAndre Przywara 7693b785f5SAndre Przywara /* Each GIC component can be identified by its ID. */ 7793b785f5SAndre Przywara frame_id = gicv3_get_component_partnum(gicr_base); 7893b785f5SAndre Przywara 7993b785f5SAndre Przywara if (frame_id == PIDR_COMPONENT_ARM_REDIST) { 8093b785f5SAndre Przywara INFO("Found %d ITSes, redistributors start at 0x%llx\n", 8193b785f5SAndre Przywara nr_itses, (unsigned long long)gicr_base); 8293b785f5SAndre Przywara break; 8393b785f5SAndre Przywara } 8493b785f5SAndre Przywara 8593b785f5SAndre Przywara if (frame_id != PIDR_COMPONENT_ARM_ITS) { 8693b785f5SAndre Przywara WARN("GICv3: found unexpected frame 0x%x\n", 8793b785f5SAndre Przywara frame_id); 8893b785f5SAndre Przywara gicr_base = 0U; 8993b785f5SAndre Przywara break; 9093b785f5SAndre Przywara } 9193b785f5SAndre Przywara 9293b785f5SAndre Przywara /* 9393b785f5SAndre Przywara * Found an ITS, now work out if it supports virtual 9493b785f5SAndre Przywara * SGIs (for direct guest injection). If yes, each 9593b785f5SAndre Przywara * ITS occupies four 64K pages, otherwise just two. 9693b785f5SAndre Przywara */ 9793b785f5SAndre Przywara its_typer = mmio_read_64(gicr_base + GITS_TYPER); 9893b785f5SAndre Przywara if ((its_typer & GITS_TYPER_VSGI) != 0U) { 9993b785f5SAndre Przywara gicr_base += 4U << 16; 10093b785f5SAndre Przywara } else { 10193b785f5SAndre Przywara gicr_base += 2U << 16; 10293b785f5SAndre Przywara } 10393b785f5SAndre Przywara nr_itses++; 10493b785f5SAndre Przywara } while (true); 10593b785f5SAndre Przywara } 10693b785f5SAndre Przywara 10793b785f5SAndre Przywara /* 10893b785f5SAndre Przywara * If this is not a GIC-600 or -700, or the autodetection above failed, 10993b785f5SAndre Przywara * use the base address from the device tree. 11093b785f5SAndre Przywara */ 11193b785f5SAndre Przywara if (gicr_base == 0U) { 1121a0f9366SAndre Przywara ret = fdt_get_reg_props_by_index(fdt, node, 1, 11393b785f5SAndre Przywara &fpga_gicv3_driver_data.gicr_base, 11493b785f5SAndre Przywara NULL); 1151a0f9366SAndre Przywara if (ret < 0) { 1161a0f9366SAndre Przywara WARN("Could not read GIC redistributor address from DT.\n"); 1171a0f9366SAndre Przywara return; 1181a0f9366SAndre Przywara } 11993b785f5SAndre Przywara } else { 12093b785f5SAndre Przywara fpga_gicv3_driver_data.gicr_base = gicr_base; 12193b785f5SAndre Przywara } 1221a0f9366SAndre Przywara 12387762bceSOliver Swede gicv3_driver_init(&fpga_gicv3_driver_data); 12487762bceSOliver Swede gicv3_distif_init(); 12587762bceSOliver Swede gicv3_rdistif_init(plat_my_core_pos()); 12687762bceSOliver Swede gicv3_cpuif_enable(plat_my_core_pos()); 12787762bceSOliver Swede } 12887762bceSOliver Swede 12987762bceSOliver Swede void fpga_pwr_gic_on_finish(void) 13087762bceSOliver Swede { 13187762bceSOliver Swede gicv3_rdistif_init(plat_my_core_pos()); 13287762bceSOliver Swede gicv3_cpuif_enable(plat_my_core_pos()); 13387762bceSOliver Swede } 13487762bceSOliver Swede 13587762bceSOliver Swede void fpga_pwr_gic_off(void) 13687762bceSOliver Swede { 13787762bceSOliver Swede gicv3_cpuif_disable(plat_my_core_pos()); 13887762bceSOliver Swede gicv3_rdistif_off(plat_my_core_pos()); 13987762bceSOliver Swede } 140283e5595SAndre Przywara 141283e5595SAndre Przywara unsigned int fpga_get_nr_gic_cores(void) 142283e5595SAndre Przywara { 143283e5595SAndre Przywara return gicv3_rdistif_get_number_frames(fpga_gicv3_driver_data.gicr_base); 144283e5595SAndre Przywara } 145c69f815bSAndre Przywara 146c69f815bSAndre Przywara uintptr_t fpga_get_redist_size(void) 147c69f815bSAndre Przywara { 148c69f815bSAndre Przywara uint64_t typer_val = mmio_read_64(fpga_gicv3_driver_data.gicr_base + 149c69f815bSAndre Przywara GICR_TYPER); 150c69f815bSAndre Przywara 151c69f815bSAndre Przywara return gicv3_redist_size(typer_val); 152c69f815bSAndre Przywara } 15393b785f5SAndre Przywara 15493b785f5SAndre Przywara uintptr_t fpga_get_redist_base(void) 15593b785f5SAndre Przywara { 15693b785f5SAndre Przywara return fpga_gicv3_driver_data.gicr_base; 15793b785f5SAndre Przywara } 158*d7e39c43SAndre Przywara 159*d7e39c43SAndre Przywara bool fpga_has_its(void) 160*d7e39c43SAndre Przywara { 161*d7e39c43SAndre Przywara return nr_itses > 0; 162*d7e39c43SAndre Przywara } 163