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