Home | History | Annotate | Download | only in v3
      1 /*
      2  * Copyright (c) 2017, 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 <arch_helpers.h>
     14 #include <assert.h>
     15 #include <gicv3.h>
     16 
     17 #include "gicv3_private.h"
     18 #include "arm_gicv3_common.h"
     19 
     20 /*
     21  * Flush the internal GIC cache of the LPIs pending tables to memory before
     22  * saving the state of the Redistributor. This is required before powering off
     23  * the GIC when the pending status must be preserved.
     24  * `rdist_proc_num` is the processor number corresponding to the Redistributor of the
     25  * current CPU.
     26  */
     27 void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num)
     28 {
     29 	uintptr_t gicr_base = 0;
     30 
     31 	assert(gicv3_driver_data);
     32 	assert(gicv3_driver_data->rdistif_base_addrs);
     33 
     34 	/*
     35 	 * The GICR_WAKER.Sleep bit should be set only when both
     36 	 * GICR_WAKER.ChildrenAsleep and GICR_WAKER.ProcessorSleep are set on
     37 	 * all the Redistributors.
     38 	 */
     39 	for (unsigned int i = 0; i < gicv3_driver_data->rdistif_num; i++) {
     40 		gicr_base = gicv3_driver_data->rdistif_base_addrs[i];
     41 		assert(gicr_base);
     42 		assert(gicr_read_waker(gicr_base) & WAKER_CA_BIT);
     43 		assert(gicr_read_waker(gicr_base) & WAKER_PS_BIT);
     44 	}
     45 
     46 	gicr_base = gicv3_driver_data->rdistif_base_addrs[rdist_proc_num];
     47 	/*
     48 	 * According to the TRM, there is only one instance of the
     49 	 * GICR_WAKER.Sleep and GICR_WAKER.Quiescent bits that can be accessed
     50 	 * through any of the Redistributor.
     51 	 */
     52 
     53 	/*
     54 	 * Set GICR_WAKER.Sleep
     55 	 * After this point, the system must be configured so that the
     56 	 * wake_request signals for the right cores are asserted when a wakeup
     57 	 * interrupt is detected. The GIC will not be able to do that anymore
     58 	 * when the GICR_WAKER.Sleep bit is set to 1.
     59 	 */
     60 	gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_SL_BIT);
     61 
     62 	/* Wait until the GICR_WAKER.Quiescent bit is set */
     63 	while (!(gicr_read_waker(gicr_base) & WAKER_QSC_BIT))
     64 		;
     65 }
     66 
     67 /*
     68  * Allow the LPIs pending state to be read back from the tables in memory after
     69  * having restored the state of the GIC Redistributor.
     70  */
     71 void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num)
     72 {
     73 	uintptr_t gicr_base;
     74 
     75 	assert(gicv3_driver_data);
     76 	assert(gicv3_driver_data->rdistif_base_addrs);
     77 
     78 	/*
     79 	 * According to the TRM, there is only one instance of the
     80 	 * GICR_WAKER.Sleep and GICR_WAKER.Quiescent bits that can be accessed
     81 	 * through any of the Redistributor.
     82 	 */
     83 	gicr_base = gicv3_driver_data->rdistif_base_addrs[rdist_proc_num];
     84 	assert(gicr_base);
     85 
     86 	/*
     87 	 * Writes to GICR_WAKER.Sleep bit are ignored if GICR_WAKER.Quiescent
     88 	 * bit is not set. We should be alright on power on path, therefore
     89 	 * coming out of sleep and Quiescent should be set, but we assert in
     90 	 * case.
     91 	 */
     92 	assert(gicr_read_waker(gicr_base) & WAKER_QSC_BIT);
     93 
     94 	/* Clear GICR_WAKER.Sleep */
     95 	gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) & ~WAKER_SL_BIT);
     96 
     97 	/*
     98 	 * We don't know if the effects of setting GICR_WAKER.Sleep bit is
     99 	 * instantaneous, so we wait until the interface is not Quiescent
    100 	 * anymore.
    101 	 */
    102 	while (gicr_read_waker(gicr_base) & WAKER_QSC_BIT)
    103 		;
    104 }
    105 
    106