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