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 61 void scmi_smt_init_agent_channel(struct scmi_msg_channel *channel __unused) 62 { 63 panic(); 64 } 65 66 static inline 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 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 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 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 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 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 */ 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 /* Handlers for SCMI Performance Domain Management protocol services */ 412 413 /* 414 * Return number of performance domains for the channel 415 * @channel_id: SCMI channel ID 416 * Return number of performance domains for the channel 417 */ 418 size_t plat_scmi_perf_count(unsigned int channel_id); 419 420 /* 421 * Return statistics on performance domains for the channel 422 * @channel_id: SCMI channel ID 423 * @stats_len: Output byte size of the statistics buffer or zero 424 * Return pointer to SCMI server statistics buffer for the channel or NULL 425 */ 426 void *plat_scmi_perf_statistics_buf(unsigned int channel_id, size_t *stats_len); 427 428 /* 429 * Get performance domain string ID (aka name) 430 * @channel_id: SCMI channel ID 431 * @domain_id: SCMI performance domain ID 432 * Return pointer to name or NULL 433 */ 434 const char *plat_scmi_perf_domain_name(unsigned int channel_id, 435 unsigned int domain_id); 436 437 /* 438 * Get performance domain sustained frequency 439 * @channel_id: SCMI channel ID 440 * @domain_id: SCMI performance domain ID 441 * @freq: Frequency value in KHz 442 * Return an SCMI compliant error code 443 */ 444 int32_t plat_scmi_perf_sustained_freq(unsigned int channel_id, 445 unsigned int domain_id, 446 unsigned int *freq); 447 448 /* 449 * Get performance domain possible levels as an array of unsigned int 450 * 451 * @channel_id: SCMI channel ID 452 * @domain_id: SCMI performance domain ID 453 * @start_index: Level index to start from 454 * @elt: Array where to store levels or NULL if querying only @nb_elts 455 * @nb_elts: [in] @elt array size, [out] number of levels 456 * 457 * When @elt is NULL, @nb_elt output value gives full number of levels 458 * remaining starting from @start_index. When @elt is not NULL, 459 * @nb_elt output value gives the number of levels stored in @elt. 460 * Return an SCMI compliant error code 461 */ 462 int32_t plat_scmi_perf_levels_array(unsigned int channel_id, 463 unsigned int domain_id, size_t start_index, 464 unsigned int *elt, size_t *nb_elts); 465 466 /* 467 * Get latency is microseconds for transition to target performance level. 468 * A default (weak) implementation outputs a latency value of 1 microsecond. 469 * 470 * @channel_id: SCMI channel ID 471 * @domain_id: SCMI performance domain ID 472 * @level: Target performance level 473 * @latency: Output latency value (microsecond) for the target level 474 * Return a compliant SCMI error code 475 */ 476 int32_t plat_scmi_perf_level_latency(unsigned int channel_id, 477 unsigned int domain_id, 478 unsigned int level, 479 unsigned int *latency); 480 481 /* 482 * Get power cost value related to target performance level. 483 * A default (weak) implementation outputs a power cost of 0. 484 * 485 * @channel_id: SCMI channel ID 486 * @domain_id: SCMI performance domain ID 487 * @level: Target performance level 488 * @power_cost: Output power cost for the performance level 489 * Return a compliant SCMI error code 490 */ 491 int32_t plat_scmi_perf_level_power_cost(unsigned int channel_id, 492 unsigned int domain_id, 493 unsigned int level, 494 unsigned int *power_cost); 495 496 /* 497 * Get current performance level of the domain 498 * @channel_id: SCMI channel ID 499 * @domain_id: SCMI performance domain ID 500 * @level: Output performance level 501 * Return a compliant SCMI error code 502 */ 503 int32_t plat_scmi_perf_level_get(unsigned int channel_id, 504 unsigned int domain_id, unsigned int *level); 505 506 /* 507 * Request change of performance level for the domain 508 * @channel_id: SCMI channel ID 509 * @domain_id: SCMI performance domain ID 510 * @level: Target performance level 511 * Return a compliant SCMI error code 512 */ 513 int32_t plat_scmi_perf_level_set(unsigned int channel_id, 514 unsigned int domain_id, unsigned int level); 515 #endif /* __DRIVERS_SCMI_MSG_H */ 516