• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  *
4  * This program is free software; you can redistribute  it and/or modify it
5  * under  the terms of  the GNU General  Public License as published by the
6  * Free Software Foundation;  either version 2 of the  License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  *
17  */
18 
19 #include <config.h>
20 #include <asm/io.h>
21 
22 uint64_t ufsboot_static_space_address = 0;
23 
24 #include "ufs.h"
25 #include "scsi.c"
26 
send_uic_command(uint32_t command,uint32_t arg1,uint32_t arg2,uint32_t arg3)27 static int send_uic_command(uint32_t command, uint32_t arg1, uint32_t arg2, uint32_t arg3)
28 {
29 	int retry = 10;
30 	unsigned int tick;
31 	uint32_t reg = 0;
32 	unsigned int tick_ready;
33 
34 	tick_ready = current_time();
35 	for (;;) {
36 		if (dwc_ufs_read_reg(UFS_HCS_OFF) & UFS_HCS_UCRDY_BIT) {
37 			break;
38 		}
39 		if (time_passed_ms(tick_ready) > UFS_HC_WAIT_UCRDY_TIMEOUT_MS) {
40 			break;
41 		}
42 	}
43 
44 	do {
45 		//debug_printf("send_uic_command: cmd = 0x%x, arg1 = 0x%x, retry = %d\n", command, arg1, retry);
46 		dwc_ufs_write_reg(UFS_IS_OFF, 0xFFFFFFFF);
47 		dwc_ufs_write_reg(UFS_UICCMDARG1_OFF, arg1);
48 		dwc_ufs_write_reg(UFS_UICCMDARG2_OFF, arg2);
49 		dwc_ufs_write_reg(UFS_UICCMDARG3_OFF, arg3);
50 
51 		dwc_ufs_write_reg(UFS_UICCMD_OFF, (command & 0xFF));
52 
53 		tick = current_time();
54 		for (;;) {
55 			if (dwc_ufs_read_reg(UFS_IS_OFF) & UFS_IS_UCCS_BIT) {
56 				reg = dwc_ufs_read_reg(UFS_UICCMDARG2_OFF) & UFS_UICCMDARG2_RET_MASK;
57 				if (!reg) {
58 					dwc_ufs_write_reg(UFS_IS_OFF, 0xFFFFFFFF);
59 					return UFS_SUCCESS;
60 				} else {
61 					debug_printf("send_uic_command: get error resp, resp = 0x%x\n", reg);
62 					ufs_waitms(1);
63 					break;
64 				}
65 			}
66 
67 			if (time_passed_ms(tick) > UFS_SEND_UIC_CMD_TIMEOUT_MS) {
68 				debug_printf("send_uic_command: wait UCCS int timeout\n");
69 				break;
70 			}
71 		}
72 	} while (--retry > 0);
73 
74 	dwc_ufs_write_reg(UFS_IS_OFF, 0xFFFFFFFF);
75 	debug_printf("send_uic_command: return error, ret = -0x%x\n", ((reg & 0xf) + RET_UIC_CONFIG_ERROR_OFF));
76 	return -((reg & 0xf) + RET_UIC_CONFIG_ERROR_OFF);
77 }
78 
ufs_config_init(void)79 static void ufs_config_init(void)
80 {
81 	int i = 0;
82 	struct dwc_ufs_utrd *p_utrd = NULL;
83 
84 	/* Unipro DL_AFC0CreditThreshold */
85 	send_uic_command(DME_SET, 0x20440000, 0, 0x0);
86 	/* Unipro DL_TC0OutAckThreshold */
87 	send_uic_command(DME_SET, 0x20450000, 0, 0x0);
88 	/* Unipro DL_TC0TXFCThreshold */
89 	send_uic_command(DME_SET, 0x20400000, 0, 0x9);
90 
91 	ufsboot_static_space_address = UFS_START_WORK_SPACE_START;
92 	ufs_memset((void*)ufsboot_static_space_address, 0, UFS_STATIC_WORK_SPACE_SIZE);
93 	ufsboot_static_space_address = BYTES_ALIGN_1024(ufsboot_static_space_address);
94 	if (!ufsboot_static_space_address) {
95 		return ;
96 	}
97 
98 	p_utrd = (struct dwc_ufs_utrd *)UFS_TR_UTP_BASE;
99 	/* UTRD init */
100 	ufs_memset((void *)UFS_TR_UTP_BASE, 0, MAX_TR_TASK * sizeof(struct dwc_ufs_utrd));
101 	writel(0x1, STATIC_UFS_TAG_ADDR);
102 
103 	dwc_ufs_write_reg(UFS_UTRLBA_OFF, UFS_TR_UTP_BASE);
104 	dwc_ufs_write_reg(UFS_UTRLBAU_OFF, 0);
105 
106 	for (i = 0; i < MAX_TR_TASK; i++) {
107 		//debug_printf("init UTRD, p_utrd addr = 0x%x\n", (uint32_t)p_utrd);
108 		p_utrd->ucdba = UFS_CMD_UPIU_BASE;
109 		p_utrd->ucdbau = 0x0;
110 		p_utrd->resp_upiu_offset = (UFS_RESP_UPIU_BASE - UFS_CMD_UPIU_BASE) >> 2;
111 		p_utrd->prdt_offset = (UFS_PRDT_BASE - UFS_CMD_UPIU_BASE) >> 2;
112 		p_utrd += 1;
113 	}
114 	/* UTMRD init */
115 	ufs_memset((void *)UFS_TMR_UTP_BASE, 0, 20 * 4);
116 	dwc_ufs_write_reg(UFS_UTMRLBA_OFF, UFS_TMR_UTP_BASE);
117 	dwc_ufs_write_reg(UFS_UTMRLBAU_OFF, 0);
118 
119 	dwc_ufs_write_reg(UFS_UTRLRSR_OFF, UFS_UTP_RUN_BIT);
120 	dwc_ufs_write_reg(UFS_UTMRLRSR_OFF, UFS_UTP_RUN_BIT);
121 	return;
122 }
123 
wait_for_cmd_completion(uint32_t tag,uint32_t timeout_ms)124 static int wait_for_cmd_completion(uint32_t tag, uint32_t timeout_ms)
125 {
126 	unsigned int tick;
127 
128 	if ((tag < 1) || (tag > MAX_TR_TASK)) {
129 		debug_printf("wait_for_cmd_completion: input tag invalid, tag = %d\n", tag);
130 		tag = 1;
131 	}
132 
133 	/* Set the doorbell for processing the request */
134 	dwc_ufs_write_reg(UFS_UTRLDBR_OFF, 0x1 << (tag - 1));
135 
136 	tick = current_time();
137 	/* Wait for the DoorBell to clear */
138 	for (;;) {
139 		if((dwc_ufs_read_reg(UFS_UTRLDBR_OFF) & (0x1 << (tag - 1))) == 0) {
140 			break;
141 		}
142 
143 		if(time_passed_ms(tick) > timeout_ms) {
144 			debug_printf("UTRL DoorBell Not Cleared and Timed Out\n");
145 			dwc_ufs_write_reg(UFS_UTRLCLR_OFF, 0);
146 			return UFS_UTRD_DOORBELL_TIMEOUT;
147 		}
148 	}
149 
150 	return UFS_SUCCESS;
151 }
152 
create_nop_out_upiu(uint32_t tag)153 static void create_nop_out_upiu(uint32_t tag)
154 {
155 	struct dwc_ufs_nop_req_upiu *cmd_upiu_ptr = NULL;
156 	struct dwc_ufs_utrd *utrd_desc = NULL;
157 	int i;
158 
159 	if ((tag < 1) || (tag > MAX_TR_TASK)) {
160 		debug_printf("create_nop_out_upiu: input tag invalid, tag = %d\n", tag);
161 		tag = 1;
162 	}
163 
164 	cmd_upiu_ptr = (struct dwc_ufs_nop_req_upiu*)UFS_CMD_UPIU_BASE;
165 	utrd_desc = (struct dwc_ufs_utrd *)UFS_TR_UTP_BASE;
166 	utrd_desc += tag - 1;
167 	debug_printf("create_nop_out_upiu: utrd_desc addr 0x%x\n", utrd_desc);
168 
169 	/* clean response upiu */
170 	ufs_memset((void *)UFS_RESP_UPIU_BASE, 0, sizeof(struct dwc_ufs_nop_resp_upiu));
171 
172 	utrd_desc->ct_and_flags = (uint8_t)(UTP_NO_DATA_TRANSFER | UTP_UFS_STORAGE_COMMAND);
173 
174 	utrd_desc->resp_upiu_length = to_littleendian16((uint16_t)sizeof(struct dwc_ufs_nop_resp_upiu) >> 2);
175 	utrd_desc->prdt_length = 0;
176 	utrd_desc->ocs = 0xf;
177 
178 	cmd_upiu_ptr->trans_type = 0x00;
179 	cmd_upiu_ptr->flags = 0x00;
180 	cmd_upiu_ptr->reserved_1 = 0x00;
181 	cmd_upiu_ptr->task_tag = tag;
182 	cmd_upiu_ptr->reserved_2 = 0x0;
183 	cmd_upiu_ptr->tot_ehs_len = 0x00;
184 	cmd_upiu_ptr->reserved_3 = 0x00;
185 	cmd_upiu_ptr->data_seg_len = 0x00;
186 	for (i = 0; i < 20; i++) {
187 		cmd_upiu_ptr->reserved_4[i] = 0x00;
188 	}
189 
190 	return;
191 }
192 
read_nop_rsp(uint32_t tag)193 static int read_nop_rsp(uint32_t tag)
194 {
195 	struct dwc_ufs_nop_resp_upiu *resp_upiu = NULL;
196 	struct dwc_ufs_utrd *utrd_desc = NULL;
197 
198 	if ((tag < 1) || (tag > MAX_TR_TASK)) {
199 		debug_printf("read_nop_rsp: input tag invalid, tag = %d\n", tag);
200 		tag = 1;
201 	}
202 
203 	resp_upiu = (struct dwc_ufs_nop_resp_upiu *)UFS_RESP_UPIU_BASE;
204 	utrd_desc = (struct dwc_ufs_utrd *)UFS_TR_UTP_BASE;
205 	utrd_desc += tag - 1;
206 
207 	debug_printf("read_nop_rsp: utrd_desc addr 0x%x\n", utrd_desc);
208 
209 	if (utrd_desc->ocs != UFS_SUCCESS) {
210 		return -((utrd_desc->ocs & 0xf) + RET_UTRD_OCS_ERROR_OFF);
211 	}
212 
213 	if ((resp_upiu->trans_type & 0x3F) != NOP_TRANS_TYPE) {
214 		debug_printf("invalid nop in\n");
215 		return UFS_INVALID_NOP_IN;
216 	}
217 
218 	if (resp_upiu->response != UFS_SUCCESS) {
219 		debug_printf("nop in response error, resp = 0x%x\n", resp_upiu->response);
220 		return UFS_NOP_RESP_FAIL;
221 	}
222 
223 	return UFS_SUCCESS;
224 }
225 
send_nop_out_cmd(void)226 static int send_nop_out_cmd(void)
227 {
228 	int ret;
229 	uint32_t tag = 0;
230 	int i;
231 
232 	tag = readl(STATIC_UFS_TAG_ADDR);
233 	debug_printf("in send nop out: read tag = %d\n", tag);
234 	for (i = 0; i < 3; i++) {
235 		if ((tag > MAX_TR_TASK) || (tag < 1)) {
236 			tag = 1;
237 		}
238 		debug_printf("create nop out: tag = %d\n", tag);
239 		create_nop_out_upiu(tag);
240 		ret = wait_for_cmd_completion(tag, UFS_SEND_NOP_OUT_TIMEOUT_MS);
241 		if (ret == UFS_SUCCESS) {
242 			ret = read_nop_rsp(tag);
243 		}
244 
245 		if (ret == UFS_SUCCESS) {
246 			break;
247 		}
248 
249 		debug_printf("nop out nop in fail, ret = %d, retry = %d\n", ret, i);
250 		ufs_waitms(1);
251 		if (ret == UFS_UTRD_DOORBELL_TIMEOUT) {
252 			tag++;
253 			writel(tag, STATIC_UFS_TAG_ADDR);
254 		}
255 	}
256 
257 	return ret;
258 }
259 
create_cmd_upiu(uint32_t opcode,enum dma_data_direction direction,uint64_t buf_addr,uint32_t rel_addr,uint32_t size,uint32_t tag)260 static int create_cmd_upiu(uint32_t opcode,
261 			   enum dma_data_direction direction,
262 			   uint64_t buf_addr, uint32_t rel_addr,
263 			   uint32_t size, uint32_t tag)
264 {
265 	struct dwc_ufs_cmd_upiu *cmd_upiu_ptr = NULL;
266 	struct dwc_ufs_utrd *utrd_desc = NULL;
267 	struct dwc_ufs_prd *prdt_table = NULL;
268 	uint32_t data_direction;
269 	uint8_t upiu_flags;
270 	uint32_t prdt_buf_size = PRDT_BUFFER_SIZE;
271 	uint64_t buf_addr_phy;
272 	uint32_t i;
273 	int ret;
274 
275 	if (opcode == UFS_OP_READ_10) {
276 		if (rel_addr % LOGICAL_BLK_SIZE) {
277 			return UFS_SOFTWARE_ERROR;
278 		}
279 		if (size % LOGICAL_BLK_SIZE) {
280 			return UFS_SOFTWARE_ERROR;
281 		}
282 	}
283 
284 	cmd_upiu_ptr = (struct dwc_ufs_cmd_upiu *)UFS_CMD_UPIU_BASE;
285 	utrd_desc = (struct dwc_ufs_utrd *)UFS_TR_UTP_BASE;
286 	utrd_desc += tag - 1;
287 	debug_printf("create_cmd_upiu: utrd_desc addr 0x%x\n", utrd_desc);
288 
289 	prdt_table = (struct dwc_ufs_prd *)UFS_PRDT_BASE;
290 
291 	if (direction == DMA_FROM_DEVICE) {
292 		data_direction = UTP_DEVICE_TO_HOST;
293 		upiu_flags = UPIU_CMD_FLAGS_READ;
294 	} else if (direction == DMA_NONE) {
295 		data_direction = UTP_NO_DATA_TRANSFER;
296 		upiu_flags = UPIU_CMD_FLAGS_NONE;
297 	} else {
298 		return UFS_SOFTWARE_ERROR;
299 	}
300 
301 	/* clean response upiu */
302 	ufs_memset((void *)UFS_RESP_UPIU_BASE, 0, sizeof(struct dwc_ufs_xfer_resp_upiu));
303 
304 	/* Update cmd_type, flags and response upiu length for transfer requests */
305 	utrd_desc->ct_and_flags =
306 		(uint8_t)(data_direction | UTP_UFS_STORAGE_COMMAND);
307 	utrd_desc->resp_upiu_length = to_littleendian16((uint16_t)
308 				      (sizeof(struct dwc_ufs_xfer_resp_upiu) >> 2));
309 	utrd_desc->ocs = 0xf;
310 	utrd_desc->prdt_length = to_littleendian16((uint16_t)
311 				 ((size + PRDT_BUFFER_SIZE - 1) / PRDT_BUFFER_SIZE));
312 
313 	cmd_upiu_ptr->trans_type       = 0x01;
314 	cmd_upiu_ptr->flags            = upiu_flags;
315 	cmd_upiu_ptr->lun              = UFS_BOOT_LUN;
316 	cmd_upiu_ptr->task_tag         = tag;
317 	cmd_upiu_ptr->cmd_set_type     = 0x0;
318 	cmd_upiu_ptr->reserved_1_0     = 0x0;
319 	cmd_upiu_ptr->reserved_1_1     = 0x0;
320 	cmd_upiu_ptr->reserved_1_2     = 0x0;
321 	cmd_upiu_ptr->tot_ehs_len      = 0x0;
322 	cmd_upiu_ptr->reserved_2       = 0x0;
323 	cmd_upiu_ptr->data_seg_len     = 0x0;
324 	cmd_upiu_ptr->exp_data_xfer_len = to_bigendian32(size);
325 
326 	ret = get_cmnd(opcode, (rel_addr / LOGICAL_BLK_SIZE),
327 		       (size / LOGICAL_BLK_SIZE), cmd_upiu_ptr->cdb);
328 	if (ret) {
329 		return UFS_SOFTWARE_ERROR;
330 	}
331 
332 	buf_addr_phy =
333 		(uint64_t)LPRAM_ADDR_FROM_LPM3_TO_CPU((uint64_t)buf_addr);
334 
335 	/* Fill PRD Table Info */
336 	if (direction != DMA_NONE) {
337 		for (i = 0; (size); i++) {
338 			prdt_table[i].base_addr =
339 				to_littleendian32((uint32_t)
340 						  (buf_addr_phy & 0xffffffff) +
341 						  (i * prdt_buf_size));
342 			prdt_table[i].upper_addr =
343 				to_littleendian32((uint32_t)
344 						  ((buf_addr_phy >> 32) & 0xffffffff));
345 			prdt_table[i].reserved1 = 0x0;
346 			prdt_table[i].size = to_littleendian32
347 					     (((prdt_buf_size < size) ? prdt_buf_size : size) - 1);
348 			size -= (prdt_buf_size < size) ? prdt_buf_size : size;
349 		}
350 	}
351 
352 	return UFS_SUCCESS;
353 }
354 
send_scsi_cmd(uint32_t opcode,enum dma_data_direction direction,uint64_t buf_addr,uint32_t rel_addr,uint32_t size,uint32_t tag)355 static int send_scsi_cmd(uint32_t opcode,
356 			 enum dma_data_direction direction,
357 			 uint64_t buf_addr, uint32_t rel_addr,
358 			 uint32_t size, uint32_t tag)
359 {
360 	int ret;
361 	uint32_t timeout_ms;
362 
363 	if (size % 0x4) {
364 		return UFS_SOFTWARE_ERROR;
365 	}
366 	if (size / PRDT_BUFFER_SIZE >= MAX_PRDT_ENTRIES) {
367 		return UFS_SOFTWARE_ERROR;
368 	}
369 
370 	if (opcode == UFS_OP_TEST_UNIT_READY) {
371 		timeout_ms = 10;
372 	} else if (opcode == UFS_OP_READ_10)
373 		//timeout_ms = 1000;
374 		//debug for reset bug
375 	{
376 		timeout_ms = 50000;
377 	} else {
378 		return UFS_SOFTWARE_ERROR;
379 	}
380 
381 	ret = create_cmd_upiu(opcode, direction, buf_addr, rel_addr, size, tag);
382 	if (ret != UFS_SUCCESS) {
383 		return ret;
384 	}
385 
386 	ret = wait_for_cmd_completion(tag, timeout_ms);
387 	return ret;
388 }
389 
handle_scsi_completion(uint32_t tag)390 static int handle_scsi_completion(uint32_t tag)
391 {
392 	struct dwc_ufs_xfer_resp_upiu *resp_upiu;
393 	struct dwc_ufs_utrd *utrd_desc;
394 	uint8_t status;
395 
396 	resp_upiu = (struct dwc_ufs_xfer_resp_upiu *)UFS_RESP_UPIU_BASE;
397 	utrd_desc = (struct dwc_ufs_utrd *)UFS_TR_UTP_BASE;
398 	utrd_desc += tag - 1;
399 	debug_printf("handle_scsi_completion: utrd_desc addr 0x%x\n", utrd_desc);
400 
401 	if (utrd_desc->ocs == UFS_SUCCESS) {
402 		status = resp_upiu->status;
403 		if (status == SAM_STAT_GOOD) {
404 			return UFS_SUCCESS;
405 		}
406 
407 		if (status == SAM_STAT_CHECK_CONDITION) {
408 			return -(RET_SENSE_KEY_OFF + (resp_upiu->sense_data[2] & 0xf));
409 		}
410 
411 		switch (status) {
412 		case SAM_STAT_CONDITION_MET:
413 			return RESP_STAT_CONDITION_MET;
414 		case SAM_STAT_BUSY:
415 			return RESP_STAT_BUSY;
416 		case SAM_STAT_RESERVATION_CONFLICT:
417 			return RESP_STAT_RESERVATION_CONFLICT;
418 		case SAM_STAT_TASK_SET_FULL:
419 			return RESP_STAT_TASK_SET_FULL;
420 		case SAM_STAT_ACA_ACTIVE:
421 			return RESP_STAT_ACA_ACTIVE;
422 		case SAM_STAT_TASK_ABORTED:
423 			return RESP_STAT_TASK_ABORTED;
424 		default:
425 			return RESP_STAT_UNKNOW;
426 		}
427 	} else {
428 		return -((utrd_desc->ocs & 0xf) + RET_UTRD_OCS_ERROR_OFF);
429 	}
430 
431 	return UFS_SUCCESS;
432 }
433 
do_scsi_cmd(uint32_t opcode,enum dma_data_direction direction,uint64_t buf_addr,uint32_t rel_addr,uint32_t size,uint32_t tag)434 static int do_scsi_cmd(uint32_t opcode,
435 		       enum dma_data_direction direction,
436 		       uint64_t buf_addr, uint32_t rel_addr,
437 		       uint32_t size, uint32_t tag)
438 {
439 	int ret = 0;
440 	if ((tag < 1) || (tag > MAX_TR_TASK)) {
441 		debug_printf("do_scsi_cmd: input tag invalid, tag = %d\n", tag);
442 		tag = 1;
443 	}
444 
445 	ret = send_scsi_cmd(opcode, direction, buf_addr, rel_addr, size, tag);
446 	if (ret != UFS_SUCCESS) {
447 		return ret;
448 	}
449 
450 	ret = handle_scsi_completion(tag);
451 	if (ret != UFS_SUCCESS) {
452 		return ret;
453 	}
454 	return ret;
455 }
456 
test_unit_ready(void)457 static int test_unit_ready(void)
458 {
459 	uint32_t tag = 0;
460 	int ret;
461 	int i;
462 
463 	tag = readl(STATIC_UFS_TAG_ADDR);
464 	debug_printf("test_unit_ready: read tag = %d\n", tag);
465 	for (i = 0; i < 4; i++) {
466 		if ((tag > MAX_TR_TASK) || (tag < 1)) {
467 			tag = 1;
468 		}
469 		debug_printf("test_unit_ready: tag = %d\n", tag);
470 
471 		ret = do_scsi_cmd(UFS_OP_TEST_UNIT_READY, DMA_NONE, 0, 0, 0, tag);
472 		if (ret == UFS_SUCCESS) {
473 			break;
474 		}
475 		debug_printf("test_unit_ready ret = %d, retry = %d\n", ret, i);
476 		ufs_waitms(1);
477 		if (ret == UFS_UTRD_DOORBELL_TIMEOUT) {
478 			tag++;
479 			writel(tag, STATIC_UFS_TAG_ADDR);
480 		}
481 	}
482 
483 	return ret;
484 }
485 
ufs_start_boot(void)486 static int ufs_start_boot(void)
487 {
488 	int ret;
489 
490 	ret = send_nop_out_cmd();
491 	if (ret) {
492 		debug_printf("ufs send nop out fail\n");
493 		return ret;
494 	}
495 
496 	debug_printf("ufs nop in out OK\n");
497 
498 	ret = test_unit_ready();
499 	if (ret) {
500 		debug_printf("ufs test unit ready fail\n");
501 		return ret;
502 	}
503 
504 	debug_printf("ufs test unit ready OK\n");
505 	return UFS_SUCCESS;
506 }
507 
ufs_read_boot_data(uint64_t buf_addr,uint32_t rel_addr,uint32_t size)508 static int ufs_read_boot_data(uint64_t buf_addr,
509 			      uint32_t rel_addr,
510 			      uint32_t size)
511 {
512 	int ret;
513 	int retry = 50;
514 	uint32_t tag = 0;
515 
516 	size = BYTES_ALIGN_4096(size);
517 	tag = readl(STATIC_UFS_TAG_ADDR);
518 	debug_printf("ufs_read_boot_data: read tag = %d\n", tag);
519 	if ((tag > MAX_TR_TASK) || (tag < 1)) {
520 		tag = 1;
521 	}
522 	debug_printf("ufs_read_boot_data: tag = %d\n", tag);
523 
524 	while (retry > 0) {
525 		ret = do_scsi_cmd(UFS_OP_READ_10, DMA_FROM_DEVICE, buf_addr, rel_addr, size, tag);
526 		if (ret == UFS_SUCCESS) {
527 			debug_printf("ufs read 10 OK\n");
528 			return ret;
529 		} else if ((ret == RESP_STAT_BUSY)
530 			   || (ret == RESP_STAT_TASK_SET_FULL)
531 			   || (ret == NOT_READY)) {
532 			ufs_waitms(1);
533 			retry--;
534 			debug_printf("ufs read 10 retry, ret = %d, retry = %d\n", ret, retry);
535 		} else {
536 			debug_printf("ufs read 10 FAIL, ret = %d\n", ret);
537 			break;
538 		}
539 	}
540 	return ret;
541 }
542 
ufs_boot_read(void * ptr,unsigned int size)543 void ufs_boot_read(void *ptr, unsigned int size)
544 {
545 	ufs_memset(ptr, 0, size);
546 	ufs_config_init();
547 	ufs_start_boot();
548 	ufs_read_boot_data((uint64_t)ptr, 0, size);
549 }
550 
551