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 if (urgent) { 164 /* Read status because it is toggled */ 165 status = MBOX_READL(MBOX_STATUS) & MBOX_STATUS_UA_MSK; 166 /* Write urgent command to urgent register */ 167 MBOX_WRITEL(cmd, MBOX_URG); 168 } else { 169 ret = mbox_prepare_cmd_only(id, cmd, is_indirect, len, arg); 170 if (ret) 171 return ret; 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 192 /* Urgent ACK is toggled */ 193 if ((new_status & MBOX_STATUS_UA_MSK) ^ status) 194 return 0; 195 196 return -ECOMM; 197 } 198 199 /* read current response offset */ 200 rout = MBOX_READL(MBOX_ROUT); 201 202 /* read response valid offset */ 203 rin = MBOX_READL(MBOX_RIN); 204 205 if (rout != rin) { 206 /* Response received */ 207 resp = MBOX_READ_RESP_BUF(rout); 208 rout++; 209 /* wrapping around when it reach the buffer size */ 210 rout %= MBOX_RESP_BUFFER_SIZE; 211 /* update next ROUT */ 212 MBOX_WRITEL(rout, MBOX_ROUT); 213 214 /* check client ID and ID */ 215 if ((MBOX_RESP_CLIENT_GET(resp) == 216 MBOX_CLIENT_ID_UBOOT) && 217 (MBOX_RESP_ID_GET(resp) == id)) { 218 ret = MBOX_RESP_ERR_GET(resp); 219 if (ret) 220 return ret; 221 222 if (resp_buf_len) { 223 buf_len = *resp_buf_len; 224 *resp_buf_len = 0; 225 } else { 226 buf_len = 0; 227 } 228 229 resp_len = MBOX_RESP_LEN_GET(resp); 230 while (resp_len) { 231 ret = mbox_polling_resp(rout); 232 if (ret) 233 return ret; 234 /* we need to process response buffer 235 * even caller doesn't need it 236 */ 237 resp = MBOX_READ_RESP_BUF(rout); 238 rout++; 239 resp_len--; 240 rout %= MBOX_RESP_BUFFER_SIZE; 241 MBOX_WRITEL(rout, MBOX_ROUT); 242 if (buf_len) { 243 /* copy response to buffer */ 244 resp_buf[*resp_buf_len] = resp; 245 (*resp_buf_len)++; 246 buf_len--; 247 } 248 } 249 return ret; 250 } 251 } 252 }; 253 254 return -EIO; 255 } 256 257 int mbox_init(void) 258 { 259 int ret; 260 261 /* enable mailbox interrupts */ 262 MBOX_WRITEL(MBOX_ALL_INTRS, MBOX_FLAGS); 263 264 /* Ensure urgent request is cleared */ 265 MBOX_WRITEL(0, MBOX_URG); 266 267 /* Ensure the Doorbell Interrupt is cleared */ 268 MBOX_WRITEL(0, MBOX_DOORBELL_FROM_SDM); 269 270 ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_RESTART, MBOX_CMD_DIRECT, 0, 271 NULL, 1, 0, NULL); 272 if (ret) 273 return ret; 274 275 /* Renable mailbox interrupts after MBOX_RESTART */ 276 MBOX_WRITEL(MBOX_ALL_INTRS, MBOX_FLAGS); 277 278 return 0; 279 } 280 281 #ifdef CONFIG_CADENCE_QSPI 282 int mbox_qspi_close(void) 283 { 284 return mbox_send_cmd(MBOX_ID_UBOOT, MBOX_QSPI_CLOSE, MBOX_CMD_DIRECT, 285 0, NULL, 0, 0, NULL); 286 } 287 288 int mbox_qspi_open(void) 289 { 290 static const struct socfpga_system_manager *sysmgr_regs = 291 (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS; 292 293 int ret; 294 u32 resp_buf[1]; 295 u32 resp_buf_len; 296 297 ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_QSPI_OPEN, MBOX_CMD_DIRECT, 298 0, NULL, 0, 0, NULL); 299 if (ret) { 300 /* retry again by closing and reopen the QSPI again */ 301 ret = mbox_qspi_close(); 302 if (ret) 303 return ret; 304 305 ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_QSPI_OPEN, 306 MBOX_CMD_DIRECT, 0, NULL, 0, 0, NULL); 307 if (ret) 308 return ret; 309 } 310 311 /* HPS will directly control the QSPI controller, no longer mailbox */ 312 resp_buf_len = 1; 313 ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_QSPI_DIRECT, MBOX_CMD_DIRECT, 314 0, NULL, 0, (u32 *)&resp_buf_len, 315 (u32 *)&resp_buf); 316 if (ret) 317 goto error; 318 319 /* We are getting QSPI ref clock and set into sysmgr boot register */ 320 printf("QSPI: Reference clock at %d Hz\n", resp_buf[0]); 321 writel(resp_buf[0], &sysmgr_regs->boot_scratch_cold0); 322 323 return 0; 324 325 error: 326 mbox_qspi_close(); 327 328 return ret; 329 } 330 #endif /* CONFIG_CADENCE_QSPI */ 331 332 int mbox_reset_cold(void) 333 { 334 int ret; 335 336 ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_REBOOT_HPS, MBOX_CMD_DIRECT, 337 0, NULL, 0, 0, NULL); 338 if (ret) { 339 /* mailbox sent failure, wait for watchdog to kick in */ 340 hang(); 341 } 342 return 0; 343 } 344 345 int mbox_send_cmd(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg, 346 u8 urgent, u32 *resp_buf_len, u32 *resp_buf) 347 { 348 return mbox_send_cmd_common(id, cmd, is_indirect, len, arg, urgent, 349 resp_buf_len, resp_buf); 350 } 351 352 int __secure mbox_send_cmd_psci(u8 id, u32 cmd, u8 is_indirect, u32 len, 353 u32 *arg, u8 urgent, u32 *resp_buf_len, 354 u32 *resp_buf) 355 { 356 return mbox_send_cmd_common(id, cmd, is_indirect, len, arg, urgent, 357 resp_buf_len, resp_buf); 358 } 359 360 int mbox_send_cmd_only(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg) 361 { 362 return mbox_send_cmd_only_common(id, cmd, is_indirect, len, arg); 363 } 364 365 int __secure mbox_send_cmd_only_psci(u8 id, u32 cmd, u8 is_indirect, u32 len, 366 u32 *arg) 367 { 368 return mbox_send_cmd_only_common(id, cmd, is_indirect, len, arg); 369 } 370 371 int mbox_rcv_resp(u32 *resp_buf, u32 resp_buf_max_len) 372 { 373 return __mbox_rcv_resp(resp_buf, resp_buf_max_len); 374 } 375 376 int __secure mbox_rcv_resp_psci(u32 *resp_buf, u32 resp_buf_max_len) 377 { 378 return __mbox_rcv_resp(resp_buf, resp_buf_max_len); 379 } 380