Commit 9acdafbc authored by danh-arm's avatar danh-arm Committed by GitHub
Browse files

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

GIC driver changes for extended power management
parents 9e75fddc 74a9578c
...@@ -40,6 +40,13 @@ ...@@ -40,6 +40,13 @@
static const gicv3_driver_data_t *driver_data; static const gicv3_driver_data_t *driver_data;
static unsigned int gicv2_compat; 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 * This function initialises the ARM GICv3 driver in EL3 with provided platform
* inputs. * inputs.
...@@ -188,6 +195,9 @@ void gicv3_rdistif_init(unsigned int proc_num) ...@@ -188,6 +195,9 @@ void gicv3_rdistif_init(unsigned int proc_num)
assert(IS_IN_EL3()); assert(IS_IN_EL3());
/* Power on redistributor */
gicv3_rdistif_on(proc_num);
gicr_base = driver_data->rdistif_base_addrs[proc_num]; gicr_base = driver_data->rdistif_base_addrs[proc_num];
/* Set the default attribute of all SGIs and PPIs */ /* Set the default attribute of all SGIs and PPIs */
...@@ -210,6 +220,19 @@ void gicv3_rdistif_init(unsigned int proc_num) ...@@ -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 * This function enables the GIC CPU interface of the calling CPU using only
* system register accesses. * system register accesses.
......
...@@ -259,6 +259,8 @@ typedef struct gicv3_driver_data { ...@@ -259,6 +259,8 @@ typedef struct gicv3_driver_data {
void gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data); void gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data);
void gicv3_distif_init(void); void gicv3_distif_init(void);
void gicv3_rdistif_init(unsigned int proc_num); 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_enable(unsigned int proc_num);
void gicv3_cpuif_disable(unsigned int proc_num); void gicv3_cpuif_disable(unsigned int proc_num);
unsigned int gicv3_get_pending_interrupt_type(void); unsigned int gicv3_get_pending_interrupt_type(void);
......
...@@ -194,6 +194,8 @@ void plat_arm_gic_driver_init(void); ...@@ -194,6 +194,8 @@ void plat_arm_gic_driver_init(void);
void plat_arm_gic_init(void); void plat_arm_gic_init(void);
void plat_arm_gic_cpuif_enable(void); void plat_arm_gic_cpuif_enable(void);
void plat_arm_gic_cpuif_disable(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_gic_pcpu_init(void);
void plat_arm_security_setup(void); void plat_arm_security_setup(void);
void plat_arm_pwrc_setup(void); void plat_arm_pwrc_setup(void);
......
...@@ -64,19 +64,6 @@ const unsigned int arm_pm_idle_states[] = { ...@@ -64,19 +64,6 @@ const unsigned int arm_pm_idle_states[] = {
}; };
#endif #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 * Function which implements the common FVP specific operations to power down a
* cluster in response to a CPU_OFF or CPU_SUSPEND request. * 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) ...@@ -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 * suspended. Perform at least the cpu specific actions followed
* by the cluster specific operations if applicable. * 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] == if (target_state->pwr_domain_state[ARM_PWR_LVL1] ==
ARM_LOCAL_STATE_OFF) ARM_LOCAL_STATE_OFF)
...@@ -213,8 +208,17 @@ void fvp_pwr_domain_suspend(const psci_power_state_t *target_state) ...@@ -213,8 +208,17 @@ void fvp_pwr_domain_suspend(const psci_power_state_t *target_state)
/* Program the power controller to enable wakeup interrupts. */ /* Program the power controller to enable wakeup interrupts. */
fvp_pwrc_set_wen(mpidr); fvp_pwrc_set_wen(mpidr);
/* Perform the common cpu specific operations */ /* Prevent interrupts from spuriously waking up this cpu */
fvp_cpu_pwrdwn_common(); 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 */ /* Perform the common cluster specific operations */
if (target_state->pwr_domain_state[ARM_PWR_LVL1] == if (target_state->pwr_domain_state[ARM_PWR_LVL1] ==
......
...@@ -97,3 +97,17 @@ void plat_arm_gic_pcpu_init(void) ...@@ -97,3 +97,17 @@ void plat_arm_gic_pcpu_init(void)
{ {
gicv2_pcpu_distif_init(); 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;
}
...@@ -43,6 +43,8 @@ ...@@ -43,6 +43,8 @@
#pragma weak plat_arm_gic_cpuif_enable #pragma weak plat_arm_gic_cpuif_enable
#pragma weak plat_arm_gic_cpuif_disable #pragma weak plat_arm_gic_cpuif_disable
#pragma weak plat_arm_gic_pcpu_init #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 */ /* The GICv3 driver only needs to be initialized in EL3 */
static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
...@@ -115,3 +117,16 @@ void plat_arm_gic_pcpu_init(void) ...@@ -115,3 +117,16 @@ void plat_arm_gic_pcpu_init(void)
{ {
gicv3_rdistif_init(plat_my_core_pos()); 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());
}
...@@ -94,3 +94,17 @@ void plat_arm_gic_pcpu_init(void) ...@@ -94,3 +94,17 @@ void plat_arm_gic_pcpu_init(void)
{ {
arm_gic_pcpu_distif_setup(); 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;
}
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