1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2019-2021, Linaro Limited 4 * Copyright (c) 2019-2021, STMicroelectronics 5 */ 6 #include <compiler.h> 7 #include <config.h> 8 #include <drivers/scmi-msg.h> 9 #include <kernel/pseudo_ta.h> 10 #include <pta_scmi_client.h> 11 #include <stdint.h> 12 #include <string.h> 13 14 static TEE_Result cmd_capabilities(uint32_t ptypes, 15 TEE_Param param[TEE_NUM_PARAMS]) 16 { 17 const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, 18 TEE_PARAM_TYPE_NONE, 19 TEE_PARAM_TYPE_NONE, 20 TEE_PARAM_TYPE_NONE); 21 uint32_t caps = 0; 22 23 if (ptypes != exp_ptypes) 24 return TEE_ERROR_BAD_PARAMETERS; 25 26 if (IS_ENABLED(CFG_SCMI_MSG_SMT)) 27 caps |= PTA_SCMI_CAPS_SMT_HEADER; 28 29 param[0].value.a = caps; 30 param[0].value.b = 0; 31 32 return TEE_SUCCESS; 33 } 34 35 static TEE_Result cmd_process_smt_channel(uint32_t ptypes, 36 TEE_Param params[TEE_NUM_PARAMS]) 37 { 38 const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 39 TEE_PARAM_TYPE_NONE, 40 TEE_PARAM_TYPE_NONE, 41 TEE_PARAM_TYPE_NONE); 42 unsigned int channel_id = params[0].value.a; 43 44 if (ptypes != exp_ptypes) 45 return TEE_ERROR_BAD_PARAMETERS; 46 47 if (IS_ENABLED(CFG_SCMI_MSG_SMT)) { 48 struct scmi_msg_channel *channel = NULL; 49 50 channel = plat_scmi_get_channel(channel_id); 51 if (!channel) 52 return TEE_ERROR_BAD_PARAMETERS; 53 54 scmi_smt_threaded_entry(channel_id); 55 56 return TEE_SUCCESS; 57 } 58 59 return TEE_ERROR_NOT_SUPPORTED; 60 } 61 62 static TEE_Result cmd_process_smt_message(uint32_t ptypes, 63 TEE_Param params[TEE_NUM_PARAMS]) 64 { 65 const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 66 TEE_PARAM_TYPE_MEMREF_INOUT, 67 TEE_PARAM_TYPE_NONE, 68 TEE_PARAM_TYPE_NONE); 69 unsigned int channel_id = params[0].value.a; 70 TEE_Param *param1 = params + 1; 71 72 if (ptypes != exp_ptypes) 73 return TEE_ERROR_BAD_PARAMETERS; 74 75 if (IS_ENABLED(CFG_SCMI_MSG_SMT)) { 76 struct scmi_msg_channel *channel = NULL; 77 78 if (param1->memref.size < SMT_BUF_SLOT_SIZE) 79 return TEE_ERROR_BAD_PARAMETERS; 80 81 channel = plat_scmi_get_channel(channel_id); 82 if (!channel) 83 return TEE_ERROR_BAD_PARAMETERS; 84 85 /* 86 * Caller provides the buffer, we bind channel to that buffer. 87 * Once message is processed, unbind the buffer since it is 88 * valid only for the current invocation. 89 */ 90 scmi_smt_set_shared_buffer(channel, param1->memref.buffer); 91 scmi_smt_threaded_entry(channel_id); 92 scmi_smt_set_shared_buffer(channel, NULL); 93 94 return TEE_SUCCESS; 95 } 96 97 return TEE_ERROR_NOT_SUPPORTED; 98 } 99 100 static TEE_Result cmd_get_channel_handle(uint32_t ptypes, 101 TEE_Param params[TEE_NUM_PARAMS]) 102 { 103 const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT, 104 TEE_PARAM_TYPE_NONE, 105 TEE_PARAM_TYPE_NONE, 106 TEE_PARAM_TYPE_NONE); 107 unsigned int channel_id = params[0].value.a; 108 unsigned int caps = params[0].value.b; 109 110 if (ptypes != exp_ptypes) 111 return TEE_ERROR_BAD_PARAMETERS; 112 113 if (IS_ENABLED(CFG_SCMI_MSG_DRIVERS)) { 114 struct scmi_msg_channel *channel = NULL; 115 116 if (!IS_ENABLED(CFG_SCMI_MSG_SMT) && 117 caps & PTA_SCMI_CAPS_SMT_HEADER) 118 return TEE_ERROR_NOT_SUPPORTED; 119 120 channel = plat_scmi_get_channel(channel_id); 121 if (!channel) 122 return TEE_ERROR_BAD_PARAMETERS; 123 124 channel->threaded = true; 125 params[0].value.a = scmi_smt_channel_handle(channel_id); 126 127 return TEE_SUCCESS; 128 } 129 130 return TEE_ERROR_NOT_SUPPORTED; 131 } 132 133 static TEE_Result pta_scmi_open_session(uint32_t ptypes __unused, 134 TEE_Param par[TEE_NUM_PARAMS] __unused, 135 void **session __unused) 136 { 137 struct ts_session *ts = ts_get_current_session(); 138 struct tee_ta_session *ta_session = to_ta_session(ts); 139 140 /* Only REE kernel is allowed to access SCMI resources */ 141 if (ta_session->clnt_id.login != TEE_LOGIN_REE_KERNEL) { 142 DMSG("Expecting TEE_LOGIN_REE_KERNEL"); 143 return TEE_ERROR_ACCESS_DENIED; 144 } 145 146 if (IS_ENABLED(CFG_SCMI_MSG_SMT)) 147 return TEE_SUCCESS; 148 149 return TEE_ERROR_NOT_SUPPORTED; 150 } 151 152 static TEE_Result pta_scmi_invoke_command(void *session __unused, uint32_t cmd, 153 uint32_t ptypes, 154 TEE_Param params[TEE_NUM_PARAMS]) 155 { 156 FMSG("SCMI command %#"PRIx32" ptypes %#"PRIx32, cmd, ptypes); 157 158 switch (cmd) { 159 case PTA_SCMI_CMD_CAPABILITIES: 160 return cmd_capabilities(ptypes, params); 161 case PTA_SCMI_CMD_PROCESS_SMT_CHANNEL: 162 return cmd_process_smt_channel(ptypes, params); 163 case PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE: 164 return cmd_process_smt_message(ptypes, params); 165 case PTA_SCMI_CMD_GET_CHANNEL_HANDLE: 166 return cmd_get_channel_handle(ptypes, params); 167 default: 168 return TEE_ERROR_NOT_SUPPORTED; 169 } 170 } 171 172 pseudo_ta_register(.uuid = PTA_SCMI_UUID, .name = PTA_SCMI_NAME, 173 .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT | 174 TA_FLAG_DEVICE_ENUM, 175 .open_session_entry_point = pta_scmi_open_session, 176 .invoke_command_entry_point = pta_scmi_invoke_command); 177