Commit a368922f authored by davidcunado-arm's avatar davidcunado-arm Committed by GitHub
Browse files

Merge pull request #1116 from soby-mathew/sm/gicv3_save_restore

GICv3 context save and restore
parents c64d1345 c5229f8c
...@@ -2107,13 +2107,32 @@ power domain levels. The handler needs to perform power management operation ...@@ -2107,13 +2107,32 @@ power domain levels. The handler needs to perform power management operation
corresponding to the local state at each power level. The generic code corresponding to the local state at each power level. The generic code
expects the handler to succeed. expects the handler to succeed.
The difference between turning a power domain off versus suspending it The difference between turning a power domain off versus suspending it is that
is that in the former case, the power domain is expected to re-initialize in the former case, the power domain is expected to re-initialize its state
its state when it is next powered on (see ``pwr_domain_on_finish()``). In the when it is next powered on (see ``pwr_domain_on_finish()``). In the latter
latter case, the power domain is expected to save enough state so that it can case, the power domain is expected to save enough state so that it can resume
resume execution by restoring this state when its powered on (see execution by restoring this state when its powered on (see
``pwr_domain_suspend_finish()``). ``pwr_domain_suspend_finish()``).
When suspending a core, the platform can also choose to power off the GICv3
Redistributor and ITS through an implementation-defined sequence. To achieve
this safely, the ITS context must be saved first. The architectural part is
implemented by the ``gicv3_its_save_disable()`` helper, but most of the needed
sequence is implementation defined and it is therefore the responsibility of
the platform code to implement the necessary sequence. Then the GIC
Redistributor context can be saved using the ``gicv3_rdistif_save()`` helper.
Powering off the Redistributor requires the implementation to support it and it
is the responsibility of the platform code to execute the right implementation
defined sequence.
When a system suspend is requested, the platform can also make use of the
``gicv3_distif_save()`` helper to save the context of the GIC Distributor after
it has saved the context of the Redistributors and ITS of all the cores in the
system. The context of the Distributor can be large and may require it to be
allocated in a special area if it cannot fit in the platform's global static
data, for example in DRAM. The Distributor can then be powered down using an
implementation-defined sequence.
plat\_psci\_ops.pwr\_domain\_pwr\_down\_wfi() plat\_psci\_ops.pwr\_domain\_pwr\_down\_wfi()
............................................. .............................................
...@@ -2159,6 +2178,10 @@ The ``target_state`` (first argument) has a similar meaning as described in ...@@ -2159,6 +2178,10 @@ The ``target_state`` (first argument) has a similar meaning as described in
the ``pwr_domain_on_finish()`` operation. The generic code expects the platform the ``pwr_domain_on_finish()`` operation. The generic code expects the platform
to succeed. to succeed.
If the Distributor, Redistributors or ITS have been powered off as part of a
suspend, their context must be restored in this function in the reverse order
to how they were saved during suspend sequence.
plat\_psci\_ops.system\_off() plat\_psci\_ops.system\_off()
............................. .............................
......
/*
* 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)
;
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* Driver for GIC500-specific features. This driver only overrides APIs that are
* different to those generic ones in GICv3 driver.
*/
#include "gicv3_private.h"
void gicv3_distif_pre_save(unsigned int proc_num)
{
arm_gicv3_distif_pre_save(proc_num);
}
void gicv3_distif_post_restore(unsigned int proc_num)
{
arm_gicv3_distif_post_restore(proc_num);
}
...@@ -18,32 +18,29 @@ ...@@ -18,32 +18,29 @@
#include "gicv3_private.h" #include "gicv3_private.h"
/* GIC600-specific register offsets */ /* GIC600-specific register offsets */
#define GICR_PWRR 0x24 #define GICR_PWRR 0x24
/* GICR_PWRR fields */ /* GICR_PWRR fields */
#define PWRR_RDPD_SHIFT 0 #define PWRR_RDPD_SHIFT 0
#define PWRR_RDGPD_SHIFT 2 #define PWRR_RDGPD_SHIFT 2
#define PWRR_RDGPO_SHIFT 3 #define PWRR_RDGPO_SHIFT 3
#define PWRR_RDGPD (1 << PWRR_RDGPD_SHIFT) #define PWRR_RDGPD (1 << PWRR_RDGPD_SHIFT)
#define PWRR_RDGPO (1 << PWRR_RDGPO_SHIFT) #define PWRR_RDGPO (1 << PWRR_RDGPO_SHIFT)
/* Values to write to GICR_PWRR register to power redistributor */ /* Values to write to GICR_PWRR register to power redistributor */
#define PWRR_ON (0 << PWRR_RDPD_SHIFT) #define PWRR_ON (0 << PWRR_RDPD_SHIFT)
#define PWRR_OFF (1 << PWRR_RDPD_SHIFT) #define PWRR_OFF (1 << PWRR_RDPD_SHIFT)
/* Generic GICv3 resources */
extern const gicv3_driver_data_t *gicv3_driver_data;
/* GIC600-specific accessor functions */ /* GIC600-specific accessor functions */
static void gicr_write_pwrr(uintptr_t base, unsigned int val) static void gicr_write_pwrr(uintptr_t base, unsigned int val)
{ {
mmio_write_32(base + GICR_PWRR, val); mmio_write_32(base + GICR_PWRR, val);
} }
static uint32_t gicr_read_pwrr(uintptr_t base) static uint32_t gicr_read_pwrr(uintptr_t base)
{ {
return mmio_read_32(base + GICR_PWRR); return mmio_read_32(base + GICR_PWRR);
} }
static int gicr_group_powering_down(uint32_t pwrr) static int gicr_group_powering_down(uint32_t pwrr)
...@@ -82,6 +79,16 @@ static void gic600_pwr_off(uintptr_t base) ...@@ -82,6 +79,16 @@ static void gic600_pwr_off(uintptr_t base)
} }
} }
void gicv3_distif_pre_save(unsigned int proc_num)
{
arm_gicv3_distif_pre_save(proc_num);
}
void gicv3_distif_post_restore(unsigned int proc_num)
{
arm_gicv3_distif_post_restore(proc_num);
}
/* /*
* Power off GIC600 redistributor * Power off GIC600 redistributor
*/ */
......
...@@ -21,6 +21,27 @@ static unsigned int gicv2_compat; ...@@ -21,6 +21,27 @@ static unsigned int gicv2_compat;
#pragma weak gicv3_rdistif_off #pragma weak gicv3_rdistif_off
#pragma weak gicv3_rdistif_on #pragma weak gicv3_rdistif_on
/* Helper macros to save and restore GICD registers to and from the context */
#define RESTORE_GICD_REGS(base, ctx, intr_num, reg, REG) \
do { \
for (unsigned int int_id = MIN_SPI_ID; int_id < intr_num; \
int_id += (1 << REG##_SHIFT)) { \
gicd_write_##reg(base, int_id, \
ctx->gicd_##reg[(int_id - MIN_SPI_ID) >> REG##_SHIFT]); \
} \
} while (0)
#define SAVE_GICD_REGS(base, ctx, intr_num, reg, REG) \
do { \
for (unsigned int int_id = MIN_SPI_ID; int_id < intr_num; \
int_id += (1 << REG##_SHIFT)) { \
ctx->gicd_##reg[(int_id - MIN_SPI_ID) >> REG##_SHIFT] =\
gicd_read_##reg(base, int_id); \
} \
} while (0)
/******************************************************************************* /*******************************************************************************
* This function initialises the ARM GICv3 driver in EL3 with provided platform * This function initialises the ARM GICv3 driver in EL3 with provided platform
* inputs. * inputs.
...@@ -406,3 +427,345 @@ unsigned int gicv3_get_interrupt_type(unsigned int id, ...@@ -406,3 +427,345 @@ unsigned int gicv3_get_interrupt_type(unsigned int id,
/* Else it is a Group 0 Secure interrupt */ /* Else it is a Group 0 Secure interrupt */
return INTR_GROUP0; return INTR_GROUP0;
} }
/*****************************************************************************
* Function to save and disable the GIC ITS register context. The power
* management of GIC ITS is implementation-defined and this function doesn't
* save any memory structures required to support ITS. As the sequence to save
* this state is implementation defined, it should be executed in platform
* specific code. Calling this function alone and then powering down the GIC and
* ITS without implementing the aforementioned platform specific code will
* corrupt the ITS state.
*
* This function must be invoked after the GIC CPU interface is disabled.
*****************************************************************************/
void gicv3_its_save_disable(uintptr_t gits_base, gicv3_its_ctx_t * const its_ctx)
{
int i;
assert(gicv3_driver_data);
assert(IS_IN_EL3());
assert(its_ctx);
assert(gits_base);
its_ctx->gits_ctlr = gits_read_ctlr(gits_base);
/* Disable the ITS */
gits_write_ctlr(gits_base, its_ctx->gits_ctlr &
(~GITS_CTLR_ENABLED_BIT));
/* Wait for quiescent state */
gits_wait_for_quiescent_bit(gits_base);
its_ctx->gits_cbaser = gits_read_cbaser(gits_base);
its_ctx->gits_cwriter = gits_read_cwriter(gits_base);
for (i = 0; i < ARRAY_SIZE(its_ctx->gits_baser); i++)
its_ctx->gits_baser[i] = gits_read_baser(gits_base, i);
}
/*****************************************************************************
* Function to restore the GIC ITS register context. The power
* management of GIC ITS is implementation defined and this function doesn't
* restore any memory structures required to support ITS. The assumption is
* that these structures are in memory and are retained during system suspend.
*
* This must be invoked before the GIC CPU interface is enabled.
*****************************************************************************/
void gicv3_its_restore(uintptr_t gits_base, const gicv3_its_ctx_t * const its_ctx)
{
int i;
assert(gicv3_driver_data);
assert(IS_IN_EL3());
assert(its_ctx);
assert(gits_base);
/* Assert that the GITS is disabled and quiescent */
assert((gits_read_ctlr(gits_base) & GITS_CTLR_ENABLED_BIT) == 0);
assert((gits_read_ctlr(gits_base) & GITS_CTLR_QUIESCENT_BIT) == 1);
gits_write_cbaser(gits_base, its_ctx->gits_cbaser);
gits_write_cwriter(gits_base, its_ctx->gits_cwriter);
for (i = 0; i < ARRAY_SIZE(its_ctx->gits_baser); i++)
gits_write_baser(gits_base, i, its_ctx->gits_baser[i]);
/* Restore the ITS CTLR but leave the ITS disabled */
gits_write_ctlr(gits_base, its_ctx->gits_ctlr &
(~GITS_CTLR_ENABLED_BIT));
}
/*****************************************************************************
* Function to save the GIC Redistributor register context. This function
* must be invoked after CPU interface disable and prior to Distributor save.
*****************************************************************************/
void gicv3_rdistif_save(unsigned int proc_num, gicv3_redist_ctx_t * const rdist_ctx)
{
uintptr_t gicr_base;
unsigned int int_id;
assert(gicv3_driver_data);
assert(proc_num < gicv3_driver_data->rdistif_num);
assert(gicv3_driver_data->rdistif_base_addrs);
assert(IS_IN_EL3());
assert(rdist_ctx);
gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
/*
* Wait for any write to GICR_CTLR to complete before trying to save any
* state.
*/
gicr_wait_for_pending_write(gicr_base);
rdist_ctx->gicr_ctlr = gicr_read_ctlr(gicr_base);
rdist_ctx->gicr_propbaser = gicr_read_propbaser(gicr_base);
rdist_ctx->gicr_pendbaser = gicr_read_pendbaser(gicr_base);
rdist_ctx->gicr_igroupr0 = gicr_read_igroupr0(gicr_base);
rdist_ctx->gicr_isenabler0 = gicr_read_isenabler0(gicr_base);
rdist_ctx->gicr_ispendr0 = gicr_read_ispendr0(gicr_base);
rdist_ctx->gicr_isactiver0 = gicr_read_isactiver0(gicr_base);
rdist_ctx->gicr_icfgr0 = gicr_read_icfgr0(gicr_base);
rdist_ctx->gicr_icfgr1 = gicr_read_icfgr1(gicr_base);
rdist_ctx->gicr_igrpmodr0 = gicr_read_igrpmodr0(gicr_base);
rdist_ctx->gicr_nsacr = gicr_read_nsacr(gicr_base);
for (int_id = MIN_SGI_ID; int_id < TOTAL_PCPU_INTR_NUM;
int_id += (1 << IPRIORITYR_SHIFT)) {
rdist_ctx->gicr_ipriorityr[(int_id - MIN_SGI_ID) >> IPRIORITYR_SHIFT] =
gicr_read_ipriorityr(gicr_base, int_id);
}
/*
* Call the pre-save hook that implements the IMP DEF sequence that may
* be required on some GIC implementations. As this may need to access
* the Redistributor registers, we pass it proc_num.
*/
gicv3_distif_pre_save(proc_num);
}
/*****************************************************************************
* Function to restore the GIC Redistributor register context. We disable
* LPI and per-cpu interrupts before we start restore of the Redistributor.
* This function must be invoked after Distributor restore but prior to
* CPU interface enable. The pending and active interrupts are restored
* after the interrupts are fully configured and enabled.
*****************************************************************************/
void gicv3_rdistif_init_restore(unsigned int proc_num,
const gicv3_redist_ctx_t * const rdist_ctx)
{
uintptr_t gicr_base;
unsigned int int_id;
assert(gicv3_driver_data);
assert(proc_num < gicv3_driver_data->rdistif_num);
assert(gicv3_driver_data->rdistif_base_addrs);
assert(IS_IN_EL3());
assert(rdist_ctx);
gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
/* Power on redistributor */
gicv3_rdistif_on(proc_num);
/*
* Call the post-restore hook that implements the IMP DEF sequence that
* may be required on some GIC implementations. As this may need to
* access the Redistributor registers, we pass it proc_num.
*/
gicv3_distif_post_restore(proc_num);
/*
* Disable all SGIs (imp. def.)/PPIs before configuring them. This is a
* more scalable approach as it avoids clearing the enable bits in the
* GICD_CTLR
*/
gicr_write_icenabler0(gicr_base, ~0);
/* Wait for pending writes to GICR_ICENABLER */
gicr_wait_for_pending_write(gicr_base);
/*
* Disable the LPIs to avoid unpredictable behavior when writing to
* GICR_PROPBASER and GICR_PENDBASER.
*/
gicr_write_ctlr(gicr_base,
rdist_ctx->gicr_ctlr & ~(GICR_CTLR_EN_LPIS_BIT));
/* Restore registers' content */
gicr_write_propbaser(gicr_base, rdist_ctx->gicr_propbaser);
gicr_write_pendbaser(gicr_base, rdist_ctx->gicr_pendbaser);
gicr_write_igroupr0(gicr_base, rdist_ctx->gicr_igroupr0);
for (int_id = MIN_SGI_ID; int_id < TOTAL_PCPU_INTR_NUM;
int_id += (1 << IPRIORITYR_SHIFT)) {
gicr_write_ipriorityr(gicr_base, int_id,
rdist_ctx->gicr_ipriorityr[
(int_id - MIN_SGI_ID) >> IPRIORITYR_SHIFT]);
}
gicr_write_icfgr0(gicr_base, rdist_ctx->gicr_icfgr0);
gicr_write_icfgr1(gicr_base, rdist_ctx->gicr_icfgr1);
gicr_write_igrpmodr0(gicr_base, rdist_ctx->gicr_igrpmodr0);
gicr_write_nsacr(gicr_base, rdist_ctx->gicr_nsacr);
/* Restore after group and priorities are set */
gicr_write_ispendr0(gicr_base, rdist_ctx->gicr_ispendr0);
gicr_write_isactiver0(gicr_base, rdist_ctx->gicr_isactiver0);
/*
* Wait for all writes to the Distributor to complete before enabling
* the SGI and PPIs.
*/
gicr_wait_for_upstream_pending_write(gicr_base);
gicr_write_isenabler0(gicr_base, rdist_ctx->gicr_isenabler0);
/*
* Restore GICR_CTLR.Enable_LPIs bit and wait for pending writes in case
* the first write to GICR_CTLR was still in flight (this write only
* restores GICR_CTLR.Enable_LPIs and no waiting is required for this
* bit).
*/
gicr_write_ctlr(gicr_base, rdist_ctx->gicr_ctlr);
gicr_wait_for_pending_write(gicr_base);
}
/*****************************************************************************
* Function to save the GIC Distributor register context. This function
* must be invoked after CPU interface disable and Redistributor save.
*****************************************************************************/
void gicv3_distif_save(gicv3_dist_ctx_t * const dist_ctx)
{
unsigned int num_ints;
assert(gicv3_driver_data);
assert(gicv3_driver_data->gicd_base);
assert(IS_IN_EL3());
assert(dist_ctx);
uintptr_t gicd_base = gicv3_driver_data->gicd_base;
num_ints = gicd_read_typer(gicd_base);
num_ints &= TYPER_IT_LINES_NO_MASK;
num_ints = (num_ints + 1) << 5;
assert(num_ints <= MAX_SPI_ID + 1);
/* Wait for pending write to complete */
gicd_wait_for_pending_write(gicd_base);
/* Save the GICD_CTLR */
dist_ctx->gicd_ctlr = gicd_read_ctlr(gicd_base);
/* Save GICD_IGROUPR for INTIDs 32 - 1020 */
SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, igroupr, IGROUPR);
/* Save GICD_ISENABLER for INT_IDs 32 - 1020 */
SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, isenabler, ISENABLER);
/* Save GICD_ISPENDR for INTIDs 32 - 1020 */
SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, ispendr, ISPENDR);
/* Save GICD_ISACTIVER for INTIDs 32 - 1020 */
SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, isactiver, ISACTIVER);
/* Save GICD_IPRIORITYR for INTIDs 32 - 1020 */
SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, ipriorityr, IPRIORITYR);
/* Save GICD_ICFGR for INTIDs 32 - 1020 */
SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, icfgr, ICFGR);
/* Save GICD_IGRPMODR for INTIDs 32 - 1020 */
SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, igrpmodr, IGRPMODR);
/* Save GICD_NSACR for INTIDs 32 - 1020 */
SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, nsacr, NSACR);
/* Save GICD_IROUTER for INTIDs 32 - 1024 */
SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, irouter, IROUTER);
/*
* GICD_ITARGETSR<n> and GICD_SPENDSGIR<n> are RAZ/WI when
* GICD_CTLR.ARE_(S|NS) bits are set which is the case for our GICv3
* driver.
*/
}
/*****************************************************************************
* Function to restore the GIC Distributor register context. We disable G0, G1S
* and G1NS interrupt groups before we start restore of the Distributor. This
* function must be invoked prior to Redistributor restore and CPU interface
* enable. The pending and active interrupts are restored after the interrupts
* are fully configured and enabled.
*****************************************************************************/
void gicv3_distif_init_restore(const gicv3_dist_ctx_t * const dist_ctx)
{
unsigned int num_ints = 0;
assert(gicv3_driver_data);
assert(gicv3_driver_data->gicd_base);
assert(IS_IN_EL3());
assert(dist_ctx);
uintptr_t gicd_base = gicv3_driver_data->gicd_base;
/*
* Clear the "enable" bits for G0/G1S/G1NS interrupts before configuring
* the ARE_S bit. The Distributor might generate a system error
* otherwise.
*/
gicd_clr_ctlr(gicd_base,
CTLR_ENABLE_G0_BIT |
CTLR_ENABLE_G1S_BIT |
CTLR_ENABLE_G1NS_BIT,
RWP_TRUE);
/* Set the ARE_S and ARE_NS bit now that interrupts have been disabled */
gicd_set_ctlr(gicd_base, CTLR_ARE_S_BIT | CTLR_ARE_NS_BIT, RWP_TRUE);
num_ints = gicd_read_typer(gicd_base);
num_ints &= TYPER_IT_LINES_NO_MASK;
num_ints = (num_ints + 1) << 5;
assert(num_ints <= MAX_SPI_ID + 1);
/* Restore GICD_IGROUPR for INTIDs 32 - 1020 */
RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, igroupr, IGROUPR);
/* Restore GICD_IPRIORITYR for INTIDs 32 - 1020 */
RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, ipriorityr, IPRIORITYR);
/* Restore GICD_ICFGR for INTIDs 32 - 1020 */
RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, icfgr, ICFGR);
/* Restore GICD_IGRPMODR for INTIDs 32 - 1020 */
RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, igrpmodr, IGRPMODR);
/* Restore GICD_NSACR for INTIDs 32 - 1020 */
RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, nsacr, NSACR);
/* Restore GICD_IROUTER for INTIDs 32 - 1020 */
RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, irouter, IROUTER);
/*
* Restore ISENABLER, ISPENDR and ISACTIVER after the interrupts are
* configured.
*/
/* Restore GICD_ISENABLER for INT_IDs 32 - 1020 */
RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, isenabler, ISENABLER);
/* Restore GICD_ISPENDR for INTIDs 32 - 1020 */
RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, ispendr, ISPENDR);
/* Restore GICD_ISACTIVER for INTIDs 32 - 1020 */
RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, isactiver, ISACTIVER);
/* Restore the GICD_CTLR */
gicd_write_ctlr(gicd_base, dist_ctx->gicd_ctlr);
gicd_wait_for_pending_write(gicd_base);
}
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#ifndef __GICV3_PRIVATE_H__ #ifndef __GICV3_PRIVATE_H__
#define __GICV3_PRIVATE_H__ #define __GICV3_PRIVATE_H__
#include <assert.h>
#include <gic_common.h> #include <gic_common.h>
#include <gicv3.h> #include <gicv3.h>
#include <mmio.h> #include <mmio.h>
...@@ -21,17 +22,6 @@ ...@@ -21,17 +22,6 @@
#define RWP_TRUE 1 #define RWP_TRUE 1
#define RWP_FALSE 0 #define RWP_FALSE 0
/*
* Macro to wait for updates to :
* GICD_CTLR[2:0] - the Group Enables
* GICD_CTLR[5:4] - the ARE bits
* GICD_ICENABLERn - the clearing of enable state for SPIs
*/
#define gicd_wait_for_pending_write(gicd_base) \
do { \
; \
} while (gicd_read_ctlr(gicd_base) & GICD_CTLR_RWP_BIT)
/* /*
* Macro to convert an mpidr to a value suitable for programming into a * Macro to convert an mpidr to a value suitable for programming into a
* GICD_IROUTER. Bits[31:24] in the MPIDR are cleared as they are not relevant * GICD_IROUTER. Bits[31:24] in the MPIDR are cleared as they are not relevant
...@@ -41,18 +31,6 @@ ...@@ -41,18 +31,6 @@
((mpidr & ~(0xff << 24)) | \ ((mpidr & ~(0xff << 24)) | \
(irm & IROUTER_IRM_MASK) << IROUTER_IRM_SHIFT) (irm & IROUTER_IRM_MASK) << IROUTER_IRM_SHIFT)
/*
* Macro to wait for updates to :
* GICR_ICENABLER0
* GICR_CTLR.DPG1S
* GICR_CTLR.DPG1NS
* GICR_CTLR.DPG0
*/
#define gicr_wait_for_pending_write(gicr_base) \
do { \
; \
} while (gicr_read_ctlr(gicr_base) & GICR_CTLR_RWP_BIT)
/* /*
* Macro to convert a GICR_TYPER affinity value into a MPIDR value. Bits[31:24] * Macro to convert a GICR_TYPER affinity value into a MPIDR value. Bits[31:24]
* are zeroes. * are zeroes.
...@@ -65,6 +43,11 @@ ...@@ -65,6 +43,11 @@
(((typer_val) >> 32) & 0xffffff)) (((typer_val) >> 32) & 0xffffff))
#endif #endif
/*******************************************************************************
* GICv3 private global variables declarations
******************************************************************************/
extern const gicv3_driver_data_t *gicv3_driver_data;
/******************************************************************************* /*******************************************************************************
* Private GICv3 function prototypes for accessing entire registers. * Private GICv3 function prototypes for accessing entire registers.
* Note: The raw register values correspond to multiple interrupt IDs and * Note: The raw register values correspond to multiple interrupt IDs and
...@@ -116,6 +99,18 @@ void gicv3_rdistif_mark_core_asleep(uintptr_t gicr_base); ...@@ -116,6 +99,18 @@ void gicv3_rdistif_mark_core_asleep(uintptr_t gicr_base);
/******************************************************************************* /*******************************************************************************
* GIC Distributor interface accessors * GIC Distributor interface accessors
******************************************************************************/ ******************************************************************************/
/*
* Wait for updates to :
* GICD_CTLR[2:0] - the Group Enables
* GICD_CTLR[5:4] - the ARE bits
* GICD_ICENABLERn - the clearing of enable state for SPIs
*/
static inline void gicd_wait_for_pending_write(uintptr_t gicd_base)
{
while (gicd_read_ctlr(gicd_base) & GICD_CTLR_RWP_BIT)
;
}
static inline unsigned int gicd_read_pidr2(uintptr_t base) static inline unsigned int gicd_read_pidr2(uintptr_t base)
{ {
return mmio_read_32(base + GICD_PIDR2_GICV3); return mmio_read_32(base + GICD_PIDR2_GICV3);
...@@ -161,6 +156,11 @@ static inline unsigned long long gicr_read_ctlr(uintptr_t base) ...@@ -161,6 +156,11 @@ static inline unsigned long long gicr_read_ctlr(uintptr_t base)
return mmio_read_64(base + GICR_CTLR); return mmio_read_64(base + GICR_CTLR);
} }
static inline void gicr_write_ctlr(uintptr_t base, uint64_t val)
{
mmio_write_64(base + GICR_CTLR, val);
}
static inline unsigned long long gicr_read_typer(uintptr_t base) static inline unsigned long long gicr_read_typer(uintptr_t base)
{ {
return mmio_read_64(base + GICR_TYPER); return mmio_read_64(base + GICR_TYPER);
...@@ -176,6 +176,29 @@ static inline void gicr_write_waker(uintptr_t base, unsigned int val) ...@@ -176,6 +176,29 @@ static inline void gicr_write_waker(uintptr_t base, unsigned int val)
mmio_write_32(base + GICR_WAKER, val); mmio_write_32(base + GICR_WAKER, val);
} }
/*
* Wait for updates to :
* GICR_ICENABLER0
* GICR_CTLR.DPG1S
* GICR_CTLR.DPG1NS
* GICR_CTLR.DPG0
*/
static inline void gicr_wait_for_pending_write(uintptr_t gicr_base)
{
while (gicr_read_ctlr(gicr_base) & GICR_CTLR_RWP_BIT)
;
}
static inline void gicr_wait_for_upstream_pending_write(uintptr_t gicr_base)
{
while (gicr_read_ctlr(gicr_base) & GICR_CTLR_UWP_BIT)
;
}
/* Private implementation of Distributor power control hooks */
void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num);
void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num);
/******************************************************************************* /*******************************************************************************
* GIC Re-distributor functions for accessing entire registers. * GIC Re-distributor functions for accessing entire registers.
* Note: The raw register values correspond to multiple interrupt IDs and * Note: The raw register values correspond to multiple interrupt IDs and
...@@ -206,6 +229,16 @@ static inline unsigned int gicr_read_igroupr0(uintptr_t base) ...@@ -206,6 +229,16 @@ static inline unsigned int gicr_read_igroupr0(uintptr_t base)
return mmio_read_32(base + GICR_IGROUPR0); return mmio_read_32(base + GICR_IGROUPR0);
} }
static inline unsigned int gicr_read_ispendr0(uintptr_t base)
{
return mmio_read_32(base + GICR_ISPENDR0);
}
static inline void gicr_write_ispendr0(uintptr_t base, unsigned int val)
{
mmio_write_32(base + GICR_ISPENDR0, val);
}
static inline void gicr_write_igroupr0(uintptr_t base, unsigned int val) static inline void gicr_write_igroupr0(uintptr_t base, unsigned int val)
{ {
mmio_write_32(base + GICR_IGROUPR0, val); mmio_write_32(base + GICR_IGROUPR0, val);
...@@ -221,14 +254,120 @@ static inline void gicr_write_igrpmodr0(uintptr_t base, unsigned int val) ...@@ -221,14 +254,120 @@ static inline void gicr_write_igrpmodr0(uintptr_t base, unsigned int val)
mmio_write_32(base + GICR_IGRPMODR0, val); mmio_write_32(base + GICR_IGRPMODR0, val);
} }
static inline unsigned int gicr_read_nsacr(uintptr_t base)
{
return mmio_read_32(base + GICR_NSACR);
}
static inline void gicr_write_nsacr(uintptr_t base, unsigned int val)
{
mmio_write_32(base + GICR_NSACR, val);
}
static inline unsigned int gicr_read_isactiver0(uintptr_t base)
{
return mmio_read_32(base + GICR_ISACTIVER0);
}
static inline void gicr_write_isactiver0(uintptr_t base, unsigned int val)
{
mmio_write_32(base + GICR_ISACTIVER0, val);
}
static inline unsigned int gicr_read_icfgr0(uintptr_t base)
{
return mmio_read_32(base + GICR_ICFGR0);
}
static inline unsigned int gicr_read_icfgr1(uintptr_t base) static inline unsigned int gicr_read_icfgr1(uintptr_t base)
{ {
return mmio_read_32(base + GICR_ICFGR1); return mmio_read_32(base + GICR_ICFGR1);
} }
static inline void gicr_write_icfgr0(uintptr_t base, unsigned int val)
{
mmio_write_32(base + GICR_ICFGR0, val);
}
static inline void gicr_write_icfgr1(uintptr_t base, unsigned int val) static inline void gicr_write_icfgr1(uintptr_t base, unsigned int val)
{ {
mmio_write_32(base + GICR_ICFGR1, val); mmio_write_32(base + GICR_ICFGR1, val);
} }
static inline unsigned int gicr_read_propbaser(uintptr_t base)
{
return mmio_read_32(base + GICR_PROPBASER);
}
static inline void gicr_write_propbaser(uintptr_t base, unsigned int val)
{
mmio_write_32(base + GICR_PROPBASER, val);
}
static inline unsigned int gicr_read_pendbaser(uintptr_t base)
{
return mmio_read_32(base + GICR_PENDBASER);
}
static inline void gicr_write_pendbaser(uintptr_t base, unsigned int val)
{
mmio_write_32(base + GICR_PENDBASER, val);
}
/*******************************************************************************
* GIC ITS functions to read and write entire ITS registers.
******************************************************************************/
static inline uint32_t gits_read_ctlr(uintptr_t base)
{
return mmio_read_32(base + GITS_CTLR);
}
static inline void gits_write_ctlr(uintptr_t base, unsigned int val)
{
mmio_write_32(base + GITS_CTLR, val);
}
static inline uint64_t gits_read_cbaser(uintptr_t base)
{
return mmio_read_64(base + GITS_CBASER);
}
static inline void gits_write_cbaser(uintptr_t base, uint64_t val)
{
mmio_write_32(base + GITS_CBASER, val);
}
static inline uint64_t gits_read_cwriter(uintptr_t base)
{
return mmio_read_64(base + GITS_CWRITER);
}
static inline void gits_write_cwriter(uintptr_t base, uint64_t val)
{
mmio_write_32(base + GITS_CWRITER, val);
}
static inline uint64_t gits_read_baser(uintptr_t base, unsigned int its_table_id)
{
assert(its_table_id < 8);
return mmio_read_64(base + GITS_BASER + (8 * its_table_id));
}
static inline void gits_write_baser(uintptr_t base, unsigned int its_table_id, uint64_t val)
{
assert(its_table_id < 8);
mmio_write_64(base + GITS_BASER + (8 * its_table_id), val);
}
/*
* Wait for Quiescent bit when GIC ITS is disabled
*/
static inline void gits_wait_for_quiescent_bit(uintptr_t gits_base)
{
assert(!(gits_read_ctlr(gits_base) & GITS_CTLR_ENABLED_BIT));
while ((gits_read_ctlr(gits_base) & GITS_CTLR_QUIESCENT_BIT) == 0)
;
}
#endif /* __GICV3_PRIVATE_H__ */ #endif /* __GICV3_PRIVATE_H__ */
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __ARM_GICV3_COMMON_H__
#define __ARM_GICV3_COMMON_H__
/*******************************************************************************
* GIC500/GIC600 Re-distributor interface registers & constants
******************************************************************************/
/* GICR_WAKER implementation-defined bit definitions */
#define WAKER_SL_SHIFT 0
#define WAKER_QSC_SHIFT 31
#define WAKER_SL_BIT (1U << WAKER_SL_SHIFT)
#define WAKER_QSC_BIT (1U << WAKER_QSC_SHIFT)
#endif /* __ARM_GICV3_COMMON_H__ */
/* /*
* Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
* *
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
...@@ -14,6 +14,10 @@ ...@@ -14,6 +14,10 @@
#define MIN_SGI_ID 0 #define MIN_SGI_ID 0
#define MIN_PPI_ID 16 #define MIN_PPI_ID 16
#define MIN_SPI_ID 32 #define MIN_SPI_ID 32
#define MAX_SPI_ID 1019
#define TOTAL_SPI_INTR_NUM (MAX_SPI_ID - MIN_SPI_ID + 1)
#define TOTAL_PCPU_INTR_NUM (MIN_SPI_ID - MIN_SGI_ID)
/* Mask for the priority field common to all GIC interfaces */ /* Mask for the priority field common to all GIC interfaces */
#define GIC_PRI_MASK 0xff #define GIC_PRI_MASK 0xff
......
/* /*
* Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
* *
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#ifndef __GICV3_H__ #ifndef __GICV3_H__
#define __GICV3_H__ #define __GICV3_H__
#include "utils_def.h"
/******************************************************************************* /*******************************************************************************
* GICv3 miscellaneous definitions * GICv3 miscellaneous definitions
******************************************************************************/ ******************************************************************************/
...@@ -66,9 +68,12 @@ ...@@ -66,9 +68,12 @@
#define GICD_CTLR_RWP_BIT (1 << GICD_CTLR_RWP_SHIFT) #define GICD_CTLR_RWP_BIT (1 << GICD_CTLR_RWP_SHIFT)
/* GICD_IROUTER shifts and masks */ /* GICD_IROUTER shifts and masks */
#define IROUTER_SHIFT 0
#define IROUTER_IRM_SHIFT 31 #define IROUTER_IRM_SHIFT 31
#define IROUTER_IRM_MASK 0x1 #define IROUTER_IRM_MASK 0x1
#define NUM_OF_DIST_REGS 30
/******************************************************************************* /*******************************************************************************
* GICv3 Re-distributor interface registers & constants * GICv3 Re-distributor interface registers & constants
******************************************************************************/ ******************************************************************************/
...@@ -77,18 +82,29 @@ ...@@ -77,18 +82,29 @@
#define GICR_CTLR 0x0 #define GICR_CTLR 0x0
#define GICR_TYPER 0x08 #define GICR_TYPER 0x08
#define GICR_WAKER 0x14 #define GICR_WAKER 0x14
#define GICR_PROPBASER 0x70
#define GICR_PENDBASER 0x78
#define GICR_IGROUPR0 (GICR_SGIBASE_OFFSET + 0x80) #define GICR_IGROUPR0 (GICR_SGIBASE_OFFSET + 0x80)
#define GICR_ISENABLER0 (GICR_SGIBASE_OFFSET + 0x100) #define GICR_ISENABLER0 (GICR_SGIBASE_OFFSET + 0x100)
#define GICR_ICENABLER0 (GICR_SGIBASE_OFFSET + 0x180) #define GICR_ICENABLER0 (GICR_SGIBASE_OFFSET + 0x180)
#define GICR_ISPENDR0 (GICR_SGIBASE_OFFSET + 0x200)
#define GICR_ICPENDR0 (GICR_SGIBASE_OFFSET + 0x280)
#define GICR_ISACTIVER0 (GICR_SGIBASE_OFFSET + 0x300)
#define GICR_ICACTIVER0 (GICR_SGIBASE_OFFSET + 0x380)
#define GICR_IPRIORITYR (GICR_SGIBASE_OFFSET + 0x400) #define GICR_IPRIORITYR (GICR_SGIBASE_OFFSET + 0x400)
#define GICR_ICFGR0 (GICR_SGIBASE_OFFSET + 0xc00) #define GICR_ICFGR0 (GICR_SGIBASE_OFFSET + 0xc00)
#define GICR_ICFGR1 (GICR_SGIBASE_OFFSET + 0xc04) #define GICR_ICFGR1 (GICR_SGIBASE_OFFSET + 0xc04)
#define GICR_IGRPMODR0 (GICR_SGIBASE_OFFSET + 0xd00) #define GICR_IGRPMODR0 (GICR_SGIBASE_OFFSET + 0xd00)
#define GICR_NSACR (GICR_SGIBASE_OFFSET + 0xe00)
/* GICR_CTLR bit definitions */ /* GICR_CTLR bit definitions */
#define GICR_CTLR_UWP_SHIFT 31
#define GICR_CTLR_UWP_MASK 0x1
#define GICR_CTLR_UWP_BIT (1U << GICR_CTLR_UWP_SHIFT)
#define GICR_CTLR_RWP_SHIFT 3 #define GICR_CTLR_RWP_SHIFT 3
#define GICR_CTLR_RWP_MASK 0x1 #define GICR_CTLR_RWP_MASK 0x1
#define GICR_CTLR_RWP_BIT (1 << GICR_CTLR_RWP_SHIFT) #define GICR_CTLR_RWP_BIT (1U << GICR_CTLR_RWP_SHIFT)
#define GICR_CTLR_EN_LPIS_BIT (1U << 0)
/* GICR_WAKER bit definitions */ /* GICR_WAKER bit definitions */
#define WAKER_CA_SHIFT 2 #define WAKER_CA_SHIFT 2
...@@ -111,6 +127,8 @@ ...@@ -111,6 +127,8 @@
#define TYPER_LAST_BIT (1 << TYPER_LAST_SHIFT) #define TYPER_LAST_BIT (1 << TYPER_LAST_SHIFT)
#define NUM_OF_REDIST_REGS 30
/******************************************************************************* /*******************************************************************************
* GICv3 CPU interface registers & constants * GICv3 CPU interface registers & constants
******************************************************************************/ ******************************************************************************/
...@@ -147,10 +165,29 @@ ...@@ -147,10 +165,29 @@
#define IAR1_EL1_INTID_SHIFT 0 #define IAR1_EL1_INTID_SHIFT 0
#define IAR1_EL1_INTID_MASK 0xffffff #define IAR1_EL1_INTID_MASK 0xffffff
/*****************************************************************************
* GICv3 ITS registers and constants
*****************************************************************************/
#define GITS_CTLR 0x0
#define GITS_IIDR 0x4
#define GITS_TYPER 0x8
#define GITS_CBASER 0x80
#define GITS_CWRITER 0x88
#define GITS_CREADR 0x90
#define GITS_BASER 0x100
/* GITS_CTLR bit definitions */
#define GITS_CTLR_ENABLED_BIT 1
#define GITS_CTLR_QUIESCENT_SHIFT 31
#define GITS_CTLR_QUIESCENT_BIT (1U << GITS_CTLR_QUIESCENT_SHIFT)
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <gic_common.h>
#include <stdint.h> #include <stdint.h>
#include <types.h> #include <types.h>
#include <utils_def.h>
#define gicv3_is_intr_id_special_identifier(id) \ #define gicv3_is_intr_id_special_identifier(id) \
(((id) >= PENDING_G1S_INTID) && ((id) <= GIC_SPURIOUS_INTERRUPT)) (((id) >= PENDING_G1S_INTID) && ((id) <= GIC_SPURIOUS_INTERRUPT))
...@@ -172,6 +209,16 @@ ...@@ -172,6 +209,16 @@
IAR0_EL1_INTID_MASK IAR0_EL1_INTID_MASK
#define gicv3_end_of_interrupt(id) write_icc_eoir0_el1(id) #define gicv3_end_of_interrupt(id) write_icc_eoir0_el1(id)
/*
* This macro returns the total number of GICD registers corresponding to
* the name.
*/
#define GICD_NUM_REGS(reg_name) \
DIV_ROUND_UP_2EVAL(TOTAL_SPI_INTR_NUM, (1 << reg_name ## _SHIFT))
#define GICR_NUM_REGS(reg_name) \
DIV_ROUND_UP_2EVAL(TOTAL_PCPU_INTR_NUM, (1 << reg_name ## _SHIFT))
/******************************************************************************* /*******************************************************************************
* This structure describes some of the implementation defined attributes of the * This structure describes some of the implementation defined attributes of the
* GICv3 IP. It is used by the platform port to specify these attributes in order * GICv3 IP. It is used by the platform port to specify these attributes in order
...@@ -229,6 +276,50 @@ typedef struct gicv3_driver_data { ...@@ -229,6 +276,50 @@ typedef struct gicv3_driver_data {
mpidr_hash_fn mpidr_to_core_pos; mpidr_hash_fn mpidr_to_core_pos;
} gicv3_driver_data_t; } gicv3_driver_data_t;
typedef struct gicv3_redist_ctx {
/* 64 bits registers */
uint64_t gicr_propbaser;
uint64_t gicr_pendbaser;
/* 32 bits registers */
uint32_t gicr_ctlr;
uint32_t gicr_igroupr0;
uint32_t gicr_isenabler0;
uint32_t gicr_ispendr0;
uint32_t gicr_isactiver0;
uint32_t gicr_ipriorityr[GICR_NUM_REGS(IPRIORITYR)];
uint32_t gicr_icfgr0;
uint32_t gicr_icfgr1;
uint32_t gicr_igrpmodr0;
uint32_t gicr_nsacr;
} gicv3_redist_ctx_t;
typedef struct gicv3_dist_ctx {
/* 64 bits registers */
uint64_t gicd_irouter[TOTAL_SPI_INTR_NUM];
/* 32 bits registers */
uint32_t gicd_ctlr;
uint32_t gicd_igroupr[GICD_NUM_REGS(IGROUPR)];
uint32_t gicd_isenabler[GICD_NUM_REGS(ISENABLER)];
uint32_t gicd_ispendr[GICD_NUM_REGS(ISPENDR)];
uint32_t gicd_isactiver[GICD_NUM_REGS(ISACTIVER)];
uint32_t gicd_ipriorityr[GICD_NUM_REGS(IPRIORITYR)];
uint32_t gicd_icfgr[GICD_NUM_REGS(ICFGR)];
uint32_t gicd_igrpmodr[GICD_NUM_REGS(IGRPMODR)];
uint32_t gicd_nsacr[GICD_NUM_REGS(NSACR)];
} gicv3_dist_ctx_t;
typedef struct gicv3_its_ctx {
/* 64 bits registers */
uint64_t gits_cbaser;
uint64_t gits_cwriter;
uint64_t gits_baser[8];
/* 32 bits registers */
uint32_t gits_ctlr;
} gicv3_its_ctx_t;
/******************************************************************************* /*******************************************************************************
* GICv3 EL3 driver API * GICv3 EL3 driver API
******************************************************************************/ ******************************************************************************/
...@@ -243,7 +334,20 @@ unsigned int gicv3_get_pending_interrupt_type(void); ...@@ -243,7 +334,20 @@ unsigned int gicv3_get_pending_interrupt_type(void);
unsigned int gicv3_get_pending_interrupt_id(void); unsigned int gicv3_get_pending_interrupt_id(void);
unsigned int gicv3_get_interrupt_type(unsigned int id, unsigned int gicv3_get_interrupt_type(unsigned int id,
unsigned int proc_num); unsigned int proc_num);
void gicv3_distif_init_restore(const gicv3_dist_ctx_t * const dist_ctx);
void gicv3_distif_save(gicv3_dist_ctx_t * const dist_ctx);
/*
* gicv3_distif_post_restore and gicv3_distif_pre_save must be implemented if
* gicv3_distif_save and gicv3_rdistif_init_restore are used. If no
* implementation-defined sequence is needed at these steps, an empty function
* can be provided.
*/
void gicv3_distif_post_restore(unsigned int proc_num);
void gicv3_distif_pre_save(unsigned int proc_num);
void gicv3_rdistif_init_restore(unsigned int proc_num, const gicv3_redist_ctx_t * const rdist_ctx);
void gicv3_rdistif_save(unsigned int proc_num, gicv3_redist_ctx_t * const rdist_ctx);
void gicv3_its_save_disable(uintptr_t gits_base, gicv3_its_ctx_t * const its_ctx);
void gicv3_its_restore(uintptr_t gits_base, const gicv3_its_ctx_t * const its_ctx);
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* __GICV3_H__ */ #endif /* __GICV3_H__ */
...@@ -18,6 +18,12 @@ ...@@ -18,6 +18,12 @@
#define BIT(nr) (1ULL << (nr)) #define BIT(nr) (1ULL << (nr))
/*
* This variant of div_round_up can be used in macro definition but should not
* be used in C code as the `div` parameter is evaluated twice.
*/
#define DIV_ROUND_UP_2EVAL(n, d) (((n) + (d) - 1) / (d))
#define MIN(x, y) __extension__ ({ \ #define MIN(x, y) __extension__ ({ \
__typeof__(x) _x = (x); \ __typeof__(x) _x = (x); \
__typeof__(y) _y = (y); \ __typeof__(y) _y = (y); \
...@@ -49,6 +55,11 @@ ...@@ -49,6 +55,11 @@
#define round_down(value, boundary) \ #define round_down(value, boundary) \
((value) & ~round_boundary(value, boundary)) ((value) & ~round_boundary(value, boundary))
#define div_round_up(val, div) __extension__ ({ \
__typeof__(div) _div = (div); \
round_up((val), _div)/_div; \
})
/* /*
* Evaluates to 1 if (ptr + inc) overflows, 0 otherwise. * Evaluates to 1 if (ptr + inc) overflows, 0 otherwise.
* Both arguments must be unsigned pointer values (i.e. uintptr_t). * Both arguments must be unsigned pointer values (i.e. uintptr_t).
......
...@@ -48,7 +48,8 @@ FVP_GICV3_SOURCES := drivers/arm/gic/common/gic_common.c \ ...@@ -48,7 +48,8 @@ FVP_GICV3_SOURCES := drivers/arm/gic/common/gic_common.c \
# Choose the GIC sources depending upon the how the FVP will be invoked # Choose the GIC sources depending upon the how the FVP will be invoked
ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV3) ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV3)
FVP_GIC_SOURCES := ${FVP_GICV3_SOURCES} FVP_GIC_SOURCES := ${FVP_GICV3_SOURCES} \
drivers/arm/gic/v3/gic500.c
else ifeq (${FVP_USE_GIC_DRIVER},FVP_GIC600) else ifeq (${FVP_USE_GIC_DRIVER},FVP_GIC600)
FVP_GIC_SOURCES := ${FVP_GICV3_SOURCES} \ FVP_GIC_SOURCES := ${FVP_GICV3_SOURCES} \
drivers/arm/gic/v3/gic600.c drivers/arm/gic/v3/gic600.c
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment