Compare commits

...

17 Commits

Author SHA1 Message Date
860a8d95c2 CorebootPayloadPkg: don't set PcdDebugPropertyMask for release builds
Don't set PcdDebugPropertyMask for release builds, and properly set it
for debug builds based on SOURCE_DEBUG_ENABLE.

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2020-03-17 15:59:54 -05:00
6105116c48 EmuVariable: only read/write Bootorder variables
Tianocore currently reads/writes a lot of NVRAM variables that
don't actually need to be saved. Occasionally some, specifically
related to the graphical/serial consoles, can become corrupted,
leading to a bricked device. To avoid this, temporarily restrict
the reading/writing of variables to Bootorder related ones
(starting with 'Boot') until a better solution can be found.

Test: build/boot google/eve, inject "bad" NVRAM data, observe
device boots normally instead of hanging with no display detected.

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2020-03-17 15:59:38 -05:00
77ddbd2deb s76-smmstore: update compiled driver
update compiled driver with one that doesn't hang on systems
built without CONFIG_SMMSTORE=y in coreboot.

Test: build/boot google/kahlee with and w.o SMMSTORE enabled

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2020-03-03 22:38:38 -06:00
f15ac4583b MdeModulePkg/SdMmcPciHcDxe: add Bayhub support
Add support for Bayhub eMMC controller found on AMD
Stoneyridge Chromebooks.

Test: build/boot various google/kahlee-based devices

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2020-03-01 13:27:11 -06:00
daa1f83b55 Add/use System76 firmware-smmstore driver
Add/use System76 firmware-smmstore driver, to compact
the smmstore NVRAM variables. Helps prevent corruption
of NVRAM variables leading to boot hang.

Compiled from system76/firmware-smmstore commit 2e94590

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2020-03-01 13:26:06 -06:00
1b66efff52 EmuVariable: enable deletion of variables
Make it possible to delete a variable by appending it with
size 0. Also ignore keysizes of 0 when reading variables.

Signed-off-by: Jeremy Soller <jeremy@system76.com>
Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2020-03-01 13:26:06 -06:00
4f60b6a439 BdsPlatform: generate SMM events to put eMMC/SD in proper mode
For Baytrail devices, coreboot leaves the eMMC/SD in PCI mode to enable
detection by Tianocore, so put into ACPI mode before OS boots.
Fixes booting on Baytrail devices.

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2020-03-01 13:25:59 -06:00
64f7b0fdba Merge pull request #8 from PatrickRudolph/fix_smm_detect
MdeModulePkg/Universal/Variable/EmuRuntimeDxe: Check SMM store return…
2020-01-08 16:10:14 -06:00
359e78336d MdeModulePkg/Universal/Variable/EmuRuntimeDxe: Check SMM store return codes
Check SMM store return code and return on error.

Fixes significant boot delay in case no SMM store is present.
This can happend quite often if the tianocore payload is build standalone
and patched into a coreboot ROM.

Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
2020-01-08 13:22:57 +01:00
81f6f9c8e8 Frontpage: add entries for Stoneyridge Chromebooks
Add entries for Aleena, Barla, Careena, Kasumi, Liara.
Remove unused entry for Purism Librem 13v2 since not a
Google device.

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2019-12-28 12:44:08 -06:00
b98c44e412 MdeModulePkg/Usb/Keyboard: add SetIdle quirk handler
Some USB keyboards, like the Aspeed BMC HID keyboard,
require the SetIdle command to be issued before interrupt
transfers can be enabled. Add a quirk handler so any similar
devices can make use of same function by the addition of the
USB vendor/device IDs.

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2019-12-17 22:57:51 -06:00
f1d5f1091d MdeModulePkg/Usb/Keyboard.c: don't request protocol before setting
No need to check the interface protocol then conditionally setting,
just set it to BOOT_PROTOCOL and check for error.

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2019-12-17 22:56:30 -06:00
2719881a54 MdeModulePkg/Usb/Keyboard.c: remove Get/SetConfig calls
SetConfig is already called during device enumeration,
no need to do it again here.

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2019-12-17 22:50:56 -06:00
115ed8d16d Prioritize Udf and ElTorito partition types over Mbr to fix ISO boots 2019-12-16 16:24:41 -06:00
8681de13a9 Frontpage: add entry for CAROLINE
Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2019-12-13 16:00:50 -06:00
1f726fc0cf MdeModulePkg/Usb/UsbMouse: Fix endpoint selection
The endpoint selected by the driver needs to not
only be an interrupt type, but have direction IN
as required to set up an asynchronous interrupt transfer.

Currently, the driver assumes that the first INT endpoint
will be of type IN, but that is not true of all devices,
and will silently fail on devices which have the OUT endpoint
before the IN. Adjust the endpoint selection loop to explictly
check for direction IN.

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2019-12-12 13:40:46 -06:00
6943792307 MdeModulePkg/Usb/EfiKey: Fix endpoint selection
The endpoint selected by the driver needs to not
only be an interrupt type, but have direction IN
as required to set up an asynchronous interrupt transfer.

Currently, the driver assumes that the first INT endpoint
will be of type IN, but that is not true of all devices,
and will silently fail on devices which have the OUT endpoint
before the IN. Adjust the endpoint selection loop to explictly
check for direction IN.

Test: detachable keyboard on Google Pixel Slate now works.

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2019-12-12 13:40:35 -06:00
20 changed files with 964 additions and 108 deletions

