TianoCore EDK2 master
Loading...
Searching...
No Matches
EmmcHci.c
Go to the documentation of this file.
1
8#include "EmmcBlockIoPei.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 = EmmcPeimHcRwMmio (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 = EmmcPeimHcRwMmio (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 = EmmcPeimHcRwMmio (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 = EmmcPeimHcRwMmio (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 = EmmcPeimHcRwMmio (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 = EmmcPeimHcCheckMmioSet (
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 = EmmcPeimHcRwMmio (Bar + EMMC_HC_SW_RST, FALSE, sizeof (SwReset), &SwReset);
309
310 if (EFI_ERROR (Status)) {
311 DEBUG ((DEBUG_ERROR, "EmmcPeimHcReset: write full 1 fails: %r\n", Status));
312 return Status;
313 }
314
315 Status = EmmcPeimHcWaitMmioSet (
316 Bar + EMMC_HC_SW_RST,
317 sizeof (SwReset),
318 0xFF,
319 0x00,
320 EMMC_TIMEOUT
321 );
322 if (EFI_ERROR (Status)) {
323 DEBUG ((DEBUG_INFO, "EmmcPeimHcReset: reset done with %r\n", Status));
324 return Status;
325 }
326
327 //
328 // Enable all interrupt after reset all.
329 //
330 Status = EmmcPeimHcEnableInterrupt (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 = EmmcPeimHcRwMmio (Bar + EMMC_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 = EmmcPeimHcRwMmio (Bar + EMMC_HC_NOR_INT_STS_EN, FALSE, sizeof (IntStatus), &IntStatus);
367
368 return Status;
369}
370
383 IN UINTN Bar,
384 OUT EMMC_HC_SLOT_CAP *Capability
385 )
386{
387 EFI_STATUS Status;
388 UINT64 Cap;
389
390 Status = EmmcPeimHcRwMmio (Bar + EMMC_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 = EmmcPeimHcRwMmio (Bar + EMMC_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 = EmmcPeimHcRwMmio (Bar + EMMC_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 = EmmcPeimHcRwMmio (Bar + EMMC_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 = EmmcPeimHcWaitMmioSet (
482 Bar + EMMC_HC_PRESENT_STATE,
483 sizeof (PresentState),
484 BIT0 | BIT1,
485 0,
486 EMMC_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 = EmmcPeimHcAndMmio (Bar + EMMC_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 EMMC_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 = EmmcPeimHcGetCapability (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 = EmmcPeimHcRwMmio (Bar + EMMC_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 = EmmcPeimHcStopClock (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 = EmmcPeimHcRwMmio (Bar + EMMC_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 = EmmcPeimHcWaitMmioSet (
617 Bar + EMMC_HC_CLOCK_CTRL,
618 sizeof (ClockCtrl),
619 BIT1,
620 BIT1,
621 EMMC_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 = EmmcPeimHcOrMmio (Bar + EMMC_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 = EmmcPeimHcRwMmio (Bar + EMMC_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 = EmmcPeimHcRwMmio (Bar + EMMC_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 = EmmcPeimHcAndMmio (Bar + EMMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);
698 } else if (BusWidth == 4) {
699 Status = EmmcPeimHcRwMmio (Bar + EMMC_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 = EmmcPeimHcRwMmio (Bar + EMMC_HC_HOST_CTRL1, FALSE, sizeof (HostCtrl1), &HostCtrl1);
707 } else if (BusWidth == 8) {
708 Status = EmmcPeimHcRwMmio (Bar + EMMC_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 = EmmcPeimHcRwMmio (Bar + EMMC_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 EMMC_HC_SLOT_CAP Capability;
740 UINT32 InitFreq;
741
742 //
743 // Calculate a divisor for SD clock frequency
744 //
745 Status = EmmcPeimHcGetCapability (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 = EmmcPeimHcClockSupply (Bar, InitFreq);
762 return Status;
763}
764
778 IN UINTN Bar
779 )
780{
781 EFI_STATUS Status;
782 EMMC_HC_SLOT_CAP Capability;
783 UINT8 MaxVoltage;
784 UINT8 HostCtrl2;
785
786 //
787 // Get the support voltage of the Host Controller
788 //
789 Status = EmmcPeimHcGetCapability (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 = EmmcPeimHcOrMmio (Bar + EMMC_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 = EmmcPeimHcPowerControl (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 = EmmcPeimHcRwMmio (Bar + EMMC_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 = EmmcPeimHcInitClockFreq (Bar);
875 if (EFI_ERROR (Status)) {
876 return Status;
877 }
878
879 Status = EmmcPeimHcInitPowerVoltage (Bar);
880 if (EFI_ERROR (Status)) {
881 return Status;
882 }
883
884 Status = EmmcPeimHcInitTimeoutCtrl (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 = EmmcPeimHcOrMmio (Bar + EMMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);
910 } else {
911 HostCtrl1 = (UINT8) ~BIT0;
912 Status = EmmcPeimHcAndMmio (Bar + EMMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);
913 }
914
915 return Status;
916}
917
931 IN EMMC_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 (EMMC_HC_ADMA_DESC_LINE));
961 Trb->AdmaDesc = EmmcPeimAllocateMem (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
1002EMMC_TRB *
1004 IN EMMC_PEIM_HC_SLOT *Slot,
1005 IN EMMC_COMMAND_PACKET *Packet
1006 )
1007{
1008 EMMC_TRB *Trb;
1009 EFI_STATUS Status;
1010 EMMC_HC_SLOT_CAP Capability;
1012 UINTN MapLength;
1013
1014 //
1015 // Calculate a divisor for SD clock frequency
1016 //
1017 Status = EmmcPeimHcGetCapability (Slot->EmmcHcBase, &Capability);
1018 if (EFI_ERROR (Status)) {
1019 return NULL;
1020 }
1021
1022 Trb = AllocateZeroPool (sizeof (EMMC_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->EmmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK) {
1052 Trb->Mode = EmmcPioMode;
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, "EmmcPeimCreateTrb: Fail to map data buffer.\n"));
1066 goto Error;
1067 }
1068 }
1069
1070 if (Trb->DataLen == 0) {
1071 Trb->Mode = EmmcNoData;
1072 } else if (Capability.Adma2 != 0) {
1073 Trb->Mode = EmmcAdmaMode;
1074 Status = BuildAdmaDescTable (Trb);
1075 if (EFI_ERROR (Status)) {
1076 goto Error;
1077 }
1078 } else if (Capability.Sdma != 0) {
1079 Trb->Mode = EmmcSdmaMode;
1080 } else {
1081 Trb->Mode = EmmcPioMode;
1082 }
1083 }
1084
1085 return Trb;
1086
1087Error:
1088 EmmcPeimFreeTrb (Trb);
1089 return NULL;
1090}
1091
1098VOID
1100 IN EMMC_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 EmmcPeimFreeMem (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 EMMC_TRB *Trb
1133 )
1134{
1135 EFI_STATUS Status;
1136 EMMC_COMMAND_PACKET *Packet;
1137 UINT32 PresentState;
1138
1139 Packet = Trb->Packet;
1140
1141 if ((Packet->EmmcCmdBlk->CommandType == EmmcCommandTypeAdtc) ||
1142 (Packet->EmmcCmdBlk->ResponseType == EmmcResponceTypeR1b) ||
1143 (Packet->EmmcCmdBlk->ResponseType == EmmcResponceTypeR5b))
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 = EmmcPeimHcCheckMmioSet (
1159 Bar + EMMC_HC_PRESENT_STATE,
1160 sizeof (PresentState),
1161 PresentState,
1162 0
1163 );
1164
1165 return Status;
1166}
1167
1181 IN UINTN Bar,
1182 IN EMMC_TRB *Trb
1183 )
1184{
1185 EFI_STATUS Status;
1186 EMMC_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 = EmmcPeimCheckTrbEnv (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 EMMC_TRB *Trb
1235 )
1236{
1237 EFI_STATUS Status;
1238 EMMC_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 = EmmcPeimHcRwMmio (Bar + EMMC_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 = EmmcPeimHcRwMmio (Bar + EMMC_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 == EmmcAdmaMode) {
1272 HostCtrl1 = BIT4;
1273 Status = EmmcPeimHcOrMmio (Bar + EMMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);
1274 if (EFI_ERROR (Status)) {
1275 return Status;
1276 }
1277 }
1278
1279 EmmcPeimHcLedOnOff (Bar, TRUE);
1280
1281 if (Trb->Mode == EmmcSdmaMode) {
1282 if ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul) {
1283 return EFI_INVALID_PARAMETER;
1284 }
1285
1286 SdmaAddr = (UINT32)(UINTN)Trb->DataPhy;
1287 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_SDMA_ADDR, FALSE, sizeof (SdmaAddr), &SdmaAddr);
1288 if (EFI_ERROR (Status)) {
1289 return Status;
1290 }
1291 } else if (Trb->Mode == EmmcAdmaMode) {
1292 AdmaAddr = (UINT64)(UINTN)Trb->AdmaDesc;
1293 Status = EmmcPeimHcRwMmio (Bar + EMMC_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 == EmmcSdmaMode) {
1301 //
1302 // Set SDMA boundary to be 512K bytes.
1303 //
1304 BlkSize |= 0x7000;
1305 }
1306
1307 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_BLK_SIZE, FALSE, sizeof (BlkSize), &BlkSize);
1308 if (EFI_ERROR (Status)) {
1309 return Status;
1310 }
1311
1312 BlkCount = 0;
1313 if (Trb->Mode != EmmcNoData) {
1314 //
1315 // Calculate Block Count.
1316 //
1317 BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);
1318 }
1319
1320 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount);
1321 if (EFI_ERROR (Status)) {
1322 return Status;
1323 }
1324
1325 Argument = Packet->EmmcCmdBlk->CommandArgument;
1326 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_ARG1, FALSE, sizeof (Argument), &Argument);
1327 if (EFI_ERROR (Status)) {
1328 return Status;
1329 }
1330
1331 TransMode = 0;
1332 if (Trb->Mode != EmmcNoData) {
1333 if (Trb->Mode != EmmcPioMode) {
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 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_TRANS_MOD, FALSE, sizeof (TransMode), &TransMode);
1347 if (EFI_ERROR (Status)) {
1348 return Status;
1349 }
1350
1351 Cmd = (UINT16)LShiftU64 (Packet->EmmcCmdBlk->CommandIndex, 8);
1352 if (Packet->EmmcCmdBlk->CommandType == EmmcCommandTypeAdtc) {
1353 Cmd |= BIT5;
1354 }
1355
1356 //
1357 // Convert ResponseType to value
1358 //
1359 if (Packet->EmmcCmdBlk->CommandType != EmmcCommandTypeBc) {
1360 switch (Packet->EmmcCmdBlk->ResponseType) {
1361 case EmmcResponceTypeR1:
1362 case EmmcResponceTypeR5:
1363 case EmmcResponceTypeR6:
1364 case EmmcResponceTypeR7:
1365 Cmd |= (BIT1 | BIT3 | BIT4);
1366 break;
1367 case EmmcResponceTypeR2:
1368 Cmd |= (BIT0 | BIT3);
1369 break;
1370 case EmmcResponceTypeR3:
1371 case EmmcResponceTypeR4:
1372 Cmd |= BIT1;
1373 break;
1374 case EmmcResponceTypeR1b:
1375 case EmmcResponceTypeR5b:
1376 Cmd |= (BIT0 | BIT1 | BIT3 | BIT4);
1377 break;
1378 default:
1379 ASSERT (FALSE);
1380 break;
1381 }
1382 }
1383
1384 //
1385 // Execute cmd
1386 //
1387 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_COMMAND, FALSE, sizeof (Cmd), &Cmd);
1388 return Status;
1389}
1390
1404 IN UINTN Bar,
1405 IN EMMC_TRB *Trb
1406 )
1407{
1408 EFI_STATUS Status;
1409 EMMC_COMMAND_PACKET *Packet;
1410 UINT16 IntStatus;
1411 UINT32 Response[4];
1412 UINT32 SdmaAddr;
1413 UINT8 Index;
1414 UINT8 SwReset;
1415 UINT32 PioLength;
1416
1417 SwReset = 0;
1418 Packet = Trb->Packet;
1419 //
1420 // Check Trb execution result by reading Normal Interrupt Status register.
1421 //
1422 Status = EmmcPeimHcRwMmio (
1423 Bar + EMMC_HC_NOR_INT_STS,
1424 TRUE,
1425 sizeof (IntStatus),
1426 &IntStatus
1427 );
1428 if (EFI_ERROR (Status)) {
1429 goto Done;
1430 }
1431
1432 //
1433 // Check Transfer Complete bit is set or not.
1434 //
1435 if ((IntStatus & BIT1) == BIT1) {
1436 if ((IntStatus & BIT15) == BIT15) {
1437 //
1438 // Read Error Interrupt Status register to check if the error is
1439 // Data Timeout Error.
1440 // If yes, treat it as success as Transfer Complete has higher
1441 // priority than Data Timeout Error.
1442 //
1443 Status = EmmcPeimHcRwMmio (
1444 Bar + EMMC_HC_ERR_INT_STS,
1445 TRUE,
1446 sizeof (IntStatus),
1447 &IntStatus
1448 );
1449 if (!EFI_ERROR (Status)) {
1450 if ((IntStatus & BIT4) == BIT4) {
1451 Status = EFI_SUCCESS;
1452 } else {
1453 Status = EFI_DEVICE_ERROR;
1454 }
1455 }
1456 }
1457
1458 goto Done;
1459 }
1460
1461 //
1462 // Check if there is a error happened during cmd execution.
1463 // If yes, then do error recovery procedure to follow SD Host Controller
1464 // Simplified Spec 3.0 section 3.10.1.
1465 //
1466 if ((IntStatus & BIT15) == BIT15) {
1467 Status = EmmcPeimHcRwMmio (
1468 Bar + EMMC_HC_ERR_INT_STS,
1469 TRUE,
1470 sizeof (IntStatus),
1471 &IntStatus
1472 );
1473 if (EFI_ERROR (Status)) {
1474 goto Done;
1475 }
1476
1477 if ((IntStatus & 0x0F) != 0) {
1478 SwReset |= BIT1;
1479 }
1480
1481 if ((IntStatus & 0xF0) != 0) {
1482 SwReset |= BIT2;
1483 }
1484
1485 Status = EmmcPeimHcRwMmio (
1486 Bar + EMMC_HC_SW_RST,
1487 FALSE,
1488 sizeof (SwReset),
1489 &SwReset
1490 );
1491 if (EFI_ERROR (Status)) {
1492 goto Done;
1493 }
1494
1495 Status = EmmcPeimHcWaitMmioSet (
1496 Bar + EMMC_HC_SW_RST,
1497 sizeof (SwReset),
1498 0xFF,
1499 0,
1500 EMMC_TIMEOUT
1501 );
1502 if (EFI_ERROR (Status)) {
1503 goto Done;
1504 }
1505
1506 Status = EFI_DEVICE_ERROR;
1507 goto Done;
1508 }
1509
1510 //
1511 // Check if DMA interrupt is signalled for the SDMA transfer.
1512 //
1513 if ((Trb->Mode == EmmcSdmaMode) && ((IntStatus & BIT3) == BIT3)) {
1514 //
1515 // Clear DMA interrupt bit.
1516 //
1517 IntStatus = BIT3;
1518 Status = EmmcPeimHcRwMmio (
1519 Bar + EMMC_HC_NOR_INT_STS,
1520 FALSE,
1521 sizeof (IntStatus),
1522 &IntStatus
1523 );
1524 if (EFI_ERROR (Status)) {
1525 goto Done;
1526 }
1527
1528 //
1529 // Update SDMA Address register.
1530 //
1531 SdmaAddr = EMMC_SDMA_ROUND_UP ((UINT32)(UINTN)Trb->DataPhy, EMMC_SDMA_BOUNDARY);
1532 Status = EmmcPeimHcRwMmio (
1533 Bar + EMMC_HC_SDMA_ADDR,
1534 FALSE,
1535 sizeof (UINT32),
1536 &SdmaAddr
1537 );
1538 if (EFI_ERROR (Status)) {
1539 goto Done;
1540 }
1541
1542 Trb->DataPhy = (UINT32)(UINTN)SdmaAddr;
1543 }
1544
1545 if ((Packet->EmmcCmdBlk->CommandType != EmmcCommandTypeAdtc) &&
1546 (Packet->EmmcCmdBlk->ResponseType != EmmcResponceTypeR1b) &&
1547 (Packet->EmmcCmdBlk->ResponseType != EmmcResponceTypeR5b))
1548 {
1549 if ((IntStatus & BIT0) == BIT0) {
1550 Status = EFI_SUCCESS;
1551 goto Done;
1552 }
1553 }
1554
1555 if (Packet->EmmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK) {
1556 //
1557 // When performing tuning procedure (Execute Tuning is set to 1) through PIO mode,
1558 // wait Buffer Read Ready bit of Normal Interrupt Status Register to be 1.
1559 // Refer to SD Host Controller Simplified Specification 3.0 figure 2-29 for details.
1560 //
1561 if ((IntStatus & BIT5) == BIT5) {
1562 //
1563 // Clear Buffer Read Ready interrupt at first.
1564 //
1565 IntStatus = BIT5;
1566 EmmcPeimHcRwMmio (Bar + EMMC_HC_NOR_INT_STS, FALSE, sizeof (IntStatus), &IntStatus);
1567 //
1568 // Read data out from Buffer Port register
1569 //
1570 for (PioLength = 0; PioLength < Trb->DataLen; PioLength += 4) {
1571 EmmcPeimHcRwMmio (Bar + EMMC_HC_BUF_DAT_PORT, TRUE, 4, (UINT8 *)Trb->Data + PioLength);
1572 }
1573
1574 Status = EFI_SUCCESS;
1575 goto Done;
1576 }
1577 }
1578
1579 Status = EFI_NOT_READY;
1580Done:
1581 //
1582 // Get response data when the cmd is executed successfully.
1583 //
1584 if (!EFI_ERROR (Status)) {
1585 if (Packet->EmmcCmdBlk->CommandType != EmmcCommandTypeBc) {
1586 for (Index = 0; Index < 4; Index++) {
1587 Status = EmmcPeimHcRwMmio (
1588 Bar + EMMC_HC_RESPONSE + Index * 4,
1589 TRUE,
1590 sizeof (UINT32),
1591 &Response[Index]
1592 );
1593 if (EFI_ERROR (Status)) {
1595 return Status;
1596 }
1597 }
1598
1599 CopyMem (Packet->EmmcStatusBlk, Response, sizeof (Response));
1600 }
1601 }
1602
1603 if (Status != EFI_NOT_READY) {
1605 }
1606
1607 return Status;
1608}
1609
1622 IN UINTN Bar,
1623 IN EMMC_TRB *Trb
1624 )
1625{
1626 EFI_STATUS Status;
1627 EMMC_COMMAND_PACKET *Packet;
1628 UINT64 Timeout;
1629 BOOLEAN InfiniteWait;
1630
1631 Packet = Trb->Packet;
1632 //
1633 // Wait Command Complete Interrupt Status bit in Normal Interrupt Status Register
1634 //
1635 Timeout = Packet->Timeout;
1636 if (Timeout == 0) {
1637 InfiniteWait = TRUE;
1638 } else {
1639 InfiniteWait = FALSE;
1640 }
1641
1642 while (InfiniteWait || (Timeout > 0)) {
1643 //
1644 // Check Trb execution result by reading Normal Interrupt Status register.
1645 //
1646 Status = EmmcPeimCheckTrbResult (Bar, Trb);
1647 if (Status != EFI_NOT_READY) {
1648 return Status;
1649 }
1650
1651 //
1652 // Stall for 1 microsecond.
1653 //
1654 MicroSecondDelay (1);
1655
1656 Timeout--;
1657 }
1658
1659 return EFI_TIMEOUT;
1660}
1661
1693EFIAPI
1695 IN EMMC_PEIM_HC_SLOT *Slot,
1696 IN OUT EMMC_COMMAND_PACKET *Packet
1697 )
1698{
1699 EFI_STATUS Status;
1700 EMMC_TRB *Trb;
1701
1702 if (Packet == NULL) {
1703 return EFI_INVALID_PARAMETER;
1704 }
1705
1706 if ((Packet->EmmcCmdBlk == NULL) || (Packet->EmmcStatusBlk == NULL)) {
1707 return EFI_INVALID_PARAMETER;
1708 }
1709
1710 if ((Packet->OutDataBuffer == NULL) && (Packet->OutTransferLength != 0)) {
1711 return EFI_INVALID_PARAMETER;
1712 }
1713
1714 if ((Packet->InDataBuffer == NULL) && (Packet->InTransferLength != 0)) {
1715 return EFI_INVALID_PARAMETER;
1716 }
1717
1718 Trb = EmmcPeimCreateTrb (Slot, Packet);
1719 if (Trb == NULL) {
1720 return EFI_OUT_OF_RESOURCES;
1721 }
1722
1723 Status = EmmcPeimWaitTrbEnv (Slot->EmmcHcBase, Trb);
1724 if (EFI_ERROR (Status)) {
1725 goto Done;
1726 }
1727
1728 Status = EmmcPeimExecTrb (Slot->EmmcHcBase, Trb);
1729 if (EFI_ERROR (Status)) {
1730 goto Done;
1731 }
1732
1733 Status = EmmcPeimWaitTrbResult (Slot->EmmcHcBase, Trb);
1734 if (EFI_ERROR (Status)) {
1735 goto Done;
1736 }
1737
1738Done:
1739 EmmcPeimFreeTrb (Trb);
1740
1741 return Status;
1742}
1743
1758 IN EMMC_PEIM_HC_SLOT *Slot
1759 )
1760{
1761 EMMC_COMMAND_BLOCK EmmcCmdBlk;
1762 EMMC_STATUS_BLOCK EmmcStatusBlk;
1763 EMMC_COMMAND_PACKET Packet;
1764 EFI_STATUS Status;
1765
1766 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));
1767 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));
1768 ZeroMem (&Packet, sizeof (Packet));
1769
1770 Packet.EmmcCmdBlk = &EmmcCmdBlk;
1771 Packet.EmmcStatusBlk = &EmmcStatusBlk;
1772 Packet.Timeout = EMMC_TIMEOUT;
1773
1774 EmmcCmdBlk.CommandIndex = EMMC_GO_IDLE_STATE;
1775 EmmcCmdBlk.CommandType = EmmcCommandTypeBc;
1776 EmmcCmdBlk.ResponseType = 0;
1777 EmmcCmdBlk.CommandArgument = 0;
1778
1779 Status = EmmcPeimExecCmd (Slot, &Packet);
1780
1781 return Status;
1782}
1783
1799 IN EMMC_PEIM_HC_SLOT *Slot,
1800 IN OUT UINT32 *Argument
1801 )
1802{
1803 EMMC_COMMAND_BLOCK EmmcCmdBlk;
1804 EMMC_STATUS_BLOCK EmmcStatusBlk;
1805 EMMC_COMMAND_PACKET Packet;
1806 EFI_STATUS Status;
1807
1808 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));
1809 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));
1810 ZeroMem (&Packet, sizeof (Packet));
1811
1812 Packet.EmmcCmdBlk = &EmmcCmdBlk;
1813 Packet.EmmcStatusBlk = &EmmcStatusBlk;
1814 Packet.Timeout = EMMC_TIMEOUT;
1815
1816 EmmcCmdBlk.CommandIndex = EMMC_SEND_OP_COND;
1817 EmmcCmdBlk.CommandType = EmmcCommandTypeBcr;
1818 EmmcCmdBlk.ResponseType = EmmcResponceTypeR3;
1819 EmmcCmdBlk.CommandArgument = *Argument;
1820
1821 Status = EmmcPeimExecCmd (Slot, &Packet);
1822 if (!EFI_ERROR (Status)) {
1823 //
1824 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
1825 //
1826 *Argument = EmmcStatusBlk.Resp0;
1827 }
1828
1829 return Status;
1830}
1831
1846 IN EMMC_PEIM_HC_SLOT *Slot
1847 )
1848{
1849 EMMC_COMMAND_BLOCK EmmcCmdBlk;
1850 EMMC_STATUS_BLOCK EmmcStatusBlk;
1851 EMMC_COMMAND_PACKET Packet;
1852 EFI_STATUS Status;
1853
1854 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));
1855 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));
1856 ZeroMem (&Packet, sizeof (Packet));
1857
1858 Packet.EmmcCmdBlk = &EmmcCmdBlk;
1859 Packet.EmmcStatusBlk = &EmmcStatusBlk;
1860 Packet.Timeout = EMMC_TIMEOUT;
1861
1862 EmmcCmdBlk.CommandIndex = EMMC_ALL_SEND_CID;
1863 EmmcCmdBlk.CommandType = EmmcCommandTypeBcr;
1864 EmmcCmdBlk.ResponseType = EmmcResponceTypeR2;
1865 EmmcCmdBlk.CommandArgument = 0;
1866
1867 Status = EmmcPeimExecCmd (Slot, &Packet);
1868
1869 return Status;
1870}
1871
1887 IN EMMC_PEIM_HC_SLOT *Slot,
1888 IN UINT32 Rca
1889 )
1890{
1891 EMMC_COMMAND_BLOCK EmmcCmdBlk;
1892 EMMC_STATUS_BLOCK EmmcStatusBlk;
1893 EMMC_COMMAND_PACKET Packet;
1894 EFI_STATUS Status;
1895
1896 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));
1897 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));
1898 ZeroMem (&Packet, sizeof (Packet));
1899
1900 Packet.EmmcCmdBlk = &EmmcCmdBlk;
1901 Packet.EmmcStatusBlk = &EmmcStatusBlk;
1902 Packet.Timeout = EMMC_TIMEOUT;
1903
1904 EmmcCmdBlk.CommandIndex = EMMC_SET_RELATIVE_ADDR;
1905 EmmcCmdBlk.CommandType = EmmcCommandTypeAc;
1906 EmmcCmdBlk.ResponseType = EmmcResponceTypeR1;
1907 EmmcCmdBlk.CommandArgument = Rca << 16;
1908
1909 Status = EmmcPeimExecCmd (Slot, &Packet);
1910
1911 return Status;
1912}
1913
1932 IN EMMC_PEIM_HC_SLOT *Slot,
1933 IN UINT32 Rca,
1934 OUT EMMC_CSD *Csd
1935 )
1936{
1937 EMMC_COMMAND_BLOCK EmmcCmdBlk;
1938 EMMC_STATUS_BLOCK EmmcStatusBlk;
1939 EMMC_COMMAND_PACKET Packet;
1940 EFI_STATUS Status;
1941
1942 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));
1943 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));
1944 ZeroMem (&Packet, sizeof (Packet));
1945
1946 Packet.EmmcCmdBlk = &EmmcCmdBlk;
1947 Packet.EmmcStatusBlk = &EmmcStatusBlk;
1948 Packet.Timeout = EMMC_TIMEOUT;
1949
1950 EmmcCmdBlk.CommandIndex = EMMC_SEND_CSD;
1951 EmmcCmdBlk.CommandType = EmmcCommandTypeAc;
1952 EmmcCmdBlk.ResponseType = EmmcResponceTypeR2;
1953 EmmcCmdBlk.CommandArgument = Rca << 16;
1954
1955 Status = EmmcPeimExecCmd (Slot, &Packet);
1956 if (!EFI_ERROR (Status)) {
1957 //
1958 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
1959 //
1960 CopyMem (((UINT8 *)Csd) + 1, &EmmcStatusBlk.Resp0, sizeof (EMMC_CSD) - 1);
1961 }
1962
1963 return Status;
1964}
1965
1980 IN EMMC_PEIM_HC_SLOT *Slot,
1981 IN UINT32 Rca
1982 )
1983{
1984 EMMC_COMMAND_BLOCK EmmcCmdBlk;
1985 EMMC_STATUS_BLOCK EmmcStatusBlk;
1986 EMMC_COMMAND_PACKET Packet;
1987 EFI_STATUS Status;
1988
1989 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));
1990 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));
1991 ZeroMem (&Packet, sizeof (Packet));
1992
1993 Packet.EmmcCmdBlk = &EmmcCmdBlk;
1994 Packet.EmmcStatusBlk = &EmmcStatusBlk;
1995 Packet.Timeout = EMMC_TIMEOUT;
1996
1997 EmmcCmdBlk.CommandIndex = EMMC_SELECT_DESELECT_CARD;
1998 EmmcCmdBlk.CommandType = EmmcCommandTypeAc;
1999 EmmcCmdBlk.ResponseType = EmmcResponceTypeR1;
2000 EmmcCmdBlk.CommandArgument = Rca << 16;
2001
2002 Status = EmmcPeimExecCmd (Slot, &Packet);
2003
2004 return Status;
2005}
2006
2021 IN EMMC_PEIM_HC_SLOT *Slot,
2022 OUT EMMC_EXT_CSD *ExtCsd
2023 )
2024{
2025 EMMC_COMMAND_BLOCK EmmcCmdBlk;
2026 EMMC_STATUS_BLOCK EmmcStatusBlk;
2027 EMMC_COMMAND_PACKET Packet;
2028 EFI_STATUS Status;
2029
2030 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));
2031 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));
2032 ZeroMem (&Packet, sizeof (Packet));
2033
2034 Packet.EmmcCmdBlk = &EmmcCmdBlk;
2035 Packet.EmmcStatusBlk = &EmmcStatusBlk;
2036 Packet.Timeout = EMMC_TIMEOUT;
2037
2038 EmmcCmdBlk.CommandIndex = EMMC_SEND_EXT_CSD;
2039 EmmcCmdBlk.CommandType = EmmcCommandTypeAdtc;
2040 EmmcCmdBlk.ResponseType = EmmcResponceTypeR1;
2041 EmmcCmdBlk.CommandArgument = 0x00000000;
2042
2043 Packet.InDataBuffer = ExtCsd;
2044 Packet.InTransferLength = sizeof (EMMC_EXT_CSD);
2045
2046 Status = EmmcPeimExecCmd (Slot, &Packet);
2047 return Status;
2048}
2049
2068 IN EMMC_PEIM_HC_SLOT *Slot,
2069 IN UINT8 Access,
2070 IN UINT8 Index,
2071 IN UINT8 Value,
2072 IN UINT8 CmdSet
2073 )
2074{
2075 EMMC_COMMAND_BLOCK EmmcCmdBlk;
2076 EMMC_STATUS_BLOCK EmmcStatusBlk;
2077 EMMC_COMMAND_PACKET Packet;
2078 EFI_STATUS Status;
2079
2080 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));
2081 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));
2082 ZeroMem (&Packet, sizeof (Packet));
2083
2084 Packet.EmmcCmdBlk = &EmmcCmdBlk;
2085 Packet.EmmcStatusBlk = &EmmcStatusBlk;
2086 Packet.Timeout = EMMC_TIMEOUT;
2087
2088 EmmcCmdBlk.CommandIndex = EMMC_SWITCH;
2089 EmmcCmdBlk.CommandType = EmmcCommandTypeAc;
2090 EmmcCmdBlk.ResponseType = EmmcResponceTypeR1b;
2091 EmmcCmdBlk.CommandArgument = (Access << 24) | (Index << 16) | (Value << 8) | CmdSet;
2092
2093 Status = EmmcPeimExecCmd (Slot, &Packet);
2094
2095 return Status;
2096}
2097
2113 IN EMMC_PEIM_HC_SLOT *Slot,
2114 IN UINT32 Rca,
2115 OUT UINT32 *DevStatus
2116 )
2117{
2118 EMMC_COMMAND_BLOCK EmmcCmdBlk;
2119 EMMC_STATUS_BLOCK EmmcStatusBlk;
2120 EMMC_COMMAND_PACKET Packet;
2121 EFI_STATUS Status;
2122
2123 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));
2124 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));
2125 ZeroMem (&Packet, sizeof (Packet));
2126
2127 Packet.EmmcCmdBlk = &EmmcCmdBlk;
2128 Packet.EmmcStatusBlk = &EmmcStatusBlk;
2129 Packet.Timeout = EMMC_TIMEOUT;
2130
2131 EmmcCmdBlk.CommandIndex = EMMC_SEND_STATUS;
2132 EmmcCmdBlk.CommandType = EmmcCommandTypeAc;
2133 EmmcCmdBlk.ResponseType = EmmcResponceTypeR1;
2134 EmmcCmdBlk.CommandArgument = Rca << 16;
2135
2136 Status = EmmcPeimExecCmd (Slot, &Packet);
2137 if (!EFI_ERROR (Status)) {
2138 *DevStatus = EmmcStatusBlk.Resp0;
2139 }
2140
2141 return Status;
2142}
2143
2159 IN EMMC_PEIM_HC_SLOT *Slot,
2160 IN UINT16 BlockCount
2161 )
2162{
2163 EMMC_COMMAND_BLOCK EmmcCmdBlk;
2164 EMMC_STATUS_BLOCK EmmcStatusBlk;
2165 EMMC_COMMAND_PACKET Packet;
2166 EFI_STATUS Status;
2167
2168 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));
2169 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));
2170 ZeroMem (&Packet, sizeof (Packet));
2171
2172 Packet.EmmcCmdBlk = &EmmcCmdBlk;
2173 Packet.EmmcStatusBlk = &EmmcStatusBlk;
2174 Packet.Timeout = EMMC_TIMEOUT;
2175
2176 EmmcCmdBlk.CommandIndex = EMMC_SET_BLOCK_COUNT;
2177 EmmcCmdBlk.CommandType = EmmcCommandTypeAc;
2178 EmmcCmdBlk.ResponseType = EmmcResponceTypeR1;
2179 EmmcCmdBlk.CommandArgument = BlockCount;
2180
2181 Status = EmmcPeimExecCmd (Slot, &Packet);
2182
2183 return Status;
2184}
2185
2205 IN EMMC_PEIM_HC_SLOT *Slot,
2206 IN EFI_LBA Lba,
2207 IN UINT32 BlockSize,
2208 IN VOID *Buffer,
2209 IN UINTN BufferSize,
2210 IN BOOLEAN IsRead
2211 )
2212{
2213 EMMC_COMMAND_BLOCK EmmcCmdBlk;
2214 EMMC_STATUS_BLOCK EmmcStatusBlk;
2215 EMMC_COMMAND_PACKET Packet;
2216 EFI_STATUS Status;
2217
2218 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));
2219 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));
2220 ZeroMem (&Packet, sizeof (Packet));
2221
2222 Packet.EmmcCmdBlk = &EmmcCmdBlk;
2223 Packet.EmmcStatusBlk = &EmmcStatusBlk;
2224 //
2225 // Calculate timeout value through the below formula.
2226 // Timeout = (transfer size) / (2MB/s).
2227 // Taking 2MB/s as divisor is because it's nearest to the eMMC lowest
2228 // transfer speed (2.4MB/s).
2229 // Refer to eMMC 5.0 spec section 6.9.1 for details.
2230 //
2231 Packet.Timeout = (BufferSize / (2 * 1024 * 1024) + 1) * 1000 * 1000;
2232
2233 if (IsRead) {
2234 Packet.InDataBuffer = Buffer;
2235 Packet.InTransferLength = (UINT32)BufferSize;
2236
2237 EmmcCmdBlk.CommandIndex = EMMC_READ_MULTIPLE_BLOCK;
2238 EmmcCmdBlk.CommandType = EmmcCommandTypeAdtc;
2239 EmmcCmdBlk.ResponseType = EmmcResponceTypeR1;
2240 } else {
2241 Packet.OutDataBuffer = Buffer;
2242 Packet.OutTransferLength = (UINT32)BufferSize;
2243
2244 EmmcCmdBlk.CommandIndex = EMMC_WRITE_MULTIPLE_BLOCK;
2245 EmmcCmdBlk.CommandType = EmmcCommandTypeAdtc;
2246 EmmcCmdBlk.ResponseType = EmmcResponceTypeR1;
2247 }
2248
2249 if (Slot->SectorAddressing) {
2250 EmmcCmdBlk.CommandArgument = (UINT32)Lba;
2251 } else {
2252 EmmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (Lba, BlockSize);
2253 }
2254
2255 Status = EmmcPeimExecCmd (Slot, &Packet);
2256
2257 return Status;
2258}
2259
2277 IN EMMC_PEIM_HC_SLOT *Slot,
2278 IN UINT8 BusWidth
2279 )
2280{
2281 EMMC_COMMAND_BLOCK EmmcCmdBlk;
2282 EMMC_STATUS_BLOCK EmmcStatusBlk;
2283 EMMC_COMMAND_PACKET Packet;
2284 EFI_STATUS Status;
2285 UINT8 TuningBlock[128];
2286
2287 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));
2288 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));
2289 ZeroMem (&Packet, sizeof (Packet));
2290
2291 Packet.EmmcCmdBlk = &EmmcCmdBlk;
2292 Packet.EmmcStatusBlk = &EmmcStatusBlk;
2293 Packet.Timeout = EMMC_TIMEOUT;
2294
2295 EmmcCmdBlk.CommandIndex = EMMC_SEND_TUNING_BLOCK;
2296 EmmcCmdBlk.CommandType = EmmcCommandTypeAdtc;
2297 EmmcCmdBlk.ResponseType = EmmcResponceTypeR1;
2298 EmmcCmdBlk.CommandArgument = 0;
2299
2300 Packet.InDataBuffer = TuningBlock;
2301 if (BusWidth == 8) {
2302 Packet.InTransferLength = sizeof (TuningBlock);
2303 } else {
2304 Packet.InTransferLength = 64;
2305 }
2306
2307 Status = EmmcPeimExecCmd (Slot, &Packet);
2308
2309 return Status;
2310}
2311
2330 IN EMMC_PEIM_HC_SLOT *Slot,
2331 IN UINT8 BusWidth
2332 )
2333{
2334 EFI_STATUS Status;
2335 UINT8 HostCtrl2;
2336 UINT8 Retry;
2337
2338 //
2339 // Notify the host that the sampling clock tuning procedure starts.
2340 //
2341 HostCtrl2 = BIT6;
2342 Status = EmmcPeimHcOrMmio (Slot->EmmcHcBase + EMMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
2343 if (EFI_ERROR (Status)) {
2344 return Status;
2345 }
2346
2347 //
2348 // Ask the device to send a sequence of tuning blocks till the tuning procedure is done.
2349 //
2350 Retry = 0;
2351 do {
2352 Status = EmmcPeimSendTuningBlk (Slot, BusWidth);
2353 if (EFI_ERROR (Status)) {
2354 return Status;
2355 }
2356
2357 Status = EmmcPeimHcRwMmio (Slot->EmmcHcBase + EMMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);
2358 if (EFI_ERROR (Status)) {
2359 return Status;
2360 }
2361
2362 if ((HostCtrl2 & (BIT6 | BIT7)) == 0) {
2363 break;
2364 }
2365
2366 if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) {
2367 return EFI_SUCCESS;
2368 }
2369 } while (++Retry < 40);
2370
2371 DEBUG ((DEBUG_ERROR, "EmmcPeimTuningClkForHs200: Send tuning block fails at %d times with HostCtrl2 %02x\n", Retry, HostCtrl2));
2372 //
2373 // Abort the tuning procedure and reset the tuning circuit.
2374 //
2375 HostCtrl2 = (UINT8) ~(BIT6 | BIT7);
2376 Status = EmmcPeimHcAndMmio (Slot->EmmcHcBase + EMMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
2377 if (EFI_ERROR (Status)) {
2378 return Status;
2379 }
2380
2381 return EFI_DEVICE_ERROR;
2382}
2383
2402 IN EMMC_PEIM_HC_SLOT *Slot,
2403 IN UINT32 Rca,
2404 IN BOOLEAN IsDdr,
2405 IN UINT8 BusWidth
2406 )
2407{
2408 EFI_STATUS Status;
2409 UINT8 Access;
2410 UINT8 Index;
2411 UINT8 Value;
2412 UINT8 CmdSet;
2413 UINT32 DevStatus;
2414
2415 //
2416 // Write Byte, the Value field is written into the byte pointed by Index.
2417 //
2418 Access = 0x03;
2419 Index = OFFSET_OF (EMMC_EXT_CSD, BusWidth);
2420 if (BusWidth == 4) {
2421 Value = 1;
2422 } else if (BusWidth == 8) {
2423 Value = 2;
2424 } else {
2425 return EFI_INVALID_PARAMETER;
2426 }
2427
2428 if (IsDdr) {
2429 Value += 4;
2430 }
2431
2432 CmdSet = 0;
2433 Status = EmmcPeimSwitch (Slot, Access, Index, Value, CmdSet);
2434 if (EFI_ERROR (Status)) {
2435 return Status;
2436 }
2437
2438 Status = EmmcPeimSendStatus (Slot, Rca, &DevStatus);
2439 if (EFI_ERROR (Status)) {
2440 return Status;
2441 }
2442
2443 //
2444 // Check the switch operation is really successful or not.
2445 //
2446 if ((DevStatus & BIT7) != 0) {
2447 return EFI_DEVICE_ERROR;
2448 }
2449
2450 Status = EmmcPeimHcSetBusWidth (Slot->EmmcHcBase, BusWidth);
2451
2452 return Status;
2453}
2454
2472 IN EMMC_PEIM_HC_SLOT *Slot,
2473 IN UINT32 Rca,
2474 IN UINT8 HsTiming,
2475 IN UINT32 ClockFreq
2476 )
2477{
2478 EFI_STATUS Status;
2479 UINT8 Access;
2480 UINT8 Index;
2481 UINT8 Value;
2482 UINT8 CmdSet;
2483 UINT32 DevStatus;
2484
2485 //
2486 // Write Byte, the Value field is written into the byte pointed by Index.
2487 //
2488 Access = 0x03;
2489 Index = OFFSET_OF (EMMC_EXT_CSD, HsTiming);
2490 Value = HsTiming;
2491 CmdSet = 0;
2492
2493 Status = EmmcPeimSwitch (Slot, Access, Index, Value, CmdSet);
2494 if (EFI_ERROR (Status)) {
2495 return Status;
2496 }
2497
2498 Status = EmmcPeimSendStatus (Slot, Rca, &DevStatus);
2499 if (EFI_ERROR (Status)) {
2500 return Status;
2501 }
2502
2503 //
2504 // Check the switch operation is really successful or not.
2505 //
2506 if ((DevStatus & BIT7) != 0) {
2507 return EFI_DEVICE_ERROR;
2508 }
2509
2510 //
2511 // Convert the clock freq unit from MHz to KHz.
2512 //
2513 Status = EmmcPeimHcClockSupply (Slot->EmmcHcBase, ClockFreq * 1000);
2514
2515 return Status;
2516}
2517
2537 IN EMMC_PEIM_HC_SLOT *Slot,
2538 IN UINT32 Rca,
2539 IN UINT32 ClockFreq,
2540 IN BOOLEAN IsDdr,
2541 IN UINT8 BusWidth
2542 )
2543{
2544 EFI_STATUS Status;
2545 UINT8 HsTiming;
2546 UINT8 HostCtrl1;
2547 UINT8 HostCtrl2;
2548
2549 Status = EmmcPeimSwitchBusWidth (Slot, Rca, IsDdr, BusWidth);
2550 if (EFI_ERROR (Status)) {
2551 return Status;
2552 }
2553
2554 //
2555 // Set to High Speed timing
2556 //
2557 HostCtrl1 = BIT2;
2558 Status = EmmcPeimHcOrMmio (Slot->EmmcHcBase + EMMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);
2559 if (EFI_ERROR (Status)) {
2560 return Status;
2561 }
2562
2563 HostCtrl2 = (UINT8) ~0x7;
2564 Status = EmmcPeimHcAndMmio (Slot->EmmcHcBase + EMMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
2565 if (EFI_ERROR (Status)) {
2566 return Status;
2567 }
2568
2569 if (IsDdr) {
2570 HostCtrl2 = BIT2;
2571 } else if (ClockFreq == 52) {
2572 HostCtrl2 = BIT0;
2573 } else {
2574 HostCtrl2 = 0;
2575 }
2576
2577 Status = EmmcPeimHcOrMmio (Slot->EmmcHcBase + EMMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
2578 if (EFI_ERROR (Status)) {
2579 return Status;
2580 }
2581
2582 HsTiming = 1;
2583 Status = EmmcPeimSwitchClockFreq (Slot, Rca, HsTiming, ClockFreq);
2584
2585 return Status;
2586}
2587
2605 IN EMMC_PEIM_HC_SLOT *Slot,
2606 IN UINT32 Rca,
2607 IN UINT32 ClockFreq,
2608 IN UINT8 BusWidth
2609 )
2610{
2611 EFI_STATUS Status;
2612 UINT8 HsTiming;
2613 UINT8 HostCtrl2;
2614 UINT16 ClockCtrl;
2615
2616 if ((BusWidth != 4) && (BusWidth != 8)) {
2617 return EFI_INVALID_PARAMETER;
2618 }
2619
2620 Status = EmmcPeimSwitchBusWidth (Slot, Rca, FALSE, BusWidth);
2621 if (EFI_ERROR (Status)) {
2622 return Status;
2623 }
2624
2625 //
2626 // Set to HS200/SDR104 timing
2627 //
2628 //
2629 // Stop bus clock at first
2630 //
2631 Status = EmmcPeimHcStopClock (Slot->EmmcHcBase);
2632 if (EFI_ERROR (Status)) {
2633 return Status;
2634 }
2635
2636 HostCtrl2 = (UINT8) ~0x7;
2637 Status = EmmcPeimHcAndMmio (Slot->EmmcHcBase + EMMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
2638 if (EFI_ERROR (Status)) {
2639 return Status;
2640 }
2641
2642 HostCtrl2 = BIT0 | BIT1;
2643 Status = EmmcPeimHcOrMmio (Slot->EmmcHcBase + EMMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
2644 if (EFI_ERROR (Status)) {
2645 return Status;
2646 }
2647
2648 //
2649 // Wait Internal Clock Stable in the Clock Control register to be 1 before set SD Clock Enable bit
2650 //
2651 Status = EmmcPeimHcWaitMmioSet (
2652 Slot->EmmcHcBase + EMMC_HC_CLOCK_CTRL,
2653 sizeof (ClockCtrl),
2654 BIT1,
2655 BIT1,
2656 EMMC_TIMEOUT
2657 );
2658 if (EFI_ERROR (Status)) {
2659 return Status;
2660 }
2661
2662 //
2663 // Set SD Clock Enable in the Clock Control register to 1
2664 //
2665 ClockCtrl = BIT2;
2666 Status = EmmcPeimHcOrMmio (Slot->EmmcHcBase + EMMC_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl);
2667
2668 HsTiming = 2;
2669 Status = EmmcPeimSwitchClockFreq (Slot, Rca, HsTiming, ClockFreq);
2670 if (EFI_ERROR (Status)) {
2671 return Status;
2672 }
2673
2674 Status = EmmcPeimTuningClkForHs200 (Slot, BusWidth);
2675
2676 return Status;
2677}
2678
2695 IN EMMC_PEIM_HC_SLOT *Slot,
2696 IN UINT32 Rca,
2697 IN UINT32 ClockFreq
2698 )
2699{
2700 EFI_STATUS Status;
2701 UINT8 HsTiming;
2702 UINT8 HostCtrl2;
2703
2704 Status = EmmcPeimSwitchToHS200 (Slot, Rca, ClockFreq, 8);
2705 if (EFI_ERROR (Status)) {
2706 return Status;
2707 }
2708
2709 //
2710 // Set to High Speed timing and set the clock frequency to a value less than 52MHz.
2711 //
2712 HsTiming = 1;
2713 Status = EmmcPeimSwitchClockFreq (Slot, Rca, HsTiming, 52);
2714 if (EFI_ERROR (Status)) {
2715 return Status;
2716 }
2717
2718 //
2719 // HS400 mode must use 8 data lines.
2720 //
2721 Status = EmmcPeimSwitchBusWidth (Slot, Rca, TRUE, 8);
2722 if (EFI_ERROR (Status)) {
2723 return Status;
2724 }
2725
2726 //
2727 // Set to HS400 timing
2728 //
2729 HostCtrl2 = (UINT8) ~0x7;
2730 Status = EmmcPeimHcAndMmio (Slot->EmmcHcBase + EMMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
2731 if (EFI_ERROR (Status)) {
2732 return Status;
2733 }
2734
2735 HostCtrl2 = BIT0 | BIT2;
2736 Status = EmmcPeimHcOrMmio (Slot->EmmcHcBase + EMMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
2737 if (EFI_ERROR (Status)) {
2738 return Status;
2739 }
2740
2741 HsTiming = 3;
2742 Status = EmmcPeimSwitchClockFreq (Slot, Rca, HsTiming, ClockFreq);
2743
2744 return Status;
2745}
2746
2762 IN EMMC_PEIM_HC_SLOT *Slot,
2763 IN UINT32 Rca
2764 )
2765{
2766 EFI_STATUS Status;
2767 EMMC_HC_SLOT_CAP Capability;
2768 UINT8 HsTiming;
2769 BOOLEAN IsDdr;
2770 UINT32 ClockFreq;
2771 UINT8 BusWidth;
2772
2773 Status = EmmcPeimGetCsd (Slot, Rca, &Slot->Csd);
2774 if (EFI_ERROR (Status)) {
2775 DEBUG ((DEBUG_ERROR, "EmmcPeimSetBusMode: EmmcPeimGetCsd fails with %r\n", Status));
2776 return Status;
2777 }
2778
2779 if ((Slot->Csd.CSizeLow | Slot->Csd.CSizeHigh << 2) == 0xFFF) {
2780 Slot->SectorAddressing = TRUE;
2781 } else {
2782 Slot->SectorAddressing = FALSE;
2783 }
2784
2785 Status = EmmcPeimSelect (Slot, Rca);
2786 if (EFI_ERROR (Status)) {
2787 DEBUG ((DEBUG_ERROR, "EmmcPeimSetBusMode: EmmcPeimSelect fails with %r\n", Status));
2788 return Status;
2789 }
2790
2791 Status = EmmcPeimHcGetCapability (Slot->EmmcHcBase, &Capability);
2792 if (EFI_ERROR (Status)) {
2793 DEBUG ((DEBUG_ERROR, "EmmcPeimSetBusMode: EmmcPeimHcGetCapability fails with %r\n", Status));
2794 return Status;
2795 }
2796
2797 ASSERT (Capability.BaseClkFreq != 0);
2798 //
2799 // Check if the Host Controller support 8bits bus width.
2800 //
2801 if (Capability.BusWidth8 != 0) {
2802 BusWidth = 8;
2803 } else {
2804 BusWidth = 4;
2805 }
2806
2807 //
2808 // Get Device_Type from EXT_CSD register.
2809 //
2810 Status = EmmcPeimGetExtCsd (Slot, &Slot->ExtCsd);
2811 if (EFI_ERROR (Status)) {
2812 DEBUG ((DEBUG_ERROR, "EmmcPeimSetBusMode: EmmcPeimGetExtCsd fails with %r\n", Status));
2813 return Status;
2814 }
2815
2816 //
2817 // Calculate supported bus speed/bus width/clock frequency.
2818 //
2819 HsTiming = 0;
2820 IsDdr = FALSE;
2821 ClockFreq = 0;
2822 if (((Slot->ExtCsd.DeviceType & (BIT4 | BIT5)) != 0) && (Capability.Sdr104 != 0)) {
2823 HsTiming = 2;
2824 IsDdr = FALSE;
2825 ClockFreq = 200;
2826 } else if (((Slot->ExtCsd.DeviceType & (BIT2 | BIT3)) != 0) && (Capability.Ddr50 != 0)) {
2827 HsTiming = 1;
2828 IsDdr = TRUE;
2829 ClockFreq = 52;
2830 } else if (((Slot->ExtCsd.DeviceType & BIT1) != 0) && (Capability.HighSpeed != 0)) {
2831 HsTiming = 1;
2832 IsDdr = FALSE;
2833 ClockFreq = 52;
2834 } else if (((Slot->ExtCsd.DeviceType & BIT0) != 0) && (Capability.HighSpeed != 0)) {
2835 HsTiming = 1;
2836 IsDdr = FALSE;
2837 ClockFreq = 26;
2838 }
2839
2840 //
2841 // Check if both of the device and the host controller support HS400 DDR mode.
2842 //
2843 if (((Slot->ExtCsd.DeviceType & (BIT6 | BIT7)) != 0) && (Capability.Hs400 != 0)) {
2844 //
2845 // The host controller supports 8bits bus.
2846 //
2847 ASSERT (BusWidth == 8);
2848 HsTiming = 3;
2849 IsDdr = TRUE;
2850 ClockFreq = 200;
2851 }
2852
2853 if ((ClockFreq == 0) || (HsTiming == 0)) {
2854 //
2855 // Continue using default setting.
2856 //
2857 return EFI_SUCCESS;
2858 }
2859
2860 DEBUG ((DEBUG_INFO, "HsTiming %d ClockFreq %d BusWidth %d Ddr %a\n", HsTiming, ClockFreq, BusWidth, IsDdr ? "TRUE" : "FALSE"));
2861
2862 if (HsTiming == 3) {
2863 //
2864 // Execute HS400 timing switch procedure
2865 //
2866 Status = EmmcPeimSwitchToHS400 (Slot, Rca, ClockFreq);
2867 } else if (HsTiming == 2) {
2868 //
2869 // Execute HS200 timing switch procedure
2870 //
2871 Status = EmmcPeimSwitchToHS200 (Slot, Rca, ClockFreq, BusWidth);
2872 } else {
2873 //
2874 // Execute High Speed timing switch procedure
2875 //
2876 Status = EmmcPeimSwitchToHighSpeed (Slot, Rca, ClockFreq, IsDdr, BusWidth);
2877 }
2878
2879 return Status;
2880}
2881
2895 IN EMMC_PEIM_HC_SLOT *Slot
2896 )
2897{
2898 EFI_STATUS Status;
2899 UINT32 Ocr;
2900 UINT32 Rca;
2901 UINTN Retry;
2902
2903 Status = EmmcPeimReset (Slot);
2904 if (EFI_ERROR (Status)) {
2905 DEBUG ((DEBUG_ERROR, "EmmcPeimIdentification: EmmcPeimReset fails with %r\n", Status));
2906 return Status;
2907 }
2908
2909 Ocr = 0;
2910 Retry = 0;
2911 do {
2912 Status = EmmcPeimGetOcr (Slot, &Ocr);
2913 if (EFI_ERROR (Status)) {
2914 DEBUG ((DEBUG_ERROR, "EmmcPeimIdentification: EmmcPeimGetOcr fails with %r\n", Status));
2915 return Status;
2916 }
2917
2918 if (Retry++ == 100) {
2919 DEBUG ((DEBUG_ERROR, "EmmcPeimIdentification: EmmcPeimGetOcr fails too many times\n"));
2920 return EFI_DEVICE_ERROR;
2921 }
2922
2923 MicroSecondDelay (10 * 1000);
2924 } while ((Ocr & BIT31) == 0);
2925
2926 Status = EmmcPeimGetAllCid (Slot);
2927 if (EFI_ERROR (Status)) {
2928 DEBUG ((DEBUG_ERROR, "EmmcPeimIdentification: EmmcPeimGetAllCid fails with %r\n", Status));
2929 return Status;
2930 }
2931
2932 //
2933 // Don't support multiple devices on the slot, that is
2934 // shared bus slot feature.
2935 //
2936 Rca = 1;
2937 Status = EmmcPeimSetRca (Slot, Rca);
2938 if (EFI_ERROR (Status)) {
2939 DEBUG ((DEBUG_ERROR, "EmmcPeimIdentification: EmmcPeimSetRca fails with %r\n", Status));
2940 return Status;
2941 }
2942
2943 //
2944 // Enter Data Tranfer Mode.
2945 //
2946 DEBUG ((DEBUG_INFO, "Found a EMMC device at slot [%d], RCA [%d]\n", Slot, Rca));
2947
2948 Status = EmmcPeimSetBusMode (Slot, Rca);
2949
2950 return Status;
2951}
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)
VOID EmmcPeimFreeMem(IN EMMC_PEIM_MEM_POOL *Pool, IN VOID *Mem, IN UINTN Size)
Definition: EmmcHcMem.c:366
VOID * EmmcPeimAllocateMem(IN EMMC_PEIM_MEM_POOL *Pool, IN UINTN Size)
Definition: EmmcHcMem.c:294
EFI_STATUS EmmcPeimHcEnableInterrupt(IN UINTN Bar)
Definition: EmmcHci.c:346
EFI_STATUS EmmcPeimHcSetBusWidth(IN UINTN Bar, IN UINT16 BusWidth)
Definition: EmmcHci.c:687
VOID EmmcPeimFreeTrb(IN EMMC_TRB *Trb)
Definition: EmmcHci.c:1099
EFI_STATUS EmmcPeimSendTuningBlk(IN EMMC_PEIM_HC_SLOT *Slot, IN UINT8 BusWidth)
Definition: EmmcHci.c:2276
EFI_STATUS EmmcPeimSelect(IN EMMC_PEIM_HC_SLOT *Slot, IN UINT32 Rca)
Definition: EmmcHci.c:1979
EFI_STATUS EmmcPeimHcInitHost(IN UINTN Bar)
Definition: EmmcHci.c:868
EFI_STATUS EmmcPeimHcClockSupply(IN UINTN Bar, IN UINT64 ClockFreq)
Definition: EmmcHci.c:514
EFI_STATUS EmmcPeimGetAllCid(IN EMMC_PEIM_HC_SLOT *Slot)
Definition: EmmcHci.c:1845
EFI_STATUS EmmcPeimGetExtCsd(IN EMMC_PEIM_HC_SLOT *Slot, OUT EMMC_EXT_CSD *ExtCsd)
Definition: EmmcHci.c:2020
EMMC_TRB * EmmcPeimCreateTrb(IN EMMC_PEIM_HC_SLOT *Slot, IN EMMC_COMMAND_PACKET *Packet)
Definition: EmmcHci.c:1003
EFI_STATUS EmmcPeimSetBlkCount(IN EMMC_PEIM_HC_SLOT *Slot, IN UINT16 BlockCount)
Definition: EmmcHci.c:2158
EFI_STATUS EmmcPeimExecTrb(IN UINTN Bar, IN EMMC_TRB *Trb)
Definition: EmmcHci.c:1232
EFI_STATUS EmmcPeimHcInitTimeoutCtrl(IN UINTN Bar)
Definition: EmmcHci.c:844
EFI_STATUS EFIAPI EmmcPeimExecCmd(IN EMMC_PEIM_HC_SLOT *Slot, IN OUT EMMC_COMMAND_PACKET *Packet)
Definition: EmmcHci.c:1694
EFI_STATUS EFIAPI EmmcPeimHcOrMmio(IN UINTN Address, IN UINT8 Count, IN VOID *OrData)
Definition: EmmcHci.c:104
EFI_STATUS BuildAdmaDescTable(IN EMMC_TRB *Trb)
Definition: EmmcHci.c:930
EFI_STATUS EmmcPeimHcGetCapability(IN UINTN Bar, OUT EMMC_HC_SLOT_CAP *Capability)
Definition: EmmcHci.c:382
EFI_STATUS EmmcPeimGetOcr(IN EMMC_PEIM_HC_SLOT *Slot, IN OUT UINT32 *Argument)
Definition: EmmcHci.c:1798
EFI_STATUS EmmcPeimSwitchClockFreq(IN EMMC_PEIM_HC_SLOT *Slot, IN UINT32 Rca, IN UINT8 HsTiming, IN UINT32 ClockFreq)
Definition: EmmcHci.c:2471
EFI_STATUS EFIAPI EmmcPeimHcRwMmio(IN UINTN Address, IN BOOLEAN Read, IN UINT8 Count, IN OUT VOID *Data)
Definition: EmmcHci.c:30
EFI_STATUS EmmcPeimSwitchBusWidth(IN EMMC_PEIM_HC_SLOT *Slot, IN UINT32 Rca, IN BOOLEAN IsDdr, IN UINT8 BusWidth)
Definition: EmmcHci.c:2401
EFI_STATUS EmmcPeimTuningClkForHs200(IN EMMC_PEIM_HC_SLOT *Slot, IN UINT8 BusWidth)
Definition: EmmcHci.c:2329
EFI_STATUS EmmcPeimCheckTrbResult(IN UINTN Bar, IN EMMC_TRB *Trb)
Definition: EmmcHci.c:1403
EFI_STATUS EmmcPeimSendStatus(IN EMMC_PEIM_HC_SLOT *Slot, IN UINT32 Rca, OUT UINT32 *DevStatus)
Definition: EmmcHci.c:2112
EFI_STATUS EmmcPeimHcInitClockFreq(IN UINTN Bar)
Definition: EmmcHci.c:734
EFI_STATUS EmmcPeimSwitch(IN EMMC_PEIM_HC_SLOT *Slot, IN UINT8 Access, IN UINT8 Index, IN UINT8 Value, IN UINT8 CmdSet)
Definition: EmmcHci.c:2067
EFI_STATUS EmmcPeimSwitchToHS200(IN EMMC_PEIM_HC_SLOT *Slot, IN UINT32 Rca, IN UINT32 ClockFreq, IN UINT8 BusWidth)
Definition: EmmcHci.c:2604
EFI_STATUS EmmcPeimCheckTrbEnv(IN UINTN Bar, IN EMMC_TRB *Trb)
Definition: EmmcHci.c:1130
EFI_STATUS EmmcPeimWaitTrbResult(IN UINTN Bar, IN EMMC_TRB *Trb)
Definition: EmmcHci.c:1621
EFI_STATUS EmmcPeimReset(IN EMMC_PEIM_HC_SLOT *Slot)
Definition: EmmcHci.c:1757
EFI_STATUS EmmcPeimHcReset(IN UINTN Bar)
Definition: EmmcHci.c:300
EFI_STATUS EFIAPI EmmcPeimHcCheckMmioSet(IN UINTN Address, IN UINT8 Count, IN UINT64 MaskValue, IN UINT64 TestValue)
Definition: EmmcHci.c:204
EFI_STATUS EmmcPeimSetRca(IN EMMC_PEIM_HC_SLOT *Slot, IN UINT32 Rca)
Definition: EmmcHci.c:1886
EFI_STATUS EmmcPeimHcCardDetect(IN UINTN Bar)
Definition: EmmcHci.c:414
EFI_STATUS EmmcPeimWaitTrbEnv(IN UINTN Bar, IN EMMC_TRB *Trb)
Definition: EmmcHci.c:1180
EFI_STATUS EmmcPeimSwitchToHighSpeed(IN EMMC_PEIM_HC_SLOT *Slot, IN UINT32 Rca, IN UINT32 ClockFreq, IN BOOLEAN IsDdr, IN UINT8 BusWidth)
Definition: EmmcHci.c:2536
EFI_STATUS EmmcPeimRwMultiBlocks(IN EMMC_PEIM_HC_SLOT *Slot, IN EFI_LBA Lba, IN UINT32 BlockSize, IN VOID *Buffer, IN UINTN BufferSize, IN BOOLEAN IsRead)
Definition: EmmcHci.c:2204
EFI_STATUS EFIAPI EmmcPeimHcAndMmio(IN UINTN Address, IN UINT8 Count, IN VOID *AndData)
Definition: EmmcHci.c:155
EFI_STATUS EmmcPeimHcStopClock(IN UINTN Bar)
Definition: EmmcHci.c:468
EFI_STATUS EmmcPeimSetBusMode(IN EMMC_PEIM_HC_SLOT *Slot, IN UINT32 Rca)
Definition: EmmcHci.c:2761
EFI_STATUS EmmcPeimGetCsd(IN EMMC_PEIM_HC_SLOT *Slot, IN UINT32 Rca, OUT EMMC_CSD *Csd)
Definition: EmmcHci.c:1931
EFI_STATUS EmmcPeimHcLedOnOff(IN UINTN Bar, IN BOOLEAN On)
Definition: EmmcHci.c:899
EFI_STATUS EmmcPeimIdentification(IN EMMC_PEIM_HC_SLOT *Slot)
Definition: EmmcHci.c:2894
EFI_STATUS EmmcPeimHcInitPowerVoltage(IN UINTN Bar)
Definition: EmmcHci.c:777
EFI_STATUS EFIAPI EmmcPeimHcWaitMmioSet(IN UINTN Address, IN UINT8 Count, IN UINT64 MaskValue, IN UINT64 TestValue, IN UINT64 Timeout)
Definition: EmmcHci.c:251
EFI_STATUS EmmcPeimHcPowerControl(IN UINTN Bar, IN UINT8 PowerCtrl)
Definition: EmmcHci.c:649
EFI_STATUS EmmcPeimSwitchToHS400(IN EMMC_PEIM_HC_SLOT *Slot, IN UINT32 Rca, IN UINT32 ClockFreq)
Definition: EmmcHci.c:2694
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 OFFSET_OF(TYPE, Field)
Definition: Base.h:758
#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
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: Emmc.h:84