1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2017-2018 Intel Corporation <www.intel.com>
11 #include <asm/arch/mailbox_s10.h>
12 #include <asm/arch/system_manager.h>
13 #include <asm/secure.h>
14 #include <asm/system.h>
16 DECLARE_GLOBAL_DATA_PTR;
18 #define MBOX_READL(reg) \
19 readl(SOCFPGA_MAILBOX_ADDRESS + (reg))
21 #define MBOX_WRITEL(data, reg) \
22 writel(data, SOCFPGA_MAILBOX_ADDRESS + (reg))
24 #define MBOX_READ_RESP_BUF(rout) \
25 MBOX_READL(MBOX_RESP_BUF + ((rout) * sizeof(u32)))
27 #define MBOX_WRITE_CMD_BUF(data, cin) \
28 MBOX_WRITEL(data, MBOX_CMD_BUF + ((cin) * sizeof(u32)))
30 static __always_inline int mbox_polling_resp(u32 rout)
33 unsigned long i = 2000;
36 rin = MBOX_READL(MBOX_RIN);
47 static __always_inline int mbox_is_cmdbuf_full(u32 cin)
49 return (((cin + 1) % MBOX_CMD_BUFFER_SIZE) == MBOX_READL(MBOX_COUT));
52 static __always_inline int mbox_is_cmdbuf_empty(u32 cin)
54 return (((MBOX_READL(MBOX_COUT) + 1) % MBOX_CMD_BUFFER_SIZE) == cin);
57 static __always_inline int mbox_wait_for_cmdbuf_empty(u32 cin)
62 if (mbox_is_cmdbuf_empty(cin))
71 static __always_inline int mbox_write_cmd_buffer(u32 *cin, u32 data,
72 int *is_cmdbuf_overflow)
77 if (mbox_is_cmdbuf_full(*cin)) {
78 if (is_cmdbuf_overflow &&
79 *is_cmdbuf_overflow == 0) {
80 /* Trigger SDM doorbell */
81 MBOX_WRITEL(1, MBOX_DOORBELL_TO_SDM);
82 *is_cmdbuf_overflow = 1;
86 /* write header to circular buffer */
87 MBOX_WRITE_CMD_BUF(data, (*cin)++);
88 *cin %= MBOX_CMD_BUFFER_SIZE;
89 MBOX_WRITEL(*cin, MBOX_CIN);
98 /* Wait for the SDM to drain the FIFO command buffer */
99 if (is_cmdbuf_overflow && *is_cmdbuf_overflow)
100 return mbox_wait_for_cmdbuf_empty(*cin);
105 /* Check for available slot and write to circular buffer.
106 * It also update command valid offset (cin) register.
108 static __always_inline int mbox_fill_cmd_circular_buff(u32 header, u32 len,
112 int is_cmdbuf_overflow = 0;
113 u32 cin = MBOX_READL(MBOX_CIN) % MBOX_CMD_BUFFER_SIZE;
115 ret = mbox_write_cmd_buffer(&cin, header, &is_cmdbuf_overflow);
119 /* write arguments */
120 for (i = 0; i < len; i++) {
121 is_cmdbuf_overflow = 0;
122 ret = mbox_write_cmd_buffer(&cin, arg[i], &is_cmdbuf_overflow);
127 /* If SDM doorbell is not triggered after the last data is
128 * written into mailbox FIFO command buffer, trigger the
129 * SDM doorbell again to ensure SDM able to read the remaining
132 if (!is_cmdbuf_overflow)
133 MBOX_WRITEL(1, MBOX_DOORBELL_TO_SDM);
138 /* Check the command and fill it into circular buffer */
139 static __always_inline int mbox_prepare_cmd_only(u8 id, u32 cmd,
140 u8 is_indirect, u32 len,
146 if (cmd > MBOX_MAX_CMD_INDEX)
149 header = MBOX_CMD_HEADER(MBOX_CLIENT_ID_UBOOT, id, len,
150 (is_indirect) ? 1 : 0, cmd);
152 ret = mbox_fill_cmd_circular_buff(header, len, arg);
157 /* Send command only without waiting for responses from SDM */
158 static __always_inline int mbox_send_cmd_only_common(u8 id, u32 cmd,
159 u8 is_indirect, u32 len,
162 return mbox_prepare_cmd_only(id, cmd, is_indirect, len, arg);
165 /* Return number of responses received in buffer */
166 static __always_inline int __mbox_rcv_resp(u32 *resp_buf, u32 resp_buf_max_len)
172 /* clear doorbell from SDM if it was SET */
173 if (MBOX_READL(MBOX_DOORBELL_FROM_SDM) & 1)
174 MBOX_WRITEL(0, MBOX_DOORBELL_FROM_SDM);
176 /* read current response offset */
177 rout = MBOX_READL(MBOX_ROUT);
178 /* read response valid offset */
179 rin = MBOX_READL(MBOX_RIN);
181 while (rin != rout && (resp_len < resp_buf_max_len)) {
182 /* Response received */
184 resp_buf[resp_len++] = MBOX_READ_RESP_BUF(rout);
187 /* wrapping around when it reach the buffer size */
188 rout %= MBOX_RESP_BUFFER_SIZE;
189 /* update next ROUT */
190 MBOX_WRITEL(rout, MBOX_ROUT);
196 /* Support one command and up to 31 words argument length only */
197 static __always_inline int mbox_send_cmd_common(u8 id, u32 cmd, u8 is_indirect,
198 u32 len, u32 *arg, u8 urgent,
211 /* Read status because it is toggled */
212 status = MBOX_READL(MBOX_STATUS) & MBOX_STATUS_UA_MSK;
213 /* Write urgent command to urgent register */
214 MBOX_WRITEL(cmd, MBOX_URG);
216 MBOX_WRITEL(1, MBOX_DOORBELL_TO_SDM);
218 ret = mbox_prepare_cmd_only(id, cmd, is_indirect, len, arg);
226 /* Wait for doorbell from SDM */
228 if (MBOX_READL(MBOX_DOORBELL_FROM_SDM))
236 /* clear interrupt */
237 MBOX_WRITEL(0, MBOX_DOORBELL_FROM_SDM);
240 u32 new_status = MBOX_READL(MBOX_STATUS);
242 /* Urgent ACK is toggled */
243 if ((new_status & MBOX_STATUS_UA_MSK) ^ status)
249 /* read current response offset */
250 rout = MBOX_READL(MBOX_ROUT);
252 /* read response valid offset */
253 rin = MBOX_READL(MBOX_RIN);
256 /* Response received */
257 resp = MBOX_READ_RESP_BUF(rout);
259 /* wrapping around when it reach the buffer size */
260 rout %= MBOX_RESP_BUFFER_SIZE;
261 /* update next ROUT */
262 MBOX_WRITEL(rout, MBOX_ROUT);
264 /* check client ID and ID */
265 if ((MBOX_RESP_CLIENT_GET(resp) ==
266 MBOX_CLIENT_ID_UBOOT) &&
267 (MBOX_RESP_ID_GET(resp) == id)) {
268 int resp_err = MBOX_RESP_ERR_GET(resp);
271 buf_len = *resp_buf_len;
277 resp_len = MBOX_RESP_LEN_GET(resp);
279 ret = mbox_polling_resp(rout);
282 /* we need to process response buffer
283 * even caller doesn't need it
285 resp = MBOX_READ_RESP_BUF(rout);
288 rout %= MBOX_RESP_BUFFER_SIZE;
289 MBOX_WRITEL(rout, MBOX_ROUT);
291 /* copy response to buffer */
292 resp_buf[*resp_buf_len] = resp;
305 static __always_inline int mbox_send_cmd_common_retry(u8 id, u32 cmd,
315 for (i = 0; i < 3; i++) {
316 ret = mbox_send_cmd_common(id, cmd, is_indirect, len, arg,
317 urgent, resp_buf_len, resp_buf);
318 if (ret == MBOX_RESP_TIMEOUT || ret == MBOX_RESP_DEVICE_BUSY)
319 udelay(2000); /* wait for 2ms before resend */
331 /* enable mailbox interrupts */
332 MBOX_WRITEL(MBOX_ALL_INTRS, MBOX_FLAGS);
334 /* Ensure urgent request is cleared */
335 MBOX_WRITEL(0, MBOX_URG);
337 /* Ensure the Doorbell Interrupt is cleared */
338 MBOX_WRITEL(0, MBOX_DOORBELL_FROM_SDM);
340 ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_RESTART, MBOX_CMD_DIRECT, 0,
345 /* Renable mailbox interrupts after MBOX_RESTART */
346 MBOX_WRITEL(MBOX_ALL_INTRS, MBOX_FLAGS);
351 #ifdef CONFIG_CADENCE_QSPI
352 int mbox_qspi_close(void)
354 return mbox_send_cmd(MBOX_ID_UBOOT, MBOX_QSPI_CLOSE, MBOX_CMD_DIRECT,
355 0, NULL, 0, 0, NULL);
358 int mbox_qspi_open(void)
364 ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_QSPI_OPEN, MBOX_CMD_DIRECT,
365 0, NULL, 0, 0, NULL);
367 /* retry again by closing and reopen the QSPI again */
368 ret = mbox_qspi_close();
372 ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_QSPI_OPEN,
373 MBOX_CMD_DIRECT, 0, NULL, 0, 0, NULL);
378 /* HPS will directly control the QSPI controller, no longer mailbox */
380 ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_QSPI_DIRECT, MBOX_CMD_DIRECT,
381 0, NULL, 0, (u32 *)&resp_buf_len,
386 /* We are getting QSPI ref clock and set into sysmgr boot register */
387 printf("QSPI: Reference clock at %d Hz\n", resp_buf[0]);
389 socfpga_get_sysmgr_addr() + SYSMGR_SOC64_BOOT_SCRATCH_COLD0);
398 #endif /* CONFIG_CADENCE_QSPI */
400 int mbox_reset_cold(void)
402 #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF)
407 ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_REBOOT_HPS, MBOX_CMD_DIRECT,
408 0, NULL, 0, 0, NULL);
410 /* mailbox sent failure, wait for watchdog to kick in */
417 /* Accepted commands: CONFIG_STATUS or RECONFIG_STATUS */
418 static __always_inline int mbox_get_fpga_config_status_common(u32 cmd)
420 u32 reconfig_status_resp_len;
421 u32 reconfig_status_resp[RECONFIG_STATUS_RESPONSE_LEN];
424 reconfig_status_resp_len = RECONFIG_STATUS_RESPONSE_LEN;
425 ret = mbox_send_cmd_common_retry(MBOX_ID_UBOOT, cmd,
426 MBOX_CMD_DIRECT, 0, NULL, 0,
427 &reconfig_status_resp_len,
428 reconfig_status_resp);
433 /* Check for any error */
434 ret = reconfig_status_resp[RECONFIG_STATUS_STATE];
435 if (ret && ret != MBOX_CFGSTAT_STATE_CONFIG)
438 /* Make sure nStatus is not 0 */
439 ret = reconfig_status_resp[RECONFIG_STATUS_PIN_STATUS];
440 if (!(ret & RCF_PIN_STATUS_NSTATUS))
441 return MBOX_CFGSTAT_STATE_ERROR_HARDWARE;
443 ret = reconfig_status_resp[RECONFIG_STATUS_SOFTFUNC_STATUS];
444 if (ret & RCF_SOFTFUNC_STATUS_SEU_ERROR)
445 return MBOX_CFGSTAT_STATE_ERROR_HARDWARE;
447 if ((ret & RCF_SOFTFUNC_STATUS_CONF_DONE) &&
448 (ret & RCF_SOFTFUNC_STATUS_INIT_DONE) &&
449 !reconfig_status_resp[RECONFIG_STATUS_STATE])
450 return 0; /* configuration success */
452 return MBOX_CFGSTAT_STATE_CONFIG;
455 int mbox_get_fpga_config_status(u32 cmd)
457 return mbox_get_fpga_config_status_common(cmd);
460 int __secure mbox_get_fpga_config_status_psci(u32 cmd)
462 return mbox_get_fpga_config_status_common(cmd);
465 int mbox_send_cmd(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg,
466 u8 urgent, u32 *resp_buf_len, u32 *resp_buf)
468 return mbox_send_cmd_common_retry(id, cmd, is_indirect, len, arg,
469 urgent, resp_buf_len, resp_buf);
472 int __secure mbox_send_cmd_psci(u8 id, u32 cmd, u8 is_indirect, u32 len,
473 u32 *arg, u8 urgent, u32 *resp_buf_len,
476 return mbox_send_cmd_common_retry(id, cmd, is_indirect, len, arg,
477 urgent, resp_buf_len, resp_buf);
480 int mbox_send_cmd_only(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg)
482 return mbox_send_cmd_only_common(id, cmd, is_indirect, len, arg);
485 int __secure mbox_send_cmd_only_psci(u8 id, u32 cmd, u8 is_indirect, u32 len,
488 return mbox_send_cmd_only_common(id, cmd, is_indirect, len, arg);
491 int mbox_rcv_resp(u32 *resp_buf, u32 resp_buf_max_len)
493 return __mbox_rcv_resp(resp_buf, resp_buf_max_len);
496 int __secure mbox_rcv_resp_psci(u32 *resp_buf, u32 resp_buf_max_len)
498 return __mbox_rcv_resp(resp_buf, resp_buf_max_len);