Merge changes from topic "ti-cluster-power" into integration

* changes:
  ti: k3: drivers: ti_sci: Put sequence number in coherent memory
  ti: k3: drivers: ti_sci: Remove indirect structure of const data
  ti: k3: common: Enable ARM cluster power down
  ti: k3: common: Rename device IDs to be more consistent
This commit is contained in:
Soby Mathew 2020-01-28 10:43:36 +00:00 committed by TrustedFirmware Code Review
commit 29763ac260
4 changed files with 137 additions and 58 deletions

View File

@ -27,5 +27,6 @@
#define PLAT_PROC_START_ID 32
#define PLAT_PROC_DEVICE_START_ID 202
#define PLAT_CLUSTER_DEVICE_START_ID 198
#endif /* BOARD_DEF_H */

View File

@ -20,32 +20,10 @@
#include "ti_sci_protocol.h"
#include "ti_sci.h"
/**
* struct ti_sci_desc - Description of SoC integration
* @host_id: Host identifier representing the compute entity
* @max_msg_size: Maximum size of data per message that can be handled
*/
struct ti_sci_desc {
uint8_t host_id;
int max_msg_size;
};
/**
* struct ti_sci_info - Structure representing a TI SCI instance
* @desc: SoC description for this instance
* @seq: Seq id used for verification for tx and rx message
*/
struct ti_sci_info {
const struct ti_sci_desc desc;
uint8_t seq;
};
static struct ti_sci_info info = {
.desc = {
.host_id = TI_SCI_HOST_ID,
.max_msg_size = TI_SCI_MAX_MESSAGE_SIZE,
},
};
#if USE_COHERENT_MEM
__section("tzfw_coherent_mem")
#endif
static uint8_t message_sequence;
/**
* struct ti_sci_xfer - Structure representing a message flow
@ -82,16 +60,16 @@ static int ti_sci_setup_one_xfer(uint16_t msg_type, uint32_t msg_flags,
struct ti_sci_msg_hdr *hdr;
/* Ensure we have sane transfer sizes */
if (rx_message_size > info.desc.max_msg_size ||
tx_message_size > info.desc.max_msg_size ||
if (rx_message_size > TI_SCI_MAX_MESSAGE_SIZE ||
tx_message_size > TI_SCI_MAX_MESSAGE_SIZE ||
rx_message_size < sizeof(*hdr) ||
tx_message_size < sizeof(*hdr))
return -ERANGE;
hdr = (struct ti_sci_msg_hdr *)tx_buf;
hdr->seq = ++info.seq;
hdr->seq = ++message_sequence;
hdr->type = msg_type;
hdr->host = info.desc.host_id;
hdr->host = TI_SCI_HOST_ID;
hdr->flags = msg_flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED;
xfer->tx_message.buf = tx_buf;
@ -131,7 +109,7 @@ static inline int ti_sci_get_response(struct ti_sci_xfer *xfer,
hdr = (struct ti_sci_msg_hdr *)msg->buf;
/* Sanity check for message response */
if (hdr->seq == info.seq)
if (hdr->seq == message_sequence)
break;
else
WARN("Message with sequence ID %u is not expected\n", hdr->seq);
@ -141,9 +119,9 @@ static inline int ti_sci_get_response(struct ti_sci_xfer *xfer,
return -EINVAL;
}
if (msg->len > info.desc.max_msg_size) {
if (msg->len > TI_SCI_MAX_MESSAGE_SIZE) {
ERROR("Unable to handle %lu xfer (max %d)\n",
msg->len, info.desc.max_msg_size);
msg->len, TI_SCI_MAX_MESSAGE_SIZE);
return -EINVAL;
}
@ -425,13 +403,13 @@ int ti_sci_device_put_no_wait(uint32_t id)
int ret;
/* Ensure we have sane transfer size */
if (sizeof(req) > info.desc.max_msg_size)
if (sizeof(req) > TI_SCI_MAX_MESSAGE_SIZE)
return -ERANGE;
hdr = (struct ti_sci_msg_hdr *)&req;
hdr->seq = ++info.seq;
hdr->seq = ++message_sequence;
hdr->type = TI_SCI_MSG_SET_DEVICE_STATE;
hdr->host = info.desc.host_id;
hdr->host = TI_SCI_HOST_ID;
/* Setup with NORESPONSE flag to keep response queue clean */
hdr->flags = TI_SCI_FLAG_REQ_GENERIC_NORESPONSE;
@ -1408,13 +1386,13 @@ int ti_sci_proc_set_boot_ctrl_no_wait(uint8_t proc_id,
int ret;
/* Ensure we have sane transfer size */
if (sizeof(req) > info.desc.max_msg_size)
if (sizeof(req) > TI_SCI_MAX_MESSAGE_SIZE)
return -ERANGE;
hdr = (struct ti_sci_msg_hdr *)&req;
hdr->seq = ++info.seq;
hdr->seq = ++message_sequence;
hdr->type = TISCI_MSG_SET_PROC_BOOT_CTRL;
hdr->host = info.desc.host_id;
hdr->host = TI_SCI_HOST_ID;
/* Setup with NORESPONSE flag to keep response queue clean */
hdr->flags = TI_SCI_FLAG_REQ_GENERIC_NORESPONSE;
@ -1650,13 +1628,13 @@ int ti_sci_proc_wait_boot_status_no_wait(uint8_t proc_id,
int ret;
/* Ensure we have sane transfer size */
if (sizeof(req) > info.desc.max_msg_size)
if (sizeof(req) > TI_SCI_MAX_MESSAGE_SIZE)
return -ERANGE;
hdr = (struct ti_sci_msg_hdr *)&req;
hdr->seq = ++info.seq;
hdr->seq = ++message_sequence;
hdr->type = TISCI_MSG_WAIT_PROC_BOOT_STATUS;
hdr->host = info.desc.host_id;
hdr->host = TI_SCI_HOST_ID;
/* Setup with NORESPONSE flag to keep response queue clean */
hdr->flags = TI_SCI_FLAG_REQ_GENERIC_NORESPONSE;

View File

@ -563,8 +563,13 @@ struct ti_sci_msg_req_set_proc_boot_config {
uint32_t config_flags_clear;
} __packed;
/* ARMV8 Control Flags */
#define PROC_BOOT_CTRL_FLAG_ARMV8_ACINACTM 0x00000001
#define PROC_BOOT_CTRL_FLAG_ARMV8_AINACTS 0x00000002
#define PROC_BOOT_CTRL_FLAG_ARMV8_L2FLUSHREQ 0x00000100
/* R5 Control Flags */
#define PROC_BOOT_CTRL_FLAG_R5_CORE_HALT 0x00000001
#define PROC_BOOT_CTRL_FLAG_R5_CORE_HALT 0x00000001
/**
* struct ti_sci_msg_req_set_proc_boot_ctrl - Set Processor boot control flags
@ -618,6 +623,8 @@ struct ti_sci_msg_req_get_proc_boot_status {
/* ARMv8 Status Flags */
#define PROC_BOOT_STATUS_FLAG_ARMV8_WFE 0x00000001
#define PROC_BOOT_STATUS_FLAG_ARMV8_WFI 0x00000002
#define PROC_BOOT_STATUS_FLAG_ARMV8_L2F_DONE 0x00000010
#define PROC_BOOT_STATUS_FLAG_ARMV8_STANDBYWFIL2 0x00000020
/* R5 Status Flags */
#define PROC_BOOT_STATUS_FLAG_R5_WFE 0x00000001

View File

@ -17,6 +17,10 @@
#include <k3_gicv3.h>
#include <ti_sci.h>
#define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0])
#define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1])
#define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
uintptr_t k3_sec_entrypoint;
static void k3_cpu_standby(plat_local_state_t cpu_state)
@ -37,30 +41,40 @@ static void k3_cpu_standby(plat_local_state_t cpu_state)
static int k3_pwr_domain_on(u_register_t mpidr)
{
int core_id, proc, device, ret;
int core, proc_id, device_id, ret;
core_id = plat_core_pos_by_mpidr(mpidr);
if (core_id < 0) {
ERROR("Could not get target core id: %d\n", core_id);
core = plat_core_pos_by_mpidr(mpidr);
if (core < 0) {
ERROR("Could not get target core id: %d\n", core);
return PSCI_E_INTERN_FAIL;
}
proc = PLAT_PROC_START_ID + core_id;
device = PLAT_PROC_DEVICE_START_ID + core_id;
proc_id = PLAT_PROC_START_ID + core;
device_id = PLAT_PROC_DEVICE_START_ID + core;
ret = ti_sci_proc_request(proc);
ret = ti_sci_proc_request(proc_id);
if (ret) {
ERROR("Request for processor failed: %d\n", ret);
return PSCI_E_INTERN_FAIL;
}
ret = ti_sci_proc_set_boot_cfg(proc, k3_sec_entrypoint, 0, 0);
ret = ti_sci_proc_set_boot_cfg(proc_id, k3_sec_entrypoint, 0, 0);
if (ret) {
ERROR("Request to set core boot address failed: %d\n", ret);
return PSCI_E_INTERN_FAIL;
}
ret = ti_sci_device_get(device);
/* sanity check these are off before starting a core */
ret = ti_sci_proc_set_boot_ctrl(proc_id,
0, PROC_BOOT_CTRL_FLAG_ARMV8_L2FLUSHREQ |
PROC_BOOT_CTRL_FLAG_ARMV8_AINACTS |
PROC_BOOT_CTRL_FLAG_ARMV8_ACINACTM);
if (ret) {
ERROR("Request to clear boot configuration failed: %d\n", ret);
return PSCI_E_INTERN_FAIL;
}
ret = ti_sci_device_get(device_id);
if (ret) {
ERROR("Request to start core failed: %d\n", ret);
return PSCI_E_INTERN_FAIL;
@ -71,17 +85,35 @@ static int k3_pwr_domain_on(u_register_t mpidr)
void k3_pwr_domain_off(const psci_power_state_t *target_state)
{
int core_id, proc, device, ret;
int core, cluster, proc_id, device_id, cluster_id, ret;
/* At very least the local core should be powering down */
assert(CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE);
/* Prevent interrupts from spuriously waking up this cpu */
k3_gic_cpuif_disable();
core_id = plat_my_core_pos();
proc = PLAT_PROC_START_ID + core_id;
device = PLAT_PROC_DEVICE_START_ID + core_id;
core = plat_my_core_pos();
cluster = MPIDR_AFFLVL1_VAL(read_mpidr_el1());
proc_id = PLAT_PROC_START_ID + core;
device_id = PLAT_PROC_DEVICE_START_ID + core;
cluster_id = PLAT_CLUSTER_DEVICE_START_ID + (cluster * 2);
/*
* If we are the last core in the cluster then we take a reference to
* the cluster device so that it does not get shutdown before we
* execute the entire cluster L2 cleaning sequence below.
*/
if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
ret = ti_sci_device_get(cluster_id);
if (ret) {
ERROR("Request to get cluster failed: %d\n", ret);
return;
}
}
/* Start by sending wait for WFI command */
ret = ti_sci_proc_wait_boot_status_no_wait(proc,
ret = ti_sci_proc_wait_boot_status_no_wait(proc_id,
/*
* Wait maximum time to give us the best chance to get
* to WFI before this command timeouts
@ -95,11 +127,72 @@ void k3_pwr_domain_off(const psci_power_state_t *target_state)
}
/* Now queue up the core shutdown request */
ret = ti_sci_device_put_no_wait(device);
ret = ti_sci_device_put_no_wait(device_id);
if (ret) {
ERROR("Sending core shutdown message failed (%d)\n", ret);
return;
}
/* If our cluster is not going down we stop here */
if (CLUSTER_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
return;
/* set AINACTS */
ret = ti_sci_proc_set_boot_ctrl_no_wait(proc_id,
PROC_BOOT_CTRL_FLAG_ARMV8_AINACTS, 0);
if (ret) {
ERROR("Sending set control message failed (%d)\n", ret);
return;
}
/* set L2FLUSHREQ */
ret = ti_sci_proc_set_boot_ctrl_no_wait(proc_id,
PROC_BOOT_CTRL_FLAG_ARMV8_L2FLUSHREQ, 0);
if (ret) {
ERROR("Sending set control message failed (%d)\n", ret);
return;
}
/* wait for L2FLUSHDONE*/
ret = ti_sci_proc_wait_boot_status_no_wait(proc_id,
UINT8_MAX, 2, UINT8_MAX, UINT8_MAX,
PROC_BOOT_STATUS_FLAG_ARMV8_L2F_DONE, 0, 0, 0);
if (ret) {
ERROR("Sending wait message failed (%d)\n", ret);
return;
}
/* clear L2FLUSHREQ */
ret = ti_sci_proc_set_boot_ctrl_no_wait(proc_id,
0, PROC_BOOT_CTRL_FLAG_ARMV8_L2FLUSHREQ);
if (ret) {
ERROR("Sending set control message failed (%d)\n", ret);
return;
}
/* set ACINACTM */
ret = ti_sci_proc_set_boot_ctrl_no_wait(proc_id,
PROC_BOOT_CTRL_FLAG_ARMV8_ACINACTM, 0);
if (ret) {
ERROR("Sending set control message failed (%d)\n", ret);
return;
}
/* wait for STANDBYWFIL2 */
ret = ti_sci_proc_wait_boot_status_no_wait(proc_id,
UINT8_MAX, 2, UINT8_MAX, UINT8_MAX,
PROC_BOOT_STATUS_FLAG_ARMV8_STANDBYWFIL2, 0, 0, 0);
if (ret) {
ERROR("Sending wait message failed (%d)\n", ret);
return;
}
/* Now queue up the cluster shutdown request */
ret = ti_sci_device_put_no_wait(cluster_id);
if (ret) {
ERROR("Sending cluster shutdown message failed (%d)\n", ret);
return;
}
}
void k3_pwr_domain_on_finish(const psci_power_state_t *target_state)