1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright 2022-2023, 2025 NXP 4 */ 5 #include <assert.h> 6 #include <drivers/imx_mu.h> 7 #include <imx-regs.h> 8 #include <kernel/delay.h> 9 #include <kernel/spinlock.h> 10 #include <string.h> 11 #include <trace.h> 12 13 #include "imx_mu_platform.h" 14 15 #define RX_TIMEOUT (100 * 1000) 16 17 #if defined(CFG_MX93) || defined(CFG_MX91) 18 #define IS_MU_TRUST (MU_BASE == MU_TRUST_BASE) 19 #else 20 #define IS_MU_TRUST false 21 #endif 22 23 static unsigned int mu_spinlock = SPINLOCK_UNLOCK; 24 25 __weak void imx_mu_plat_init(vaddr_t base __unused) 26 { 27 } 28 29 __weak TEE_Result imx_mu_plat_send(vaddr_t base __unused, 30 unsigned int index __unused, 31 uint32_t msg __unused) 32 { 33 return TEE_ERROR_NOT_IMPLEMENTED; 34 } 35 36 __weak TEE_Result imx_mu_plat_receive(vaddr_t base __unused, 37 unsigned int index __unused, 38 uint32_t *msg __unused) 39 { 40 return TEE_ERROR_NOT_IMPLEMENTED; 41 } 42 43 /* 44 * Receive a message via the MU 45 * 46 * @base: virtual base address of the MU controller 47 * @[out]msg: message received 48 */ 49 static TEE_Result imx_mu_receive_msg(vaddr_t base, struct imx_mu_msg *msg) 50 { 51 TEE_Result res = TEE_ERROR_GENERIC; 52 unsigned int count = 0; 53 uint32_t response = 0; 54 unsigned int nb_channel = 0; 55 uint64_t tout_rx = timeout_init_us(RX_TIMEOUT); 56 57 assert(base && msg); 58 59 do { 60 res = imx_mu_plat_receive(base, 0, &response); 61 if (timeout_elapsed(tout_rx)) 62 break; 63 } while (res == TEE_ERROR_NO_DATA); 64 65 if (res) 66 return res; 67 68 memcpy(&msg->header, &response, sizeof(response)); 69 70 /* Check the size of the message to receive */ 71 if (msg->header.size > IMX_MU_MSG_SIZE) { 72 EMSG("Size of the message is > than IMX_MU_MSG_SIZE"); 73 return TEE_ERROR_BAD_FORMAT; 74 } 75 76 nb_channel = imx_mu_plat_get_rx_channel(base); 77 78 for (count = 1; count < msg->header.size; count++) { 79 res = imx_mu_plat_receive(base, count % nb_channel, 80 &msg->data.u32[count - 1]); 81 if (res) 82 return res; 83 } 84 85 return TEE_SUCCESS; 86 } 87 88 /* 89 * Send a message via the MU 90 * 91 * @base: virtual base address of the MU controller 92 * @[in]msg: message to send 93 */ 94 static TEE_Result imx_mu_send_msg(vaddr_t base, struct imx_mu_msg *msg) 95 { 96 TEE_Result res = TEE_ERROR_GENERIC; 97 unsigned int count = 0; 98 unsigned int nb_channel = 0; 99 unsigned int start_index = 0; 100 unsigned int end_index = 0; 101 uint32_t word = 0; 102 103 assert(base && msg); 104 105 if (msg->header.size > IMX_MU_MSG_SIZE) { 106 EMSG("msg->size is > than IMX_MU_MSG_SIZE"); 107 return TEE_ERROR_BAD_FORMAT; 108 } 109 110 if (IS_MU_TRUST) { 111 /* 112 * make sure command (bit[31:26]) is higher than SCM_CR2_CMD_VAL 113 * SCM_CR2_CMD_VAL is set to 0 by ELE FW. but let’s use 114 * max value. 115 */ 116 word |= GENMASK_32(31, 26); 117 118 /* size (including dummy header) -> bit[19:16]*/ 119 word |= SHIFT_U32(((msg->header.size + 1) & GENMASK_32(3, 0)), 120 16); 121 122 res = imx_mu_plat_send(base, start_index, word); 123 if (res) 124 return res; 125 126 start_index++; 127 memcpy(&word, &msg->header, sizeof(uint32_t)); 128 res = imx_mu_plat_send(base, start_index, word); 129 if (res) 130 return res; 131 132 start_index++; 133 /* 134 * TR15 is reserved for special USM commands 135 */ 136 nb_channel = imx_mu_plat_get_tx_channel(base) - 1; 137 end_index = msg->header.size + 1; 138 assert(end_index < nb_channel); 139 } else { 140 memcpy(&word, &msg->header, sizeof(uint32_t)); 141 res = imx_mu_plat_send(base, start_index, word); 142 if (res) 143 return res; 144 145 start_index++; 146 nb_channel = imx_mu_plat_get_tx_channel(base); 147 end_index = msg->header.size; 148 } 149 150 for (count = start_index; count < end_index; count++) { 151 res = imx_mu_plat_send(base, count % nb_channel, 152 msg->data.u32[count - start_index]); 153 if (res) 154 return res; 155 } 156 157 return TEE_SUCCESS; 158 } 159 160 void imx_mu_init(vaddr_t base) 161 { 162 uint32_t exceptions = 0; 163 164 if (!base) { 165 EMSG("Bad MU base address"); 166 return; 167 } 168 169 exceptions = cpu_spin_lock_xsave(&mu_spinlock); 170 171 imx_mu_plat_init(base); 172 173 cpu_spin_unlock_xrestore(&mu_spinlock, exceptions); 174 } 175 176 TEE_Result imx_mu_call(vaddr_t base, struct imx_mu_msg *msg, 177 bool wait_for_answer) 178 { 179 TEE_Result res = TEE_ERROR_GENERIC; 180 uint32_t exceptions = 0; 181 182 if (!base || !msg) 183 return TEE_ERROR_BAD_PARAMETERS; 184 185 exceptions = cpu_spin_lock_xsave(&mu_spinlock); 186 187 res = imx_mu_send_msg(base, msg); 188 if (res == TEE_SUCCESS && wait_for_answer) 189 res = imx_mu_receive_msg(base, msg); 190 191 cpu_spin_unlock_xrestore(&mu_spinlock, exceptions); 192 193 return res; 194 } 195