mirror of https://github.com/acidanthera/audk.git
EmbeddedPkg/MmcDxe: set I/O speed and bus width in SD stack
Add more SD commands to support 4-bit bus width & iospeed. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org> Tested-by: Ryan Harkin <ryan.harkin@linaro.org> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
This commit is contained in:
parent
752ae80514
commit
e06253ba80
|
@ -80,6 +80,22 @@ typedef struct {
|
||||||
UINT32 PowerUp: 1; // This bit is set to LOW if the card has not finished the power up routine
|
UINT32 PowerUp: 1; // This bit is set to LOW if the card has not finished the power up routine
|
||||||
} OCR;
|
} OCR;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT8 SD_SPEC: 4; // SD Memory Card - Spec. Version [59:56]
|
||||||
|
UINT8 SCR_STRUCTURE: 4; // SCR Structure [63:60]
|
||||||
|
UINT8 SD_BUS_WIDTHS: 4; // DAT Bus widths supported [51:48]
|
||||||
|
UINT8 DATA_STAT_AFTER_ERASE: 1; // Data Status after erases [55]
|
||||||
|
UINT8 SD_SECURITY: 3; // CPRM Security Support [54:52]
|
||||||
|
UINT8 EX_SECURITY_1: 1; // Extended Security Support [43]
|
||||||
|
UINT8 SD_SPEC4: 1; // Spec. Version 4.00 or higher [42]
|
||||||
|
UINT8 RESERVED_1: 2; // Reserved [41:40]
|
||||||
|
UINT8 SD_SPEC3: 1; // Spec. Version 3.00 or higher [47]
|
||||||
|
UINT8 EX_SECURITY_2: 3; // Extended Security Support [46:44]
|
||||||
|
UINT8 CMD_SUPPORT: 4; // Command Support bits [35:32]
|
||||||
|
UINT8 RESERVED_2: 4; // Reserved [39:36]
|
||||||
|
UINT32 RESERVED_3; // Manufacturer Usage [31:0]
|
||||||
|
} SCR;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UINT32 NOT_USED; // 1 [0:0]
|
UINT32 NOT_USED; // 1 [0:0]
|
||||||
UINT32 CRC; // CRC7 checksum [7:1]
|
UINT32 CRC; // CRC7 checksum [7:1]
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
#include <Library/TimerLib.h>
|
||||||
|
|
||||||
#include "Mmc.h"
|
#include "Mmc.h"
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
|
@ -41,6 +44,11 @@ typedef union {
|
||||||
|
|
||||||
#define EMMC_SWITCH_ERROR (1 << 7)
|
#define EMMC_SWITCH_ERROR (1 << 7)
|
||||||
|
|
||||||
|
#define SD_BUS_WIDTH_1BIT (1 << 0)
|
||||||
|
#define SD_BUS_WIDTH_4BIT (1 << 2)
|
||||||
|
|
||||||
|
#define SD_CCC_SWITCH (1 << 10)
|
||||||
|
|
||||||
#define DEVICE_STATE(x) (((x) >> 9) & 0xf)
|
#define DEVICE_STATE(x) (((x) >> 9) & 0xf)
|
||||||
typedef enum _EMMC_DEVICE_STATE {
|
typedef enum _EMMC_DEVICE_STATE {
|
||||||
EMMC_IDLE_STATE = 0,
|
EMMC_IDLE_STATE = 0,
|
||||||
|
@ -296,9 +304,12 @@ InitializeSdMmcDevice (
|
||||||
{
|
{
|
||||||
UINT32 CmdArg;
|
UINT32 CmdArg;
|
||||||
UINT32 Response[4];
|
UINT32 Response[4];
|
||||||
|
UINT32 Buffer[128];
|
||||||
UINTN BlockSize;
|
UINTN BlockSize;
|
||||||
UINTN CardSize;
|
UINTN CardSize;
|
||||||
UINTN NumBlocks;
|
UINTN NumBlocks;
|
||||||
|
BOOLEAN CccSwitch;
|
||||||
|
SCR Scr;
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
EFI_MMC_HOST_PROTOCOL *MmcHost;
|
EFI_MMC_HOST_PROTOCOL *MmcHost;
|
||||||
|
|
||||||
|
@ -319,6 +330,11 @@ InitializeSdMmcDevice (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
PrintCSD (Response);
|
PrintCSD (Response);
|
||||||
|
if (MMC_CSD_GET_CCC(Response) & SD_CCC_SWITCH) {
|
||||||
|
CccSwitch = TRUE;
|
||||||
|
} else {
|
||||||
|
CccSwitch = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) {
|
if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) {
|
||||||
CardSize = HC_MMC_CSD_GET_DEVICESIZE (Response);
|
CardSize = HC_MMC_CSD_GET_DEVICESIZE (Response);
|
||||||
|
@ -349,6 +365,96 @@ InitializeSdMmcDevice (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, CmdArg);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "%a(MMC_CMD55): Error and Status = %r\n", Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "%a(MMC_CMD55): Error and Status = %r\n", Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
if ((Response[0] & MMC_STATUS_APP_CMD) == 0) {
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SCR */
|
||||||
|
Status = MmcHost->SendCommand (MmcHost, MMC_ACMD51, 0);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "%a(MMC_ACMD51): Error and Status = %r\n", __func__, Status));
|
||||||
|
return Status;
|
||||||
|
} else {
|
||||||
|
Status = MmcHost->ReadBlockData (MmcHost, 0, 8, Buffer);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "%a(MMC_ACMD51): ReadBlockData Error and Status = %r\n", __func__, Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
CopyMem (&Scr, Buffer, 8);
|
||||||
|
if (Scr.SD_SPEC == 2) {
|
||||||
|
if (Scr.SD_SPEC3 == 1) {
|
||||||
|
if (Scr.SD_SPEC4 == 1) {
|
||||||
|
DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 4.xx\n"));
|
||||||
|
} else {
|
||||||
|
DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 3.0x\n"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (Scr.SD_SPEC4 == 0) {
|
||||||
|
DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 2.0\n"));
|
||||||
|
} else {
|
||||||
|
DEBUG ((EFI_D_ERROR, "Found invalid SD Card\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((Scr.SD_SPEC3 == 0) && (Scr.SD_SPEC4 == 0)) {
|
||||||
|
if (Scr.SD_SPEC == 1) {
|
||||||
|
DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 1.10\n"));
|
||||||
|
} else {
|
||||||
|
DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 1.0\n"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DEBUG ((EFI_D_ERROR, "Found invalid SD Card\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (CccSwitch) {
|
||||||
|
/* SD Switch, Mode:1, Group:0, Value:1 */
|
||||||
|
CmdArg = 1 << 31 | 0x00FFFFFF;
|
||||||
|
CmdArg &= ~(0xF << (0 * 4));
|
||||||
|
CmdArg |= 1 << (0 * 4);
|
||||||
|
Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, CmdArg);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "%a(MMC_CMD6): Error and Status = %r\n", Status));
|
||||||
|
return Status;
|
||||||
|
} else {
|
||||||
|
Status = MmcHost->ReadBlockData (MmcHost, 0, 64, Buffer);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "%a(MMC_CMD6): ReadBlockData Error and Status = %r\n", Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Scr.SD_BUS_WIDTHS & SD_BUS_WIDTH_4BIT) {
|
||||||
|
CmdArg = MmcHostInstance->CardInfo.RCA << 16;
|
||||||
|
Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, CmdArg);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "%a(MMC_CMD55): Error and Status = %r\n", Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
/* Width: 4 */
|
||||||
|
Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, 2);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "%a(MMC_CMD6): Error and Status = %r\n", Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (MMC_HOST_HAS_SETIOS(MmcHost)) {
|
||||||
|
Status = MmcHost->SetIos (MmcHost, 26 * 1000 * 1000, 4, EMMCBACKWARD);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "%a(SetIos): Error and Status = %r\n", Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue