@param[in] DriveStrength The value for drive length group.\r
@param[in] PowerLimit The value for power limit group.\r
@param[in] Mode Switch or check function.\r
+ @param[out] SwitchResp The return switch function status.\r
\r
@retval EFI_SUCCESS The operation is done correctly.\r
@retval Others The operation fails.\r
**/\r
EFI_STATUS\r
SdCardSwitch (\r
- IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
- IN UINT8 Slot,\r
- IN UINT8 AccessMode,\r
- IN UINT8 CommandSystem,\r
- IN UINT8 DriveStrength,\r
- IN UINT8 PowerLimit,\r
- IN BOOLEAN Mode\r
+ IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
+ IN UINT8 Slot,\r
+ IN UINT8 AccessMode,\r
+ IN UINT8 CommandSystem,\r
+ IN UINT8 DriveStrength,\r
+ IN UINT8 PowerLimit,\r
+ IN BOOLEAN Mode,\r
+ OUT UINT8 *SwitchResp\r
)\r
{\r
EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
EFI_STATUS Status;\r
UINT32 ModeValue;\r
- UINT8 Data[64];\r
\r
ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) << 12) | \\r
ModeValue;\r
\r
- Packet.InDataBuffer = Data;\r
- Packet.InTransferLength = sizeof (Data);\r
+ Packet.InDataBuffer = SwitchResp;\r
+ Packet.InTransferLength = 64;\r
\r
Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
\r
UINT8 AccessMode;\r
UINT8 HostCtrl1;\r
UINT8 HostCtrl2;\r
+ UINT8 SwitchResp[64];\r
SD_MMC_HC_PRIVATE_DATA *Private;\r
\r
Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
-\r
//\r
- // Calculate supported bus speed/bus width/clock frequency.\r
+ // Get the supported bus speed from SWITCH cmd return data group #1.\r
+ //\r
+ Status = SdCardSwitch (PassThru, Slot, 0xF, 0xF, 0xF, 0xF, FALSE, SwitchResp);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Calculate supported bus speed/bus width/clock frequency by host and device capability.\r
//\r
ClockFreq = 0;\r
- if (S18A && (Capability->Sdr104 != 0)) {\r
+ if (S18A && (Capability->Sdr104 != 0) && ((SwitchResp[13] & BIT3) != 0)) {\r
ClockFreq = 208;\r
AccessMode = 3;\r
- } else if (S18A && (Capability->Sdr50 != 0)) {\r
+ } else if (S18A && (Capability->Sdr50 != 0) && ((SwitchResp[13] & BIT2) != 0)) {\r
ClockFreq = 100;\r
AccessMode = 2;\r
- } else if (S18A && (Capability->Ddr50 != 0)) {\r
+ } else if (S18A && (Capability->Ddr50 != 0) && ((SwitchResp[13] & BIT4) != 0)) {\r
ClockFreq = 50;\r
AccessMode = 4;\r
- } else {\r
+ } else if ((SwitchResp[13] & BIT1) != 0) {\r
ClockFreq = 50;\r
AccessMode = 1;\r
+ } else {\r
+ ClockFreq = 25;\r
+ AccessMode = 0;\r
}\r
\r
- DEBUG ((EFI_D_INFO, "SdCardSetBusMode: AccessMode %d ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));\r
-\r
- Status = SdCardSwitch (PassThru, Slot, AccessMode, 0, 0, 0, TRUE);\r
+ Status = SdCardSwitch (PassThru, Slot, AccessMode, 0xF, 0xF, 0xF, TRUE, SwitchResp);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
+ if ((SwitchResp[16] & 0xF) != AccessMode) {\r
+ 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));\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, "SdCardSetBusMode: Switch to AccessMode %d ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));\r
+\r
//\r
// Set to Hight Speed timing\r
//\r
@param[in] DriveStrength The value for drive length group.\r
@param[in] PowerLimit The value for power limit group.\r
@param[in] Mode Switch or check function.\r
+ @param[out] SwitchResp The return switch function status.\r
\r
@retval EFI_SUCCESS The operation is done correctly.\r
@retval Others The operation fails.\r
**/\r
EFI_STATUS\r
SdPeimSwitch (\r
- IN SD_PEIM_HC_SLOT *Slot,\r
- IN UINT8 AccessMode,\r
- IN UINT8 CommandSystem,\r
- IN UINT8 DriveStrength,\r
- IN UINT8 PowerLimit,\r
- IN BOOLEAN Mode\r
+ IN SD_PEIM_HC_SLOT *Slot,\r
+ IN UINT8 AccessMode,\r
+ IN UINT8 CommandSystem,\r
+ IN UINT8 DriveStrength,\r
+ IN UINT8 PowerLimit,\r
+ IN BOOLEAN Mode,\r
+ OUT UINT8 *SwitchResp\r
)\r
{\r
SD_COMMAND_BLOCK SdCmdBlk;\r
SD_COMMAND_PACKET Packet;\r
EFI_STATUS Status;\r
UINT32 ModeValue;\r
- UINT8 Data[64];\r
\r
ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));\r
ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));\r
SdCmdBlk.CommandArgument = (AccessMode & 0xF) | ((PowerLimit & 0xF) << 4) | \\r
((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) << 12) | \\r
ModeValue;\r
- Packet.InDataBuffer = Data;\r
- Packet.InTransferLength = sizeof (Data);\r
+ Packet.InDataBuffer = SwitchResp;\r
+ Packet.InTransferLength = 64;\r
\r
Status = SdPeimExecCmd (Slot, &Packet);\r
\r
UINT8 AccessMode;\r
UINT8 HostCtrl1;\r
UINT8 HostCtrl2;\r
+ UINT8 SwitchResp[64];\r
\r
Status = SdPeimGetCsd (Slot, Rca, &Slot->Csd);\r
if (EFI_ERROR (Status)) {\r
}\r
\r
//\r
- // Calculate supported bus speed/bus width/clock frequency.\r
+ // Get the supported bus speed from SWITCH cmd return data group #1.\r
+ //\r
+ Status = SdPeimSwitch (Slot, 0xF, 0xF, 0xF, 0xF, FALSE, SwitchResp);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Calculate supported bus speed/bus width/clock frequency by host and device capability.\r
//\r
ClockFreq = 0;\r
- if (S18a && (Capability.Sdr104 != 0)) {\r
+ if (S18a && (Capability.Sdr104 != 0) && ((SwitchResp[13] & BIT3) != 0)) {\r
ClockFreq = 208;\r
AccessMode = 3;\r
- } else if (S18a && (Capability.Sdr50 != 0)) {\r
+ } else if (S18a && (Capability.Sdr50 != 0) && ((SwitchResp[13] & BIT2) != 0)) {\r
ClockFreq = 100;\r
AccessMode = 2;\r
- } else if (S18a && (Capability.Ddr50 != 0)) {\r
+ } else if (S18a && (Capability.Ddr50 != 0) && ((SwitchResp[13] & BIT4) != 0)) {\r
ClockFreq = 50;\r
AccessMode = 4;\r
- } else {\r
+ } else if ((SwitchResp[13] & BIT1) != 0) {\r
ClockFreq = 50;\r
AccessMode = 1;\r
+ } else {\r
+ ClockFreq = 25;\r
+ AccessMode = 0;\r
}\r
\r
- DEBUG ((EFI_D_INFO, "AccessMode %d ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));\r
+ DEBUG ((EFI_D_INFO, "SdPeimSetBusMode: AccessMode %d ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));\r
\r
- Status = SdPeimSwitch (Slot, AccessMode, 0, 0, 0, TRUE);\r
+ Status = SdPeimSwitch (Slot, AccessMode, 0xF, 0xF, 0xF, TRUE, SwitchResp);\r
if (EFI_ERROR (Status)) {\r
DEBUG ((EFI_D_ERROR, "SdPeimSetBusMode: SdPeimSwitch fails with %r\n", Status));\r
return Status;\r
}\r
\r
+ if ((SwitchResp[16] & 0xF) != AccessMode) {\r
+ 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));\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
//\r
// Set to Hight Speed timing\r
//\r
@param[in] DriveStrength The value for drive length group.\r
@param[in] PowerLimit The value for power limit group.\r
@param[in] Mode Switch or check function.\r
+ @param[out] SwitchResp The return switch function status.\r
\r
@retval EFI_SUCCESS The operation is done correctly.\r
@retval Others The operation fails.\r
**/\r
EFI_STATUS\r
SdPeimSwitch (\r
- IN SD_PEIM_HC_SLOT *Slot,\r
- IN UINT8 AccessMode,\r
- IN UINT8 CommandSystem,\r
- IN UINT8 DriveStrength,\r
- IN UINT8 PowerLimit,\r
- IN BOOLEAN Mode\r
+ IN SD_PEIM_HC_SLOT *Slot,\r
+ IN UINT8 AccessMode,\r
+ IN UINT8 CommandSystem,\r
+ IN UINT8 DriveStrength,\r
+ IN UINT8 PowerLimit,\r
+ IN BOOLEAN Mode,\r
+ OUT UINT8 *SwitchResp\r
);\r
\r
/**\r