/*
 * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

/*
 * Driver for implementation defined features that are identical in ARM GICv3
* implementations (GIC-500 and GIC-600 for now). This driver only overrides
* APIs that are different to those generic ones in GICv3 driver.
 */

#include <arch_helpers.h>
#include <assert.h>
#include <gicv3.h>

#include "gicv3_private.h"
#include "arm_gicv3_common.h"

/*
 * Flush the internal GIC cache of the LPIs pending tables to memory before
 * saving the state of the Redistributor. This is required before powering off
 * the GIC when the pending status must be preserved.
 * `rdist_proc_num` is the processor number corresponding to the Redistributor of the
 * current CPU.
 */
void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num)
{
	uintptr_t gicr_base = 0;

	assert(gicv3_driver_data);
	assert(gicv3_driver_data->rdistif_base_addrs);

	/*
	 * The GICR_WAKER.Sleep bit should be set only when both
	 * GICR_WAKER.ChildrenAsleep and GICR_WAKER.ProcessorSleep are set on
	 * all the Redistributors.
	 */
	for (unsigned int i = 0; i < gicv3_driver_data->rdistif_num; i++) {
		gicr_base = gicv3_driver_data->rdistif_base_addrs[i];
		assert(gicr_base);
		assert(gicr_read_waker(gicr_base) & WAKER_CA_BIT);
		assert(gicr_read_waker(gicr_base) & WAKER_PS_BIT);
	}

	gicr_base = gicv3_driver_data->rdistif_base_addrs[rdist_proc_num];
	/*
	 * According to the TRM, there is only one instance of the
	 * GICR_WAKER.Sleep and GICR_WAKER.Quiescent bits that can be accessed
	 * through any of the Redistributor.
	 */

	/*
	 * Set GICR_WAKER.Sleep
	 * After this point, the system must be configured so that the
	 * wake_request signals for the right cores are asserted when a wakeup
	 * interrupt is detected. The GIC will not be able to do that anymore
	 * when the GICR_WAKER.Sleep bit is set to 1.
	 */
	gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_SL_BIT);

	/* Wait until the GICR_WAKER.Quiescent bit is set */
	while (!(gicr_read_waker(gicr_base) & WAKER_QSC_BIT))
		;
}

/*
 * Allow the LPIs pending state to be read back from the tables in memory after
 * having restored the state of the GIC Redistributor.
 */
void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num)
{
	uintptr_t gicr_base;

	assert(gicv3_driver_data);
	assert(gicv3_driver_data->rdistif_base_addrs);

	/*
	 * According to the TRM, there is only one instance of the
	 * GICR_WAKER.Sleep and GICR_WAKER.Quiescent bits that can be accessed
	 * through any of the Redistributor.
	 */
	gicr_base = gicv3_driver_data->rdistif_base_addrs[rdist_proc_num];
	assert(gicr_base);

	/*
	 * Writes to GICR_WAKER.Sleep bit are ignored if GICR_WAKER.Quiescent
	 * bit is not set. We should be alright on power on path, therefore
	 * coming out of sleep and Quiescent should be set, but we assert in
	 * case.
	 */
	assert(gicr_read_waker(gicr_base) & WAKER_QSC_BIT);

	/* Clear GICR_WAKER.Sleep */
	gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) & ~WAKER_SL_BIT);

	/*
	 * We don't know if the effects of setting GICR_WAKER.Sleep bit is
	 * instantaneous, so we wait until the interface is not Quiescent
	 * anymore.
	 */
	while (gicr_read_waker(gicr_base) & WAKER_QSC_BIT)
		;
}

