• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2019, Intel Corporation. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <lib/mmio.h>
8 #include <common/debug.h>
9 #include <drivers/delay_timer.h>
10 
11 #include "socfpga_mailbox.h"
12 #include "socfpga_sip_svc.h"
13 
fill_mailbox_circular_buffer(uint32_t header_cmd,uint32_t * args,int len)14 static int fill_mailbox_circular_buffer(uint32_t header_cmd, uint32_t *args,
15 					int len)
16 {
17 	uint32_t cmd_free_offset;
18 	int i;
19 
20 	cmd_free_offset = mmio_read_32(MBOX_OFFSET + MBOX_CIN);
21 
22 	mmio_write_32(MBOX_OFFSET + MBOX_CMD_BUFFER + (cmd_free_offset++ * 4),
23 			header_cmd);
24 
25 
26 	for (i = 0; i < len; i++) {
27 		cmd_free_offset %= MBOX_CMD_BUFFER_SIZE;
28 		mmio_write_32(MBOX_OFFSET + MBOX_CMD_BUFFER +
29 				(cmd_free_offset++ * 4), args[i]);
30 	}
31 
32 	cmd_free_offset %= MBOX_CMD_BUFFER_SIZE;
33 	mmio_write_32(MBOX_OFFSET + MBOX_CIN, cmd_free_offset);
34 
35 	return 0;
36 }
37 
mailbox_read_response(int job_id,uint32_t * response,int resp_len)38 int mailbox_read_response(int job_id, uint32_t *response, int resp_len)
39 {
40 	int rin = 0;
41 	int rout = 0;
42 	int response_length = 0;
43 	int resp = 0;
44 	int total_resp_len = 0;
45 
46 	if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM))
47 		mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0);
48 
49 	rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
50 	rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
51 
52 	if (rout != rin) {
53 		resp = mmio_read_32(MBOX_OFFSET +
54 				    MBOX_RESP_BUFFER + ((rout++)*4));
55 
56 		rout %= MBOX_RESP_BUFFER_SIZE;
57 		mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
58 
59 		if (MBOX_RESP_CLIENT_ID(resp) != MBOX_ATF_CLIENT_ID ||
60 		   MBOX_RESP_JOB_ID(resp) != job_id) {
61 			return MBOX_WRONG_ID;
62 		}
63 
64 		if (MBOX_RESP_ERR(resp) > 0) {
65 			INFO("Error in response: %x\n", resp);
66 			return -resp;
67 		}
68 		response_length = MBOX_RESP_LEN(resp);
69 
70 		while (response_length) {
71 
72 			response_length--;
73 			resp = mmio_read_32(MBOX_OFFSET +
74 						MBOX_RESP_BUFFER +
75 						(rout)*4);
76 			if (response && resp_len) {
77 				*(response + total_resp_len) = resp;
78 				resp_len--;
79 				total_resp_len++;
80 			}
81 			rout++;
82 			rout %= MBOX_RESP_BUFFER_SIZE;
83 			mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
84 		}
85 		return total_resp_len;
86 	}
87 
88 	return MBOX_NO_RESPONSE;
89 }
90 
91 
mailbox_poll_response(int job_id,int urgent,uint32_t * response,int resp_len)92 int mailbox_poll_response(int job_id, int urgent, uint32_t *response,
93 				int resp_len)
94 {
95 	int timeout = 0xFFFFFF;
96 	int rin = 0;
97 	int rout = 0;
98 	int response_length = 0;
99 	int resp = 0;
100 	int total_resp_len = 0;
101 
102 	while (1) {
103 
104 		while (timeout > 0 &&
105 			!(mmio_read_32(MBOX_OFFSET +
106 				MBOX_DOORBELL_FROM_SDM) & 1)) {
107 			timeout--;
108 		}
109 
110 		if (!timeout) {
111 			INFO("Timed out waiting for SDM");
112 			return MBOX_TIMEOUT;
113 		}
114 
115 		mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0);
116 
117 		if (urgent & 1) {
118 			mdelay(5);
119 			if ((mmio_read_32(MBOX_OFFSET + MBOX_STATUS) &
120 				MBOX_STATUS_UA_MASK) ^
121 				(urgent & MBOX_STATUS_UA_MASK)) {
122 				mmio_write_32(MBOX_OFFSET + MBOX_URG, 0);
123 				return 0;
124 			}
125 
126 			mmio_write_32(MBOX_OFFSET + MBOX_URG, 0);
127 			INFO("Error: Mailbox did not get UA");
128 			return -1;
129 		}
130 
131 		rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
132 		rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
133 
134 		while (rout != rin) {
135 			resp = mmio_read_32(MBOX_OFFSET +
136 					    MBOX_RESP_BUFFER + ((rout++)*4));
137 
138 			rout %= MBOX_RESP_BUFFER_SIZE;
139 			mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
140 
141 			if (MBOX_RESP_CLIENT_ID(resp) != MBOX_ATF_CLIENT_ID ||
142 			   MBOX_RESP_JOB_ID(resp) != job_id)
143 				continue;
144 
145 			if (MBOX_RESP_ERR(resp) > 0) {
146 				INFO("Error in response: %x\n", resp);
147 				return -MBOX_RESP_ERR(resp);
148 			}
149 			response_length = MBOX_RESP_LEN(resp);
150 
151 			while (response_length) {
152 				response_length--;
153 				resp = mmio_read_32(MBOX_OFFSET +
154 							MBOX_RESP_BUFFER +
155 							(rout)*4);
156 				if (response && resp_len) {
157 					*(response + total_resp_len) = resp;
158 					resp_len--;
159 					total_resp_len++;
160 				}
161 				rout++;
162 				rout %= MBOX_RESP_BUFFER_SIZE;
163 				mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
164 			}
165 			return total_resp_len;
166 		}
167 	}
168 }
169 
mailbox_send_cmd_async(int job_id,unsigned int cmd,uint32_t * args,int len,int urgent)170 int mailbox_send_cmd_async(int job_id, unsigned int cmd, uint32_t *args,
171 			  int len, int urgent)
172 {
173 	if (urgent)
174 		mmio_write_32(MBOX_OFFSET + MBOX_URG, 1);
175 
176 	fill_mailbox_circular_buffer(MBOX_CLIENT_ID_CMD(MBOX_ATF_CLIENT_ID) |
177 					MBOX_JOB_ID_CMD(job_id) |
178 					MBOX_CMD_LEN_CMD(len) |
179 					MBOX_INDIRECT |
180 					cmd, args, len);
181 
182 	mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1);
183 
184 	return 0;
185 }
186 
mailbox_send_cmd(int job_id,unsigned int cmd,uint32_t * args,int len,int urgent,uint32_t * response,int resp_len)187 int mailbox_send_cmd(int job_id, unsigned int cmd, uint32_t *args,
188 			int len, int urgent, uint32_t *response, int resp_len)
189 {
190 	int status = 0;
191 
192 	if (urgent) {
193 		urgent |= mmio_read_32(MBOX_OFFSET + MBOX_STATUS) &
194 					MBOX_STATUS_UA_MASK;
195 		mmio_write_32(MBOX_OFFSET + MBOX_URG, cmd);
196 	}
197 
198 	else {
199 		status = fill_mailbox_circular_buffer(
200 			MBOX_CLIENT_ID_CMD(MBOX_ATF_CLIENT_ID) |
201 			MBOX_JOB_ID_CMD(job_id) |
202 			MBOX_CMD_LEN_CMD(len) |
203 			cmd, args, len);
204 	}
205 
206 	if (status)
207 		return status;
208 
209 	mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1);
210 	status = mailbox_poll_response(job_id, urgent, response, resp_len);
211 
212 	return status;
213 }
214 
mailbox_clear_response(void)215 void mailbox_clear_response(void)
216 {
217 	mmio_write_32(MBOX_OFFSET + MBOX_ROUT,
218 		mmio_read_32(MBOX_OFFSET + MBOX_RIN));
219 }
220 
mailbox_set_int(int interrupt)221 void mailbox_set_int(int interrupt)
222 {
223 
224 	mmio_write_32(MBOX_OFFSET+MBOX_INT, MBOX_COE_BIT(interrupt) |
225 			MBOX_UAE_BIT(interrupt));
226 }
227 
228 
mailbox_set_qspi_open(void)229 void mailbox_set_qspi_open(void)
230 {
231 	mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
232 	mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_OPEN, 0, 0, 0, NULL, 0);
233 }
234 
mailbox_set_qspi_direct(void)235 void mailbox_set_qspi_direct(void)
236 {
237 	mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_DIRECT, 0, 0, 0, NULL, 0);
238 }
239 
mailbox_set_qspi_close(void)240 void mailbox_set_qspi_close(void)
241 {
242 	mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
243 	mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_CLOSE, 0, 0, 0, NULL, 0);
244 }
245 
mailbox_get_qspi_clock(void)246 int mailbox_get_qspi_clock(void)
247 {
248 	mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
249 	return mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_DIRECT, 0, 0, 0,
250 				NULL, 0);
251 }
252 
mailbox_qspi_set_cs(int device_select)253 void mailbox_qspi_set_cs(int device_select)
254 {
255 	uint32_t cs_setting = device_select;
256 
257 	/* QSPI device select settings at 31:28 */
258 	cs_setting = (cs_setting << 28);
259 	mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
260 	mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_SET_CS, &cs_setting,
261 				1, 0, NULL, 0);
262 }
263 
mailbox_reset_cold(void)264 void mailbox_reset_cold(void)
265 {
266 	mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
267 	mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_REBOOT_HPS, 0, 0, 0, NULL, 0);
268 }
269 
mailbox_init(void)270 int mailbox_init(void)
271 {
272 	int status = 0;
273 
274 	mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE |
275 			MBOX_INT_FLAG_UAE);
276 	mmio_write_32(MBOX_OFFSET + MBOX_URG, 0);
277 	mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0);
278 
279 	status = mailbox_send_cmd(0, MBOX_CMD_RESTART, 0, 0, 1, NULL, 0);
280 
281 	if (status)
282 		return status;
283 
284 	mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE |
285 			MBOX_INT_FLAG_UAE);
286 
287 	return 0;
288 }
289 
intel_mailbox_get_config_status(uint32_t cmd)290 uint32_t intel_mailbox_get_config_status(uint32_t cmd)
291 {
292 	uint32_t status, res;
293 	uint32_t response[6];
294 
295 	status = mailbox_send_cmd(1, cmd, NULL, 0, 0, response,
296 		sizeof(response) / sizeof(response[0]));
297 
298 	if (status < 0)
299 		return status;
300 
301 	res = response[RECONFIG_STATUS_STATE];
302 	if (res && res != MBOX_CFGSTAT_STATE_CONFIG)
303 		return res;
304 
305 	res = response[RECONFIG_STATUS_PIN_STATUS];
306 	if (!(res & PIN_STATUS_NSTATUS))
307 		return MBOX_CFGSTAT_STATE_ERROR_HARDWARE;
308 
309 	res = response[RECONFIG_STATUS_SOFTFUNC_STATUS];
310 	if (res & SOFTFUNC_STATUS_SEU_ERROR)
311 		return MBOX_CFGSTAT_STATE_ERROR_HARDWARE;
312 
313 	if ((res & SOFTFUNC_STATUS_CONF_DONE) &&
314 		(res & SOFTFUNC_STATUS_INIT_DONE))
315 		return 0;
316 
317 	return MBOX_CFGSTAT_STATE_CONFIG;
318 }
319 
intel_mailbox_is_fpga_not_ready(void)320 int intel_mailbox_is_fpga_not_ready(void)
321 {
322 	int ret = intel_mailbox_get_config_status(MBOX_RECONFIG_STATUS);
323 
324 	if (ret && ret != MBOX_CFGSTAT_STATE_CONFIG)
325 		ret = intel_mailbox_get_config_status(MBOX_CONFIG_STATUS);
326 
327 	return ret;
328 }
329