MdeModulePkg/SdMmcPciHcDxe Fix eMMC HS400 switch sequence

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1140

In eMMC HS400 switch sequence flow eMMC driver attempted
to execute SEND_STATUS just after switching bus timing to high
speed and before downgrading clock frequency to 52MHz. Since link
was at that time in incorrect state SEND_STATUS was failing which
made driver think switch to HS400 failed.
This change makes driver always change clock frequency after
switching bus timing and before executing SEND_STATUS.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Albecki Mateusz <mateusz.albecki@intel.com>
Reviewed-by: Hao Wu <hao.a.wu@intel.com>
This commit is contained in:
Albecki, Mateusz 2019-02-18 19:11:37 +08:00 committed by Hao Wu
parent 68c67d3a2a
commit 195f673f62
1 changed files with 20 additions and 19 deletions

View File

@ -642,7 +642,7 @@ EmmcSwitchBusWidth (
}
/**
Switch the clock frequency to the specified value.
Switch the bus timing and clock frequency.
Refer to EMMC Electrical Standard Spec 5.1 Section 6.6 and SD Host Controller
Simplified Spec 3.0 Figure 3-3 for details.
@ -660,7 +660,7 @@ EmmcSwitchBusWidth (
**/
EFI_STATUS
EmmcSwitchClockFreq (
EmmcSwitchBusTiming (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
IN UINT8 Slot,
@ -689,22 +689,10 @@ EmmcSwitchClockFreq (
Status = EmmcSwitch (PassThru, Slot, Access, Index, Value, CmdSet);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "EmmcSwitchClockFreq: Switch to hstiming %d fails with %r\n", HsTiming, Status));
DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Switch to hstiming %d fails with %r\n", HsTiming, Status));
return Status;
}
Status = EmmcSendStatus (PassThru, Slot, Rca, &DevStatus);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "EmmcSwitchClockFreq: Send status fails with %r\n", Status));
return Status;
}
//
// Check the switch operation is really successful or not.
//
if ((DevStatus & BIT7) != 0) {
DEBUG ((DEBUG_ERROR, "EmmcSwitchClockFreq: The switch operation fails as DevStatus is 0x%08x\n", DevStatus));
return EFI_DEVICE_ERROR;
}
//
// Convert the clock freq unit from MHz to KHz.
//
@ -713,6 +701,19 @@ EmmcSwitchClockFreq (
return Status;
}
Status = EmmcSendStatus (PassThru, Slot, Rca, &DevStatus);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Send status fails with %r\n", Status));
return Status;
}
//
// Check the switch operation is really successful or not.
//
if ((DevStatus & BIT7) != 0) {
DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: The switch operation fails as DevStatus is 0x%08x\n", DevStatus));
return EFI_DEVICE_ERROR;
}
if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
Status = mOverride->NotifyPhase (
Private->ControllerHandle,
@ -799,7 +800,7 @@ EmmcSwitchToHighSpeed (
}
HsTiming = 1;
Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
return Status;
}
@ -887,7 +888,7 @@ EmmcSwitchToHS200 (
Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl);
HsTiming = 2;
Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
if (EFI_ERROR (Status)) {
return Status;
}
@ -937,7 +938,7 @@ EmmcSwitchToHS400 (
// Set to Hight Speed timing and set the clock frequency to a value less than 52MHz.
//
HsTiming = 1;
Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, SdMmcMmcHsSdr, 52);
Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming, SdMmcMmcHsSdr, 52);
if (EFI_ERROR (Status)) {
return Status;
}
@ -957,7 +958,7 @@ EmmcSwitchToHS400 (
}
HsTiming = 3;
Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
return Status;
}