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