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 <hang.h>
9 #include <wait_bit.h>
10 #include <asm/global_data.h>
11 #include <asm/io.h>
12 #include <asm/arch/mailbox_s10.h>
13 #include <asm/arch/system_manager.h>
14 #include <asm/secure.h>
15 #include <asm/system.h>
16
17 DECLARE_GLOBAL_DATA_PTR;
18
19 #define MBOX_READL(reg) \
20 readl(SOCFPGA_MAILBOX_ADDRESS + (reg))
21
22 #define MBOX_WRITEL(data, reg) \
23 writel(data, SOCFPGA_MAILBOX_ADDRESS + (reg))
24
25 #define MBOX_READ_RESP_BUF(rout) \
26 MBOX_READL(MBOX_RESP_BUF + ((rout) * sizeof(u32)))
27
28 #define MBOX_WRITE_CMD_BUF(data, cin) \
29 MBOX_WRITEL(data, MBOX_CMD_BUF + ((cin) * sizeof(u32)))
30
mbox_polling_resp(u32 rout)31 static __always_inline int mbox_polling_resp(u32 rout)
32 {
33 u32 rin;
34 unsigned long i = 2000;
35
36 while (i) {
37 rin = MBOX_READL(MBOX_RIN);
38 if (rout != rin)
39 return 0;
40
41 udelay(1000);
42 i--;
43 }
44
45 return -ETIMEDOUT;
46 }
47
mbox_is_cmdbuf_full(u32 cin)48 static __always_inline int mbox_is_cmdbuf_full(u32 cin)
49 {
50 return (((cin + 1) % MBOX_CMD_BUFFER_SIZE) == MBOX_READL(MBOX_COUT));
51 }
52
mbox_is_cmdbuf_empty(u32 cin)53 static __always_inline int mbox_is_cmdbuf_empty(u32 cin)
54 {
55 return (((MBOX_READL(MBOX_COUT) + 1) % MBOX_CMD_BUFFER_SIZE) == cin);
56 }
57
mbox_wait_for_cmdbuf_empty(u32 cin)58 static __always_inline int mbox_wait_for_cmdbuf_empty(u32 cin)
59 {
60 int timeout = 2000;
61
62 while (timeout) {
63 if (mbox_is_cmdbuf_empty(cin))
64 return 0;
65 udelay(1000);
66 timeout--;
67 }
68
69 return -ETIMEDOUT;
70 }
71
mbox_write_cmd_buffer(u32 * cin,u32 data,int * is_cmdbuf_overflow)72 static __always_inline int mbox_write_cmd_buffer(u32 *cin, u32 data,
73 int *is_cmdbuf_overflow)
74 {
75 int timeout = 1000;
76
77 while (timeout) {
78 if (mbox_is_cmdbuf_full(*cin)) {
79 if (is_cmdbuf_overflow &&
80 *is_cmdbuf_overflow == 0) {
81 /* Trigger SDM doorbell */
82 MBOX_WRITEL(1, MBOX_DOORBELL_TO_SDM);
83 *is_cmdbuf_overflow = 1;
84 }
85 udelay(1000);
86 } else {
87 /* write header to circular buffer */
88 MBOX_WRITE_CMD_BUF(data, (*cin)++);
89 *cin %= MBOX_CMD_BUFFER_SIZE;
90 MBOX_WRITEL(*cin, MBOX_CIN);
91 break;
92 }
93 timeout--;
94 }
95
96 if (!timeout)
97 return -ETIMEDOUT;
98
99 /* Wait for the SDM to drain the FIFO command buffer */
100 if (is_cmdbuf_overflow && *is_cmdbuf_overflow)
101 return mbox_wait_for_cmdbuf_empty(*cin);
102
103 return 0;
104 }
105
106 /* Check for available slot and write to circular buffer.
107 * It also update command valid offset (cin) register.
108 */
mbox_fill_cmd_circular_buff(u32 header,u32 len,u32 * arg)109 static __always_inline int mbox_fill_cmd_circular_buff(u32 header, u32 len,
110 u32 *arg)
111 {
112 int i, ret;
113 int is_cmdbuf_overflow = 0;
114 u32 cin = MBOX_READL(MBOX_CIN) % MBOX_CMD_BUFFER_SIZE;
115
116 ret = mbox_write_cmd_buffer(&cin, header, &is_cmdbuf_overflow);
117 if (ret)
118 return ret;
119
120 /* write arguments */
121 for (i = 0; i < len; i++) {
122 is_cmdbuf_overflow = 0;
123 ret = mbox_write_cmd_buffer(&cin, arg[i], &is_cmdbuf_overflow);
124 if (ret)
125 return ret;
126 }
127
128 /* If SDM doorbell is not triggered after the last data is
129 * written into mailbox FIFO command buffer, trigger the
130 * SDM doorbell again to ensure SDM able to read the remaining
131 * data.
132 */
133 if (!is_cmdbuf_overflow)
134 MBOX_WRITEL(1, MBOX_DOORBELL_TO_SDM);
135
136 return 0;
137 }
138
139 /* Check the command and fill it into circular buffer */
mbox_prepare_cmd_only(u8 id,u32 cmd,u8 is_indirect,u32 len,u32 * arg)140 static __always_inline int mbox_prepare_cmd_only(u8 id, u32 cmd,
141 u8 is_indirect, u32 len,
142 u32 *arg)
143 {
144 u32 header;
145 int ret;
146
147 if (cmd > MBOX_MAX_CMD_INDEX)
148 return -EINVAL;
149
150 header = MBOX_CMD_HEADER(MBOX_CLIENT_ID_UBOOT, id, len,
151 (is_indirect) ? 1 : 0, cmd);
152
153 ret = mbox_fill_cmd_circular_buff(header, len, arg);
154
155 return ret;
156 }
157
158 /* Send command only without waiting for responses from SDM */
mbox_send_cmd_only_common(u8 id,u32 cmd,u8 is_indirect,u32 len,u32 * arg)159 static __always_inline int mbox_send_cmd_only_common(u8 id, u32 cmd,
160 u8 is_indirect, u32 len,
161 u32 *arg)
162 {
163 return mbox_prepare_cmd_only(id, cmd, is_indirect, len, arg);
164 }
165
166 /* Return number of responses received in buffer */
__mbox_rcv_resp(u32 * resp_buf,u32 resp_buf_max_len)167 static __always_inline int __mbox_rcv_resp(u32 *resp_buf, u32 resp_buf_max_len)
168 {
169 u32 rin;
170 u32 rout;
171 u32 resp_len = 0;
172
173 /* clear doorbell from SDM if it was SET */
174 if (MBOX_READL(MBOX_DOORBELL_FROM_SDM) & 1)
175 MBOX_WRITEL(0, MBOX_DOORBELL_FROM_SDM);
176
177 /* read current response offset */
178 rout = MBOX_READL(MBOX_ROUT);
179 /* read response valid offset */
180 rin = MBOX_READL(MBOX_RIN);
181
182 while (rin != rout && (resp_len < resp_buf_max_len)) {
183 /* Response received */
184 if (resp_buf)
185 resp_buf[resp_len++] = MBOX_READ_RESP_BUF(rout);
186
187 rout++;
188 /* wrapping around when it reach the buffer size */
189 rout %= MBOX_RESP_BUFFER_SIZE;
190 /* update next ROUT */
191 MBOX_WRITEL(rout, MBOX_ROUT);
192 }
193
194 return resp_len;
195 }
196
197 /* Support one command and up to 31 words argument length only */
mbox_send_cmd_common(u8 id,u32 cmd,u8 is_indirect,u32 len,u32 * arg,u8 urgent,u32 * resp_buf_len,u32 * resp_buf)198 static __always_inline int mbox_send_cmd_common(u8 id, u32 cmd, u8 is_indirect,
199 u32 len, u32 *arg, u8 urgent,
200 u32 *resp_buf_len,
201 u32 *resp_buf)
202 {
203 u32 rin;
204 u32 resp;
205 u32 rout;
206 u32 status;
207 u32 resp_len;
208 u32 buf_len;
209 int ret;
210
211 if (urgent) {
212 /* Read status because it is toggled */
213 status = MBOX_READL(MBOX_STATUS) & MBOX_STATUS_UA_MSK;
214 /* Write urgent command to urgent register */
215 MBOX_WRITEL(cmd, MBOX_URG);
216 /* write doorbell */
217 MBOX_WRITEL(1, MBOX_DOORBELL_TO_SDM);
218 } else {
219 ret = mbox_prepare_cmd_only(id, cmd, is_indirect, len, arg);
220 if (ret)
221 return ret;
222 }
223
224 while (1) {
225 ret = 1000;
226
227 /* Wait for doorbell from SDM */
228 do {
229 if (MBOX_READL(MBOX_DOORBELL_FROM_SDM))
230 break;
231 udelay(1000);
232 } while (--ret);
233
234 if (!ret)
235 return -ETIMEDOUT;
236
237 /* clear interrupt */
238 MBOX_WRITEL(0, MBOX_DOORBELL_FROM_SDM);
239
240 if (urgent) {
241 u32 new_status = MBOX_READL(MBOX_STATUS);
242
243 /* Urgent ACK is toggled */
244 if ((new_status & MBOX_STATUS_UA_MSK) ^ status)
245 return 0;
246
247 return -ECOMM;
248 }
249
250 /* read current response offset */
251 rout = MBOX_READL(MBOX_ROUT);
252
253 /* read response valid offset */
254 rin = MBOX_READL(MBOX_RIN);
255
256 if (rout != rin) {
257 /* Response received */
258 resp = MBOX_READ_RESP_BUF(rout);
259 rout++;
260 /* wrapping around when it reach the buffer size */
261 rout %= MBOX_RESP_BUFFER_SIZE;
262 /* update next ROUT */
263 MBOX_WRITEL(rout, MBOX_ROUT);
264
265 /* check client ID and ID */
266 if ((MBOX_RESP_CLIENT_GET(resp) ==
267 MBOX_CLIENT_ID_UBOOT) &&
268 (MBOX_RESP_ID_GET(resp) == id)) {
269 int resp_err = MBOX_RESP_ERR_GET(resp);
270
271 if (resp_buf_len) {
272 buf_len = *resp_buf_len;
273 *resp_buf_len = 0;
274 } else {
275 buf_len = 0;
276 }
277
278 resp_len = MBOX_RESP_LEN_GET(resp);
279 while (resp_len) {
280 ret = mbox_polling_resp(rout);
281 if (ret)
282 return ret;
283 /* we need to process response buffer
284 * even caller doesn't need it
285 */
286 resp = MBOX_READ_RESP_BUF(rout);
287 rout++;
288 resp_len--;
289 rout %= MBOX_RESP_BUFFER_SIZE;
290 MBOX_WRITEL(rout, MBOX_ROUT);
291 if (buf_len) {
292 /* copy response to buffer */
293 resp_buf[*resp_buf_len] = resp;
294 (*resp_buf_len)++;
295 buf_len--;
296 }
297 }
298 return resp_err;
299 }
300 }
301 }
302
303 return -EIO;
304 }
305
mbox_send_cmd_common_retry(u8 id,u32 cmd,u8 is_indirect,u32 len,u32 * arg,u8 urgent,u32 * resp_buf_len,u32 * resp_buf)306 static __always_inline int mbox_send_cmd_common_retry(u8 id, u32 cmd,
307 u8 is_indirect,
308 u32 len, u32 *arg,
309 u8 urgent,
310 u32 *resp_buf_len,
311 u32 *resp_buf)
312 {
313 int ret;
314 int i;
315
316 for (i = 0; i < 3; i++) {
317 ret = mbox_send_cmd_common(id, cmd, is_indirect, len, arg,
318 urgent, resp_buf_len, resp_buf);
319 if (ret == MBOX_RESP_TIMEOUT || ret == MBOX_RESP_DEVICE_BUSY)
320 udelay(2000); /* wait for 2ms before resend */
321 else
322 break;
323 }
324
325 return ret;
326 }
327
mbox_init(void)328 int mbox_init(void)
329 {
330 int ret;
331
332 /* enable mailbox interrupts */
333 MBOX_WRITEL(MBOX_ALL_INTRS, MBOX_FLAGS);
334
335 /* Ensure urgent request is cleared */
336 MBOX_WRITEL(0, MBOX_URG);
337
338 /* Ensure the Doorbell Interrupt is cleared */
339 MBOX_WRITEL(0, MBOX_DOORBELL_FROM_SDM);
340
341 ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_RESTART, MBOX_CMD_DIRECT, 0,
342 NULL, 1, 0, NULL);
343 if (ret)
344 return ret;
345
346 /* Renable mailbox interrupts after MBOX_RESTART */
347 MBOX_WRITEL(MBOX_ALL_INTRS, MBOX_FLAGS);
348
349 return 0;
350 }
351
352 #ifdef CONFIG_CADENCE_QSPI
mbox_qspi_close(void)353 int mbox_qspi_close(void)
354 {
355 return mbox_send_cmd(MBOX_ID_UBOOT, MBOX_QSPI_CLOSE, MBOX_CMD_DIRECT,
356 0, NULL, 0, 0, NULL);
357 }
358
mbox_qspi_open(void)359 int mbox_qspi_open(void)
360 {
361 int ret;
362 u32 resp_buf[1];
363 u32 resp_buf_len;
364
365 ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_QSPI_OPEN, MBOX_CMD_DIRECT,
366 0, NULL, 0, 0, NULL);
367 if (ret) {
368 /* retry again by closing and reopen the QSPI again */
369 ret = mbox_qspi_close();
370 if (ret)
371 return ret;
372
373 ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_QSPI_OPEN,
374 MBOX_CMD_DIRECT, 0, NULL, 0, 0, NULL);
375 if (ret)
376 return ret;
377 }
378
379 /* HPS will directly control the QSPI controller, no longer mailbox */
380 resp_buf_len = 1;
381 ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_QSPI_DIRECT, MBOX_CMD_DIRECT,
382 0, NULL, 0, (u32 *)&resp_buf_len,
383 (u32 *)&resp_buf);
384 if (ret)
385 goto error;
386
387 /* We are getting QSPI ref clock and set into sysmgr boot register */
388 printf("QSPI: Reference clock at %d Hz\n", resp_buf[0]);
389 writel(resp_buf[0],
390 socfpga_get_sysmgr_addr() + SYSMGR_SOC64_BOOT_SCRATCH_COLD0);
391
392 return 0;
393
394 error:
395 mbox_qspi_close();
396
397 return ret;
398 }
399 #endif /* CONFIG_CADENCE_QSPI */
400
mbox_reset_cold(void)401 int mbox_reset_cold(void)
402 {
403 #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF)
404 psci_system_reset();
405 #else
406 int ret;
407
408 ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_REBOOT_HPS, MBOX_CMD_DIRECT,
409 0, NULL, 0, 0, NULL);
410 if (ret) {
411 /* mailbox sent failure, wait for watchdog to kick in */
412 hang();
413 }
414 #endif
415 return 0;
416 }
417
418 /* Accepted commands: CONFIG_STATUS or RECONFIG_STATUS */
mbox_get_fpga_config_status_common(u32 cmd)419 static __always_inline int mbox_get_fpga_config_status_common(u32 cmd)
420 {
421 u32 reconfig_status_resp_len;
422 u32 reconfig_status_resp[RECONFIG_STATUS_RESPONSE_LEN];
423 int ret;
424
425 reconfig_status_resp_len = RECONFIG_STATUS_RESPONSE_LEN;
426 ret = mbox_send_cmd_common_retry(MBOX_ID_UBOOT, cmd,
427 MBOX_CMD_DIRECT, 0, NULL, 0,
428 &reconfig_status_resp_len,
429 reconfig_status_resp);
430
431 if (ret)
432 return ret;
433
434 /* Check for any error */
435 ret = reconfig_status_resp[RECONFIG_STATUS_STATE];
436 if (ret && ret != MBOX_CFGSTAT_STATE_CONFIG)
437 return ret;
438
439 /* Make sure nStatus is not 0 */
440 ret = reconfig_status_resp[RECONFIG_STATUS_PIN_STATUS];
441 if (!(ret & RCF_PIN_STATUS_NSTATUS))
442 return MBOX_CFGSTAT_STATE_ERROR_HARDWARE;
443
444 ret = reconfig_status_resp[RECONFIG_STATUS_SOFTFUNC_STATUS];
445 if (ret & RCF_SOFTFUNC_STATUS_SEU_ERROR)
446 return MBOX_CFGSTAT_STATE_ERROR_HARDWARE;
447
448 if ((ret & RCF_SOFTFUNC_STATUS_CONF_DONE) &&
449 (ret & RCF_SOFTFUNC_STATUS_INIT_DONE) &&
450 !reconfig_status_resp[RECONFIG_STATUS_STATE])
451 return 0; /* configuration success */
452
453 return MBOX_CFGSTAT_STATE_CONFIG;
454 }
455
mbox_get_fpga_config_status(u32 cmd)456 int mbox_get_fpga_config_status(u32 cmd)
457 {
458 return mbox_get_fpga_config_status_common(cmd);
459 }
460
mbox_get_fpga_config_status_psci(u32 cmd)461 int __secure mbox_get_fpga_config_status_psci(u32 cmd)
462 {
463 return mbox_get_fpga_config_status_common(cmd);
464 }
465
mbox_send_cmd(u8 id,u32 cmd,u8 is_indirect,u32 len,u32 * arg,u8 urgent,u32 * resp_buf_len,u32 * resp_buf)466 int mbox_send_cmd(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg,
467 u8 urgent, u32 *resp_buf_len, u32 *resp_buf)
468 {
469 return mbox_send_cmd_common_retry(id, cmd, is_indirect, len, arg,
470 urgent, resp_buf_len, resp_buf);
471 }
472
mbox_send_cmd_psci(u8 id,u32 cmd,u8 is_indirect,u32 len,u32 * arg,u8 urgent,u32 * resp_buf_len,u32 * resp_buf)473 int __secure mbox_send_cmd_psci(u8 id, u32 cmd, u8 is_indirect, u32 len,
474 u32 *arg, u8 urgent, u32 *resp_buf_len,
475 u32 *resp_buf)
476 {
477 return mbox_send_cmd_common_retry(id, cmd, is_indirect, len, arg,
478 urgent, resp_buf_len, resp_buf);
479 }
480
mbox_send_cmd_only(u8 id,u32 cmd,u8 is_indirect,u32 len,u32 * arg)481 int mbox_send_cmd_only(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg)
482 {
483 return mbox_send_cmd_only_common(id, cmd, is_indirect, len, arg);
484 }
485
mbox_send_cmd_only_psci(u8 id,u32 cmd,u8 is_indirect,u32 len,u32 * arg)486 int __secure mbox_send_cmd_only_psci(u8 id, u32 cmd, u8 is_indirect, u32 len,
487 u32 *arg)
488 {
489 return mbox_send_cmd_only_common(id, cmd, is_indirect, len, arg);
490 }
491
mbox_rcv_resp(u32 * resp_buf,u32 resp_buf_max_len)492 int mbox_rcv_resp(u32 *resp_buf, u32 resp_buf_max_len)
493 {
494 return __mbox_rcv_resp(resp_buf, resp_buf_max_len);
495 }
496
mbox_rcv_resp_psci(u32 * resp_buf,u32 resp_buf_max_len)497 int __secure mbox_rcv_resp_psci(u32 *resp_buf, u32 resp_buf_max_len)
498 {
499 return __mbox_rcv_resp(resp_buf, resp_buf_max_len);
500 }
501