Merge pull request #793 from jeenu-arm/gic-changes

GIC driver changes for extended power management
This commit is contained in:
danh-arm 2016-12-20 12:26:23 +00:00 committed by GitHub
commit 9acdafbccf
7 changed files with 90 additions and 16 deletions

View File

@ -40,6 +40,13 @@
static const gicv3_driver_data_t *driver_data;
static unsigned int gicv2_compat;
/*
* Redistributor power operations are weakly bound so that they can be
* overridden
*/
#pragma weak gicv3_rdistif_off
#pragma weak gicv3_rdistif_on
/*******************************************************************************
* This function initialises the ARM GICv3 driver in EL3 with provided platform
* inputs.
@ -188,6 +195,9 @@ void gicv3_rdistif_init(unsigned int proc_num)
assert(IS_IN_EL3());
/* Power on redistributor */
gicv3_rdistif_on(proc_num);
gicr_base = driver_data->rdistif_base_addrs[proc_num];
/* Set the default attribute of all SGIs and PPIs */
@ -210,6 +220,19 @@ void gicv3_rdistif_init(unsigned int proc_num)
}
}
/*******************************************************************************
* Functions to perform power operations on GIC Redistributor
******************************************************************************/
void gicv3_rdistif_off(unsigned int proc_num)
{
return;
}
void gicv3_rdistif_on(unsigned int proc_num)
{
return;
}
/*******************************************************************************
* This function enables the GIC CPU interface of the calling CPU using only
* system register accesses.

View File

@ -259,6 +259,8 @@ typedef struct gicv3_driver_data {
void gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data);
void gicv3_distif_init(void);
void gicv3_rdistif_init(unsigned int proc_num);
void gicv3_rdistif_on(unsigned int proc_num);
void gicv3_rdistif_off(unsigned int proc_num);
void gicv3_cpuif_enable(unsigned int proc_num);
void gicv3_cpuif_disable(unsigned int proc_num);
unsigned int gicv3_get_pending_interrupt_type(void);

View File

@ -194,6 +194,8 @@ void plat_arm_gic_driver_init(void);
void plat_arm_gic_init(void);
void plat_arm_gic_cpuif_enable(void);
void plat_arm_gic_cpuif_disable(void);
void plat_arm_gic_redistif_on(void);
void plat_arm_gic_redistif_off(void);
void plat_arm_gic_pcpu_init(void);
void plat_arm_security_setup(void);
void plat_arm_pwrc_setup(void);

View File

@ -64,19 +64,6 @@ const unsigned int arm_pm_idle_states[] = {
};
#endif
/*******************************************************************************
* Function which implements the common FVP specific operations to power down a
* cpu in response to a CPU_OFF or CPU_SUSPEND request.
******************************************************************************/
static void fvp_cpu_pwrdwn_common(void)
{
/* Prevent interrupts from spuriously waking up this cpu */
plat_arm_gic_cpuif_disable();
/* Program the power controller to power off this cpu. */
fvp_pwrc_write_ppoffr(read_mpidr_el1());
}
/*******************************************************************************
* Function which implements the common FVP specific operations to power down a
* cluster in response to a CPU_OFF or CPU_SUSPEND request.
@ -180,7 +167,15 @@ void fvp_pwr_domain_off(const psci_power_state_t *target_state)
* suspended. Perform at least the cpu specific actions followed
* by the cluster specific operations if applicable.
*/
fvp_cpu_pwrdwn_common();
/* Prevent interrupts from spuriously waking up this cpu */
plat_arm_gic_cpuif_disable();
/* Turn redistributor off */
plat_arm_gic_redistif_off();
/* Program the power controller to power off this cpu. */
fvp_pwrc_write_ppoffr(read_mpidr_el1());
if (target_state->pwr_domain_state[ARM_PWR_LVL1] ==
ARM_LOCAL_STATE_OFF)
@ -213,8 +208,17 @@ void fvp_pwr_domain_suspend(const psci_power_state_t *target_state)
/* Program the power controller to enable wakeup interrupts. */
fvp_pwrc_set_wen(mpidr);
/* Perform the common cpu specific operations */
fvp_cpu_pwrdwn_common();
/* Prevent interrupts from spuriously waking up this cpu */
plat_arm_gic_cpuif_disable();
/*
* The Redistributor is not powered off as it can potentially prevent
* wake up events reaching the CPUIF and/or might lead to losing
* register context.
*/
/* Program the power controller to power off this cpu. */
fvp_pwrc_write_ppoffr(read_mpidr_el1());
/* Perform the common cluster specific operations */
if (target_state->pwr_domain_state[ARM_PWR_LVL1] ==

View File

@ -97,3 +97,17 @@ void plat_arm_gic_pcpu_init(void)
{
gicv2_pcpu_distif_init();
}
/******************************************************************************
* Stubs for Redistributor power management. Although GICv2 doesn't have
* Redistributor interface, these are provided for the sake of uniform GIC API
*****************************************************************************/
void plat_arm_gic_redistif_on(void)
{
return;
}
void plat_arm_gic_redistif_off(void)
{
return;
}

View File

@ -43,6 +43,8 @@
#pragma weak plat_arm_gic_cpuif_enable
#pragma weak plat_arm_gic_cpuif_disable
#pragma weak plat_arm_gic_pcpu_init
#pragma weak plat_arm_gic_redistif_on
#pragma weak plat_arm_gic_redistif_off
/* The GICv3 driver only needs to be initialized in EL3 */
static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
@ -115,3 +117,16 @@ void plat_arm_gic_pcpu_init(void)
{
gicv3_rdistif_init(plat_my_core_pos());
}
/******************************************************************************
* ARM common helpers to power GIC redistributor interface
*****************************************************************************/
void plat_arm_gic_redistif_on(void)
{
gicv3_rdistif_on(plat_my_core_pos());
}
void plat_arm_gic_redistif_off(void)
{
gicv3_rdistif_off(plat_my_core_pos());
}

View File

@ -94,3 +94,17 @@ void plat_arm_gic_pcpu_init(void)
{
arm_gic_pcpu_distif_setup();
}
/******************************************************************************
* Stubs for Redistributor power management. Although legacy configuration isn't
* supported, these are provided for the sake of uniform GIC API
*****************************************************************************/
void plat_arm_gic_redistif_on(void)
{
return;
}
void plat_arm_gic_redistif_off(void)
{
return;
}