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 __DRIVERS_SCMI_MSG_H
8 #define __DRIVERS_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 struct clk;
150 
151 #ifdef CFG_SCMI_MSG_USE_CLK
152 /*
153  * Expose a clock through SCMI
154  * @clk: Clock to be exposed
155  * @channel_id: SCMI server channel exposing the clock
156  * @scmi_id: SCMI ID of the clock within the channel
157  */
158 TEE_Result scmi_clk_add(struct clk *clk, unsigned int channel_id,
159 			unsigned int scmi_id);
160 #else
scmi_clk_add(struct clk * clk __unused,unsigned int channel_id __unused,unsigned int scmi_id __unused)161 static inline TEE_Result scmi_clk_add(struct clk *clk __unused,
162 				      unsigned int channel_id __unused,
163 				      unsigned int scmi_id __unused)
164 {
165 	return TEE_ERROR_NOT_SUPPORTED;
166 }
167 #endif
168 
169 /* Platform callback functions */
170 
171 /*
172  * Return the SCMI channel related to an agent
173  * @channel_id: SCMI channel ID
174  * Return a pointer to channel on success, NULL otherwise
175  */
176 struct scmi_msg_channel *plat_scmi_get_channel(unsigned int channel_id);
177 
178 /* Scmi-msg uses the channel ID as handle. Must channel_id is valid */
scmi_smt_channel_handle(unsigned int channel_id)179 static inline unsigned int scmi_smt_channel_handle(unsigned int channel_id)
180 {
181 	assert(plat_scmi_get_channel(channel_id));
182 
183 	return channel_id;
184 }
185 
186 /*
187  * Return how many SCMI protocols supported by the platform
188  * According to the SCMI specification, this function does not target
189  * a specific channel ID and shall return all platform known capabilities.
190  */
191 size_t plat_scmi_protocol_count(void);
192 
193 /*
194  * Get the count and list of SCMI protocols (but base) supported for an agent
195  *
196  * @channel_id: SCMI channel ID
197  * Return a pointer to a null terminated array supported protocol IDs.
198  */
199 const uint8_t *plat_scmi_protocol_list(unsigned int channel_id);
200 
201 /* Get the name of the SCMI vendor for the platform */
202 const char *plat_scmi_vendor_name(void);
203 
204 /* Get the name of the SCMI sub-vendor for the platform */
205 const char *plat_scmi_sub_vendor_name(void);
206 
207 /* Handlers for SCMI Clock protocol services */
208 
209 /*
210  * Return number of clock controllers for an agent
211  * @channel_id: SCMI channel ID
212  * Return number of clock controllers
213  */
214 size_t plat_scmi_clock_count(unsigned int channel_id);
215 
216 /*
217  * Get clock controller string ID (aka name)
218  * @channel_id: SCMI channel ID
219  * @scmi_id: SCMI clock ID
220  * Return pointer to name or NULL
221  */
222 const char *plat_scmi_clock_get_name(unsigned int channel_id,
223 				     unsigned int scmi_id);
224 
225 /*
226  * Get clock possible rate as an array of frequencies in Hertz.
227  *
228  * @channel_id: SCMI channel ID
229  * @scmi_id: SCMI clock ID
230  * @start_index: Requested start index for the exposed rates array
231  * @rates: Output rates array or NULL if only querying @nb_elts
232  * @nb_elts: [in] Array size of @rates, [out] Number of rates loaded in @rates
233  * Return an SCMI compliant error code
234  */
235 int32_t plat_scmi_clock_rates_array(unsigned int channel_id,
236 				    unsigned int scmi_id, size_t start_index,
237 				    unsigned long *rates, size_t *nb_elts);
238 
239 /*
240  * Get clock possible rate as range with regular steps in Hertz
241  *
242  * @channel_id: SCMI channel ID
243  * @scmi_id: SCMI clock ID
244  * @min_max_step: 3 cell array for min, max and step rate data
245  * Return an SCMI compliant error code
246  */
247 int32_t plat_scmi_clock_rates_by_step(unsigned int channel_id,
248 				      unsigned int scmi_id,
249 				      unsigned long *min_max_step);
250 
251 /*
252  * Get clock rate in Hertz
253  * @channel_id: SCMI channel ID
254  * @scmi_id: SCMI clock ID
255  * Return clock rate or 0 if not supported
256  */
257 unsigned long plat_scmi_clock_get_rate(unsigned int channel_id,
258 				       unsigned int scmi_id);
259 
260 /*
261  * Set clock rate in Hertz
262  * @channel_id: SCMI channel ID
263  * @scmi_id: SCMI clock ID
264  * @rate: Target clock frequency in Hertz
265  * Return a compliant SCMI error code
266  */
267 int32_t plat_scmi_clock_set_rate(unsigned int channel_id, unsigned int scmi_id,
268 				 unsigned long rate);
269 
270 /*
271  * Get clock state (enabled or disabled)
272  * @channel_id: SCMI channel ID
273  * @scmi_id: SCMI clock ID
274  * Return 1 if clock is enabled, 0 if disables, or a negative SCMI error code
275  */
276 int32_t plat_scmi_clock_get_state(unsigned int channel_id,
277 				  unsigned int scmi_id);
278 
279 /*
280  * Get clock state (enabled or disabled)
281  * @channel_id: SCMI channel ID
282  * @scmi_id: SCMI clock ID
283  * @enable_not_disable: Enable clock if true, disable clock otherwise
284  * Return a compliant SCMI error code
285  */
286 int32_t plat_scmi_clock_set_state(unsigned int channel_id, unsigned int scmi_id,
287 				  bool enable_not_disable);
288 
289 /* Handlers for SCMI Reset Domain protocol services */
290 
291 /*
292  * Return number of reset domains for the agent
293  * @channel_id: SCMI channel ID
294  * Return number of reset domains
295  */
296 size_t plat_scmi_rd_count(unsigned int channel_id);
297 
298 /*
299  * Get reset domain string ID (aka name)
300  * @channel_id: SCMI channel ID
301  * @scmi_id: SCMI reset domain ID
302  * Return pointer to name or NULL
303  */
304 const char *plat_scmi_rd_get_name(unsigned int channel_id,
305 				  unsigned int scmi_id);
306 
307 /*
308  * Perform a reset cycle on a target reset domain
309  * @channel_id: SCMI channel ID
310  * @scmi_id: SCMI reset domain ID
311  * @state: Target reset state (see SCMI specification, 0 means context loss)
312  * Return a compliant SCMI error code
313  */
314 int32_t plat_scmi_rd_autonomous(unsigned int channel_id, unsigned int scmi_id,
315 				unsigned int state);
316 
317 /*
318  * Assert or deassert target reset domain
319  * @channel_id: SCMI channel ID
320  * @scmi_id: SCMI reset domain ID
321  * @assert_not_deassert: Assert domain if true, otherwise deassert domain
322  * Return a compliant SCMI error code
323  */
324 int32_t plat_scmi_rd_set_state(unsigned int channel_id, unsigned int scmi_id,
325 			       bool assert_not_deassert);
326 
327 /* Handlers for SCMI Voltage Domain protocol services */
328 
329 /*
330  * Return number of voltage domain for an agent
331  * @channel_id: SCMI channel ID
332  * Return number of voltage domains
333  */
334 size_t plat_scmi_voltd_count(unsigned int channel_id);
335 
336 /*
337  * Get voltage domain string ID (aka name)
338  * @channel_id: SCMI channel ID
339  * @scmi_id: SCMI voltage domain ID
340  * Return pointer to name or NULL
341  */
342 const char *plat_scmi_voltd_get_name(unsigned int channel_id,
343 				     unsigned int scmi_id);
344 
345 /*
346  * Get voltage domain possible levels as an array of voltages in microvolt.
347  *
348  * @channel_id: SCMI channel ID
349  * @scmi_id: SCMI voltage domain ID
350  * @start_index: Level index to start from.
351  * @levels: If NULL, function returns, else output rates array
352  * @nb_elts: Array size of @levels.
353  * Return an SCMI compliant error code
354  */
355 int32_t plat_scmi_voltd_levels_array(unsigned int channel_id,
356 				     unsigned int scmi_id, size_t start_index,
357 				     long *levels, size_t *nb_elts);
358 
359 /*
360  * Get voltage domain possible levels as range with regular steps in microvolt
361  *
362  * @channel_id: SCMI channel ID
363  * @scmi_id: SCMI voltage domain ID
364  * @min_max_step: 3 cell array for min, max and step voltage data
365  * Return an SCMI compliant error code
366  */
367 int32_t plat_scmi_voltd_levels_by_step(unsigned int channel_id,
368 				       unsigned int scmi_id,
369 				       long *min_max_step);
370 
371 /*
372  * Get current voltage domain level in microvolt
373  * @channel_id: SCMI channel ID
374  * @scmi_id: SCMI voltage domain ID
375  * @level: Out parameter for the current voltage level
376  * Return an SCMI compliant error code
377  */
378 int32_t plat_scmi_voltd_get_level(unsigned int channel_id, unsigned int scmi_id,
379 				  long *level);
380 
381 /*
382  * Set voltage domain level voltage domain
383  * @channel_id: SCMI channel ID
384  * @scmi_id: SCMI voltage domain ID
385  * @level: Target voltage domain level in microvolt
386  * Return a compliant SCMI error code
387  */
388 int32_t plat_scmi_voltd_set_level(unsigned int channel_id, unsigned int scmi_id,
389 				  long level);
390 
391 /*
392  * Get voltage domain state configuration (enabled or disabled)
393  * @channel_id: SCMI channel ID
394  * @scmi_id: SCMI voltage domain ID
395  * @config: output state configuration value SCMI_VOLTAGE_DOMAIN_CONFIG_*
396  * Return a compliant SCMI error code
397  */
398 int32_t plat_scmi_voltd_get_config(unsigned int channel_id,
399 				   unsigned int scmi_id, uint32_t *config);
400 
401 /*
402  * Get voltage domain state configuration (enabled or disabled)
403  * @channel_id: SCMI channel ID
404  * @scmi_id: SCMI voltage domain ID
405  * @config: Target state configuration value SCMI_VOLTAGE_DOMAIN_CONFIG_*
406  * Return a compliant SCMI error code
407  */
408 int32_t plat_scmi_voltd_set_config(unsigned int channel_id,
409 				   unsigned int scmi_id, uint32_t config);
410 
411 #endif /* __DRIVERS_SCMI_MSG_H */
412