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