blob: 9e1f9738cb4a63b80bfc9bcd1130d43822218a79 [file] [log] [blame]
Dan Handley9df48042015-03-19 18:58:55 +00001/*
Vikram Kanigiri72084192016-02-08 16:29:30 +00002 * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
Dan Handley9df48042015-03-19 18:58:55 +00003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <arch_helpers.h>
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000032#include <assert.h>
Dan Handley9df48042015-03-19 18:58:55 +000033#include <css_def.h>
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000034#include <debug.h>
Dan Handley9df48042015-03-19 18:58:55 +000035#include <platform.h>
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000036#include <string.h>
Dan Handley9df48042015-03-19 18:58:55 +000037#include "css_mhu.h"
38#include "css_scpi.h"
39
Vikram Kanigiri72084192016-02-08 16:29:30 +000040#define SCPI_SHARED_MEM_SCP_TO_AP PLAT_CSS_SCP_COM_SHARED_MEM_BASE
41#define SCPI_SHARED_MEM_AP_TO_SCP (PLAT_CSS_SCP_COM_SHARED_MEM_BASE \
42 + 0x100)
Dan Handley9df48042015-03-19 18:58:55 +000043
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000044#define SCPI_CMD_HEADER_AP_TO_SCP \
45 ((scpi_cmd_t *) SCPI_SHARED_MEM_AP_TO_SCP)
46#define SCPI_CMD_PAYLOAD_AP_TO_SCP \
47 ((void *) (SCPI_SHARED_MEM_AP_TO_SCP + sizeof(scpi_cmd_t)))
Dan Handley9df48042015-03-19 18:58:55 +000048
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000049/* ID of the MHU slot used for the SCPI protocol */
50#define SCPI_MHU_SLOT_ID 0
Dan Handley9df48042015-03-19 18:58:55 +000051
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000052static void scpi_secure_message_start(void)
Dan Handley9df48042015-03-19 18:58:55 +000053{
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000054 mhu_secure_message_start(SCPI_MHU_SLOT_ID);
Dan Handley9df48042015-03-19 18:58:55 +000055}
56
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000057static void scpi_secure_message_send(size_t payload_size)
Dan Handley9df48042015-03-19 18:58:55 +000058{
59 /* Make sure payload can be seen by SCP */
60 if (MHU_PAYLOAD_CACHED)
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000061 flush_dcache_range(SCPI_SHARED_MEM_AP_TO_SCP,
62 sizeof(scpi_cmd_t) + payload_size);
Dan Handley9df48042015-03-19 18:58:55 +000063
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000064 mhu_secure_message_send(SCPI_MHU_SLOT_ID);
Dan Handley9df48042015-03-19 18:58:55 +000065}
66
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000067static void scpi_secure_message_receive(scpi_cmd_t *cmd)
Dan Handley9df48042015-03-19 18:58:55 +000068{
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000069 uint32_t mhu_status;
Dan Handley9df48042015-03-19 18:58:55 +000070
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000071 assert(cmd != NULL);
Dan Handley9df48042015-03-19 18:58:55 +000072
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000073 mhu_status = mhu_secure_message_wait();
74
75 /* Expect an SCPI message, reject any other protocol */
76 if (mhu_status != (1 << SCPI_MHU_SLOT_ID)) {
77 ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n",
78 mhu_status);
79 panic();
80 }
Dan Handley9df48042015-03-19 18:58:55 +000081
82 /* Make sure we don't read stale data */
83 if (MHU_PAYLOAD_CACHED)
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000084 inv_dcache_range(SCPI_SHARED_MEM_SCP_TO_AP, sizeof(*cmd));
Dan Handley9df48042015-03-19 18:58:55 +000085
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000086 memcpy(cmd, (void *) SCPI_SHARED_MEM_SCP_TO_AP, sizeof(*cmd));
Dan Handley9df48042015-03-19 18:58:55 +000087}
88
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000089static void scpi_secure_message_end(void)
Dan Handley9df48042015-03-19 18:58:55 +000090{
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000091 mhu_secure_message_end(SCPI_MHU_SLOT_ID);
Dan Handley9df48042015-03-19 18:58:55 +000092}
93
94int scpi_wait_ready(void)
95{
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000096 scpi_cmd_t scpi_cmd;
97
98 VERBOSE("Waiting for SCP_READY command...\n");
99
Dan Handley9df48042015-03-19 18:58:55 +0000100 /* Get a message from the SCP */
101 scpi_secure_message_start();
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000102 scpi_secure_message_receive(&scpi_cmd);
Dan Handley9df48042015-03-19 18:58:55 +0000103 scpi_secure_message_end();
104
105 /* We are expecting 'SCP Ready', produce correct error if it's not */
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000106 scpi_status_t status = SCP_OK;
107 if (scpi_cmd.id != SCPI_CMD_SCP_READY) {
108 ERROR("Unexpected SCP command: expected command #%u, got command #%u\n",
109 SCPI_CMD_SCP_READY, scpi_cmd.id);
110 status = SCP_E_SUPPORT;
111 } else if (scpi_cmd.size != 0) {
112 ERROR("SCP_READY command has incorrect size: expected 0, got %u\n",
113 scpi_cmd.size);
114 status = SCP_E_SIZE;
115 }
Dan Handley9df48042015-03-19 18:58:55 +0000116
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000117 VERBOSE("Sending response for SCP_READY command\n");
118
119 /*
120 * Send our response back to SCP.
121 * We are using the same SCPI header, just update the status field.
122 */
123 scpi_cmd.status = status;
124 scpi_secure_message_start();
125 memcpy((void *) SCPI_SHARED_MEM_AP_TO_SCP, &scpi_cmd, sizeof(scpi_cmd));
126 scpi_secure_message_send(0);
127 scpi_secure_message_end();
Dan Handley9df48042015-03-19 18:58:55 +0000128
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000129 return status == SCP_OK ? 0 : -1;
Dan Handley9df48042015-03-19 18:58:55 +0000130}
131
132void scpi_set_css_power_state(unsigned mpidr, scpi_power_state_t cpu_state,
133 scpi_power_state_t cluster_state, scpi_power_state_t css_state)
134{
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000135 scpi_cmd_t *cmd;
136 uint32_t state = 0;
137 uint32_t *payload_addr;
138
139 state |= mpidr & 0x0f; /* CPU ID */
Dan Handley9df48042015-03-19 18:58:55 +0000140 state |= (mpidr & 0xf00) >> 4; /* Cluster ID */
141 state |= cpu_state << 8;
142 state |= cluster_state << 12;
143 state |= css_state << 16;
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000144
145 scpi_secure_message_start();
146
147 /* Populate the command header */
148 cmd = SCPI_CMD_HEADER_AP_TO_SCP;
149 cmd->id = SCPI_CMD_SET_CSS_POWER_STATE;
150 cmd->set = SCPI_SET_NORMAL;
151 cmd->sender = 0;
152 cmd->size = sizeof(state);
153 /* Populate the command payload */
154 payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP;
155 *payload_addr = state;
156 scpi_secure_message_send(sizeof(state));
157 /*
158 * SCP does not reply to this command in order to avoid MHU interrupts
159 * from the sender, which could interfere with its power state request.
160 */
161
162 scpi_secure_message_end();
Dan Handley9df48042015-03-19 18:58:55 +0000163}
164
165uint32_t scpi_sys_power_state(scpi_system_state_t system_state)
166{
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000167 scpi_cmd_t *cmd;
168 uint8_t *payload_addr;
169 scpi_cmd_t response;
170
171 scpi_secure_message_start();
Dan Handley9df48042015-03-19 18:58:55 +0000172
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000173 /* Populate the command header */
174 cmd = SCPI_CMD_HEADER_AP_TO_SCP;
175 cmd->id = SCPI_CMD_SYS_POWER_STATE;
176 cmd->set = 0;
177 cmd->sender = 0;
178 cmd->size = sizeof(*payload_addr);
179 /* Populate the command payload */
180 payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP;
181 *payload_addr = system_state & 0xff;
182 scpi_secure_message_send(sizeof(*payload_addr));
183
184 scpi_secure_message_receive(&response);
185
Dan Handley9df48042015-03-19 18:58:55 +0000186 scpi_secure_message_end();
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000187
188 return response.status;
Dan Handley9df48042015-03-19 18:58:55 +0000189}