1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2018 Intel Corporation <www.intel.com>
4  */
5 
6 #include <common.h>
7 #include <altera.h>
8 #include <log.h>
9 #include <watchdog.h>
10 #include <asm/arch/mailbox_s10.h>
11 #include <asm/arch/smc_api.h>
12 #include <linux/delay.h>
13 #include <linux/intel-smc.h>
14 
15 #define RECONFIG_STATUS_POLL_RESP_TIMEOUT_MS		60000
16 #define RECONFIG_STATUS_INTERVAL_DELAY_US		1000000
17 
18 #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF)
19 
20 #define BITSTREAM_CHUNK_SIZE				0xFFFF0
21 #define RECONFIG_STATUS_POLL_RETRY_MAX			100
22 
23 /*
24  * Polling the FPGA configuration status.
25  * Return 0 for success, non-zero for error.
26  */
reconfig_status_polling_resp(void)27 static int reconfig_status_polling_resp(void)
28 {
29 	int ret;
30 	unsigned long start = get_timer(0);
31 
32 	while (1) {
33 		ret = invoke_smc(INTEL_SIP_SMC_FPGA_CONFIG_ISDONE, NULL, 0,
34 				 NULL, 0);
35 
36 		if (!ret)
37 			return 0;	/* configuration success */
38 
39 		if (ret != INTEL_SIP_SMC_STATUS_BUSY)
40 			return ret;
41 
42 		if (get_timer(start) > RECONFIG_STATUS_POLL_RESP_TIMEOUT_MS)
43 			return -ETIMEDOUT;	/* time out */
44 
45 		puts(".");
46 		udelay(RECONFIG_STATUS_INTERVAL_DELAY_US);
47 		WATCHDOG_RESET();
48 	}
49 
50 	return -ETIMEDOUT;
51 }
52 
send_bitstream(const void * rbf_data,size_t rbf_size)53 static int send_bitstream(const void *rbf_data, size_t rbf_size)
54 {
55 	int i;
56 	u64 res_buf[3];
57 	u64 args[2];
58 	u32 xfer_count = 0;
59 	int ret, wr_ret = 0, retry = 0;
60 	size_t buf_size = (rbf_size > BITSTREAM_CHUNK_SIZE) ?
61 				BITSTREAM_CHUNK_SIZE : rbf_size;
62 
63 	while (rbf_size || xfer_count) {
64 		if (!wr_ret && rbf_size) {
65 			args[0] = (u64)rbf_data;
66 			args[1] = buf_size;
67 			wr_ret = invoke_smc(INTEL_SIP_SMC_FPGA_CONFIG_WRITE,
68 					    args, 2, NULL, 0);
69 
70 			debug("wr_ret = %d, rbf_data = %p, buf_size = %08lx\n",
71 			      wr_ret, rbf_data, buf_size);
72 
73 			if (wr_ret)
74 				continue;
75 
76 			rbf_size -= buf_size;
77 			rbf_data += buf_size;
78 
79 			if (buf_size >= rbf_size)
80 				buf_size = rbf_size;
81 
82 			xfer_count++;
83 			puts(".");
84 		} else {
85 			ret = invoke_smc(
86 				INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE,
87 				NULL, 0, res_buf, ARRAY_SIZE(res_buf));
88 			if (!ret) {
89 				for (i = 0; i < ARRAY_SIZE(res_buf); i++) {
90 					if (!res_buf[i])
91 						break;
92 					xfer_count--;
93 					wr_ret = 0;
94 					retry = 0;
95 				}
96 			} else if (ret !=
97 				   INTEL_SIP_SMC_STATUS_BUSY)
98 				return ret;
99 			else if (!xfer_count)
100 				return INTEL_SIP_SMC_STATUS_ERROR;
101 
102 			if (++retry >= RECONFIG_STATUS_POLL_RETRY_MAX)
103 				return -ETIMEDOUT;
104 
105 			udelay(20000);
106 		}
107 		WATCHDOG_RESET();
108 	}
109 
110 	return 0;
111 }
112 
113 /*
114  * This is the interface used by FPGA driver.
115  * Return 0 for success, non-zero for error.
116  */
intel_sdm_mb_load(Altera_desc * desc,const void * rbf_data,size_t rbf_size)117 int intel_sdm_mb_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
118 {
119 	int ret;
120 	u64 arg = 1;
121 
122 	debug("Invoking FPGA_CONFIG_START...\n");
123 
124 	ret = invoke_smc(INTEL_SIP_SMC_FPGA_CONFIG_START, &arg, 1, NULL, 0);
125 
126 	if (ret) {
127 		puts("Failure in RECONFIG mailbox command!\n");
128 		return ret;
129 	}
130 
131 	ret = send_bitstream(rbf_data, rbf_size);
132 	if (ret) {
133 		puts("Error sending bitstream!\n");
134 		return ret;
135 	}
136 
137 	/* Make sure we don't send MBOX_RECONFIG_STATUS too fast */
138 	udelay(RECONFIG_STATUS_INTERVAL_DELAY_US);
139 
140 	debug("Polling with MBOX_RECONFIG_STATUS...\n");
141 	ret = reconfig_status_polling_resp();
142 	if (ret) {
143 		puts("FPGA reconfiguration failed!");
144 		return ret;
145 	}
146 
147 	puts("FPGA reconfiguration OK!\n");
148 
149 	return ret;
150 }
151 
152 #else
153 
154 static const struct mbox_cfgstat_state {
155 	int			err_no;
156 	const char		*error_name;
157 } mbox_cfgstat_state[] = {
158 	{MBOX_CFGSTAT_STATE_IDLE, "FPGA in idle mode."},
159 	{MBOX_CFGSTAT_STATE_CONFIG, "FPGA in config mode."},
160 	{MBOX_CFGSTAT_STATE_FAILACK, "Acknowledgment failed!"},
161 	{MBOX_CFGSTAT_STATE_ERROR_INVALID, "Invalid bitstream!"},
162 	{MBOX_CFGSTAT_STATE_ERROR_CORRUPT, "Corrupted bitstream!"},
163 	{MBOX_CFGSTAT_STATE_ERROR_AUTH, "Authentication failed!"},
164 	{MBOX_CFGSTAT_STATE_ERROR_CORE_IO, "I/O error!"},
165 	{MBOX_CFGSTAT_STATE_ERROR_HARDWARE, "Hardware error!"},
166 	{MBOX_CFGSTAT_STATE_ERROR_FAKE, "Fake error!"},
167 	{MBOX_CFGSTAT_STATE_ERROR_BOOT_INFO, "Error in boot info!"},
168 	{MBOX_CFGSTAT_STATE_ERROR_QSPI_ERROR, "Error in QSPI!"},
169 	{MBOX_RESP_ERROR, "Mailbox general error!"},
170 	{-ETIMEDOUT, "I/O timeout error"},
171 	{-1, "Unknown error!"}
172 };
173 
174 #define MBOX_CFGSTAT_MAX ARRAY_SIZE(mbox_cfgstat_state)
175 
mbox_cfgstat_to_str(int err)176 static const char *mbox_cfgstat_to_str(int err)
177 {
178 	int i;
179 
180 	for (i = 0; i < MBOX_CFGSTAT_MAX - 1; i++) {
181 		if (mbox_cfgstat_state[i].err_no == err)
182 			return mbox_cfgstat_state[i].error_name;
183 	}
184 
185 	return mbox_cfgstat_state[MBOX_CFGSTAT_MAX - 1].error_name;
186 }
187 
188 /*
189  * Add the ongoing transaction's command ID into pending list and return
190  * the command ID for next transfer.
191  */
add_transfer(u32 * xfer_pending_list,size_t list_size,u8 id)192 static u8 add_transfer(u32 *xfer_pending_list, size_t list_size, u8 id)
193 {
194 	int i;
195 
196 	for (i = 0; i < list_size; i++) {
197 		if (xfer_pending_list[i])
198 			continue;
199 		xfer_pending_list[i] = id;
200 		debug("ID(%d) added to transaction pending list\n", id);
201 		/*
202 		 * Increment command ID for next transaction.
203 		 * Valid command ID (4 bits) is from 1 to 15.
204 		 */
205 		id = (id % 15) + 1;
206 		break;
207 	}
208 
209 	return id;
210 }
211 
212 /*
213  * Check whether response ID match the command ID in the transfer
214  * pending list. If a match is found in the transfer pending list,
215  * it clears the transfer pending list and return the matched
216  * command ID.
217  */
get_and_clr_transfer(u32 * xfer_pending_list,size_t list_size,u8 id)218 static int get_and_clr_transfer(u32 *xfer_pending_list, size_t list_size,
219 				u8 id)
220 {
221 	int i;
222 
223 	for (i = 0; i < list_size; i++) {
224 		if (id != xfer_pending_list[i])
225 			continue;
226 		xfer_pending_list[i] = 0;
227 		return id;
228 	}
229 
230 	return 0;
231 }
232 
233 /*
234  * Polling the FPGA configuration status.
235  * Return 0 for success, non-zero for error.
236  */
reconfig_status_polling_resp(void)237 static int reconfig_status_polling_resp(void)
238 {
239 	int ret;
240 	unsigned long start = get_timer(0);
241 
242 	while (1) {
243 		ret = mbox_get_fpga_config_status(MBOX_RECONFIG_STATUS);
244 		if (!ret)
245 			return 0;	/* configuration success */
246 
247 		if (ret != MBOX_CFGSTAT_STATE_CONFIG)
248 			return ret;
249 
250 		if (get_timer(start) > RECONFIG_STATUS_POLL_RESP_TIMEOUT_MS)
251 			break;	/* time out */
252 
253 		puts(".");
254 		udelay(RECONFIG_STATUS_INTERVAL_DELAY_US);
255 		WATCHDOG_RESET();
256 	}
257 
258 	return -ETIMEDOUT;
259 }
260 
get_resp_hdr(u32 * r_index,u32 * w_index,u32 * resp_count,u32 * resp_buf,u32 buf_size,u32 client_id)261 static u32 get_resp_hdr(u32 *r_index, u32 *w_index, u32 *resp_count,
262 			u32 *resp_buf, u32 buf_size, u32 client_id)
263 {
264 	u32 buf[MBOX_RESP_BUFFER_SIZE];
265 	u32 mbox_hdr;
266 	u32 resp_len;
267 	u32 hdr_len;
268 	u32 i;
269 
270 	if (*resp_count < buf_size) {
271 		u32 rcv_len_max = buf_size - *resp_count;
272 
273 		if (rcv_len_max > MBOX_RESP_BUFFER_SIZE)
274 			rcv_len_max = MBOX_RESP_BUFFER_SIZE;
275 		resp_len = mbox_rcv_resp(buf, rcv_len_max);
276 
277 		for (i = 0; i < resp_len; i++) {
278 			resp_buf[(*w_index)++] = buf[i];
279 			*w_index %= buf_size;
280 			(*resp_count)++;
281 		}
282 	}
283 
284 	/* No response in buffer */
285 	if (*resp_count == 0)
286 		return 0;
287 
288 	mbox_hdr = resp_buf[*r_index];
289 
290 	hdr_len = MBOX_RESP_LEN_GET(mbox_hdr);
291 
292 	/* Insufficient header length to return a mailbox header */
293 	if ((*resp_count - 1) < hdr_len)
294 		return 0;
295 
296 	*r_index += (hdr_len + 1);
297 	*r_index %= buf_size;
298 	*resp_count -= (hdr_len + 1);
299 
300 	/* Make sure response belongs to us */
301 	if (MBOX_RESP_CLIENT_GET(mbox_hdr) != client_id)
302 		return 0;
303 
304 	return mbox_hdr;
305 }
306 
307 /* Send bit stream data to SDM via RECONFIG_DATA mailbox command */
send_reconfig_data(const void * rbf_data,size_t rbf_size,u32 xfer_max,u32 buf_size_max)308 static int send_reconfig_data(const void *rbf_data, size_t rbf_size,
309 			      u32 xfer_max, u32 buf_size_max)
310 {
311 	u32 response_buffer[MBOX_RESP_BUFFER_SIZE];
312 	u32 xfer_pending[MBOX_RESP_BUFFER_SIZE];
313 	u32 resp_rindex = 0;
314 	u32 resp_windex = 0;
315 	u32 resp_count = 0;
316 	u32 xfer_count = 0;
317 	int resp_err = 0;
318 	u8 cmd_id = 1;
319 	u32 args[3];
320 	int ret;
321 
322 	debug("SDM xfer_max = %d\n", xfer_max);
323 	debug("SDM buf_size_max = %x\n\n", buf_size_max);
324 
325 	memset(xfer_pending, 0, sizeof(xfer_pending));
326 
327 	while (rbf_size || xfer_count) {
328 		if (!resp_err && rbf_size && xfer_count < xfer_max) {
329 			args[0] = MBOX_ARG_DESC_COUNT(1);
330 			args[1] = (u64)rbf_data;
331 			if (rbf_size >= buf_size_max) {
332 				args[2] = buf_size_max;
333 				rbf_size -= buf_size_max;
334 				rbf_data += buf_size_max;
335 			} else {
336 				args[2] = (u64)rbf_size;
337 				rbf_size = 0;
338 			}
339 
340 			resp_err = mbox_send_cmd_only(cmd_id, MBOX_RECONFIG_DATA,
341 						 MBOX_CMD_INDIRECT, 3, args);
342 			if (!resp_err) {
343 				xfer_count++;
344 				cmd_id = add_transfer(xfer_pending,
345 						      MBOX_RESP_BUFFER_SIZE,
346 						      cmd_id);
347 			}
348 			puts(".");
349 		} else {
350 			u32 resp_hdr = get_resp_hdr(&resp_rindex, &resp_windex,
351 						    &resp_count,
352 						    response_buffer,
353 						    MBOX_RESP_BUFFER_SIZE,
354 						    MBOX_CLIENT_ID_UBOOT);
355 
356 			/*
357 			 * If no valid response header found or
358 			 * non-zero length from RECONFIG_DATA
359 			 */
360 			if (!resp_hdr || MBOX_RESP_LEN_GET(resp_hdr))
361 				continue;
362 
363 			/* Check for response's status */
364 			if (!resp_err) {
365 				resp_err = MBOX_RESP_ERR_GET(resp_hdr);
366 				debug("Response error code: %08x\n", resp_err);
367 			}
368 
369 			ret = get_and_clr_transfer(xfer_pending,
370 						   MBOX_RESP_BUFFER_SIZE,
371 						   MBOX_RESP_ID_GET(resp_hdr));
372 			if (ret) {
373 				/* Claim and reuse the ID */
374 				cmd_id = (u8)ret;
375 				xfer_count--;
376 			}
377 
378 			if (resp_err && !xfer_count)
379 				return resp_err;
380 		}
381 		WATCHDOG_RESET();
382 	}
383 
384 	return 0;
385 }
386 
387 /*
388  * This is the interface used by FPGA driver.
389  * Return 0 for success, non-zero for error.
390  */
intel_sdm_mb_load(Altera_desc * desc,const void * rbf_data,size_t rbf_size)391 int intel_sdm_mb_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
392 {
393 	int ret;
394 	u32 resp_len = 2;
395 	u32 resp_buf[2];
396 
397 	debug("Sending MBOX_RECONFIG...\n");
398 	ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_RECONFIG, MBOX_CMD_DIRECT, 0,
399 			    NULL, 0, &resp_len, resp_buf);
400 	if (ret) {
401 		puts("Failure in RECONFIG mailbox command!\n");
402 		return ret;
403 	}
404 
405 	ret = send_reconfig_data(rbf_data, rbf_size, resp_buf[0], resp_buf[1]);
406 	if (ret) {
407 		printf("RECONFIG_DATA error: %08x, %s\n", ret,
408 		       mbox_cfgstat_to_str(ret));
409 		return ret;
410 	}
411 
412 	/* Make sure we don't send MBOX_RECONFIG_STATUS too fast */
413 	udelay(RECONFIG_STATUS_INTERVAL_DELAY_US);
414 
415 	debug("Polling with MBOX_RECONFIG_STATUS...\n");
416 	ret = reconfig_status_polling_resp();
417 	if (ret) {
418 		printf("RECONFIG_STATUS Error: %08x, %s\n", ret,
419 		       mbox_cfgstat_to_str(ret));
420 		return ret;
421 	}
422 
423 	puts("FPGA reconfiguration OK!\n");
424 
425 	return ret;
426 }
427 #endif
428