From f14d188681b2c6f49ccd22595b112da7b02798f8 Mon Sep 17 00:00:00 2001 From: Soby Mathew Date: Mon, 26 Oct 2015 14:01:53 +0000 Subject: Prepare platforms to use refactored ARM GIC drivers This patch adds platform helpers for the new GICv2 and GICv3 drivers in plat_gicv2.c and plat_gicv3.c. The platforms can include the appropriate file in their build according to the GIC driver to be used. The existing plat_gic.c is only meant for the legacy GIC driver. In the case of ARM platforms, the major changes are as follows: 1. The crash reporting helper macro `arm_print_gic_regs` that prints the GIC CPU interface register values has been modified to detect the type of CPU interface being used (System register or memory mappped interface) before using the right interface to print the registers. 2. The power management helper function that is called after a core is powered up has been further refactored. This is to highlight that the per-cpu distributor interface should be initialised only when the core was originally powered down using the CPU_OFF PSCI API and not when the CPU_SUSPEND PSCI API was used. 3. In the case of CSS platforms, the system power domain restore helper `arm_system_pwr_domain_resume()` is now only invoked in the `suspend_finish` handler as the system power domain is always expected to be initialized when the `on_finish` handler is invoked. Change-Id: I7fc27d61fc6c2a60cea2436b676c5737d0257df6 --- plat/arm/css/common/css_pm.c | 99 +++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 57 deletions(-) (limited to 'plat/arm/css/common/css_pm.c') diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c index 3f468570..1d9bd594 100644 --- a/plat/arm/css/common/css_pm.c +++ b/plat/arm/css/common/css_pm.c @@ -41,6 +41,12 @@ #include #include "css_scpi.h" +/* Macros to read the CSS power domain state */ +#define CSS_CORE_PWR_STATE(state) (state)->pwr_domain_state[ARM_PWR_LVL0] +#define CSS_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[ARM_PWR_LVL1] +#define CSS_SYSTEM_PWR_STATE(state) ((PLAT_MAX_PWR_LVL > ARM_PWR_LVL1) ?\ + (state)->pwr_domain_state[ARM_PWR_LVL2] : 0) + /* Allow CSS platforms to override `plat_arm_psci_pm_ops` */ #pragma weak plat_arm_psci_pm_ops @@ -93,50 +99,37 @@ int css_pwr_domain_on(u_register_t mpidr) return PSCI_E_SUCCESS; } -/******************************************************************************* - * Handler called when a power level has just been powered on after - * being turned off earlier. The target_state encodes the low power state that - * each level has woken up from. - ******************************************************************************/ -void css_pwr_domain_on_finish(const psci_power_state_t *target_state) +static void css_pwr_domain_on_finisher_common( + const psci_power_state_t *target_state) { - assert(target_state->pwr_domain_state[ARM_PWR_LVL0] == - ARM_LOCAL_STATE_OFF); - - if (PLAT_MAX_PWR_LVL > ARM_PWR_LVL1) { - /* - * Perform system initialization if woken up from system - * suspend. - */ - if (target_state->pwr_domain_state[ARM_PWR_LVL2] == - ARM_LOCAL_STATE_OFF) - arm_system_pwr_domain_resume(); - } + assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF); /* * Perform the common cluster specific operations i.e enable coherency * if this cluster was off. */ - if (target_state->pwr_domain_state[ARM_PWR_LVL1] == - ARM_LOCAL_STATE_OFF) + if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} +/******************************************************************************* + * Handler called when a power level has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. This handler would never be invoked with + * the system power domain uninitialized as either the primary would have taken + * care of it as part of cold boot or the first core awakened from system + * suspend would have already initialized it. + ******************************************************************************/ +void css_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + /* Assert that the system power domain need not be initialized */ + assert(CSS_SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_RUN); - if (PLAT_MAX_PWR_LVL > ARM_PWR_LVL1) { - /* - * Skip GIC CPU interface and per-CPU Distributor interface - * setups if woken up from system suspend as it is done as - * part of css_system_pwr_domain_resume(). - */ - if (target_state->pwr_domain_state[ARM_PWR_LVL2] == - ARM_LOCAL_STATE_OFF) - return; - } + css_pwr_domain_on_finisher_common(target_state); /* Enable the gic cpu interface */ arm_gic_cpuif_setup(); - - /* todo: Is this setup only needed after a cold boot? */ + /* Program the gic per-cpu distributor interface */ arm_gic_pcpu_distif_setup(); } @@ -154,19 +147,12 @@ static void css_power_down_common(const psci_power_state_t *target_state) /* Prevent interrupts from spuriously waking up this cpu */ arm_gic_cpuif_deactivate(); - if (PLAT_MAX_PWR_LVL > ARM_PWR_LVL1) { - /* - * Check if power down at system power domain level is - * requested. - */ - if (target_state->pwr_domain_state[ARM_PWR_LVL2] == - ARM_LOCAL_STATE_OFF) + /* Check if power down at system power domain level is requested */ + if (CSS_SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) system_state = scpi_power_retention; - } /* Cluster is to be turned off, so disable coherency */ - if (target_state->pwr_domain_state[ARM_PWR_LVL1] == - ARM_LOCAL_STATE_OFF) { + if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) { cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr())); cluster_state = scpi_power_off; } @@ -187,9 +173,7 @@ static void css_power_down_common(const psci_power_state_t *target_state) ******************************************************************************/ void css_pwr_domain_off(const psci_power_state_t *target_state) { - assert(target_state->pwr_domain_state[ARM_PWR_LVL0] == - ARM_LOCAL_STATE_OFF); - + assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF); css_power_down_common(target_state); } @@ -200,16 +184,13 @@ void css_pwr_domain_off(const psci_power_state_t *target_state) void css_pwr_domain_suspend(const psci_power_state_t *target_state) { /* - * Juno has retention only at cpu level. Just return + * CSS currently supports retention only at cpu level. Just return * as nothing is to be done for retention. */ - if (target_state->pwr_domain_state[ARM_PWR_LVL0] == - ARM_LOCAL_STATE_RET) + if (CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_RET) return; - assert(target_state->pwr_domain_state[ARM_PWR_LVL0] == - ARM_LOCAL_STATE_OFF); - + assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF); css_power_down_common(target_state); } @@ -223,14 +204,18 @@ void css_pwr_domain_suspend(const psci_power_state_t *target_state) void css_pwr_domain_suspend_finish( const psci_power_state_t *target_state) { - /* - * Return as nothing is to be done on waking up from retention. - */ - if (target_state->pwr_domain_state[ARM_PWR_LVL0] == - ARM_LOCAL_STATE_RET) + /* Return as nothing is to be done on waking up from retention. */ + if (CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_RET) return; - css_pwr_domain_on_finish(target_state); + /* Perform system domain restore if woken up from system suspend */ + if (CSS_SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) + arm_system_pwr_domain_resume(); + else + /* Enable the gic cpu interface */ + arm_gic_cpuif_setup(); + + css_pwr_domain_on_finisher_common(target_state); } /******************************************************************************* -- cgit From 27573c59a6bf16c2330b41453f87bdd60afb2144 Mon Sep 17 00:00:00 2001 From: Achin Gupta Date: Tue, 3 Nov 2015 14:18:34 +0000 Subject: Rework use of ARM GIC drivers on ARM platforms Suport for ARM GIC v2.0 and v3.0 drivers has been reworked to create three separate drivers instead of providing a single driver that can work on both versions of the GIC architecture. These drivers correspond to the following software use cases: 1. A GICv2 only driver that can run only on ARM GIC v2.0 implementations e.g. GIC-400 2. A GICv3 only driver that can run only on ARM GIC v3.0 implementations e.g. GIC-500 in a mode where all interrupt regimes use GICv3 features 3. A deprecated GICv3 driver that operates in legacy mode. This driver can operate only in the GICv2 mode in the secure world. On a GICv3 system, this driver allows normal world to run in either GICv3 mode (asymmetric mode) or in the GICv2 mode. Both modes of operation are deprecated on GICv3 systems. ARM platforms implement both versions of the GIC architecture. This patch adds a layer of abstraction to help ARM platform ports chose the right GIC driver and corresponding platform support. This is as described below: 1. A set of ARM common functions have been introduced to initialise the GIC and the driver during cold and warm boot. These functions are prefixed as "plat_arm_gic_". Weak definitions of these functions have been provided for each type of driver. 2. Each platform includes the sources that implement the right functions directly into the its makefile. The FVP can be instantiated with different versions of the GIC architecture. It uses the FVP_USE_GIC_DRIVER build option to specify which of the three drivers should be included in the build. 3. A list of secure interrupts has to be provided to initialise each of the three GIC drivers. For GIC v3.0 the interrupt ids have to be further categorised as Group 0 and Group 1 Secure interrupts. For GIC v2.0, the two types are merged and treated as Group 0 interrupts. The two lists of interrupts are exported from the platform_def.h. The lists are constructed by adding a list of board specific interrupt ids to a list of ids common to all ARM platforms and Compute sub-systems. This patch also makes some fields of `arm_config` data structure in FVP redundant and these unused fields are removed. Change-Id: Ibc8c087be7a8a6b041b78c2c3bd0c648cd2035d8 --- plat/arm/css/common/css_pm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'plat/arm/css/common/css_pm.c') diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c index 1d9bd594..6d6646e0 100644 --- a/plat/arm/css/common/css_pm.c +++ b/plat/arm/css/common/css_pm.c @@ -30,7 +30,6 @@ #include #include -#include #include #include #include @@ -127,10 +126,11 @@ void css_pwr_domain_on_finish(const psci_power_state_t *target_state) css_pwr_domain_on_finisher_common(target_state); + /* Program the gic per-cpu distributor or re-distributor interface */ + plat_arm_gic_pcpu_init(); + /* Enable the gic cpu interface */ - arm_gic_cpuif_setup(); - /* Program the gic per-cpu distributor interface */ - arm_gic_pcpu_distif_setup(); + plat_arm_gic_cpuif_enable(); } /******************************************************************************* @@ -145,7 +145,7 @@ static void css_power_down_common(const psci_power_state_t *target_state) uint32_t system_state = scpi_power_on; /* Prevent interrupts from spuriously waking up this cpu */ - arm_gic_cpuif_deactivate(); + plat_arm_gic_cpuif_disable(); /* Check if power down at system power domain level is requested */ if (CSS_SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) @@ -213,7 +213,7 @@ void css_pwr_domain_suspend_finish( arm_system_pwr_domain_resume(); else /* Enable the gic cpu interface */ - arm_gic_cpuif_setup(); + plat_arm_gic_cpuif_enable(); css_pwr_domain_on_finisher_common(target_state); } -- cgit