From d33603016971adbe2aba04f96c2a45b56d33f99a Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Mon, 28 Dec 2015 14:55:41 -0800 Subject: [PATCH] Tegra: GIC: enable FIQ interrupt handling Tegra chips support multiple FIQ interrupt sources. These interrupts are enabled in the GICD/GICC interfaces by the tegra_gic driver. A new FIQ handler would be added in a subsequent change which can be registered by the platform code. This patch adds the GIC programming as part of the tegra_gic_setup() which now takes an array of all the FIQ interrupts to be enabled for the platform. The Tegra132 and Tegra210 platforms right now do not register for any FIQ interrupts themselves, but will definitely use this support in the future. Change-Id: I0ea164be901cd6681167028fea0567399f18d4b8 Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/common/tegra_bl31_setup.c | 6 +-- plat/nvidia/tegra/common/tegra_common.mk | 1 - plat/nvidia/tegra/common/tegra_gic.c | 47 ++++++++++++++++++++- plat/nvidia/tegra/common/tegra_pm.c | 2 +- plat/nvidia/tegra/include/t132/tegra_def.h | 5 +++ plat/nvidia/tegra/include/t210/tegra_def.h | 5 +++ plat/nvidia/tegra/include/tegra_private.h | 8 +++- plat/nvidia/tegra/soc/t132/plat_setup.c | 15 ++++++- plat/nvidia/tegra/soc/t210/plat_setup.c | 13 +++++- 9 files changed, 90 insertions(+), 12 deletions(-) diff --git a/plat/nvidia/tegra/common/tegra_bl31_setup.c b/plat/nvidia/tegra/common/tegra_bl31_setup.c index cb38f95f..142839c8 100644 --- a/plat/nvidia/tegra/common/tegra_bl31_setup.c +++ b/plat/nvidia/tegra/common/tegra_bl31_setup.c @@ -185,6 +185,9 @@ void bl31_platform_setup(void) { uint32_t tmp_reg; + /* Initialize the gic cpu and distributor interfaces */ + plat_gic_setup(); + /* * Initialize delay timer */ @@ -216,9 +219,6 @@ void bl31_platform_setup(void) tmp_reg = SCR_RES1_BITS | SCR_RW_BIT; write_scr(tmp_reg); - /* Initialize the gic cpu and distributor interfaces */ - tegra_gic_setup(); - INFO("BL3-1: Tegra platform setup complete\n"); } diff --git a/plat/nvidia/tegra/common/tegra_common.mk b/plat/nvidia/tegra/common/tegra_common.mk index acea50be..de6cd04e 100644 --- a/plat/nvidia/tegra/common/tegra_common.mk +++ b/plat/nvidia/tegra/common/tegra_common.mk @@ -47,7 +47,6 @@ PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \ COMMON_DIR := plat/nvidia/tegra/common BL31_SOURCES += drivers/arm/gic/gic_v2.c \ - drivers/arm/gic/gic_v3.c \ drivers/console/aarch64/console.S \ drivers/delay_timer/delay_timer.c \ drivers/ti/uart/aarch64/16550_console.S \ diff --git a/plat/nvidia/tegra/common/tegra_gic.c b/plat/nvidia/tegra/common/tegra_gic.c index ee129757..786eefc1 100644 --- a/plat/nvidia/tegra/common/tegra_gic.c +++ b/plat/nvidia/tegra/common/tegra_gic.c @@ -47,6 +47,9 @@ (GIC_HIGHEST_NS_PRIORITY << 16) | \ (GIC_HIGHEST_NS_PRIORITY << 24)) +static const unsigned int *g_irq_sec_ptr; +static unsigned int g_num_irqs; + /******************************************************************************* * Place the cpu interface in a state where it can never make a cpu exit wfi as * as result of an asserted interrupt. This is critical for powering down a cpu @@ -110,7 +113,9 @@ static void tegra_gic_pcpu_distif_setup(unsigned int gicd_base) ******************************************************************************/ static void tegra_gic_distif_setup(unsigned int gicd_base) { - unsigned int index, num_ints; + unsigned int index, num_ints, irq_num; + uint8_t target_cpus; + uint32_t val; /* * Mark out non-secure interrupts. Calculate number of @@ -128,6 +133,41 @@ static void tegra_gic_distif_setup(unsigned int gicd_base) GICD_IPRIORITYR_DEF_VAL); } + /* Configure SPI secure interrupts now */ + if (g_irq_sec_ptr) { + + /* Read the target CPU mask */ + target_cpus = TEGRA_SEC_IRQ_TARGET_MASK & GIC_TARGET_CPU_MASK; + + for (index = 0; index < g_num_irqs; index++) { + irq_num = g_irq_sec_ptr[index]; + + if (irq_num >= MIN_SPI_ID) { + + /* Configure as a secure interrupt */ + gicd_clr_igroupr(gicd_base, irq_num); + + /* Configure SPI priority */ + mmio_write_8(gicd_base + GICD_IPRIORITYR + + irq_num, + GIC_HIGHEST_SEC_PRIORITY & + GIC_PRI_MASK); + + /* Configure as level triggered */ + val = gicd_read_icfgr(gicd_base, irq_num); + val |= (3 << ((irq_num & 0xF) << 1)); + gicd_write_icfgr(gicd_base, irq_num, val); + + /* Route SPI to the target CPUs */ + gicd_set_itargetsr(gicd_base, irq_num, + target_cpus); + + /* Enable this interrupt */ + gicd_set_isenabler(gicd_base, irq_num); + } + } + } + /* * Configure the SGI and PPI. This is done in a separated function * because each CPU is responsible for initializing its own private @@ -139,8 +179,11 @@ static void tegra_gic_distif_setup(unsigned int gicd_base) gicd_write_ctlr(gicd_base, ENABLE_GRP0 | ENABLE_GRP1); } -void tegra_gic_setup(void) +void tegra_gic_setup(const unsigned int *irq_sec_ptr, unsigned int num_irqs) { + g_irq_sec_ptr = irq_sec_ptr; + g_num_irqs = num_irqs; + tegra_gic_cpuif_setup(TEGRA_GICC_BASE); tegra_gic_distif_setup(TEGRA_GICD_BASE); } diff --git a/plat/nvidia/tegra/common/tegra_pm.c b/plat/nvidia/tegra/common/tegra_pm.c index 11ea8197..ca49dabd 100644 --- a/plat/nvidia/tegra/common/tegra_pm.c +++ b/plat/nvidia/tegra/common/tegra_pm.c @@ -183,7 +183,7 @@ void tegra_pwr_domain_on_finish(const psci_power_state_t *target_state) /* * Initialize the GIC cpu and distributor interfaces */ - tegra_gic_setup(); + plat_gic_setup(); /* * Check if we are exiting from deep sleep. diff --git a/plat/nvidia/tegra/include/t132/tegra_def.h b/plat/nvidia/tegra/include/t132/tegra_def.h index 318f4def..3bafb87d 100644 --- a/plat/nvidia/tegra/include/t132/tegra_def.h +++ b/plat/nvidia/tegra/include/t132/tegra_def.h @@ -48,6 +48,11 @@ #define PLAT_MAX_RET_STATE 1 #define PLAT_MAX_OFF_STATE (PSTATE_ID_SOC_POWERDN + 1) +/******************************************************************************* + * Secure IRQ definitions + ******************************************************************************/ +#define TEGRA_SEC_IRQ_TARGET_MASK 0x3 /* 2 Denver's */ + /******************************************************************************* * GIC memory map ******************************************************************************/ diff --git a/plat/nvidia/tegra/include/t210/tegra_def.h b/plat/nvidia/tegra/include/t210/tegra_def.h index ce85427e..cc4c2d9f 100644 --- a/plat/nvidia/tegra/include/t210/tegra_def.h +++ b/plat/nvidia/tegra/include/t210/tegra_def.h @@ -56,6 +56,11 @@ #define PLAT_MAX_RET_STATE 1 #define PLAT_MAX_OFF_STATE (PSTATE_ID_SOC_POWERDN + 1) +/******************************************************************************* + * Secure IRQ definitions + ******************************************************************************/ +#define TEGRA_SEC_IRQ_TARGET_MASK 0xF /* 4 A57's or 4 A53's */ + /******************************************************************************* * GIC memory map ******************************************************************************/ diff --git a/plat/nvidia/tegra/include/tegra_private.h b/plat/nvidia/tegra/include/tegra_private.h index ef4d55b4..f5ffa9e0 100644 --- a/plat/nvidia/tegra/include/tegra_private.h +++ b/plat/nvidia/tegra/include/tegra_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -42,6 +42,9 @@ #define TEGRA_DRAM_BASE 0x80000000 #define TEGRA_DRAM_END 0x27FFFFFFF +/******************************************************************************* + * Struct for parameters received from BL2 + ******************************************************************************/ typedef struct plat_params_from_bl2 { /* TZ memory size */ uint64_t tzdram_size; @@ -58,13 +61,14 @@ int32_t tegra_soc_validate_power_state(unsigned int power_state, /* Declarations for plat_setup.c */ const mmap_region_t *plat_get_mmio_map(void); uint32_t plat_get_console_from_id(int id); +void plat_gic_setup(void); /* Declarations for plat_secondary.c */ void plat_secondary_setup(void); int plat_lock_cpu_vectors(void); /* Declarations for tegra_gic.c */ -void tegra_gic_setup(void); +void tegra_gic_setup(const unsigned int *irq_sec_ptr, unsigned int num_irqs); void tegra_gic_cpuif_deactivate(void); /* Declarations for tegra_security.c */ diff --git a/plat/nvidia/tegra/soc/t132/plat_setup.c b/plat/nvidia/tegra/soc/t132/plat_setup.c index 337a2c59..651bd089 100644 --- a/plat/nvidia/tegra/soc/t132/plat_setup.c +++ b/plat/nvidia/tegra/soc/t132/plat_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -28,8 +28,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include +#include +#include #include +#include +#include /******************************************************************************* * The Tegra power domain tree has a single system level power domain i.e. a @@ -106,3 +109,11 @@ uint32_t plat_get_console_from_id(int id) return tegra132_uart_addresses[id]; } + +/******************************************************************************* + * Initialize the GIC and SGIs + ******************************************************************************/ +void plat_gic_setup(void) +{ + tegra_gic_setup(NULL, 0); +} diff --git a/plat/nvidia/tegra/soc/t210/plat_setup.c b/plat/nvidia/tegra/soc/t210/plat_setup.c index 246faf87..42eefe79 100644 --- a/plat/nvidia/tegra/soc/t210/plat_setup.c +++ b/plat/nvidia/tegra/soc/t210/plat_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -28,8 +28,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include +#include #include #include +#include #include /******************************************************************************* @@ -112,3 +115,11 @@ uint32_t plat_get_console_from_id(int id) return tegra210_uart_addresses[id]; } + +/******************************************************************************* + * Initialize the GIC and SGIs + ******************************************************************************/ +void plat_gic_setup(void) +{ + tegra_gic_setup(NULL, 0); +} -- 2.30.2