MdeModulePkg/SdMmcPciHcDxe: Check SD's supported bus mode before switch
Before switch to a bus mode, we need check if the SD device supports this bus mode. Cc: Wu, Hao A <hao.a.wu@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Feng Tian <feng.tian@intel.com>
This commit is contained in:
parent
8c983d3e06
commit
6263ae931d
|
@ -591,6 +591,7 @@ SdCardSetBusWidth (
|
||||||
@param[in] DriveStrength The value for drive length group.
|
@param[in] DriveStrength The value for drive length group.
|
||||||
@param[in] PowerLimit The value for power limit group.
|
@param[in] PowerLimit The value for power limit group.
|
||||||
@param[in] Mode Switch or check function.
|
@param[in] Mode Switch or check function.
|
||||||
|
@param[out] SwitchResp The return switch function status.
|
||||||
|
|
||||||
@retval EFI_SUCCESS The operation is done correctly.
|
@retval EFI_SUCCESS The operation is done correctly.
|
||||||
@retval Others The operation fails.
|
@retval Others The operation fails.
|
||||||
|
@ -598,13 +599,14 @@ SdCardSetBusWidth (
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
SdCardSwitch (
|
SdCardSwitch (
|
||||||
IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
|
IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
|
||||||
IN UINT8 Slot,
|
IN UINT8 Slot,
|
||||||
IN UINT8 AccessMode,
|
IN UINT8 AccessMode,
|
||||||
IN UINT8 CommandSystem,
|
IN UINT8 CommandSystem,
|
||||||
IN UINT8 DriveStrength,
|
IN UINT8 DriveStrength,
|
||||||
IN UINT8 PowerLimit,
|
IN UINT8 PowerLimit,
|
||||||
IN BOOLEAN Mode
|
IN BOOLEAN Mode,
|
||||||
|
OUT UINT8 *SwitchResp
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
|
EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
|
||||||
|
@ -612,7 +614,6 @@ SdCardSwitch (
|
||||||
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
|
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
UINT32 ModeValue;
|
UINT32 ModeValue;
|
||||||
UINT8 Data[64];
|
|
||||||
|
|
||||||
ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
|
ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
|
||||||
ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
|
ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
|
||||||
|
@ -631,8 +632,8 @@ SdCardSwitch (
|
||||||
((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) << 12) | \
|
((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) << 12) | \
|
||||||
ModeValue;
|
ModeValue;
|
||||||
|
|
||||||
Packet.InDataBuffer = Data;
|
Packet.InDataBuffer = SwitchResp;
|
||||||
Packet.InTransferLength = sizeof (Data);
|
Packet.InTransferLength = 64;
|
||||||
|
|
||||||
Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
|
Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
|
||||||
|
|
||||||
|
@ -891,6 +892,7 @@ SdCardSetBusMode (
|
||||||
UINT8 AccessMode;
|
UINT8 AccessMode;
|
||||||
UINT8 HostCtrl1;
|
UINT8 HostCtrl1;
|
||||||
UINT8 HostCtrl2;
|
UINT8 HostCtrl2;
|
||||||
|
UINT8 SwitchResp[64];
|
||||||
SD_MMC_HC_PRIVATE_DATA *Private;
|
SD_MMC_HC_PRIVATE_DATA *Private;
|
||||||
|
|
||||||
Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
|
Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
|
||||||
|
@ -908,31 +910,45 @@ SdCardSetBusMode (
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Calculate supported bus speed/bus width/clock frequency.
|
// Get the supported bus speed from SWITCH cmd return data group #1.
|
||||||
//
|
//
|
||||||
ClockFreq = 0;
|
Status = SdCardSwitch (PassThru, Slot, 0xF, 0xF, 0xF, 0xF, FALSE, SwitchResp);
|
||||||
if (S18A && (Capability->Sdr104 != 0)) {
|
|
||||||
ClockFreq = 208;
|
|
||||||
AccessMode = 3;
|
|
||||||
} else if (S18A && (Capability->Sdr50 != 0)) {
|
|
||||||
ClockFreq = 100;
|
|
||||||
AccessMode = 2;
|
|
||||||
} else if (S18A && (Capability->Ddr50 != 0)) {
|
|
||||||
ClockFreq = 50;
|
|
||||||
AccessMode = 4;
|
|
||||||
} else {
|
|
||||||
ClockFreq = 50;
|
|
||||||
AccessMode = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG ((EFI_D_INFO, "SdCardSetBusMode: AccessMode %d ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));
|
|
||||||
|
|
||||||
Status = SdCardSwitch (PassThru, Slot, AccessMode, 0, 0, 0, TRUE);
|
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// Calculate supported bus speed/bus width/clock frequency by host and device capability.
|
||||||
|
//
|
||||||
|
ClockFreq = 0;
|
||||||
|
if (S18A && (Capability->Sdr104 != 0) && ((SwitchResp[13] & BIT3) != 0)) {
|
||||||
|
ClockFreq = 208;
|
||||||
|
AccessMode = 3;
|
||||||
|
} else if (S18A && (Capability->Sdr50 != 0) && ((SwitchResp[13] & BIT2) != 0)) {
|
||||||
|
ClockFreq = 100;
|
||||||
|
AccessMode = 2;
|
||||||
|
} else if (S18A && (Capability->Ddr50 != 0) && ((SwitchResp[13] & BIT4) != 0)) {
|
||||||
|
ClockFreq = 50;
|
||||||
|
AccessMode = 4;
|
||||||
|
} else if ((SwitchResp[13] & BIT1) != 0) {
|
||||||
|
ClockFreq = 50;
|
||||||
|
AccessMode = 1;
|
||||||
|
} else {
|
||||||
|
ClockFreq = 25;
|
||||||
|
AccessMode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
// Set to Hight Speed timing
|
||||||
|
|
|
@ -2192,6 +2192,7 @@ SdPeimSetBusWidth (
|
||||||
@param[in] DriveStrength The value for drive length group.
|
@param[in] DriveStrength The value for drive length group.
|
||||||
@param[in] PowerLimit The value for power limit group.
|
@param[in] PowerLimit The value for power limit group.
|
||||||
@param[in] Mode Switch or check function.
|
@param[in] Mode Switch or check function.
|
||||||
|
@param[out] SwitchResp The return switch function status.
|
||||||
|
|
||||||
@retval EFI_SUCCESS The operation is done correctly.
|
@retval EFI_SUCCESS The operation is done correctly.
|
||||||
@retval Others The operation fails.
|
@retval Others The operation fails.
|
||||||
|
@ -2199,12 +2200,13 @@ SdPeimSetBusWidth (
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
SdPeimSwitch (
|
SdPeimSwitch (
|
||||||
IN SD_PEIM_HC_SLOT *Slot,
|
IN SD_PEIM_HC_SLOT *Slot,
|
||||||
IN UINT8 AccessMode,
|
IN UINT8 AccessMode,
|
||||||
IN UINT8 CommandSystem,
|
IN UINT8 CommandSystem,
|
||||||
IN UINT8 DriveStrength,
|
IN UINT8 DriveStrength,
|
||||||
IN UINT8 PowerLimit,
|
IN UINT8 PowerLimit,
|
||||||
IN BOOLEAN Mode
|
IN BOOLEAN Mode,
|
||||||
|
OUT UINT8 *SwitchResp
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
SD_COMMAND_BLOCK SdCmdBlk;
|
SD_COMMAND_BLOCK SdCmdBlk;
|
||||||
|
@ -2212,7 +2214,6 @@ SdPeimSwitch (
|
||||||
SD_COMMAND_PACKET Packet;
|
SD_COMMAND_PACKET Packet;
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
UINT32 ModeValue;
|
UINT32 ModeValue;
|
||||||
UINT8 Data[64];
|
|
||||||
|
|
||||||
ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));
|
ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));
|
||||||
ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));
|
ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));
|
||||||
|
@ -2230,8 +2231,8 @@ SdPeimSwitch (
|
||||||
SdCmdBlk.CommandArgument = (AccessMode & 0xF) | ((PowerLimit & 0xF) << 4) | \
|
SdCmdBlk.CommandArgument = (AccessMode & 0xF) | ((PowerLimit & 0xF) << 4) | \
|
||||||
((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) << 12) | \
|
((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) << 12) | \
|
||||||
ModeValue;
|
ModeValue;
|
||||||
Packet.InDataBuffer = Data;
|
Packet.InDataBuffer = SwitchResp;
|
||||||
Packet.InTransferLength = sizeof (Data);
|
Packet.InTransferLength = 64;
|
||||||
|
|
||||||
Status = SdPeimExecCmd (Slot, &Packet);
|
Status = SdPeimExecCmd (Slot, &Packet);
|
||||||
|
|
||||||
|
@ -2617,6 +2618,7 @@ SdPeimSetBusMode (
|
||||||
UINT8 AccessMode;
|
UINT8 AccessMode;
|
||||||
UINT8 HostCtrl1;
|
UINT8 HostCtrl1;
|
||||||
UINT8 HostCtrl2;
|
UINT8 HostCtrl2;
|
||||||
|
UINT8 SwitchResp[64];
|
||||||
|
|
||||||
Status = SdPeimGetCsd (Slot, Rca, &Slot->Csd);
|
Status = SdPeimGetCsd (Slot, Rca, &Slot->Csd);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
|
@ -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;
|
ClockFreq = 0;
|
||||||
if (S18a && (Capability.Sdr104 != 0)) {
|
if (S18a && (Capability.Sdr104 != 0) && ((SwitchResp[13] & BIT3) != 0)) {
|
||||||
ClockFreq = 208;
|
ClockFreq = 208;
|
||||||
AccessMode = 3;
|
AccessMode = 3;
|
||||||
} else if (S18a && (Capability.Sdr50 != 0)) {
|
} else if (S18a && (Capability.Sdr50 != 0) && ((SwitchResp[13] & BIT2) != 0)) {
|
||||||
ClockFreq = 100;
|
ClockFreq = 100;
|
||||||
AccessMode = 2;
|
AccessMode = 2;
|
||||||
} else if (S18a && (Capability.Ddr50 != 0)) {
|
} else if (S18a && (Capability.Ddr50 != 0) && ((SwitchResp[13] & BIT4) != 0)) {
|
||||||
ClockFreq = 50;
|
ClockFreq = 50;
|
||||||
AccessMode = 4;
|
AccessMode = 4;
|
||||||
} else {
|
} else if ((SwitchResp[13] & BIT1) != 0) {
|
||||||
ClockFreq = 50;
|
ClockFreq = 50;
|
||||||
AccessMode = 1;
|
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)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_ERROR, "SdPeimSetBusMode: SdPeimSwitch fails with %r\n", Status));
|
DEBUG ((EFI_D_ERROR, "SdPeimSetBusMode: SdPeimSwitch fails with %r\n", Status));
|
||||||
return 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
|
// Set to Hight Speed timing
|
||||||
//
|
//
|
||||||
|
|
|
@ -254,6 +254,7 @@ SdPeimHcInitHost (
|
||||||
@param[in] DriveStrength The value for drive length group.
|
@param[in] DriveStrength The value for drive length group.
|
||||||
@param[in] PowerLimit The value for power limit group.
|
@param[in] PowerLimit The value for power limit group.
|
||||||
@param[in] Mode Switch or check function.
|
@param[in] Mode Switch or check function.
|
||||||
|
@param[out] SwitchResp The return switch function status.
|
||||||
|
|
||||||
@retval EFI_SUCCESS The operation is done correctly.
|
@retval EFI_SUCCESS The operation is done correctly.
|
||||||
@retval Others The operation fails.
|
@retval Others The operation fails.
|
||||||
|
@ -261,12 +262,13 @@ SdPeimHcInitHost (
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
SdPeimSwitch (
|
SdPeimSwitch (
|
||||||
IN SD_PEIM_HC_SLOT *Slot,
|
IN SD_PEIM_HC_SLOT *Slot,
|
||||||
IN UINT8 AccessMode,
|
IN UINT8 AccessMode,
|
||||||
IN UINT8 CommandSystem,
|
IN UINT8 CommandSystem,
|
||||||
IN UINT8 DriveStrength,
|
IN UINT8 DriveStrength,
|
||||||
IN UINT8 PowerLimit,
|
IN UINT8 PowerLimit,
|
||||||
IN BOOLEAN Mode
|
IN BOOLEAN Mode,
|
||||||
|
OUT UINT8 *SwitchResp
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue