1 /** @file 2 3 The SD host controller driver model and HC protocol routines. 4 5 Copyright (c) 2013-2016 Intel Corporation. 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 18 19 #include "SDController.h" 20 21 22 EFI_DRIVER_BINDING_PROTOCOL gSDControllerDriverBinding = { 23 SDControllerSupported, 24 SDControllerStart, 25 SDControllerStop, 26 0x20, 27 NULL, 28 NULL 29 }; 30 31 32 EFI_SD_HOST_IO_PROTOCOL mSDHostIo = { 33 EFI_SD_HOST_IO_PROTOCOL_REVISION_01, 34 { 35 0, // HighSpeedSupport 36 0, // V18Support 37 0, // V30Support 38 0, // V33Support 39 0, // Reserved0 40 0, // BusWidth4 41 0, // BusWidth8 42 0, // Reserved1 43 0, // Reserved1 44 (512 * 1024) //BoundarySize 45 }, 46 SendCommand, 47 SetClockFrequency, 48 SetBusWidth, 49 SetHostVoltage, 50 ResetSDHost, 51 EnableAutoStopCmd, 52 DetectCardAndInitHost, 53 SetBlockLength, 54 SetHighSpeedMode, 55 SetDDRMode 56 }; 57 58 /** 59 Find sdclk_freq_sel and upr_sdclk_freq_sel bits 60 for Clock Control Register (CLK_CTL)Offset 2Ch when using 8bit or 10bit 61 divided clock mode. 62 63 @param BaseClockFreg Base Clock Frequency in Hz For SD Clock in the 64 Capabilities register. 65 @param TargetFreq Target Frequency in Hz to reach. 66 @param Is8BitMode True if 8-bit Divided Clock Mode else 10bit mode. 67 @param Bits sdclk_freq_sel and upr_sdclk_freq_sel bits for 68 TargetFreq. 69 70 @return EFI_SUCCESS // Bits setup. 71 @return EFI_UNSUPPORTED // Cannot divide base clock to reach target clock. 72 **/ 73 EFI_STATUS 74 DividedClockModeBits ( 75 IN CONST UINTN BaseClockFreg, 76 IN CONST UINTN TargetFreq, 77 IN CONST BOOLEAN Is8BitMode, 78 OUT UINT16 *Bits 79 ) 80 { 81 UINTN N; 82 UINTN CurrFreq; 83 84 *Bits = 0; 85 CurrFreq = BaseClockFreg; 86 N = 0; 87 // 88 // N == 0 same for 8bit & 10bit mode i.e. BaseClockFreg of controller. 89 // 90 if (TargetFreq < CurrFreq) { 91 if (Is8BitMode) { 92 N = 1; 93 do { 94 // 95 // N values for 8bit mode when N > 0. 96 // Bit[15:8] SDCLK Frequency Select at offset 2Ch 97 // 80h - base clock divided by 256 98 // 40h - base clock divided by 128 99 // 20h - base clock divided by 64 100 // 10h - base clock divided by 32 101 // 08h - base clock divided by 16 102 // 04h - base clock divided by 8 103 // 02h - base clock divided by 4 104 // 01h - base clock divided by 2 105 // 106 CurrFreq = BaseClockFreg / (2 * N); 107 if (TargetFreq >= CurrFreq) { 108 break; 109 } 110 N *= 2; 111 if (N > V_MMIO_CLKCTL_MAX_8BIT_FREQ_SEL) { 112 return EFI_UNSUPPORTED; 113 } 114 } while (TRUE); 115 } else { 116 N = 1; 117 CurrFreq = BaseClockFreg / (2 * N); 118 // 119 // (try N = 0 or 1 first since don't want divide by 0). 120 // 121 if (TargetFreq < CurrFreq) { 122 // 123 // If still no match then calculate it for 10bit. 124 // N values for 10bit mode. 125 // N 1/2N Divided Clock (Duty 50%). 126 // from Spec "The length of divider is extended to 10 bits and all 127 // divider values shall be supported. 128 // 129 N = (BaseClockFreg / TargetFreq) / 2; 130 131 // 132 // Can only be N or N+1; 133 // 134 CurrFreq = BaseClockFreg / (2 * N); 135 if (TargetFreq < CurrFreq) { 136 N++; 137 CurrFreq = BaseClockFreg / (2 * N); 138 } 139 140 if (N > V_MMIO_CLKCTL_MAX_10BIT_FREQ_SEL) { 141 return EFI_UNSUPPORTED; 142 } 143 144 // 145 // Set upper bits of SDCLK Frequency Select (bits 7:6 of reg 0x2c). 146 // 147 *Bits |= ((UINT16) ((N >> 2) & B_MMIO_CLKCTL_UPR_SDCLK_FREQ_SEL_MASK)); 148 } 149 } 150 } 151 152 // 153 // Set lower bits of SDCLK Frequency Select (bits 15:8 of reg 0x2c). 154 // 155 *Bits |= ((UINT16) ((UINT8) N) << 8); 156 DEBUG ( 157 (EFI_D_INFO, 158 "SDIO:DividedClockModeBits: %dbit mode Want %dHz Got %dHz bits = %04x\r\n", 159 (Is8BitMode) ? 8 : 10, 160 TargetFreq, 161 CurrFreq, 162 (UINTN) *Bits 163 )); 164 165 return EFI_SUCCESS; 166 } 167 168 /** 169 Print type of error and command index 170 171 @param CommandIndex Command index to set the command index field of command register. 172 @param ErrorCode Error interrupt status read from host controller 173 174 @return EFI_DEVICE_ERROR 175 @return EFI_TIMEOUT 176 @return EFI_CRC_ERROR 177 178 **/ 179 EFI_STATUS 180 GetErrorReason ( 181 IN UINT16 CommandIndex, 182 IN UINT16 ErrorCode 183 ) 184 { 185 EFI_STATUS Status; 186 187 Status = EFI_DEVICE_ERROR; 188 189 DEBUG((EFI_D_ERROR, "[%2d] -- ", CommandIndex)); 190 191 if (ErrorCode & BIT0) { 192 Status = EFI_TIMEOUT; 193 DEBUG((EFI_D_ERROR, "Command Timeout Erro")); 194 } 195 196 if (ErrorCode & BIT1) { 197 Status = EFI_CRC_ERROR; 198 DEBUG((EFI_D_ERROR, "Command CRC Error")); 199 } 200 201 if (ErrorCode & BIT2) { 202 DEBUG((EFI_D_ERROR, "Command End Bit Error")); 203 } 204 205 if (ErrorCode & BIT3) { 206 DEBUG((EFI_D_ERROR, "Command Index Error")); 207 } 208 if (ErrorCode & BIT4) { 209 Status = EFI_TIMEOUT; 210 DEBUG((EFI_D_ERROR, "Data Timeout Error")); 211 } 212 213 if (ErrorCode & BIT5) { 214 Status = EFI_CRC_ERROR; 215 DEBUG((EFI_D_ERROR, "Data CRC Error")); 216 } 217 218 if (ErrorCode & BIT6) { 219 DEBUG((EFI_D_ERROR, "Data End Bit Error")); 220 } 221 222 if (ErrorCode & BIT7) { 223 DEBUG((EFI_D_ERROR, "Current Limit Error")); 224 } 225 226 if (ErrorCode & BIT8) { 227 DEBUG((EFI_D_ERROR, "Auto CMD12 Error")); 228 } 229 230 if (ErrorCode & BIT9) { 231 DEBUG((EFI_D_ERROR, "ADMA Error")); 232 } 233 234 DEBUG((EFI_D_ERROR, "\n")); 235 236 return Status; 237 } 238 /** 239 Enable/Disable High Speed transfer mode 240 241 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. 242 @param Enable TRUE to Enable, FALSE to Disable 243 244 @return EFI_SUCCESS 245 **/ 246 EFI_STATUS 247 EFIAPI 248 SetHighSpeedMode ( 249 IN EFI_SD_HOST_IO_PROTOCOL *This, 250 IN BOOLEAN Enable 251 ) 252 { 253 UINT32 Data; 254 SDHOST_DATA *SDHostData; 255 EFI_PCI_IO_PROTOCOL *PciIo; 256 257 SDHostData = SDHOST_DATA_FROM_THIS (This); 258 PciIo = SDHostData->PciIo; 259 260 PciIo->Mem.Read ( 261 PciIo, 262 EfiPciIoWidthUint8, 263 0, 264 (UINT64)MMIO_HOSTCTL, 265 1, 266 &Data 267 ); 268 269 if (Enable) { 270 if (PcdGetBool(PcdSdHciQuirkNoHiSpd)) { 271 DEBUG ((EFI_D_INFO, "SDIO: Quirk never set High Speed Enable bit\r\n")); 272 return EFI_SUCCESS; 273 } 274 DEBUG ((EFI_D_INFO, "Enable High Speed transfer mode ... \r\n")); 275 Data |= BIT2; 276 } else { 277 Data &= ~BIT2; 278 } 279 PciIo->Mem.Write ( 280 PciIo, 281 EfiPciIoWidthUint8, 282 0, 283 (UINT64)MMIO_HOSTCTL, 284 1, 285 &Data 286 ); 287 return EFI_SUCCESS; 288 } 289 EFI_STATUS 290 EFIAPI 291 SetDDRMode ( 292 IN EFI_SD_HOST_IO_PROTOCOL *This, 293 IN BOOLEAN Enable 294 ) 295 { 296 UINT16 Data; 297 SDHOST_DATA *SDHostData; 298 EFI_PCI_IO_PROTOCOL *PciIo; 299 SDHostData = SDHOST_DATA_FROM_THIS (This); 300 PciIo = SDHostData->PciIo; 301 PciIo->Mem.Read ( 302 PciIo, 303 EfiPciIoWidthUint16, 304 0, 305 (UINT64)MMIO_HOSTCTL2, 306 1, 307 &Data 308 ); 309 Data &= 0xFFF0; 310 if (Enable) { 311 Data |= 0x0004; // Enable DDR50 by default, later should enable other mode like HS200/400 312 Data |= BIT3; // Enable 1.8V Signaling 313 } 314 PciIo->Mem.Write ( 315 PciIo, 316 EfiPciIoWidthUint16, 317 0, 318 (UINT64)MMIO_HOSTCTL2, 319 1, 320 &Data 321 ); 322 return EFI_SUCCESS; 323 } 324 /** 325 Power on/off the LED associated with the slot 326 327 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. 328 @param Enable TRUE to set LED on, FALSE to set LED off 329 330 @return EFI_SUCCESS 331 **/ 332 EFI_STATUS 333 HostLEDEnable ( 334 IN EFI_SD_HOST_IO_PROTOCOL *This, 335 IN BOOLEAN Enable 336 ) 337 { 338 SDHOST_DATA *SDHostData; 339 EFI_PCI_IO_PROTOCOL *PciIo; 340 UINT32 Data; 341 342 SDHostData = SDHOST_DATA_FROM_THIS (This); 343 PciIo = SDHostData->PciIo; 344 345 PciIo->Mem.Read ( 346 PciIo, 347 EfiPciIoWidthUint8, 348 0, 349 (UINT64)MMIO_HOSTCTL, 350 1, 351 &Data 352 ); 353 354 if (Enable) { 355 // 356 //LED On 357 // 358 Data |= BIT0; 359 } else { 360 // 361 //LED Off 362 // 363 Data &= ~BIT0; 364 } 365 366 PciIo->Mem.Write ( 367 PciIo, 368 EfiPciIoWidthUint8, 369 0, 370 (UINT64)MMIO_HOSTCTL, 371 1, 372 &Data 373 ); 374 375 return EFI_SUCCESS; 376 } 377 378 379 /** 380 The main function used to send the command to the card inserted into the SD host slot. 381 It will assemble the arguments to set the command register and wait for the command 382 and transfer completed until timeout. Then it will read the response register to fill 383 the ResponseData. 384 385 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. 386 @param CommandIndex The command index to set the command index field of command register. 387 @param Argument Command argument to set the argument field of command register. 388 @param DataType TRANSFER_TYPE, indicates no data, data in or data out. 389 @param Buffer Contains the data read from / write to the device. 390 @param BufferSize The size of the buffer. 391 @param ResponseType RESPONSE_TYPE. 392 @param TimeOut Time out value in 1 ms unit. 393 @param ResponseData Depending on the ResponseType, such as CSD or card status. 394 395 @retval EFI_SUCCESS 396 @retval EFI_INVALID_PARAMETER 397 @retval EFI_OUT_OF_RESOURCES 398 @retval EFI_TIMEOUT 399 @retval EFI_DEVICE_ERROR 400 401 **/ 402 403 EFI_STATUS 404 EFIAPI 405 SendCommand ( 406 IN EFI_SD_HOST_IO_PROTOCOL *This, 407 IN UINT16 CommandIndex, 408 IN UINT32 Argument, 409 IN TRANSFER_TYPE DataType, 410 IN UINT8 *Buffer, OPTIONAL 411 IN UINT32 BufferSize, 412 IN RESPONSE_TYPE ResponseType, 413 IN UINT32 TimeOut, 414 OUT UINT32 *ResponseData OPTIONAL 415 ) 416 /*++ 417 418 Routine Description: 419 The main function used to send the command to the card inserted into the SD host 420 slot. 421 It will assemble the arguments to set the command register and wait for the command 422 and transfer completed until timeout. Then it will read the response register to fill 423 the ResponseData 424 425 Arguments: 426 This - Pointer to EFI_SD_HOST_IO_PROTOCOL 427 CommandIndex - The command index to set the command index field of command register 428 Argument - Command argument to set the argument field of command register 429 DataType - TRANSFER_TYPE, indicates no data, data in or data out 430 Buffer - Contains the data read from / write to the device 431 BufferSize - The size of the buffer 432 ResponseType - RESPONSE_TYPE 433 TimeOut - Time out value in 1 ms unit 434 ResponseData - Depending on the ResponseType, such as CSD or card status 435 436 Returns: 437 EFI_SUCCESS 438 EFI_INVALID_PARAMETER 439 EFI_OUT_OF_RESOURCES 440 EFI_TIMEOUT 441 EFI_DEVICE_ERROR 442 443 --*/ 444 { 445 EFI_STATUS Status; 446 SDHOST_DATA *SDHostData; 447 EFI_PCI_IO_PROTOCOL *PciIo; 448 UINT32 ResponseDataCount; 449 UINT32 Data; 450 UINT64 Data64; 451 UINT8 Index; 452 INTN TimeOut2; 453 BOOLEAN AutoCMD12Enable = FALSE; 454 455 456 Status = EFI_SUCCESS; 457 ResponseDataCount = 1; 458 SDHostData = SDHOST_DATA_FROM_THIS (This); 459 PciIo = SDHostData->PciIo; 460 AutoCMD12Enable = (CommandIndex & AUTO_CMD12_ENABLE) ? TRUE : FALSE; 461 CommandIndex = CommandIndex & CMD_INDEX_MASK; 462 463 if (Buffer != NULL && DataType == NoData) { 464 Status = EFI_INVALID_PARAMETER; 465 DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n")); 466 goto Exit; 467 } 468 469 if (((UINTN)Buffer & (This->HostCapability.BoundarySize - 1)) != (UINTN)NULL) { 470 Status = EFI_INVALID_PARAMETER; 471 DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n")); 472 goto Exit; 473 } 474 475 DEBUG ((EFI_D_INFO, "SendCommand: Command Index = %d \r\n", CommandIndex)); 476 // 477 TimeOut2 = 1000; // 10 ms 478 do { 479 PciIo->Mem.Read ( 480 PciIo, 481 EfiPciIoWidthUint32, 482 0, 483 (UINT64)MMIO_PSTATE, 484 1, 485 &Data 486 ); 487 gBS->Stall (10); 488 }while ((TimeOut2-- > 0) && (Data & BIT0)); 489 TimeOut2 = 1000; // 10 ms 490 do { 491 PciIo->Mem.Read ( 492 PciIo, 493 EfiPciIoWidthUint32, 494 0, 495 (UINT64)MMIO_PSTATE, 496 1, 497 &Data 498 ); 499 gBS->Stall (10); 500 }while ((TimeOut2-- > 0) && (Data & BIT1)); 501 //Clear status bits 502 // 503 Data = 0xFFFF; 504 PciIo->Mem.Write ( 505 PciIo, 506 EfiPciIoWidthUint16, 507 0, 508 (UINT64)MMIO_NINTSTS, 509 1, 510 &Data 511 ); 512 513 Data = 0xFFFF; 514 PciIo->Mem.Write ( 515 PciIo, 516 EfiPciIoWidthUint16, 517 0, 518 (UINT64)MMIO_ERINTSTS, 519 1, 520 &Data 521 ); 522 523 524 if (Buffer != NULL) { 525 PciIo->Mem.Write ( 526 PciIo, 527 EfiPciIoWidthUint32, 528 0, 529 (UINT64)MMIO_DMAADR, 530 1, 531 &Buffer 532 ); 533 534 PciIo->Mem.Read ( 535 PciIo, 536 EfiPciIoWidthUint16, 537 0, 538 (UINT64)MMIO_BLKSZ, 539 1, 540 &Data 541 ); 542 Data &= ~(0xFFF); 543 if (BufferSize <= SDHostData->BlockLength) { 544 Data |= (BufferSize | 0x7000); 545 } else { 546 Data |= (SDHostData->BlockLength | 0x7000); 547 } 548 549 550 PciIo->Mem.Write ( 551 PciIo, 552 EfiPciIoWidthUint16, 553 0, 554 (UINT64)MMIO_BLKSZ, 555 1, 556 &Data 557 ); 558 if (BufferSize <= SDHostData->BlockLength) { 559 Data = 1; 560 } else { 561 Data = BufferSize / SDHostData->BlockLength; 562 } 563 PciIo->Mem.Write ( 564 PciIo, 565 EfiPciIoWidthUint16, 566 0, 567 (UINT64)MMIO_BLKCNT, 568 1, 569 &Data 570 ); 571 572 } else { 573 Data = 0; 574 PciIo->Mem.Write ( 575 PciIo, 576 EfiPciIoWidthUint16, 577 0, 578 (UINT64)MMIO_BLKSZ, 579 1, 580 &Data 581 ); 582 PciIo->Mem.Write ( 583 PciIo, 584 EfiPciIoWidthUint16, 585 0, 586 (UINT64)MMIO_BLKCNT, 587 1, 588 &Data 589 ); 590 } 591 592 // 593 //Argument 594 // 595 Data = Argument; 596 PciIo->Mem.Write ( 597 PciIo, 598 EfiPciIoWidthUint32, 599 0, 600 (UINT64)MMIO_CMDARG, 601 1, 602 &Data 603 ); 604 605 606 PciIo->Mem.Read ( 607 PciIo, 608 EfiPciIoWidthUint16, 609 0, 610 (UINT64)MMIO_XFRMODE, 611 1, 612 &Data 613 ); 614 615 616 DEBUG ((EFI_D_INFO, "Transfer mode read = 0x%x \r\n", (Data & 0xFFFF))); 617 // 618 //BIT0 - DMA Enable 619 //BIT2 - Auto Cmd12 620 // 621 if (DataType == InData) { 622 Data |= BIT4 | BIT0; 623 } else if (DataType == OutData){ 624 Data &= ~BIT4; 625 Data |= BIT0; 626 } else { 627 Data &= ~(BIT4 | BIT0); 628 } 629 630 if (BufferSize <= SDHostData->BlockLength) { 631 Data &= ~ (BIT5 | BIT1 | BIT2); 632 Data |= BIT1; // Enable block count always 633 } else { 634 if (SDHostData->IsAutoStopCmd && AutoCMD12Enable) { 635 Data |= (BIT5 | BIT1 | BIT2); 636 } else { 637 Data |= (BIT5 | BIT1); 638 } 639 } 640 641 DEBUG ((EFI_D_INFO, "Transfer mode write = 0x%x \r\n", (Data & 0xffff))); 642 PciIo->Mem.Write ( 643 PciIo, 644 EfiPciIoWidthUint16, 645 0, 646 (UINT64)MMIO_XFRMODE, 647 1, 648 &Data 649 ); 650 // 651 //Command 652 // 653 //ResponseTypeSelect IndexCheck CRCCheck ResponseType 654 // 00 0 0 NoResponse 655 // 01 0 1 R2 656 // 10 0 0 R3, R4 657 // 10 1 1 R1, R5, R6, R7 658 // 11 1 1 R1b, R5b 659 // 660 switch (ResponseType) { 661 case ResponseNo: 662 Data = (CommandIndex << 8); 663 ResponseDataCount = 0; 664 break; 665 666 case ResponseR1: 667 case ResponseR5: 668 case ResponseR6: 669 case ResponseR7: 670 Data = (CommandIndex << 8) | BIT1 | BIT4| BIT3; 671 ResponseDataCount = 1; 672 break; 673 674 case ResponseR1b: 675 case ResponseR5b: 676 Data = (CommandIndex << 8) | BIT0 | BIT1 | BIT4| BIT3; 677 ResponseDataCount = 1; 678 break; 679 680 case ResponseR2: 681 Data = (CommandIndex << 8) | BIT0 | BIT3; 682 ResponseDataCount = 4; 683 break; 684 685 case ResponseR3: 686 case ResponseR4: 687 Data = (CommandIndex << 8) | BIT1; 688 ResponseDataCount = 1; 689 break; 690 691 default: 692 ASSERT (0); 693 Status = EFI_INVALID_PARAMETER; 694 DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n")); 695 goto Exit; 696 } 697 698 if (DataType != NoData) { 699 Data |= BIT5; 700 } 701 702 HostLEDEnable (This, TRUE); 703 704 705 PciIo->Mem.Write ( 706 PciIo, 707 EfiPciIoWidthUint16, 708 0, 709 (UINT64)MMIO_SDCMD, 710 1, 711 &Data 712 ); 713 714 715 Data = 0; 716 do { 717 PciIo->Mem.Read ( 718 PciIo, 719 EfiPciIoWidthUint16, 720 0, 721 (UINT64)MMIO_ERINTSTS, 722 1, 723 &Data 724 ); 725 726 if ((Data & 0x07FF) != 0) { 727 Status = GetErrorReason (CommandIndex, (UINT16)Data); 728 DEBUG ((EFI_D_ERROR, "SendCommand: Error happens \r\n")); 729 goto Exit; 730 } 731 732 PciIo->Mem.Read ( 733 PciIo, 734 EfiPciIoWidthUint16, 735 0, 736 (UINT64)MMIO_NINTSTS, 737 1, 738 &Data 739 ); 740 741 if ((Data & BIT0) == BIT0) { 742 // 743 //Command completed, can read response 744 // 745 if (DataType == NoData) { 746 break; 747 } else { 748 // 749 //Transfer completed 750 // 751 if ((Data & BIT1) == BIT1) { 752 break; 753 } 754 } 755 } 756 757 gBS->Stall (1 * 1000); 758 759 TimeOut --; 760 761 } while (TimeOut > 0); 762 763 if (TimeOut == 0) { 764 Status = EFI_TIMEOUT; 765 DEBUG ((EFI_D_ERROR, "SendCommand: Time out \r\n")); 766 goto Exit; 767 } 768 769 if (ResponseData != NULL) { 770 PciIo->Mem.Read ( 771 PciIo, 772 EfiPciIoWidthUint32, 773 0, 774 (UINT64)MMIO_RESP, 775 ResponseDataCount, 776 ResponseData 777 ); 778 if (ResponseType == ResponseR2) { 779 // 780 // Adjustment for R2 response 781 // 782 Data = 1; 783 for (Index = 0; Index < ResponseDataCount; Index++) { 784 Data64 = LShiftU64(*ResponseData, 8); 785 *ResponseData = (UINT32)((Data64 & 0xFFFFFFFF) | Data); 786 Data = (UINT32)RShiftU64 (Data64, 32); 787 ResponseData++; 788 } 789 } 790 } 791 792 Exit: 793 HostLEDEnable (This, FALSE); 794 return Status; 795 } 796 797 /** 798 Set max clock frequency of the host, the actual frequency may not be the same as MaxFrequency. 799 It depends on the max frequency the host can support, divider, and host speed mode. 800 801 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. 802 @param MaxFrequency Max frequency in HZ. 803 804 @retval EFI_SUCCESS 805 @retval EFI_TIMEOUT 806 807 **/ 808 EFI_STATUS 809 EFIAPI 810 SetClockFrequency ( 811 IN EFI_SD_HOST_IO_PROTOCOL *This, 812 IN UINT32 MaxFrequency 813 ) 814 { 815 UINT32 Data; 816 UINT16 FreqSelBits; 817 EFI_STATUS Status; 818 SDHOST_DATA *SDHostData; 819 EFI_PCI_IO_PROTOCOL *PciIo; 820 UINT32 TimeOutCount; 821 UINT32 Revision; 822 823 SDHostData = SDHOST_DATA_FROM_THIS (This); 824 PciIo = SDHostData->PciIo; 825 Data = 0; 826 PciIo->Mem.Write ( 827 PciIo, 828 EfiPciIoWidthUint16, 829 0, 830 (UINT64)MMIO_CLKCTL, 831 1, 832 &Data 833 ); 834 835 PciIo->Mem.Read ( 836 PciIo, 837 EfiPciIoWidthUint8, 838 0, 839 (UINT64)MMIO_CTRLRVER, 840 1, 841 &Revision 842 ); 843 Revision &= 0x000000FF; 844 845 Status = DividedClockModeBits ( 846 SDHostData->BaseClockInMHz * 1000 * 1000, 847 MaxFrequency, 848 (Revision < SDHCI_SPEC_300), 849 &FreqSelBits 850 ); 851 852 if (EFI_ERROR (Status)) { 853 // 854 // Cannot reach MaxFrequency with SDHostData->BaseClockInMHz. 855 // 856 ASSERT_EFI_ERROR (Status); 857 return Status; 858 } 859 860 Data = 0; 861 862 // 863 //Enable internal clock and Stop Clock Enable 864 // 865 Data = BIT0; 866 PciIo->Mem.Write ( 867 PciIo, 868 EfiPciIoWidthUint16, 869 0, 870 (UINT64)MMIO_CLKCTL, 871 1, 872 &Data 873 ); 874 875 TimeOutCount = TIME_OUT_1S; 876 do { 877 PciIo->Mem.Read ( 878 PciIo, 879 EfiPciIoWidthUint16, 880 0, 881 (UINT64)MMIO_CLKCTL, 882 1, 883 &Data 884 ); 885 gBS->Stall (1 * 1000); 886 TimeOutCount --; 887 if (TimeOutCount == 0) { 888 DEBUG ((EFI_D_ERROR, "SetClockFrequency: Time out \r\n")); 889 return EFI_TIMEOUT; 890 } 891 } while ((Data & BIT1) != BIT1); 892 893 DEBUG ((EFI_D_INFO, "Base Clock In MHz: %d\r\n", SDHostData->BaseClockInMHz)); 894 895 Data = (BIT0 | ((UINT32) FreqSelBits)); 896 DEBUG ((EFI_D_INFO, "Data write to MMIO_CLKCTL: 0x%04x \r\n", Data)); 897 PciIo->Mem.Write ( 898 PciIo, 899 EfiPciIoWidthUint16, 900 0, 901 (UINT64)MMIO_CLKCTL, 902 1, 903 &Data 904 ); 905 906 TimeOutCount = TIME_OUT_1S; 907 do { 908 PciIo->Mem.Read ( 909 PciIo, 910 EfiPciIoWidthUint16, 911 0, 912 (UINT64)MMIO_CLKCTL, 913 1, 914 &Data 915 ); 916 gBS->Stall (1 * 1000); 917 TimeOutCount --; 918 if (TimeOutCount == 0) { 919 DEBUG ((EFI_D_ERROR, "SetClockFrequency: Time out \r\n")); 920 return EFI_TIMEOUT; 921 } 922 } while ((Data & BIT1) != BIT1); 923 gBS->Stall (20 * 1000); 924 Data |= BIT2; 925 PciIo->Mem.Write ( 926 PciIo, 927 EfiPciIoWidthUint16, 928 0, 929 (UINT64)MMIO_CLKCTL, 930 1, 931 &Data 932 ); 933 934 return EFI_SUCCESS; 935 } 936 937 /** 938 Set bus width of the host controller 939 940 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. 941 @param BusWidth Bus width in 1, 4, 8 bits. 942 943 @retval EFI_SUCCESS 944 @retval EFI_INVALID_PARAMETER 945 946 **/ 947 EFI_STATUS 948 EFIAPI 949 SetBusWidth ( 950 IN EFI_SD_HOST_IO_PROTOCOL *This, 951 IN UINT32 BusWidth 952 ) 953 { 954 SDHOST_DATA *SDHostData; 955 EFI_PCI_IO_PROTOCOL *PciIo; 956 UINT8 Data; 957 958 SDHostData = SDHOST_DATA_FROM_THIS (This); 959 960 961 if ((BusWidth != 1) && (BusWidth != 4) && (BusWidth != 8)) { 962 DEBUG ((EFI_D_ERROR, "SetBusWidth: Invalid parameter \r\n")); 963 return EFI_INVALID_PARAMETER; 964 } 965 966 if ((SDHostData->SDHostIo.HostCapability.BusWidth8 == FALSE) && (BusWidth == 8)) { 967 DEBUG ((EFI_D_ERROR, "SetBusWidth: Invalid parameter \r\n")); 968 return EFI_INVALID_PARAMETER; 969 } 970 971 PciIo = SDHostData->PciIo; 972 973 PciIo->Mem.Read ( 974 PciIo, 975 EfiPciIoWidthUint8, 976 0, 977 (UINT64)MMIO_HOSTCTL, 978 1, 979 &Data 980 ); 981 // 982 // BIT5 8-bit MMC Support (MMC8): 983 // If set, IOH supports 8-bit MMC. When cleared, IOH does not support this feature 984 // 985 if (BusWidth == 8) { 986 DEBUG ((EFI_D_INFO, "Bus Width is 8-bit ... \r\n")); 987 Data |= BIT5; 988 } else if (BusWidth == 4) { 989 DEBUG ((EFI_D_INFO, "Bus Width is 4-bit ... \r\n")); 990 Data &= ~BIT5; 991 Data |= BIT1; 992 } else { 993 DEBUG ((EFI_D_INFO, "Bus Width is 1-bit ... \r\n")); 994 Data &= ~BIT5; 995 Data &= ~BIT1; 996 } 997 998 PciIo->Mem.Write ( 999 PciIo, 1000 EfiPciIoWidthUint8, 1001 0, 1002 (UINT64)MMIO_HOSTCTL, 1003 1, 1004 &Data 1005 ); 1006 1007 return EFI_SUCCESS; 1008 } 1009 1010 1011 /** 1012 Set voltage which could supported by the host controller. 1013 Support 0(Power off the host), 1.8V, 3.0V, 3.3V 1014 1015 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. 1016 @param Voltage Units in 0.1 V. 1017 1018 @retval EFI_SUCCESS 1019 @retval EFI_INVALID_PARAMETER 1020 1021 **/ 1022 EFI_STATUS 1023 EFIAPI 1024 SetHostVoltage ( 1025 IN EFI_SD_HOST_IO_PROTOCOL *This, 1026 IN UINT32 Voltage 1027 ) 1028 { 1029 SDHOST_DATA *SDHostData; 1030 EFI_PCI_IO_PROTOCOL *PciIo; 1031 UINT8 Data; 1032 EFI_STATUS Status; 1033 1034 SDHostData = SDHOST_DATA_FROM_THIS (This); 1035 PciIo = SDHostData->PciIo; 1036 Status = EFI_SUCCESS; 1037 1038 PciIo->Mem.Read ( 1039 PciIo, 1040 EfiPciIoWidthUint8, 1041 0, 1042 (UINT64)MMIO_PWRCTL, 1043 1, 1044 &Data 1045 ); 1046 1047 if (Voltage == 0) { 1048 // 1049 //Power Off the host 1050 // 1051 Data &= ~BIT0; 1052 } else if (Voltage <= 18 && This->HostCapability.V18Support) { 1053 // 1054 //1.8V 1055 // 1056 Data |= (BIT1 | BIT3 | BIT0); 1057 } else if (Voltage > 18 && Voltage <= 30 && This->HostCapability.V30Support) { 1058 // 1059 //3.0V 1060 // 1061 Data |= (BIT2 | BIT3 | BIT0); 1062 } else if (Voltage > 30 && Voltage <= 33 && This->HostCapability.V33Support) { 1063 // 1064 //3.3V 1065 // 1066 Data |= (BIT1 | BIT2 | BIT3 | BIT0); 1067 } else { 1068 Status = EFI_UNSUPPORTED; 1069 goto Exit; 1070 } 1071 1072 PciIo->Mem.Write ( 1073 PciIo, 1074 EfiPciIoWidthUint8, 1075 0, 1076 (UINT64)MMIO_PWRCTL, 1077 1, 1078 &Data 1079 ); 1080 gBS->Stall (10 * 1000); 1081 1082 Exit: 1083 return Status; 1084 } 1085 1086 1087 1088 /** 1089 Reset the host controller. 1090 1091 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. 1092 @param ResetAll TRUE to reset all. 1093 1094 @retval EFI_SUCCESS 1095 @retval EFI_TIMEOUT 1096 1097 **/ 1098 EFI_STATUS 1099 EFIAPI 1100 ResetSDHost ( 1101 IN EFI_SD_HOST_IO_PROTOCOL *This, 1102 IN RESET_TYPE ResetType 1103 ) 1104 { 1105 SDHOST_DATA *SDHostData; 1106 EFI_PCI_IO_PROTOCOL *PciIo; 1107 UINT32 Data; 1108 UINT16 ErrStatus; 1109 UINT32 Mask; 1110 UINT32 TimeOutCount; 1111 UINT16 SaveClkCtl; 1112 UINT16 ZeroClkCtl; 1113 1114 SDHostData = SDHOST_DATA_FROM_THIS (This); 1115 PciIo = SDHostData->PciIo; 1116 Mask = 0; 1117 ErrStatus = 0; 1118 1119 if (ResetType == Reset_Auto) { 1120 PciIo->Mem.Read ( 1121 PciIo, 1122 EfiPciIoWidthUint16, 1123 0, 1124 (UINT64)MMIO_ERINTSTS, 1125 1, 1126 &ErrStatus 1127 ); 1128 if ((ErrStatus & 0xF) != 0) { 1129 // 1130 //Command Line 1131 // 1132 Mask |= BIT1; 1133 } 1134 if ((ErrStatus & 0x70) != 0) { 1135 // 1136 //Data Line 1137 // 1138 Mask |= BIT2; 1139 } 1140 } 1141 1142 1143 if (ResetType == Reset_DAT || ResetType == Reset_DAT_CMD) { 1144 Mask |= BIT2; 1145 } 1146 if (ResetType == Reset_CMD || ResetType == Reset_DAT_CMD) { 1147 Mask |= BIT1; 1148 } 1149 if (ResetType == Reset_All) { 1150 Mask = BIT0; 1151 } 1152 1153 if (Mask == 0) { 1154 return EFI_SUCCESS; 1155 } 1156 1157 // 1158 // To improve SD stability, we zero the MMIO_CLKCTL register and 1159 // stall for 50 microseconds before resetting the controller. We 1160 // restore the register setting following the reset operation. 1161 // 1162 PciIo->Mem.Read ( 1163 PciIo, 1164 EfiPciIoWidthUint16, 1165 0, 1166 (UINT64)MMIO_CLKCTL, 1167 1, 1168 &SaveClkCtl 1169 ); 1170 1171 ZeroClkCtl = (UINT16) 0; 1172 PciIo->Mem.Write ( 1173 PciIo, 1174 EfiPciIoWidthUint16, 1175 0, 1176 (UINT64)MMIO_CLKCTL, 1177 1, 1178 &ZeroClkCtl 1179 ); 1180 1181 gBS->Stall (50); 1182 1183 // 1184 // Reset the SD host controller 1185 // 1186 PciIo->Mem.Write ( 1187 PciIo, 1188 EfiPciIoWidthUint8, 1189 0, 1190 (UINT64)MMIO_SWRST, 1191 1, 1192 &Mask 1193 ); 1194 1195 Data = 0; 1196 TimeOutCount = TIME_OUT_1S; 1197 do { 1198 1199 gBS->Stall (1 * 1000); 1200 1201 TimeOutCount --; 1202 1203 PciIo->Mem.Read ( 1204 PciIo, 1205 EfiPciIoWidthUint8, 1206 0, 1207 (UINT64)MMIO_SWRST, 1208 1, 1209 &Data 1210 ); 1211 if ((Data & Mask) == 0) { 1212 break; 1213 } 1214 } while (TimeOutCount > 0); 1215 1216 // 1217 // We now restore the MMIO_CLKCTL register which we set to 0 above. 1218 // 1219 PciIo->Mem.Write ( 1220 PciIo, 1221 EfiPciIoWidthUint16, 1222 0, 1223 (UINT64)MMIO_CLKCTL, 1224 1, 1225 &SaveClkCtl 1226 ); 1227 1228 if (TimeOutCount == 0) { 1229 DEBUG ((EFI_D_ERROR, "ResetSDHost: Time out \r\n")); 1230 return EFI_TIMEOUT; 1231 } 1232 1233 return EFI_SUCCESS; 1234 } 1235 1236 1237 /** 1238 Enable auto stop on the host controller. 1239 1240 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. 1241 @param Enable TRUE to enable, FALSE to disable. 1242 1243 @retval EFI_SUCCESS 1244 @retval EFI_TIMEOUT 1245 1246 **/ 1247 EFI_STATUS 1248 EFIAPI 1249 EnableAutoStopCmd ( 1250 IN EFI_SD_HOST_IO_PROTOCOL *This, 1251 IN BOOLEAN Enable 1252 ) 1253 { 1254 SDHOST_DATA *SDHostData; 1255 1256 SDHostData = SDHOST_DATA_FROM_THIS (This); 1257 1258 SDHostData->IsAutoStopCmd = Enable; 1259 1260 return EFI_SUCCESS; 1261 } 1262 1263 /** 1264 Set the Block length on the host controller. 1265 1266 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. 1267 @param BlockLength card supportes block length. 1268 1269 @retval EFI_SUCCESS 1270 @retval EFI_TIMEOUT 1271 1272 **/ 1273 EFI_STATUS 1274 EFIAPI 1275 SetBlockLength ( 1276 IN EFI_SD_HOST_IO_PROTOCOL *This, 1277 IN UINT32 BlockLength 1278 ) 1279 { 1280 SDHOST_DATA *SDHostData; 1281 1282 SDHostData = SDHOST_DATA_FROM_THIS (This); 1283 1284 DEBUG ((EFI_D_INFO, "Block length on the host controller: %d \r\n", BlockLength)); 1285 SDHostData->BlockLength = BlockLength; 1286 1287 return EFI_SUCCESS; 1288 } 1289 1290 1291 /** 1292 Find whether these is a card inserted into the slot. If so init the host. 1293 If not, return EFI_NOT_FOUND. 1294 1295 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. 1296 1297 @retval EFI_SUCCESS 1298 @retval EFI_NOT_FOUND 1299 1300 **/ 1301 EFI_STATUS 1302 EFIAPI 1303 DetectCardAndInitHost ( 1304 IN EFI_SD_HOST_IO_PROTOCOL *This 1305 ) 1306 { 1307 SDHOST_DATA *SDHostData; 1308 EFI_PCI_IO_PROTOCOL *PciIo; 1309 UINT32 Data; 1310 EFI_STATUS Status; 1311 UINT8 Voltages[] = { 33, 30, 18 }; 1312 UINTN Loop; 1313 1314 SDHostData = SDHOST_DATA_FROM_THIS (This); 1315 PciIo = SDHostData->PciIo; 1316 Status = EFI_NOT_FOUND; 1317 1318 Data = 0; 1319 PciIo->Mem.Read ( 1320 PciIo, 1321 EfiPciIoWidthUint32, 1322 0, 1323 (UINT64)MMIO_PSTATE, 1324 1, 1325 &Data 1326 ); 1327 1328 if ((Data & (BIT16 | BIT17 | BIT18)) != (BIT16 | BIT17 | BIT18)) { 1329 // 1330 // Has no card inserted 1331 // 1332 DEBUG ((EFI_D_INFO, "DetectCardAndInitHost: No Cards \r\n")); 1333 Status = EFI_NOT_FOUND; 1334 goto Exit; 1335 } 1336 DEBUG ((EFI_D_INFO, "DetectCardAndInitHost: Find Cards \r\n")); 1337 1338 Status = EFI_NOT_FOUND; 1339 for (Loop = 0; Loop < sizeof (Voltages); Loop++) { 1340 DEBUG (( 1341 EFI_D_INFO, 1342 "DetectCardAndInitHost: SetHostVoltage %d.%dV \r\n", 1343 Voltages[Loop] / 10, 1344 Voltages[Loop] % 10 1345 )); 1346 Status = SetHostVoltage (This, Voltages[Loop]); 1347 if (EFI_ERROR (Status)) { 1348 DEBUG ((EFI_D_INFO, "DetectCardAndInitHost set voltages: [failed]\n")); 1349 } else { 1350 DEBUG ((EFI_D_INFO, "DetectCardAndInitHost set voltages: [success]\n")); 1351 break; 1352 } 1353 } 1354 if (EFI_ERROR (Status)) { 1355 DEBUG ((EFI_D_ERROR, "DetectCardAndInitHost: Fail to set voltage \r\n")); 1356 goto Exit; 1357 } 1358 1359 Status = SetClockFrequency (This, FREQUENCY_OD); 1360 if (EFI_ERROR (Status)) { 1361 DEBUG ((EFI_D_ERROR, "DetectCardAndInitHost: Fail to set frequency \r\n")); 1362 goto Exit; 1363 } 1364 SetBusWidth (This, 1); 1365 1366 // 1367 //Enable normal status change 1368 // 1369 1370 Data = (BIT0 | BIT1); 1371 1372 PciIo->Mem.Write ( 1373 PciIo, 1374 EfiPciIoWidthUint16, 1375 0, 1376 (UINT64)MMIO_NINTEN, 1377 1, 1378 &Data 1379 ); 1380 1381 // 1382 //Enable error status change 1383 // 1384 PciIo->Mem.Read ( 1385 PciIo, 1386 EfiPciIoWidthUint16, 1387 0, 1388 (UINT64)MMIO_ERINTEN, 1389 1, 1390 &Data 1391 ); 1392 1393 Data |= (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7 | BIT8); 1394 1395 PciIo->Mem.Write ( 1396 PciIo, 1397 EfiPciIoWidthUint16, 1398 0, 1399 (UINT64)MMIO_ERINTEN, 1400 1, 1401 &Data 1402 ); 1403 1404 // 1405 //Data transfer Timeout control 1406 // 1407 Data = 0x0E; 1408 1409 PciIo->Mem.Write ( 1410 PciIo, 1411 EfiPciIoWidthUint8, 1412 0, 1413 (UINT64)MMIO_TOCTL, 1414 1, 1415 &Data 1416 ); 1417 // 1418 //Set Default Bus width as 1 bit 1419 // 1420 1421 Exit: 1422 return Status; 1423 1424 } 1425 1426 /** 1427 Entry point for EFI drivers. 1428 1429 @param ImageHandle EFI_HANDLE. 1430 @param SystemTable EFI_SYSTEM_TABLE. 1431 1432 @retval EFI_SUCCESS Driver is successfully loaded. 1433 @return Others Failed. 1434 1435 **/ 1436 EFI_STATUS 1437 EFIAPI 1438 InitializeSDController ( 1439 IN EFI_HANDLE ImageHandle, 1440 IN EFI_SYSTEM_TABLE *SystemTable 1441 ) 1442 { 1443 return EfiLibInstallDriverBindingComponentName2 ( 1444 ImageHandle, 1445 SystemTable, 1446 &gSDControllerDriverBinding, 1447 ImageHandle, 1448 &gSDControllerName, 1449 &gSDControllerName2 1450 ); 1451 } 1452 1453 1454 /** 1455 Test to see if this driver supports ControllerHandle. Any 1456 ControllerHandle that has SDHostIoProtocol installed will be supported. 1457 1458 @param This Protocol instance pointer. 1459 @param Controller Handle of device to test. 1460 @param RemainingDevicePath Not used. 1461 1462 @return EFI_SUCCESS This driver supports this device. 1463 @return EFI_UNSUPPORTED This driver does not support this device. 1464 1465 **/ 1466 EFI_STATUS 1467 EFIAPI 1468 SDControllerSupported ( 1469 IN EFI_DRIVER_BINDING_PROTOCOL *This, 1470 IN EFI_HANDLE Controller, 1471 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 1472 ) 1473 { 1474 EFI_STATUS OpenStatus; 1475 EFI_STATUS Status; 1476 EFI_PCI_IO_PROTOCOL *PciIo; 1477 PCI_CLASSC PciClass; 1478 EFI_SD_HOST_IO_PROTOCOL *SdHostIo; 1479 Status = gBS->OpenProtocol ( 1480 Controller, 1481 &gEfiSDHostIoProtocolGuid, 1482 (VOID **)&SdHostIo, 1483 This->DriverBindingHandle, 1484 Controller, 1485 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1486 ); 1487 if (!EFI_ERROR (Status)) { 1488 DEBUG (( DEBUG_INFO, "SdHost controller is already started\n")); 1489 return EFI_ALREADY_STARTED; 1490 } 1491 1492 // 1493 // Test whether there is PCI IO Protocol attached on the controller handle. 1494 // 1495 OpenStatus = gBS->OpenProtocol ( 1496 Controller, 1497 &gEfiPciIoProtocolGuid, 1498 (VOID **) &PciIo, 1499 This->DriverBindingHandle, 1500 Controller, 1501 EFI_OPEN_PROTOCOL_BY_DRIVER 1502 ); 1503 1504 if (EFI_ERROR (OpenStatus)) { 1505 return OpenStatus; 1506 } 1507 1508 Status = PciIo->Pci.Read ( 1509 PciIo, 1510 EfiPciIoWidthUint8, 1511 PCI_CLASSCODE_OFFSET, 1512 sizeof (PCI_CLASSC) / sizeof (UINT8), 1513 &PciClass 1514 ); 1515 1516 if (EFI_ERROR (Status)) { 1517 Status = EFI_UNSUPPORTED; 1518 goto ON_EXIT; 1519 } 1520 1521 // 1522 // Test whether the controller belongs to SD type 1523 // 1524 if ((PciClass.BaseCode != PCI_CLASS_SYSTEM_PERIPHERAL) || 1525 (PciClass.SubClassCode != PCI_SUBCLASS_SD_HOST_CONTROLLER) || 1526 ((PciClass.PI != PCI_IF_STANDARD_HOST_NO_DMA) && (PciClass.PI != PCI_IF_STANDARD_HOST_SUPPORT_DMA)) 1527 ) { 1528 1529 Status = EFI_UNSUPPORTED; 1530 } 1531 1532 ON_EXIT: 1533 gBS->CloseProtocol ( 1534 Controller, 1535 &gEfiPciIoProtocolGuid, 1536 This->DriverBindingHandle, 1537 Controller 1538 ); 1539 1540 return Status; 1541 } 1542 /** 1543 Starting the SD Host Controller Driver. 1544 1545 @param This Protocol instance pointer. 1546 @param Controller Handle of device to test. 1547 @param RemainingDevicePath Not used. 1548 1549 @retval EFI_SUCCESS This driver supports this device. 1550 @retval EFI_UNSUPPORTED This driver does not support this device. 1551 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error. 1552 EFI_OUT_OF_RESOURCES- Failed due to resource shortage. 1553 1554 **/ 1555 EFI_STATUS 1556 EFIAPI 1557 SDControllerStart ( 1558 IN EFI_DRIVER_BINDING_PROTOCOL *This, 1559 IN EFI_HANDLE Controller, 1560 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 1561 ) 1562 { 1563 EFI_STATUS Status; 1564 EFI_PCI_IO_PROTOCOL *PciIo; 1565 SDHOST_DATA *SDHostData; 1566 UINT32 Data; 1567 1568 1569 SDHostData = NULL; 1570 Data = 0; 1571 1572 // 1573 // Open PCI I/O Protocol and save pointer to open protocol 1574 // in private data area. 1575 // 1576 Status = gBS->OpenProtocol ( 1577 Controller, 1578 &gEfiPciIoProtocolGuid, 1579 (VOID **) &PciIo, 1580 This->DriverBindingHandle, 1581 Controller, 1582 EFI_OPEN_PROTOCOL_BY_DRIVER 1583 ); 1584 1585 if (EFI_ERROR (Status)) { 1586 goto Exit; 1587 } 1588 1589 // 1590 // Enable the SD Host Controller MMIO space 1591 // 1592 Status = PciIo->Attributes ( 1593 PciIo, 1594 EfiPciIoAttributeOperationEnable, 1595 EFI_PCI_DEVICE_ENABLE, 1596 NULL 1597 ); 1598 if (EFI_ERROR (Status)) { 1599 Status = EFI_OUT_OF_RESOURCES; 1600 goto Exit; 1601 } 1602 1603 1604 SDHostData = (SDHOST_DATA*)AllocateZeroPool(sizeof (SDHOST_DATA)); 1605 if (SDHostData == NULL) { 1606 Status = EFI_OUT_OF_RESOURCES; 1607 goto Exit; 1608 } 1609 1610 SDHostData->Signature = SDHOST_DATA_SIGNATURE; 1611 SDHostData->PciIo = PciIo; 1612 1613 CopyMem (&SDHostData->SDHostIo, &mSDHostIo, sizeof (EFI_SD_HOST_IO_PROTOCOL)); 1614 1615 ResetSDHost (&SDHostData->SDHostIo, Reset_All); 1616 1617 PciIo->Mem.Read ( 1618 PciIo, 1619 EfiPciIoWidthUint16, 1620 0, 1621 (UINT64)MMIO_CTRLRVER, 1622 1, 1623 &Data 1624 ); 1625 SDHostData->SDHostIo.HostCapability.HostVersion = Data & 0xFF; 1626 DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: HostVersion 0x%x \r\n", SDHostData->SDHostIo.HostCapability.HostVersion)); 1627 1628 PciIo->Mem.Read ( 1629 PciIo, 1630 EfiPciIoWidthUint32, 1631 0, 1632 (UINT64)MMIO_CAP, 1633 1, 1634 &Data 1635 ); 1636 DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: MMIO_CAP 0x%x \r\n", Data)); 1637 if ((Data & BIT18) != 0) { 1638 SDHostData->SDHostIo.HostCapability.BusWidth8 = TRUE; 1639 } 1640 1641 if ((Data & BIT21) != 0) { 1642 SDHostData->SDHostIo.HostCapability.HighSpeedSupport = TRUE; 1643 } 1644 1645 if ((Data & BIT24) != 0) { 1646 SDHostData->SDHostIo.HostCapability.V33Support = TRUE; 1647 } 1648 1649 if ((Data & BIT25) != 0) { 1650 SDHostData->SDHostIo.HostCapability.V30Support = TRUE; 1651 } 1652 1653 if ((Data & BIT26) != 0) { 1654 SDHostData->SDHostIo.HostCapability.V18Support = TRUE; 1655 } 1656 1657 SDHostData->SDHostIo.HostCapability.BusWidth4 = TRUE; 1658 1659 if(SDHostData->SDHostIo.HostCapability.HostVersion < SDHCI_SPEC_300) { 1660 1661 1662 1663 SDHostData->BaseClockInMHz = (Data >> 8) & 0x3F; 1664 } 1665 else { 1666 SDHostData->BaseClockInMHz = (Data >> 8) & 0xFF; 1667 1668 } 1669 1670 SDHostData->BlockLength = 512 << ((Data >> 16) & 0x03); 1671 DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: BlockLength 0x%x \r\n", SDHostData->BlockLength)); 1672 SDHostData->IsAutoStopCmd = TRUE; 1673 1674 Status = gBS->InstallProtocolInterface ( 1675 &Controller, 1676 &gEfiSDHostIoProtocolGuid, 1677 EFI_NATIVE_INTERFACE, 1678 &SDHostData->SDHostIo 1679 ); 1680 if (EFI_ERROR (Status)) { 1681 goto Exit; 1682 } 1683 1684 // 1685 // Install the component name protocol 1686 // 1687 SDHostData->ControllerNameTable = NULL; 1688 1689 AddUnicodeString2 ( 1690 "eng", 1691 gSDControllerName.SupportedLanguages, 1692 &SDHostData->ControllerNameTable, 1693 L"SD Host Controller", 1694 TRUE 1695 ); 1696 AddUnicodeString2 ( 1697 "en", 1698 gSDControllerName2.SupportedLanguages, 1699 &SDHostData->ControllerNameTable, 1700 L"SD Host Controller", 1701 FALSE 1702 ); 1703 1704 Exit: 1705 if (EFI_ERROR (Status)) { 1706 if (SDHostData != NULL) { 1707 FreePool (SDHostData); 1708 } 1709 } 1710 1711 return Status; 1712 } 1713 1714 1715 /** 1716 Stop this driver on ControllerHandle. Support stopping any child handles 1717 created by this driver. 1718 1719 @param This Protocol instance pointer. 1720 @param Controller Handle of device to stop driver on. 1721 @param NumberOfChildren Number of Children in the ChildHandleBuffer. 1722 @param ChildHandleBuffer List of handles for the children we need to stop. 1723 1724 @return EFI_SUCCESS 1725 @return others 1726 1727 **/ 1728 EFI_STATUS 1729 EFIAPI 1730 SDControllerStop ( 1731 IN EFI_DRIVER_BINDING_PROTOCOL *This, 1732 IN EFI_HANDLE Controller, 1733 IN UINTN NumberOfChildren, 1734 IN EFI_HANDLE *ChildHandleBuffer 1735 ) 1736 { 1737 EFI_STATUS Status; 1738 EFI_SD_HOST_IO_PROTOCOL *SDHostIo; 1739 SDHOST_DATA *SDHostData; 1740 1741 Status = gBS->OpenProtocol ( 1742 Controller, 1743 &gEfiSDHostIoProtocolGuid, 1744 (VOID **) &SDHostIo, 1745 This->DriverBindingHandle, 1746 Controller, 1747 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1748 ); 1749 1750 // 1751 // Test whether the Controller handler passed in is a valid 1752 // Usb controller handle that should be supported, if not, 1753 // return the error status directly 1754 // 1755 if (EFI_ERROR (Status)) { 1756 return Status; 1757 } 1758 1759 SetHostVoltage (SDHostIo, 0); 1760 1761 SDHostData = SDHOST_DATA_FROM_THIS(SDHostIo); 1762 1763 // 1764 // Uninstall Block I/O protocol from the device handle 1765 // 1766 Status = gBS->UninstallProtocolInterface ( 1767 Controller, 1768 &gEfiSDHostIoProtocolGuid, 1769 SDHostIo 1770 ); 1771 if (EFI_ERROR (Status)) { 1772 return Status; 1773 } 1774 1775 FreeUnicodeStringTable (SDHostData->ControllerNameTable); 1776 1777 FreePool (SDHostData); 1778 1779 gBS->CloseProtocol ( 1780 Controller, 1781 &gEfiPciIoProtocolGuid, 1782 This->DriverBindingHandle, 1783 Controller 1784 ); 1785 1786 return EFI_SUCCESS; 1787 } 1788 1789 1790 1791