xref: /aosp_15_r20/external/arm-trusted-firmware/drivers/scmi-msg/reset_domain.c (revision 54fd6939e177f8ff529b10183254802c76df6d08)
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