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