diff --git a/plat/ti/k3/board/generic/include/board_def.h b/plat/ti/k3/board/generic/include/board_def.h index c1a5966..0d45116 100644 --- a/plat/ti/k3/board/generic/include/board_def.h +++ b/plat/ti/k3/board/generic/include/board_def.h @@ -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 */ diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c index ac33278..e390efe 100644 --- a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c +++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c @@ -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 @@ 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 @@ 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 @@ 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 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 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 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; diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h b/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h index a921e51..2d23f9a 100644 --- a/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h +++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h @@ -563,8 +563,13 @@ 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 @@ /* 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 diff --git a/plat/ti/k3/common/k3_psci.c b/plat/ti/k3/common/k3_psci.c index de9cefe..cf0a21d 100644 --- a/plat/ti/k3/common/k3_psci.c +++ b/plat/ti/k3/common/k3_psci.c @@ -17,6 +17,10 @@ #include #include +#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 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 @@ 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 @@ } /* 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)