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
This commit is contained in:
parent
1298ae0234
commit
05b128f25e
|
@ -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;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
|
@ -81,9 +81,34 @@ typedef uint32_t scpi_status_t;
|
|||
typedef enum {
|
||||
SCPI_CMD_SCP_READY = 0x01,
|
||||
SCPI_CMD_SET_CSS_POWER_STATE = 0x03,
|
||||
SCPI_CMD_GET_CSS_POWER_STATE = 0x04,
|
||||
SCPI_CMD_SYS_POWER_STATE = 0x05
|
||||
} scpi_command_t;
|
||||
|
||||
/*
|
||||
* Macros to parse SCP response to GET_CSS_POWER_STATE command
|
||||
*
|
||||
* [3:0] : cluster ID
|
||||
* [7:4] : cluster state: 0 = on; 3 = off; rest are reserved
|
||||
* [15:8]: on/off state for individual CPUs in the cluster
|
||||
*
|
||||
* Payload is in little-endian
|
||||
*/
|
||||
#define CLUSTER_ID(_resp) ((_resp) & 0xf)
|
||||
#define CLUSTER_POWER_STATE(_resp) (((_resp) >> 4) & 0xf)
|
||||
|
||||
/* Result is a bit mask of CPU on/off states in the cluster */
|
||||
#define CPU_POWER_STATE(_resp) (((_resp) >> 8) & 0xff)
|
||||
|
||||
/*
|
||||
* For GET_CSS_POWER_STATE, SCP returns the power states of every cluster. The
|
||||
* size of response depends on the number of clusters in the system. The
|
||||
* SCP-to-AP payload contains 2 bytes per cluster. Make sure the response is
|
||||
* large enough to contain power states of a given cluster
|
||||
*/
|
||||
#define CHECK_RESPONSE(_resp, _clus) \
|
||||
(_resp.size >= (((_clus) + 1) * 2))
|
||||
|
||||
typedef enum {
|
||||
scpi_power_on = 0,
|
||||
scpi_power_retention = 1,
|
||||
|
@ -101,6 +126,8 @@ extern void scpi_set_css_power_state(unsigned mpidr,
|
|||
scpi_power_state_t cpu_state,
|
||||
scpi_power_state_t cluster_state,
|
||||
scpi_power_state_t css_state);
|
||||
int scpi_get_css_power_state(unsigned int mpidr, unsigned int *cpu_state_p,
|
||||
unsigned int *cluster_state_p);
|
||||
uint32_t scpi_sys_power_state(scpi_system_state_t system_state);
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue