1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu /* 8*91f16700Schasinglulu * Driver for implementation defined features that are identical in ARM GICv3 9*91f16700Schasinglulu * implementations (GIC-500 and GIC-600 for now). This driver only overrides 10*91f16700Schasinglulu * APIs that are different to those generic ones in GICv3 driver. 11*91f16700Schasinglulu */ 12*91f16700Schasinglulu 13*91f16700Schasinglulu #include <assert.h> 14*91f16700Schasinglulu 15*91f16700Schasinglulu #include <arch_helpers.h> 16*91f16700Schasinglulu #include <drivers/arm/arm_gicv3_common.h> 17*91f16700Schasinglulu #include <drivers/arm/gicv3.h> 18*91f16700Schasinglulu 19*91f16700Schasinglulu #include "gicv3_private.h" 20*91f16700Schasinglulu 21*91f16700Schasinglulu /* 22*91f16700Schasinglulu * Flush the internal GIC cache of the LPIs pending tables to memory before 23*91f16700Schasinglulu * saving the state of the Redistributor. This is required before powering off 24*91f16700Schasinglulu * the GIC when the pending status must be preserved. 25*91f16700Schasinglulu * `rdist_proc_num` is the processor number corresponding to the Redistributor of the 26*91f16700Schasinglulu * current CPU. 27*91f16700Schasinglulu */ 28*91f16700Schasinglulu void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num) 29*91f16700Schasinglulu { 30*91f16700Schasinglulu uintptr_t gicr_base = 0; 31*91f16700Schasinglulu 32*91f16700Schasinglulu assert(gicv3_driver_data); 33*91f16700Schasinglulu assert(gicv3_driver_data->rdistif_base_addrs); 34*91f16700Schasinglulu 35*91f16700Schasinglulu /* 36*91f16700Schasinglulu * The GICR_WAKER.Sleep bit should be set only when both 37*91f16700Schasinglulu * GICR_WAKER.ChildrenAsleep and GICR_WAKER.ProcessorSleep are set on 38*91f16700Schasinglulu * all the Redistributors. 39*91f16700Schasinglulu */ 40*91f16700Schasinglulu for (unsigned int i = 0; i < gicv3_driver_data->rdistif_num; i++) { 41*91f16700Schasinglulu gicr_base = gicv3_driver_data->rdistif_base_addrs[i]; 42*91f16700Schasinglulu assert(gicr_base); 43*91f16700Schasinglulu assert(gicr_read_waker(gicr_base) & WAKER_CA_BIT); 44*91f16700Schasinglulu assert(gicr_read_waker(gicr_base) & WAKER_PS_BIT); 45*91f16700Schasinglulu } 46*91f16700Schasinglulu 47*91f16700Schasinglulu gicr_base = gicv3_driver_data->rdistif_base_addrs[rdist_proc_num]; 48*91f16700Schasinglulu /* 49*91f16700Schasinglulu * According to the TRM, there is only one instance of the 50*91f16700Schasinglulu * GICR_WAKER.Sleep and GICR_WAKER.Quiescent bits that can be accessed 51*91f16700Schasinglulu * through any of the Redistributor. 52*91f16700Schasinglulu */ 53*91f16700Schasinglulu 54*91f16700Schasinglulu /* 55*91f16700Schasinglulu * Set GICR_WAKER.Sleep 56*91f16700Schasinglulu * After this point, the system must be configured so that the 57*91f16700Schasinglulu * wake_request signals for the right cores are asserted when a wakeup 58*91f16700Schasinglulu * interrupt is detected. The GIC will not be able to do that anymore 59*91f16700Schasinglulu * when the GICR_WAKER.Sleep bit is set to 1. 60*91f16700Schasinglulu */ 61*91f16700Schasinglulu gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_SL_BIT); 62*91f16700Schasinglulu 63*91f16700Schasinglulu /* Wait until the GICR_WAKER.Quiescent bit is set */ 64*91f16700Schasinglulu while (!(gicr_read_waker(gicr_base) & WAKER_QSC_BIT)) 65*91f16700Schasinglulu ; 66*91f16700Schasinglulu } 67*91f16700Schasinglulu 68*91f16700Schasinglulu /* 69*91f16700Schasinglulu * Allow the LPIs pending state to be read back from the tables in memory after 70*91f16700Schasinglulu * having restored the state of the GIC Redistributor. 71*91f16700Schasinglulu */ 72*91f16700Schasinglulu void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num) 73*91f16700Schasinglulu { 74*91f16700Schasinglulu uintptr_t gicr_base; 75*91f16700Schasinglulu 76*91f16700Schasinglulu assert(gicv3_driver_data); 77*91f16700Schasinglulu assert(gicv3_driver_data->rdistif_base_addrs); 78*91f16700Schasinglulu 79*91f16700Schasinglulu /* 80*91f16700Schasinglulu * According to the TRM, there is only one instance of the 81*91f16700Schasinglulu * GICR_WAKER.Sleep and GICR_WAKER.Quiescent bits that can be accessed 82*91f16700Schasinglulu * through any of the Redistributor. 83*91f16700Schasinglulu */ 84*91f16700Schasinglulu gicr_base = gicv3_driver_data->rdistif_base_addrs[rdist_proc_num]; 85*91f16700Schasinglulu assert(gicr_base); 86*91f16700Schasinglulu 87*91f16700Schasinglulu /* 88*91f16700Schasinglulu * If the GIC had power removed, the GICR_WAKER state will be reset. 89*91f16700Schasinglulu * Since the GICR_WAKER.Sleep and GICR_WAKER.Quiescent bits are cleared, 90*91f16700Schasinglulu * we can exit early. This also prevents the following assert from 91*91f16700Schasinglulu * erroneously triggering. 92*91f16700Schasinglulu */ 93*91f16700Schasinglulu if (!(gicr_read_waker(gicr_base) & WAKER_SL_BIT)) 94*91f16700Schasinglulu return; 95*91f16700Schasinglulu 96*91f16700Schasinglulu /* 97*91f16700Schasinglulu * Writes to GICR_WAKER.Sleep bit are ignored if GICR_WAKER.Quiescent 98*91f16700Schasinglulu * bit is not set. We should be alright on power on path, therefore 99*91f16700Schasinglulu * coming out of sleep and Quiescent should be set, but we assert in 100*91f16700Schasinglulu * case. 101*91f16700Schasinglulu */ 102*91f16700Schasinglulu assert(gicr_read_waker(gicr_base) & WAKER_QSC_BIT); 103*91f16700Schasinglulu 104*91f16700Schasinglulu /* Clear GICR_WAKER.Sleep */ 105*91f16700Schasinglulu gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) & ~WAKER_SL_BIT); 106*91f16700Schasinglulu 107*91f16700Schasinglulu /* 108*91f16700Schasinglulu * We don't know if the effects of setting GICR_WAKER.Sleep bit is 109*91f16700Schasinglulu * instantaneous, so we wait until the interface is not Quiescent 110*91f16700Schasinglulu * anymore. 111*91f16700Schasinglulu */ 112*91f16700Schasinglulu while (gicr_read_waker(gicr_base) & WAKER_QSC_BIT) 113*91f16700Schasinglulu ; 114*91f16700Schasinglulu } 115*91f16700Schasinglulu 116