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