UINT32 PowerUp: 1; // This bit is set to LOW if the card has not finished the power up routine\r
} OCR;\r
\r
+typedef struct {\r
+ UINT8 SD_SPEC: 4; // SD Memory Card - Spec. Version [59:56]\r
+ UINT8 SCR_STRUCTURE: 4; // SCR Structure [63:60]\r
+ UINT8 SD_BUS_WIDTHS: 4; // DAT Bus widths supported [51:48]\r
+ UINT8 DATA_STAT_AFTER_ERASE: 1; // Data Status after erases [55]\r
+ UINT8 SD_SECURITY: 3; // CPRM Security Support [54:52]\r
+ UINT8 EX_SECURITY_1: 1; // Extended Security Support [43]\r
+ UINT8 SD_SPEC4: 1; // Spec. Version 4.00 or higher [42]\r
+ UINT8 RESERVED_1: 2; // Reserved [41:40]\r
+ UINT8 SD_SPEC3: 1; // Spec. Version 3.00 or higher [47]\r
+ UINT8 EX_SECURITY_2: 3; // Extended Security Support [46:44]\r
+ UINT8 CMD_SUPPORT: 4; // Command Support bits [35:32]\r
+ UINT8 RESERVED_2: 4; // Reserved [39:36]\r
+ UINT32 RESERVED_3; // Manufacturer Usage [31:0]\r
+} SCR;\r
+\r
typedef struct {\r
UINT32 NOT_USED; // 1 [0:0]\r
UINT32 CRC; // CRC7 checksum [7:1]\r
*\r
**/\r
\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/TimerLib.h>\r
+\r
#include "Mmc.h"\r
\r
typedef union {\r
\r
#define EMMC_SWITCH_ERROR (1 << 7)\r
\r
+#define SD_BUS_WIDTH_1BIT (1 << 0)\r
+#define SD_BUS_WIDTH_4BIT (1 << 2)\r
+\r
+#define SD_CCC_SWITCH (1 << 10)\r
+\r
#define DEVICE_STATE(x) (((x) >> 9) & 0xf)\r
typedef enum _EMMC_DEVICE_STATE {\r
EMMC_IDLE_STATE = 0,\r
{\r
UINT32 CmdArg;\r
UINT32 Response[4];\r
+ UINT32 Buffer[128];\r
UINTN BlockSize;\r
UINTN CardSize;\r
UINTN NumBlocks;\r
+ BOOLEAN CccSwitch;\r
+ SCR Scr;\r
EFI_STATUS Status;\r
EFI_MMC_HOST_PROTOCOL *MmcHost;\r
\r
return Status;\r
}\r
PrintCSD (Response);\r
+ if (MMC_CSD_GET_CCC(Response) & SD_CCC_SWITCH) {\r
+ CccSwitch = TRUE;\r
+ } else {\r
+ CccSwitch = FALSE;\r
+ }\r
\r
if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) {\r
CardSize = HC_MMC_CSD_GET_DEVICESIZE (Response);\r
return Status;\r
}\r
\r
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, CmdArg);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD55): Error and Status = %r\n", Status));\r
+ return Status;\r
+ }\r
+ Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD55): Error and Status = %r\n", Status));\r
+ return Status;\r
+ }\r
+ if ((Response[0] & MMC_STATUS_APP_CMD) == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ /* SCR */\r
+ Status = MmcHost->SendCommand (MmcHost, MMC_ACMD51, 0);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "%a(MMC_ACMD51): Error and Status = %r\n", __func__, Status));\r
+ return Status;\r
+ } else {\r
+ Status = MmcHost->ReadBlockData (MmcHost, 0, 8, Buffer);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "%a(MMC_ACMD51): ReadBlockData Error and Status = %r\n", __func__, Status));\r
+ return Status;\r
+ }\r
+ CopyMem (&Scr, Buffer, 8);\r
+ if (Scr.SD_SPEC == 2) {\r
+ if (Scr.SD_SPEC3 == 1) {\r
+ if (Scr.SD_SPEC4 == 1) {\r
+ DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 4.xx\n"));\r
+ } else {\r
+ DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 3.0x\n"));\r
+ }\r
+ } else {\r
+ if (Scr.SD_SPEC4 == 0) {\r
+ DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 2.0\n"));\r
+ } else {\r
+ DEBUG ((EFI_D_ERROR, "Found invalid SD Card\n"));\r
+ }\r
+ }\r
+ } else {\r
+ if ((Scr.SD_SPEC3 == 0) && (Scr.SD_SPEC4 == 0)) {\r
+ if (Scr.SD_SPEC == 1) {\r
+ DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 1.10\n"));\r
+ } else {\r
+ DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 1.0\n"));\r
+ }\r
+ } else {\r
+ DEBUG ((EFI_D_ERROR, "Found invalid SD Card\n"));\r
+ }\r
+ }\r
+ }\r
+ if (CccSwitch) {\r
+ /* SD Switch, Mode:1, Group:0, Value:1 */\r
+ CmdArg = 1 << 31 | 0x00FFFFFF;\r
+ CmdArg &= ~(0xF << (0 * 4));\r
+ CmdArg |= 1 << (0 * 4);\r
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, CmdArg);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD6): Error and Status = %r\n", Status));\r
+ return Status;\r
+ } else {\r
+ Status = MmcHost->ReadBlockData (MmcHost, 0, 64, Buffer);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD6): ReadBlockData Error and Status = %r\n", Status));\r
+ return Status;\r
+ }\r
+ }\r
+ }\r
+ if (Scr.SD_BUS_WIDTHS & SD_BUS_WIDTH_4BIT) {\r
+ CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, CmdArg);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD55): Error and Status = %r\n", Status));\r
+ return Status;\r
+ }\r
+ /* Width: 4 */\r
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, 2);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD6): Error and Status = %r\n", Status));\r
+ return Status;\r
+ }\r
+ }\r
+ if (MMC_HOST_HAS_SETIOS(MmcHost)) {\r
+ Status = MmcHost->SetIos (MmcHost, 26 * 1000 * 1000, 4, EMMCBACKWARD);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "%a(SetIos): Error and Status = %r\n", Status));\r
+ return Status;\r
+ }\r
+ }\r
return EFI_SUCCESS;\r
}\r
\r