View File

@ -1265,6 +1265,11 @@ Returns:
Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 20000000);
ASSERT (Status == EFI_SUCCESS);
//
// invoke SMM handler to put eMMC/SD devices into ACPI mode for OS
//
IoWrite8(0xb2, 0xcd);
//
// To give the User a chance to enter Setup here, if user set TimeOut is 0.
// BDS should still give user a chance to enter Setup

View File

@ -42,6 +42,7 @@ Abstract:
#include <Library/UefiLib.h>
#include <Library/DxeServicesTableLib.h>
#include <Library/DevicePathLib.h>
#include <Library/IoLib.h>
#include <Protocol/PciIo.h>

View File

@ -110,6 +110,10 @@ INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
INF MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
!if $(ARCH) == IA32
!else
INF RuleOverride=BINARY USE = X64 CorebootPayloadPkg/s76-smmstore/s76-smmstore.inf
!endif
INF MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf

View File

@ -293,10 +293,12 @@
[PcdsPatchableInModule.common]
gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x7
gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F
!if $(SOURCE_DEBUG_ENABLE)
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
!else
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F
!if $(TARGET) == DEBUG
!if $(SOURCE_DEBUG_ENABLE)
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
!else
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2B
!endif
!endif
#

View File

@ -294,10 +294,12 @@
[PcdsPatchableInModule.common]
gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x7
gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F
!if $(SOURCE_DEBUG_ENABLE)
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
!else
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F
!if $(TARGET) == DEBUG
!if $(SOURCE_DEBUG_ENABLE)
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
!else
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2B
!endif
!endif
#

Binary file not shown.

View File

@ -0,0 +1,9 @@
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = system76-firmware-smmstore
FILE_GUID = 764f0f8d-658b-4d32-a057-b44fb209512c
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
[Binaries.X64]
PE32|s76-smmstore.efi|*

View File

