blob: 4a09526b9d371db1bb29e7b45d6f9dcbb2ecf3b2 [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
Tien Hock, Loh500b2322019-10-30 14:49:40 +080021static int current_block;
22static int read_block;
23static int current_buffer;
24static int send_id;
25static int rcv_id;
26static int max_blocks;
27static uint32_t bytes_per_block;
28static uint32_t blocks_submitted;
Hadi Asyrafi616da772019-06-27 11:34:03 +080029
30struct fpga_config_info {
31 uint32_t addr;
32 int size;
33 int size_written;
34 uint32_t write_requested;
35 int subblocks_sent;
36 int block_number;
37};
38
39/* SiP Service UUID */
40DEFINE_SVC_UUID2(intl_svc_uid,
41 0xa85273b0, 0xe85a, 0x4862, 0xa6, 0x2a,
42 0xfa, 0x88, 0x88, 0x17, 0x68, 0x81);
43
44uint64_t socfpga_sip_handler(uint32_t smc_fid,
45 uint64_t x1,
46 uint64_t x2,
47 uint64_t x3,
48 uint64_t x4,
49 void *cookie,
50 void *handle,
51 uint64_t flags)
52{
53 ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
54 SMC_RET1(handle, SMC_UNK);
55}
56
57struct fpga_config_info fpga_config_buffers[FPGA_CONFIG_BUFFER_SIZE];
58
59static void intel_fpga_sdm_write_buffer(struct fpga_config_info *buffer)
60{
61 uint32_t args[3];
62
63 while (max_blocks > 0 && buffer->size > buffer->size_written) {
64 if (buffer->size - buffer->size_written <=
65 bytes_per_block) {
66 args[0] = (1<<8);
67 args[1] = buffer->addr + buffer->size_written;
68 args[2] = buffer->size - buffer->size_written;
69 buffer->size_written +=
70 buffer->size - buffer->size_written;
71 buffer->subblocks_sent++;
Tien Hock, Loh500b2322019-10-30 14:49:40 +080072 mailbox_send_cmd_async(
73 send_id++ % MBOX_MAX_JOB_ID,
Hadi Asyrafi616da772019-06-27 11:34:03 +080074 MBOX_RECONFIG_DATA,
75 args, 3, 0);
76 current_buffer++;
77 current_buffer %= FPGA_CONFIG_BUFFER_SIZE;
78 } else {
79 args[0] = (1<<8);
80 args[1] = buffer->addr + buffer->size_written;
81 args[2] = bytes_per_block;
82 buffer->size_written += bytes_per_block;
Tien Hock, Loh500b2322019-10-30 14:49:40 +080083 mailbox_send_cmd_async(
84 send_id++ % MBOX_MAX_JOB_ID,
Hadi Asyrafi616da772019-06-27 11:34:03 +080085 MBOX_RECONFIG_DATA,
86 args, 3, 0);
87 buffer->subblocks_sent++;
88 }
89 max_blocks--;
90 }
91}
92
93static int intel_fpga_sdm_write_all(void)
94{
95 int i;
96
97 for (i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++)
98 intel_fpga_sdm_write_buffer(
99 &fpga_config_buffers[current_buffer]);
100
101 return 0;
102}
103
104uint32_t intel_mailbox_fpga_config_isdone(void)
105{
Hadi Asyrafic5168162019-10-21 16:25:07 +0800106 return intel_mailbox_get_config_status(MBOX_RECONFIG_STATUS);
Hadi Asyrafi616da772019-06-27 11:34:03 +0800107}
108
109static int mark_last_buffer_xfer_completed(uint32_t *buffer_addr_completed)
110{
111 int i;
112
113 for (i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
114 if (fpga_config_buffers[i].block_number == current_block) {
115 fpga_config_buffers[i].subblocks_sent--;
116 if (fpga_config_buffers[i].subblocks_sent == 0
117 && fpga_config_buffers[i].size <=
118 fpga_config_buffers[i].size_written) {
119 fpga_config_buffers[i].write_requested = 0;
120 current_block++;
121 *buffer_addr_completed =
122 fpga_config_buffers[i].addr;
123 return 0;
124 }
125 }
126 }
127
128 return -1;
129}
130
131unsigned int address_in_ddr(uint32_t *addr)
132{
133 if (((unsigned long long)addr > DRAM_BASE) &&
134 ((unsigned long long)addr < DRAM_BASE + DRAM_SIZE))
135 return 0;
136
137 return -1;
138}
139
Tien Hock, Loh500b2322019-10-30 14:49:40 +0800140int mailbox_poll_response(int job_id, int urgent, uint32_t *response);
141
Hadi Asyrafi616da772019-06-27 11:34:03 +0800142int intel_fpga_config_completed_write(uint32_t *completed_addr,
143 uint32_t *count)
144{
145 uint32_t status = INTEL_SIP_SMC_STATUS_OK;
146 *count = 0;
147 int resp_len = 0;
148 uint32_t resp[5];
149 int all_completed = 1;
Hadi Asyrafi616da772019-06-27 11:34:03 +0800150
Tien Hock, Loh500b2322019-10-30 14:49:40 +0800151 while (*count < 3) {
Hadi Asyrafi616da772019-06-27 11:34:03 +0800152
Tien Hock, Loh500b2322019-10-30 14:49:40 +0800153 resp_len = mailbox_read_response(
154 rcv_id % MBOX_MAX_JOB_ID, resp);
Hadi Asyrafi616da772019-06-27 11:34:03 +0800155
Tien Hock, Loh500b2322019-10-30 14:49:40 +0800156 if (resp_len < 0)
157 break;
Hadi Asyrafi616da772019-06-27 11:34:03 +0800158
Hadi Asyrafi616da772019-06-27 11:34:03 +0800159 max_blocks++;
Tien Hock, Loh500b2322019-10-30 14:49:40 +0800160 rcv_id++;
161
Hadi Asyrafi616da772019-06-27 11:34:03 +0800162 if (mark_last_buffer_xfer_completed(
163 &completed_addr[*count]) == 0)
164 *count = *count + 1;
165 else
166 break;
Hadi Asyrafi616da772019-06-27 11:34:03 +0800167 }
168
169 if (*count <= 0) {
170 if (resp_len != MBOX_NO_RESPONSE &&
171 resp_len != MBOX_TIMEOUT && resp_len != 0) {
Tien Hock, Loh500b2322019-10-30 14:49:40 +0800172 mailbox_clear_response();
Hadi Asyrafi616da772019-06-27 11:34:03 +0800173 return INTEL_SIP_SMC_STATUS_ERROR;
174 }
175
176 *count = 0;
177 }
178
179 intel_fpga_sdm_write_all();
180
181 if (*count > 0)
182 status = INTEL_SIP_SMC_STATUS_OK;
183 else if (*count == 0)
184 status = INTEL_SIP_SMC_STATUS_BUSY;
185
186 for (int i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
187 if (fpga_config_buffers[i].write_requested != 0) {
188 all_completed = 0;
189 break;
190 }
191 }
192
193 if (all_completed == 1)
194 return INTEL_SIP_SMC_STATUS_OK;
195
196 return status;
197}
198
199int intel_fpga_config_start(uint32_t config_type)
200{
201 uint32_t response[3];
202 int status = 0;
203
Tien Hock, Loh500b2322019-10-30 14:49:40 +0800204 mailbox_clear_response();
205
206 mailbox_send_cmd(1, MBOX_CMD_CANCEL, 0, 0, 0, response);
207
208 status = mailbox_send_cmd(1, MBOX_RECONFIG, 0, 0, 0,
Hadi Asyrafi616da772019-06-27 11:34:03 +0800209 response);
210
211 if (status < 0)
212 return status;
213
214 max_blocks = response[0];
215 bytes_per_block = response[1];
216
217 for (int i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
218 fpga_config_buffers[i].size = 0;
219 fpga_config_buffers[i].size_written = 0;
220 fpga_config_buffers[i].addr = 0;
221 fpga_config_buffers[i].write_requested = 0;
222 fpga_config_buffers[i].block_number = 0;
223 fpga_config_buffers[i].subblocks_sent = 0;
224 }
225
226 blocks_submitted = 0;
227 current_block = 0;
Tien Hock, Loh500b2322019-10-30 14:49:40 +0800228 read_block = 0;
Hadi Asyrafi616da772019-06-27 11:34:03 +0800229 current_buffer = 0;
Tien Hock, Loh500b2322019-10-30 14:49:40 +0800230 send_id = 0;
231 rcv_id = 0;
Hadi Asyrafi616da772019-06-27 11:34:03 +0800232
233 return 0;
234}
235
236
237uint32_t intel_fpga_config_write(uint64_t mem, uint64_t size)
238{
239 int i = 0;
240 uint32_t status = INTEL_SIP_SMC_STATUS_OK;
241
242 if (mem < DRAM_BASE || mem > DRAM_BASE + DRAM_SIZE)
243 status = INTEL_SIP_SMC_STATUS_REJECTED;
244
245 if (mem + size > DRAM_BASE + DRAM_SIZE)
246 status = INTEL_SIP_SMC_STATUS_REJECTED;
247
248 for (i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
249 if (!fpga_config_buffers[i].write_requested) {
250 fpga_config_buffers[i].addr = mem;
251 fpga_config_buffers[i].size = size;
252 fpga_config_buffers[i].size_written = 0;
253 fpga_config_buffers[i].write_requested = 1;
254 fpga_config_buffers[i].block_number =
255 blocks_submitted++;
256 fpga_config_buffers[i].subblocks_sent = 0;
257 break;
258 }
259 }
260
261
262 if (i == FPGA_CONFIG_BUFFER_SIZE) {
263 status = INTEL_SIP_SMC_STATUS_REJECTED;
264 return status;
265 } else if (i == FPGA_CONFIG_BUFFER_SIZE - 1) {
266 status = INTEL_SIP_SMC_STATUS_BUSY;
267 }
268
269 intel_fpga_sdm_write_all();
270
271 return status;
272}
273
274/*
275 * This function is responsible for handling all SiP calls from the NS world
276 */
277
278uintptr_t sip_smc_handler(uint32_t smc_fid,
279 u_register_t x1,
280 u_register_t x2,
281 u_register_t x3,
282 u_register_t x4,
283 void *cookie,
284 void *handle,
285 u_register_t flags)
286{
287 uint32_t status = INTEL_SIP_SMC_STATUS_OK;
288 uint32_t completed_addr[3];
289 uint32_t count = 0;
290
291 switch (smc_fid) {
292 case SIP_SVC_UID:
293 /* Return UID to the caller */
294 SMC_UUID_RET(handle, intl_svc_uid);
295 break;
296 case INTEL_SIP_SMC_FPGA_CONFIG_ISDONE:
297 status = intel_mailbox_fpga_config_isdone();
298 SMC_RET4(handle, status, 0, 0, 0);
299 break;
300 case INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM:
301 SMC_RET3(handle, INTEL_SIP_SMC_STATUS_OK,
302 INTEL_SIP_SMC_FPGA_CONFIG_ADDR,
303 INTEL_SIP_SMC_FPGA_CONFIG_SIZE -
304 INTEL_SIP_SMC_FPGA_CONFIG_ADDR);
305 break;
306 case INTEL_SIP_SMC_FPGA_CONFIG_START:
307 status = intel_fpga_config_start(x1);
308 SMC_RET4(handle, status, 0, 0, 0);
309 break;
310 case INTEL_SIP_SMC_FPGA_CONFIG_WRITE:
311 status = intel_fpga_config_write(x1, x2);
312 SMC_RET4(handle, status, 0, 0, 0);
313 break;
314 case INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE:
315 status = intel_fpga_config_completed_write(completed_addr,
316 &count);
317 switch (count) {
318 case 1:
319 SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK,
320 completed_addr[0], 0, 0);
321 break;
322 case 2:
323 SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK,
324 completed_addr[0],
325 completed_addr[1], 0);
326 break;
327 case 3:
328 SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK,
329 completed_addr[0],
330 completed_addr[1],
331 completed_addr[2]);
332 break;
333 case 0:
334 SMC_RET4(handle, status, 0, 0, 0);
335 break;
336 default:
Tien Hock, Loh500b2322019-10-30 14:49:40 +0800337 mailbox_clear_response();
Hadi Asyrafi616da772019-06-27 11:34:03 +0800338 SMC_RET1(handle, INTEL_SIP_SMC_STATUS_ERROR);
339 }
340 break;
341
342 default:
343 return socfpga_sip_handler(smc_fid, x1, x2, x3, x4,
344 cookie, handle, flags);
345 }
346}
347
348DECLARE_RT_SVC(
Hadi Asyrafi4d9f3952019-10-23 17:35:32 +0800349 socfpga_sip_svc,
Hadi Asyrafi616da772019-06-27 11:34:03 +0800350 OEN_SIP_START,
351 OEN_SIP_END,
352 SMC_TYPE_FAST,
353 NULL,
354 sip_smc_handler
355);
356
357DECLARE_RT_SVC(
Hadi Asyrafi4d9f3952019-10-23 17:35:32 +0800358 socfpga_sip_svc_std,
Hadi Asyrafi616da772019-06-27 11:34:03 +0800359 OEN_SIP_START,
360 OEN_SIP_END,
361 SMC_TYPE_YIELD,
362 NULL,
363 sip_smc_handler
364);