1 /*
2 * Copyright (c) 2020-2023, Intel Corporation. All rights reserved.
3 * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include <lib/mmio.h>
9 #include <lib/spinlock.h>
10 #include <common/debug.h>
11 #include <drivers/delay_timer.h>
12 #include <platform_def.h>
13
14 #include "socfpga_mailbox.h"
15 #include "socfpga_plat_def.h"
16 #include "socfpga_private.h"
17 #include "socfpga_sip_svc.h"
18 #include "socfpga_system_manager.h"
19
20 #if SIP_SVC_V3
21 /* Function prototypes */
22 void mailbox_init_v3(void);
23 static int mailbox_response_handler_fsm(void);
24 static inline void mailbox_free_cmd_desc(sdm_command_t *cmd_desc);
25 static sdm_response_t *mailbox_get_resp_desc(uint8_t client_id, uint8_t job_id,
26 uint8_t *index);
27 static sdm_command_t *mailbox_get_cmd_desc(uint8_t client_id, uint8_t job_id);
28 static inline void mailbox_free_resp_desc(uint8_t index);
29 static sdm_command_t *mailbox_get_free_cmd_desc(void);
30 static sdm_response_t *mailbox_get_resp_desc_cid(uint8_t client_id,
31 uint8_t *index);
32 static int mailbox_read_response_v3(uint8_t client_id, uint8_t *job_id,
33 uint32_t *header, uint32_t *resp,
34 uint32_t *resp_len,
35 uint8_t ignore_client_id);
36 static int mailbox_poll_response_v3(uint8_t client_id, uint8_t job_id,
37 uint32_t *resp, unsigned int *resp_len,
38 uint32_t urgent);
39
40 static spinlock_t mbox_db_lock; /* Mailbox service data base lock */
41 static spinlock_t mbox_write_lock; /* Hardware mailbox FIFO write lock */
42 static spinlock_t mbox_read_lock; /* Hardware mailbox FIFO read lock */
43
44 static mailbox_service_t mbox_svc; /* Mailbox service data base */
45 static uint8_t async_v1_job_id;
46 #endif /* #if SIP_SVC_V3 */
47
48 static mailbox_payload_t mailbox_resp_payload;
49 static mailbox_container_t mailbox_resp_ctr = {0, 0, &mailbox_resp_payload};
50
is_mailbox_cmdbuf_full(uint32_t cin)51 static bool is_mailbox_cmdbuf_full(uint32_t cin)
52 {
53 uint32_t cout = mmio_read_32(MBOX_OFFSET + MBOX_COUT);
54
55 return (((cin + 1U) % MBOX_CMD_BUFFER_SIZE) == cout);
56 }
57
is_mailbox_cmdbuf_empty(uint32_t cin)58 static bool is_mailbox_cmdbuf_empty(uint32_t cin)
59 {
60 uint32_t cout = mmio_read_32(MBOX_OFFSET + MBOX_COUT);
61
62 return (((cout + 1U) % MBOX_CMD_BUFFER_SIZE) == cin);
63 }
64
wait_for_mailbox_cmdbuf_empty(uint32_t cin)65 static int wait_for_mailbox_cmdbuf_empty(uint32_t cin)
66 {
67 unsigned int timeout = 20000U;
68
69 do {
70 if (is_mailbox_cmdbuf_empty(cin)) {
71 break;
72 }
73 udelay(50U);
74 } while (--timeout != 0U);
75
76 if (timeout == 0U) {
77 return MBOX_TIMEOUT;
78 }
79
80 return MBOX_RET_OK;
81 }
82
write_mailbox_cmd_buffer(uint32_t * cin,uint32_t cout,uint32_t data,bool * is_doorbell_triggered)83 static int write_mailbox_cmd_buffer(uint32_t *cin, uint32_t cout,
84 uint32_t data,
85 bool *is_doorbell_triggered)
86 {
87 unsigned int timeout = 20000U;
88
89 VERBOSE("MBOX: 0x%x\n", data);
90
91 do {
92 if (is_mailbox_cmdbuf_full(*cin)) {
93 if (!(*is_doorbell_triggered)) {
94 mmio_write_32(MBOX_OFFSET +
95 MBOX_DOORBELL_TO_SDM, 1U);
96 *is_doorbell_triggered = true;
97 }
98 udelay(50U);
99 } else {
100 mmio_write_32(MBOX_ENTRY_TO_ADDR(CMD, (*cin)++), data);
101 *cin %= MBOX_CMD_BUFFER_SIZE;
102 mmio_write_32(MBOX_OFFSET + MBOX_CIN, *cin);
103 break;
104 }
105 } while (--timeout != 0U);
106
107 if (timeout == 0U) {
108 return MBOX_TIMEOUT;
109 }
110
111 if (*is_doorbell_triggered) {
112 int ret = wait_for_mailbox_cmdbuf_empty(*cin);
113 return ret;
114 }
115
116 return MBOX_RET_OK;
117 }
118
119 /*
120 * Function description: Write the command header, and its payload one by one
121 * into the mailbox command buffer. Along with this, check for mailbox buffer
122 * full condition and trigger doorbell to SDM if the command buffer is full.
123 */
fill_mailbox_circular_buffer(uint32_t header_cmd,uint32_t * args,unsigned int len)124 static int fill_mailbox_circular_buffer(uint32_t header_cmd, uint32_t *args,
125 unsigned int len)
126 {
127 uint32_t sdm_read_offset, cmd_free_offset;
128 unsigned int i;
129 int ret;
130 bool is_doorbell_triggered = false;
131
132 #if SIP_SVC_V3
133 spin_lock(&mbox_write_lock);
134 #endif
135
136 cmd_free_offset = mmio_read_32(MBOX_OFFSET + MBOX_CIN);
137 sdm_read_offset = mmio_read_32(MBOX_OFFSET + MBOX_COUT);
138
139 /* Write the command header here */
140 ret = write_mailbox_cmd_buffer(&cmd_free_offset, sdm_read_offset,
141 header_cmd, &is_doorbell_triggered);
142 if (ret != 0) {
143 goto restart_mailbox;
144 }
145
146 /* Write the payload here w.r.to args and its len - one by one. */
147 for (i = 0U; i < len; i++) {
148 is_doorbell_triggered = false;
149 ret = write_mailbox_cmd_buffer(&cmd_free_offset,
150 sdm_read_offset, args[i],
151 &is_doorbell_triggered);
152 if (ret != 0) {
153 goto restart_mailbox;
154 }
155 }
156
157 mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U);
158
159 #if SIP_SVC_V3
160 spin_unlock(&mbox_write_lock);
161 #endif
162 return MBOX_RET_OK;
163
164 restart_mailbox:
165 /*
166 * Attempt to restart mailbox if the driver not able to write
167 * into mailbox command buffer
168 */
169 if (MBOX_CMD_MASK(header_cmd) != MBOX_CMD_RESTART) {
170 INFO("Mailbox timed out: Attempting mailbox reset\n");
171 ret = mailbox_init();
172
173 if (ret == MBOX_TIMEOUT) {
174 INFO("Error: Mailbox fail to restart\n");
175 }
176 }
177
178 #if SIP_SVC_V3
179 spin_unlock(&mbox_write_lock);
180 #endif
181 return MBOX_TIMEOUT;
182 }
183
mailbox_read_response(unsigned int * job_id,uint32_t * response,unsigned int * resp_len)184 int mailbox_read_response(unsigned int *job_id, uint32_t *response,
185 unsigned int *resp_len)
186 {
187 #if SIP_SVC_V3
188 return mailbox_read_response_v3(MBOX_ATF_CLIENT_ID,
189 (uint8_t *)job_id, NULL,
190 response, resp_len,
191 0);
192 #else
193 uint32_t rin;
194 uint32_t rout;
195 uint32_t resp_data;
196 unsigned int ret_resp_len;
197
198 if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM) == 1U) {
199 mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U);
200 }
201
202 rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
203 rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
204
205 if (rout != rin) {
206 resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++));
207
208 rout %= MBOX_RESP_BUFFER_SIZE;
209 mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
210
211
212 if (MBOX_RESP_CLIENT_ID(resp_data) != MBOX_ATF_CLIENT_ID) {
213 return MBOX_WRONG_ID;
214 }
215
216 *job_id = MBOX_RESP_JOB_ID(resp_data);
217
218 ret_resp_len = MBOX_RESP_LEN(resp_data);
219
220 if (iterate_resp(ret_resp_len, response, resp_len)
221 != MBOX_RET_OK) {
222 return MBOX_TIMEOUT;
223 }
224
225 if (MBOX_RESP_ERR(resp_data) > 0U) {
226 INFO("SDM response: Return Code: 0x%x\n", MBOX_RESP_ERR(resp_data));
227 return -MBOX_RESP_ERR(resp_data);
228 }
229
230 return MBOX_RET_OK;
231 }
232
233 return MBOX_NO_RESPONSE;
234 #endif
235 }
236
mailbox_read_response_async(unsigned int * job_id,uint32_t * header,uint32_t * response,unsigned int * resp_len,uint8_t ignore_client_id)237 int mailbox_read_response_async(unsigned int *job_id, uint32_t *header,
238 uint32_t *response, unsigned int *resp_len,
239 uint8_t ignore_client_id)
240 {
241 #if SIP_SVC_V3
242 /* Just to avoid the build warning */
243 (void)mailbox_resp_ctr;
244 return mailbox_read_response_v3(MBOX_ATF_CLIENT_ID,
245 (uint8_t *)job_id, header,
246 response, resp_len,
247 ignore_client_id);
248 #else
249 uint32_t rin;
250 uint32_t rout;
251 uint32_t resp_data;
252 uint32_t ret_resp_len = 0;
253 uint8_t is_done = 0;
254 uint32_t resp_len_check = 0;
255
256 if ((mailbox_resp_ctr.flag & MBOX_PAYLOAD_FLAG_BUSY) != 0) {
257 ret_resp_len = MBOX_RESP_LEN(
258 mailbox_resp_ctr.payload->header) -
259 mailbox_resp_ctr.index;
260 }
261
262 if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM) == 1U) {
263 mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U);
264 }
265
266 rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
267 rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
268
269 while (rout != rin && !is_done) {
270
271 resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++));
272
273 rout %= MBOX_RESP_BUFFER_SIZE;
274 mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
275 rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
276
277 if ((mailbox_resp_ctr.flag & MBOX_PAYLOAD_FLAG_BUSY) != 0) {
278 mailbox_resp_ctr.payload->data[mailbox_resp_ctr.index] = resp_data;
279 mailbox_resp_ctr.index++;
280 ret_resp_len--;
281 } else {
282 if (!ignore_client_id) {
283 if (MBOX_RESP_CLIENT_ID(resp_data) != MBOX_ATF_CLIENT_ID) {
284 *resp_len = 0;
285 return MBOX_WRONG_ID;
286 }
287 }
288 *job_id = MBOX_RESP_JOB_ID(resp_data);
289 ret_resp_len = MBOX_RESP_LEN(resp_data);
290 mailbox_resp_ctr.payload->header = resp_data;
291 mailbox_resp_ctr.flag |= MBOX_PAYLOAD_FLAG_BUSY;
292 }
293
294 if (ret_resp_len == 0) {
295 is_done = 1;
296 }
297 }
298
299 if (is_done != 0) {
300
301 /* copy header data to input address if applicable */
302 if (header != 0) {
303 *header = mailbox_resp_ctr.payload->header;
304 }
305
306 /* copy response data to input buffer if applicable */
307 ret_resp_len = MBOX_RESP_LEN(mailbox_resp_ctr.payload->header);
308 if ((ret_resp_len > 0) && (response != NULL) && (resp_len != NULL)) {
309 if (*resp_len > ret_resp_len) {
310 *resp_len = ret_resp_len;
311 }
312
313 resp_len_check = (uint32_t) *resp_len;
314
315 if (resp_len_check > MBOX_DATA_MAX_LEN) {
316 return MBOX_RET_ERROR;
317 }
318
319 memcpy_s((uint8_t *) response, *resp_len * MBOX_WORD_BYTE,
320 (uint8_t *) mailbox_resp_ctr.payload->data,
321 *resp_len * MBOX_WORD_BYTE);
322 }
323
324 /* reset async response param */
325 mailbox_resp_ctr.index = 0;
326 mailbox_resp_ctr.flag = 0;
327
328 if (MBOX_RESP_ERR(mailbox_resp_ctr.payload->header) > 0U) {
329 INFO("Error in async response: %x\n",
330 mailbox_resp_ctr.payload->header);
331 return -MBOX_RESP_ERR(mailbox_resp_ctr.payload->header);
332 }
333
334 return MBOX_RET_OK;
335 }
336
337 *resp_len = 0;
338 return (mailbox_resp_ctr.flag & MBOX_PAYLOAD_FLAG_BUSY) ? MBOX_BUSY : MBOX_NO_RESPONSE;
339 #endif
340 }
341
mailbox_poll_response(uint32_t job_id,uint32_t urgent,uint32_t * response,unsigned int * resp_len)342 int mailbox_poll_response(uint32_t job_id, uint32_t urgent, uint32_t *response,
343 unsigned int *resp_len)
344 {
345 #if SIP_SVC_V3
346 return mailbox_poll_response_v3(MBOX_ATF_CLIENT_ID, (uint8_t)job_id,
347 response, resp_len, urgent);
348 #else
349 unsigned int timeout = 40U;
350 unsigned int sdm_loop = 255U;
351 unsigned int ret_resp_len;
352 uint32_t rin;
353 uint32_t rout;
354 uint32_t resp_data;
355
356 while (sdm_loop != 0U) {
357 do {
358 if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM)
359 == 1U) {
360 break;
361 }
362 mdelay(10U);
363 } while (--timeout != 0U);
364
365 if (timeout == 0U) {
366 break;
367 }
368
369 mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U);
370
371 if ((urgent & 1U) != 0U) {
372 mdelay(5U);
373 if ((mmio_read_32(MBOX_OFFSET + MBOX_STATUS) &
374 MBOX_STATUS_UA_MASK) ^
375 (urgent & MBOX_STATUS_UA_MASK)) {
376 mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U);
377 return MBOX_RET_OK;
378 }
379
380 mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U);
381 ERROR("MBOX: Mailbox did not get UA");
382 return MBOX_RET_ERROR;
383 }
384
385 rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
386 rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
387
388 while (rout != rin) {
389 resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP,
390 (rout)++));
391
392 rout %= MBOX_RESP_BUFFER_SIZE;
393 mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
394
395 if ((MBOX_RESP_CLIENT_ID(resp_data) != MBOX_ATF_CLIENT_ID) ||
396 (MBOX_RESP_JOB_ID(resp_data) != job_id)) {
397 continue;
398 }
399
400 /* Get the return response len from the response header. */
401 ret_resp_len = MBOX_RESP_LEN(resp_data);
402
403 /* Print the response header. */
404 VERBOSE("MBOX: RespHdr: cid %d, jid %d, len %d, err_code 0x%x\n",
405 MBOX_RESP_CLIENT_ID(resp_data),
406 MBOX_RESP_JOB_ID(resp_data),
407 MBOX_RESP_LEN(resp_data),
408 MBOX_RESP_ERR(resp_data));
409
410 if (iterate_resp(ret_resp_len, response, resp_len)
411 != MBOX_RET_OK) {
412 return MBOX_TIMEOUT;
413 }
414
415 if (MBOX_RESP_ERR(resp_data) > 0U) {
416 INFO("SDM response: Return Code: 0x%x\n", MBOX_RESP_ERR(resp_data));
417 return -MBOX_RESP_ERR(resp_data);
418 }
419
420 return MBOX_RET_OK;
421 }
422
423 sdm_loop--;
424 }
425
426 INFO("Timed out waiting for SDM\n");
427 return MBOX_TIMEOUT;
428 #endif
429 }
430
iterate_resp(uint32_t mbox_resp_len,uint32_t * resp_buf,unsigned int * resp_len)431 int iterate_resp(uint32_t mbox_resp_len, uint32_t *resp_buf,
432 unsigned int *resp_len)
433 {
434 unsigned int timeout, total_resp_len = 0U;
435 uint32_t resp_data;
436 uint32_t rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
437 uint32_t rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
438
439 while (mbox_resp_len > 0U) {
440 timeout = 100U;
441 mbox_resp_len--;
442 resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++));
443
444 if ((resp_buf != NULL) && (resp_len != NULL)
445 && (*resp_len != 0U)) {
446 *(resp_buf + total_resp_len) = resp_data;
447 *resp_len = *resp_len - 1;
448 total_resp_len++;
449 }
450 rout %= MBOX_RESP_BUFFER_SIZE;
451 mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
452
453 do {
454 rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
455 if (rout == rin) {
456 mdelay(10U);
457 } else {
458 break;
459 }
460 timeout--;
461 } while ((mbox_resp_len > 0U) && (timeout != 0U));
462
463 if (timeout == 0U) {
464 INFO("Timed out waiting for SDM\n");
465 return MBOX_TIMEOUT;
466 }
467 }
468
469 if (resp_len)
470 *resp_len = total_resp_len;
471
472 return MBOX_RET_OK;
473 }
474
mailbox_send_cmd_async_ext(uint32_t header_cmd,uint32_t * args,unsigned int len)475 int mailbox_send_cmd_async_ext(uint32_t header_cmd, uint32_t *args,
476 unsigned int len)
477 {
478 return fill_mailbox_circular_buffer(header_cmd, args, len);
479 }
480
mailbox_send_cmd_async(uint32_t * job_id,uint32_t cmd,uint32_t * args,unsigned int len,unsigned int indirect)481 int mailbox_send_cmd_async(uint32_t *job_id, uint32_t cmd, uint32_t *args,
482 unsigned int len, unsigned int indirect)
483 {
484 int status;
485
486 status = fill_mailbox_circular_buffer(
487 MBOX_CLIENT_ID_CMD(MBOX_ATF_CLIENT_ID) |
488 MBOX_JOB_ID_CMD(*job_id) |
489 MBOX_CMD_LEN_CMD(len) |
490 MBOX_INDIRECT(indirect) |
491 cmd, args, len);
492 if (status < 0) {
493 return status;
494 }
495
496 #if SIP_SVC_V3
497 async_v1_job_id = (uint8_t)*job_id;
498 #endif
499 *job_id = (*job_id + 1U) % MBOX_MAX_IND_JOB_ID;
500
501 return MBOX_RET_OK;
502 }
503
mailbox_send_cmd(uint32_t job_id,uint32_t cmd,uint32_t * args,unsigned int len,uint32_t urgent,uint32_t * response,unsigned int * resp_len)504 int mailbox_send_cmd(uint32_t job_id, uint32_t cmd, uint32_t *args,
505 unsigned int len, uint32_t urgent, uint32_t *response,
506 unsigned int *resp_len)
507 {
508 int status = 0;
509
510 if (urgent != 0U) {
511 urgent |= mmio_read_32(MBOX_OFFSET + MBOX_STATUS) &
512 MBOX_STATUS_UA_MASK;
513 mmio_write_32(MBOX_OFFSET + MBOX_URG, cmd);
514 mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U);
515 } else {
516 status = fill_mailbox_circular_buffer(
517 MBOX_CLIENT_ID_CMD(MBOX_ATF_CLIENT_ID) |
518 MBOX_JOB_ID_CMD(job_id) |
519 MBOX_CMD_LEN_CMD(len) |
520 cmd, args, len);
521 }
522
523 if (status != 0) {
524 return status;
525 }
526
527 status = mailbox_poll_response(job_id, urgent, response, resp_len);
528
529 return status;
530 }
531
mailbox_clear_response(void)532 void mailbox_clear_response(void)
533 {
534 mmio_write_32(MBOX_OFFSET + MBOX_ROUT,
535 mmio_read_32(MBOX_OFFSET + MBOX_RIN));
536 }
537
mailbox_set_int(uint32_t interrupt)538 void mailbox_set_int(uint32_t interrupt)
539 {
540 mmio_write_32(MBOX_OFFSET+MBOX_INT,
541 MBOX_COE_BIT(interrupt) |
542 MBOX_RIE_BIT(interrupt) |
543 MBOX_UAE_BIT(interrupt));
544 }
545
mailbox_set_qspi_open(void)546 void mailbox_set_qspi_open(void)
547 {
548 mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
549 mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_OPEN, NULL, 0U,
550 CMD_CASUAL, NULL, NULL);
551 }
552
mailbox_set_qspi_direct(void)553 void mailbox_set_qspi_direct(void)
554 {
555 uint32_t response[1], qspi_clk, reg;
556 unsigned int resp_len = ARRAY_SIZE(response);
557
558 mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_DIRECT, NULL, 0U,
559 CMD_CASUAL, response, &resp_len);
560
561 qspi_clk = response[0];
562 INFO("QSPI ref clock: %u\n", qspi_clk);
563
564 /*
565 * Store QSPI ref clock frequency in BOOT_SCRATCH_COLD_0 register for
566 * later boot loader (i.e. u-boot) use.
567 * The frequency is stored in kHz and occupies BOOT_SCRATCH_COLD_0
568 * register bits[27:0].
569 */
570 qspi_clk /= 1000;
571 reg = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_0));
572 reg &= ~SYSMGR_QSPI_REFCLK_MASK;
573 reg |= qspi_clk & SYSMGR_QSPI_REFCLK_MASK;
574 mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_0), reg);
575 }
576
mailbox_set_qspi_close(void)577 void mailbox_set_qspi_close(void)
578 {
579 mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
580 mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_CLOSE, NULL, 0U,
581 CMD_CASUAL, NULL, NULL);
582 }
583
mailbox_qspi_set_cs(uint32_t device_select)584 void mailbox_qspi_set_cs(uint32_t device_select)
585 {
586 uint32_t cs_setting;
587
588 /* QSPI device select settings at 31:28 */
589 cs_setting = (device_select << 28);
590 mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
591 mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_SET_CS, &cs_setting,
592 1U, CMD_CASUAL, NULL, NULL);
593 }
594
mailbox_hps_qspi_enable(void)595 void mailbox_hps_qspi_enable(void)
596 {
597 mailbox_set_qspi_open();
598 mailbox_set_qspi_direct();
599 }
600
mailbox_reset_cold(void)601 void mailbox_reset_cold(void)
602 {
603 mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
604
605 mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_REBOOT_HPS, 0U, 0U,
606 CMD_CASUAL, NULL, NULL);
607 }
608
mailbox_reset_warm(uint32_t reset_type)609 void mailbox_reset_warm(uint32_t reset_type)
610 {
611 mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
612
613 reset_type = 0x01; // Warm reset header data must be 1
614 mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_REBOOT_HPS, &reset_type, 1U,
615 CMD_CASUAL, NULL, NULL);
616 }
617
mailbox_rsu_get_spt_offset(uint32_t * resp_buf,unsigned int resp_buf_len)618 int mailbox_rsu_get_spt_offset(uint32_t *resp_buf, unsigned int resp_buf_len)
619 {
620 return mailbox_send_cmd(MBOX_JOB_ID, MBOX_GET_SUBPARTITION_TABLE,
621 NULL, 0U, CMD_CASUAL, resp_buf,
622 &resp_buf_len);
623 }
624
625 struct rsu_status_info {
626 uint64_t current_image;
627 uint64_t fail_image;
628 uint32_t state;
629 uint32_t version;
630 uint32_t error_location;
631 uint32_t error_details;
632 uint32_t retry_counter;
633 };
634
mailbox_rsu_status(uint32_t * resp_buf,unsigned int resp_buf_len)635 int mailbox_rsu_status(uint32_t *resp_buf, unsigned int resp_buf_len)
636 {
637 int ret;
638 struct rsu_status_info *info = (struct rsu_status_info *)resp_buf;
639
640 info->retry_counter = ~0U;
641
642 ret = mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_STATUS, NULL, 0U,
643 CMD_CASUAL, resp_buf,
644 &resp_buf_len);
645
646 if (ret < 0) {
647 return ret;
648 }
649
650 if (info->retry_counter != ~0U) {
651 if ((info->version & RSU_VERSION_ACMF_MASK) == 0U) {
652 info->version |= RSU_VERSION_ACMF;
653 }
654 }
655
656 return ret;
657 }
658
mailbox_rsu_get_device_info(uint32_t * resp_buf,unsigned int resp_buf_len)659 int mailbox_rsu_get_device_info(uint32_t *resp_buf, unsigned int resp_buf_len)
660 {
661 return mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_GET_DEVICE_INFO, NULL, 0U,
662 CMD_CASUAL, resp_buf,
663 &resp_buf_len);
664 }
665
mailbox_rsu_update(uint32_t * flash_offset)666 int mailbox_rsu_update(uint32_t *flash_offset)
667 {
668 return mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_UPDATE,
669 flash_offset, 2U,
670 CMD_CASUAL, NULL, NULL);
671 }
672
mailbox_hps_stage_notify(uint32_t execution_stage)673 int mailbox_hps_stage_notify(uint32_t execution_stage)
674 {
675 return mailbox_send_cmd(MBOX_JOB_ID, MBOX_HPS_STAGE_NOTIFY,
676 &execution_stage, 1U, CMD_CASUAL,
677 NULL, NULL);
678 }
679
mailbox_init(void)680 int mailbox_init(void)
681 {
682 int status;
683
684 mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE |
685 MBOX_INT_FLAG_UAE);
686
687 mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U);
688 mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U);
689
690 status = mailbox_send_cmd(0U, MBOX_CMD_RESTART, NULL, 0U,
691 CMD_URGENT, NULL, NULL);
692
693 if (status != 0) {
694 return status;
695 }
696
697 #if SIP_SVC_V3
698 /* Initialize the mailbox version3 implementation, and in V3 we
699 * are interested in only RIE interrupt
700 */
701 mailbox_init_v3();
702 mailbox_set_int(MBOX_INT_FLAG_RIE);
703 #else
704 mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE |
705 MBOX_INT_FLAG_UAE);
706 #endif
707
708 return MBOX_RET_OK;
709 }
710
mailbox_send_fpga_config_comp(void)711 int mailbox_send_fpga_config_comp(void)
712 {
713 int ret;
714
715 ret = mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_FPGA_CONFIG_COMP, NULL, 0U,
716 CMD_CASUAL, NULL, NULL);
717
718 if (ret != 0) {
719 INFO("SOCFPGA: FPGA configuration complete response, Return Code: 0x%x\n",
720 MBOX_RESP_ERR(-ret));
721 return MBOX_RET_ERROR;
722 }
723
724 return MBOX_RET_OK;
725 }
726
intel_mailbox_get_config_status(uint32_t cmd,bool init_done,uint32_t * err_states)727 int intel_mailbox_get_config_status(uint32_t cmd, bool init_done,
728 uint32_t *err_states)
729 {
730 int status;
731 uint32_t res, response[6];
732 unsigned int resp_len = ARRAY_SIZE(response);
733
734 status = mailbox_send_cmd(MBOX_JOB_ID, cmd, NULL, 0U, CMD_CASUAL,
735 response, &resp_len);
736
737 if (status < 0) {
738 return status;
739 }
740
741 res = response[RECONFIG_STATUS_STATE];
742
743 if (err_states != NULL)
744 *err_states = res;
745
746 if (res == MBOX_CFGSTAT_VAB_BS_PREAUTH) {
747 return MBOX_CFGSTAT_STATE_CONFIG;
748 }
749
750 if ((res != 0U) && (res != MBOX_CFGSTAT_STATE_CONFIG)) {
751 return res;
752 }
753
754 res = response[RECONFIG_STATUS_PIN_STATUS];
755 if ((res & PIN_STATUS_NSTATUS) == 0U) {
756 return MBOX_CFGSTAT_STATE_ERROR_HARDWARE;
757 }
758
759 res = response[RECONFIG_STATUS_SOFTFUNC_STATUS];
760 if ((res & SOFTFUNC_STATUS_SEU_ERROR) != 0U) {
761 return MBOX_CFGSTAT_STATE_ERROR_HARDWARE;
762 }
763
764 if ((res & SOFTFUNC_STATUS_CONF_DONE) == 0U) {
765 return MBOX_CFGSTAT_STATE_CONFIG;
766 }
767
768 if (init_done && (res & SOFTFUNC_STATUS_INIT_DONE) == 0U) {
769 return MBOX_CFGSTAT_STATE_CONFIG;
770 }
771
772 return MBOX_RET_OK;
773 }
774
intel_mailbox_is_fpga_not_ready(void)775 int intel_mailbox_is_fpga_not_ready(void)
776 {
777 int ret = intel_mailbox_get_config_status(MBOX_RECONFIG_STATUS, true, NULL);
778
779 if ((ret != MBOX_RET_OK) && (ret != MBOX_CFGSTAT_STATE_CONFIG)) {
780 ret = intel_mailbox_get_config_status(MBOX_CONFIG_STATUS,
781 false, NULL);
782 }
783
784 return ret;
785 }
786
mailbox_hwmon_readtemp(uint32_t chan,uint32_t * resp_buf)787 int mailbox_hwmon_readtemp(uint32_t chan, uint32_t *resp_buf)
788 {
789 unsigned int resp_len = sizeof(resp_buf);
790
791 return mailbox_send_cmd(MBOX_JOB_ID, MBOX_HWMON_READTEMP, &chan, 1U,
792 CMD_CASUAL, resp_buf,
793 &resp_len);
794
795 }
796
mailbox_hwmon_readvolt(uint32_t chan,uint32_t * resp_buf)797 int mailbox_hwmon_readvolt(uint32_t chan, uint32_t *resp_buf)
798 {
799 unsigned int resp_len = sizeof(resp_buf);
800
801 return mailbox_send_cmd(MBOX_JOB_ID, MBOX_HWMON_READVOLT, &chan, 1U,
802 CMD_CASUAL, resp_buf,
803 &resp_len);
804 }
805
mailbox_seu_err_status(uint32_t * resp_buf,unsigned int resp_buf_len)806 int mailbox_seu_err_status(uint32_t *resp_buf, unsigned int resp_buf_len)
807 {
808
809 return mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_SEU_ERR_READ, NULL, 0U,
810 CMD_CASUAL, resp_buf,
811 &resp_buf_len);
812 }
813
mailbox_safe_inject_seu_err(uint32_t * arg,unsigned int len)814 int mailbox_safe_inject_seu_err(uint32_t *arg, unsigned int len)
815 {
816 return mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_SAFE_INJECT_SEU_ERR, arg, len,
817 CMD_CASUAL, NULL, NULL);
818 }
819
820 #if SIP_SVC_V3
mailbox_fill_cmd_desc(uint8_t client_id,uint8_t job_id,uint32_t * resp_buff)821 static int mailbox_fill_cmd_desc(uint8_t client_id, uint8_t job_id,
822 uint32_t *resp_buff)
823 {
824 sdm_command_t *cmd_desc = NULL;
825
826 /* Get a free command descriptor */
827 cmd_desc = mailbox_get_free_cmd_desc();
828 if (cmd_desc == NULL) {
829 return MBOX_BUFFER_FULL;
830 }
831
832 /* Record all the given values for the command. */
833 cmd_desc->client_id = client_id;
834 cmd_desc->job_id = job_id;
835 cmd_desc->cb = NULL;
836 cmd_desc->cb_args = resp_buff;
837 cmd_desc->cb_args_len = 0U;
838
839 return MBOX_RET_OK;
840 }
841
842 /* Returns the command descriptor based on the client and job ID. */
mailbox_get_cmd_desc(uint8_t client_id,uint8_t job_id)843 static sdm_command_t *mailbox_get_cmd_desc(uint8_t client_id, uint8_t job_id)
844 {
845 spin_lock(&mbox_db_lock);
846 for (uint32_t count = 0; count < MBOX_SVC_CMD_QUEUE_SIZE; count++) {
847 if ((mbox_svc.cmd_queue[count].client_id == client_id) &&
848 (mbox_svc.cmd_queue[count].job_id == job_id) &&
849 (mbox_svc.cmd_queue[count].flags & MBOX_SVC_CMD_IS_USED)) {
850 spin_unlock(&mbox_db_lock);
851 return &(mbox_svc.cmd_queue[count]);
852 }
853 }
854
855 spin_unlock(&mbox_db_lock);
856 VERBOSE("MBOX: Command descriptor not found for cid %d, jid %d\n",
857 client_id, job_id);
858
859 return NULL;
860 }
861
862 /* Returns the response descriptor based on only client ID. */
mailbox_get_resp_desc_cid(uint8_t client_id,uint8_t * index)863 static sdm_response_t *mailbox_get_resp_desc_cid(uint8_t client_id, uint8_t *index)
864 {
865 spin_lock(&mbox_db_lock);
866
867 for (uint32_t count = 0; count < MBOX_SVC_RESP_QUEUE_SIZE; count++) {
868 if ((mbox_svc.resp_queue[count].client_id == client_id) &&
869 (mbox_svc.resp_queue[count].flags & FLAG_SDM_RESPONSE_IS_VALID)) {
870 *index = count;
871 /*
872 * Once we get the valid response descriptor, get the
873 * job ID and mark up the bitmaps.
874 */
875 uint8_t job_id = mbox_svc.resp_queue[count].job_id;
876 uint8_t transaction_id = MBOX_GET_TRANS_ID(client_id, job_id);
877
878 mbox_svc.received_bitmap[transaction_id / MBOX_TID_BITMAP_SIZE] &=
879 ~(1ULL << (transaction_id % MBOX_TID_BITMAP_SIZE));
880 mbox_svc.interrupt_bitmap[transaction_id / MBOX_TID_BITMAP_SIZE] &=
881 ~(1ULL << (transaction_id % MBOX_TID_BITMAP_SIZE));
882 spin_unlock(&mbox_db_lock);
883 return &(mbox_svc.resp_queue[count]);
884 }
885 }
886
887 spin_unlock(&mbox_db_lock);
888 VERBOSE("MBOX: Response descriptor not found for cid %d\n", client_id);
889
890 return NULL;
891 }
892
893 /* Returns the response descriptor based on the client and job ID. */
mailbox_get_resp_desc(uint8_t client_id,uint8_t job_id,uint8_t * index)894 static sdm_response_t *mailbox_get_resp_desc(uint8_t client_id, uint8_t job_id, uint8_t *index)
895 {
896 spin_lock(&mbox_db_lock);
897 /*
898 * Let's first check whether we have a response bitmap set for the given
899 * client ID and job ID.
900 */
901 uint8_t transaction_id = MBOX_GET_TRANS_ID(client_id, job_id);
902
903 if ((mbox_svc.received_bitmap[transaction_id / MBOX_TID_BITMAP_SIZE] &
904 (1ULL << (transaction_id % MBOX_TID_BITMAP_SIZE))) == 0) {
905 spin_unlock(&mbox_db_lock);
906 VERBOSE("MBOX: Response bitmap not set for cid %d, jid %d, bitmap 0x%16lx\n",
907 client_id, job_id, mbox_svc.received_bitmap[transaction_id / 64]);
908 return NULL;
909 }
910
911 for (uint32_t count = 0; count < MBOX_SVC_RESP_QUEUE_SIZE; count++) {
912 if (mbox_svc.resp_queue[count].flags & FLAG_SDM_RESPONSE_IS_VALID) {
913 if ((mbox_svc.resp_queue[count].client_id == client_id) &&
914 (mbox_svc.resp_queue[count].job_id == job_id)) {
915 *index = count;
916 mbox_svc.received_bitmap[transaction_id / MBOX_TID_BITMAP_SIZE] &=
917 ~(1ULL << (transaction_id % MBOX_TID_BITMAP_SIZE));
918 mbox_svc.interrupt_bitmap[transaction_id / MBOX_TID_BITMAP_SIZE] &=
919 ~(1ULL << (transaction_id % MBOX_TID_BITMAP_SIZE));
920 spin_unlock(&mbox_db_lock);
921 return &(mbox_svc.resp_queue[count]);
922 }
923 }
924 }
925
926 spin_unlock(&mbox_db_lock);
927 VERBOSE("MBOX: Response descriptor not found for cid %d, jid %d\n",
928 client_id, job_id);
929
930 return NULL;
931 }
932
mailbox_get_free_resp_desc(void)933 static int32_t mailbox_get_free_resp_desc(void)
934 {
935 spin_lock(&mbox_db_lock);
936 static uint32_t free_index = MBOX_SVC_RESP_QUEUE_SIZE - 1;
937 uint32_t count = 0U, try = 0U;
938
939 for (try = 0; try < MBOX_SVC_RESP_QUEUE_SIZE; try++) {
940 free_index = (free_index + 1) % MBOX_SVC_RESP_QUEUE_SIZE;
941 if (!(mbox_svc.resp_queue[free_index].flags &
942 FLAG_SDM_RESPONSE_IS_USED)) {
943 count = free_index;
944 spin_unlock(&mbox_db_lock);
945 return count;
946 }
947 }
948
949 /* No free descriptors are available */
950 spin_unlock(&mbox_db_lock);
951 VERBOSE("MBOX: No free response descriptors are available\n");
952
953 return MBOX_BUFFER_FULL;
954 }
955
mailbox_get_free_cmd_desc(void)956 static sdm_command_t *mailbox_get_free_cmd_desc(void)
957 {
958 spin_lock(&mbox_db_lock);
959 static uint32_t free_index;
960
961 /* Rollover the command queue free index */
962 if (free_index == (MBOX_SVC_CMD_QUEUE_SIZE - 1)) {
963 free_index = 0U;
964 }
965
966 for (; free_index < MBOX_SVC_CMD_QUEUE_SIZE; free_index++) {
967 if (!(mbox_svc.cmd_queue[free_index].flags &
968 MBOX_SVC_CMD_IS_USED)) {
969 mbox_svc.cmd_queue[free_index].flags |= MBOX_SVC_CMD_IS_USED;
970 spin_unlock(&mbox_db_lock);
971 return &(mbox_svc.cmd_queue[free_index]);
972 }
973 }
974
975 /* No free command descriptors are available */
976 spin_unlock(&mbox_db_lock);
977 VERBOSE("MBOX: No free command descriptors available\n");
978
979 return NULL;
980 }
981
mailbox_free_cmd_desc(sdm_command_t * cmd_desc)982 static inline void mailbox_free_cmd_desc(sdm_command_t *cmd_desc)
983 {
984 if (cmd_desc == NULL) {
985 return;
986 }
987
988 spin_lock(&mbox_db_lock);
989 memset((void *)cmd_desc, 0, sizeof(sdm_command_t));
990 spin_unlock(&mbox_db_lock);
991 }
992
mailbox_free_resp_desc(uint8_t index)993 static inline void mailbox_free_resp_desc(uint8_t index)
994 {
995 if (index >= MBOX_SVC_RESP_QUEUE_SIZE) {
996 return;
997 }
998
999 spin_lock(&mbox_db_lock);
1000 memset((void *)&mbox_svc.resp_queue[index], 0, sizeof(sdm_response_t));
1001 spin_unlock(&mbox_db_lock);
1002 }
1003
1004 /*
1005 * This function serves the V1 _sync_read and _async_read functionality, and it
1006 * is introduced as part of V3 framework to keep backward compatible with V1
1007 * clients.
1008 */
mailbox_read_response_v3(uint8_t client_id,uint8_t * job_id,uint32_t * header,uint32_t * resp,uint32_t * resp_len,uint8_t ignore_client_id)1009 static int mailbox_read_response_v3(uint8_t client_id, uint8_t *job_id,
1010 uint32_t *header, uint32_t *resp,
1011 uint32_t *resp_len,
1012 uint8_t ignore_client_id)
1013 {
1014 uint8_t di = 0U;
1015 int status = MBOX_RET_OK;
1016 sdm_response_t *resp_desc = NULL;
1017 sdm_command_t *cmd_desc = NULL;
1018
1019 /*
1020 * In the V1, the client ID is always MBOX_ATF_CLIENT_ID and in this
1021 * routine we will collect the response which only belongs to this
1022 * client ID. So safe to ignore this input.
1023 */
1024 (void)ignore_client_id;
1025
1026 /* Clear the SDM doorbell interrupt */
1027 if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM) == 1U)
1028 mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U);
1029
1030 /* Fill the command descriptor index and get the same */
1031 status = mailbox_fill_cmd_desc(client_id, async_v1_job_id, resp);
1032 if (status != MBOX_RET_OK) {
1033 return status;
1034 }
1035
1036 cmd_desc = mailbox_get_cmd_desc(client_id, async_v1_job_id);
1037
1038 /* Get the response from SDM, just go through one cycle */
1039 status = mailbox_response_handler_fsm();
1040 if (status != MBOX_RET_OK) {
1041 mailbox_free_cmd_desc(cmd_desc);
1042 *resp_len = 0U;
1043 return status;
1044 }
1045
1046 /* Check the local response queue with the given client ID */
1047 resp_desc = mailbox_get_resp_desc_cid(client_id, &di);
1048 if (resp_desc == NULL) {
1049 mailbox_free_cmd_desc(cmd_desc);
1050 *resp_len = 0U;
1051 return MBOX_NO_RESPONSE;
1052 }
1053
1054 /* Update the received mailbox response length, job ID and header */
1055 *job_id = resp_desc->job_id;
1056 *resp_len = resp_desc->rcvd_resp_len;
1057 if (header != NULL) {
1058 *header = resp_desc->header;
1059 }
1060
1061 /* Check the mailbox response error code */
1062 if (MBOX_RESP_ERR(resp_desc->header) > 0U) {
1063 INFO("MBOX: Error in async response: %x\n", resp_desc->header);
1064 status = -MBOX_RESP_ERR(resp_desc->header);
1065 }
1066
1067 /* Free up the response and command descriptors */
1068 mailbox_free_resp_desc(di);
1069 mailbox_free_cmd_desc(cmd_desc);
1070
1071 return status;
1072 }
1073
mailbox_send_cmd_async_v3(uint8_t client_id,uint8_t job_id,uint32_t cmd,uint32_t * args,uint32_t args_len,uint8_t cmd_flag,sdm_command_callback cb,uint32_t * cb_args,uint32_t cb_args_len)1074 int mailbox_send_cmd_async_v3(uint8_t client_id, uint8_t job_id, uint32_t cmd,
1075 uint32_t *args, uint32_t args_len, uint8_t cmd_flag,
1076 sdm_command_callback cb, uint32_t *cb_args,
1077 uint32_t cb_args_len)
1078 {
1079 int status = 0;
1080 sdm_command_t *cmd_desc = NULL;
1081
1082 VERBOSE("MBOX: cid: %d, jid: %d, cmd: %d, cmd_flag: %d\n",
1083 client_id, job_id, cmd, cmd_flag);
1084
1085 if (IS_CMD_SET(cmd_flag, URGENT)) {
1086 mmio_write_32(MBOX_OFFSET + MBOX_URG, cmd);
1087 mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U);
1088 } else {
1089 /* Get a free command descriptor */
1090 cmd_desc = mailbox_get_free_cmd_desc();
1091 if (cmd_desc == NULL) {
1092 return MBOX_BUFFER_FULL;
1093 }
1094
1095 /* Record all the given values for the command. */
1096 cmd_desc->client_id = client_id;
1097 cmd_desc->job_id = job_id;
1098 cmd_desc->cb = cb;
1099 cmd_desc->cb_args = cb_args;
1100 cmd_desc->cb_args_len = cb_args_len;
1101
1102 /* Push the command to mailbox FIFO */
1103 status = fill_mailbox_circular_buffer(
1104 MBOX_FRAME_CMD_HEADER(client_id, job_id,
1105 args_len, IS_CMD_SET(cmd_flag, INDIRECT), cmd),
1106 args,
1107 args_len);
1108
1109 if (status != MBOX_RET_OK) {
1110 INFO("MBOX: Failed to push the command to mailbox FIFO\n");
1111 /* Free the command descriptor. */
1112 mailbox_free_cmd_desc(cmd_desc);
1113 }
1114 }
1115
1116 INFO("MBOX: %s: status: %d\n", __func__, status);
1117
1118 return status;
1119 }
1120
mailbox_poll_response_v3(uint8_t client_id,uint8_t job_id,uint32_t * resp,unsigned int * resp_len,uint32_t urgent)1121 static int mailbox_poll_response_v3(uint8_t client_id, uint8_t job_id,
1122 uint32_t *resp, unsigned int *resp_len,
1123 uint32_t urgent)
1124 {
1125 unsigned int timeout = 40U;
1126 unsigned int sdm_loop = 255U;
1127 bool is_cmd_desc_fill = false;
1128 uint8_t di = 0U;
1129 sdm_response_t *resp_desc = NULL;
1130 sdm_command_t *cmd_desc = NULL;
1131
1132 while (sdm_loop != 0U) {
1133 do {
1134 if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM)
1135 == 1U) {
1136 break;
1137 }
1138 mdelay(10U);
1139 } while (--timeout != 0U);
1140
1141 if (timeout == 0U) {
1142 INFO("%s: Timed out waiting for SDM intr\n", __func__);
1143 break;
1144 }
1145
1146 mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U);
1147
1148 if ((urgent & 1U) != 0U) {
1149 mdelay(5U);
1150 if ((mmio_read_32(MBOX_OFFSET + MBOX_STATUS) &
1151 MBOX_STATUS_UA_MASK) ^
1152 (urgent & MBOX_STATUS_UA_MASK)) {
1153 mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U);
1154 return MBOX_RET_OK;
1155 }
1156
1157 mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U);
1158 ERROR("MBOX: Mailbox did not get UA");
1159 return MBOX_RET_ERROR;
1160 }
1161
1162 /* Fill the command descriptor index and get the same. */
1163 if (!is_cmd_desc_fill) {
1164 if (mailbox_fill_cmd_desc(client_id, job_id, resp) !=
1165 MBOX_RET_OK) {
1166 return MBOX_BUFFER_FULL;
1167 }
1168
1169 cmd_desc = mailbox_get_cmd_desc(client_id, job_id);
1170 is_cmd_desc_fill = true;
1171 }
1172
1173 /* Since it is sync call, will try to read till it time out */
1174 (void)mailbox_response_handler_fsm();
1175
1176 /* Check the response queue with the given client ID and job ID */
1177 resp_desc = mailbox_get_resp_desc(client_id, job_id, &di);
1178 if (resp_desc != NULL) {
1179 VERBOSE("%s: Resp received for cid %d, jid %d\n",
1180 __func__, resp_desc->client_id, resp_desc->job_id);
1181
1182 uint16_t header = resp_desc->header;
1183
1184 /* Update the return response length */
1185 if (resp_len != NULL) {
1186 *resp_len = resp_desc->rcvd_resp_len;
1187 }
1188
1189 /* Free the response and command descriptor */
1190 mailbox_free_resp_desc(di);
1191 mailbox_free_cmd_desc(cmd_desc);
1192
1193 if (MBOX_RESP_ERR(header) > 0U) {
1194 INFO("%s: SDM err code: 0x%x\n", __func__,
1195 MBOX_RESP_ERR(header));
1196 return -MBOX_RESP_ERR(header);
1197 }
1198
1199 VERBOSE("%s: MBOX_RET_OK\n", __func__);
1200 return MBOX_RET_OK;
1201 }
1202 sdm_loop--;
1203 }
1204
1205 INFO("%s: Timed out waiting for SDM\n", __func__);
1206 return MBOX_TIMEOUT;
1207 }
1208
1209 /* SDM response parser handler state machine. */
mailbox_response_parser(void)1210 static void mailbox_response_parser(void)
1211 {
1212 int di = -1; /* Descriptor index */
1213 uint32_t rin;
1214 uint32_t rout;
1215
1216 switch (mbox_svc.next_resp_state) {
1217 case SRS_WAIT_FOR_RESP:
1218 {
1219 mbox_svc.resp_state = SRS_WAIT_FOR_RESP;
1220
1221 rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
1222 rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
1223 if (rin != rout) {
1224 mbox_svc.next_resp_state = SRS_WAIT_FOR_HEADER;
1225 }
1226
1227 break;
1228 }
1229
1230 case SRS_WAIT_FOR_HEADER:
1231 {
1232 mbox_svc.resp_state = SRS_WAIT_FOR_HEADER;
1233 uint32_t resp_hdr;
1234 uint8_t trans_id = 0U;
1235
1236 rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
1237 rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
1238 if (rin != rout) {
1239 /* Read the header and dequeue from the queue. */
1240 resp_hdr = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++));
1241 rout %= MBOX_RESP_BUFFER_SIZE;
1242 mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
1243
1244 /* Allocate a new response descriptor */
1245 di = mailbox_get_free_resp_desc();
1246 if (di != -1) {
1247 mbox_svc.curr_di = di;
1248 mbox_svc.resp_queue[di].header = resp_hdr;
1249 mbox_svc.resp_queue[di].client_id = MBOX_RESP_CLIENT_ID(resp_hdr);
1250 mbox_svc.resp_queue[di].job_id = MBOX_RESP_JOB_ID(resp_hdr);
1251 mbox_svc.resp_queue[di].resp_len = MBOX_RESP_LEN(resp_hdr);
1252 mbox_svc.resp_queue[di].flags |= (FLAG_SDM_RESPONSE_IS_USED |
1253 FLAG_SDM_RESPONSE_IS_IN_PROGRESS);
1254 mbox_svc.resp_queue[di].err_code = MBOX_RESP_ERR(resp_hdr);
1255 trans_id = MBOX_RESP_TRANSACTION_ID(resp_hdr);
1256
1257 VERBOSE("MBOX: Resp Hdr: cid %d, jid %d, len %d, err_code 0x%x\n",
1258 mbox_svc.resp_queue[di].client_id,
1259 mbox_svc.resp_queue[di].job_id,
1260 mbox_svc.resp_queue[di].resp_len,
1261 mbox_svc.resp_queue[di].err_code);
1262
1263 /* Check if the response is an argument response */
1264 if (mbox_svc.resp_queue[di].resp_len > 0) {
1265 mbox_svc.next_resp_state = SRS_WAIT_FOR_ARGUMENTS;
1266 } else {
1267 VERBOSE("MBOX: Received complete response with no args\n");
1268 /* Non argument response, done */
1269 mbox_svc.resp_queue[mbox_svc.curr_di].flags |=
1270 FLAG_SDM_RESPONSE_IS_VALID;
1271
1272 /* Go back to waiting for new response */
1273 mbox_svc.next_resp_state = SRS_WAIT_FOR_RESP;
1274 mbox_svc.curr_di = -1;
1275
1276 /* Mark the transaction ID as received */
1277 spin_lock(&mbox_db_lock);
1278 mbox_svc.received_bitmap[trans_id / MBOX_TID_BITMAP_SIZE] |=
1279 (1ULL << (trans_id % MBOX_TID_BITMAP_SIZE));
1280 spin_unlock(&mbox_db_lock);
1281 }
1282 } else {
1283 mbox_svc.next_resp_state = SRS_SYNC_ERROR;
1284 }
1285 }
1286 break;
1287 }
1288
1289 case SRS_WAIT_FOR_ARGUMENTS:
1290 {
1291 mbox_svc.resp_state = SRS_WAIT_FOR_ARGUMENTS;
1292 uint16_t mbox_resp_len = mbox_svc.resp_queue[mbox_svc.curr_di].resp_len;
1293 uint32_t *read_buff = NULL;
1294 uint16_t read_len = 0U;
1295 uint16_t read_max_len = 0U;
1296 uint32_t timeout = 0U;
1297
1298 /* Determine where to copy the buffer. */
1299 sdm_command_t *cmd_desc = mailbox_get_cmd_desc(
1300 mbox_svc.resp_queue[mbox_svc.curr_di].client_id,
1301 mbox_svc.resp_queue[mbox_svc.curr_di].job_id);
1302 if (cmd_desc != NULL && cmd_desc->cb_args != NULL) {
1303 read_buff = cmd_desc->cb_args;
1304 read_max_len = mbox_resp_len;
1305 } else {
1306 read_buff = (uint32_t *)mbox_svc.resp_queue[mbox_svc.curr_di].resp_data;
1307 read_max_len = MBOX_SVC_MAX_RESP_DATA_SIZE;
1308 }
1309
1310 rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
1311 rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
1312
1313 while ((read_len < mbox_resp_len) && (rin != rout) && (read_len < read_max_len)) {
1314 timeout = 10000U;
1315
1316 /* Copy the response data to the buffer */
1317 read_buff[read_len++] = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++));
1318
1319 VERBOSE("MBOX: 0x%x\n", read_buff[read_len - 1]);
1320
1321 /* Update the read out buffer index */
1322 rout %= MBOX_RESP_BUFFER_SIZE;
1323 mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
1324
1325 /*
1326 * The response buffer is of 16 words size, this loop checks
1327 * if the response buffer is empty and if empty trigger an
1328 * interrupt to SDM and wait for the response buffer to fill
1329 */
1330 do {
1331 if (read_len == mbox_resp_len)
1332 break;
1333
1334 rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
1335 if (rout == rin) {
1336 mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U);
1337 udelay(100);
1338 } else {
1339 break;
1340 }
1341 timeout--;
1342 } while ((read_len < mbox_resp_len) && (timeout != 0U));
1343
1344 if (timeout == 0U) {
1345 INFO("MBOX: Timeout waiting for response data\n");
1346 mbox_svc.next_resp_state = SRS_SYNC_ERROR;
1347 break;
1348 }
1349 }
1350
1351 /* Check if we have received all the arguments */
1352 mbox_svc.resp_queue[mbox_svc.curr_di].rcvd_resp_len = read_len;
1353 if (mbox_resp_len == read_len) {
1354 uint8_t transaction_id =
1355 ((mbox_svc.resp_queue[mbox_svc.curr_di].client_id << 4) |
1356 (mbox_svc.resp_queue[mbox_svc.curr_di].job_id));
1357 VERBOSE("MBOX: Received all the response data len %d, transaction_id %d\n",
1358 read_len, transaction_id);
1359
1360 spin_lock(&mbox_db_lock);
1361 mbox_svc.received_bitmap[transaction_id / MBOX_TID_BITMAP_SIZE] |=
1362 (1ULL << (transaction_id % MBOX_TID_BITMAP_SIZE));
1363 spin_unlock(&mbox_db_lock);
1364
1365 mbox_svc.resp_queue[mbox_svc.curr_di].flags |= FLAG_SDM_RESPONSE_IS_VALID;
1366 mbox_svc.next_resp_state = SRS_WAIT_FOR_RESP;
1367 mbox_svc.curr_di = -1;
1368 } else {
1369 mbox_svc.next_resp_state = SRS_SYNC_ERROR;
1370 VERBOSE("MBOX: Received partial response data len %d, max len %d\n",
1371 read_len, read_max_len);
1372 }
1373 break;
1374 }
1375
1376 case SRS_SYNC_ERROR:
1377 {
1378 mbox_svc.resp_state = SRS_SYNC_ERROR;
1379 INFO("MBOX: Error in response handling\n");
1380 break;
1381 }
1382
1383 default:
1384 break;
1385 } /* switch */
1386 }
1387
mailbox_response_handler_fsm(void)1388 static int mailbox_response_handler_fsm(void)
1389 {
1390 int status = MBOX_RET_OK;
1391
1392 spin_lock(&mbox_read_lock);
1393 /* Mailbox peripheral response parser */
1394 do {
1395 /* Iterate till the state machine transition ends */
1396 mailbox_response_parser();
1397
1398 /* Note down if there is any error in the response parsing */
1399 if (mbox_svc.next_resp_state == SRS_SYNC_ERROR) {
1400 status = MBOX_RET_ERROR;
1401 }
1402
1403 } while (mbox_svc.resp_state != mbox_svc.next_resp_state);
1404 spin_unlock(&mbox_read_lock);
1405
1406 return status;
1407 }
1408
mailbox_response_poll_on_intr_v3(uint8_t * client_id,uint8_t * job_id,uint64_t * bitmap)1409 int mailbox_response_poll_on_intr_v3(uint8_t *client_id, uint8_t *job_id,
1410 uint64_t *bitmap)
1411 {
1412 uint32_t i = 0U;
1413 int status = MBOX_RET_OK;
1414
1415 /* Clear the SDM doorbell interrupt immediately */
1416 if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM) == 1U) {
1417 mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U);
1418 }
1419
1420 /* Check mailbox FIFO for any pending responses available to read. */
1421 status = mailbox_response_handler_fsm();
1422 if (status != MBOX_RET_OK) {
1423 return status;
1424 }
1425
1426 /*
1427 * Once we read the complete mailbox FIFO, let's mark up the bitmap for
1428 * available responses with respect to each transcation IDs.
1429 */
1430 status = MBOX_NO_RESPONSE;
1431 spin_lock(&mbox_db_lock);
1432 for (i = 0; i < MBOX_MAX_TIDS_BITMAP; i++) {
1433 bitmap[i] = mbox_svc.interrupt_bitmap[i] ^ mbox_svc.received_bitmap[i];
1434 if (bitmap[i] != 0 && status == MBOX_NO_RESPONSE) {
1435 status = MBOX_RET_OK;
1436 }
1437
1438 mbox_svc.interrupt_bitmap[i] = mbox_svc.received_bitmap[i];
1439 }
1440 spin_unlock(&mbox_db_lock);
1441
1442 return status;
1443 }
1444
mailbox_response_poll_v3(uint8_t client_id,uint8_t job_id,uint64_t * ret_args,uint32_t * ret_args_len)1445 int mailbox_response_poll_v3(uint8_t client_id, uint8_t job_id,
1446 uint64_t *ret_args, uint32_t *ret_args_len)
1447 {
1448 sdm_command_t *cmd_desc = NULL;
1449 sdm_response_t *resp_desc = NULL;
1450 uint8_t di = 0U;
1451 int status = MBOX_RET_OK;
1452
1453 /*
1454 * Let's first check the local response queue with the given
1455 * client ID and job ID
1456 */
1457 resp_desc = mailbox_get_resp_desc(client_id, job_id, &di);
1458 if (resp_desc == NULL) {
1459 /* Not available in the local queue, let's read mailbox FIFO */
1460 status = mailbox_response_handler_fsm();
1461 if (status != MBOX_RET_OK) {
1462 return status;
1463 }
1464
1465 resp_desc = mailbox_get_resp_desc(client_id, job_id, &di);
1466 }
1467 cmd_desc = mailbox_get_cmd_desc(client_id, job_id);
1468
1469 if (cmd_desc != NULL && resp_desc != NULL) {
1470 VERBOSE("MBOX: Resp found for cid %d, jid %d\n", client_id, job_id);
1471
1472 /* Command callback function */
1473 *ret_args_len = cmd_desc->cb(resp_desc, cmd_desc, ret_args);
1474
1475 /* Free the command and response descriptors. */
1476 mailbox_free_cmd_desc(cmd_desc);
1477 mailbox_free_resp_desc(di);
1478
1479 return MBOX_RET_OK;
1480 }
1481
1482 INFO("MBOX: No resp found for cid: %d, jid: %d\n", client_id, job_id);
1483
1484 return MBOX_NO_RESPONSE;
1485 }
1486
mailbox_init_v3(void)1487 void mailbox_init_v3(void)
1488 {
1489 uint32_t count;
1490
1491 memset((void *)&mbox_svc, 0, sizeof(mbox_svc));
1492
1493 mbox_svc.next_resp_state = SRS_WAIT_FOR_RESP;
1494 mbox_svc.resp_state = SRS_WAIT_FOR_RESP;
1495
1496 /* Free all entries from the response queue. */
1497 for (count = 0; count < MBOX_SVC_RESP_QUEUE_SIZE; count++) {
1498 mbox_svc.resp_queue[count].flags = 0;
1499 }
1500
1501 /* Free all entries from the command queue. */
1502 for (count = 0; count < MBOX_SVC_CMD_QUEUE_SIZE; count++) {
1503 mbox_svc.cmd_queue[count].flags = 0;
1504 }
1505
1506 mbox_svc.curr_di = -1;
1507 }
1508 #endif /* #if SIP_SVC_V3 */
1509