1 /** @file 2 This file implement the MMC Host Protocol for the DesignWare SD. 3 4 Copyright (c) 2014-2016, Linaro Limited. All rights reserved. 5 Copyright (c) 2014-2016, Hisilicon Limited. All rights reserved. 6 7 This program and the accompanying materials 8 are licensed and made available under the terms and conditions of the BSD License 9 which accompanies this distribution. The full text of the license may be found at 10 http://opensource.org/licenses/bsd-license.php 11 12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 14 15 **/ 16 17 #include <Library/BaseMemoryLib.h> 18 #include <Library/CacheMaintenanceLib.h> 19 #include <Library/DebugLib.h> 20 #include <Library/DevicePathLib.h> 21 #include <Library/IoLib.h> 22 #include <Library/MemoryAllocationLib.h> 23 #include <Library/PcdLib.h> 24 #include <Library/TimerLib.h> 25 #include <Library/UefiBootServicesTableLib.h> 26 #include <Library/UefiLib.h> 27 #include <Protocol/MmcHost.h> 28 29 #include <Library/PrintLib.h> 30 #include <Library/SerialPortLib.h> 31 32 #include "DwSd.h" 33 34 #define DWSD_DESC_PAGE 1 35 #define DWSD_BLOCK_SIZE 512 36 #define DWSD_DMA_BUF_SIZE (512 * 8) 37 38 #define DWSD_DMA_THRESHOLD 16 39 40 #define MAX_IDLE_LOOPS 1000000 41 42 typedef struct { 43 UINT32 Des0; 44 UINT32 Des1; 45 UINT32 Des2; 46 UINT32 Des3; 47 } DWSD_IDMAC_DESCRIPTOR; 48 49 EFI_MMC_HOST_PROTOCOL *gpMmcHost; 50 DWSD_IDMAC_DESCRIPTOR *gpIdmacDesc; 51 EFI_GUID mDwSdDevicePathGuid = EFI_CALLER_ID_GUID; 52 STATIC UINT32 mDwSdCommand; 53 STATIC UINT32 mDwSdArgument; 54 55 EFI_STATUS 56 DwSdSendCommand ( 57 IN EFI_MMC_HOST_PROTOCOL *This, 58 IN MMC_CMD MmcCmd, 59 IN UINT32 Argument 60 ); 61 EFI_STATUS 62 DwSdReceiveResponse ( 63 IN EFI_MMC_HOST_PROTOCOL *This, 64 IN MMC_RESPONSE_TYPE Type, 65 IN UINT32* Buffer 66 ); 67 68 EFI_STATUS 69 DwSdReadBlockData ( 70 IN EFI_MMC_HOST_PROTOCOL *This, 71 IN EFI_LBA Lba, 72 IN UINTN Length, 73 IN UINT32* Buffer 74 ); 75 76 BOOLEAN 77 DwSdIsPowerOn ( 78 VOID 79 ) 80 { 81 return TRUE; 82 } 83 84 EFI_STATUS 85 DwSdInitialize ( 86 VOID 87 ) 88 { 89 DEBUG ((EFI_D_BLKIO, "DwSdInitialize()")); 90 return EFI_SUCCESS; 91 } 92 93 BOOLEAN 94 DwSdIsCardPresent ( 95 IN EFI_MMC_HOST_PROTOCOL *This 96 ) 97 { 98 UINT32 Value; 99 100 /* 101 * FIXME 102 * At first, reading GPIO pin shouldn't exist in SD driver. We need to 103 * add some callbacks to handle settings for hardware platform. 104 * In the second, reading GPIO pin should be based on GPIO driver. Now 105 * GPIO driver could only be used for one PL061 gpio controller. And it's 106 * used to detect jumper setting. As a workaround, we have to read the gpio 107 * register instead at here. 108 * 109 */ 110 Value = MmioRead32 (0xf8012000 + (1 << 2)); 111 if (Value) 112 return FALSE; 113 return TRUE; 114 } 115 116 BOOLEAN 117 DwSdIsReadOnly ( 118 IN EFI_MMC_HOST_PROTOCOL *This 119 ) 120 { 121 /* FIXME */ 122 return FALSE; 123 } 124 125 EFI_STATUS 126 DwSdBuildDevicePath ( 127 IN EFI_MMC_HOST_PROTOCOL *This, 128 IN EFI_DEVICE_PATH_PROTOCOL **DevicePath 129 ) 130 { 131 EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode; 132 133 NewDevicePathNode = CreateDeviceNode (HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH)); 134 CopyGuid (& ((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid, &mDwSdDevicePathGuid); 135 136 *DevicePath = NewDevicePathNode; 137 return EFI_SUCCESS; 138 } 139 140 EFI_STATUS 141 DwSdUpdateClock ( 142 VOID 143 ) 144 { 145 UINT32 Data; 146 147 /* CMD_UPDATE_CLK */ 148 Data = BIT_CMD_WAIT_PRVDATA_COMPLETE | BIT_CMD_UPDATE_CLOCK_ONLY | 149 BIT_CMD_START; 150 MmioWrite32 (DWSD_CMD, Data); 151 while (1) { 152 Data = MmioRead32 (DWSD_CMD); 153 if (!(Data & CMD_START_BIT)) 154 break; 155 Data = MmioRead32 (DWSD_RINTSTS); 156 if (Data & DWSD_INT_HLE) 157 { 158 Print (L"failed to update mmc clock frequency\n"); 159 return EFI_DEVICE_ERROR; 160 } 161 } 162 return EFI_SUCCESS; 163 } 164 165 EFI_STATUS 166 DwSdSetClock ( 167 IN UINTN ClockFreq 168 ) 169 { 170 UINT32 Divider, Rate, Data, Count; 171 EFI_STATUS Status; 172 BOOLEAN Found = FALSE; 173 174 for (Divider = 1; Divider < 256; Divider++) { 175 Rate = PcdGet32 (PcdDwSdDxeClockFrequencyInHz); 176 if ((Rate / (2 * Divider)) <= ClockFreq) { 177 Found = TRUE; 178 break; 179 } 180 } 181 if (Found == FALSE) 182 return EFI_NOT_FOUND; 183 184 // Wait until MMC is idle 185 Count = 0; 186 do { 187 Data = MmioRead32 (DWSD_STATUS); 188 if (Count++ > MAX_IDLE_LOOPS) 189 break; 190 } while (Data & DWSD_STS_DATA_BUSY); 191 192 // Disable MMC clock first 193 MmioWrite32 (DWSD_CLKENA, 0); 194 Status = DwSdUpdateClock (); 195 ASSERT (!EFI_ERROR (Status)); 196 197 MmioWrite32 (DWSD_CLKDIV, Divider); 198 Status = DwSdUpdateClock (); 199 ASSERT (!EFI_ERROR (Status)); 200 201 // Enable MMC clock 202 MmioWrite32 (DWSD_CLKENA, 1); 203 MmioWrite32 (DWSD_CLKSRC, 0); 204 Status = DwSdUpdateClock (); 205 ASSERT (!EFI_ERROR (Status)); 206 return EFI_SUCCESS; 207 } 208 209 EFI_STATUS 210 DwSdNotifyState ( 211 IN EFI_MMC_HOST_PROTOCOL *This, 212 IN MMC_STATE State 213 ) 214 { 215 UINT32 Data; 216 EFI_STATUS Status; 217 218 switch (State) { 219 case MmcInvalidState: 220 ASSERT (0); 221 break; 222 case MmcHwInitializationState: 223 MmioWrite32 (DWSD_PWREN, 1); 224 225 // If device already turn on then restart it 226 Data = DWSD_CTRL_RESET_ALL; 227 MmioWrite32 (DWSD_CTRL, Data); 228 do { 229 // Wait until reset operation finished 230 Data = MmioRead32 (DWSD_CTRL); 231 } while (Data & DWSD_CTRL_RESET_ALL); 232 233 MmioWrite32 (DWSD_RINTSTS, ~0); 234 MmioWrite32 (DWSD_INTMASK, 0); 235 MmioWrite32 (DWSD_TMOUT, ~0); 236 MmioWrite32 (DWSD_IDINTEN, 0); 237 MmioWrite32 (DWSD_BMOD, DWSD_IDMAC_SWRESET); 238 239 MmioWrite32 (DWSD_BLKSIZ, DWSD_BLOCK_SIZE); 240 do { 241 Data = MmioRead32 (DWSD_BMOD); 242 } while (Data & DWSD_IDMAC_SWRESET); 243 244 245 Data = DWSD_DMA_BURST_SIZE(2) | DWSD_FIFO_TWMARK(8) | DWSD_FIFO_RWMARK(7) | (2 << 28); 246 MmioWrite32 (DWSD_FIFOTH, Data); 247 Data = DWSD_CARD_RD_THR(512) | DWSD_CARD_RD_THR_EN; 248 MmioWrite32 (DWSD_CARDTHRCTL, Data); 249 250 // Set Data Length & Data Timer 251 MmioWrite32 (DWSD_CTYPE, 0); 252 MmioWrite32 (DWSD_DEBNCE, 0x00ffffff); 253 254 // Setup clock that could not be higher than 400KHz. 255 Status = DwSdSetClock (400000); 256 ASSERT (!EFI_ERROR (Status)); 257 MicroSecondDelay (100); 258 259 break; 260 case MmcIdleState: 261 break; 262 case MmcReadyState: 263 break; 264 case MmcIdentificationState: 265 break; 266 case MmcStandByState: 267 break; 268 case MmcTransferState: 269 break; 270 case MmcSendingDataState: 271 break; 272 case MmcReceiveDataState: 273 break; 274 case MmcProgrammingState: 275 break; 276 case MmcDisconnectState: 277 break; 278 default: 279 ASSERT (0); 280 } 281 return EFI_SUCCESS; 282 } 283 284 EFI_STATUS 285 SendCommand ( 286 IN MMC_CMD MmcCmd, 287 IN UINT32 Argument 288 ) 289 { 290 UINT32 Data, ErrMask, Count; 291 292 MmioWrite32 (DWSD_RINTSTS, ~0); 293 MmioWrite32 (DWSD_CMDARG, Argument); 294 MicroSecondDelay(500); 295 // Wait until MMC is idle 296 Count = 0; 297 do { 298 Data = MmioRead32 (DWSD_STATUS); 299 if (Count++ > MAX_IDLE_LOOPS) 300 break; 301 } while (Data & DWSD_STS_DATA_BUSY); 302 303 MmioWrite32 (DWSD_CMD, MmcCmd); 304 305 ErrMask = DWSD_INT_EBE | DWSD_INT_HLE | DWSD_INT_RTO | 306 DWSD_INT_RCRC | DWSD_INT_RE; 307 ErrMask |= DWSD_INT_DCRC | DWSD_INT_DRT | DWSD_INT_SBE; 308 do { 309 MicroSecondDelay(500); 310 Data = MmioRead32 (DWSD_RINTSTS); 311 312 if (Data & ErrMask) { 313 DEBUG ((EFI_D_ERROR, "Data:%x, ErrMask:%x, TBBCNT:%x, TCBCNT:%x, BYTCNT:%x, BLKSIZ:%x\n", Data, ErrMask, MmioRead32 (DWSD_TBBCNT), MmioRead32 (DWSD_TCBCNT), MmioRead32 (DWSD_BYTCNT), MmioRead32 (DWSD_BLKSIZ))); 314 return EFI_DEVICE_ERROR; 315 } 316 if (Data & DWSD_INT_DTO) // Transfer Done 317 break; 318 } while (!(Data & DWSD_INT_CMD_DONE)); 319 MmcCmd &= 0x3f; 320 if (MmcCmd == 17) 321 MicroSecondDelay(100); 322 else if (MmcCmd != 13) 323 MicroSecondDelay(5000); 324 325 return EFI_SUCCESS; 326 } 327 328 UINTN ACmd = 0; 329 330 EFI_STATUS 331 DwSdSendCommand ( 332 IN EFI_MMC_HOST_PROTOCOL *This, 333 IN MMC_CMD MmcCmd, 334 IN UINT32 Argument 335 ) 336 { 337 UINT32 Cmd = 0; 338 EFI_STATUS Status = EFI_SUCCESS; 339 BOOLEAN Pending = FALSE; 340 UINT32 Data; 341 342 switch (MMC_GET_INDX(MmcCmd)) { 343 case MMC_INDX(0): 344 //Cmd = BIT_CMD_SEND_INIT; 345 Cmd = BIT_CMD_WAIT_PRVDATA_COMPLETE; 346 break; 347 case MMC_INDX(1): 348 Cmd = BIT_CMD_RESPONSE_EXPECT; 349 break; 350 case MMC_INDX(2): 351 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_LONG_RESPONSE | 352 BIT_CMD_CHECK_RESPONSE_CRC | BIT_CMD_WAIT_PRVDATA_COMPLETE; 353 break; 354 case MMC_INDX(3): 355 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | 356 BIT_CMD_WAIT_PRVDATA_COMPLETE; 357 break; 358 case MMC_INDX(6): 359 if (!ACmd) { 360 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | 361 BIT_CMD_DATA_EXPECTED | BIT_CMD_WAIT_PRVDATA_COMPLETE; 362 } else { 363 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | 364 BIT_CMD_WAIT_PRVDATA_COMPLETE; 365 } 366 if (!ACmd) 367 Pending = TRUE; 368 break; 369 case MMC_INDX(7): 370 if (Argument) 371 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | 372 BIT_CMD_WAIT_PRVDATA_COMPLETE; 373 else 374 Cmd = 0; 375 break; 376 case MMC_INDX(8): 377 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | 378 BIT_CMD_READ | 379 BIT_CMD_WAIT_PRVDATA_COMPLETE; 380 break; 381 case MMC_INDX(9): 382 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | 383 BIT_CMD_LONG_RESPONSE | BIT_CMD_WAIT_PRVDATA_COMPLETE; 384 break; 385 case MMC_INDX(12): 386 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | 387 BIT_CMD_STOP_ABORT_CMD; 388 break; 389 case MMC_INDX(13): 390 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC; 391 break; 392 case MMC_INDX(17): 393 case MMC_INDX(18): 394 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | 395 BIT_CMD_DATA_EXPECTED | BIT_CMD_READ | 396 BIT_CMD_WAIT_PRVDATA_COMPLETE; 397 Pending = TRUE; 398 Data = MmioRead32 (DWSD_CTRL); 399 Data |= DWSD_CTRL_FIFO_RESET; 400 MmioWrite32 (DWSD_CTRL, Data); 401 while (MmioRead32 (DWSD_CTRL) & DWSD_CTRL_FIFO_RESET) { 402 }; 403 break; 404 case MMC_INDX(24): 405 case MMC_INDX(25): 406 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | 407 BIT_CMD_DATA_EXPECTED | BIT_CMD_WRITE | 408 BIT_CMD_WAIT_PRVDATA_COMPLETE; 409 Pending = TRUE; 410 break; 411 case MMC_INDX(30): 412 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | 413 BIT_CMD_DATA_EXPECTED; 414 break; 415 case MMC_INDX(41): 416 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_WAIT_PRVDATA_COMPLETE; 417 break; 418 case MMC_INDX(51): 419 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC | 420 BIT_CMD_DATA_EXPECTED | BIT_CMD_READ | 421 BIT_CMD_WAIT_PRVDATA_COMPLETE; 422 Pending = TRUE; 423 break; 424 case MMC_INDX(55): 425 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC; 426 ACmd = 1; 427 break; 428 default: 429 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC; 430 break; 431 } 432 433 Cmd |= MMC_GET_INDX(MmcCmd) | BIT_CMD_USE_HOLD_REG | BIT_CMD_START; 434 if (Pending) { 435 mDwSdCommand = Cmd; 436 mDwSdArgument = Argument; 437 } else { 438 mDwSdCommand = 0; 439 mDwSdArgument = 0; 440 Status = SendCommand (Cmd, Argument); 441 } 442 /* Clear ACMD */ 443 if (MMC_GET_INDX(MmcCmd) != MMC_INDX(55)) 444 ACmd = 0; 445 return Status; 446 } 447 448 EFI_STATUS 449 DwSdReceiveResponse ( 450 IN EFI_MMC_HOST_PROTOCOL *This, 451 IN MMC_RESPONSE_TYPE Type, 452 IN UINT32* Buffer 453 ) 454 { 455 if (Buffer == NULL) { 456 return EFI_INVALID_PARAMETER; 457 } 458 459 if ( (Type == MMC_RESPONSE_TYPE_R1) 460 || (Type == MMC_RESPONSE_TYPE_R1b) 461 || (Type == MMC_RESPONSE_TYPE_R3) 462 || (Type == MMC_RESPONSE_TYPE_R6) 463 || (Type == MMC_RESPONSE_TYPE_R7)) 464 { 465 Buffer[0] = MmioRead32 (DWSD_RESP0); 466 } else if (Type == MMC_RESPONSE_TYPE_R2) { 467 Buffer[0] = MmioRead32 (DWSD_RESP0); 468 Buffer[1] = MmioRead32 (DWSD_RESP1); 469 Buffer[2] = MmioRead32 (DWSD_RESP2); 470 Buffer[3] = MmioRead32 (DWSD_RESP3); 471 } 472 return EFI_SUCCESS; 473 } 474 475 EFI_STATUS 476 PrepareDmaData ( 477 IN DWSD_IDMAC_DESCRIPTOR* IdmacDesc, 478 IN UINTN Length, 479 IN UINT32* Buffer 480 ) 481 { 482 UINTN Cnt, Idx, LastIdx, Blks; 483 484 if (Length % 4) { 485 DEBUG ((EFI_D_ERROR, "Length isn't aligned with 4\n")); 486 return EFI_BAD_BUFFER_SIZE; 487 } 488 if (Length < DWSD_DMA_THRESHOLD) { 489 return EFI_BUFFER_TOO_SMALL; 490 } 491 Cnt = (Length + DWSD_DMA_BUF_SIZE - 1) / DWSD_DMA_BUF_SIZE; 492 Blks = (Length + DWSD_BLOCK_SIZE - 1 ) / DWSD_BLOCK_SIZE; 493 Length = DWSD_BLOCK_SIZE * Blks; 494 495 for (Idx = 0; Idx < Cnt; Idx++) { 496 (IdmacDesc + Idx)->Des0 = DWSD_IDMAC_DES0_OWN | DWSD_IDMAC_DES0_CH | 497 DWSD_IDMAC_DES0_DIC; 498 (IdmacDesc + Idx)->Des1 = DWSD_IDMAC_DES1_BS1(DWSD_DMA_BUF_SIZE); 499 /* Buffer Address */ 500 (IdmacDesc + Idx)->Des2 = (UINT32)((UINTN)Buffer + DWSD_DMA_BUF_SIZE * Idx); 501 /* Next Descriptor Address */ 502 (IdmacDesc + Idx)->Des3 = (UINT32)((UINTN)IdmacDesc + 503 (sizeof(DWSD_IDMAC_DESCRIPTOR) * (Idx + 1))); 504 } 505 /* First Descriptor */ 506 IdmacDesc->Des0 |= DWSD_IDMAC_DES0_FS; 507 /* Last Descriptor */ 508 LastIdx = Cnt - 1; 509 (IdmacDesc + LastIdx)->Des0 |= DWSD_IDMAC_DES0_LD; 510 (IdmacDesc + LastIdx)->Des0 &= ~(DWSD_IDMAC_DES0_DIC | DWSD_IDMAC_DES0_CH); 511 (IdmacDesc + LastIdx)->Des1 = DWSD_IDMAC_DES1_BS1(Length - 512 (LastIdx * DWSD_DMA_BUF_SIZE)); 513 /* Set the Next field of Last Descriptor */ 514 (IdmacDesc + LastIdx)->Des3 = 0; 515 MmioWrite32 (DWSD_DBADDR, (UINT32)((UINTN)IdmacDesc)); 516 517 return EFI_SUCCESS; 518 } 519 520 VOID 521 StartDma ( 522 UINTN Length 523 ) 524 { 525 UINT32 Data; 526 527 Data = MmioRead32 (DWSD_CTRL); 528 Data |= DWSD_CTRL_INT_EN | DWSD_CTRL_DMA_EN | DWSD_CTRL_IDMAC_EN; 529 MmioWrite32 (DWSD_CTRL, Data); 530 Data = MmioRead32 (DWSD_BMOD); 531 Data |= DWSD_IDMAC_ENABLE | DWSD_IDMAC_FB; 532 MmioWrite32 (DWSD_BMOD, Data); 533 534 MmioWrite32 (DWSD_BLKSIZ, DWSD_BLOCK_SIZE); 535 MmioWrite32 (DWSD_BYTCNT, Length); 536 } 537 538 STATIC 539 EFI_STATUS 540 ReadFifo ( 541 IN UINTN Length, 542 IN UINT32* Buffer 543 ) 544 { 545 UINT32 Data, Received, Count; 546 547 Received = 0; 548 Count = (Length + 3) / 4; 549 while (Received < Count) { 550 Data = MmioRead32 (DWSD_RINTSTS); 551 if (Data & DWSD_INT_CMD_DONE) { 552 *(Buffer + Received) = MmioRead32 (DWSD_FIFO_START); 553 Received++; 554 } else { 555 DEBUG ((EFI_D_ERROR, "Received:%d, RINTSTS:%x\n", Received, Data)); 556 } 557 } 558 while (1) { 559 Data = MmioRead32 (DWSD_RINTSTS); 560 if (Data & DWSD_INT_DTO) 561 break; 562 } 563 /* FIXME */ 564 MicroSecondDelay (1000); 565 return EFI_SUCCESS; 566 } 567 568 EFI_STATUS 569 DwSdReadBlockData ( 570 IN EFI_MMC_HOST_PROTOCOL *This, 571 IN EFI_LBA Lba, 572 IN UINTN Length, 573 IN UINT32* Buffer 574 ) 575 { 576 EFI_STATUS Status; 577 UINT32 DescPages, CountPerPage, Count, Data; 578 EFI_TPL Tpl; 579 580 Tpl = gBS->RaiseTPL (TPL_NOTIFY); 581 582 CountPerPage = EFI_PAGE_SIZE / 16; 583 Count = (Length + DWSD_DMA_BUF_SIZE - 1) / DWSD_DMA_BUF_SIZE; 584 DescPages = (Count + CountPerPage - 1) / CountPerPage; 585 586 InvalidateDataCacheRange (Buffer, Length); 587 588 Status = PrepareDmaData (gpIdmacDesc, Length, Buffer); 589 if (EFI_ERROR (Status)) { 590 if (Status == EFI_BUFFER_TOO_SMALL) { 591 Data = MmioRead32 (DWSD_CTRL); 592 Data |= DWSD_CTRL_FIFO_RESET; 593 MmioWrite32 (DWSD_CTRL, Data); 594 while (MmioRead32 (DWSD_CTRL) & DWSD_CTRL_FIFO_RESET) { 595 }; 596 597 Status = SendCommand (mDwSdCommand, mDwSdArgument); 598 if (EFI_ERROR (Status)) { 599 DEBUG ((EFI_D_ERROR, "Failed to read data from FIFO, mDwSdCommand:%x, mDwSdArgument:%x, Status:%r\n", mDwSdCommand, mDwSdArgument, Status)); 600 goto out; 601 } 602 Status = ReadFifo (Length, Buffer); 603 } 604 goto out; 605 } else { 606 607 WriteBackDataCacheRange (gpIdmacDesc, DescPages * EFI_PAGE_SIZE); 608 StartDma (Length); 609 610 Status = SendCommand (mDwSdCommand, mDwSdArgument); 611 if (EFI_ERROR (Status)) { 612 DEBUG ((EFI_D_ERROR, "Failed to read data, mDwSdCommand:%x, mDwSdArgument:%x, Status:%r\n", mDwSdCommand, mDwSdArgument, Status)); 613 goto out; 614 } 615 616 /* Wait until data transfer finished */ 617 while (MmioRead32 (DWSD_TCBCNT) < MmioRead32 (DWSD_BYTCNT)) { 618 } 619 620 } 621 out: 622 // Restore Tpl 623 gBS->RestoreTPL (Tpl); 624 return Status; 625 } 626 627 EFI_STATUS 628 DwSdWriteBlockData ( 629 IN EFI_MMC_HOST_PROTOCOL *This, 630 IN EFI_LBA Lba, 631 IN UINTN Length, 632 IN UINT32* Buffer 633 ) 634 { 635 EFI_STATUS Status; 636 UINT32 DescPages, CountPerPage, Count; 637 EFI_TPL Tpl; 638 639 Tpl = gBS->RaiseTPL (TPL_NOTIFY); 640 641 CountPerPage = EFI_PAGE_SIZE / 16; 642 Count = (Length + DWSD_DMA_BUF_SIZE - 1) / DWSD_DMA_BUF_SIZE; 643 DescPages = (Count + CountPerPage - 1) / CountPerPage; 644 645 WriteBackDataCacheRange (Buffer, Length); 646 647 Status = PrepareDmaData (gpIdmacDesc, Length, Buffer); 648 if (EFI_ERROR (Status)) 649 goto out; 650 651 WriteBackDataCacheRange (gpIdmacDesc, DescPages * EFI_PAGE_SIZE); 652 StartDma (Length); 653 654 Status = SendCommand (mDwSdCommand, mDwSdArgument); 655 if (EFI_ERROR (Status)) { 656 DEBUG ((EFI_D_ERROR, "Failed to write data, mDwSdCommand:%x, mDwSdArgument:%x, Status:%r\n", mDwSdCommand, mDwSdArgument, Status)); 657 goto out; 658 } 659 out: 660 // Restore Tpl 661 gBS->RestoreTPL (Tpl); 662 return Status; 663 } 664 665 EFI_STATUS 666 DwSdSetIos ( 667 IN EFI_MMC_HOST_PROTOCOL *This, 668 IN UINT32 BusClockFreq, 669 IN UINT32 BusWidth, 670 IN UINT32 TimingMode 671 ) 672 { 673 EFI_STATUS Status = EFI_SUCCESS; 674 UINT32 Data; 675 676 if (TimingMode != EMMCBACKWARD) { 677 Data = MmioRead32 (DWSD_UHSREG); 678 switch (TimingMode) { 679 case EMMCHS52DDR1V2: 680 case EMMCHS52DDR1V8: 681 Data |= 1 << 16; 682 break; 683 case EMMCHS52: 684 case EMMCHS26: 685 Data &= ~(1 << 16); 686 break; 687 default: 688 return EFI_UNSUPPORTED; 689 } 690 MmioWrite32 (DWSD_UHSREG, Data); 691 } 692 693 switch (BusWidth) { 694 case 1: 695 MmioWrite32 (DWSD_CTYPE, 0); 696 break; 697 case 4: 698 MmioWrite32 (DWSD_CTYPE, 1); 699 break; 700 case 8: 701 MmioWrite32 (DWSD_CTYPE, 1 << 16); 702 break; 703 default: 704 return EFI_UNSUPPORTED; 705 } 706 if (BusClockFreq) { 707 Status = DwSdSetClock (BusClockFreq); 708 } 709 return Status; 710 } 711 712 BOOLEAN 713 DwSdIsMultiBlock ( 714 IN EFI_MMC_HOST_PROTOCOL *This 715 ) 716 { 717 return TRUE; 718 } 719 720 EFI_MMC_HOST_PROTOCOL gMciHost = { 721 MMC_HOST_PROTOCOL_REVISION, 722 DwSdIsCardPresent, 723 DwSdIsReadOnly, 724 DwSdBuildDevicePath, 725 DwSdNotifyState, 726 DwSdSendCommand, 727 DwSdReceiveResponse, 728 DwSdReadBlockData, 729 DwSdWriteBlockData, 730 DwSdSetIos, 731 DwSdIsMultiBlock 732 }; 733 734 EFI_STATUS 735 DwSdDxeInitialize ( 736 IN EFI_HANDLE ImageHandle, 737 IN EFI_SYSTEM_TABLE *SystemTable 738 ) 739 { 740 EFI_STATUS Status; 741 EFI_HANDLE Handle; 742 743 Handle = NULL; 744 745 DEBUG ((EFI_D_BLKIO, "DwSdDxeInitialize()\n")); 746 747 //Publish Component Name, BlockIO protocol interfaces 748 Status = gBS->InstallMultipleProtocolInterfaces ( 749 &Handle, 750 &gEfiMmcHostProtocolGuid, &gMciHost, 751 NULL 752 ); 753 ASSERT_EFI_ERROR (Status); 754 755 return EFI_SUCCESS; 756 } 757