* Re: [patch_2] make EDK Driver Support BH720+EMMC chip
@ 2019-01-23 10:39 Mike Li (WH)
2019-01-23 10:45 ` [patch_3] " Mike Li (WH)
0 siblings, 1 reply; 2+ messages in thread
From: Mike Li (WH) @ 2019-01-23 10:39 UTC (permalink / raw)
To: Mike Li (WH), Xiaoguang Yu (WH), Ernest Zhang(WH), Andy Dai (WH)
Cc: Shirley Her (SC), edk2-devel@lists.01.org
Hi, all
The following modifications are made to enable EDK Driver Support BH720 CHIP.
--- /c/yx/edk2/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c 2019-01-21 15:36:12.186739600 -0800
+++ /c/MyWorkspace/edk2-vUDK2018/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c 2019-01-10 14:34:23.072538900 -0800
@@ -1,7 +1,6 @@
/** @file
This file provides some helper functions which are specific for EMMC device.
- Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -527,17 +526,35 @@ EmmcTuningClkForHs200 (
if (EFI_ERROR (Status)) {
return Status;
}
+
+ if(BhtHostPciSupport(PciIo)){
+ //set data transfer with 4bit
+ Status = SdMmcHcSetBusWidth (PciIo, Slot, 4);
+ //enable hardware tuning
+ HostCtrl2 = (~0x10);
+ Status = SdMmcHcAndMmio (PciIo, Slot, 0x110,sizeof (HostCtrl2), &HostCtrl2);
+
+ Status = EmmcSendTuningBlk (PassThru, Slot, 4);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status));
+ return Status;
+ }
+
+ }
//
// Ask the device to send a sequence of tuning blocks till the tuning procedure is done.
//
Retry = 0;
do {
- Status = EmmcSendTuningBlk (PassThru, Slot, BusWidth);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status));
- return Status;
- }
-
+ if(!BhtHostPciSupport(PciIo)){
+ Status = EmmcSendTuningBlk (PassThru, Slot, BusWidth);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status));
+ return Status;
+ }
+ } else {
+ gBS->Stall(5000);
+ }
Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);
if (EFI_ERROR (Status)) {
return Status;
@@ -548,6 +565,10 @@ EmmcTuningClkForHs200 (
}
if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) {
+ if(BhtHostPciSupport(PciIo)){
+ //set data transfer with default
+ Status = SdMmcHcSetBusWidth (PciIo, Slot, BusWidth);
+ }
return EFI_SUCCESS;
}
} while (++Retry < 40);
@@ -652,7 +673,6 @@ EmmcSwitchBusWidth (
@param[in] Slot The slot number of the SD card to send the command to.
@param[in] Rca The relative device address to be assigned.
@param[in] HsTiming The value to be written to HS_TIMING field of EXT_CSD register.
- @param[in] Timing The bus mode timing indicator.
@param[in] ClockFreq The max clock frequency to be set, the unit is MHz.
@retval EFI_SUCCESS The operation is done correctly.
@@ -666,7 +686,6 @@ EmmcSwitchClockFreq (
IN UINT8 Slot,
IN UINT16 Rca,
IN UINT8 HsTiming,
- IN SD_MMC_BUS_MODE Timing,
IN UINT32 ClockFreq
)
{
@@ -708,28 +727,7 @@ EmmcSwitchClockFreq (
//
// Convert the clock freq unit from MHz to KHz.
//
- Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
- Status = mOverride->NotifyPhase (
- Private->ControllerHandle,
- Slot,
- EdkiiSdMmcSwitchClockFreqPost,
- &Timing
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "%a: SD/MMC switch clock freq post notifier callback failed - %r\n",
- __FUNCTION__,
- Status
- ));
- return Status;
- }
- }
+ Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->Capability[Slot]);
return Status;
}
@@ -764,13 +762,10 @@ EmmcSwitchToHighSpeed (
IN UINT8 BusWidth
)
{
- EFI_STATUS Status;
- UINT8 HsTiming;
- UINT8 HostCtrl1;
- SD_MMC_BUS_MODE Timing;
- SD_MMC_HC_PRIVATE_DATA *Private;
-
- Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
+ EFI_STATUS Status;
+ UINT8 HsTiming;
+ UINT8 HostCtrl1;
+ UINT8 HostCtrl2;
Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr, BusWidth);
if (EFI_ERROR (Status)) {
@@ -785,21 +780,31 @@ EmmcSwitchToHighSpeed (
return Status;
}
+ //
+ // Clean UHS Mode Select field of Host Control 2 reigster before update
+ //
+ HostCtrl2 = (UINT8)~0x7;
+ Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Set UHS Mode Select field of Host Control 2 reigster to SDR12/25/50
+ //
if (IsDdr) {
- Timing = SdMmcMmcHsDdr;
+ HostCtrl2 = BIT2;
} else if (ClockFreq == 52) {
- Timing = SdMmcMmcHsSdr;
+ HostCtrl2 = BIT0;
} else {
- Timing = SdMmcMmcLegacy;
+ HostCtrl2 = 0;
}
-
- Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);
+ Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
if (EFI_ERROR (Status)) {
return Status;
}
HsTiming = 1;
- Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
+ Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq);
return Status;
}
@@ -831,13 +836,10 @@ EmmcSwitchToHS200 (
IN UINT8 BusWidth
)
{
- EFI_STATUS Status;
- UINT8 HsTiming;
- UINT16 ClockCtrl;
- SD_MMC_BUS_MODE Timing;
- SD_MMC_HC_PRIVATE_DATA *Private;
-
- Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
+ EFI_STATUS Status;
+ UINT8 HsTiming;
+ UINT8 HostCtrl2;
+ UINT16 ClockCtrl;
if ((BusWidth != 4) && (BusWidth != 8)) {
return EFI_INVALID_PARAMETER;
@@ -857,29 +859,60 @@ EmmcSwitchToHS200 (
if (EFI_ERROR (Status)) {
return Status;
}
-
- Timing = SdMmcMmcHs200;
-
- Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);
+ //
+ // Clean UHS Mode Select field of Host Control 2 reigster before update
+ //
+ HostCtrl2 = (UINT8)~0x7;
+ Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Set UHS Mode Select field of Host Control 2 reigster to SDR104
+ //
+ HostCtrl2 = BIT0 | BIT1;
+ Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
if (EFI_ERROR (Status)) {
return Status;
}
-
//
// Wait Internal Clock Stable in the Clock Control register to be 1 before set SD Clock Enable bit
//
- Status = SdMmcHcWaitMmioSet (
- PciIo,
- Slot,
- SD_MMC_HC_CLOCK_CTRL,
- sizeof (ClockCtrl),
- BIT1,
- BIT1,
- SD_MMC_HC_GENERIC_TIMEOUT
+ if (BhtHostPciSupport(PciIo)) {
+ Status = SdMmcHcWaitMmioSet (
+ PciIo,
+ Slot,
+ 0x1cc,
+ sizeof (ClockCtrl),
+ BIT14,
+ BIT14,
+ SD_MMC_HC_GENERIC_TIMEOUT
+ );
+ }
+ else {
+ Status = SdMmcHcWaitMmioSet (
+ PciIo,
+ Slot,
+ SD_MMC_HC_CLOCK_CTRL,
+ sizeof (ClockCtrl),
+ BIT1,
+ BIT1,
+ SD_MMC_HC_GENERIC_TIMEOUT
);
+ }
if (EFI_ERROR (Status)) {
return Status;
}
+
+ if (BhtHostPciSupport(PciIo)){
+ //Wait 2nd Card Detect debounce Finished by wait twice of debounce max time
+ UINT32 value32;
+ while (1) {
+ Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof(value32), &value32);
+ if (((value32 >> 18) & 0x01) == ((value32 >> 16) & 0x01))
+ break;
+ }
+ }
//
// Set SD Clock Enable in the Clock Control register to 1
//
@@ -887,12 +920,33 @@ 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 = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq);
if (EFI_ERROR (Status)) {
return Status;
}
- Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusWidth);
+ if (BhtHostPciSupport(PciIo)){
+ Status = SdMmcHcWaitMmioSet (
+ PciIo,
+ Slot,
+ 0x1cc,
+ sizeof (ClockCtrl),
+ BIT11,
+ BIT11,
+ SD_MMC_CLOCK_STABLE_TIMEOUT
+ );
+ if (EFI_ERROR(Status)) {
+ DbgMsg(L"Wait Clock Stable timeout, ClockFreq=%d\n", ClockFreq);
+ return Status;
+ }
+ }
+
+ if (EFI_ERROR(Status)) {
+ DbgMsg(L"Emmc tuning failed\n");
+ return Status;
+ }
+
+
return Status;
}
@@ -922,12 +976,9 @@ EmmcSwitchToHS400 (
IN UINT32 ClockFreq
)
{
- EFI_STATUS Status;
- UINT8 HsTiming;
- SD_MMC_BUS_MODE Timing;
- SD_MMC_HC_PRIVATE_DATA *Private;
-
- Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
+ EFI_STATUS Status;
+ UINT8 HsTiming;
+ UINT8 HostCtrl2;
Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, 8);
if (EFI_ERROR (Status)) {
@@ -937,7 +988,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 = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, 52);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -948,16 +999,25 @@ EmmcSwitchToHS400 (
if (EFI_ERROR (Status)) {
return Status;
}
-
- Timing = SdMmcMmcHs400;
-
- Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);
+ //
+ // Clean UHS Mode Select field of Host Control 2 reigster before update
+ //
+ HostCtrl2 = (UINT8)~0x7;
+ Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Set UHS Mode Select field of Host Control 2 reigster to HS400
+ //
+ HostCtrl2 = BIT0 | BIT2;
+ Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
if (EFI_ERROR (Status)) {
return Status;
}
HsTiming = 3;
- Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
+ Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq);
return Status;
}
@@ -1008,7 +1068,7 @@ EmmcSetBusMode (
return Status;
}
- ASSERT (Private->BaseClkFreq[Slot] != 0);
+ ASSERT (Private->Capability[Slot].BaseClkFreq != 0);
//
// Check if the Host Controller support 8bits bus width.
//
@@ -1080,6 +1140,42 @@ EmmcSetBusMode (
// Execute HS200 timing switch procedure
//
Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, BusWidth);
+ if (EFI_ERROR(Status)) {
+ if (BhtHostPciSupport(PciIo)) {
+ UINT32 val32;
+ DbgMsg(L"switch to HS200 200MHZ failed, freq decrease to 100MHz\n");
+ ClockFreq = 100;
+
+ SdMmcHcRwMmio (PciIo, Slot, 0x3C, TRUE, sizeof(val32), &val32);
+ val32 &= ~BIT22;
+ SdMmcHcRwMmio (PciIo, Slot, 0x3C, FALSE, sizeof(val32), &val32);
+ val32 = (BIT26 | BIT25);
+ SdMmcHcOrMmio (PciIo, Slot, 0x2C, sizeof(val32), &val32);
+
+ Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, BusWidth);
+ if (EFI_ERROR(Status)) {
+ if (((ExtCsd.DeviceType & BIT1) != 0) && (Private->Capability[Slot].HighSpeed != 0)) {
+ DbgMsg(L"switch to HS200 100MHZ failed, mode decrease to HS 50MHz\n");
+
+ HsTiming = 1;
+ IsDdr = FALSE;
+ ClockFreq = 52;
+ Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca, ClockFreq, IsDdr, BusWidth);
+ }
+ else if (((ExtCsd.DeviceType & BIT0) != 0) && (Private->Capability[Slot].HighSpeed != 0)) {
+ DbgMsg(L"switch to HS200 100MHZ failed, mode decrease to HS 25MHz\n");
+
+ HsTiming = 1;
+ IsDdr = FALSE;
+ ClockFreq = 26;
+ Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca, ClockFreq, IsDdr, BusWidth);
+ }
+ else {
+ DbgMsg(L"switch to HS200 100MHZ failed, but emmc chip didn't support hs mode\n");
+ }
+ }
+ }
+ }
} else {
//
// Execute High Speed timing switch procedure
Please check it!
Br,
Mike
From: Mike Li (WH)
Sent: 2019年1月23日 17:29
To: Xiaoguang Yu (WH); Ernest Zhang(WH); Andy Dai (WH)
Cc: Shirley Her (SC); 'edk2-devel@lists.01.org'
Subject: [edk2] [patch_1] make EDK Driver Support BH720+EMMC chip
Hi, all
The following modifications are made to enable EDK Driver Support BH720 CHIP.
--- /c/MyWorkspace/edk2-vUDK2018/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c 2019-01-10 14:35:21.342736200 -0800
+++ /c/yx/edk2/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c 2019-01-21 15:36:12.195715300 -0800
@@ -4,6 +4,7 @@
It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use.
+ Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -16,8 +17,6 @@
**/
#include "SdMmcPciHcDxe.h"
-int g_deviceId = 0;
-
/**
Dump the content of SD/MMC host controller's Capability Register.
@@ -47,7 +46,8 @@ DumpCapabilityReg (
DEBUG ((DEBUG_INFO, " Voltage 3.3 %a\n", Capability->Voltage33 ? "TRUE" : "FALSE"));
DEBUG ((DEBUG_INFO, " Voltage 3.0 %a\n", Capability->Voltage30 ? "TRUE" : "FALSE"));
DEBUG ((DEBUG_INFO, " Voltage 1.8 %a\n", Capability->Voltage18 ? "TRUE" : "FALSE"));
- DEBUG ((DEBUG_INFO, " 64-bit Sys Bus %a\n", Capability->SysBus64 ? "TRUE" : "FALSE"));
+ DEBUG ((DEBUG_INFO, " V4 64-bit Sys Bus %a\n", Capability->SysBus64V4 ? "TRUE" : "FALSE"));
+ DEBUG ((DEBUG_INFO, " V3 64-bit Sys Bus %a\n", Capability->SysBus64V3 ? "TRUE" : "FALSE"));
DEBUG ((DEBUG_INFO, " Async Interrupt %a\n", Capability->AsyncInt ? "TRUE" : "FALSE"));
DEBUG ((DEBUG_INFO, " SlotType "));
if (Capability->SlotType == 0x00) {
@@ -419,9 +419,39 @@ SdMmcHcWaitMmioSet (
}
/**
+ Get the controller version information from the specified slot.
+
+ @param[in] PciIo The PCI IO protocol instance.
+ @param[in] Slot The slot number of the SD card to send the command to.
+ @param[out] Version The buffer to store the version information.
+
+ @retval EFI_SUCCESS The operation executes successfully.
+ @retval Others The operation fails.
+
+**/
+EFI_STATUS
+SdMmcHcGetControllerVersion (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT8 Slot,
+ OUT UINT16 *Version
+ )
+{
+ EFI_STATUS Status;
+
+ Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (UINT16), Version);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *Version &= 0xFF;
+
+ return EFI_SUCCESS;
+}
+
+/**
Software reset the specified SD/MMC host controller and enable all interrupts.
- @param[in] PciIo The PCI IO protocol instance.
+ @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
@param[in] Slot The slot number of the SD card to send the command to.
@retval EFI_SUCCESS The software reset executes successfully.
@@ -430,18 +460,38 @@ SdMmcHcWaitMmioSet (
**/
EFI_STATUS
SdMmcHcReset (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN SD_MMC_HC_PRIVATE_DATA *Private,
IN UINT8 Slot
)
{
EFI_STATUS Status;
UINT8 SwReset;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ //
+ // Notify the SD/MMC override protocol that we are about to reset
+ // the SD/MMC host controller.
+ //
+ if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
+ Status = mOverride->NotifyPhase (
+ Private->ControllerHandle,
+ Slot,
+ EdkiiSdMmcResetPre,
+ NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN,
+ "%a: SD/MMC pre reset notifier callback failed - %r\n",
+ __FUNCTION__, Status));
+ return Status;
+ }
+ }
- SwReset = 0xFF;
- Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_SW_RST, FALSE, sizeof (SwReset), &SwReset);
+ PciIo = Private->PciIo;
+ SwReset = BIT0;
+ Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_SW_RST, sizeof (SwReset), &SwReset);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "SdMmcHcReset: write full 1 fails: %r\n", Status));
+ DEBUG ((DEBUG_ERROR, "SdMmcHcReset: write SW Reset for All fails: %r\n", Status));
return Status;
}
@@ -450,7 +500,7 @@ SdMmcHcReset (
Slot,
SD_MMC_HC_SW_RST,
sizeof (SwReset),
- 0xFF,
+ BIT0,
0x00,
SD_MMC_HC_GENERIC_TIMEOUT
);
@@ -458,10 +508,33 @@ SdMmcHcReset (
DEBUG ((DEBUG_INFO, "SdMmcHcReset: reset done with %r\n", Status));
return Status;
}
+
//
// Enable all interrupt after reset all.
//
Status = SdMmcHcEnableInterrupt (PciIo, Slot);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "SdMmcHcReset: SdMmcHcEnableInterrupt done with %r\n",
+ Status));
+ return Status;
+ }
+
+ //
+ // Notify the SD/MMC override protocol that we have just reset
+ // the SD/MMC host controller.
+ //
+ if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
+ Status = mOverride->NotifyPhase (
+ Private->ControllerHandle,
+ Slot,
+ EdkiiSdMmcResetPost,
+ NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN,
+ "%a: SD/MMC post reset notifier callback failed - %r\n",
+ __FUNCTION__, Status));
+ }
+ }
return Status;
}
@@ -680,7 +753,8 @@ SdMmcHcStopClock (
@param[in] PciIo The PCI IO protocol instance.
@param[in] Slot The slot number of the SD card to send the command to.
@param[in] ClockFreq The max clock frequency to be set. The unit is KHz.
- @param[in] Capability The capability of the slot.
+ @param[in] BaseClkFreq The base clock frequency of host controller in MHz.
+ @param[in] ControllerVer The version of host controller.
@retval EFI_SUCCESS The clock is supplied successfully.
@retval Others The clock isn't supplied successfully.
@@ -691,23 +765,21 @@ SdMmcHcClockSupply (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT8 Slot,
IN UINT64 ClockFreq,
- IN SD_MMC_HC_SLOT_CAP Capability
+ IN UINT32 BaseClkFreq,
+ IN UINT16 ControllerVer
)
{
EFI_STATUS Status;
- UINT32 BaseClkFreq;
UINT32 SettingFreq;
UINT32 Divisor;
UINT32 Remainder;
- UINT16 ControllerVer;
UINT16 ClockCtrl;
//
// Calculate a divisor for SD clock frequency
//
- ASSERT (Capability.BaseClkFreq != 0);
+ ASSERT (BaseClkFreq != 0);
- BaseClkFreq = Capability.BaseClkFreq;
if (ClockFreq == 0) {
return EFI_INVALID_PARAMETER;
}
@@ -736,17 +808,15 @@ SdMmcHcClockSupply (
DEBUG ((DEBUG_INFO, "BaseClkFreq %dMHz Divisor %d ClockFreq %dKhz\n", BaseClkFreq, Divisor, ClockFreq));
- Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (ControllerVer), &ControllerVer);
- if (EFI_ERROR (Status)) {
- return Status;
- }
//
// Set SDCLK Frequency Select and Internal Clock Enable fields in Clock Control register.
//
- if (((ControllerVer & 0xFF) == 2) || ((ControllerVer & 0xFF) == 3)) {
+ if ((ControllerVer >= SD_MMC_HC_CTRL_VER_300) &&
+ (ControllerVer <= SD_MMC_HC_CTRL_VER_420)) {
ASSERT (Divisor <= 0x3FF);
ClockCtrl = ((Divisor & 0xFF) << 8) | ((Divisor & 0x300) >> 2);
- } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {
+ } else if ((ControllerVer == SD_MMC_HC_CTRL_VER_100) ||
+ (ControllerVer == SD_MMC_HC_CTRL_VER_200)) {
//
// Only the most significant bit can be used as divisor.
//
@@ -894,11 +964,62 @@ SdMmcHcSetBusWidth (
}
/**
- Supply SD/MMC card with lowest clock frequency at initialization.
+ Configure V4 controller enhancements at initialization.
@param[in] PciIo The PCI IO protocol instance.
@param[in] Slot The slot number of the SD card to send the command to.
@param[in] Capability The capability of the slot.
+ @param[in] ControllerVer The version of host controller.
+
+ @retval EFI_SUCCESS The clock is supplied successfully.
+
+**/
+EFI_STATUS
+SdMmcHcInitV4Enhancements (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT8 Slot,
+ IN SD_MMC_HC_SLOT_CAP Capability,
+ IN UINT16 ControllerVer
+ )
+{
+ EFI_STATUS Status;
+ UINT16 HostCtrl2;
+
+ //
+ // Check if controller version V4 or higher
+ //
+ if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
+ HostCtrl2 = SD_MMC_HC_V4_EN;
+ //
+ // Check if V4 64bit support is available
+ //
+ if (Capability.SysBus64V4 != 0) {
+ HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;
+ DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));
+ }
+ //
+ // Check if controller version V4.10 or higher
+ //
+ if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) {
+ HostCtrl2 |= SD_MMC_HC_26_DATA_LEN_ADMA_EN;
+ DEBUG ((DEBUG_INFO, "Enabled V4 26 bit data length ADMA support\n"));
+ }
+ Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Supply SD/MMC card with lowest clock frequency at initialization.
+
+ @param[in] PciIo The PCI IO protocol instance.
+ @param[in] Slot The slot number of the SD card to send the command to.
+ @param[in] BaseClkFreq The base clock frequency of host controller in MHz.
+ @param[in] ControllerVer The version of host controller.
@retval EFI_SUCCESS The clock is supplied successfully.
@retval Others The clock isn't supplied successfully.
@@ -908,16 +1029,20 @@ EFI_STATUS
SdMmcHcInitClockFreq (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT8 Slot,
- IN SD_MMC_HC_SLOT_CAP Capability
+ IN UINT32 BaseClkFreq,
+ IN UINT16 ControllerVer
)
{
EFI_STATUS Status;
UINT32 InitFreq;
//
- // Calculate a divisor for SD clock frequency
+ // According to SDHCI specification ver. 4.2, BaseClkFreq field value of
+ // the Capability Register 1 can be zero, which means a need for obtaining
+ // the clock frequency via another method. Fail in case it is not updated
+ // by SW at this point.
//
- if (Capability.BaseClkFreq == 0) {
+ if (BaseClkFreq == 0) {
//
// Don't support get Base Clock Frequency information via another method
//
@@ -927,7 +1052,7 @@ SdMmcHcInitClockFreq (
// Supply 400KHz clock frequency at initialization phase.
//
InitFreq = 400;
- Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, Capability);
+ Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq, ControllerVer);
return Status;
}
@@ -988,15 +1113,6 @@ SdMmcHcInitPowerVoltage (
// Set SD Bus Voltage Select and SD Bus Power fields in Power Control Register
//
Status = SdMmcHcPowerControl (PciIo, Slot, MaxVoltage);
- if (BhtHostPciSupport(PciIo)){
- // 1.8V signaling enable
- HostCtrl2 = BIT3;
- Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
- gBS->Stall (5000);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
return Status;
}
@@ -1032,9 +1148,8 @@ SdMmcHcInitTimeoutCtrl (
Initial SD/MMC host controller with lowest clock frequency, max power and max timeout value
at initialization.
- @param[in] PciIo The PCI IO protocol instance.
+ @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
@param[in] Slot The slot number of the SD card to send the command to.
- @param[in] Capability The capability of the slot.
@retval EFI_SUCCESS The host controller is initialized successfully.
@retval Others The host controller isn't initialized successfully.
@@ -1042,96 +1157,164 @@ SdMmcHcInitTimeoutCtrl (
**/
EFI_STATUS
SdMmcHcInitHost (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN UINT8 Slot,
- IN SD_MMC_HC_SLOT_CAP Capability
+ IN SD_MMC_HC_PRIVATE_DATA *Private,
+ IN UINT8 Slot
)
{
- EFI_STATUS Status;
- UINT32 value32;
-
- if (BhtHostPciSupport(PciIo)){
-
- DbgMsg(L"find bht emmc chip\n");
- /* FET on */
- PciBhtOr32(PciIo, 0xEC, 0x3);
- /* Led on */
- //PciBhtAnd32(PciIo, 0x334, (UINT32)~BIT13);
- PciBhtOr32(PciIo, 0xD4, BIT6);
- /* Set 1.8v emmc signaling flag */
- PciBhtOr32(PciIo, 0x308, BIT4);
- /* Set 200MBaseClock */
- value32 = PciBhtRead32(PciIo, 0x304);
- value32 &= 0x0000FFFF;
- value32 |= 0x25100000;
- PciBhtWrite32(PciIo, 0x304, value32);
- PciBhtOr32(PciIo, 0x3E4, BIT22);
- PciBhtWrite32(PciIo, 0x300, 0x21400033);
-
- //enable internal clk
- value32 = BIT0;
- Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL,sizeof(value32), &value32);
-
- //reset pll start
- Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32);
- value32 |= BIT12;
- Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32);
- gBS->Stall(1);
-
- //reset pll end
- Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE,sizeof(value32), &value32);
- value32 &= ~BIT12;
- value32 |= BIT18;
- Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32);
-
- //wait BaseClk stable 0x1CC bit14
- Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32);
- while(!(value32&BIT14)){
- gBS->Stall(100);
- Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32);
- DbgMsg(L"1CC=0x%08x\n", value32);
- }
-
- if (value32 & BIT18)
- {
- //Wait 2nd Card Detect debounce Finished by wait twice of debounce max time
- while (1) {
- Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof(value32), &value32);
- if (((value32 >> 16) & 0x01) == ((value32 >> 18) & 0x01))
- break;
- }
- //force pll active end
- Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32);
- value32 &= ~BIT18;
- Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32);
- }
-
- Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability);
- if (EFI_ERROR (Status)) {
- DbgMsg(L"emmc host init failure\n");
- return Status;
- }
-
-
- }
-
- Status = SdMmcHcInitClockFreq (PciIo, Slot, Capability);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (!BhtHostPciSupport(PciIo)){
- Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability);
- if (EFI_ERROR (Status)) {
- return Status;
- }
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ SD_MMC_HC_SLOT_CAP Capability;
+
+ //
+ // Notify the SD/MMC override protocol that we are about to initialize
+ // the SD/MMC host controller.
+ //
+ if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
+ Status = mOverride->NotifyPhase (
+ Private->ControllerHandle,
+ Slot,
+ EdkiiSdMmcInitHostPre,
+ NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN,
+ "%a: SD/MMC pre init notifier callback failed - %r\n",
+ __FUNCTION__, Status));
+ return Status;
+ }
+ }
+
+ PciIo = Private->PciIo;
+ Capability = Private->Capability[Slot];
+
+ Status = SdMmcHcInitV4Enhancements (PciIo, Slot, Capability, Private->ControllerVersion[Slot]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
+ if (EFI_ERROR (Status)) {
+ return Status;
}
-
+
+ Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
Status = SdMmcHcInitTimeoutCtrl (PciIo, Slot);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Notify the SD/MMC override protocol that we are have just initialized
+ // the SD/MMC host controller.
+ //
+ if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
+ Status = mOverride->NotifyPhase (
+ Private->ControllerHandle,
+ Slot,
+ EdkiiSdMmcInitHostPost,
+ NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN,
+ "%a: SD/MMC post init notifier callback failed - %r\n",
+ __FUNCTION__, Status));
+ }
+ }
return Status;
}
/**
+ Set SD Host Controler control 2 registry according to selected speed.
+
+ @param[in] ControllerHandle The handle of the controller.
+ @param[in] PciIo The PCI IO protocol instance.
+ @param[in] Slot The slot number of the SD card to send the command to.
+ @param[in] Timing The timing to select.
+
+ @retval EFI_SUCCESS The timing is set successfully.
+ @retval Others The timing isn't set successfully.
+**/
+EFI_STATUS
+SdMmcHcUhsSignaling (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT8 Slot,
+ IN SD_MMC_BUS_MODE Timing
+ )
+{
+ EFI_STATUS Status;
+ UINT8 HostCtrl2;
+
+ HostCtrl2 = (UINT8)~SD_MMC_HC_CTRL_UHS_MASK;
+ Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ switch (Timing) {
+ case SdMmcUhsSdr12:
+ HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR12;
+ break;
+ case SdMmcUhsSdr25:
+ HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR25;
+ break;
+ case SdMmcUhsSdr50:
+ HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR50;
+ break;
+ case SdMmcUhsSdr104:
+ HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR104;
+ break;
+ case SdMmcUhsDdr50:
+ HostCtrl2 = SD_MMC_HC_CTRL_UHS_DDR50;
+ break;
+ case SdMmcMmcLegacy:
+ HostCtrl2 = SD_MMC_HC_CTRL_MMC_LEGACY;
+ break;
+ case SdMmcMmcHsSdr:
+ HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS_SDR;
+ break;
+ case SdMmcMmcHsDdr:
+ HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS_DDR;
+ break;
+ case SdMmcMmcHs200:
+ HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS200;
+ break;
+ case SdMmcMmcHs400:
+ HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS400;
+ break;
+ default:
+ HostCtrl2 = 0;
+ break;
+ }
+ Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
+ Status = mOverride->NotifyPhase (
+ ControllerHandle,
+ Slot,
+ EdkiiSdMmcUhsSignaling,
+ &Timing
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: SD/MMC uhs signaling notifier callback failed - %r\n",
+ __FUNCTION__,
+ Status
+ ));
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
Turn on/off LED.
@param[in] PciIo The PCI IO protocol instance.
@@ -1166,9 +1349,10 @@ SdMmcHcLedOnOff (
/**
Build ADMA descriptor table for transfer.
- Refer to SD Host Controller Simplified spec 3.0 Section 1.13 for details.
+ Refer to SD Host Controller Simplified spec 4.2 Section 1.13 for details.
@param[in] Trb The pointer to the SD_MMC_HC_TRB instance.
+ @param[in] ControllerVer The version of host controller.
@retval EFI_SUCCESS The ADMA descriptor table is created successfully.
@retval Others The ADMA descriptor table isn't created successfully.
@@ -1176,7 +1360,8 @@ SdMmcHcLedOnOff (
**/
EFI_STATUS
BuildAdmaDescTable (
- IN SD_MMC_HC_TRB *Trb
+ IN SD_MMC_HC_TRB *Trb,
+ IN UINT16 ControllerVer
)
{
EFI_PHYSICAL_ADDRESS Data;
@@ -1184,49 +1369,93 @@ BuildAdmaDescTable (
UINT64 Entries;
UINT32 Index;
UINT64 Remaining;
- UINT32 Address;
+ UINT64 Address;
UINTN TableSize;
EFI_PCI_IO_PROTOCOL *PciIo;
EFI_STATUS Status;
UINTN Bytes;
+ BOOLEAN AddressingMode64;
+ BOOLEAN DataLength26;
+ UINT32 AdmaMaxDataPerLine;
+ UINT32 DescSize;
+ VOID *AdmaDesc;
+
+ AddressingMode64 = FALSE;
+ DataLength26 = FALSE;
+ AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_16B;
+ DescSize = sizeof (SD_MMC_HC_ADMA_32_DESC_LINE);
+ AdmaDesc = NULL;
Data = Trb->DataPhy;
DataLen = Trb->DataLen;
PciIo = Trb->Private->PciIo;
+
//
- // Only support 32bit ADMA Descriptor Table
+ // Detect whether 64bit addressing is supported.
//
- if ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul)) {
+ if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
+ Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
+ SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
+ if (!EFI_ERROR (Status)) {
+ AddressingMode64 = TRUE;
+ DescSize = sizeof (SD_MMC_HC_ADMA_64_DESC_LINE);
+ }
+ }
+ //
+ // Check for valid ranges in 32bit ADMA Descriptor Table
+ //
+ if (!AddressingMode64 &&
+ ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul))) {
return EFI_INVALID_PARAMETER;
}
//
- // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to 0)
- // for 32-bit address descriptor table.
+ // Check address field alignment
//
- if ((Data & (BIT0 | BIT1)) != 0) {
- DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data));
+ if (AddressingMode64) {
+ //
+ // Address field shall be set on 64-bit boundary (Lower 3-bit is always set to 0)
+ //
+ if ((Data & (BIT0 | BIT1 | BIT2)) != 0) {
+ DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 8 bytes boundary!\n", Data));
+ }
+ } else {
+ //
+ // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to 0)
+ //
+ if ((Data & (BIT0 | BIT1)) != 0) {
+ DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data));
+ }
+ }
+ //
+ // Detect whether 26bit data length is supported.
+ //
+ Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
+ SD_MMC_HC_26_DATA_LEN_ADMA_EN, SD_MMC_HC_26_DATA_LEN_ADMA_EN);
+ if (!EFI_ERROR (Status)) {
+ DataLength26 = TRUE;
+ AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_26B;
}
- Entries = DivU64x32 ((DataLen + ADMA_MAX_DATA_PER_LINE - 1), ADMA_MAX_DATA_PER_LINE);
- TableSize = (UINTN)MultU64x32 (Entries, sizeof (SD_MMC_HC_ADMA_DESC_LINE));
+ Entries = DivU64x32 ((DataLen + AdmaMaxDataPerLine - 1), AdmaMaxDataPerLine);
+ TableSize = (UINTN)MultU64x32 (Entries, DescSize);
Trb->AdmaPages = (UINT32)EFI_SIZE_TO_PAGES (TableSize);
Status = PciIo->AllocateBuffer (
PciIo,
AllocateAnyPages,
EfiBootServicesData,
EFI_SIZE_TO_PAGES (TableSize),
- (VOID **)&Trb->AdmaDesc,
+ (VOID **)&AdmaDesc,
0
);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
- ZeroMem (Trb->AdmaDesc, TableSize);
+ ZeroMem (AdmaDesc, TableSize);
Bytes = TableSize;
Status = PciIo->Map (
PciIo,
EfiPciIoOperationBusMasterCommonBuffer,
- Trb->AdmaDesc,
+ AdmaDesc,
&Bytes,
&Trb->AdmaDescPhy,
&Trb->AdmaMap
@@ -1239,12 +1468,13 @@ BuildAdmaDescTable (
PciIo->FreeBuffer (
PciIo,
EFI_SIZE_TO_PAGES (TableSize),
- Trb->AdmaDesc
+ AdmaDesc
);
return EFI_OUT_OF_RESOURCES;
}
- if ((UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
+ if ((!AddressingMode64) &&
+ (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
//
// The ADMA doesn't support 64bit addressing.
//
@@ -1255,35 +1485,71 @@ BuildAdmaDescTable (
PciIo->FreeBuffer (
PciIo,
EFI_SIZE_TO_PAGES (TableSize),
- Trb->AdmaDesc
+ AdmaDesc
);
return EFI_DEVICE_ERROR;
}
Remaining = DataLen;
- Address = (UINT32)Data;
+ Address = Data;
+ if (!AddressingMode64) {
+ Trb->Adma32Desc = AdmaDesc;
+ Trb->Adma64Desc = NULL;
+ } else {
+ Trb->Adma64Desc = AdmaDesc;
+ Trb->Adma32Desc = NULL;
+ }
for (Index = 0; Index < Entries; Index++) {
- if (Remaining <= ADMA_MAX_DATA_PER_LINE) {
- Trb->AdmaDesc[Index].Valid = 1;
- Trb->AdmaDesc[Index].Act = 2;
- Trb->AdmaDesc[Index].Length = (UINT16)Remaining;
- Trb->AdmaDesc[Index].Address = Address;
- break;
+ if (!AddressingMode64) {
+ if (Remaining <= AdmaMaxDataPerLine) {
+ Trb->Adma32Desc[Index].Valid = 1;
+ Trb->Adma32Desc[Index].Act = 2;
+ if (DataLength26) {
+ Trb->Adma32Desc[Index].UpperLength = (UINT16)RShiftU64 (Remaining, 16);
+ }
+ Trb->Adma32Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16);
+ Trb->Adma32Desc[Index].Address = (UINT32)Address;
+ break;
+ } else {
+ Trb->Adma32Desc[Index].Valid = 1;
+ Trb->Adma32Desc[Index].Act = 2;
+ if (DataLength26) {
+ Trb->Adma32Desc[Index].UpperLength = 0;
+ }
+ Trb->Adma32Desc[Index].LowerLength = 0;
+ Trb->Adma32Desc[Index].Address = (UINT32)Address;
+ }
} else {
- Trb->AdmaDesc[Index].Valid = 1;
- Trb->AdmaDesc[Index].Act = 2;
- Trb->AdmaDesc[Index].Length = 0;
- Trb->AdmaDesc[Index].Address = Address;
+ if (Remaining <= AdmaMaxDataPerLine) {
+ Trb->Adma64Desc[Index].Valid = 1;
+ Trb->Adma64Desc[Index].Act = 2;
+ if (DataLength26) {
+ Trb->Adma64Desc[Index].UpperLength = (UINT16)RShiftU64 (Remaining, 16);
+ }
+ Trb->Adma64Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16);
+ Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
+ Trb->Adma64Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);
+ break;
+ } else {
+ Trb->Adma64Desc[Index].Valid = 1;
+ Trb->Adma64Desc[Index].Act = 2;
+ if (DataLength26) {
+ Trb->Adma64Desc[Index].UpperLength = 0;
+ }
+ Trb->Adma64Desc[Index].LowerLength = 0;
+ Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
+ Trb->Adma64Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);
+ }
}
- Remaining -= ADMA_MAX_DATA_PER_LINE;
- Address += ADMA_MAX_DATA_PER_LINE;
+ Remaining -= AdmaMaxDataPerLine;
+ Address += AdmaMaxDataPerLine;
}
//
// Set the last descriptor line as end of descriptor table
//
- Trb->AdmaDesc[Index].End = 1;
+ AddressingMode64 ? (Trb->Adma64Desc[Index].End = 1) : (Trb->Adma32Desc[Index].End = 1);
return EFI_SUCCESS;
}
@@ -1381,7 +1647,7 @@ SdMmcCreateTrb (
Trb->Mode = SdMmcNoData;
} else if (Private->Capability[Slot].Adma2 != 0) {
Trb->Mode = SdMmcAdmaMode;
- Status = BuildAdmaDescTable (Trb);
+ Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);
if (EFI_ERROR (Status)) {
PciIo->Unmap (PciIo, Trb->DataMap);
goto Error;
@@ -1427,11 +1693,18 @@ SdMmcFreeTrb (
Trb->AdmaMap
);
}
- if (Trb->AdmaDesc != NULL) {
+ if (Trb->Adma32Desc != NULL) {
+ PciIo->FreeBuffer (
+ PciIo,
+ Trb->AdmaPages,
+ Trb->Adma32Desc
+ );
+ }
+ if (Trb->Adma64Desc != NULL) {
PciIo->FreeBuffer (
PciIo,
Trb->AdmaPages,
- Trb->AdmaDesc
+ Trb->Adma64Desc
);
}
if (Trb->DataMap != NULL) {
@@ -1571,12 +1844,15 @@ SdMmcExecTrb (
UINT16 Cmd;
UINT16 IntStatus;
UINT32 Argument;
- UINT16 BlkCount;
+ UINT32 BlkCount;
UINT16 BlkSize;
UINT16 TransMode;
UINT8 HostCtrl1;
- UINT32 SdmaAddr;
+ UINT64 SdmaAddr;
UINT64 AdmaAddr;
+ BOOLEAN AddressingMode64;
+
+ AddressingMode64 = FALSE;
Packet = Trb->Packet;
PciIo = Trb->Private->PciIo;
@@ -1609,13 +1885,28 @@ SdMmcExecTrb (
SdMmcHcLedOnOff (PciIo, Trb->Slot, TRUE);
+ if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {
+ Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
+ SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
+ if (!EFI_ERROR (Status)) {
+ AddressingMode64 = TRUE;
+ }
+ }
+
if (Trb->Mode == SdMmcSdmaMode) {
- if ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul) {
+ if ((!AddressingMode64) &&
+ ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul)) {
return EFI_INVALID_PARAMETER;
}
- SdmaAddr = (UINT32)(UINTN)Trb->DataPhy;
- Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (SdmaAddr), &SdmaAddr);
+ SdmaAddr = (UINT64)(UINTN)Trb->DataPhy;
+
+ if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {
+ Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (UINT64), &SdmaAddr);
+ } else {
+ Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &SdmaAddr);
+ }
+
if (EFI_ERROR (Status)) {
return Status;
}
@@ -1645,9 +1936,13 @@ SdMmcExecTrb (
//
// Calcuate Block Count.
//
- BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);
+ BlkCount = (Trb->DataLen / Trb->BlockSize);
+ }
+ if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_410) {
+ Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &BlkCount);
+ } else {
+ Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (UINT16), &BlkCount);
}
- Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -1743,7 +2038,7 @@ SdMmcCheckTrbResult (
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
UINT16 IntStatus;
UINT32 Response[4];
- UINT32 SdmaAddr;
+ UINT64 SdmaAddr;
UINT8 Index;
UINT8 SwReset;
UINT32 PioLength;
@@ -1867,8 +2162,19 @@ SdMmcCheckTrbResult (
//
// Update SDMA Address register.
//
- SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINT32)(UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY);
- Status = SdMmcHcRwMmio (
+ SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY);
+
+ if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {
+ Status = SdMmcHcRwMmio (
+ Private->PciIo,
+ Trb->Slot,
+ SD_MMC_HC_ADMA_SYS_ADDR,
+ FALSE,
+ sizeof (UINT64),
+ &SdmaAddr
+ );
+ } else {
+ Status = SdMmcHcRwMmio (
Private->PciIo,
Trb->Slot,
SD_MMC_HC_SDMA_ADDR,
@@ -1876,10 +2182,12 @@ SdMmcCheckTrbResult (
sizeof (UINT32),
&SdmaAddr
);
+ }
+
if (EFI_ERROR (Status)) {
goto Done;
}
- Trb->DataPhy = (UINT32)(UINTN)SdmaAddr;
+ Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;
}
if ((Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeAdtc) &&
@@ -2000,281 +2308,3 @@ SdMmcWaitTrbResult (
return EFI_TIMEOUT;
}
-BOOLEAN BhtHostPciSupport(EFI_PCI_IO_PROTOCOL *PciIo)
-{
- PCI_TYPE00 Pci;
-
- PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32,
- 0, sizeof Pci / sizeof (UINT32), &Pci);
-
- DEBUG ((DEBUG_INFO, "check device %04x:%04x\n", Pci.Hdr.VendorId, Pci.Hdr.DeviceId));
-
- if (Pci.Hdr.VendorId != 0x1217)
- goto end;
-
- switch (Pci.Hdr.DeviceId)
- {
- case 0x8420: //PCI_DEV_ID_SDS0
- case 0x8421: //PCI_DEV_ID_SDS1
- case 0x8520: //PCI_DEV_ID_FJ2
- case 0x8620: //PCI_DEV_ID_SB0
- case 0x8621: //PCI_DEV_ID_SB1
- g_deviceId = Pci.Hdr.DeviceId;
- return 1;
- default:
- break;
- }
-
- end:
- return 0;
-}
-
-void DbgNull(IN CONST CHAR16 * fmt, ...)
-{
-}
-
-UINT32 bht_readl(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset)
-{
- UINT32 arg;
- PciIo->Mem.Read(PciIo,EfiPciIoWidthUint32,1,offset,1,&arg);
- return arg;
-}
-
-void bht_writel(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value)
-{
- PciIo->Mem.Write(PciIo,EfiPciIoWidthUint32,1,offset,1,&value);
-}
-
-
-UINT32 PciBhtRead32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset)
-{
- UINT32 i = 0;
- UINT32 tmp[3] = {0};
-
- if((g_deviceId == PCI_DEV_ID_SDS0) ||
- (g_deviceId == PCI_DEV_ID_SDS1) ||
- (g_deviceId == PCI_DEV_ID_FJ2) ||
- (g_deviceId == PCI_DEV_ID_SB0) ||
- (g_deviceId == PCI_DEV_ID_SB1))
- {
- // For Sandstorm, HW implement a mapping method by memory space reg to access PCI reg.
- // Enable mapping
-
- // Check function conflict
- if((g_deviceId == PCI_DEV_ID_SDS0) ||
- (g_deviceId == PCI_DEV_ID_FJ2) ||
- (g_deviceId == PCI_DEV_ID_SB0) ||
- (g_deviceId == PCI_DEV_ID_SB1))
- {
- i = 0;
- bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000);
- while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x40000000) == 0)
- {
- if(i == 5)
- {
- //DbgMsg((DRIVERNAME " - %s() function 0 can't lock!\n", __FUNCTION__));
- goto RD_DIS_MAPPING;
- }
- gBS->Stall(1000);
- i++;
- bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000);
-
- }
- }
- else if(g_deviceId == PCI_DEV_ID_SDS1)
- {
- i = 0;
- bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000);
- while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x20000000) == 0)
- {
- if(i == 5)
- {
- //DbgErr((DRIVERNAME " - %s() function 1 can't lock!\n", __FUNCTION__));
- goto RD_DIS_MAPPING;
- }
- gBS->Stall(1000);
- i++;
- bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000);
- }
- }
-
- // Check last operation is complete
- i = 0;
- while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000)
- {
- if(i == 5)
- {
- //DbgErr((DRIVERNAME " - [204] = 0x%x\n", RegisterRead32(ELN_dPCIRMappingCtl)));
- //DbgErr((DRIVERNAME " - [208] = 0x%x\n", RegisterRead32(ELN_dPCIRMappingEn)));
- //DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__));
- goto RD_DIS_MAPPING;
- }
- gBS->Stall(1000);
- i += 1;
- }
-
- // Set register address
- tmp[0] |= 0x40000000;
- tmp[0] |= offset;
- bht_writel(PciIo, BHT_PCIRMappingCtl, tmp[0]);
-
- // Check read is complete
- i = 0;
- while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0x40000000)
- {
- if(i == 5)
- {
- //DbgErr((DRIVERNAME " - %s() check read operation complete timeout!!!\n", __FUNCTION__));
- goto RD_DIS_MAPPING;
- }
- gBS->Stall(1000);
- i += 1;
- }
-
- // Get PCIR value
- tmp[1] = bht_readl(PciIo, BHT_PCIRMappingVal);
-
-RD_DIS_MAPPING:
- // Disable mapping
- bht_writel(PciIo, BHT_PCIRMappingEn, 0x80000000);
-
- //DbgDebug(L"%s offset=%x Value:%x\n", __FUNCTION__, offset, tmp[1]);
- return tmp[1];
- }
-
- //DbgDebug(L"%s offset=%x Value:%x\n", __FUNCTION__, offset, tmp[0]);
- return tmp[0];
-}
-
-void PciBhtWrite32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value)
-{
- UINT32 tmp = 0;
- UINT32 i = 0;
-
- if((g_deviceId == PCI_DEV_ID_SDS0) ||
- (g_deviceId == PCI_DEV_ID_SDS1) ||
- (g_deviceId == PCI_DEV_ID_FJ2) ||
- (g_deviceId == PCI_DEV_ID_SB0) ||
- (g_deviceId == PCI_DEV_ID_SB1))
- {
- // For Sandstorm, HW implement a mapping method by memory space reg to access PCI reg.
- // Upper caller doesn't need to set 0xD0.
-
- // Enable mapping
-
- // Check function conflict
- if((g_deviceId == PCI_DEV_ID_SDS0) ||
- (g_deviceId == PCI_DEV_ID_FJ2) ||
- (g_deviceId == PCI_DEV_ID_SB0) ||
- (g_deviceId == PCI_DEV_ID_SB1))
- {
- i = 0;
- bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000);
- while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x40000000) == 0)
- {
- if(i == 5)
- {
- //DbgErr((DRIVERNAME " - %s() function 0 can't lock!\n", __FUNCTION__));
- goto WR_DIS_MAPPING;
- }
-
- gBS->Stall(1000);
- i++;
- bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000);
- }
- }
- else if(g_deviceId == PCI_DEV_ID_SDS1)
- {
- i = 0;
- bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000);
-
- while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x20000000) == 0)
- {
- if(i == 5)
- {
- //DbgErr((DRIVERNAME " - %s() function 0 can't lock!\n", __FUNCTION__));
- goto WR_DIS_MAPPING;
- }
-
- gBS->Stall(1000);
- i++;
- bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000);
- }
- }
-
- // Enable MEM access
- bht_writel(PciIo, BHT_PCIRMappingVal, 0x80000000);
- bht_writel(PciIo, BHT_PCIRMappingCtl, 0x800000D0);
-
- // Check last operation is complete
- i = 0;
- while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000)
- {
- if(i == 5)
- {
- //DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__));
- goto WR_DIS_MAPPING;
- }
- gBS->Stall(1000);
- i += 1;
- }
-
- // Set write value
- bht_writel(PciIo, BHT_PCIRMappingVal, value);
- // Set register address
- tmp |= 0x80000000;
- tmp |= offset;
- bht_writel(PciIo, BHT_PCIRMappingCtl, tmp);
-
- // Check write is complete
- i = 0;
- while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0x80000000)
- {
- if(i == 5)
- {
- //DbgErr((DRIVERNAME " - %s() check write operation complete timeout!!!\n", __FUNCTION__));
- goto WR_DIS_MAPPING;
- }
- gBS->Stall(1000);
- i += 1;
- }
-
-WR_DIS_MAPPING:
- // Disable MEM access
- bht_writel(PciIo, BHT_PCIRMappingVal, 0x80000001);
- bht_writel(PciIo, BHT_PCIRMappingCtl, 0x800000D0);
-
- // Check last operation is complete
- i = 0;
- while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000)
- {
- if(i == 5)
- {
- //DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__));
- break;
- }
- gBS->Stall(1000);
- i += 1;
- }
-
- // Disable function conflict
-
- // Disable mapping
- bht_writel(PciIo, BHT_PCIRMappingEn, 0x80000000);
- }
-}
-
-void PciBhtOr32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value)
-{
- UINT32 arg;
- arg = PciBhtRead32(PciIo, offset);
- PciBhtWrite32(PciIo, offset, value | arg);
-}
-
-void PciBhtAnd32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value)
-{
- UINT32 arg;
- arg = PciBhtRead32(PciIo, offset);
- PciBhtWrite32(PciIo, offset, value & arg);
-}
-
Please check it!
Br,
Mike
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [patch_3] make EDK Driver Support BH720+EMMC chip
2019-01-23 10:39 [patch_2] make EDK Driver Support BH720+EMMC chip Mike Li (WH)
@ 2019-01-23 10:45 ` Mike Li (WH)
0 siblings, 0 replies; 2+ messages in thread
From: Mike Li (WH) @ 2019-01-23 10:45 UTC (permalink / raw)
To: Mike Li (WH), Xiaoguang Yu (WH), Ernest Zhang(WH), Andy Dai (WH)
Cc: Shirley Her (SC), edk2-devel@lists.01.org
Hi, all
The following modifications are made to enable EDK Driver Support BH720 CHIP.
--- /c/yx/edk2/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c 2019-01-21 15:36:12.188734400 -0800
+++ /c/MyWorkspace/edk2-vUDK2018/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c 2018-08-13 22:40:04.802226200 -0700
@@ -1,7 +1,6 @@
/** @file
This file provides some helper functions which are specific for SD card device.
- Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -319,9 +318,116 @@ SdCardSetRca (
return Status;
}
+/**
+ Send command SEND_CSD to the SD device to get the data of the CSD register.
+
+ Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
+
+ @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
+ @param[in] Slot The slot number of the SD card to send the command to.
+ @param[in] Rca The relative device address of selected device.
+ @param[out] Csd The buffer to store the content of the CSD register.
+ Note the caller should ignore the lowest byte of this
+ buffer as the content of this byte is meaningless even
+ if the operation succeeds.
+
+ @retval EFI_SUCCESS The operation is done correctly.
+ @retval Others The operation fails.
+
+**/
+EFI_STATUS
+SdCardGetCsd (
+ IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
+ IN UINT8 Slot,
+ IN UINT16 Rca,
+ OUT SD_CSD *Csd
+ )
+{
+ EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
+ EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
+ EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
+ EFI_STATUS Status;
+
+ ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
+ ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
+ ZeroMem (&Packet, sizeof (Packet));
+ Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
+ Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
+ Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;
+ SdMmcCmdBlk.CommandIndex = SD_SEND_CSD;
+ SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
+ SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;
+ SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
+ Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
+ if (!EFI_ERROR (Status)) {
+ //
+ // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
+ //
+ CopyMem (((UINT8*)Csd) + 1, &SdMmcStatusBlk.Resp0, sizeof (SD_CSD) - 1);
+ }
+
+ return Status;
+}
+
+/**
+ Send command SEND_CSD to the SD device to get the data of the CSD register.
+
+ Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
+
+ @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
+ @param[in] Slot The slot number of the SD card to send the command to.
+ @param[in] Rca The relative device address of selected device.
+ @param[out] Scr The buffer to store the content of the SCR register.
+
+ @retval EFI_SUCCESS The operation is done correctly.
+ @retval Others The operation fails.
+
+**/
+EFI_STATUS
+SdCardGetScr (
+ IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
+ IN UINT8 Slot,
+ IN UINT16 Rca,
+ OUT SD_SCR *Scr
+ )
+{
+ EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
+ EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
+ EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
+ EFI_STATUS Status;
+
+ ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
+ ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
+ ZeroMem (&Packet, sizeof (Packet));
+
+ Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
+ Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
+ Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;
+
+ SdMmcCmdBlk.CommandIndex = SD_APP_CMD;
+ SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
+ SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
+ SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
+
+ Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SdMmcCmdBlk.CommandIndex = SD_SEND_SCR;
+ SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;
+ SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
+
+ Packet.InDataBuffer = Scr;
+ Packet.InTransferLength = sizeof (SD_SCR);
+
+ Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
+
+ return Status;
+}
/**
Send command SELECT_DESELECT_CARD to the SD device to select/deselect it.
@@ -785,8 +891,8 @@ SdCardSetBusMode (
UINT8 BusWidth;
UINT8 AccessMode;
UINT8 HostCtrl1;
+ UINT8 HostCtrl2;
UINT8 SwitchResp[64];
- SD_MMC_BUS_MODE Timing;
SD_MMC_HC_PRIVATE_DATA *Private;
Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
@@ -818,23 +924,18 @@ SdCardSetBusMode (
if (S18A && (Capability->Sdr104 != 0) && ((SwitchResp[13] & BIT3) != 0)) {
ClockFreq = 208;
AccessMode = 3;
- Timing = SdMmcUhsSdr104;
} else if (S18A && (Capability->Sdr50 != 0) && ((SwitchResp[13] & BIT2) != 0)) {
ClockFreq = 100;
AccessMode = 2;
- Timing = SdMmcUhsSdr50;
} else if (S18A && (Capability->Ddr50 != 0) && ((SwitchResp[13] & BIT4) != 0)) {
ClockFreq = 50;
AccessMode = 4;
- Timing = SdMmcUhsDdr50;
} else if ((SwitchResp[13] & BIT1) != 0) {
ClockFreq = 50;
AccessMode = 1;
- Timing = SdMmcUhsSdr25;
} else {
ClockFreq = 25;
AccessMode = 0;
- Timing = SdMmcUhsSdr12;
}
Status = SdCardSwitch (PassThru, Slot, AccessMode, 0xF, 0xF, 0xF, TRUE, SwitchResp);
@@ -860,32 +961,20 @@ SdCardSetBusMode (
}
}
- Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);
+ HostCtrl2 = (UINT8)~0x7;
+ Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
if (EFI_ERROR (Status)) {
return Status;
}
-
- Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
+ HostCtrl2 = AccessMode;
+ Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
if (EFI_ERROR (Status)) {
return Status;
}
- if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
- Status = mOverride->NotifyPhase (
- Private->ControllerHandle,
- Slot,
- EdkiiSdMmcSwitchClockFreqPost,
- &Timing
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "%a: SD/MMC switch clock freq post notifier callback failed - %r\n",
- __FUNCTION__,
- Status
- ));
- return Status;
- }
+ Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, *Capability);
+ if (EFI_ERROR (Status)) {
+ return Status;
}
if ((AccessMode == 3) || ((AccessMode == 2) && (Capability->TuningSDR50 != 0))) {
@@ -996,10 +1085,9 @@ SdCardIdentification (
return Status;
}
- if (((ControllerVer & 0xFF) >= SD_MMC_HC_CTRL_VER_300) &&
- ((ControllerVer & 0xFF) <= SD_MMC_HC_CTRL_VER_420)) {
+ if (((ControllerVer & 0xFF) == 2) || ((ControllerVer & 0xFF) == 3)) {
S18r = TRUE;
- } else if (((ControllerVer & 0xFF) == SD_MMC_HC_CTRL_VER_100) || ((ControllerVer & 0xFF) == SD_MMC_HC_CTRL_VER_200)) {
+ } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {
S18r = FALSE;
} else {
ASSERT (FALSE);
@@ -1065,7 +1153,7 @@ SdCardIdentification (
goto Error;
}
- SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
+ SdMmcHcInitClockFreq (PciIo, Slot, Private->Capability[Slot]);
gBS->Stall (1000);
please check it!
Br,
Mike
From: Mike Li (WH)
Sent: 2019年1月23日 18:39
To: Mike Li (WH); Xiaoguang Yu (WH); Ernest Zhang(WH); Andy Dai (WH)
Cc: Shirley Her (SC); edk2-devel@lists.01.org
Subject: RE: [edk2] [patch_2] make EDK Driver Support BH720+EMMC chip
Hi, all
The following modifications are made to enable EDK Driver Support BH720 CHIP.
--- /c/yx/edk2/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c 2019-01-21 15:36:12.186739600 -0800
+++ /c/MyWorkspace/edk2-vUDK2018/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c 2019-01-10 14:34:23.072538900 -0800
@@ -1,7 +1,6 @@
/** @file
This file provides some helper functions which are specific for EMMC device.
- Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -527,17 +526,35 @@ EmmcTuningClkForHs200 (
if (EFI_ERROR (Status)) {
return Status;
}
+
+ if(BhtHostPciSupport(PciIo)){
+ //set data transfer with 4bit
+ Status = SdMmcHcSetBusWidth (PciIo, Slot, 4);
+ //enable hardware tuning
+ HostCtrl2 = (~0x10);
+ Status = SdMmcHcAndMmio (PciIo, Slot, 0x110,sizeof (HostCtrl2), &HostCtrl2);
+
+ Status = EmmcSendTuningBlk (PassThru, Slot, 4);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status));
+ return Status;
+ }
+
+ }
//
// Ask the device to send a sequence of tuning blocks till the tuning procedure is done.
//
Retry = 0;
do {
- Status = EmmcSendTuningBlk (PassThru, Slot, BusWidth);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status));
- return Status;
- }
-
+ if(!BhtHostPciSupport(PciIo)){
+ Status = EmmcSendTuningBlk (PassThru, Slot, BusWidth);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status));
+ return Status;
+ }
+ } else {
+ gBS->Stall(5000);
+ }
Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);
if (EFI_ERROR (Status)) {
return Status;
@@ -548,6 +565,10 @@ EmmcTuningClkForHs200 (
}
if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) {
+ if(BhtHostPciSupport(PciIo)){
+ //set data transfer with default
+ Status = SdMmcHcSetBusWidth (PciIo, Slot, BusWidth);
+ }
return EFI_SUCCESS;
}
} while (++Retry < 40);
@@ -652,7 +673,6 @@ EmmcSwitchBusWidth (
@param[in] Slot The slot number of the SD card to send the command to.
@param[in] Rca The relative device address to be assigned.
@param[in] HsTiming The value to be written to HS_TIMING field of EXT_CSD register.
- @param[in] Timing The bus mode timing indicator.
@param[in] ClockFreq The max clock frequency to be set, the unit is MHz.
@retval EFI_SUCCESS The operation is done correctly.
@@ -666,7 +686,6 @@ EmmcSwitchClockFreq (
IN UINT8 Slot,
IN UINT16 Rca,
IN UINT8 HsTiming,
- IN SD_MMC_BUS_MODE Timing,
IN UINT32 ClockFreq
)
{
@@ -708,28 +727,7 @@ EmmcSwitchClockFreq (
//
// Convert the clock freq unit from MHz to KHz.
//
- Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
- Status = mOverride->NotifyPhase (
- Private->ControllerHandle,
- Slot,
- EdkiiSdMmcSwitchClockFreqPost,
- &Timing
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "%a: SD/MMC switch clock freq post notifier callback failed - %r\n",
- __FUNCTION__,
- Status
- ));
- return Status;
- }
- }
+ Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->Capability[Slot]);
return Status;
}
@@ -764,13 +762,10 @@ EmmcSwitchToHighSpeed (
IN UINT8 BusWidth
)
{
- EFI_STATUS Status;
- UINT8 HsTiming;
- UINT8 HostCtrl1;
- SD_MMC_BUS_MODE Timing;
- SD_MMC_HC_PRIVATE_DATA *Private;
-
- Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
+ EFI_STATUS Status;
+ UINT8 HsTiming;
+ UINT8 HostCtrl1;
+ UINT8 HostCtrl2;
Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr, BusWidth);
if (EFI_ERROR (Status)) {
@@ -785,21 +780,31 @@ EmmcSwitchToHighSpeed (
return Status;
}
+ //
+ // Clean UHS Mode Select field of Host Control 2 reigster before update
+ //
+ HostCtrl2 = (UINT8)~0x7;
+ Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Set UHS Mode Select field of Host Control 2 reigster to SDR12/25/50
+ //
if (IsDdr) {
- Timing = SdMmcMmcHsDdr;
+ HostCtrl2 = BIT2;
} else if (ClockFreq == 52) {
- Timing = SdMmcMmcHsSdr;
+ HostCtrl2 = BIT0;
} else {
- Timing = SdMmcMmcLegacy;
+ HostCtrl2 = 0;
}
-
- Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);
+ Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
if (EFI_ERROR (Status)) {
return Status;
}
HsTiming = 1;
- Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
+ Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq);
return Status;
}
@@ -831,13 +836,10 @@ EmmcSwitchToHS200 (
IN UINT8 BusWidth
)
{
- EFI_STATUS Status;
- UINT8 HsTiming;
- UINT16 ClockCtrl;
- SD_MMC_BUS_MODE Timing;
- SD_MMC_HC_PRIVATE_DATA *Private;
-
- Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
+ EFI_STATUS Status;
+ UINT8 HsTiming;
+ UINT8 HostCtrl2;
+ UINT16 ClockCtrl;
if ((BusWidth != 4) && (BusWidth != 8)) {
return EFI_INVALID_PARAMETER;
@@ -857,29 +859,60 @@ EmmcSwitchToHS200 (
if (EFI_ERROR (Status)) {
return Status;
}
-
- Timing = SdMmcMmcHs200;
-
- Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);
+ //
+ // Clean UHS Mode Select field of Host Control 2 reigster before update
+ //
+ HostCtrl2 = (UINT8)~0x7;
+ Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Set UHS Mode Select field of Host Control 2 reigster to SDR104
+ //
+ HostCtrl2 = BIT0 | BIT1;
+ Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
if (EFI_ERROR (Status)) {
return Status;
}
-
//
// Wait Internal Clock Stable in the Clock Control register to be 1 before set SD Clock Enable bit
//
- Status = SdMmcHcWaitMmioSet (
- PciIo,
- Slot,
- SD_MMC_HC_CLOCK_CTRL,
- sizeof (ClockCtrl),
- BIT1,
- BIT1,
- SD_MMC_HC_GENERIC_TIMEOUT
+ if (BhtHostPciSupport(PciIo)) {
+ Status = SdMmcHcWaitMmioSet (
+ PciIo,
+ Slot,
+ 0x1cc,
+ sizeof (ClockCtrl),
+ BIT14,
+ BIT14,
+ SD_MMC_HC_GENERIC_TIMEOUT
+ );
+ }
+ else {
+ Status = SdMmcHcWaitMmioSet (
+ PciIo,
+ Slot,
+ SD_MMC_HC_CLOCK_CTRL,
+ sizeof (ClockCtrl),
+ BIT1,
+ BIT1,
+ SD_MMC_HC_GENERIC_TIMEOUT
);
+ }
if (EFI_ERROR (Status)) {
return Status;
}
+
+ if (BhtHostPciSupport(PciIo)){
+ //Wait 2nd Card Detect debounce Finished by wait twice of debounce max time
+ UINT32 value32;
+ while (1) {
+ Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof(value32), &value32);
+ if (((value32 >> 18) & 0x01) == ((value32 >> 16) & 0x01))
+ break;
+ }
+ }
//
// Set SD Clock Enable in the Clock Control register to 1
//
@@ -887,12 +920,33 @@ 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 = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq);
if (EFI_ERROR (Status)) {
return Status;
}
- Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusWidth);
+ if (BhtHostPciSupport(PciIo)){
+ Status = SdMmcHcWaitMmioSet (
+ PciIo,
+ Slot,
+ 0x1cc,
+ sizeof (ClockCtrl),
+ BIT11,
+ BIT11,
+ SD_MMC_CLOCK_STABLE_TIMEOUT
+ );
+ if (EFI_ERROR(Status)) {
+ DbgMsg(L"Wait Clock Stable timeout, ClockFreq=%d\n", ClockFreq);
+ return Status;
+ }
+ }
+
+ if (EFI_ERROR(Status)) {
+ DbgMsg(L"Emmc tuning failed\n");
+ return Status;
+ }
+
+
return Status;
}
@@ -922,12 +976,9 @@ EmmcSwitchToHS400 (
IN UINT32 ClockFreq
)
{
- EFI_STATUS Status;
- UINT8 HsTiming;
- SD_MMC_BUS_MODE Timing;
- SD_MMC_HC_PRIVATE_DATA *Private;
-
- Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
+ EFI_STATUS Status;
+ UINT8 HsTiming;
+ UINT8 HostCtrl2;
Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, 8);
if (EFI_ERROR (Status)) {
@@ -937,7 +988,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 = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, 52);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -948,16 +999,25 @@ EmmcSwitchToHS400 (
if (EFI_ERROR (Status)) {
return Status;
}
-
- Timing = SdMmcMmcHs400;
-
- Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);
+ //
+ // Clean UHS Mode Select field of Host Control 2 reigster before update
+ //
+ HostCtrl2 = (UINT8)~0x7;
+ Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Set UHS Mode Select field of Host Control 2 reigster to HS400
+ //
+ HostCtrl2 = BIT0 | BIT2;
+ Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
if (EFI_ERROR (Status)) {
return Status;
}
HsTiming = 3;
- Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
+ Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq);
return Status;
}
@@ -1008,7 +1068,7 @@ EmmcSetBusMode (
return Status;
}
- ASSERT (Private->BaseClkFreq[Slot] != 0);
+ ASSERT (Private->Capability[Slot].BaseClkFreq != 0);
//
// Check if the Host Controller support 8bits bus width.
//
@@ -1080,6 +1140,42 @@ EmmcSetBusMode (
// Execute HS200 timing switch procedure
//
Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, BusWidth);
+ if (EFI_ERROR(Status)) {
+ if (BhtHostPciSupport(PciIo)) {
+ UINT32 val32;
+ DbgMsg(L"switch to HS200 200MHZ failed, freq decrease to 100MHz\n");
+ ClockFreq = 100;
+
+ SdMmcHcRwMmio (PciIo, Slot, 0x3C, TRUE, sizeof(val32), &val32);
+ val32 &= ~BIT22;
+ SdMmcHcRwMmio (PciIo, Slot, 0x3C, FALSE, sizeof(val32), &val32);
+ val32 = (BIT26 | BIT25);
+ SdMmcHcOrMmio (PciIo, Slot, 0x2C, sizeof(val32), &val32);
+
+ Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, BusWidth);
+ if (EFI_ERROR(Status)) {
+ if (((ExtCsd.DeviceType & BIT1) != 0) && (Private->Capability[Slot].HighSpeed != 0)) {
+ DbgMsg(L"switch to HS200 100MHZ failed, mode decrease to HS 50MHz\n");
+
+ HsTiming = 1;
+ IsDdr = FALSE;
+ ClockFreq = 52;
+ Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca, ClockFreq, IsDdr, BusWidth);
+ }
+ else if (((ExtCsd.DeviceType & BIT0) != 0) && (Private->Capability[Slot].HighSpeed != 0)) {
+ DbgMsg(L"switch to HS200 100MHZ failed, mode decrease to HS 25MHz\n");
+
+ HsTiming = 1;
+ IsDdr = FALSE;
+ ClockFreq = 26;
+ Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca, ClockFreq, IsDdr, BusWidth);
+ }
+ else {
+ DbgMsg(L"switch to HS200 100MHZ failed, but emmc chip didn't support hs mode\n");
+ }
+ }
+ }
+ }
} else {
//
// Execute High Speed timing switch procedure
Please check it!
Br,
Mike
From: Mike Li (WH)
Sent: 2019年1月23日 17:29
To: Xiaoguang Yu (WH); Ernest Zhang(WH); Andy Dai (WH)
Cc: Shirley Her (SC); 'edk2-devel@lists.01.org'
Subject: [edk2] [patch_1] make EDK Driver Support BH720+EMMC chip
Hi, all
The following modifications are made to enable EDK Driver Support BH720 CHIP.
--- /c/MyWorkspace/edk2-vUDK2018/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c 2019-01-10 14:35:21.342736200 -0800
+++ /c/yx/edk2/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c 2019-01-21 15:36:12.195715300 -0800
@@ -4,6 +4,7 @@
It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use.
+ Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -16,8 +17,6 @@
**/
#include "SdMmcPciHcDxe.h"
-int g_deviceId = 0;
-
/**
Dump the content of SD/MMC host controller's Capability Register.
@@ -47,7 +46,8 @@ DumpCapabilityReg (
DEBUG ((DEBUG_INFO, " Voltage 3.3 %a\n", Capability->Voltage33 ? "TRUE" : "FALSE"));
DEBUG ((DEBUG_INFO, " Voltage 3.0 %a\n", Capability->Voltage30 ? "TRUE" : "FALSE"));
DEBUG ((DEBUG_INFO, " Voltage 1.8 %a\n", Capability->Voltage18 ? "TRUE" : "FALSE"));
- DEBUG ((DEBUG_INFO, " 64-bit Sys Bus %a\n", Capability->SysBus64 ? "TRUE" : "FALSE"));
+ DEBUG ((DEBUG_INFO, " V4 64-bit Sys Bus %a\n", Capability->SysBus64V4 ? "TRUE" : "FALSE"));
+ DEBUG ((DEBUG_INFO, " V3 64-bit Sys Bus %a\n", Capability->SysBus64V3 ? "TRUE" : "FALSE"));
DEBUG ((DEBUG_INFO, " Async Interrupt %a\n", Capability->AsyncInt ? "TRUE" : "FALSE"));
DEBUG ((DEBUG_INFO, " SlotType "));
if (Capability->SlotType == 0x00) {
@@ -419,9 +419,39 @@ SdMmcHcWaitMmioSet (
}
/**
+ Get the controller version information from the specified slot.
+
+ @param[in] PciIo The PCI IO protocol instance.
+ @param[in] Slot The slot number of the SD card to send the command to.
+ @param[out] Version The buffer to store the version information.
+
+ @retval EFI_SUCCESS The operation executes successfully.
+ @retval Others The operation fails.
+
+**/
+EFI_STATUS
+SdMmcHcGetControllerVersion (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT8 Slot,
+ OUT UINT16 *Version
+ )
+{
+ EFI_STATUS Status;
+
+ Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (UINT16), Version);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *Version &= 0xFF;
+
+ return EFI_SUCCESS;
+}
+
+/**
Software reset the specified SD/MMC host controller and enable all interrupts.
- @param[in] PciIo The PCI IO protocol instance.
+ @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
@param[in] Slot The slot number of the SD card to send the command to.
@retval EFI_SUCCESS The software reset executes successfully.
@@ -430,18 +460,38 @@ SdMmcHcWaitMmioSet (
**/
EFI_STATUS
SdMmcHcReset (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN SD_MMC_HC_PRIVATE_DATA *Private,
IN UINT8 Slot
)
{
EFI_STATUS Status;
UINT8 SwReset;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ //
+ // Notify the SD/MMC override protocol that we are about to reset
+ // the SD/MMC host controller.
+ //
+ if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
+ Status = mOverride->NotifyPhase (
+ Private->ControllerHandle,
+ Slot,
+ EdkiiSdMmcResetPre,
+ NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN,
+ "%a: SD/MMC pre reset notifier callback failed - %r\n",
+ __FUNCTION__, Status));
+ return Status;
+ }
+ }
- SwReset = 0xFF;
- Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_SW_RST, FALSE, sizeof (SwReset), &SwReset);
+ PciIo = Private->PciIo;
+ SwReset = BIT0;
+ Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_SW_RST, sizeof (SwReset), &SwReset);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "SdMmcHcReset: write full 1 fails: %r\n", Status));
+ DEBUG ((DEBUG_ERROR, "SdMmcHcReset: write SW Reset for All fails: %r\n", Status));
return Status;
}
@@ -450,7 +500,7 @@ SdMmcHcReset (
Slot,
SD_MMC_HC_SW_RST,
sizeof (SwReset),
- 0xFF,
+ BIT0,
0x00,
SD_MMC_HC_GENERIC_TIMEOUT
);
@@ -458,10 +508,33 @@ SdMmcHcReset (
DEBUG ((DEBUG_INFO, "SdMmcHcReset: reset done with %r\n", Status));
return Status;
}
+
//
// Enable all interrupt after reset all.
//
Status = SdMmcHcEnableInterrupt (PciIo, Slot);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "SdMmcHcReset: SdMmcHcEnableInterrupt done with %r\n",
+ Status));
+ return Status;
+ }
+
+ //
+ // Notify the SD/MMC override protocol that we have just reset
+ // the SD/MMC host controller.
+ //
+ if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
+ Status = mOverride->NotifyPhase (
+ Private->ControllerHandle,
+ Slot,
+ EdkiiSdMmcResetPost,
+ NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN,
+ "%a: SD/MMC post reset notifier callback failed - %r\n",
+ __FUNCTION__, Status));
+ }
+ }
return Status;
}
@@ -680,7 +753,8 @@ SdMmcHcStopClock (
@param[in] PciIo The PCI IO protocol instance.
@param[in] Slot The slot number of the SD card to send the command to.
@param[in] ClockFreq The max clock frequency to be set. The unit is KHz.
- @param[in] Capability The capability of the slot.
+ @param[in] BaseClkFreq The base clock frequency of host controller in MHz.
+ @param[in] ControllerVer The version of host controller.
@retval EFI_SUCCESS The clock is supplied successfully.
@retval Others The clock isn't supplied successfully.
@@ -691,23 +765,21 @@ SdMmcHcClockSupply (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT8 Slot,
IN UINT64 ClockFreq,
- IN SD_MMC_HC_SLOT_CAP Capability
+ IN UINT32 BaseClkFreq,
+ IN UINT16 ControllerVer
)
{
EFI_STATUS Status;
- UINT32 BaseClkFreq;
UINT32 SettingFreq;
UINT32 Divisor;
UINT32 Remainder;
- UINT16 ControllerVer;
UINT16 ClockCtrl;
//
// Calculate a divisor for SD clock frequency
//
- ASSERT (Capability.BaseClkFreq != 0);
+ ASSERT (BaseClkFreq != 0);
- BaseClkFreq = Capability.BaseClkFreq;
if (ClockFreq == 0) {
return EFI_INVALID_PARAMETER;
}
@@ -736,17 +808,15 @@ SdMmcHcClockSupply (
DEBUG ((DEBUG_INFO, "BaseClkFreq %dMHz Divisor %d ClockFreq %dKhz\n", BaseClkFreq, Divisor, ClockFreq));
- Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (ControllerVer), &ControllerVer);
- if (EFI_ERROR (Status)) {
- return Status;
- }
//
// Set SDCLK Frequency Select and Internal Clock Enable fields in Clock Control register.
//
- if (((ControllerVer & 0xFF) == 2) || ((ControllerVer & 0xFF) == 3)) {
+ if ((ControllerVer >= SD_MMC_HC_CTRL_VER_300) &&
+ (ControllerVer <= SD_MMC_HC_CTRL_VER_420)) {
ASSERT (Divisor <= 0x3FF);
ClockCtrl = ((Divisor & 0xFF) << 8) | ((Divisor & 0x300) >> 2);
- } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {
+ } else if ((ControllerVer == SD_MMC_HC_CTRL_VER_100) ||
+ (ControllerVer == SD_MMC_HC_CTRL_VER_200)) {
//
// Only the most significant bit can be used as divisor.
//
@@ -894,11 +964,62 @@ SdMmcHcSetBusWidth (
}
/**
- Supply SD/MMC card with lowest clock frequency at initialization.
+ Configure V4 controller enhancements at initialization.
@param[in] PciIo The PCI IO protocol instance.
@param[in] Slot The slot number of the SD card to send the command to.
@param[in] Capability The capability of the slot.
+ @param[in] ControllerVer The version of host controller.
+
+ @retval EFI_SUCCESS The clock is supplied successfully.
+
+**/
+EFI_STATUS
+SdMmcHcInitV4Enhancements (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT8 Slot,
+ IN SD_MMC_HC_SLOT_CAP Capability,
+ IN UINT16 ControllerVer
+ )
+{
+ EFI_STATUS Status;
+ UINT16 HostCtrl2;
+
+ //
+ // Check if controller version V4 or higher
+ //
+ if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
+ HostCtrl2 = SD_MMC_HC_V4_EN;
+ //
+ // Check if V4 64bit support is available
+ //
+ if (Capability.SysBus64V4 != 0) {
+ HostCtrl2 |= SD_MMC_HC_64_ADDR_EN;
+ DEBUG ((DEBUG_INFO, "Enabled V4 64 bit system bus support\n"));
+ }
+ //
+ // Check if controller version V4.10 or higher
+ //
+ if (ControllerVer >= SD_MMC_HC_CTRL_VER_410) {
+ HostCtrl2 |= SD_MMC_HC_26_DATA_LEN_ADMA_EN;
+ DEBUG ((DEBUG_INFO, "Enabled V4 26 bit data length ADMA support\n"));
+ }
+ Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Supply SD/MMC card with lowest clock frequency at initialization.
+
+ @param[in] PciIo The PCI IO protocol instance.
+ @param[in] Slot The slot number of the SD card to send the command to.
+ @param[in] BaseClkFreq The base clock frequency of host controller in MHz.
+ @param[in] ControllerVer The version of host controller.
@retval EFI_SUCCESS The clock is supplied successfully.
@retval Others The clock isn't supplied successfully.
@@ -908,16 +1029,20 @@ EFI_STATUS
SdMmcHcInitClockFreq (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT8 Slot,
- IN SD_MMC_HC_SLOT_CAP Capability
+ IN UINT32 BaseClkFreq,
+ IN UINT16 ControllerVer
)
{
EFI_STATUS Status;
UINT32 InitFreq;
//
- // Calculate a divisor for SD clock frequency
+ // According to SDHCI specification ver. 4.2, BaseClkFreq field value of
+ // the Capability Register 1 can be zero, which means a need for obtaining
+ // the clock frequency via another method. Fail in case it is not updated
+ // by SW at this point.
//
- if (Capability.BaseClkFreq == 0) {
+ if (BaseClkFreq == 0) {
//
// Don't support get Base Clock Frequency information via another method
//
@@ -927,7 +1052,7 @@ SdMmcHcInitClockFreq (
// Supply 400KHz clock frequency at initialization phase.
//
InitFreq = 400;
- Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, Capability);
+ Status = SdMmcHcClockSupply (PciIo, Slot, InitFreq, BaseClkFreq, ControllerVer);
return Status;
}
@@ -988,15 +1113,6 @@ SdMmcHcInitPowerVoltage (
// Set SD Bus Voltage Select and SD Bus Power fields in Power Control Register
//
Status = SdMmcHcPowerControl (PciIo, Slot, MaxVoltage);
- if (BhtHostPciSupport(PciIo)){
- // 1.8V signaling enable
- HostCtrl2 = BIT3;
- Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
- gBS->Stall (5000);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
return Status;
}
@@ -1032,9 +1148,8 @@ SdMmcHcInitTimeoutCtrl (
Initial SD/MMC host controller with lowest clock frequency, max power and max timeout value
at initialization.
- @param[in] PciIo The PCI IO protocol instance.
+ @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
@param[in] Slot The slot number of the SD card to send the command to.
- @param[in] Capability The capability of the slot.
@retval EFI_SUCCESS The host controller is initialized successfully.
@retval Others The host controller isn't initialized successfully.
@@ -1042,96 +1157,164 @@ SdMmcHcInitTimeoutCtrl (
**/
EFI_STATUS
SdMmcHcInitHost (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN UINT8 Slot,
- IN SD_MMC_HC_SLOT_CAP Capability
+ IN SD_MMC_HC_PRIVATE_DATA *Private,
+ IN UINT8 Slot
)
{
- EFI_STATUS Status;
- UINT32 value32;
-
- if (BhtHostPciSupport(PciIo)){
-
- DbgMsg(L"find bht emmc chip\n");
- /* FET on */
- PciBhtOr32(PciIo, 0xEC, 0x3);
- /* Led on */
- //PciBhtAnd32(PciIo, 0x334, (UINT32)~BIT13);
- PciBhtOr32(PciIo, 0xD4, BIT6);
- /* Set 1.8v emmc signaling flag */
- PciBhtOr32(PciIo, 0x308, BIT4);
- /* Set 200MBaseClock */
- value32 = PciBhtRead32(PciIo, 0x304);
- value32 &= 0x0000FFFF;
- value32 |= 0x25100000;
- PciBhtWrite32(PciIo, 0x304, value32);
- PciBhtOr32(PciIo, 0x3E4, BIT22);
- PciBhtWrite32(PciIo, 0x300, 0x21400033);
-
- //enable internal clk
- value32 = BIT0;
- Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL,sizeof(value32), &value32);
-
- //reset pll start
- Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32);
- value32 |= BIT12;
- Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32);
- gBS->Stall(1);
-
- //reset pll end
- Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE,sizeof(value32), &value32);
- value32 &= ~BIT12;
- value32 |= BIT18;
- Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32);
-
- //wait BaseClk stable 0x1CC bit14
- Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32);
- while(!(value32&BIT14)){
- gBS->Stall(100);
- Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32);
- DbgMsg(L"1CC=0x%08x\n", value32);
- }
-
- if (value32 & BIT18)
- {
- //Wait 2nd Card Detect debounce Finished by wait twice of debounce max time
- while (1) {
- Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof(value32), &value32);
- if (((value32 >> 16) & 0x01) == ((value32 >> 18) & 0x01))
- break;
- }
- //force pll active end
- Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32);
- value32 &= ~BIT18;
- Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32);
- }
-
- Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability);
- if (EFI_ERROR (Status)) {
- DbgMsg(L"emmc host init failure\n");
- return Status;
- }
-
-
- }
-
- Status = SdMmcHcInitClockFreq (PciIo, Slot, Capability);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (!BhtHostPciSupport(PciIo)){
- Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability);
- if (EFI_ERROR (Status)) {
- return Status;
- }
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ SD_MMC_HC_SLOT_CAP Capability;
+
+ //
+ // Notify the SD/MMC override protocol that we are about to initialize
+ // the SD/MMC host controller.
+ //
+ if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
+ Status = mOverride->NotifyPhase (
+ Private->ControllerHandle,
+ Slot,
+ EdkiiSdMmcInitHostPre,
+ NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN,
+ "%a: SD/MMC pre init notifier callback failed - %r\n",
+ __FUNCTION__, Status));
+ return Status;
+ }
+ }
+
+ PciIo = Private->PciIo;
+ Capability = Private->Capability[Slot];
+
+ Status = SdMmcHcInitV4Enhancements (PciIo, Slot, Capability, Private->ControllerVersion[Slot]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
+ if (EFI_ERROR (Status)) {
+ return Status;
}
-
+
+ Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
Status = SdMmcHcInitTimeoutCtrl (PciIo, Slot);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Notify the SD/MMC override protocol that we are have just initialized
+ // the SD/MMC host controller.
+ //
+ if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
+ Status = mOverride->NotifyPhase (
+ Private->ControllerHandle,
+ Slot,
+ EdkiiSdMmcInitHostPost,
+ NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN,
+ "%a: SD/MMC post init notifier callback failed - %r\n",
+ __FUNCTION__, Status));
+ }
+ }
return Status;
}
/**
+ Set SD Host Controler control 2 registry according to selected speed.
+
+ @param[in] ControllerHandle The handle of the controller.
+ @param[in] PciIo The PCI IO protocol instance.
+ @param[in] Slot The slot number of the SD card to send the command to.
+ @param[in] Timing The timing to select.
+
+ @retval EFI_SUCCESS The timing is set successfully.
+ @retval Others The timing isn't set successfully.
+**/
+EFI_STATUS
+SdMmcHcUhsSignaling (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT8 Slot,
+ IN SD_MMC_BUS_MODE Timing
+ )
+{
+ EFI_STATUS Status;
+ UINT8 HostCtrl2;
+
+ HostCtrl2 = (UINT8)~SD_MMC_HC_CTRL_UHS_MASK;
+ Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ switch (Timing) {
+ case SdMmcUhsSdr12:
+ HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR12;
+ break;
+ case SdMmcUhsSdr25:
+ HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR25;
+ break;
+ case SdMmcUhsSdr50:
+ HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR50;
+ break;
+ case SdMmcUhsSdr104:
+ HostCtrl2 = SD_MMC_HC_CTRL_UHS_SDR104;
+ break;
+ case SdMmcUhsDdr50:
+ HostCtrl2 = SD_MMC_HC_CTRL_UHS_DDR50;
+ break;
+ case SdMmcMmcLegacy:
+ HostCtrl2 = SD_MMC_HC_CTRL_MMC_LEGACY;
+ break;
+ case SdMmcMmcHsSdr:
+ HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS_SDR;
+ break;
+ case SdMmcMmcHsDdr:
+ HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS_DDR;
+ break;
+ case SdMmcMmcHs200:
+ HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS200;
+ break;
+ case SdMmcMmcHs400:
+ HostCtrl2 = SD_MMC_HC_CTRL_MMC_HS400;
+ break;
+ default:
+ HostCtrl2 = 0;
+ break;
+ }
+ Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
+ Status = mOverride->NotifyPhase (
+ ControllerHandle,
+ Slot,
+ EdkiiSdMmcUhsSignaling,
+ &Timing
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: SD/MMC uhs signaling notifier callback failed - %r\n",
+ __FUNCTION__,
+ Status
+ ));
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
Turn on/off LED.
@param[in] PciIo The PCI IO protocol instance.
@@ -1166,9 +1349,10 @@ SdMmcHcLedOnOff (
/**
Build ADMA descriptor table for transfer.
- Refer to SD Host Controller Simplified spec 3.0 Section 1.13 for details.
+ Refer to SD Host Controller Simplified spec 4.2 Section 1.13 for details.
@param[in] Trb The pointer to the SD_MMC_HC_TRB instance.
+ @param[in] ControllerVer The version of host controller.
@retval EFI_SUCCESS The ADMA descriptor table is created successfully.
@retval Others The ADMA descriptor table isn't created successfully.
@@ -1176,7 +1360,8 @@ SdMmcHcLedOnOff (
**/
EFI_STATUS
BuildAdmaDescTable (
- IN SD_MMC_HC_TRB *Trb
+ IN SD_MMC_HC_TRB *Trb,
+ IN UINT16 ControllerVer
)
{
EFI_PHYSICAL_ADDRESS Data;
@@ -1184,49 +1369,93 @@ BuildAdmaDescTable (
UINT64 Entries;
UINT32 Index;
UINT64 Remaining;
- UINT32 Address;
+ UINT64 Address;
UINTN TableSize;
EFI_PCI_IO_PROTOCOL *PciIo;
EFI_STATUS Status;
UINTN Bytes;
+ BOOLEAN AddressingMode64;
+ BOOLEAN DataLength26;
+ UINT32 AdmaMaxDataPerLine;
+ UINT32 DescSize;
+ VOID *AdmaDesc;
+
+ AddressingMode64 = FALSE;
+ DataLength26 = FALSE;
+ AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_16B;
+ DescSize = sizeof (SD_MMC_HC_ADMA_32_DESC_LINE);
+ AdmaDesc = NULL;
Data = Trb->DataPhy;
DataLen = Trb->DataLen;
PciIo = Trb->Private->PciIo;
+
//
- // Only support 32bit ADMA Descriptor Table
+ // Detect whether 64bit addressing is supported.
//
- if ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul)) {
+ if (ControllerVer >= SD_MMC_HC_CTRL_VER_400) {
+ Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
+ SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
+ if (!EFI_ERROR (Status)) {
+ AddressingMode64 = TRUE;
+ DescSize = sizeof (SD_MMC_HC_ADMA_64_DESC_LINE);
+ }
+ }
+ //
+ // Check for valid ranges in 32bit ADMA Descriptor Table
+ //
+ if (!AddressingMode64 &&
+ ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul))) {
return EFI_INVALID_PARAMETER;
}
//
- // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to 0)
- // for 32-bit address descriptor table.
+ // Check address field alignment
//
- if ((Data & (BIT0 | BIT1)) != 0) {
- DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data));
+ if (AddressingMode64) {
+ //
+ // Address field shall be set on 64-bit boundary (Lower 3-bit is always set to 0)
+ //
+ if ((Data & (BIT0 | BIT1 | BIT2)) != 0) {
+ DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 8 bytes boundary!\n", Data));
+ }
+ } else {
+ //
+ // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to 0)
+ //
+ if ((Data & (BIT0 | BIT1)) != 0) {
+ DEBUG ((DEBUG_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data));
+ }
+ }
+ //
+ // Detect whether 26bit data length is supported.
+ //
+ Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
+ SD_MMC_HC_26_DATA_LEN_ADMA_EN, SD_MMC_HC_26_DATA_LEN_ADMA_EN);
+ if (!EFI_ERROR (Status)) {
+ DataLength26 = TRUE;
+ AdmaMaxDataPerLine = ADMA_MAX_DATA_PER_LINE_26B;
}
- Entries = DivU64x32 ((DataLen + ADMA_MAX_DATA_PER_LINE - 1), ADMA_MAX_DATA_PER_LINE);
- TableSize = (UINTN)MultU64x32 (Entries, sizeof (SD_MMC_HC_ADMA_DESC_LINE));
+ Entries = DivU64x32 ((DataLen + AdmaMaxDataPerLine - 1), AdmaMaxDataPerLine);
+ TableSize = (UINTN)MultU64x32 (Entries, DescSize);
Trb->AdmaPages = (UINT32)EFI_SIZE_TO_PAGES (TableSize);
Status = PciIo->AllocateBuffer (
PciIo,
AllocateAnyPages,
EfiBootServicesData,
EFI_SIZE_TO_PAGES (TableSize),
- (VOID **)&Trb->AdmaDesc,
+ (VOID **)&AdmaDesc,
0
);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
- ZeroMem (Trb->AdmaDesc, TableSize);
+ ZeroMem (AdmaDesc, TableSize);
Bytes = TableSize;
Status = PciIo->Map (
PciIo,
EfiPciIoOperationBusMasterCommonBuffer,
- Trb->AdmaDesc,
+ AdmaDesc,
&Bytes,
&Trb->AdmaDescPhy,
&Trb->AdmaMap
@@ -1239,12 +1468,13 @@ BuildAdmaDescTable (
PciIo->FreeBuffer (
PciIo,
EFI_SIZE_TO_PAGES (TableSize),
- Trb->AdmaDesc
+ AdmaDesc
);
return EFI_OUT_OF_RESOURCES;
}
- if ((UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
+ if ((!AddressingMode64) &&
+ (UINT64)(UINTN)Trb->AdmaDescPhy > 0x100000000ul) {
//
// The ADMA doesn't support 64bit addressing.
//
@@ -1255,35 +1485,71 @@ BuildAdmaDescTable (
PciIo->FreeBuffer (
PciIo,
EFI_SIZE_TO_PAGES (TableSize),
- Trb->AdmaDesc
+ AdmaDesc
);
return EFI_DEVICE_ERROR;
}
Remaining = DataLen;
- Address = (UINT32)Data;
+ Address = Data;
+ if (!AddressingMode64) {
+ Trb->Adma32Desc = AdmaDesc;
+ Trb->Adma64Desc = NULL;
+ } else {
+ Trb->Adma64Desc = AdmaDesc;
+ Trb->Adma32Desc = NULL;
+ }
for (Index = 0; Index < Entries; Index++) {
- if (Remaining <= ADMA_MAX_DATA_PER_LINE) {
- Trb->AdmaDesc[Index].Valid = 1;
- Trb->AdmaDesc[Index].Act = 2;
- Trb->AdmaDesc[Index].Length = (UINT16)Remaining;
- Trb->AdmaDesc[Index].Address = Address;
- break;
+ if (!AddressingMode64) {
+ if (Remaining <= AdmaMaxDataPerLine) {
+ Trb->Adma32Desc[Index].Valid = 1;
+ Trb->Adma32Desc[Index].Act = 2;
+ if (DataLength26) {
+ Trb->Adma32Desc[Index].UpperLength = (UINT16)RShiftU64 (Remaining, 16);
+ }
+ Trb->Adma32Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16);
+ Trb->Adma32Desc[Index].Address = (UINT32)Address;
+ break;
+ } else {
+ Trb->Adma32Desc[Index].Valid = 1;
+ Trb->Adma32Desc[Index].Act = 2;
+ if (DataLength26) {
+ Trb->Adma32Desc[Index].UpperLength = 0;
+ }
+ Trb->Adma32Desc[Index].LowerLength = 0;
+ Trb->Adma32Desc[Index].Address = (UINT32)Address;
+ }
} else {
- Trb->AdmaDesc[Index].Valid = 1;
- Trb->AdmaDesc[Index].Act = 2;
- Trb->AdmaDesc[Index].Length = 0;
- Trb->AdmaDesc[Index].Address = Address;
+ if (Remaining <= AdmaMaxDataPerLine) {
+ Trb->Adma64Desc[Index].Valid = 1;
+ Trb->Adma64Desc[Index].Act = 2;
+ if (DataLength26) {
+ Trb->Adma64Desc[Index].UpperLength = (UINT16)RShiftU64 (Remaining, 16);
+ }
+ Trb->Adma64Desc[Index].LowerLength = (UINT16)(Remaining & MAX_UINT16);
+ Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
+ Trb->Adma64Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);
+ break;
+ } else {
+ Trb->Adma64Desc[Index].Valid = 1;
+ Trb->Adma64Desc[Index].Act = 2;
+ if (DataLength26) {
+ Trb->Adma64Desc[Index].UpperLength = 0;
+ }
+ Trb->Adma64Desc[Index].LowerLength = 0;
+ Trb->Adma64Desc[Index].LowerAddress = (UINT32)Address;
+ Trb->Adma64Desc[Index].UpperAddress = (UINT32)RShiftU64 (Address, 32);
+ }
}
- Remaining -= ADMA_MAX_DATA_PER_LINE;
- Address += ADMA_MAX_DATA_PER_LINE;
+ Remaining -= AdmaMaxDataPerLine;
+ Address += AdmaMaxDataPerLine;
}
//
// Set the last descriptor line as end of descriptor table
//
- Trb->AdmaDesc[Index].End = 1;
+ AddressingMode64 ? (Trb->Adma64Desc[Index].End = 1) : (Trb->Adma32Desc[Index].End = 1);
return EFI_SUCCESS;
}
@@ -1381,7 +1647,7 @@ SdMmcCreateTrb (
Trb->Mode = SdMmcNoData;
} else if (Private->Capability[Slot].Adma2 != 0) {
Trb->Mode = SdMmcAdmaMode;
- Status = BuildAdmaDescTable (Trb);
+ Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);
if (EFI_ERROR (Status)) {
PciIo->Unmap (PciIo, Trb->DataMap);
goto Error;
@@ -1427,11 +1693,18 @@ SdMmcFreeTrb (
Trb->AdmaMap
);
}
- if (Trb->AdmaDesc != NULL) {
+ if (Trb->Adma32Desc != NULL) {
+ PciIo->FreeBuffer (
+ PciIo,
+ Trb->AdmaPages,
+ Trb->Adma32Desc
+ );
+ }
+ if (Trb->Adma64Desc != NULL) {
PciIo->FreeBuffer (
PciIo,
Trb->AdmaPages,
- Trb->AdmaDesc
+ Trb->Adma64Desc
);
}
if (Trb->DataMap != NULL) {
@@ -1571,12 +1844,15 @@ SdMmcExecTrb (
UINT16 Cmd;
UINT16 IntStatus;
UINT32 Argument;
- UINT16 BlkCount;
+ UINT32 BlkCount;
UINT16 BlkSize;
UINT16 TransMode;
UINT8 HostCtrl1;
- UINT32 SdmaAddr;
+ UINT64 SdmaAddr;
UINT64 AdmaAddr;
+ BOOLEAN AddressingMode64;
+
+ AddressingMode64 = FALSE;
Packet = Trb->Packet;
PciIo = Trb->Private->PciIo;
@@ -1609,13 +1885,28 @@ SdMmcExecTrb (
SdMmcHcLedOnOff (PciIo, Trb->Slot, TRUE);
+ if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {
+ Status = SdMmcHcCheckMmioSet(PciIo, Trb->Slot, SD_MMC_HC_HOST_CTRL2, sizeof(UINT16),
+ SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN, SD_MMC_HC_V4_EN|SD_MMC_HC_64_ADDR_EN);
+ if (!EFI_ERROR (Status)) {
+ AddressingMode64 = TRUE;
+ }
+ }
+
if (Trb->Mode == SdMmcSdmaMode) {
- if ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul) {
+ if ((!AddressingMode64) &&
+ ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul)) {
return EFI_INVALID_PARAMETER;
}
- SdmaAddr = (UINT32)(UINTN)Trb->DataPhy;
- Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (SdmaAddr), &SdmaAddr);
+ SdmaAddr = (UINT64)(UINTN)Trb->DataPhy;
+
+ if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {
+ Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (UINT64), &SdmaAddr);
+ } else {
+ Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &SdmaAddr);
+ }
+
if (EFI_ERROR (Status)) {
return Status;
}
@@ -1645,9 +1936,13 @@ SdMmcExecTrb (
//
// Calcuate Block Count.
//
- BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);
+ BlkCount = (Trb->DataLen / Trb->BlockSize);
+ }
+ if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_410) {
+ Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_SDMA_ADDR, FALSE, sizeof (UINT32), &BlkCount);
+ } else {
+ Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (UINT16), &BlkCount);
}
- Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -1743,7 +2038,7 @@ SdMmcCheckTrbResult (
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
UINT16 IntStatus;
UINT32 Response[4];
- UINT32 SdmaAddr;
+ UINT64 SdmaAddr;
UINT8 Index;
UINT8 SwReset;
UINT32 PioLength;
@@ -1867,8 +2162,19 @@ SdMmcCheckTrbResult (
//
// Update SDMA Address register.
//
- SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINT32)(UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY);
- Status = SdMmcHcRwMmio (
+ SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY);
+
+ if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {
+ Status = SdMmcHcRwMmio (
+ Private->PciIo,
+ Trb->Slot,
+ SD_MMC_HC_ADMA_SYS_ADDR,
+ FALSE,
+ sizeof (UINT64),
+ &SdmaAddr
+ );
+ } else {
+ Status = SdMmcHcRwMmio (
Private->PciIo,
Trb->Slot,
SD_MMC_HC_SDMA_ADDR,
@@ -1876,10 +2182,12 @@ SdMmcCheckTrbResult (
sizeof (UINT32),
&SdmaAddr
);
+ }
+
if (EFI_ERROR (Status)) {
goto Done;
}
- Trb->DataPhy = (UINT32)(UINTN)SdmaAddr;
+ Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;
}
if ((Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeAdtc) &&
@@ -2000,281 +2308,3 @@ SdMmcWaitTrbResult (
return EFI_TIMEOUT;
}
-BOOLEAN BhtHostPciSupport(EFI_PCI_IO_PROTOCOL *PciIo)
-{
- PCI_TYPE00 Pci;
-
- PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32,
- 0, sizeof Pci / sizeof (UINT32), &Pci);
-
- DEBUG ((DEBUG_INFO, "check device %04x:%04x\n", Pci.Hdr.VendorId, Pci.Hdr.DeviceId));
-
- if (Pci.Hdr.VendorId != 0x1217)
- goto end;
-
- switch (Pci.Hdr.DeviceId)
- {
- case 0x8420: //PCI_DEV_ID_SDS0
- case 0x8421: //PCI_DEV_ID_SDS1
- case 0x8520: //PCI_DEV_ID_FJ2
- case 0x8620: //PCI_DEV_ID_SB0
- case 0x8621: //PCI_DEV_ID_SB1
- g_deviceId = Pci.Hdr.DeviceId;
- return 1;
- default:
- break;
- }
-
- end:
- return 0;
-}
-
-void DbgNull(IN CONST CHAR16 * fmt, ...)
-{
-}
-
-UINT32 bht_readl(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset)
-{
- UINT32 arg;
- PciIo->Mem.Read(PciIo,EfiPciIoWidthUint32,1,offset,1,&arg);
- return arg;
-}
-
-void bht_writel(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value)
-{
- PciIo->Mem.Write(PciIo,EfiPciIoWidthUint32,1,offset,1,&value);
-}
-
-
-UINT32 PciBhtRead32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset)
-{
- UINT32 i = 0;
- UINT32 tmp[3] = {0};
-
- if((g_deviceId == PCI_DEV_ID_SDS0) ||
- (g_deviceId == PCI_DEV_ID_SDS1) ||
- (g_deviceId == PCI_DEV_ID_FJ2) ||
- (g_deviceId == PCI_DEV_ID_SB0) ||
- (g_deviceId == PCI_DEV_ID_SB1))
- {
- // For Sandstorm, HW implement a mapping method by memory space reg to access PCI reg.
- // Enable mapping
-
- // Check function conflict
- if((g_deviceId == PCI_DEV_ID_SDS0) ||
- (g_deviceId == PCI_DEV_ID_FJ2) ||
- (g_deviceId == PCI_DEV_ID_SB0) ||
- (g_deviceId == PCI_DEV_ID_SB1))
- {
- i = 0;
- bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000);
- while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x40000000) == 0)
- {
- if(i == 5)
- {
- //DbgMsg((DRIVERNAME " - %s() function 0 can't lock!\n", __FUNCTION__));
- goto RD_DIS_MAPPING;
- }
- gBS->Stall(1000);
- i++;
- bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000);
-
- }
- }
- else if(g_deviceId == PCI_DEV_ID_SDS1)
- {
- i = 0;
- bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000);
- while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x20000000) == 0)
- {
- if(i == 5)
- {
- //DbgErr((DRIVERNAME " - %s() function 1 can't lock!\n", __FUNCTION__));
- goto RD_DIS_MAPPING;
- }
- gBS->Stall(1000);
- i++;
- bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000);
- }
- }
-
- // Check last operation is complete
- i = 0;
- while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000)
- {
- if(i == 5)
- {
- //DbgErr((DRIVERNAME " - [204] = 0x%x\n", RegisterRead32(ELN_dPCIRMappingCtl)));
- //DbgErr((DRIVERNAME " - [208] = 0x%x\n", RegisterRead32(ELN_dPCIRMappingEn)));
- //DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__));
- goto RD_DIS_MAPPING;
- }
- gBS->Stall(1000);
- i += 1;
- }
-
- // Set register address
- tmp[0] |= 0x40000000;
- tmp[0] |= offset;
- bht_writel(PciIo, BHT_PCIRMappingCtl, tmp[0]);
-
- // Check read is complete
- i = 0;
- while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0x40000000)
- {
- if(i == 5)
- {
- //DbgErr((DRIVERNAME " - %s() check read operation complete timeout!!!\n", __FUNCTION__));
- goto RD_DIS_MAPPING;
- }
- gBS->Stall(1000);
- i += 1;
- }
-
- // Get PCIR value
- tmp[1] = bht_readl(PciIo, BHT_PCIRMappingVal);
-
-RD_DIS_MAPPING:
- // Disable mapping
- bht_writel(PciIo, BHT_PCIRMappingEn, 0x80000000);
-
- //DbgDebug(L"%s offset=%x Value:%x\n", __FUNCTION__, offset, tmp[1]);
- return tmp[1];
- }
-
- //DbgDebug(L"%s offset=%x Value:%x\n", __FUNCTION__, offset, tmp[0]);
- return tmp[0];
-}
-
-void PciBhtWrite32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value)
-{
- UINT32 tmp = 0;
- UINT32 i = 0;
-
- if((g_deviceId == PCI_DEV_ID_SDS0) ||
- (g_deviceId == PCI_DEV_ID_SDS1) ||
- (g_deviceId == PCI_DEV_ID_FJ2) ||
- (g_deviceId == PCI_DEV_ID_SB0) ||
- (g_deviceId == PCI_DEV_ID_SB1))
- {
- // For Sandstorm, HW implement a mapping method by memory space reg to access PCI reg.
- // Upper caller doesn't need to set 0xD0.
-
- // Enable mapping
-
- // Check function conflict
- if((g_deviceId == PCI_DEV_ID_SDS0) ||
- (g_deviceId == PCI_DEV_ID_FJ2) ||
- (g_deviceId == PCI_DEV_ID_SB0) ||
- (g_deviceId == PCI_DEV_ID_SB1))
- {
- i = 0;
- bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000);
- while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x40000000) == 0)
- {
- if(i == 5)
- {
- //DbgErr((DRIVERNAME " - %s() function 0 can't lock!\n", __FUNCTION__));
- goto WR_DIS_MAPPING;
- }
-
- gBS->Stall(1000);
- i++;
- bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000);
- }
- }
- else if(g_deviceId == PCI_DEV_ID_SDS1)
- {
- i = 0;
- bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000);
-
- while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x20000000) == 0)
- {
- if(i == 5)
- {
- //DbgErr((DRIVERNAME " - %s() function 0 can't lock!\n", __FUNCTION__));
- goto WR_DIS_MAPPING;
- }
-
- gBS->Stall(1000);
- i++;
- bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000);
- }
- }
-
- // Enable MEM access
- bht_writel(PciIo, BHT_PCIRMappingVal, 0x80000000);
- bht_writel(PciIo, BHT_PCIRMappingCtl, 0x800000D0);
-
- // Check last operation is complete
- i = 0;
- while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000)
- {
- if(i == 5)
- {
- //DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__));
- goto WR_DIS_MAPPING;
- }
- gBS->Stall(1000);
- i += 1;
- }
-
- // Set write value
- bht_writel(PciIo, BHT_PCIRMappingVal, value);
- // Set register address
- tmp |= 0x80000000;
- tmp |= offset;
- bht_writel(PciIo, BHT_PCIRMappingCtl, tmp);
-
- // Check write is complete
- i = 0;
- while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0x80000000)
- {
- if(i == 5)
- {
- //DbgErr((DRIVERNAME " - %s() check write operation complete timeout!!!\n", __FUNCTION__));
- goto WR_DIS_MAPPING;
- }
- gBS->Stall(1000);
- i += 1;
- }
-
-WR_DIS_MAPPING:
- // Disable MEM access
- bht_writel(PciIo, BHT_PCIRMappingVal, 0x80000001);
- bht_writel(PciIo, BHT_PCIRMappingCtl, 0x800000D0);
-
- // Check last operation is complete
- i = 0;
- while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000)
- {
- if(i == 5)
- {
- //DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__));
- break;
- }
- gBS->Stall(1000);
- i += 1;
- }
-
- // Disable function conflict
-
- // Disable mapping
- bht_writel(PciIo, BHT_PCIRMappingEn, 0x80000000);
- }
-}
-
-void PciBhtOr32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value)
-{
- UINT32 arg;
- arg = PciBhtRead32(PciIo, offset);
- PciBhtWrite32(PciIo, offset, value | arg);
-}
-
-void PciBhtAnd32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value)
-{
- UINT32 arg;
- arg = PciBhtRead32(PciIo, offset);
- PciBhtWrite32(PciIo, offset, value & arg);
-}
-
Please check it!
Br,
Mike
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2019-01-23 10:45 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-01-23 10:39 [patch_2] make EDK Driver Support BH720+EMMC chip Mike Li (WH)
2019-01-23 10:45 ` [patch_3] " Mike Li (WH)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox