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