xref: /rk3399_ARM-atf/plat/arm/board/arm_fpga/fpga_gicv3.c (revision 683bb4d7bdfd42e6e026902c43797f132b2a75d5)
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