1 /* 2 * Copyright 2023-2025 NXP 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 9 #include <arch_helpers.h> 10 #include <common/debug.h> 11 #include <drivers/arm/css/scmi.h> 12 #include "scmi_imx9.h" 13 #include <scmi_private.h> 14 15 /* 16 * API to set the SCMI AP core reset address and attributes 17 */ 18 int scmi_core_set_reset_addr(void *p, uint64_t reset_addr, uint32_t cpu_id, 19 uint32_t attr) 20 { 21 mailbox_mem_t *mbx_mem; 22 unsigned int token = 0U; 23 int ret; 24 scmi_channel_t *ch = (scmi_channel_t *)p; 25 26 validate_scmi_channel(ch); 27 28 scmi_get_channel(ch); 29 30 mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); 31 mbx_mem->msg_header = SCMI_MSG_CREATE(IMX9_SCMI_CORE_PROTO_ID, 32 IMX9_SCMI_CORE_RESET_ADDR_SET_MSG, token); 33 mbx_mem->len = IMX9_SCMI_CORE_RESET_ADDR_SET_MSG_LEN; 34 mbx_mem->flags = SCMI_FLAG_RESP_POLL; 35 SCMI_PAYLOAD_ARG4(mbx_mem->payload, cpu_id, attr, 36 reset_addr & 0xffffffff, reset_addr >> 32); 37 38 scmi_send_sync_command(ch); 39 40 /* Get the return values */ 41 SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret); 42 assert(mbx_mem->len == IMX9_SCMI_CORE_RESET_ADDR_SET_RESP_LEN); 43 assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); 44 45 scmi_put_channel(ch); 46 47 return ret; 48 } 49 50 int scmi_core_start(void *p, uint32_t cpu_id) 51 { 52 mailbox_mem_t *mbx_mem; 53 unsigned int token = 0U; 54 int ret; 55 scmi_channel_t *ch = (scmi_channel_t *)p; 56 57 validate_scmi_channel(ch); 58 59 scmi_get_channel(ch); 60 61 mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); 62 mbx_mem->msg_header = SCMI_MSG_CREATE(IMX9_SCMI_CORE_PROTO_ID, 63 IMX9_SCMI_CORE_START_MSG, token); 64 mbx_mem->len = IMX9_SCMI_CORE_START_MSG_LEN; 65 mbx_mem->flags = SCMI_FLAG_RESP_POLL; 66 SCMI_PAYLOAD_ARG1(mbx_mem->payload, cpu_id); 67 68 scmi_send_sync_command(ch); 69 70 /* Get the return values */ 71 SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret); 72 assert(mbx_mem->len == IMX9_SCMI_CORE_START_RESP_LEN); 73 assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); 74 75 scmi_put_channel(ch); 76 77 return ret; 78 } 79 80 int scmi_core_stop(void *p, uint32_t cpu_id) 81 { 82 mailbox_mem_t *mbx_mem; 83 unsigned int token = 0U; 84 int ret; 85 scmi_channel_t *ch = (scmi_channel_t *)p; 86 87 validate_scmi_channel(ch); 88 89 scmi_get_channel(ch); 90 91 mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); 92 mbx_mem->msg_header = SCMI_MSG_CREATE(IMX9_SCMI_CORE_PROTO_ID, 93 IMX9_SCMI_CORE_STOP_MSG, token); 94 mbx_mem->len = IMX9_SCMI_CORE_STOP_MSG_LEN; 95 mbx_mem->flags = SCMI_FLAG_RESP_POLL; 96 SCMI_PAYLOAD_ARG1(mbx_mem->payload, cpu_id); 97 98 scmi_send_sync_command(ch); 99 100 /* Get the return values */ 101 SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret); 102 assert(mbx_mem->len == IMX9_SCMI_CORE_STOP_RESP_LEN); 103 assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); 104 105 scmi_put_channel(ch); 106 107 return ret; 108 } 109 110 int scmi_core_set_sleep_mode(void *p, uint32_t cpu_id, uint32_t wakeup, 111 uint32_t mode) 112 { 113 mailbox_mem_t *mbx_mem; 114 unsigned int token = 0U; 115 int ret; 116 scmi_channel_t *ch = (scmi_channel_t *)p; 117 118 validate_scmi_channel(ch); 119 120 scmi_get_channel(ch); 121 122 mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); 123 mbx_mem->msg_header = SCMI_MSG_CREATE(IMX9_SCMI_CORE_PROTO_ID, 124 IMX9_SCMI_CORE_SETSLEEPMODE_MSG, token); 125 mbx_mem->len = IMX9_SCMI_CORE_SETSLEEPMODE_MSG_LEN; 126 mbx_mem->flags = SCMI_FLAG_RESP_POLL; 127 SCMI_PAYLOAD_ARG3(mbx_mem->payload, cpu_id, wakeup, mode); 128 129 scmi_send_sync_command(ch); 130 131 /* Get the return values */ 132 SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret); 133 assert(mbx_mem->len == IMX9_SCMI_CORE_SETSLEEPMODE_RESP_LEN); 134 assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); 135 136 scmi_put_channel(ch); 137 138 return ret; 139 } 140 141 int scmi_core_Irq_wake_set(void *p, uint32_t cpu_id, uint32_t mask_idx, 142 uint32_t num_mask, uint32_t *mask) 143 { 144 mailbox_mem_t *mbx_mem; 145 unsigned int token = 0U; 146 int ret; 147 scmi_channel_t *ch = (scmi_channel_t *)p; 148 149 validate_scmi_channel(ch); 150 151 scmi_get_channel(ch); 152 153 mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); 154 mbx_mem->msg_header = SCMI_MSG_CREATE(IMX9_SCMI_CORE_PROTO_ID, 155 IMX9_SCMI_CORE_SETIRQWAKESET_MSG, token); 156 mbx_mem->len = IMX9_SCMI_CORE_SETIRQWAKESET_MSG_LEN; 157 mbx_mem->flags = SCMI_FLAG_RESP_POLL; 158 SCMI_PAYLOAD_ARG3(mbx_mem->payload, cpu_id, mask_idx, num_mask); 159 160 for (unsigned int i = 0U; i < num_mask; i++) { 161 mbx_mem->payload[3U + i] = mask[i]; 162 } 163 164 scmi_send_sync_command(ch); 165 166 /* Get the return values */ 167 SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret); 168 assert(mbx_mem->len == IMX9_SCMI_CORE_SETIRQWAKESET_RESP_LEN); 169 assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); 170 171 scmi_put_channel(ch); 172 173 return ret; 174 } 175 176 int scmi_core_nonIrq_wake_set(void *p, uint32_t cpu_id, uint32_t mask_idx, 177 uint32_t num_mask, uint32_t mask) 178 { 179 mailbox_mem_t *mbx_mem; 180 unsigned int token = 0U; 181 int ret; 182 scmi_channel_t *ch = (scmi_channel_t *)p; 183 184 validate_scmi_channel(ch); 185 scmi_get_channel(ch); 186 187 mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); 188 mbx_mem->msg_header = SCMI_MSG_CREATE(IMX9_SCMI_CORE_PROTO_ID, 189 IMX9_SCMI_CORE_NONIRQWAKESET_MSG, token); 190 mbx_mem->len = IMX9_SCMI_CORE_NONIRQWAKESET_MSG_LEN; 191 mbx_mem->flags = SCMI_FLAG_RESP_POLL; 192 SCMI_PAYLOAD_ARG4(mbx_mem->payload, cpu_id, mask_idx, num_mask, mask); 193 194 scmi_send_sync_command(ch); 195 196 /* Get the return values */ 197 SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret); 198 assert(mbx_mem->len == IMX9_SCMI_CORE_NONIRQWAKESET_RESP_LEN); 199 assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); 200 201 scmi_put_channel(ch); 202 203 return ret; 204 } 205 206 int scmi_core_lpm_mode_set(void *p, uint32_t cpu_id, 207 uint32_t num_configs, 208 struct scmi_lpm_config *cfg) 209 { 210 mailbox_mem_t *mbx_mem; 211 unsigned int token = 0U; 212 int ret; 213 scmi_channel_t *ch = (scmi_channel_t *)p; 214 215 validate_scmi_channel(ch); 216 217 scmi_get_channel(ch); 218 219 mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); 220 mbx_mem->msg_header = SCMI_MSG_CREATE(IMX9_SCMI_CORE_PROTO_ID, 221 IMX9_SCMI_CORE_LPMMODESET_MSG, token); 222 mbx_mem->len = IMX9_SCMI_CORE_LPMMODESET_MSG_LEN + 223 (num_configs * sizeof(struct scmi_lpm_config)); 224 mbx_mem->flags = SCMI_FLAG_RESP_POLL; 225 SCMI_PAYLOAD_ARG2(mbx_mem->payload, cpu_id, num_configs); 226 227 /* The lpm config starts from byte 2 in the payload memory */ 228 unsigned int j = 2U; 229 230 for (unsigned int i = 0U; i < num_configs; i++) { 231 mmio_write_32((uintptr_t)&mbx_mem->payload[j++], 232 cfg[i].power_domain); 233 mmio_write_32((uintptr_t)&mbx_mem->payload[j++], 234 cfg[i].lpmsetting); 235 mmio_write_32((uintptr_t)&mbx_mem->payload[j++], 236 cfg[i].retentionmask); 237 } 238 scmi_send_sync_command(ch); 239 240 /* Get the return values */ 241 SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret); 242 assert(mbx_mem->len == IMX9_SCMI_CORE_LPMMODESET_RESP_LEN); 243 assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); 244 245 scmi_put_channel(ch); 246 247 return ret; 248 } 249 250 int scmi_per_lpm_mode_set(void *p, uint32_t cpu_id, uint32_t num_configs, 251 struct scmi_per_lpm_config *cfg) 252 { 253 mailbox_mem_t *mbx_mem; 254 unsigned int token = 0U; 255 int ret; 256 scmi_channel_t *ch = (scmi_channel_t *)p; 257 struct scmi_per_lpm_config *tmp = cfg; 258 259 validate_scmi_channel(ch); 260 261 scmi_get_channel(ch); 262 263 do { 264 mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); 265 mbx_mem->msg_header = SCMI_MSG_CREATE(IMX9_SCMI_CORE_PROTO_ID, 266 IMX9_SCMI_PER_LPMMODESET_MSG, token); 267 mbx_mem->len = IMX9_SCMI_PER_LPMMODESET_MSG_LEN + 268 (num_configs * sizeof(struct scmi_per_lpm_config)); 269 mbx_mem->flags = SCMI_FLAG_RESP_POLL; 270 SCMI_PAYLOAD_ARG2(mbx_mem->payload, cpu_id, num_configs); 271 272 /* The lpm config starts from byte 2 in the payload memory */ 273 unsigned int j = 2U; 274 275 for (unsigned int i = 0U; i < num_configs; i++) { 276 mmio_write_32((uintptr_t)&mbx_mem->payload[j++], 277 cfg[i].perId); 278 mmio_write_32((uintptr_t)&mbx_mem->payload[j++], 279 cfg[i].lpmSetting); 280 } 281 scmi_send_sync_command(ch); 282 283 /* Get the return values */ 284 SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret); 285 assert(mbx_mem->len == IMX9_SCMI_PER_LPMMODESET_RESP_LEN); 286 assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); 287 288 if (num_configs > MAX_PER_LPI_CONFIGS_PER_CMD) { 289 num_configs -= MAX_PER_LPI_CONFIGS_PER_CMD; 290 tmp += MAX_PER_LPI_CONFIGS_PER_CMD; 291 } else { 292 break; 293 } 294 } while (num_configs); 295 296 scmi_put_channel(ch); 297 298 return ret; 299 } 300 301 int scmi_perf_mode_set(void *p, uint32_t domain_id, uint32_t perf_level) 302 { 303 mailbox_mem_t *mbx_mem; 304 unsigned int token = 0U; 305 int ret; 306 scmi_channel_t *ch = (scmi_channel_t *)p; 307 308 validate_scmi_channel(ch); 309 310 scmi_get_channel(ch); 311 312 mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); 313 mbx_mem->msg_header = SCMI_MSG_CREATE(IMX9_SCMI_PERF_PROTO_ID, 314 IMX9_SCMI_CORE_PERFLEVELSET_MSG, token); 315 mbx_mem->len = IMX9_SCMI_CORE_PERFLEVELSET_MSG_LEN; 316 mbx_mem->flags = SCMI_FLAG_RESP_POLL; 317 SCMI_PAYLOAD_ARG2(mbx_mem->payload, domain_id, perf_level); 318 319 scmi_send_sync_command(ch); 320 321 /* Get the return values */ 322 SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret); 323 assert(mbx_mem->len == IMX9_SCMI_CORE_PERFLEVELSET_RESP_LEN); 324 assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); 325 326 scmi_put_channel(ch); 327 328 return ret; 329 330 } 331 332 int scmi_core_info_get(void *p, uint32_t cpu_id, uint32_t *runmode, 333 uint32_t *sleepmode, uint64_t *vector) 334 { 335 mailbox_mem_t *mbx_mem; 336 unsigned int token = 0U; 337 int ret; 338 scmi_channel_t *ch = (scmi_channel_t *)p; 339 uint32_t lo_addr, hi_addr; 340 341 validate_scmi_channel(ch); 342 343 scmi_get_channel(ch); 344 345 mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); 346 mbx_mem->msg_header = SCMI_MSG_CREATE(IMX9_SCMI_CORE_PROTO_ID, 347 IMX9_SCMI_CORE_GETINFO_MSG, token); 348 mbx_mem->len = IMX9_SCMI_CORE_GETINFO_MSG_LEN; 349 mbx_mem->flags = SCMI_FLAG_RESP_POLL; 350 SCMI_PAYLOAD_ARG1(mbx_mem->payload, cpu_id); 351 352 scmi_send_sync_command(ch); 353 354 /* Get the return values */ 355 SCMI_PAYLOAD_RET_VAL5(mbx_mem->payload, ret, *runmode, *sleepmode, 356 lo_addr, hi_addr); 357 *vector = lo_addr | (uint64_t)hi_addr << 32; 358 assert(mbx_mem->len == IMX9_SCMI_CORE_START_RESP_LEN); 359 assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); 360 361 scmi_put_channel(ch); 362 363 return ret; 364 } 365