blob: 61218ebed5a160c946258090c7d39b1e258e7ac7 [file] [log] [blame]
Hadi Asyrafi616da772019-06-27 11:34:03 +08001/*
2 * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <common/debug.h>
9#include <common/runtime_svc.h>
10#include <tools_share/uuid.h>
11
Hadi Asyrafi6f8a2b22019-10-23 18:34:14 +080012#include "socfpga_mailbox.h"
Hadi Asyrafiab1132f2019-10-22 10:31:45 +080013#include "socfpga_sip_svc.h"
Hadi Asyrafi616da772019-06-27 11:34:03 +080014
15/* Number of SiP Calls implemented */
16#define SIP_NUM_CALLS 0x3
17
18/* Total buffer the driver can hold */
19#define FPGA_CONFIG_BUFFER_SIZE 4
20
21int current_block;
22int current_buffer;
23int current_id = 1;
24int max_blocks;
25uint32_t bytes_per_block;
26uint32_t blocks_submitted;
27uint32_t blocks_completed;
28
29struct fpga_config_info {
30 uint32_t addr;
31 int size;
32 int size_written;
33 uint32_t write_requested;
34 int subblocks_sent;
35 int block_number;
36};
37
38/* SiP Service UUID */
39DEFINE_SVC_UUID2(intl_svc_uid,
40 0xa85273b0, 0xe85a, 0x4862, 0xa6, 0x2a,
41 0xfa, 0x88, 0x88, 0x17, 0x68, 0x81);
42
43uint64_t socfpga_sip_handler(uint32_t smc_fid,
44 uint64_t x1,
45 uint64_t x2,
46 uint64_t x3,
47 uint64_t x4,
48 void *cookie,
49 void *handle,
50 uint64_t flags)
51{
52 ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
53 SMC_RET1(handle, SMC_UNK);
54}
55
56struct fpga_config_info fpga_config_buffers[FPGA_CONFIG_BUFFER_SIZE];
57
58static void intel_fpga_sdm_write_buffer(struct fpga_config_info *buffer)
59{
60 uint32_t args[3];
61
62 while (max_blocks > 0 && buffer->size > buffer->size_written) {
63 if (buffer->size - buffer->size_written <=
64 bytes_per_block) {
65 args[0] = (1<<8);
66 args[1] = buffer->addr + buffer->size_written;
67 args[2] = buffer->size - buffer->size_written;
68 buffer->size_written +=
69 buffer->size - buffer->size_written;
70 buffer->subblocks_sent++;
71 mailbox_send_cmd_async(0x4,
72 MBOX_RECONFIG_DATA,
73 args, 3, 0);
74 current_buffer++;
75 current_buffer %= FPGA_CONFIG_BUFFER_SIZE;
76 } else {
77 args[0] = (1<<8);
78 args[1] = buffer->addr + buffer->size_written;
79 args[2] = bytes_per_block;
80 buffer->size_written += bytes_per_block;
81 mailbox_send_cmd_async(0x4,
82 MBOX_RECONFIG_DATA,
83 args, 3, 0);
84 buffer->subblocks_sent++;
85 }
86 max_blocks--;
87 }
88}
89
90static int intel_fpga_sdm_write_all(void)
91{
92 int i;
93
94 for (i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++)
95 intel_fpga_sdm_write_buffer(
96 &fpga_config_buffers[current_buffer]);
97
98 return 0;
99}
100
101uint32_t intel_mailbox_fpga_config_isdone(void)
102{
103 uint32_t args[2];
104 uint32_t response[6];
105 int status;
106
107 status = mailbox_send_cmd(1, MBOX_RECONFIG_STATUS, args, 0, 0,
108 response);
109
110 if (status < 0)
111 return INTEL_SIP_SMC_STATUS_ERROR;
112
113 if (response[RECONFIG_STATUS_STATE] &&
114 response[RECONFIG_STATUS_STATE] != MBOX_CFGSTAT_STATE_CONFIG)
115 return INTEL_SIP_SMC_STATUS_ERROR;
116
117 if (!(response[RECONFIG_STATUS_PIN_STATUS] & PIN_STATUS_NSTATUS))
118 return INTEL_SIP_SMC_STATUS_ERROR;
119
120 if (response[RECONFIG_STATUS_SOFTFUNC_STATUS] &
121 SOFTFUNC_STATUS_SEU_ERROR)
122 return INTEL_SIP_SMC_STATUS_ERROR;
123
124 if ((response[RECONFIG_STATUS_SOFTFUNC_STATUS] &
125 SOFTFUNC_STATUS_CONF_DONE) &&
126 (response[RECONFIG_STATUS_SOFTFUNC_STATUS] &
127 SOFTFUNC_STATUS_INIT_DONE))
128 return INTEL_SIP_SMC_STATUS_OK;
129
130 return INTEL_SIP_SMC_STATUS_ERROR;
131}
132
133static int mark_last_buffer_xfer_completed(uint32_t *buffer_addr_completed)
134{
135 int i;
136
137 for (i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
138 if (fpga_config_buffers[i].block_number == current_block) {
139 fpga_config_buffers[i].subblocks_sent--;
140 if (fpga_config_buffers[i].subblocks_sent == 0
141 && fpga_config_buffers[i].size <=
142 fpga_config_buffers[i].size_written) {
143 fpga_config_buffers[i].write_requested = 0;
144 current_block++;
145 *buffer_addr_completed =
146 fpga_config_buffers[i].addr;
147 return 0;
148 }
149 }
150 }
151
152 return -1;
153}
154
155unsigned int address_in_ddr(uint32_t *addr)
156{
157 if (((unsigned long long)addr > DRAM_BASE) &&
158 ((unsigned long long)addr < DRAM_BASE + DRAM_SIZE))
159 return 0;
160
161 return -1;
162}
163
164int intel_fpga_config_completed_write(uint32_t *completed_addr,
165 uint32_t *count)
166{
167 uint32_t status = INTEL_SIP_SMC_STATUS_OK;
168 *count = 0;
169 int resp_len = 0;
170 uint32_t resp[5];
171 int all_completed = 1;
172 int count_check = 0;
173
174 if (address_in_ddr(completed_addr) != 0 || address_in_ddr(count) != 0)
175 return INTEL_SIP_SMC_STATUS_ERROR;
176
177 for (count_check = 0; count_check < 3; count_check++)
178 if (address_in_ddr(&completed_addr[*count + count_check]) != 0)
179 return INTEL_SIP_SMC_STATUS_ERROR;
180
181 resp_len = mailbox_read_response(0x4, resp);
182
183 while (resp_len >= 0 && *count < 3) {
184 max_blocks++;
185 if (mark_last_buffer_xfer_completed(
186 &completed_addr[*count]) == 0)
187 *count = *count + 1;
188 else
189 break;
190 resp_len = mailbox_read_response(0x4, resp);
191 }
192
193 if (*count <= 0) {
194 if (resp_len != MBOX_NO_RESPONSE &&
195 resp_len != MBOX_TIMEOUT && resp_len != 0) {
196 return INTEL_SIP_SMC_STATUS_ERROR;
197 }
198
199 *count = 0;
200 }
201
202 intel_fpga_sdm_write_all();
203
204 if (*count > 0)
205 status = INTEL_SIP_SMC_STATUS_OK;
206 else if (*count == 0)
207 status = INTEL_SIP_SMC_STATUS_BUSY;
208
209 for (int i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
210 if (fpga_config_buffers[i].write_requested != 0) {
211 all_completed = 0;
212 break;
213 }
214 }
215
216 if (all_completed == 1)
217 return INTEL_SIP_SMC_STATUS_OK;
218
219 return status;
220}
221
222int intel_fpga_config_start(uint32_t config_type)
223{
224 uint32_t response[3];
225 int status = 0;
226
227 status = mailbox_send_cmd(2, MBOX_RECONFIG, 0, 0, 0,
228 response);
229
230 if (status < 0)
231 return status;
232
233 max_blocks = response[0];
234 bytes_per_block = response[1];
235
236 for (int i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
237 fpga_config_buffers[i].size = 0;
238 fpga_config_buffers[i].size_written = 0;
239 fpga_config_buffers[i].addr = 0;
240 fpga_config_buffers[i].write_requested = 0;
241 fpga_config_buffers[i].block_number = 0;
242 fpga_config_buffers[i].subblocks_sent = 0;
243 }
244
245 blocks_submitted = 0;
246 current_block = 0;
247 current_buffer = 0;
248
249 return 0;
250}
251
252
253uint32_t intel_fpga_config_write(uint64_t mem, uint64_t size)
254{
255 int i = 0;
256 uint32_t status = INTEL_SIP_SMC_STATUS_OK;
257
258 if (mem < DRAM_BASE || mem > DRAM_BASE + DRAM_SIZE)
259 status = INTEL_SIP_SMC_STATUS_REJECTED;
260
261 if (mem + size > DRAM_BASE + DRAM_SIZE)
262 status = INTEL_SIP_SMC_STATUS_REJECTED;
263
264 for (i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
265 if (!fpga_config_buffers[i].write_requested) {
266 fpga_config_buffers[i].addr = mem;
267 fpga_config_buffers[i].size = size;
268 fpga_config_buffers[i].size_written = 0;
269 fpga_config_buffers[i].write_requested = 1;
270 fpga_config_buffers[i].block_number =
271 blocks_submitted++;
272 fpga_config_buffers[i].subblocks_sent = 0;
273 break;
274 }
275 }
276
277
278 if (i == FPGA_CONFIG_BUFFER_SIZE) {
279 status = INTEL_SIP_SMC_STATUS_REJECTED;
280 return status;
281 } else if (i == FPGA_CONFIG_BUFFER_SIZE - 1) {
282 status = INTEL_SIP_SMC_STATUS_BUSY;
283 }
284
285 intel_fpga_sdm_write_all();
286
287 return status;
288}
289
290/*
291 * This function is responsible for handling all SiP calls from the NS world
292 */
293
294uintptr_t sip_smc_handler(uint32_t smc_fid,
295 u_register_t x1,
296 u_register_t x2,
297 u_register_t x3,
298 u_register_t x4,
299 void *cookie,
300 void *handle,
301 u_register_t flags)
302{
303 uint32_t status = INTEL_SIP_SMC_STATUS_OK;
304 uint32_t completed_addr[3];
305 uint32_t count = 0;
306
307 switch (smc_fid) {
308 case SIP_SVC_UID:
309 /* Return UID to the caller */
310 SMC_UUID_RET(handle, intl_svc_uid);
311 break;
312 case INTEL_SIP_SMC_FPGA_CONFIG_ISDONE:
313 status = intel_mailbox_fpga_config_isdone();
314 SMC_RET4(handle, status, 0, 0, 0);
315 break;
316 case INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM:
317 SMC_RET3(handle, INTEL_SIP_SMC_STATUS_OK,
318 INTEL_SIP_SMC_FPGA_CONFIG_ADDR,
319 INTEL_SIP_SMC_FPGA_CONFIG_SIZE -
320 INTEL_SIP_SMC_FPGA_CONFIG_ADDR);
321 break;
322 case INTEL_SIP_SMC_FPGA_CONFIG_START:
323 status = intel_fpga_config_start(x1);
324 SMC_RET4(handle, status, 0, 0, 0);
325 break;
326 case INTEL_SIP_SMC_FPGA_CONFIG_WRITE:
327 status = intel_fpga_config_write(x1, x2);
328 SMC_RET4(handle, status, 0, 0, 0);
329 break;
330 case INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE:
331 status = intel_fpga_config_completed_write(completed_addr,
332 &count);
333 switch (count) {
334 case 1:
335 SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK,
336 completed_addr[0], 0, 0);
337 break;
338 case 2:
339 SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK,
340 completed_addr[0],
341 completed_addr[1], 0);
342 break;
343 case 3:
344 SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK,
345 completed_addr[0],
346 completed_addr[1],
347 completed_addr[2]);
348 break;
349 case 0:
350 SMC_RET4(handle, status, 0, 0, 0);
351 break;
352 default:
353 SMC_RET1(handle, INTEL_SIP_SMC_STATUS_ERROR);
354 }
355 break;
356
357 default:
358 return socfpga_sip_handler(smc_fid, x1, x2, x3, x4,
359 cookie, handle, flags);
360 }
361}
362
363DECLARE_RT_SVC(
Hadi Asyrafi4d9f3952019-10-23 17:35:32 +0800364 socfpga_sip_svc,
Hadi Asyrafi616da772019-06-27 11:34:03 +0800365 OEN_SIP_START,
366 OEN_SIP_END,
367 SMC_TYPE_FAST,
368 NULL,
369 sip_smc_handler
370);
371
372DECLARE_RT_SVC(
Hadi Asyrafi4d9f3952019-10-23 17:35:32 +0800373 socfpga_sip_svc_std,
Hadi Asyrafi616da772019-06-27 11:34:03 +0800374 OEN_SIP_START,
375 OEN_SIP_END,
376 SMC_TYPE_YIELD,
377 NULL,
378 sip_smc_handler
379);