Skip to content

Commit

Permalink
MdeModulePkg/SdMmcPciHcDxe: Check SD's supported bus mode before switch
Browse files Browse the repository at this point in the history
Before switch to a bus mode, we need check if the SD device supports
this bus mode.

Cc: Wu, Hao A <[email protected]>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Feng Tian <[email protected]>
  • Loading branch information
ftian1 committed May 6, 2016
1 parent 8c983d3 commit 6263ae9
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 41 deletions.
54 changes: 35 additions & 19 deletions MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
Original file line number Diff line number Diff line change
Expand Up @@ -591,28 +591,29 @@ SdCardSetBusWidth (
@param[in] DriveStrength The value for drive length group.
@param[in] PowerLimit The value for power limit group.
@param[in] Mode Switch or check function.
@param[out] SwitchResp The return switch function status.
@retval EFI_SUCCESS The operation is done correctly.
@retval Others The operation fails.
**/
EFI_STATUS
SdCardSwitch (
IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
IN UINT8 Slot,
IN UINT8 AccessMode,
IN UINT8 CommandSystem,
IN UINT8 DriveStrength,
IN UINT8 PowerLimit,
IN BOOLEAN Mode
IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
IN UINT8 Slot,
IN UINT8 AccessMode,
IN UINT8 CommandSystem,
IN UINT8 DriveStrength,
IN UINT8 PowerLimit,
IN BOOLEAN Mode,
OUT UINT8 *SwitchResp
)
{
EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
EFI_STATUS Status;
UINT32 ModeValue;
UINT8 Data[64];

ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
Expand All @@ -631,8 +632,8 @@ SdCardSwitch (
((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) << 12) | \
ModeValue;

Packet.InDataBuffer = Data;
Packet.InTransferLength = sizeof (Data);
Packet.InDataBuffer = SwitchResp;
Packet.InTransferLength = 64;

Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);

Expand Down Expand Up @@ -891,6 +892,7 @@ SdCardSetBusMode (
UINT8 AccessMode;
UINT8 HostCtrl1;
UINT8 HostCtrl2;
UINT8 SwitchResp[64];
SD_MMC_HC_PRIVATE_DATA *Private;

Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
Expand All @@ -908,32 +910,46 @@ SdCardSetBusMode (
if (EFI_ERROR (Status)) {
return Status;
}

//
// Calculate supported bus speed/bus width/clock frequency.
// Get the supported bus speed from SWITCH cmd return data group #1.
//
Status = SdCardSwitch (PassThru, Slot, 0xF, 0xF, 0xF, 0xF, FALSE, SwitchResp);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Calculate supported bus speed/bus width/clock frequency by host and device capability.
//
ClockFreq = 0;
if (S18A && (Capability->Sdr104 != 0)) {
if (S18A && (Capability->Sdr104 != 0) && ((SwitchResp[13] & BIT3) != 0)) {
ClockFreq = 208;
AccessMode = 3;
} else if (S18A && (Capability->Sdr50 != 0)) {
} else if (S18A && (Capability->Sdr50 != 0) && ((SwitchResp[13] & BIT2) != 0)) {
ClockFreq = 100;
AccessMode = 2;
} else if (S18A && (Capability->Ddr50 != 0)) {
} else if (S18A && (Capability->Ddr50 != 0) && ((SwitchResp[13] & BIT4) != 0)) {
ClockFreq = 50;
AccessMode = 4;
} else {
} else if ((SwitchResp[13] & BIT1) != 0) {
ClockFreq = 50;
AccessMode = 1;
} else {
ClockFreq = 25;
AccessMode = 0;
}

DEBUG ((EFI_D_INFO, "SdCardSetBusMode: AccessMode %d ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));

Status = SdCardSwitch (PassThru, Slot, AccessMode, 0, 0, 0, TRUE);
Status = SdCardSwitch (PassThru, Slot, AccessMode, 0xF, 0xF, 0xF, TRUE, SwitchResp);
if (EFI_ERROR (Status)) {
return Status;
}

if ((SwitchResp[16] & 0xF) != AccessMode) {
DEBUG ((EFI_D_ERROR, "SdCardSetBusMode: Switch to AccessMode %d ClockFreq %d BusWidth %d fails! The Switch response is 0x%1x\n", AccessMode, ClockFreq, BusWidth, SwitchResp[16] & 0xF));
return EFI_DEVICE_ERROR;
}

DEBUG ((EFI_D_INFO, "SdCardSetBusMode: Switch to AccessMode %d ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));

//
// Set to Hight Speed timing
//
Expand Down
48 changes: 32 additions & 16 deletions MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.c
Original file line number Diff line number Diff line change
Expand Up @@ -2192,27 +2192,28 @@ SdPeimSetBusWidth (
@param[in] DriveStrength The value for drive length group.
@param[in] PowerLimit The value for power limit group.
@param[in] Mode Switch or check function.
@param[out] SwitchResp The return switch function status.
@retval EFI_SUCCESS The operation is done correctly.
@retval Others The operation fails.
**/
EFI_STATUS
SdPeimSwitch (
IN SD_PEIM_HC_SLOT *Slot,
IN UINT8 AccessMode,
IN UINT8 CommandSystem,
IN UINT8 DriveStrength,
IN UINT8 PowerLimit,
IN BOOLEAN Mode
IN SD_PEIM_HC_SLOT *Slot,
IN UINT8 AccessMode,
IN UINT8 CommandSystem,
IN UINT8 DriveStrength,
IN UINT8 PowerLimit,
IN BOOLEAN Mode,
OUT UINT8 *SwitchResp
)
{
SD_COMMAND_BLOCK SdCmdBlk;
SD_STATUS_BLOCK SdStatusBlk;
SD_COMMAND_PACKET Packet;
EFI_STATUS Status;
UINT32 ModeValue;
UINT8 Data[64];

ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));
ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));
Expand All @@ -2230,8 +2231,8 @@ SdPeimSwitch (
SdCmdBlk.CommandArgument = (AccessMode & 0xF) | ((PowerLimit & 0xF) << 4) | \
((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) << 12) | \
ModeValue;
Packet.InDataBuffer = Data;
Packet.InTransferLength = sizeof (Data);
Packet.InDataBuffer = SwitchResp;
Packet.InTransferLength = 64;

Status = SdPeimExecCmd (Slot, &Packet);

Expand Down Expand Up @@ -2617,6 +2618,7 @@ SdPeimSetBusMode (
UINT8 AccessMode;
UINT8 HostCtrl1;
UINT8 HostCtrl2;
UINT8 SwitchResp[64];

Status = SdPeimGetCsd (Slot, Rca, &Slot->Csd);
if (EFI_ERROR (Status)) {
Expand All @@ -2643,31 +2645,45 @@ SdPeimSetBusMode (
}

//
// Calculate supported bus speed/bus width/clock frequency.
// Get the supported bus speed from SWITCH cmd return data group #1.
//
Status = SdPeimSwitch (Slot, 0xF, 0xF, 0xF, 0xF, FALSE, SwitchResp);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Calculate supported bus speed/bus width/clock frequency by host and device capability.
//
ClockFreq = 0;
if (S18a && (Capability.Sdr104 != 0)) {
if (S18a && (Capability.Sdr104 != 0) && ((SwitchResp[13] & BIT3) != 0)) {
ClockFreq = 208;
AccessMode = 3;
} else if (S18a && (Capability.Sdr50 != 0)) {
} else if (S18a && (Capability.Sdr50 != 0) && ((SwitchResp[13] & BIT2) != 0)) {
ClockFreq = 100;
AccessMode = 2;
} else if (S18a && (Capability.Ddr50 != 0)) {
} else if (S18a && (Capability.Ddr50 != 0) && ((SwitchResp[13] & BIT4) != 0)) {
ClockFreq = 50;
AccessMode = 4;
} else {
} else if ((SwitchResp[13] & BIT1) != 0) {
ClockFreq = 50;
AccessMode = 1;
} else {
ClockFreq = 25;
AccessMode = 0;
}

DEBUG ((EFI_D_INFO, "AccessMode %d ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));
DEBUG ((EFI_D_INFO, "SdPeimSetBusMode: AccessMode %d ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));

Status = SdPeimSwitch (Slot, AccessMode, 0, 0, 0, TRUE);
Status = SdPeimSwitch (Slot, AccessMode, 0xF, 0xF, 0xF, TRUE, SwitchResp);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SdPeimSetBusMode: SdPeimSwitch fails with %r\n", Status));
return Status;
}

if ((SwitchResp[16] & 0xF) != AccessMode) {
DEBUG ((EFI_D_ERROR, "SdPeimSetBusMode: SdPeimSwitch to AccessMode %d ClockFreq %d BusWidth %d fails! The Switch response is 0x%1x\n", AccessMode, ClockFreq, BusWidth, SwitchResp[16] & 0xF));
return EFI_DEVICE_ERROR;
}
//
// Set to Hight Speed timing
//
Expand Down
14 changes: 8 additions & 6 deletions MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,19 +254,21 @@ SdPeimHcInitHost (
@param[in] DriveStrength The value for drive length group.
@param[in] PowerLimit The value for power limit group.
@param[in] Mode Switch or check function.
@param[out] SwitchResp The return switch function status.
@retval EFI_SUCCESS The operation is done correctly.
@retval Others The operation fails.
**/
EFI_STATUS
SdPeimSwitch (
IN SD_PEIM_HC_SLOT *Slot,
IN UINT8 AccessMode,
IN UINT8 CommandSystem,
IN UINT8 DriveStrength,
IN UINT8 PowerLimit,
IN BOOLEAN Mode
IN SD_PEIM_HC_SLOT *Slot,
IN UINT8 AccessMode,
IN UINT8 CommandSystem,
IN UINT8 DriveStrength,
IN UINT8 PowerLimit,
IN BOOLEAN Mode,
OUT UINT8 *SwitchResp
);

/**
Expand Down

0 comments on commit 6263ae9

Please sign in to comment.