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