1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * Description:
8  *      SCMI performance domain management protocol support.
9  */
10 
11 #ifndef INTERNAL_SCMI_PERF_H
12 #define INTERNAL_SCMI_PERF_H
13 
14 #ifdef BUILD_HAS_MOD_TRANSPORT
15 #    include <mod_transport.h>
16 #endif
17 
18 #include <internal/scmi.h>
19 
20 #include <mod_scmi_perf.h>
21 
22 #include <fwk_event.h>
23 #include <fwk_id.h>
24 
25 #include <stdbool.h>
26 #include <stdint.h>
27 
28 #define SCMI_PROTOCOL_VERSION_PERF UINT32_C(0x20000)
29 
30 #define SCMI_PERF_SUPPORTS_STATS_SHARED_MEM_REGION  0
31 #define SCMI_PERF_STATS_SHARED_MEM_REGION_ADDR_LOW  0
32 #define SCMI_PERF_STATS_SHARED_MEM_REGION_ADDR_HIGH 0
33 #define SCMI_PERF_STATS_SHARED_MEM_REGION_LENGTH    0
34 
35 enum scmi_perf_notification_id {
36     SCMI_PERF_LIMITS_CHANGED = 0x000,
37     SCMI_PERF_LEVEL_CHANGED = 0x001,
38 };
39 
40 /* Event indices */
41 enum scmi_perf_event_idx {
42     SCMI_PERF_EVENT_IDX_LEVEL_GET_REQUEST,
43 #ifdef BUILD_HAS_SCMI_PERF_FAST_CHANNELS
44     SCMI_PERF_EVENT_IDX_FAST_CHANNELS_PROCESS,
45 #endif
46     SCMI_PERF_EVENT_IDX_COUNT,
47 };
48 
49 struct perf_operations {
50     /*
51      * Service identifier currently requesting operation.
52      * A 'none' value means that there is no pending request.
53      */
54     fwk_id_t service_id;
55 };
56 
57 struct perf_opp_table {
58     /* Pointer to DVFS OPP table */
59     struct mod_dvfs_opp *opps;
60 
61     /* Number of OPPs */
62     size_t opp_count;
63 
64     /* The DVFS identifier for this OPP table */
65     fwk_id_t dvfs_id;
66 };
67 
68 #ifdef BUILD_HAS_SCMI_PERF_FAST_CHANNELS
69 /* fast channel context */
70 struct fast_channel_ctx {
71     /* The fast channel address */
72     struct mod_transport_fast_channel_addr fch_address;
73 
74     /* Transport Fast Channels API */
75     const struct mod_transport_fast_channels_api *transport_fch_api;
76 };
77 
78 #endif
79 
80 /*!
81  * \brief Domain context.
82  */
83 struct scmi_perf_domain_ctx {
84     /* Current limits */
85     struct mod_scmi_perf_level_limits level_limits;
86 
87     /* Current level */
88     uint32_t curr_level;
89 
90     /* Tables of OPPs */
91     struct perf_opp_table *opp_table;
92 
93 #ifdef BUILD_HAS_SCMI_PERF_FAST_CHANNELS
94 
95     /* Table of fast channel context */
96     struct fast_channel_ctx fch_ctx[MOD_SCMI_PERF_FAST_CHANNEL_COUNT];
97 
98 #endif
99 };
100 
101 struct mod_scmi_perf_ctx {
102     /* SCMI Performance Module Configuration */
103     const struct mod_scmi_perf_config *config;
104 
105     /* Number of performance domains */
106     uint32_t domain_count;
107 
108     /* SCMI module API */
109     const struct mod_scmi_from_protocol_api *scmi_api;
110 
111     /* DVFS module API */
112     const struct mod_dvfs_domain_api *dvfs_api;
113 
114 #ifdef BUILD_HAS_MOD_PERF_CONTROLLER
115     /* Performance controller module API */
116     const struct mod_perf_controller_perf_api *perf_controller_api;
117 #endif
118 
119     struct scmi_perf_domain_ctx *domain_ctx_table;
120 
121     struct perf_opp_table *opp_table;
122 
123     unsigned int dvfs_doms_count;
124 };
125 
126 /*
127  * PROTOCOL_ATTRIBUTES
128  */
129 
130 #define SCMI_PERF_PROTOCOL_ATTRIBUTES_POWER_MW_POS     16
131 #define SCMI_PERF_PROTOCOL_ATTRIBUTES_NUM_DOMAINS_POS   0
132 
133 #define SCMI_PERF_PROTOCOL_ATTRIBUTES_POWER_MW_MASK \
134     (UINT32_C(0x1) << SCMI_PERF_PROTOCOL_ATTRIBUTES_POWER_MW_POS)
135 #define SCMI_PERF_PROTOCOL_ATTRIBUTES_NUM_DOMAINS_MASK   \
136     (UINT32_C(0xFFFF) << SCMI_PERF_PROTOCOL_ATTRIBUTES_NUM_DOMAINS_POS)
137 
138 #define SCMI_PERF_PROTOCOL_ATTRIBUTES(POWER_MW, NUM_DOMAINS) \
139     ( \
140         (((POWER_MW) << SCMI_PERF_PROTOCOL_ATTRIBUTES_POWER_MW_POS) & \
141             SCMI_PERF_PROTOCOL_ATTRIBUTES_POWER_MW_MASK) | \
142         (((NUM_DOMAINS) << SCMI_PERF_PROTOCOL_ATTRIBUTES_NUM_DOMAINS_POS) & \
143             SCMI_PERF_PROTOCOL_ATTRIBUTES_NUM_DOMAINS_MASK) \
144     )
145 
146 struct scmi_perf_protocol_attributes_p2a {
147     int32_t status;
148     uint32_t attributes;
149     uint32_t statistics_address_low;
150     uint32_t statistics_address_high;
151     uint32_t statistics_len;
152 };
153 
154 /*
155  * PERFORMANCE_DOMAIN_ATTRIBUTES
156  */
157 
158 #define SCMI_PERF_DOMAIN_ATTRIBUTES_CAN_SET_LIMITS_POS 31U
159 #define SCMI_PERF_DOMAIN_ATTRIBUTES_CAN_SET_LEVEL_POS  30U
160 #define SCMI_PERF_DOMAIN_ATTRIBUTES_LIMITS_NOTIFY_POS  29U
161 #define SCMI_PERF_DOMAIN_ATTRIBUTES_LEVEL_NOTIFY_POS   28U
162 #define SCMI_PERF_DOMAIN_ATTRIBUTES_FAST_CHANNEL_POS   27U
163 
164 #define SCMI_PERF_DOMAIN_ATTRIBUTES_CAN_SET_LIMITS_MASK \
165     (UINT32_C(0x1) << SCMI_PERF_DOMAIN_ATTRIBUTES_CAN_SET_LIMITS_POS)
166 #define SCMI_PERF_DOMAIN_ATTRIBUTES_CAN_SET_LEVEL_MASK \
167     (UINT32_C(0x1) << SCMI_PERF_DOMAIN_ATTRIBUTES_CAN_SET_LEVEL_POS)
168 
169 #define SCMI_PERF_DOMAIN_ATTRIBUTES_LIMITS_NOTIFY_MASK \
170     (UINT32_C(0x1) << SCMI_PERF_DOMAIN_ATTRIBUTES_LIMITS_NOTIFY_POS)
171 #define SCMI_PERF_DOMAIN_ATTRIBUTES_LEVEL_NOTIFY_MASK \
172     (UINT32_C(0x1) << SCMI_PERF_DOMAIN_ATTRIBUTES_LEVEL_NOTIFY_POS)
173 
174 #define SCMI_PERF_FC_MIN_RATE_LIMIT 4000U
175 
176 #define SCMI_PERF_DOMAIN_ATTRIBUTES_FAST_CHANNEL_MASK \
177     (UINT32_C(0x1) << SCMI_PERF_DOMAIN_ATTRIBUTES_FAST_CHANNEL_POS)
178 
179 #define SCMI_PERF_DOMAIN_ATTRIBUTES_FAST_CHANNEL_MASK \
180     (UINT32_C(0x1) << SCMI_PERF_DOMAIN_ATTRIBUTES_FAST_CHANNEL_POS)
181 
182 #define SCMI_PERF_DOMAIN_ATTRIBUTES(LEVEL_NOTIFY, LIMITS_NOTIFY, \
183                                     CAN_SET_LEVEL, CAN_SET_LIMITS, \
184                                     FAST_CHANNEL) \
185     ( \
186         (((LEVEL_NOTIFY) << \
187             SCMI_PERF_DOMAIN_ATTRIBUTES_LEVEL_NOTIFY_POS) & \
188             SCMI_PERF_DOMAIN_ATTRIBUTES_LEVEL_NOTIFY_MASK) | \
189         (((LIMITS_NOTIFY) << \
190             SCMI_PERF_DOMAIN_ATTRIBUTES_LIMITS_NOTIFY_POS) & \
191             SCMI_PERF_DOMAIN_ATTRIBUTES_LIMITS_NOTIFY_MASK) | \
192         (((CAN_SET_LEVEL) << \
193             SCMI_PERF_DOMAIN_ATTRIBUTES_CAN_SET_LEVEL_POS) & \
194             SCMI_PERF_DOMAIN_ATTRIBUTES_CAN_SET_LEVEL_MASK) | \
195         (((CAN_SET_LIMITS) << \
196             SCMI_PERF_DOMAIN_ATTRIBUTES_CAN_SET_LIMITS_POS) & \
197             SCMI_PERF_DOMAIN_ATTRIBUTES_CAN_SET_LIMITS_MASK) | \
198         (((FAST_CHANNEL) << \
199             SCMI_PERF_DOMAIN_ATTRIBUTES_FAST_CHANNEL_POS) & \
200             SCMI_PERF_DOMAIN_ATTRIBUTES_FAST_CHANNEL_MASK) \
201     )
202 
203 struct scmi_perf_domain_attributes_a2p {
204     uint32_t domain_id;
205 };
206 
207 #define SCMI_PERF_DOMAIN_RATE_LIMIT_POS  0
208 #define SCMI_PERF_DOMAIN_RATE_LIMIT_MASK \
209     (UINT32_C(0xFFFFF) << SCMI_PERF_DOMAIN_RATE_LIMIT_POS)
210 
211 struct scmi_perf_domain_attributes_p2a {
212     int32_t status;
213     uint32_t attributes;
214     uint32_t rate_limit;
215     uint32_t sustained_freq;
216     uint32_t sustained_perf_level;
217     uint8_t name[16];
218 };
219 
220 /*
221  * PERFORMANCE_DESCRIBE_LEVELS
222  */
223 
224 #define SCMI_PERF_LEVELS_MAX(MAILBOX_SIZE) \
225     ((sizeof(struct scmi_perf_describe_levels_p2a) < MAILBOX_SIZE)  ? \
226      ((MAILBOX_SIZE - sizeof(struct scmi_perf_describe_levels_p2a))   \
227         / sizeof(struct scmi_perf_level)) : 0)
228 
229 #define SCMI_PERF_LEVEL_ATTRIBUTES_POS  0
230 #define SCMI_PERF_LEVEL_ATTRIBUTES_MASK \
231     (UINT32_C(0xFFFF) << SCMI_PERF_LEVEL_ATTRIBUTES_POS)
232 
233 #define SCMI_PERF_LEVEL_ATTRIBUTES(LATENCY) \
234     (((LATENCY) << SCMI_PERF_LEVEL_ATTRIBUTES_POS) & \
235         SCMI_PERF_LEVEL_ATTRIBUTES_MASK)
236 
237 struct scmi_perf_level {
238     uint32_t performance_level;
239     uint32_t power_cost;
240     uint32_t attributes;
241 };
242 
243 struct scmi_perf_describe_levels_a2p {
244     uint32_t domain_id;
245     uint32_t level_index;
246 };
247 
248 #define SCMI_PERF_NUM_LEVELS_REMAINING_LEVELS_POS  16
249 #define SCMI_PERF_NUM_LEVELS_NUM_LEVELS_POS        0
250 
251 #define SCMI_PERF_NUM_LEVELS_REMAINING_LEVELS_MASK \
252     (UINT32_C(0xFFFF) << SCMI_PERF_NUM_LEVELS_REMAINING_LEVELS_POS)
253 #define SCMI_PERF_NUM_LEVELS_NUM_LEVELS_MASK \
254     (UINT32_C(0xFFF) << SCMI_PERF_NUM_LEVELS_NUM_LEVELS_POS)
255 
256 #define SCMI_PERF_NUM_LEVELS(NUM_LEVELS, REMAINING_LEVELS) \
257     ((((NUM_LEVELS) << SCMI_PERF_NUM_LEVELS_NUM_LEVELS_POS) & \
258         SCMI_PERF_NUM_LEVELS_NUM_LEVELS_MASK) | \
259      (((REMAINING_LEVELS) << SCMI_PERF_NUM_LEVELS_REMAINING_LEVELS_POS) & \
260         SCMI_PERF_NUM_LEVELS_REMAINING_LEVELS_MASK))
261 
262 struct scmi_perf_describe_levels_p2a {
263     int32_t status;
264     uint32_t num_levels;
265 
266     struct scmi_perf_level perf_levels[];
267 };
268 
269 /*
270  * PERFORMANCE_LIMITS_SET
271  */
272 
273 struct scmi_perf_limits_set_a2p {
274     uint32_t domain_id;
275     uint32_t range_max;
276     uint32_t range_min;
277 };
278 
279 struct scmi_perf_limits_set_p2a {
280     int32_t status;
281 };
282 
283 /*
284  * PERFORMANCE_LIMITS_GET
285  */
286 
287 struct scmi_perf_limits_get_a2p {
288     uint32_t domain_id;
289 };
290 
291 struct scmi_perf_limits_get_p2a {
292     int32_t status;
293     uint32_t range_max;
294     uint32_t range_min;
295 };
296 
297 /*
298  * PERFORMANCE_LEVEL_SET
299  */
300 
301 struct scmi_perf_level_set_a2p {
302     uint32_t domain_id;
303     uint32_t performance_level;
304 };
305 
306 struct scmi_perf_level_set_p2a {
307     int32_t status;
308 };
309 
310 /*
311  * PERFORMANCE_LEVEL_GET
312  */
313 
314 struct scmi_perf_level_get_a2p {
315     uint32_t domain_id;
316 };
317 
318 struct scmi_perf_level_get_p2a {
319     int32_t status;
320     uint32_t performance_level;
321 };
322 
323 /*
324  * PERFORMANCE_NOTIFY_LIMITS
325  */
326 
327 #define SCMI_PERF_NOTIFY_LIMITS_NOTIFY_ENABLE_MASK UINT32_C(0x1)
328 
329 struct scmi_perf_notify_limits_a2p {
330     uint32_t domain_id;
331     uint32_t notify_enable;
332 };
333 
334 struct scmi_perf_notify_limits_p2a {
335     int32_t status;
336 };
337 
338 /*
339  * PERFORMANCE_NOTIFY_LEVEL
340  */
341 
342 #define SCMI_PERF_NOTIFY_LEVEL_NOTIFY_ENABLE_MASK UINT32_C(0x1)
343 
344 struct scmi_perf_notify_level_a2p {
345     uint32_t domain_id;
346     uint32_t notify_enable;
347 };
348 
349 struct scmi_perf_notify_level_p2a {
350     int32_t status;
351 };
352 
353 /*
354  * PERFORMANCE_LEVEL_CHANGED
355  */
356 struct scmi_perf_level_changed {
357     uint32_t agent_id;
358     uint32_t domain_id;
359     uint32_t performance_level;
360 };
361 
362 /*
363  * PERFORMANCE_LIMITS_CHANGED
364  */
365 struct scmi_perf_limits_changed {
366     uint32_t agent_id;
367     uint32_t domain_id;
368     uint32_t range_max;
369     uint32_t range_min;
370 };
371 
372 /*
373  * PERFORMANCE_DESCRIBE_FASTCHANNEL
374  */
375 
376 struct scmi_perf_describe_fc_a2p {
377     uint32_t domain_id;
378     uint32_t message_id;
379 };
380 
381 struct scmi_perf_describe_fc_p2a {
382     int32_t status;
383     uint32_t attributes;
384     uint32_t rate_limit;
385     uint32_t chan_addr_low;
386     uint32_t chan_addr_high;
387     uint32_t chan_size;
388     uint32_t doorbell_addr_low;
389     uint32_t doorbell_addr_high;
390     uint32_t doorbell_set_mask_low;
391     uint32_t doorbell_set_mask_high;
392     uint32_t doorbell_preserve_mask_low;
393     uint32_t doorbell_preserve_mask_high;
394 };
395 
396 fwk_id_t get_dependency_id(unsigned int el_idx);
397 
398 /*
399  * Interface to SCMI Perf FastChannels stub
400  */
401 struct mod_scmi_perf_private_api_perf_stub {
402     int (*perf_set_level)(
403         fwk_id_t domain_id,
404         unsigned int agent_id,
405         uint32_t perf_level);
406 
407     int (*perf_set_limits)(
408         fwk_id_t domain_id,
409         unsigned int agent_id,
410         const struct mod_scmi_perf_level_limits *limits);
411 
412     int (*find_opp_for_level)(
413         struct scmi_perf_domain_ctx *domain_ctx,
414         uint32_t *level,
415         bool use_nearest);
416 
417     void (*notify_limits_updated)(
418         fwk_id_t domain_id,
419         uint32_t range_min,
420         uint32_t range_max);
421 };
422 
423 void perf_fch_set_fch_get_level(uint32_t domain_idx, uint32_t level);
424 
425 bool perf_fch_prot_msg_attributes_has_fastchannels(
426     const struct scmi_protocol_message_attributes_a2p *parameters);
427 
428 bool perf_fch_domain_has_fastchannels(uint32_t domain_idx);
429 
430 int perf_fch_describe_fast_channels(
431     fwk_id_t service_id,
432     const uint32_t *payload);
433 
434 int perf_fch_init(
435     fwk_id_t module_id,
436     unsigned int element_count,
437     const void *data,
438     struct mod_scmi_perf_ctx *mod_ctx,
439     struct mod_scmi_perf_private_api_perf_stub *api);
440 
441 int perf_fch_bind(fwk_id_t id, unsigned int round);
442 
443 int perf_fch_start(fwk_id_t id);
444 
445 int perf_fch_process_event(const struct fwk_event *event);
446 
447 /*
448  * Interface to SCMI Perf Protocol stub
449  */
450 int perf_prot_ops_init(
451     fwk_id_t module_id,
452     unsigned int element_count,
453     const void *data,
454     struct mod_scmi_perf_ctx *mod_ctx,
455     struct mod_scmi_perf_private_api_perf_stub *api);
456 
457 int perf_prot_ops_bind(fwk_id_t id, unsigned int round);
458 
459 int perf_prot_ops_start(fwk_id_t id);
460 
461 void perf_prot_ops_process_bind_request(
462     fwk_id_t source_id,
463     fwk_id_t target_id,
464     fwk_id_t api_id,
465     const void **api);
466 
467 int perf_prot_ops_process_events(
468     const struct fwk_event *event,
469     struct fwk_event *resp_event);
470 
471 void perf_prot_ops_update_stats(fwk_id_t domain_id, uint32_t level);
472 
473 void perf_prot_ops_notify_limits(
474     unsigned int domain_idx,
475     uint32_t range_min,
476     uint32_t range_max);
477 
478 void perf_prot_ops_notify_level(
479     unsigned int domain_idx,
480     uint32_t level,
481     uint32_t cookie);
482 
483 #endif /* INTERNAL_SCMI_PERF_H */
484