/** @file\r
This file provides some helper functions which are specific for EMMC 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
}\r
\r
/**\r
- Switch the clock frequency to the specified value.\r
+ Switch the bus timing and clock frequency.\r
\r
Refer to EMMC Electrical Standard Spec 5.1 Section 6.6 and SD Host Controller\r
Simplified Spec 3.0 Figure 3-3 for details.\r
@param[in] Slot The slot number of the SD card to send the command to.\r
@param[in] Rca The relative device address to be assigned.\r
@param[in] HsTiming The value to be written to HS_TIMING field of EXT_CSD register.\r
+ @param[in] Timing The bus mode timing indicator.\r
@param[in] ClockFreq The max clock frequency to be set, the unit is MHz.\r
\r
@retval EFI_SUCCESS The operation is done correctly.\r
\r
**/\r
EFI_STATUS\r
-EmmcSwitchClockFreq (\r
+EmmcSwitchBusTiming (\r
IN EFI_PCI_IO_PROTOCOL *PciIo,\r
IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
IN UINT8 Slot,\r
IN UINT16 Rca,\r
IN UINT8 HsTiming,\r
+ IN SD_MMC_BUS_MODE Timing,\r
IN UINT32 ClockFreq\r
)\r
{\r
\r
Status = EmmcSwitch (PassThru, Slot, Access, Index, Value, CmdSet);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "EmmcSwitchClockFreq: Switch to hstiming %d fails with %r\n", HsTiming, Status));\r
+ DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Switch to hstiming %d fails with %r\n", HsTiming, Status));\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Convert the clock freq unit from MHz to KHz.\r
+ //\r
+ Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);\r
+ if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
Status = EmmcSendStatus (PassThru, Slot, Rca, &DevStatus);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "EmmcSwitchClockFreq: Send status fails with %r\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Send status fails with %r\n", Status));\r
return Status;\r
}\r
//\r
// Check the switch operation is really successful or not.\r
//\r
if ((DevStatus & BIT7) != 0) {\r
- DEBUG ((DEBUG_ERROR, "EmmcSwitchClockFreq: The switch operation fails as DevStatus is 0x%08x\n", DevStatus));\r
+ DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: The switch operation fails as DevStatus is 0x%08x\n", DevStatus));\r
return EFI_DEVICE_ERROR;\r
}\r
- //\r
- // Convert the clock freq unit from MHz to KHz.\r
- //\r
- Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->Capability[Slot]);\r
+\r
+ if (mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
+ Status = mOverride->NotifyPhase (\r
+ Private->ControllerHandle,\r
+ Slot,\r
+ EdkiiSdMmcSwitchClockFreqPost,\r
+ &Timing\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "%a: SD/MMC switch clock freq post notifier callback failed - %r\n",\r
+ __FUNCTION__,\r
+ Status\r
+ ));\r
+ return Status;\r
+ }\r
+ }\r
\r
return Status;\r
}\r
IN UINT8 BusWidth\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT8 HsTiming;\r
- UINT8 HostCtrl1;\r
- UINT8 HostCtrl2;\r
+ EFI_STATUS Status;\r
+ UINT8 HsTiming;\r
+ UINT8 HostCtrl1;\r
+ SD_MMC_BUS_MODE Timing;\r
+ SD_MMC_HC_PRIVATE_DATA *Private;\r
+\r
+ Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);\r
\r
Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr, BusWidth);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- //\r
- // Clean UHS Mode Select field of Host Control 2 reigster before update\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
- //\r
- // Set UHS Mode Select field of Host Control 2 reigster to SDR12/25/50\r
- //\r
if (IsDdr) {\r
- HostCtrl2 = BIT2;\r
+ Timing = SdMmcMmcHsDdr;\r
} else if (ClockFreq == 52) {\r
- HostCtrl2 = BIT0;\r
+ Timing = SdMmcMmcHsSdr;\r
} else {\r
- HostCtrl2 = 0;\r
+ Timing = SdMmcMmcLegacy;\r
}\r
- Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
+\r
+ Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
HsTiming = 1;\r
- Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq);\r
+ Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);\r
\r
return Status;\r
}\r
IN UINT8 BusWidth\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT8 HsTiming;\r
- UINT8 HostCtrl2;\r
- UINT16 ClockCtrl;\r
+ EFI_STATUS Status;\r
+ UINT8 HsTiming;\r
+ UINT16 ClockCtrl;\r
+ SD_MMC_BUS_MODE Timing;\r
+ SD_MMC_HC_PRIVATE_DATA *Private;\r
+\r
+ Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);\r
\r
if ((BusWidth != 4) && (BusWidth != 8)) {\r
return EFI_INVALID_PARAMETER;\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- //\r
- // Clean UHS Mode Select field of Host Control 2 reigster before update\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
- //\r
- // Set UHS Mode Select field of Host Control 2 reigster to SDR104\r
- //\r
- HostCtrl2 = BIT0 | BIT1;\r
- Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
+\r
+ Timing = SdMmcMmcHs200;\r
+\r
+ Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
+\r
//\r
// Wait Internal Clock Stable in the Clock Control register to be 1 before set SD Clock Enable bit\r
//\r
Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl);\r
\r
HsTiming = 2;\r
- Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq);\r
+ Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
IN UINT32 ClockFreq\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT8 HsTiming;\r
- UINT8 HostCtrl2;\r
+ EFI_STATUS Status;\r
+ UINT8 HsTiming;\r
+ SD_MMC_BUS_MODE Timing;\r
+ SD_MMC_HC_PRIVATE_DATA *Private;\r
+\r
+ Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);\r
\r
Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, 8);\r
if (EFI_ERROR (Status)) {\r
// Set to Hight Speed timing and set the clock frequency to a value less than 52MHz.\r
//\r
HsTiming = 1;\r
- Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, 52);\r
+ Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming, SdMmcMmcHsSdr, 52);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- //\r
- // Clean UHS Mode Select field of Host Control 2 reigster before update\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
- //\r
- // Set UHS Mode Select field of Host Control 2 reigster to HS400\r
- //\r
- HostCtrl2 = BIT0 | BIT2;\r
- Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
+\r
+ Timing = SdMmcMmcHs400;\r
+\r
+ Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
HsTiming = 3;\r
- Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq);\r
+ Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);\r
\r
return Status;\r
}\r
return Status;\r
}\r
\r
- ASSERT (Private->Capability[Slot].BaseClkFreq != 0);\r
+ ASSERT (Private->BaseClkFreq[Slot] != 0);\r
//\r
// Check if the Host Controller support 8bits bus width.\r
//\r