1ae8c8068SEtienne Carriere /* SPDX-License-Identifier: BSD-3-Clause */ 2ae8c8068SEtienne Carriere /* 3ae8c8068SEtienne Carriere * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. 4659a1f88SEtienne Carriere * Copyright (c) 2019-2021, Linaro Limited 5ae8c8068SEtienne Carriere */ 6ae8c8068SEtienne Carriere 7ae8c8068SEtienne Carriere #ifndef SCMI_MSG_H 8ae8c8068SEtienne Carriere #define SCMI_MSG_H 9ae8c8068SEtienne Carriere 10ae8c8068SEtienne Carriere #include <compiler.h> 11ae8c8068SEtienne Carriere #include <kernel/panic.h> 12ae8c8068SEtienne Carriere #include <mm/core_memprot.h> 13ae8c8068SEtienne Carriere #include <stdbool.h> 14ae8c8068SEtienne Carriere #include <stddef.h> 15ae8c8068SEtienne Carriere #include <stdint.h> 16ae8c8068SEtienne Carriere 17ae8c8068SEtienne Carriere /* Minimum size expected for SMT based shared memory message buffers */ 18ae8c8068SEtienne Carriere #define SMT_BUF_SLOT_SIZE 128 19ae8c8068SEtienne Carriere 20c22983c9SEtienne Carriere /* Standard values for SCMI voltage domain protocol configuration state */ 21c22983c9SEtienne Carriere #define SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_ON 0x7 22c22983c9SEtienne Carriere #define SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_OFF 0 23c22983c9SEtienne Carriere 24ae8c8068SEtienne Carriere /* A channel abstract a communication path between agent and server */ 25ae8c8068SEtienne Carriere struct scmi_msg_channel; 26ae8c8068SEtienne Carriere 27ae8c8068SEtienne Carriere /* 28ae8c8068SEtienne Carriere * struct scmi_msg_channel - Shared memory buffer for a agent-to-server channel 29ae8c8068SEtienne Carriere * 30ae8c8068SEtienne Carriere * @shm_addr: Address of the shared memory for the SCMI channel 31ae8c8068SEtienne Carriere * @shm_size: Byte size of the shared memory for the SCMI channel 32ae8c8068SEtienne Carriere * @busy: True when channel is busy, flase when channel is free 33ae8c8068SEtienne Carriere * @threaded: True is executed in a threaded context, false otherwise 34064bf8dcSEtienne Carriere * @agent_name: Agent name, SCMI protocol exposes 16 bytes max, or NULL 35ae8c8068SEtienne Carriere */ 36ae8c8068SEtienne Carriere struct scmi_msg_channel { 37ae8c8068SEtienne Carriere struct io_pa_va shm_addr; 38ae8c8068SEtienne Carriere size_t shm_size; 39ae8c8068SEtienne Carriere bool busy; 40ae8c8068SEtienne Carriere bool threaded; 41ae8c8068SEtienne Carriere const char *agent_name; 42ae8c8068SEtienne Carriere }; 43ae8c8068SEtienne Carriere 44a58c4d70SEtienne Carriere /* 45a58c4d70SEtienne Carriere * Initialize SMT memory buffer, called by platform at init for each 46a58c4d70SEtienne Carriere * agent channel using the SMT header format. 47a58c4d70SEtienne Carriere * This function depends on CFG_SCMI_MSG_SMT. 48a58c4d70SEtienne Carriere * 49a58c4d70SEtienne Carriere * @chan: Pointer to the channel shared memory to be initialized 50a58c4d70SEtienne Carriere */ 51a58c4d70SEtienne Carriere void scmi_smt_init_agent_channel(struct scmi_msg_channel *chan); 52a58c4d70SEtienne Carriere 53a58c4d70SEtienne Carriere /* 54064bf8dcSEtienne Carriere * Process SMT formatted message in a fastcall SMC execution context. 55a58c4d70SEtienne Carriere * Called by platform on SMC entry. When returning, output message is 56a58c4d70SEtienne Carriere * available in shared memory for agent to read the response. 57a58c4d70SEtienne Carriere * This function depends on CFG_SCMI_MSG_SMT_FASTCALL_ENTRY. 58a58c4d70SEtienne Carriere * 59659a1f88SEtienne Carriere * @channel_id: SCMI channel ID the SMT belongs to 60a58c4d70SEtienne Carriere */ 61659a1f88SEtienne Carriere void scmi_smt_fastcall_smc_entry(unsigned int channel_id); 62a58c4d70SEtienne Carriere 63a58c4d70SEtienne Carriere /* 64a58c4d70SEtienne Carriere * Process SMT formatted message in a secure interrupt execution context. 65a58c4d70SEtienne Carriere * Called by platform interrupt handler. When returning, output message is 66a58c4d70SEtienne Carriere * available in shared memory for agent to read the response. 67a58c4d70SEtienne Carriere * This function depends on CFG_SCMI_MSG_SMT_INTERRUPT_ENTRY. 68a58c4d70SEtienne Carriere * 69659a1f88SEtienne Carriere * @channel_id: SCMI channel ID the SMT belongs to 70a58c4d70SEtienne Carriere */ 71659a1f88SEtienne Carriere void scmi_smt_interrupt_entry(unsigned int channel_id); 72a58c4d70SEtienne Carriere 73a58c4d70SEtienne Carriere /* 74a58c4d70SEtienne Carriere * Process SMT formatted message in a TEE thread execution context. 75a58c4d70SEtienne Carriere * When returning, output message is available in shared memory for 76a58c4d70SEtienne Carriere * agent to read the response. 77a58c4d70SEtienne Carriere * This function depends on CFG_SCMI_MSG_SMT_THREAD_ENTRY. 78a58c4d70SEtienne Carriere * 79659a1f88SEtienne Carriere * @channel_id: SCMI channel ID the SMT belongs to 80a58c4d70SEtienne Carriere */ 81659a1f88SEtienne Carriere void scmi_smt_threaded_entry(unsigned int channel_id); 82a58c4d70SEtienne Carriere 83ae8c8068SEtienne Carriere /* Platform callback functions */ 84ae8c8068SEtienne Carriere 85ae8c8068SEtienne Carriere /* 86ae8c8068SEtienne Carriere * Return the SCMI channel related to an agent 87659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 88ae8c8068SEtienne Carriere * Return a pointer to channel on success, NULL otherwise 89ae8c8068SEtienne Carriere */ 90659a1f88SEtienne Carriere struct scmi_msg_channel *plat_scmi_get_channel(unsigned int channel_id); 91ae8c8068SEtienne Carriere 92ae8c8068SEtienne Carriere /* 93ae8c8068SEtienne Carriere * Return how many SCMI protocols supported by the platform 94ae8c8068SEtienne Carriere * According to the SCMI specification, this function does not target 95659a1f88SEtienne Carriere * a specific channel ID and shall return all platform known capabilities. 96ae8c8068SEtienne Carriere */ 97ae8c8068SEtienne Carriere size_t plat_scmi_protocol_count(void); 98ae8c8068SEtienne Carriere 99ae8c8068SEtienne Carriere /* 100ae8c8068SEtienne Carriere * Get the count and list of SCMI protocols (but base) supported for an agent 101ae8c8068SEtienne Carriere * 102659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 103ae8c8068SEtienne Carriere * Return a pointer to a null terminated array supported protocol IDs. 104ae8c8068SEtienne Carriere */ 105659a1f88SEtienne Carriere const uint8_t *plat_scmi_protocol_list(unsigned int channel_id); 106ae8c8068SEtienne Carriere 107ae8c8068SEtienne Carriere /* Get the name of the SCMI vendor for the platform */ 108ae8c8068SEtienne Carriere const char *plat_scmi_vendor_name(void); 109ae8c8068SEtienne Carriere 110ae8c8068SEtienne Carriere /* Get the name of the SCMI sub-vendor for the platform */ 111ae8c8068SEtienne Carriere const char *plat_scmi_sub_vendor_name(void); 112ae8c8068SEtienne Carriere 113a7a9e3baSEtienne Carriere /* Handlers for SCMI Clock protocol services */ 114a7a9e3baSEtienne Carriere 115a7a9e3baSEtienne Carriere /* 116a7a9e3baSEtienne Carriere * Return number of clock controllers for an agent 117659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 118a7a9e3baSEtienne Carriere * Return number of clock controllers 119a7a9e3baSEtienne Carriere */ 120659a1f88SEtienne Carriere size_t plat_scmi_clock_count(unsigned int channel_id); 121a7a9e3baSEtienne Carriere 122a7a9e3baSEtienne Carriere /* 123a7a9e3baSEtienne Carriere * Get clock controller string ID (aka name) 124659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 125a7a9e3baSEtienne Carriere * @scmi_id: SCMI clock ID 126a7a9e3baSEtienne Carriere * Return pointer to name or NULL 127a7a9e3baSEtienne Carriere */ 128659a1f88SEtienne Carriere const char *plat_scmi_clock_get_name(unsigned int channel_id, 129a7a9e3baSEtienne Carriere unsigned int scmi_id); 130a7a9e3baSEtienne Carriere 131a7a9e3baSEtienne Carriere /* 132a7a9e3baSEtienne Carriere * Get clock possible rate as an array of frequencies in Hertz. 133a7a9e3baSEtienne Carriere * 134659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 135a7a9e3baSEtienne Carriere * @scmi_id: SCMI clock ID 136d9be1b35SEtienne Carriere * @start_index: Requested start index for the exposed rates array 137*ec8c2914SEtienne Carriere * @rates: If NULL, function returns, else output rates array 138a7a9e3baSEtienne Carriere * @nb_elts: Array size of @rates. 139a7a9e3baSEtienne Carriere * Return an SCMI compliant error code 140a7a9e3baSEtienne Carriere */ 141659a1f88SEtienne Carriere int32_t plat_scmi_clock_rates_array(unsigned int channel_id, 142659a1f88SEtienne Carriere unsigned int scmi_id, size_t start_index, 143659a1f88SEtienne Carriere unsigned long *rates, size_t *nb_elts); 144a7a9e3baSEtienne Carriere 145a7a9e3baSEtienne Carriere /* 146a7a9e3baSEtienne Carriere * Get clock possible rate as range with regular steps in Hertz 147a7a9e3baSEtienne Carriere * 148659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 149a7a9e3baSEtienne Carriere * @scmi_id: SCMI clock ID 150a7a9e3baSEtienne Carriere * @min_max_step: 3 cell array for min, max and step rate data 151a7a9e3baSEtienne Carriere * Return an SCMI compliant error code 152a7a9e3baSEtienne Carriere */ 153659a1f88SEtienne Carriere int32_t plat_scmi_clock_rates_by_step(unsigned int channel_id, 154a7a9e3baSEtienne Carriere unsigned int scmi_id, 155a7a9e3baSEtienne Carriere unsigned long *min_max_step); 156a7a9e3baSEtienne Carriere 157a7a9e3baSEtienne Carriere /* 158a7a9e3baSEtienne Carriere * Get clock rate in Hertz 159659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 160a7a9e3baSEtienne Carriere * @scmi_id: SCMI clock ID 161a7a9e3baSEtienne Carriere * Return clock rate or 0 if not supported 162a7a9e3baSEtienne Carriere */ 163659a1f88SEtienne Carriere unsigned long plat_scmi_clock_get_rate(unsigned int channel_id, 164a7a9e3baSEtienne Carriere unsigned int scmi_id); 165a7a9e3baSEtienne Carriere 166a7a9e3baSEtienne Carriere /* 167a7a9e3baSEtienne Carriere * Set clock rate in Hertz 168659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 169a7a9e3baSEtienne Carriere * @scmi_id: SCMI clock ID 170a7a9e3baSEtienne Carriere * @rate: Target clock frequency in Hertz 171a7a9e3baSEtienne Carriere * Return a compliant SCMI error code 172a7a9e3baSEtienne Carriere */ 173659a1f88SEtienne Carriere int32_t plat_scmi_clock_set_rate(unsigned int channel_id, unsigned int scmi_id, 174a7a9e3baSEtienne Carriere unsigned long rate); 175a7a9e3baSEtienne Carriere 176a7a9e3baSEtienne Carriere /* 177a7a9e3baSEtienne Carriere * Get clock state (enabled or disabled) 178659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 179a7a9e3baSEtienne Carriere * @scmi_id: SCMI clock ID 180a7a9e3baSEtienne Carriere * Return 1 if clock is enabled, 0 if disables, or a negative SCMI error code 181a7a9e3baSEtienne Carriere */ 182659a1f88SEtienne Carriere int32_t plat_scmi_clock_get_state(unsigned int channel_id, 183659a1f88SEtienne Carriere unsigned int scmi_id); 184a7a9e3baSEtienne Carriere 185a7a9e3baSEtienne Carriere /* 186a7a9e3baSEtienne Carriere * Get clock state (enabled or disabled) 187659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 188a7a9e3baSEtienne Carriere * @scmi_id: SCMI clock ID 189a7a9e3baSEtienne Carriere * @enable_not_disable: Enable clock if true, disable clock otherwise 190a7a9e3baSEtienne Carriere * Return a compliant SCMI error code 191a7a9e3baSEtienne Carriere */ 192659a1f88SEtienne Carriere int32_t plat_scmi_clock_set_state(unsigned int channel_id, unsigned int scmi_id, 193a7a9e3baSEtienne Carriere bool enable_not_disable); 19456a1f10eSEtienne Carriere 19556a1f10eSEtienne Carriere /* Handlers for SCMI Reset Domain protocol services */ 19656a1f10eSEtienne Carriere 19756a1f10eSEtienne Carriere /* 19856a1f10eSEtienne Carriere * Return number of reset domains for the agent 199659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 20056a1f10eSEtienne Carriere * Return number of reset domains 20156a1f10eSEtienne Carriere */ 202659a1f88SEtienne Carriere size_t plat_scmi_rd_count(unsigned int channel_id); 20356a1f10eSEtienne Carriere 20456a1f10eSEtienne Carriere /* 20556a1f10eSEtienne Carriere * Get reset domain string ID (aka name) 206659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 20756a1f10eSEtienne Carriere * @scmi_id: SCMI reset domain ID 20856a1f10eSEtienne Carriere * Return pointer to name or NULL 20956a1f10eSEtienne Carriere */ 210659a1f88SEtienne Carriere const char *plat_scmi_rd_get_name(unsigned int channel_id, 211659a1f88SEtienne Carriere unsigned int scmi_id); 21256a1f10eSEtienne Carriere 21356a1f10eSEtienne Carriere /* 21456a1f10eSEtienne Carriere * Perform a reset cycle on a target reset domain 215659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 21656a1f10eSEtienne Carriere * @scmi_id: SCMI reset domain ID 21756a1f10eSEtienne Carriere * @state: Target reset state (see SCMI specification, 0 means context loss) 21856a1f10eSEtienne Carriere * Return a compliant SCMI error code 21956a1f10eSEtienne Carriere */ 220659a1f88SEtienne Carriere int32_t plat_scmi_rd_autonomous(unsigned int channel_id, unsigned int scmi_id, 22156a1f10eSEtienne Carriere unsigned int state); 22256a1f10eSEtienne Carriere 22356a1f10eSEtienne Carriere /* 22456a1f10eSEtienne Carriere * Assert or deassert target reset domain 225659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 22656a1f10eSEtienne Carriere * @scmi_id: SCMI reset domain ID 22756a1f10eSEtienne Carriere * @assert_not_deassert: Assert domain if true, otherwise deassert domain 22856a1f10eSEtienne Carriere * Return a compliant SCMI error code 22956a1f10eSEtienne Carriere */ 230659a1f88SEtienne Carriere int32_t plat_scmi_rd_set_state(unsigned int channel_id, unsigned int scmi_id, 23156a1f10eSEtienne Carriere bool assert_not_deassert); 23256a1f10eSEtienne Carriere 233006d89b8SEtienne Carriere /* Handlers for SCMI Voltage Domain protocol services */ 234006d89b8SEtienne Carriere 235006d89b8SEtienne Carriere /* 236006d89b8SEtienne Carriere * Return number of voltage domain for an agent 237659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 238006d89b8SEtienne Carriere * Return number of voltage domains 239006d89b8SEtienne Carriere */ 240659a1f88SEtienne Carriere size_t plat_scmi_voltd_count(unsigned int channel_id); 241006d89b8SEtienne Carriere 242006d89b8SEtienne Carriere /* 243006d89b8SEtienne Carriere * Get clock controller string ID (aka name) 244659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 245006d89b8SEtienne Carriere * @scmi_id: SCMI voltage domain ID 246006d89b8SEtienne Carriere * Return pointer to name or NULL 247006d89b8SEtienne Carriere */ 248659a1f88SEtienne Carriere const char *plat_scmi_voltd_get_name(unsigned int channel_id, 249006d89b8SEtienne Carriere unsigned int scmi_id); 250006d89b8SEtienne Carriere 251006d89b8SEtienne Carriere /* 252006d89b8SEtienne Carriere * Get voltage domain possible levels as an array of voltages in microvolt. 253006d89b8SEtienne Carriere * 254659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 255006d89b8SEtienne Carriere * @scmi_id: SCMI voltage domain ID 256006d89b8SEtienne Carriere * @start_index: Level index to start from. 257*ec8c2914SEtienne Carriere * @levels: If NULL, function returns, else output rates array 258006d89b8SEtienne Carriere * @nb_elts: Array size of @levels. 259006d89b8SEtienne Carriere * Return an SCMI compliant error code 260006d89b8SEtienne Carriere */ 261659a1f88SEtienne Carriere int32_t plat_scmi_voltd_levels_array(unsigned int channel_id, 262006d89b8SEtienne Carriere unsigned int scmi_id, size_t start_index, 263006d89b8SEtienne Carriere long *levels, size_t *nb_elts); 264006d89b8SEtienne Carriere 265006d89b8SEtienne Carriere /* 266006d89b8SEtienne Carriere * Get voltage domain possible levels as range with regular steps in microvolt 267006d89b8SEtienne Carriere * 268659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 269006d89b8SEtienne Carriere * @scmi_id: SCMI voltage domain ID 270006d89b8SEtienne Carriere * @min_max_step: 3 cell array for min, max and step voltage data 271006d89b8SEtienne Carriere * Return an SCMI compliant error code 272006d89b8SEtienne Carriere */ 273659a1f88SEtienne Carriere int32_t plat_scmi_voltd_levels_by_step(unsigned int channel_id, 274006d89b8SEtienne Carriere unsigned int scmi_id, 275006d89b8SEtienne Carriere long *min_max_step); 276006d89b8SEtienne Carriere 277006d89b8SEtienne Carriere /* 278006d89b8SEtienne Carriere * Get current voltage domain level in microvolt 279659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 280006d89b8SEtienne Carriere * @scmi_id: SCMI voltage domain ID 281006d89b8SEtienne Carriere * Return clock rate or 0 if not supported 282006d89b8SEtienne Carriere */ 283659a1f88SEtienne Carriere long plat_scmi_voltd_get_level(unsigned int channel_id, unsigned int scmi_id); 284006d89b8SEtienne Carriere 285006d89b8SEtienne Carriere /* 286006d89b8SEtienne Carriere * Set voltage domain level voltage domain 287659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 288006d89b8SEtienne Carriere * @scmi_id: SCMI clock ID 289006d89b8SEtienne Carriere * @level: Target voltage domain level in microvolt 290006d89b8SEtienne Carriere * Return a compliant SCMI error code 291006d89b8SEtienne Carriere */ 292659a1f88SEtienne Carriere int32_t plat_scmi_voltd_set_level(unsigned int channel_id, unsigned int scmi_id, 293006d89b8SEtienne Carriere long level); 294006d89b8SEtienne Carriere 295006d89b8SEtienne Carriere /* 296006d89b8SEtienne Carriere * Get voltage domain state configuration (enabled or disabled) 297659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 298006d89b8SEtienne Carriere * @scmi_id: SCMI voltage domain ID 299*ec8c2914SEtienne Carriere * @config: output state configuration value SCMI_VOLTAGE_DOMAIN_CONFIG_* 300006d89b8SEtienne Carriere * Return a compliant SCMI error code 301006d89b8SEtienne Carriere */ 302659a1f88SEtienne Carriere int32_t plat_scmi_voltd_get_config(unsigned int channel_id, 303659a1f88SEtienne Carriere unsigned int scmi_id, uint32_t *config); 304006d89b8SEtienne Carriere 305006d89b8SEtienne Carriere /* 306006d89b8SEtienne Carriere * Get voltage domain state configuration (enabled or disabled) 307659a1f88SEtienne Carriere * @channel_id: SCMI channel ID 308*ec8c2914SEtienne Carriere * @scmi_id: SCMI voltage domain ID 309*ec8c2914SEtienne Carriere * @config: Target state configuration value SCMI_VOLTAGE_DOMAIN_CONFIG_* 310006d89b8SEtienne Carriere * Return a compliant SCMI error code 311006d89b8SEtienne Carriere */ 312659a1f88SEtienne Carriere int32_t plat_scmi_voltd_set_config(unsigned int channel_id, 313659a1f88SEtienne Carriere unsigned int scmi_id, uint32_t config); 314006d89b8SEtienne Carriere 315ae8c8068SEtienne Carriere #endif /* SCMI_MSG_H */ 316