/** @file\r
This file provides some helper functions which are specific for SD card device.\r
\r
+ Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.\r
Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
return Status;\r
}\r
\r
-/**\r
- Send command SEND_CSD to the SD device to get the data of the CSD register.\r
-\r
- Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
-\r
- @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
- @param[in] Slot The slot number of the SD card to send the command to.\r
- @param[in] Rca The relative device address of selected device.\r
- @param[out] Csd The buffer to store the content of the CSD register.\r
- Note the caller should ignore the lowest byte of this\r
- buffer as the content of this byte is meaningless even\r
- if the operation succeeds.\r
-\r
- @retval EFI_SUCCESS The operation is done correctly.\r
- @retval Others The operation fails.\r
-\r
-**/\r
-EFI_STATUS\r
-SdCardGetCsd (\r
- IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
- IN UINT8 Slot,\r
- IN UINT16 Rca,\r
- OUT SD_CSD *Csd\r
- )\r
-{\r
- EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
- EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
- EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
- EFI_STATUS Status;\r
-\r
- ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
- ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
- ZeroMem (&Packet, sizeof (Packet));\r
-\r
- Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
- Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
- Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
-\r
- SdMmcCmdBlk.CommandIndex = SD_SEND_CSD;\r
- SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
- SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;\r
- SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;\r
-\r
- Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.\r
- //\r
- CopyMem (((UINT8*)Csd) + 1, &SdMmcStatusBlk.Resp0, sizeof (SD_CSD) - 1);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Send command SEND_CSD to the SD device to get the data of the CSD register.\r
-\r
- Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
-\r
- @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
- @param[in] Slot The slot number of the SD card to send the command to.\r
- @param[in] Rca The relative device address of selected device.\r
- @param[out] Scr The buffer to store the content of the SCR register.\r
-\r
- @retval EFI_SUCCESS The operation is done correctly.\r
- @retval Others The operation fails.\r
-\r
-**/\r
-EFI_STATUS\r
-SdCardGetScr (\r
- IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
- IN UINT8 Slot,\r
- IN UINT16 Rca,\r
- OUT SD_SCR *Scr\r
- )\r
-{\r
- EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
- EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
- EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
- EFI_STATUS Status;\r
-\r
- ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
- ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
- ZeroMem (&Packet, sizeof (Packet));\r
-\r
- Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
- Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
- Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
-\r
- SdMmcCmdBlk.CommandIndex = SD_APP_CMD;\r
- SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
- SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
- SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;\r
-\r
- Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- SdMmcCmdBlk.CommandIndex = SD_SEND_SCR;\r
- SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;\r
- SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
-\r
- Packet.InDataBuffer = Scr;\r
- Packet.InTransferLength = sizeof (SD_SCR);\r
-\r
- Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
-\r
- return Status;\r
-}\r
-\r
/**\r
Send command SELECT_DESELECT_CARD to the SD device to select/deselect it.\r
\r
\r
Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
\r
- @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
- @param[in] Slot The slot number of the SD card to send the command to.\r
- @param[in] AccessMode The value for access mode group.\r
- @param[in] CommandSystem The value for command set group.\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
+ @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
+ @param[in] Slot The slot number of the SD card to send the command to.\r
+ @param[in] BusTiming Target bus timing based on which access group value will be set.\r
+ @param[in] CommandSystem The value for command set group.\r
+ @param[in] DriverStrength The value for driver strength 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
SdCardSwitch (\r
IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
IN UINT8 Slot,\r
- IN UINT8 AccessMode,\r
+ IN SD_MMC_BUS_MODE BusTiming,\r
IN UINT8 CommandSystem,\r
- IN UINT8 DriveStrength,\r
+ IN SD_DRIVER_STRENGTH_TYPE DriverStrength,\r
IN UINT8 PowerLimit,\r
IN BOOLEAN Mode,\r
OUT UINT8 *SwitchResp\r
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
EFI_STATUS Status;\r
UINT32 ModeValue;\r
+ UINT8 AccessMode;\r
\r
ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
\r
ModeValue = Mode ? BIT31 : 0;\r
- SdMmcCmdBlk.CommandArgument = (AccessMode & 0xF) | ((PowerLimit & 0xF) << 4) | \\r
- ((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) << 12) | \\r
+\r
+ switch (BusTiming) {\r
+ case SdMmcUhsDdr50:\r
+ AccessMode = 0x4;\r
+ break;\r
+ case SdMmcUhsSdr104:\r
+ AccessMode = 0x3;\r
+ break;\r
+ case SdMmcUhsSdr50:\r
+ AccessMode = 0x2;\r
+ break;\r
+ case SdMmcUhsSdr25:\r
+ case SdMmcSdHs:\r
+ AccessMode = 0x1;\r
+ break;\r
+ case SdMmcUhsSdr12:\r
+ case SdMmcSdDs:\r
+ AccessMode = 0;\r
+ break;\r
+ default:\r
+ AccessMode = 0xF;\r
+ }\r
+\r
+ SdMmcCmdBlk.CommandArgument = (AccessMode & 0xF) | ((CommandSystem & 0xF) << 4) | \\r
+ ((DriverStrength & 0xF) << 8) | ((PowerLimit & 0xF) << 12) | \\r
ModeValue;\r
\r
Packet.InDataBuffer = SwitchResp;\r
Packet.InTransferLength = 64;\r
\r
Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Mode) {\r
+ if ((((AccessMode & 0xF) != 0xF) && ((SwitchResp[16] & 0xF) != AccessMode)) ||\r
+ (((CommandSystem & 0xF) != 0xF) && (((SwitchResp[16] >> 4) & 0xF) != CommandSystem)) ||\r
+ (((DriverStrength & 0xF) != 0xF) && ((SwitchResp[15] & 0xF) != DriverStrength)) ||\r
+ (((PowerLimit & 0xF) != 0xF) && (((SwitchResp[15] >> 4) & 0xF) != PowerLimit))) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ }\r
\r
return Status;\r
}\r
return Status;\r
}\r
\r
+/**\r
+ Check if passed BusTiming is supported in both controller and card.\r
+\r
+ @param[in] Private Pointer to controller private data\r
+ @param[in] SlotIndex Index of the slot in the controller\r
+ @param[in] CardSupportedBusTimings Bitmask indicating which bus timings are supported by card\r
+ @param[in] IsInUhsI Flag indicating if link is in UHS-I\r
+\r
+ @retval TRUE Both card and controller support given BusTiming\r
+ @retval FALSE Card or controller doesn't support given BusTiming\r
+**/\r
+BOOLEAN\r
+SdIsBusTimingSupported (\r
+ IN SD_MMC_HC_PRIVATE_DATA *Private,\r
+ IN UINT8 SlotIndex,\r
+ IN UINT8 CardSupportedBusTimings,\r
+ IN BOOLEAN IsInUhsI,\r
+ IN SD_MMC_BUS_MODE BusTiming\r
+ )\r
+{\r
+ SD_MMC_HC_SLOT_CAP *Capability;\r
+\r
+ Capability = &Private->Capability[SlotIndex];\r
+\r
+ if (IsInUhsI) {\r
+ switch (BusTiming) {\r
+ case SdMmcUhsSdr104:\r
+ if ((Capability->Sdr104 != 0) && ((CardSupportedBusTimings & BIT3) != 0)) {\r
+ return TRUE;\r
+ }\r
+ break;\r
+ case SdMmcUhsDdr50:\r
+ if ((Capability->Ddr50 != 0) && ((CardSupportedBusTimings & BIT4) != 0)) {\r
+ return TRUE;\r
+ }\r
+ break;\r
+ case SdMmcUhsSdr50:\r
+ if ((Capability->Sdr50 != 0) && ((CardSupportedBusTimings & BIT2) != 0)) {\r
+ return TRUE;\r
+ }\r
+ break;\r
+ case SdMmcUhsSdr25:\r
+ if ((CardSupportedBusTimings & BIT1) != 0) {\r
+ return TRUE;\r
+ }\r
+ break;\r
+ case SdMmcUhsSdr12:\r
+ if ((CardSupportedBusTimings & BIT0) != 0) {\r
+ return TRUE;\r
+ }\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ } else {\r
+ switch (BusTiming) {\r
+ case SdMmcSdHs:\r
+ if ((Capability->HighSpeed != 0) && (CardSupportedBusTimings & BIT1) != 0) {\r
+ return TRUE;\r
+ }\r
+ break;\r
+ case SdMmcSdDs:\r
+ if ((CardSupportedBusTimings & BIT0) != 0) {\r
+ return TRUE;\r
+ }\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Get the target bus timing to set on the link. This function\r
+ will try to select highest bus timing supported by card, controller\r
+ and the driver.\r
+\r
+ @param[in] Private Pointer to controller private data\r
+ @param[in] SlotIndex Index of the slot in the controller\r
+ @param[in] CardSupportedBusTimings Bitmask indicating which bus timings are supported by card\r
+ @param[in] IsInUhsI Flag indicating if link is in UHS-I\r
+\r
+ @return Bus timing value that should be set on link\r
+**/\r
+SD_MMC_BUS_MODE\r
+SdGetTargetBusTiming (\r
+ IN SD_MMC_HC_PRIVATE_DATA *Private,\r
+ IN UINT8 SlotIndex,\r
+ IN UINT8 CardSupportedBusTimings,\r
+ IN BOOLEAN IsInUhsI\r
+ )\r
+{\r
+ SD_MMC_BUS_MODE BusTiming;\r
+\r
+ if (IsInUhsI) {\r
+ BusTiming = SdMmcUhsSdr104;\r
+ } else {\r
+ BusTiming = SdMmcSdHs;\r
+ }\r
+\r
+ while (BusTiming > SdMmcSdDs) {\r
+ if (SdIsBusTimingSupported (Private, SlotIndex, CardSupportedBusTimings, IsInUhsI, BusTiming)) {\r
+ break;\r
+ }\r
+ BusTiming--;\r
+ }\r
+\r
+ return BusTiming;\r
+}\r
+\r
+/**\r
+ Get the target bus width to be set on the bus.\r
+\r
+ @param[in] Private Pointer to controller private data\r
+ @param[in] SlotIndex Index of the slot in the controller\r
+ @param[in] BusTiming Bus timing set on the bus\r
+\r
+ @return Bus width to be set on the bus\r
+**/\r
+UINT8\r
+SdGetTargetBusWidth (\r
+ IN SD_MMC_HC_PRIVATE_DATA *Private,\r
+ IN UINT8 SlotIndex,\r
+ IN SD_MMC_BUS_MODE BusTiming\r
+ )\r
+{\r
+ UINT8 BusWidth;\r
+ UINT8 PreferredBusWidth;\r
+\r
+ PreferredBusWidth = Private->Slot[SlotIndex].OperatingParameters.BusWidth;\r
+\r
+ if (BusTiming == SdMmcSdDs || BusTiming == SdMmcSdHs) {\r
+ if (PreferredBusWidth != EDKII_SD_MMC_BUS_WIDTH_IGNORE &&\r
+ (PreferredBusWidth == 1 || PreferredBusWidth == 4)) {\r
+ BusWidth = PreferredBusWidth;\r
+ } else {\r
+ BusWidth = 4;\r
+ }\r
+ } else {\r
+ //\r
+ // UHS-I modes support only 4-bit width.\r
+ // Switch to 4-bit has been done before calling this function anyway so\r
+ // this is purely informational.\r
+ //\r
+ BusWidth = 4;\r
+ }\r
+\r
+ return BusWidth;\r
+}\r
+\r
+/**\r
+ Get the target clock frequency to be set on the bus.\r
+\r
+ @param[in] Private Pointer to controller private data\r
+ @param[in] SlotIndex Index of the slot in the controller\r
+ @param[in] BusTiming Bus timing to be set on the bus\r
+\r
+ @return Value of the clock frequency to be set on bus in MHz\r
+**/\r
+UINT32\r
+SdGetTargetBusClockFreq (\r
+ IN SD_MMC_HC_PRIVATE_DATA *Private,\r
+ IN UINT8 SlotIndex,\r
+ IN SD_MMC_BUS_MODE BusTiming\r
+ )\r
+{\r
+ UINT32 PreferredClockFreq;\r
+ UINT32 MaxClockFreq;\r
+\r
+ PreferredClockFreq = Private->Slot[SlotIndex].OperatingParameters.ClockFreq;\r
+\r
+ switch (BusTiming) {\r
+ case SdMmcUhsSdr104:\r
+ MaxClockFreq = 208;\r
+ break;\r
+ case SdMmcUhsSdr50:\r
+ MaxClockFreq = 100;\r
+ break;\r
+ case SdMmcUhsDdr50:\r
+ case SdMmcUhsSdr25:\r
+ case SdMmcSdHs:\r
+ MaxClockFreq = 50;\r
+ break;\r
+ case SdMmcUhsSdr12:\r
+ case SdMmcSdDs:\r
+ default:\r
+ MaxClockFreq = 25;\r
+ }\r
+\r
+ if (PreferredClockFreq != EDKII_SD_MMC_CLOCK_FREQ_IGNORE && PreferredClockFreq < MaxClockFreq) {\r
+ return PreferredClockFreq;\r
+ } else {\r
+ return MaxClockFreq;\r
+ }\r
+}\r
+\r
+/**\r
+ Get the driver strength to be set on bus.\r
+\r
+ @param[in] Private Pointer to controller private data\r
+ @param[in] SlotIndex Index of the slot in the controller\r
+ @param[in] CardSupportedDriverStrengths Bitmask indicating which driver strengths are supported on the card\r
+ @param[in] BusTiming Bus timing set on the bus\r
+\r
+ @return Value of the driver strength to be set on the bus\r
+**/\r
+EDKII_SD_MMC_DRIVER_STRENGTH\r
+SdGetTargetDriverStrength (\r
+ IN SD_MMC_HC_PRIVATE_DATA *Private,\r
+ IN UINT8 SlotIndex,\r
+ IN UINT8 CardSupportedDriverStrengths,\r
+ IN SD_MMC_BUS_MODE BusTiming\r
+ )\r
+{\r
+ EDKII_SD_MMC_DRIVER_STRENGTH PreferredDriverStrength;\r
+ EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength;\r
+\r
+ if (BusTiming == SdMmcSdDs || BusTiming == SdMmcSdHs) {\r
+ DriverStrength.Sd = SdDriverStrengthIgnore;\r
+ return DriverStrength;\r
+ }\r
+\r
+ PreferredDriverStrength = Private->Slot[SlotIndex].OperatingParameters.DriverStrength;\r
+ DriverStrength.Sd = SdDriverStrengthTypeB;\r
+\r
+ if (PreferredDriverStrength.Sd != EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE &&\r
+ (CardSupportedDriverStrengths & (BIT0 << PreferredDriverStrength.Sd))) {\r
+\r
+ if ((PreferredDriverStrength.Sd == SdDriverStrengthTypeA &&\r
+ (Private->Capability[SlotIndex].DriverTypeA != 0)) ||\r
+ (PreferredDriverStrength.Sd == SdDriverStrengthTypeC &&\r
+ (Private->Capability[SlotIndex].DriverTypeC != 0)) ||\r
+ (PreferredDriverStrength.Sd == SdDriverStrengthTypeD &&\r
+ (Private->Capability[SlotIndex].DriverTypeD != 0))) {\r
+ DriverStrength.Sd = PreferredDriverStrength.Sd;\r
+ }\r
+ }\r
+\r
+ return DriverStrength;\r
+}\r
+\r
+/**\r
+ Get the target settings for the bus mode.\r
+\r
+ @param[in] Private Pointer to controller private data\r
+ @param[in] SlotIndex Index of the slot in the controller\r
+ @param[in] SwitchQueryResp Pointer to switch query response\r
+ @param[in] IsInUhsI Flag indicating if link is in UHS-I mode\r
+ @param[out] BusMode Target configuration of the bus\r
+**/\r
+VOID\r
+SdGetTargetBusMode (\r
+ IN SD_MMC_HC_PRIVATE_DATA *Private,\r
+ IN UINT8 SlotIndex,\r
+ IN UINT8 *SwitchQueryResp,\r
+ IN BOOLEAN IsInUhsI,\r
+ OUT SD_MMC_BUS_SETTINGS *BusMode\r
+ )\r
+{\r
+ BusMode->BusTiming = SdGetTargetBusTiming (Private, SlotIndex, SwitchQueryResp[13], IsInUhsI);\r
+ BusMode->BusWidth = SdGetTargetBusWidth (Private, SlotIndex, BusMode->BusTiming);\r
+ BusMode->ClockFreq = SdGetTargetBusClockFreq (Private, SlotIndex, BusMode->BusTiming);\r
+ BusMode->DriverStrength = SdGetTargetDriverStrength (Private, SlotIndex, SwitchQueryResp[9], BusMode->BusTiming);\r
+}\r
+\r
/**\r
Switch the high speed timing according to request.\r
\r
{\r
EFI_STATUS Status;\r
SD_MMC_HC_SLOT_CAP *Capability;\r
- UINT32 ClockFreq;\r
- UINT8 BusWidth;\r
- UINT8 AccessMode;\r
UINT8 HostCtrl1;\r
- UINT8 HostCtrl2;\r
UINT8 SwitchResp[64];\r
SD_MMC_HC_PRIVATE_DATA *Private;\r
+ SD_MMC_BUS_SETTINGS BusMode;\r
\r
Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);\r
\r
return Status;\r
}\r
\r
- BusWidth = 4;\r
-\r
- Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, BusWidth);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ if (S18A) {\r
+ //\r
+ // For UHS-I speed modes 4-bit data bus is requiered so we\r
+ // switch here irrespective of platform preference.\r
+ //\r
+ Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, 4);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
}\r
+\r
//\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
+ Status = SdCardSwitch (PassThru, Slot, 0xFF, 0xF, SdDriverStrengthIgnore, 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) && ((SwitchResp[13] & BIT3) != 0)) {\r
- ClockFreq = 208;\r
- AccessMode = 3;\r
- } else if (S18A && (Capability->Sdr50 != 0) && ((SwitchResp[13] & BIT2) != 0)) {\r
- ClockFreq = 100;\r
- AccessMode = 2;\r
- } else if (S18A && (Capability->Ddr50 != 0) && ((SwitchResp[13] & BIT4) != 0)) {\r
- ClockFreq = 50;\r
- AccessMode = 4;\r
- } else if ((SwitchResp[13] & BIT1) != 0) {\r
- ClockFreq = 50;\r
- AccessMode = 1;\r
- } else {\r
- ClockFreq = 25;\r
- AccessMode = 0;\r
+\r
+ SdGetTargetBusMode (Private, Slot, SwitchResp, S18A, &BusMode);\r
+\r
+ DEBUG ((DEBUG_INFO, "SdCardSetBusMode: Target bus mode: bus timing = %d, bus width = %d, clock freq[MHz] = %d, driver strength = %d\n",\r
+ BusMode.BusTiming, BusMode.BusWidth, BusMode.ClockFreq, BusMode.DriverStrength.Sd));\r
+\r
+ if (!S18A) {\r
+ Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, BusMode.BusWidth);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
}\r
\r
- Status = SdCardSwitch (PassThru, Slot, AccessMode, 0xF, 0xF, 0xF, TRUE, SwitchResp);\r
+ Status = SdCardSwitch (PassThru, Slot, BusMode.BusTiming, 0xF, BusMode.DriverStrength.Sd, 0xF, TRUE, SwitchResp);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- if ((SwitchResp[16] & 0xF) != AccessMode) {\r
- DEBUG ((DEBUG_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
+ Status = SdMmcSetDriverStrength (Private->PciIo, Slot, BusMode.DriverStrength.Sd);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
}\r
\r
- DEBUG ((DEBUG_INFO, "SdCardSetBusMode: Switch to AccessMode %d ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));\r
-\r
//\r
- // Set to Hight Speed timing\r
+ // Set to High Speed timing\r
//\r
- if (AccessMode == 1) {\r
+ if (BusMode.BusTiming == SdMmcSdHs) {\r
HostCtrl1 = BIT2;\r
Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
if (EFI_ERROR (Status)) {\r
}\r
}\r
\r
- HostCtrl2 = (UINT8)~0x7;\r
- Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- HostCtrl2 = AccessMode;\r
- Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
+ Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, BusMode.BusTiming);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, *Capability);\r
+ Status = SdMmcHcClockSupply (Private, Slot, BusMode.BusTiming, FALSE, BusMode.ClockFreq * 1000);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- if ((AccessMode == 3) || ((AccessMode == 2) && (Capability->TuningSDR50 != 0))) {\r
+ if ((BusMode.BusTiming == SdMmcUhsSdr104) || ((BusMode.BusTiming == SdMmcUhsSdr50) && (Capability->TuningSDR50 != 0))) {\r
Status = SdCardTuningClock (PciIo, PassThru, Slot);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
return Status;\r
}\r
\r
- if ((ControllerVer & 0xFF) == 2) {\r
+ if (((ControllerVer & 0xFF) >= SD_MMC_HC_CTRL_VER_300) &&\r
+ ((ControllerVer & 0xFF) <= SD_MMC_HC_CTRL_VER_420)) {\r
S18r = TRUE;\r
- } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {\r
+ } else if (((ControllerVer & 0xFF) == SD_MMC_HC_CTRL_VER_100) || ((ControllerVer & 0xFF) == SD_MMC_HC_CTRL_VER_200)) {\r
S18r = FALSE;\r
} else {\r
ASSERT (FALSE);\r
goto Error;\r
}\r
\r
- SdMmcHcInitClockFreq (PciIo, Slot, Private->Capability[Slot]);\r
+ Status = SdMmcHcStartSdClock (PciIo, Slot);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
\r
gBS->Stall (1000);\r
\r