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 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 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 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 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 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 */ 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 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 574 void ufs_set_flag(int idn) 575 { 576 ufs_query(QUERY_SET_FLAG, idn, 0, 0, 0, 0); 577 } 578 579 void ufs_clear_flag(int idn) 580 { 581 ufs_query(QUERY_CLEAR_FLAG, idn, 0, 0, 0, 0); 582 } 583 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 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 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 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 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 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 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 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