plat/arm/board/arm_fpga: Initialize the Generic Interrupt Controller

This initializes the GIC using the Arm GIC drivers in TF-A.
The initial FPGA image uses a GIC600 implementation, and so that its
power controller is enabled, this platform port calls the corresponding
implementation-specific routines.

Signed-off-by: Oliver Swede <oli.swede@arm.com>
Change-Id: I88d5a073eead4b653b1ca73273182cd98a95e4c5
This commit is contained in:
Oliver Swede 2019-12-03 14:08:21 +00:00
parent 2d696d1811
commit 87762bce84
6 changed files with 123 additions and 7 deletions

View File

@ -51,11 +51,12 @@ void bl31_plat_arch_setup(void)
void bl31_platform_setup(void)
{
/* Initialize the GIC driver, cpu and distributor interfaces */
plat_fpga_gic_init();
/* Write frequency to CNTCRL and initialize timer */
generic_delay_timer_init();
mmio_write_32(FPGA_TIMER_BASE, ((1 << 8) | 1UL));
/* TODO: initialize GIC using the specifications of the FPGA image */
}
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <drivers/arm/gicv3.h>
#include <drivers/arm/gic_common.h>
#include <plat/common/platform.h>
#include <platform_def.h>
static const interrupt_prop_t fpga_interrupt_props[] = {
PLATFORM_G1S_PROPS(INTR_GROUP1S),
PLATFORM_G0_PROPS(INTR_GROUP0)
};
static uintptr_t fpga_rdistif_base_addrs[PLATFORM_CORE_COUNT];
static unsigned int fpga_mpidr_to_core_pos(unsigned long mpidr)
{
return (unsigned int)plat_core_pos_by_mpidr(mpidr);
}
static const gicv3_driver_data_t fpga_gicv3_driver_data = {
.gicd_base = GICD_BASE,
.gicr_base = GICR_BASE,
.interrupt_props = fpga_interrupt_props,
.interrupt_props_num = ARRAY_SIZE(fpga_interrupt_props),
.rdistif_num = PLATFORM_CORE_COUNT,
.rdistif_base_addrs = fpga_rdistif_base_addrs,
.mpidr_to_core_pos = fpga_mpidr_to_core_pos
};
void plat_fpga_gic_init(void)
{
gicv3_driver_init(&fpga_gicv3_driver_data);
gicv3_distif_init();
gicv3_rdistif_init(plat_my_core_pos());
gicv3_cpuif_enable(plat_my_core_pos());
}
void fpga_pwr_gic_on_finish(void)
{
gicv3_rdistif_init(plat_my_core_pos());
gicv3_cpuif_enable(plat_my_core_pos());
}
void fpga_pwr_gic_off(void)
{
gicv3_cpuif_disable(plat_my_core_pos());
gicv3_rdistif_off(plat_my_core_pos());
}

View File

@ -9,6 +9,8 @@
#include <lib/psci/psci.h>
#include <plat/arm/common/plat_arm.h>
#include <plat/common/platform.h>
#include "fpga_private.h"
#include <platform_def.h>
/*
@ -52,8 +54,15 @@ static int fpga_pwr_domain_on(u_register_t mpidr)
return PSCI_E_SUCCESS;
}
void fpga_pwr_domain_on_finish(const psci_power_state_t *target_state)
{
fpga_pwr_gic_on_finish();
}
static void fpga_pwr_domain_off(const psci_power_state_t *target_state)
{
fpga_pwr_gic_off();
while (1) {
wfi();
}
@ -74,6 +83,7 @@ static void fpga_cpu_standby(plat_local_state_t cpu_state)
plat_psci_ops_t plat_fpga_psci_pm_ops = {
.pwr_domain_on = fpga_pwr_domain_on,
.pwr_domain_on_finish = fpga_pwr_domain_on_finish,
.pwr_domain_off = fpga_pwr_domain_off,
.cpu_standby = fpga_cpu_standby
};

View File

@ -11,4 +11,8 @@ unsigned int plat_fpga_calc_core_pos(u_register_t mpidr);
void fpga_console_init(void);
void plat_fpga_gic_init(void);
void fpga_pwr_gic_on_finish(void);
void fpga_pwr_gic_off(void);
#endif

View File

@ -28,8 +28,51 @@
#define BL31_BASE UL(0x80000000)
#define BL31_LIMIT UL(0x80100000)
#define PLAT_MAX_RET_STATE 1
#define PLAT_MAX_OFF_STATE 2
#define GICD_BASE 0x30000000
#define GICR_BASE 0x30040000
#define PLAT_SDEI_NORMAL_PRI 0x70
#define ARM_IRQ_SEC_PHY_TIMER 29
#define ARM_IRQ_SEC_SGI_0 8
#define ARM_IRQ_SEC_SGI_1 9
#define ARM_IRQ_SEC_SGI_2 10
#define ARM_IRQ_SEC_SGI_3 11
#define ARM_IRQ_SEC_SGI_4 12
#define ARM_IRQ_SEC_SGI_5 13
#define ARM_IRQ_SEC_SGI_6 14
#define ARM_IRQ_SEC_SGI_7 15
/*
* Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3
* terminology. On a GICv2 system or mode, the lists will be merged and treated
* as Group 0 interrupts.
*/
#define PLATFORM_G1S_PROPS(grp) \
INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \
GIC_INTR_CFG_LEVEL), \
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, (grp), \
GIC_INTR_CFG_EDGE), \
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, (grp), \
GIC_INTR_CFG_EDGE), \
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, (grp), \
GIC_INTR_CFG_EDGE), \
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, (grp), \
GIC_INTR_CFG_EDGE), \
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, (grp), \
GIC_INTR_CFG_EDGE), \
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, (grp), \
GIC_INTR_CFG_EDGE)
#define PLATFORM_G0_PROPS(grp) \
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, PLAT_SDEI_NORMAL_PRI, (grp), \
GIC_INTR_CFG_EDGE), \
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \
GIC_INTR_CFG_EDGE)
#define PLAT_MAX_RET_STATE 1
#define PLAT_MAX_OFF_STATE 2
#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2

View File

@ -37,9 +37,14 @@ HW_ASSISTED_COHERENCY := 1
FPGA_CPU_LIBS := lib/cpus/${ARCH}/aem_generic.S \
lib/cpus/aarch64/neoverse_zeus.S
FPGA_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
drivers/arm/gic/v3/gicv3_main.c \
plat/common/plat_gicv3.c
FPGA_GIC_SOURCES := drivers/arm/gic/v3/gicv3_helpers.c \
drivers/arm/gic/v3/gicdv3_helpers.c \
drivers/arm/gic/v3/gicrv3_helpers.c \
drivers/arm/gic/v3/gicv3_main.c \
drivers/arm/gic/v3/gic600.c \
drivers/arm/gic/common/gic_common.c \
plat/common/plat_gicv3.c \
plat/arm/board/arm_fpga/fpga_gicv3.c
PLAT_INCLUDES := -Iplat/arm/board/arm_fpga/include