1 /** @file
2 *
3 *  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
4 *  Copyright (c) 2011 - 2014, ARM Limited. All rights reserved.
5 *
6 *  This program and the accompanying materials
7 *  are licensed and made available under the terms and conditions of the BSD License
8 *  which accompanies this distribution.  The full text of the license may be found at
9 *  http://opensource.org/licenses/bsd-license.php
10 *
11 *  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 *  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 *
14 **/
15 
16 #include "MmcHostDxe.h"
17 
18 EMBEDDED_EXTERNAL_DEVICE   *gTPS65950;
19 UINT8                      mMaxDataTransferRate = 0;
20 UINT32                     mRca = 0;
21 BOOLEAN                    mBitModeSet = FALSE;
22 
23 
24 typedef struct {
25   VENDOR_DEVICE_PATH  Mmc;
26   EFI_DEVICE_PATH     End;
27 } MMCHS_DEVICE_PATH;
28 
29 MMCHS_DEVICE_PATH gMMCDevicePath = {
30   {
31     {
32       HARDWARE_DEVICE_PATH,
33       HW_VENDOR_DP,
34       { (UINT8)(sizeof(VENDOR_DEVICE_PATH)), (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8) },
35     },
36     { 0xb615f1f5, 0x5088, 0x43cd, { 0x80, 0x9c, 0xa1, 0x6e, 0x52, 0x48, 0x7d, 0x00 } }
37   },
38   {
39     END_DEVICE_PATH_TYPE,
40     END_ENTIRE_DEVICE_PATH_SUBTYPE,
41     { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
42   }
43 };
44 
45 BOOLEAN
IgnoreCommand(UINT32 Command)46 IgnoreCommand (
47   UINT32 Command
48   )
49 {
50   switch(Command) {
51     case MMC_CMD12:
52       return TRUE;
53     case MMC_CMD13:
54       return TRUE;
55     default:
56       return FALSE;
57   }
58 }
59 
60 UINT32
TranslateCommand(UINT32 Command)61 TranslateCommand (
62   UINT32 Command
63   )
64 {
65   UINT32 Translation;
66 
67   switch(Command) {
68     case MMC_CMD2:
69       Translation = CMD2;
70       break;
71     case MMC_CMD3:
72       Translation = CMD3;
73       break;
74     /*case MMC_CMD6:
75       Translation = CMD6;
76       break;*/
77     case MMC_CMD7:
78       Translation = CMD7;
79       break;
80     case MMC_CMD8:
81       Translation = CMD8;
82       break;
83     case MMC_CMD9:
84       Translation = CMD9;
85       break;
86     /*case MMC_CMD12:
87       Translation = CMD12;
88       break;
89     case MMC_CMD13:
90       Translation = CMD13;
91       break;*/
92     case MMC_CMD16:
93       Translation = CMD16;
94       break;
95     case MMC_CMD17:
96       Translation = 0x113A0014;//CMD17;
97       break;
98     case MMC_CMD24:
99       Translation = CMD24 | 4;
100       break;
101     case MMC_CMD55:
102       Translation = CMD55;
103       break;
104     case MMC_ACMD41:
105       Translation = ACMD41;
106       break;
107     default:
108       Translation = Command;
109   }
110 
111   return Translation;
112 }
113 
114 VOID
CalculateCardCLKD(UINTN * ClockFrequencySelect)115 CalculateCardCLKD (
116   UINTN *ClockFrequencySelect
117   )
118 {
119   UINTN    TransferRateValue = 0;
120   UINTN    TimeValue = 0 ;
121   UINTN    Frequency = 0;
122 
123   DEBUG ((DEBUG_BLKIO, "CalculateCardCLKD()\n"));
124 
125   // For SD Cards  we would need to send CMD6 to set
126   // speeds abouve 25MHz. High Speed mode 50 MHz and up
127 
128   // Calculate Transfer rate unit (Bits 2:0 of TRAN_SPEED)
129   switch (mMaxDataTransferRate & 0x7) { // 2
130     case 0:
131       TransferRateValue = 100 * 1000;
132       break;
133 
134     case 1:
135       TransferRateValue = 1 * 1000 * 1000;
136       break;
137 
138     case 2:
139       TransferRateValue = 10 * 1000 * 1000;
140       break;
141 
142     case 3:
143       TransferRateValue = 100 * 1000 * 1000;
144       break;
145 
146     default:
147       DEBUG ((DEBUG_BLKIO, "Invalid parameter.\n"));
148       ASSERT(FALSE);
149       return;
150   }
151 
152   //Calculate Time value (Bits 6:3 of TRAN_SPEED)
153   switch ((mMaxDataTransferRate >> 3) & 0xF) { // 6
154     case 1:
155       TimeValue = 10;
156       break;
157 
158     case 2:
159       TimeValue = 12;
160       break;
161 
162     case 3:
163       TimeValue = 13;
164       break;
165 
166     case 4:
167       TimeValue = 15;
168       break;
169 
170     case 5:
171       TimeValue = 20;
172       break;
173 
174     case 6:
175       TimeValue = 25;
176       break;
177 
178     case 7:
179       TimeValue = 30;
180       break;
181 
182     case 8:
183       TimeValue = 35;
184       break;
185 
186     case 9:
187       TimeValue = 40;
188       break;
189 
190     case 10:
191       TimeValue = 45;
192       break;
193 
194     case 11:
195       TimeValue = 50;
196       break;
197 
198     case 12:
199       TimeValue = 55;
200       break;
201 
202     case 13:
203       TimeValue = 60;
204       break;
205 
206     case 14:
207       TimeValue = 70;
208       break;
209 
210     case 15:
211       TimeValue = 80;
212       break;
213 
214     default:
215       DEBUG ((DEBUG_BLKIO, "Invalid parameter.\n"));
216       ASSERT(FALSE);
217       return;
218   }
219 
220   Frequency = TransferRateValue * TimeValue/10;
221 
222   // Calculate Clock divider value to program in MMCHS_SYSCTL[CLKD] field.
223   *ClockFrequencySelect = ((MMC_REFERENCE_CLK/Frequency) + 1);
224 
225   DEBUG ((DEBUG_BLKIO, "mMaxDataTransferRate: 0x%x, Frequency: %d KHz, ClockFrequencySelect: %x\n", mMaxDataTransferRate, Frequency/1000, *ClockFrequencySelect));
226 }
227 
228 VOID
UpdateMMCHSClkFrequency(UINTN NewCLKD)229 UpdateMMCHSClkFrequency (
230   UINTN NewCLKD
231   )
232 {
233   DEBUG ((DEBUG_BLKIO, "UpdateMMCHSClkFrequency()\n"));
234 
235   // Set Clock enable to 0x0 to not provide the clock to the card
236   MmioAnd32 (MMCHS_SYSCTL, ~CEN);
237 
238   // Set new clock frequency.
239   MmioAndThenOr32 (MMCHS_SYSCTL, ~CLKD_MASK, NewCLKD << 6);
240 
241   // Poll till Internal Clock Stable
242   while ((MmioRead32 (MMCHS_SYSCTL) & ICS_MASK) != ICS);
243 
244   // Set Clock enable to 0x1 to provide the clock to the card
245   MmioOr32 (MMCHS_SYSCTL, CEN);
246 }
247 
248 EFI_STATUS
InitializeMMCHS(VOID)249 InitializeMMCHS (
250   VOID
251   )
252 {
253   UINT8      Data;
254   EFI_STATUS Status;
255 
256   DEBUG ((DEBUG_BLKIO, "InitializeMMCHS()\n"));
257 
258   // Select Device group to belong to P1 device group in Power IC.
259   Data = DEV_GRP_P1;
260   Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VMMC1_DEV_GRP), 1, &Data);
261   ASSERT_EFI_ERROR(Status);
262 
263   // Configure voltage regulator for MMC1 in Power IC to output 3.0 voltage.
264   Data = VSEL_3_00V;
265   Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VMMC1_DEDICATED_REG), 1, &Data);
266   ASSERT_EFI_ERROR(Status);
267 
268   // After ramping up voltage, set VDDS stable bit to indicate that voltage level is stable.
269   MmioOr32 (CONTROL_PBIAS_LITE, (PBIASLITEVMODE0 | PBIASLITEPWRDNZ0 | PBIASSPEEDCTRL0 | PBIASLITEVMODE1 | PBIASLITEWRDNZ1));
270 
271   // Enable WP GPIO
272   MmioAndThenOr32 (GPIO1_BASE + GPIO_OE, ~BIT23, BIT23);
273 
274   // Enable Card Detect
275   Data = CARD_DETECT_ENABLE;
276   gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID2, TPS65950_GPIO_CTRL), 1, &Data);
277 
278   return Status;
279 }
280 
281 BOOLEAN
MMCIsCardPresent(IN EFI_MMC_HOST_PROTOCOL * This)282 MMCIsCardPresent (
283   IN EFI_MMC_HOST_PROTOCOL     *This
284   )
285 {
286   EFI_STATUS  Status;
287   UINT8       Data;
288 
289   //
290   // Card detect is a GPIO0 on the TPS65950
291   //
292   Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID2, GPIODATAIN1), 1, &Data);
293   if (EFI_ERROR (Status)) {
294     return FALSE;
295   }
296 
297   return !(Data & CARD_DETECT_BIT);
298 }
299 
300 BOOLEAN
MMCIsReadOnly(IN EFI_MMC_HOST_PROTOCOL * This)301 MMCIsReadOnly (
302   IN EFI_MMC_HOST_PROTOCOL     *This
303   )
304 {
305   /* Note:
306    * On our BeagleBoard the SD card WP pin is always read as TRUE.
307    * Probably something wrong with GPIO configuration.
308    * BeagleBoard-xM uses microSD cards so there is no write protect at all.
309    * Hence commenting out SD card WP pin read status.
310    */
311   //return (MmioRead32 (GPIO1_BASE + GPIO_DATAIN) & BIT23) == BIT23;
312   return 0;
313 
314 }
315 
316 // TODO
317 EFI_GUID mPL180MciDevicePathGuid = EFI_CALLER_ID_GUID;
318 
319 EFI_STATUS
MMCBuildDevicePath(IN EFI_MMC_HOST_PROTOCOL * This,IN EFI_DEVICE_PATH_PROTOCOL ** DevicePath)320 MMCBuildDevicePath (
321   IN EFI_MMC_HOST_PROTOCOL     *This,
322   IN EFI_DEVICE_PATH_PROTOCOL  **DevicePath
323   )
324 {
325   EFI_DEVICE_PATH_PROTOCOL    *NewDevicePathNode;
326 
327   NewDevicePathNode = CreateDeviceNode(HARDWARE_DEVICE_PATH,HW_VENDOR_DP,sizeof(VENDOR_DEVICE_PATH));
328   CopyGuid(&((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid,&mPL180MciDevicePathGuid);
329   *DevicePath = NewDevicePathNode;
330   return EFI_SUCCESS;
331 }
332 
333 EFI_STATUS
MMCSendCommand(IN EFI_MMC_HOST_PROTOCOL * This,IN MMC_CMD MmcCmd,IN UINT32 Argument)334 MMCSendCommand (
335   IN EFI_MMC_HOST_PROTOCOL     *This,
336   IN MMC_CMD                   MmcCmd,
337   IN UINT32                    Argument
338   )
339 {
340   UINTN MmcStatus;
341   UINTN RetryCount = 0;
342 
343   if (IgnoreCommand(MmcCmd))
344     return EFI_SUCCESS;
345 
346   MmcCmd = TranslateCommand(MmcCmd);
347 
348   //DEBUG ((EFI_D_ERROR, "MMCSendCommand(%d)\n", MmcCmd));
349 
350   // Check if command line is in use or not. Poll till command line is available.
351   while ((MmioRead32 (MMCHS_PSTATE) & DATI_MASK) == DATI_NOT_ALLOWED);
352 
353   // Provide the block size.
354   MmioWrite32 (MMCHS_BLK, BLEN_512BYTES);
355 
356   // Setting Data timeout counter value to max value.
357   MmioAndThenOr32 (MMCHS_SYSCTL, ~DTO_MASK, DTO_VAL);
358 
359   // Clear Status register.
360   MmioWrite32 (MMCHS_STAT, 0xFFFFFFFF);
361 
362   // Set command argument register
363   MmioWrite32 (MMCHS_ARG, Argument);
364 
365   //TODO: fix this
366   //Enable interrupt enable events to occur
367   //MmioWrite32 (MMCHS_IE, CmdInterruptEnableVal);
368 
369   // Send a command
370   MmioWrite32 (MMCHS_CMD, MmcCmd);
371 
372   // Check for the command status.
373   while (RetryCount < MAX_RETRY_COUNT) {
374     do {
375       MmcStatus = MmioRead32 (MMCHS_STAT);
376     } while (MmcStatus == 0);
377 
378     // Read status of command response
379     if ((MmcStatus & ERRI) != 0) {
380 
381       // Perform soft-reset for mmci_cmd line.
382       MmioOr32 (MMCHS_SYSCTL, SRC);
383       while ((MmioRead32 (MMCHS_SYSCTL) & SRC));
384 
385       //DEBUG ((EFI_D_INFO, "MmcStatus: 0x%x\n", MmcStatus));
386       return EFI_DEVICE_ERROR;
387     }
388 
389     // Check if command is completed.
390     if ((MmcStatus & CC) == CC) {
391       MmioWrite32 (MMCHS_STAT, CC);
392       break;
393     }
394 
395     RetryCount++;
396   }
397 
398   if (RetryCount == MAX_RETRY_COUNT) {
399     DEBUG ((DEBUG_BLKIO, "MMCSendCommand: Timeout\n"));
400     return EFI_TIMEOUT;
401   }
402 
403   return EFI_SUCCESS;
404 }
405 
406 EFI_STATUS
MMCNotifyState(IN EFI_MMC_HOST_PROTOCOL * This,IN MMC_STATE State)407 MMCNotifyState (
408   IN EFI_MMC_HOST_PROTOCOL    *This,
409   IN MMC_STATE                State
410   )
411 {
412   EFI_STATUS              Status;
413   UINTN                   FreqSel;
414 
415   switch(State) {
416     case MmcInvalidState:
417       ASSERT(0);
418       break;
419     case MmcHwInitializationState:
420       mBitModeSet = FALSE;
421 
422       DEBUG ((DEBUG_BLKIO, "MMCHwInitializationState()\n"));
423       Status = InitializeMMCHS ();
424       if (EFI_ERROR(Status)) {
425         DEBUG ((DEBUG_BLKIO, "Initialize MMC host controller fails. Status: %x\n", Status));
426         return Status;
427       }
428 
429       // Software reset of the MMCHS host controller.
430       MmioWrite32 (MMCHS_SYSCONFIG, SOFTRESET);
431       gBS->Stall(1000);
432       while ((MmioRead32 (MMCHS_SYSSTATUS) & RESETDONE_MASK) != RESETDONE);
433 
434       // Soft reset for all.
435       MmioWrite32 (MMCHS_SYSCTL, SRA);
436       gBS->Stall(1000);
437       while ((MmioRead32 (MMCHS_SYSCTL) & SRA) != 0x0);
438 
439       //Voltage capabilities initialization. Activate VS18 and VS30.
440       MmioOr32 (MMCHS_CAPA, (VS30 | VS18));
441 
442       // Wakeup configuration
443       MmioOr32 (MMCHS_SYSCONFIG, ENAWAKEUP);
444       MmioOr32 (MMCHS_HCTL, IWE);
445 
446       // MMCHS Controller default initialization
447       MmioOr32 (MMCHS_CON, (OD | DW8_1_4_BIT | CEATA_OFF));
448 
449       MmioWrite32 (MMCHS_HCTL, (SDVS_3_0_V | DTW_1_BIT | SDBP_OFF));
450 
451       // Enable internal clock
452       MmioOr32 (MMCHS_SYSCTL, ICE);
453 
454       // Set the clock frequency to 80KHz.
455       UpdateMMCHSClkFrequency (CLKD_80KHZ);
456 
457       // Enable SD bus power.
458       MmioOr32 (MMCHS_HCTL, (SDBP_ON));
459 
460       // Poll till SD bus power bit is set.
461       while ((MmioRead32 (MMCHS_HCTL) & SDBP_MASK) != SDBP_ON);
462 
463       // Enable interrupts.
464       MmioWrite32 (MMCHS_IE, (BADA_EN | CERR_EN | DEB_EN | DCRC_EN | DTO_EN | CIE_EN |
465         CEB_EN | CCRC_EN | CTO_EN | BRR_EN | BWR_EN | TC_EN | CC_EN));
466 
467       // Controller INIT procedure start.
468       MmioOr32 (MMCHS_CON, INIT);
469       MmioWrite32 (MMCHS_CMD, 0x00000000);
470       while (!(MmioRead32 (MMCHS_STAT) & CC));
471 
472       // Wait for 1 ms
473       gBS->Stall (1000);
474 
475       // Set CC bit to 0x1 to clear the flag
476       MmioOr32 (MMCHS_STAT, CC);
477 
478       // Retry INIT procedure.
479       MmioWrite32 (MMCHS_CMD, 0x00000000);
480       while (!(MmioRead32 (MMCHS_STAT) & CC));
481 
482       // End initialization sequence
483       MmioAnd32 (MMCHS_CON, ~INIT);
484 
485       MmioOr32 (MMCHS_HCTL, (SDVS_3_0_V | DTW_1_BIT | SDBP_ON));
486 
487       // Change clock frequency to 400KHz to fit protocol
488       UpdateMMCHSClkFrequency(CLKD_400KHZ);
489 
490       MmioOr32 (MMCHS_CON, OD);
491       break;
492     case MmcIdleState:
493       break;
494     case MmcReadyState:
495       break;
496     case MmcIdentificationState:
497       break;
498     case MmcStandByState:
499       CalculateCardCLKD (&FreqSel);
500       UpdateMMCHSClkFrequency (FreqSel);
501       break;
502     case MmcTransferState:
503       if (!mBitModeSet) {
504         Status = MMCSendCommand (This, CMD55, mRca << 16);
505         if (!EFI_ERROR (Status)) {
506           // Set device into 4-bit data bus mode
507           Status = MMCSendCommand (This, ACMD6, 0x2);
508           if (!EFI_ERROR (Status)) {
509             // Set host controler into 4-bit mode
510             MmioOr32 (MMCHS_HCTL, DTW_4_BIT);
511             DEBUG ((DEBUG_BLKIO, "SD Memory Card set to 4-bit mode\n"));
512             mBitModeSet = TRUE;
513           }
514         }
515       }
516       break;
517     case MmcSendingDataState:
518       break;
519     case MmcReceiveDataState:
520       break;
521     case MmcProgrammingState:
522       break;
523     case MmcDisconnectState:
524     default:
525       ASSERT(0);
526   }
527   return EFI_SUCCESS;
528 }
529 
530 EFI_STATUS
MMCReceiveResponse(IN EFI_MMC_HOST_PROTOCOL * This,IN MMC_RESPONSE_TYPE Type,IN UINT32 * Buffer)531 MMCReceiveResponse (
532   IN EFI_MMC_HOST_PROTOCOL     *This,
533   IN MMC_RESPONSE_TYPE         Type,
534   IN UINT32*                   Buffer
535   )
536 {
537   if (Buffer == NULL) {
538     return EFI_INVALID_PARAMETER;
539   }
540 
541   if (Type == MMC_RESPONSE_TYPE_R2) {
542     Buffer[0] = MmioRead32 (MMCHS_RSP10);
543     Buffer[1] = MmioRead32 (MMCHS_RSP32);
544     Buffer[2] = MmioRead32 (MMCHS_RSP54);
545     Buffer[3] = MmioRead32 (MMCHS_RSP76);
546   } else {
547     Buffer[0] = MmioRead32 (MMCHS_RSP10);
548   }
549 
550   if (Type == MMC_RESPONSE_TYPE_CSD) {
551     mMaxDataTransferRate = Buffer[3] & 0xFF;
552   } else if (Type == MMC_RESPONSE_TYPE_RCA) {
553     mRca = Buffer[0] >> 16;
554   }
555 
556   return EFI_SUCCESS;
557 }
558 
559 EFI_STATUS
MMCReadBlockData(IN EFI_MMC_HOST_PROTOCOL * This,IN EFI_LBA Lba,IN UINTN Length,IN UINT32 * Buffer)560 MMCReadBlockData (
561   IN EFI_MMC_HOST_PROTOCOL      *This,
562   IN EFI_LBA                    Lba,
563   IN UINTN                      Length,
564   IN UINT32*                    Buffer
565   )
566 {
567   UINTN MmcStatus;
568   UINTN Count;
569   UINTN RetryCount = 0;
570 
571   DEBUG ((DEBUG_BLKIO, "MMCReadBlockData(LBA: 0x%x, Length: 0x%x, Buffer: 0x%x)\n", Lba, Length, Buffer));
572 
573   // Check controller status to make sure there is no error.
574   while (RetryCount < MAX_RETRY_COUNT) {
575     do {
576       // Read Status.
577       MmcStatus = MmioRead32 (MMCHS_STAT);
578     } while(MmcStatus == 0);
579 
580     // Check if Buffer read ready (BRR) bit is set?
581     if (MmcStatus & BRR) {
582 
583       // Clear BRR bit
584       MmioOr32 (MMCHS_STAT, BRR);
585 
586       for (Count = 0; Count < Length / 4; Count++) {
587         *Buffer++ = MmioRead32(MMCHS_DATA);
588       }
589       break;
590     }
591     RetryCount++;
592   }
593 
594   if (RetryCount == MAX_RETRY_COUNT) {
595     return EFI_TIMEOUT;
596   }
597 
598   return EFI_SUCCESS;
599 }
600 
601 EFI_STATUS
MMCWriteBlockData(IN EFI_MMC_HOST_PROTOCOL * This,IN EFI_LBA Lba,IN UINTN Length,IN UINT32 * Buffer)602 MMCWriteBlockData (
603   IN EFI_MMC_HOST_PROTOCOL    *This,
604   IN EFI_LBA                  Lba,
605   IN UINTN                    Length,
606   IN UINT32*                  Buffer
607   )
608 {
609   UINTN MmcStatus;
610   UINTN Count;
611   UINTN RetryCount = 0;
612 
613   // Check controller status to make sure there is no error.
614   while (RetryCount < MAX_RETRY_COUNT) {
615     do {
616       // Read Status.
617       MmcStatus = MmioRead32 (MMCHS_STAT);
618     } while(MmcStatus == 0);
619 
620     // Check if Buffer write ready (BWR) bit is set?
621     if (MmcStatus & BWR) {
622 
623       // Clear BWR bit
624       MmioOr32 (MMCHS_STAT, BWR);
625 
626       // Write block worth of data.
627       for (Count = 0; Count < Length / 4; Count++) {
628         MmioWrite32 (MMCHS_DATA, *Buffer++);
629       }
630 
631       break;
632     }
633     RetryCount++;
634   }
635 
636   if (RetryCount == MAX_RETRY_COUNT) {
637     return EFI_TIMEOUT;
638   }
639 
640   return EFI_SUCCESS;
641 }
642 
643 EFI_MMC_HOST_PROTOCOL gMMCHost = {
644   MMC_HOST_PROTOCOL_REVISION,
645   MMCIsCardPresent,
646   MMCIsReadOnly,
647   MMCBuildDevicePath,
648   MMCNotifyState,
649   MMCSendCommand,
650   MMCReceiveResponse,
651   MMCReadBlockData,
652   MMCWriteBlockData
653 };
654 
655 EFI_STATUS
MMCInitialize(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)656 MMCInitialize (
657   IN EFI_HANDLE         ImageHandle,
658   IN EFI_SYSTEM_TABLE   *SystemTable
659   )
660 {
661   EFI_STATUS    Status;
662   EFI_HANDLE    Handle = NULL;
663 
664   DEBUG ((DEBUG_BLKIO, "MMCInitialize()\n"));
665 
666   Status = gBS->LocateProtocol (&gEmbeddedExternalDeviceProtocolGuid, NULL, (VOID **)&gTPS65950);
667   ASSERT_EFI_ERROR(Status);
668 
669   Status = gBS->InstallMultipleProtocolInterfaces (
670                   &Handle,
671                   &gEfiMmcHostProtocolGuid,         &gMMCHost,
672                   NULL
673                   );
674   ASSERT_EFI_ERROR (Status);
675 
676   return Status;
677 }
678