blob: 170b7e184659590f283804622a30dd2b12364ec7 [file] [log] [blame]
Sumit Garg0f18bc42018-06-15 15:20:53 +05301/*
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
28static void scpi_secure_message_start(void)
29{
30 mhu_secure_message_start(SCPI_MHU_SLOT_ID);
31}
32
33static 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
45static 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
70static void scpi_secure_message_end(void)
71{
72 mhu_secure_message_end(SCPI_MHU_SLOT_ID);
73}
74
75int 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
113void 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
146uint32_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}
Ard Biesheuvel6fc122f2018-06-15 15:25:42 +0530171
172uint32_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}