@ -737,6 +737,8 @@ GetDeviceNameFromProduct (
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 13");
} else if (!StrCmp(Product, L"Akali 360")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 13");
} else if (!StrCmp(Product, L"Aleena")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 315");
} else if (!StrCmp(Product, L"Atlas")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Google Pixelbook Go 2019");
} else if (!StrCmp(Product, L"Auron")) {
@ -751,12 +753,18 @@ GetDeviceNameFromProduct (
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 15 CB5-532");
} else if (!StrCmp(Product, L"Bard")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 715");
} else if (!StrCmp(Product, L"Barla")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 11A G6 EE");
} else if (!StrCmp(Product, L"Buddy")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebase 24");
} else if (!StrCmp(Product, L"Butterfly")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Pavilion Chromebook 14");
} else if (!StrCmp(Product, L"Candy")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 11 3120");
} else if (!StrCmp(Product, L"Careena")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 14");
} else if (!StrCmp(Product, L"Caroline")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Samsung Chromebook Pro");
} else if (!StrCmp(Product, L"Cave")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook Flip C302");
} else if (!StrCmp(Product, L"Celes")) {
@ -787,6 +795,8 @@ GetDeviceNameFromProduct (
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"AMD StonyRidge Chromebook");
} else if (!StrCmp(Product, L"Guado")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebox 2 / CN62");
} else if (!StrCmp(Product, L"Kasumi")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 311");
} else if (!StrCmp(Product, L"Kefka")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 11 3180/3189");
} else if (!StrCmp(Product, L"Kench")) {
@ -797,8 +807,8 @@ GetDeviceNameFromProduct (
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 14 for Work");
} else if (!StrCmp(Product, L"Leon")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Toshiba Chromebook");
} else if (!StrCmp(Product, L"Librem 13 v2")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Purism Librem 13 v2");
} else if (!StrCmp(Product, L"Liara")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo 14e Chromebook");
} else if (!StrCmp(Product, L"Lulu")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 13 7310");
} else if (!StrCmp(Product, L"Link")) {

210
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c Executable file → Normal file
View File

@ -526,15 +526,34 @@ EmmcTuningClkForHs200 (
if (EFI_ERROR (Status)) {
return Status;
}
if(BhtHostPciSupport(PciIo)) {
//set data transfer with 4bit
Status = SdMmcHcSetBusWidth (PciIo, Slot, 4);
//enable hardware tuning
HostCtrl2 = (UINT8)(~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);
@ -547,6 +566,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);
@ -770,10 +793,21 @@ EmmcSwitchToHighSpeed (
Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
DbgMsg("switch to HS mode %dMHz\n", ClockFreq);
Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr, BusWidth);
if (EFI_ERROR (Status)) {
return Status;
}
if (BhtHostPciSupport(PciIo)) {
HsTiming = 1;
Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// Set to Hight Speed timing
//
@ -796,8 +830,10 @@ EmmcSwitchToHighSpeed (
return Status;
}
HsTiming = 1;
Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
if (!BhtHostPciSupport(PciIo)) {
HsTiming = 1;
Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
}
return Status;
}
@ -837,6 +873,8 @@ EmmcSwitchToHS200 (
Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
DbgMsg("switch to HS200 mode %dMHz\n", ClockFreq);
if ((BusWidth != 4) && (BusWidth != 8)) {
return EFI_INVALID_PARAMETER;
}
@ -845,6 +883,15 @@ EmmcSwitchToHS200 (
if (EFI_ERROR (Status)) {
return Status;
}
if (BhtHostPciSupport(PciIo)){
HsTiming = 2;
Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// Set to HS200/SDR104 timing
//
@ -866,31 +913,73 @@ EmmcSwitchToHS200 (
//
// 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
//
ClockCtrl = BIT2;
Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl);
HsTiming = 2;
Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
if (EFI_ERROR (Status)) {
return Status;
if (!BhtHostPciSupport(PciIo)) {
HsTiming = 2;
Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
if (EFI_ERROR (Status)) {
return Status;
}
} else {
Status = SdMmcHcWaitMmioSet (
PciIo,
Slot,
0x1cc,
sizeof (ClockCtrl),
BIT11,
BIT11,
SD_MMC_CLOCK_STABLE_TIMEOUT
);
if (EFI_ERROR(Status)) {
DbgMsg("Wait Clock Stable timeout, ClockFreq=%d\n", ClockFreq);
return Status;
}
}
Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusWidth);
if (EFI_ERROR(Status)) {
DbgMsg("Emmc tuning failed\n");
}
return Status;
}
@ -1068,6 +1157,37 @@ EmmcSetBusMode (
DEBUG ((DEBUG_INFO, "EmmcSetBusMode: HsTiming %d ClockFreq %d BusWidth %d Ddr %a\n", HsTiming, ClockFreq, BusWidth, IsDdr ? "TRUE":"FALSE"));
if (BhtHostPciSupport(PciIo)) {
UINT8 EmmcVar;
UINTN EmmcVarSize;
Status = gRT->GetVariable (
L"EMMC_FORCE_CARD_MODE",
&gEfiGenericVariableGuid,
NULL,
&EmmcVarSize,
&EmmcVar
);
if (!EFI_ERROR(Status) && EmmcVar <= 2) {
if (EmmcVar == 2) {
HsTiming = 2;
IsDdr = FALSE;
ClockFreq = 200;
} else if (EmmcVar == 1) {
HsTiming = 2;
IsDdr = FALSE;
ClockFreq = 100;
} else {
HsTiming = 1;
IsDdr = FALSE;
ClockFreq = 52;
}
} else {
HsTiming = 1;
IsDdr = FALSE;
ClockFreq = 52;
}
}
if (HsTiming == 3) {
//
// Execute HS400 timing switch procedure
@ -1078,6 +1198,60 @@ EmmcSetBusMode (
// Execute HS200 timing switch procedure
//
Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, BusWidth);
if (EFI_ERROR(Status)) {
if (BhtHostPciSupport(PciIo)) {
UINT32 val32;
UINT16 EmmcVar;
UINTN EmmcVarSize;
DbgMsg("switch to HS200 200MHZ failed, freq decrease to 100MHz\n");
#if !defined(HS100_ALLPASS_PHASE) || HS100_ALLPASS_PHASE > 10 || HS100_ALLPASS_PHASE < 0
#error "HS100_ALLPASS_PHASE is undefined or value is invalid"
#else
val32 = PciBhtRead32(PciIo, 0x300);
val32 &= 0xFF0FFFFF;
EmmcVarSize = sizeof(EmmcVar);
Status = gRT->GetVariable (
L"EMMC_HS100_ALLPASS_PHASE",
&gEfiGenericVariableGuid,
NULL,
&EmmcVarSize,
&EmmcVar
);
if (EFI_ERROR(Status) || EmmcVar > 10)
EmmcVar = HS100_ALLPASS_PHASE;
val32 |= (EmmcVar << 20);
PciBhtWrite32(PciIo, 0x300, 0x21000033 | val32);
#endif
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("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("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("switch to HS200 100MHZ failed, but emmc chip didn't support hs mode\n");
}
}
}
}
} else {
//
// Execute High Speed timing switch procedure

View File

@ -295,6 +295,13 @@ SdMmcPciHcEnumerateDevice (
continue;
}
if (BhtHostPciSupport(Private->PciIo)) {
Status = SdMmcHcGetCapability (Private->PciIo, Slot, &Private->Capability[Slot]);
if (EFI_ERROR (Status)) {
continue;
}
}
Private->Slot[Slot].MediaPresent = TRUE;
Private->Slot[Slot].Initialized = TRUE;
RoutineNum = sizeof (mCardTypeDetectRoutineTable) / sizeof (CARD_TYPE_DETECT_ROUTINE);
@ -311,6 +318,7 @@ SdMmcPciHcEnumerateDevice (
// This card doesn't get initialized correctly.
//
if (Index == RoutineNum) {
DEBUG ((DEBUG_INFO, "Load driver failure\n"));
Private->Slot[Slot].Initialized = FALSE;
}
@ -530,6 +538,8 @@ SdMmcPciHcDriverBindingStart (
UINT32 RoutineNum;
BOOLEAN MediaPresent;
BOOLEAN Support64BitDma;
UINT16 IntStatus;
UINT32 value;
DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStart: Start\n"));
@ -685,6 +695,13 @@ SdMmcPciHcDriverBindingStart (
continue;
}
if (BhtHostPciSupport(PciIo)) {
Status = SdMmcHcGetCapability (PciIo, Slot, &Private->Capability[Slot]);
if (EFI_ERROR (Status)) {
continue;
}
}
Private->Slot[Slot].MediaPresent = TRUE;
Private->Slot[Slot].Initialized = TRUE;
RoutineNum = sizeof (mCardTypeDetectRoutineTable) / sizeof (CARD_TYPE_DETECT_ROUTINE);
@ -701,9 +718,52 @@ SdMmcPciHcDriverBindingStart (
// This card doesn't get initialized correctly.
//
if (Index == RoutineNum) {
DEBUG ((DEBUG_INFO, "Load driver failure\n"));
Private->Slot[Slot].Initialized = FALSE;
}
}
if (BhtHostPciSupport(Private->PciIo)) {
DbgMsg("HOST_CLK_DRIVE_STRENGTH: 0x%x\n",HOST_CLK_DRIVE_STRENGTH);
DbgMsg("HOST_DAT_DRIVE_STRENGTH: 0x%x\n",HOST_DAT_DRIVE_STRENGTH);
DbgMsg("HS200_ALLPASS_PHASE: 0x%x\n",HS200_ALLPASS_PHASE);
DbgMsg("HS100_ALLPASS_PHASE: 0x%x\n",HS100_ALLPASS_PHASE);
SdMmcHcRwMmio (Private->PciIo,0,0x110,TRUE,sizeof (value),&value);
DbgMsg("0x110: 0x%x\n",value);
SdMmcHcRwMmio (Private->PciIo,0,0x114,TRUE,sizeof (value),&value);
DbgMsg("0x114: 0x%x\n",value);
SdMmcHcRwMmio (Private->PciIo,0,0x1a8,TRUE,sizeof (value),&value);
DbgMsg("MEM 1A8: 0x%x\n",value);
SdMmcHcRwMmio (Private->PciIo,0,0x1ac,TRUE,sizeof (value),&value);
DbgMsg("MEM 1AC: 0x%x\n",value);
SdMmcHcRwMmio (Private->PciIo,0,0x1B0,TRUE,sizeof (value),&value);
DbgMsg("MEM 1B0: 0x%x\n",value);
SdMmcHcRwMmio (Private->PciIo,0,0x1CC,TRUE,sizeof (value),&value);
DbgMsg("MEM 1CC: 0x%x\n",value);
DbgMsg(" - pcr 0x300 = 0x%08x\n", PciBhtRead32(Private->PciIo, 0x300));
DbgMsg(" - pcr 0x304 = 0x%08x\n", PciBhtRead32(Private->PciIo, 0x304));
DbgMsg(" - pcr 0x328 = 0x%08x\n", PciBhtRead32(Private->PciIo, 0x328));
DbgMsg(" - pcr 0x3e4 = 0x%08x\n", PciBhtRead32(Private->PciIo, 0x3e4));
SdMmcHcRwMmio (Private->PciIo,0,0x040,TRUE,sizeof (value),&value);
DbgMsg("0x40: 0x%x\n",value);
SdMmcHcRwMmio (Private->PciIo,0,SD_MMC_HC_PRESENT_STATE,TRUE,sizeof (value),&value);
DbgMsg("Present State: 0x%x\n",value);
SdMmcHcRwMmio (Private->PciIo,0,SD_MMC_HC_HOST_CTRL1,TRUE,sizeof (IntStatus),&IntStatus);
DbgMsg("Power&Host1: 0x%x\n",IntStatus);
SdMmcHcRwMmio (Private->PciIo,0,SD_MMC_HC_CLOCK_CTRL,TRUE,sizeof (IntStatus),&IntStatus);
DbgMsg("CLK: 0x%x\n",IntStatus);
SdMmcHcRwMmio (Private->PciIo,0,SD_MMC_HC_TIMEOUT_CTRL,TRUE,sizeof (IntStatus),&IntStatus);
DbgMsg("SWR&Timeout: 0x%x\n",IntStatus);
SdMmcHcRwMmio (Private->PciIo,0,SD_MMC_HC_NOR_INT_STS,TRUE,sizeof (value),&value);
DbgMsg("INR&IER: 0x%x\n",value);
SdMmcHcRwMmio (Private->PciIo,0,SD_MMC_HC_HOST_CTRL2,TRUE,sizeof (IntStatus),&IntStatus);
DbgMsg("Host2: 0x%x\n",IntStatus);
}
//
// Enable 64-bit DMA support in the PCI layer if this controller

View File

@ -25,6 +25,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/UefiDriverEntryPoint.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiLib.h>
@ -38,6 +39,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/SdMmcOverride.h>
#include <Protocol/SdMmcPassThru.h>
#include <Guid/DebugMask.h>
#include "SdMmcPciHci.h"
extern EFI_COMPONENT_NAME_PROTOCOL gSdMmcPciHcComponentName;
@ -51,10 +54,16 @@ extern EDKII_SD_MMC_OVERRIDE *mOverride;
#define SD_MMC_HC_PRIVATE_FROM_THIS(a) \
CR(a, SD_MMC_HC_PRIVATE_DATA, PassThru, SD_MMC_HC_PRIVATE_SIGNATURE)
#define HOST_CLK_DRIVE_STRENGTH 2
#define HOST_DAT_DRIVE_STRENGTH 2
#define HS200_ALLPASS_PHASE 0
#define HS100_ALLPASS_PHASE 6
//
// Generic time out value, 1 microsecond as unit.
//
#define SD_MMC_HC_GENERIC_TIMEOUT 1 * 1000 * 1000
#define SD_MMC_CLOCK_STABLE_TIMEOUT 3 * 1000
//
// SD/MMC async transfer timer interval, set by experience.

View File

@ -18,12 +18,12 @@
##
[Defines]
INF_VERSION = 0x00010005
INF_VERSION = 0x00010007
BASE_NAME = SdMmcPciHcDxe
MODULE_UNI_FILE = SdMmcPciHcDxe.uni
FILE_GUID = 8E325979-3FE1-4927-AAE2-8F5C4BD2AF0D
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
VERSION_STRING = 1.5.4
ENTRY_POINT = InitializeSdMmcPciHcDxe
#
@ -67,6 +67,9 @@
gEfiPciIoProtocolGuid ## TO_START
gEfiSdMmcPassThruProtocolGuid ## BY_START
[Guids]
gEfiGenericVariableGuid
# [Event]
# EVENT_TYPE_PERIODIC_TIMER ## SOMETIMES_CONSUMES

View File

@ -17,6 +17,9 @@
#include "SdMmcPciHcDxe.h"
int g_deviceId = 0;
/**
Dump the content of SD/MMC host controller's Capability Register.
@ -1031,6 +1034,15 @@ 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;
}
@ -1082,6 +1094,7 @@ SdMmcHcInitHost (
EFI_STATUS Status;
EFI_PCI_IO_PROTOCOL *PciIo;
SD_MMC_HC_SLOT_CAP Capability;
UINT32 value32;
//
// Notify the SD/MMC override protocol that we are about to initialize
@ -1104,14 +1117,199 @@ SdMmcHcInitHost (
PciIo = Private->PciIo;
Capability = Private->Capability[Slot];
if (BhtHostPciSupport(PciIo)){
UINT8 CardMode;
UINT16 EmmcVar;
UINTN EmmcVarSize;
UINT64 Cap;
DbgMsg("find bht emmc chip\n");
//unlock PCR write protect
#ifdef DISABLE_L1_2
PciBhtAnd32(PciIo, 0xd0, ~(BIT31));
PciBhtAnd32(PciIo, 0x90, ~(BIT1 | BIT0));
value32 = PciBhtRead32(PciIo, 0xe0);
value32 &= ~(BIT31 | BIT30 | BIT29 | BIT28);
value32 |= (BIT29 | BIT28);
PciBhtWrite32(PciIo, 0xe0, value32);
value32 = PciBhtRead32(PciIo, 0xfc);
value32 &= ~(BIT19 | BIT18 | BIT17 | BIT16);
value32 |= (BIT19);
PciBhtWrite32(PciIo, 0xfc, value32);
value32 = PciBhtRead32(PciIo, 0x3f4);
value32 &= ~(BIT3 | BIT2 | BIT1 | BIT0);
value32 |= (BIT3 | BIT1);
PciBhtWrite32(PciIo, 0x3f4, value32);
value32 = PciBhtRead32(PciIo, 0x248);
value32 &= ~(BIT3 | BIT2 | BIT1 | BIT0);
value32 |= (BIT3 | BIT1);
PciBhtWrite32(PciIo, 0x248, value32);
value32 = PciBhtRead32(PciIo, 0x90);
value32 &= ~(BIT1 | BIT0);
value32 |= (BIT1);
PciBhtWrite32(PciIo, 0x90, value32);
#endif
/* 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;
#if !defined(HOST_CLK_DRIVE_STRENGTH) || HOST_CLK_DRIVE_STRENGTH > 7 || HOST_CLK_DRIVE_STRENGTH < 0
#error "HOST_CMD_DRIVE_STRENGTH is undefined or value is invalid"
#else
EmmcVarSize = sizeof(EmmcVar);
Status = gRT->GetVariable (
L"EMMC_CLK_DRIVER_STRENGTH",
&gEfiGenericVariableGuid,
NULL,
&EmmcVarSize,
&EmmcVar
);
if (EFI_ERROR(Status))
EmmcVar = HOST_CLK_DRIVE_STRENGTH;
value32 &= 0xFFFFFF8F;
value32 |= ((EmmcVar & 0x7) << 4);
#endif
#if !defined(HOST_DAT_DRIVE_STRENGTH) || HOST_DAT_DRIVE_STRENGTH > 7 || HOST_DAT_DRIVE_STRENGTH < 0
#error "HOST_DATA_DRIVE_STRENGTH is undefined or value is invalid"
#else
EmmcVarSize = sizeof(EmmcVar);
Status = gRT->GetVariable (
L"EMMC_DATA_DRIVER_STRENGTH",
&gEfiGenericVariableGuid,
NULL,
&EmmcVarSize,
&EmmcVar
);
if (EFI_ERROR(Status))
EmmcVar = HOST_DAT_DRIVE_STRENGTH;
value32 &= 0xFFFFFFF1;
value32 |= ((EmmcVar & 0x7) << 1);
#endif
PciBhtWrite32(PciIo, 0x304, value32);
PciBhtOr32(PciIo, 0x3E4, BIT22);
EmmcVarSize = sizeof(CardMode);
Status = gRT->GetVariable (
L"EMMC_FORCE_CARD_MODE",
&gEfiGenericVariableGuid,
NULL,
&EmmcVarSize,
&CardMode
);
if (EFI_ERROR(Status) || CardMode > 2) {
CardMode = 0;
}
if (CardMode == 1) {
#if !defined(HS100_ALLPASS_PHASE) || HS100_ALLPASS_PHASE > 10 || HS100_ALLPASS_PHASE < 0
#error "HS200_ALLPASS_PHASE is undefined or value is invalid"
#else
EmmcVarSize = sizeof(EmmcVar);
Status = gRT->GetVariable (
L"EMMC_HS100_ALLPASS_PHASE",
&gEfiGenericVariableGuid,
NULL,
&EmmcVarSize,
&EmmcVar
);
if (EFI_ERROR(Status) || EmmcVar > 10)
EmmcVar = HS100_ALLPASS_PHASE;
#endif
} else if (CardMode == 2) {
#if !defined(HS200_ALLPASS_PHASE) || HS200_ALLPASS_PHASE > 10 || HS200_ALLPASS_PHASE < 0
#error "HS200_ALLPASS_PHASE is undefined or value is invalid"
#else
EmmcVarSize = sizeof(EmmcVar);
Status = gRT->GetVariable (
L"EMMC_HS200_ALLPASS_PHASE",
&gEfiGenericVariableGuid,
NULL,
&EmmcVarSize,
&EmmcVar
);
if (EFI_ERROR(Status) || EmmcVar > 10)
EmmcVar = HS200_ALLPASS_PHASE;
}
#endif
value32 = 0x21000033 | (EmmcVar << 20);
PciBhtWrite32(PciIo, 0x300, value32);
//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("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 = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CAP, TRUE, sizeof (Cap), &Cap);
if (EFI_ERROR (Status)) {
return Status;
}
CopyMem (&Capability, &Cap, sizeof (Cap));
Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability);
if (EFI_ERROR (Status)) {
DbgMsg("emmc host init failure\n");
return Status;
}
}
Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot]);
if (EFI_ERROR (Status)) {
return Status;
}
Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability);
if (EFI_ERROR (Status)) {
return Status;
if (!BhtHostPciSupport(PciIo)){
Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability);
if (EFI_ERROR (Status)) {
return Status;
}
}
Status = SdMmcHcInitTimeoutCtrl (PciIo, Slot);
@ -2096,3 +2294,280 @@ 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);
}

View File

@ -552,4 +552,42 @@ SdMmcHcUhsSignaling (
IN SD_MMC_BUS_MODE Timing
);
BOOLEAN
BhtHostPciSupport(EFI_PCI_IO_PROTOCOL *PciIo);
UINT32
PciBhtRead32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset);
void
PciBhtWrite32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value);
void
PciBhtOr32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value);
void
PciBhtAnd32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value);
extern void
DbgNull(IN CONST CHAR16 * fmt, ...);
#if(0)
#define DbgMsg(arg, ...) Print(L##arg, __VA_ARGS__)
#else
#define DbgMsg(...) DEBUG((DEBUG_INFO, __VA_ARGS__))
#endif
#define PCI_DEV_ID_RJ 0x8320
#define PCI_DEV_ID_SDS0 0x8420
#define PCI_DEV_ID_SDS1 0x8421
#define PCI_DEV_ID_FJ2 0x8520
#define PCI_DEV_ID_SB0 0x8620
#define PCI_DEV_ID_SB1 0x8621
// O2/BHT add BAR1 for PCIR mapping registers
// These registers is defined by O2/BHT, but we may follow name definition rule.
#define BHT_PCIRMappingVal (0x200) /* PCI CFG Space Register Mapping Value Register */
#define BHT_PCIRMappingCtl (0x204) /* PCI CFG Space Register Mapping Control Register */
#define BHT_PCIRMappingEn (0x208) /* PCI CFG Space Register Mapping Enable Register */
#define BHT_GPIOCTL (0x210) /* GPIO control register*/
#endif

View File

@ -221,7 +221,7 @@ USBKeyboardDriverBindingStart (
EndpointNumber = UsbKeyboardDevice->InterfaceDescriptor.NumEndpoints;
//
// Traverse endpoints to find interrupt endpoint
// Traverse endpoints to find interrupt endpoint IN
//
Found = FALSE;
for (Index = 0; Index < EndpointNumber; Index++) {
@ -232,7 +232,8 @@ USBKeyboardDriverBindingStart (
&EndpointDescriptor
);
if ((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) {
if ((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT &&
(EndpointDescriptor.EndpointAddress & USB_ENDPOINT_DIR_IN) ) {
//
// We only care interrupt endpoint here
//

View File

@ -793,6 +793,29 @@ InitKeyboardLayout (
}
/**
Determine if SetIdle request is needed
@param DevDesc The EFI_USB_DEVICE_DESCRIPTOR instance.
@retval TRUE The USB device requires SetIdle to be called.
@retval FALSE The USB device does not require SetIdle to be called.
**/
BOOLEAN
UsbQuirkRequireSetIdle (
IN EFI_USB_DEVICE_DESCRIPTOR DevDesc
)
{
switch (DevDesc.IdVendor) {
case 0x0557:
return DevDesc.IdProduct == 0x2419;
default:
return FALSE;
}
}
/**
Initialize USB keyboard device and all private data structures.
@ -807,10 +830,8 @@ InitUSBKeyboard (
IN OUT USB_KB_DEV *UsbKeyboardDevice
)
{
UINT16 ConfigValue;
UINT8 Protocol;
EFI_STATUS Status;
UINT32 TransferResult;
EFI_STATUS Status;
EFI_USB_DEVICE_DESCRIPTOR DevDesc;
REPORT_STATUS_CODE_WITH_DEVICE_PATH (
EFI_PROGRESS_CODE,
@ -823,55 +844,38 @@ InitUSBKeyboard (
InitQueue (&UsbKeyboardDevice->EfiKeyQueueForNotify, sizeof (EFI_KEY_DATA));
//
// Use the config out of the descriptor
// Assumed the first config is the correct one and this is not always the case
// Get device descriptor so vendor/device IDs available
// for quirk handling
//
Status = UsbGetConfiguration (
Status = UsbKeyboardDevice->UsbIo->UsbGetDeviceDescriptor (
UsbKeyboardDevice->UsbIo,
&ConfigValue,
&TransferResult
);
&DevDesc);
if (EFI_ERROR (Status)) {
ConfigValue = 0x01;
//
// Uses default configuration to configure the USB Keyboard device.
//
Status = UsbSetConfiguration (
UsbKeyboardDevice->UsbIo,
ConfigValue,
&TransferResult
);
if (EFI_ERROR (Status)) {
//
// If configuration could not be set here, it means
// the keyboard interface has some errors and could
// not be initialized
//
REPORT_STATUS_CODE_WITH_DEVICE_PATH (
EFI_ERROR_CODE | EFI_ERROR_MINOR,
(EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INTERFACE_ERROR),
UsbKeyboardDevice->DevicePath
);
return EFI_DEVICE_ERROR;
}
return EFI_DEVICE_ERROR;
}
UsbGetProtocolRequest (
UsbKeyboardDevice->UsbIo,
UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
&Protocol
);
//
// Set boot protocol for the USB Keyboard.
// This driver only supports boot protocol.
//
if (Protocol != BOOT_PROTOCOL) {
UsbSetProtocolRequest (
UsbKeyboardDevice->UsbIo,
UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
BOOT_PROTOCOL
Status = UsbSetProtocolRequest (
UsbKeyboardDevice->UsbIo,
UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
BOOT_PROTOCOL
);
if (EFI_ERROR (Status)) {
//
// If protocol could not be set here, it means
// the keyboard interface has some errors and could
// not be initialized
//
REPORT_STATUS_CODE_WITH_DEVICE_PATH (
EFI_ERROR_CODE | EFI_ERROR_MINOR,
(EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INTERFACE_ERROR),
UsbKeyboardDevice->DevicePath
);
return EFI_DEVICE_ERROR;
}
UsbKeyboardDevice->CtrlOn = FALSE;
@ -896,6 +900,16 @@ InitUSBKeyboard (
UsbKeyboardDevice->CurrentNsKey = NULL;
//
// Some keyboards don't send interrupt transfers until SetIdle is called
//
if (UsbQuirkRequireSetIdle(DevDesc)) {
UsbSetIdleRequest(UsbKeyboardDevice->UsbIo,
UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
0,
0);
}
//
// Sync the initial state of lights on keyboard.
//

View File

@ -329,4 +329,18 @@ InitializeKeyState (
OUT EFI_KEY_STATE *KeyState
);
/**
Determine if SetIdle request is needed
@param DevDesc The EFI_USB_DEVICE_DESCRIPTOR instance.
@retval TRUE The USB device requires SetIdle to be called.
@retval FALSE The USB device does not require SetIdle to be called.
**/
BOOLEAN
UsbQuirkRequireSetIdle (
IN EFI_USB_DEVICE_DESCRIPTOR DevDesc
);
#endif

View File

@ -209,7 +209,7 @@ USBMouseDriverBindingStart (
EndpointNumber = UsbMouseDevice->InterfaceDescriptor.NumEndpoints;
//
// Traverse endpoints to find interrupt endpoint
// Traverse endpoints to find interrupt endpoint IN
//
Found = FALSE;
for (Index = 0; Index < EndpointNumber; Index++) {
@ -219,7 +219,8 @@ USBMouseDriverBindingStart (
&EndpointDescriptor
);
if ((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) {
if ((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT &&
(EndpointDescriptor.EndpointAddress & USB_ENDPOINT_DIR_IN) ) {
//
// We only care interrupt endpoint here
//

View File

@ -44,8 +44,8 @@ EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding = {
//
PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable[] = {
PartitionInstallGptChildHandles,
PartitionInstallMbrChildHandles,
PartitionInstallUdfChildHandles,
PartitionInstallMbrChildHandles,
NULL
};

View File

@ -944,6 +944,8 @@ UpdateVariable (
UINTN VarSize;
VARIABLE_GLOBAL *Global;
UINTN NonVolatileVarableStoreSize;
UINT32 Result;
BOOLEAN Delete = FALSE;
Global = &mVariableModuleGlobal->VariableGlobal[Physical];
@ -976,10 +978,8 @@ UpdateVariable (
// specified causes it to be deleted.
//
if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {
Variable->CurrPtr->State &= VAR_DELETED;
UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, FALSE, TRUE, FALSE);
Status = EFI_SUCCESS;
goto Done;
DataSize = 0;
Delete = TRUE;
}
//
@ -989,8 +989,12 @@ UpdateVariable (
if (Variable->CurrPtr->DataSize == DataSize &&
CompareMem (Data, GetVariableDataPtr (Variable->CurrPtr), DataSize) == 0
) {
Status = EFI_SUCCESS;
goto Done;
if (Delete) {
goto Update;
} else {
Status = EFI_SUCCESS;
goto Done;
}
} else if (Variable->CurrPtr->State == VAR_ADDED) {
//
// Mark the old variable as in delete transition
@ -1032,6 +1036,10 @@ UpdateVariable (
VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize);
VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize);
if (Delete) {
goto Store;
}
if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {
NonVolatileVarableStoreSize = ((VARIABLE_STORE_HEADER *)(UINTN)(Global->NonVolatileVariableBase))->Size;
if ((((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0)
@ -1089,7 +1097,17 @@ UpdateVariable (
DataSize
);
if (storeInitialized && ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0)) {
Store:
// If the store is initialized
// And we are storing or deleting a non volatile variable
// And variable name starts with 'Boot'
// Send the new data to SMMSTORE
if (storeInitialized && (
(Attributes & EFI_VARIABLE_NON_VOLATILE) != 0 || (
Delete &&
(Variable->CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0
)) && (!StrnCmp(L"Boot", VariableName, StrLen(L"Boot")))
) {
/* TODO: add hook for logging nv changes here */
@ -1108,7 +1126,10 @@ UpdateVariable (
CopyMem (keydata + sizeof (EFI_GUID), VariableName, VarNameSize);
CopyMem (valdata, Data, DataSize);
call_smm(SMMSTORE_APM_CNT, SMMSTORE_CMD_APPEND, (UINT32)rt_buffer_phys);
Result = call_smm(SMMSTORE_APM_CNT, SMMSTORE_CMD_APPEND, (UINT32)rt_buffer_phys);
if (Result != SMMSTORE_RET_SUCCESS) {
return EFI_DEVICE_ERROR;
}
/* call into SMM through EFI_ISA_IO_PROTOCOL to write to 0xb2:
* set registers (how?)
* UINT8 Data = ...;
@ -1116,6 +1137,7 @@ UpdateVariable (
*/
}
Update:
//
// Mark the old variable as deleted
//
@ -1123,7 +1145,11 @@ UpdateVariable (
Variable->CurrPtr->State &= VAR_DELETED;
}
UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE);
if (Delete) {
UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, FALSE, TRUE, FALSE);
} else {
UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE);
}
Status = EFI_SUCCESS;
@ -1875,7 +1901,7 @@ VariableCommonInitialize (
)
{
EFI_STATUS Status;
UINT32 Result;
//
// Allocate memory for mVariableModuleGlobal
//
@ -1928,14 +1954,18 @@ VariableCommonInitialize (
.bufsize = sizeof(buf),
};
ASSERT((UINTN)&read_cmd <= 0x100000000 - sizeof(read_cmd));
call_smm(SMMSTORE_APM_CNT, SMMSTORE_CMD_READ, (UINT32)(UINTN)&read_cmd);
Result = call_smm(SMMSTORE_APM_CNT, SMMSTORE_CMD_READ, (UINT32)(UINTN)&read_cmd);
if (Result != SMMSTORE_RET_SUCCESS) {
// The SMM store hasn't been compiled in. There's nothing we can do.
return EFI_SUCCESS;
}
DEBUG ((DEBUG_WARN, "Initialize buffer from 0x%x bytes of flash\n", read_cmd.bufsize));
int i = 0;
while (i < read_cmd.bufsize) {
// assume native endian
UINT32 keysz = ((UINT32 *)(buf + i))[0];
if (keysz == 0xffffffff)
if (keysz == 0 || keysz == 0xffffffff)
break; // no more entries
UINTN valsz = ((UINT32 *)(buf + i))[1];
@ -1949,23 +1979,27 @@ VariableCommonInitialize (
EFI_GUID *guid = (EFI_GUID *)(buf + i + 8);
VOID *data = (VOID *)(buf + i + 8 + keysz);
DEBUG ((DEBUG_WARN, "Fetching variable: %s\n", varname));
DEBUG ((DEBUG_WARN, "buf: %p, buf+i: %p, guid: %p, varname: %p, data: %p\n", buf, buf + i, guid, varname, data));
VARIABLE_POINTER_TRACK Variable;
FindVariable (varname, guid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal);
// only update Boot* variables
if (!StrnCmp(L"Boot", varname, StrLen(L"Boot"))) {
DEBUG ((DEBUG_WARN, "Fetching variable: %s\n", varname));
DEBUG ((DEBUG_WARN, "buf: %p, buf+i: %p, guid: %p, varname: %p, data: %p\n", buf, buf + i, guid, varname, data));
VARIABLE_POINTER_TRACK Variable;
FindVariable (varname, guid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal);
DEBUG ((DEBUG_WARN, "Updating variable: %s\n", varname));
UpdateVariable (
varname,
guid,
data,
valsz,
// all of these variables are nv
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
&Variable
);
DEBUG ((DEBUG_WARN, "Updating variable: %s\n", varname));
UpdateVariable (
varname,
guid,
data,
valsz,
// all of these variables are nv
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
&Variable
);
} else {
DEBUG ((DEBUG_WARN, "Skipping non-Boot variable: %s\n", varname));
}
}
DEBUG ((DEBUG_WARN, "Added variable: 0x%x, val size: %x\n", keysz, valsz));
// no UEFI variable since it's at most the GUID part, so skip
i += 8 + keysz + valsz + 1;
i = (i + 3) & ~3;