xref: /rk3399_ARM-atf/drivers/ufs/ufs.c (revision 83ef8698f9d1477c892cad15b4e48574ed634903)
1 /*
2  * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <endian.h>
9 #include <errno.h>
10 #include <stdint.h>
11 #include <string.h>
12 
13 #include <platform_def.h>
14 
15 #include <arch_helpers.h>
16 #include <common/debug.h>
17 #include <drivers/delay_timer.h>
18 #include <drivers/ufs.h>
19 #include <lib/mmio.h>
20 
21 #define CDB_ADDR_MASK			127
22 #define ALIGN_CDB(x)			(((x) + CDB_ADDR_MASK) & ~CDB_ADDR_MASK)
23 #define ALIGN_8(x)			(((x) + 7) & ~7)
24 
25 #define UFS_DESC_SIZE			0x400
26 #define MAX_UFS_DESC_SIZE		0x8000		/* 32 descriptors */
27 
28 #define MAX_PRDT_SIZE			0x40000		/* 256KB */
29 
30 static ufs_params_t ufs_params;
31 static int nutrs;	/* Number of UTP Transfer Request Slots */
32 
33 int ufshc_send_uic_cmd(uintptr_t base, uic_cmd_t *cmd)
34 {
35 	unsigned int data;
36 
37 	if (base == 0 || cmd == NULL)
38 		return -EINVAL;
39 
40 	data = mmio_read_32(base + HCS);
41 	if ((data & HCS_UCRDY) == 0)
42 		return -EBUSY;
43 	mmio_write_32(base + IS, ~0);
44 	mmio_write_32(base + UCMDARG1, cmd->arg1);
45 	mmio_write_32(base + UCMDARG2, cmd->arg2);
46 	mmio_write_32(base + UCMDARG3, cmd->arg3);
47 	mmio_write_32(base + UICCMD, cmd->op);
48 
49 	do {
50 		data = mmio_read_32(base + IS);
51 	} while ((data & UFS_INT_UCCS) == 0);
52 	mmio_write_32(base + IS, UFS_INT_UCCS);
53 	return mmio_read_32(base + UCMDARG2) & CONFIG_RESULT_CODE_MASK;
54 }
55 
56 int ufshc_dme_get(unsigned int attr, unsigned int idx, unsigned int *val)
57 {
58 	uintptr_t base;
59 	unsigned int data;
60 	int result, retries;
61 	uic_cmd_t cmd;
62 
63 	assert(ufs_params.reg_base != 0);
64 
65 	if (val == NULL)
66 		return -EINVAL;
67 
68 	base = ufs_params.reg_base;
69 	for (retries = 0; retries < 100; retries++) {
70 		data = mmio_read_32(base + HCS);
71 		if ((data & HCS_UCRDY) != 0)
72 			break;
73 		mdelay(1);
74 	}
75 	if (retries >= 100)
76 		return -EBUSY;
77 
78 	cmd.arg1 = (attr << 16) | GEN_SELECTOR_IDX(idx);
79 	cmd.arg2 = 0;
80 	cmd.arg3 = 0;
81 	cmd.op = DME_GET;
82 	for (retries = 0; retries < UFS_UIC_COMMAND_RETRIES; ++retries) {
83 		result = ufshc_send_uic_cmd(base, &cmd);
84 		if (result == 0)
85 			break;
86 		data = mmio_read_32(base + IS);
87 		if (data & UFS_INT_UE)
88 			return -EINVAL;
89 	}
90 	if (retries >= UFS_UIC_COMMAND_RETRIES)
91 		return -EIO;
92 
93 	*val = mmio_read_32(base + UCMDARG3);
94 	return 0;
95 }
96 
97 int ufshc_dme_set(unsigned int attr, unsigned int idx, unsigned int val)
98 {
99 	uintptr_t base;
100 	unsigned int data;
101 	int result, retries;
102 	uic_cmd_t cmd;
103 
104 	assert((ufs_params.reg_base != 0));
105 
106 	base = ufs_params.reg_base;
107 	cmd.arg1 = (attr << 16) | GEN_SELECTOR_IDX(idx);
108 	cmd.arg2 = 0;
109 	cmd.arg3 = val;
110 	cmd.op = DME_SET;
111 
112 	for (retries = 0; retries < UFS_UIC_COMMAND_RETRIES; ++retries) {
113 		result = ufshc_send_uic_cmd(base, &cmd);
114 		if (result == 0)
115 			break;
116 		data = mmio_read_32(base + IS);
117 		if (data & UFS_INT_UE)
118 			return -EINVAL;
119 	}
120 	if (retries >= UFS_UIC_COMMAND_RETRIES)
121 		return -EIO;
122 
123 	return 0;
124 }
125 
126 static int ufshc_hce_enable(uintptr_t base)
127 {
128 	unsigned int data;
129 	int retries;
130 
131 	/* Enable Host Controller */
132 	mmio_write_32(base + HCE, HCE_ENABLE);
133 
134 	/* Wait until basic initialization sequence completed */
135 	for (retries = 0; retries < HCE_ENABLE_INNER_RETRIES; ++retries) {
136 		data = mmio_read_32(base + HCE);
137 		if (data & HCE_ENABLE) {
138 			break;
139 		}
140 		udelay(HCE_ENABLE_TIMEOUT_US);
141 	}
142 	if (retries >= HCE_ENABLE_INNER_RETRIES) {
143 		return -ETIMEDOUT;
144 	}
145 
146 	return 0;
147 }
148 
149 static int ufshc_hce_disable(uintptr_t base)
150 {
151 	unsigned int data;
152 	int timeout;
153 
154 	/* Disable Host Controller */
155 	mmio_write_32(base + HCE, HCE_DISABLE);
156 	timeout = HCE_DISABLE_TIMEOUT_US;
157 	do {
158 		data = mmio_read_32(base + HCE);
159 		if ((data & HCE_ENABLE) == HCE_DISABLE) {
160 			break;
161 		}
162 		udelay(1);
163 	} while (--timeout > 0);
164 
165 	if (timeout <= 0) {
166 		return -ETIMEDOUT;
167 	}
168 
169 	return 0;
170 }
171 
172 
173 static int ufshc_reset(uintptr_t base)
174 {
175 	unsigned int data;
176 	int retries, result;
177 
178 	/* disable controller if enabled */
179 	if (mmio_read_32(base + HCE) & HCE_ENABLE) {
180 		result = ufshc_hce_disable(base);
181 		if (result != 0) {
182 			return -EIO;
183 		}
184 	}
185 
186 	for (retries = 0; retries < HCE_ENABLE_OUTER_RETRIES; ++retries) {
187 		result = ufshc_hce_enable(base);
188 		if (result == 0) {
189 			break;
190 		}
191 	}
192 	if (retries >= HCE_ENABLE_OUTER_RETRIES) {
193 		return -EIO;
194 	}
195 
196 	/* Enable Interrupts */
197 	data = UFS_INT_UCCS | UFS_INT_ULSS | UFS_INT_UE | UFS_INT_UTPES |
198 	       UFS_INT_DFES | UFS_INT_HCFES | UFS_INT_SBFES;
199 	mmio_write_32(base + IE, data);
200 
201 	return 0;
202 }
203 
204 static int ufshc_dme_link_startup(uintptr_t base)
205 {
206 	uic_cmd_t cmd;
207 
208 	memset(&cmd, 0, sizeof(cmd));
209 	cmd.op = DME_LINKSTARTUP;
210 	return ufshc_send_uic_cmd(base, &cmd);
211 }
212 
213 static int ufshc_link_startup(uintptr_t base)
214 {
215 	int data, result;
216 	int retries;
217 
218 	for (retries = DME_LINKSTARTUP_RETRIES; retries > 0; retries--) {
219 		result = ufshc_dme_link_startup(base);
220 		if (result != 0) {
221 			/* Reset controller before trying again */
222 			result = ufshc_reset(base);
223 			if (result != 0) {
224 				return result;
225 			}
226 			continue;
227 		}
228 		assert(mmio_read_32(base + HCS) & HCS_DP);
229 		data = mmio_read_32(base + IS);
230 		if (data & UFS_INT_ULSS)
231 			mmio_write_32(base + IS, UFS_INT_ULSS);
232 		return 0;
233 	}
234 	return -EIO;
235 }
236 
237 /* Read Door Bell register to check if slot zero is available */
238 static int is_slot_available(void)
239 {
240 	if (mmio_read_32(ufs_params.reg_base + UTRLDBR) & 0x1) {
241 		return -EBUSY;
242 	}
243 	return 0;
244 }
245 
246 static void get_utrd(utp_utrd_t *utrd)
247 {
248 	uintptr_t base;
249 	int result;
250 	utrd_header_t *hd;
251 
252 	assert(utrd != NULL);
253 	result = is_slot_available();
254 	assert(result == 0);
255 
256 	/* clear utrd */
257 	memset((void *)utrd, 0, sizeof(utp_utrd_t));
258 	base = ufs_params.desc_base;
259 	/* clear the descriptor */
260 	memset((void *)base, 0, UFS_DESC_SIZE);
261 
262 	utrd->header = base;
263 	utrd->task_tag = 1; /* We always use the first slot */
264 	/* CDB address should be aligned with 128 bytes */
265 	utrd->upiu = ALIGN_CDB(utrd->header + sizeof(utrd_header_t));
266 	utrd->resp_upiu = ALIGN_8(utrd->upiu + sizeof(cmd_upiu_t));
267 	utrd->size_upiu = utrd->resp_upiu - utrd->upiu;
268 	utrd->size_resp_upiu = ALIGN_8(sizeof(resp_upiu_t));
269 	utrd->prdt = utrd->resp_upiu + utrd->size_resp_upiu;
270 
271 	hd = (utrd_header_t *)utrd->header;
272 	hd->ucdba = utrd->upiu & UINT32_MAX;
273 	hd->ucdbau = (utrd->upiu >> 32) & UINT32_MAX;
274 	/* Both RUL and RUO is based on DWORD */
275 	hd->rul = utrd->size_resp_upiu >> 2;
276 	hd->ruo = utrd->size_upiu >> 2;
277 	(void)result;
278 }
279 
280 /*
281  * Prepare UTRD, Command UPIU, Response UPIU.
282  */
283 static int ufs_prepare_cmd(utp_utrd_t *utrd, uint8_t op, uint8_t lun,
284 			   int lba, uintptr_t buf, size_t length)
285 {
286 	utrd_header_t *hd;
287 	cmd_upiu_t *upiu;
288 	prdt_t *prdt;
289 	unsigned int ulba;
290 	unsigned int lba_cnt;
291 	int prdt_size;
292 	uintptr_t desc_limit;
293 	size_t flush_size;
294 
295 	hd = (utrd_header_t *)utrd->header;
296 	upiu = (cmd_upiu_t *)utrd->upiu;
297 
298 	hd->i = 1;
299 	hd->ct = CT_UFS_STORAGE;
300 	hd->ocs = OCS_MASK;
301 
302 	upiu->trans_type = CMD_UPIU;
303 	upiu->task_tag = utrd->task_tag;
304 	upiu->cdb[0] = op;
305 	ulba = (unsigned int)lba;
306 	lba_cnt = (unsigned int)(length >> UFS_BLOCK_SHIFT);
307 	switch (op) {
308 	case CDBCMD_TEST_UNIT_READY:
309 		break;
310 	case CDBCMD_READ_CAPACITY_10:
311 		hd->dd = DD_OUT;
312 		upiu->flags = UPIU_FLAGS_R | UPIU_FLAGS_ATTR_S;
313 		upiu->lun = lun;
314 		break;
315 	case CDBCMD_READ_10:
316 		hd->dd = DD_OUT;
317 		upiu->flags = UPIU_FLAGS_R | UPIU_FLAGS_ATTR_S;
318 		upiu->lun = lun;
319 		upiu->cdb[1] = RW_WITHOUT_CACHE;
320 		/* set logical block address */
321 		upiu->cdb[2] = (ulba >> 24) & 0xff;
322 		upiu->cdb[3] = (ulba >> 16) & 0xff;
323 		upiu->cdb[4] = (ulba >> 8) & 0xff;
324 		upiu->cdb[5] = ulba & 0xff;
325 		/* set transfer length */
326 		upiu->cdb[7] = (lba_cnt >> 8) & 0xff;
327 		upiu->cdb[8] = lba_cnt & 0xff;
328 		break;
329 	case CDBCMD_WRITE_10:
330 		hd->dd = DD_IN;
331 		upiu->flags = UPIU_FLAGS_W | UPIU_FLAGS_ATTR_S;
332 		upiu->lun = lun;
333 		upiu->cdb[1] = RW_WITHOUT_CACHE;
334 		/* set logical block address */
335 		upiu->cdb[2] = (ulba >> 24) & 0xff;
336 		upiu->cdb[3] = (ulba >> 16) & 0xff;
337 		upiu->cdb[4] = (ulba >> 8) & 0xff;
338 		upiu->cdb[5] = ulba & 0xff;
339 		/* set transfer length */
340 		upiu->cdb[7] = (lba_cnt >> 8) & 0xff;
341 		upiu->cdb[8] = lba_cnt & 0xff;
342 		break;
343 	default:
344 		assert(0);
345 		break;
346 	}
347 	if (hd->dd == DD_IN) {
348 		flush_dcache_range(buf, length);
349 	} else if (hd->dd == DD_OUT) {
350 		inv_dcache_range(buf, length);
351 	}
352 
353 	utrd->size_prdt = 0;
354 	if (length) {
355 		upiu->exp_data_trans_len = htobe32(length);
356 		assert(lba_cnt <= UINT16_MAX);
357 		prdt = (prdt_t *)utrd->prdt;
358 
359 		desc_limit = ufs_params.desc_base + ufs_params.desc_size;
360 		prdt_size = 0;
361 		while (length > 0) {
362 			if ((uintptr_t)prdt + sizeof(prdt_t) > desc_limit) {
363 				ERROR("UFS: Exceeded descriptor limit. Image is too large\n");
364 				panic();
365 			}
366 			prdt->dba = (unsigned int)(buf & UINT32_MAX);
367 			prdt->dbau = (unsigned int)((buf >> 32) & UINT32_MAX);
368 			/* prdt->dbc counts from 0 */
369 			if (length > MAX_PRDT_SIZE) {
370 				prdt->dbc = MAX_PRDT_SIZE - 1;
371 				length = length - MAX_PRDT_SIZE;
372 			} else {
373 				prdt->dbc = length - 1;
374 				length = 0;
375 			}
376 			buf += MAX_PRDT_SIZE;
377 			prdt++;
378 			prdt_size += sizeof(prdt_t);
379 		}
380 		utrd->size_prdt = ALIGN_8(prdt_size);
381 		hd->prdtl = utrd->size_prdt >> 2;
382 		hd->prdto = (utrd->size_upiu + utrd->size_resp_upiu) >> 2;
383 	}
384 
385 	flush_size = utrd->prdt + utrd->size_prdt - utrd->header;
386 	flush_dcache_range(utrd->header, flush_size);
387 	return 0;
388 }
389 
390 static int ufs_prepare_query(utp_utrd_t *utrd, uint8_t op, uint8_t idn,
391 			     uint8_t index, uint8_t sel,
392 			     uintptr_t buf, size_t length)
393 {
394 	utrd_header_t *hd;
395 	query_upiu_t *query_upiu;
396 
397 
398 	hd = (utrd_header_t *)utrd->header;
399 	query_upiu = (query_upiu_t *)utrd->upiu;
400 
401 	hd->i = 1;
402 	hd->ct = CT_UFS_STORAGE;
403 	hd->ocs = OCS_MASK;
404 
405 	query_upiu->trans_type = QUERY_REQUEST_UPIU;
406 	query_upiu->task_tag = utrd->task_tag;
407 	query_upiu->ts.desc.opcode = op;
408 	query_upiu->ts.desc.idn = idn;
409 	query_upiu->ts.desc.index = index;
410 	query_upiu->ts.desc.selector = sel;
411 	switch (op) {
412 	case QUERY_READ_DESC:
413 		query_upiu->query_func = QUERY_FUNC_STD_READ;
414 		query_upiu->ts.desc.length = htobe16(length);
415 		break;
416 	case QUERY_WRITE_DESC:
417 		query_upiu->query_func = QUERY_FUNC_STD_WRITE;
418 		query_upiu->ts.desc.length = htobe16(length);
419 		memcpy((void *)(utrd->upiu + sizeof(query_upiu_t)),
420 		       (void *)buf, length);
421 		break;
422 	case QUERY_READ_ATTR:
423 	case QUERY_READ_FLAG:
424 		query_upiu->query_func = QUERY_FUNC_STD_READ;
425 		break;
426 	case QUERY_CLEAR_FLAG:
427 	case QUERY_SET_FLAG:
428 		query_upiu->query_func = QUERY_FUNC_STD_WRITE;
429 		break;
430 	case QUERY_WRITE_ATTR:
431 		query_upiu->query_func = QUERY_FUNC_STD_WRITE;
432 		query_upiu->ts.attr.value = htobe32(*((uint32_t *)buf));
433 		break;
434 	default:
435 		assert(0);
436 		break;
437 	}
438 	flush_dcache_range((uintptr_t)utrd->header, UFS_DESC_SIZE);
439 	return 0;
440 }
441 
442 static void ufs_prepare_nop_out(utp_utrd_t *utrd)
443 {
444 	utrd_header_t *hd;
445 	nop_out_upiu_t *nop_out;
446 
447 	hd = (utrd_header_t *)utrd->header;
448 	nop_out = (nop_out_upiu_t *)utrd->upiu;
449 
450 	hd->i = 1;
451 	hd->ct = CT_UFS_STORAGE;
452 	hd->ocs = OCS_MASK;
453 
454 	nop_out->trans_type = 0;
455 	nop_out->task_tag = utrd->task_tag;
456 	flush_dcache_range((uintptr_t)utrd->header, UFS_DESC_SIZE);
457 }
458 
459 static void ufs_send_request(int task_tag)
460 {
461 	unsigned int data;
462 	int slot;
463 
464 	slot = task_tag - 1;
465 	/* clear all interrupts */
466 	mmio_write_32(ufs_params.reg_base + IS, ~0);
467 
468 	mmio_write_32(ufs_params.reg_base + UTRLRSR, 1);
469 	assert(mmio_read_32(ufs_params.reg_base + UTRLRSR) == 1);
470 
471 	data = UTRIACR_IAEN | UTRIACR_CTR | UTRIACR_IACTH(0x1F) |
472 	       UTRIACR_IATOVAL(0xFF);
473 	mmio_write_32(ufs_params.reg_base + UTRIACR, data);
474 	/* send request */
475 	mmio_setbits_32(ufs_params.reg_base + UTRLDBR, 1 << slot);
476 }
477 
478 static int ufs_check_resp(utp_utrd_t *utrd, int trans_type)
479 {
480 	utrd_header_t *hd;
481 	resp_upiu_t *resp;
482 	sense_data_t *sense;
483 	unsigned int data;
484 	int slot;
485 
486 	hd = (utrd_header_t *)utrd->header;
487 	resp = (resp_upiu_t *)utrd->resp_upiu;
488 	do {
489 		data = mmio_read_32(ufs_params.reg_base + IS);
490 		if ((data & ~(UFS_INT_UCCS | UFS_INT_UTRCS)) != 0)
491 			return -EIO;
492 	} while ((data & UFS_INT_UTRCS) == 0);
493 	slot = utrd->task_tag - 1;
494 
495 	data = mmio_read_32(ufs_params.reg_base + UTRLDBR);
496 	assert((data & (1 << slot)) == 0);
497 	/*
498 	 * Invalidate the header after DMA read operation has
499 	 * completed to avoid cpu referring to the prefetched
500 	 * data brought in before DMA completion.
501 	 */
502 	inv_dcache_range((uintptr_t)hd, UFS_DESC_SIZE);
503 	assert(hd->ocs == OCS_SUCCESS);
504 	assert((resp->trans_type & TRANS_TYPE_CODE_MASK) == trans_type);
505 
506 	sense = &resp->sd.sense;
507 	if (sense->resp_code == SENSE_DATA_VALID &&
508 	    sense->sense_key == SENSE_KEY_UNIT_ATTENTION && sense->asc == 0x29 &&
509 	    sense->ascq == 0) {
510 		WARN("Unit Attention Condition\n");
511 		return -EAGAIN;
512 	}
513 
514 	(void)resp;
515 	(void)slot;
516 	return 0;
517 }
518 
519 static void ufs_send_cmd(utp_utrd_t *utrd, uint8_t cmd_op, uint8_t lun, int lba, uintptr_t buf,
520 			 size_t length)
521 {
522 	int result, i;
523 
524 	for (i = 0; i < UFS_CMD_RETRIES; ++i) {
525 		get_utrd(utrd);
526 		result = ufs_prepare_cmd(utrd, cmd_op, lun, lba, buf, length);
527 		assert(result == 0);
528 		ufs_send_request(utrd->task_tag);
529 		result = ufs_check_resp(utrd, RESPONSE_UPIU);
530 		if (result == 0 || result == -EIO) {
531 			break;
532 		}
533 	}
534 	assert(result == 0);
535 	(void)result;
536 }
537 
538 #ifdef UFS_RESP_DEBUG
539 static void dump_upiu(utp_utrd_t *utrd)
540 {
541 	utrd_header_t *hd;
542 	int i;
543 
544 	hd = (utrd_header_t *)utrd->header;
545 	INFO("utrd:0x%x, ruo:0x%x, rul:0x%x, ocs:0x%x, UTRLDBR:0x%x\n",
546 		(unsigned int)(uintptr_t)utrd, hd->ruo, hd->rul, hd->ocs,
547 		mmio_read_32(ufs_params.reg_base + UTRLDBR));
548 	for (i = 0; i < sizeof(utrd_header_t); i += 4) {
549 		INFO("[%lx]:0x%x\n",
550 			(uintptr_t)utrd->header + i,
551 			*(unsigned int *)((uintptr_t)utrd->header + i));
552 	}
553 
554 	for (i = 0; i < sizeof(cmd_upiu_t); i += 4) {
555 		INFO("cmd[%lx]:0x%x\n",
556 			utrd->upiu + i,
557 			*(unsigned int *)(utrd->upiu + i));
558 	}
559 	for (i = 0; i < sizeof(resp_upiu_t); i += 4) {
560 		INFO("resp[%lx]:0x%x\n",
561 			utrd->resp_upiu + i,
562 			*(unsigned int *)(utrd->resp_upiu + i));
563 	}
564 	for (i = 0; i < sizeof(prdt_t); i += 4) {
565 		INFO("prdt[%lx]:0x%x\n",
566 			utrd->prdt + i,
567 			*(unsigned int *)(utrd->prdt + i));
568 	}
569 }
570 #endif
571 
572 static void ufs_verify_init(void)
573 {
574 	utp_utrd_t utrd;
575 	int result;
576 
577 	get_utrd(&utrd);
578 	ufs_prepare_nop_out(&utrd);
579 	ufs_send_request(utrd.task_tag);
580 	result = ufs_check_resp(&utrd, NOP_IN_UPIU);
581 	assert(result == 0);
582 	(void)result;
583 }
584 
585 static void ufs_verify_ready(void)
586 {
587 	utp_utrd_t utrd;
588 	ufs_send_cmd(&utrd, CDBCMD_TEST_UNIT_READY, 0, 0, 0, 0);
589 }
590 
591 static void ufs_query(uint8_t op, uint8_t idn, uint8_t index, uint8_t sel,
592 		      uintptr_t buf, size_t size)
593 {
594 	utp_utrd_t utrd;
595 	query_resp_upiu_t *resp;
596 	int result;
597 
598 	switch (op) {
599 	case QUERY_READ_FLAG:
600 	case QUERY_READ_ATTR:
601 	case QUERY_READ_DESC:
602 	case QUERY_WRITE_DESC:
603 	case QUERY_WRITE_ATTR:
604 		assert(((buf & 3) == 0) && (size != 0));
605 		break;
606 	default:
607 		/* Do nothing in default case */
608 		break;
609 	}
610 	get_utrd(&utrd);
611 	ufs_prepare_query(&utrd, op, idn, index, sel, buf, size);
612 	ufs_send_request(utrd.task_tag);
613 	result = ufs_check_resp(&utrd, QUERY_RESPONSE_UPIU);
614 	assert(result == 0);
615 	resp = (query_resp_upiu_t *)utrd.resp_upiu;
616 #ifdef UFS_RESP_DEBUG
617 	dump_upiu(&utrd);
618 #endif
619 	assert(resp->query_resp == QUERY_RESP_SUCCESS);
620 
621 	switch (op) {
622 	case QUERY_READ_FLAG:
623 		*(uint32_t *)buf = (uint32_t)resp->ts.flag.value;
624 		break;
625 	case QUERY_READ_DESC:
626 		memcpy((void *)buf,
627 		       (void *)(utrd.resp_upiu + sizeof(query_resp_upiu_t)),
628 		       size);
629 		break;
630 	case QUERY_READ_ATTR:
631 		*(uint32_t *)buf = htobe32(resp->ts.attr.value);
632 		break;
633 	default:
634 		/* Do nothing in default case */
635 		break;
636 	}
637 	(void)result;
638 }
639 
640 unsigned int ufs_read_attr(int idn)
641 {
642 	unsigned int value;
643 
644 	ufs_query(QUERY_READ_ATTR, idn, 0, 0,
645 		  (uintptr_t)&value, sizeof(value));
646 	return value;
647 }
648 
649 void ufs_write_attr(int idn, unsigned int value)
650 {
651 	ufs_query(QUERY_WRITE_ATTR, idn, 0, 0,
652 		  (uintptr_t)&value, sizeof(value));
653 }
654 
655 unsigned int ufs_read_flag(int idn)
656 {
657 	unsigned int value;
658 
659 	ufs_query(QUERY_READ_FLAG, idn, 0, 0,
660 		  (uintptr_t)&value, sizeof(value));
661 	return value;
662 }
663 
664 void ufs_set_flag(int idn)
665 {
666 	ufs_query(QUERY_SET_FLAG, idn, 0, 0, 0, 0);
667 }
668 
669 void ufs_clear_flag(int idn)
670 {
671 	ufs_query(QUERY_CLEAR_FLAG, idn, 0, 0, 0, 0);
672 }
673 
674 void ufs_read_desc(int idn, int index, uintptr_t buf, size_t size)
675 {
676 	ufs_query(QUERY_READ_DESC, idn, index, 0, buf, size);
677 }
678 
679 void ufs_write_desc(int idn, int index, uintptr_t buf, size_t size)
680 {
681 	ufs_query(QUERY_WRITE_DESC, idn, index, 0, buf, size);
682 }
683 
684 static int ufs_read_capacity(int lun, unsigned int *num, unsigned int *size)
685 {
686 	utp_utrd_t utrd;
687 	resp_upiu_t *resp;
688 	sense_data_t *sense;
689 	unsigned char data[CACHE_WRITEBACK_GRANULE << 1];
690 	uintptr_t buf;
691 	int retries = UFS_READ_CAPACITY_RETRIES;
692 
693 	assert((ufs_params.reg_base != 0) &&
694 	       (ufs_params.desc_base != 0) &&
695 	       (ufs_params.desc_size >= UFS_DESC_SIZE) &&
696 	       (num != NULL) && (size != NULL));
697 
698 	/* align buf address */
699 	buf = (uintptr_t)data;
700 	buf = (buf + CACHE_WRITEBACK_GRANULE - 1) &
701 	      ~(CACHE_WRITEBACK_GRANULE - 1);
702 	do {
703 		ufs_send_cmd(&utrd, CDBCMD_READ_CAPACITY_10, lun, 0,
704 			    buf, READ_CAPACITY_LENGTH);
705 #ifdef UFS_RESP_DEBUG
706 		dump_upiu(&utrd);
707 #endif
708 		resp = (resp_upiu_t *)utrd.resp_upiu;
709 		sense = &resp->sd.sense;
710 		if (!((sense->resp_code == SENSE_DATA_VALID) &&
711 		    (sense->sense_key == SENSE_KEY_UNIT_ATTENTION) &&
712 		    (sense->asc == 0x29) && (sense->ascq == 0))) {
713 			inv_dcache_range(buf, CACHE_WRITEBACK_GRANULE);
714 			/* last logical block address */
715 			*num = be32toh(*(unsigned int *)buf);
716 			if (*num)
717 				*num += 1;
718 			/* logical block length in bytes */
719 			*size = be32toh(*(unsigned int *)(buf + 4));
720 
721 			return 0;
722 		}
723 
724 	} while (retries-- > 0);
725 
726 	return -ETIMEDOUT;
727 }
728 
729 size_t ufs_read_blocks(int lun, int lba, uintptr_t buf, size_t size)
730 {
731 	utp_utrd_t utrd;
732 	resp_upiu_t *resp;
733 
734 	assert((ufs_params.reg_base != 0) &&
735 	       (ufs_params.desc_base != 0) &&
736 	       (ufs_params.desc_size >= UFS_DESC_SIZE));
737 
738 	ufs_send_cmd(&utrd, CDBCMD_READ_10, lun, lba, buf, size);
739 #ifdef UFS_RESP_DEBUG
740 	dump_upiu(&utrd);
741 #endif
742 	/*
743 	 * Invalidate prefetched cache contents before cpu
744 	 * accesses the buf.
745 	 */
746 	inv_dcache_range(buf, size);
747 	resp = (resp_upiu_t *)utrd.resp_upiu;
748 	return size - resp->res_trans_cnt;
749 }
750 
751 size_t ufs_write_blocks(int lun, int lba, const uintptr_t buf, size_t size)
752 {
753 	utp_utrd_t utrd;
754 	resp_upiu_t *resp;
755 
756 	assert((ufs_params.reg_base != 0) &&
757 	       (ufs_params.desc_base != 0) &&
758 	       (ufs_params.desc_size >= UFS_DESC_SIZE));
759 
760 	ufs_send_cmd(&utrd, CDBCMD_WRITE_10, lun, lba, buf, size);
761 #ifdef UFS_RESP_DEBUG
762 	dump_upiu(&utrd);
763 #endif
764 	resp = (resp_upiu_t *)utrd.resp_upiu;
765 	return size - resp->res_trans_cnt;
766 }
767 
768 static int ufs_set_fdevice_init(void)
769 {
770 	unsigned int result;
771 	int timeout;
772 
773 	ufs_set_flag(FLAG_DEVICE_INIT);
774 
775 	timeout = FDEVICEINIT_TIMEOUT_MS;
776 	do {
777 		result = ufs_read_flag(FLAG_DEVICE_INIT);
778 		if (!result) {
779 			break;
780 		}
781 		mdelay(5);
782 		timeout -= 5;
783 	} while (timeout > 0);
784 
785 	if (result != 0U) {
786 		return -ETIMEDOUT;
787 	}
788 
789 	return 0;
790 }
791 
792 static void ufs_enum(void)
793 {
794 	unsigned int blk_num, blk_size;
795 	int i, result;
796 
797 	mmio_write_32(ufs_params.reg_base + UTRLBA,
798 		      ufs_params.desc_base & UINT32_MAX);
799 	mmio_write_32(ufs_params.reg_base + UTRLBAU,
800 		      (ufs_params.desc_base >> 32) & UINT32_MAX);
801 
802 	ufs_verify_init();
803 	ufs_verify_ready();
804 
805 	result = ufs_set_fdevice_init();
806 	assert(result == 0);
807 
808 	blk_num = 0;
809 	blk_size = 0;
810 
811 	/* dump available LUNs */
812 	for (i = 0; i < UFS_MAX_LUNS; i++) {
813 		result = ufs_read_capacity(i, &blk_num, &blk_size);
814 		if (result != 0) {
815 			WARN("UFS LUN%d dump failed\n", i);
816 		}
817 		if (blk_num && blk_size) {
818 			INFO("UFS LUN%d contains %d blocks with %d-byte size\n",
819 			     i, blk_num, blk_size);
820 		}
821 	}
822 
823 	(void)result;
824 }
825 
826 static void ufs_get_device_info(struct ufs_dev_desc *card_data)
827 {
828 	uint8_t desc_buf[DESC_DEVICE_MAX_SIZE];
829 
830 	ufs_query(QUERY_READ_DESC, DESC_TYPE_DEVICE, 0, 0,
831 				(uintptr_t)desc_buf, DESC_DEVICE_MAX_SIZE);
832 
833 	/*
834 	 * getting vendor (manufacturerID) and Bank Index in big endian
835 	 * format
836 	 */
837 	card_data->wmanufacturerid = (uint16_t)((desc_buf[DEVICE_DESC_PARAM_MANF_ID] << 8) |
838 				     (desc_buf[DEVICE_DESC_PARAM_MANF_ID + 1]));
839 }
840 
841 int ufs_init(const ufs_ops_t *ops, ufs_params_t *params)
842 {
843 	int result;
844 	unsigned int data;
845 	uic_cmd_t cmd;
846 	struct ufs_dev_desc card = {0};
847 
848 	assert((params != NULL) &&
849 	       (params->reg_base != 0) &&
850 	       (params->desc_base != 0) &&
851 	       (params->desc_size >= UFS_DESC_SIZE));
852 
853 	memcpy(&ufs_params, params, sizeof(ufs_params_t));
854 
855 	/* 0 means 1 slot */
856 	nutrs = (mmio_read_32(ufs_params.reg_base + CAP) & CAP_NUTRS_MASK) + 1;
857 	if (nutrs > (ufs_params.desc_size / UFS_DESC_SIZE)) {
858 		nutrs = ufs_params.desc_size / UFS_DESC_SIZE;
859 	}
860 
861 
862 	if (ufs_params.flags & UFS_FLAGS_SKIPINIT) {
863 		mmio_write_32(ufs_params.reg_base + UTRLBA,
864 			      ufs_params.desc_base & UINT32_MAX);
865 		mmio_write_32(ufs_params.reg_base + UTRLBAU,
866 			      (ufs_params.desc_base >> 32) & UINT32_MAX);
867 
868 		result = ufshc_dme_get(0x1571, 0, &data);
869 		assert(result == 0);
870 		result = ufshc_dme_get(0x41, 0, &data);
871 		assert(result == 0);
872 		if (data == 1) {
873 			/* prepare to exit hibernate mode */
874 			memset(&cmd, 0, sizeof(uic_cmd_t));
875 			cmd.op = DME_HIBERNATE_EXIT;
876 			result = ufshc_send_uic_cmd(ufs_params.reg_base,
877 						    &cmd);
878 			assert(result == 0);
879 			data = mmio_read_32(ufs_params.reg_base + UCMDARG2);
880 			assert(data == 0);
881 			do {
882 				data = mmio_read_32(ufs_params.reg_base + IS);
883 			} while ((data & UFS_INT_UHXS) == 0);
884 			mmio_write_32(ufs_params.reg_base + IS, UFS_INT_UHXS);
885 			data = mmio_read_32(ufs_params.reg_base + HCS);
886 			assert((data & HCS_UPMCRS_MASK) == HCS_PWR_LOCAL);
887 		}
888 		result = ufshc_dme_get(0x1568, 0, &data);
889 		assert(result == 0);
890 		assert((data > 0) && (data <= 3));
891 	} else {
892 		assert((ops != NULL) && (ops->phy_init != NULL) &&
893 		       (ops->phy_set_pwr_mode != NULL));
894 
895 		result = ufshc_reset(ufs_params.reg_base);
896 		assert(result == 0);
897 		ops->phy_init(&ufs_params);
898 		result = ufshc_link_startup(ufs_params.reg_base);
899 		assert(result == 0);
900 
901 		ufs_enum();
902 
903 		ufs_get_device_info(&card);
904 		if (card.wmanufacturerid == UFS_VENDOR_SKHYNIX) {
905 			ufs_params.flags |= UFS_FLAGS_VENDOR_SKHYNIX;
906 		}
907 
908 		ops->phy_set_pwr_mode(&ufs_params);
909 	}
910 
911 	(void)result;
912 	return 0;
913 }
914