blob: 421fa44e30edcf3bb360810ece047ad14bc43304 [file] [log] [blame]
Hadi Asyrafi2f11d542019-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 Asyrafid09adcb2019-10-23 18:34:14 +080012#include "socfpga_mailbox.h"
Hadi Asyrafid25041b2019-10-22 10:31:45 +080013#include "socfpga_sip_svc.h"
Hadi Asyrafi2f11d542019-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{
Hadi Asyrafiec7d0052019-10-21 16:25:07 +0800103 return intel_mailbox_get_config_status(MBOX_RECONFIG_STATUS);
Hadi Asyrafi2f11d542019-06-27 11:34:03 +0800104}
105
106static int mark_last_buffer_xfer_completed(uint32_t *buffer_addr_completed)
107{
108 int i;
109
110 for (i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
111 if (fpga_config_buffers[i].block_number == current_block) {
112 fpga_config_buffers[i].subblocks_sent--;
113 if (fpga_config_buffers[i].subblocks_sent == 0
114 && fpga_config_buffers[i].size <=
115 fpga_config_buffers[i].size_written) {
116 fpga_config_buffers[i].write_requested = 0;
117 current_block++;
118 *buffer_addr_completed =
119 fpga_config_buffers[i].addr;
120 return 0;
121 }
122 }
123 }
124
125 return -1;
126}
127
128unsigned int address_in_ddr(uint32_t *addr)
129{
130 if (((unsigned long long)addr > DRAM_BASE) &&
131 ((unsigned long long)addr < DRAM_BASE + DRAM_SIZE))
132 return 0;
133
134 return -1;
135}
136
137int intel_fpga_config_completed_write(uint32_t *completed_addr,
138 uint32_t *count)
139{
140 uint32_t status = INTEL_SIP_SMC_STATUS_OK;
141 *count = 0;
142 int resp_len = 0;
143 uint32_t resp[5];
144 int all_completed = 1;
145 int count_check = 0;
146
147 if (address_in_ddr(completed_addr) != 0 || address_in_ddr(count) != 0)
148 return INTEL_SIP_SMC_STATUS_ERROR;
149
150 for (count_check = 0; count_check < 3; count_check++)
151 if (address_in_ddr(&completed_addr[*count + count_check]) != 0)
152 return INTEL_SIP_SMC_STATUS_ERROR;
153
154 resp_len = mailbox_read_response(0x4, resp);
155
156 while (resp_len >= 0 && *count < 3) {
157 max_blocks++;
158 if (mark_last_buffer_xfer_completed(
159 &completed_addr[*count]) == 0)
160 *count = *count + 1;
161 else
162 break;
163 resp_len = mailbox_read_response(0x4, resp);
164 }
165
166 if (*count <= 0) {
167 if (resp_len != MBOX_NO_RESPONSE &&
168 resp_len != MBOX_TIMEOUT && resp_len != 0) {
169 return INTEL_SIP_SMC_STATUS_ERROR;
170 }
171
172 *count = 0;
173 }
174
175 intel_fpga_sdm_write_all();
176
177 if (*count > 0)
178 status = INTEL_SIP_SMC_STATUS_OK;
179 else if (*count == 0)
180 status = INTEL_SIP_SMC_STATUS_BUSY;
181
182 for (int i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
183 if (fpga_config_buffers[i].write_requested != 0) {
184 all_completed = 0;
185 break;
186 }
187 }
188
189 if (all_completed == 1)
190 return INTEL_SIP_SMC_STATUS_OK;
191
192 return status;
193}
194
195int intel_fpga_config_start(uint32_t config_type)
196{
197 uint32_t response[3];
198 int status = 0;
199
200 status = mailbox_send_cmd(2, MBOX_RECONFIG, 0, 0, 0,
201 response);
202
203 if (status < 0)
204 return status;
205
206 max_blocks = response[0];
207 bytes_per_block = response[1];
208
209 for (int i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
210 fpga_config_buffers[i].size = 0;
211 fpga_config_buffers[i].size_written = 0;
212 fpga_config_buffers[i].addr = 0;
213 fpga_config_buffers[i].write_requested = 0;
214 fpga_config_buffers[i].block_number = 0;
215 fpga_config_buffers[i].subblocks_sent = 0;
216 }
217
218 blocks_submitted = 0;
219 current_block = 0;
220 current_buffer = 0;
221
222 return 0;
223}
224
225
226uint32_t intel_fpga_config_write(uint64_t mem, uint64_t size)
227{
228 int i = 0;
229 uint32_t status = INTEL_SIP_SMC_STATUS_OK;
230
231 if (mem < DRAM_BASE || mem > DRAM_BASE + DRAM_SIZE)
232 status = INTEL_SIP_SMC_STATUS_REJECTED;
233
234 if (mem + size > DRAM_BASE + DRAM_SIZE)
235 status = INTEL_SIP_SMC_STATUS_REJECTED;
236
237 for (i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
238 if (!fpga_config_buffers[i].write_requested) {
239 fpga_config_buffers[i].addr = mem;
240 fpga_config_buffers[i].size = size;
241 fpga_config_buffers[i].size_written = 0;
242 fpga_config_buffers[i].write_requested = 1;
243 fpga_config_buffers[i].block_number =
244 blocks_submitted++;
245 fpga_config_buffers[i].subblocks_sent = 0;
246 break;
247 }
248 }
249
250
251 if (i == FPGA_CONFIG_BUFFER_SIZE) {
252 status = INTEL_SIP_SMC_STATUS_REJECTED;
253 return status;
254 } else if (i == FPGA_CONFIG_BUFFER_SIZE - 1) {
255 status = INTEL_SIP_SMC_STATUS_BUSY;
256 }
257
258 intel_fpga_sdm_write_all();
259
260 return status;
261}
262
263/*
264 * This function is responsible for handling all SiP calls from the NS world
265 */
266
267uintptr_t sip_smc_handler(uint32_t smc_fid,
268 u_register_t x1,
269 u_register_t x2,
270 u_register_t x3,
271 u_register_t x4,
272 void *cookie,
273 void *handle,
274 u_register_t flags)
275{
276 uint32_t status = INTEL_SIP_SMC_STATUS_OK;
277 uint32_t completed_addr[3];
278 uint32_t count = 0;
279
280 switch (smc_fid) {
281 case SIP_SVC_UID:
282 /* Return UID to the caller */
283 SMC_UUID_RET(handle, intl_svc_uid);
284 break;
285 case INTEL_SIP_SMC_FPGA_CONFIG_ISDONE:
286 status = intel_mailbox_fpga_config_isdone();
287 SMC_RET4(handle, status, 0, 0, 0);
288 break;
289 case INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM:
290 SMC_RET3(handle, INTEL_SIP_SMC_STATUS_OK,
291 INTEL_SIP_SMC_FPGA_CONFIG_ADDR,
292 INTEL_SIP_SMC_FPGA_CONFIG_SIZE -
293 INTEL_SIP_SMC_FPGA_CONFIG_ADDR);
294 break;
295 case INTEL_SIP_SMC_FPGA_CONFIG_START:
296 status = intel_fpga_config_start(x1);
297 SMC_RET4(handle, status, 0, 0, 0);
298 break;
299 case INTEL_SIP_SMC_FPGA_CONFIG_WRITE:
300 status = intel_fpga_config_write(x1, x2);
301 SMC_RET4(handle, status, 0, 0, 0);
302 break;
303 case INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE:
304 status = intel_fpga_config_completed_write(completed_addr,
305 &count);
306 switch (count) {
307 case 1:
308 SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK,
309 completed_addr[0], 0, 0);
310 break;
311 case 2:
312 SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK,
313 completed_addr[0],
314 completed_addr[1], 0);
315 break;
316 case 3:
317 SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK,
318 completed_addr[0],
319 completed_addr[1],
320 completed_addr[2]);
321 break;
322 case 0:
323 SMC_RET4(handle, status, 0, 0, 0);
324 break;
325 default:
326 SMC_RET1(handle, INTEL_SIP_SMC_STATUS_ERROR);
327 }
328 break;
329
330 default:
331 return socfpga_sip_handler(smc_fid, x1, x2, x3, x4,
332 cookie, handle, flags);
333 }
334}
335
336DECLARE_RT_SVC(
Hadi Asyrafic76d4232019-10-23 17:35:32 +0800337 socfpga_sip_svc,
Hadi Asyrafi2f11d542019-06-27 11:34:03 +0800338 OEN_SIP_START,
339 OEN_SIP_END,
340 SMC_TYPE_FAST,
341 NULL,
342 sip_smc_handler
343);
344
345DECLARE_RT_SVC(
Hadi Asyrafic76d4232019-10-23 17:35:32 +0800346 socfpga_sip_svc_std,
Hadi Asyrafi2f11d542019-06-27 11:34:03 +0800347 OEN_SIP_START,
348 OEN_SIP_END,
349 SMC_TYPE_YIELD,
350 NULL,
351 sip_smc_handler
352);