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