3 * Copyright (c) 2011, ARM Limited. All rights reserved.
5 * This program and the accompanying materials
6 * are licensed and made available under the terms and conditions of the BSD License
7 * which accompanies this distribution. The full text of the license may be found at
8 * http://opensource.org/licenses/bsd-license.php
10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include <Protocol/MmcHost.h>
16 #include <Library/DebugLib.h>
17 #include <Library/BaseMemoryLib.h>
18 #include <Library/TimerLib.h>
25 #define MAX_RETRY_COUNT 200
29 MMC_HOST_INSTANCE
*MmcHostInstance
,
32 MmcHostInstance
->State
= State
;
33 return MmcHostInstance
->MmcHost
->NotifyState(State
);
36 VOID
PrintOCR(UINT32 ocr
) {
37 UINTN minv
, maxv
, volts
;
44 // The MMC register bits [23:8] indicate the working range of the card
45 for (loop
= 8; loop
< 24; loop
++) {
46 if (ocr
& (1 << loop
)) {
47 if (minv
> volts
) minv
= volts
;
48 if (maxv
< volts
) maxv
= volts
+ 1;
53 DEBUG((EFI_D_ERROR
, "- PrintOCR ocr (0x%X)\n",ocr
));
54 DEBUG((EFI_D_ERROR
, "\t- Card operating voltage: %d.%d to %d.%d\n", minv
/10, minv
% 10, maxv
/10, maxv
% 10));
55 if (((ocr
>> 29) & 3) == 0)
56 DEBUG((EFI_D_ERROR
, "\t- AccessMode: Byte Mode\n"));
58 DEBUG((EFI_D_ERROR
, "\t- AccessMode: Block Mode (0x%X)\n",((ocr
>> 29) & 3)));
60 if (ocr
& MMC_OCR_POWERUP
)
61 DEBUG((EFI_D_ERROR
, "\t- PowerUp\n"));
63 DEBUG((EFI_D_ERROR
, "\t- Voltage Not Supported\n"));
66 VOID
PrintCID(UINT32
* cid
) {
67 DEBUG((EFI_D_ERROR
, "- PrintCID\n"));
68 DEBUG((EFI_D_ERROR
, "\t- Manufacturing date: %d/%d\n",(cid
[0] >> 8) & 0xF,(cid
[0] >> 12) & 0xFF));
69 DEBUG((EFI_D_ERROR
, "\t- Product serial number: 0x%X%X\n",cid
[1] & 0xFFFFFF,(cid
[0] >> 24) & 0xFF));
70 DEBUG((EFI_D_ERROR
, "\t- Product revision: %d\n",cid
[1] >> 24));
71 //DEBUG((EFI_D_ERROR, "\t- Product name: %s\n",(char*)(cid + 2)));
72 DEBUG((EFI_D_ERROR
, "\t- OEM ID: %c%c\n",(cid
[3] >> 8) & 0xFF,(cid
[3] >> 16) & 0xFF));
75 VOID
PrintCSD(UINT32
* csd
) {
77 CONST CHAR8
* str_unit
[] = { "100kbit/s","1Mbit/s","10Mbit/s","100MBit/s","Unkbown","Unkbown","Unkbown","Unkbown" };
78 CONST CHAR8
* str_value
[] = { "1.0","1.2","1.3","1.5","2.0","2.5","3.0","3.5","4.0","4.5","5.0","Unknown","Unknown","Unknown","Unknown" };
80 if (((csd
[2] >> 30) & 0x3) == 0)
81 DEBUG((EFI_D_ERROR
, "- PrintCSD Version 1.01-1.10/Version 2.00/Standard Capacity\n"));
82 else if (((csd
[2] >> 30) & 0x3) == 1)
83 DEBUG((EFI_D_ERROR
, "- PrintCSD Version 2.00/High Capacity\n"));
85 DEBUG((EFI_D_ERROR
, "- PrintCSD Version Higher than v3.3\n"));
87 DEBUG((EFI_D_ERROR
, "\t- Supported card command class: 0x%X\n",MMC_CSD_GET_CCC(csd
)));
88 DEBUG((EFI_D_ERROR
, "\t- Speed: %a %a\n",str_value
[(MMC_CSD_GET_TRANSPEED(csd
) >> 3) & 0xF],str_unit
[MMC_CSD_GET_TRANSPEED(csd
) & 7]));
89 DEBUG((EFI_D_ERROR
, "\t- Maximum Read Data Block: %d\n",2 << (MMC_CSD_GET_READBLLEN(csd
)-1)));
90 DEBUG((EFI_D_ERROR
, "\t- Maximum Write Data Block: %d\n",2 << (MMC_CSD_GET_WRITEBLLEN(csd
)-1)));
92 if (!MMC_CSD_GET_FILEFORMATGRP(csd
)) {
93 val32
= MMC_CSD_GET_FILEFORMAT(csd
);
94 if (val32
== 0) DEBUG((EFI_D_ERROR
, "\t- Format(0): Hard disk-like file system with partition table\n"));
95 else if (val32
== 1) DEBUG((EFI_D_ERROR
, "\t- Format(1): DOS FAT (floppy-like) with boot sector only (no partition table)\n"));
96 else if (val32
== 2) DEBUG((EFI_D_ERROR
, "\t- Format(2): Universal File Format\n"));
97 else DEBUG((EFI_D_ERROR
, "\t- Format(3): Others/Unknown\n"));
99 DEBUG((EFI_D_ERROR
, "\t- Format: Reserved\n"));
103 VOID
PrintRCA(UINT32 rca
) {
104 DEBUG((EFI_D_ERROR
, "- PrintRCA: 0x%X\n",rca
));
105 DEBUG((EFI_D_ERROR
, "\t- Status: 0x%X\n",rca
& 0xFFFF));
106 DEBUG((EFI_D_ERROR
, "\t- RCA: 0x%X\n",(rca
>> 16) & 0xFFFF));
109 VOID
PrintResponseR1(UINT32 response
) {
110 DEBUG((EFI_D_ERROR
, "Response: 0x%X\n",response
));
111 if (response
& (1 << 8)) DEBUG((EFI_D_ERROR
, "\t- READY_FOR_DATA\n"));
113 if (((response
>> 9) & 0xF) == 0) DEBUG((EFI_D_ERROR
, "\t- State: Idle\n"));
114 else if (((response
>> 9) & 0xF) == 1) DEBUG((EFI_D_ERROR
, "\t- State: Ready\n"));
115 else if (((response
>> 9) & 0xF) == 2) DEBUG((EFI_D_ERROR
, "\t- State: Ident\n"));
116 else if (((response
>> 9) & 0xF) == 3) DEBUG((EFI_D_ERROR
, "\t- State: StandBy\n"));
117 else if (((response
>> 9) & 0xF) == 4) DEBUG((EFI_D_ERROR
, "\t- State: Tran\n"));
118 else if (((response
>> 9) & 0xF) == 5) DEBUG((EFI_D_ERROR
, "\t- State: Data\n"));
119 else if (((response
>> 9) & 0xF) == 6) DEBUG((EFI_D_ERROR
, "\t- State: Rcv\n"));
120 else if (((response
>> 9) & 0xF) == 7) DEBUG((EFI_D_ERROR
, "\t- State: Prg\n"));
121 else if (((response
>> 9) & 0xF) == 8) DEBUG((EFI_D_ERROR
, "\t- State: Dis\n"));
122 else DEBUG((EFI_D_ERROR
, "\t- State: Reserved\n"));
127 MmcIdentificationMode (
128 MMC_HOST_INSTANCE
*MmcHostInstance
135 EFI_MMC_HOST_PROTOCOL
*MmcHost
;
137 MmcHost
= MmcHostInstance
->MmcHost
;
141 if (MmcHost
== NULL
) {
142 return EFI_INVALID_PARAMETER
;
145 // We can get into this function if we restart the identification mode
146 if (MmcHostInstance
->State
== MmcHwInitializationState
) {
147 // Initialize the MMC Host HW
148 Status
= MmcNotifyState (MmcHostInstance
, MmcHwInitializationState
);
149 if (EFI_ERROR(Status
)) {
150 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode() : Error MmcHwInitializationState\n"));
154 //Note: Could even be used in all cases. But it looks this command could put the state machine into inactive for some cards
155 Status
= MmcHost
->SendCommand(MMC_CMD0
, 0);
156 if (EFI_ERROR(Status
)) {
157 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode(MMC_CMD0): Error\n"));
162 Status
= MmcNotifyState (MmcHostInstance
, MmcIdleState
);
163 if (EFI_ERROR(Status
)) {
164 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode() : Error MmcIdleState\n"));
168 // Are we using SDIO ?
169 Status
= MmcHost
->SendCommand(MMC_CMD5
, 0);
170 if (Status
== EFI_SUCCESS
) {
171 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode(MMC_CMD5): Error - SDIO not supported.\n"));
172 return EFI_UNSUPPORTED
;
175 // Check which kind of card we are using. Ver2.00 or later SD Memory Card (PL180 is SD v1.1)
176 CmdArg
= (0x0UL
<< 12 | BIT8
| 0xCEUL
<< 0);
177 Status
= MmcHost
->SendCommand(MMC_CMD8
, CmdArg
);
178 if (Status
== EFI_SUCCESS
) {
179 DEBUG ((EFI_D_ERROR
, "Card is SD2.0 => Supports high capacity\n"));
181 MmcHost
->ReceiveResponse(MMC_RESPONSE_TYPE_R7
,Response
);
182 PrintResponseR1(Response
[0]);
184 DEBUG ((EFI_D_ERROR
, "Not a SD2.0 Card\n"));
187 // We need to wait for the MMC or SD card is ready => (gCardInfo.OCRData.Busy == 1)
188 timer
= MAX_RETRY_COUNT
;
190 // SD Card or MMC Card ? CMD55 indicates to the card that the next command is an application specific command
191 Status
= MmcHost
->SendCommand(MMC_CMD55
, 0);
192 if (Status
== EFI_SUCCESS
) {
193 DEBUG ((EFI_D_INFO
, "Card should be SD\n"));
195 MmcHostInstance
->CardInfo
.CardType
= SD_CARD_2
;
197 MmcHostInstance
->CardInfo
.CardType
= SD_CARD
;
200 // Note: The first time CmdArg will be zero
201 CmdArg
= ((UINTN
*) &(MmcHostInstance
->CardInfo
.OCRData
))[0];
205 Status
= MmcHost
->SendCommand(MMC_ACMD41
, CmdArg
);
206 if (EFI_ERROR(Status
)) {
207 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode(ACMD41): Error\n"));
210 MmcHost
->ReceiveResponse(MMC_RESPONSE_TYPE_OCR
,Response
);
211 ((UINT32
*) &(MmcHostInstance
->CardInfo
.OCRData
))[0] = Response
[0];
213 DEBUG ((EFI_D_INFO
, "Card should be MMC\n"));
214 MmcHostInstance
->CardInfo
.CardType
= MMC_CARD
;
216 Status
= MmcHost
->SendCommand(MMC_CMD1
, 0x800000);
217 if (EFI_ERROR(Status
)) {
218 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode(ACMD41): Error\n"));
221 MmcHost
->ReceiveResponse(MMC_RESPONSE_TYPE_OCR
,Response
);
222 ((UINT32
*) &(MmcHostInstance
->CardInfo
.OCRData
))[0] = Response
[0];
225 if (MmcHostInstance
->CardInfo
.OCRData
.Busy
== 0) {
226 MicroSecondDelay(10*1000);
229 if ((MmcHostInstance
->CardInfo
.CardType
== SD_CARD_2
) && (MmcHostInstance
->CardInfo
.OCRData
.AccessMode
& BIT1
)) {
230 MmcHostInstance
->CardInfo
.CardType
= SD_CARD_2_HIGH
;
231 DEBUG ((EFI_D_ERROR
, "High capacity card.\n"));
233 break; // The MMC/SD card is ready. Continue the Identification Mode
238 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode(): No Card\n"));
242 PrintOCR(Response
[0]);
245 Status
= MmcNotifyState (MmcHostInstance
, MmcReadyState
);
246 if (EFI_ERROR(Status
)) {
247 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode() : Error MmcReadyState\n"));
251 Status
= MmcHost
->SendCommand(MMC_CMD2
, 0);
252 if (EFI_ERROR(Status
)) {
253 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode(MMC_CMD2): Error\n"));
257 MmcHost
->ReceiveResponse(MMC_RESPONSE_TYPE_CID
,Response
);
260 Status
= MmcNotifyState (MmcHostInstance
, MmcIdentificationState
);
261 if (EFI_ERROR(Status
)) {
262 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode() : Error MmcIdentificationState\n"));
267 Status
= MmcHost
->SendCommand(MMC_CMD3
, CmdArg
);
268 if (EFI_ERROR(Status
)) {
269 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode(MMC_CMD3): Error\n"));
272 MmcHost
->ReceiveResponse(MMC_RESPONSE_TYPE_RCA
,Response
);
273 PrintRCA(Response
[0]);
275 // For MMC card, RCA is assigned by CMD3 while CMD3 dumps the RCA for SD card
276 if (MmcHostInstance
->CardInfo
.CardType
!= MMC_CARD
) {
277 MmcHostInstance
->CardInfo
.RCA
= Response
[0] >> 16;
279 MmcHostInstance
->CardInfo
.RCA
= CmdArg
;
282 Status
= MmcNotifyState (MmcHostInstance
, MmcStandByState
);
283 if (EFI_ERROR(Status
)) {
284 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode() : Error MmcStandByState\n"));
294 IN EFI_BLOCK_IO_PROTOCOL
*This
,
295 IN BOOLEAN ExtendedVerification
297 // Implement me. Either send a CMD0 (could not work for some MMC host) or just turn off/turn
298 // on power and restart Identification mode
304 EFI_MMC_HOST_PROTOCOL
*MmcHost
307 if (!MmcHost
->IsCardPresent()) {
314 #define MMCI0_BLOCKLEN 512
315 #define MMCI0_TIMEOUT 10000
317 EFI_STATUS
MmcIoBlocks (
318 IN EFI_BLOCK_IO_PROTOCOL
*This
,
327 UINTN CardSize
, NumBlocks
, BlockSize
, CmdArg
;
330 MMC_HOST_INSTANCE
*MmcHostInstance
;
331 EFI_MMC_HOST_PROTOCOL
*MmcHost
;
332 UINTN BytesRemainingToBeTransfered
;
333 UINTN BlockCount
= 1;
335 MmcHostInstance
= MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS(This
);
336 ASSERT(MmcHostInstance
!= 0);
337 MmcHost
= MmcHostInstance
->MmcHost
;
341 return EFI_INVALID_PARAMETER
;
344 // Check if a Card is Present
345 if (!MmcHost
->IsCardPresent()) {
346 MmcHostInstance
->BlockIo
.Media
->MediaPresent
= FALSE
;
347 MmcHostInstance
->BlockIo
.Media
->LastBlock
= 0;
348 MmcHostInstance
->BlockIo
.Media
->BlockSize
= 512; // Should be zero but there is a bug in DiskIo
349 MmcHostInstance
->BlockIo
.Media
->ReadOnly
= FALSE
;
353 // If the driver has not been initialized yet then go into Iddentification Mode
354 if (MmcHostInstance
->State
== MmcHwInitializationState
) {
355 MmcIdentificationMode (MmcHostInstance
);
357 CmdArg
= MmcHostInstance
->CardInfo
.RCA
<< 16;
358 Status
= MmcHost
->SendCommand(MMC_CMD9
, CmdArg
);
359 if (EFI_ERROR(Status
)) {
360 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode(MMC_CMD9): Error\n"));
364 MmcHost
->ReceiveResponse(MMC_RESPONSE_TYPE_CSD
,Response
);
368 if (MmcHostInstance
->CardInfo
.CardType
== SD_CARD_2_HIGH
) {
369 ASSERT(0); //TODO: Implementation needed
370 CardSize
= MMC_CSD_GET_DEVICESIZE(Response
);
371 NumBlocks
= ((CardSize
+ 1) * 1024);;
372 BlockSize
= 1 << MMC_CSD_GET_READBLLEN(Response
);
374 CardSize
= MMC_CSD_GET_DEVICESIZE(Response
);
375 NumBlocks
= (CardSize
+ 1) * (1 << (MMC_CSD_GET_DEVICESIZEMULT(Response
) + 2));
376 BlockSize
= 1 << MMC_CSD_GET_READBLLEN(Response
);
379 //For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes.
380 if (BlockSize
> 512) {
381 NumBlocks
= MultU64x32(NumBlocks
, BlockSize
/512);
385 MmcHostInstance
->BlockIo
.Media
->LastBlock
= (NumBlocks
- 1);
386 MmcHostInstance
->BlockIo
.Media
->BlockSize
= BlockSize
;
387 MmcHostInstance
->BlockIo
.Media
->ReadOnly
= MmcHost
->IsReadOnly();
388 MmcHostInstance
->BlockIo
.Media
->MediaPresent
= TRUE
;
389 MmcHostInstance
->BlockIo
.Media
->MediaId
++;
391 CmdArg
= MmcHostInstance
->CardInfo
.RCA
<< 16;
392 Status
= MmcHost
->SendCommand(MMC_CMD7
, CmdArg
);
393 if (EFI_ERROR(Status
)) {
394 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode(MMC_CMD7): Error\n"));
399 Status
= MmcNotifyState (MmcHostInstance
, MmcTransferState
);
400 if (EFI_ERROR(Status
)) {
401 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode() : Error MmcTransferState\n"));
405 // Maybe test if the card has changed to update gMmcMedia information
406 if (MmcHostInstance
->State
== MmcTransferState
) {
407 //DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : MmcTransferState\n"));
408 } else if (MmcHostInstance
->State
== MmcStandByState
) {
409 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode() : MmcStandByState\n"));
415 if (Lba
> This
->Media
->LastBlock
) {
417 return EFI_INVALID_PARAMETER
;
420 if ((BufferSize
% This
->Media
->BlockSize
) != 0) {
422 return EFI_BAD_BUFFER_SIZE
;
425 BytesRemainingToBeTransfered
= BufferSize
;
426 while (BytesRemainingToBeTransfered
> 0) {
428 Status
= MmcHost
->SendCommand(MMC_CMD16
, This
->Media
->BlockSize
);
429 if (EFI_ERROR(Status
)) {
430 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode(MMC_CMD16): Error This->Media->BlockSize:%d\n",This
->Media
->BlockSize
));
435 // Block Count (not used). Could return an error for SD card
436 MmcHost
->SendCommand(MMC_CMD23
, BlockCount
);
438 //Set command argument based on the card access mode (Byte mode or Block mode)
439 if (MmcHostInstance
->CardInfo
.OCRData
.AccessMode
& BIT1
) {
442 CmdArg
= Lba
* This
->Media
->BlockSize
;
445 if (Transfer
== MMC_IOBLOCKS_READ
) {
447 // Read a single block
450 //TODO: Should we support read stream (MMC_CMD11)
454 // Write a single block
457 //TODO: Should we support write stream (MMC_CMD20)
460 Status
= MmcHost
->SendCommand(Cmd
, CmdArg
);
461 if (EFI_ERROR(Status
)) {
462 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode(MMC_CMD%d): Error\n",Cmd
));
467 if (Transfer
== MMC_IOBLOCKS_READ
) {
469 // Read one block of Data
470 Status
= MmcHost
->ReadBlockData(Lba
,This
->Media
->BlockSize
,Buffer
);
471 if (EFI_ERROR(Status
)) {
472 DEBUG((EFI_D_BLKIO
, "MmcIdentificationMode(): Error Read Block Data"));
480 Status
= MmcNotifyState (MmcHostInstance
, MmcProgrammingState
);
481 if (EFI_ERROR(Status
)) {
482 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode() : Error MmcProgrammingState\n"));
487 // Write one block of Data
488 Status
= MmcHost
->WriteBlockData(Lba
,This
->Media
->BlockSize
,Buffer
);
489 if (EFI_ERROR(Status
)) {
490 DEBUG((EFI_D_BLKIO
, "MmcIdentificationMode(): Error Write Block Data"));
495 //TODO: Write a steam
500 // Command 12 - Stop transmission (ends read)
501 Status
= MmcHost
->SendCommand(MMC_CMD12
, 0);
502 MmcHost
->ReceiveResponse(MMC_RESPONSE_TYPE_R1b
,Response
);
504 // Command 13 - Read status and wait for programming to complete (return to tran)
505 timer
= MMCI0_TIMEOUT
;
506 while ((MMC_R0_CURRENTSTATE(Response
) != MMC_R0_STATE_TRAN
) && timer
) {
507 MmcHost
->SendCommand(MMC_CMD13
, 0);
508 MmcHost
->ReceiveResponse(MMC_RESPONSE_TYPE_R1
,Response
);
509 NanoSecondDelay(100);
513 Status
= MmcNotifyState (MmcHostInstance
, MmcTransferState
);
514 if (EFI_ERROR(Status
)) {
515 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode() : Error MmcTransferState\n"));
519 BytesRemainingToBeTransfered
-= This
->Media
->BlockSize
;
521 Buffer
= (UINT8
*)Buffer
+ This
->Media
->BlockSize
;
530 IN EFI_BLOCK_IO_PROTOCOL
*This
,
536 return MmcIoBlocks (This
, MMC_IOBLOCKS_READ
, MediaId
, Lba
, BufferSize
, Buffer
);
542 IN EFI_BLOCK_IO_PROTOCOL
*This
,
548 return MmcIoBlocks (This
, MMC_IOBLOCKS_WRITE
, MediaId
, Lba
, BufferSize
, Buffer
);
554 IN EFI_BLOCK_IO_PROTOCOL
*This