xref: /arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_mailbox.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2020-2022, Intel Corporation. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <lib/mmio.h>
8*91f16700Schasinglulu #include <common/debug.h>
9*91f16700Schasinglulu #include <drivers/delay_timer.h>
10*91f16700Schasinglulu #include <platform_def.h>
11*91f16700Schasinglulu 
12*91f16700Schasinglulu #include "socfpga_mailbox.h"
13*91f16700Schasinglulu #include "socfpga_plat_def.h"
14*91f16700Schasinglulu #include "socfpga_sip_svc.h"
15*91f16700Schasinglulu #include "socfpga_system_manager.h"
16*91f16700Schasinglulu 
17*91f16700Schasinglulu static mailbox_payload_t mailbox_resp_payload;
18*91f16700Schasinglulu static mailbox_container_t mailbox_resp_ctr = {0, 0, &mailbox_resp_payload};
19*91f16700Schasinglulu 
20*91f16700Schasinglulu static bool is_mailbox_cmdbuf_full(uint32_t cin)
21*91f16700Schasinglulu {
22*91f16700Schasinglulu 	uint32_t cout = mmio_read_32(MBOX_OFFSET + MBOX_COUT);
23*91f16700Schasinglulu 
24*91f16700Schasinglulu 	return (((cin + 1U) % MBOX_CMD_BUFFER_SIZE) == cout);
25*91f16700Schasinglulu }
26*91f16700Schasinglulu 
27*91f16700Schasinglulu static bool is_mailbox_cmdbuf_empty(uint32_t cin)
28*91f16700Schasinglulu {
29*91f16700Schasinglulu 	uint32_t cout = mmio_read_32(MBOX_OFFSET + MBOX_COUT);
30*91f16700Schasinglulu 
31*91f16700Schasinglulu 	return (((cout + 1U) % MBOX_CMD_BUFFER_SIZE) == cin);
32*91f16700Schasinglulu }
33*91f16700Schasinglulu 
34*91f16700Schasinglulu static int wait_for_mailbox_cmdbuf_empty(uint32_t cin)
35*91f16700Schasinglulu {
36*91f16700Schasinglulu 	unsigned int timeout = 200U;
37*91f16700Schasinglulu 
38*91f16700Schasinglulu 	do {
39*91f16700Schasinglulu 		if (is_mailbox_cmdbuf_empty(cin)) {
40*91f16700Schasinglulu 			break;
41*91f16700Schasinglulu 		}
42*91f16700Schasinglulu 		mdelay(10U);
43*91f16700Schasinglulu 	} while (--timeout != 0U);
44*91f16700Schasinglulu 
45*91f16700Schasinglulu 	if (timeout == 0U) {
46*91f16700Schasinglulu 		return MBOX_TIMEOUT;
47*91f16700Schasinglulu 	}
48*91f16700Schasinglulu 
49*91f16700Schasinglulu 	return MBOX_RET_OK;
50*91f16700Schasinglulu }
51*91f16700Schasinglulu 
52*91f16700Schasinglulu static int write_mailbox_cmd_buffer(uint32_t *cin, uint32_t cout,
53*91f16700Schasinglulu 				    uint32_t data,
54*91f16700Schasinglulu 				    bool *is_doorbell_triggered)
55*91f16700Schasinglulu {
56*91f16700Schasinglulu 	unsigned int timeout = 100U;
57*91f16700Schasinglulu 
58*91f16700Schasinglulu 	do {
59*91f16700Schasinglulu 		if (is_mailbox_cmdbuf_full(*cin)) {
60*91f16700Schasinglulu 			if (!(*is_doorbell_triggered)) {
61*91f16700Schasinglulu 				mmio_write_32(MBOX_OFFSET +
62*91f16700Schasinglulu 					      MBOX_DOORBELL_TO_SDM, 1U);
63*91f16700Schasinglulu 				*is_doorbell_triggered = true;
64*91f16700Schasinglulu 			}
65*91f16700Schasinglulu 			mdelay(10U);
66*91f16700Schasinglulu 		} else {
67*91f16700Schasinglulu 			mmio_write_32(MBOX_ENTRY_TO_ADDR(CMD, (*cin)++), data);
68*91f16700Schasinglulu 			*cin %= MBOX_CMD_BUFFER_SIZE;
69*91f16700Schasinglulu 			mmio_write_32(MBOX_OFFSET + MBOX_CIN, *cin);
70*91f16700Schasinglulu 			break;
71*91f16700Schasinglulu 		}
72*91f16700Schasinglulu 	} while (--timeout != 0U);
73*91f16700Schasinglulu 
74*91f16700Schasinglulu 	if (timeout == 0U) {
75*91f16700Schasinglulu 		return MBOX_TIMEOUT;
76*91f16700Schasinglulu 	}
77*91f16700Schasinglulu 
78*91f16700Schasinglulu 	if (*is_doorbell_triggered) {
79*91f16700Schasinglulu 		int ret = wait_for_mailbox_cmdbuf_empty(*cin);
80*91f16700Schasinglulu 		return ret;
81*91f16700Schasinglulu 	}
82*91f16700Schasinglulu 
83*91f16700Schasinglulu 	return MBOX_RET_OK;
84*91f16700Schasinglulu }
85*91f16700Schasinglulu 
86*91f16700Schasinglulu static int fill_mailbox_circular_buffer(uint32_t header_cmd, uint32_t *args,
87*91f16700Schasinglulu 					unsigned int len)
88*91f16700Schasinglulu {
89*91f16700Schasinglulu 	uint32_t sdm_read_offset, cmd_free_offset;
90*91f16700Schasinglulu 	unsigned int i;
91*91f16700Schasinglulu 	int ret;
92*91f16700Schasinglulu 	bool is_doorbell_triggered = false;
93*91f16700Schasinglulu 
94*91f16700Schasinglulu 	cmd_free_offset = mmio_read_32(MBOX_OFFSET + MBOX_CIN);
95*91f16700Schasinglulu 	sdm_read_offset = mmio_read_32(MBOX_OFFSET + MBOX_COUT);
96*91f16700Schasinglulu 
97*91f16700Schasinglulu 	ret = write_mailbox_cmd_buffer(&cmd_free_offset, sdm_read_offset,
98*91f16700Schasinglulu 				       header_cmd, &is_doorbell_triggered);
99*91f16700Schasinglulu 	if (ret != 0) {
100*91f16700Schasinglulu 		goto restart_mailbox;
101*91f16700Schasinglulu 	}
102*91f16700Schasinglulu 
103*91f16700Schasinglulu 	for (i = 0U; i < len; i++) {
104*91f16700Schasinglulu 		is_doorbell_triggered = false;
105*91f16700Schasinglulu 		ret = write_mailbox_cmd_buffer(&cmd_free_offset,
106*91f16700Schasinglulu 					       sdm_read_offset, args[i],
107*91f16700Schasinglulu 					       &is_doorbell_triggered);
108*91f16700Schasinglulu 		if (ret != 0) {
109*91f16700Schasinglulu 			goto restart_mailbox;
110*91f16700Schasinglulu 		}
111*91f16700Schasinglulu 	}
112*91f16700Schasinglulu 
113*91f16700Schasinglulu 	mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U);
114*91f16700Schasinglulu 
115*91f16700Schasinglulu 	return MBOX_RET_OK;
116*91f16700Schasinglulu 
117*91f16700Schasinglulu restart_mailbox:
118*91f16700Schasinglulu 	/*
119*91f16700Schasinglulu 	 * Attempt to restart mailbox if the driver not able to write
120*91f16700Schasinglulu 	 * into mailbox command buffer
121*91f16700Schasinglulu 	 */
122*91f16700Schasinglulu 	if (MBOX_CMD_MASK(header_cmd) != MBOX_CMD_RESTART) {
123*91f16700Schasinglulu 		INFO("Mailbox timed out: Attempting mailbox reset\n");
124*91f16700Schasinglulu 		ret = mailbox_init();
125*91f16700Schasinglulu 
126*91f16700Schasinglulu 		if (ret == MBOX_TIMEOUT) {
127*91f16700Schasinglulu 			INFO("Error: Mailbox fail to restart\n");
128*91f16700Schasinglulu 		}
129*91f16700Schasinglulu 	}
130*91f16700Schasinglulu 
131*91f16700Schasinglulu 	return MBOX_TIMEOUT;
132*91f16700Schasinglulu }
133*91f16700Schasinglulu 
134*91f16700Schasinglulu int mailbox_read_response(unsigned int *job_id, uint32_t *response,
135*91f16700Schasinglulu 				unsigned int *resp_len)
136*91f16700Schasinglulu {
137*91f16700Schasinglulu 	uint32_t rin;
138*91f16700Schasinglulu 	uint32_t rout;
139*91f16700Schasinglulu 	uint32_t resp_data;
140*91f16700Schasinglulu 	unsigned int ret_resp_len;
141*91f16700Schasinglulu 
142*91f16700Schasinglulu 	if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM) == 1U) {
143*91f16700Schasinglulu 		mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U);
144*91f16700Schasinglulu 	}
145*91f16700Schasinglulu 
146*91f16700Schasinglulu 	rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
147*91f16700Schasinglulu 	rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
148*91f16700Schasinglulu 
149*91f16700Schasinglulu 	if (rout != rin) {
150*91f16700Schasinglulu 		resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++));
151*91f16700Schasinglulu 
152*91f16700Schasinglulu 		rout %= MBOX_RESP_BUFFER_SIZE;
153*91f16700Schasinglulu 		mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
154*91f16700Schasinglulu 
155*91f16700Schasinglulu 
156*91f16700Schasinglulu 		if (MBOX_RESP_CLIENT_ID(resp_data) != MBOX_ATF_CLIENT_ID) {
157*91f16700Schasinglulu 			return MBOX_WRONG_ID;
158*91f16700Schasinglulu 		}
159*91f16700Schasinglulu 
160*91f16700Schasinglulu 		*job_id = MBOX_RESP_JOB_ID(resp_data);
161*91f16700Schasinglulu 
162*91f16700Schasinglulu 		ret_resp_len = MBOX_RESP_LEN(resp_data);
163*91f16700Schasinglulu 
164*91f16700Schasinglulu 		if (iterate_resp(ret_resp_len, response, resp_len)
165*91f16700Schasinglulu 			!= MBOX_RET_OK) {
166*91f16700Schasinglulu 			return MBOX_TIMEOUT;
167*91f16700Schasinglulu 		}
168*91f16700Schasinglulu 
169*91f16700Schasinglulu 		if (MBOX_RESP_ERR(resp_data) > 0U) {
170*91f16700Schasinglulu 			INFO("Error in response: %x\n", resp_data);
171*91f16700Schasinglulu 			return -MBOX_RESP_ERR(resp_data);
172*91f16700Schasinglulu 		}
173*91f16700Schasinglulu 
174*91f16700Schasinglulu 		return MBOX_RET_OK;
175*91f16700Schasinglulu 	}
176*91f16700Schasinglulu 	return MBOX_NO_RESPONSE;
177*91f16700Schasinglulu }
178*91f16700Schasinglulu 
179*91f16700Schasinglulu int mailbox_read_response_async(unsigned int *job_id, uint32_t *header,
180*91f16700Schasinglulu 				uint32_t *response, unsigned int *resp_len,
181*91f16700Schasinglulu 				uint8_t ignore_client_id)
182*91f16700Schasinglulu {
183*91f16700Schasinglulu 	uint32_t rin;
184*91f16700Schasinglulu 	uint32_t rout;
185*91f16700Schasinglulu 	uint32_t resp_data;
186*91f16700Schasinglulu 	uint32_t ret_resp_len = 0;
187*91f16700Schasinglulu 	uint8_t is_done = 0;
188*91f16700Schasinglulu 	uint32_t resp_len_check = 0;
189*91f16700Schasinglulu 
190*91f16700Schasinglulu 	if ((mailbox_resp_ctr.flag & MBOX_PAYLOAD_FLAG_BUSY) != 0) {
191*91f16700Schasinglulu 		ret_resp_len = MBOX_RESP_LEN(
192*91f16700Schasinglulu 				mailbox_resp_ctr.payload->header) -
193*91f16700Schasinglulu 				mailbox_resp_ctr.index;
194*91f16700Schasinglulu 	}
195*91f16700Schasinglulu 
196*91f16700Schasinglulu 	if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM) == 1U) {
197*91f16700Schasinglulu 		mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U);
198*91f16700Schasinglulu 	}
199*91f16700Schasinglulu 
200*91f16700Schasinglulu 	rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
201*91f16700Schasinglulu 	rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
202*91f16700Schasinglulu 
203*91f16700Schasinglulu 	while (rout != rin && !is_done) {
204*91f16700Schasinglulu 
205*91f16700Schasinglulu 		resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++));
206*91f16700Schasinglulu 
207*91f16700Schasinglulu 		rout %= MBOX_RESP_BUFFER_SIZE;
208*91f16700Schasinglulu 		mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
209*91f16700Schasinglulu 		rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
210*91f16700Schasinglulu 
211*91f16700Schasinglulu 		if ((mailbox_resp_ctr.flag & MBOX_PAYLOAD_FLAG_BUSY) != 0) {
212*91f16700Schasinglulu 			mailbox_resp_ctr.payload->data[mailbox_resp_ctr.index] = resp_data;
213*91f16700Schasinglulu 			mailbox_resp_ctr.index++;
214*91f16700Schasinglulu 			ret_resp_len--;
215*91f16700Schasinglulu 		} else {
216*91f16700Schasinglulu 			if (!ignore_client_id) {
217*91f16700Schasinglulu 				if (MBOX_RESP_CLIENT_ID(resp_data) != MBOX_ATF_CLIENT_ID) {
218*91f16700Schasinglulu 					*resp_len = 0;
219*91f16700Schasinglulu 					return MBOX_WRONG_ID;
220*91f16700Schasinglulu 				}
221*91f16700Schasinglulu 			}
222*91f16700Schasinglulu 
223*91f16700Schasinglulu 			*job_id = MBOX_RESP_JOB_ID(resp_data);
224*91f16700Schasinglulu 			ret_resp_len = MBOX_RESP_LEN(resp_data);
225*91f16700Schasinglulu 			mailbox_resp_ctr.payload->header = resp_data;
226*91f16700Schasinglulu 			mailbox_resp_ctr.flag |= MBOX_PAYLOAD_FLAG_BUSY;
227*91f16700Schasinglulu 		}
228*91f16700Schasinglulu 
229*91f16700Schasinglulu 		if (ret_resp_len == 0) {
230*91f16700Schasinglulu 			is_done = 1;
231*91f16700Schasinglulu 		}
232*91f16700Schasinglulu 	}
233*91f16700Schasinglulu 
234*91f16700Schasinglulu 	if (is_done != 0) {
235*91f16700Schasinglulu 
236*91f16700Schasinglulu 		/* copy header data to input address if applicable */
237*91f16700Schasinglulu 		if (header != 0) {
238*91f16700Schasinglulu 			*header = mailbox_resp_ctr.payload->header;
239*91f16700Schasinglulu 		}
240*91f16700Schasinglulu 
241*91f16700Schasinglulu 		/* copy response data to input buffer if applicable */
242*91f16700Schasinglulu 		ret_resp_len = MBOX_RESP_LEN(mailbox_resp_ctr.payload->header);
243*91f16700Schasinglulu 		if ((ret_resp_len > 0) && (response != NULL) && (resp_len != NULL)) {
244*91f16700Schasinglulu 			if (*resp_len > ret_resp_len) {
245*91f16700Schasinglulu 				*resp_len = ret_resp_len;
246*91f16700Schasinglulu 			}
247*91f16700Schasinglulu 
248*91f16700Schasinglulu 			resp_len_check = (uint32_t) *resp_len;
249*91f16700Schasinglulu 
250*91f16700Schasinglulu 			if (resp_len_check > MBOX_DATA_MAX_LEN) {
251*91f16700Schasinglulu 				return MBOX_RET_ERROR;
252*91f16700Schasinglulu 			}
253*91f16700Schasinglulu 
254*91f16700Schasinglulu 			memcpy((uint8_t *) response,
255*91f16700Schasinglulu 				(uint8_t *) mailbox_resp_ctr.payload->data,
256*91f16700Schasinglulu 				*resp_len * MBOX_WORD_BYTE);
257*91f16700Schasinglulu 		}
258*91f16700Schasinglulu 
259*91f16700Schasinglulu 		/* reset async response param */
260*91f16700Schasinglulu 		mailbox_resp_ctr.index = 0;
261*91f16700Schasinglulu 		mailbox_resp_ctr.flag = 0;
262*91f16700Schasinglulu 
263*91f16700Schasinglulu 		if (MBOX_RESP_ERR(mailbox_resp_ctr.payload->header) > 0U) {
264*91f16700Schasinglulu 			INFO("Error in async response: %x\n",
265*91f16700Schasinglulu 				mailbox_resp_ctr.payload->header);
266*91f16700Schasinglulu 			return -MBOX_RESP_ERR(mailbox_resp_ctr.payload->header);
267*91f16700Schasinglulu 		}
268*91f16700Schasinglulu 
269*91f16700Schasinglulu 		return MBOX_RET_OK;
270*91f16700Schasinglulu 	}
271*91f16700Schasinglulu 
272*91f16700Schasinglulu 	*resp_len = 0;
273*91f16700Schasinglulu 	return (mailbox_resp_ctr.flag & MBOX_PAYLOAD_FLAG_BUSY) ? MBOX_BUSY : MBOX_NO_RESPONSE;
274*91f16700Schasinglulu }
275*91f16700Schasinglulu 
276*91f16700Schasinglulu int mailbox_poll_response(uint32_t job_id, uint32_t urgent, uint32_t *response,
277*91f16700Schasinglulu 				unsigned int *resp_len)
278*91f16700Schasinglulu {
279*91f16700Schasinglulu 	unsigned int timeout = 40U;
280*91f16700Schasinglulu 	unsigned int sdm_loop = 255U;
281*91f16700Schasinglulu 	unsigned int ret_resp_len;
282*91f16700Schasinglulu 	uint32_t rin;
283*91f16700Schasinglulu 	uint32_t rout;
284*91f16700Schasinglulu 	uint32_t resp_data;
285*91f16700Schasinglulu 
286*91f16700Schasinglulu 	while (sdm_loop != 0U) {
287*91f16700Schasinglulu 
288*91f16700Schasinglulu 		do {
289*91f16700Schasinglulu 			if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM)
290*91f16700Schasinglulu 				== 1U) {
291*91f16700Schasinglulu 				break;
292*91f16700Schasinglulu 			}
293*91f16700Schasinglulu 			mdelay(10U);
294*91f16700Schasinglulu 		} while (--timeout != 0U);
295*91f16700Schasinglulu 
296*91f16700Schasinglulu 		if (timeout == 0U) {
297*91f16700Schasinglulu 			break;
298*91f16700Schasinglulu 		}
299*91f16700Schasinglulu 
300*91f16700Schasinglulu 		mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U);
301*91f16700Schasinglulu 
302*91f16700Schasinglulu 		if ((urgent & 1U) != 0U) {
303*91f16700Schasinglulu 			mdelay(5U);
304*91f16700Schasinglulu 			if ((mmio_read_32(MBOX_OFFSET + MBOX_STATUS) &
305*91f16700Schasinglulu 				MBOX_STATUS_UA_MASK) ^
306*91f16700Schasinglulu 				(urgent & MBOX_STATUS_UA_MASK)) {
307*91f16700Schasinglulu 				mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U);
308*91f16700Schasinglulu 				return MBOX_RET_OK;
309*91f16700Schasinglulu 			}
310*91f16700Schasinglulu 
311*91f16700Schasinglulu 			mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U);
312*91f16700Schasinglulu 			INFO("Error: Mailbox did not get UA");
313*91f16700Schasinglulu 			return MBOX_RET_ERROR;
314*91f16700Schasinglulu 		}
315*91f16700Schasinglulu 
316*91f16700Schasinglulu 		rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
317*91f16700Schasinglulu 		rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
318*91f16700Schasinglulu 
319*91f16700Schasinglulu 		while (rout != rin) {
320*91f16700Schasinglulu 			resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP,
321*91f16700Schasinglulu 								(rout)++));
322*91f16700Schasinglulu 
323*91f16700Schasinglulu 			rout %= MBOX_RESP_BUFFER_SIZE;
324*91f16700Schasinglulu 			mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
325*91f16700Schasinglulu 
326*91f16700Schasinglulu 			if (MBOX_RESP_CLIENT_ID(resp_data) != MBOX_ATF_CLIENT_ID
327*91f16700Schasinglulu 				|| MBOX_RESP_JOB_ID(resp_data) != job_id) {
328*91f16700Schasinglulu 				continue;
329*91f16700Schasinglulu 			}
330*91f16700Schasinglulu 
331*91f16700Schasinglulu 			ret_resp_len = MBOX_RESP_LEN(resp_data);
332*91f16700Schasinglulu 
333*91f16700Schasinglulu 			if (iterate_resp(ret_resp_len, response, resp_len)
334*91f16700Schasinglulu 				!= MBOX_RET_OK) {
335*91f16700Schasinglulu 				return MBOX_TIMEOUT;
336*91f16700Schasinglulu 			}
337*91f16700Schasinglulu 
338*91f16700Schasinglulu 			if (MBOX_RESP_ERR(resp_data) > 0U) {
339*91f16700Schasinglulu 				INFO("Error in response: %x\n", resp_data);
340*91f16700Schasinglulu 				return -MBOX_RESP_ERR(resp_data);
341*91f16700Schasinglulu 			}
342*91f16700Schasinglulu 
343*91f16700Schasinglulu 			return MBOX_RET_OK;
344*91f16700Schasinglulu 		}
345*91f16700Schasinglulu 
346*91f16700Schasinglulu 	sdm_loop--;
347*91f16700Schasinglulu 	}
348*91f16700Schasinglulu 
349*91f16700Schasinglulu 	INFO("Timed out waiting for SDM\n");
350*91f16700Schasinglulu 	return MBOX_TIMEOUT;
351*91f16700Schasinglulu }
352*91f16700Schasinglulu 
353*91f16700Schasinglulu int iterate_resp(uint32_t mbox_resp_len, uint32_t *resp_buf,
354*91f16700Schasinglulu 			unsigned int *resp_len)
355*91f16700Schasinglulu {
356*91f16700Schasinglulu 	unsigned int timeout, total_resp_len = 0U;
357*91f16700Schasinglulu 	uint32_t resp_data;
358*91f16700Schasinglulu 	uint32_t rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
359*91f16700Schasinglulu 	uint32_t rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
360*91f16700Schasinglulu 
361*91f16700Schasinglulu 	while (mbox_resp_len > 0U) {
362*91f16700Schasinglulu 		timeout = 100U;
363*91f16700Schasinglulu 		mbox_resp_len--;
364*91f16700Schasinglulu 		resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++));
365*91f16700Schasinglulu 
366*91f16700Schasinglulu 		if ((resp_buf != NULL) && (resp_len != NULL)
367*91f16700Schasinglulu 			&& (*resp_len != 0U)) {
368*91f16700Schasinglulu 			*(resp_buf + total_resp_len)
369*91f16700Schasinglulu 					= resp_data;
370*91f16700Schasinglulu 			*resp_len = *resp_len - 1;
371*91f16700Schasinglulu 			total_resp_len++;
372*91f16700Schasinglulu 		}
373*91f16700Schasinglulu 		rout %= MBOX_RESP_BUFFER_SIZE;
374*91f16700Schasinglulu 		mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
375*91f16700Schasinglulu 
376*91f16700Schasinglulu 		do {
377*91f16700Schasinglulu 			rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
378*91f16700Schasinglulu 			if (rout == rin) {
379*91f16700Schasinglulu 				mdelay(10U);
380*91f16700Schasinglulu 			} else {
381*91f16700Schasinglulu 				break;
382*91f16700Schasinglulu 			}
383*91f16700Schasinglulu 			timeout--;
384*91f16700Schasinglulu 		} while ((mbox_resp_len > 0U) && (timeout != 0U));
385*91f16700Schasinglulu 
386*91f16700Schasinglulu 		if (timeout == 0U) {
387*91f16700Schasinglulu 			INFO("Timed out waiting for SDM\n");
388*91f16700Schasinglulu 			return MBOX_TIMEOUT;
389*91f16700Schasinglulu 		}
390*91f16700Schasinglulu 	}
391*91f16700Schasinglulu 
392*91f16700Schasinglulu 	if (resp_len)
393*91f16700Schasinglulu 		*resp_len = total_resp_len;
394*91f16700Schasinglulu 
395*91f16700Schasinglulu 	return MBOX_RET_OK;
396*91f16700Schasinglulu }
397*91f16700Schasinglulu 
398*91f16700Schasinglulu int mailbox_send_cmd_async_ext(uint32_t header_cmd, uint32_t *args,
399*91f16700Schasinglulu 			unsigned int len)
400*91f16700Schasinglulu {
401*91f16700Schasinglulu 	return fill_mailbox_circular_buffer(header_cmd, args, len);
402*91f16700Schasinglulu }
403*91f16700Schasinglulu 
404*91f16700Schasinglulu int mailbox_send_cmd_async(uint32_t *job_id, uint32_t cmd, uint32_t *args,
405*91f16700Schasinglulu 			  unsigned int len, unsigned int indirect)
406*91f16700Schasinglulu {
407*91f16700Schasinglulu 	int status;
408*91f16700Schasinglulu 
409*91f16700Schasinglulu 	status = fill_mailbox_circular_buffer(
410*91f16700Schasinglulu 				MBOX_CLIENT_ID_CMD(MBOX_ATF_CLIENT_ID) |
411*91f16700Schasinglulu 				MBOX_JOB_ID_CMD(*job_id) |
412*91f16700Schasinglulu 				MBOX_CMD_LEN_CMD(len) |
413*91f16700Schasinglulu 				MBOX_INDIRECT(indirect) |
414*91f16700Schasinglulu 				cmd, args, len);
415*91f16700Schasinglulu 	if (status < 0) {
416*91f16700Schasinglulu 		return status;
417*91f16700Schasinglulu 	}
418*91f16700Schasinglulu 
419*91f16700Schasinglulu 	*job_id = (*job_id + 1U) % MBOX_MAX_IND_JOB_ID;
420*91f16700Schasinglulu 
421*91f16700Schasinglulu 	return MBOX_RET_OK;
422*91f16700Schasinglulu }
423*91f16700Schasinglulu 
424*91f16700Schasinglulu int mailbox_send_cmd(uint32_t job_id, uint32_t cmd, uint32_t *args,
425*91f16700Schasinglulu 			unsigned int len, uint32_t urgent, uint32_t *response,
426*91f16700Schasinglulu 			unsigned int *resp_len)
427*91f16700Schasinglulu {
428*91f16700Schasinglulu 	int status = 0;
429*91f16700Schasinglulu 
430*91f16700Schasinglulu 	if (urgent != 0U) {
431*91f16700Schasinglulu 		urgent |= mmio_read_32(MBOX_OFFSET + MBOX_STATUS) &
432*91f16700Schasinglulu 					MBOX_STATUS_UA_MASK;
433*91f16700Schasinglulu 		mmio_write_32(MBOX_OFFSET + MBOX_URG, cmd);
434*91f16700Schasinglulu 		mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U);
435*91f16700Schasinglulu 	}
436*91f16700Schasinglulu 
437*91f16700Schasinglulu 	else {
438*91f16700Schasinglulu 		status = fill_mailbox_circular_buffer(
439*91f16700Schasinglulu 			MBOX_CLIENT_ID_CMD(MBOX_ATF_CLIENT_ID) |
440*91f16700Schasinglulu 			MBOX_JOB_ID_CMD(job_id) |
441*91f16700Schasinglulu 			MBOX_CMD_LEN_CMD(len) |
442*91f16700Schasinglulu 			cmd, args, len);
443*91f16700Schasinglulu 	}
444*91f16700Schasinglulu 
445*91f16700Schasinglulu 	if (status != 0) {
446*91f16700Schasinglulu 		return status;
447*91f16700Schasinglulu 	}
448*91f16700Schasinglulu 
449*91f16700Schasinglulu 	status = mailbox_poll_response(job_id, urgent, response, resp_len);
450*91f16700Schasinglulu 
451*91f16700Schasinglulu 	return status;
452*91f16700Schasinglulu }
453*91f16700Schasinglulu 
454*91f16700Schasinglulu void mailbox_clear_response(void)
455*91f16700Schasinglulu {
456*91f16700Schasinglulu 	mmio_write_32(MBOX_OFFSET + MBOX_ROUT,
457*91f16700Schasinglulu 		mmio_read_32(MBOX_OFFSET + MBOX_RIN));
458*91f16700Schasinglulu }
459*91f16700Schasinglulu 
460*91f16700Schasinglulu void mailbox_set_int(uint32_t interrupt)
461*91f16700Schasinglulu {
462*91f16700Schasinglulu 
463*91f16700Schasinglulu 	mmio_write_32(MBOX_OFFSET+MBOX_INT, MBOX_COE_BIT(interrupt) |
464*91f16700Schasinglulu 			MBOX_UAE_BIT(interrupt));
465*91f16700Schasinglulu }
466*91f16700Schasinglulu 
467*91f16700Schasinglulu 
468*91f16700Schasinglulu void mailbox_set_qspi_open(void)
469*91f16700Schasinglulu {
470*91f16700Schasinglulu 	mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
471*91f16700Schasinglulu 	mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_OPEN, NULL, 0U,
472*91f16700Schasinglulu 				CMD_CASUAL, NULL, NULL);
473*91f16700Schasinglulu }
474*91f16700Schasinglulu 
475*91f16700Schasinglulu void mailbox_set_qspi_direct(void)
476*91f16700Schasinglulu {
477*91f16700Schasinglulu 	uint32_t response[1], qspi_clk, reg;
478*91f16700Schasinglulu 	unsigned int resp_len = ARRAY_SIZE(response);
479*91f16700Schasinglulu 
480*91f16700Schasinglulu 	mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_DIRECT, NULL, 0U,
481*91f16700Schasinglulu 			 CMD_CASUAL, response, &resp_len);
482*91f16700Schasinglulu 
483*91f16700Schasinglulu 	qspi_clk = response[0];
484*91f16700Schasinglulu 	INFO("QSPI ref clock: %u\n", qspi_clk);
485*91f16700Schasinglulu 
486*91f16700Schasinglulu 	/*
487*91f16700Schasinglulu 	 * Store QSPI ref clock frequency in BOOT_SCRATCH_COLD_0 register for
488*91f16700Schasinglulu 	 * later boot loader (i.e. u-boot) use.
489*91f16700Schasinglulu 	 * The frequency is stored in kHz and occupies BOOT_SCRATCH_COLD_0
490*91f16700Schasinglulu 	 * register bits[27:0].
491*91f16700Schasinglulu 	 */
492*91f16700Schasinglulu 	qspi_clk /= 1000;
493*91f16700Schasinglulu 	reg = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_0));
494*91f16700Schasinglulu 	reg &= ~SYSMGR_QSPI_REFCLK_MASK;
495*91f16700Schasinglulu 	reg |= qspi_clk & SYSMGR_QSPI_REFCLK_MASK;
496*91f16700Schasinglulu 	mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_0), reg);
497*91f16700Schasinglulu }
498*91f16700Schasinglulu 
499*91f16700Schasinglulu void mailbox_set_qspi_close(void)
500*91f16700Schasinglulu {
501*91f16700Schasinglulu 	mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
502*91f16700Schasinglulu 	mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_CLOSE, NULL, 0U,
503*91f16700Schasinglulu 				CMD_CASUAL, NULL, NULL);
504*91f16700Schasinglulu }
505*91f16700Schasinglulu 
506*91f16700Schasinglulu void mailbox_qspi_set_cs(uint32_t device_select)
507*91f16700Schasinglulu {
508*91f16700Schasinglulu 	uint32_t cs_setting;
509*91f16700Schasinglulu 
510*91f16700Schasinglulu 	/* QSPI device select settings at 31:28 */
511*91f16700Schasinglulu 	cs_setting = (device_select << 28);
512*91f16700Schasinglulu 	mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
513*91f16700Schasinglulu 	mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_SET_CS, &cs_setting,
514*91f16700Schasinglulu 				1U, CMD_CASUAL, NULL, NULL);
515*91f16700Schasinglulu }
516*91f16700Schasinglulu 
517*91f16700Schasinglulu void mailbox_hps_qspi_enable(void)
518*91f16700Schasinglulu {
519*91f16700Schasinglulu 	mailbox_set_qspi_open();
520*91f16700Schasinglulu 	mailbox_set_qspi_direct();
521*91f16700Schasinglulu }
522*91f16700Schasinglulu 
523*91f16700Schasinglulu void mailbox_reset_cold(void)
524*91f16700Schasinglulu {
525*91f16700Schasinglulu 	mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
526*91f16700Schasinglulu 
527*91f16700Schasinglulu 	mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_REBOOT_HPS, 0U, 0U,
528*91f16700Schasinglulu 				 CMD_CASUAL, NULL, NULL);
529*91f16700Schasinglulu }
530*91f16700Schasinglulu 
531*91f16700Schasinglulu void mailbox_reset_warm(uint32_t reset_type)
532*91f16700Schasinglulu {
533*91f16700Schasinglulu 	mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
534*91f16700Schasinglulu 
535*91f16700Schasinglulu 	reset_type = 0x01; // Warm reset header data must be 1
536*91f16700Schasinglulu 	mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_REBOOT_HPS, &reset_type, 1U,
537*91f16700Schasinglulu 				 CMD_CASUAL, NULL, NULL);
538*91f16700Schasinglulu }
539*91f16700Schasinglulu 
540*91f16700Schasinglulu int mailbox_rsu_get_spt_offset(uint32_t *resp_buf, unsigned int resp_buf_len)
541*91f16700Schasinglulu {
542*91f16700Schasinglulu 	return mailbox_send_cmd(MBOX_JOB_ID, MBOX_GET_SUBPARTITION_TABLE,
543*91f16700Schasinglulu 				NULL, 0U, CMD_CASUAL, resp_buf,
544*91f16700Schasinglulu 				&resp_buf_len);
545*91f16700Schasinglulu }
546*91f16700Schasinglulu 
547*91f16700Schasinglulu struct rsu_status_info {
548*91f16700Schasinglulu 	uint64_t current_image;
549*91f16700Schasinglulu 	uint64_t fail_image;
550*91f16700Schasinglulu 	uint32_t state;
551*91f16700Schasinglulu 	uint32_t version;
552*91f16700Schasinglulu 	uint32_t error_location;
553*91f16700Schasinglulu 	uint32_t error_details;
554*91f16700Schasinglulu 	uint32_t retry_counter;
555*91f16700Schasinglulu };
556*91f16700Schasinglulu 
557*91f16700Schasinglulu int mailbox_rsu_status(uint32_t *resp_buf, unsigned int resp_buf_len)
558*91f16700Schasinglulu {
559*91f16700Schasinglulu 	int ret;
560*91f16700Schasinglulu 	struct rsu_status_info *info = (struct rsu_status_info *)resp_buf;
561*91f16700Schasinglulu 
562*91f16700Schasinglulu 	info->retry_counter = ~0U;
563*91f16700Schasinglulu 
564*91f16700Schasinglulu 	ret = mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_STATUS, NULL, 0U,
565*91f16700Schasinglulu 				CMD_CASUAL, resp_buf,
566*91f16700Schasinglulu 				&resp_buf_len);
567*91f16700Schasinglulu 
568*91f16700Schasinglulu 	if (ret < 0) {
569*91f16700Schasinglulu 		return ret;
570*91f16700Schasinglulu 	}
571*91f16700Schasinglulu 
572*91f16700Schasinglulu 	if (info->retry_counter != ~0U) {
573*91f16700Schasinglulu 		if ((info->version & RSU_VERSION_ACMF_MASK) == 0U) {
574*91f16700Schasinglulu 			info->version |= RSU_VERSION_ACMF;
575*91f16700Schasinglulu 		}
576*91f16700Schasinglulu 	}
577*91f16700Schasinglulu 
578*91f16700Schasinglulu 	return ret;
579*91f16700Schasinglulu }
580*91f16700Schasinglulu 
581*91f16700Schasinglulu int mailbox_rsu_update(uint32_t *flash_offset)
582*91f16700Schasinglulu {
583*91f16700Schasinglulu 	return mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_UPDATE,
584*91f16700Schasinglulu 				flash_offset, 2U,
585*91f16700Schasinglulu 				CMD_CASUAL, NULL, NULL);
586*91f16700Schasinglulu }
587*91f16700Schasinglulu 
588*91f16700Schasinglulu int mailbox_hps_stage_notify(uint32_t execution_stage)
589*91f16700Schasinglulu {
590*91f16700Schasinglulu 	return mailbox_send_cmd(MBOX_JOB_ID, MBOX_HPS_STAGE_NOTIFY,
591*91f16700Schasinglulu 				&execution_stage, 1U, CMD_CASUAL,
592*91f16700Schasinglulu 				NULL, NULL);
593*91f16700Schasinglulu }
594*91f16700Schasinglulu 
595*91f16700Schasinglulu int mailbox_init(void)
596*91f16700Schasinglulu {
597*91f16700Schasinglulu 	int status;
598*91f16700Schasinglulu 
599*91f16700Schasinglulu 	mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE |
600*91f16700Schasinglulu 			MBOX_INT_FLAG_UAE);
601*91f16700Schasinglulu 	mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U);
602*91f16700Schasinglulu 	mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U);
603*91f16700Schasinglulu 
604*91f16700Schasinglulu 	status = mailbox_send_cmd(0U, MBOX_CMD_RESTART, NULL, 0U,
605*91f16700Schasinglulu 					CMD_URGENT, NULL, NULL);
606*91f16700Schasinglulu 
607*91f16700Schasinglulu 	if (status != 0) {
608*91f16700Schasinglulu 		return status;
609*91f16700Schasinglulu 	}
610*91f16700Schasinglulu 
611*91f16700Schasinglulu 	mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE |
612*91f16700Schasinglulu 			MBOX_INT_FLAG_UAE);
613*91f16700Schasinglulu 
614*91f16700Schasinglulu 	return MBOX_RET_OK;
615*91f16700Schasinglulu }
616*91f16700Schasinglulu 
617*91f16700Schasinglulu int intel_mailbox_get_config_status(uint32_t cmd, bool init_done)
618*91f16700Schasinglulu {
619*91f16700Schasinglulu 	int status;
620*91f16700Schasinglulu 	uint32_t res, response[6];
621*91f16700Schasinglulu 	unsigned int resp_len = ARRAY_SIZE(response);
622*91f16700Schasinglulu 
623*91f16700Schasinglulu 	status = mailbox_send_cmd(MBOX_JOB_ID, cmd, NULL, 0U, CMD_CASUAL,
624*91f16700Schasinglulu 				response, &resp_len);
625*91f16700Schasinglulu 
626*91f16700Schasinglulu 	if (status < 0) {
627*91f16700Schasinglulu 		return status;
628*91f16700Schasinglulu 	}
629*91f16700Schasinglulu 
630*91f16700Schasinglulu 	res = response[RECONFIG_STATUS_STATE];
631*91f16700Schasinglulu 
632*91f16700Schasinglulu 	if (res == MBOX_CFGSTAT_VAB_BS_PREAUTH) {
633*91f16700Schasinglulu 		return MBOX_CFGSTAT_STATE_CONFIG;
634*91f16700Schasinglulu 	}
635*91f16700Schasinglulu 
636*91f16700Schasinglulu 	if ((res != 0U) && (res != MBOX_CFGSTAT_STATE_CONFIG)) {
637*91f16700Schasinglulu 		return res;
638*91f16700Schasinglulu 	}
639*91f16700Schasinglulu 
640*91f16700Schasinglulu 	res = response[RECONFIG_STATUS_PIN_STATUS];
641*91f16700Schasinglulu 	if ((res & PIN_STATUS_NSTATUS) == 0U) {
642*91f16700Schasinglulu 		return MBOX_CFGSTAT_STATE_ERROR_HARDWARE;
643*91f16700Schasinglulu 	}
644*91f16700Schasinglulu 
645*91f16700Schasinglulu 	res = response[RECONFIG_STATUS_SOFTFUNC_STATUS];
646*91f16700Schasinglulu 	if ((res & SOFTFUNC_STATUS_SEU_ERROR) != 0U) {
647*91f16700Schasinglulu 		ERROR("SoftFunction Status SEU ERROR\n");
648*91f16700Schasinglulu 	}
649*91f16700Schasinglulu 
650*91f16700Schasinglulu 	if ((res & SOFTFUNC_STATUS_CONF_DONE) == 0U) {
651*91f16700Schasinglulu 		return MBOX_CFGSTAT_STATE_CONFIG;
652*91f16700Schasinglulu 	}
653*91f16700Schasinglulu 
654*91f16700Schasinglulu 	if (init_done && (res & SOFTFUNC_STATUS_INIT_DONE) == 0U) {
655*91f16700Schasinglulu 		return MBOX_CFGSTAT_STATE_CONFIG;
656*91f16700Schasinglulu 	}
657*91f16700Schasinglulu 
658*91f16700Schasinglulu 	return MBOX_RET_OK;
659*91f16700Schasinglulu }
660*91f16700Schasinglulu 
661*91f16700Schasinglulu int intel_mailbox_is_fpga_not_ready(void)
662*91f16700Schasinglulu {
663*91f16700Schasinglulu 	int ret = intel_mailbox_get_config_status(MBOX_RECONFIG_STATUS, true);
664*91f16700Schasinglulu 
665*91f16700Schasinglulu 	if ((ret != MBOX_RET_OK) && (ret != MBOX_CFGSTAT_STATE_CONFIG)) {
666*91f16700Schasinglulu 		ret = intel_mailbox_get_config_status(MBOX_CONFIG_STATUS,
667*91f16700Schasinglulu 							false);
668*91f16700Schasinglulu 	}
669*91f16700Schasinglulu 
670*91f16700Schasinglulu 	return ret;
671*91f16700Schasinglulu }
672*91f16700Schasinglulu 
673*91f16700Schasinglulu int mailbox_hwmon_readtemp(uint32_t chan, uint32_t *resp_buf)
674*91f16700Schasinglulu {
675*91f16700Schasinglulu 	unsigned int resp_len = sizeof(resp_buf);
676*91f16700Schasinglulu 
677*91f16700Schasinglulu 	return mailbox_send_cmd(MBOX_JOB_ID, MBOX_HWMON_READTEMP, &chan, 1U,
678*91f16700Schasinglulu 				CMD_CASUAL, resp_buf,
679*91f16700Schasinglulu 				&resp_len);
680*91f16700Schasinglulu 
681*91f16700Schasinglulu }
682*91f16700Schasinglulu 
683*91f16700Schasinglulu int mailbox_hwmon_readvolt(uint32_t chan, uint32_t *resp_buf)
684*91f16700Schasinglulu {
685*91f16700Schasinglulu 	unsigned int resp_len = sizeof(resp_buf);
686*91f16700Schasinglulu 
687*91f16700Schasinglulu 	return mailbox_send_cmd(MBOX_JOB_ID, MBOX_HWMON_READVOLT, &chan, 1U,
688*91f16700Schasinglulu 				CMD_CASUAL, resp_buf,
689*91f16700Schasinglulu 				&resp_len);
690*91f16700Schasinglulu }
691*91f16700Schasinglulu 
692*91f16700Schasinglulu int mailbox_seu_err_status(uint32_t *resp_buf, unsigned int resp_buf_len)
693*91f16700Schasinglulu {
694*91f16700Schasinglulu 
695*91f16700Schasinglulu 	return mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_SEU_ERR_READ, NULL, 0U,
696*91f16700Schasinglulu 				CMD_CASUAL, resp_buf,
697*91f16700Schasinglulu 				&resp_buf_len);
698*91f16700Schasinglulu }
699