From 80c50eeaf9cf5aa0c749175f9dcca9774ad041b1 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Fri, 19 Oct 2018 11:42:28 -0700 Subject: [PATCH] Tegra: support for native GICv2 drivers This patch converts Tegra platforms to support native GICv2 drivers. This involves removes Tegra's GIC driver port platforms to use interrupt_props Change-Id: I83d8a690ff276dd97928dc60824a4fd36999bb30 Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/common/tegra_common.mk | 2 +- plat/nvidia/tegra/common/tegra_gic.c | 321 ------------------ plat/nvidia/tegra/common/tegra_gicv2.c | 7 +- plat/nvidia/tegra/include/drivers/tegra_gic.h | 29 ++ plat/nvidia/tegra/include/plat_macros.S | 1 + plat/nvidia/tegra/include/tegra_private.h | 26 +- plat/nvidia/tegra/soc/t132/platform_t132.mk | 2 +- plat/nvidia/tegra/soc/t186/plat_setup.c | 26 +- plat/nvidia/tegra/soc/t210/platform_t210.mk | 10 +- 9 files changed, 54 insertions(+), 370 deletions(-) delete mode 100644 plat/nvidia/tegra/common/tegra_gic.c create mode 100644 plat/nvidia/tegra/include/drivers/tegra_gic.h diff --git a/plat/nvidia/tegra/common/tegra_common.mk b/plat/nvidia/tegra/common/tegra_common.mk index 6469f751..6a0854ee 100644 --- a/plat/nvidia/tegra/common/tegra_common.mk +++ b/plat/nvidia/tegra/common/tegra_common.mk @@ -22,12 +22,12 @@ TEGRA_GICv2_SOURCES := drivers/arm/gic/common/gic_common.c \ BL31_SOURCES += drivers/console/aarch64/console.S \ drivers/delay_timer/delay_timer.c \ drivers/ti/uart/aarch64/16550_console.S \ + ${TEGRA_GICv2_SOURCES} \ ${COMMON_DIR}/aarch64/tegra_helpers.S \ ${COMMON_DIR}/drivers/pmc/pmc.c \ ${COMMON_DIR}/tegra_bl31_setup.c \ ${COMMON_DIR}/tegra_delay_timer.c \ ${COMMON_DIR}/tegra_fiq_glue.c \ - ${COMMON_DIR}/tegra_gic.c \ ${COMMON_DIR}/tegra_platform.c \ ${COMMON_DIR}/tegra_pm.c \ ${COMMON_DIR}/tegra_sip_calls.c \ diff --git a/plat/nvidia/tegra/common/tegra_gic.c b/plat/nvidia/tegra/common/tegra_gic.c deleted file mode 100644 index c3dc5f65..00000000 --- a/plat/nvidia/tegra/common/tegra_gic.c +++ /dev/null @@ -1,321 +0,0 @@ -/* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Value used to initialize Non-Secure IRQ priorities four at a time */ -#define GICD_IPRIORITYR_DEF_VAL \ - (GIC_HIGHEST_NS_PRIORITY | \ - (GIC_HIGHEST_NS_PRIORITY << 8) | \ - (GIC_HIGHEST_NS_PRIORITY << 16) | \ - (GIC_HIGHEST_NS_PRIORITY << 24)) - -static const irq_sec_cfg_t *g_irq_sec_ptr; -static uint32_t 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 - ******************************************************************************/ -void tegra_gic_cpuif_deactivate(void) -{ - uint32_t val; - - /* Disable secure, non-secure interrupts and disable their bypass */ - val = gicc_read_ctlr(TEGRA_GICC_BASE); - val &= ~(ENABLE_GRP0 | ENABLE_GRP1); - val |= FIQ_BYP_DIS_GRP1 | FIQ_BYP_DIS_GRP0; - val |= IRQ_BYP_DIS_GRP0 | IRQ_BYP_DIS_GRP1; - gicc_write_ctlr(TEGRA_GICC_BASE, val); -} - -/******************************************************************************* - * Enable secure interrupts and set the priority mask register to allow all - * interrupts to trickle in. - ******************************************************************************/ -static void tegra_gic_cpuif_setup(uint32_t gicc_base) -{ - uint32_t val; - - val = ENABLE_GRP0 | ENABLE_GRP1 | FIQ_EN | FIQ_BYP_DIS_GRP0; - val |= IRQ_BYP_DIS_GRP0 | FIQ_BYP_DIS_GRP1 | IRQ_BYP_DIS_GRP1; - - gicc_write_ctlr(gicc_base, val); - gicc_write_pmr(gicc_base, GIC_PRI_MASK); -} - -/******************************************************************************* - * Per cpu gic distributor setup which will be done by all cpus after a cold - * boot/hotplug. This marks out the secure interrupts & enables them. - ******************************************************************************/ -static void tegra_gic_pcpu_distif_setup(uint32_t gicd_base) -{ - uint32_t index, sec_ppi_sgi_mask = 0; - - assert(gicd_base != 0U); - - /* Setup PPI priorities doing four at a time */ - for (index = 0U; index < 32U; index += 4U) { - gicd_write_ipriorityr(gicd_base, index, - GICD_IPRIORITYR_DEF_VAL); - } - - /* - * Invert the bitmask to create a mask for non-secure PPIs and - * SGIs. Program the GICD_IGROUPR0 with this bit mask. This write will - * update the GICR_IGROUPR0 as well in case we are running on a GICv3 - * system. This is critical if GICD_CTLR.ARE_NS=1. - */ - gicd_write_igroupr(gicd_base, 0, ~sec_ppi_sgi_mask); -} - -/******************************************************************************* - * Global gic distributor setup which will be done by the primary cpu after a - * cold boot. It marks out the non secure SPIs, PPIs & SGIs and enables them. - * It then enables the secure GIC distributor interface. - ******************************************************************************/ -static void tegra_gic_distif_setup(uint32_t gicd_base) -{ - uint32_t index, num_ints, irq_num; - uint8_t target_cpus; - uint32_t val; - - /* - * Mark out non-secure interrupts. Calculate number of - * IGROUPR registers to consider. Will be equal to the - * number of IT_LINES - */ - num_ints = gicd_read_typer(gicd_base) & IT_LINES_NO_MASK; - num_ints = (num_ints + 1U) << 5; - for (index = MIN_SPI_ID; index < num_ints; index += 32U) { - gicd_write_igroupr(gicd_base, index, 0xFFFFFFFFU); - } - - /* Setup SPI priorities doing four at a time */ - for (index = MIN_SPI_ID; index < num_ints; index += 4U) { - gicd_write_ipriorityr(gicd_base, index, - GICD_IPRIORITYR_DEF_VAL); - } - - /* Configure SPI secure interrupts now */ - if (g_irq_sec_ptr != NULL) { - - for (index = 0U; index < g_num_irqs; index++) { - irq_num = g_irq_sec_ptr[index].irq; - target_cpus = (uint8_t)g_irq_sec_ptr[index].target_cpus; - - if (irq_num >= MIN_SPI_ID) { - - /* Configure as a secure interrupt */ - gicd_clr_igroupr(gicd_base, irq_num); - - /* Configure SPI priority */ - mmio_write_8((uint64_t)gicd_base + - (uint64_t)GICD_IPRIORITYR + - (uint64_t)irq_num, - GIC_HIGHEST_SEC_PRIORITY & - GIC_PRI_MASK); - - /* Configure as level triggered */ - val = gicd_read_icfgr(gicd_base, irq_num); - val |= (3U << ((irq_num & 0xFU) << 1U)); - 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 - * interrupts. - */ - tegra_gic_pcpu_distif_setup(gicd_base); - - /* enable distributor */ - gicd_write_ctlr(gicd_base, ENABLE_GRP0 | ENABLE_GRP1); -} - -void tegra_gic_setup(const irq_sec_cfg_t *irq_sec_ptr, uint32_t 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); -} - -/******************************************************************************* - * An ARM processor signals interrupt exceptions through the IRQ and FIQ pins. - * The interrupt controller knows which pin/line it uses to signal a type of - * interrupt. This function provides a common implementation of - * plat_interrupt_type_to_line() in an ARM GIC environment for optional re-use - * across platforms. It lets the interrupt management framework determine - * for a type of interrupt and security state, which line should be used in the - * SCR_EL3 to control its routing to EL3. The interrupt line is represented as - * the bit position of the IRQ or FIQ bit in the SCR_EL3. - ******************************************************************************/ -static uint32_t tegra_gic_interrupt_type_to_line(uint32_t type, - uint32_t security_state) -{ - assert((type == INTR_TYPE_S_EL1) || - (type == INTR_TYPE_EL3) || - (type == INTR_TYPE_NS)); - - assert(sec_state_is_valid(security_state)); - - /* - * We ignore the security state parameter under the assumption that - * both normal and secure worlds are using ARM GICv2. This parameter - * will be used when the secure world starts using GICv3. - */ - return gicv2_interrupt_type_to_line(TEGRA_GICC_BASE, type); -} - -/******************************************************************************* - * This function returns the type of the highest priority pending interrupt at - * the GIC cpu interface. INTR_TYPE_INVAL is returned when there is no - * interrupt pending. - ******************************************************************************/ -static uint32_t tegra_gic_get_pending_interrupt_type(void) -{ - uint32_t id; - uint32_t index; - uint32_t ret = INTR_TYPE_NS; - - id = gicc_read_hppir(TEGRA_GICC_BASE) & INT_ID_MASK; - - /* get the interrupt type */ - if (id < 1022U) { - for (index = 0U; index < g_num_irqs; index++) { - if (id == g_irq_sec_ptr[index].irq) { - ret = g_irq_sec_ptr[index].type; - break; - } - } - } else { - if (id == GIC_SPURIOUS_INTERRUPT) { - ret = INTR_TYPE_INVAL; - } - } - - return ret; -} - -/******************************************************************************* - * This function returns the id of the highest priority pending interrupt at - * the GIC cpu interface. INTR_ID_UNAVAILABLE is returned when there is no - * interrupt pending. - ******************************************************************************/ -static uint32_t tegra_gic_get_pending_interrupt_id(void) -{ - uint32_t id, ret; - - id = gicc_read_hppir(TEGRA_GICC_BASE) & INT_ID_MASK; - - if (id < 1022U) { - ret = id; - } else if (id == 1023U) { - ret = 0xFFFFFFFFU; /* INTR_ID_UNAVAILABLE */ - } else { - /* - * Find out which non-secure interrupt it is under the assumption that - * the GICC_CTLR.AckCtl bit is 0. - */ - ret = gicc_read_ahppir(TEGRA_GICC_BASE) & INT_ID_MASK; - } - - return ret; -} - -/******************************************************************************* - * This functions reads the GIC cpu interface Interrupt Acknowledge register - * to start handling the pending interrupt. It returns the contents of the IAR. - ******************************************************************************/ -static uint32_t tegra_gic_acknowledge_interrupt(void) -{ - return gicc_read_IAR(TEGRA_GICC_BASE); -} - -/******************************************************************************* - * This functions writes the GIC cpu interface End Of Interrupt register with - * the passed value to finish handling the active interrupt - ******************************************************************************/ -static void tegra_gic_end_of_interrupt(uint32_t id) -{ - gicc_write_EOIR(TEGRA_GICC_BASE, id); -} - -/******************************************************************************* - * This function returns the type of the interrupt id depending upon the group - * this interrupt has been configured under by the interrupt controller i.e. - * group0 or group1. - ******************************************************************************/ -static uint32_t tegra_gic_get_interrupt_type(uint32_t id) -{ - uint32_t group; - uint32_t index; - uint32_t ret = INTR_TYPE_NS; - - group = gicd_get_igroupr(TEGRA_GICD_BASE, id); - - /* get the interrupt type */ - if (group == GRP0) { - for (index = 0U; index < g_num_irqs; index++) { - if (id == g_irq_sec_ptr[index].irq) { - ret = g_irq_sec_ptr[index].type; - break; - } - } - } - - return ret; -} - -uint32_t plat_ic_get_pending_interrupt_id(void) -{ - return tegra_gic_get_pending_interrupt_id(); -} - -uint32_t plat_ic_get_pending_interrupt_type(void) -{ - return tegra_gic_get_pending_interrupt_type(); -} - -uint32_t plat_ic_acknowledge_interrupt(void) -{ - return tegra_gic_acknowledge_interrupt(); -} - -uint32_t plat_ic_get_interrupt_type(uint32_t id) -{ - return tegra_gic_get_interrupt_type(id); -} - -void plat_ic_end_of_interrupt(uint32_t id) -{ - tegra_gic_end_of_interrupt(id); -} - -uint32_t plat_interrupt_type_to_line(uint32_t type, - uint32_t security_state) -{ - return tegra_gic_interrupt_type_to_line(type, security_state); -} diff --git a/plat/nvidia/tegra/common/tegra_gicv2.c b/plat/nvidia/tegra/common/tegra_gicv2.c index 6ccbd156..c42c5ec3 100644 --- a/plat/nvidia/tegra/common/tegra_gicv2.c +++ b/plat/nvidia/tegra/common/tegra_gicv2.c @@ -15,7 +15,8 @@ /****************************************************************************** * Tegra common helper to setup the GICv2 driver data. *****************************************************************************/ -void tegra_gic_setup(tegra_gic_cfg_t *cfg) +void tegra_gic_setup(const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num) { /* * Tegra GIC configuration settings @@ -27,8 +28,8 @@ void tegra_gic_setup(tegra_gic_cfg_t *cfg) */ tegra_gic_data.gicd_base = TEGRA_GICD_BASE; tegra_gic_data.gicc_base = TEGRA_GICC_BASE; - tegra_gic_data.g0_interrupt_num = cfg->g0_int_num; - tegra_gic_data.g0_interrupt_array = cfg->g0_int_array; + tegra_gic_data.interrupt_props = interrupt_props; + tegra_gic_data.interrupt_props_num = interrupt_props_num; gicv2_driver_init(&tegra_gic_data); } diff --git a/plat/nvidia/tegra/include/drivers/tegra_gic.h b/plat/nvidia/tegra/include/drivers/tegra_gic.h new file mode 100644 index 00000000..2fe316d2 --- /dev/null +++ b/plat/nvidia/tegra/include/drivers/tegra_gic.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __TEGRA_GIC_H__ +#define __TEGRA_GIC_H__ + +#include + +/******************************************************************************* + * Per-CPU struct describing FIQ state to be stored + ******************************************************************************/ +typedef struct pcpu_fiq_state { + uint64_t elr_el3; + uint64_t spsr_el3; +} pcpu_fiq_state_t; + +/******************************************************************************* + * Fucntion declarations + ******************************************************************************/ +void tegra_gic_cpuif_deactivate(void); +void tegra_gic_init(void); +void tegra_gic_pcpu_init(void); +void tegra_gic_setup(const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num); + +#endif /* __TEGRA_GIC_H__ */ diff --git a/plat/nvidia/tegra/include/plat_macros.S b/plat/nvidia/tegra/include/plat_macros.S index 14e7d8a3..01ae821e 100644 --- a/plat/nvidia/tegra/include/plat_macros.S +++ b/plat/nvidia/tegra/include/plat_macros.S @@ -7,6 +7,7 @@ #ifndef PLAT_MACROS_S #define PLAT_MACROS_S +#include #include .section .rodata.gic_reg_name, "aS" diff --git a/plat/nvidia/tegra/include/tegra_private.h b/plat/nvidia/tegra/include/tegra_private.h index c4c277eb..7ca32c3d 100644 --- a/plat/nvidia/tegra/include/tegra_private.h +++ b/plat/nvidia/tegra/include/tegra_private.h @@ -8,8 +8,10 @@ #define TEGRA_PRIVATE_H #include +#include #include #include +#include #include /******************************************************************************* @@ -30,26 +32,6 @@ typedef struct plat_params_from_bl2 { int uart_id; } plat_params_from_bl2_t; -/******************************************************************************* - * Per-CPU struct describing FIQ state to be stored - ******************************************************************************/ -typedef struct pcpu_fiq_state { - uint64_t elr_el3; - uint64_t spsr_el3; -} pcpu_fiq_state_t; - -/******************************************************************************* - * Struct describing per-FIQ configuration settings - ******************************************************************************/ -typedef struct irq_sec_cfg { - /* IRQ number */ - unsigned int irq; - /* Target CPUs servicing this interrupt */ - unsigned int target_cpus; - /* type = INTR_TYPE_S_EL1 or INTR_TYPE_EL3 */ - uint32_t type; -} irq_sec_cfg_t; - /******************************************************************************* * Struct describing parameters passed to bl31 ******************************************************************************/ @@ -82,10 +64,6 @@ void tegra_fiq_handler_setup(void); int tegra_fiq_get_intr_context(void); void tegra_fiq_set_ns_entrypoint(uint64_t entrypoint); -/* Declarations for tegra_gic.c */ -void tegra_gic_cpuif_deactivate(void); -void tegra_gic_setup(const irq_sec_cfg_t *irq_sec_ptr, uint32_t num_irqs); - /* Declarations for tegra_security.c */ void tegra_security_setup(void); void tegra_security_setup_videomem(uintptr_t base, uint64_t size); diff --git a/plat/nvidia/tegra/soc/t132/platform_t132.mk b/plat/nvidia/tegra/soc/t132/platform_t132.mk index 8b3d238f..f15ee747 100644 --- a/plat/nvidia/tegra/soc/t132/platform_t132.mk +++ b/plat/nvidia/tegra/soc/t132/platform_t132.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c index 233644b6..da5530f0 100644 --- a/plat/nvidia/tegra/soc/t186/plat_setup.c +++ b/plat/nvidia/tegra/soc/t186/plat_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -14,7 +14,10 @@ #include #include #include +#include +#include #include +#include #include #include #include @@ -185,17 +188,11 @@ void plat_early_platform_setup(void) } /* Secure IRQs for Tegra186 */ -static const irq_sec_cfg_t tegra186_sec_irqs[] = { - { - TEGRA186_TOP_WDT_IRQ, - TEGRA186_SEC_IRQ_TARGET_MASK, - INTR_TYPE_EL3, - }, - { - TEGRA186_AON_WDT_IRQ, - TEGRA186_SEC_IRQ_TARGET_MASK, - INTR_TYPE_EL3, - }, +static const interrupt_prop_t tegra186_interrupt_props[] = { + INTR_PROP_DESC(TEGRA186_TOP_WDT_IRQ, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(TEGRA186_AON_WDT_IRQ, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE) }; /******************************************************************************* @@ -203,14 +200,13 @@ static const irq_sec_cfg_t tegra186_sec_irqs[] = { ******************************************************************************/ void plat_gic_setup(void) { - tegra_gic_setup(tegra186_sec_irqs, - sizeof(tegra186_sec_irqs) / sizeof(tegra186_sec_irqs[0])); + tegra_gic_setup(tegra186_interrupt_props, ARRAY_SIZE(tegra186_interrupt_props)); /* * Initialize the FIQ handler only if the platform supports any * FIQ interrupt sources. */ - if (sizeof(tegra186_sec_irqs) > 0) + if (sizeof(tegra186_interrupt_props) > 0) tegra_fiq_handler_setup(); } diff --git a/plat/nvidia/tegra/soc/t210/platform_t210.mk b/plat/nvidia/tegra/soc/t210/platform_t210.mk index 97ca3f1d..b0a474c8 100644 --- a/plat/nvidia/tegra/soc/t210/platform_t210.mk +++ b/plat/nvidia/tegra/soc/t210/platform_t210.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -22,12 +22,12 @@ $(eval $(call add_define,MAX_XLAT_TABLES)) MAX_MMAP_REGIONS := 8 $(eval $(call add_define,MAX_MMAP_REGIONS)) -BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ - lib/cpus/aarch64/cortex_a57.S \ +BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S \ ${COMMON_DIR}/drivers/flowctrl/flowctrl.c \ ${COMMON_DIR}/drivers/memctrl/memctrl_v1.c \ - ${SOC_DIR}/plat_psci_handlers.c \ - ${SOC_DIR}/plat_setup.c \ + ${SOC_DIR}/plat_psci_handlers.c \ + ${SOC_DIR}/plat_setup.c \ ${SOC_DIR}/plat_secondary.c # Enable workarounds for selected Cortex-A57 erratas. -- 2.30.2