1 /* 2 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <string.h> 9 10 #include <platform_def.h> 11 12 #include <arch_helpers.h> 13 #include <common/debug.h> 14 #include <sq_common.h> 15 16 #include "sq_mhu.h" 17 #include "sq_scpi.h" 18 19 #define SCPI_SHARED_MEM_SCP_TO_AP PLAT_SQ_SCP_COM_SHARED_MEM_BASE 20 #define SCPI_SHARED_MEM_AP_TO_SCP (PLAT_SQ_SCP_COM_SHARED_MEM_BASE \ 21 + 0x100) 22 23 #define SCPI_CMD_HEADER_AP_TO_SCP \ 24 ((scpi_cmd_t *) SCPI_SHARED_MEM_AP_TO_SCP) 25 #define SCPI_CMD_PAYLOAD_AP_TO_SCP \ 26 ((void *) (SCPI_SHARED_MEM_AP_TO_SCP + sizeof(scpi_cmd_t))) 27 28 /* ID of the MHU slot used for the SCPI protocol */ 29 #define SCPI_MHU_SLOT_ID 0 30 31 static void scpi_secure_message_start(void) 32 { 33 mhu_secure_message_start(SCPI_MHU_SLOT_ID); 34 } 35 36 static void scpi_secure_message_send(size_t payload_size) 37 { 38 /* 39 * Ensure that any write to the SCPI payload area is seen by SCP before 40 * we write to the MHU register. If these 2 writes were reordered by 41 * the CPU then SCP would read stale payload data 42 */ 43 dmbst(); 44 45 mhu_secure_message_send(SCPI_MHU_SLOT_ID); 46 } 47 48 static void scpi_secure_message_receive(scpi_cmd_t *cmd) 49 { 50 uint32_t mhu_status; 51 52 assert(cmd != NULL); 53 54 mhu_status = mhu_secure_message_wait(); 55 56 /* Expect an SCPI message, reject any other protocol */ 57 if (mhu_status != (1 << SCPI_MHU_SLOT_ID)) { 58 ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n", 59 mhu_status); 60 panic(); 61 } 62 63 /* 64 * Ensure that any read to the SCPI payload area is done after reading 65 * the MHU register. If these 2 reads were reordered then the CPU would 66 * read invalid payload data 67 */ 68 dmbld(); 69 70 memcpy(cmd, (void *) SCPI_SHARED_MEM_SCP_TO_AP, sizeof(*cmd)); 71 } 72 73 static void scpi_secure_message_end(void) 74 { 75 mhu_secure_message_end(SCPI_MHU_SLOT_ID); 76 } 77 78 int scpi_wait_ready(void) 79 { 80 scpi_cmd_t scpi_cmd; 81 scpi_status_t status = SCP_OK; 82 83 VERBOSE("Waiting for SCP_READY command...\n"); 84 85 /* Get a message from the SCP */ 86 scpi_secure_message_start(); 87 scpi_secure_message_receive(&scpi_cmd); 88 scpi_secure_message_end(); 89 90 /* We are expecting 'SCP Ready', produce correct error if it's not */ 91 if (scpi_cmd.id != SCPI_CMD_SCP_READY) { 92 ERROR("Unexpected SCP command: expected command #%u," 93 "got command #%u\n", SCPI_CMD_SCP_READY, scpi_cmd.id); 94 status = SCP_E_SUPPORT; 95 } else if (scpi_cmd.size != 0) { 96 ERROR("SCP_READY command has incorrect size: expected 0," 97 "got %u\n", scpi_cmd.size); 98 status = SCP_E_SIZE; 99 } 100 101 VERBOSE("Sending response for SCP_READY command\n"); 102 103 /* 104 * Send our response back to SCP. 105 * We are using the same SCPI header, just update the status field. 106 */ 107 scpi_cmd.status = status; 108 scpi_secure_message_start(); 109 memcpy((void *) SCPI_SHARED_MEM_AP_TO_SCP, &scpi_cmd, sizeof(scpi_cmd)); 110 scpi_secure_message_send(0); 111 scpi_secure_message_end(); 112 113 return status == SCP_OK ? 0 : -1; 114 } 115 116 void scpi_set_sq_power_state(unsigned int mpidr, scpi_power_state_t cpu_state, 117 scpi_power_state_t cluster_state, scpi_power_state_t sq_state) 118 { 119 scpi_cmd_t *cmd; 120 uint32_t state = 0; 121 uint32_t *payload_addr; 122 123 state |= mpidr & 0x0f; /* CPU ID */ 124 state |= (mpidr & 0xf00) >> 4; /* Cluster ID */ 125 state |= cpu_state << 8; 126 state |= cluster_state << 12; 127 state |= sq_state << 16; 128 129 scpi_secure_message_start(); 130 131 /* Populate the command header */ 132 cmd = SCPI_CMD_HEADER_AP_TO_SCP; 133 cmd->id = SCPI_CMD_SET_POWER_STATE; 134 cmd->set = SCPI_SET_NORMAL; 135 cmd->sender = 0; 136 cmd->size = sizeof(state); 137 /* Populate the command payload */ 138 payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP; 139 *payload_addr = state; 140 scpi_secure_message_send(sizeof(state)); 141 142 /* 143 * SCP does not reply to this command in order to avoid MHU interrupts 144 * from the sender, which could interfere with its power state request. 145 */ 146 scpi_secure_message_end(); 147 } 148 149 uint32_t scpi_sys_power_state(scpi_system_state_t system_state) 150 { 151 scpi_cmd_t *cmd; 152 uint8_t *payload_addr; 153 scpi_cmd_t response; 154 155 scpi_secure_message_start(); 156 157 /* Populate the command header */ 158 cmd = SCPI_CMD_HEADER_AP_TO_SCP; 159 cmd->id = SCPI_CMD_SYS_POWER_STATE; 160 cmd->set = 0; 161 cmd->sender = 0; 162 cmd->size = sizeof(*payload_addr); 163 /* Populate the command payload */ 164 payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP; 165 *payload_addr = system_state & 0xff; 166 scpi_secure_message_send(sizeof(*payload_addr)); 167 168 scpi_secure_message_receive(&response); 169 170 scpi_secure_message_end(); 171 172 return response.status; 173 } 174 175 uint32_t scpi_get_draminfo(struct draminfo *info) 176 { 177 scpi_cmd_t *cmd; 178 struct { 179 scpi_cmd_t cmd; 180 struct draminfo info; 181 } response; 182 uint32_t mhu_status; 183 184 scpi_secure_message_start(); 185 186 /* Populate the command header */ 187 cmd = SCPI_CMD_HEADER_AP_TO_SCP; 188 cmd->id = SCPI_CMD_GET_DRAMINFO; 189 cmd->set = SCPI_SET_EXTENDED; 190 cmd->sender = 0; 191 cmd->size = 0; 192 193 scpi_secure_message_send(0); 194 195 mhu_status = mhu_secure_message_wait(); 196 197 /* Expect an SCPI message, reject any other protocol */ 198 if (mhu_status != (1 << SCPI_MHU_SLOT_ID)) { 199 ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n", 200 mhu_status); 201 panic(); 202 } 203 204 /* 205 * Ensure that any read to the SCPI payload area is done after reading 206 * the MHU register. If these 2 reads were reordered then the CPU would 207 * read invalid payload data 208 */ 209 dmbld(); 210 211 memcpy(&response, (void *)SCPI_SHARED_MEM_SCP_TO_AP, sizeof(response)); 212 213 scpi_secure_message_end(); 214 215 if (response.cmd.status == SCP_OK) 216 *info = response.info; 217 218 return response.cmd.status; 219 } 220