1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2017-2018 Intel Corporation <www.intel.com> 4 * 5 */ 6 7 #include <common.h> 8 #include <wait_bit.h> 9 #include <asm/io.h> 10 #include <asm/arch/mailbox_s10.h> 11 #include <asm/arch/system_manager.h> 12 #include <asm/secure.h> 13 14 DECLARE_GLOBAL_DATA_PTR; 15 16 #define MBOX_READL(reg) \ 17 readl(SOCFPGA_MAILBOX_ADDRESS + (reg)) 18 19 #define MBOX_WRITEL(data, reg) \ 20 writel(data, SOCFPGA_MAILBOX_ADDRESS + (reg)) 21 22 #define MBOX_READ_RESP_BUF(rout) \ 23 MBOX_READL(MBOX_RESP_BUF + ((rout) * sizeof(u32))) 24 25 #define MBOX_WRITE_CMD_BUF(data, cin) \ 26 MBOX_WRITEL(data, MBOX_CMD_BUF + ((cin) * sizeof(u32))) 27 28 static __always_inline int mbox_polling_resp(u32 rout) 29 { 30 u32 rin; 31 unsigned long i = ~0; 32 33 while (i) { 34 rin = MBOX_READL(MBOX_RIN); 35 if (rout != rin) 36 return 0; 37 38 i--; 39 } 40 41 return -ETIMEDOUT; 42 } 43 44 /* Check for available slot and write to circular buffer. 45 * It also update command valid offset (cin) register. 46 */ 47 static __always_inline int mbox_fill_cmd_circular_buff(u32 header, u32 len, 48 u32 *arg) 49 { 50 u32 cin; 51 u32 cout; 52 u32 i; 53 54 cin = MBOX_READL(MBOX_CIN) % MBOX_CMD_BUFFER_SIZE; 55 cout = MBOX_READL(MBOX_COUT) % MBOX_CMD_BUFFER_SIZE; 56 57 /* if command buffer is full or not enough free space 58 * to fit the data 59 */ 60 if (((cin + 1) % MBOX_CMD_BUFFER_SIZE) == cout || 61 ((MBOX_CMD_BUFFER_SIZE - cin + cout - 1) % 62 MBOX_CMD_BUFFER_SIZE) < len) 63 return -ENOMEM; 64 65 /* write header to circular buffer */ 66 MBOX_WRITE_CMD_BUF(header, cin++); 67 /* wrapping around when it reach the buffer size */ 68 cin %= MBOX_CMD_BUFFER_SIZE; 69 70 /* write arguments */ 71 for (i = 0; i < len; i++) { 72 MBOX_WRITE_CMD_BUF(arg[i], cin++); 73 /* wrapping around when it reach the buffer size */ 74 cin %= MBOX_CMD_BUFFER_SIZE; 75 } 76 77 /* write command valid offset */ 78 MBOX_WRITEL(cin, MBOX_CIN); 79 80 return 0; 81 } 82 83 /* Check the command and fill it into circular buffer */ 84 static __always_inline int mbox_prepare_cmd_only(u8 id, u32 cmd, 85 u8 is_indirect, u32 len, 86 u32 *arg) 87 { 88 u32 header; 89 int ret; 90 91 /* Total length is command + argument length */ 92 if ((len + 1) > MBOX_CMD_BUFFER_SIZE) 93 return -EINVAL; 94 95 if (cmd > MBOX_MAX_CMD_INDEX) 96 return -EINVAL; 97 98 header = MBOX_CMD_HEADER(MBOX_CLIENT_ID_UBOOT, id, len, 99 (is_indirect) ? 1 : 0, cmd); 100 101 ret = mbox_fill_cmd_circular_buff(header, len, arg); 102 103 return ret; 104 } 105 106 /* Send command only without waiting for responses from SDM */ 107 static __always_inline int mbox_send_cmd_only_common(u8 id, u32 cmd, 108 u8 is_indirect, u32 len, 109 u32 *arg) 110 { 111 int ret = mbox_prepare_cmd_only(id, cmd, is_indirect, len, arg); 112 /* write doorbell */ 113 MBOX_WRITEL(1, MBOX_DOORBELL_TO_SDM); 114 115 return ret; 116 } 117 118 /* Return number of responses received in buffer */ 119 static __always_inline int __mbox_rcv_resp(u32 *resp_buf, u32 resp_buf_max_len) 120 { 121 u32 rin; 122 u32 rout; 123 u32 resp_len = 0; 124 125 /* clear doorbell from SDM if it was SET */ 126 if (MBOX_READL(MBOX_DOORBELL_FROM_SDM) & 1) 127 MBOX_WRITEL(0, MBOX_DOORBELL_FROM_SDM); 128 129 /* read current response offset */ 130 rout = MBOX_READL(MBOX_ROUT); 131 /* read response valid offset */ 132 rin = MBOX_READL(MBOX_RIN); 133 134 while (rin != rout && (resp_len < resp_buf_max_len)) { 135 /* Response received */ 136 if (resp_buf) 137 resp_buf[resp_len++] = MBOX_READ_RESP_BUF(rout); 138 139 rout++; 140 /* wrapping around when it reach the buffer size */ 141 rout %= MBOX_RESP_BUFFER_SIZE; 142 /* update next ROUT */ 143 MBOX_WRITEL(rout, MBOX_ROUT); 144 } 145 146 return resp_len; 147 } 148 149 /* Support one command and up to 31 words argument length only */ 150 static __always_inline int mbox_send_cmd_common(u8 id, u32 cmd, u8 is_indirect, 151 u32 len, u32 *arg, u8 urgent, 152 u32 *resp_buf_len, 153 u32 *resp_buf) 154 { 155 u32 rin; 156 u32 resp; 157 u32 rout; 158 u32 status; 159 u32 resp_len; 160 u32 buf_len; 161 int ret; 162 163 ret = mbox_prepare_cmd_only(id, cmd, is_indirect, len, arg); 164 if (ret) 165 return ret; 166 167 if (urgent) { 168 /* Read status because it is toggled */ 169 status = MBOX_READL(MBOX_STATUS) & MBOX_STATUS_UA_MSK; 170 /* Send command as urgent command */ 171 MBOX_WRITEL(1, MBOX_URG); 172 } 173 174 /* write doorbell */ 175 MBOX_WRITEL(1, MBOX_DOORBELL_TO_SDM); 176 177 while (1) { 178 ret = ~0; 179 180 /* Wait for doorbell from SDM */ 181 while (!MBOX_READL(MBOX_DOORBELL_FROM_SDM) && ret--) 182 ; 183 if (!ret) 184 return -ETIMEDOUT; 185 186 /* clear interrupt */ 187 MBOX_WRITEL(0, MBOX_DOORBELL_FROM_SDM); 188 189 if (urgent) { 190 u32 new_status = MBOX_READL(MBOX_STATUS); 191 /* urgent command doesn't have response */ 192 MBOX_WRITEL(0, MBOX_URG); 193 /* Urgent ACK is toggled */ 194 if ((new_status & MBOX_STATUS_UA_MSK) ^ status) 195 return 0; 196 197 return -ECOMM; 198 } 199 200 /* read current response offset */ 201 rout = MBOX_READL(MBOX_ROUT); 202 203 /* read response valid offset */ 204 rin = MBOX_READL(MBOX_RIN); 205 206 if (rout != rin) { 207 /* Response received */ 208 resp = MBOX_READ_RESP_BUF(rout); 209 rout++; 210 /* wrapping around when it reach the buffer size */ 211 rout %= MBOX_RESP_BUFFER_SIZE; 212 /* update next ROUT */ 213 MBOX_WRITEL(rout, MBOX_ROUT); 214 215 /* check client ID and ID */ 216 if ((MBOX_RESP_CLIENT_GET(resp) == 217 MBOX_CLIENT_ID_UBOOT) && 218 (MBOX_RESP_ID_GET(resp) == id)) { 219 ret = MBOX_RESP_ERR_GET(resp); 220 if (ret) 221 return ret; 222 223 if (resp_buf_len) { 224 buf_len = *resp_buf_len; 225 *resp_buf_len = 0; 226 } else { 227 buf_len = 0; 228 } 229 230 resp_len = MBOX_RESP_LEN_GET(resp); 231 while (resp_len) { 232 ret = mbox_polling_resp(rout); 233 if (ret) 234 return ret; 235 /* we need to process response buffer 236 * even caller doesn't need it 237 */ 238 resp = MBOX_READ_RESP_BUF(rout); 239 rout++; 240 resp_len--; 241 rout %= MBOX_RESP_BUFFER_SIZE; 242 MBOX_WRITEL(rout, MBOX_ROUT); 243 if (buf_len) { 244 /* copy response to buffer */ 245 resp_buf[*resp_buf_len] = resp; 246 (*resp_buf_len)++; 247 buf_len--; 248 } 249 } 250 return ret; 251 } 252 } 253 }; 254 255 return -EIO; 256 } 257 258 int mbox_init(void) 259 { 260 int ret; 261 262 /* enable mailbox interrupts */ 263 MBOX_WRITEL(MBOX_ALL_INTRS, MBOX_FLAGS); 264 265 /* Ensure urgent request is cleared */ 266 MBOX_WRITEL(0, MBOX_URG); 267 268 /* Ensure the Doorbell Interrupt is cleared */ 269 MBOX_WRITEL(0, MBOX_DOORBELL_FROM_SDM); 270 271 ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_RESTART, MBOX_CMD_DIRECT, 0, 272 NULL, 1, 0, NULL); 273 if (ret) 274 return ret; 275 276 /* Renable mailbox interrupts after MBOX_RESTART */ 277 MBOX_WRITEL(MBOX_ALL_INTRS, MBOX_FLAGS); 278 279 return 0; 280 } 281 282 #ifdef CONFIG_CADENCE_QSPI 283 int mbox_qspi_close(void) 284 { 285 return mbox_send_cmd(MBOX_ID_UBOOT, MBOX_QSPI_CLOSE, MBOX_CMD_DIRECT, 286 0, NULL, 0, 0, NULL); 287 } 288 289 int mbox_qspi_open(void) 290 { 291 static const struct socfpga_system_manager *sysmgr_regs = 292 (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS; 293 294 int ret; 295 u32 resp_buf[1]; 296 u32 resp_buf_len; 297 298 ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_QSPI_OPEN, MBOX_CMD_DIRECT, 299 0, NULL, 0, 0, NULL); 300 if (ret) { 301 /* retry again by closing and reopen the QSPI again */ 302 ret = mbox_qspi_close(); 303 if (ret) 304 return ret; 305 306 ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_QSPI_OPEN, 307 MBOX_CMD_DIRECT, 0, NULL, 0, 0, NULL); 308 if (ret) 309 return ret; 310 } 311 312 /* HPS will directly control the QSPI controller, no longer mailbox */ 313 resp_buf_len = 1; 314 ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_QSPI_DIRECT, MBOX_CMD_DIRECT, 315 0, NULL, 0, (u32 *)&resp_buf_len, 316 (u32 *)&resp_buf); 317 if (ret) 318 goto error; 319 320 /* We are getting QSPI ref clock and set into sysmgr boot register */ 321 printf("QSPI: Reference clock at %d Hz\n", resp_buf[0]); 322 writel(resp_buf[0], &sysmgr_regs->boot_scratch_cold0); 323 324 return 0; 325 326 error: 327 mbox_qspi_close(); 328 329 return ret; 330 } 331 #endif /* CONFIG_CADENCE_QSPI */ 332 333 int mbox_reset_cold(void) 334 { 335 int ret; 336 337 ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_REBOOT_HPS, MBOX_CMD_DIRECT, 338 0, NULL, 0, 0, NULL); 339 if (ret) { 340 /* mailbox sent failure, wait for watchdog to kick in */ 341 hang(); 342 } 343 return 0; 344 } 345 346 int mbox_send_cmd(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg, 347 u8 urgent, u32 *resp_buf_len, u32 *resp_buf) 348 { 349 return mbox_send_cmd_common(id, cmd, is_indirect, len, arg, urgent, 350 resp_buf_len, resp_buf); 351 } 352 353 int __secure mbox_send_cmd_psci(u8 id, u32 cmd, u8 is_indirect, u32 len, 354 u32 *arg, u8 urgent, u32 *resp_buf_len, 355 u32 *resp_buf) 356 { 357 return mbox_send_cmd_common(id, cmd, is_indirect, len, arg, urgent, 358 resp_buf_len, resp_buf); 359 } 360 361 int mbox_send_cmd_only(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg) 362 { 363 return mbox_send_cmd_only_common(id, cmd, is_indirect, len, arg); 364 } 365 366 int __secure mbox_send_cmd_only_psci(u8 id, u32 cmd, u8 is_indirect, u32 len, 367 u32 *arg) 368 { 369 return mbox_send_cmd_only_common(id, cmd, is_indirect, len, arg); 370 } 371 372 int mbox_rcv_resp(u32 *resp_buf, u32 resp_buf_max_len) 373 { 374 return __mbox_rcv_resp(resp_buf, resp_buf_max_len); 375 } 376 377 int __secure mbox_rcv_resp_psci(u32 *resp_buf, u32 resp_buf_max_len) 378 { 379 return __mbox_rcv_resp(resp_buf, resp_buf_max_len); 380 } 381