summaryrefslogtreecommitdiffstats
path: root/MdeModulePkg
diff options
context:
space:
mode:
authorFeng Tian <feng.tian@intel.com>2016-05-03 09:57:55 +0800
committerFeng Tian <feng.tian@intel.com>2016-05-06 16:10:01 +0800
commit6263ae931d66d3aaace09e6819e305ef171a806a (patch)
tree2b6b55a4fd62d88d57b6fee7c37a7ee179c10670 /MdeModulePkg
parent8c983d3e06da799e623a9f46fcaa207455482091 (diff)
downloadedk2-6263ae931d66d3aaace09e6819e305ef171a806a.tar.gz
edk2-6263ae931d66d3aaace09e6819e305ef171a806a.tar.bz2
edk2-6263ae931d66d3aaace09e6819e305ef171a806a.zip
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>
Diffstat (limited to 'MdeModulePkg')
-rw-r--r--MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c54
-rw-r--r--MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.c48
-rw-r--r--MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.h14
3 files changed, 75 insertions, 41 deletions
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
index b4e2c58430..8193f4eb2f 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
@@ -591,6 +591,7 @@ 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.
@@ -598,13 +599,14 @@ SdCardSetBusWidth (
**/
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;
@@ -612,7 +614,6 @@ SdCardSwitch (
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
EFI_STATUS Status;
UINT32 ModeValue;
- UINT8 Data[64];
ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
@@ -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);
@@ -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);
@@ -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
//
diff --git a/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.c b/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.c
index bb6df8fd9f..c251fbecb3 100644
--- a/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.c
+++ b/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.c
@@ -2192,6 +2192,7 @@ 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.
@@ -2199,12 +2200,13 @@ SdPeimSetBusWidth (
**/
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;
@@ -2212,7 +2214,6 @@ SdPeimSwitch (
SD_COMMAND_PACKET Packet;
EFI_STATUS Status;
UINT32 ModeValue;
- UINT8 Data[64];
ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));
ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));
@@ -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);
@@ -2617,6 +2618,7 @@ SdPeimSetBusMode (
UINT8 AccessMode;
UINT8 HostCtrl1;
UINT8 HostCtrl2;
+ UINT8 SwitchResp[64];
Status = SdPeimGetCsd (Slot, Rca, &Slot->Csd);
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;
- 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
//
diff --git a/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.h b/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.h
index 2f443045b7..b7c0dbc9f3 100644
--- a/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.h
+++ b/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.h
@@ -254,6 +254,7 @@ 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.
@@ -261,12 +262,13 @@ SdPeimHcInitHost (
**/
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
);
/**