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 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 /* 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 */ 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