1 // SPDX-License-Identifier: BSD-3-Clause 2 /* 3 * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved. 4 * Copyright (c) 2019-2020, Linaro Limited 5 */ 6 #include <cdefs.h> 7 #include <string.h> 8 9 #include <drivers/scmi-msg.h> 10 #include <drivers/scmi.h> 11 #include <lib/utils.h> 12 #include <lib/utils_def.h> 13 14 #include "common.h" 15 16 static bool message_id_is_supported(unsigned int message_id); 17 18 #pragma weak plat_scmi_rstd_count 19 #pragma weak plat_scmi_rstd_get_name 20 #pragma weak plat_scmi_rstd_autonomous 21 #pragma weak plat_scmi_rstd_set_state 22 23 size_t plat_scmi_rstd_count(unsigned int agent_id __unused) 24 { 25 return 0U; 26 } 27 28 const char *plat_scmi_rstd_get_name(unsigned int agent_id __unused, 29 unsigned int scmi_id __unused) 30 { 31 return NULL; 32 } 33 34 int32_t plat_scmi_rstd_autonomous(unsigned int agent_id __unused, 35 unsigned int scmi_id __unused, 36 unsigned int state __unused) 37 { 38 return SCMI_NOT_SUPPORTED; 39 } 40 41 int32_t plat_scmi_rstd_set_state(unsigned int agent_id __unused, 42 unsigned int scmi_id __unused, 43 bool assert_not_deassert __unused) 44 { 45 return SCMI_NOT_SUPPORTED; 46 } 47 48 static void report_version(struct scmi_msg *msg) 49 { 50 struct scmi_protocol_version_p2a return_values = { 51 .status = SCMI_SUCCESS, 52 .version = SCMI_PROTOCOL_VERSION_RESET_DOMAIN, 53 }; 54 55 if (msg->in_size != 0U) { 56 scmi_status_response(msg, SCMI_PROTOCOL_ERROR); 57 return; 58 } 59 60 scmi_write_response(msg, &return_values, sizeof(return_values)); 61 } 62 63 static void report_attributes(struct scmi_msg *msg) 64 { 65 struct scmi_protocol_attributes_p2a return_values = { 66 .status = SCMI_SUCCESS, 67 .attributes = plat_scmi_rstd_count(msg->agent_id), 68 }; 69 70 if (msg->in_size != 0U) { 71 scmi_status_response(msg, SCMI_PROTOCOL_ERROR); 72 return; 73 } 74 75 scmi_write_response(msg, &return_values, sizeof(return_values)); 76 } 77 78 static void report_message_attributes(struct scmi_msg *msg) 79 { 80 struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in; 81 struct scmi_protocol_message_attributes_p2a return_values = { 82 .status = SCMI_SUCCESS, 83 /* For this protocol, attributes shall be zero */ 84 .attributes = 0U, 85 }; 86 87 if (msg->in_size != sizeof(*in_args)) { 88 scmi_status_response(msg, SCMI_PROTOCOL_ERROR); 89 return; 90 } 91 92 if (!message_id_is_supported(in_args->message_id)) { 93 scmi_status_response(msg, SCMI_NOT_FOUND); 94 return; 95 } 96 97 scmi_write_response(msg, &return_values, sizeof(return_values)); 98 } 99 100 static void reset_domain_attributes(struct scmi_msg *msg) 101 { 102 struct scmi_reset_domain_attributes_a2p *in_args = (void *)msg->in; 103 struct scmi_reset_domain_attributes_p2a return_values; 104 const char *name = NULL; 105 unsigned int domain_id = 0U; 106 107 if (msg->in_size != sizeof(*in_args)) { 108 scmi_status_response(msg, SCMI_PROTOCOL_ERROR); 109 return; 110 } 111 112 domain_id = SPECULATION_SAFE_VALUE(in_args->domain_id); 113 114 if (domain_id >= plat_scmi_rstd_count(msg->agent_id)) { 115 scmi_status_response(msg, SCMI_INVALID_PARAMETERS); 116 return; 117 } 118 119 name = plat_scmi_rstd_get_name(msg->agent_id, domain_id); 120 if (name == NULL) { 121 scmi_status_response(msg, SCMI_NOT_FOUND); 122 return; 123 } 124 125 zeromem(&return_values, sizeof(return_values)); 126 COPY_NAME_IDENTIFIER(return_values.name, name); 127 return_values.status = SCMI_SUCCESS; 128 return_values.flags = 0U; /* Async and Notif are not supported */ 129 return_values.latency = SCMI_RESET_DOMAIN_ATTR_UNK_LAT; 130 131 scmi_write_response(msg, &return_values, sizeof(return_values)); 132 } 133 134 static void reset_request(struct scmi_msg *msg) 135 { 136 struct scmi_reset_domain_request_a2p *in_args = (void *)msg->in; 137 struct scmi_reset_domain_request_p2a out_args = { 138 .status = SCMI_SUCCESS, 139 }; 140 unsigned int domain_id = 0U; 141 142 if (msg->in_size != sizeof(*in_args)) { 143 scmi_status_response(msg, SCMI_PROTOCOL_ERROR); 144 return; 145 } 146 147 domain_id = SPECULATION_SAFE_VALUE(in_args->domain_id); 148 149 if (domain_id >= plat_scmi_rstd_count(msg->agent_id)) { 150 scmi_status_response(msg, SCMI_NOT_FOUND); 151 return; 152 } 153 154 if ((in_args->flags & SCMI_RESET_DOMAIN_AUTO) != 0U) { 155 out_args.status = plat_scmi_rstd_autonomous(msg->agent_id, 156 domain_id, 157 in_args->reset_state); 158 } else if ((in_args->flags & SCMI_RESET_DOMAIN_EXPLICIT) != 0U) { 159 out_args.status = plat_scmi_rstd_set_state(msg->agent_id, 160 domain_id, true); 161 } else { 162 out_args.status = plat_scmi_rstd_set_state(msg->agent_id, 163 domain_id, false); 164 } 165 166 if (out_args.status != SCMI_SUCCESS) { 167 scmi_status_response(msg, out_args.status); 168 } else { 169 scmi_write_response(msg, &out_args, sizeof(out_args)); 170 } 171 } 172 173 static const scmi_msg_handler_t scmi_rstd_handler_table[] = { 174 [SCMI_PROTOCOL_VERSION] = report_version, 175 [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes, 176 [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes, 177 [SCMI_RESET_DOMAIN_ATTRIBUTES] = reset_domain_attributes, 178 [SCMI_RESET_DOMAIN_REQUEST] = reset_request, 179 }; 180 181 static bool message_id_is_supported(unsigned int message_id) 182 { 183 return (message_id < ARRAY_SIZE(scmi_rstd_handler_table)) && 184 (scmi_rstd_handler_table[message_id] != NULL); 185 } 186 187 scmi_msg_handler_t scmi_msg_get_rstd_handler(struct scmi_msg *msg) 188 { 189 unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id); 190 191 if (message_id >= ARRAY_SIZE(scmi_rstd_handler_table)) { 192 VERBOSE("Reset domain handle not found %u\n", msg->message_id); 193 return NULL; 194 } 195 196 return scmi_rstd_handler_table[message_id]; 197 } 198