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 * @chan: 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 /* Platform callback functions */ 122 123 /* 124 * Return the SCMI channel related to an agent 125 * @channel_id: SCMI channel ID 126 * Return a pointer to channel on success, NULL otherwise 127 */ 128 struct scmi_msg_channel *plat_scmi_get_channel(unsigned int channel_id); 129 130 /* Scmi-msg uses the channel ID as handle. Must channel_id is valid */ 131 static inline unsigned int scmi_smt_channel_handle(unsigned int channel_id) 132 { 133 assert(plat_scmi_get_channel(channel_id)); 134 135 return channel_id; 136 } 137 138 /* 139 * Return how many SCMI protocols supported by the platform 140 * According to the SCMI specification, this function does not target 141 * a specific channel ID and shall return all platform known capabilities. 142 */ 143 size_t plat_scmi_protocol_count(void); 144 145 /* 146 * Get the count and list of SCMI protocols (but base) supported for an agent 147 * 148 * @channel_id: SCMI channel ID 149 * Return a pointer to a null terminated array supported protocol IDs. 150 */ 151 const uint8_t *plat_scmi_protocol_list(unsigned int channel_id); 152 153 /* Get the name of the SCMI vendor for the platform */ 154 const char *plat_scmi_vendor_name(void); 155 156 /* Get the name of the SCMI sub-vendor for the platform */ 157 const char *plat_scmi_sub_vendor_name(void); 158 159 /* Handlers for SCMI Clock protocol services */ 160 161 /* 162 * Return number of clock controllers for an agent 163 * @channel_id: SCMI channel ID 164 * Return number of clock controllers 165 */ 166 size_t plat_scmi_clock_count(unsigned int channel_id); 167 168 /* 169 * Get clock controller string ID (aka name) 170 * @channel_id: SCMI channel ID 171 * @scmi_id: SCMI clock ID 172 * Return pointer to name or NULL 173 */ 174 const char *plat_scmi_clock_get_name(unsigned int channel_id, 175 unsigned int scmi_id); 176 177 /* 178 * Get clock possible rate as an array of frequencies in Hertz. 179 * 180 * @channel_id: SCMI channel ID 181 * @scmi_id: SCMI clock ID 182 * @start_index: Requested start index for the exposed rates array 183 * @rates: If NULL, function returns, else output rates array 184 * @nb_elts: Array size of @rates. 185 * Return an SCMI compliant error code 186 */ 187 int32_t plat_scmi_clock_rates_array(unsigned int channel_id, 188 unsigned int scmi_id, size_t start_index, 189 unsigned long *rates, size_t *nb_elts); 190 191 /* 192 * Get clock possible rate as range with regular steps in Hertz 193 * 194 * @channel_id: SCMI channel ID 195 * @scmi_id: SCMI clock ID 196 * @min_max_step: 3 cell array for min, max and step rate data 197 * Return an SCMI compliant error code 198 */ 199 int32_t plat_scmi_clock_rates_by_step(unsigned int channel_id, 200 unsigned int scmi_id, 201 unsigned long *min_max_step); 202 203 /* 204 * Get clock rate in Hertz 205 * @channel_id: SCMI channel ID 206 * @scmi_id: SCMI clock ID 207 * Return clock rate or 0 if not supported 208 */ 209 unsigned long plat_scmi_clock_get_rate(unsigned int channel_id, 210 unsigned int scmi_id); 211 212 /* 213 * Set clock rate in Hertz 214 * @channel_id: SCMI channel ID 215 * @scmi_id: SCMI clock ID 216 * @rate: Target clock frequency in Hertz 217 * Return a compliant SCMI error code 218 */ 219 int32_t plat_scmi_clock_set_rate(unsigned int channel_id, unsigned int scmi_id, 220 unsigned long rate); 221 222 /* 223 * Get clock state (enabled or disabled) 224 * @channel_id: SCMI channel ID 225 * @scmi_id: SCMI clock ID 226 * Return 1 if clock is enabled, 0 if disables, or a negative SCMI error code 227 */ 228 int32_t plat_scmi_clock_get_state(unsigned int channel_id, 229 unsigned int scmi_id); 230 231 /* 232 * Get clock state (enabled or disabled) 233 * @channel_id: SCMI channel ID 234 * @scmi_id: SCMI clock ID 235 * @enable_not_disable: Enable clock if true, disable clock otherwise 236 * Return a compliant SCMI error code 237 */ 238 int32_t plat_scmi_clock_set_state(unsigned int channel_id, unsigned int scmi_id, 239 bool enable_not_disable); 240 241 /* Handlers for SCMI Reset Domain protocol services */ 242 243 /* 244 * Return number of reset domains for the agent 245 * @channel_id: SCMI channel ID 246 * Return number of reset domains 247 */ 248 size_t plat_scmi_rd_count(unsigned int channel_id); 249 250 /* 251 * Get reset domain string ID (aka name) 252 * @channel_id: SCMI channel ID 253 * @scmi_id: SCMI reset domain ID 254 * Return pointer to name or NULL 255 */ 256 const char *plat_scmi_rd_get_name(unsigned int channel_id, 257 unsigned int scmi_id); 258 259 /* 260 * Perform a reset cycle on a target reset domain 261 * @channel_id: SCMI channel ID 262 * @scmi_id: SCMI reset domain ID 263 * @state: Target reset state (see SCMI specification, 0 means context loss) 264 * Return a compliant SCMI error code 265 */ 266 int32_t plat_scmi_rd_autonomous(unsigned int channel_id, unsigned int scmi_id, 267 unsigned int state); 268 269 /* 270 * Assert or deassert target reset domain 271 * @channel_id: SCMI channel ID 272 * @scmi_id: SCMI reset domain ID 273 * @assert_not_deassert: Assert domain if true, otherwise deassert domain 274 * Return a compliant SCMI error code 275 */ 276 int32_t plat_scmi_rd_set_state(unsigned int channel_id, unsigned int scmi_id, 277 bool assert_not_deassert); 278 279 /* Handlers for SCMI Voltage Domain protocol services */ 280 281 /* 282 * Return number of voltage domain for an agent 283 * @channel_id: SCMI channel ID 284 * Return number of voltage domains 285 */ 286 size_t plat_scmi_voltd_count(unsigned int channel_id); 287 288 /* 289 * Get clock controller string ID (aka name) 290 * @channel_id: SCMI channel ID 291 * @scmi_id: SCMI voltage domain ID 292 * Return pointer to name or NULL 293 */ 294 const char *plat_scmi_voltd_get_name(unsigned int channel_id, 295 unsigned int scmi_id); 296 297 /* 298 * Get voltage domain possible levels as an array of voltages in microvolt. 299 * 300 * @channel_id: SCMI channel ID 301 * @scmi_id: SCMI voltage domain ID 302 * @start_index: Level index to start from. 303 * @levels: If NULL, function returns, else output rates array 304 * @nb_elts: Array size of @levels. 305 * Return an SCMI compliant error code 306 */ 307 int32_t plat_scmi_voltd_levels_array(unsigned int channel_id, 308 unsigned int scmi_id, size_t start_index, 309 long *levels, size_t *nb_elts); 310 311 /* 312 * Get voltage domain possible levels as range with regular steps in microvolt 313 * 314 * @channel_id: SCMI channel ID 315 * @scmi_id: SCMI voltage domain ID 316 * @min_max_step: 3 cell array for min, max and step voltage data 317 * Return an SCMI compliant error code 318 */ 319 int32_t plat_scmi_voltd_levels_by_step(unsigned int channel_id, 320 unsigned int scmi_id, 321 long *min_max_step); 322 323 /* 324 * Get current voltage domain level in microvolt 325 * @channel_id: SCMI channel ID 326 * @scmi_id: SCMI voltage domain ID 327 * Return clock rate or 0 if not supported 328 */ 329 long plat_scmi_voltd_get_level(unsigned int channel_id, unsigned int scmi_id); 330 331 /* 332 * Set voltage domain level voltage domain 333 * @channel_id: SCMI channel ID 334 * @scmi_id: SCMI clock ID 335 * @level: Target voltage domain level in microvolt 336 * Return a compliant SCMI error code 337 */ 338 int32_t plat_scmi_voltd_set_level(unsigned int channel_id, unsigned int scmi_id, 339 long level); 340 341 /* 342 * Get voltage domain state configuration (enabled or disabled) 343 * @channel_id: SCMI channel ID 344 * @scmi_id: SCMI voltage domain ID 345 * @config: output state configuration value SCMI_VOLTAGE_DOMAIN_CONFIG_* 346 * Return a compliant SCMI error code 347 */ 348 int32_t plat_scmi_voltd_get_config(unsigned int channel_id, 349 unsigned int scmi_id, uint32_t *config); 350 351 /* 352 * Get voltage domain state configuration (enabled or disabled) 353 * @channel_id: SCMI channel ID 354 * @scmi_id: SCMI voltage domain ID 355 * @config: Target state configuration value SCMI_VOLTAGE_DOMAIN_CONFIG_* 356 * Return a compliant SCMI error code 357 */ 358 int32_t plat_scmi_voltd_set_config(unsigned int channel_id, 359 unsigned int scmi_id, uint32_t config); 360 361 #endif /* SCMI_MSG_H */ 362