1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /*
3 * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
4 * Copyright (c) 2019-2021, Linaro Limited
5 */
6
7 #ifndef SCMI_MSG_H
8 #define SCMI_MSG_H
9
10 #include <compiler.h>
11 #include <kernel/panic.h>
12 #include <mm/core_memprot.h>
13 #include <stdbool.h>
14 #include <stddef.h>
15 #include <stdint.h>
16
17 /* Minimum size expected for SMT based shared memory message buffers */
18 #define SMT_BUF_SLOT_SIZE U(128)
19
20 /* Standard values for SCMI voltage domain protocol configuration state */
21 #define SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_ON U(0x7)
22 #define SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_OFF U(0)
23
24 /* A channel abstract a communication path between agent and server */
25 struct scmi_msg_channel;
26
27 /*
28 * struct scmi_msg_channel - Shared memory buffer for a agent-to-server channel
29 *
30 * @shm_addr: Address of the shared memory for the SCMI channel
31 * @shm_size: Byte size of the shared memory for the SCMI channel
32 * @busy: True when channel is busy, flase when channel is free
33 * @threaded: True is executed in a threaded context, false otherwise
34 */
35 struct scmi_msg_channel {
36 struct io_pa_va shm_addr;
37 size_t shm_size;
38 bool busy;
39 bool threaded;
40 };
41
42 #ifdef CFG_SCMI_MSG_SMT
43 /*
44 * Initialize SMT memory buffer, called by platform at init for each
45 * agent channel using the SMT header format.
46 * This function depends on CFG_SCMI_MSG_SMT.
47 *
48 * @channel: Pointer to the channel shared memory to be initialized
49 */
50 void scmi_smt_init_agent_channel(struct scmi_msg_channel *channel);
51
52 /*
53 * Set SMT shared buffer location
54 *
55 * @channel: SCMI channel reference
56 * @base: virtual address of the shared buffer or NULL to clear the reference
57 */
58 void scmi_smt_set_shared_buffer(struct scmi_msg_channel *channel, void *base);
59 #else
60 static inline
scmi_smt_init_agent_channel(struct scmi_msg_channel * channel __unused)61 void scmi_smt_init_agent_channel(struct scmi_msg_channel *channel __unused)
62 {
63 panic();
64 }
65
66 static inline
scmi_smt_set_shared_buffer(struct scmi_msg_channel * channel __unused,void * base __unused)67 void scmi_smt_set_shared_buffer(struct scmi_msg_channel *channel __unused,
68 void *base __unused)
69 {
70 }
71 #endif /* CFG_SCMI_MSG_SMT */
72
73 #ifdef CFG_SCMI_MSG_SMT_FASTCALL_ENTRY
74 /*
75 * Process SMT formatted message in a fastcall SMC execution context.
76 * Called by platform on SMC entry. When returning, output message is
77 * available in shared memory for agent to read the response.
78 * This function depends on CFG_SCMI_MSG_SMT_FASTCALL_ENTRY.
79 *
80 * @channel_id: SCMI channel ID the SMT belongs to
81 */
82 void scmi_smt_fastcall_smc_entry(unsigned int channel_id);
83 #else
scmi_smt_fastcall_smc_entry(unsigned int channel_id __unused)84 static inline void scmi_smt_fastcall_smc_entry(unsigned int channel_id __unused)
85 {
86 }
87 #endif
88
89 #ifdef CFG_SCMI_MSG_SMT_INTERRUPT_ENTRY
90 /*
91 * Process SMT formatted message in a secure interrupt execution context.
92 * Called by platform interrupt handler. When returning, output message is
93 * available in shared memory for agent to read the response.
94 * This function depends on CFG_SCMI_MSG_SMT_INTERRUPT_ENTRY.
95 *
96 * @channel_id: SCMI channel ID the SMT belongs to
97 */
98 void scmi_smt_interrupt_entry(unsigned int channel_id);
99 #else
scmi_smt_interrupt_entry(unsigned int channel_id __unused)100 static inline void scmi_smt_interrupt_entry(unsigned int channel_id __unused)
101 {
102 }
103 #endif
104
105 #ifdef CFG_SCMI_MSG_SMT_THREAD_ENTRY
106 /*
107 * Process SMT formatted message in a TEE thread execution context.
108 * When returning, output message is available in shared memory for
109 * agent to read the response.
110 * This function depends on CFG_SCMI_MSG_SMT_THREAD_ENTRY.
111 *
112 * @channel_id: SCMI channel ID the SMT belongs to
113 */
114 void scmi_smt_threaded_entry(unsigned int channel_id);
115 #else
scmi_smt_threaded_entry(unsigned int channel_id __unused)116 static inline void scmi_smt_threaded_entry(unsigned int channel_id __unused)
117 {
118 }
119 #endif
120
121 #ifdef CFG_SCMI_MSG_SHM_MSG
122 /*
123 * Process MSG formatted message in a TEE thread execution context.
124 * When returning, output message is available in shared memory for
125 * agent to read the response.
126 * This function depends on CFG_SCMI_MSG_MSG_THREAD_ENTRY.
127 *
128 * @channel_id: SCMI channel ID
129 * @in_buf: Shared buffer storing input SCMI message
130 * @in_size: Byte size of @in_buf, including MSG header and message payload
131 * @out_buf: Shared buffer storing input SCMI message
132 * @out_size: [in] @out_buf max byte size
133 * [out] @out_buf output byte size (MSG header and message payload)
134 */
135 TEE_Result scmi_msg_threaded_entry(unsigned int channel_id,
136 void *in_buf, size_t in_size,
137 void *out_buf, size_t *out_size);
138 #else
scmi_msg_threaded_entry(unsigned int chan_id __unused,void * in_buf __unused,size_t in_size __unused,void * out_buf __unused,size_t * out_size __unused)139 static inline TEE_Result scmi_msg_threaded_entry(unsigned int chan_id __unused,
140 void *in_buf __unused,
141 size_t in_size __unused,
142 void *out_buf __unused,
143 size_t *out_size __unused)
144 {
145 return TEE_ERROR_NOT_SUPPORTED;
146 }
147 #endif
148
149 /* Platform callback functions */
150
151 /*
152 * Return the SCMI channel related to an agent
153 * @channel_id: SCMI channel ID
154 * Return a pointer to channel on success, NULL otherwise
155 */
156 struct scmi_msg_channel *plat_scmi_get_channel(unsigned int channel_id);
157
158 /* Scmi-msg uses the channel ID as handle. Must channel_id is valid */
scmi_smt_channel_handle(unsigned int channel_id)159 static inline unsigned int scmi_smt_channel_handle(unsigned int channel_id)
160 {
161 assert(plat_scmi_get_channel(channel_id));
162
163 return channel_id;
164 }
165
166 /*
167 * Return how many SCMI protocols supported by the platform
168 * According to the SCMI specification, this function does not target
169 * a specific channel ID and shall return all platform known capabilities.
170 */
171 size_t plat_scmi_protocol_count(void);
172
173 /*
174 * Get the count and list of SCMI protocols (but base) supported for an agent
175 *
176 * @channel_id: SCMI channel ID
177 * Return a pointer to a null terminated array supported protocol IDs.
178 */
179 const uint8_t *plat_scmi_protocol_list(unsigned int channel_id);
180
181 /* Get the name of the SCMI vendor for the platform */
182 const char *plat_scmi_vendor_name(void);
183
184 /* Get the name of the SCMI sub-vendor for the platform */
185 const char *plat_scmi_sub_vendor_name(void);
186
187 /* Handlers for SCMI Clock protocol services */
188
189 /*
190 * Return number of clock controllers for an agent
191 * @channel_id: SCMI channel ID
192 * Return number of clock controllers
193 */
194 size_t plat_scmi_clock_count(unsigned int channel_id);
195
196 /*
197 * Get clock controller string ID (aka name)
198 * @channel_id: SCMI channel ID
199 * @scmi_id: SCMI clock ID
200 * Return pointer to name or NULL
201 */
202 const char *plat_scmi_clock_get_name(unsigned int channel_id,
203 unsigned int scmi_id);
204
205 /*
206 * Get clock possible rate as an array of frequencies in Hertz.
207 *
208 * @channel_id: SCMI channel ID
209 * @scmi_id: SCMI clock ID
210 * @start_index: Requested start index for the exposed rates array
211 * @rates: Output rates array or NULL if only querying @nb_elts
212 * @nb_elts: [in] Array size of @rates, [out] Number of rates loaded in @rates
213 * Return an SCMI compliant error code
214 */
215 int32_t plat_scmi_clock_rates_array(unsigned int channel_id,
216 unsigned int scmi_id, size_t start_index,
217 unsigned long *rates, size_t *nb_elts);
218
219 /*
220 * Get clock possible rate as range with regular steps in Hertz
221 *
222 * @channel_id: SCMI channel ID
223 * @scmi_id: SCMI clock ID
224 * @min_max_step: 3 cell array for min, max and step rate data
225 * Return an SCMI compliant error code
226 */
227 int32_t plat_scmi_clock_rates_by_step(unsigned int channel_id,
228 unsigned int scmi_id,
229 unsigned long *min_max_step);
230
231 /*
232 * Get clock rate in Hertz
233 * @channel_id: SCMI channel ID
234 * @scmi_id: SCMI clock ID
235 * Return clock rate or 0 if not supported
236 */
237 unsigned long plat_scmi_clock_get_rate(unsigned int channel_id,
238 unsigned int scmi_id);
239
240 /*
241 * Set clock rate in Hertz
242 * @channel_id: SCMI channel ID
243 * @scmi_id: SCMI clock ID
244 * @rate: Target clock frequency in Hertz
245 * Return a compliant SCMI error code
246 */
247 int32_t plat_scmi_clock_set_rate(unsigned int channel_id, unsigned int scmi_id,
248 unsigned long rate);
249
250 /*
251 * Get clock state (enabled or disabled)
252 * @channel_id: SCMI channel ID
253 * @scmi_id: SCMI clock ID
254 * Return 1 if clock is enabled, 0 if disables, or a negative SCMI error code
255 */
256 int32_t plat_scmi_clock_get_state(unsigned int channel_id,
257 unsigned int scmi_id);
258
259 /*
260 * Get clock state (enabled or disabled)
261 * @channel_id: SCMI channel ID
262 * @scmi_id: SCMI clock ID
263 * @enable_not_disable: Enable clock if true, disable clock otherwise
264 * Return a compliant SCMI error code
265 */
266 int32_t plat_scmi_clock_set_state(unsigned int channel_id, unsigned int scmi_id,
267 bool enable_not_disable);
268
269 /* Handlers for SCMI Reset Domain protocol services */
270
271 /*
272 * Return number of reset domains for the agent
273 * @channel_id: SCMI channel ID
274 * Return number of reset domains
275 */
276 size_t plat_scmi_rd_count(unsigned int channel_id);
277
278 /*
279 * Get reset domain string ID (aka name)
280 * @channel_id: SCMI channel ID
281 * @scmi_id: SCMI reset domain ID
282 * Return pointer to name or NULL
283 */
284 const char *plat_scmi_rd_get_name(unsigned int channel_id,
285 unsigned int scmi_id);
286
287 /*
288 * Perform a reset cycle on a target reset domain
289 * @channel_id: SCMI channel ID
290 * @scmi_id: SCMI reset domain ID
291 * @state: Target reset state (see SCMI specification, 0 means context loss)
292 * Return a compliant SCMI error code
293 */
294 int32_t plat_scmi_rd_autonomous(unsigned int channel_id, unsigned int scmi_id,
295 unsigned int state);
296
297 /*
298 * Assert or deassert target reset domain
299 * @channel_id: SCMI channel ID
300 * @scmi_id: SCMI reset domain ID
301 * @assert_not_deassert: Assert domain if true, otherwise deassert domain
302 * Return a compliant SCMI error code
303 */
304 int32_t plat_scmi_rd_set_state(unsigned int channel_id, unsigned int scmi_id,
305 bool assert_not_deassert);
306
307 /* Handlers for SCMI Voltage Domain protocol services */
308
309 /*
310 * Return number of voltage domain for an agent
311 * @channel_id: SCMI channel ID
312 * Return number of voltage domains
313 */
314 size_t plat_scmi_voltd_count(unsigned int channel_id);
315
316 /*
317 * Get clock controller string ID (aka name)
318 * @channel_id: SCMI channel ID
319 * @scmi_id: SCMI voltage domain ID
320 * Return pointer to name or NULL
321 */
322 const char *plat_scmi_voltd_get_name(unsigned int channel_id,
323 unsigned int scmi_id);
324
325 /*
326 * Get voltage domain possible levels as an array of voltages in microvolt.
327 *
328 * @channel_id: SCMI channel ID
329 * @scmi_id: SCMI voltage domain ID
330 * @start_index: Level index to start from.
331 * @levels: If NULL, function returns, else output rates array
332 * @nb_elts: Array size of @levels.
333 * Return an SCMI compliant error code
334 */
335 int32_t plat_scmi_voltd_levels_array(unsigned int channel_id,
336 unsigned int scmi_id, size_t start_index,
337 long *levels, size_t *nb_elts);
338
339 /*
340 * Get voltage domain possible levels as range with regular steps in microvolt
341 *
342 * @channel_id: SCMI channel ID
343 * @scmi_id: SCMI voltage domain ID
344 * @min_max_step: 3 cell array for min, max and step voltage data
345 * Return an SCMI compliant error code
346 */
347 int32_t plat_scmi_voltd_levels_by_step(unsigned int channel_id,
348 unsigned int scmi_id,
349 long *min_max_step);
350
351 /*
352 * Get current voltage domain level in microvolt
353 * @channel_id: SCMI channel ID
354 * @scmi_id: SCMI voltage domain ID
355 * @level: Out parameter for the current voltage level
356 * Return an SCMI compliant error code
357 */
358 int32_t plat_scmi_voltd_get_level(unsigned int channel_id, unsigned int scmi_id,
359 long *level);
360
361 /*
362 * Set voltage domain level voltage domain
363 * @channel_id: SCMI channel ID
364 * @scmi_id: SCMI clock ID
365 * @level: Target voltage domain level in microvolt
366 * Return a compliant SCMI error code
367 */
368 int32_t plat_scmi_voltd_set_level(unsigned int channel_id, unsigned int scmi_id,
369 long level);
370
371 /*
372 * Get voltage domain state configuration (enabled or disabled)
373 * @channel_id: SCMI channel ID
374 * @scmi_id: SCMI voltage domain ID
375 * @config: output state configuration value SCMI_VOLTAGE_DOMAIN_CONFIG_*
376 * Return a compliant SCMI error code
377 */
378 int32_t plat_scmi_voltd_get_config(unsigned int channel_id,
379 unsigned int scmi_id, uint32_t *config);
380
381 /*
382 * Get voltage domain state configuration (enabled or disabled)
383 * @channel_id: SCMI channel ID
384 * @scmi_id: SCMI voltage domain ID
385 * @config: Target state configuration value SCMI_VOLTAGE_DOMAIN_CONFIG_*
386 * Return a compliant SCMI error code
387 */
388 int32_t plat_scmi_voltd_set_config(unsigned int channel_id,
389 unsigned int scmi_id, uint32_t config);
390
391 #endif /* SCMI_MSG_H */
392