\r
Refer to SD Host Controller Simplified spec 3.0 Section 3.2.1 for details.\r
\r
- @param[in] PciIo The PCI IO protocol instance.\r
- @param[in] Slot The slot number of the SD card to send the command to.\r
- @param[in] ClockFreq The max clock frequency to be set. The unit is KHz.\r
- @param[in] BaseClkFreq The base clock frequency of host controller in MHz.\r
- @param[in] ControllerVer The version of host controller.\r
+ @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
+ @param[in] Slot The slot number of the SD card to send the command to.\r
+ @param[in] BusTiming BusTiming at which the frequency change is done.\r
+ @param[in] FirstTimeSetup Flag to indicate whether the clock is being setup for the first time.\r
+ @param[in] ClockFreq The max clock frequency to be set. The unit is KHz.\r
\r
@retval EFI_SUCCESS The clock is supplied successfully.\r
@retval Others The clock isn't supplied successfully.\r
**/\r
EFI_STATUS\r
SdMmcHcClockSupply (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT8 Slot,\r
- IN UINT64 ClockFreq,\r
- IN UINT32 BaseClkFreq,\r
- IN UINT16 ControllerVer\r
+ IN SD_MMC_HC_PRIVATE_DATA *Private,\r
+ IN UINT8 Slot,\r
+ IN SD_MMC_BUS_MODE BusTiming,\r
+ IN BOOLEAN FirstTimeSetup,\r
+ IN UINT64 ClockFreq\r
)\r
{\r
EFI_STATUS Status;\r
UINT32 Divisor;\r
UINT32 Remainder;\r
UINT16 ClockCtrl;\r
+ UINT32 BaseClkFreq;\r
+ UINT16 ControllerVer;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
\r
- //\r
- // Calculate a divisor for SD clock frequency\r
- //\r
- ASSERT (BaseClkFreq != 0);\r
+ PciIo = Private->PciIo;\r
+ BaseClkFreq = Private->BaseClkFreq[Slot];\r
+ ControllerVer = Private->ControllerVersion[Slot];\r
\r
- if (ClockFreq == 0) {\r
+ if (BaseClkFreq == 0 || ClockFreq == 0) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
ClockCtrl = BIT2;\r
Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl);\r
\r
+ //\r
+ // We don't notify the platform on first time setup to avoid changing\r
+ // legacy behavior. During first time setup we also don't know what type\r
+ // of the card slot it is and which enum value of BusTiming applies.\r
+ //\r
+ if (!FirstTimeSetup && mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
+ Status = mOverride->NotifyPhase (\r
+ Private->ControllerHandle,\r
+ Slot,\r
+ EdkiiSdMmcSwitchClockFreqPost,\r
+ &BusTiming\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
\r
return EFI_SUCCESS;\r
}\r
\r
-/**\r
- Supply SD/MMC card with lowest clock frequency at initialization.\r
-\r
- @param[in] PciIo The PCI IO protocol instance.\r
- @param[in] Slot The slot number of the SD card to send the command to.\r
- @param[in] BaseClkFreq The base clock frequency of host controller in MHz.\r
- @param[in] ControllerVer The version of host controller.\r
-\r
- @retval EFI_SUCCESS The clock is supplied successfully.\r
- @retval Others The clock isn't supplied successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-SdMmcHcInitClockFreq (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT8 Slot,\r
- IN UINT32 BaseClkFreq,\r
- IN UINT16 ControllerVer\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT32 InitFreq;\r
-\r
- //\r
- // According to SDHCI specification ver. 4.2, BaseClkFreq field value of\r
- // the Capability Register 1 can be zero, which means a need for obtaining\r
- // the clock frequency via another method. Fail in case it is not updated\r
- // by SW at this point.\r
- //\r
- if (BaseClkFreq == 0) {\r
- //\r
- // Don't support get Base Clock Frequency information via another method\r
- //\r
- return EFI_UNSUPPORTED;\r
- }\r
- //\r
- // Supply 400KHz clock frequency at initialization phase.\r
- //\r
- InitFreq = 400;\r
- Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq, ControllerVer);\r
- return Status;\r
-}\r
-\r
/**\r
Supply SD/MMC card with maximum voltage at initialization.\r
\r
return Status;\r
}\r
\r
- Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);\r
+ //\r
+ // Perform first time clock setup with 400 KHz frequency.\r
+ // We send the 0 as the BusTiming value because at this time\r
+ // we still do not know the slot type and which enum value will apply.\r
+ // Since it is a first time setup SdMmcHcClockSupply won't notify\r
+ // the platofrm driver anyway so it doesn't matter.\r
+ //\r
+ Status = SdMmcHcClockSupply (Private, Slot, 0, TRUE, 400);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r