diff options
author | Jeenu Viswambharan <jeenu.viswambharan@arm.com> | 2016-08-04 12:44:52 +0100 |
---|---|---|
committer | Jeenu Viswambharan <jeenu.viswambharan@arm.com> | 2016-09-15 11:18:48 +0100 |
commit | 05b128f25edb351c537e55f90851189c35d45855 (patch) | |
tree | 4a0dc7fc89a3a0d37fa7cef4c77da3a01a2e68d8 /plat/arm/css/common/css_scpi.c | |
parent | 1298ae023484077dcab596eb8e963cef96fe9605 (diff) |
SCPI: Add function to query CSS power state
This patch adds the function scpi_get_css_power_state to perform the
'Get CSS Power State' SCP command and handle its response. The function
parses SCP response to obtain power states of requested cluster and CPUs
within.
Change-Id: I3ea26e48dff1a139da73f6c1e0893f21accaf9f0
Diffstat (limited to 'plat/arm/css/common/css_scpi.c')
-rw-r--r-- | plat/arm/css/common/css_scpi.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/plat/arm/css/common/css_scpi.c b/plat/arm/css/common/css_scpi.c index 02d573c9..90a8939d 100644 --- a/plat/arm/css/common/css_scpi.c +++ b/plat/arm/css/common/css_scpi.c @@ -41,11 +41,18 @@ #define SCPI_SHARED_MEM_AP_TO_SCP (PLAT_CSS_SCP_COM_SHARED_MEM_BASE \ + 0x100) +/* Header and payload addresses for commands from AP to SCP */ #define SCPI_CMD_HEADER_AP_TO_SCP \ ((scpi_cmd_t *) SCPI_SHARED_MEM_AP_TO_SCP) #define SCPI_CMD_PAYLOAD_AP_TO_SCP \ ((void *) (SCPI_SHARED_MEM_AP_TO_SCP + sizeof(scpi_cmd_t))) +/* Header and payload addresses for responses from SCP to AP */ +#define SCPI_RES_HEADER_SCP_TO_AP \ + ((scpi_cmd_t *) SCPI_SHARED_MEM_SCP_TO_AP) +#define SCPI_RES_PAYLOAD_SCP_TO_AP \ + ((void *) (SCPI_SHARED_MEM_SCP_TO_AP + sizeof(scpi_cmd_t))) + /* ID of the MHU slot used for the SCPI protocol */ #define SCPI_MHU_SLOT_ID 0 @@ -163,6 +170,68 @@ void scpi_set_css_power_state(unsigned mpidr, scpi_power_state_t cpu_state, scpi_secure_message_end(); } +/* + * Query and obtain CSS power state from SCP. + * + * In response to the query, SCP returns power states of all CPUs in all + * clusters of the system. The returned response is then filtered based on the + * supplied MPIDR. Power states of requested cluster and CPUs within are updated + * via. supplied non-NULL pointer arguments. + * + * Returns 0 on success, or -1 on errors. + */ +int scpi_get_css_power_state(unsigned int mpidr, unsigned int *cpu_state_p, + unsigned int *cluster_state_p) +{ + scpi_cmd_t *cmd; + scpi_cmd_t response; + int power_state, cpu, cluster, rc = -1; + + /* + * Extract CPU and cluster membership of the given MPIDR. SCPI caters + * for only up to 0xf clusters, and 8 CPUs per cluster + */ + cpu = mpidr & MPIDR_AFFLVL_MASK; + cluster = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + if (cpu >= 8 || cluster >= 0xf) + return -1; + + scpi_secure_message_start(); + + /* Populate request headers */ + cmd = memset(SCPI_CMD_HEADER_AP_TO_SCP, 0, sizeof(*cmd)); + cmd->id = SCPI_CMD_GET_CSS_POWER_STATE; + + /* + * Send message and wait for SCP's response + */ + scpi_secure_message_send(0); + scpi_secure_message_receive(&response); + + if (response.status != SCP_OK) + goto exit; + + /* Validate SCP response */ + if (!CHECK_RESPONSE(response, cluster)) + goto exit; + + /* Extract power states for required cluster */ + power_state = *(((uint16_t *) SCPI_RES_PAYLOAD_SCP_TO_AP) + cluster); + if (CLUSTER_ID(power_state) != cluster) + goto exit; + + /* Update power state via. pointers */ + if (cluster_state_p) + *cluster_state_p = CLUSTER_POWER_STATE(power_state); + if (cpu_state_p) + *cpu_state_p = CPU_POWER_STATE(power_state); + rc = 0; + +exit: + scpi_secure_message_end(); + return rc; +} + uint32_t scpi_sys_power_state(scpi_system_state_t system_state) { scpi_cmd_t *cmd; |