1a2847172SGrzegorz Jaszczyk /* 2a2847172SGrzegorz Jaszczyk * Copyright (C) 2018 Marvell International Ltd. 3a2847172SGrzegorz Jaszczyk * 4a2847172SGrzegorz Jaszczyk * SPDX-License-Identifier: BSD-3-Clause 5a2847172SGrzegorz Jaszczyk * https://spdx.org/licenses 6a2847172SGrzegorz Jaszczyk */ 7a2847172SGrzegorz Jaszczyk 8a2847172SGrzegorz Jaszczyk #include <platform_def.h> 9a2847172SGrzegorz Jaszczyk 10a2847172SGrzegorz Jaszczyk #include <common/debug.h> 11a2847172SGrzegorz Jaszczyk #include <common/interrupt_props.h> 12a2847172SGrzegorz Jaszczyk #include <drivers/arm/gicv3.h> 13a2847172SGrzegorz Jaszczyk #include <plat/common/platform.h> 14a2847172SGrzegorz Jaszczyk 15a2847172SGrzegorz Jaszczyk #include <marvell_def.h> 16a2847172SGrzegorz Jaszczyk #include <plat_marvell.h> 17a2847172SGrzegorz Jaszczyk 18a2847172SGrzegorz Jaszczyk /****************************************************************************** 19a2847172SGrzegorz Jaszczyk * The following functions are defined as weak to allow a platform to override 20a2847172SGrzegorz Jaszczyk * the way the GICv3 driver is initialised and used. 21a2847172SGrzegorz Jaszczyk ****************************************************************************** 22a2847172SGrzegorz Jaszczyk */ 23a2847172SGrzegorz Jaszczyk #pragma weak plat_marvell_gic_driver_init 24a2847172SGrzegorz Jaszczyk #pragma weak plat_marvell_gic_init 25a2847172SGrzegorz Jaszczyk #pragma weak plat_marvell_gic_cpuif_enable 26a2847172SGrzegorz Jaszczyk #pragma weak plat_marvell_gic_cpuif_disable 27a2847172SGrzegorz Jaszczyk #pragma weak plat_marvell_gic_pcpu_init 28a2847172SGrzegorz Jaszczyk 29a2847172SGrzegorz Jaszczyk /* The GICv3 driver only needs to be initialized in EL3 */ 30a2847172SGrzegorz Jaszczyk static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; 31a2847172SGrzegorz Jaszczyk 32a2847172SGrzegorz Jaszczyk static const interrupt_prop_t marvell_interrupt_props[] = { 33a2847172SGrzegorz Jaszczyk PLAT_MARVELL_G1S_IRQ_PROPS(INTR_GROUP1S), 34a2847172SGrzegorz Jaszczyk PLAT_MARVELL_G0_IRQ_PROPS(INTR_GROUP0) 35a2847172SGrzegorz Jaszczyk }; 36a2847172SGrzegorz Jaszczyk 37a2847172SGrzegorz Jaszczyk /* 38a2847172SGrzegorz Jaszczyk * We save and restore the GICv3 context on system suspend. Allocate the 39a2847172SGrzegorz Jaszczyk * data in the designated EL3 Secure carve-out memory 40a2847172SGrzegorz Jaszczyk */ 41*da04341eSChris Kay static gicv3_redist_ctx_t rdist_ctx __section(".arm_el3_tzc_dram"); 42*da04341eSChris Kay static gicv3_dist_ctx_t dist_ctx __section(".arm_el3_tzc_dram"); 43a2847172SGrzegorz Jaszczyk 44a2847172SGrzegorz Jaszczyk /* 45a2847172SGrzegorz Jaszczyk * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register 46a2847172SGrzegorz Jaszczyk * to core position. 47a2847172SGrzegorz Jaszczyk * 48a2847172SGrzegorz Jaszczyk * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity 49a2847172SGrzegorz Jaszczyk * values read from GICR_TYPER don't have an MT field. To reuse the same 50a2847172SGrzegorz Jaszczyk * translation used for CPUs, we insert MT bit read from the PE's MPIDR into 51a2847172SGrzegorz Jaszczyk * that read from GICR_TYPER. 52a2847172SGrzegorz Jaszczyk * 53a2847172SGrzegorz Jaszczyk * Assumptions: 54a2847172SGrzegorz Jaszczyk * 55a2847172SGrzegorz Jaszczyk * - All CPUs implemented in the system have MPIDR_EL1.MT bit set; 56a2847172SGrzegorz Jaszczyk * - No CPUs implemented in the system use affinity level 3. 57a2847172SGrzegorz Jaszczyk */ 58a2847172SGrzegorz Jaszczyk static unsigned int marvell_gicv3_mpidr_hash(u_register_t mpidr) 59a2847172SGrzegorz Jaszczyk { 60a2847172SGrzegorz Jaszczyk mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); 61a2847172SGrzegorz Jaszczyk return plat_marvell_calc_core_pos(mpidr); 62a2847172SGrzegorz Jaszczyk } 63a2847172SGrzegorz Jaszczyk 64a2847172SGrzegorz Jaszczyk const gicv3_driver_data_t marvell_gic_data = { 65a2847172SGrzegorz Jaszczyk .gicd_base = PLAT_MARVELL_GICD_BASE, 66a2847172SGrzegorz Jaszczyk .gicr_base = PLAT_MARVELL_GICR_BASE, 67a2847172SGrzegorz Jaszczyk .interrupt_props = marvell_interrupt_props, 68a2847172SGrzegorz Jaszczyk .interrupt_props_num = ARRAY_SIZE(marvell_interrupt_props), 69a2847172SGrzegorz Jaszczyk .rdistif_num = PLATFORM_CORE_COUNT, 70a2847172SGrzegorz Jaszczyk .rdistif_base_addrs = rdistif_base_addrs, 71a2847172SGrzegorz Jaszczyk .mpidr_to_core_pos = marvell_gicv3_mpidr_hash 72a2847172SGrzegorz Jaszczyk }; 73a2847172SGrzegorz Jaszczyk 74a2847172SGrzegorz Jaszczyk void plat_marvell_gic_driver_init(void) 75a2847172SGrzegorz Jaszczyk { 76a2847172SGrzegorz Jaszczyk /* 77a2847172SGrzegorz Jaszczyk * The GICv3 driver is initialized in EL3 and does not need 78a2847172SGrzegorz Jaszczyk * to be initialized again in SEL1. This is because the S-EL1 79a2847172SGrzegorz Jaszczyk * can use GIC system registers to manage interrupts and does 80a2847172SGrzegorz Jaszczyk * not need GIC interface base addresses to be configured. 81a2847172SGrzegorz Jaszczyk */ 82a2847172SGrzegorz Jaszczyk #if IMAGE_BL31 83a2847172SGrzegorz Jaszczyk gicv3_driver_init(&marvell_gic_data); 84a2847172SGrzegorz Jaszczyk #endif 85a2847172SGrzegorz Jaszczyk } 86a2847172SGrzegorz Jaszczyk 87a2847172SGrzegorz Jaszczyk /****************************************************************************** 88a2847172SGrzegorz Jaszczyk * Marvell common helper to initialize the GIC. Only invoked by BL31 89a2847172SGrzegorz Jaszczyk ****************************************************************************** 90a2847172SGrzegorz Jaszczyk */ 91a2847172SGrzegorz Jaszczyk void plat_marvell_gic_init(void) 92a2847172SGrzegorz Jaszczyk { 93a2847172SGrzegorz Jaszczyk /* Initialize GIC-600 Multi Chip feature, 94a2847172SGrzegorz Jaszczyk * only if the maximum number of north bridges 95a2847172SGrzegorz Jaszczyk * is more than 1 - otherwise no need for multi 96a2847172SGrzegorz Jaszczyk * chip feature initialization 97a2847172SGrzegorz Jaszczyk */ 98a2847172SGrzegorz Jaszczyk #if (PLAT_MARVELL_NORTHB_COUNT > 1) 99a2847172SGrzegorz Jaszczyk if (gic600_multi_chip_init()) 100a2847172SGrzegorz Jaszczyk ERROR("GIC-600 Multi Chip initialization failed\n"); 101a2847172SGrzegorz Jaszczyk #endif 102a2847172SGrzegorz Jaszczyk gicv3_distif_init(); 103a2847172SGrzegorz Jaszczyk gicv3_rdistif_init(plat_my_core_pos()); 104a2847172SGrzegorz Jaszczyk gicv3_cpuif_enable(plat_my_core_pos()); 105a2847172SGrzegorz Jaszczyk } 106a2847172SGrzegorz Jaszczyk 107a2847172SGrzegorz Jaszczyk /****************************************************************************** 108a2847172SGrzegorz Jaszczyk * Marvell common helper to enable the GIC CPU interface 109a2847172SGrzegorz Jaszczyk ****************************************************************************** 110a2847172SGrzegorz Jaszczyk */ 111a2847172SGrzegorz Jaszczyk void plat_marvell_gic_cpuif_enable(void) 112a2847172SGrzegorz Jaszczyk { 113a2847172SGrzegorz Jaszczyk gicv3_cpuif_enable(plat_my_core_pos()); 114a2847172SGrzegorz Jaszczyk } 115a2847172SGrzegorz Jaszczyk 116a2847172SGrzegorz Jaszczyk /****************************************************************************** 117a2847172SGrzegorz Jaszczyk * Marvell common helper to disable the GIC CPU interface 118a2847172SGrzegorz Jaszczyk ****************************************************************************** 119a2847172SGrzegorz Jaszczyk */ 120a2847172SGrzegorz Jaszczyk void plat_marvell_gic_cpuif_disable(void) 121a2847172SGrzegorz Jaszczyk { 122a2847172SGrzegorz Jaszczyk gicv3_cpuif_disable(plat_my_core_pos()); 123a2847172SGrzegorz Jaszczyk } 124a2847172SGrzegorz Jaszczyk 125a2847172SGrzegorz Jaszczyk /****************************************************************************** 126a2847172SGrzegorz Jaszczyk * Marvell common helper to init. the per-cpu redistributor interface in GICv3 127a2847172SGrzegorz Jaszczyk ****************************************************************************** 128a2847172SGrzegorz Jaszczyk */ 129a2847172SGrzegorz Jaszczyk void plat_marvell_gic_pcpu_init(void) 130a2847172SGrzegorz Jaszczyk { 131a2847172SGrzegorz Jaszczyk gicv3_rdistif_init(plat_my_core_pos()); 132a2847172SGrzegorz Jaszczyk } 133a2847172SGrzegorz Jaszczyk 134a2847172SGrzegorz Jaszczyk /****************************************************************************** 135a2847172SGrzegorz Jaszczyk * Marvell common helper to save SPI irq states in GICv3 136a2847172SGrzegorz Jaszczyk ****************************************************************************** 137a2847172SGrzegorz Jaszczyk */ 138a2847172SGrzegorz Jaszczyk void plat_marvell_gic_irq_save(void) 139a2847172SGrzegorz Jaszczyk { 140a2847172SGrzegorz Jaszczyk 141a2847172SGrzegorz Jaszczyk /* 142a2847172SGrzegorz Jaszczyk * If an ITS is available, save its context before 143a2847172SGrzegorz Jaszczyk * the Redistributor using: 144a2847172SGrzegorz Jaszczyk * gicv3_its_save_disable(gits_base, &its_ctx[i]) 145a2847172SGrzegorz Jaszczyk * Additionally, an implementation-defined sequence may 146a2847172SGrzegorz Jaszczyk * be required to save the whole ITS state. 147a2847172SGrzegorz Jaszczyk */ 148a2847172SGrzegorz Jaszczyk 149a2847172SGrzegorz Jaszczyk /* 150a2847172SGrzegorz Jaszczyk * Save the GIC Redistributors and ITS contexts before the 151a2847172SGrzegorz Jaszczyk * Distributor context. As we only handle SYSTEM SUSPEND API, 152a2847172SGrzegorz Jaszczyk * we only need to save the context of the CPU that is issuing 153a2847172SGrzegorz Jaszczyk * the SYSTEM SUSPEND call, i.e. the current CPU. 154a2847172SGrzegorz Jaszczyk */ 155a2847172SGrzegorz Jaszczyk gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx); 156a2847172SGrzegorz Jaszczyk 157a2847172SGrzegorz Jaszczyk /* Save the GIC Distributor context */ 158a2847172SGrzegorz Jaszczyk gicv3_distif_save(&dist_ctx); 159a2847172SGrzegorz Jaszczyk 160a2847172SGrzegorz Jaszczyk /* 161a2847172SGrzegorz Jaszczyk * From here, all the components of the GIC can be safely powered down 162a2847172SGrzegorz Jaszczyk * as long as there is an alternate way to handle wakeup interrupt 163a2847172SGrzegorz Jaszczyk * sources. 164a2847172SGrzegorz Jaszczyk */ 165a2847172SGrzegorz Jaszczyk } 166a2847172SGrzegorz Jaszczyk 167a2847172SGrzegorz Jaszczyk /****************************************************************************** 168a2847172SGrzegorz Jaszczyk * Marvell common helper to restore SPI irq states in GICv3 169a2847172SGrzegorz Jaszczyk ****************************************************************************** 170a2847172SGrzegorz Jaszczyk */ 171a2847172SGrzegorz Jaszczyk void plat_marvell_gic_irq_restore(void) 172a2847172SGrzegorz Jaszczyk { 173a2847172SGrzegorz Jaszczyk /* Restore the GIC Distributor context */ 174a2847172SGrzegorz Jaszczyk gicv3_distif_init_restore(&dist_ctx); 175a2847172SGrzegorz Jaszczyk 176a2847172SGrzegorz Jaszczyk /* 177a2847172SGrzegorz Jaszczyk * Restore the GIC Redistributor and ITS contexts after the 178a2847172SGrzegorz Jaszczyk * Distributor context. As we only handle SYSTEM SUSPEND API, 179a2847172SGrzegorz Jaszczyk * we only need to restore the context of the CPU that issued 180a2847172SGrzegorz Jaszczyk * the SYSTEM SUSPEND call. 181a2847172SGrzegorz Jaszczyk */ 182a2847172SGrzegorz Jaszczyk gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx); 183a2847172SGrzegorz Jaszczyk 184a2847172SGrzegorz Jaszczyk /* 185a2847172SGrzegorz Jaszczyk * If an ITS is available, restore its context after 186a2847172SGrzegorz Jaszczyk * the Redistributor using: 187a2847172SGrzegorz Jaszczyk * gicv3_its_restore(gits_base, &its_ctx[i]) 188a2847172SGrzegorz Jaszczyk * An implementation-defined sequence may be required to 189a2847172SGrzegorz Jaszczyk * restore the whole ITS state. The ITS must also be 190a2847172SGrzegorz Jaszczyk * re-enabled after this sequence has been executed. 191a2847172SGrzegorz Jaszczyk */ 192a2847172SGrzegorz Jaszczyk } 193a2847172SGrzegorz Jaszczyk 194a2847172SGrzegorz Jaszczyk /****************************************************************************** 195a2847172SGrzegorz Jaszczyk * Marvell common helper to save per-cpu PPI irq states in GICv3 196a2847172SGrzegorz Jaszczyk ****************************************************************************** 197a2847172SGrzegorz Jaszczyk */ 198a2847172SGrzegorz Jaszczyk void plat_marvell_gic_irq_pcpu_save(void) 199a2847172SGrzegorz Jaszczyk { 200a2847172SGrzegorz Jaszczyk gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx); 201a2847172SGrzegorz Jaszczyk } 202a2847172SGrzegorz Jaszczyk 203a2847172SGrzegorz Jaszczyk /****************************************************************************** 204a2847172SGrzegorz Jaszczyk * Marvell common helper to restore per-cpu PPI irq states in GICv3 205a2847172SGrzegorz Jaszczyk ****************************************************************************** 206a2847172SGrzegorz Jaszczyk */ 207a2847172SGrzegorz Jaszczyk void plat_marvell_gic_irq_pcpu_restore(void) 208a2847172SGrzegorz Jaszczyk { 209a2847172SGrzegorz Jaszczyk gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx); 210a2847172SGrzegorz Jaszczyk } 211