TianoCore EDK2 master
Loading...
Searching...
No Matches
SdHci.c
Go to the documentation of this file.
1
8#include "SdBlockIoPei.h"
9
29EFIAPI
31 IN UINTN Address,
32 IN BOOLEAN Read,
33 IN UINT8 Count,
34 IN OUT VOID *Data
35 )
36{
37 if ((Address == 0) || (Data == NULL)) {
38 return EFI_INVALID_PARAMETER;
39 }
40
41 if ((Count != 1) && (Count != 2) && (Count != 4) && (Count != 8)) {
42 return EFI_INVALID_PARAMETER;
43 }
44
45 switch (Count) {
46 case 1:
47 if (Read) {
48 *(UINT8 *)Data = MmioRead8 (Address);
49 } else {
50 MmioWrite8 (Address, *(UINT8 *)Data);
51 }
52
53 break;
54 case 2:
55 if (Read) {
56 *(UINT16 *)Data = MmioRead16 (Address);
57 } else {
58 MmioWrite16 (Address, *(UINT16 *)Data);
59 }
60
61 break;
62 case 4:
63 if (Read) {
64 *(UINT32 *)Data = MmioRead32 (Address);
65 } else {
66 MmioWrite32 (Address, *(UINT32 *)Data);
67 }
68
69 break;
70 case 8:
71 if (Read) {
72 *(UINT64 *)Data = MmioRead64 (Address);
73 } else {
74 MmioWrite64 (Address, *(UINT64 *)Data);
75 }
76
77 break;
78 default:
79 ASSERT (FALSE);
80 return EFI_INVALID_PARAMETER;
81 }
82
83 return EFI_SUCCESS;
84}
85
103EFIAPI
105 IN UINTN Address,
106 IN UINT8 Count,
107 IN VOID *OrData
108 )
109{
110 EFI_STATUS Status;
111 UINT64 Data;
112 UINT64 Or;
113
114 Status = SdPeimHcRwMmio (Address, TRUE, Count, &Data);
115 if (EFI_ERROR (Status)) {
116 return Status;
117 }
118
119 if (Count == 1) {
120 Or = *(UINT8 *)OrData;
121 } else if (Count == 2) {
122 Or = *(UINT16 *)OrData;
123 } else if (Count == 4) {
124 Or = *(UINT32 *)OrData;
125 } else if (Count == 8) {
126 Or = *(UINT64 *)OrData;
127 } else {
128 return EFI_INVALID_PARAMETER;
129 }
130
131 Data |= Or;
132 Status = SdPeimHcRwMmio (Address, FALSE, Count, &Data);
133
134 return Status;
135}
136
154EFIAPI
156 IN UINTN Address,
157 IN UINT8 Count,
158 IN VOID *AndData
159 )
160{
161 EFI_STATUS Status;
162 UINT64 Data;
163 UINT64 And;
164
165 Status = SdPeimHcRwMmio (Address, TRUE, Count, &Data);
166 if (EFI_ERROR (Status)) {
167 return Status;
168 }
169
170 if (Count == 1) {
171 And = *(UINT8 *)AndData;
172 } else if (Count == 2) {
173 And = *(UINT16 *)AndData;
174 } else if (Count == 4) {
175 And = *(UINT32 *)AndData;
176 } else if (Count == 8) {
177 And = *(UINT64 *)AndData;
178 } else {
179 return EFI_INVALID_PARAMETER;
180 }
181
182 Data &= And;
183 Status = SdPeimHcRwMmio (Address, FALSE, Count, &Data);
184
185 return Status;
186}
187
203EFIAPI
205 IN UINTN Address,
206 IN UINT8 Count,
207 IN UINT64 MaskValue,
208 IN UINT64 TestValue
209 )
210{
211 EFI_STATUS Status;
212 UINT64 Value;
213
214 //
215 // Access PCI MMIO space to see if the value is the tested one.
216 //
217 Value = 0;
218 Status = SdPeimHcRwMmio (Address, TRUE, Count, &Value);
219 if (EFI_ERROR (Status)) {
220 return Status;
221 }
222
223 Value &= MaskValue;
224
225 if (Value == TestValue) {
226 return EFI_SUCCESS;
227 }
228
229 return EFI_NOT_READY;
230}
231
250EFIAPI
252 IN UINTN Address,
253 IN UINT8 Count,
254 IN UINT64 MaskValue,
255 IN UINT64 TestValue,
256 IN UINT64 Timeout
257 )
258{
259 EFI_STATUS Status;
260 BOOLEAN InfiniteWait;
261
262 if (Timeout == 0) {
263 InfiniteWait = TRUE;
264 } else {
265 InfiniteWait = FALSE;
266 }
267
268 while (InfiniteWait || (Timeout > 0)) {
269 Status = SdPeimHcCheckMmioSet (
270 Address,
271 Count,
272 MaskValue,
273 TestValue
274 );
275 if (Status != EFI_NOT_READY) {
276 return Status;
277 }
278
279 //
280 // Stall for 1 microsecond.
281 //
283
284 Timeout--;
285 }
286
287 return EFI_TIMEOUT;
288}
289
301 IN UINTN Bar
302 )
303{
304 EFI_STATUS Status;
305 UINT8 SwReset;
306
307 SwReset = 0xFF;
308 Status = SdPeimHcRwMmio (Bar + SD_HC_SW_RST, FALSE, sizeof (SwReset), &SwReset);
309
310 if (EFI_ERROR (Status)) {
311 DEBUG ((DEBUG_ERROR, "SdPeimHcReset: write full 1 fails: %r\n", Status));
312 return Status;
313 }
314
315 Status = SdPeimHcWaitMmioSet (
316 Bar + SD_HC_SW_RST,
317 sizeof (SwReset),
318 0xFF,
319 0x00,
320 SD_TIMEOUT
321 );
322 if (EFI_ERROR (Status)) {
323 DEBUG ((DEBUG_INFO, "SdPeimHcReset: reset done with %r\n", Status));
324 return Status;
325 }
326
327 //
328 // Enable all interrupt after reset all.
329 //
330 Status = SdPeimHcEnableInterrupt (Bar);
331
332 return Status;
333}
334
347 IN UINTN Bar
348 )
349{
350 EFI_STATUS Status;
351 UINT16 IntStatus;
352
353 //
354 // Enable all bits in Error Interrupt Status Enable Register
355 //
356 IntStatus = 0xFFFF;
357 Status = SdPeimHcRwMmio (Bar + SD_HC_ERR_INT_STS_EN, FALSE, sizeof (IntStatus), &IntStatus);
358 if (EFI_ERROR (Status)) {
359 return Status;
360 }
361
362 //
363 // Enable all bits in Normal Interrupt Status Enable Register
364 //
365 IntStatus = 0xFFFF;
366 Status = SdPeimHcRwMmio (Bar + SD_HC_NOR_INT_STS_EN, FALSE, sizeof (IntStatus), &IntStatus);
367
368 return Status;
369}
370
383 IN UINTN Bar,
384 OUT SD_HC_SLOT_CAP *Capability
385 )
386{
387 EFI_STATUS Status;
388 UINT64 Cap;
389
390 Status = SdPeimHcRwMmio (Bar + SD_HC_CAP, TRUE, sizeof (Cap), &Cap);
391 if (EFI_ERROR (Status)) {
392 return Status;
393 }
394
395 CopyMem (Capability, &Cap, sizeof (Cap));
396
397 return EFI_SUCCESS;
398}
399
415 IN UINTN Bar
416 )
417{
418 EFI_STATUS Status;
419 UINT16 Data;
420 UINT32 PresentState;
421
422 //
423 // Check Normal Interrupt Status Register
424 //
425 Status = SdPeimHcRwMmio (Bar + SD_HC_NOR_INT_STS, TRUE, sizeof (Data), &Data);
426 if (EFI_ERROR (Status)) {
427 return Status;
428 }
429
430 if ((Data & (BIT6 | BIT7)) != 0) {
431 //
432 // Clear BIT6 and BIT7 by writing 1 to these two bits if set.
433 //
434 Data &= BIT6 | BIT7;
435 Status = SdPeimHcRwMmio (Bar + SD_HC_NOR_INT_STS, FALSE, sizeof (Data), &Data);
436 if (EFI_ERROR (Status)) {
437 return Status;
438 }
439 }
440
441 //
442 // Check Present State Register to see if there is a card presented.
443 //
444 Status = SdPeimHcRwMmio (Bar + SD_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);
445 if (EFI_ERROR (Status)) {
446 return Status;
447 }
448
449 if ((PresentState & BIT16) != 0) {
450 return EFI_SUCCESS;
451 } else {
452 return EFI_NO_MEDIA;
453 }
454}
455
469 IN UINTN Bar
470 )
471{
472 EFI_STATUS Status;
473 UINT32 PresentState;
474 UINT16 ClockCtrl;
475
476 //
477 // Ensure no SD transactions are occurring on the SD Bus by
478 // waiting for Command Inhibit (DAT) and Command Inhibit (CMD)
479 // in the Present State register to be 0.
480 //
481 Status = SdPeimHcWaitMmioSet (
482 Bar + SD_HC_PRESENT_STATE,
483 sizeof (PresentState),
484 BIT0 | BIT1,
485 0,
486 SD_TIMEOUT
487 );
488 if (EFI_ERROR (Status)) {
489 return Status;
490 }
491
492 //
493 // Set SD Clock Enable in the Clock Control register to 0
494 //
495 ClockCtrl = (UINT16) ~BIT2;
496 Status = SdPeimHcAndMmio (Bar + SD_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl);
497
498 return Status;
499}
500
515 IN UINTN Bar,
516 IN UINT64 ClockFreq
517 )
518{
519 EFI_STATUS Status;
520 SD_HC_SLOT_CAP Capability;
521 UINT32 BaseClkFreq;
522 UINT32 SettingFreq;
523 UINT32 Divisor;
524 UINT32 Remainder;
525 UINT16 ControllerVer;
526 UINT16 ClockCtrl;
527
528 //
529 // Calculate a divisor for SD clock frequency
530 //
531 Status = SdPeimHcGetCapability (Bar, &Capability);
532 if (EFI_ERROR (Status)) {
533 return Status;
534 }
535
536 ASSERT (Capability.BaseClkFreq != 0);
537
538 BaseClkFreq = Capability.BaseClkFreq;
539
540 if (ClockFreq == 0) {
541 return EFI_INVALID_PARAMETER;
542 }
543
544 if (ClockFreq > (BaseClkFreq * 1000)) {
545 ClockFreq = BaseClkFreq * 1000;
546 }
547
548 //
549 // Calculate the divisor of base frequency.
550 //
551 Divisor = 0;
552 SettingFreq = BaseClkFreq * 1000;
553 while (ClockFreq < SettingFreq) {
554 Divisor++;
555
556 SettingFreq = (BaseClkFreq * 1000) / (2 * Divisor);
557 Remainder = (BaseClkFreq * 1000) % (2 * Divisor);
558 if ((ClockFreq == SettingFreq) && (Remainder == 0)) {
559 break;
560 }
561
562 if ((ClockFreq == SettingFreq) && (Remainder != 0)) {
563 SettingFreq++;
564 }
565 }
566
567 DEBUG ((DEBUG_INFO, "BaseClkFreq %dMHz Divisor %d ClockFreq %dKhz\n", BaseClkFreq, Divisor, ClockFreq));
568
569 Status = SdPeimHcRwMmio (Bar + SD_HC_CTRL_VER, TRUE, sizeof (ControllerVer), &ControllerVer);
570 if (EFI_ERROR (Status)) {
571 return Status;
572 }
573
574 //
575 // Set SDCLK Frequency Select and Internal Clock Enable fields in Clock Control register.
576 //
577 if ((ControllerVer & 0xFF) == 2) {
578 ASSERT (Divisor <= 0x3FF);
579 ClockCtrl = ((Divisor & 0xFF) << 8) | ((Divisor & 0x300) >> 2);
580 } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {
581 //
582 // Only the most significant bit can be used as divisor.
583 //
584 if (((Divisor - 1) & Divisor) != 0) {
585 Divisor = 1 << (HighBitSet32 (Divisor) + 1);
586 }
587
588 ASSERT (Divisor <= 0x80);
589 ClockCtrl = (Divisor & 0xFF) << 8;
590 } else {
591 DEBUG ((DEBUG_ERROR, "Unknown SD Host Controller Spec version [0x%x]!!!\n", ControllerVer));
592 return EFI_UNSUPPORTED;
593 }
594
595 //
596 // Stop bus clock at first
597 //
598 Status = SdPeimHcStopClock (Bar);
599 if (EFI_ERROR (Status)) {
600 return Status;
601 }
602
603 //
604 // Supply clock frequency with specified divisor
605 //
606 ClockCtrl |= BIT0;
607 Status = SdPeimHcRwMmio (Bar + SD_HC_CLOCK_CTRL, FALSE, sizeof (ClockCtrl), &ClockCtrl);
608 if (EFI_ERROR (Status)) {
609 DEBUG ((DEBUG_ERROR, "Set SDCLK Frequency Select and Internal Clock Enable fields fails\n"));
610 return Status;
611 }
612
613 //
614 // Wait Internal Clock Stable in the Clock Control register to be 1
615 //
616 Status = SdPeimHcWaitMmioSet (
617 Bar + SD_HC_CLOCK_CTRL,
618 sizeof (ClockCtrl),
619 BIT1,
620 BIT1,
621 SD_TIMEOUT
622 );
623 if (EFI_ERROR (Status)) {
624 return Status;
625 }
626
627 //
628 // Set SD Clock Enable in the Clock Control register to 1
629 //
630 ClockCtrl = BIT2;
631 Status = SdPeimHcOrMmio (Bar + SD_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl);
632
633 return Status;
634}
635
650 IN UINTN Bar,
651 IN UINT8 PowerCtrl
652 )
653{
654 EFI_STATUS Status;
655
656 //
657 // Clr SD Bus Power
658 //
659 PowerCtrl &= (UINT8) ~BIT0;
660 Status = SdPeimHcRwMmio (Bar + SD_HC_POWER_CTRL, FALSE, sizeof (PowerCtrl), &PowerCtrl);
661 if (EFI_ERROR (Status)) {
662 return Status;
663 }
664
665 //
666 // Set SD Bus Voltage Select and SD Bus Power fields in Power Control Register
667 //
668 PowerCtrl |= BIT0;
669 Status = SdPeimHcRwMmio (Bar + SD_HC_POWER_CTRL, FALSE, sizeof (PowerCtrl), &PowerCtrl);
670
671 return Status;
672}
673
688 IN UINTN Bar,
689 IN UINT16 BusWidth
690 )
691{
692 EFI_STATUS Status;
693 UINT8 HostCtrl1;
694
695 if (BusWidth == 1) {
696 HostCtrl1 = (UINT8) ~(BIT5 | BIT1);
697 Status = SdPeimHcAndMmio (Bar + SD_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);
698 } else if (BusWidth == 4) {
699 Status = SdPeimHcRwMmio (Bar + SD_HC_HOST_CTRL1, TRUE, sizeof (HostCtrl1), &HostCtrl1);
700 if (EFI_ERROR (Status)) {
701 return Status;
702 }
703
704 HostCtrl1 |= BIT1;
705 HostCtrl1 &= (UINT8) ~BIT5;
706 Status = SdPeimHcRwMmio (Bar + SD_HC_HOST_CTRL1, FALSE, sizeof (HostCtrl1), &HostCtrl1);
707 } else if (BusWidth == 8) {
708 Status = SdPeimHcRwMmio (Bar + SD_HC_HOST_CTRL1, TRUE, sizeof (HostCtrl1), &HostCtrl1);
709 if (EFI_ERROR (Status)) {
710 return Status;
711 }
712
713 HostCtrl1 &= (UINT8) ~BIT1;
714 HostCtrl1 |= BIT5;
715 Status = SdPeimHcRwMmio (Bar + SD_HC_HOST_CTRL1, FALSE, sizeof (HostCtrl1), &HostCtrl1);
716 } else {
717 ASSERT (FALSE);
718 return EFI_INVALID_PARAMETER;
719 }
720
721 return Status;
722}
723
735 IN UINTN Bar
736 )
737{
738 EFI_STATUS Status;
739 SD_HC_SLOT_CAP Capability;
740 UINT32 InitFreq;
741
742 //
743 // Calculate a divisor for SD clock frequency
744 //
745 Status = SdPeimHcGetCapability (Bar, &Capability);
746 if (EFI_ERROR (Status)) {
747 return Status;
748 }
749
750 if (Capability.BaseClkFreq == 0) {
751 //
752 // Don't support get Base Clock Frequency information via another method
753 //
754 return EFI_UNSUPPORTED;
755 }
756
757 //
758 // Supply 400KHz clock frequency at initialization phase.
759 //
760 InitFreq = 400;
761 Status = SdPeimHcClockSupply (Bar, InitFreq);
762 return Status;
763}
764
778 IN UINTN Bar
779 )
780{
781 EFI_STATUS Status;
782 SD_HC_SLOT_CAP Capability;
783 UINT8 MaxVoltage;
784 UINT8 HostCtrl2;
785
786 //
787 // Get the support voltage of the Host Controller
788 //
789 Status = SdPeimHcGetCapability (Bar, &Capability);
790 if (EFI_ERROR (Status)) {
791 return Status;
792 }
793
794 //
795 // Calculate supported maximum voltage according to SD Bus Voltage Select
796 //
797 if (Capability.Voltage33 != 0) {
798 //
799 // Support 3.3V
800 //
801 MaxVoltage = 0x0E;
802 } else if (Capability.Voltage30 != 0) {
803 //
804 // Support 3.0V
805 //
806 MaxVoltage = 0x0C;
807 } else if (Capability.Voltage18 != 0) {
808 //
809 // Support 1.8V
810 //
811 MaxVoltage = 0x0A;
812 HostCtrl2 = BIT3;
813 Status = SdPeimHcOrMmio (Bar + SD_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
814 if (EFI_ERROR (Status)) {
815 return Status;
816 }
817
818 MicroSecondDelay (5000);
819 } else {
820 ASSERT (FALSE);
821 return EFI_DEVICE_ERROR;
822 }
823
824 //
825 // Set SD Bus Voltage Select and SD Bus Power fields in Power Control Register
826 //
827 Status = SdPeimHcPowerControl (Bar, MaxVoltage);
828
829 return Status;
830}
831
845 IN UINTN Bar
846 )
847{
848 EFI_STATUS Status;
849 UINT8 Timeout;
850
851 Timeout = 0x0E;
852 Status = SdPeimHcRwMmio (Bar + SD_HC_TIMEOUT_CTRL, FALSE, sizeof (Timeout), &Timeout);
853
854 return Status;
855}
856
869 IN UINTN Bar
870 )
871{
872 EFI_STATUS Status;
873
874 Status = SdPeimHcInitClockFreq (Bar);
875 if (EFI_ERROR (Status)) {
876 return Status;
877 }
878
879 Status = SdPeimHcInitPowerVoltage (Bar);
880 if (EFI_ERROR (Status)) {
881 return Status;
882 }
883
884 Status = SdPeimHcInitTimeoutCtrl (Bar);
885 return Status;
886}
887
900 IN UINTN Bar,
901 IN BOOLEAN On
902 )
903{
904 EFI_STATUS Status;
905 UINT8 HostCtrl1;
906
907 if (On) {
908 HostCtrl1 = BIT0;
909 Status = SdPeimHcOrMmio (Bar + SD_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);
910 } else {
911 HostCtrl1 = (UINT8) ~BIT0;
912 Status = SdPeimHcAndMmio (Bar + SD_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);
913 }
914
915 return Status;
916}
917
931 IN SD_TRB *Trb
932 )
933{
935 UINT64 DataLen;
936 UINT64 Entries;
937 UINT32 Index;
938 UINT64 Remaining;
939 UINT32 Address;
940
941 Data = Trb->DataPhy;
942 DataLen = Trb->DataLen;
943 //
944 // Only support 32bit ADMA Descriptor Table
945 //
946 if ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul)) {
947 return EFI_INVALID_PARAMETER;
948 }
949
950 //
951 // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to 0)
952 // for 32-bit address descriptor table.
953 //
954 if ((Data & (BIT0 | BIT1)) != 0) {
955 DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data));
956 }
957
958 Entries = DivU64x32 ((DataLen + ADMA_MAX_DATA_PER_LINE - 1), ADMA_MAX_DATA_PER_LINE);
959
960 Trb->AdmaDescSize = (UINTN)MultU64x32 (Entries, sizeof (SD_HC_ADMA_DESC_LINE));
961 Trb->AdmaDesc = SdPeimAllocateMem (Trb->Slot->Private->Pool, Trb->AdmaDescSize);
962 if (Trb->AdmaDesc == NULL) {
963 return EFI_OUT_OF_RESOURCES;
964 }
965
966 Remaining = DataLen;
967 Address = (UINT32)Data;
968 for (Index = 0; Index < Entries; Index++) {
969 if (Remaining <= ADMA_MAX_DATA_PER_LINE) {
970 Trb->AdmaDesc[Index].Valid = 1;
971 Trb->AdmaDesc[Index].Act = 2;
972 Trb->AdmaDesc[Index].Length = (UINT16)Remaining;
973 Trb->AdmaDesc[Index].Address = Address;
974 break;
975 } else {
976 Trb->AdmaDesc[Index].Valid = 1;
977 Trb->AdmaDesc[Index].Act = 2;
978 Trb->AdmaDesc[Index].Length = 0;
979 Trb->AdmaDesc[Index].Address = Address;
980 }
981
982 Remaining -= ADMA_MAX_DATA_PER_LINE;
983 Address += ADMA_MAX_DATA_PER_LINE;
984 }
985
986 //
987 // Set the last descriptor line as end of descriptor table
988 //
989 Trb->AdmaDesc[Index].End = 1;
990 return EFI_SUCCESS;
991}
992
1002SD_TRB *
1004 IN SD_PEIM_HC_SLOT *Slot,
1005 IN SD_COMMAND_PACKET *Packet
1006 )
1007{
1008 SD_TRB *Trb;
1009 EFI_STATUS Status;
1010 SD_HC_SLOT_CAP Capability;
1012 UINTN MapLength;
1013
1014 //
1015 // Calculate a divisor for SD clock frequency
1016 //
1017 Status = SdPeimHcGetCapability (Slot->SdHcBase, &Capability);
1018 if (EFI_ERROR (Status)) {
1019 return NULL;
1020 }
1021
1022 Trb = AllocateZeroPool (sizeof (SD_TRB));
1023 if (Trb == NULL) {
1024 return NULL;
1025 }
1026
1027 Trb->Slot = Slot;
1028 Trb->BlockSize = 0x200;
1029 Trb->Packet = Packet;
1030 Trb->Timeout = Packet->Timeout;
1031
1032 if ((Packet->InTransferLength != 0) && (Packet->InDataBuffer != NULL)) {
1033 Trb->Data = Packet->InDataBuffer;
1034 Trb->DataLen = Packet->InTransferLength;
1035 Trb->Read = TRUE;
1036 } else if ((Packet->OutTransferLength != 0) && (Packet->OutDataBuffer != NULL)) {
1037 Trb->Data = Packet->OutDataBuffer;
1038 Trb->DataLen = Packet->OutTransferLength;
1039 Trb->Read = FALSE;
1040 } else if ((Packet->InTransferLength == 0) && (Packet->OutTransferLength == 0)) {
1041 Trb->Data = NULL;
1042 Trb->DataLen = 0;
1043 } else {
1044 goto Error;
1045 }
1046
1047 if ((Trb->DataLen != 0) && (Trb->DataLen < Trb->BlockSize)) {
1048 Trb->BlockSize = (UINT16)Trb->DataLen;
1049 }
1050
1051 if (Packet->SdCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK) {
1052 Trb->Mode = SdPioMode;
1053 } else {
1054 if (Trb->Read) {
1056 } else {
1058 }
1059
1060 if (Trb->DataLen != 0) {
1061 MapLength = Trb->DataLen;
1062 Status = IoMmuMap (MapOp, Trb->Data, &MapLength, &Trb->DataPhy, &Trb->DataMap);
1063
1064 if (EFI_ERROR (Status) || (MapLength != Trb->DataLen)) {
1065 DEBUG ((DEBUG_ERROR, "SdPeimCreateTrb: Fail to map data buffer.\n"));
1066 goto Error;
1067 }
1068 }
1069
1070 if (Trb->DataLen == 0) {
1071 Trb->Mode = SdNoData;
1072 } else if (Capability.Adma2 != 0) {
1073 Trb->Mode = SdAdmaMode;
1074 Status = BuildAdmaDescTable (Trb);
1075 if (EFI_ERROR (Status)) {
1076 goto Error;
1077 }
1078 } else if (Capability.Sdma != 0) {
1079 Trb->Mode = SdSdmaMode;
1080 } else {
1081 Trb->Mode = SdPioMode;
1082 }
1083 }
1084
1085 return Trb;
1086
1087Error:
1088 SdPeimFreeTrb (Trb);
1089 return NULL;
1090}
1091
1098VOID
1100 IN SD_TRB *Trb
1101 )
1102{
1103 if ((Trb != NULL) && (Trb->DataMap != NULL)) {
1104 IoMmuUnmap (Trb->DataMap);
1105 }
1106
1107 if ((Trb != NULL) && (Trb->AdmaDesc != NULL)) {
1108 SdPeimFreeMem (Trb->Slot->Private->Pool, Trb->AdmaDesc, Trb->AdmaDescSize);
1109 }
1110
1111 if (Trb != NULL) {
1112 FreePool (Trb);
1113 }
1114
1115 return;
1116}
1117
1131 IN UINTN Bar,
1132 IN SD_TRB *Trb
1133 )
1134{
1135 EFI_STATUS Status;
1136 SD_COMMAND_PACKET *Packet;
1137 UINT32 PresentState;
1138
1139 Packet = Trb->Packet;
1140
1141 if ((Packet->SdCmdBlk->CommandType == SdCommandTypeAdtc) ||
1142 (Packet->SdCmdBlk->ResponseType == SdResponseTypeR1b) ||
1143 (Packet->SdCmdBlk->ResponseType == SdResponseTypeR5b))
1144 {
1145 //
1146 // Wait Command Inhibit (CMD) and Command Inhibit (DAT) in
1147 // the Present State register to be 0
1148 //
1149 PresentState = BIT0 | BIT1;
1150 } else {
1151 //
1152 // Wait Command Inhibit (CMD) in the Present State register
1153 // to be 0
1154 //
1155 PresentState = BIT0;
1156 }
1157
1158 Status = SdPeimHcCheckMmioSet (
1159 Bar + SD_HC_PRESENT_STATE,
1160 sizeof (PresentState),
1161 PresentState,
1162 0
1163 );
1164
1165 return Status;
1166}
1167
1181 IN UINTN Bar,
1182 IN SD_TRB *Trb
1183 )
1184{
1185 EFI_STATUS Status;
1186 SD_COMMAND_PACKET *Packet;
1187 UINT64 Timeout;
1188 BOOLEAN InfiniteWait;
1189
1190 //
1191 // Wait Command Complete Interrupt Status bit in Normal Interrupt Status Register
1192 //
1193 Packet = Trb->Packet;
1194 Timeout = Packet->Timeout;
1195 if (Timeout == 0) {
1196 InfiniteWait = TRUE;
1197 } else {
1198 InfiniteWait = FALSE;
1199 }
1200
1201 while (InfiniteWait || (Timeout > 0)) {
1202 //
1203 // Check Trb execution result by reading Normal Interrupt Status register.
1204 //
1205 Status = SdPeimCheckTrbEnv (Bar, Trb);
1206 if (Status != EFI_NOT_READY) {
1207 return Status;
1208 }
1209
1210 //
1211 // Stall for 1 microsecond.
1212 //
1213 MicroSecondDelay (1);
1214
1215 Timeout--;
1216 }
1217
1218 return EFI_TIMEOUT;
1219}
1220
1233 IN UINTN Bar,
1234 IN SD_TRB *Trb
1235 )
1236{
1237 EFI_STATUS Status;
1238 SD_COMMAND_PACKET *Packet;
1239 UINT16 Cmd;
1240 UINT16 IntStatus;
1241 UINT32 Argument;
1242 UINT16 BlkCount;
1243 UINT16 BlkSize;
1244 UINT16 TransMode;
1245 UINT8 HostCtrl1;
1246 UINT32 SdmaAddr;
1247 UINT64 AdmaAddr;
1248
1249 Packet = Trb->Packet;
1250 //
1251 // Clear all bits in Error Interrupt Status Register
1252 //
1253 IntStatus = 0xFFFF;
1254 Status = SdPeimHcRwMmio (Bar + SD_HC_ERR_INT_STS, FALSE, sizeof (IntStatus), &IntStatus);
1255 if (EFI_ERROR (Status)) {
1256 return Status;
1257 }
1258
1259 //
1260 // Clear all bits in Normal Interrupt Status Register
1261 //
1262 IntStatus = 0xFFFF;
1263 Status = SdPeimHcRwMmio (Bar + SD_HC_NOR_INT_STS, FALSE, sizeof (IntStatus), &IntStatus);
1264 if (EFI_ERROR (Status)) {
1265 return Status;
1266 }
1267
1268 //
1269 // Set Host Control 1 register DMA Select field
1270 //
1271 if (Trb->Mode == SdAdmaMode) {
1272 HostCtrl1 = BIT4;
1273 Status = SdPeimHcOrMmio (Bar + SD_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);
1274 if (EFI_ERROR (Status)) {
1275 return Status;
1276 }
1277 }
1278
1279 SdPeimHcLedOnOff (Bar, TRUE);
1280
1281 if (Trb->Mode == SdSdmaMode) {
1282 if ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul) {
1283 return EFI_INVALID_PARAMETER;
1284 }
1285
1286 SdmaAddr = (UINT32)(UINTN)Trb->DataPhy;
1287 Status = SdPeimHcRwMmio (Bar + SD_HC_SDMA_ADDR, FALSE, sizeof (SdmaAddr), &SdmaAddr);
1288 if (EFI_ERROR (Status)) {
1289 return Status;
1290 }
1291 } else if (Trb->Mode == SdAdmaMode) {
1292 AdmaAddr = (UINT64)(UINTN)Trb->AdmaDesc;
1293 Status = SdPeimHcRwMmio (Bar + SD_HC_ADMA_SYS_ADDR, FALSE, sizeof (AdmaAddr), &AdmaAddr);
1294 if (EFI_ERROR (Status)) {
1295 return Status;
1296 }
1297 }
1298
1299 BlkSize = Trb->BlockSize;
1300 if (Trb->Mode == SdSdmaMode) {
1301 //
1302 // Set SDMA boundary to be 512K bytes.
1303 //
1304 BlkSize |= 0x7000;
1305 }
1306
1307 Status = SdPeimHcRwMmio (Bar + SD_HC_BLK_SIZE, FALSE, sizeof (BlkSize), &BlkSize);
1308 if (EFI_ERROR (Status)) {
1309 return Status;
1310 }
1311
1312 BlkCount = 0;
1313 if (Trb->Mode != SdNoData) {
1314 //
1315 // Calculate Block Count.
1316 //
1317 BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);
1318 }
1319
1320 Status = SdPeimHcRwMmio (Bar + SD_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount);
1321 if (EFI_ERROR (Status)) {
1322 return Status;
1323 }
1324
1325 Argument = Packet->SdCmdBlk->CommandArgument;
1326 Status = SdPeimHcRwMmio (Bar + SD_HC_ARG1, FALSE, sizeof (Argument), &Argument);
1327 if (EFI_ERROR (Status)) {
1328 return Status;
1329 }
1330
1331 TransMode = 0;
1332 if (Trb->Mode != SdNoData) {
1333 if (Trb->Mode != SdPioMode) {
1334 TransMode |= BIT0;
1335 }
1336
1337 if (Trb->Read) {
1338 TransMode |= BIT4;
1339 }
1340
1341 if (BlkCount > 1) {
1342 TransMode |= BIT5 | BIT1;
1343 }
1344
1345 //
1346 // SD memory card needs to use AUTO CMD12 feature.
1347 //
1348 if (BlkCount > 1) {
1349 TransMode |= BIT2;
1350 }
1351 }
1352
1353 Status = SdPeimHcRwMmio (Bar + SD_HC_TRANS_MOD, FALSE, sizeof (TransMode), &TransMode);
1354 if (EFI_ERROR (Status)) {
1355 return Status;
1356 }
1357
1358 Cmd = (UINT16)LShiftU64 (Packet->SdCmdBlk->CommandIndex, 8);
1359 if (Packet->SdCmdBlk->CommandType == SdCommandTypeAdtc) {
1360 Cmd |= BIT5;
1361 }
1362
1363 //
1364 // Convert ResponseType to value
1365 //
1366 if (Packet->SdCmdBlk->CommandType != SdCommandTypeBc) {
1367 switch (Packet->SdCmdBlk->ResponseType) {
1368 case SdResponseTypeR1:
1369 case SdResponseTypeR5:
1370 case SdResponseTypeR6:
1371 case SdResponseTypeR7:
1372 Cmd |= (BIT1 | BIT3 | BIT4);
1373 break;
1374 case SdResponseTypeR2:
1375 Cmd |= (BIT0 | BIT3);
1376 break;
1377 case SdResponseTypeR3:
1378 case SdResponseTypeR4:
1379 Cmd |= BIT1;
1380 break;
1381 case SdResponseTypeR1b:
1382 case SdResponseTypeR5b:
1383 Cmd |= (BIT0 | BIT1 | BIT3 | BIT4);
1384 break;
1385 default:
1386 ASSERT (FALSE);
1387 break;
1388 }
1389 }
1390
1391 //
1392 // Execute cmd
1393 //
1394 Status = SdPeimHcRwMmio (Bar + SD_HC_COMMAND, FALSE, sizeof (Cmd), &Cmd);
1395 return Status;
1396}
1397
1411 IN UINTN Bar,
1412 IN SD_TRB *Trb
1413 )
1414{
1415 EFI_STATUS Status;
1416 SD_COMMAND_PACKET *Packet;
1417 UINT16 IntStatus;
1418 UINT32 Response[4];
1419 UINT32 SdmaAddr;
1420 UINT8 Index;
1421 UINT8 SwReset;
1422 UINT32 PioLength;
1423
1424 SwReset = 0;
1425 Packet = Trb->Packet;
1426 //
1427 // Check Trb execution result by reading Normal Interrupt Status register.
1428 //
1429 Status = SdPeimHcRwMmio (
1430 Bar + SD_HC_NOR_INT_STS,
1431 TRUE,
1432 sizeof (IntStatus),
1433 &IntStatus
1434 );
1435 if (EFI_ERROR (Status)) {
1436 goto Done;
1437 }
1438
1439 //
1440 // Check Transfer Complete bit is set or not.
1441 //
1442 if ((IntStatus & BIT1) == BIT1) {
1443 if ((IntStatus & BIT15) == BIT15) {
1444 //
1445 // Read Error Interrupt Status register to check if the error is
1446 // Data Timeout Error.
1447 // If yes, treat it as success as Transfer Complete has higher
1448 // priority than Data Timeout Error.
1449 //
1450 Status = SdPeimHcRwMmio (
1451 Bar + SD_HC_ERR_INT_STS,
1452 TRUE,
1453 sizeof (IntStatus),
1454 &IntStatus
1455 );
1456 if (!EFI_ERROR (Status)) {
1457 if ((IntStatus & BIT4) == BIT4) {
1458 Status = EFI_SUCCESS;
1459 } else {
1460 Status = EFI_DEVICE_ERROR;
1461 }
1462 }
1463 }
1464
1465 goto Done;
1466 }
1467
1468 //
1469 // Check if there is a error happened during cmd execution.
1470 // If yes, then do error recovery procedure to follow SD Host Controller
1471 // Simplified Spec 3.0 section 3.10.1.
1472 //
1473 if ((IntStatus & BIT15) == BIT15) {
1474 Status = SdPeimHcRwMmio (
1475 Bar + SD_HC_ERR_INT_STS,
1476 TRUE,
1477 sizeof (IntStatus),
1478 &IntStatus
1479 );
1480 if (EFI_ERROR (Status)) {
1481 goto Done;
1482 }
1483
1484 if ((IntStatus & 0x0F) != 0) {
1485 SwReset |= BIT1;
1486 }
1487
1488 if ((IntStatus & 0xF0) != 0) {
1489 SwReset |= BIT2;
1490 }
1491
1492 Status = SdPeimHcRwMmio (
1493 Bar + SD_HC_SW_RST,
1494 FALSE,
1495 sizeof (SwReset),
1496 &SwReset
1497 );
1498 if (EFI_ERROR (Status)) {
1499 goto Done;
1500 }
1501
1502 Status = SdPeimHcWaitMmioSet (
1503 Bar + SD_HC_SW_RST,
1504 sizeof (SwReset),
1505 0xFF,
1506 0,
1507 SD_TIMEOUT
1508 );
1509 if (EFI_ERROR (Status)) {
1510 goto Done;
1511 }
1512
1513 Status = EFI_DEVICE_ERROR;
1514 goto Done;
1515 }
1516
1517 //
1518 // Check if DMA interrupt is signalled for the SDMA transfer.
1519 //
1520 if ((Trb->Mode == SdSdmaMode) && ((IntStatus & BIT3) == BIT3)) {
1521 //
1522 // Clear DMA interrupt bit.
1523 //
1524 IntStatus = BIT3;
1525 Status = SdPeimHcRwMmio (
1526 Bar + SD_HC_NOR_INT_STS,
1527 FALSE,
1528 sizeof (IntStatus),
1529 &IntStatus
1530 );
1531 if (EFI_ERROR (Status)) {
1532 goto Done;
1533 }
1534
1535 //
1536 // Update SDMA Address register.
1537 //
1538 SdmaAddr = SD_SDMA_ROUND_UP ((UINT32)(UINTN)Trb->DataPhy, SD_SDMA_BOUNDARY);
1539 Status = SdPeimHcRwMmio (
1540 Bar + SD_HC_SDMA_ADDR,
1541 FALSE,
1542 sizeof (UINT32),
1543 &SdmaAddr
1544 );
1545 if (EFI_ERROR (Status)) {
1546 goto Done;
1547 }
1548
1549 Trb->DataPhy = (UINT32)(UINTN)SdmaAddr;
1550 }
1551
1552 if ((Packet->SdCmdBlk->CommandType != SdCommandTypeAdtc) &&
1553 (Packet->SdCmdBlk->ResponseType != SdResponseTypeR1b) &&
1554 (Packet->SdCmdBlk->ResponseType != SdResponseTypeR5b))
1555 {
1556 if ((IntStatus & BIT0) == BIT0) {
1557 Status = EFI_SUCCESS;
1558 goto Done;
1559 }
1560 }
1561
1562 if (Packet->SdCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK) {
1563 //
1564 // When performing tuning procedure (Execute Tuning is set to 1) through PIO mode,
1565 // wait Buffer Read Ready bit of Normal Interrupt Status Register to be 1.
1566 // Refer to SD Host Controller Simplified Specification 3.0 figure 2-29 for details.
1567 //
1568 if ((IntStatus & BIT5) == BIT5) {
1569 //
1570 // Clear Buffer Read Ready interrupt at first.
1571 //
1572 IntStatus = BIT5;
1573 SdPeimHcRwMmio (Bar + SD_HC_NOR_INT_STS, FALSE, sizeof (IntStatus), &IntStatus);
1574 //
1575 // Read data out from Buffer Port register
1576 //
1577 for (PioLength = 0; PioLength < Trb->DataLen; PioLength += 4) {
1578 SdPeimHcRwMmio (Bar + SD_HC_BUF_DAT_PORT, TRUE, 4, (UINT8 *)Trb->Data + PioLength);
1579 }
1580
1581 Status = EFI_SUCCESS;
1582 goto Done;
1583 }
1584 }
1585
1586 Status = EFI_NOT_READY;
1587Done:
1588 //
1589 // Get response data when the cmd is executed successfully.
1590 //
1591 if (!EFI_ERROR (Status)) {
1592 if (Packet->SdCmdBlk->CommandType != SdCommandTypeBc) {
1593 for (Index = 0; Index < 4; Index++) {
1594 Status = SdPeimHcRwMmio (
1595 Bar + SD_HC_RESPONSE + Index * 4,
1596 TRUE,
1597 sizeof (UINT32),
1598 &Response[Index]
1599 );
1600 if (EFI_ERROR (Status)) {
1601 SdPeimHcLedOnOff (Bar, FALSE);
1602 return Status;
1603 }
1604 }
1605
1606 CopyMem (Packet->SdStatusBlk, Response, sizeof (Response));
1607 }
1608 }
1609
1610 if (Status != EFI_NOT_READY) {
1611 SdPeimHcLedOnOff (Bar, FALSE);
1612 }
1613
1614 return Status;
1615}
1616
1629 IN UINTN Bar,
1630 IN SD_TRB *Trb
1631 )
1632{
1633 EFI_STATUS Status;
1634 SD_COMMAND_PACKET *Packet;
1635 UINT64 Timeout;
1636 BOOLEAN InfiniteWait;
1637
1638 Packet = Trb->Packet;
1639 //
1640 // Wait Command Complete Interrupt Status bit in Normal Interrupt Status Register
1641 //
1642 Timeout = Packet->Timeout;
1643 if (Timeout == 0) {
1644 InfiniteWait = TRUE;
1645 } else {
1646 InfiniteWait = FALSE;
1647 }
1648
1649 while (InfiniteWait || (Timeout > 0)) {
1650 //
1651 // Check Trb execution result by reading Normal Interrupt Status register.
1652 //
1653 Status = SdPeimCheckTrbResult (Bar, Trb);
1654 if (Status != EFI_NOT_READY) {
1655 return Status;
1656 }
1657
1658 //
1659 // Stall for 1 microsecond.
1660 //
1661 MicroSecondDelay (1);
1662
1663 Timeout--;
1664 }
1665
1666 return EFI_TIMEOUT;
1667}
1668
1700EFIAPI
1702 IN SD_PEIM_HC_SLOT *Slot,
1703 IN OUT SD_COMMAND_PACKET *Packet
1704 )
1705{
1706 EFI_STATUS Status;
1707 SD_TRB *Trb;
1708
1709 if (Packet == NULL) {
1710 return EFI_INVALID_PARAMETER;
1711 }
1712
1713 if ((Packet->SdCmdBlk == NULL) || (Packet->SdStatusBlk == NULL)) {
1714 return EFI_INVALID_PARAMETER;
1715 }
1716
1717 if ((Packet->OutDataBuffer == NULL) && (Packet->OutTransferLength != 0)) {
1718 return EFI_INVALID_PARAMETER;
1719 }
1720
1721 if ((Packet->InDataBuffer == NULL) && (Packet->InTransferLength != 0)) {
1722 return EFI_INVALID_PARAMETER;
1723 }
1724
1725 Trb = SdPeimCreateTrb (Slot, Packet);
1726 if (Trb == NULL) {
1727 return EFI_OUT_OF_RESOURCES;
1728 }
1729
1730 Status = SdPeimWaitTrbEnv (Slot->SdHcBase, Trb);
1731 if (EFI_ERROR (Status)) {
1732 goto Done;
1733 }
1734
1735 Status = SdPeimExecTrb (Slot->SdHcBase, Trb);
1736 if (EFI_ERROR (Status)) {
1737 goto Done;
1738 }
1739
1740 Status = SdPeimWaitTrbResult (Slot->SdHcBase, Trb);
1741 if (EFI_ERROR (Status)) {
1742 goto Done;
1743 }
1744
1745Done:
1746 SdPeimFreeTrb (Trb);
1747
1748 return Status;
1749}
1750
1764 IN SD_PEIM_HC_SLOT *Slot
1765 )
1766{
1767 SD_COMMAND_BLOCK SdCmdBlk;
1768 SD_STATUS_BLOCK SdStatusBlk;
1769 SD_COMMAND_PACKET Packet;
1770 EFI_STATUS Status;
1771
1772 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));
1773 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));
1774 ZeroMem (&Packet, sizeof (Packet));
1775
1776 Packet.SdCmdBlk = &SdCmdBlk;
1777 Packet.SdStatusBlk = &SdStatusBlk;
1778 Packet.Timeout = SD_TIMEOUT;
1779
1780 SdCmdBlk.CommandIndex = SD_GO_IDLE_STATE;
1781 SdCmdBlk.CommandType = SdCommandTypeBc;
1782 SdCmdBlk.ResponseType = 0;
1783 SdCmdBlk.CommandArgument = 0;
1784
1785 Status = SdPeimExecCmd (Slot, &Packet);
1786
1787 return Status;
1788}
1789
1806 IN SD_PEIM_HC_SLOT *Slot,
1807 IN UINT8 SupplyVoltage,
1808 IN UINT8 CheckPattern
1809 )
1810{
1811 SD_COMMAND_BLOCK SdCmdBlk;
1812 SD_STATUS_BLOCK SdStatusBlk;
1813 SD_COMMAND_PACKET Packet;
1814 EFI_STATUS Status;
1815
1816 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));
1817 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));
1818 ZeroMem (&Packet, sizeof (Packet));
1819
1820 Packet.SdCmdBlk = &SdCmdBlk;
1821 Packet.SdStatusBlk = &SdStatusBlk;
1822 Packet.Timeout = SD_TIMEOUT;
1823
1824 SdCmdBlk.CommandIndex = SD_SEND_IF_COND;
1825 SdCmdBlk.CommandType = SdCommandTypeBcr;
1826 SdCmdBlk.ResponseType = SdResponseTypeR7;
1827 SdCmdBlk.CommandArgument = (SupplyVoltage << 8) | CheckPattern;
1828
1829 Status = SdPeimExecCmd (Slot, &Packet);
1830 if (!EFI_ERROR (Status)) {
1831 if (SdStatusBlk.Resp0 != SdCmdBlk.CommandArgument) {
1832 return EFI_DEVICE_ERROR;
1833 }
1834 }
1835
1836 return Status;
1837}
1838
1854 IN SD_PEIM_HC_SLOT *Slot,
1855 IN UINT32 VoltageWindow,
1856 IN BOOLEAN S18r
1857 )
1858{
1859 SD_COMMAND_BLOCK SdCmdBlk;
1860 SD_STATUS_BLOCK SdStatusBlk;
1861 SD_COMMAND_PACKET Packet;
1862 EFI_STATUS Status;
1863 UINT32 Switch;
1864
1865 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));
1866 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));
1867 ZeroMem (&Packet, sizeof (Packet));
1868
1869 Packet.SdCmdBlk = &SdCmdBlk;
1870 Packet.SdStatusBlk = &SdStatusBlk;
1871 Packet.Timeout = SD_TIMEOUT;
1872
1873 SdCmdBlk.CommandIndex = SDIO_SEND_OP_COND;
1874 SdCmdBlk.CommandType = SdCommandTypeBcr;
1875 SdCmdBlk.ResponseType = SdResponseTypeR4;
1876
1877 Switch = S18r ? BIT24 : 0;
1878
1879 SdCmdBlk.CommandArgument = (VoltageWindow & 0xFFFFFF) | Switch;
1880
1881 Status = SdPeimExecCmd (Slot, &Packet);
1882
1883 return Status;
1884}
1885
1906 IN SD_PEIM_HC_SLOT *Slot,
1907 IN UINT16 Rca,
1908 IN UINT32 VoltageWindow,
1909 IN BOOLEAN S18r,
1910 IN BOOLEAN Xpc,
1911 IN BOOLEAN Hcs,
1912 OUT UINT32 *Ocr
1913 )
1914{
1915 SD_COMMAND_BLOCK SdCmdBlk;
1916 SD_STATUS_BLOCK SdStatusBlk;
1917 SD_COMMAND_PACKET Packet;
1918 EFI_STATUS Status;
1919 UINT32 Switch;
1920 UINT32 MaxPower;
1921 UINT32 HostCapacity;
1922
1923 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));
1924 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));
1925 ZeroMem (&Packet, sizeof (Packet));
1926
1927 Packet.SdCmdBlk = &SdCmdBlk;
1928 Packet.SdStatusBlk = &SdStatusBlk;
1929 Packet.Timeout = SD_TIMEOUT;
1930
1931 SdCmdBlk.CommandIndex = SD_APP_CMD;
1932 SdCmdBlk.CommandType = SdCommandTypeAc;
1933 SdCmdBlk.ResponseType = SdResponseTypeR1;
1934 SdCmdBlk.CommandArgument = (UINT32)Rca << 16;
1935
1936 Status = SdPeimExecCmd (Slot, &Packet);
1937 if (EFI_ERROR (Status)) {
1938 return Status;
1939 }
1940
1941 SdCmdBlk.CommandIndex = SD_SEND_OP_COND;
1942 SdCmdBlk.CommandType = SdCommandTypeBcr;
1943 SdCmdBlk.ResponseType = SdResponseTypeR3;
1944
1945 Switch = S18r ? BIT24 : 0;
1946 MaxPower = Xpc ? BIT28 : 0;
1947 HostCapacity = Hcs ? BIT30 : 0;
1948 SdCmdBlk.CommandArgument = (VoltageWindow & 0xFFFFFF) | Switch | MaxPower | HostCapacity;
1949
1950 Status = SdPeimExecCmd (Slot, &Packet);
1951 if (!EFI_ERROR (Status)) {
1952 //
1953 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
1954 //
1955 *Ocr = SdStatusBlk.Resp0;
1956 }
1957
1958 return Status;
1959}
1960
1975 IN SD_PEIM_HC_SLOT *Slot
1976 )
1977{
1978 SD_COMMAND_BLOCK SdCmdBlk;
1979 SD_STATUS_BLOCK SdStatusBlk;
1980 SD_COMMAND_PACKET Packet;
1981 EFI_STATUS Status;
1982
1983 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));
1984 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));
1985 ZeroMem (&Packet, sizeof (Packet));
1986
1987 Packet.SdCmdBlk = &SdCmdBlk;
1988 Packet.SdStatusBlk = &SdStatusBlk;
1989 Packet.Timeout = SD_TIMEOUT;
1990
1991 SdCmdBlk.CommandIndex = SD_ALL_SEND_CID;
1992 SdCmdBlk.CommandType = SdCommandTypeBcr;
1993 SdCmdBlk.ResponseType = SdResponseTypeR2;
1994 SdCmdBlk.CommandArgument = 0;
1995
1996 Status = SdPeimExecCmd (Slot, &Packet);
1997
1998 return Status;
1999}
2000
2016 IN SD_PEIM_HC_SLOT *Slot,
2017 OUT UINT16 *Rca
2018 )
2019{
2020 SD_COMMAND_BLOCK SdCmdBlk;
2021 SD_STATUS_BLOCK SdStatusBlk;
2022 SD_COMMAND_PACKET Packet;
2023 EFI_STATUS Status;
2024
2025 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));
2026 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));
2027 ZeroMem (&Packet, sizeof (Packet));
2028
2029 Packet.SdCmdBlk = &SdCmdBlk;
2030 Packet.SdStatusBlk = &SdStatusBlk;
2031 Packet.Timeout = SD_TIMEOUT;
2032
2033 SdCmdBlk.CommandIndex = SD_SET_RELATIVE_ADDR;
2034 SdCmdBlk.CommandType = SdCommandTypeBcr;
2035 SdCmdBlk.ResponseType = SdResponseTypeR6;
2036
2037 Status = SdPeimExecCmd (Slot, &Packet);
2038 if (!EFI_ERROR (Status)) {
2039 *Rca = (UINT16)(SdStatusBlk.Resp0 >> 16);
2040 }
2041
2042 return Status;
2043}
2044
2063 IN SD_PEIM_HC_SLOT *Slot,
2064 IN UINT16 Rca,
2065 OUT SD_CSD *Csd
2066 )
2067{
2068 SD_COMMAND_BLOCK SdCmdBlk;
2069 SD_STATUS_BLOCK SdStatusBlk;
2070 SD_COMMAND_PACKET Packet;
2071 EFI_STATUS Status;
2072
2073 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));
2074 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));
2075 ZeroMem (&Packet, sizeof (Packet));
2076
2077 Packet.SdCmdBlk = &SdCmdBlk;
2078 Packet.SdStatusBlk = &SdStatusBlk;
2079 Packet.Timeout = SD_TIMEOUT;
2080
2081 SdCmdBlk.CommandIndex = SD_SEND_CSD;
2082 SdCmdBlk.CommandType = SdCommandTypeAc;
2083 SdCmdBlk.ResponseType = SdResponseTypeR2;
2084 SdCmdBlk.CommandArgument = (UINT32)Rca << 16;
2085
2086 Status = SdPeimExecCmd (Slot, &Packet);
2087 if (!EFI_ERROR (Status)) {
2088 //
2089 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
2090 //
2091 CopyMem (((UINT8 *)Csd) + 1, &SdStatusBlk.Resp0, sizeof (SD_CSD) - 1);
2092 }
2093
2094 return Status;
2095}
2096
2111 IN SD_PEIM_HC_SLOT *Slot,
2112 IN UINT16 Rca
2113 )
2114{
2115 SD_COMMAND_BLOCK SdCmdBlk;
2116 SD_STATUS_BLOCK SdStatusBlk;
2117 SD_COMMAND_PACKET Packet;
2118 EFI_STATUS Status;
2119
2120 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));
2121 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));
2122 ZeroMem (&Packet, sizeof (Packet));
2123
2124 Packet.SdCmdBlk = &SdCmdBlk;
2125 Packet.SdStatusBlk = &SdStatusBlk;
2126 Packet.Timeout = SD_TIMEOUT;
2127
2128 SdCmdBlk.CommandIndex = SD_SELECT_DESELECT_CARD;
2129 SdCmdBlk.CommandType = SdCommandTypeAc;
2130 SdCmdBlk.ResponseType = SdResponseTypeR1b;
2131 SdCmdBlk.CommandArgument = (UINT32)Rca << 16;
2132
2133 Status = SdPeimExecCmd (Slot, &Packet);
2134
2135 return Status;
2136}
2137
2151 IN SD_PEIM_HC_SLOT *Slot
2152 )
2153{
2154 SD_COMMAND_BLOCK SdCmdBlk;
2155 SD_STATUS_BLOCK SdStatusBlk;
2156 SD_COMMAND_PACKET Packet;
2157 EFI_STATUS Status;
2158
2159 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));
2160 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));
2161 ZeroMem (&Packet, sizeof (Packet));
2162
2163 Packet.SdCmdBlk = &SdCmdBlk;
2164 Packet.SdStatusBlk = &SdStatusBlk;
2165 Packet.Timeout = SD_TIMEOUT;
2166
2167 SdCmdBlk.CommandIndex = SD_VOLTAGE_SWITCH;
2168 SdCmdBlk.CommandType = SdCommandTypeAc;
2169 SdCmdBlk.ResponseType = SdResponseTypeR1;
2170 SdCmdBlk.CommandArgument = 0;
2171
2172 Status = SdPeimExecCmd (Slot, &Packet);
2173
2174 return Status;
2175}
2176
2192 IN SD_PEIM_HC_SLOT *Slot,
2193 IN UINT16 Rca,
2194 IN UINT8 BusWidth
2195 )
2196{
2197 SD_COMMAND_BLOCK SdCmdBlk;
2198 SD_STATUS_BLOCK SdStatusBlk;
2199 SD_COMMAND_PACKET Packet;
2200 EFI_STATUS Status;
2201 UINT8 Value;
2202
2203 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));
2204 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));
2205 ZeroMem (&Packet, sizeof (Packet));
2206
2207 Packet.SdCmdBlk = &SdCmdBlk;
2208 Packet.SdStatusBlk = &SdStatusBlk;
2209 Packet.Timeout = SD_TIMEOUT;
2210
2211 SdCmdBlk.CommandIndex = SD_APP_CMD;
2212 SdCmdBlk.CommandType = SdCommandTypeAc;
2213 SdCmdBlk.ResponseType = SdResponseTypeR1;
2214 SdCmdBlk.CommandArgument = (UINT32)Rca << 16;
2215
2216 Status = SdPeimExecCmd (Slot, &Packet);
2217 if (EFI_ERROR (Status)) {
2218 return Status;
2219 }
2220
2221 SdCmdBlk.CommandIndex = SD_SET_BUS_WIDTH;
2222 SdCmdBlk.CommandType = SdCommandTypeAc;
2223 SdCmdBlk.ResponseType = SdResponseTypeR1;
2224
2225 if (BusWidth == 1) {
2226 Value = 0;
2227 } else if (BusWidth == 4) {
2228 Value = 2;
2229 } else {
2230 return EFI_INVALID_PARAMETER;
2231 }
2232
2233 SdCmdBlk.CommandArgument = Value & 0x3;
2234
2235 Status = SdPeimExecCmd (Slot, &Packet);
2236
2237 return Status;
2238}
2239
2259 IN SD_PEIM_HC_SLOT *Slot,
2260 IN UINT8 AccessMode,
2261 IN UINT8 CommandSystem,
2262 IN UINT8 DriveStrength,
2263 IN UINT8 PowerLimit,
2264 IN BOOLEAN Mode,
2265 OUT UINT8 *SwitchResp
2266 )
2267{
2268 SD_COMMAND_BLOCK SdCmdBlk;
2269 SD_STATUS_BLOCK SdStatusBlk;
2270 SD_COMMAND_PACKET Packet;
2271 EFI_STATUS Status;
2272 UINT32 ModeValue;
2273
2274 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));
2275 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));
2276 ZeroMem (&Packet, sizeof (Packet));
2277
2278 Packet.SdCmdBlk = &SdCmdBlk;
2279 Packet.SdStatusBlk = &SdStatusBlk;
2280 Packet.Timeout = SD_TIMEOUT;
2281
2282 SdCmdBlk.CommandIndex = SD_SWITCH_FUNC;
2283 SdCmdBlk.CommandType = SdCommandTypeAdtc;
2284 SdCmdBlk.ResponseType = SdResponseTypeR1;
2285
2286 ModeValue = Mode ? BIT31 : 0;
2287 SdCmdBlk.CommandArgument = (AccessMode & 0xF) | ((PowerLimit & 0xF) << 4) | \
2288 ((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) << 12) | \
2289 ModeValue;
2290 Packet.InDataBuffer = SwitchResp;
2291 Packet.InTransferLength = 64;
2292
2293 Status = SdPeimExecCmd (Slot, &Packet);
2294
2295 return Status;
2296}
2297
2313 IN SD_PEIM_HC_SLOT *Slot,
2314 IN UINT16 Rca,
2315 OUT UINT32 *DevStatus
2316 )
2317{
2318 SD_COMMAND_BLOCK SdCmdBlk;
2319 SD_STATUS_BLOCK SdStatusBlk;
2320 SD_COMMAND_PACKET Packet;
2321 EFI_STATUS Status;
2322
2323 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));
2324 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));
2325 ZeroMem (&Packet, sizeof (Packet));
2326
2327 Packet.SdCmdBlk = &SdCmdBlk;
2328 Packet.SdStatusBlk = &SdStatusBlk;
2329 Packet.Timeout = SD_TIMEOUT;
2330
2331 SdCmdBlk.CommandIndex = SD_SEND_STATUS;
2332 SdCmdBlk.CommandType = SdCommandTypeAc;
2333 SdCmdBlk.ResponseType = SdResponseTypeR1;
2334 SdCmdBlk.CommandArgument = (UINT32)Rca << 16;
2335
2336 Status = SdPeimExecCmd (Slot, &Packet);
2337 if (!EFI_ERROR (Status)) {
2338 *DevStatus = SdStatusBlk.Resp0;
2339 }
2340
2341 return Status;
2342}
2343
2363 IN SD_PEIM_HC_SLOT *Slot,
2364 IN EFI_LBA Lba,
2365 IN UINT32 BlockSize,
2366 IN VOID *Buffer,
2367 IN UINTN BufferSize,
2368 IN BOOLEAN IsRead
2369 )
2370{
2371 SD_COMMAND_BLOCK SdCmdBlk;
2372 SD_STATUS_BLOCK SdStatusBlk;
2373 SD_COMMAND_PACKET Packet;
2374 EFI_STATUS Status;
2375
2376 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));
2377 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));
2378 ZeroMem (&Packet, sizeof (Packet));
2379
2380 Packet.SdCmdBlk = &SdCmdBlk;
2381 Packet.SdStatusBlk = &SdStatusBlk;
2382 //
2383 // Calculate timeout value through the below formula.
2384 // Timeout = (transfer size) / (2MB/s).
2385 // Taking 2MB/s as divisor is because it's the lowest
2386 // transfer speed of class 2.
2387 //
2388 Packet.Timeout = (BufferSize / (2 * 1024 * 1024) + 1) * 1000 * 1000;
2389
2390 if (IsRead) {
2391 Packet.InDataBuffer = Buffer;
2392 Packet.InTransferLength = (UINT32)BufferSize;
2393
2394 SdCmdBlk.CommandIndex = SD_READ_SINGLE_BLOCK;
2395 SdCmdBlk.CommandType = SdCommandTypeAdtc;
2396 SdCmdBlk.ResponseType = SdResponseTypeR1;
2397 } else {
2398 Packet.OutDataBuffer = Buffer;
2399 Packet.OutTransferLength = (UINT32)BufferSize;
2400
2401 SdCmdBlk.CommandIndex = SD_WRITE_SINGLE_BLOCK;
2402 SdCmdBlk.CommandType = SdCommandTypeAdtc;
2403 SdCmdBlk.ResponseType = SdResponseTypeR1;
2404 }
2405
2406 if (Slot->SectorAddressing) {
2407 SdCmdBlk.CommandArgument = (UINT32)Lba;
2408 } else {
2409 SdCmdBlk.CommandArgument = (UINT32)MultU64x32 (Lba, BlockSize);
2410 }
2411
2412 Status = SdPeimExecCmd (Slot, &Packet);
2413
2414 return Status;
2415}
2416
2436 IN SD_PEIM_HC_SLOT *Slot,
2437 IN EFI_LBA Lba,
2438 IN UINT32 BlockSize,
2439 IN VOID *Buffer,
2440 IN UINTN BufferSize,
2441 IN BOOLEAN IsRead
2442 )
2443{
2444 SD_COMMAND_BLOCK SdCmdBlk;
2445 SD_STATUS_BLOCK SdStatusBlk;
2446 SD_COMMAND_PACKET Packet;
2447 EFI_STATUS Status;
2448
2449 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));
2450 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));
2451 ZeroMem (&Packet, sizeof (Packet));
2452
2453 Packet.SdCmdBlk = &SdCmdBlk;
2454 Packet.SdStatusBlk = &SdStatusBlk;
2455 //
2456 // Calculate timeout value through the below formula.
2457 // Timeout = (transfer size) / (2MB/s).
2458 // Taking 2MB/s as divisor is because it's the lowest
2459 // transfer speed of class 2.
2460 //
2461 Packet.Timeout = (BufferSize / (2 * 1024 * 1024) + 1) * 1000 * 1000;
2462
2463 if (IsRead) {
2464 Packet.InDataBuffer = Buffer;
2465 Packet.InTransferLength = (UINT32)BufferSize;
2466
2467 SdCmdBlk.CommandIndex = SD_READ_MULTIPLE_BLOCK;
2468 SdCmdBlk.CommandType = SdCommandTypeAdtc;
2469 SdCmdBlk.ResponseType = SdResponseTypeR1;
2470 } else {
2471 Packet.OutDataBuffer = Buffer;
2472 Packet.OutTransferLength = (UINT32)BufferSize;
2473
2474 SdCmdBlk.CommandIndex = SD_WRITE_MULTIPLE_BLOCK;
2475 SdCmdBlk.CommandType = SdCommandTypeAdtc;
2476 SdCmdBlk.ResponseType = SdResponseTypeR1;
2477 }
2478
2479 if (Slot->SectorAddressing) {
2480 SdCmdBlk.CommandArgument = (UINT32)Lba;
2481 } else {
2482 SdCmdBlk.CommandArgument = (UINT32)MultU64x32 (Lba, BlockSize);
2483 }
2484
2485 Status = SdPeimExecCmd (Slot, &Packet);
2486
2487 return Status;
2488}
2489
2506 IN SD_PEIM_HC_SLOT *Slot
2507 )
2508{
2509 SD_COMMAND_BLOCK SdCmdBlk;
2510 SD_STATUS_BLOCK SdStatusBlk;
2511 SD_COMMAND_PACKET Packet;
2512 EFI_STATUS Status;
2513 UINT8 TuningBlock[64];
2514
2515 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));
2516 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));
2517 ZeroMem (&Packet, sizeof (Packet));
2518
2519 Packet.SdCmdBlk = &SdCmdBlk;
2520 Packet.SdStatusBlk = &SdStatusBlk;
2521 Packet.Timeout = SD_TIMEOUT;
2522
2523 SdCmdBlk.CommandIndex = SD_SEND_TUNING_BLOCK;
2524 SdCmdBlk.CommandType = SdCommandTypeAdtc;
2525 SdCmdBlk.ResponseType = SdResponseTypeR1;
2526 SdCmdBlk.CommandArgument = 0;
2527
2528 Packet.InDataBuffer = TuningBlock;
2529 Packet.InTransferLength = sizeof (TuningBlock);
2530
2531 Status = SdPeimExecCmd (Slot, &Packet);
2532
2533 return Status;
2534}
2535
2553 IN SD_PEIM_HC_SLOT *Slot
2554 )
2555{
2556 EFI_STATUS Status;
2557 UINT8 HostCtrl2;
2558 UINT8 Retry;
2559
2560 //
2561 // Notify the host that the sampling clock tuning procedure starts.
2562 //
2563 HostCtrl2 = BIT6;
2564 Status = SdPeimHcOrMmio (Slot->SdHcBase + SD_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
2565 if (EFI_ERROR (Status)) {
2566 return Status;
2567 }
2568
2569 //
2570 // Ask the device to send a sequence of tuning blocks till the tuning procedure is done.
2571 //
2572 Retry = 0;
2573 do {
2574 Status = SdPeimSendTuningBlk (Slot);
2575 if (EFI_ERROR (Status)) {
2576 return Status;
2577 }
2578
2579 Status = SdPeimHcRwMmio (Slot->SdHcBase + SD_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);
2580 if (EFI_ERROR (Status)) {
2581 return Status;
2582 }
2583
2584 if ((HostCtrl2 & (BIT6 | BIT7)) == 0) {
2585 break;
2586 }
2587
2588 if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) {
2589 return EFI_SUCCESS;
2590 }
2591 } while (++Retry < 40);
2592
2593 DEBUG ((DEBUG_ERROR, "SdPeimTuningClock: Send tuning block fails at %d times with HostCtrl2 %02x\n", Retry, HostCtrl2));
2594 //
2595 // Abort the tuning procedure and reset the tuning circuit.
2596 //
2597 HostCtrl2 = (UINT8) ~(BIT6 | BIT7);
2598 Status = SdPeimHcAndMmio (Slot->SdHcBase + SD_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
2599 if (EFI_ERROR (Status)) {
2600 return Status;
2601 }
2602
2603 return EFI_DEVICE_ERROR;
2604}
2605
2622 IN SD_PEIM_HC_SLOT *Slot,
2623 IN UINT16 Rca,
2624 IN UINT8 BusWidth
2625 )
2626{
2627 EFI_STATUS Status;
2628 UINT32 DevStatus;
2629
2630 Status = SdPeimSetBusWidth (Slot, Rca, BusWidth);
2631 if (EFI_ERROR (Status)) {
2632 return Status;
2633 }
2634
2635 Status = SdPeimSendStatus (Slot, Rca, &DevStatus);
2636 if (EFI_ERROR (Status)) {
2637 return Status;
2638 }
2639
2640 //
2641 // Check the switch operation is really successful or not.
2642 //
2643 if ((DevStatus >> 16) != 0) {
2644 return EFI_DEVICE_ERROR;
2645 }
2646
2647 Status = SdPeimHcSetBusWidth (Slot->SdHcBase, BusWidth);
2648
2649 return Status;
2650}
2651
2668 IN SD_PEIM_HC_SLOT *Slot,
2669 IN UINT16 Rca,
2670 IN BOOLEAN S18a
2671 )
2672{
2673 EFI_STATUS Status;
2674 SD_HC_SLOT_CAP Capability;
2675 UINT32 ClockFreq;
2676 UINT8 BusWidth;
2677 UINT8 AccessMode;
2678 UINT8 HostCtrl1;
2679 UINT8 HostCtrl2;
2680 UINT8 SwitchResp[64];
2681
2682 Status = SdPeimGetCsd (Slot, Rca, &Slot->Csd);
2683 if (EFI_ERROR (Status)) {
2684 DEBUG ((DEBUG_ERROR, "SdPeimSetBusMode: SdPeimGetCsd fails with %r\n", Status));
2685 return Status;
2686 }
2687
2688 Status = SdPeimHcGetCapability (Slot->SdHcBase, &Capability);
2689 if (EFI_ERROR (Status)) {
2690 return Status;
2691 }
2692
2693 Status = SdPeimSelect (Slot, Rca);
2694 if (EFI_ERROR (Status)) {
2695 DEBUG ((DEBUG_ERROR, "SdPeimSetBusMode: SdPeimSelect fails with %r\n", Status));
2696 return Status;
2697 }
2698
2699 BusWidth = 4;
2700 Status = SdPeimSwitchBusWidth (Slot, Rca, BusWidth);
2701 if (EFI_ERROR (Status)) {
2702 DEBUG ((DEBUG_ERROR, "SdPeimSetBusMode: SdPeimSwitchBusWidth fails with %r\n", Status));
2703 return Status;
2704 }
2705
2706 //
2707 // Get the supported bus speed from SWITCH cmd return data group #1.
2708 //
2709 ZeroMem (SwitchResp, sizeof (SwitchResp));
2710 Status = SdPeimSwitch (Slot, 0xF, 0xF, 0xF, 0xF, FALSE, SwitchResp);
2711 if (EFI_ERROR (Status)) {
2712 return Status;
2713 }
2714
2715 //
2716 // Calculate supported bus speed/bus width/clock frequency by host and device capability.
2717 //
2718 ClockFreq = 0;
2719 if (S18a && (Capability.Sdr104 != 0) && ((SwitchResp[13] & BIT3) != 0)) {
2720 ClockFreq = 208;
2721 AccessMode = 3;
2722 } else if (S18a && (Capability.Sdr50 != 0) && ((SwitchResp[13] & BIT2) != 0)) {
2723 ClockFreq = 100;
2724 AccessMode = 2;
2725 } else if (S18a && (Capability.Ddr50 != 0) && ((SwitchResp[13] & BIT4) != 0)) {
2726 ClockFreq = 50;
2727 AccessMode = 4;
2728 } else if ((SwitchResp[13] & BIT1) != 0) {
2729 ClockFreq = 50;
2730 AccessMode = 1;
2731 } else {
2732 ClockFreq = 25;
2733 AccessMode = 0;
2734 }
2735
2736 DEBUG ((DEBUG_INFO, "SdPeimSetBusMode: AccessMode %d ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));
2737
2738 Status = SdPeimSwitch (Slot, AccessMode, 0xF, 0xF, 0xF, TRUE, SwitchResp);
2739 if (EFI_ERROR (Status)) {
2740 DEBUG ((DEBUG_ERROR, "SdPeimSetBusMode: SdPeimSwitch fails with %r\n", Status));
2741 return Status;
2742 }
2743
2744 if ((SwitchResp[16] & 0xF) != AccessMode) {
2745 DEBUG ((DEBUG_ERROR, "SdPeimSetBusMode: SdPeimSwitch to AccessMode %d ClockFreq %d BusWidth %d fails! The Switch response is 0x%1x\n", AccessMode, ClockFreq, BusWidth, SwitchResp[16] & 0xF));
2746 return EFI_DEVICE_ERROR;
2747 }
2748
2749 //
2750 // Set to High Speed timing
2751 //
2752 if (AccessMode == 1) {
2753 HostCtrl1 = BIT2;
2754 Status = SdPeimHcOrMmio (Slot->SdHcBase + SD_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);
2755 if (EFI_ERROR (Status)) {
2756 return Status;
2757 }
2758 }
2759
2760 HostCtrl2 = (UINT8) ~0x7;
2761 Status = SdPeimHcAndMmio (Slot->SdHcBase + SD_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
2762 if (EFI_ERROR (Status)) {
2763 return Status;
2764 }
2765
2766 HostCtrl2 = AccessMode;
2767 Status = SdPeimHcOrMmio (Slot->SdHcBase + SD_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
2768 if (EFI_ERROR (Status)) {
2769 return Status;
2770 }
2771
2772 Status = SdPeimHcClockSupply (Slot->SdHcBase, ClockFreq * 1000);
2773 if (EFI_ERROR (Status)) {
2774 DEBUG ((DEBUG_ERROR, "SdPeimSetBusMode: SdPeimHcClockSupply %r\n", Status));
2775 return Status;
2776 }
2777
2778 if ((AccessMode == 3) || ((AccessMode == 2) && (Capability.TuningSDR50 != 0))) {
2779 Status = SdPeimTuningClock (Slot);
2780 if (EFI_ERROR (Status)) {
2781 DEBUG ((DEBUG_ERROR, "SdPeimSetBusMode: SdPeimTuningClock fails with %r\n", Status));
2782 return Status;
2783 }
2784 }
2785
2786 DEBUG ((DEBUG_INFO, "SdPeimSetBusMode: SdPeimSetBusMode %r\n", Status));
2787
2788 return Status;
2789}
2790
2804 IN SD_PEIM_HC_SLOT *Slot
2805 )
2806{
2807 EFI_STATUS Status;
2808 UINT32 Ocr;
2809 UINT16 Rca;
2810 BOOLEAN Xpc;
2811 BOOLEAN S18r;
2812 UINT64 MaxCurrent;
2813 UINT64 Current;
2814 UINT16 ControllerVer;
2815 UINT8 PowerCtrl;
2816 UINT32 PresentState;
2817 UINT8 HostCtrl2;
2818 SD_HC_SLOT_CAP Capability;
2819 UINTN Retry;
2820
2821 //
2822 // 1. Send Cmd0 to the device
2823 //
2824 Status = SdPeimReset (Slot);
2825 if (EFI_ERROR (Status)) {
2826 DEBUG ((DEBUG_ERROR, "SdPeimIdentification: Executing Cmd0 fails with %r\n", Status));
2827 return Status;
2828 }
2829
2830 //
2831 // 2. Send Cmd8 to the device
2832 //
2833 Status = SdPeimVoltageCheck (Slot, 0x1, 0xFF);
2834 if (EFI_ERROR (Status)) {
2835 DEBUG ((DEBUG_ERROR, "SdPeimIdentification: Executing Cmd8 fails with %r\n", Status));
2836 return Status;
2837 }
2838
2839 //
2840 // 3. Send SDIO Cmd5 to the device to the SDIO device OCR register.
2841 //
2842 Status = SdioSendOpCond (Slot, 0, FALSE);
2843 if (!EFI_ERROR (Status)) {
2844 DEBUG ((DEBUG_ERROR, "SdPeimIdentification: Found SDIO device, ignore it as we don't support\n"));
2845 return EFI_DEVICE_ERROR;
2846 }
2847
2848 //
2849 // 4. Send Acmd41 with voltage window 0 to the device
2850 //
2851 Status = SdPeimSendOpCond (Slot, 0, 0, FALSE, FALSE, FALSE, &Ocr);
2852 if (EFI_ERROR (Status)) {
2853 DEBUG ((DEBUG_ERROR, "SdPeimIdentification: Executing SdPeimSendOpCond fails with %r\n", Status));
2854 return EFI_DEVICE_ERROR;
2855 }
2856
2857 Status = SdPeimHcGetCapability (Slot->SdHcBase, &Capability);
2858 if (EFI_ERROR (Status)) {
2859 return Status;
2860 }
2861
2862 Status = SdPeimHcRwMmio (Slot->SdHcBase + SD_HC_MAX_CURRENT_CAP, TRUE, sizeof (Current), &Current);
2863 if (EFI_ERROR (Status)) {
2864 return Status;
2865 }
2866
2867 if (Capability.Voltage33 != 0) {
2868 //
2869 // Support 3.3V
2870 //
2871 MaxCurrent = ((UINT32)Current & 0xFF) * 4;
2872 } else if (Capability.Voltage30 != 0) {
2873 //
2874 // Support 3.0V
2875 //
2876 MaxCurrent = (((UINT32)Current >> 8) & 0xFF) * 4;
2877 } else if (Capability.Voltage18 != 0) {
2878 //
2879 // Support 1.8V
2880 //
2881 MaxCurrent = (((UINT32)Current >> 16) & 0xFF) * 4;
2882 } else {
2883 ASSERT (FALSE);
2884 return EFI_DEVICE_ERROR;
2885 }
2886
2887 if (MaxCurrent >= 150) {
2888 Xpc = TRUE;
2889 } else {
2890 Xpc = FALSE;
2891 }
2892
2893 Status = SdPeimHcRwMmio (Slot->SdHcBase + SD_HC_CTRL_VER, TRUE, sizeof (ControllerVer), &ControllerVer);
2894 if (EFI_ERROR (Status)) {
2895 return Status;
2896 }
2897
2898 if ((ControllerVer & 0xFF) == 2) {
2899 S18r = TRUE;
2900 } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {
2901 S18r = FALSE;
2902 } else {
2903 ASSERT (FALSE);
2904 return EFI_UNSUPPORTED;
2905 }
2906
2907 //
2908 // 5. Repeatly send Acmd41 with supply voltage window to the device.
2909 // Note here we only support the cards complied with SD physical
2910 // layer simplified spec version 2.0 and version 3.0 and above.
2911 //
2912 Ocr = 0;
2913 Retry = 0;
2914 do {
2915 Status = SdPeimSendOpCond (Slot, 0, Ocr, S18r, Xpc, TRUE, &Ocr);
2916 if (EFI_ERROR (Status)) {
2917 DEBUG ((DEBUG_ERROR, "SdPeimIdentification: SdPeimSendOpCond fails with %r Ocr %x, S18r %x, Xpc %x\n", Status, Ocr, S18r, Xpc));
2918 return EFI_DEVICE_ERROR;
2919 }
2920
2921 if (Retry++ == 100) {
2922 DEBUG ((DEBUG_ERROR, "SdPeimIdentification: SdPeimSendOpCond fails too many times\n"));
2923 return EFI_DEVICE_ERROR;
2924 }
2925
2926 MicroSecondDelay (10 * 1000);
2927 } while ((Ocr & BIT31) == 0);
2928
2929 //
2930 // 6. If the S18a bit is set and the Host Controller supports 1.8V signaling
2931 // (One of support bits is set to 1: SDR50, SDR104 or DDR50 in the
2932 // Capabilities register), switch its voltage to 1.8V.
2933 //
2934 if (((Capability.Sdr50 != 0) ||
2935 (Capability.Sdr104 != 0) ||
2936 (Capability.Ddr50 != 0)) &&
2937 ((Ocr & BIT24) != 0))
2938 {
2939 Status = SdPeimVoltageSwitch (Slot);
2940 if (EFI_ERROR (Status)) {
2941 DEBUG ((DEBUG_ERROR, "SdPeimIdentification: Executing SdPeimVoltageSwitch fails with %r\n", Status));
2942 Status = EFI_DEVICE_ERROR;
2943 goto Error;
2944 } else {
2945 Status = SdPeimHcStopClock (Slot->SdHcBase);
2946 if (EFI_ERROR (Status)) {
2947 Status = EFI_DEVICE_ERROR;
2948 goto Error;
2949 }
2950
2951 SdPeimHcRwMmio (Slot->SdHcBase + SD_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);
2952 if (((PresentState >> 20) & 0xF) != 0) {
2953 DEBUG ((DEBUG_ERROR, "SdPeimIdentification: SwitchVoltage fails with PresentState = 0x%x\n", PresentState));
2954 Status = EFI_DEVICE_ERROR;
2955 goto Error;
2956 }
2957
2958 HostCtrl2 = BIT3;
2959 SdPeimHcOrMmio (Slot->SdHcBase + SD_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
2960
2961 MicroSecondDelay (5000);
2962
2963 SdPeimHcRwMmio (Slot->SdHcBase + SD_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);
2964 if ((HostCtrl2 & BIT3) == 0) {
2965 DEBUG ((DEBUG_ERROR, "SdPeimIdentification: SwitchVoltage fails with HostCtrl2 = 0x%x\n", HostCtrl2));
2966 Status = EFI_DEVICE_ERROR;
2967 goto Error;
2968 }
2969
2970 SdPeimHcInitClockFreq (Slot->SdHcBase);
2971
2972 MicroSecondDelay (1000);
2973
2974 SdPeimHcRwMmio (Slot->SdHcBase + SD_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);
2975 if (((PresentState >> 20) & 0xF) != 0xF) {
2976 DEBUG ((DEBUG_ERROR, "SdPeimIdentification: SwitchVoltage fails with PresentState = 0x%x, It should be 0xF\n", PresentState));
2977 Status = EFI_DEVICE_ERROR;
2978 goto Error;
2979 }
2980 }
2981
2982 DEBUG ((DEBUG_INFO, "SdPeimIdentification: Switch to 1.8v signal voltage success\n"));
2983 }
2984
2985 Status = SdPeimAllSendCid (Slot);
2986 if (EFI_ERROR (Status)) {
2987 DEBUG ((DEBUG_ERROR, "SdPeimIdentification: Executing SdPeimAllSendCid fails with %r\n", Status));
2988 return Status;
2989 }
2990
2991 Status = SdPeimSetRca (Slot, &Rca);
2992 if (EFI_ERROR (Status)) {
2993 DEBUG ((DEBUG_ERROR, "SdPeimIdentification: Executing SdPeimSetRca fails with %r\n", Status));
2994 return Status;
2995 }
2996
2997 //
2998 // Enter Data Tranfer Mode.
2999 //
3000 DEBUG ((DEBUG_INFO, "Found a SD device at slot [%d]\n", Slot));
3001
3002 Status = SdPeimSetBusMode (Slot, Rca, ((Ocr & BIT24) != 0));
3003
3004 return Status;
3005
3006Error:
3007 //
3008 // Set SD Bus Power = 0
3009 //
3010 PowerCtrl = (UINT8) ~BIT0;
3011 Status = SdPeimHcAndMmio (Slot->SdHcBase + SD_HC_POWER_CTRL, sizeof (PowerCtrl), &PowerCtrl);
3012 return EFI_DEVICE_ERROR;
3013}
UINT64 UINTN
EFI_STATUS IoMmuUnmap(IN VOID *Mapping)
Definition: DmaMem.c:132
EFI_STATUS IoMmuMap(IN EDKII_IOMMU_OPERATION Operation, IN VOID *HostAddress, IN OUT UINTN *NumberOfBytes, OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, OUT VOID **Mapping)
Definition: DmaMem.c:60
UINTN EFIAPI MicroSecondDelay(IN UINTN MicroSeconds)
UINT64 EFIAPI DivU64x32(IN UINT64 Dividend, IN UINT32 Divisor)
Definition: DivU64x32.c:29
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
Definition: MultU64x32.c:27
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: LShiftU64.c:28
INTN EFIAPI HighBitSet32(IN UINT32 Operand)
Definition: HighBitSet32.c:27
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
UINT64 EFIAPI MmioWrite64(IN UINTN Address, IN UINT64 Value)
Definition: IoLib.c:400
UINT64 EFIAPI MmioRead64(IN UINTN Address)
Definition: IoLib.c:355
UINT16 EFIAPI MmioRead16(IN UINTN Address)
Definition: IoLib.c:170
UINT8 EFIAPI MmioRead8(IN UINTN Address)
Definition: IoLib.c:82
UINT8 EFIAPI MmioWrite8(IN UINTN Address, IN UINT8 Value)
Definition: IoLib.c:126
UINT32 EFIAPI MmioRead32(IN UINTN Address)
Definition: IoLib.c:262
UINT16 EFIAPI MmioWrite16(IN UINTN Address, IN UINT16 Value)
Definition: IoLib.c:216
UINT32 EFIAPI MmioWrite32(IN UINTN Address, IN UINT32 Value)
Definition: IoLib.c:309
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
EDKII_IOMMU_OPERATION
Definition: IoMmu.h:44
@ EdkiiIoMmuOperationBusMasterWrite
Definition: IoMmu.h:54
@ EdkiiIoMmuOperationBusMasterRead
Definition: IoMmu.h:49
VOID SdPeimFreeMem(IN SD_PEIM_MEM_POOL *Pool, IN VOID *Mem, IN UINTN Size)
Definition: SdHcMem.c:366
VOID * SdPeimAllocateMem(IN SD_PEIM_MEM_POOL *Pool, IN UINTN Size)
Definition: SdHcMem.c:294
EFI_STATUS SdPeimHcSetBusWidth(IN UINTN Bar, IN UINT16 BusWidth)
Definition: SdHci.c:687
EFI_STATUS SdPeimVoltageCheck(IN SD_PEIM_HC_SLOT *Slot, IN UINT8 SupplyVoltage, IN UINT8 CheckPattern)
Definition: SdHci.c:1805
EFI_STATUS SdPeimHcStopClock(IN UINTN Bar)
Definition: SdHci.c:468
EFI_STATUS EFIAPI SdPeimHcRwMmio(IN UINTN Address, IN BOOLEAN Read, IN UINT8 Count, IN OUT VOID *Data)
Definition: SdHci.c:30
EFI_STATUS SdPeimGetCsd(IN SD_PEIM_HC_SLOT *Slot, IN UINT16 Rca, OUT SD_CSD *Csd)
Definition: SdHci.c:2062
EFI_STATUS EFIAPI SdPeimHcWaitMmioSet(IN UINTN Address, IN UINT8 Count, IN UINT64 MaskValue, IN UINT64 TestValue, IN UINT64 Timeout)
Definition: SdHci.c:251
EFI_STATUS SdPeimWaitTrbResult(IN UINTN Bar, IN SD_TRB *Trb)
Definition: SdHci.c:1628
EFI_STATUS SdPeimCheckTrbResult(IN UINTN Bar, IN SD_TRB *Trb)
Definition: SdHci.c:1410
EFI_STATUS SdPeimTuningClock(IN SD_PEIM_HC_SLOT *Slot)
Definition: SdHci.c:2552
EFI_STATUS SdPeimReset(IN SD_PEIM_HC_SLOT *Slot)
Definition: SdHci.c:1763
SD_TRB * SdPeimCreateTrb(IN SD_PEIM_HC_SLOT *Slot, IN SD_COMMAND_PACKET *Packet)
Definition: SdHci.c:1003
EFI_STATUS SdPeimHcClockSupply(IN UINTN Bar, IN UINT64 ClockFreq)
Definition: SdHci.c:514
EFI_STATUS SdPeimExecTrb(IN UINTN Bar, IN SD_TRB *Trb)
Definition: SdHci.c:1232
EFI_STATUS SdPeimHcCardDetect(IN UINTN Bar)
Definition: SdHci.c:414
EFI_STATUS SdPeimHcInitHost(IN UINTN Bar)
Definition: SdHci.c:868
EFI_STATUS SdPeimHcInitClockFreq(IN UINTN Bar)
Definition: SdHci.c:734
EFI_STATUS SdPeimSelect(IN SD_PEIM_HC_SLOT *Slot, IN UINT16 Rca)
Definition: SdHci.c:2110
EFI_STATUS SdPeimHcPowerControl(IN UINTN Bar, IN UINT8 PowerCtrl)
Definition: SdHci.c:649
EFI_STATUS SdPeimSetBusMode(IN SD_PEIM_HC_SLOT *Slot, IN UINT16 Rca, IN BOOLEAN S18a)
Definition: SdHci.c:2667
EFI_STATUS SdPeimVoltageSwitch(IN SD_PEIM_HC_SLOT *Slot)
Definition: SdHci.c:2150
EFI_STATUS SdPeimHcInitTimeoutCtrl(IN UINTN Bar)
Definition: SdHci.c:844
EFI_STATUS SdPeimHcEnableInterrupt(IN UINTN Bar)
Definition: SdHci.c:346
EFI_STATUS SdPeimSendTuningBlk(IN SD_PEIM_HC_SLOT *Slot)
Definition: SdHci.c:2505
EFI_STATUS SdioSendOpCond(IN SD_PEIM_HC_SLOT *Slot, IN UINT32 VoltageWindow, IN BOOLEAN S18r)
Definition: SdHci.c:1853
EFI_STATUS SdPeimRwMultiBlocks(IN SD_PEIM_HC_SLOT *Slot, IN EFI_LBA Lba, IN UINT32 BlockSize, IN VOID *Buffer, IN UINTN BufferSize, IN BOOLEAN IsRead)
Definition: SdHci.c:2435
EFI_STATUS SdPeimSendOpCond(IN SD_PEIM_HC_SLOT *Slot, IN UINT16 Rca, IN UINT32 VoltageWindow, IN BOOLEAN S18r, IN BOOLEAN Xpc, IN BOOLEAN Hcs, OUT UINT32 *Ocr)
Definition: SdHci.c:1905
EFI_STATUS SdPeimCheckTrbEnv(IN UINTN Bar, IN SD_TRB *Trb)
Definition: SdHci.c:1130
EFI_STATUS SdPeimSwitchBusWidth(IN SD_PEIM_HC_SLOT *Slot, IN UINT16 Rca, IN UINT8 BusWidth)
Definition: SdHci.c:2621
EFI_STATUS EFIAPI SdPeimHcOrMmio(IN UINTN Address, IN UINT8 Count, IN VOID *OrData)
Definition: SdHci.c:104
EFI_STATUS SdPeimAllSendCid(IN SD_PEIM_HC_SLOT *Slot)
Definition: SdHci.c:1974
EFI_STATUS SdPeimSetRca(IN SD_PEIM_HC_SLOT *Slot, OUT UINT16 *Rca)
Definition: SdHci.c:2015
EFI_STATUS EFIAPI SdPeimHcCheckMmioSet(IN UINTN Address, IN UINT8 Count, IN UINT64 MaskValue, IN UINT64 TestValue)
Definition: SdHci.c:204
EFI_STATUS SdPeimHcReset(IN UINTN Bar)
Definition: SdHci.c:300
EFI_STATUS SdPeimIdentification(IN SD_PEIM_HC_SLOT *Slot)
Definition: SdHci.c:2803
EFI_STATUS SdPeimSendStatus(IN SD_PEIM_HC_SLOT *Slot, IN UINT16 Rca, OUT UINT32 *DevStatus)
Definition: SdHci.c:2312
EFI_STATUS SdPeimSetBusWidth(IN SD_PEIM_HC_SLOT *Slot, IN UINT16 Rca, IN UINT8 BusWidth)
Definition: SdHci.c:2191
EFI_STATUS BuildAdmaDescTable(IN SD_TRB *Trb)
Definition: SdHci.c:930
EFI_STATUS SdPeimWaitTrbEnv(IN UINTN Bar, IN SD_TRB *Trb)
Definition: SdHci.c:1180
VOID SdPeimFreeTrb(IN SD_TRB *Trb)
Definition: SdHci.c:1099
EFI_STATUS EFIAPI SdPeimHcAndMmio(IN UINTN Address, IN UINT8 Count, IN VOID *AndData)
Definition: SdHci.c:155
EFI_STATUS SdPeimRwSingleBlock(IN SD_PEIM_HC_SLOT *Slot, IN EFI_LBA Lba, IN UINT32 BlockSize, IN VOID *Buffer, IN UINTN BufferSize, IN BOOLEAN IsRead)
Definition: SdHci.c:2362
EFI_STATUS SdPeimHcInitPowerVoltage(IN UINTN Bar)
Definition: SdHci.c:777
EFI_STATUS SdPeimSwitch(IN SD_PEIM_HC_SLOT *Slot, IN UINT8 AccessMode, IN UINT8 CommandSystem, IN UINT8 DriveStrength, IN UINT8 PowerLimit, IN BOOLEAN Mode, OUT UINT8 *SwitchResp)
Definition: SdHci.c:2258
EFI_STATUS SdPeimHcLedOnOff(IN UINTN Bar, IN BOOLEAN On)
Definition: SdHci.c:899
EFI_STATUS SdPeimHcGetCapability(IN UINTN Bar, OUT SD_HC_SLOT_CAP *Capability)
Definition: SdHci.c:382
EFI_STATUS EFIAPI SdPeimExecCmd(IN SD_PEIM_HC_SLOT *Slot, IN OUT SD_COMMAND_PACKET *Packet)
Definition: SdHci.c:1701
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
UINT64 EFI_LBA
Definition: UefiBaseType.h:45
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
Definition: Sd.h:78