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
fpga_mpidr_to_core_pos(unsigned long mpidr)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
plat_fpga_gic_init(void)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
fpga_pwr_gic_on_finish(void)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
fpga_pwr_gic_off(void)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
fpga_get_nr_gic_cores(void)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
fpga_get_redist_size(void)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
fpga_get_redist_base(void)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
fpga_has_its(void)159*d7e39c43SAndre Przywara bool fpga_has_its(void)
160*d7e39c43SAndre Przywara {
161*d7e39c43SAndre Przywara return nr_itses > 0;
162*d7e39c43SAndre Przywara }
163