]> git.proxmox.com Git - mirror_edk2.git/commitdiff
QuarkSocPkg: Add new package for Quark SoC X1000
authorMichael Kinney <michael.d.kinney@intel.com>
Tue, 15 Dec 2015 19:22:23 +0000 (19:22 +0000)
committermdkinney <mdkinney@Edk2>
Tue, 15 Dec 2015 19:22:23 +0000 (19:22 +0000)
Changes for V4
==============
1) Remove Unicode character from C source file
2) Move delete of QuarkSocPkg\QuarkNorthCluster\Binary\QuarkMicrocode
   from QuarkPlatformPkg commit to QuarkSocPkg commit

Changes for V2
==============
1) Sync with new APIs in SmmCpuFeaturesLib class
2) Use new generic PCI serial driver PciSioSerialDxe in MdeModulePkg
3) Remove PCI serial driver from QuarkSocPkg
4) Apply optimizations to MtrrLib from MtrrLib in UefiCpuPkg
5) Convert all UNI files to utf-8
6) Replace tabs with spaces and remove trailing spaces
7) Add License.txt

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Michael Kinney <michael.d.kinney@intel.com>
Acked-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19286 6f19259b-4bc3-4df7-8a09-765794883524

176 files changed:
QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperLib.inf [new file with mode: 0644]
QuarkSocPkg/Contributions.txt [new file with mode: 0644]
QuarkSocPkg/License.txt [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Include/DdrMemoryController.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCBase.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCConfig.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCDxe.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCPeim.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCRegs.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Include/Library/IntelQNCLib.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Include/Library/QNCAccessLib.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Include/Library/QNCSmmLib.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Include/Ppi/QNCMemoryInit.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Include/Protocol/PchInfo.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Include/Protocol/PlatformPolicy.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Include/Protocol/QncS3Support.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Include/Protocol/SmmIchnDispatch2.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Include/Protocol/Spi.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Include/QNCAccess.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Include/QNCCommonDefinitions.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Include/QuarkNcSocId.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/CommonHeader.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/IntelQNCLib.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/IntelQNCLib.inf [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/PciExpress.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/MtrrLib/MtrrLib.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/MtrrLib/MtrrLib.inf [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/MtrrLib/MtrrLib.uni [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/BaseAccess.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/QNCAccessLib.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/QNCAccessLib.inf [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/RuntimeAccess.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/RuntimeQNCAccessLib.inf [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.inf [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/ResetSystemLib/ResetSystemLib.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/ResetSystemLib/ResetSystemLib.inf [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/CommonHeader.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.inf [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.uni [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInit.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInit.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInitPei.inf [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/core_types.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/gen5_iosf_sb_definitions.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/general_definitions.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/hte.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/hte.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/io.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/lprint.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit_utils.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit_utils.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/memory_options.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/mrc.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/mrc.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/platform.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/prememinit.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/prememinit.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/CommonHeader.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/DxeQNCSmbus.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/DxeQNCSmbus.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyRegion.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyRegion.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInit.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInit.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInitDxe.inf [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCRootPorts.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCSmbus.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCSmbusExec.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.inf [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccess.inf [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccessDriver.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccessDriver.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmControlDxe/SmmControlDriver.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmControlDxe/SmmControlDxe.inf [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/CommonHeader.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmGpi.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmHelpers.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmPeriodicTimer.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmQncn.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmSw.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmSx.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmm.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmCore.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmDispatcher.inf [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmHelpers.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmHelpers.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmRegisters.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCxSmmHelpers.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.inf [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmControlPei/SmmControlPei.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmControlPei/SmmControlPei.inf [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Spi/Common/SpiCommon.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Spi/Common/SpiCommon.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Spi/PchSpiRuntime.inf [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Spi/PchSpiSmm.inf [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpi.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpi.h [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpi.c [new file with mode: 0644]
QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpi.h [new file with mode: 0644]
QuarkSocPkg/QuarkSocPkg.dec [new file with mode: 0644]
QuarkSocPkg/QuarkSocPkg.dsc [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Include/CEATA.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Include/I2cRegs.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Include/Ioh.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Include/IohAccess.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Include/IohCommonDefinitions.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Include/Library/I2cLib.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Include/Library/IohLib.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Include/MMC.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Include/SDCard.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Include/SDHostIo.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/CommonHeader.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohBds.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohData.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInit.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInitDxe.inf [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Library/I2cLib/CommonHeader.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Library/I2cLib/I2cLib.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Library/I2cLib/I2cLib.inf [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Library/IohLib/CommonHeader.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Library/IohLib/IohLib.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Library/IohLib/IohLib.inf [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/ComponentName.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/ComponentName.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDController.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDController.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDControllerDxe.inf [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATA.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATABlockIo.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/ComponentName.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/ComponentName.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDBlockIo.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDTransfer.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDevice.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDevice.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDeviceDxe.inf [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.inf [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/ComponentName.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/ComponentName.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Descriptor.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Ohci.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Ohci.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDebug.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDebug.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDxe.inf [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciReg.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciReg.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciSched.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciSched.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciUrb.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciUrb.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/UsbHcMem.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/UsbHcMem.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/Descriptor.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhcPeim.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhcPeim.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciPei.inf [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciReg.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciReg.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciSched.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciSched.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciUrb.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciUrb.h [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/UsbHcMem.c [new file with mode: 0644]
QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/UsbHcMem.h [new file with mode: 0644]

diff --git a/QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperLib.inf b/QuarkPlatformPkg/Library/PlatformPcieHelperLib/PlatformPcieHelperLib.inf
new file mode 100644 (file)
index 0000000..89747d4
--- /dev/null
@@ -0,0 +1,47 @@
+## @file\r
+# Library producing Pci Express Helper routines.\r
+#\r
+# Copyright (c) 2013 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = PlatformPcieHelperLib\r
+  FILE_GUID                      = C153F460-5D8A-4d44-83BB-A8AF5CEF132C\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = PlatformPcieHelperLib\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32\r
+#\r
+\r
+[Sources]\r
+  PlatformPcieHelperLib.c\r
+  SocUnit.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+  QuarkPlatformPkg/QuarkPlatformPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  PcdLib\r
+  IoLib\r
+  DebugLib\r
+  TimerLib\r
+  QNCAccessLib\r
+  IntelQNCLib\r
diff --git a/QuarkSocPkg/Contributions.txt b/QuarkSocPkg/Contributions.txt
new file mode 100644 (file)
index 0000000..f87cbd7
--- /dev/null
@@ -0,0 +1,218 @@
+\r
+======================\r
+= Code Contributions =\r
+======================\r
+\r
+To make a contribution to a TianoCore project, follow these steps.\r
+1. Create a change description in the format specified below to\r
+   use in the source control commit log.\r
+2. Your commit message must include your "Signed-off-by" signature,\r
+   and "Contributed-under" message.\r
+3. Your "Contributed-under" message explicitly states that the\r
+   contribution is made under the terms of the specified\r
+   contribution agreement.  Your "Contributed-under" message\r
+   must include the name of contribution agreement and version.\r
+   For example: Contributed-under: TianoCore Contribution Agreement 1.0\r
+   The "TianoCore Contribution Agreement" is included below in\r
+   this document.\r
+4. Submit your code to the TianoCore project using the process\r
+   that the project documents on its web page.  If the process is\r
+   not documented, then submit the code on development email list\r
+   for the project.\r
+5. It is preferred that contributions are submitted using the same\r
+   copyright license as the base project. When that is not possible,\r
+   then contributions using the following licenses can be accepted:\r
+   * BSD (2-clause): http://opensource.org/licenses/BSD-2-Clause\r
+   * BSD (3-clause): http://opensource.org/licenses/BSD-3-Clause\r
+   * MIT: http://opensource.org/licenses/MIT\r
+   * Python-2.0: http://opensource.org/licenses/Python-2.0\r
+   * Zlib: http://opensource.org/licenses/Zlib\r
+\r
+   Contributions of code put into the public domain can also be\r
+   accepted.\r
+\r
+   Contributions using other licenses might be accepted, but further\r
+   review will be required.\r
+\r
+=====================================================\r
+= Change Description / Commit Message / Patch Email =\r
+=====================================================\r
+\r
+Your change description should use the standard format for a\r
+commit message, and must include your "Signed-off-by" signature\r
+and the "Contributed-under" message.\r
+\r
+== Sample Change Description / Commit Message =\r
+\r
+=== Start of sample patch email message ===\r
+\r
+From: Contributor Name <contributor@example.com>\r
+Subject: [PATCH] CodeModule: Brief-single-line-summary\r
+\r
+Full-commit-message\r
+\r
+Contributed-under: TianoCore Contribution Agreement 1.0\r
+Signed-off-by: Contributor Name <contributor@example.com>\r
+---\r
+\r
+An extra message for the patch email which will not be considered part\r
+of the commit message can be added here.\r
+\r
+Patch content inline or attached\r
+\r
+=== End of sample patch email message ===\r
+\r
+=== Notes for sample patch email ===\r
+\r
+* The first line of commit message is taken from the email's subject\r
+  line following [PATCH]. The remaining portion of the commit message\r
+  is the email's content until the '---' line.\r
+* git format-patch is one way to create this format\r
+\r
+=== Definitions for sample patch email ===\r
+\r
+* "CodeModule" is a short idenfier for the affected code.  For\r
+  example MdePkg, or MdeModulePkg UsbBusDxe.\r
+* "Brief-single-line-summary" is a short summary of the change.\r
+* The entire first line should be less than ~70 characters.\r
+* "Full-commit-message" a verbose multiple line comment describing\r
+  the change.  Each line should be less than ~70 characters.\r
+* "Contributed-under" explicitely states that the contribution is\r
+  made under the terms of the contribtion agreement.  This\r
+  agreement is included below in this document.\r
+* "Signed-off-by" is the contributor's signature identifying them\r
+  by their real/legal name and their email address.\r
+\r
+========================================\r
+= TianoCore Contribution Agreement 1.0 =\r
+========================================\r
+\r
+INTEL CORPORATION ("INTEL") MAKES AVAILABLE SOFTWARE, DOCUMENTATION,\r
+INFORMATION AND/OR OTHER MATERIALS FOR USE IN THE TIANOCORE OPEN SOURCE\r
+PROJECT (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE\r
+TERMS AND CONDITIONS OF THIS AGREEMENT BETWEEN YOU AND INTEL AND/OR THE\r
+TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR\r
+REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE OF THE\r
+CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS\r
+OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED\r
+BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS\r
+AGREEMENT AND THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE\r
+AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT\r
+USE THE CONTENT.\r
+\r
+Unless otherwise indicated, all Content made available on the TianoCore\r
+site is provided to you under the terms and conditions of the BSD\r
+License ("BSD"). A copy of the BSD License is available at\r
+http://opensource.org/licenses/bsd-license.php\r
+or when applicable, in the associated License.txt file.\r
+\r
+Certain other content may be made available under other licenses as\r
+indicated in or with such Content. (For example, in a License.txt file.)\r
+\r
+You accept and agree to the following terms and conditions for Your\r
+present and future Contributions submitted to TianoCore site. Except\r
+for the license granted to Intel hereunder, You reserve all right,\r
+title, and interest in and to Your Contributions.\r
+\r
+== SECTION 1: Definitions ==\r
+* "You" or "Contributor" shall mean the copyright owner or legal\r
+  entity authorized by the copyright owner that is making a\r
+  Contribution hereunder. All other entities that control, are\r
+  controlled by, or are under common control with that entity are\r
+  considered to be a single Contributor. For the purposes of this\r
+  definition, "control" means (i) the power, direct or indirect, to\r
+  cause the direction or management of such entity, whether by\r
+  contract or otherwise, or (ii) ownership of fifty percent (50%)\r
+  or more of the outstanding shares, or (iii) beneficial ownership\r
+  of such entity.\r
+* "Contribution" shall mean any original work of authorship,\r
+  including any modifications or additions to an existing work,\r
+  that is intentionally submitted by You to the TinaoCore site for\r
+  inclusion in, or documentation of, any of the Content. For the\r
+  purposes of this definition, "submitted" means any form of\r
+  electronic, verbal, or written communication sent to the\r
+  TianoCore site or its representatives, including but not limited\r
+  to communication on electronic mailing lists, source code\r
+  control systems, and issue tracking systems that are managed by,\r
+  or on behalf of, the TianoCore site for the purpose of\r
+  discussing and improving the Content, but excluding\r
+  communication that is conspicuously marked or otherwise\r
+  designated in writing by You as "Not a Contribution."\r
+\r
+== SECTION 2: License for Contributions ==\r
+* Contributor hereby agrees that redistribution and use of the\r
+  Contribution in source and binary forms, with or without\r
+  modification, are permitted provided that the following\r
+  conditions are met:\r
+** Redistributions of source code must retain the Contributor's\r
+   copyright notice, this list of conditions and the following\r
+   disclaimer.\r
+** Redistributions in binary form must reproduce the Contributor's\r
+   copyright notice, this list of conditions and the following\r
+   disclaimer in the documentation and/or other materials provided\r
+   with the distribution.\r
+* Disclaimer. None of the names of Contributor, Intel, or the names\r
+  of their respective contributors may be used to endorse or\r
+  promote products derived from this software without specific\r
+  prior written permission.\r
+* Contributor grants a license (with the right to sublicense) under\r
+  claims of Contributor's patents that Contributor can license that\r
+  are infringed by the Contribution (as delivered by Contributor) to\r
+  make, use, distribute, sell, offer for sale, and import the\r
+  Contribution and derivative works thereof solely to the minimum\r
+  extent necessary for licensee to exercise the granted copyright\r
+  license; this patent license applies solely to those portions of\r
+  the Contribution that are unmodified. No hardware per se is\r
+  licensed.\r
+* EXCEPT AS EXPRESSLY SET FORTH IN SECTION 3 BELOW, THE\r
+  CONTRIBUTION IS PROVIDED BY THE CONTRIBUTOR "AS IS" AND ANY\r
+  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r
+  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\r
+  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\r
+  CONTRIBUTOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
+  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\r
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\r
+  CONTRIBUTION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\r
+  DAMAGE.\r
+\r
+== SECTION 3: Representations ==\r
+* You represent that You are legally entitled to grant the above\r
+  license. If your employer(s) has rights to intellectual property\r
+  that You create that includes Your Contributions, You represent\r
+  that You have received permission to make Contributions on behalf\r
+  of that employer, that Your employer has waived such rights for\r
+  Your Contributions.\r
+* You represent that each of Your Contributions is Your original\r
+  creation (see Section 4 for submissions on behalf of others).\r
+  You represent that Your Contribution submissions include complete\r
+  details of any third-party license or other restriction\r
+  (including, but not limited to, related patents and trademarks)\r
+  of which You are personally aware and which are associated with\r
+  any part of Your Contributions.\r
+\r
+== SECTION 4: Third Party Contributions ==\r
+* Should You wish to submit work that is not Your original creation,\r
+  You may submit it to TianoCore site separately from any\r
+  Contribution, identifying the complete details of its source\r
+  and of any license or other restriction (including, but not\r
+  limited to, related patents, trademarks, and license agreements)\r
+  of which You are personally aware, and conspicuously marking the\r
+  work as "Submitted on behalf of a third-party: [named here]".\r
+\r
+== SECTION 5: Miscellaneous ==\r
+* Applicable Laws. Any claims arising under or relating to this\r
+  Agreement shall be governed by the internal substantive laws of\r
+  the State of Delaware or federal courts located in Delaware,\r
+  without regard to principles of conflict of laws.\r
+* Language. This Agreement is in the English language only, which\r
+  language shall be controlling in all respects, and all versions\r
+  of this Agreement in any other language shall be for accommodation\r
+  only and shall not be binding. All communications and notices made\r
+  or given pursuant to this Agreement, and all documentation and\r
+  support to be provided, unless otherwise noted, shall be in the\r
+  English language.\r
+\r
diff --git a/QuarkSocPkg/License.txt b/QuarkSocPkg/License.txt
new file mode 100644 (file)
index 0000000..be68999
--- /dev/null
@@ -0,0 +1,25 @@
+Copyright (c) 2012, Intel Corporation. All rights reserved.\r
+\r
+Redistribution and use in source and binary forms, with or without\r
+modification, are permitted provided that the following conditions\r
+are met:\r
+\r
+* Redistributions of source code must retain the above copyright\r
+  notice, this list of conditions and the following disclaimer.\r
+* Redistributions in binary form must reproduce the above copyright\r
+  notice, this list of conditions and the following disclaimer in\r
+  the documentation and/or other materials provided with the\r
+  distribution.\r
+\r
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\r
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\r
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\r
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+POSSIBILITY OF SUCH DAMAGE.\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/DdrMemoryController.h b/QuarkSocPkg/QuarkNorthCluster/Include/DdrMemoryController.h
new file mode 100644 (file)
index 0000000..de777c5
--- /dev/null
@@ -0,0 +1,257 @@
+/** @file\r
+Memory controller configuration.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#ifndef __DDR_MEMORY_CONTROLLER_H__\r
+#define __DDR_MEMORY_CONTROLLER_H__\r
+\r
+//\r
+// DDR timing data definitions.\r
+// These are used to create bitmaps of valid timing configurations.\r
+//\r
+\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_FREQUENCY_UNKNOWN    0xFF\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_REFRESH_RATE_UNKNOWN 0xFF\r
+\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TCL_20    0x01\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TCL_25    0x00\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TCL_30    0x02\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TCL_ALL   0x03\r
+\r
+\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRCD_02   0x02\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRCD_03   0x01\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRCD_04   0x00\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRCD_ALL  0x03\r
+\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRP_02    0x02\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRP_03    0x01\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRP_04    0x00\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRP_ALL   0x03\r
+\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRAS_05   0x05\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRAS_06   0x04\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRAS_07   0x03\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRAS_08   0x02\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRAS_09   0x01\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRAS_10   0x00\r
+#define DUAL_CHANNEL_DDR_TIMING_DATA_TRAS_ALL  0x07\r
+\r
+#define DUAL_CHANNEL_DDR_DATA_TYPE_REGISTERED    0x01\r
+#define DUAL_CHANNEL_DDR_DATA_TYPE_UNREGISTERED  0x02\r
+#define DUAL_CHANNEL_DDR_DATA_TYPE_BUFFERED      0x04\r
+#define DUAL_CHANNEL_DDR_DATA_TYPE_UNBUFFERED    0x08\r
+#define DUAL_CHANNEL_DDR_DATA_TYPE_SDR           0x10\r
+#define DUAL_CHANNEL_DDR_DATA_TYPE_DDR           0x20\r
+\r
+\r
+//\r
+// Maximum number of SDRAM channels supported by the memory controller\r
+//\r
+#define MAX_CHANNELS 1\r
+\r
+//\r
+// Maximum number of DIMM sockets supported by the memory controller\r
+//\r
+#define MAX_SOCKETS 1\r
+\r
+//\r
+// Maximum number of sides supported per DIMM\r
+//\r
+#define   MAX_SIDES                         2\r
+\r
+//\r
+// Maximum number of "Socket Sets", where a "Socket Set is a set of matching\r
+// DIMM's from the various channels\r
+//\r
+#define   MAX_SOCKET_SETS                   2\r
+\r
+//\r
+// Maximum number of rows supported by the memory controller\r
+//\r
+#define MAX_ROWS (MAX_SIDES * MAX_SOCKETS)\r
+\r
+//\r
+// Maximum number of memory ranges supported by the memory controller\r
+//\r
+#define MAX_RANGES (MAX_ROWS + 5)\r
+\r
+//\r
+// Maximum Number of Log entries\r
+//\r
+#define   MEMORY_LOG_MAX_INDEX          16\r
+\r
+\r
+typedef struct _MEMORY_LOG_ENTRY {\r
+  EFI_STATUS_CODE_VALUE                     Event;\r
+  EFI_STATUS_CODE_TYPE                      Severity;\r
+  UINT8                                     Data;\r
+} MEMORY_LOG_ENTRY;\r
+\r
+typedef struct _MEMORY_LOG {\r
+  UINT8                                     Index;\r
+  MEMORY_LOG_ENTRY                      Entry[MEMORY_LOG_MAX_INDEX];\r
+} MEMORY_LOG;\r
+\r
+\r
+\r
+//\r
+// Defined ECC types\r
+//\r
+#define DUAL_CHANNEL_DDR_ECC_TYPE_NONE             0x01   // No error checking\r
+#define DUAL_CHANNEL_DDR_ECC_TYPE_EC               0x02   // Error checking only\r
+#define DUAL_CHANNEL_DDR_ECC_TYPE_SECC             0x04   // Software Scrubbing ECC\r
+#define DUAL_CHANNEL_DDR_ECC_TYPE_HECC             0x08   // Hardware Scrubbing ECC\r
+#define DUAL_CHANNEL_DDR_ECC_TYPE_CKECC            0x10   // Chip Kill ECC\r
+\r
+//\r
+// Row configuration status values\r
+//\r
+#define DUAL_CHANNEL_DDR_ROW_CONFIG_SUCCESS        0x00  // No error\r
+#define DUAL_CHANNEL_DDR_ROW_CONFIG_UNKNOWN        0x01  // Pattern mismatch, no memory\r
+#define DUAL_CHANNEL_DDR_ROW_CONFIG_UNSUPPORTED    0x02  // Memory type not supported\r
+#define DUAL_CHANNEL_DDR_ROW_CONFIG_ADDRESS_ERROR  0x03  // Row/Col/Bnk mismatch\r
+#define DUAL_CHANNEL_DDR_ROW_CONFIG_ECC_ERROR      0x04  // Received ECC error\r
+#define DUAL_CHANNEL_DDR_ROW_CONFIG_NOT_PRESENT    0x05  // Row is not present\r
+#define DUAL_CHANNEL_DDR_ROW_CONFIG_DISABLED       0x06  // Row is disabled\r
+\r
+\r
+//\r
+// Memory range types\r
+//\r
+typedef enum {\r
+  DualChannelDdrMainMemory,\r
+  DualChannelDdrSmramCacheable,\r
+  DualChannelDdrSmramNonCacheable,\r
+  DualChannelDdrGraphicsMemoryCacheable,\r
+  DualChannelDdrGraphicsMemoryNonCacheable,\r
+  DualChannelDdrReservedMemory,\r
+  DualChannelDdrMaxMemoryRangeType\r
+} DUAL_CHANNEL_DDR_MEMORY_RANGE_TYPE;\r
+\r
+//\r
+// Memory map range information\r
+//\r
+typedef struct {\r
+  EFI_PHYSICAL_ADDRESS                          PhysicalAddress;\r
+  EFI_PHYSICAL_ADDRESS                          CpuAddress;\r
+  EFI_PHYSICAL_ADDRESS                          RangeLength;\r
+  DUAL_CHANNEL_DDR_MEMORY_RANGE_TYPE                 Type;\r
+} DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE;\r
+typedef struct {\r
+    unsigned    dramType        :1;                 /**< Type: 0 = RESERVED; 1 = DDR2 */\r
+    unsigned    dramWidth       :1;                 /**< Width: 0 = x8; 1 = x16 */\r
+    unsigned    dramDensity     :2;                 /**< Density: 00b = 2Gb; 01b = 1Gb; 10b = 512Mb; 11b = 256Mb */\r
+    unsigned    dramSpeed       :1;                 /**< Speed Grade: 0 = RESERVED; 1 = 800MT/s;*/\r
+    unsigned    dramTimings     :3;                 /**< Timings: 4-4-4, 5-5-5, 6-6-6 */\r
+    unsigned    dramRanks       :1;                 /**< Ranks: 0 = Single Rank; 1 = Dual Rank */\r
+} DramGeometry;                                     /**< DRAM Geometry Descriptor */\r
+\r
+typedef union _RegDRP {\r
+    UINT32    raw;\r
+    struct {\r
+        unsigned rank0Enabled       :1;     /**< Rank 0 Enable */\r
+        unsigned rank0DevWidth      :2;     /**< DRAM Device Width (x8,x16) */\r
+        unsigned rank0DevDensity    :2;     /**< DRAM Device Density (256Mb,512Mb,1Gb,2Gb) */\r
+        unsigned reserved2          :1;\r
+        unsigned rank1Enabled       :1;     /**< Rank 1 Enable */\r
+        unsigned reserved3          :5;\r
+        unsigned dramType           :1;     /**< DRAM Type (0=DDR2) */\r
+        unsigned reserved4          :5;\r
+        unsigned reserved5          :14;\r
+      } field;\r
+} RegDRP;                                   /**< DRAM Rank Population and Interface Register */\r
+\r
+\r
+typedef union {\r
+    UINT32    raw;\r
+    struct {\r
+        unsigned dramFrequency      :3;     /**< DRAM Frequency (000=RESERVED,010=667,011=800) */\r
+        unsigned tRP                :2;     /**< Precharge to Activate Delay (3,4,5,6) */\r
+        unsigned reserved1          :1;\r
+        unsigned tRCD               :2;     /**< Activate to CAS Delay (3,4,5,6) */\r
+        unsigned reserved2          :1;\r
+        unsigned tCL                :2;     /**< CAS Latency (3,4,5,6) */\r
+        unsigned reserved3          :21;\r
+      } field;\r
+} RegDTR0;                                  /**< DRAM Timing Register 0 */\r
+\r
+typedef union {\r
+    UINT32    raw;\r
+    struct {\r
+        unsigned tWRRD_dly          :2;     /**< Additional Write to Read Delay (0,1,2,3) */\r
+        unsigned reserved1          :1;\r
+        unsigned tRDWR_dly          :2;     /**< Additional Read to Write Delay (0,1,2,3) */\r
+        unsigned reserved2          :1;\r
+        unsigned tRDRD_dr_dly       :1;     /**< Additional Read to Read Delay (1,2) */\r
+        unsigned reserved3          :1;\r
+        unsigned tRD_dly            :3;     /**< Additional Read Data Sampling Delay (0-7) */\r
+        unsigned reserved4          :1;\r
+        unsigned tRCVEN_halfclk_dly :4;     /**< Additional RCVEN Half Clock Delay Control */\r
+        unsigned reserved5          :1;\r
+        unsigned readDqDelay        :2;     /**< Read DQ Delay */\r
+        unsigned reserved6          :13;\r
+      } field;\r
+} RegDTR1;                                  /**< DRAM Timing Register 1 */\r
+\r
+typedef union {\r
+    UINT32    raw;\r
+    struct {\r
+        unsigned ckStaticDisable    :1;     /**< CK/CK# Static Disable */\r
+        unsigned reserved1          :3;\r
+        unsigned ckeStaticDisable   :2;     /**< CKE Static Disable */\r
+        unsigned reserved2          :8;\r
+        unsigned refreshPeriod      :2;     /**< Refresh Period (disabled,128clks,3.9us,7.8us) */\r
+        unsigned refreshQueueDepth  :2;     /**< Refresh Queue Depth (1,2,4,8) */\r
+        unsigned reserved5          :13;\r
+        unsigned initComplete       :1;     /**< Initialization Complete */\r
+      } field;\r
+} RegDCO;\r
+\r
+//\r
+// MRC Data Structure\r
+//\r
+typedef struct {\r
+    RegDRP          drp;\r
+    RegDTR0         dtr0;\r
+    RegDTR1         dtr1;\r
+    RegDCO          dco;\r
+    UINT32          reg0104;\r
+    UINT32          reg0120;\r
+    UINT32          reg0121;\r
+    UINT32          reg0123;\r
+    UINT32          reg0111;\r
+    UINT32          reg0130;\r
+    UINT8           refreshPeriod;      /**< Placeholder for the chosen refresh\r
+                                         *   period.  This value will NOT be\r
+                                         *   programmed into DCO until all\r
+                                         *   initialization is done.\r
+                                         */\r
+    UINT8           ddr2Odt;            /**< 0 = Disabled, 1 = 75 ohm, 2 = 150ohm, 3 = 50ohm */\r
+    UINT8           sku;                /**< Detected QuarkNcSocId SKU */\r
+    UINT8           capabilities;       /**< Capabilities Available on this part */\r
+    UINT8           state;              /**< NORMAL_BOOT, S3_RESUME */\r
+    UINT32          memSize;            /**< Memory size */\r
+    UINT16          pmBase;             /**< PM Base */\r
+    UINT16          mrcVersion;         /**< MRC Version */\r
+    UINT32          hecbase;            /**< HECBASE shifted left 16 bits */\r
+    DramGeometry    geometry;          /**< DRAM Geometry */\r
+} MRC_DATA_STRUCTURE;             /**< QuarkNcSocId Memory Parameters for MRC */\r
+\r
+typedef struct _EFI_MEMINIT_CONFIG_DATA {\r
+  MRC_DATA_STRUCTURE                        MrcData;\r
+} EFI_MEMINIT_CONFIG_DATA;\r
+\r
+\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCBase.h b/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCBase.h
new file mode 100644 (file)
index 0000000..92ad948
--- /dev/null
@@ -0,0 +1,23 @@
+/** @file\r
+Public include file for the QNC Base\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __INTEL_QNC_BASE_H__\r
+#define __INTEL_QNC_BASE_H__\r
+\r
+#include <IntelQNCRegs.h>\r
+#include <IntelQNCConfig.h>\r
+\r
+#endif\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCConfig.h b/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCConfig.h
new file mode 100644 (file)
index 0000000..7736012
--- /dev/null
@@ -0,0 +1,106 @@
+/** @file\r
+Some configuration of QNC Package\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __INTEL_QNC_CONFIG_H__\r
+#define __INTEL_QNC_CONFIG_H__\r
+\r
+//\r
+// QNC Fixed configurations.\r
+//\r
+\r
+//\r
+// Memory arbiter fixed config values.\r
+//\r
+#define QNC_FIXED_CONFIG_ASTATUS  ((UINT32) (\\r
+          (ASTATUS_PRI_NORMAL << ASTATUS0_DEFAULT_BP) | \\r
+          (ASTATUS_PRI_NORMAL << ASTATUS1_DEFAULT_BP) | \\r
+          (ASTATUS_PRI_URGENT << ASTATUS0_RASISED_BP) | \\r
+          (ASTATUS_PRI_URGENT << ASTATUS1_RASISED_BP) \\r
+          ))\r
+\r
+//\r
+// Memory Manager fixed config values.\r
+//\r
+#define V_DRAM_NON_HOST_RQ_LIMIT                    2\r
+\r
+//\r
+// RMU Thermal config fixed config values for TS in Vref Mode.\r
+//\r
+#define V_TSCGF1_CONFIG_ISNSCURRENTSEL_VREF_MODE    0x04\r
+#define V_TSCGF2_CONFIG2_ISPARECTRL_VREF_MODE       0x01\r
+#define V_TSCGF1_CONFIG_IBGEN_VREF_MODE             1\r
+#define V_TSCGF2_CONFIG_IDSCONTROL_VREF_MODE        0x011b\r
+#define V_TSCGF2_CONFIG2_ICALCOARSETUNE_VREF_MODE   0x34\r
+\r
+//\r
+// RMU Thermal config fixed config values for TS in Ratiometric mode.\r
+//\r
+#define V_TSCGF1_CONFIG_ISNSCURRENTSEL_RATIO_MODE   0x04\r
+#define V_TSCGF1_CONFIG_ISNSCHOPSEL_RATIO_MODE      0x02\r
+#define V_TSCGF1_CONFIG_ISNSINTERNALVREFEN_RATIO_MODE 1\r
+#define V_TSCGF2_CONFIG_IDSCONTROL_RATIO_MODE       0x011f\r
+#define V_TSCGF2_CONFIG_IDSTIMING_RATIO_MODE        0x0001\r
+#define V_TSCGF2_CONFIG2_ICALCONFIGSEL_RATIO_MODE   0x01\r
+#define V_TSCGF2_CONFIG2_ISPARECTRL_RATIO_MODE      0x00\r
+#define V_TSCGF1_CONFIG_IBGEN_RATIO_MODE            0\r
+#define V_TSCGF1_CONFIG_IBGCHOPEN_RATIO_MODE        0\r
+#define V_TSCGF3_CONFIG_ITSGAMMACOEFF_RATIO_MODE    0xC8\r
+#define V_TSCGF2_CONFIG2_ICALCOARSETUNE_RATIO_MODE  0x17\r
+\r
+//\r
+// iCLK fixed config values.\r
+//\r
+#define V_MUXTOP_FLEX2                              3\r
+#define V_MUXTOP_FLEX1                              1\r
+\r
+//\r
+// PCIe Root Port fixed config values.\r
+//\r
+#define V_PCIE_ROOT_PORT_SBIC_VALUE                 (B_QNC_PCIE_IOSFSBCTL_SBIC_IDLE_NEVER)\r
+\r
+//\r
+// QNC structures for configuration.\r
+//\r
+\r
+typedef union {\r
+  struct {\r
+    UINT32  PortErrorMask               :8;\r
+    UINT32  SlotImplemented             :1;\r
+    UINT32  Reserved1                   :1;\r
+    UINT32  AspmEnable                  :1;\r
+    UINT32  AspmAutoEnable              :1;\r
+    UINT32  AspmL0sEnable               :2;\r
+    UINT32  AspmL1Enable                :1;\r
+    UINT32  PmeInterruptEnable          :1;\r
+    UINT32  PhysicalSlotNumber          :13;\r
+    UINT32  Reserved2                   :1;\r
+    UINT32  PmSciEnable                 :1;\r
+    UINT32  HotplugSciEnable            :1;\r
+  } Bits;\r
+  UINT32 Uint32;\r
+} PCIEXP_ROOT_PORT_CONFIGURATION;\r
+\r
+typedef union {\r
+  UINT32 Uint32;\r
+  struct {\r
+    UINT32 Pcie_0     :1;   // 0: Disabled; 1: Enabled*\r
+    UINT32 Pcie_1     :1;   // 0: Disabled; 1: Enabled*\r
+    UINT32 Smbus      :1;   // 0: Disabled; 1: Enabled*\r
+    UINT32 Rsvd       :29;  // 0\r
+  } Bits;\r
+} QNC_DEVICE_ENABLES;\r
+\r
+#endif\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCDxe.h b/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCDxe.h
new file mode 100644 (file)
index 0000000..c266595
--- /dev/null
@@ -0,0 +1,23 @@
+/** @file\r
+Public include file for the QNC Dxe\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __INTEL_QNC_DXE_H__\r
+#define __INTEL_QNC_DXE_H__\r
+\r
+#include <IntelQNCRegs.h>\r
+#include <IntelQNCConfig.h>\r
+\r
+#endif\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCPeim.h b/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCPeim.h
new file mode 100644 (file)
index 0000000..5b27b1d
--- /dev/null
@@ -0,0 +1,23 @@
+/** @file\r
+Public include file for the QNC Pei\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __INTEL_QNC_PEIM_H__\r
+#define __INTEL_QNC_PEIM_H__\r
+\r
+#include <IntelQNCRegs.h>\r
+#include <IntelQNCConfig.h>\r
+\r
+#endif\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCRegs.h b/QuarkSocPkg/QuarkNorthCluster/Include/IntelQNCRegs.h
new file mode 100644 (file)
index 0000000..63dd04c
--- /dev/null
@@ -0,0 +1,54 @@
+/** @file\r
+Registers definition for Intel QuarkNcSocId.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __INTEL_QNC_REGS_H__\r
+#define __INTEL_QNC_REGS_H__\r
+\r
+#include <QNCAccess.h>\r
+\r
+//\r
+// PCI HostBridge Segment number\r
+//\r
+#define QNC_PCI_HOST_BRIDGE_SEGMENT_NUMBER    0\r
+\r
+//\r
+// PCI RootBridge resource allocation's attribute\r
+//\r
+#define QNC_PCI_ROOT_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTE \\r
+  EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM\r
+\r
+//\r
+// PCI HostBridge resource appeture\r
+//\r
+#define QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSBASE     0x0\r
+#define QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSLIMIT    0xff\r
+#define QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_TSEG_SIZE   0x10000000\r
+\r
+//\r
+// PCI RootBridge configure port\r
+//\r
+#define QNC_PCI_ROOT_BRIDGE_CONFIGURATION_ADDRESS_PORT  0xCF8\r
+#define QNC_PCI_ROOT_BRIDGE_CONFIGURATION_DATA_PORT     0xCFC\r
+\r
+//\r
+// PCI Rootbridge's support feature\r
+//\r
+#define QNC_PCI_ROOT_BRIDGE_SUPPORTED                   (EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO | \\r
+                                                         EFI_PCI_ATTRIBUTE_ISA_IO         | \\r
+                                                         EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO | \\r
+                                                         EFI_PCI_ATTRIBUTE_VGA_MEMORY     | \\r
+                                                         EFI_PCI_ATTRIBUTE_VGA_IO)\r
+\r
+#endif // __INTEL_QNC_REGS_H__\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Library/IntelQNCLib.h b/QuarkSocPkg/QuarkNorthCluster/Include/Library/IntelQNCLib.h
new file mode 100644 (file)
index 0000000..7cda8b1
--- /dev/null
@@ -0,0 +1,290 @@
+/** @file\r
+Library that provides QNC specific library services in PEI phase\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __INTEL_QNC_LIB_H__\r
+#define __INTEL_QNC_LIB_H__\r
+\r
+/**\r
+  This function initializes the QNC register before MRC.\r
+  It sets RCBA, PMBASE, disable Watchdog timer and initialize QNC GPIO.\r
+  If the function cannot complete it'll ASSERT().\r
+**/\r
+VOID\r
+EFIAPI\r
+PeiQNCPreMemInit (\r
+  VOID\r
+  );\r
+\r
+\r
+/**\r
+  Used to check SCH if it's S3 state.  Clear the register state after query.\r
+\r
+  @retval TRUE if it's S3 state.\r
+  @retval FALSE if it's not S3 state.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+QNCCheckS3AndClearState (\r
+   VOID\r
+  );\r
+\r
+/**\r
+  Used to check SCH if system wakes up from power on reset. Clear the register state after query.\r
+\r
+  @retval TRUE  if system wakes up from power on reset\r
+  @retval FALSE if system does not wake up from power on reset\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+QNCCheckPowerOnResetAndClearState (\r
+   VOID\r
+  );\r
+\r
+/**\r
+  This function is used to clear SMI and wake status.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+QNCClearSmiAndWake (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Used to initialize the QNC register after MRC.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+PeiQNCPostMemInit (\r
+  VOID\r
+  );\r
+\r
+/** Send DRAM Ready opcode.\r
+\r
+  @param[in]       OpcodeParam  Parameter to DRAM ready opcode.\r
+\r
+  @retval          VOID\r
+**/\r
+VOID\r
+EFIAPI\r
+QNCSendOpcodeDramReady (\r
+  IN UINT32   OpcodeParam\r
+  );\r
+\r
+/**\r
+\r
+  Relocate RMU Main binary to memory after MRC to improve performance.\r
+\r
+  @param[in]  DestBaseAddress  - Specify the new memory address for the RMU Main binary.\r
+  @param[in]  SrcBaseAddress   - Specify the current memory address for the RMU Main binary.\r
+  @param[in]  Size             - Specify size of the RMU Main binary.\r
+\r
+  @retval     VOID\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+RmuMainRelocation (\r
+  IN CONST UINT32   DestBaseAddress,\r
+  IN CONST UINT32   SrcBaseAddress,\r
+  IN CONST UINTN    Size\r
+  );\r
+\r
+/**\r
+  Get the total memory size\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+QNCGetTotalMemorysize (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Get the memory range of TSEG.\r
+  The TSEG's memory is below TOLM.\r
+\r
+  @param[out] BaseAddress The base address of TSEG's memory range\r
+  @param[out] MemorySize  The size of TSEG's memory range\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+QNCGetTSEGMemoryRange (\r
+  OUT UINT64  *BaseAddress,\r
+  OUT UINT64  *MemorySize\r
+  );\r
+\r
+/**\r
+  Updates the PAM registers in the MCH for the requested range and mode.\r
+\r
+  @param   Start        The start address of the memory region\r
+  @param   Length       The length, in bytes, of the memory region\r
+  @param   ReadEnable   Pointer to the boolean variable on whether to enable read for legacy memory section.\r
+                        If NULL, then read attribute will not be touched by this call.\r
+  @param   ReadEnable   Pointer to the boolean variable on whether to enable write for legacy memory section.\r
+                        If NULL, then write attribute will not be touched by this call.\r
+  @param   Granularity  A pointer to granularity, in bytes, that the PAM registers support\r
+\r
+  @retval  RETURN_SUCCESS            The PAM registers in the MCH were updated\r
+  @retval  RETURN_INVALID_PARAMETER  The memory range is not valid in legacy region.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+QNCLegacyRegionManipulation (\r
+  IN  UINT32                  Start,\r
+  IN  UINT32                  Length,\r
+  IN  BOOLEAN                 *ReadEnable,\r
+  IN  BOOLEAN                 *WriteEnable,\r
+  OUT UINT32                  *Granularity\r
+  );\r
+\r
+/**\r
+  Do early init of pci express rootports on Soc.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+PciExpressEarlyInit (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Complete initialization of all the pci express rootports on Soc.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciExpressInit (\r
+  );\r
+\r
+/**\r
+  Determine if QNC is supported.\r
+\r
+  @retval FALSE  QNC is not supported.\r
+  @retval TRUE   QNC is supported.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsQncSupported (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Get the DeviceId of the SoC\r
+\r
+  @retval PCI DeviceId of the SoC\r
+**/\r
+UINT16\r
+EFIAPI\r
+QncGetSocDeviceId (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Enable SMI detection of legacy flash access violations.\r
+**/\r
+VOID\r
+EFIAPI\r
+QncEnableLegacyFlashAccessViolationSmi (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Setup RMU Thermal sensor registers for Vref mode.\r
+**/\r
+VOID\r
+EFIAPI\r
+QNCThermalSensorSetVRefMode (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Setup RMU Thermal sensor registers for Ratiometric mode.\r
+**/\r
+VOID\r
+EFIAPI\r
+QNCThermalSensorSetRatiometricMode (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Setup RMU Thermal sensor trip point values.\r
+\r
+  @param[in]  CatastrophicTripOnDegreesCelsius  - Catastrophic set trip point threshold.\r
+  @param[in]  HotTripOnDegreesCelsius           - Hot set trip point threshold.\r
+  @param[in]  HotTripOffDegreesCelsius          - Hot clear trip point threshold.\r
+\r
+  @retval     VOID\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+QNCThermalSensorSetTripValues (\r
+  IN  CONST UINTN             CatastrophicTripOnDegreesCelsius,\r
+  IN  CONST UINTN             HotTripOnDegreesCelsius,\r
+  IN  CONST UINTN             HotTripOffDegreesCelsius\r
+  );\r
+\r
+/**\r
+  Enable RMU Thermal sensor with a Catastrophic Trip point.\r
+\r
+  @retval  EFI_SUCCESS            Trip points setup.\r
+  @retval  EFI_INVALID_PARAMETER  Invalid trip point value.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+QNCThermalSensorEnableWithCatastrophicTrip (\r
+  IN  CONST UINTN             CatastrophicTripOnDegreesCelsius\r
+  );\r
+\r
+/**\r
+  Lock all RMU Thermal sensor control & trip point registers.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+QNCThermalSensorLockAllRegisters (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Set chipset policy for double bit ECC error.\r
+\r
+  @param[in]       PolicyValue  Policy to config on double bit ECC error.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+QNCPolicyDblEccBitErr (\r
+  IN  CONST UINT32                        PolicyValue\r
+  );\r
+\r
+/**\r
+  Determine if running on secure Quark hardware Sku.\r
+\r
+  @retval FALSE  Base Quark Sku or unprovisioned Secure Sku running.\r
+  @retval TRUE   Provisioned SecureSku hardware running.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+QncIsSecureProvisionedSku (\r
+  VOID\r
+  );\r
+#endif\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Library/QNCAccessLib.h b/QuarkSocPkg/QuarkNorthCluster/Include/Library/QNCAccessLib.h
new file mode 100644 (file)
index 0000000..4496167
--- /dev/null
@@ -0,0 +1,167 @@
+/** @file\r
+Library functions for Setting QNC internal network port\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __QNC_ACCESS_LIB_H__\r
+#define __QNC_ACCESS_LIB_H__\r
+\r
+#include <IntelQNCRegs.h>\r
+\r
+#define MESSAGE_READ_DW(Port, Reg)  \\r
+        (UINT32)((QUARK_OPCODE_READ << QNC_MCR_OP_OFFSET) | ((Port << QNC_MCR_PORT_OFFSET) & 0xFF0000) | ((Reg << QNC_MCR_REG_OFFSET) & 0xFF00) | 0xF0)\r
+\r
+#define MESSAGE_WRITE_DW(Port, Reg)  \\r
+        (UINT32)((QUARK_OPCODE_WRITE << QNC_MCR_OP_OFFSET) | ((Port << QNC_MCR_PORT_OFFSET) & 0xFF0000) | ((Reg << QNC_MCR_REG_OFFSET) & 0xFF00) | 0xF0)\r
+\r
+#define ALT_MESSAGE_READ_DW(Port, Reg)  \\r
+        (UINT32)((QUARK_ALT_OPCODE_READ << QNC_MCR_OP_OFFSET) | ((Port << QNC_MCR_PORT_OFFSET) & 0xFF0000) | ((Reg << QNC_MCR_REG_OFFSET) & 0xFF00) | 0xF0)\r
+\r
+#define ALT_MESSAGE_WRITE_DW(Port, Reg)  \\r
+        (UINT32)((QUARK_ALT_OPCODE_WRITE << QNC_MCR_OP_OFFSET) | ((Port << QNC_MCR_PORT_OFFSET) & 0xFF0000) | ((Reg << QNC_MCR_REG_OFFSET) & 0xFF00) | 0xF0)\r
+\r
+#define MESSAGE_IO_READ_DW(Port, Reg)  \\r
+        (UINT32)((QUARK_OPCODE_IO_READ << QNC_MCR_OP_OFFSET) | ((Port << QNC_MCR_PORT_OFFSET) & 0xFF0000) | ((Reg << QNC_MCR_REG_OFFSET) & 0xFF00) | 0xF0)\r
+\r
+#define MESSAGE_IO_WRITE_DW(Port, Reg)  \\r
+        (UINT32)((QUARK_OPCODE_IO_WRITE << QNC_MCR_OP_OFFSET) | ((Port << QNC_MCR_PORT_OFFSET) & 0xFF0000) | ((Reg << QNC_MCR_REG_OFFSET) & 0xFF00) | 0xF0)\r
+\r
+#define MESSAGE_SHADOW_DW(Port, Reg)  \\r
+        (UINT32)((QUARK_DRAM_BASE_ADDR_READY << QNC_MCR_OP_OFFSET) | ((Port << QNC_MCR_PORT_OFFSET) & 0xFF0000) | ((Reg << QNC_MCR_REG_OFFSET) & 0xFF00) | 0xF0)\r
+\r
+\r
+/**\r
+  Read required data from QNC internal message network\r
+**/\r
+UINT32\r
+EFIAPI\r
+QNCPortRead(\r
+  UINT8 Port,\r
+  UINT32 RegAddress\r
+  );\r
+\r
+/**\r
+  Write prepared data into QNC internal message network.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+QNCPortWrite (\r
+  UINT8 Port,\r
+  UINT32 RegAddress,\r
+  UINT32 WriteValue\r
+  );\r
+\r
+/**\r
+  Read required data from QNC internal message network\r
+**/\r
+UINT32\r
+EFIAPI\r
+QNCAltPortRead(\r
+  UINT8 Port,\r
+  UINT32 RegAddress\r
+  );\r
+\r
+/**\r
+  Write prepared data into QNC internal message network.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+QNCAltPortWrite (\r
+  UINT8 Port,\r
+  UINT32 RegAddress,\r
+  UINT32 WriteValue\r
+  );\r
+\r
+/**\r
+  Read required data from QNC internal message network\r
+**/\r
+UINT32\r
+EFIAPI\r
+QNCPortIORead(\r
+  UINT8 Port,\r
+  UINT32 RegAddress\r
+  );\r
+\r
+/**\r
+  Write prepared data into QNC internal message network.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+QNCPortIOWrite (\r
+  UINT8 Port,\r
+  UINT32 RegAddress,\r
+  UINT32 WriteValue\r
+  );\r
+\r
+/**\r
+  This is for the special consideration for QNC MMIO write, as required by FWG,\r
+  a reading must be performed after MMIO writing to ensure the expected write\r
+  is processed and data is flushed into chipset\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+QNCMmIoWrite (\r
+  UINT32             MmIoAddress,\r
+  QNC_MEM_IO_WIDTH    Width,\r
+  UINT32             DataNumber,\r
+  VOID               *pData\r
+  );\r
+\r
+UINT32\r
+EFIAPI\r
+QncHsmmcRead (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+QncHsmmcWrite (\r
+  UINT32 WriteValue\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+QncImrWrite (\r
+  UINT32 ImrBaseOffset,\r
+  UINT32 ImrLow,\r
+  UINT32 ImrHigh,\r
+  UINT32 ImrReadMask,\r
+  UINT32 ImrWriteMask\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+QncIClkAndThenOr (\r
+  UINT32 RegAddress,\r
+  UINT32 AndValue,\r
+  UINT32 OrValue\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+QncIClkOr (\r
+  UINT32 RegAddress,\r
+  UINT32 OrValue\r
+  );\r
+\r
+UINTN\r
+EFIAPI\r
+QncGetPciExpressBaseAddress (\r
+  VOID\r
+  );\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Library/QNCSmmLib.h b/QuarkSocPkg/QuarkNorthCluster/Include/Library/QNCSmmLib.h
new file mode 100644 (file)
index 0000000..731aebc
--- /dev/null
@@ -0,0 +1,63 @@
+/** @file\r
+QNC Smm Library Services header file.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __QNC_SMM_LIB_H__\r
+#define __QNC_SMM_LIB_H__\r
+\r
+/**\r
+  This routine is the chipset code that accepts a request to "open" a region of SMRAM.\r
+  The region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.\r
+  The use of "open" means that the memory is visible from all boot-service\r
+  and SMM agents.\r
+\r
+  @retval FALSE  Cannot open a locked SMRAM region\r
+  @retval TRUE   Success to open SMRAM region.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+QNCOpenSmramRegion (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  This routine is the chipset code that accepts a request to "close" a region of SMRAM.\r
+  The region could be legacy AB or TSEG near top of physical memory.\r
+  The use of "close" means that the memory is only visible from SMM agents,\r
+  not from BS or RT code.\r
+\r
+  @retval FALSE  Cannot open a locked SMRAM region\r
+  @retval TRUE   Success to open SMRAM region.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+QNCCloseSmramRegion (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  This routine is the chipset code that accepts a request to "lock" SMRAM.\r
+  The region could be legacy AB or TSEG near top of physical memory.\r
+  The use of "lock" means that the memory can no longer be opened\r
+  to BS state.\r
+**/\r
+VOID\r
+EFIAPI\r
+QNCLockSmramRegion (\r
+  VOID\r
+  );\r
+\r
+\r
+#endif\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Ppi/QNCMemoryInit.h b/QuarkSocPkg/QuarkNorthCluster/Include/Ppi/QNCMemoryInit.h
new file mode 100644 (file)
index 0000000..2d99bff
--- /dev/null
@@ -0,0 +1,42 @@
+/** @file\r
+Memory Initialization PPI used in EFI PEI interface\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __QNC_MEMORY_INIT_H__\r
+#define __QNC_MEMORY_INIT_H__\r
+\r
+#include "mrc.h"\r
+\r
+#define PEI_QNC_MEMORY_INIT_PPI_GUID \\r
+  {0x21ff1fee, 0xd33a, 0x4fce, {0xa6, 0x5e, 0x95, 0x5e, 0xa3, 0xc4, 0x1f, 0x40}}\r
+\r
+\r
+\r
+\r
+//\r
+// PPI Function Declarations\r
+//\r
+typedef\r
+VOID\r
+(EFIAPI *PEI_QNC_MEMORY_INIT) (\r
+  IN OUT    MRCParams_t     *MRCDATA\r
+  );\r
+\r
+typedef struct _PEI_QNC_MEMORY_INIT_PPI {\r
+  PEI_QNC_MEMORY_INIT     MrcStart;\r
+}PEI_QNC_MEMORY_INIT_PPI;\r
+\r
+extern EFI_GUID gQNCMemoryInitPpiGuid;\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/PchInfo.h b/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/PchInfo.h
new file mode 100644 (file)
index 0000000..26c78ef
--- /dev/null
@@ -0,0 +1,54 @@
+/** @file\r
+This file defines the QNC Info Protocol.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+#ifndef _PCH_INFO_H_\r
+#define _PCH_INFO_H_\r
+\r
+//\r
+// Extern the GUID for protocol users.\r
+//\r
+extern EFI_GUID                       gEfiQncInfoProtocolGuid;\r
+\r
+//\r
+// Forward reference for ANSI C compatibility\r
+//\r
+typedef struct _EFI_QNC_INFO_PROTOCOL EFI_QNC_INFO_PROTOCOL;\r
+\r
+//\r
+// Protocol revision number\r
+// Any backwards compatible changes to this protocol will result in an update in the revision number\r
+// Major changes will require publication of a new protocol\r
+//\r
+// Revision 1:  Original version\r
+// Revision 2:   Add RCVersion item to EFI_QNC_INFO_PROTOCOL\r
+//\r
+#define QNC_INFO_PROTOCOL_REVISION_1  1\r
+#define QNC_INFO_PROTOCOL_REVISION_2  2\r
+\r
+//\r
+// RCVersion[7:0] is the release number.\r
+//\r
+#define QNC_RC_VERSION                0x01020000\r
+\r
+//\r
+// Protocol definition\r
+//\r
+struct _EFI_QNC_INFO_PROTOCOL {\r
+  UINT8   Revision;\r
+  UINT8   BusNumber;\r
+  UINT32  RCVersion;\r
+};\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/PlatformPolicy.h b/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/PlatformPolicy.h
new file mode 100644 (file)
index 0000000..e080bcc
--- /dev/null
@@ -0,0 +1,37 @@
+/** @file\r
+Protocol used for Platform Policy definition.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+\r
+#ifndef _PLATFORM_POLICY_H_\r
+#define _PLATFORM_POLICY_H_\r
+\r
+typedef struct _EFI_PLATFORM_POLICY_PROTOCOL EFI_PLATFORM_POLICY_PROTOCOL;\r
+\r
+#define EFI_PLATFORM_POLICY_PROTOCOL_GUID \\r
+  { \\r
+    0x2977064f, 0xab96, 0x4fa9, { 0x85, 0x45, 0xf9, 0xc4, 0x02, 0x51, 0xe0, 0x7f } \\r
+  }\r
+\r
+//\r
+// Protocol to describe various platform information. Add to this as needed.\r
+//\r
+struct _EFI_PLATFORM_POLICY_PROTOCOL {\r
+  UINT8 NumRsvdSmbusAddresses;\r
+  UINT8 *RsvdSmbusAddresses;\r
+};\r
+\r
+extern EFI_GUID gEfiPlatformPolicyProtocolGuid;\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/QncS3Support.h b/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/QncS3Support.h
new file mode 100644 (file)
index 0000000..9d39932
--- /dev/null
@@ -0,0 +1,90 @@
+/** @file\r
+This file defines the QNC S3 support Protocol.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+#ifndef _QNC_S3_SUPPORT_PROTOCOL_H_\r
+#define _QNC_S3_SUPPORT_PROTOCOL_H_\r
+\r
+//\r
+// Extern the GUID for protocol users.\r
+//\r
+extern EFI_GUID                             gEfiQncS3SupportProtocolGuid;\r
+\r
+//\r
+// Forward reference for ANSI C compatibility\r
+//\r
+typedef struct _EFI_QNC_S3_SUPPORT_PROTOCOL EFI_QNC_S3_SUPPORT_PROTOCOL;\r
+\r
+typedef enum {\r
+  QncS3ItemTypeInitPcieRootPortDownstream,\r
+  QncS3ItemTypeMax\r
+} EFI_QNC_S3_DISPATCH_ITEM_TYPE;\r
+\r
+//\r
+// It's better not to use pointer here because the size of pointer in DXE is 8, but it's 4 in PEI\r
+// plug 4 to ParameterSize in PEIM if you really need it\r
+//\r
+typedef struct {\r
+  UINT32                        Reserved;\r
+} EFI_QNC_S3_PARAMETER_INIT_PCIE_ROOT_PORT_DOWNSTREAM;\r
+\r
+typedef union {\r
+  EFI_QNC_S3_PARAMETER_INIT_PCIE_ROOT_PORT_DOWNSTREAM   PcieRootPortData;\r
+} EFI_DISPATCH_CONTEXT_UNION;\r
+\r
+typedef struct {\r
+  EFI_QNC_S3_DISPATCH_ITEM_TYPE Type;\r
+  VOID                          *Parameter;\r
+} EFI_QNC_S3_DISPATCH_ITEM;\r
+\r
+//\r
+// Member functions\r
+//\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_QNC_S3_SUPPORT_SET_S3_DISPATCH_ITEM) (\r
+  IN     EFI_QNC_S3_SUPPORT_PROTOCOL   * This,\r
+  IN     EFI_QNC_S3_DISPATCH_ITEM      * DispatchItem,\r
+  OUT    VOID                         **S3DispatchEntryPoint,\r
+  OUT    VOID                         **Context\r
+  );\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Set an item to be dispatched at S3 resume time. At the same time, the entry point\r
+  of the QNC S3 support image is returned to be used in subsequent boot script save\r
+  call\r
+\r
+Arguments:\r
+\r
+  This                    - Pointer to the protocol instance.\r
+  DispatchItem            - The item to be dispatched.\r
+  S3DispatchEntryPoint    - The entry point of the QNC S3 support image.\r
+\r
+Returns:\r
+\r
+  EFI_STATUS\r
+\r
+--*/\r
+\r
+//\r
+// Protocol definition\r
+//\r
+struct _EFI_QNC_S3_SUPPORT_PROTOCOL {\r
+  EFI_QNC_S3_SUPPORT_SET_S3_DISPATCH_ITEM SetDispatchItem;\r
+};\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/SmmIchnDispatch2.h b/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/SmmIchnDispatch2.h
new file mode 100644 (file)
index 0000000..e3f7291
--- /dev/null
@@ -0,0 +1,121 @@
+/** @file\r
+Intel-only SMM Child Dispatcher Protocol.\r
+\r
+This protocol provides a parent dispatch service for a collection of\r
+chipset-specific SMI source.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#ifndef __SMM_ICHN_DISPATCH2_H__\r
+#define __SMM_ICHN_DISPATCH2_H__\r
+\r
+//\r
+// Share some common definitions with Framework SMM\r
+//\r
+#include <Protocol/SmmIchnDispatch.h>\r
+\r
+#include <PiSmm.h>\r
+\r
+//\r
+// Global ID for the ICH SMI Protocol\r
+//\r
+#define EFI_SMM_ICHN_DISPATCH2_PROTOCOL_GUID \\r
+  { \\r
+    0xadf3a128, 0x416d, 0x4060, {0x8d, 0xdf, 0x30, 0xa1, 0xd7, 0xaa, 0xb6, 0x99 } \\r
+  }\r
+\r
+typedef struct _EFI_SMM_ICHN_DISPATCH2_PROTOCOL EFI_SMM_ICHN_DISPATCH2_PROTOCOL;\r
+\r
+typedef struct {\r
+  EFI_SMM_ICHN_SMI_TYPE Type;\r
+} EFI_SMM_ICHN_REGISTER_CONTEXT;\r
+\r
+//\r
+// Member functions\r
+//\r
+/**\r
+  Register a child SMI source dispatch function with a parent SMM driver\r
+\r
+  @param  This                  Protocol instance pointer.\r
+  @param  DispatchFunction      Pointer to dispatch function to be invoked for\r
+                                this SMI source\r
+  @param  RegisterContext       Pointer to the dispatch function's context.\r
+                                The caller fills this context in before calling\r
+                                the register function to indicate to the register\r
+                                function the ICHN SMI source for which the dispatch\r
+                                function should be invoked.\r
+  @param  DispatchHandle        Handle generated by the dispatcher to track the\r
+                                function instance.\r
+\r
+  @retval EFI_SUCCESS           The dispatch function has been successfully\r
+                                registered and the SMI source has been enabled.\r
+  @retval EFI_DEVICE_ERROR      The driver was unable to enable the SMI source.\r
+  @retval EFI_OUT_OF_RESOURCES  Not enough memory (system or SMM) to manage this\r
+                                child.\r
+  @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The ICHN input value\r
+                                is not within valid range.\r
+\r
+**/\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_SMM_ICHN_DISPATCH2_REGISTER) (\r
+  IN CONST EFI_SMM_ICHN_DISPATCH2_PROTOCOL   *This,\r
+  IN       EFI_SMM_HANDLER_ENTRY_POINT2      DispatchFunction,\r
+  IN OUT   EFI_SMM_ICHN_REGISTER_CONTEXT     *RegisterContext,\r
+     OUT   EFI_HANDLE                        *DispatchHandle\r
+  );\r
+\r
+/**\r
+  Unregister a child SMI source dispatch function with a parent SMM driver\r
+\r
+  @param  This                  Protocol instance pointer.\r
+  @param  DispatchHandle        Handle of dispatch function to deregister.\r
+\r
+  @retval EFI_SUCCESS           The dispatch function has been successfully\r
+                                unregistered and the SMI source has been disabled\r
+                                if there are no other registered child dispatch\r
+                                functions for this SMI source.\r
+  @retval EFI_INVALID_PARAMETER Handle is invalid.\r
+  @retval other\r
+\r
+**/\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_SMM_ICHN_DISPATCH2_UNREGISTER) (\r
+  IN EFI_SMM_ICHN_DISPATCH2_PROTOCOL          *This,\r
+  IN EFI_HANDLE                               DispatchHandle\r
+  );\r
+\r
+//\r
+// Interface structure for the SMM Ich n specific SMI Dispatch Protocol\r
+//\r
+/**\r
+  @par Protocol Description:\r
+  Provides a parent dispatch service for ICH SMI sources.\r
+\r
+  @param Register\r
+  Installs a child service to be dispatched by this protocol.\r
+\r
+  @param UnRegister\r
+  Removes a child service dispatched by this protocol.\r
+\r
+**/\r
+struct _EFI_SMM_ICHN_DISPATCH2_PROTOCOL {\r
+  EFI_SMM_ICHN_DISPATCH2_REGISTER   Register;\r
+  EFI_SMM_ICHN_DISPATCH2_UNREGISTER UnRegister;\r
+};\r
+\r
+extern EFI_GUID gEfiSmmIchnDispatch2ProtocolGuid;\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/Spi.h b/QuarkSocPkg/QuarkNorthCluster/Include/Protocol/Spi.h
new file mode 100644 (file)
index 0000000..137f9b3
--- /dev/null
@@ -0,0 +1,351 @@
+/** @file\r
+This file defines the EFI SPI Protocol which implements the\r
+Intel(R) ICH SPI Host Controller Compatibility Interface.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+#ifndef _SPI_H_\r
+#define _SPI_H_\r
+\r
+//\r
+// Define the SPI protocol GUID\r
+//\r
+// EDK and EDKII have different GUID formats\r
+//\r
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)\r
+#define EFI_SPI_PROTOCOL_GUID \\r
+  { \\r
+    0x1156efc6, 0xea32, 0x4396, 0xb5, 0xd5, 0x26, 0x93, 0x2e, 0x83, 0xc3, 0x13 \\r
+  }\r
+#define EFI_SMM_SPI_PROTOCOL_GUID \\r
+  { \\r
+    0xD9072C35, 0xEB8F, 0x43ad, 0xA2, 0x20, 0x34, 0xD4, 0x0E, 0x2A, 0x82, 0x85 \\r
+  }\r
+#else\r
+#define EFI_SPI_PROTOCOL_GUID \\r
+  { \\r
+    0x1156efc6, 0xea32, 0x4396, \\r
+    { \\r
+      0xb5, 0xd5, 0x26, 0x93, 0x2e, 0x83, 0xc3, 0x13 \\r
+    } \\r
+  }\r
+#define EFI_SMM_SPI_PROTOCOL_GUID \\r
+  { \\r
+    0xD9072C35, 0xEB8F, 0x43ad, \\r
+    { \\r
+      0xA2, 0x20, 0x34, 0xD4, 0x0E, 0x2A, 0x82, 0x85 \\r
+    } \\r
+  }\r
+#endif\r
+//\r
+// Extern the GUID for protocol users.\r
+//\r
+extern EFI_GUID                   gEfiSpiProtocolGuid;\r
+extern EFI_GUID                   gEfiSmmSpiProtocolGuid;\r
+\r
+//\r
+// Forward reference for ANSI C compatibility\r
+//\r
+typedef struct _EFI_SPI_PROTOCOL  EFI_SPI_PROTOCOL;\r
+\r
+//\r
+// SPI protocol data structures and definitions\r
+//\r
+//\r
+// Number of Prefix Opcodes allowed on the SPI interface\r
+//\r
+#define SPI_NUM_PREFIX_OPCODE 2\r
+\r
+//\r
+// Number of Opcodes in the Opcode Menu\r
+//\r
+#define SPI_NUM_OPCODE  8\r
+\r
+#ifdef SERVER_BIOS_FLAG\r
+//\r
+// SPI default opcode slots\r
+//\r
+#define SPI_OPCODE_JEDEC_ID_INDEX        0\r
+#endif // SERVER_BIOS_FLAG\r
+\r
+//\r
+// Opcode Type\r
+//    EnumSpiOpcodeCommand: Command without address\r
+//    EnumSpiOpcodeRead: Read with address\r
+//    EnumSpiOpcodeWrite: Write with address\r
+//\r
+typedef enum {\r
+  EnumSpiOpcodeReadNoAddr,\r
+  EnumSpiOpcodeWriteNoAddr,\r
+  EnumSpiOpcodeRead,\r
+  EnumSpiOpcodeWrite,\r
+  EnumSpiOpcodeMax\r
+} SPI_OPCODE_TYPE;\r
+\r
+typedef enum {\r
+  EnumSpiCycle20MHz,\r
+  EnumSpiCycle33MHz,\r
+  EnumSpiCycle66MHz,  // not supported by PCH\r
+  EnumSpiCycle50MHz,\r
+  EnumSpiCycleMax\r
+} SPI_CYCLE_FREQUENCY;\r
+\r
+typedef enum {\r
+  EnumSpiRegionAll,\r
+  EnumSpiRegionBios,\r
+  EnumSpiRegionMe,\r
+  EnumSpiRegionGbE,\r
+  EnumSpiRegionDescriptor,\r
+  EnumSpiRegionPlatformData,\r
+  EnumSpiRegionMax\r
+} SPI_REGION_TYPE;\r
+\r
+//\r
+// Hardware Sequencing required operations (as listed in CougarPoint EDS Table 5-55: "Hardware\r
+// Sequencing Commands and Opcode Requirements"\r
+//\r
+typedef enum {\r
+  EnumSpiOperationWriteStatus,\r
+  EnumSpiOperationProgramData_1_Byte,\r
+  EnumSpiOperationProgramData_64_Byte,\r
+  EnumSpiOperationReadData,\r
+  EnumSpiOperationWriteDisable,\r
+  EnumSpiOperationReadStatus,\r
+  EnumSpiOperationWriteEnable,\r
+  EnumSpiOperationFastRead,\r
+  EnumSpiOperationEnableWriteStatus,\r
+  EnumSpiOperationErase_256_Byte,\r
+  EnumSpiOperationErase_4K_Byte,\r
+  EnumSpiOperationErase_8K_Byte,\r
+  EnumSpiOperationErase_64K_Byte,\r
+  EnumSpiOperationFullChipErase,\r
+  EnumSpiOperationJedecId,\r
+  EnumSpiOperationDualOutputFastRead,\r
+  EnumSpiOperationDiscoveryParameters,\r
+  EnumSpiOperationOther,\r
+  EnumSpiOperationMax\r
+} SPI_OPERATION;\r
+\r
+//\r
+// Opcode menu entries\r
+//   Type            Operation Type (value to be programmed to the OPTYPE register)\r
+//   Code            The opcode (value to be programmed to the OPMENU register)\r
+//   Frequency       The expected frequency to be used (value to be programmed to the SSFC\r
+//                   Register)\r
+//   Operation       Which Hardware Sequencing required operation this opcode respoinds to.\r
+//                   The required operations are listed in EDS Table 5-55: "Hardware\r
+//                   Sequencing Commands and Opcode Requirements"\r
+//                   If the opcode does not corresponds to any operation listed, use\r
+//                   EnumSpiOperationOther\r
+//\r
+typedef struct _SPI_OPCODE_MENU_ENTRY {\r
+  SPI_OPCODE_TYPE     Type;\r
+  UINT8               Code;\r
+  SPI_CYCLE_FREQUENCY Frequency;\r
+  SPI_OPERATION       Operation;\r
+} SPI_OPCODE_MENU_ENTRY;\r
+\r
+//\r
+// Initialization data table loaded to the SPI host controller\r
+//    VendorId        Vendor ID of the SPI device\r
+//    DeviceId0       Device ID0 of the SPI device\r
+//    DeviceId1       Device ID1 of the SPI device\r
+//    PrefixOpcode    Prefix opcodes which are loaded into the SPI host controller\r
+//    OpcodeMenu      Opcodes which are loaded into the SPI host controller Opcode Menu\r
+//    BiosStartOffset The offset of the start of the BIOS image relative to the flash device.\r
+//                    Please note this is a Flash Linear Address, NOT a memory space address.\r
+//                    This value is platform specific and depends on the system flash map.\r
+//                    This value is only used on non Descriptor mode.\r
+//    BiosSize        The the BIOS Image size in flash. This value is platform specific\r
+//                    and depends on the system flash map. Please note BIOS Image size may\r
+//                    be smaller than BIOS Region size (in Descriptor Mode) or the flash size\r
+//                    (in Non Descriptor Mode), and in this case, BIOS Image is supposed to be\r
+//                    placed at the top end of the BIOS Region (in Descriptor Mode) or the flash\r
+//                    (in Non Descriptor Mode)\r
+//\r
+typedef struct _SPI_INIT_TABLE {\r
+  UINT8                 VendorId;\r
+  UINT8                 DeviceId0;\r
+  UINT8                 DeviceId1;\r
+  UINT8                 PrefixOpcode[SPI_NUM_PREFIX_OPCODE];\r
+  SPI_OPCODE_MENU_ENTRY OpcodeMenu[SPI_NUM_OPCODE];\r
+  UINTN                 BiosStartOffset;\r
+  UINTN                 BiosSize;\r
+} SPI_INIT_TABLE;\r
+\r
+//\r
+// Public Info struct to show current initialized state of the spi interface.\r
+// OpcodeIndex must be less then SPI_NUM_OPCODE for operation to be supported.\r
+//\r
+typedef struct _SPI_INIT_INFO {\r
+  SPI_INIT_TABLE        *InitTable;\r
+  UINT8                 JedecIdOpcodeIndex;\r
+  UINT8                 OtherOpcodeIndex;\r
+  UINT8                 WriteStatusOpcodeIndex;\r
+  UINT8                 ProgramOpcodeIndex;\r
+  UINT8                 ReadOpcodeIndex;\r
+  UINT8                 EraseOpcodeIndex;\r
+  UINT8                 ReadStatusOpcodeIndex;\r
+  UINT8                 FullChipEraseOpcodeIndex;\r
+} SPI_INIT_INFO;\r
+\r
+//\r
+// Protocol member functions\r
+//\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_SPI_INIT) (\r
+  IN EFI_SPI_PROTOCOL     * This,\r
+  IN SPI_INIT_TABLE       * InitTable\r
+  );\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Initializes the host controller to execute SPI commands.\r
+\r
+Arguments:\r
+\r
+  This                    Pointer to the EFI_SPI_PROTOCOL instance.\r
+  InitTable               Pointer to caller-allocated buffer containing the SPI\r
+                          interface initialization table.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             Opcode initialization on the SPI host controller completed.\r
+  EFI_ACCESS_DENIED       The SPI configuration interface is locked.\r
+  EFI_OUT_OF_RESOURCES    Not enough resource available to initialize the device.\r
+  EFI_DEVICE_ERROR        Device error, operation failed.\r
+\r
+--*/\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_SPI_LOCK) (\r
+  IN EFI_SPI_PROTOCOL     * This\r
+  );\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Lock the SPI Static Configuration Interface.\r
+  Once locked, the interface is no longer open for configuration changes.\r
+  The lock state automatically clears on next system reset.\r
+\r
+Arguments:\r
+\r
+  This      Pointer to the EFI_SPI_PROTOCOL instance.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             Lock operation succeed.\r
+  EFI_DEVICE_ERROR        Device error, operation failed.\r
+  EFI_ACCESS_DENIED       The interface has already been locked.\r
+\r
+--*/\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_SPI_EXECUTE) (\r
+  IN     EFI_SPI_PROTOCOL   * This,\r
+  IN     UINT8              OpcodeIndex,\r
+  IN     UINT8              PrefixOpcodeIndex,\r
+  IN     BOOLEAN            DataCycle,\r
+  IN     BOOLEAN            Atomic,\r
+  IN     BOOLEAN            ShiftOut,\r
+  IN     UINTN              Address,\r
+  IN     UINT32             DataByteCount,\r
+  IN OUT UINT8              *Buffer,\r
+  IN     SPI_REGION_TYPE    SpiRegionType\r
+  );\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Execute SPI commands from the host controller.\r
+\r
+Arguments:\r
+\r
+  This                    Pointer to the EFI_SPI_PROTOCOL instance.\r
+  OpcodeIndex             Index of the command in the OpCode Menu.\r
+  PrefixOpcodeIndex       Index of the first command to run when in an atomic cycle sequence.\r
+  DataCycle               TRUE if the SPI cycle contains data\r
+  Atomic                  TRUE if the SPI cycle is atomic and interleave cycles are not allowed.\r
+  ShiftOut                If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.\r
+  Address                 In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform\r
+                          Region, this value specifies the offset from the Region Base; for BIOS Region,\r
+                          this value specifies the offset from the start of the BIOS Image. In Non\r
+                          Descriptor Mode, this value specifies the offset from the start of the BIOS Image.\r
+                          Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor\r
+                          Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is\r
+                          supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or\r
+                          the flash (in Non Descriptor Mode)\r
+  DataByteCount           Number of bytes in the data portion of the SPI cycle.\r
+  Buffer                  Pointer to caller-allocated buffer containing the dada received or sent during the SPI cycle.\r
+  SpiRegionType           SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,\r
+                          EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in\r
+                          Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode\r
+                          and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative\r
+                          to base of the 1st flash device (i.e., it is a Flash Linear Address).\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             Command succeed.\r
+  EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+  EFI_UNSUPPORTED         Command not supported.\r
+  EFI_DEVICE_ERROR        Device error, command aborts abnormally.\r
+\r
+--*/\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_SPI_INFO) (\r
+  IN EFI_SPI_PROTOCOL     *This,\r
+  OUT SPI_INIT_INFO      **InitInfoPtr\r
+  );\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Return info about SPI host controller, to help callers usage of Execute\r
+  service.\r
+\r
+  If 0xff is returned as an opcode index in init info struct\r
+  then device does not support the operation.\r
+\r
+Arguments:\r
+\r
+  This                    Pointer to the EFI_SPI_PROTOCOL instance.\r
+  InitInfoPtr             Pointer to init info written to this memory location.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             Information returned.\r
+  EFI_INVALID_PARAMETER   Invalid parameter.\r
+  EFI_NOT_READY           Required resources not setup.\r
+  Others                  Unexpected error happened.\r
+\r
+--*/\r
+\r
+//\r
+// Protocol definition\r
+//\r
+struct _EFI_SPI_PROTOCOL {\r
+  EFI_SPI_INIT    Init;\r
+  EFI_SPI_LOCK    Lock;\r
+  EFI_SPI_EXECUTE Execute;\r
+  EFI_SPI_INFO    Info;\r
+};\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/QNCAccess.h b/QuarkSocPkg/QuarkNorthCluster/Include/QNCAccess.h
new file mode 100644 (file)
index 0000000..b77d3c9
--- /dev/null
@@ -0,0 +1,183 @@
+/** @file\r
+Macros to simplify and abstract the interface to PCI configuration.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+\r
+#ifndef _QNC_ACCESS_H_\r
+#define _QNC_ACCESS_H_\r
+\r
+#include "QuarkNcSocId.h"\r
+#include "QNCCommonDefinitions.h"\r
+\r
+#define EFI_LPC_PCI_ADDRESS( Register ) \\r
+  EFI_PCI_ADDRESS(PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, PCI_FUNCTION_NUMBER_QNC_LPC, Register)\r
+\r
+//\r
+// QNC Controller PCI access macros\r
+//\r
+#define QNC_RCRB_BASE (QNCMmio32 (PciDeviceMmBase (0, PCI_DEVICE_NUMBER_QNC_LPC, 0), R_QNC_LPC_RCBA) & B_QNC_LPC_RCBA_MASK)\r
+\r
+//\r
+// Device 0x1f, Function 0\r
+//\r
+\r
+#define LpcPciCfg32( Register ) \\r
+  QNCMmPci32(0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register )\r
+\r
+#define LpcPciCfg32Or( Register, OrData ) \\r
+  QNCMmPci32Or( 0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register, OrData )\r
+\r
+#define LpcPciCfg32And( Register, AndData ) \\r
+  QNCMmPci32And( 0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register, AndData )\r
+\r
+#define LpcPciCfg32AndThenOr( Register, AndData, OrData ) \\r
+  QNCMmPci32AndThenOr( 0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register, AndData, OrData )\r
+\r
+#define LpcPciCfg16( Register ) \\r
+  QNCMmPci16( 0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register )\r
+\r
+#define LpcPciCfg16Or( Register, OrData ) \\r
+  QNCMmPci16Or(  0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register, OrData )\r
+\r
+#define LpcPciCfg16And( Register, AndData ) \\r
+  QNCMmPci16And( 0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register, AndData )\r
+\r
+#define LpcPciCfg16AndThenOr( Register, AndData, OrData ) \\r
+  QNCMmPci16AndThenOr( 0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register, AndData, OrData )\r
+\r
+#define LpcPciCfg8( Register ) \\r
+  QNCMmPci8( 0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register )\r
+\r
+#define LpcPciCfg8Or( Register, OrData ) \\r
+  QNCMmPci8Or(  0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register, OrData )\r
+\r
+#define LpcPciCfg8And( Register, AndData ) \\r
+  QNCMmPci8And(  0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register, AndData )\r
+\r
+#define LpcPciCfg8AndThenOr( Register, AndData, OrData ) \\r
+  QNCMmPci8AndThenOr(  0,PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, Register, AndData, OrData )\r
+\r
+//\r
+// Root Complex Register Block\r
+//\r
+\r
+#define MmRcrb32( Register ) \\r
+  QNCMmio32( QNC_RCRB_BASE, Register )\r
+\r
+#define MmRcrb32Or( Register, OrData ) \\r
+  QNCMmio32Or( QNC_RCRB_BASE, Register, OrData )\r
+\r
+#define MmRcrb32And( Register, AndData ) \\r
+  QNCMmio32And( QNC_RCRB_BASE, Register, AndData )\r
+\r
+#define MmRcrb32AndThenOr( Register, AndData, OrData ) \\r
+  QNCMmio32AndThenOr( QNC_RCRB_BASE, Register, AndData, OrData )\r
+\r
+#define MmRcrb16( Register ) \\r
+  QNCMmio16( QNC_RCRB_BASE, Register )\r
+\r
+#define MmRcrb16Or( Register, OrData ) \\r
+  QNCMmio16Or( QNC_RCRB_BASE, Register, OrData )\r
+\r
+#define MmRcrb16And( Register, AndData ) \\r
+  QNCMmio16And( QNC_RCRB_BASE, Register, AndData )\r
+\r
+#define MmRcrb16AndThenOr( Register, AndData, OrData ) \\r
+  QNCMmio16AndThenOr( QNC_RCRB_BASE, Register, AndData, OrData )\r
+\r
+#define MmRcrb8( Register ) \\r
+  QNCMmio8( QNC_RCRB_BASE, Register )\r
+\r
+#define MmRcrb8Or( Register, OrData ) \\r
+  QNCMmio8Or( QNC_RCRB_BASE, Register, OrData )\r
+\r
+#define MmRcrb8And( Register, AndData ) \\r
+  QNCMmio8And( QNC_RCRB_BASE, Register, AndData )\r
+\r
+#define MmRcrb8AndThenOr( Register, AndData, OrData ) \\r
+  QNCMmio8AndThenOr( QNC_RCRB_BASE, Register, AndData, OrData )\r
+\r
+//\r
+// Memory Controller PCI access macros\r
+//\r
+\r
+//\r
+// Device 0, Function 0\r
+//\r
+\r
+#define McD0PciCfg64(Register)                              QNCMmPci32           (0, MC_BUS, 0, 0, Register)\r
+#define McD0PciCfg64Or(Register, OrData)                    QNCMmPci32Or         (0, MC_BUS, 0, 0, Register, OrData)\r
+#define McD0PciCfg64And(Register, AndData)                  QNCMmPci32And        (0, MC_BUS, 0, 0, Register, AndData)\r
+#define McD0PciCfg64AndThenOr(Register, AndData, OrData)    QNCMmPci32AndThenOr  (0, MC_BUS, 0, 0, Register, AndData, OrData)\r
+\r
+#define McD0PciCfg32(Register)                              QNCMmPci32           (0, MC_BUS, 0, 0, Register)\r
+#define McD0PciCfg32Or(Register, OrData)                    QNCMmPci32Or         (0, MC_BUS, 0, 0, Register, OrData)\r
+#define McD0PciCfg32And(Register, AndData)                  QNCMmPci32And        (0, MC_BUS, 0, 0, Register, AndData)\r
+#define McD0PciCfg32AndThenOr(Register, AndData, OrData)    QNCMmPci32AndThenOr  (0, MC_BUS, 0, 0, Register, AndData, OrData)\r
+\r
+#define McD0PciCfg16(Register)                              QNCMmPci16           (0, MC_BUS, 0, 0, Register)\r
+#define McD0PciCfg16Or(Register, OrData)                    QNCMmPci16Or         (0, MC_BUS, 0, 0, Register, OrData)\r
+#define McD0PciCfg16And(Register, AndData)                  QNCMmPci16And        (0, MC_BUS, 0, 0, Register, AndData)\r
+#define McD0PciCfg16AndThenOr(Register, AndData, OrData)    QNCMmPci16AndThenOr  (0, MC_BUS, 0, 0, Register, AndData, OrData)\r
+\r
+#define McD0PciCfg8(Register)                               QNCMmPci8            (0, MC_BUS, 0, 0, Register)\r
+#define McD0PciCfg8Or(Register, OrData)                     QNCMmPci8Or          (0, MC_BUS, 0, 0, Register, OrData)\r
+#define McD0PciCfg8And(Register, AndData)                   QNCMmPci8And         (0, MC_BUS, 0, 0, Register, AndData)\r
+#define McD0PciCfg8AndThenOr( Register, AndData, OrData )   QNCMmPci8AndThenOr   (0, MC_BUS, 0, 0, Register, AndData, OrData)\r
+\r
+\r
+//\r
+// Memory Controller Hub Memory Mapped IO register access ???\r
+//\r
+#define MCH_REGION_BASE                     (McD0PciCfg64 (MC_MCHBAR_OFFSET) & ~BIT0)\r
+#define McMmioAddress(Register)             ((UINTN) MCH_REGION_BASE + (UINTN) (Register))\r
+\r
+#define McMmio32Ptr(Register)               ((volatile UINT32*) McMmioAddress (Register))\r
+#define McMmio64Ptr(Register)               ((volatile UINT64*) McMmioAddress (Register))\r
+\r
+#define McMmio64(Register)                            *McMmio64Ptr( Register )\r
+#define McMmio64Or(Register, OrData)                  (McMmio64 (Register) |= (UINT64)(OrData))\r
+#define McMmio64And(Register, AndData)                (McMmio64 (Register) &= (UINT64)(AndData))\r
+#define McMmio64AndThenOr(Register, AndData, OrData)  (McMmio64 ( Register ) = (McMmio64( Register ) & (UINT64)(AndData)) | (UINT64)(OrData))\r
+\r
+#define McMmio32(Register)                            *McMmio32Ptr (Register)\r
+#define McMmio32Or(Register, OrData)                  (McMmio32 (Register) |= (UINT32)(OrData))\r
+#define McMmio32And(Register, AndData)                (McMmio32 (Register) &= (UINT32)(AndData))\r
+#define McMmio32AndThenOr(Register, AndData, OrData)  (McMmio32 (Register) = (McMmio32 (Register) & (UINT32) (AndData)) | (UINT32) (OrData))\r
+\r
+#define McMmio16Ptr(Register)                         ((volatile UINT16*) McMmioAddress (Register))\r
+#define McMmio16(Register)                            *McMmio16Ptr (Register)\r
+#define McMmio16Or(Register, OrData)                  (McMmio16 (Register) |= (UINT16) (OrData))\r
+#define McMmio16And(Register, AndData)                (McMmio16 (Register) &= (UINT16) (AndData))\r
+#define McMmio16AndThenOr(Register, AndData, OrData)  (McMmio16 (Register) = (McMmio16 (Register) & (UINT16) (AndData)) | (UINT16) (OrData))\r
+\r
+#define McMmio8Ptr(Register)                          ((volatile UINT8 *)McMmioAddress (Register))\r
+#define McMmio8(Register)                             *McMmio8Ptr (Register)\r
+#define McMmio8Or(Register, OrData)                   (McMmio8 (Register) |= (UINT8) (OrData))\r
+#define McMmio8And(Register, AndData)                 (McMmio8 (Register) &= (UINT8) (AndData))\r
+#define McMmio8AndThenOr(Register, AndData, OrData)   (McMmio8 (Register) = (McMmio8 (Register) & (UINT8) (AndData)) | (UINT8) (OrData))\r
+\r
+//\r
+// QNC memory mapped related data structure deifinition\r
+//\r
+typedef enum {\r
+  QNCMmioWidthUint8  = 0,\r
+  QNCMmioWidthUint16 = 1,\r
+  QNCMmioWidthUint32 = 2,\r
+  QNCMmioWidthUint64 = 3,\r
+  QNCMmioWidthMaximum\r
+} QNC_MEM_IO_WIDTH;\r
+\r
+#endif\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/QNCCommonDefinitions.h b/QuarkSocPkg/QuarkNorthCluster/Include/QNCCommonDefinitions.h
new file mode 100644 (file)
index 0000000..88d3d88
--- /dev/null
@@ -0,0 +1,356 @@
+/** @file\r
+This header file provides common definitions just for MCH using to avoid including extra module's file.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _QNC_COMMON_DEFINITIONS_H_\r
+#define _QNC_COMMON_DEFINITIONS_H_\r
+\r
+//\r
+// PCI CONFIGURATION MAP REGISTER OFFSETS\r
+//\r
+#ifndef PCI_VID\r
+#define PCI_VID             0x0000        // Vendor ID Register\r
+#define PCI_DID             0x0002        // Device ID Register\r
+#define PCI_CMD             0x0004        // PCI Command Register\r
+#define PCI_STS             0x0006        // PCI Status Register\r
+#define PCI_RID             0x0008        // Revision ID Register\r
+#define PCI_IFT             0x0009        // Interface Type\r
+#define PCI_SCC             0x000A        // Sub Class Code Register\r
+#define PCI_BCC             0x000B        // Base Class Code Register\r
+#define PCI_CLS             0x000C        // Cache Line Size\r
+#define PCI_PMLT            0x000D        // Primary Master Latency Timer\r
+#define PCI_HDR             0x000E        // Header Type Register\r
+#define PCI_BIST            0x000F        // Built in Self Test Register\r
+#define PCI_BAR0            0x0010        // Base Address Register 0\r
+#define PCI_BAR1            0x0014        // Base Address Register 1\r
+#define PCI_BAR2            0x0018        // Base Address Register 2\r
+#define PCI_PBUS            0x0018        // Primary Bus Number Register\r
+#define PCI_SBUS            0x0019        // Secondary Bus Number Register\r
+#define PCI_SUBUS           0x001A        // Subordinate Bus Number Register\r
+#define PCI_SMLT            0x001B        // Secondary Master Latency Timer\r
+#define PCI_BAR3            0x001C        // Base Address Register 3\r
+#define PCI_IOBASE          0x001C        // I/O base Register\r
+#define PCI_IOLIMIT         0x001D        // I/O Limit Register\r
+#define PCI_SECSTATUS       0x001E        // Secondary Status Register\r
+#define PCI_BAR4            0x0020        // Base Address Register 4\r
+#define PCI_MEMBASE         0x0020        // Memory Base Register\r
+#define PCI_MEMLIMIT        0x0022        // Memory Limit Register\r
+#define PCI_BAR5            0x0024        // Base Address Register 5\r
+#define PCI_PRE_MEMBASE     0x0024        // Prefetchable memory Base register\r
+#define PCI_PRE_MEMLIMIT    0x0026        // Prefetchable memory Limit register\r
+#define PCI_PRE_MEMBASE_U   0x0028        // Prefetchable memory base upper 32 bits\r
+#define PCI_PRE_MEMLIMIT_U  0x002C        // Prefetchable memory limit upper 32 bits\r
+#define PCI_SVID            0x002C        // Subsystem Vendor ID\r
+#define PCI_SID             0x002E        // Subsystem ID\r
+#define PCI_IOBASE_U        0x0030        // I/O base Upper Register\r
+#define PCI_IOLIMIT_U       0x0032        // I/O Limit Upper Register\r
+#define PCI_CAPP            0x0034        // Capabilities Pointer\r
+#define PCI_EROM            0x0038        // Expansion ROM Base Address\r
+#define PCI_INTLINE         0x003C        // Interrupt Line Register\r
+#define PCI_INTPIN          0x003D        // Interrupt Pin Register\r
+#define PCI_MAXGNT          0x003E        // Max Grant Register\r
+#define PCI_BRIDGE_CNTL     0x003E        // Bridge Control Register\r
+#define PCI_MAXLAT          0x003F        // Max Latency Register\r
+#endif\r
+//\r
+// Bit Difinitions\r
+//\r
+#ifndef BIT0\r
+#define BIT0                     0x0001\r
+#define BIT1                     0x0002\r
+#define BIT2                     0x0004\r
+#define BIT3                     0x0008\r
+#define BIT4                     0x0010\r
+#define BIT5                     0x0020\r
+#define BIT6                     0x0040\r
+#define BIT7                     0x0080\r
+#define BIT8                     0x0100\r
+#define BIT9                     0x0200\r
+#define BIT10                    0x0400\r
+#define BIT11                    0x0800\r
+#define BIT12                    0x1000\r
+#define BIT13                    0x2000\r
+#define BIT14                    0x4000\r
+#define BIT15                    0x8000\r
+#define BIT16                0x00010000\r
+#define BIT17                0x00020000\r
+#define BIT18                0x00040000\r
+#define BIT19                0x00080000\r
+#define BIT20                0x00100000\r
+#define BIT21                0x00200000\r
+#define BIT22                0x00400000\r
+#define BIT23                0x00800000\r
+#define BIT24                0x01000000\r
+#define BIT25                0x02000000\r
+#define BIT26                0x04000000\r
+#define BIT27                0x08000000\r
+#define BIT28                0x10000000\r
+#define BIT29                0x20000000\r
+#define BIT30                0x40000000\r
+#define BIT31                0x80000000\r
+#endif\r
+\r
+\r
+//\r
+//  Common Memory mapped Io access macros ------------------------------------------\r
+//\r
+#define QNCMmioAddress( BaseAddr, Register ) \\r
+    ( (UINTN)BaseAddr + \\r
+      (UINTN)(Register) \\r
+    )\r
+\r
+//\r
+// UINT64\r
+//\r
+#define QNCMmio64Ptr( BaseAddr, Register ) \\r
+    ( (volatile UINT64 *)QNCMmioAddress( BaseAddr, Register ) )\r
+\r
+#define QNCMmio64( BaseAddr, Register ) \\r
+    *QNCMmio64Ptr( BaseAddr, Register )\r
+\r
+#define QNCMmio64Or( BaseAddr, Register, OrData ) \\r
+    QNCMmio64( BaseAddr, Register ) = \\r
+      (UINT64) ( \\r
+        QNCMmio64( BaseAddr, Register ) | \\r
+        (UINT64)(OrData) \\r
+      )\r
+\r
+#define QNCMmio64And( BaseAddr, Register, AndData ) \\r
+    QNCMmio64( BaseAddr, Register ) = \\r
+      (UINT64) ( \\r
+        QNCMmio64( BaseAddr, Register ) & \\r
+        (UINT64)(AndData) \\r
+      )\r
+\r
+#define QNCMmio64AndThenOr( BaseAddr, Register, AndData, OrData ) \\r
+    QNCMmio64( BaseAddr, Register ) = \\r
+      (UINT64) ( \\r
+        ( QNCMmio64( BaseAddr, Register ) & \\r
+            (UINT64)(AndData) \\r
+        ) | \\r
+        (UINT64)(OrData) \\r
+      )\r
+\r
+//\r
+// UINT32\r
+//\r
+#define QNCMmio32Ptr( BaseAddr, Register ) \\r
+    ( (volatile UINT32 *)QNCMmioAddress( BaseAddr, Register ) )\r
+\r
+#define QNCMmio32( BaseAddr, Register ) \\r
+    *QNCMmio32Ptr( BaseAddr, Register )\r
+\r
+#define QNCMmio32Or( BaseAddr, Register, OrData ) \\r
+    QNCMmio32( BaseAddr, Register ) = \\r
+      (UINT32) ( \\r
+        QNCMmio32( BaseAddr, Register ) | \\r
+        (UINT32)(OrData) \\r
+      )\r
+\r
+#define QNCMmio32And( BaseAddr, Register, AndData ) \\r
+    QNCMmio32( BaseAddr, Register ) = \\r
+      (UINT32) ( \\r
+        QNCMmio32( BaseAddr, Register ) & \\r
+        (UINT32)(AndData) \\r
+      )\r
+\r
+#define QNCMmio32AndThenOr( BaseAddr, Register, AndData, OrData ) \\r
+    QNCMmio32( BaseAddr, Register ) = \\r
+      (UINT32) ( \\r
+        ( QNCMmio32( BaseAddr, Register ) & \\r
+            (UINT32)(AndData) \\r
+        ) | \\r
+        (UINT32)(OrData) \\r
+      )\r
+//\r
+// UINT16\r
+//\r
+\r
+#define QNCMmio16Ptr( BaseAddr, Register ) \\r
+    ( (volatile UINT16 *)QNCMmioAddress( BaseAddr, Register ) )\r
+\r
+#define QNCMmio16( BaseAddr, Register ) \\r
+    *QNCMmio16Ptr( BaseAddr, Register )\r
+\r
+#define QNCMmio16Or( BaseAddr, Register, OrData ) \\r
+    QNCMmio16( BaseAddr, Register ) = \\r
+      (UINT16) ( \\r
+        QNCMmio16( BaseAddr, Register ) | \\r
+        (UINT16)(OrData) \\r
+      )\r
+\r
+#define QNCMmio16And( BaseAddr, Register, AndData ) \\r
+    QNCMmio16( BaseAddr, Register ) = \\r
+      (UINT16) ( \\r
+        QNCMmio16( BaseAddr, Register ) & \\r
+        (UINT16)(AndData) \\r
+      )\r
+\r
+#define QNCMmio16AndThenOr( BaseAddr, Register, AndData, OrData ) \\r
+    QNCMmio16( BaseAddr, Register ) = \\r
+      (UINT16) ( \\r
+        ( QNCMmio16( BaseAddr, Register ) & \\r
+            (UINT16)(AndData) \\r
+        ) | \\r
+        (UINT16)(OrData) \\r
+      )\r
+//\r
+// UINT8\r
+//\r
+#define QNCMmio8Ptr( BaseAddr, Register ) \\r
+    ( (volatile UINT8 *)QNCMmioAddress( BaseAddr, Register ) )\r
+\r
+#define QNCMmio8( BaseAddr, Register ) \\r
+    *QNCMmio8Ptr( BaseAddr, Register )\r
+\r
+#define QNCMmio8Or( BaseAddr, Register, OrData ) \\r
+    QNCMmio8( BaseAddr, Register ) = \\r
+      (UINT8) ( \\r
+        QNCMmio8( BaseAddr, Register ) | \\r
+        (UINT8)(OrData) \\r
+      )\r
+\r
+#define QNCMmio8And( BaseAddr, Register, AndData ) \\r
+    QNCMmio8( BaseAddr, Register ) = \\r
+      (UINT8) ( \\r
+        QNCMmio8( BaseAddr, Register ) & \\r
+        (UINT8)(AndData) \\r
+      )\r
+\r
+#define QNCMmio8AndThenOr( BaseAddr, Register, AndData, OrData ) \\r
+    QNCMmio8( BaseAddr, Register ) = \\r
+      (UINT8) ( \\r
+        ( QNCMmio8( BaseAddr, Register ) & \\r
+            (UINT8)(AndData) \\r
+          ) | \\r
+        (UINT8)(OrData) \\r
+      )\r
+\r
+//\r
+//  Common Memory mapped Pci access macros ------------------------------------------\r
+//\r
+\r
+#define QNCMmPciAddress( Segment, Bus, Device, Function, Register ) \\r
+  ( (UINTN) QncGetPciExpressBaseAddress() + \\r
+    (UINTN)(Bus << 20) + \\r
+    (UINTN)(Device << 15) + \\r
+    (UINTN)(Function << 12) + \\r
+    (UINTN)(Register) \\r
+  )\r
+\r
+//\r
+// Macro to calculate the Pci device's base memory mapped address\r
+//\r
+#define PciDeviceMmBase( Bus, Device, Function) \\r
+    ( (UINTN) QncGetPciExpressBaseAddress () + \\r
+      (UINTN)(Bus << 20) + \\r
+      (UINTN)(Device << 15) + \\r
+      (UINTN)(Function << 12) \\r
+    )\r
+\r
+//\r
+// UINT32\r
+//\r
+#define QNCMmPci32Ptr( Segment, Bus, Device, Function, Register ) \\r
+  ( (volatile UINT32 *)QNCMmPciAddress( Segment, Bus, Device, Function, Register ) )\r
+\r
+#define QNCMmPci32( Segment, Bus, Device, Function, Register ) \\r
+  *QNCMmPci32Ptr( Segment, Bus, Device, Function, Register )\r
+\r
+#define QNCMmPci32Or( Segment, Bus, Device, Function, Register, OrData ) \\r
+  QNCMmPci32( Segment, Bus, Device, Function, Register ) = \\r
+    (UINT32) ( \\r
+      QNCMmPci32( Segment, Bus, Device, Function, Register ) | \\r
+      (UINT32)(OrData) \\r
+    )\r
+\r
+#define QNCMmPci32And( Segment, Bus, Device, Function, Register, AndData ) \\r
+  QNCMmPci32( Segment, Bus, Device, Function, Register ) = \\r
+    (UINT32) ( \\r
+      QNCMmPci32( Segment, Bus, Device, Function, Register ) & \\r
+      (UINT32)(AndData) \\r
+    )\r
+\r
+#define QNCMmPci32AndThenOr( Segment, Bus, Device, Function, Register, AndData, OrData ) \\r
+  QNCMmPci32( Segment, Bus, Device, Function, Register ) = \\r
+    (UINT32) ( \\r
+      ( QNCMmPci32( Segment, Bus, Device, Function, Register ) & \\r
+          (UINT32)(AndData) \\r
+      ) | \\r
+      (UINT32)(OrData) \\r
+    )\r
+//\r
+// UINT16\r
+//\r
+#define QNCMmPci16Ptr( Segment, Bus, Device, Function, Register ) \\r
+  ( (volatile UINT16 *)QNCMmPciAddress( Segment, Bus, Device, Function, Register ) )\r
+\r
+#define QNCMmPci16( Segment, Bus, Device, Function, Register ) \\r
+  *QNCMmPci16Ptr( Segment, Bus, Device, Function, Register )\r
+\r
+#define QNCMmPci16Or( Segment, Bus, Device, Function, Register, OrData ) \\r
+  QNCMmPci16( Segment, Bus, Device, Function, Register ) = \\r
+    (UINT16) ( \\r
+      QNCMmPci16( Segment, Bus, Device, Function, Register ) | \\r
+      (UINT16)(OrData) \\r
+    )\r
+\r
+#define QNCMmPci16And( Segment, Bus, Device, Function, Register, AndData ) \\r
+  QNCMmPci16( Segment, Bus, Device, Function, Register ) = \\r
+    (UINT16) ( \\r
+      QNCMmPci16( Segment, Bus, Device, Function, Register ) & \\r
+      (UINT16)(AndData) \\r
+    )\r
+\r
+#define QNCMmPci16AndThenOr( Segment, Bus, Device, Function, Register, AndData, OrData ) \\r
+  QNCMmPci16( Segment, Bus, Device, Function, Register ) = \\r
+    (UINT16) ( \\r
+      ( QNCMmPci16( Segment, Bus, Device, Function, Register ) & \\r
+          (UINT16)(AndData) \\r
+      ) | \\r
+      (UINT16)(OrData) \\r
+    )\r
+//\r
+// UINT8\r
+//\r
+#define QNCMmPci8Ptr( Segment, Bus, Device, Function, Register ) \\r
+  ( (volatile UINT8 *)QNCMmPciAddress( Segment, Bus, Device, Function, Register ) )\r
+\r
+#define QNCMmPci8( Segment, Bus, Device, Function, Register ) \\r
+  *QNCMmPci8Ptr( Segment, Bus, Device, Function, Register )\r
+\r
+#define QNCMmPci8Or( Segment, Bus, Device, Function, Register, OrData ) \\r
+  QNCMmPci8( Segment, Bus, Device, Function, Register ) = \\r
+    (UINT8) ( \\r
+      QNCMmPci8( Segment, Bus, Device, Function, Register ) | \\r
+      (UINT8)(OrData) \\r
+    )\r
+\r
+#define QNCMmPci8And( Segment, Bus, Device, Function, Register, AndData ) \\r
+  QNCMmPci8( Segment, Bus, Device, Function, Register ) = \\r
+    (UINT8) ( \\r
+      QNCMmPci8( Segment, Bus, Device, Function, Register ) & \\r
+      (UINT8)(AndData) \\r
+    )\r
+\r
+#define QNCMmPci8AndThenOr( Segment, Bus, Device, Function, Register, AndData, OrData ) \\r
+  QNCMmPci8( Segment, Bus, Device, Function, Register ) = \\r
+    (UINT8) ( \\r
+      ( QNCMmPci8( Segment, Bus, Device, Function, Register ) & \\r
+          (UINT8)(AndData) \\r
+        ) | \\r
+      (UINT8)(OrData) \\r
+    )\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Include/QuarkNcSocId.h b/QuarkSocPkg/QuarkNorthCluster/Include/QuarkNcSocId.h
new file mode 100644 (file)
index 0000000..a9f3edd
--- /dev/null
@@ -0,0 +1,757 @@
+/** @file\r
+QuarkNcSocId Register Definitions\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Definitions beginning with "R_" are registers\r
+Definitions beginning with "B_" are bits within registers\r
+Definitions beginning with "V_" are meaningful values of bits within the registers\r
+Definitions beginning with "S_" are register sizes\r
+Definitions beginning with "N_" are the bit position\r
+\r
+**/\r
+\r
+#ifndef _QUARK_NC_SOC_ID_H_\r
+#define _QUARK_NC_SOC_ID_H_\r
+\r
+//\r
+// QNC GMCH Equates\r
+//\r
+\r
+//\r
+// DEVICE 0 (Memroy Controller Hub)\r
+//\r
+#define MC_BUS                  PCI_BUS_NUMBER_QNC\r
+#define MC_DEV                  0x00\r
+#define MC_FUN                  0x00\r
+\r
+#define   QUARK_MC_VENDOR_ID      V_INTEL_VENDOR_ID\r
+#define   QUARK_MC_DEVICE_ID      0x0958\r
+#define   QUARK2_MC_DEVICE_ID     0x12C0\r
+#define   QNC_MC_REV_ID_A0      0x00\r
+\r
+\r
+//\r
+// MCR - B0:D0:F0:RD0h (WO)- Message control register\r
+// [31:24] Message opcode - D0 read; E0 write;\r
+// [23:16] Message port\r
+// [15:8 ] Message target register address\r
+// [ 7:4 ] Message write byte enable : F is enable\r
+// [ 3:0 ] Reserved\r
+//\r
+#define QNC_ACCESS_PORT_MCR              0xD0          // Message Control Register\r
+// Always Set to 0xF0\r
+\r
+//\r
+//MDR - B0:D0:F0:RD4h (RW)- Message data register\r
+//\r
+#define QNC_ACCESS_PORT_MDR              0xD4          // Message Data Register\r
+\r
+//\r
+//MEA - B0:D0:F0:RD8h (RW)- Message extended address register\r
+//\r
+#define QNC_ACCESS_PORT_MEA              0xD8          // Message Extended Address Register\r
+\r
+#define  QNC_MCR_OP_OFFSET           24           // Offset of the opcode field in MCR\r
+#define  QNC_MCR_PORT_OFFSET         16           // Offset of the port field in MCR\r
+#define  QNC_MCR_REG_OFFSET          8            // Offset of the register field in MCR\r
+\r
+//\r
+// Misc Useful Macros\r
+//\r
+\r
+#define LShift16(value) (value << 16)\r
+\r
+//\r
+// QNC Message OpCodes and Attributes\r
+//\r
+#define QUARK_OPCODE_READ              0x10         // Quark message bus "read" opcode\r
+#define QUARK_OPCODE_WRITE             0x11         // Quark message bus "write" opcode\r
+\r
+//\r
+// Alternative opcodes for the SCSS block\r
+//\r
+#define QUARK_ALT_OPCODE_READ          0x06         // Quark message bus "read" opcode\r
+#define QUARK_ALT_OPCODE_WRITE         0x07         // Quark message bus "write" opcode\r
+\r
+//\r
+// QNC Message OpCodes and Attributes for IO\r
+//\r
+#define QUARK_OPCODE_IO_READ           0x02         // Quark message bus "IO read" opcode\r
+#define QUARK_OPCODE_IO_WRITE          0x03         // Quark message bus "IO write" opcode\r
+\r
+\r
+#define QUARK_DRAM_BASE_ADDR_READY     0x78         // Quark message bus "RMU Main binary shadow" opcode\r
+\r
+#define QUARK_ECC_SCRUB_RESUME         0xC2         // Quark Remote Management Unit "scrub resume" opcode\r
+#define QUARK_ECC_SCRUB_PAUSE          0xC3         // Quark Remote Management Unit "scrub pause" opcode\r
+\r
+//\r
+// QNC Message Ports and Registers\r
+//\r
+// Start of SB Port IDs\r
+#define QUARK_NC_MEMORY_ARBITER_SB_PORT_ID    0x00\r
+#define QUARK_NC_MEMORY_CONTROLLER_SB_PORT_ID 0x01\r
+#define QUARK_NC_HOST_BRIDGE_SB_PORT_ID       0x03\r
+#define QUARK_NC_RMU_SB_PORT_ID               0x04\r
+#define QUARK_NC_MEMORY_MANAGER_SB_PORT_ID    0x05\r
+#define QUARK_SC_USB_AFE_SB_PORT_ID           0x14\r
+#define QUARK_SC_PCIE_AFE_SB_PORT_ID          0x16\r
+#define QUARK_SCSS_SOC_UNIT_SB_PORT_ID        0x31\r
+#define QUARK_SCSS_FUSE_SB_PORT_ID            0x33\r
+#define QUARK_ICLK_SB_PORT_ID                 0x32\r
+#define QUARK_SCSS_CRU_SB_PORT_ID             0x34\r
+\r
+//\r
+// Quark Memory Arbiter Registers.\r
+//\r
+#define   QUARK_NC_MEMORY_ARBITER_REG_ASTATUS     0x21        // Memory Arbiter PRI Status encodings register.\r
+#define   ASTATUS_PRI_CASUAL                    0x0         // Serviced only if convenient\r
+#define   ASTATUS_PRI_IMPENDING                 0x1         // Serviced if the DRAM is in Self-Refresh.\r
+#define   ASTATUS_PRI_NORMAL                    0x2         // Normal request servicing.\r
+#define   ASTATUS_PRI_URGENT                    0x3         // Urgent request servicing.\r
+#define   ASTATUS1_RASISED_BP                   (10)\r
+#define   ASTATUS1_RASISED_BP_MASK              (0x03 << ASTATUS1_RASISED_BP)\r
+#define   ASTATUS0_RASISED_BP                   (8)\r
+#define   ASTATUS0_RASISED_BP_MASK              (0x03 << ASTATUS1_RASISED_BP)\r
+#define   ASTATUS1_DEFAULT_BP                   (2)\r
+#define   ASTATUS1_DEFAULT_BP_MASK              (0x03 << ASTATUS1_RASISED_BP)\r
+#define   ASTATUS0_DEFAULT_BP                   (0)\r
+#define   ASTATUS0_DEFAULT_BP_MASK              (0x03 << ASTATUS1_RASISED_BP)\r
+\r
+//\r
+// Quark Memory Controller Registers.\r
+//\r
+#define QUARK_NC_MEMORY_CONTROLLER_REG_DFUSESTAT  0x70        // Fuse status register.\r
+#define   B_DFUSESTAT_ECC_DIS                     (BIT0)    // Disable ECC.\r
+\r
+//\r
+// Quark Remote Management Unit Registers.\r
+//\r
+#define QNC_MSG_TMPM_REG_PMBA                   0x70        // Power Management I/O Base Address\r
+\r
+#define QUARK_NC_RMU_REG_CONFIG                   0x71        // Remote Management Unit configuration register.\r
+#define   TS_LOCK_AUX_TRIP_PT_REGS_ENABLE         (BIT6)\r
+#define   TS_LOCK_THRM_CTRL_REGS_ENABLE           (BIT5)\r
+\r
+#define QUARK_NC_RMU_REG_OPTIONS_1              0x72        // Remote Management Unit Options register 1.\r
+#define   OPTIONS_1_DMA_DISABLE                   (BIT0)\r
+\r
+#define QUARK_NC_RMU_REG_WDT_CONTROL              0x74        // Remote Management Unit Watchdog control register.\r
+#define   B_WDT_CONTROL_DBL_ECC_BIT_ERR_MASK      (BIT19 | BIT18)\r
+#define   B_WDT_CONTROL_DBL_ECC_BIT_ERR_BP        18\r
+#define   V_WDT_CONTROL_DBL_ECC_BIT_ERR_NONE      (0x0 << B_WDT_CONTROL_DBL_ECC_BIT_ERR_BP)\r
+#define   V_WDT_CONTROL_DBL_ECC_BIT_ERR_CAT       (0x1 << B_WDT_CONTROL_DBL_ECC_BIT_ERR_BP)\r
+#define   V_WDT_CONTROL_DBL_ECC_BIT_ERR_WARM      (0x2 << B_WDT_CONTROL_DBL_ECC_BIT_ERR_BP)\r
+#define   V_WDT_CONTROL_DBL_ECC_BIT_ERR_SERR      (0x3 << B_WDT_CONTROL_DBL_ECC_BIT_ERR_BP)\r
+\r
+#define QUARK_NC_RMU_REG_TS_MODE                  0xB0        // Remote Management Unit Thermal sensor mode register.\r
+#define   TS_ENABLE                               (BIT15)\r
+#define QUARK_NC_RMU_REG_TS_TRIP                  0xB2        // Remote Management Unit Thermal sensor programmable trip point register.\r
+#define   TS_HOT_TRIP_CLEAR_THOLD_BP              24\r
+#define   TS_HOT_TRIP_CLEAR_THOLD_MASK            (0xFF << TS_HOT_TRIP_CLEAR_THOLD_BP)\r
+#define   TS_CAT_TRIP_CLEAR_THOLD_BP              16\r
+#define   TS_CAT_TRIP_CLEAR_THOLD_MASK            (0xFF << TS_CAT_TRIP_CLEAR_THOLD_BP)\r
+#define   TS_HOT_TRIP_SET_THOLD_BP                8\r
+#define   TS_HOT_TRIP_SET_THOLD_MASK              (0xFF << TS_HOT_TRIP_SET_THOLD_BP)\r
+#define   TS_CAT_TRIP_SET_THOLD_BP                0\r
+#define   TS_CAT_TRIP_SET_THOLD_MASK              (0xFF << TS_CAT_TRIP_SET_THOLD_BP)\r
+\r
+#define QUARK_NC_ECC_SCRUB_CONFIG_REG             0x50\r
+#define   SCRUB_CFG_INTERVAL_SHIFT              0x00\r
+#define   SCRUB_CFG_INTERVAL_MASK               0xFF\r
+#define   SCRUB_CFG_BLOCKSIZE_SHIFT             0x08\r
+#define   SCRUB_CFG_BLOCKSIZE_MASK              0x1F\r
+#define   SCRUB_CFG_ACTIVE                      (BIT13)\r
+#define   SCRUB_CFG_INVALID                     0x00000FFF\r
+\r
+#define QUARK_NC_ECC_SCRUB_START_MEM_REG          0x76\r
+#define QUARK_NC_ECC_SCRUB_END_MEM_REG            0x77\r
+#define QUARK_NC_ECC_SCRUB_NEXT_READ_REG          0x7C\r
+\r
+#define SCRUB_RESUME_MSG() ((UINT32)( \\r
+          (QUARK_ECC_SCRUB_RESUME << QNC_MCR_OP_OFFSET) | \\r
+          (QUARK_NC_RMU_SB_PORT_ID << QNC_MCR_PORT_OFFSET) | \\r
+          0xF0))\r
+\r
+#define SCRUB_PAUSE_MSG() ((UINT32)( \\r
+          (QUARK_ECC_SCRUB_PAUSE << QNC_MCR_OP_OFFSET) | \\r
+          (QUARK_NC_RMU_SB_PORT_ID << QNC_MCR_PORT_OFFSET) | \\r
+          0xF0))\r
+\r
+//\r
+// Quark Memory Manager Registers\r
+//\r
+#define QUARK_NC_MEMORY_MANAGER_ESRAMPGCTRL_BLOCK     0x82\r
+#define   BLOCK_ENABLE_PG                           (1 << 28)\r
+#define   BLOCK_DISABLE_PG                          (1 << 29)\r
+#define QUARK_NC_MEMORY_MANAGER_BIMRVCTL              0x19\r
+#define   EnableIMRInt                                BIT31\r
+#define QUARK_NC_MEMORY_MANAGER_BSMMVCTL              0x1C\r
+#define   EnableSMMInt                                BIT31\r
+#define QUARK_NC_MEMORY_MANAGER_BTHCTRL               0x20\r
+#define   DRAM_NON_HOST_RQ_LIMIT_BP                   0\r
+#define   DRAM_NON_HOST_RQ_LIMIT_MASK                 (0x3f << DRAM_NON_HOST_RQ_LIMIT_BP)\r
+\r
+#define QUARK_NC_TOTAL_IMR_SET                        0x8\r
+#define QUARK_NC_MEMORY_MANAGER_IMR0                  0x40\r
+#define QUARK_NC_MEMORY_MANAGER_IMR1                  0x44\r
+#define QUARK_NC_MEMORY_MANAGER_IMR2                  0x48\r
+#define QUARK_NC_MEMORY_MANAGER_IMR3                  0x4C\r
+#define QUARK_NC_MEMORY_MANAGER_IMR4                  0x50\r
+#define QUARK_NC_MEMORY_MANAGER_IMR5                  0x54\r
+#define QUARK_NC_MEMORY_MANAGER_IMR6                  0x58\r
+#define QUARK_NC_MEMORY_MANAGER_IMR7                  0x5C\r
+  #define QUARK_NC_MEMORY_MANAGER_IMRXL               0x00\r
+    #define IMR_LOCK                                BIT31\r
+    #define IMR_EN                                  BIT30\r
+    #define IMRL_MASK                               0x00FFFFFC\r
+    #define IMRL_RESET                              0x00000000\r
+  #define QUARK_NC_MEMORY_MANAGER_IMRXH               0x01\r
+    #define IMRH_MASK                               0x00FFFFFC\r
+    #define IMRH_RESET                              0x00000000\r
+  #define QUARK_NC_MEMORY_MANAGER_IMRXRM              0x02\r
+  #define QUARK_NC_MEMORY_MANAGER_IMRXWM              0x03\r
+    #define IMRX_ALL_ACCESS                         0xFFFFFFFF\r
+    #define CPU_SNOOP                               BIT30\r
+    #define RMU                                     BIT29\r
+    #define CPU0_NON_SMM                            BIT0\r
+\r
+//\r
+// Quark Host Bridge Registers\r
+//\r
+#define QNC_MSG_FSBIC_REG_HMISC                0x03       // Host Misellaneous Controls\r
+#define   SMI_EN                              (BIT19)     // SMI Global Enable (from Legacy Bridge)\r
+#define QNC_MSG_FSBIC_REG_HSMMC                0x04       // Host SMM Control\r
+#define   NON_HOST_SMM_WR_OPEN                (BIT18)     // SMM Writes OPEN\r
+#define   NON_HOST_SMM_RD_OPEN                (BIT17)     // SMM Writes OPEN\r
+#define   SMM_CODE_RD_OPEN                    (BIT16)     // SMM Code read OPEN\r
+#define   SMM_CTL_EN                          (BIT3)      // SMM enable\r
+#define   SMM_WRITE_OPEN                      (BIT2)      // SMM Writes OPEN\r
+#define   SMM_READ_OPEN                       (BIT1)      // SMM Reads OPEN\r
+#define   SMM_LOCKED                          (BIT0)      // SMM Locked\r
+#define   SMM_START_MASK                      0x0000FFF0\r
+#define   SMM_END_MASK                        0xFFF00000\r
+#define QUARK_NC_HOST_BRIDGE_HMBOUND_REG              0x08\r
+#define   HMBOUND_MASK                        0x0FFFFF000\r
+#define   HMBOUND_LOCK                        BIT0\r
+#define QUARK_NC_HOST_BRIDGE_HLEGACY_REG              0x0A\r
+#define   HLEGACY_SMI_PIN_VALUE               BIT12\r
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_CAP            0x40\r
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE       0x41\r
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000        0x42\r
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX16K_80000        0x44\r
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX16K_A0000        0x46\r
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_C0000         0x48\r
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_C8000         0x4A\r
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_D0000         0x4C\r
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_D8000         0x4E\r
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_E0000         0x50\r
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_E8000         0x52\r
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F0000         0x54\r
+#define QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000         0x56\r
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_SMRR_PHYSBASE  0x58\r
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_SMRR_PHYSMASK  0x59\r
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0      0x5A\r
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK0      0x5B\r
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE1      0x5C\r
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK1      0x5D\r
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE2      0x5E\r
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK2      0x5F\r
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE3      0x60\r
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK3      0x61\r
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE4      0x62\r
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK4      0x63\r
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE5      0x64\r
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK5      0x65\r
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE6      0x66\r
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK6      0x67\r
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE7      0x68\r
+#define QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSMASK7      0x69\r
+\r
+//\r
+// System On Chip Unit (SOCUnit) Registers.\r
+//\r
+#define QUARK_SCSS_SOC_UNIT_STPDDRCFG           0x00\r
+#define   B_STPDDRCFG_FORCE_RECOVERY              BIT0\r
+#define QUARK_SCSS_SOC_UNIT_SPI_ROM_FUSE    0x25\r
+#define   B_ROM_FUSE_IN_SECURE_SKU              BIT6\r
+\r
+#define QUARK_SCSS_SOC_UNIT_TSCGF1_CONFIG       0x31\r
+#define   B_TSCGF1_CONFIG_ISNSCURRENTSEL_MASK   (BIT5 | BIT4 | BIT3)\r
+#define   B_TSCGF1_CONFIG_ISNSCURRENTSEL_BP     3\r
+#define   B_TSCGF1_CONFIG_ISNSCHOPSEL_MASK      (BIT12 | BIT11 | BIT10 | BIT9 | BIT8)\r
+#define   B_TSCGF1_CONFIG_ISNSCHOPSEL_BP        8\r
+#define   B_TSCGF1_CONFIG_IBGEN                 BIT17\r
+#define   B_TSCGF1_CONFIG_IBGEN_BP              17\r
+#define   B_TSCGF1_CONFIG_IBGCHOPEN             BIT18\r
+#define   B_TSCGF1_CONFIG_IBGCHOPEN_BP          18\r
+#define   B_TSCGF1_CONFIG_ISNSINTERNALVREFEN    BIT14\r
+#define   B_TSCGF1_CONFIG_ISNSINTERNALVREFEN_BP 14\r
+\r
+#define QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG       0x32\r
+#define   B_TSCGF2_CONFIG_IDSCONTROL_MASK       0x0000FFFF\r
+#define   B_TSCGF2_CONFIG_IDSCONTROL_BP         0\r
+#define   B_TSCGF2_CONFIG_IDSTIMING_MASK        0xFFFF0000\r
+#define   B_TSCGF2_CONFIG_IDSTIMING_BP          16\r
+\r
+#define QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG2      0x33\r
+#define   B_TSCGF2_CONFIG2_ISPARECTRL_MASK      0xFF000000\r
+#define   B_TSCGF2_CONFIG2_ISPARECTRL_BP        24\r
+#define   B_TSCGF2_CONFIG2_ICALCONFIGSEL_MASK   (BIT9 | BIT8)\r
+#define   B_TSCGF2_CONFIG2_ICALCONFIGSEL_BP     8\r
+#define   B_TSCGF2_CONFIG2_ICALCOARSETUNE_MASK  0x000000FF\r
+#define   B_TSCGF2_CONFIG2_ICALCOARSETUNE_BP    0\r
+\r
+#define QUARK_SCSS_SOC_UNIT_TSCGF3_CONFIG       0x34\r
+#define   B_TSCGF3_CONFIG_ITSRST                BIT0\r
+#define   B_TSCGF3_CONFIG_ITSGAMMACOEFF_BP      11\r
+#define   B_TSCGF3_CONFIG_ITSGAMMACOEFF_MASK    (0xFFF << B_TSCGF3_CONFIG_ITSGAMMACOEFF_BP)\r
+\r
+#define QUARK_SCSS_SOC_UNIT_SOCCLKEN_CONFIG     0x36\r
+#define   SOCCLKEN_CONFIG_PHY_I_SIDE_RST_L      BIT20\r
+#define   SOCCLKEN_CONFIG_PHY_I_CMNRESET_L      BIT19\r
+#define   SOCCLKEN_CONFIG_SBI_BB_RST_B          BIT18\r
+#define   SOCCLKEN_CONFIG_SBI_RST_100_CORE_B    BIT17\r
+#define   SOCCLKEN_CONFIG_BB_RST_B              BIT16\r
+\r
+#define QUARK_SCSS_SOC_UNIT_SOCCLKEN_CONFIG     0x36\r
+\r
+#define QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW       0x51\r
+#define   B_CFG_STICKY_RW_SMM_VIOLATION         BIT0\r
+#define   B_CFG_STICKY_RW_HMB_VIOLATION         BIT1\r
+#define   B_CFG_STICKY_RW_IMR_VIOLATION         BIT2\r
+#define   B_CFG_STICKY_RW_DECC_VIOLATION        BIT3\r
+#define   B_CFG_STICKY_RW_WARM_RST              BIT4\r
+#define   B_CFG_STICKY_RW_FORCE_RECOVERY        BIT9\r
+#define   B_CFG_STICKY_RW_VIOLATION             (B_CFG_STICKY_RW_SMM_VIOLATION | B_CFG_STICKY_RW_HMB_VIOLATION | B_CFG_STICKY_RW_IMR_VIOLATION | B_CFG_STICKY_RW_DECC_VIOLATION)\r
+#define   B_CFG_STICKY_RW_ALL                   (B_CFG_STICKY_RW_VIOLATION | B_CFG_STICKY_RW_WARM_RST)\r
+\r
+//\r
+// iCLK Registers.\r
+//\r
+#define QUARK_ICLK_MUXTOP                       0x0140\r
+#define   B_MUXTOP_FLEX2_MASK                   (BIT25 | BIT24 | BIT23)\r
+#define   B_MUXTOP_FLEX2_BP                     23\r
+#define   B_MUXTOP_FLEX1_MASK                   (BIT22 | BIT21 | BIT20)\r
+#define   B_MUXTOP_FLEX1_BP                     20\r
+\r
+#define QUARK_ICLK_SSC1                         0x0314\r
+#define QUARK_ICLK_SSC2                         0x0414\r
+#define QUARK_ICLK_SSC3                         0x0514\r
+#define QUARK_ICLK_REF2_DBUFF0                  0x2000\r
+\r
+//\r
+// PCIe AFE Unit Registers (QUARK_SC_PCIE_AFE_SB_PORT_ID).\r
+//\r
+#define QUARK_PCIE_AFE_PCIE_RXPICTRL0_L0        0x2080\r
+#define QUARK_PCIE_AFE_PCIE_RXPICTRL0_L1        0x2180\r
+#define   OCFGPIMIXLOAD_1_0                   BIT6\r
+#define   OCFGPIMIXLOAD_1_0_MASK              0xFFFFFF3F\r
+\r
+//\r
+// QNC ICH Equates\r
+//\r
+#define V_INTEL_VENDOR_ID              0x8086\r
+\r
+#define PCI_BUS_NUMBER_QNC              0x00\r
+\r
+//\r
+// PCI to LPC Bridge Registers (D31:F0)\r
+//\r
+#define PCI_DEVICE_NUMBER_QNC_LPC       31\r
+#define PCI_FUNCTION_NUMBER_QNC_LPC     0\r
+\r
+#define R_QNC_LPC_VENDOR_ID             0x00\r
+#define   V_LPC_VENDOR_ID             V_INTEL_VENDOR_ID\r
+#define R_QNC_LPC_DEVICE_ID             0x02\r
+#define   QUARK_V_LPC_DEVICE_ID_0           0x095E\r
+#define R_QNC_LPC_REV_ID                0x08\r
+\r
+#define R_QNC_LPC_SMBUS_BASE            0x40 //~0x43\r
+#define   B_QNC_LPC_SMBUS_BASE_EN         (BIT31)\r
+#define   B_QNC_LPC_SMBUS_BASE_MASK       0x0000FFC0 //[15:6]\r
+//\r
+// SMBus register offsets from SMBA - "SMBA" (D31:F0:R40h)\r
+//        Suggested Value for SMBA = 0x1040\r
+//\r
+#define R_QNC_SMBUS_HCTL                0x00   // Host Control Register R/W\r
+#define   B_QNC_SMBUS_START               (BIT4)   // Start/Stop\r
+#define     V_QNC_SMBUS_HCTL_CMD_QUICK               0\r
+#define     V_QNC_SMBUS_HCTL_CMD_BYTE                1\r
+#define     V_QNC_SMBUS_HCTL_CMD_BYTE_DATA           2\r
+#define     V_QNC_SMBUS_HCTL_CMD_WORD_DATA           3\r
+#define     V_QNC_SMBUS_HCTL_CMD_PROCESS_CALL        4\r
+#define     V_QNC_SMBUS_HCTL_CMD_BLOCK               5\r
+\r
+#define R_QNC_SMBUS_HSTS                0x01   // Host Status Register R/W\r
+#define   B_QNC_SMBUS_BERR                (BIT2)   // BUS Error\r
+#define   B_QNC_SMBUS_DERR                (BIT1)   // Device Error\r
+#define   B_QNC_SMBUS_BYTE_DONE_STS       (BIT0)   // Completion Status\r
+#define   B_QNC_SMBUS_HSTS_ALL            0x07\r
+\r
+#define R_QNC_SMBUS_HCLK                0x02   // Host Clock Divider Register R/W\r
+#define     V_QNC_SMBUS_HCLK_100KHZ         0x0054\r
+\r
+#define R_QNC_SMBUS_TSA                 0x04   // Transmit Slave Address Register R/W\r
+#define     V_QNC_SMBUS_RW_SEL_READ         1\r
+#define     V_QNC_SMBUS_RW_SEL_WRITE        0\r
+\r
+#define R_QNC_SMBUS_HCMD                0x05   // Host Command Register R/W\r
+#define R_QNC_SMBUS_HD0                 0x06   // Data 0 Register R/W\r
+#define R_QNC_SMBUS_HD1                 0x07   // Data 1 Register R/W\r
+#define R_QNC_SMBUS_HBD                 0x20   // Host Block Data Register R/W [255:0] ~ 3Fh\r
+\r
+#define R_QNC_LPC_GBA_BASE              0x44\r
+#define   B_QNC_LPC_GPA_BASE_MASK         0x0000FFC0\r
+//\r
+// GPIO register offsets from GBA - "GPIO" (D31:F0:R44h)\r
+//        Suggested Value for GBA = 0x1080\r
+//\r
+#define R_QNC_GPIO_CGEN_CORE_WELL       0x00\r
+#define R_QNC_GPIO_CGIO_CORE_WELL       0x04\r
+#define R_QNC_GPIO_CGLVL_CORE_WELL      0x08\r
+#define R_QNC_GPIO_CGTPE_CORE_WELL      0x0C   // Core well GPIO Trigger Positive Edge Enable\r
+#define R_QNC_GPIO_CGTNE_CORE_WELL      0x10   // Core well GPIO Trigger Negative Edge Enable\r
+#define R_QNC_GPIO_CGGPE_CORE_WELL      0x14   // Core well GPIO GPE Enable\r
+#define R_QNC_GPIO_CGSMI_CORE_WELL      0x18   // Core well GPIO SMI Enable\r
+#define R_QNC_GPIO_CGTS_CORE_WELL       0x1C   // Core well GPIO Trigger Status\r
+#define R_QNC_GPIO_RGEN_RESUME_WELL     0x20\r
+#define R_QNC_GPIO_RGIO_RESUME_WELL     0x24\r
+#define R_QNC_GPIO_RGLVL_RESUME_WELL    0x28\r
+#define R_QNC_GPIO_RGTPE_RESUME_WELL    0x2C   // Resume well GPIO Trigger Positive Edge Enable\r
+#define R_QNC_GPIO_RGTNE_RESUME_WELL    0x30   // Resume well GPIO Trigger Negative Edge Enable\r
+#define R_QNC_GPIO_RGGPE_RESUME_WELL    0x34   // Resume well GPIO GPE Enable\r
+#define R_QNC_GPIO_RGSMI_RESUME_WELL    0x38   // Resume well GPIO SMI Enable\r
+#define R_QNC_GPIO_RGTS_RESUME_WELL     0x3C   // Resume well GPIO Trigger Status\r
+#define R_QNC_GPIO_CNMIEN_CORE_WELL     0x40   // Core well GPIO NMI Enable\r
+#define R_QNC_GPIO_RNMIEN_RESUME_WELL   0x44   // Resume well GPIO NMI Enable\r
+\r
+#define R_QNC_LPC_PM1BLK                0x48\r
+#define   B_QNC_LPC_PM1BLK_MASK           0x0000FFF0\r
+//\r
+// ACPI register offsets from PM1BLK - "ACPI PM1 Block" (D31:F0:R48h)\r
+//        Suggested Value for PM1BLK = 0x1000\r
+//\r
+#define R_QNC_PM1BLK_PM1S               0x00\r
+#define  S_QNC_PM1BLK_PM1S               2\r
+#define   B_QNC_PM1BLK_PM1S_ALL           (BIT15+BIT14+BIT10+BIT5+BIT0)\r
+#define   B_QNC_PM1BLK_PM1S_WAKE          (BIT15)\r
+#define   B_QNC_PM1BLK_PM1S_PCIEWSTS      (BIT14)\r
+#define   B_QNC_PM1BLK_PM1S_RTC           (BIT10)\r
+#define   B_QNC_PM1BLK_PM1S_GLOB          (BIT5)\r
+#define   B_QNC_PM1BLK_PM1S_TO            (BIT0)\r
+#define    N_QNC_PM1BLK_PM1S_RTC           10\r
+\r
+\r
+#define R_QNC_PM1BLK_PM1E               0x02\r
+#define  S_QNC_PM1BLK_PM1E               2\r
+#define   B_QNC_PM1BLK_PM1E_PWAKED        (BIT14)\r
+#define   B_QNC_PM1BLK_PM1E_RTC           (BIT10)\r
+#define   B_QNC_PM1BLK_PM1E_GLOB          (BIT5)\r
+#define    N_QNC_PM1BLK_PM1E_RTC           10\r
+\r
+#define R_QNC_PM1BLK_PM1C               0x04\r
+#define   B_QNC_PM1BLK_PM1C_SLPEN         (BIT13)\r
+#define   B_QNC_PM1BLK_PM1C_SLPTP         (BIT12+BIT11+BIT10)\r
+#define    V_S0                           0x00000000\r
+#define    V_S3                           0x00001400\r
+#define    V_S4                           0x00001800\r
+#define    V_S5                           0x00001C00\r
+#define   B_QNC_PM1BLK_PM1C_SCIEN         (BIT0)\r
+\r
+#define R_QNC_PM1BLK_PM1T               0x08\r
+\r
+#define R_QNC_LPC_GPE0BLK               0x4C\r
+#define   B_QNC_LPC_GPE0BLK_MASK          0x0000FFC0\r
+//        Suggested Value for GPE0BLK = 0x10C0\r
+//\r
+#define R_QNC_GPE0BLK_GPE0S             0x00          // General Purpose Event 0 Status\r
+#define  S_QNC_GPE0BLK_GPE0S             4\r
+#define   B_QNC_GPE0BLK_GPE0S_ALL         0x00003F800 // used to clear the status reg\r
+#define   B_QNC_GPE0BLK_GPE0S_PCIE        (BIT17)     // PCIE\r
+#define   B_QNC_GPE0BLK_GPE0S_GPIO        (BIT14)     // GPIO\r
+#define   B_QNC_GPE0BLK_GPE0S_EGPE        (BIT13)     // External GPE\r
+#define    N_QNC_GPE0BLK_GPE0S_THRM        12\r
+\r
+#define R_QNC_GPE0BLK_GPE0E             0x04          // General Purpose Event 0 Enable\r
+#define  S_QNC_GPE0BLK_GPE0E             4\r
+#define   B_QNC_GPE0BLK_GPE0E_PCIE        (BIT17)     // PCIE\r
+#define   B_QNC_GPE0BLK_GPE0E_GPIO        (BIT14)     // GPIO\r
+#define   B_QNC_GPE0BLK_GPE0E_EGPE        (BIT13)     // External GPE\r
+#define    N_QNC_GPE0BLK_GPE0E_THRM        12\r
+\r
+#define R_QNC_GPE0BLK_SMIE              0x10          // SMI_B Enable\r
+#define  S_QNC_GPE0BLK_SMIE              4\r
+#define   B_QNC_GPE0BLK_SMIE_ALL          0x0003871F\r
+#define   B_QNC_GPE0BLK_SMIE_APM          (BIT4)      // APM\r
+#define   B_QNC_GPE0BLK_SMIE_SLP          (BIT2)      // Sleep\r
+#define   B_QNC_GPE0BLK_SMIE_SWT          (BIT1)      // Software Timer\r
+#define    N_QNC_GPE0BLK_SMIE_GPIO         9\r
+#define    N_QNC_GPE0BLK_SMIE_ESMI         8\r
+#define    N_QNC_GPE0BLK_SMIE_APM          4\r
+#define    N_QNC_GPE0BLK_SMIE_SPI          3\r
+#define    N_QNC_GPE0BLK_SMIE_SLP          2\r
+#define    N_QNC_GPE0BLK_SMIE_SWT          1\r
+\r
+#define R_QNC_GPE0BLK_SMIS              0x14           // SMI Status Register.\r
+#define  S_QNC_GPE0BLK_SMIS              4\r
+#define   B_QNC_GPE0BLK_SMIS_ALL          0x0003871F\r
+#define   B_QNC_GPE0BLK_SMIS_EOS          (BIT31)      // End of SMI\r
+#define   B_QNC_GPE0BLK_SMIS_APM          (BIT4)       // APM\r
+#define   B_QNC_GPE0BLK_SMIS_SPI          (BIT3)       // SPI\r
+#define   B_QNC_GPE0BLK_SMIS_SLP          (BIT2)       // Sleep\r
+#define   B_QNC_GPE0BLK_SMIS_SWT          (BIT1)       // Software Timer\r
+#define   B_QNC_GPE0BLK_SMIS_BIOS         (BIT0)       // BIOS\r
+#define    N_QNC_GPE0BLK_SMIS_GPIO         9\r
+#define    N_QNC_GPE0BLK_SMIS_APM          4\r
+#define    N_QNC_GPE0BLK_SMIS_SPI          3\r
+#define    N_QNC_GPE0BLK_SMIS_SLP          2\r
+#define    N_QNC_GPE0BLK_SMIS_SWT          1\r
+\r
+#define R_QNC_GPE0BLK_PMCW              0x28            // Power Management Configuration Core Well\r
+#define   B_QNC_GPE0BLK_PMCW_PSE          (BIT31)       // Periodic SMI Enable\r
+\r
+#define R_QNC_GPE0BLK_PMSW              0x2C            // Power Management Configuration Suspend/Resume Well\r
+#define    B_QNC_GPE0BLK_PMSW_DRAM_INIT   (BIT0)        // Dram Initialization Sctrachpad\r
+\r
+#define R_QNC_LPC_ACTL                  0x58\r
+#define    V_QNC_LPC_ACTL_SCIS_IRQ9        0x00\r
+\r
+//\r
+// Number of PIRQs supported. PIRQA~PIRQH\r
+//\r
+#define QNC_NUMBER_PIRQS                8\r
+#define R_QNC_LPC_PIRQA_ROUT            0x60\r
+#define R_QNC_LPC_PIRQB_ROUT            0x61\r
+#define R_QNC_LPC_PIRQC_ROUT            0x62\r
+#define R_QNC_LPC_PIRQD_ROUT            0x63\r
+#define R_QNC_LPC_PIRQE_ROUT            0x64\r
+#define R_QNC_LPC_PIRQF_ROUT            0x65\r
+#define R_QNC_LPC_PIRQG_ROUT            0x66\r
+#define R_QNC_LPC_PIRQH_ROUT            0x67\r
+\r
+//\r
+// Bit values are the same for R_TNC_LPC_PIRQA_ROUT to\r
+//                             R_TNC_LPC_PIRQH_ROUT\r
+#define   B_QNC_LPC_PIRQX_ROUT            (BIT3+BIT2+BIT1+BIT0)\r
+\r
+#define R_QNC_LPC_WDTBA                 0x84\r
+// Watchdog Timer register offsets from WDTBASE (in R_QNC_LPC_WDTBA)------------BEGIN\r
+#define R_QNC_LPC_WDT_WDTCR             0x10\r
+#define R_QNC_LPC_WDT_WDTLR             0x18\r
+// Watchdog Timer register offsets from WDTBASE (in R_QNC_LPC_WDTBA)--------------END\r
+\r
+#define R_QNC_LPC_FWH_BIOS_DEC          0xD4\r
+#define   B_QNC_LPC_FWH_BIOS_DEC_F8       (BIT31)\r
+#define   B_QNC_LPC_FWH_BIOS_DEC_F0       (BIT30)\r
+#define   B_QNC_LPC_FWH_BIOS_DEC_E8       (BIT29)\r
+#define   B_QNC_LPC_FWH_BIOS_DEC_E0       (BIT28)\r
+#define   B_QNC_LPC_FWH_BIOS_DEC_D8       (BIT27)\r
+#define   B_QNC_LPC_FWH_BIOS_DEC_D0       (BIT26)\r
+#define   B_QNC_LPC_FWH_BIOS_DEC_C8       (BIT25)\r
+#define   B_QNC_LPC_FWH_BIOS_DEC_C0       (BIT24)\r
+\r
+#define R_QNC_LPC_BIOS_CNTL             0xD8\r
+#define  S_QNC_LPC_BIOS_CNTL             4\r
+#define   B_QNC_LPC_BIOS_CNTL_PFE         (BIT8)\r
+#define   B_QNC_LPC_BIOS_CNTL_SMM_BWP     (BIT5)\r
+#define   B_QNC_LPC_BIOS_CNTL_BCD         (BIT2)\r
+#define   B_QNC_LPC_BIOS_CNTL_BLE         (BIT1)\r
+#define   B_QNC_LPC_BIOS_CNTL_BIOSWE      (BIT0)\r
+#define    N_QNC_LPC_BIOS_CNTL_BLE         1\r
+#define    N_QNC_LPC_BIOS_CNTL_BIOSWE      0\r
+\r
+#define R_QNC_LPC_RCBA                  0xF0\r
+#define   B_QNC_LPC_RCBA_MASK             0xFFFFC000\r
+#define   B_QNC_LPC_RCBA_EN               (BIT0)\r
+\r
+//---------------------------------------------------------------------------\r
+//  Fixed IO Decode on QuarkNcSocId\r
+//\r
+//  20h(2B) 24h(2B) 28h(2B) 2Ch(2B) 30h(2B) 34h(2B) 38h(2B) 3Ch(2B) : R/W 8259 master\r
+//  40h(3B): R/W 8254\r
+//  43h(1B): W   8254\r
+//  50h(3B): R/W 8254\r
+//  53h(1B): W   8254\r
+//  61h(1B): R/W NMI Controller\r
+//  63h(1B): R/W NMI Controller - can be disabled\r
+//  65h(1B): R/W NMI Controller - can be disabled\r
+//  67h(1B): R/W NMI Controller - can be disabled\r
+//  70h(1B): W   NMI & RTC\r
+//  71h(1B): R/W RTC\r
+//  72h(1B): R RTC; W NMI&RTC\r
+//  73h(1B): R/W RTC\r
+//  74h(1B): R RTC; W NMI&RTC\r
+//  75h(1B): R/W RTC\r
+//  76h(1B): R RTC; W NMI&RTC\r
+//  77h(1B): R/W RTC\r
+//  84h(3B): R/W Internal/LPC\r
+//  88h(1B): R/W Internal/LPC\r
+//  8Ch(3B): R/W Internal/LPC\r
+//  A0h(2B) A4h(2B) A8h(2B) ACh(2B) B0h(2B) B4h(2B) B8h(2B) BCh(2B): R/W 8259 slave\r
+//  B2h(1B) B3h(1B): R/W Power management\r
+//  3B0h-3BBh: R/W VGA\r
+//  3C0h-3DFh: R/W VGA\r
+//  CF8h(4B): R/W Internal\r
+//  CF9h(1B): R/W LPC\r
+//  CFCh(4B): R/W Internal\r
+//---------------------------------------------------------------------------\r
+\r
+#define R_APM_CNT                                       0xB2\r
+\r
+//\r
+// Reset Generator I/O Port\r
+//\r
+#define RST_CNT                                       0xCF9\r
+#define   B_RST_CNT_COLD_RST                            (BIT3)     // Cold reset\r
+#define   B_RST_CNT_WARM_RST                            (BIT1)     // Warm reset\r
+\r
+//\r
+// Processor interface registers (NMI)\r
+//\r
+\r
+#define  PCI_DEVICE_NUMBER_QNC_IOSF2AHB_0                20\r
+#define  PCI_DEVICE_NUMBER_QNC_IOSF2AHB_1                21\r
+#define  PCI_FUNCTION_NUMBER_QNC_IOSF2AHB                 0\r
+\r
+//\r
+// Pci Express Root Ports (D23:F0/F1)\r
+//\r
+#define PCI_DEVICE_NUMBER_PCIE_ROOTPORT                 23\r
+#define PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0             0\r
+#define PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1             1\r
+\r
+#define MAX_PCI_EXPRESS_ROOT_PORTS                      2\r
+\r
+#define R_QNC_PCIE_BNUM                             0x18\r
+#define R_QNC_PCIE_CAP_PTR                          0x34\r
+\r
+#define PCIE_CAPID                                  0x10  //PCIE Capability ID\r
+#define PCIE_CAP_EXT_HEARDER_OFFSET                 0x100 //PCIE Capability ID\r
+#define PCIE_DEV_CAP_OFFSET                         0x04 //PCIE Device Capability reg offset\r
+#define PCIE_LINK_CAP_OFFSET                        0x0C //PCIE Link Capability reg offset\r
+#define PCIE_LINK_CNT_OFFSET                        0x10 //PCIE Link control reg offset\r
+#define PCIE_LINK_STS_OFFSET                        0x12 //PCIE Link status reg offset\r
+#define PCIE_SLOT_CAP_OFFSET                        0x14 //PCIE Link Capability reg offset\r
+\r
+#define R_QNC_PCIE_XCAP                             0x42  //~ 43h\r
+#define   B_QNC_PCIE_XCAP_SI                          (BIT8)  //slot implemented\r
+#define R_QNC_PCIE_DCAP                             0x44  //~ 47h\r
+#define   B_QNC_PCIE_DCAP_E1AL                        (BIT11 | BIT10 | BIT9) // L1 Acceptable exit latency\r
+#define   B_QNC_PCIE_DCAP_E0AL                        (BIT8 | BIT7 | BIT6)   // L0 Acceptable exit latency\r
+#define R_QNC_PCIE_DCTL                             0x48  //~ 49h\r
+#define   B_QNC_PCIE_DCTL_URE                         (BIT3)  //Unsupported Request Reporting Enable\r
+#define   B_QNC_PCIE_DCTL_FEE                         (BIT2)  //Fatal error Reporting Enable\r
+#define   B_QNC_PCIE_DCTL_NFE                         (BIT1)  //Non Fatal error Reporting Enable\r
+#define   B_QNC_PCIE_DCTL_CEE                         (BIT0)  //Correctable error Reporting Enable\r
+#define R_QNC_PCIE_LCAP                             0x4C  //~ 4Fh\r
+#define   B_QNC_PCIE_LCAP_CPM                         (BIT18)  //clock power management supported\r
+#define   B_QNC_PCIE_LCAP_EL1_MASK                   (BIT17 | BIT16 | BIT15)  //L1 Exit latency mask\r
+#define   B_QNC_PCIE_LCAP_EL0_MASK                   (BIT14 | BIT13 | BIT12)  //L0 Exit latency mask\r
+#define   B_QNC_PCIE_LCAP_APMS_MASK                   (BIT11 | BIT10)  //Active state link PM support mask\r
+#define   V_QNC_PCIE_LCAP_APMS_OFFSET                 10  //Active state link PM support mask\r
+#define R_QNC_PCIE_LCTL                             0x50  //~ 51h\r
+#define   B_QNC_PCIE_LCTL_CCC                         (BIT6)  // Clock clock configuration\r
+#define   B_QNC_PCIE_LCTL_RL                          (BIT5)  // Retrain link\r
+#define R_QNC_PCIE_LSTS                             0x52  //~ 53h\r
+#define   B_QNC_PCIE_LSTS_SCC                         (BIT12) //Slot clock configuration\r
+#define   B_QNC_PCIE_LSTS_LT                          (BIT11) //Link training\r
+#define R_QNC_PCIE_SLCAP                            0x54  //~ 57h\r
+#define   B_QNC_PCIE_SLCAP_MASK_RSV_VALUE             0x0006007F\r
+#define   V_QNC_PCIE_SLCAP_SLV                        0x0A  //Slot power limit value [14:7]\r
+#define   V_QNC_PCIE_SLCAP_SLV_OFFSET                 7     //Slot power limit value offset is 7 [14:7]\r
+#define   V_QNC_PCIE_SLCAP_PSN_OFFSET                 19    //Slot number offset is 19 [31:19]\r
+#define R_QNC_PCIE_SLCTL                            0x58    //~ 59h\r
+#define   B_QNC_PCIE_SLCTL_HPE                        (BIT5)  // Hot plug interrupt enable\r
+#define   B_QNC_PCIE_SLCTL_PDE                        (BIT3)  // Presense detect change enable\r
+#define   B_QNC_PCIE_SLCTL_ABE                        (BIT0)  // Attention Button Pressed Enable\r
+#define R_QNC_PCIE_SLSTS                            0x5A    //~ 5Bh\r
+#define   B_QNC_PCIE_SLSTS_PDS                        (BIT6)  // Present Detect State = 1b : has device connected\r
+#define   B_QNC_PCIE_SLSTS_PDC                        (BIT3)  // Present Detect changed = 1b : PDS state has changed\r
+#define   B_QNC_PCIE_SLSTS_ABP                        (BIT0)  // Attention Button Pressed\r
+#define R_QNC_PCIE_RCTL                             0x5C    //~ 5Dh\r
+#define   B_QNC_PCIE_RCTL_PIE                         (BIT3)  //Root PCI-E PME Interrupt Enable\r
+#define   B_QNC_PCIE_RCTL_SFE                         (BIT2)  //Root PCI-E System Error on Fatal Error Enable\r
+#define   B_QNC_PCIE_RCTL_SNE                         (BIT1)  //Root PCI-E System Error on Non-Fatal Error Enable\r
+#define   B_QNC_PCIE_RCTL_SCE                         (BIT0)  //Root PCI-E System Error on Correctable Error Enable\r
+#define R_QNC_PCIE_SVID                             0x94  //~ 97h\r
+#define R_QNC_PCIE_CCFG                             0xD0  //~ D3h\r
+#define   B_QNC_PCIE_CCFG_UPSD                        (BIT24)  // Upstream Posted Split Disable\r
+#define   B_QNC_PCIE_CCFG_UNRS                        (BIT15)  // Upstream Non-Posted Request Size\r
+#define   B_QNC_PCIE_CCFG_UPRS                        (BIT14)  // Upstream Posted Request Size\r
+#define R_QNC_PCIE_MPC2                             0xD4  //~ D7h\r
+#define   B_QNC_PCIE_MPC2_IPF                         (BIT11)  // ISOF Packet Fast Transmit Mode\r
+#define R_QNC_PCIE_MPC                              0xD8  //~ DBh\r
+#define   B_QNC_PCIE_MPC_PMCE                         (BIT31)  // PM SCI Enable\r
+#define   B_QNC_PCIE_MPC_HPCE                         (BIT30)  // Hot plug SCI enable\r
+\r
+#define   B_QNC_PCIE_MPC_HPME                         (BIT1)   // Hot plug SMI enable\r
+#define   B_QNC_PCIE_MPC_PMME                         (BIT0)   // PM SMI Enable\r
+#define R_QNC_PCIE_IOSFSBCTL                        0xF6\r
+#define   B_QNC_PCIE_IOSFSBCTL_SBIC_MASK              (BIT1 | BIT0) // IOSF Sideband ISM Idle Counter.\r
+#define   B_QNC_PCIE_IOSFSBCTL_SBIC_IDLE_NEVER        (BIT1 | BIT0) // Never transition to IDLE.\r
+\r
+#define V_PCIE_MAX_TRY_TIMES                       200\r
+\r
+//\r
+// Misc PCI register offsets and sizes\r
+//\r
+#define R_EFI_PCI_SVID                              0x2C\r
+\r
+//\r
+// IO_APIC\r
+//\r
+#define IOAPIC_BASE                                 0xFEC00000\r
+#define IOAPIC_SIZE                                 0x1000\r
+\r
+//\r
+// Chipset configuration registers RCBA - "Root Complex Base Address" (D31:F0:RF0h)\r
+//            Suggested Value for  RCBA = 0xFED1C000\r
+//\r
+\r
+#define R_QNC_RCRB_SPIBASE                          0x3020       // SPI (Serial Peripheral Interface) in RCRB\r
+#define R_QNC_RCRB_SPIS                             (R_QNC_RCRB_SPIBASE + 0x00)  // SPI Status\r
+#define   B_QNC_RCRB_SPIS_SCL                       (BIT15)    // SPI Configuration Lockdown\r
+#define   B_QNC_RCRB_SPIS_BAS                       (BIT3)     // Blocked Access Status\r
+#define   B_QNC_RCRB_SPIS_CDS                       (BIT2)     // Cycle Done Status\r
+#define   B_QNC_RCRB_SPIS_SCIP                      (BIT0)     // SPI Cycle in Progress\r
+\r
+#define R_QNC_RCRB_SPIC                             (R_QNC_RCRB_SPIBASE + 0x02)  // SPI Control\r
+#define   B_QNC_RCRB_SPIC_DC                          (BIT14)    // SPI Data Cycle Enable\r
+#define   B_QNC_RCRB_SPIC_DBC                         0x3F00     // SPI Data Byte Count (1..8,16,24,32,40,48,56,64)\r
+#define   B_QNC_RCRB_SPIC_COP                         (BIT6+BIT5+BIT4)          // SPI Cycle Opcode Pointer\r
+#define   B_QNC_RCRB_SPIC_SPOP                        (BIT3)     // Sequence Prefix Opcode Pointer\r
+#define   B_QNC_RCRB_SPIC_ACS                         (BIT2)     // SPI Atomic Cycle Sequence\r
+#define   B_QNC_RCRB_SPIC_SCGO                        (BIT1)     // SPI Cycle Go\r
+\r
+#define R_QNC_RCRB_SPIA                             (R_QNC_RCRB_SPIBASE + 0x04)  // SPI Address\r
+#define   B_QNC_RCRB_SPIA_MASK                      0x00FFFFFF     // SPI Address mask\r
+#define R_QNC_RCRB_SPID0                            (R_QNC_RCRB_SPIBASE + 0x08)  // SPI Data 0\r
+#define R_QNC_RCRB_SPIPREOP                         (R_QNC_RCRB_SPIBASE + 0x54)  // Prefix Opcode Configuration\r
+#define R_QNC_RCRB_SPIOPTYPE                        (R_QNC_RCRB_SPIBASE + 0x56)  // Opcode Type Configuration\r
+#define   B_QNC_RCRB_SPIOPTYPE_NOADD_READ             0\r
+#define   B_QNC_RCRB_SPIOPTYPE_NOADD_WRITE            (BIT0)\r
+#define   B_QNC_RCRB_SPIOPTYPE_ADD_READ               (BIT1)\r
+#define   B_QNC_RCRB_SPIOPTYPE_ADD_WRITE              (BIT0 + BIT1)\r
+#define R_QNC_RCRB_SPIOPMENU                        (R_QNC_RCRB_SPIBASE + 0x58)  // Opcode Menu Configuration //R_OPMENU\r
+\r
+#define R_QNC_RCRB_SPIPBR0                          (R_QNC_RCRB_SPIBASE + 0x60)  // Protected BIOS Range 0.\r
+#define R_QNC_RCRB_SPIPBR1                          (R_QNC_RCRB_SPIBASE + 0x64)  // Protected BIOS Range 1.\r
+#define R_QNC_RCRB_SPIPBR2                          (R_QNC_RCRB_SPIBASE + 0x68)  // Protected BIOS Range 2.\r
+#define   B_QNC_RCRB_SPIPBRn_WPE                      (BIT31)                    // Write Protection Enable for above 3 registers.\r
+\r
+#define R_QNC_RCRB_AGENT0IR                         0x3140   // AGENT0 interrupt route\r
+#define R_QNC_RCRB_AGENT1IR                         0x3142   // AGENT1 interrupt route\r
+#define R_QNC_RCRB_AGENT2IR                         0x3144   // AGENT2 interrupt route\r
+#define R_QNC_RCRB_AGENT3IR                         0x3146   // AGENT3 interrupt route\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/CommonHeader.h b/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/CommonHeader.h
new file mode 100644 (file)
index 0000000..ba25fd1
--- /dev/null
@@ -0,0 +1,38 @@
+/** @file\r
+Common header file shared by all source files.\r
+\r
+This file includes package header files, library classes and protocol, PPI & GUID definitions.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#ifndef __COMMON_HEADER_H_\r
+#define __COMMON_HEADER_H_\r
+\r
+\r
+\r
+#include <PiPei.h>\r
+#include <IntelQNCBase.h>\r
+\r
+#include <Library/IntelQNCLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/CpuLib.h>\r
+#include <Library/PciCf8Lib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PciLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/QNCAccessLib.h>\r
+#include <IndustryStandard/Pci22.h>\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/IntelQNCLib.c b/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/IntelQNCLib.c
new file mode 100644 (file)
index 0000000..142b508
--- /dev/null
@@ -0,0 +1,777 @@
+/** @file\r
+Lib function for Pei QNC.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include "CommonHeader.h"\r
+\r
+/**\r
+  This function provides the necessary SOC initialization\r
+  before MRC running. It sets RCBA, GPIO, PMBASE\r
+  and some parts of SOC through SOC message method.\r
+  If the function cannot complete it'll ASSERT().\r
+**/\r
+VOID\r
+EFIAPI\r
+PeiQNCPreMemInit (\r
+  VOID\r
+  )\r
+{\r
+  UINT32                            RegValue;\r
+\r
+  // QNCPortWrite(Port#, Offset, Value)\r
+\r
+  //\r
+  // Set the fixed PRI Status encodings config.\r
+  //\r
+  QNCPortWrite (\r
+    QUARK_NC_MEMORY_ARBITER_SB_PORT_ID,\r
+    QUARK_NC_MEMORY_ARBITER_REG_ASTATUS,\r
+    QNC_FIXED_CONFIG_ASTATUS\r
+    );\r
+\r
+  // Sideband register write to Remote Management Unit\r
+  QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QNC_MSG_TMPM_REG_PMBA, (BIT31 | PcdGet16 (PcdPmbaIoBaseAddress)));\r
+\r
+  // Configurable I/O address in iLB (legacy block)\r
+\r
+  LpcPciCfg32 (R_QNC_LPC_SMBUS_BASE) = BIT31 | PcdGet16 (PcdSmbaIoBaseAddress);\r
+  LpcPciCfg32 (R_QNC_LPC_GBA_BASE) = BIT31 | PcdGet16 (PcdGbaIoBaseAddress);\r
+  LpcPciCfg32 (R_QNC_LPC_PM1BLK) = BIT31 | PcdGet16 (PcdPm1blkIoBaseAddress);\r
+  LpcPciCfg32 (R_QNC_LPC_GPE0BLK) = BIT31 | PcdGet16 (PcdGpe0blkIoBaseAddress);\r
+  LpcPciCfg32 (R_QNC_LPC_WDTBA) = BIT31 | PcdGet16 (PcdWdtbaIoBaseAddress);\r
+\r
+  //\r
+  // Program RCBA Base Address\r
+  //\r
+  LpcPciCfg32AndThenOr (R_QNC_LPC_RCBA, (~B_QNC_LPC_RCBA_MASK), (((UINT32)(PcdGet64 (PcdRcbaMmioBaseAddress))) | B_QNC_LPC_RCBA_EN));\r
+\r
+  //\r
+  // Program Memory Manager fixed config values.\r
+  //\r
+\r
+  RegValue = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_BTHCTRL);\r
+  RegValue &= ~(DRAM_NON_HOST_RQ_LIMIT_MASK);\r
+  RegValue |= (V_DRAM_NON_HOST_RQ_LIMIT << DRAM_NON_HOST_RQ_LIMIT_BP);\r
+  QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_BTHCTRL, RegValue);\r
+\r
+  //\r
+  // Program iCLK fixed config values.\r
+  //\r
+  QncIClkAndThenOr (\r
+    QUARK_ICLK_MUXTOP,\r
+    (UINT32) ~(B_MUXTOP_FLEX2_MASK | B_MUXTOP_FLEX1_MASK),\r
+    (V_MUXTOP_FLEX2 << B_MUXTOP_FLEX2_BP) | (V_MUXTOP_FLEX1 << B_MUXTOP_FLEX1_BP)\r
+    );\r
+  QncIClkAndThenOr (\r
+    QUARK_ICLK_REF2_DBUFF0,\r
+    (UINT32) ~(BIT0), // bit[0] cleared\r
+    0\r
+    );\r
+  QncIClkOr (\r
+    QUARK_ICLK_SSC1,\r
+    BIT0              // bit[0] set\r
+    );\r
+  QncIClkOr (\r
+    QUARK_ICLK_SSC2,\r
+    BIT0              // bit[0] set\r
+    );\r
+  QncIClkOr (\r
+    QUARK_ICLK_SSC3,\r
+    BIT0              // bit[0] set\r
+    );\r
+\r
+  //\r
+  // Set RMU DMA disable bit post boot.\r
+  //\r
+  RegValue = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_OPTIONS_1);\r
+  RegValue |= OPTIONS_1_DMA_DISABLE;\r
+  QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_OPTIONS_1, RegValue);\r
+}\r
+\r
+/**\r
+  Do north cluster init which needs to be done AFTER MRC init.\r
+\r
+  @param   VOID\r
+\r
+  @retval  VOID\r
+**/\r
+\r
+VOID\r
+EFIAPI\r
+PeiQNCPostMemInit (\r
+  VOID\r
+  )\r
+{\r
+  //\r
+  // Program SVID/SID the same as VID/DID for all devices except root ports.\r
+  //\r
+  QNCMmPci32(0, MC_BUS, MC_DEV, MC_FUN, R_EFI_PCI_SVID) = QNCMmPci32(0, MC_BUS, MC_DEV, MC_FUN, PCI_VENDOR_ID_OFFSET);\r
+  QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, PCI_FUNCTION_NUMBER_QNC_LPC, R_EFI_PCI_SVID) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, PCI_FUNCTION_NUMBER_QNC_LPC, PCI_VENDOR_ID_OFFSET);\r
+  QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_IOSF2AHB_0, PCI_FUNCTION_NUMBER_QNC_IOSF2AHB, R_EFI_PCI_SVID) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_IOSF2AHB_0, PCI_FUNCTION_NUMBER_QNC_IOSF2AHB, PCI_VENDOR_ID_OFFSET);\r
+  QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_IOSF2AHB_1, PCI_FUNCTION_NUMBER_QNC_IOSF2AHB, R_EFI_PCI_SVID) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_IOSF2AHB_1, PCI_FUNCTION_NUMBER_QNC_IOSF2AHB, PCI_VENDOR_ID_OFFSET);\r
+  return;\r
+}\r
+\r
+/**\r
+  Used to check QNC if it's S3 state.  Clear the register state after query.\r
+\r
+  @retval TRUE if it's S3 state.\r
+  @retval FALSE if it's not S3 state.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+QNCCheckS3AndClearState (\r
+   VOID\r
+  )\r
+{\r
+  BOOLEAN       S3WakeEventFound;\r
+  UINT16        Pm1Sts;\r
+  UINT16        Pm1En;\r
+  UINT16        Pm1Cnt;\r
+  UINT32        Gpe0Sts;\r
+  UINT32        Gpe0En;\r
+  UINT32        NewValue;\r
+  CHAR8         *EventDescStr;\r
+\r
+  S3WakeEventFound = FALSE;\r
+  EventDescStr = NULL;\r
+\r
+  //\r
+  // Read the ACPI registers,\r
+  //\r
+  Pm1Sts  = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1S);\r
+  Pm1En   = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E);\r
+  Pm1Cnt  = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);\r
+  Gpe0Sts = IoRead32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0S);\r
+  Gpe0En  = IoRead32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0E);\r
+\r
+  //\r
+  // Clear Power Management 1 Enable Register and\r
+  // General Purpost Event 0 Enables Register\r
+  //\r
+  IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E, 0);\r
+  IoWrite32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0E, 0);\r
+\r
+  if ((Pm1Sts & B_QNC_PM1BLK_PM1S_WAKE) != 0 && (Pm1Cnt & B_QNC_PM1BLK_PM1C_SLPTP) == V_S3) {\r
+\r
+    //\r
+    // Detect the actual WAKE event\r
+    //\r
+    if ((Pm1Sts & B_QNC_PM1BLK_PM1S_RTC) && (Pm1En & B_QNC_PM1BLK_PM1E_RTC)) {\r
+      EventDescStr = "RTC Alarm";\r
+      S3WakeEventFound = TRUE;\r
+    }\r
+    if ((Pm1Sts & B_QNC_PM1BLK_PM1S_PCIEWSTS) && !(Pm1En & B_QNC_PM1BLK_PM1E_PWAKED)) {\r
+      EventDescStr = "PCIe WAKE";\r
+      S3WakeEventFound = TRUE;\r
+    }\r
+    if ((Gpe0Sts & B_QNC_GPE0BLK_GPE0S_PCIE) && (Gpe0En & B_QNC_GPE0BLK_GPE0E_PCIE)) {\r
+      EventDescStr = "PCIe";\r
+      S3WakeEventFound = TRUE;\r
+    }\r
+    if ((Gpe0Sts & B_QNC_GPE0BLK_GPE0S_GPIO) && (Gpe0En & B_QNC_GPE0BLK_GPE0E_GPIO)) {\r
+      EventDescStr = "GPIO";\r
+      S3WakeEventFound = TRUE;\r
+    }\r
+    if ((Gpe0Sts & B_QNC_GPE0BLK_GPE0S_EGPE) && (Gpe0En & B_QNC_GPE0BLK_GPE0E_EGPE)) {\r
+      EventDescStr = "Ext. GPE";\r
+      S3WakeEventFound = TRUE;\r
+    }\r
+    if (S3WakeEventFound == FALSE) {\r
+      EventDescStr = "Unknown";\r
+    }\r
+    DEBUG ((EFI_D_INFO, "S3 Wake Event - %a\n", EventDescStr));\r
+\r
+    //\r
+    // If no Power Button Override event occurs and one enabled wake event occurs,\r
+    // just do S3 resume and clear the state.\r
+    //\r
+    IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, (Pm1Cnt & (~B_QNC_PM1BLK_PM1C_SLPTP)));\r
+\r
+    //\r
+    // Set EOS to de Assert SMI\r
+    //\r
+    IoWrite32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS,  B_QNC_GPE0BLK_SMIS_EOS);\r
+\r
+    //\r
+    // Enable SMI globally\r
+    //\r
+    NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);\r
+    NewValue |= SMI_EN;\r
+    QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);\r
+\r
+    return  TRUE;\r
+  }\r
+\r
+  return  FALSE;\r
+}\r
+\r
+/**\r
+  Used to check QNC if system wakes up from power on reset. Clear the register state after query.\r
+\r
+  @retval TRUE  if system wakes up from power on reset\r
+  @retval FALSE if system does not wake up from power on reset\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+QNCCheckPowerOnResetAndClearState (\r
+   VOID\r
+  )\r
+{\r
+  UINT16                Pm1Sts;\r
+  UINT16                Pm1Cnt;\r
+\r
+  //\r
+  // Read the ACPI registers,\r
+  // PM1_STS information cannot be lost after power down, unless CMOS is cleared.\r
+  //\r
+  Pm1Sts  = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1S);\r
+  Pm1Cnt  = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);\r
+\r
+  //\r
+  // If B_SLP_TYP is S5\r
+  //\r
+  if ((Pm1Sts & B_QNC_PM1BLK_PM1S_WAKE) != 0 && (Pm1Cnt & B_QNC_PM1BLK_PM1C_SLPTP) == V_S5) {\r
+    IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, (Pm1Cnt & (~B_QNC_PM1BLK_PM1C_SLPTP)));\r
+    return  TRUE;\r
+  }\r
+\r
+  return  FALSE;\r
+}\r
+\r
+/**\r
+  This function is used to clear SMI and wake status.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+QNCClearSmiAndWake (\r
+  VOID\r
+  )\r
+{\r
+  UINT32    Gpe0Sts;\r
+  UINT32    SmiSts;\r
+\r
+  //\r
+  // Read the ACPI registers\r
+  //\r
+  Gpe0Sts = IoRead32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0S);\r
+  SmiSts  = IoRead32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS);\r
+\r
+  //\r
+  // Clear any SMI or wake state from the boot\r
+  //\r
+  Gpe0Sts |= B_QNC_GPE0BLK_GPE0S_ALL;\r
+  SmiSts  |= B_QNC_GPE0BLK_SMIS_ALL;\r
+\r
+  //\r
+  // Write them back\r
+  //\r
+  IoWrite32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0S, Gpe0Sts);\r
+  IoWrite32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS,  SmiSts);\r
+}\r
+\r
+/** Send DRAM Ready opcode.\r
+\r
+  @param[in]       OpcodeParam  Parameter to DRAM ready opcode.\r
+\r
+  @retval          VOID\r
+**/\r
+VOID\r
+EFIAPI\r
+QNCSendOpcodeDramReady (\r
+  IN UINT32   OpcodeParam\r
+  )\r
+{\r
+\r
+  //\r
+  // Before sending DRAM ready place invalid value in Scrub Config.\r
+  //\r
+  QNCPortWrite (\r
+    QUARK_NC_RMU_SB_PORT_ID,\r
+    QUARK_NC_ECC_SCRUB_CONFIG_REG,\r
+    SCRUB_CFG_INVALID\r
+    );\r
+\r
+  //\r
+  // Send opcode and use param to notify HW of new RMU firmware location.\r
+  //\r
+  McD0PciCfg32 (QNC_ACCESS_PORT_MDR) = OpcodeParam;\r
+  McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_SHADOW_DW (QUARK_NC_RMU_SB_PORT_ID, 0);\r
+\r
+  //\r
+  // HW completed tasks on DRAM ready when scrub config read back as zero.\r
+  //\r
+  while (QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_CONFIG_REG) != 0) {\r
+    MicroSecondDelay (10);\r
+  }\r
+}\r
+\r
+/**\r
+\r
+  Relocate RMU Main binary to memory after MRC to improve performance.\r
+\r
+  @param[in]  DestBaseAddress  - Specify the new memory address for the RMU Main binary.\r
+  @param[in]  SrcBaseAddress   - Specify the current memory address for the RMU Main binary.\r
+  @param[in]  Size             - Specify size of the RMU Main binary.\r
+\r
+  @retval     VOID\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+RmuMainRelocation (\r
+  IN CONST UINT32   DestBaseAddress,\r
+  IN CONST UINT32   SrcBaseAddress,\r
+  IN CONST UINTN    Size\r
+  )\r
+{\r
+  //\r
+  // Shadow RMU Main binary into main memory.\r
+  //\r
+  CopyMem ((VOID *)(UINTN)DestBaseAddress,(VOID *)(UINTN) SrcBaseAddress, Size);\r
+}\r
+\r
+\r
+/**\r
+  Get the total memory size\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+QNCGetTotalMemorysize (\r
+  VOID\r
+  )\r
+{\r
+  return  QNCPortRead(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_HMBOUND_REG) & HMBOUND_MASK;\r
+}\r
+\r
+\r
+/**\r
+  Get the memory range of TSEG.\r
+  The TSEG's memory is below TOLM.\r
+\r
+  @param[out] BaseAddress The base address of TSEG's memory range\r
+  @param[out] MemorySize  The size of TSEG's memory range\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+QNCGetTSEGMemoryRange (\r
+  OUT UINT64  *BaseAddress,\r
+  OUT UINT64  *MemorySize\r
+  )\r
+{\r
+  UINT64 Register = 0;\r
+  UINT64 SMMAddress = 0;\r
+\r
+  Register = QncHsmmcRead ();\r
+\r
+  //\r
+  // Get the SMRAM Base address\r
+  //\r
+  SMMAddress = Register & SMM_START_MASK;\r
+  *BaseAddress = LShift16 (SMMAddress);\r
+\r
+  //\r
+  // Get the SMRAM size\r
+  //\r
+  SMMAddress = ((Register & SMM_END_MASK) | (~SMM_END_MASK)) + 1;\r
+  *MemorySize = SMMAddress - (*BaseAddress);\r
+\r
+  DEBUG ((\r
+    EFI_D_INFO,\r
+    "TSEG's memory range: BaseAddress = 0x%x, Size = 0x%x\n",\r
+    (UINT32)*BaseAddress,\r
+    (UINT32)*MemorySize\r
+    ));\r
+}\r
+\r
+/**\r
+  Updates the PAM registers in the MCH for the requested range and mode.\r
+\r
+  @param   Start        The start address of the memory region\r
+  @param   Length       The length, in bytes, of the memory region\r
+  @param   ReadEnable   Pointer to the boolean variable on whether to enable read for legacy memory section.\r
+                        If NULL, then read attribute will not be touched by this call.\r
+  @param   ReadEnable   Pointer to the boolean variable on whether to enable write for legacy memory section.\r
+                        If NULL, then write attribute will not be touched by this call.\r
+  @param   Granularity  A pointer to granularity, in bytes, that the PAM registers support\r
+\r
+  @retval  RETURN_SUCCESS            The PAM registers in the MCH were updated\r
+  @retval  RETURN_INVALID_PARAMETER  The memory range is not valid in legacy region.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+QNCLegacyRegionManipulation (\r
+  IN  UINT32                  Start,\r
+  IN  UINT32                  Length,\r
+  IN  BOOLEAN                 *ReadEnable,\r
+  IN  BOOLEAN                 *WriteEnable,\r
+  OUT UINT32                  *Granularity\r
+  )\r
+{\r
+  //\r
+  // Do nothing cos no such support on QNC\r
+  //\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Determine if QNC is supported.\r
+\r
+  @retval FALSE  QNC is not supported.\r
+  @retval TRUE   QNC is supported.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsQncSupported (\r
+  VOID\r
+  )\r
+{\r
+  UINT16  SocVendorId;\r
+  UINT16  SocDeviceId;\r
+\r
+  SocVendorId = MmioRead16 (\r
+                  PciDeviceMmBase (MC_BUS,\r
+                  MC_DEV,\r
+                  MC_FUN) + PCI_VENDOR_ID_OFFSET\r
+                  );\r
+\r
+  SocDeviceId = QncGetSocDeviceId();\r
+\r
+  //\r
+  // Verify that this is a supported chipset\r
+  //\r
+  if ((SocVendorId != QUARK_MC_VENDOR_ID) || ((SocDeviceId != QUARK_MC_DEVICE_ID) && (SocDeviceId != QUARK2_MC_DEVICE_ID))) {\r
+    DEBUG ((DEBUG_ERROR, "QNC code doesn't support the Soc VendorId:0x%04x Soc DeviceId:0x%04x!\n", SocVendorId, SocDeviceId));\r
+    return FALSE;\r
+  }\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Get the DeviceId of the SoC\r
+\r
+  @retval PCI DeviceId of the SoC\r
+**/\r
+UINT16\r
+EFIAPI\r
+QncGetSocDeviceId (\r
+  VOID\r
+  )\r
+{\r
+  UINT16  SocDeviceId;\r
+\r
+  SocDeviceId = MmioRead16 (\r
+                  PciDeviceMmBase (\r
+                    MC_BUS,\r
+                    MC_DEV,\r
+                    MC_FUN\r
+                    ) + PCI_DEVICE_ID_OFFSET\r
+                  );\r
+\r
+  return SocDeviceId;\r
+}\r
+\r
+/**\r
+  Enable SMI detection of legacy flash access violations.\r
+**/\r
+VOID\r
+EFIAPI\r
+QncEnableLegacyFlashAccessViolationSmi (\r
+  VOID\r
+  )\r
+{\r
+  UINT32  BcValue;\r
+\r
+  BcValue = LpcPciCfg32 (R_QNC_LPC_BIOS_CNTL);\r
+\r
+  //\r
+  // Clear BIOSWE & set BLE.\r
+  //\r
+  BcValue &= (~B_QNC_LPC_BIOS_CNTL_BIOSWE);\r
+  BcValue |= (B_QNC_LPC_BIOS_CNTL_BLE);\r
+\r
+  LpcPciCfg32 (R_QNC_LPC_BIOS_CNTL) = BcValue;\r
+\r
+  DEBUG ((EFI_D_INFO, "BIOS Control Lock Enabled!\n"));\r
+}\r
+\r
+/**\r
+  Setup RMU Thermal sensor registers for Vref mode.\r
+**/\r
+VOID\r
+EFIAPI\r
+QNCThermalSensorSetVRefMode (\r
+  VOID\r
+  )\r
+{\r
+  UINT32                             Tscgf1Config;\r
+  UINT32                             Tscgf2Config;\r
+  UINT32                             Tscgf2Config2;\r
+\r
+  Tscgf1Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF1_CONFIG);\r
+  Tscgf2Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG);\r
+  Tscgf2Config2 = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG2);\r
+\r
+  Tscgf1Config &= ~(B_TSCGF1_CONFIG_ISNSCURRENTSEL_MASK);\r
+  Tscgf1Config |= (V_TSCGF1_CONFIG_ISNSCURRENTSEL_VREF_MODE << B_TSCGF1_CONFIG_ISNSCURRENTSEL_BP);\r
+\r
+  Tscgf1Config &= ~(B_TSCGF1_CONFIG_IBGEN);\r
+  Tscgf1Config |= (V_TSCGF1_CONFIG_IBGEN_VREF_MODE << B_TSCGF1_CONFIG_IBGEN_BP);\r
+\r
+  Tscgf2Config2 &= ~(B_TSCGF2_CONFIG2_ISPARECTRL_MASK);\r
+  Tscgf2Config2 |= (V_TSCGF2_CONFIG2_ISPARECTRL_VREF_MODE << B_TSCGF2_CONFIG2_ISPARECTRL_BP);\r
+\r
+  Tscgf2Config2 &= ~(B_TSCGF2_CONFIG2_ICALCOARSETUNE_MASK);\r
+  Tscgf2Config2 |= (V_TSCGF2_CONFIG2_ICALCOARSETUNE_VREF_MODE << B_TSCGF2_CONFIG2_ICALCOARSETUNE_BP);\r
+\r
+  Tscgf2Config &= ~(B_TSCGF2_CONFIG_IDSCONTROL_MASK);\r
+  Tscgf2Config |= (V_TSCGF2_CONFIG_IDSCONTROL_VREF_MODE << B_TSCGF2_CONFIG_IDSCONTROL_BP);\r
+\r
+  QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF1_CONFIG, Tscgf1Config);\r
+  QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG, Tscgf2Config);\r
+  QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG2, Tscgf2Config2);\r
+}\r
+\r
+/**\r
+  Setup RMU Thermal sensor registers for Ratiometric mode.\r
+**/\r
+VOID\r
+EFIAPI\r
+QNCThermalSensorSetRatiometricMode (\r
+  VOID\r
+  )\r
+{\r
+  UINT32                             Tscgf1Config;\r
+  UINT32                             Tscgf2Config;\r
+  UINT32                             Tscgf2Config2;\r
+  UINT32                             Tscgf3Config;\r
+\r
+  Tscgf1Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF1_CONFIG);\r
+  Tscgf2Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG);\r
+  Tscgf2Config2 = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG2);\r
+  Tscgf3Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF3_CONFIG);\r
+\r
+  Tscgf1Config &= ~(B_TSCGF1_CONFIG_ISNSCURRENTSEL_MASK);\r
+  Tscgf1Config |= (V_TSCGF1_CONFIG_ISNSCURRENTSEL_RATIO_MODE << B_TSCGF1_CONFIG_ISNSCURRENTSEL_BP);\r
+\r
+  Tscgf1Config &= ~(B_TSCGF1_CONFIG_ISNSCHOPSEL_MASK);\r
+  Tscgf1Config |= (V_TSCGF1_CONFIG_ISNSCHOPSEL_RATIO_MODE  << B_TSCGF1_CONFIG_ISNSCHOPSEL_BP);\r
+\r
+  Tscgf1Config &= ~(B_TSCGF1_CONFIG_ISNSINTERNALVREFEN);\r
+  Tscgf1Config |= (V_TSCGF1_CONFIG_ISNSINTERNALVREFEN_RATIO_MODE << B_TSCGF1_CONFIG_ISNSINTERNALVREFEN_BP);\r
+\r
+  Tscgf1Config &= ~(B_TSCGF1_CONFIG_IBGEN);\r
+  Tscgf1Config |= (V_TSCGF1_CONFIG_IBGEN_RATIO_MODE << B_TSCGF1_CONFIG_IBGEN_BP);\r
+\r
+  Tscgf1Config &= ~(B_TSCGF1_CONFIG_IBGCHOPEN);\r
+  Tscgf1Config |= (V_TSCGF1_CONFIG_IBGCHOPEN_RATIO_MODE << B_TSCGF1_CONFIG_IBGCHOPEN_BP);\r
+\r
+  Tscgf2Config2 &= ~(B_TSCGF2_CONFIG2_ICALCONFIGSEL_MASK);\r
+  Tscgf2Config2 |= (V_TSCGF2_CONFIG2_ICALCONFIGSEL_RATIO_MODE << B_TSCGF2_CONFIG2_ICALCONFIGSEL_BP);\r
+\r
+  Tscgf2Config2 &= ~(B_TSCGF2_CONFIG2_ISPARECTRL_MASK);\r
+  Tscgf2Config2 |= (V_TSCGF2_CONFIG2_ISPARECTRL_RATIO_MODE << B_TSCGF2_CONFIG2_ISPARECTRL_BP);\r
+\r
+  Tscgf2Config2 &= ~(B_TSCGF2_CONFIG2_ICALCOARSETUNE_MASK);\r
+  Tscgf2Config2 |= (V_TSCGF2_CONFIG2_ICALCOARSETUNE_RATIO_MODE << B_TSCGF2_CONFIG2_ICALCOARSETUNE_BP);\r
+\r
+  Tscgf2Config &= ~(B_TSCGF2_CONFIG_IDSCONTROL_MASK);\r
+  Tscgf2Config |= (V_TSCGF2_CONFIG_IDSCONTROL_RATIO_MODE << B_TSCGF2_CONFIG_IDSCONTROL_BP);\r
+\r
+  Tscgf2Config &= ~(B_TSCGF2_CONFIG_IDSTIMING_MASK);\r
+  Tscgf2Config |= (V_TSCGF2_CONFIG_IDSTIMING_RATIO_MODE << B_TSCGF2_CONFIG_IDSTIMING_BP);\r
+\r
+  Tscgf3Config &= ~(B_TSCGF3_CONFIG_ITSGAMMACOEFF_MASK);\r
+  Tscgf3Config |= (V_TSCGF3_CONFIG_ITSGAMMACOEFF_RATIO_MODE << B_TSCGF3_CONFIG_ITSGAMMACOEFF_BP);\r
+\r
+  QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF1_CONFIG, Tscgf1Config);\r
+  QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG, Tscgf2Config);\r
+  QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG2, Tscgf2Config2);\r
+  QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF3_CONFIG, Tscgf3Config);\r
+}\r
+\r
+/**\r
+  Setup RMU Thermal sensor trip point values.\r
+\r
+  @param[in]  CatastrophicTripOnDegreesCelsius  - Catastrophic set trip point threshold.\r
+  @param[in]  HotTripOnDegreesCelsius           - Hot set trip point threshold.\r
+  @param[in]  HotTripOffDegreesCelsius          - Hot clear trip point threshold.\r
+\r
+  @retval  EFI_SUCCESS            Trip points setup.\r
+  @retval  EFI_INVALID_PARAMETER  Invalid trip point value.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+QNCThermalSensorSetTripValues (\r
+  IN  CONST UINTN             CatastrophicTripOnDegreesCelsius,\r
+  IN  CONST UINTN             HotTripOnDegreesCelsius,\r
+  IN  CONST UINTN             HotTripOffDegreesCelsius\r
+  )\r
+{\r
+  UINT32 RegisterValue;\r
+\r
+  //\r
+  // Register fields are 8-bit temperature values of granularity 1 degree C\r
+  // where 0x00 corresponds to -50 degrees C\r
+  // and 0xFF corresponds to 205 degrees C.\r
+  //\r
+  // User passes unsigned values in degrees Celsius so trips < 0 not supported.\r
+  //\r
+  // Add 50 to user values to get values for register fields.\r
+  //\r
+\r
+  if ((CatastrophicTripOnDegreesCelsius > 205) || (HotTripOnDegreesCelsius > 205) || (HotTripOffDegreesCelsius > 205)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Set new values.\r
+  //\r
+  RegisterValue =\r
+    ((0 + 50) << TS_CAT_TRIP_CLEAR_THOLD_BP) | // Cat Trip Clear value must be less than Cat Trip Set Value.\r
+    ((CatastrophicTripOnDegreesCelsius + 50) << TS_CAT_TRIP_SET_THOLD_BP) |\r
+    ((HotTripOnDegreesCelsius + 50) << TS_HOT_TRIP_SET_THOLD_BP) |\r
+    ((HotTripOffDegreesCelsius + 50) << TS_HOT_TRIP_CLEAR_THOLD_BP)\r
+    ;\r
+\r
+  QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_TS_TRIP, RegisterValue);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Enable RMU Thermal sensor with a Catastrophic Trip point.\r
+\r
+  @retval  EFI_SUCCESS            Trip points setup.\r
+  @retval  EFI_INVALID_PARAMETER  Invalid trip point value.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+QNCThermalSensorEnableWithCatastrophicTrip (\r
+  IN  CONST UINTN             CatastrophicTripOnDegreesCelsius\r
+  )\r
+{\r
+  UINT32                             Tscgf3Config;\r
+  UINT32                             TsModeReg;\r
+  UINT32                             TsTripReg;\r
+\r
+  //\r
+  // Trip Register fields are 8-bit temperature values of granularity 1 degree C\r
+  // where 0x00 corresponds to -50 degrees C\r
+  // and 0xFF corresponds to 205 degrees C.\r
+  //\r
+  // User passes unsigned values in degrees Celsius so trips < 0 not supported.\r
+  //\r
+  // Add 50 to user values to get values for register fields.\r
+  //\r
+\r
+  if (CatastrophicTripOnDegreesCelsius > 205) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Tscgf3Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF3_CONFIG);\r
+  TsModeReg = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_TS_MODE);\r
+  TsTripReg = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_TS_TRIP);\r
+\r
+  //\r
+  // Setup Catastrophic Trip point.\r
+  //\r
+  TsTripReg &= ~(TS_CAT_TRIP_SET_THOLD_MASK);\r
+  TsTripReg |= ((CatastrophicTripOnDegreesCelsius + 50) << TS_CAT_TRIP_SET_THOLD_BP);\r
+  TsTripReg &= ~(TS_CAT_TRIP_CLEAR_THOLD_MASK);\r
+  TsTripReg |= ((0 + 50) << TS_CAT_TRIP_CLEAR_THOLD_BP);  // Cat Trip Clear value must be less than Cat Trip Set Value.\r
+  QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_TS_TRIP, TsTripReg);\r
+\r
+  //\r
+  // To enable the TS do the following:\r
+  //    1)  Take the TS out of reset by setting itsrst to 0x0.\r
+  //    2)  Enable the TS using RMU Thermal sensor mode register.\r
+  //\r
+\r
+  Tscgf3Config &= ~(B_TSCGF3_CONFIG_ITSRST);\r
+  TsModeReg |= TS_ENABLE;\r
+\r
+  QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF3_CONFIG, Tscgf3Config);\r
+  QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_TS_MODE, TsModeReg);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Lock all RMU Thermal sensor control & trip point registers.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+QNCThermalSensorLockAllRegisters (\r
+  VOID\r
+  )\r
+{\r
+  UINT32                             RegValue;\r
+  UINT32                             LockMask;\r
+\r
+  LockMask = TS_LOCK_THRM_CTRL_REGS_ENABLE | TS_LOCK_AUX_TRIP_PT_REGS_ENABLE;\r
+\r
+  RegValue = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_CONFIG);\r
+  RegValue |= LockMask;\r
+  QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_CONFIG, RegValue);\r
+\r
+  ASSERT ((LockMask == (QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_CONFIG) & LockMask)));\r
+}\r
+\r
+/**\r
+  Set chipset policy for double bit ECC error.\r
+\r
+  @param[in]       PolicyValue  Policy to config on double bit ECC error.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+QNCPolicyDblEccBitErr (\r
+  IN  CONST UINT32                        PolicyValue\r
+  )\r
+{\r
+  UINT32 Register;\r
+  Register = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_WDT_CONTROL);\r
+  Register &= ~(B_WDT_CONTROL_DBL_ECC_BIT_ERR_MASK);\r
+  Register |= PolicyValue;\r
+  QNCPortWrite (\r
+    QUARK_NC_RMU_SB_PORT_ID,\r
+    QUARK_NC_RMU_REG_WDT_CONTROL,\r
+    Register\r
+    );\r
+}\r
+\r
+/**\r
+  Determine if running on secure Quark hardware Sku.\r
+\r
+  @retval FALSE  Base Quark Sku or unprovisioned Secure Sku running.\r
+  @retval TRUE   Provisioned SecureSku hardware running.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+QncIsSecureProvisionedSku (\r
+  VOID\r
+  )\r
+{\r
+  // Read QUARK Secure SKU Fuse\r
+  return ((QNCAltPortRead (QUARK_SCSS_FUSE_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_SPI_ROM_FUSE) & BIT6) == BIT6);\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/IntelQNCLib.inf b/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/IntelQNCLib.inf
new file mode 100644 (file)
index 0000000..691a7e4
--- /dev/null
@@ -0,0 +1,63 @@
+## @file\r
+# Intel QNC Library Instance\r
+#\r
+# Intel QNC Library Instance\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = IntelQNCLib\r
+  FILE_GUID                      = F5B2EA6C-8148-4a4e-88EA-38A4A51F389F\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = IntelQNCLib\r
+\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  PciExpress.c\r
+  IntelQNCLib.c\r
+  CommonHeader.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  TimerLib\r
+  DebugLib\r
+  PcdLib\r
+  PciLib\r
+  IoLib\r
+  PciCf8Lib\r
+  BaseLib\r
+  CpuLib\r
+  QNCAccessLib\r
+\r
+[Pcd]\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdGbaIoBaseAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPmbaIoBaseAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmbaIoBaseAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdWdtbaIoBaseAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdRcbaMmioBaseAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdDeviceEnables\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPcieRootPortConfiguration\r
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/PciExpress.c b/QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/PciExpress.c
new file mode 100644 (file)
index 0000000..5cb0fb8
--- /dev/null
@@ -0,0 +1,949 @@
+/** @file\r
+QNC PCI Express initialization entry\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "CommonHeader.h"\r
+\r
+#define PCIEXP_ROOT_PORT_URE_ENABLE    BIT0   //  unsupported request reporting enable\r
+#define PCIEXP_ROOT_PORT_FEE_ENABLE    BIT1   //  Fatal Error Reporting Enable\r
+#define PCIEXP_ROOT_PORT_NFE_ENABLE    BIT2   //  Non-Fatal Error Reporting Enable\r
+#define PCIEXP_ROOT_PORT_CEE_ENABLE    BIT3   //  Correctable Error Reporting Enable\r
+#define PCIEXP_ROOT_PORT_SFE_ENABLE    BIT4   //  System Error on Fatal Error Enable\r
+#define PCIEXP_ROOT_PORT_SNE_ENABLE    BIT5   //  System Error on Non-Fatal Error Enable\r
+#define PCIEXP_ROOT_PORT_SCE_ENABLE    BIT6   //  System Error on Correctable Error Enable\r
+\r
+EFI_STATUS\r
+PcieStall (\r
+  IN UINTN              Microseconds\r
+  )\r
+{\r
+  MicroSecondDelay (Microseconds);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Find the Offset to a given Capabilities ID\r
+    CAPID list:\r
+      0x01 = PCI Power Management Interface\r
+      0x04 = Slot Identification\r
+      0x05 = MSI Capability\r
+      0x10 = PCI Express Capability\r
+\r
+  @param[in]  Bus                     Bus number of the interested device\r
+  @param[in]  Device                  Device number of the interested device\r
+  @param[in]  Function                Function number of the interested device\r
+  @param[in]  CapId                   Capability ID to be scanned\r
+\r
+  @retval Offset of desired CAPID\r
+\r
+**/\r
+UINT32\r
+PcieFindCapId (\r
+  UINT8   Bus,\r
+  UINT8   Device,\r
+  UINT8   Function,\r
+  UINT8   CapId\r
+  )\r
+{\r
+  UINT8    CapHeader;\r
+\r
+  //\r
+  // Always start at Offset 0x34\r
+  //\r
+  CapHeader = QNCMmPci8 (0, Bus, Device, Function, R_QNC_PCIE_CAP_PTR);\r
+\r
+  if (CapHeader == 0xFF) {\r
+     return 0;\r
+  }\r
+\r
+  while (CapHeader != 0) {\r
+    if (QNCMmPci8 (0, Bus, Device, Function, CapHeader) == CapId) {\r
+      return CapHeader;\r
+    }\r
+    CapHeader = QNCMmPci8 (0, Bus, Device, Function, CapHeader + 1);\r
+  }\r
+  return 0;\r
+}\r
+\r
+/**\r
+\r
+  Search and return the offset of desired Pci Express Capability ID\r
+    CAPID list:\r
+      0x0001 = Advanced Error Rreporting Capability\r
+      0x0002 = Virtual Channel Capability\r
+      0x0003 = Device Serial Number Capability\r
+      0x0004 = Power Budgeting Capability\r
+\r
+  @param[in]  Bus                     Bus number of the interested device\r
+  @param[in]  Device                  Device number of the interested device\r
+  @param[in]  Function                Function number of the interested device\r
+  @param[in]  CapId                   Capability ID to be scanned\r
+\r
+  @retval Offset of desired CAPID\r
+\r
+**/\r
+UINT32\r
+PcieFindExtendedCapId (\r
+  UINT8   Bus,\r
+  UINT8   Device,\r
+  UINT8   Function,\r
+  UINT16  CapId\r
+  )\r
+{\r
+  UINT16    CapHeaderOffset;\r
+  UINT16    CapHeaderId;\r
+\r
+  // Start to search at Offset 0x100\r
+  // Get Capability Header\r
+  CapHeaderId = 0;\r
+  CapHeaderOffset = PCIE_CAP_EXT_HEARDER_OFFSET;\r
+\r
+  while (CapHeaderOffset != 0 && CapHeaderId != 0xFFFF) {\r
+    CapHeaderId = QNCMmPci16 (0, Bus, Device, Function, CapHeaderOffset);\r
+    if (CapHeaderId == CapId) {\r
+      return CapHeaderOffset;\r
+    }\r
+    CapHeaderOffset = (QNCMmPci16 (0, Bus, Device, Function, CapHeaderOffset + 2) >> 4);\r
+  }\r
+  return 0;\r
+}\r
+\r
+/**\r
+\r
+  Map Vc on both root port and downstream device\r
+\r
+  @param[in]  Bus1                    Bus number of the root port\r
+  @param[in]  Device1                 Device number of the root port\r
+  @param[in]  Function1               Function number of the root port\r
+  @param[in]  Bus2                    Bus number of the downstream device\r
+  @param[in]  Device2                 Device number of the downstream device\r
+  @param[in]  Function2               Function number of the downstream device\r
+\r
+  @retval EFI_SUCCESS    Map Vc successful\r
+\r
+**/\r
+EFI_STATUS\r
+PcieInitTcxVc0 (\r
+  IN UINT8   Bus1,\r
+  IN UINT8   Device1,\r
+  IN UINT8   Function1,\r
+  IN UINT8   Bus2,\r
+  IN UINT8   Device2,\r
+  IN UINT8   Function2\r
+  )\r
+{\r
+  UINT32  Offset;\r
+\r
+  //\r
+  // Initialize TCx-VC0 value on the port to only use TC0\r
+  //\r
+  Offset = PcieFindExtendedCapId (Bus1, Device1, Function1, 2);\r
+  if (Offset == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  QNCMmPci8AndThenOr (0, Bus1, Device1, Function1, (Offset + PCIE_SLOT_CAP_OFFSET), ~0xF, 1);\r
+\r
+  // Set TCx-VC0 value on the Endpoint\r
+\r
+  Offset = PcieFindExtendedCapId (Bus2, Device2, Function2, 2);\r
+  if (Offset == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  QNCMmPci8AndThenOr (0, Bus2, Device2, Function2, (Offset + PCIE_SLOT_CAP_OFFSET), ~0xF, 1);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Map Traffic Class x to Vc0 on both root port and downstream device\r
+\r
+  @param[in]  Bus1                    Bus number of the root port\r
+  @param[in]  Device1                 Device number of the root port\r
+  @param[in]  Function1               Function number of the root port\r
+  @param[in]  Bus2                    Bus number of the downstream device\r
+  @param[in]  Device2                 Device number of the downstream device\r
+  @param[in]  Function2               Function number of the downstream device\r
+  @param[in]  TCx                     Traffic Class to be mapped to vc0\r
+\r
+  @retval EFI_SUCCESS    Map Tcx to Vc0 successful\r
+\r
+**/\r
+EFI_STATUS\r
+PcieMapTcxVc0 (\r
+  IN UINT8   Bus1,\r
+  IN UINT8   Device1,\r
+  IN UINT8   Function1,\r
+  IN UINT8   Bus2,\r
+  IN UINT8   Device2,\r
+  IN UINT8   Function2,\r
+  IN UINT8   TCx\r
+  )\r
+{\r
+  UINT32  Offset;\r
+\r
+  //\r
+  // Set TCx-VC0 value on the port\r
+  //\r
+\r
+  Offset = PcieFindExtendedCapId (Bus1, Device1, Function1, 2);\r
+  if (Offset == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  QNCMmPci8 (0, Bus1, Device1, Function1, (Offset + PCIE_SLOT_CAP_OFFSET)) = (UINT8)(1 << TCx);\r
+\r
+  // Set TCx-VC0 value on the Endpoint\r
+\r
+  Offset = PcieFindExtendedCapId (Bus2, Device2, Function2, 2);\r
+  if (Offset == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  QNCMmPci8 (0, Bus2, Device2, Function2, (Offset + PCIE_SLOT_CAP_OFFSET)) = (UINT8)(1 << TCx);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Set common clock for both root port and downstream device.\r
+\r
+  @param[in]  Bus1                    Bus number of the root port\r
+  @param[in]  Device1                 Device number of the root port\r
+  @param[in]  Function1               Function number of the root port\r
+  @param[in]  Bus2                    Device number of the downstream device\r
+  @param[in]  Device2                 Function number of the downstream device\r
+\r
+  @retval EFI_SUCCESS    Set common clock successful\r
+\r
+**/\r
+EFI_STATUS\r
+PcieSetCommonClock (\r
+  IN UINT8   Bus1,\r
+  IN UINT8   Device1,\r
+  IN UINT8   Function1,\r
+  IN UINT8   Bus2,\r
+  IN UINT8   Device2\r
+ )\r
+{\r
+  UINT32      CapOffset1;\r
+  UINT32      CapOffset2;\r
+  UINT8       Function2;\r
+  UINT8       CommonClock;\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Get the pointer to the Port PCI Express Capability Structure.\r
+  //\r
+  CommonClock = 0;\r
+  CapOffset1 = PcieFindCapId (Bus1, Device1, Function1, PCIE_CAPID);\r
+  if (CapOffset1 == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Step 1\r
+  // Read the Slot Clock Configuration bit of the Link status register of the root port and the endpoint device connected to the port\r
+  // If both components have this bit set to 1, then System BIOS should set the "Common Clock Configuration" bit in the Link Control Registers\r
+  // for both components at both sides of the link to indicate that components at both ends\r
+  // of the link use a common clock source\r
+  //\r
+\r
+  //\r
+  // Check the Port Slot Clock Configuration Bit.\r
+  //\r
+  if ((QNCMmPci16 (0, Bus1, Device1, Function1, (CapOffset1 + PCIE_LINK_STS_OFFSET)) & B_QNC_PCIE_LSTS_SCC) == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  for (Function2 = 0; Function2 < 8; Function2++) {\r
+    //\r
+    // Check the Endpoint Slot Clock Configuration Bit.\r
+    //\r
+    CapOffset2 = PcieFindCapId (Bus2, Device2, Function2, PCIE_CAPID);\r
+    if ((CapOffset2 != 0) &&\r
+       ((QNCMmPci16 (0, Bus2, Device2, Function2, (CapOffset2 + PCIE_LINK_STS_OFFSET)) & B_QNC_PCIE_LSTS_SCC) != 0)) {\r
+\r
+      //\r
+      // Common clock is supported, set common clock bit on root port\r
+      // and the endpoint\r
+      //\r
+      if (CommonClock == 0) {\r
+        QNCMmPci8Or (0, Bus1, Device1, Function1, (CapOffset1 + PCIE_LINK_CNT_OFFSET), B_QNC_PCIE_LCTL_CCC);\r
+        CommonClock++;\r
+      }\r
+      QNCMmPci8Or (0, Bus2, Device2, Function2, (CapOffset2 + PCIE_LINK_CNT_OFFSET), B_QNC_PCIE_LCTL_CCC);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Step 2   If the Common Clock Configuration bit was changed by BIOS in step 1,\r
+  // System BIOS should initiate a link training by setting the Retrain Link bit\r
+  // in the Link Control register of the root port (D28:F0/F1 offset\r
+  // 50h [5]) to "1b" and then poll the Link Training bit in the Link Status\r
+  // register of the root port (D28:F0/F1/F2/F3/F4/F5 offset 52h [11]) until it is\r
+  // "0b".\r
+  //\r
+  if (CommonClock == 0) {\r
+    Status = EFI_UNSUPPORTED;\r
+  } else {\r
+    //\r
+    // Retrain the Link per PCI Express Specification.\r
+    //\r
+    QNCMmPci8Or (0, Bus1, Device1, Function1, (CapOffset1 + PCIE_LINK_CNT_OFFSET), B_QNC_PCIE_LCTL_RL);\r
+\r
+    //\r
+    // Wait until Re-Training has completed.\r
+    //\r
+    while ((QNCMmPci16 (0, Bus1, Device1, Function1, (CapOffset1 + PCIE_LINK_STS_OFFSET)) & B_QNC_PCIE_LSTS_LT) != 0);\r
+    Status = EFI_SUCCESS;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Enables the CLKREQ# PM on all the end point functions\r
+\r
+  @param[in]  Bus                Bus number of the downstream device\r
+  @param[in]  Device             Device number of the downstream device\r
+\r
+  @retval None\r
+\r
+**/\r
+VOID\r
+PcieSetClkreq (\r
+  IN  UINT8   Bus,\r
+  IN  UINT8   Device\r
+ )\r
+{\r
+  UINT8  Function;\r
+  UINT32 CapOffset;\r
+\r
+  //\r
+  // Parse thro all the functions of the endpoint and find the PCIe Cap ID (offset 10h) and if\r
+  // exists then enable the CLKREQ# bit (BIT8) on that function\r
+  //\r
+  for (Function = 0; Function < 8; Function++) {\r
+    //\r
+    // Find the PCIe Cap Id (offset 10h)\r
+    //\r
+    CapOffset = PcieFindCapId (Bus, Device, Function, PCIE_CAPID);\r
+    if (CapOffset == 0) {\r
+       continue;\r
+    }\r
+\r
+    //\r
+    // Check if CLKREQ# is supported by the endpoints\r
+    //\r
+    if ((QNCMmPci32 (0, Bus, Device, Function, (CapOffset + PCIE_LINK_CAP_OFFSET))\r
+      & B_QNC_PCIE_LCAP_CPM) != B_QNC_PCIE_LCAP_CPM) {\r
+      //\r
+      // CLKREQ# is not supported so dont do anything\r
+      //\r
+      return;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Now enable the CLKREQ#\r
+  //\r
+  for (Function = 0; Function < 8; Function++) {\r
+    //\r
+    // Find the PCIe Cap Id (offset 10h)\r
+    //\r
+    CapOffset = PcieFindCapId (Bus, Device, Function, PCIE_CAPID);\r
+    if (CapOffset == 0) {\r
+       continue;\r
+    }\r
+\r
+    QNCMmPci16Or (0, Bus, Device, Function, (CapOffset + PCIE_LINK_CNT_OFFSET), BIT8);\r
+  }\r
+}\r
+\r
+/**\r
+\r
+  Configure ASPM automatically for both root port and downstream device.\r
+\r
+  @param[in]  RootBus                    Bus number of the root port\r
+  @param[in]  RootDevice                 Device number of the root port\r
+  @param[in]  RootFunction               Function number of the root port\r
+  @param[in]  EndpointBus                Bus number of the downstream device\r
+  @param[in]  EndpointDevice             Device number of the downstream device\r
+  @param[in]  EndpointFunction           Function number of the downstream device\r
+  @param[in]  LinkAspmVal                Currently used ASPM setting\r
+\r
+  @retval EFI_SUCCESS    Configure ASPM successful\r
+\r
+**/\r
+EFI_STATUS\r
+PcieSetAspmAuto (\r
+  IN  UINT8   RootBus,\r
+  IN  UINT8   RootDevice,\r
+  IN  UINT8   RootFunction,\r
+  IN  UINT8   EndpointBus,\r
+  IN  UINT8   EndpointDevice,\r
+  IN  UINT8   EndpointFunction,\r
+  OUT UINT16  *LinkAspmVal\r
+ )\r
+{\r
+  UINT32    RootPcieCapOffset;\r
+  UINT32    EndpointPcieCapOffset;\r
+  UINT16    RootPortAspm;\r
+  UINT16    EndPointAspm;\r
+  UINT16    EndPointVendorId;\r
+  UINT16    EndPointDeviceId;\r
+  UINT8     EndPointRevId;\r
+  UINT16    AspmVal;\r
+  UINT32    PortLxLat;\r
+  UINT32    EndPointLxLat;\r
+  UINT32    LxLat;\r
+\r
+  //\r
+  // Get the pointer to the Port PCI Express Capability Structure.\r
+  //\r
+  RootPcieCapOffset = PcieFindCapId (RootBus, RootDevice, RootFunction, PCIE_CAPID);\r
+  if (RootPcieCapOffset == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Get the pointer to the Endpoint PCI Express Capability Structure.\r
+  //\r
+  EndpointPcieCapOffset = PcieFindCapId (EndpointBus, EndpointDevice, EndpointFunction, PCIE_CAPID);\r
+  if (EndpointPcieCapOffset == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Obtain initial ASPM settings from respective port capability registers.\r
+  //\r
+  RootPortAspm  = (QNCMmPci16 (0, RootBus, RootDevice, RootFunction, (RootPcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_APMS_MASK) >> V_QNC_PCIE_LCAP_APMS_OFFSET;\r
+\r
+  //\r
+  // Configure downstream device if present.\r
+  //\r
+  EndPointAspm  = (QNCMmPci16 (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_APMS_MASK) >> V_QNC_PCIE_LCAP_APMS_OFFSET;\r
+\r
+  //\r
+  // Mask APMC with values from lookup table.\r
+  // RevID of 0xFF applies to all steppings.\r
+  //\r
+\r
+  EndPointVendorId = QNCMmPci16 (0, EndpointBus, EndpointDevice, EndpointFunction, 0);\r
+  EndPointDeviceId = QNCMmPci16 (0, EndpointBus, EndpointDevice, EndpointFunction, 2);\r
+  EndPointRevId    = QNCMmPci8 (0, EndpointBus, EndpointDevice, EndpointFunction, 8);\r
+\r
+  // TODO: Mask with latency/acceptable latency comparison results.\r
+\r
+  AspmVal = RootPortAspm;\r
+  if (RootPortAspm > EndPointAspm) {\r
+    AspmVal = EndPointAspm;\r
+  }\r
+\r
+  //\r
+  // Check if L1 should be enabled based on port and endpoint L1 exit latency.\r
+  //\r
+  if(AspmVal & BIT1) {\r
+    PortLxLat      = QNCMmPci32 (0, RootBus, RootDevice, RootFunction, (RootPcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_EL1_MASK;\r
+    EndPointLxLat  = QNCMmPci32 (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_EL1_MASK;\r
+\r
+    LxLat = PortLxLat;\r
+    if(PortLxLat < EndPointLxLat) {\r
+      LxLat = EndPointLxLat;\r
+    }\r
+\r
+    //\r
+    // check if the value is bigger than endpoint L1 acceptable exit latency, if it is\r
+    // larger than accepted value, then we should disable L1\r
+    //\r
+    LxLat >>= 6;\r
+    if(LxLat > (QNCMmPci32 (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_DEV_CAP_OFFSET)) & B_QNC_PCIE_DCAP_E1AL)) {\r
+      AspmVal &= ~BIT1;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Check if L0s should be enabled based on port and endpoint L0s exit latency.\r
+  //\r
+  if(AspmVal & BIT0) {\r
+    PortLxLat      = QNCMmPci32 (0, RootBus, RootDevice, RootFunction, (RootPcieCapOffset+ PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_EL0_MASK;\r
+    EndPointLxLat  = QNCMmPci32 (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_EL0_MASK;\r
+\r
+    LxLat = PortLxLat;\r
+    if(PortLxLat < EndPointLxLat) {\r
+      LxLat = EndPointLxLat;\r
+    }\r
+\r
+    //\r
+    // check if the value is bigger than endpoint L0s acceptable exit latency, if it is\r
+    // larger than accepted value, then we should disable L0s\r
+    //\r
+    LxLat >>= 6;\r
+    if(LxLat > (QNCMmPci32 (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_DEV_CAP_OFFSET)) & B_QNC_PCIE_DCAP_E0AL)) {\r
+      AspmVal &= ~BIT0;\r
+    }\r
+  }\r
+\r
+  RootPortAspm = AspmVal;\r
+\r
+  *LinkAspmVal = AspmVal;\r
+  //\r
+  // Set Endpoint Aspm\r
+  //\r
+  QNCMmPci16AndThenOr (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_LINK_CNT_OFFSET), 0xFFFC, AspmVal);\r
+\r
+\r
+  //\r
+  // Set Root Port Aspm\r
+  //\r
+  QNCMmPci16AndThenOr (0, RootBus, RootDevice, RootFunction, (RootPcieCapOffset + PCIE_LINK_CNT_OFFSET), 0xFFFC, RootPortAspm);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Configure ASPM based on the given setting for the interested device.\r
+\r
+  @param[in]  Bus                    Bus number of the interested device\r
+  @param[in]  Device                 Device number of the interested device\r
+  @param[in]  Function               Function number of the interested device\r
+  @param[in]  AspmSetting            Aspm setting\r
+  @param[in]  LinkAspmVal            Currently used ASPM setting\r
+\r
+  @retval EFI_SUCCESS    Configure ASPM successful\r
+\r
+**/\r
+EFI_STATUS\r
+PcieSetAspmManual (\r
+  IN  UINT8   Bus,\r
+  IN  UINT8   Device,\r
+  IN  UINT8   Function,\r
+  IN  UINT8   AspmSetting,\r
+  OUT UINT16  *LinkAspmVal\r
+ )\r
+{\r
+  UINT32    PcieCapOffset;\r
+  UINT16    PortAspm;\r
+\r
+  //\r
+  // Get the pointer to the Port PCI Express Capability Structure.\r
+  //\r
+  PcieCapOffset = PcieFindCapId (Bus, Device, Function, PCIE_CAPID);\r
+  if (PcieCapOffset == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  // Read the Link Capability register's ASPM setting\r
+  PortAspm = (QNCMmPci16 (0, Bus, Device, Function, (PcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_APMS_MASK) >> V_QNC_PCIE_LCAP_APMS_OFFSET;\r
+  // Mask it with the Setup selection\r
+  PortAspm &= AspmSetting;\r
+\r
+  *LinkAspmVal = PortAspm;\r
+  // Write it to the Link Control register\r
+  QNCMmPci16AndThenOr (0, Bus, Device, Function, (PcieCapOffset + PCIE_LINK_CNT_OFFSET), 0xFFFC, PortAspm);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Perform Initialization on one PCI Express root port.\r
+\r
+  @param[in]  RootPortIndex          Index of PCI Express root port\r
+  @param[in]  RootPortConfig         Pointer to the given pcie root port configuration\r
+  @param[in]  PciExpressBar          Base address of pcie space\r
+  @param[in]  QNCRootComplexBar       Base address of root complex\r
+  @param[in]  QNCPmioBase             Base address of PM IO space\r
+  @param[in]  QNCGpeBase              Base address of gpe IO space\r
+\r
+  @retval EFI_SUCCESS    Initialization successful\r
+\r
+**/\r
+EFI_STATUS\r
+QNCRootPortInit (\r
+  IN UINT32                                    RootPortIndex,\r
+  IN PCIEXP_ROOT_PORT_CONFIGURATION            *RootPortConfig,\r
+  IN UINT64                                    PciExpressBar,\r
+  IN UINT32                                    QNCRootComplexBar,\r
+  IN UINT32                                    QNCPmioBase,\r
+  IN UINT32                                    QNCGpeBase\r
+  )\r
+{\r
+  UINT64            RPBase;\r
+  UINT64            EndPointBase;\r
+  UINT64            LpcBase;\r
+  UINT16            AspmVal;\r
+  UINT16            SlotStatus;\r
+  UINTN             Index;\r
+  UINT32            CapOffset;\r
+  UINT32            DwordReg;\r
+\r
+  RPBase = PciExpressBar + (((PCI_BUS_NUMBER_QNC << 8) + ((PCI_DEVICE_NUMBER_PCIE_ROOTPORT) << 3) + ((PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex) << 0)) << 12);\r
+  LpcBase = PciExpressBar + (((PCI_BUS_NUMBER_QNC << 8) + (31 << 3) + (0 << 0)) << 12);\r
+  CapOffset = PcieFindCapId (PCI_BUS_NUMBER_QNC, (UINT8)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT), (UINT8)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex), PCIE_CAPID);\r
+\r
+  if (CapOffset == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Initialize "Slot Implmemented Bit" for this root port\r
+  //\r
+  if (RootPortConfig[RootPortIndex].Bits.SlotImplemented) {\r
+    QNCMmio16Or (RPBase, R_QNC_PCIE_XCAP, B_QNC_PCIE_XCAP_SI);\r
+  }\r
+\r
+  //\r
+  // For Root Port Slots Numbering on the CRBs.\r
+  //  Root Port 0 = Slot 1\r
+  //  Root Port 1 = Slot 2\r
+  //  Root Port 2 = Slot 3\r
+  //  Root Port 3 = Slot 4\r
+  //\r
+  DwordReg = QNCMmio32 (RPBase, R_QNC_PCIE_SLCAP);\r
+  DwordReg &= B_QNC_PCIE_SLCAP_MASK_RSV_VALUE;\r
+  DwordReg |= (V_QNC_PCIE_SLCAP_SLV << V_QNC_PCIE_SLCAP_SLV_OFFSET);\r
+  DwordReg |= ((RootPortConfig[RootPortIndex].Bits.PhysicalSlotNumber) << V_QNC_PCIE_SLCAP_PSN_OFFSET) ;\r
+  QNCMmio32 (RPBase, R_QNC_PCIE_SLCAP) = DwordReg;\r
+\r
+  //\r
+  // Check for a Presence Detect Change.\r
+  //\r
+  SlotStatus = QNCMmio16 (RPBase, R_QNC_PCIE_SLSTS);\r
+  if ((SlotStatus & (B_QNC_PCIE_SLSTS_PDS + B_QNC_PCIE_SLSTS_PDC)) == 0) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Temporarily Hardcode the Root Port Bridge Number to 2.\r
+  //\r
+  // This Endpoint check should immediately pass.  Howerver, a 900ms delay\r
+  // has been added to match the timing requirements of the PCI Express Base\r
+  // Specification, Revision 1.0A, Section 6.6 ("...software must allow 1.0s\r
+  // after a reset of a device, before it may determine that a device which\r
+  // fails to return a Successful Completion status for a valid Configuration\r
+  // Request is a broken device").  Note that a 100ms delay was already added\r
+  // after the Root Ports were first taken out of reset.\r
+  //\r
+  QNCMmio32AndThenOr (RPBase, R_QNC_PCIE_BNUM, 0xFF0000FF, 0x00020200);\r
+  //\r
+  // Only do this when a downstream device is present\r
+  //\r
+  EndPointBase = PciExpressBar + (((2 << 8) + (0 << 3) + (0 << 0)) << 12);\r
+  if ((SlotStatus & B_QNC_PCIE_SLSTS_PDS) != 0) {\r
+    for (Index = 0; Index < V_PCIE_MAX_TRY_TIMES; Index++){\r
+      if (QNCMmio16 (EndPointBase, 0x0) != 0xFFFF) {\r
+        break;\r
+      }\r
+      PcieStall (15);\r
+    }\r
+    if (Index >= V_PCIE_MAX_TRY_TIMES) {\r
+      //\r
+      // Clear Bus Numbers.\r
+      //\r
+      QNCMmio32And (RPBase, R_QNC_PCIE_BNUM, 0xFF0000FF);\r
+      return EFI_NOT_FOUND;\r
+    }\r
+  }\r
+\r
+  //\r
+  // PCI Express* Virtual Channels\r
+  // Clear TC1-7 Traffic classes.\r
+  // Map TC0-VC0\r
+  //\r
+  PcieInitTcxVc0 (PCI_BUS_NUMBER_QNC, (UINT8)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT), (UINT8)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex), 2, 0, 0);\r
+  PcieMapTcxVc0 (PCI_BUS_NUMBER_QNC, (UINT8)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT), (UINT8)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex), 2, 0, 0, 0x0);\r
+\r
+  //\r
+  // Set Common Clock for inserted cards\r
+  //\r
+  if ((SlotStatus & B_QNC_PCIE_SLSTS_PDS) != 0) {\r
+    PcieSetCommonClock (PCI_BUS_NUMBER_QNC, (UINT8)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT), (UINT8)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex), 2, 0);\r
+  }\r
+\r
+  //\r
+  // Flow for Enabling ASPM\r
+  //\r
+  if (RootPortConfig[RootPortIndex].Bits.AspmEnable) {\r
+    if (RootPortConfig[RootPortIndex].Bits.AspmAutoEnable) {\r
+      PcieSetAspmAuto (PCI_BUS_NUMBER_QNC, (UINT8)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT), (UINT8)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex), 2, 0, 0, &AspmVal);\r
+    } else {\r
+      //\r
+      // Set ASPM values according to setup selections, masked by capabilities\r
+      //\r
+      PcieSetAspmManual (\r
+        PCI_BUS_NUMBER_QNC,\r
+        (UINT8) (PCI_DEVICE_NUMBER_PCIE_ROOTPORT),\r
+        (UINT8) (PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex),\r
+        (UINT8) ((RootPortConfig[RootPortIndex].Bits.AspmL0sEnable & 0x01) | (RootPortConfig[RootPortIndex].Bits.AspmL1Enable << 1)),\r
+        &AspmVal\r
+        );\r
+    }\r
+  }\r
+\r
+  //\r
+  // Enable the PCIe CLKREQ#\r
+  //\r
+  if ((SlotStatus & B_QNC_PCIE_SLSTS_PDS) != 0) {\r
+    PcieSetClkreq (2, 0);\r
+  }\r
+\r
+  //\r
+  // Clear Bus Numbers\r
+  //\r
+  QNCMmio32And (RPBase, R_QNC_PCIE_BNUM, 0xFF0000FF);\r
+\r
+  //\r
+  // Additional configurations\r
+  //\r
+\r
+  //\r
+  // PCI-E Unsupported Request Reporting Enable\r
+  //\r
+  if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_URE_ENABLE) {\r
+    QNCMmio16Or (RPBase, R_QNC_PCIE_DCTL, B_QNC_PCIE_DCTL_URE);\r
+  }\r
+\r
+  //\r
+  // Device Fatal Error Reporting Enable\r
+  //\r
+  if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_FEE_ENABLE) {\r
+    QNCMmio16Or (RPBase, R_QNC_PCIE_DCTL, B_QNC_PCIE_DCTL_FEE);\r
+  }\r
+\r
+  //\r
+  // Device Non Fatal Error Reporting Enable\r
+  //\r
+  if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_NFE_ENABLE) {\r
+    QNCMmio16Or (RPBase, R_QNC_PCIE_DCTL, B_QNC_PCIE_DCTL_NFE);\r
+  }\r
+\r
+  //\r
+  // Device Correctable Error Reporting Enable\r
+  //\r
+  if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_CEE_ENABLE) {\r
+    QNCMmio16Or (RPBase, R_QNC_PCIE_DCTL, B_QNC_PCIE_DCTL_CEE);\r
+  }\r
+  //\r
+  // Root PCI-E PME Interrupt Enable\r
+  //\r
+  if (RootPortConfig[RootPortIndex].Bits.PmeInterruptEnable) {\r
+    QNCMmio16Or (RPBase, R_QNC_PCIE_RCTL, B_QNC_PCIE_RCTL_PIE);\r
+  }\r
+  //\r
+  // Root PCI-E System Error on Fatal Error Enable\r
+  //\r
+  if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_SFE_ENABLE) {\r
+    QNCMmio16Or (RPBase, R_QNC_PCIE_RCTL, B_QNC_PCIE_RCTL_SFE);\r
+  }\r
+\r
+  //\r
+  // Root PCI-E System Error on Non-Fatal Error Enable\r
+  //\r
+  if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_SNE_ENABLE) {\r
+    QNCMmio16Or (RPBase, R_QNC_PCIE_RCTL, B_QNC_PCIE_RCTL_SNE);\r
+  }\r
+\r
+  //\r
+  // Root PCI-E System Error on Correctable Error Enable\r
+  //\r
+  if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_SCE_ENABLE) {\r
+    QNCMmio16Or (RPBase, R_QNC_PCIE_RCTL, B_QNC_PCIE_RCTL_SCE);\r
+  }\r
+\r
+  //\r
+  // Root PCI-E Powermanagement SCI Enabled\r
+  //\r
+  if (RootPortConfig[RootPortIndex].Bits.PmSciEnable) {\r
+    //\r
+    // Make sure that PME Interrupt Enable bit of Root Control register\r
+    // of PCI Express Capability struceture is cleared\r
+    //\r
+    QNCMmio32And (RPBase, R_QNC_PCIE_RCTL, (~B_QNC_PCIE_RCTL_PIE));\r
+    QNCMmio32AndThenOr (RPBase, R_QNC_PCIE_MPC, (~B_QNC_PCIE_MPC_PMME), B_QNC_PCIE_MPC_PMCE);\r
+\r
+    //\r
+    // Make sure GPE0 Stutus RW1C Bit is clear.\r
+    //\r
+    DwordReg = IoRead32 (QNCGpeBase + R_QNC_GPE0BLK_GPE0S);\r
+    if ((DwordReg & B_QNC_GPE0BLK_GPE0S_PCIE) != 0) {\r
+      IoWrite32 (QNCGpeBase + R_QNC_GPE0BLK_GPE0S, B_QNC_GPE0BLK_GPE0S_PCIE);\r
+    }\r
+  }\r
+\r
+  //\r
+  // PCIe Hot Plug SCI Enable\r
+  //\r
+  if (RootPortConfig[RootPortIndex].Bits.HotplugSciEnable) {\r
+    //\r
+    // Write clear for :\r
+    // Attention Button Pressed (bit0)\r
+    // Presence Detect Changed (bit3)\r
+    //\r
+    QNCMmio32Or (RPBase, R_QNC_PCIE_SLSTS, (B_QNC_PCIE_SLSTS_PDC | B_QNC_PCIE_SLSTS_ABP));\r
+\r
+    //\r
+    // Sequence 2: Program the following bits in Slot Control register at offset 18h\r
+    // of PCI Express* Capability structure:\r
+    // Attention Button Pressed Enable (bit0) = 1b\r
+    // Presence Detect Changed Enable (bit3) = 1b\r
+    // Hot Plug Interrupt Enable (bit5) = 0b\r
+    //\r
+    QNCMmio32AndThenOr (RPBase, R_QNC_PCIE_SLCTL, (~B_QNC_PCIE_SLCTL_HPE), (B_QNC_PCIE_SLCTL_PDE | B_QNC_PCIE_SLCTL_ABE));\r
+\r
+    //\r
+    // Sequence 3: Program Misc Port Config (MPC) register at PCI config space offset\r
+    // D8h as follows:\r
+    // Hot Plug SCI Enable (HPCE, bit30) = 1b\r
+    // Hot Plug SMI Enable (HPME, bit1) = 0b\r
+    //\r
+    QNCMmio32AndThenOr (RPBase, R_QNC_PCIE_MPC, (~B_QNC_PCIE_MPC_HPME), B_QNC_PCIE_MPC_HPCE);\r
+  }\r
+\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Perform Initialization of the Downstream Root Ports\r
+**/\r
+VOID\r
+QNCDownStreamPortsInit (\r
+  IN PCIEXP_ROOT_PORT_CONFIGURATION             *RootPortConfig,\r
+  IN QNC_DEVICE_ENABLES                      *QNCDeviceEnables,\r
+  IN UINT64                                     PciExpressBar,\r
+  IN UINT32                                     QNCRootComplexBar,\r
+  IN UINT32                                     QNCPmioBase,\r
+  IN UINT32                                     QNCGpeBase,\r
+  OUT UINTN                                     *RpEnableMask\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  UINT32         Index;\r
+\r
+  //\r
+  // Initialize every root port and downstream device\r
+  //\r
+  for (Index = 0;Index < MAX_PCI_EXPRESS_ROOT_PORTS;Index++) {\r
+    if ((QNCDeviceEnables->Uint32 & (1 << Index)) != 0) {\r
+      Status = QNCRootPortInit (\r
+               Index,\r
+               RootPortConfig,\r
+               PciExpressBar,\r
+               QNCRootComplexBar,\r
+               QNCPmioBase,\r
+               QNCGpeBase\r
+               );\r
+\r
+      if (!EFI_ERROR (Status)) {\r
+        (*RpEnableMask) |= LShiftU64(1, Index);\r
+        DEBUG ((EFI_D_INFO, " Root Port %x device found, enabled. RpEnableMask: 0x%x\n", Index + 1, *RpEnableMask));\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Do early init of pci express rootports on Soc.\r
+\r
+**/\r
+\r
+VOID\r
+EFIAPI\r
+PciExpressEarlyInit (\r
+  VOID\r
+  )\r
+{\r
+  //\r
+  // Setup Message Bus Idle Counter (SBIC) values.\r
+  //\r
+  QNCMmPci8(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_IOSFSBCTL) = QNCMmPci8AndThenOr(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_IOSFSBCTL, (~B_QNC_PCIE_IOSFSBCTL_SBIC_MASK), V_PCIE_ROOT_PORT_SBIC_VALUE);\r
+  QNCMmPci8(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, R_QNC_PCIE_IOSFSBCTL) = QNCMmPci8AndThenOr(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, R_QNC_PCIE_IOSFSBCTL, (~B_QNC_PCIE_IOSFSBCTL_SBIC_MASK), V_PCIE_ROOT_PORT_SBIC_VALUE);\r
+\r
+  //\r
+  // Program SVID/SID the same as VID/DID for Root ports.\r
+  //\r
+  QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_SVID) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, PCI_VENDOR_ID_OFFSET);\r
+  QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, R_QNC_PCIE_SVID) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, PCI_VENDOR_ID_OFFSET);\r
+\r
+  //\r
+  // Set the IPF bit in MCR2\r
+  //\r
+  QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_MPC2) = QNCMmPci32Or(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_MPC2, B_QNC_PCIE_MPC2_IPF);\r
+  QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, R_QNC_PCIE_MPC2) = QNCMmPci32Or(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, R_QNC_PCIE_MPC2, B_QNC_PCIE_MPC2_IPF);\r
+\r
+  //\r
+  // Set up the Posted and Non Posted Request sizes for PCIe\r
+  //\r
+  QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_CCFG) = QNCMmPci32AndThenOr(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_CCFG, ~B_QNC_PCIE_CCFG_UPSD, (B_QNC_PCIE_CCFG_UNRS | B_QNC_PCIE_CCFG_UPRS));\r
+\r
+  return;\r
+}\r
+\r
+\r
+/**\r
+  Complete initialization all the pci express rootports on Soc.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciExpressInit (\r
+  )\r
+{\r
+  UINT64                            PciExpressBar;\r
+  UINT32                            QNCRootComplexBar;\r
+  UINT32                            QNCGpioBase;\r
+  UINT32                            QNCPmioBase;\r
+  UINT32                            QNCGpeBase;\r
+  UINTN                             RpEnableMask;\r
+  PCIEXP_ROOT_PORT_CONFIGURATION    *mRootPortConfig;\r
+  QNC_DEVICE_ENABLES                mQNCDeviceEnables;\r
+\r
+  //\r
+  // Get BAR registers\r
+  //\r
+  QNCRootComplexBar  = QNC_RCRB_BASE;\r
+  QNCGpioBase        = LpcPciCfg32 (R_QNC_LPC_GBA_BASE) & B_QNC_LPC_GPA_BASE_MASK;\r
+  QNCPmioBase        = LpcPciCfg32 (R_QNC_LPC_PM1BLK) & B_QNC_LPC_PM1BLK_MASK;\r
+  QNCGpeBase         = LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & B_QNC_LPC_GPE0BLK_MASK;\r
+  RpEnableMask = 0;                 // assume all root ports are disabled\r
+\r
+  PciExpressBar = PcdGet64 (PcdPciExpressBaseAddress);\r
+\r
+  //\r
+  // Get platform information from PCD entries\r
+  //\r
+  mQNCDeviceEnables.Uint32 = PcdGet32 (PcdDeviceEnables);\r
+  mRootPortConfig = (PCIEXP_ROOT_PORT_CONFIGURATION*) PcdGetPtr (PcdPcieRootPortConfiguration);\r
+\r
+  DEBUG ((EFI_D_INFO, " mRootPortConfig: 0x%x,  value1: 0x%x, value2: 0x%x, value3: 0x%x, value4: 0x%x\n",\r
+          mRootPortConfig, mRootPortConfig[0].Uint32, mRootPortConfig[1].Uint32,\r
+          mRootPortConfig[2].Uint32, mRootPortConfig[3].Uint32));\r
+\r
+  QNCDownStreamPortsInit (\r
+                         mRootPortConfig,\r
+                         &mQNCDeviceEnables,\r
+                         PciExpressBar,\r
+                         QNCRootComplexBar,\r
+                         QNCPmioBase,\r
+                         QNCGpeBase,\r
+                         &RpEnableMask\r
+                         );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/MtrrLib/MtrrLib.c b/QuarkSocPkg/QuarkNorthCluster/Library/MtrrLib/MtrrLib.c
new file mode 100644 (file)
index 0000000..4a88dff
--- /dev/null
@@ -0,0 +1,2117 @@
+/** @file\r
+MTRR setting library\r
+\r
+Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Base.h>\r
+\r
+#include <Library/MtrrLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/CpuLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/QNCAccessLib.h>\r
+\r
+#define QUARK_SOC_CPUID_FAMILY_MODEL_STEPPING         0x590\r
+\r
+//\r
+// Context to save and restore when MTRRs are programmed\r
+//\r
+typedef struct {\r
+  UINTN    Cr4;\r
+  BOOLEAN  InterruptState;\r
+} MTRR_CONTEXT;\r
+\r
+//\r
+// This table defines the offset, base and length of the fixed MTRRs\r
+//\r
+CONST FIXED_MTRR  mMtrrLibFixedMtrrTable[] = {\r
+  { QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000, 0,       SIZE_64KB },\r
+  { QUARK_NC_HOST_BRIDGE_MTRR_FIX16K_80000, 0x80000, SIZE_16KB },\r
+  { QUARK_NC_HOST_BRIDGE_MTRR_FIX16K_A0000, 0xA0000, SIZE_16KB },\r
+  { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_C0000,  0xC0000, SIZE_4KB  },\r
+  { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_C8000,  0xC8000, SIZE_4KB  },\r
+  { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_D0000,  0xD0000, SIZE_4KB  },\r
+  { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_D8000,  0xD8000, SIZE_4KB  },\r
+  { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_E0000,  0xE0000, SIZE_4KB  },\r
+  { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_E8000,  0xE8000, SIZE_4KB  },\r
+  { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F0000,  0xF0000, SIZE_4KB  },\r
+  { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000,  0xF8000, SIZE_4KB  }\r
+};\r
+\r
+//\r
+// Lookup table used to print MTRRs\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mMtrrMemoryCacheTypeShortName[] = {\r
+  "UC",  // CacheUncacheable\r
+  "WC",  // CacheWriteCombining\r
+  "R*",  // Invalid\r
+  "R*",  // Invalid\r
+  "WT",  // CacheWriteThrough\r
+  "WP",  // CacheWriteProtected\r
+  "WB",  // CacheWriteBack\r
+  "R*"   // Invalid\r
+};\r
+\r
+UINT64\r
+MtrrRegisterRead (\r
+  IN  UINT32  MtrrRegister\r
+  )\r
+{\r
+  UINT64  Result;\r
+\r
+  Result = (UINT64)QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, MtrrRegister);\r
+  if (MtrrRegister >= QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000 && MtrrRegister <= QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000) {\r
+    Result = Result | LShiftU64 ((UINT64)QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, MtrrRegister + 1), 32);\r
+  }\r
+  return Result;\r
+}\r
+\r
+UINT64\r
+MtrrRegisterWrite (\r
+  IN  UINT32  MtrrRegister,\r
+  IN  UINT64  Value\r
+  )\r
+{\r
+  QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, MtrrRegister, (UINT32)Value);\r
+  if (MtrrRegister >= QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000 && MtrrRegister <= QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000) {\r
+    QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, MtrrRegister + 1, (UINT32)RShiftU64 (Value, 32));\r
+  }\r
+  return Value;\r
+}\r
+\r
+UINT64\r
+MtrrRegisterBitFieldWrite (\r
+  IN  UINT32  MtrrRegister,\r
+  IN  UINTN   StartBit,\r
+  IN  UINTN   EndBit,\r
+  IN  UINT64  Value\r
+  )\r
+{\r
+  return MtrrRegisterWrite (\r
+           MtrrRegister,\r
+           BitFieldWrite64 (\r
+             MtrrRegisterRead (MtrrRegister),\r
+             StartBit,\r
+             EndBit,\r
+             Value\r
+             )\r
+           );\r
+}\r
+\r
+/**\r
+  Worker function returns the variable MTRR count for the CPU.\r
+\r
+  @return Variable MTRR count\r
+\r
+**/\r
+UINT32\r
+GetVariableMtrrCountWorker (\r
+  VOID\r
+  )\r
+{\r
+  UINT32  VariableMtrrCount;\r
+\r
+  VariableMtrrCount = (UINT32)(MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_CAP) & MTRR_LIB_IA32_MTRR_CAP_VCNT_MASK);\r
+  ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
+  return VariableMtrrCount;\r
+}\r
+\r
+/**\r
+  Returns the variable MTRR count for the CPU.\r
+\r
+  @return Variable MTRR count\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+GetVariableMtrrCount (\r
+  VOID\r
+  )\r
+{\r
+  if (!IsMtrrSupported ()) {\r
+    return 0;\r
+  }\r
+  return GetVariableMtrrCountWorker ();\r
+}\r
+\r
+/**\r
+  Worker function returns the firmware usable variable MTRR count for the CPU.\r
+\r
+  @return Firmware usable variable MTRR count\r
+\r
+**/\r
+UINT32\r
+GetFirmwareVariableMtrrCountWorker (\r
+  VOID\r
+  )\r
+{\r
+  UINT32  VariableMtrrCount;\r
+  UINT32  ReservedMtrrNumber;\r
+\r
+  VariableMtrrCount = GetVariableMtrrCountWorker ();\r
+  ReservedMtrrNumber = PcdGet32 (PcdCpuNumberOfReservedVariableMtrrs);\r
+  if (VariableMtrrCount < ReservedMtrrNumber) {\r
+    return 0;\r
+  }\r
+\r
+  return VariableMtrrCount - ReservedMtrrNumber;\r
+}\r
+\r
+/**\r
+  Returns the firmware usable variable MTRR count for the CPU.\r
+\r
+  @return Firmware usable variable MTRR count\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+GetFirmwareVariableMtrrCount (\r
+  VOID\r
+  )\r
+{\r
+  if (!IsMtrrSupported ()) {\r
+    return 0;\r
+  }\r
+  return GetFirmwareVariableMtrrCountWorker ();\r
+}\r
+\r
+/**\r
+  Worker function returns the default MTRR cache type for the system.\r
+\r
+  If MtrrSetting is not NULL, returns the default MTRR cache type from input\r
+  MTRR settings buffer.\r
+  If MtrrSetting is NULL, returns the default MTRR cache type from MSR.\r
+\r
+  @param[in]  MtrrSetting    A buffer holding all MTRRs content.\r
+\r
+  @return  The default MTRR cache type.\r
+\r
+**/\r
+MTRR_MEMORY_CACHE_TYPE\r
+MtrrGetDefaultMemoryTypeWorker (\r
+  IN MTRR_SETTINGS      *MtrrSetting\r
+  )\r
+{\r
+  if (MtrrSetting == NULL) {\r
+    return (MTRR_MEMORY_CACHE_TYPE) (MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE) & 0x7);\r
+  } else {\r
+    return (MTRR_MEMORY_CACHE_TYPE) (MtrrSetting->MtrrDefType & 0x7);\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Returns the default MTRR cache type for the system.\r
+\r
+  @return  The default MTRR cache type.\r
+\r
+**/\r
+MTRR_MEMORY_CACHE_TYPE\r
+EFIAPI\r
+MtrrGetDefaultMemoryType (\r
+  VOID\r
+  )\r
+{\r
+  if (!IsMtrrSupported ()) {\r
+    return CacheUncacheable;\r
+  }\r
+  return MtrrGetDefaultMemoryTypeWorker (NULL);\r
+}\r
+\r
+/**\r
+  Preparation before programming MTRR.\r
+\r
+  This function will do some preparation for programming MTRRs:\r
+  disable cache, invalid cache and disable MTRR caching functionality\r
+\r
+  @param[out] MtrrContext  Pointer to context to save\r
+\r
+**/\r
+VOID\r
+PreMtrrChange (\r
+  OUT MTRR_CONTEXT  *MtrrContext\r
+  )\r
+{\r
+  //\r
+  // Disable interrupts and save current interrupt state\r
+  //\r
+  MtrrContext->InterruptState = SaveAndDisableInterrupts();\r
+\r
+  //\r
+  // Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)\r
+  //\r
+  AsmDisableCache ();\r
+\r
+  //\r
+  // Save original CR4 value and clear PGE flag (Bit 7)\r
+  //\r
+  MtrrContext->Cr4 = AsmReadCr4 ();\r
+  AsmWriteCr4 (MtrrContext->Cr4 & (~BIT7));\r
+\r
+  //\r
+  // Flush all TLBs\r
+  //\r
+  CpuFlushTlb ();\r
+\r
+  //\r
+  // Disable MTRRs\r
+  //\r
+  MtrrRegisterBitFieldWrite (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE, 10, 11, 0);\r
+}\r
+\r
+/**\r
+  Cleaning up after programming MTRRs.\r
+\r
+  This function will do some clean up after programming MTRRs:\r
+  Flush all TLBs,  re-enable caching, restore CR4.\r
+\r
+  @param[in] MtrrContext  Pointer to context to restore\r
+\r
+**/\r
+VOID\r
+PostMtrrChangeEnableCache (\r
+  IN MTRR_CONTEXT  *MtrrContext\r
+  )\r
+{\r
+  //\r
+  // Flush all TLBs\r
+  //\r
+  CpuFlushTlb ();\r
+\r
+  //\r
+  // Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)\r
+  //\r
+  AsmEnableCache ();\r
+\r
+  //\r
+  // Restore original CR4 value\r
+  //\r
+  AsmWriteCr4 (MtrrContext->Cr4);\r
+\r
+  //\r
+  // Restore original interrupt state\r
+  //\r
+  SetInterruptState (MtrrContext->InterruptState);\r
+}\r
+\r
+/**\r
+  Cleaning up after programming MTRRs.\r
+\r
+  This function will do some clean up after programming MTRRs:\r
+  enable MTRR caching functionality, and enable cache\r
+\r
+  @param[in] MtrrContext  Pointer to context to restore\r
+\r
+**/\r
+VOID\r
+PostMtrrChange (\r
+  IN MTRR_CONTEXT  *MtrrContext\r
+  )\r
+{\r
+  //\r
+  // Enable Cache MTRR\r
+  //\r
+  MtrrRegisterBitFieldWrite (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE, 10, 11, 3);\r
+\r
+  PostMtrrChangeEnableCache (MtrrContext);\r
+}\r
+\r
+/**\r
+  Worker function gets the content in fixed MTRRs\r
+\r
+  @param[out]  FixedSettings  A buffer to hold fixed MTRRs content.\r
+\r
+  @retval The pointer of FixedSettings\r
+\r
+**/\r
+MTRR_FIXED_SETTINGS*\r
+MtrrGetFixedMtrrWorker (\r
+  OUT MTRR_FIXED_SETTINGS         *FixedSettings\r
+  )\r
+{\r
+  UINT32  Index;\r
+\r
+  for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
+      FixedSettings->Mtrr[Index] =\r
+        MtrrRegisterRead (mMtrrLibFixedMtrrTable[Index].Msr);\r
+  }\r
+\r
+  return FixedSettings;\r
+}\r
+\r
+\r
+/**\r
+  This function gets the content in fixed MTRRs\r
+\r
+  @param[out]  FixedSettings  A buffer to hold fixed MTRRs content.\r
+\r
+  @retval The pointer of FixedSettings\r
+\r
+**/\r
+MTRR_FIXED_SETTINGS*\r
+EFIAPI\r
+MtrrGetFixedMtrr (\r
+  OUT MTRR_FIXED_SETTINGS         *FixedSettings\r
+  )\r
+{\r
+  if (!IsMtrrSupported ()) {\r
+    return FixedSettings;\r
+  }\r
+\r
+  return MtrrGetFixedMtrrWorker (FixedSettings);\r
+}\r
+\r
+\r
+/**\r
+  Worker function will get the raw value in variable MTRRs\r
+\r
+  If MtrrSetting is not NULL, gets the variable MTRRs raw value from input\r
+  MTRR settings buffer.\r
+  If MtrrSetting is NULL, gets the variable MTRRs raw value from MTRRs.\r
+\r
+  @param[in]  MtrrSetting        A buffer holding all MTRRs content.\r
+  @param[in]  VariableMtrrCount  Number of variable MTRRs.\r
+  @param[out] VariableSettings   A buffer to hold variable MTRRs content.\r
+\r
+  @return The VariableSettings input pointer\r
+\r
+**/\r
+MTRR_VARIABLE_SETTINGS*\r
+MtrrGetVariableMtrrWorker (\r
+  IN  MTRR_SETTINGS           *MtrrSetting,\r
+  IN  UINT32                  VariableMtrrCount,\r
+  OUT MTRR_VARIABLE_SETTINGS  *VariableSettings\r
+  )\r
+{\r
+  UINT32  Index;\r
+\r
+  ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
+\r
+  for (Index = 0; Index < VariableMtrrCount; Index++) {\r
+    if (MtrrSetting == NULL) {\r
+      VariableSettings->Mtrr[Index].Base =\r
+        MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0 + (Index << 1));\r
+      VariableSettings->Mtrr[Index].Mask =\r
+        MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0 + (Index << 1) + 1);\r
+    } else {\r
+      VariableSettings->Mtrr[Index].Base = MtrrSetting->Variables.Mtrr[Index].Base;\r
+      VariableSettings->Mtrr[Index].Mask = MtrrSetting->Variables.Mtrr[Index].Mask;\r
+    }\r
+  }\r
+\r
+  return  VariableSettings;\r
+}\r
+\r
+/**\r
+  This function will get the raw value in variable MTRRs\r
+\r
+  @param[out]  VariableSettings   A buffer to hold variable MTRRs content.\r
+\r
+  @return The VariableSettings input pointer\r
+\r
+**/\r
+MTRR_VARIABLE_SETTINGS*\r
+EFIAPI\r
+MtrrGetVariableMtrr (\r
+  OUT MTRR_VARIABLE_SETTINGS         *VariableSettings\r
+  )\r
+{\r
+  if (!IsMtrrSupported ()) {\r
+    return VariableSettings;\r
+  }\r
+\r
+  return MtrrGetVariableMtrrWorker (\r
+           NULL,\r
+           GetVariableMtrrCountWorker (),\r
+           VariableSettings\r
+           );\r
+}\r
+\r
+/**\r
+  Programs fixed MTRRs registers.\r
+\r
+  @param[in]      MemoryCacheType  The memory type to set.\r
+  @param[in, out] Base             The base address of memory range.\r
+  @param[in, out] Length           The length of memory range.\r
+  @param[out]     ReturnMsrNum     The index of the fixed MTRR MSR to program.\r
+  @param[out]     ReturnClearMask  The bits to clear in the fixed MTRR MSR.\r
+  @param[out]     ReturnOrMask     The bits to set in the fixed MTRR MSR.\r
+\r
+  @retval RETURN_SUCCESS      The cache type was updated successfully\r
+  @retval RETURN_UNSUPPORTED  The requested range or cache type was invalid\r
+                              for the fixed MTRRs.\r
+\r
+**/\r
+RETURN_STATUS\r
+ProgramFixedMtrr (\r
+  IN     UINT64               MemoryCacheType,\r
+  IN OUT UINT64               *Base,\r
+  IN OUT UINT64               *Length,\r
+  OUT    UINT32               *ReturnMsrNum,\r
+  OUT    UINT64               *ReturnClearMask,\r
+  OUT    UINT64               *ReturnOrMask\r
+  )\r
+{\r
+  UINT32  MsrNum;\r
+  UINT32  ByteShift;\r
+  UINT64  TempQword;\r
+  UINT64  OrMask;\r
+  UINT64  ClearMask;\r
+\r
+  TempQword = 0;\r
+  OrMask    = 0;\r
+  ClearMask = 0;\r
+\r
+  for (MsrNum = 0; MsrNum < MTRR_NUMBER_OF_FIXED_MTRR; MsrNum++) {\r
+    if ((*Base >= mMtrrLibFixedMtrrTable[MsrNum].BaseAddress) &&\r
+        (*Base <\r
+            (\r
+              mMtrrLibFixedMtrrTable[MsrNum].BaseAddress +\r
+              (8 * mMtrrLibFixedMtrrTable[MsrNum].Length)\r
+            )\r
+          )\r
+        ) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (MsrNum == MTRR_NUMBER_OF_FIXED_MTRR) {\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // We found the fixed MTRR to be programmed\r
+  //\r
+  for (ByteShift = 0; ByteShift < 8; ByteShift++) {\r
+    if (*Base ==\r
+         (\r
+           mMtrrLibFixedMtrrTable[MsrNum].BaseAddress +\r
+           (ByteShift * mMtrrLibFixedMtrrTable[MsrNum].Length)\r
+         )\r
+       ) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (ByteShift == 8) {\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+\r
+  for (\r
+        ;\r
+        ((ByteShift < 8) && (*Length >= mMtrrLibFixedMtrrTable[MsrNum].Length));\r
+        ByteShift++\r
+      ) {\r
+    OrMask |= LShiftU64 ((UINT64) MemoryCacheType, (UINT32) (ByteShift * 8));\r
+    ClearMask |= LShiftU64 ((UINT64) 0xFF, (UINT32) (ByteShift * 8));\r
+    *Length -= mMtrrLibFixedMtrrTable[MsrNum].Length;\r
+    *Base += mMtrrLibFixedMtrrTable[MsrNum].Length;\r
+  }\r
+\r
+  if (ByteShift < 8 && (*Length != 0)) {\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+\r
+  *ReturnMsrNum    = MsrNum;\r
+  *ReturnClearMask = ClearMask;\r
+  *ReturnOrMask    = OrMask;\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Worker function gets the attribute of variable MTRRs.\r
+\r
+  This function shadows the content of variable MTRRs into an\r
+  internal array: VariableMtrr.\r
+\r
+  @param[in]   VariableSettings           The variable MTRR values to shadow\r
+  @param[in]   FirmwareVariableMtrrCount  The number of variable MTRRs available to firmware\r
+  @param[in]   MtrrValidBitsMask          The mask for the valid bit of the MTRR\r
+  @param[in]   MtrrValidAddressMask       The valid address mask for MTRR\r
+  @param[out]  VariableMtrr               The array to shadow variable MTRRs content\r
+\r
+  @return                       The return value of this parameter indicates the\r
+                                number of MTRRs which has been used.\r
+\r
+**/\r
+UINT32\r
+MtrrGetMemoryAttributeInVariableMtrrWorker (\r
+  IN  MTRR_VARIABLE_SETTINGS  *VariableSettings,\r
+  IN  UINTN                   FirmwareVariableMtrrCount,\r
+  IN  UINT64                  MtrrValidBitsMask,\r
+  IN  UINT64                  MtrrValidAddressMask,\r
+  OUT VARIABLE_MTRR           *VariableMtrr\r
+  )\r
+{\r
+  UINTN   Index;\r
+  UINT32  UsedMtrr;\r
+\r
+  ZeroMem (VariableMtrr, sizeof (VARIABLE_MTRR) * MTRR_NUMBER_OF_VARIABLE_MTRR);\r
+  for (Index = 0, UsedMtrr = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
+    if ((VariableSettings->Mtrr[Index].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) != 0) {\r
+      VariableMtrr[Index].Msr         = (UINT32)Index;\r
+      VariableMtrr[Index].BaseAddress = (VariableSettings->Mtrr[Index].Base & MtrrValidAddressMask);\r
+      VariableMtrr[Index].Length      = ((~(VariableSettings->Mtrr[Index].Mask & MtrrValidAddressMask)) & MtrrValidBitsMask) + 1;\r
+      VariableMtrr[Index].Type        = (VariableSettings->Mtrr[Index].Base & 0x0ff);\r
+      VariableMtrr[Index].Valid       = TRUE;\r
+      VariableMtrr[Index].Used        = TRUE;\r
+      UsedMtrr++;\r
+    }\r
+  }\r
+  return UsedMtrr;\r
+}\r
+\r
+\r
+/**\r
+  Gets the attribute of variable MTRRs.\r
+\r
+  This function shadows the content of variable MTRRs into an\r
+  internal array: VariableMtrr.\r
+\r
+  @param[in]   MtrrValidBitsMask     The mask for the valid bit of the MTRR\r
+  @param[in]   MtrrValidAddressMask  The valid address mask for MTRR\r
+  @param[out]  VariableMtrr          The array to shadow variable MTRRs content\r
+\r
+  @return                       The return value of this paramter indicates the\r
+                                number of MTRRs which has been used.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+MtrrGetMemoryAttributeInVariableMtrr (\r
+  IN  UINT64                    MtrrValidBitsMask,\r
+  IN  UINT64                    MtrrValidAddressMask,\r
+  OUT VARIABLE_MTRR             *VariableMtrr\r
+  )\r
+{\r
+  MTRR_VARIABLE_SETTINGS  VariableSettings;\r
+\r
+  if (!IsMtrrSupported ()) {\r
+    return 0;\r
+  }\r
+\r
+  MtrrGetVariableMtrrWorker (\r
+    NULL,\r
+    GetVariableMtrrCountWorker (),\r
+    &VariableSettings\r
+    );\r
+\r
+  return MtrrGetMemoryAttributeInVariableMtrrWorker (\r
+           &VariableSettings,\r
+           GetFirmwareVariableMtrrCountWorker (),\r
+           MtrrValidBitsMask,\r
+           MtrrValidAddressMask,\r
+           VariableMtrr\r
+           );\r
+}\r
+\r
+\r
+/**\r
+  Checks overlap between given memory range and MTRRs.\r
+\r
+  @param[in]  FirmwareVariableMtrrCount  The number of variable MTRRs available\r
+                                         to firmware.\r
+  @param[in]  Start                      The start address of memory range.\r
+  @param[in]  End                        The end address of memory range.\r
+  @param[in]  VariableMtrr               The array to shadow variable MTRRs content\r
+\r
+  @retval TRUE             Overlap exists.\r
+  @retval FALSE            No overlap.\r
+\r
+**/\r
+BOOLEAN\r
+CheckMemoryAttributeOverlap (\r
+  IN UINTN             FirmwareVariableMtrrCount,\r
+  IN PHYSICAL_ADDRESS  Start,\r
+  IN PHYSICAL_ADDRESS  End,\r
+  IN VARIABLE_MTRR     *VariableMtrr\r
+  )\r
+{\r
+  UINT32  Index;\r
+\r
+  for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
+    if (\r
+         VariableMtrr[Index].Valid &&\r
+         !(\r
+           (Start > (VariableMtrr[Index].BaseAddress +\r
+                     VariableMtrr[Index].Length - 1)\r
+           ) ||\r
+           (End < VariableMtrr[Index].BaseAddress)\r
+         )\r
+       ) {\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+\r
+/**\r
+  Marks a variable MTRR as non-valid.\r
+\r
+  @param[in]   Index         The index of the array VariableMtrr to be invalidated\r
+  @param[in]   VariableMtrr  The array to shadow variable MTRRs content\r
+  @param[out]  UsedMtrr      The number of MTRRs which has already been used\r
+\r
+**/\r
+VOID\r
+InvalidateShadowMtrr (\r
+  IN   UINTN              Index,\r
+  IN   VARIABLE_MTRR      *VariableMtrr,\r
+  OUT  UINT32             *UsedMtrr\r
+  )\r
+{\r
+  VariableMtrr[Index].Valid = FALSE;\r
+  *UsedMtrr = *UsedMtrr - 1;\r
+}\r
+\r
+\r
+/**\r
+  Combines memory attributes.\r
+\r
+  If overlap exists between given memory range and MTRRs, try to combine them.\r
+\r
+  @param[in]       FirmwareVariableMtrrCount  The number of variable MTRRs\r
+                                              available to firmware.\r
+  @param[in]       Attributes                 The memory type to set.\r
+  @param[in, out]  Base                       The base address of memory range.\r
+  @param[in, out]  Length                     The length of memory range.\r
+  @param[in]       VariableMtrr               The array to shadow variable MTRRs content\r
+  @param[in, out]  UsedMtrr                   The number of MTRRs which has already been used\r
+  @param[out]      OverwriteExistingMtrr      Returns whether an existing MTRR was used\r
+\r
+  @retval EFI_SUCCESS            Memory region successfully combined.\r
+  @retval EFI_ACCESS_DENIED      Memory region cannot be combined.\r
+\r
+**/\r
+RETURN_STATUS\r
+CombineMemoryAttribute (\r
+  IN     UINT32             FirmwareVariableMtrrCount,\r
+  IN     UINT64             Attributes,\r
+  IN OUT UINT64             *Base,\r
+  IN OUT UINT64             *Length,\r
+  IN     VARIABLE_MTRR      *VariableMtrr,\r
+  IN OUT UINT32             *UsedMtrr,\r
+  OUT    BOOLEAN            *OverwriteExistingMtrr\r
+  )\r
+{\r
+  UINT32  Index;\r
+  UINT64  CombineStart;\r
+  UINT64  CombineEnd;\r
+  UINT64  MtrrEnd;\r
+  UINT64  EndAddress;\r
+  BOOLEAN CoveredByExistingMtrr;\r
+\r
+  *OverwriteExistingMtrr = FALSE;\r
+  CoveredByExistingMtrr = FALSE;\r
+  EndAddress = *Base +*Length - 1;\r
+\r
+  for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
+\r
+    MtrrEnd = VariableMtrr[Index].BaseAddress + VariableMtrr[Index].Length - 1;\r
+    if (\r
+         !VariableMtrr[Index].Valid ||\r
+         (\r
+           *Base > (MtrrEnd) ||\r
+           (EndAddress < VariableMtrr[Index].BaseAddress)\r
+         )\r
+       ) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Combine same attribute MTRR range\r
+    //\r
+    if (Attributes == VariableMtrr[Index].Type) {\r
+      //\r
+      // if the MTRR range contain the request range, set a flag, then continue to\r
+      // invalidate any MTRR of the same request range with higher priority cache type.\r
+      //\r
+      if (VariableMtrr[Index].BaseAddress <= *Base && MtrrEnd >= EndAddress) {\r
+        CoveredByExistingMtrr = TRUE;\r
+        continue;\r
+      }\r
+      //\r
+      // invalid this MTRR, and program the combine range\r
+      //\r
+      CombineStart  =\r
+        (*Base) < VariableMtrr[Index].BaseAddress ?\r
+          (*Base) :\r
+          VariableMtrr[Index].BaseAddress;\r
+      CombineEnd    = EndAddress > MtrrEnd ? EndAddress : MtrrEnd;\r
+\r
+      //\r
+      // Record the MTRR usage status in VariableMtrr array.\r
+      //\r
+      InvalidateShadowMtrr (Index, VariableMtrr, UsedMtrr);\r
+      *Base       = CombineStart;\r
+      *Length     = CombineEnd - CombineStart + 1;\r
+      EndAddress  = CombineEnd;\r
+      *OverwriteExistingMtrr = TRUE;\r
+      continue;\r
+    } else {\r
+      //\r
+      // The cache type is different, but the range is convered by one MTRR\r
+      //\r
+      if (VariableMtrr[Index].BaseAddress == *Base && MtrrEnd == EndAddress) {\r
+        InvalidateShadowMtrr (Index, VariableMtrr, UsedMtrr);\r
+        continue;\r
+      }\r
+\r
+    }\r
+\r
+    if ((Attributes== MTRR_CACHE_WRITE_THROUGH &&\r
+         VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK) ||\r
+        (Attributes == MTRR_CACHE_WRITE_BACK &&\r
+         VariableMtrr[Index].Type == MTRR_CACHE_WRITE_THROUGH) ||\r
+        (Attributes == MTRR_CACHE_UNCACHEABLE) ||\r
+        (VariableMtrr[Index].Type == MTRR_CACHE_UNCACHEABLE)\r
+     ) {\r
+      *OverwriteExistingMtrr = TRUE;\r
+      continue;\r
+    }\r
+    //\r
+    // Other type memory overlap is invalid\r
+    //\r
+    return RETURN_ACCESS_DENIED;\r
+  }\r
+\r
+  if (CoveredByExistingMtrr) {\r
+    *Length = 0;\r
+  }\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Calculates the maximum value which is a power of 2, but less the MemoryLength.\r
+\r
+  @param[in]  MemoryLength        The number to pass in.\r
+\r
+  @return The maximum value which is align to power of 2 and less the MemoryLength\r
+\r
+**/\r
+UINT64\r
+Power2MaxMemory (\r
+  IN UINT64                     MemoryLength\r
+  )\r
+{\r
+  UINT64  Result;\r
+\r
+  if (RShiftU64 (MemoryLength, 32) != 0) {\r
+    Result = LShiftU64 (\r
+               (UINT64) GetPowerOfTwo32 (\r
+                          (UINT32) RShiftU64 (MemoryLength, 32)\r
+                          ),\r
+               32\r
+               );\r
+  } else {\r
+    Result = (UINT64) GetPowerOfTwo32 ((UINT32) MemoryLength);\r
+  }\r
+\r
+  return Result;\r
+}\r
+\r
+\r
+/**\r
+  Determines the MTRR numbers used to program a memory range.\r
+\r
+  This function first checks the alignment of the base address.\r
+  If the alignment of the base address <= Length, cover the memory range\r
+ (BaseAddress, alignment) by a MTRR, then BaseAddress += alignment and\r
+  Length -= alignment. Repeat the step until alignment > Length.\r
+\r
+  Then this function determines which direction of programming the variable\r
+  MTRRs for the remaining length will use fewer MTRRs.\r
+\r
+  @param[in]  BaseAddress Length of Memory to program MTRR\r
+  @param[in]  Length      Length of Memory to program MTRR\r
+  @param[in]  MtrrNumber  Pointer to the number of necessary MTRRs\r
+\r
+  @retval TRUE        Positive direction is better.\r
+          FALSE       Negative direction is better.\r
+\r
+**/\r
+BOOLEAN\r
+GetMtrrNumberAndDirection (\r
+  IN UINT64      BaseAddress,\r
+  IN UINT64      Length,\r
+  IN UINTN       *MtrrNumber\r
+  )\r
+{\r
+  UINT64  TempQword;\r
+  UINT64  Alignment;\r
+  UINT32  Positive;\r
+  UINT32  Subtractive;\r
+\r
+  *MtrrNumber = 0;\r
+\r
+  if (BaseAddress != 0) {\r
+    do {\r
+      //\r
+      // Calculate the alignment of the base address.\r
+      //\r
+      Alignment = LShiftU64 (1, (UINTN)LowBitSet64 (BaseAddress));\r
+\r
+      if (Alignment > Length) {\r
+        break;\r
+      }\r
+\r
+      (*MtrrNumber)++;\r
+      BaseAddress += Alignment;\r
+      Length -= Alignment;\r
+    } while (TRUE);\r
+\r
+    if (Length == 0) {\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  TempQword   = Length;\r
+  Positive    = 0;\r
+  Subtractive = 0;\r
+\r
+  do {\r
+    TempQword -= Power2MaxMemory (TempQword);\r
+    Positive++;\r
+  } while (TempQword != 0);\r
+\r
+  TempQword = Power2MaxMemory (LShiftU64 (Length, 1)) - Length;\r
+  Subtractive++;\r
+  do {\r
+    TempQword -= Power2MaxMemory (TempQword);\r
+    Subtractive++;\r
+  } while (TempQword != 0);\r
+\r
+  if (Positive <= Subtractive) {\r
+    *MtrrNumber += Positive;\r
+    return TRUE;\r
+  } else {\r
+    *MtrrNumber += Subtractive;\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Invalid variable MTRRs according to the value in the shadow array.\r
+\r
+  This function programs MTRRs according to the values specified\r
+  in the shadow array.\r
+\r
+  @param[in, out]  VariableSettings   Variable MTRR settings\r
+  @param[in]       VariableMtrrCount  Number of variable MTRRs\r
+  @param[in, out]  VariableMtrr       Shadow of variable MTRR contents\r
+\r
+**/\r
+VOID\r
+InvalidateMtrr (\r
+  IN OUT MTRR_VARIABLE_SETTINGS  *VariableSettings,\r
+  IN     UINTN                   VariableMtrrCount,\r
+  IN OUT VARIABLE_MTRR           *VariableMtrr\r
+  )\r
+{\r
+  UINTN         Index;\r
+\r
+  for (Index = 0; Index < VariableMtrrCount; Index++) {\r
+    if (!VariableMtrr[Index].Valid && VariableMtrr[Index].Used) {\r
+       VariableSettings->Mtrr[Index].Base = 0;\r
+       VariableSettings->Mtrr[Index].Mask = 0;\r
+       VariableMtrr[Index].Used = FALSE;\r
+    }\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Programs variable MTRRs\r
+\r
+  This function programs variable MTRRs\r
+\r
+  @param[in, out]  VariableSettings      Variable MTRR settings.\r
+  @param[in]       MtrrNumber            Index of MTRR to program.\r
+  @param[in]       BaseAddress           Base address of memory region.\r
+  @param[in]       Length                Length of memory region.\r
+  @param[in]       MemoryCacheType       Memory type to set.\r
+  @param[in]       MtrrValidAddressMask  The valid address mask for MTRR\r
+\r
+**/\r
+VOID\r
+ProgramVariableMtrr (\r
+  IN OUT MTRR_VARIABLE_SETTINGS  *VariableSettings,\r
+  IN     UINTN                   MtrrNumber,\r
+  IN     PHYSICAL_ADDRESS        BaseAddress,\r
+  IN     UINT64                  Length,\r
+  IN     UINT64                  MemoryCacheType,\r
+  IN     UINT64                  MtrrValidAddressMask\r
+  )\r
+{\r
+  UINT64        TempQword;\r
+\r
+  //\r
+  // MTRR Physical Base\r
+  //\r
+  TempQword = (BaseAddress & MtrrValidAddressMask) | MemoryCacheType;\r
+  VariableSettings->Mtrr[MtrrNumber].Base = TempQword;\r
+\r
+  //\r
+  // MTRR Physical Mask\r
+  //\r
+  TempQword = ~(Length - 1);\r
+  VariableSettings->Mtrr[MtrrNumber].Mask = (TempQword & MtrrValidAddressMask) | MTRR_LIB_CACHE_MTRR_ENABLED;\r
+}\r
+\r
+\r
+/**\r
+  Converts the Memory attribute value to MTRR_MEMORY_CACHE_TYPE.\r
+\r
+  If MtrrSetting is not NULL, gets the default memory attribute from input\r
+  MTRR settings buffer.\r
+  If MtrrSetting is NULL, gets the default memory attribute from MSR.\r
+\r
+  @param[in]  MtrrSetting        A buffer holding all MTRRs content.\r
+  @param[in]  MtrrType           MTRR memory type\r
+\r
+  @return The enum item in MTRR_MEMORY_CACHE_TYPE\r
+\r
+**/\r
+MTRR_MEMORY_CACHE_TYPE\r
+GetMemoryCacheTypeFromMtrrType (\r
+  IN MTRR_SETTINGS         *MtrrSetting,\r
+  IN UINT64                MtrrType\r
+  )\r
+{\r
+  switch (MtrrType) {\r
+  case MTRR_CACHE_UNCACHEABLE:\r
+    return CacheUncacheable;\r
+  case MTRR_CACHE_WRITE_COMBINING:\r
+    return CacheWriteCombining;\r
+  case MTRR_CACHE_WRITE_THROUGH:\r
+    return CacheWriteThrough;\r
+  case MTRR_CACHE_WRITE_PROTECTED:\r
+    return CacheWriteProtected;\r
+  case MTRR_CACHE_WRITE_BACK:\r
+    return CacheWriteBack;\r
+  default:\r
+    //\r
+    // MtrrType is MTRR_CACHE_INVALID_TYPE, that means\r
+    // no MTRR covers the range\r
+    //\r
+    return MtrrGetDefaultMemoryTypeWorker (MtrrSetting);\r
+  }\r
+}\r
+\r
+/**\r
+  Initializes the valid bits mask and valid address mask for MTRRs.\r
+\r
+  This function initializes the valid bits mask and valid address mask for MTRRs.\r
+\r
+  @param[out]  MtrrValidBitsMask     The mask for the valid bit of the MTRR\r
+  @param[out]  MtrrValidAddressMask  The valid address mask for the MTRR\r
+\r
+**/\r
+VOID\r
+MtrrLibInitializeMtrrMask (\r
+  OUT UINT64 *MtrrValidBitsMask,\r
+  OUT UINT64 *MtrrValidAddressMask\r
+  )\r
+{\r
+  UINT32  RegEax;\r
+  UINT8   PhysicalAddressBits;\r
+\r
+  AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+\r
+  if (RegEax >= 0x80000008) {\r
+    AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
+\r
+    PhysicalAddressBits = (UINT8) RegEax;\r
+\r
+    *MtrrValidBitsMask    = LShiftU64 (1, PhysicalAddressBits) - 1;\r
+    *MtrrValidAddressMask = *MtrrValidBitsMask & 0xfffffffffffff000ULL;\r
+  } else {\r
+    *MtrrValidBitsMask    = MTRR_LIB_MSR_VALID_MASK;\r
+    *MtrrValidAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Determines the real attribute of a memory range.\r
+\r
+  This function is to arbitrate the real attribute of the memory when\r
+  there are 2 MTRRs covers the same memory range.  For further details,\r
+  please refer the IA32 Software Developer's Manual, Volume 3,\r
+  Section 10.11.4.1.\r
+\r
+  @param[in]  MtrrType1    The first kind of Memory type\r
+  @param[in]  MtrrType2    The second kind of memory type\r
+\r
+**/\r
+UINT64\r
+MtrrPrecedence (\r
+  IN UINT64    MtrrType1,\r
+  IN UINT64    MtrrType2\r
+  )\r
+{\r
+  UINT64 MtrrType;\r
+\r
+  MtrrType = MTRR_CACHE_INVALID_TYPE;\r
+  switch (MtrrType1) {\r
+  case MTRR_CACHE_UNCACHEABLE:\r
+    MtrrType = MTRR_CACHE_UNCACHEABLE;\r
+    break;\r
+  case MTRR_CACHE_WRITE_COMBINING:\r
+    if (\r
+         MtrrType2==MTRR_CACHE_WRITE_COMBINING ||\r
+         MtrrType2==MTRR_CACHE_UNCACHEABLE\r
+       ) {\r
+      MtrrType = MtrrType2;\r
+    }\r
+    break;\r
+  case MTRR_CACHE_WRITE_THROUGH:\r
+    if (\r
+         MtrrType2==MTRR_CACHE_WRITE_THROUGH ||\r
+         MtrrType2==MTRR_CACHE_WRITE_BACK\r
+       ) {\r
+      MtrrType = MTRR_CACHE_WRITE_THROUGH;\r
+    } else if(MtrrType2==MTRR_CACHE_UNCACHEABLE) {\r
+      MtrrType = MTRR_CACHE_UNCACHEABLE;\r
+    }\r
+    break;\r
+  case MTRR_CACHE_WRITE_PROTECTED:\r
+    if (MtrrType2 == MTRR_CACHE_WRITE_PROTECTED ||\r
+        MtrrType2 == MTRR_CACHE_UNCACHEABLE) {\r
+      MtrrType = MtrrType2;\r
+    }\r
+    break;\r
+  case MTRR_CACHE_WRITE_BACK:\r
+    if (\r
+         MtrrType2== MTRR_CACHE_UNCACHEABLE ||\r
+         MtrrType2==MTRR_CACHE_WRITE_THROUGH ||\r
+         MtrrType2== MTRR_CACHE_WRITE_BACK\r
+       ) {\r
+      MtrrType = MtrrType2;\r
+    }\r
+    break;\r
+  case MTRR_CACHE_INVALID_TYPE:\r
+    MtrrType = MtrrType2;\r
+    break;\r
+  default:\r
+    break;\r
+  }\r
+\r
+  if (MtrrType2 == MTRR_CACHE_INVALID_TYPE) {\r
+    MtrrType = MtrrType1;\r
+  }\r
+  return MtrrType;\r
+}\r
+\r
+/**\r
+  Worker function will get the memory cache type of the specific address.\r
+\r
+  If MtrrSetting is not NULL, gets the memory cache type from input\r
+  MTRR settings buffer.\r
+  If MtrrSetting is NULL, gets the memory cache type from MTRRs.\r
+\r
+  @param[in]  MtrrSetting        A buffer holding all MTRRs content.\r
+  @param[in]  Address            The specific address\r
+\r
+  @return Memory cache type of the specific address\r
+\r
+**/\r
+MTRR_MEMORY_CACHE_TYPE\r
+MtrrGetMemoryAttributeByAddressWorker (\r
+  IN MTRR_SETTINGS      *MtrrSetting,\r
+  IN PHYSICAL_ADDRESS   Address\r
+  )\r
+{\r
+  UINT64                  TempQword;\r
+  UINTN                   Index;\r
+  UINTN                   SubIndex;\r
+  UINT64                  MtrrType;\r
+  UINT64                  TempMtrrType;\r
+  MTRR_MEMORY_CACHE_TYPE  CacheType;\r
+  VARIABLE_MTRR           VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];\r
+  UINT64                  MtrrValidBitsMask;\r
+  UINT64                  MtrrValidAddressMask;\r
+  UINTN                   VariableMtrrCount;\r
+  MTRR_VARIABLE_SETTINGS  VariableSettings;\r
+\r
+  //\r
+  // Check if MTRR is enabled, if not, return UC as attribute\r
+  //\r
+  if (MtrrSetting == NULL) {\r
+    TempQword = MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE);\r
+  } else {\r
+    TempQword = MtrrSetting->MtrrDefType;\r
+  }\r
+  MtrrType = MTRR_CACHE_INVALID_TYPE;\r
+\r
+  if ((TempQword & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
+    return CacheUncacheable;\r
+  }\r
+\r
+  //\r
+  // If address is less than 1M, then try to go through the fixed MTRR\r
+  //\r
+  if (Address < BASE_1MB) {\r
+    if ((TempQword & MTRR_LIB_CACHE_FIXED_MTRR_ENABLED) != 0) {\r
+      //\r
+      // Go through the fixed MTRR\r
+      //\r
+      for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
+         if (Address >= mMtrrLibFixedMtrrTable[Index].BaseAddress &&\r
+             Address  < (\r
+                          mMtrrLibFixedMtrrTable[Index].BaseAddress +\r
+                          (mMtrrLibFixedMtrrTable[Index].Length * 8)\r
+                        )\r
+            ) {\r
+           SubIndex =\r
+             ((UINTN)Address - mMtrrLibFixedMtrrTable[Index].BaseAddress) /\r
+               mMtrrLibFixedMtrrTable[Index].Length;\r
+           if (MtrrSetting == NULL) {\r
+             TempQword = MtrrRegisterRead (mMtrrLibFixedMtrrTable[Index].Msr);\r
+           } else {\r
+             TempQword = MtrrSetting->Fixed.Mtrr[Index];\r
+           }\r
+           MtrrType =  RShiftU64 (TempQword, SubIndex * 8) & 0xFF;\r
+           return GetMemoryCacheTypeFromMtrrType (MtrrSetting, MtrrType);\r
+         }\r
+      }\r
+    }\r
+  }\r
+  MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);\r
+\r
+  MtrrGetVariableMtrrWorker (\r
+    MtrrSetting,\r
+    GetVariableMtrrCountWorker (),\r
+    &VariableSettings\r
+    );\r
+\r
+  MtrrGetMemoryAttributeInVariableMtrrWorker (\r
+           &VariableSettings,\r
+           GetFirmwareVariableMtrrCountWorker (),\r
+           MtrrValidBitsMask,\r
+           MtrrValidAddressMask,\r
+           VariableMtrr\r
+           );\r
+\r
+  //\r
+  // Go through the variable MTRR\r
+  //\r
+  VariableMtrrCount = GetVariableMtrrCountWorker ();\r
+  ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
+\r
+  for (Index = 0; Index < VariableMtrrCount; Index++) {\r
+    if (VariableMtrr[Index].Valid) {\r
+      if (Address >= VariableMtrr[Index].BaseAddress &&\r
+          Address < VariableMtrr[Index].BaseAddress+VariableMtrr[Index].Length) {\r
+        TempMtrrType = VariableMtrr[Index].Type;\r
+        MtrrType = MtrrPrecedence (MtrrType, TempMtrrType);\r
+      }\r
+    }\r
+  }\r
+  CacheType = GetMemoryCacheTypeFromMtrrType (MtrrSetting, MtrrType);\r
+\r
+  return CacheType;\r
+}\r
+\r
+\r
+/**\r
+  This function will get the memory cache type of the specific address.\r
+\r
+  This function is mainly for debug purpose.\r
+\r
+  @param[in]  Address   The specific address\r
+\r
+  @return Memory cache type of the specific address\r
+\r
+**/\r
+MTRR_MEMORY_CACHE_TYPE\r
+EFIAPI\r
+MtrrGetMemoryAttribute (\r
+  IN PHYSICAL_ADDRESS   Address\r
+  )\r
+{\r
+  if (!IsMtrrSupported ()) {\r
+    return CacheUncacheable;\r
+  }\r
+\r
+  return MtrrGetMemoryAttributeByAddressWorker (NULL, Address);\r
+}\r
+\r
+/**\r
+  Worker function prints all MTRRs for debugging.\r
+\r
+  If MtrrSetting is not NULL, print MTRR settings from from input MTRR\r
+  settings buffer.\r
+  If MtrrSetting is NULL, print MTRR settings from MTRRs.\r
+\r
+  @param  MtrrSetting    A buffer holding all MTRRs content.\r
+**/\r
+VOID\r
+MtrrDebugPrintAllMtrrsWorker (\r
+  IN MTRR_SETTINGS    *MtrrSetting\r
+  )\r
+{\r
+  DEBUG_CODE (\r
+    MTRR_SETTINGS  LocalMtrrs;\r
+    MTRR_SETTINGS  *Mtrrs;\r
+    UINTN          Index;\r
+    UINTN          Index1;\r
+    UINTN          VariableMtrrCount;\r
+    UINT64         Base;\r
+    UINT64         Limit;\r
+    UINT64         MtrrBase;\r
+    UINT64         MtrrLimit;\r
+    UINT64         RangeBase;\r
+    UINT64         RangeLimit;\r
+    UINT64         NoRangeBase;\r
+    UINT64         NoRangeLimit;\r
+    UINT32         RegEax;\r
+    UINTN          MemoryType;\r
+    UINTN          PreviousMemoryType;\r
+    BOOLEAN        Found;\r
+\r
+    if (!IsMtrrSupported ()) {\r
+      return;\r
+    }\r
+\r
+    DEBUG((DEBUG_CACHE, "MTRR Settings\n"));\r
+    DEBUG((DEBUG_CACHE, "=============\n"));\r
+\r
+    if (MtrrSetting != NULL) {\r
+      Mtrrs = MtrrSetting;\r
+    } else {\r
+      MtrrGetAllMtrrs (&LocalMtrrs);\r
+      Mtrrs = &LocalMtrrs;\r
+    }\r
+\r
+    DEBUG((DEBUG_CACHE, "MTRR Default Type: %016lx\n", Mtrrs->MtrrDefType));\r
+    for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
+      DEBUG((DEBUG_CACHE, "Fixed MTRR[%02d]   : %016lx\n", Index, Mtrrs->Fixed.Mtrr[Index]));\r
+    }\r
+\r
+    VariableMtrrCount = GetVariableMtrrCount ();\r
+    for (Index = 0; Index < VariableMtrrCount; Index++) {\r
+      DEBUG((DEBUG_CACHE, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",\r
+        Index,\r
+        Mtrrs->Variables.Mtrr[Index].Base,\r
+        Mtrrs->Variables.Mtrr[Index].Mask\r
+        ));\r
+    }\r
+    DEBUG((DEBUG_CACHE, "\n"));\r
+    DEBUG((DEBUG_CACHE, "MTRR Ranges\n"));\r
+    DEBUG((DEBUG_CACHE, "====================================\n"));\r
+\r
+    Base = 0;\r
+    PreviousMemoryType = MTRR_CACHE_INVALID_TYPE;\r
+    for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
+      Base = mMtrrLibFixedMtrrTable[Index].BaseAddress;\r
+      for (Index1 = 0; Index1 < 8; Index1++) {\r
+      MemoryType = (UINTN)(RShiftU64 (Mtrrs->Fixed.Mtrr[Index], Index1 * 8) & 0xff);\r
+        if (MemoryType > CacheWriteBack) {\r
+          MemoryType = MTRR_CACHE_INVALID_TYPE;\r
+        }\r
+        if (MemoryType != PreviousMemoryType) {\r
+          if (PreviousMemoryType != MTRR_CACHE_INVALID_TYPE) {\r
+            DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));\r
+          }\r
+          PreviousMemoryType = MemoryType;\r
+          DEBUG((DEBUG_CACHE, "%a:%016lx-", mMtrrMemoryCacheTypeShortName[MemoryType], Base));\r
+        }\r
+        Base += mMtrrLibFixedMtrrTable[Index].Length;\r
+      }\r
+    }\r
+    DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));\r
+\r
+    VariableMtrrCount = GetVariableMtrrCount ();\r
+\r
+    Limit        = BIT36 - 1;\r
+    AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+    if (RegEax >= 0x80000008) {\r
+      AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
+      Limit = LShiftU64 (1, RegEax & 0xff) - 1;\r
+    }\r
+    Base = BASE_1MB;\r
+    PreviousMemoryType = MTRR_CACHE_INVALID_TYPE;\r
+    do {\r
+      MemoryType = MtrrGetMemoryAttributeByAddressWorker (Mtrrs, Base);\r
+      if (MemoryType > CacheWriteBack) {\r
+        MemoryType = MTRR_CACHE_INVALID_TYPE;\r
+      }\r
+\r
+      if (MemoryType != PreviousMemoryType) {\r
+        if (PreviousMemoryType != MTRR_CACHE_INVALID_TYPE) {\r
+          DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));\r
+        }\r
+        PreviousMemoryType = MemoryType;\r
+        DEBUG((DEBUG_CACHE, "%a:%016lx-", mMtrrMemoryCacheTypeShortName[MemoryType], Base));\r
+      }\r
+\r
+      RangeBase    = BASE_1MB;\r
+      NoRangeBase  = BASE_1MB;\r
+      RangeLimit   = Limit;\r
+      NoRangeLimit = Limit;\r
+\r
+      for (Index = 0, Found = FALSE; Index < VariableMtrrCount; Index++) {\r
+        if ((Mtrrs->Variables.Mtrr[Index].Mask & BIT11) == 0) {\r
+          //\r
+          // If mask is not valid, then do not display range\r
+          //\r
+          continue;\r
+        }\r
+        MtrrBase  = (Mtrrs->Variables.Mtrr[Index].Base & (~(SIZE_4KB - 1)));\r
+        MtrrLimit = MtrrBase + ((~(Mtrrs->Variables.Mtrr[Index].Mask & (~(SIZE_4KB - 1)))) & Limit);\r
+\r
+        if (Base >= MtrrBase && Base < MtrrLimit) {\r
+          Found = TRUE;\r
+        }\r
+\r
+        if (Base >= MtrrBase && MtrrBase > RangeBase) {\r
+          RangeBase = MtrrBase;\r
+        }\r
+        if (Base > MtrrLimit && MtrrLimit > RangeBase) {\r
+          RangeBase = MtrrLimit + 1;\r
+        }\r
+        if (Base < MtrrBase && MtrrBase < RangeLimit) {\r
+          RangeLimit = MtrrBase - 1;\r
+        }\r
+        if (Base < MtrrLimit && MtrrLimit <= RangeLimit) {\r
+          RangeLimit = MtrrLimit;\r
+        }\r
+\r
+        if (Base > MtrrLimit && NoRangeBase < MtrrLimit) {\r
+          NoRangeBase = MtrrLimit + 1;\r
+        }\r
+        if (Base < MtrrBase && NoRangeLimit > MtrrBase) {\r
+          NoRangeLimit = MtrrBase - 1;\r
+        }\r
+      }\r
+\r
+      if (Found) {\r
+        Base = RangeLimit + 1;\r
+      } else {\r
+        Base = NoRangeLimit + 1;\r
+      }\r
+    } while (Base < Limit);\r
+    DEBUG((DEBUG_CACHE, "%016lx\n\n", Base - 1));\r
+  );\r
+}\r
+\r
+\r
+/**\r
+  This function prints all MTRRs for debugging.\r
+**/\r
+VOID\r
+EFIAPI\r
+MtrrDebugPrintAllMtrrs (\r
+  VOID\r
+  )\r
+{\r
+  MtrrDebugPrintAllMtrrsWorker (NULL);\r
+}\r
+\r
+\r
+/**\r
+  Worker function attempts to set the attributes for a memory range.\r
+\r
+  If MtrrSettings is not NULL, set the attributes into the input MTRR\r
+  settings buffer.\r
+  If MtrrSettings is NULL, set the attributes into MTRRs registers.\r
+\r
+  @param[in, out]  MtrrSetting       A buffer holding all MTRRs content.\r
+  @param[in]       BaseAddress       The physical address that is the start\r
+                                     address of a memory region.\r
+  @param[in]       Length            The size in bytes of the memory region.\r
+  @param[in]       Attribute         The bit mask of attributes to set for the\r
+                                     memory region.\r
+\r
+  @retval RETURN_SUCCESS            The attributes were set for the memory\r
+                                    region.\r
+  @retval RETURN_INVALID_PARAMETER  Length is zero.\r
+  @retval RETURN_UNSUPPORTED        The processor does not support one or\r
+                                    more bytes of the memory resource range\r
+                                    specified by BaseAddress and Length.\r
+  @retval RETURN_UNSUPPORTED        The bit mask of attributes is not support\r
+                                    for the memory resource range specified\r
+                                    by BaseAddress and Length.\r
+  @retval RETURN_ACCESS_DENIED      The attributes for the memory resource\r
+                                    range specified by BaseAddress and Length\r
+                                    cannot be modified.\r
+  @retval RETURN_OUT_OF_RESOURCES   There are not enough system resources to\r
+                                    modify the attributes of the memory\r
+                                    resource range.\r
+\r
+**/\r
+RETURN_STATUS\r
+MtrrSetMemoryAttributeWorker (\r
+  IN OUT MTRR_SETTINGS           *MtrrSetting,\r
+  IN PHYSICAL_ADDRESS            BaseAddress,\r
+  IN UINT64                      Length,\r
+  IN MTRR_MEMORY_CACHE_TYPE      Attribute\r
+  )\r
+{\r
+  UINT64                    TempQword;\r
+  RETURN_STATUS             Status;\r
+  UINT64                    MemoryType;\r
+  UINT64                    Alignment;\r
+  BOOLEAN                   OverLap;\r
+  BOOLEAN                   Positive;\r
+  UINT32                    MsrNum;\r
+  UINTN                     MtrrNumber;\r
+  VARIABLE_MTRR             VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];\r
+  UINT32                    UsedMtrr;\r
+  UINT64                    MtrrValidBitsMask;\r
+  UINT64                    MtrrValidAddressMask;\r
+  BOOLEAN                   OverwriteExistingMtrr;\r
+  UINT32                    FirmwareVariableMtrrCount;\r
+  MTRR_CONTEXT              MtrrContext;\r
+  BOOLEAN                   MtrrContextValid;\r
+  BOOLEAN                   FixedSettingsValid[MTRR_NUMBER_OF_FIXED_MTRR];\r
+  BOOLEAN                   FixedSettingsModified[MTRR_NUMBER_OF_FIXED_MTRR];\r
+  MTRR_FIXED_SETTINGS       WorkingFixedSettings;\r
+  UINT32                    VariableMtrrCount;\r
+  MTRR_VARIABLE_SETTINGS    OriginalVariableSettings;\r
+  BOOLEAN                   ProgramVariableSettings;\r
+  MTRR_VARIABLE_SETTINGS    WorkingVariableSettings;\r
+  UINT32                    Index;\r
+  UINT64                    ClearMask;\r
+  UINT64                    OrMask;\r
+  UINT64                    NewValue;\r
+  MTRR_VARIABLE_SETTINGS    *VariableSettings;\r
+\r
+  MtrrContextValid  = FALSE;\r
+  VariableMtrrCount = 0;\r
+  ZeroMem (&WorkingFixedSettings, sizeof (WorkingFixedSettings));\r
+  for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
+    FixedSettingsValid[Index]    = FALSE;\r
+    FixedSettingsModified[Index] = FALSE;\r
+  }\r
+  ProgramVariableSettings = FALSE;\r
+\r
+  if (!IsMtrrSupported ()) {\r
+    Status = RETURN_UNSUPPORTED;\r
+    goto Done;\r
+  }\r
+\r
+  MtrrLibInitializeMtrrMask (&MtrrValidBitsMask, &MtrrValidAddressMask);\r
+\r
+  TempQword = 0;\r
+  MemoryType = (UINT64)Attribute;\r
+  OverwriteExistingMtrr = FALSE;\r
+\r
+  //\r
+  // Check for an invalid parameter\r
+  //\r
+  if (Length == 0) {\r
+    Status = RETURN_INVALID_PARAMETER;\r
+    goto Done;\r
+  }\r
+\r
+  if (\r
+       (BaseAddress & ~MtrrValidAddressMask) != 0 ||\r
+       (Length & ~MtrrValidAddressMask) != 0\r
+     ) {\r
+    Status = RETURN_UNSUPPORTED;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Check if Fixed MTRR\r
+  //\r
+  Status = RETURN_SUCCESS;\r
+  if (BaseAddress < BASE_1MB) {\r
+    while ((BaseAddress < BASE_1MB) && (Length > 0) && Status == RETURN_SUCCESS) {\r
+      Status = ProgramFixedMtrr (MemoryType, &BaseAddress, &Length, &MsrNum, &ClearMask, &OrMask);\r
+      if (RETURN_ERROR (Status)) {\r
+        goto Done;\r
+      }\r
+      if (MtrrSetting != NULL) {\r
+        MtrrSetting->Fixed.Mtrr[MsrNum] = (MtrrSetting->Fixed.Mtrr[MsrNum] & ~ClearMask) | OrMask;\r
+        MtrrSetting->MtrrDefType |= MTRR_LIB_CACHE_FIXED_MTRR_ENABLED;\r
+      } else {\r
+        if (!FixedSettingsValid[MsrNum]) {\r
+          WorkingFixedSettings.Mtrr[MsrNum] = MtrrRegisterRead (mMtrrLibFixedMtrrTable[MsrNum].Msr);\r
+          FixedSettingsValid[MsrNum] = TRUE;\r
+        }\r
+        NewValue = (WorkingFixedSettings.Mtrr[MsrNum] & ~ClearMask) | OrMask;\r
+        if (WorkingFixedSettings.Mtrr[MsrNum] != NewValue) {\r
+          WorkingFixedSettings.Mtrr[MsrNum] = NewValue;\r
+          FixedSettingsModified[MsrNum] = TRUE;\r
+        }\r
+      }\r
+    }\r
+\r
+    if (Length == 0) {\r
+      //\r
+      // A Length of 0 can only make sense for fixed MTTR ranges.\r
+      // Since we just handled the fixed MTRRs, we can skip the\r
+      // variable MTRR section.\r
+      //\r
+      goto Done;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Since memory ranges below 1MB will be overridden by the fixed MTRRs,\r
+  // we can set the base to 0 to save variable MTRRs.\r
+  //\r
+  if (BaseAddress == BASE_1MB) {\r
+    BaseAddress = 0;\r
+    Length += SIZE_1MB;\r
+  }\r
+\r
+  //\r
+  // Read all variable MTRRs\r
+  //\r
+  VariableMtrrCount = GetVariableMtrrCountWorker ();\r
+  FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCountWorker ();\r
+  if (MtrrSetting != NULL) {\r
+    VariableSettings = &MtrrSetting->Variables;\r
+  } else {\r
+    MtrrGetVariableMtrrWorker (NULL, VariableMtrrCount, &OriginalVariableSettings);\r
+    CopyMem (&WorkingVariableSettings, &OriginalVariableSettings, sizeof (WorkingVariableSettings));\r
+    ProgramVariableSettings = TRUE;\r
+    VariableSettings = &WorkingVariableSettings;\r
+  }\r
+\r
+  //\r
+  // Check for overlap\r
+  //\r
+  UsedMtrr = MtrrGetMemoryAttributeInVariableMtrrWorker (\r
+               VariableSettings,\r
+               FirmwareVariableMtrrCount,\r
+               MtrrValidBitsMask,\r
+               MtrrValidAddressMask,\r
+               VariableMtrr\r
+               );\r
+  OverLap = CheckMemoryAttributeOverlap (\r
+              FirmwareVariableMtrrCount,\r
+              BaseAddress,\r
+              BaseAddress + Length - 1,\r
+              VariableMtrr\r
+              );\r
+  if (OverLap) {\r
+    Status = CombineMemoryAttribute (\r
+               FirmwareVariableMtrrCount,\r
+               MemoryType,\r
+               &BaseAddress,\r
+               &Length,\r
+               VariableMtrr,\r
+               &UsedMtrr,\r
+               &OverwriteExistingMtrr\r
+               );\r
+    if (RETURN_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    if (Length == 0) {\r
+      //\r
+      // Combined successfully, invalidate the now-unused MTRRs\r
+      //\r
+      InvalidateMtrr (VariableSettings, VariableMtrrCount, VariableMtrr);\r
+      Status = RETURN_SUCCESS;\r
+      goto Done;\r
+    }\r
+  }\r
+\r
+  //\r
+  // The memory type is the same with the type specified by\r
+  // MTRR_LIB_IA32_MTRR_DEF_TYPE.\r
+  //\r
+  if ((!OverwriteExistingMtrr) && (Attribute == MtrrGetDefaultMemoryType ())) {\r
+    //\r
+    // Invalidate the now-unused MTRRs\r
+    //\r
+    InvalidateMtrr (VariableSettings, VariableMtrrCount, VariableMtrr);\r
+    goto Done;\r
+  }\r
+\r
+  Positive = GetMtrrNumberAndDirection (BaseAddress, Length, &MtrrNumber);\r
+\r
+  if ((UsedMtrr + MtrrNumber) > FirmwareVariableMtrrCount) {\r
+    Status = RETURN_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Invalidate the now-unused MTRRs\r
+  //\r
+  InvalidateMtrr (VariableSettings, VariableMtrrCount, VariableMtrr);\r
+\r
+  //\r
+  // Find first unused MTRR\r
+  //\r
+  for (MsrNum = 0; MsrNum < VariableMtrrCount; MsrNum++) {\r
+    if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (BaseAddress != 0) {\r
+    do {\r
+      //\r
+      // Calculate the alignment of the base address.\r
+      //\r
+      Alignment = LShiftU64 (1, (UINTN)LowBitSet64 (BaseAddress));\r
+\r
+      if (Alignment > Length) {\r
+        break;\r
+      }\r
+\r
+      //\r
+      // Find unused MTRR\r
+      //\r
+      for (; MsrNum < VariableMtrrCount; MsrNum++) {\r
+        if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
+          break;\r
+        }\r
+      }\r
+\r
+      ProgramVariableMtrr (\r
+        VariableSettings,\r
+        MsrNum,\r
+        BaseAddress,\r
+        Alignment,\r
+        MemoryType,\r
+        MtrrValidAddressMask\r
+        );\r
+      BaseAddress += Alignment;\r
+      Length -= Alignment;\r
+    } while (TRUE);\r
+\r
+    if (Length == 0) {\r
+      goto Done;\r
+    }\r
+  }\r
+\r
+  TempQword = Length;\r
+\r
+  if (!Positive) {\r
+    Length = Power2MaxMemory (LShiftU64 (TempQword, 1));\r
+\r
+    //\r
+    // Find unused MTRR\r
+    //\r
+    for (; MsrNum < VariableMtrrCount; MsrNum++) {\r
+      if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    ProgramVariableMtrr (\r
+      VariableSettings,\r
+      MsrNum,\r
+      BaseAddress,\r
+      Length,\r
+      MemoryType,\r
+      MtrrValidAddressMask\r
+      );\r
+    BaseAddress += Length;\r
+    TempQword   = Length - TempQword;\r
+    MemoryType  = MTRR_CACHE_UNCACHEABLE;\r
+  }\r
+\r
+  do {\r
+    //\r
+    // Find unused MTRR\r
+    //\r
+    for (; MsrNum < VariableMtrrCount; MsrNum++) {\r
+      if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    Length = Power2MaxMemory (TempQword);\r
+    if (!Positive) {\r
+      BaseAddress -= Length;\r
+    }\r
+\r
+    ProgramVariableMtrr (\r
+      VariableSettings,\r
+      MsrNum,\r
+      BaseAddress,\r
+      Length,\r
+      MemoryType,\r
+      MtrrValidAddressMask\r
+      );\r
+\r
+    if (Positive) {\r
+      BaseAddress += Length;\r
+    }\r
+    TempQword -= Length;\r
+\r
+  } while (TempQword > 0);\r
+\r
+Done:\r
+\r
+  //\r
+  // Write fixed MTRRs that have been modified\r
+  //\r
+  for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
+    if (FixedSettingsModified[Index]) {\r
+      if (!MtrrContextValid) {\r
+        PreMtrrChange (&MtrrContext);\r
+        MtrrContextValid = TRUE;\r
+      }\r
+      MtrrRegisterWrite (\r
+        mMtrrLibFixedMtrrTable[Index].Msr,\r
+        WorkingFixedSettings.Mtrr[Index]\r
+        );\r
+    }\r
+  }\r
+\r
+  //\r
+  // Write variable MTRRs\r
+  //\r
+  if (ProgramVariableSettings) {\r
+    for (Index = 0; Index < VariableMtrrCount; Index++) {\r
+      if (WorkingVariableSettings.Mtrr[Index].Base != OriginalVariableSettings.Mtrr[Index].Base ||\r
+          WorkingVariableSettings.Mtrr[Index].Mask != OriginalVariableSettings.Mtrr[Index].Mask    ) {\r
+        if (!MtrrContextValid) {\r
+          PreMtrrChange (&MtrrContext);\r
+          MtrrContextValid = TRUE;\r
+        }\r
+        MtrrRegisterWrite (\r
+          QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0 + (Index << 1),\r
+          WorkingVariableSettings.Mtrr[Index].Base\r
+          );\r
+        MtrrRegisterWrite (\r
+          QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0 + (Index << 1) + 1,\r
+          WorkingVariableSettings.Mtrr[Index].Mask\r
+          );\r
+      }\r
+    }\r
+  }\r
+  if (MtrrContextValid) {\r
+    PostMtrrChange (&MtrrContext);\r
+  }\r
+\r
+  DEBUG((DEBUG_CACHE, "  Status = %r\n", Status));\r
+  if (!RETURN_ERROR (Status)) {\r
+    if (MtrrSetting != NULL) {\r
+      MtrrSetting->MtrrDefType |= MTRR_LIB_CACHE_MTRR_ENABLED;\r
+    }\r
+    MtrrDebugPrintAllMtrrsWorker (MtrrSetting);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This function attempts to set the attributes for a memory range.\r
+\r
+  @param[in]  BaseAddress        The physical address that is the start\r
+                                 address of a memory region.\r
+  @param[in]  Length             The size in bytes of the memory region.\r
+  @param[in]  Attributes         The bit mask of attributes to set for the\r
+                                 memory region.\r
+\r
+  @retval RETURN_SUCCESS            The attributes were set for the memory\r
+                                    region.\r
+  @retval RETURN_INVALID_PARAMETER  Length is zero.\r
+  @retval RETURN_UNSUPPORTED        The processor does not support one or\r
+                                    more bytes of the memory resource range\r
+                                    specified by BaseAddress and Length.\r
+  @retval RETURN_UNSUPPORTED        The bit mask of attributes is not support\r
+                                    for the memory resource range specified\r
+                                    by BaseAddress and Length.\r
+  @retval RETURN_ACCESS_DENIED      The attributes for the memory resource\r
+                                    range specified by BaseAddress and Length\r
+                                    cannot be modified.\r
+  @retval RETURN_OUT_OF_RESOURCES   There are not enough system resources to\r
+                                    modify the attributes of the memory\r
+                                    resource range.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+MtrrSetMemoryAttribute (\r
+  IN PHYSICAL_ADDRESS        BaseAddress,\r
+  IN UINT64                  Length,\r
+  IN MTRR_MEMORY_CACHE_TYPE  Attribute\r
+  )\r
+{\r
+  DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, Length));\r
+  return MtrrSetMemoryAttributeWorker (\r
+           NULL,\r
+           BaseAddress,\r
+           Length,\r
+           Attribute\r
+           );\r
+}\r
+\r
+/**\r
+  This function attempts to set the attributes into MTRR setting buffer for a memory range.\r
+\r
+  @param[in, out]  MtrrSetting  MTRR setting buffer to be set.\r
+  @param[in]       BaseAddress  The physical address that is the start address\r
+                                of a memory region.\r
+  @param[in]       Length       The size in bytes of the memory region.\r
+  @param[in]       Attribute    The bit mask of attributes to set for the\r
+                                memory region.\r
+\r
+  @retval RETURN_SUCCESS            The attributes were set for the memory region.\r
+  @retval RETURN_INVALID_PARAMETER  Length is zero.\r
+  @retval RETURN_UNSUPPORTED        The processor does not support one or more bytes of the\r
+                                    memory resource range specified by BaseAddress and Length.\r
+  @retval RETURN_UNSUPPORTED        The bit mask of attributes is not support for the memory resource\r
+                                    range specified by BaseAddress and Length.\r
+  @retval RETURN_ACCESS_DENIED      The attributes for the memory resource range specified by\r
+                                    BaseAddress and Length cannot be modified.\r
+  @retval RETURN_OUT_OF_RESOURCES   There are not enough system resources to modify the attributes of\r
+                                    the memory resource range.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+MtrrSetMemoryAttributeInMtrrSettings (\r
+  IN OUT MTRR_SETTINGS       *MtrrSetting,\r
+  IN PHYSICAL_ADDRESS        BaseAddress,\r
+  IN UINT64                  Length,\r
+  IN MTRR_MEMORY_CACHE_TYPE  Attribute\r
+  )\r
+{\r
+  DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttributeMtrrSettings(%p) %a:%016lx-%016lx\n", MtrrSetting, mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, Length));\r
+  return MtrrSetMemoryAttributeWorker (\r
+           MtrrSetting,\r
+           BaseAddress,\r
+           Length,\r
+           Attribute\r
+           );\r
+}\r
+\r
+/**\r
+  Worker function setting variable MTRRs\r
+\r
+  @param[in]  VariableSettings   A buffer to hold variable MTRRs content.\r
+\r
+**/\r
+VOID\r
+MtrrSetVariableMtrrWorker (\r
+  IN MTRR_VARIABLE_SETTINGS         *VariableSettings\r
+  )\r
+{\r
+  UINT32  Index;\r
+  UINT32  VariableMtrrCount;\r
+\r
+  VariableMtrrCount = GetVariableMtrrCountWorker ();\r
+  ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
+\r
+  for (Index = 0; Index < VariableMtrrCount; Index++) {\r
+    MtrrRegisterWrite (\r
+      QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0 + (Index << 1),\r
+      VariableSettings->Mtrr[Index].Base\r
+      );\r
+    MtrrRegisterWrite (\r
+      QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0 + (Index << 1) + 1,\r
+      VariableSettings->Mtrr[Index].Mask\r
+      );\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  This function sets variable MTRRs\r
+\r
+  @param[in]  VariableSettings   A buffer to hold variable MTRRs content.\r
+\r
+  @return The pointer of VariableSettings\r
+\r
+**/\r
+MTRR_VARIABLE_SETTINGS*\r
+EFIAPI\r
+MtrrSetVariableMtrr (\r
+  IN MTRR_VARIABLE_SETTINGS         *VariableSettings\r
+  )\r
+{\r
+  MTRR_CONTEXT  MtrrContext;\r
+\r
+  if (!IsMtrrSupported ()) {\r
+    return VariableSettings;\r
+  }\r
+\r
+  PreMtrrChange (&MtrrContext);\r
+  MtrrSetVariableMtrrWorker (VariableSettings);\r
+  PostMtrrChange (&MtrrContext);\r
+  MtrrDebugPrintAllMtrrs ();\r
+\r
+  return  VariableSettings;\r
+}\r
+\r
+/**\r
+  Worker function setting fixed MTRRs\r
+\r
+  @param[in]  FixedSettings  A buffer to hold fixed MTRRs content.\r
+\r
+**/\r
+VOID\r
+MtrrSetFixedMtrrWorker (\r
+  IN MTRR_FIXED_SETTINGS          *FixedSettings\r
+  )\r
+{\r
+  UINT32  Index;\r
+\r
+  for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
+     MtrrRegisterWrite (\r
+       mMtrrLibFixedMtrrTable[Index].Msr,\r
+       FixedSettings->Mtrr[Index]\r
+       );\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  This function sets fixed MTRRs\r
+\r
+  @param[in]  FixedSettings  A buffer to hold fixed MTRRs content.\r
+\r
+  @retval The pointer of FixedSettings\r
+\r
+**/\r
+MTRR_FIXED_SETTINGS*\r
+EFIAPI\r
+MtrrSetFixedMtrr (\r
+  IN MTRR_FIXED_SETTINGS          *FixedSettings\r
+  )\r
+{\r
+  MTRR_CONTEXT  MtrrContext;\r
+\r
+  if (!IsMtrrSupported ()) {\r
+    return FixedSettings;\r
+  }\r
+\r
+  PreMtrrChange (&MtrrContext);\r
+  MtrrSetFixedMtrrWorker (FixedSettings);\r
+  PostMtrrChange (&MtrrContext);\r
+  MtrrDebugPrintAllMtrrs ();\r
+\r
+  return FixedSettings;\r
+}\r
+\r
+\r
+/**\r
+  This function gets the content in all MTRRs (variable and fixed)\r
+\r
+  @param[out]  MtrrSetting  A buffer to hold all MTRRs content.\r
+\r
+  @retval the pointer of MtrrSetting\r
+\r
+**/\r
+MTRR_SETTINGS *\r
+EFIAPI\r
+MtrrGetAllMtrrs (\r
+  OUT MTRR_SETTINGS                *MtrrSetting\r
+  )\r
+{\r
+  if (!IsMtrrSupported ()) {\r
+    return MtrrSetting;\r
+  }\r
+\r
+  //\r
+  // Get fixed MTRRs\r
+  //\r
+  MtrrGetFixedMtrrWorker (&MtrrSetting->Fixed);\r
+\r
+  //\r
+  // Get variable MTRRs\r
+  //\r
+  MtrrGetVariableMtrrWorker (\r
+    NULL,\r
+    GetVariableMtrrCountWorker (),\r
+    &MtrrSetting->Variables\r
+    );\r
+\r
+  //\r
+  // Get MTRR_DEF_TYPE value\r
+  //\r
+  MtrrSetting->MtrrDefType = MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE);\r
+\r
+  return MtrrSetting;\r
+}\r
+\r
+\r
+/**\r
+  This function sets all MTRRs (variable and fixed)\r
+\r
+  @param[in]  MtrrSetting  A buffer holding all MTRRs content.\r
+\r
+  @retval The pointer of MtrrSetting\r
+\r
+**/\r
+MTRR_SETTINGS *\r
+EFIAPI\r
+MtrrSetAllMtrrs (\r
+  IN MTRR_SETTINGS                *MtrrSetting\r
+  )\r
+{\r
+  MTRR_CONTEXT  MtrrContext;\r
+\r
+  if (!IsMtrrSupported ()) {\r
+    return MtrrSetting;\r
+  }\r
+\r
+  PreMtrrChange (&MtrrContext);\r
+\r
+  //\r
+  // Set fixed MTRRs\r
+  //\r
+  MtrrSetFixedMtrrWorker (&MtrrSetting->Fixed);\r
+\r
+  //\r
+  // Set variable MTRRs\r
+  //\r
+  MtrrSetVariableMtrrWorker (&MtrrSetting->Variables);\r
+\r
+  //\r
+  // Set MTRR_DEF_TYPE value\r
+  //\r
+  MtrrRegisterWrite (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE, MtrrSetting->MtrrDefType);\r
+\r
+  PostMtrrChangeEnableCache (&MtrrContext);\r
+\r
+  MtrrDebugPrintAllMtrrs ();\r
+\r
+  return MtrrSetting;\r
+}\r
+\r
+\r
+/**\r
+  Checks if MTRR is supported.\r
+\r
+  @retval TRUE  MTRR is supported.\r
+  @retval FALSE MTRR is not supported.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsMtrrSupported (\r
+  VOID\r
+  )\r
+{\r
+  UINT32  RegEax;\r
+\r
+  //\r
+  // Check CPUID(1).EAX[0..11] for Quark SoC\r
+  //\r
+  AsmCpuid (1, &RegEax, NULL, NULL, NULL);\r
+  if ((RegEax & 0xfff) == QUARK_SOC_CPUID_FAMILY_MODEL_STEPPING) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/MtrrLib/MtrrLib.inf b/QuarkSocPkg/QuarkNorthCluster/Library/MtrrLib/MtrrLib.inf
new file mode 100644 (file)
index 0000000..d0c2d5a
--- /dev/null
@@ -0,0 +1,48 @@
+## @file\r
+#  MTRR library provides APIs for MTRR operation.\r
+#\r
+#  Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution.  The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = MtrrLib\r
+  MODULE_UNI_FILE                = MtrrLib.uni\r
+  FILE_GUID                      = 6826b408-f4f3-47ee-917f-af7047f9d937\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = MtrrLib\r
+\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources]\r
+  MtrrLib.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  UefiCpuPkg/UefiCpuPkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseMemoryLib\r
+  BaseLib\r
+  CpuLib\r
+  DebugLib\r
+  QNCAccessLib\r
+\r
+[Pcd]\r
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuNumberOfReservedVariableMtrrs   ## SOMETIMES_CONSUMES\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/MtrrLib/MtrrLib.uni b/QuarkSocPkg/QuarkNorthCluster/Library/MtrrLib/MtrrLib.uni
new file mode 100644 (file)
index 0000000..85afa9c
--- /dev/null
@@ -0,0 +1,24 @@
+// /** @file\r
+// MtrrLib Module Localized Abstract and Description Content\r
+//\r
+// Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.<BR>\r
+//\r
+// This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution.  The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+//\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+// **/\r
+\r
+\r
+#string STR_MODULE_ABSTRACT\r
+#language en-US\r
+"MTRR library provides APIs for MTRR operation"\r
+\r
+#string STR_MODULE_DESCRIPTION\r
+#language en-US\r
+"MTRR library provides APIs for MTRR operation."\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/BaseAccess.c b/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/BaseAccess.c
new file mode 100644 (file)
index 0000000..ccf64f7
--- /dev/null
@@ -0,0 +1,34 @@
+/** @file\r
+Base Lib function for QNC internal network access.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+//\r
+// The package level header files this module uses\r
+//\r
+#include <Uefi.h>\r
+\r
+/**\r
+  Gets the base address of PCI Express for Quark North Cluster.\r
+\r
+  @return The base address of PCI Express for Quark North Cluster.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+QncGetPciExpressBaseAddress (\r
+  VOID\r
+  )\r
+{\r
+  return (UINTN) PcdGet64(PcdPciExpressBaseAddress);\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/QNCAccessLib.c b/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/QNCAccessLib.c
new file mode 100644 (file)
index 0000000..4e77cc2
--- /dev/null
@@ -0,0 +1,333 @@
+/** @file\r
+Common Lib function for QNC internal network access.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+//\r
+// The package level header files this module uses\r
+//\r
+#include <Uefi.h>\r
+\r
+#include <IntelQNCRegs.h>\r
+#include <Library/QNCAccessLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <IndustryStandard/Pci22.h>\r
+\r
+UINT32\r
+EFIAPI\r
+QNCPortRead(\r
+  UINT8 Port,\r
+  UINT32 RegAddress\r
+  )\r
+{\r
+  McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);\r
+  McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_READ_DW (Port, RegAddress);\r
+  return McD0PciCfg32 (QNC_ACCESS_PORT_MDR);\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+QNCPortWrite (\r
+  UINT8 Port,\r
+  UINT32 RegAddress,\r
+  UINT32 WriteValue\r
+  )\r
+{\r
+  McD0PciCfg32 (QNC_ACCESS_PORT_MDR) = WriteValue;\r
+  McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);\r
+  McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_WRITE_DW (Port, RegAddress);\r
+}\r
+\r
+UINT32\r
+EFIAPI\r
+QNCAltPortRead (\r
+  UINT8 Port,\r
+  UINT32 RegAddress\r
+  )\r
+{\r
+  McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);\r
+  McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = ALT_MESSAGE_READ_DW (Port, RegAddress);\r
+  return McD0PciCfg32 (QNC_ACCESS_PORT_MDR);\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+QNCAltPortWrite (\r
+  UINT8 Port,\r
+  UINT32 RegAddress,\r
+  UINT32 WriteValue\r
+  )\r
+{\r
+  McD0PciCfg32 (QNC_ACCESS_PORT_MDR) = WriteValue;\r
+  McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);\r
+  McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = ALT_MESSAGE_WRITE_DW (Port, RegAddress);\r
+}\r
+\r
+UINT32\r
+EFIAPI\r
+QNCPortIORead(\r
+  UINT8 Port,\r
+  UINT32 RegAddress\r
+  )\r
+{\r
+  McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);\r
+  McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_IO_READ_DW (Port, RegAddress);\r
+  return McD0PciCfg32 (QNC_ACCESS_PORT_MDR);\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+QNCPortIOWrite (\r
+  UINT8 Port,\r
+  UINT32 RegAddress,\r
+  UINT32 WriteValue\r
+  )\r
+{\r
+  McD0PciCfg32 (QNC_ACCESS_PORT_MDR) = WriteValue;\r
+  McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);\r
+  McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_IO_WRITE_DW (Port, RegAddress);\r
+}\r
+\r
+RETURN_STATUS\r
+EFIAPI\r
+QNCMmIoWrite (\r
+  UINT32             MmIoAddress,\r
+  QNC_MEM_IO_WIDTH    Width,\r
+  UINT32             DataNumber,\r
+  VOID               *pData\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This is for the special consideration for QNC MMIO write, as required by FWG, a reading must be performed after MMIO writing\r
+to ensure the expected write is processed and data is flushed into chipset\r
+\r
+Arguments:\r
+\r
+  Row -- row number to be cleared ( start from 1 )\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+  RETURN_STATUS  Status;\r
+  UINTN          Index;\r
+\r
+  Status = RETURN_SUCCESS;\r
+\r
+  for (Index =0; Index < DataNumber; Index++) {\r
+    switch (Width) {\r
+      case QNCMmioWidthUint8:\r
+        QNCMmio8 (MmIoAddress, 0) = ((UINT8 *)pData)[Index];\r
+        if (QNCMmio8 (MmIoAddress, 0) != ((UINT8*)pData)[Index]) {\r
+          Status = RETURN_DEVICE_ERROR;\r
+          break;\r
+        }\r
+        break;\r
+\r
+      case QNCMmioWidthUint16:\r
+        QNCMmio16 (MmIoAddress, 0) = ((UINT16 *)pData)[Index];\r
+        if (QNCMmio16 (MmIoAddress, 0) != ((UINT16 *)pData)[Index]) {\r
+          Status = RETURN_DEVICE_ERROR;\r
+          break;\r
+        }\r
+        break;\r
+\r
+      case QNCMmioWidthUint32:\r
+        QNCMmio32 (MmIoAddress, 0) = ((UINT32 *)pData)[Index];\r
+        if (QNCMmio32 (MmIoAddress, 0) != ((UINT32 *)pData)[Index]) {\r
+          Status = RETURN_DEVICE_ERROR;\r
+          break;\r
+        }\r
+        break;\r
+\r
+      case QNCMmioWidthUint64:\r
+        QNCMmio64 (MmIoAddress, 0) = ((UINT64 *)pData)[Index];\r
+        if (QNCMmio64 (MmIoAddress, 0) != ((UINT64 *)pData)[Index]) {\r
+          Status = RETURN_DEVICE_ERROR;\r
+          break;\r
+        }\r
+        break;\r
+\r
+      default:\r
+        break;\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+UINT32\r
+EFIAPI\r
+QncHsmmcRead (\r
+  VOID\r
+  )\r
+{\r
+  return QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC);\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+QncHsmmcWrite (\r
+  UINT32 WriteValue\r
+  )\r
+{\r
+  UINT16  DeviceId;\r
+  UINT32  Data32;\r
+\r
+  //\r
+  // Check what Soc we are running on (read Host bridge DeviceId)\r
+  //\r
+  DeviceId = QNCMmPci16(0, MC_BUS, MC_DEV, MC_FUN, PCI_DEVICE_ID_OFFSET);\r
+\r
+  if (DeviceId == QUARK2_MC_DEVICE_ID) {\r
+    //\r
+    // Disable HSMMC configuration\r
+    //\r
+    Data32 = QncHsmmcRead ();\r
+    Data32 &= ~SMM_CTL_EN;\r
+    QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC, Data32);\r
+\r
+    //\r
+    // Validate HSMMC configuration is disabled\r
+    //\r
+    Data32 = QncHsmmcRead ();\r
+    ASSERT((Data32 & SMM_CTL_EN) == 0);\r
+\r
+    //\r
+    // Enable HSMMC configuration\r
+    //\r
+    WriteValue |= SMM_CTL_EN;\r
+  }\r
+\r
+  //\r
+  // Write the register value\r
+  //\r
+  QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC, WriteValue);\r
+\r
+  if (DeviceId == QUARK2_MC_DEVICE_ID) {\r
+    //\r
+    // Validate HSMMC configuration is enabled\r
+    //\r
+    Data32 = QncHsmmcRead ();\r
+    ASSERT((Data32 & SMM_CTL_EN) != 0);\r
+  }\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+QncImrWrite (\r
+  UINT32 ImrBaseOffset,\r
+  UINT32 ImrLow,\r
+  UINT32 ImrHigh,\r
+  UINT32 ImrReadMask,\r
+  UINT32 ImrWriteMask\r
+  )\r
+{\r
+  UINT16  DeviceId;\r
+  UINT32  Data32;\r
+\r
+  //\r
+  // Check what Soc we are running on (read Host bridge DeviceId)\r
+  //\r
+  DeviceId = QNCMmPci16(0, MC_BUS, MC_DEV, MC_FUN, PCI_DEVICE_ID_OFFSET);\r
+\r
+  //\r
+  // Disable IMR protection\r
+  //\r
+  if (DeviceId == QUARK2_MC_DEVICE_ID) {\r
+    //\r
+    // Disable IMR protection\r
+    //\r
+    Data32 = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL);\r
+    Data32 &= ~IMR_EN;\r
+    QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL, Data32);\r
+\r
+    //\r
+    // Validate IMR protection is disabled\r
+    //\r
+    Data32 = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL);\r
+    ASSERT((Data32 & IMR_EN) == 0);\r
+\r
+    //\r
+    // Update the IMR (IMRXL must be last as it may enable IMR violation checking)\r
+    //\r
+    QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXRM, ImrReadMask);\r
+    QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXWM, ImrWriteMask);\r
+    QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXH, ImrHigh);\r
+    QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL, ImrLow);\r
+\r
+    //\r
+    // Validate IMR protection is enabled/disabled\r
+    //\r
+    Data32 = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL);\r
+    ASSERT((Data32 & IMR_EN) == (ImrLow & IMR_EN));\r
+  } else {\r
+    //\r
+    // Disable IMR protection (allow all access)\r
+    //\r
+    QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXRM, (UINT32)IMRX_ALL_ACCESS);\r
+    QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXWM, (UINT32)IMRX_ALL_ACCESS);\r
+\r
+    //\r
+    // Update the IMR (IMRXRM/IMRXWM must be last as they restrict IMR access)\r
+    //\r
+    QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL, (ImrLow & ~IMR_EN));\r
+    QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXH, ImrHigh);\r
+    QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXRM, ImrReadMask);\r
+    QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXWM, ImrWriteMask);\r
+  }\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+QncIClkAndThenOr (\r
+  UINT32 RegAddress,\r
+  UINT32 AndValue,\r
+  UINT32 OrValue\r
+  )\r
+{\r
+  UINT32 RegValue;\r
+  //\r
+  // Whenever an iCLK SB register (Endpoint 32h) is being programmed the access\r
+  // should always consist of a READ from the address followed by 2 identical\r
+  // WRITEs to that address.\r
+  //\r
+  RegValue = QNCAltPortRead (QUARK_ICLK_SB_PORT_ID, RegAddress);\r
+  RegValue &= AndValue;\r
+  RegValue |= OrValue;\r
+  QNCAltPortWrite (QUARK_ICLK_SB_PORT_ID, RegAddress, RegValue);\r
+  QNCAltPortWrite (QUARK_ICLK_SB_PORT_ID, RegAddress, RegValue);\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+QncIClkOr (\r
+  UINT32 RegAddress,\r
+  UINT32 OrValue\r
+  )\r
+{\r
+  UINT32 RegValue;\r
+  //\r
+  // Whenever an iCLK SB register (Endpoint 32h) is being programmed the access\r
+  // should always consist of a READ from the address followed by 2 identical\r
+  // WRITEs to that address.\r
+  //\r
+  RegValue = QNCAltPortRead (QUARK_ICLK_SB_PORT_ID, RegAddress);\r
+  RegValue |= OrValue;\r
+  QNCAltPortWrite (QUARK_ICLK_SB_PORT_ID, RegAddress, RegValue);\r
+  QNCAltPortWrite (QUARK_ICLK_SB_PORT_ID, RegAddress, RegValue);\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/QNCAccessLib.inf b/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/QNCAccessLib.inf
new file mode 100644 (file)
index 0000000..6fb2d66
--- /dev/null
@@ -0,0 +1,43 @@
+## @file\r
+# Base Intel QNC Library Instance\r
+#\r
+# Intel QNC internal network access Library Instance\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = QNCAccessLib\r
+  FILE_GUID                      = CC13B9FB-DAF5-4b42-907F-122216787C05\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = QNCAccessLib\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources]\r
+  QNCAccessLib.c\r
+  BaseAccess.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  DebugLib\r
+\r
+[Pcd]\r
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/RuntimeAccess.c b/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/RuntimeAccess.c
new file mode 100644 (file)
index 0000000..a421759
--- /dev/null
@@ -0,0 +1,148 @@
+/** @file\r
+Runtime Lib function for QNC internal network access.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Guid/EventGroup.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeLib.h>\r
+#include <Library/QNCAccessLib.h>\r
+\r
+///\r
+/// Set Virtual Address Map Event\r
+///\r
+EFI_EVENT                               mDxeRuntimeQncAccessLibVirtualNotifyEvent = NULL;\r
+\r
+///\r
+/// Module global that contains the base physical address of the PCI Express MMIO range.\r
+///\r
+UINTN                                   mDxeRuntimeQncAccessLibPciExpressBaseAddress = 0;\r
+\r
+/**\r
+  Convert the physical PCI Express MMIO address to a virtual address.\r
+\r
+  @param[in]    Event   The event that is being processed.\r
+  @param[in]    Context The Event Context.\r
+**/\r
+VOID\r
+EFIAPI\r
+DxeRuntimeQncAccessLibVirtualNotify (\r
+  IN EFI_EVENT  Event,\r
+  IN VOID       *Context\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+\r
+  //\r
+  // Convert the physical PCI Express MMIO address to a virtual address.\r
+  //\r
+  Status = EfiConvertPointer (0, (VOID **) &mDxeRuntimeQncAccessLibPciExpressBaseAddress);\r
+\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+  The constructor function to setup globals and goto virtual mode notify.\r
+\r
+  @param  ImageHandle   The firmware allocated handle for the EFI image.\r
+  @param  SystemTable   A pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS   The constructor completed successfully.\r
+  @retval Other value   The constructor did not complete successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DxeRuntimeQncAccessLibConstructor (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Cache the physical address of the PCI Express MMIO range into a module global variable\r
+  //\r
+  mDxeRuntimeQncAccessLibPciExpressBaseAddress = (UINTN) PcdGet64(PcdPciExpressBaseAddress);\r
+\r
+  //\r
+  // Register SetVirtualAddressMap () notify function\r
+  //\r
+  Status = gBS->CreateEventEx (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  DxeRuntimeQncAccessLibVirtualNotify,\r
+                  NULL,\r
+                  &gEfiEventVirtualAddressChangeGuid,\r
+                  &mDxeRuntimeQncAccessLibVirtualNotifyEvent\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  The destructor function frees any allocated buffers and closes the Set Virtual\r
+  Address Map event.\r
+\r
+  @param  ImageHandle   The firmware allocated handle for the EFI image.\r
+  @param  SystemTable   A pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS   The destructor completed successfully.\r
+  @retval Other value   The destructor did not complete successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DxeRuntimeQncAccessLibDestructor (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Close the Set Virtual Address Map event\r
+  //\r
+  Status = gBS->CloseEvent (mDxeRuntimeQncAccessLibVirtualNotifyEvent);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Gets the base address of PCI Express for Quark North Cluster.\r
+\r
+  @return The base address of PCI Express for Quark North Cluster.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+QncGetPciExpressBaseAddress (\r
+  VOID\r
+  )\r
+{\r
+  //\r
+  // If system goes to virtual mode then virtual notify callback will update\r
+  // mDxeRuntimeQncAccessLibPciExpressBaseAddress with virtual address of\r
+  // PCIe memory base.\r
+  //\r
+  return mDxeRuntimeQncAccessLibPciExpressBaseAddress;\r
+}\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/RuntimeQNCAccessLib.inf b/QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/RuntimeQNCAccessLib.inf
new file mode 100644 (file)
index 0000000..e734aed
--- /dev/null
@@ -0,0 +1,49 @@
+## @file\r
+# DXE Runtime Intel QNC Library Instance\r
+#\r
+# Intel QNC internal network access Library Instance.\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = RuntimeQNCAccessLib\r
+  FILE_GUID                      = E6B51D93-E4C8-4425-9FA9-9DED814220F9\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = QNCAccessLib|DXE_RUNTIME_DRIVER\r
+  CONSTRUCTOR                    = DxeRuntimeQncAccessLibConstructor\r
+  DESTRUCTOR                     = DxeRuntimeQncAccessLibDestructor\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32\r
+#\r
+\r
+[Sources]\r
+  QNCAccessLib.c\r
+  RuntimeAccess.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  DebugLib\r
+  PcdLib\r
+  UefiBootServicesTableLib\r
+  UefiRuntimeLib\r
+\r
+[Pcd]\r
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.c b/QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.c
new file mode 100644 (file)
index 0000000..6ddc099
--- /dev/null
@@ -0,0 +1,322 @@
+/** @file\r
+QNC Smm Library Services that implements SMM Region access, S/W SMI generation and detection.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include <Base.h>\r
+#include <IntelQNCRegs.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Uefi/UefiBaseType.h>\r
+#include <Library/QNCAccessLib.h>\r
+\r
+#define BOOT_SERVICE_SOFTWARE_SMI_DATA          0\r
+#define RUNTIME_SOFTWARE_SMI_DATA               1\r
+\r
+/**\r
+  Triggers a run time or boot time SMI.\r
+\r
+  This function triggers a software SMM interrupt and set the APMC status with an 8-bit Data.\r
+\r
+  @param  Data                 The value to set the APMC status.\r
+\r
+**/\r
+VOID\r
+InternalTriggerSmi (\r
+  IN UINT8                     Data\r
+  )\r
+{\r
+  UINT16        PM1BLK_Base;\r
+  UINT16        GPE0BLK_Base;\r
+  UINT32        NewValue;\r
+\r
+  //\r
+  // Get PM1BLK_Base & GPE0BLK_Base\r
+  //\r
+  PM1BLK_Base = PcdGet16 (PcdPm1blkIoBaseAddress);\r
+  GPE0BLK_Base = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF);\r
+\r
+\r
+  //\r
+  // Enable APM SMI\r
+  //\r
+  IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIE), B_QNC_GPE0BLK_SMIE_APM);\r
+\r
+  //\r
+  // Enable SMI globally\r
+  //\r
+  NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);\r
+  NewValue |= SMI_EN;\r
+  QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);\r
+\r
+  //\r
+  // Set APM_STS\r
+  //\r
+  IoWrite8 (PcdGet16 (PcdSmmDataPort), Data);\r
+\r
+  //\r
+  // Generate the APM SMI\r
+  //\r
+  IoWrite8 (PcdGet16 (PcdSmmActivationPort), PcdGet8 (PcdSmmActivationData));\r
+\r
+  //\r
+  // Clear the APM SMI Status Bit\r
+  //\r
+  IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_APM);\r
+\r
+  //\r
+  // Set the EOS Bit\r
+  //\r
+  IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS);\r
+}\r
+\r
+\r
+/**\r
+  Triggers an SMI at boot time.\r
+\r
+  This function triggers a software SMM interrupt at boot time.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+TriggerBootServiceSoftwareSmi (\r
+  VOID\r
+  )\r
+{\r
+  InternalTriggerSmi (BOOT_SERVICE_SOFTWARE_SMI_DATA);\r
+}\r
+\r
+\r
+/**\r
+  Triggers an SMI at run time.\r
+\r
+  This function triggers a software SMM interrupt at run time.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+TriggerRuntimeSoftwareSmi (\r
+  VOID\r
+  )\r
+{\r
+  InternalTriggerSmi (RUNTIME_SOFTWARE_SMI_DATA);\r
+}\r
+\r
+\r
+/**\r
+  Gets the software SMI data.\r
+\r
+  This function tests if a software SMM interrupt happens. If a software SMI happens,\r
+  it retrieves the SMM data and returns it as a non-negative value; otherwise a negative\r
+  value is returned.\r
+\r
+  @return Data                 The data retrieved from SMM data port in case of a software SMI;\r
+                               otherwise a negative value.\r
+\r
+**/\r
+INTN\r
+InternalGetSwSmiData (\r
+  VOID\r
+  )\r
+{\r
+  UINT8                        SmiStatus;\r
+  UINT8                        Data;\r
+\r
+  SmiStatus = IoRead8 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS);\r
+  if (((SmiStatus & B_QNC_GPE0BLK_SMIS_APM) != 0) &&\r
+       (IoRead8 (PcdGet16 (PcdSmmActivationPort)) == PcdGet8 (PcdSmmActivationData))) {\r
+    Data = IoRead8 (PcdGet16 (PcdSmmDataPort));\r
+    return (INTN)(UINTN)Data;\r
+  }\r
+\r
+  return -1;\r
+}\r
+\r
+\r
+/**\r
+  Test if a boot time software SMI happened.\r
+\r
+  This function tests if a software SMM interrupt happened. If a software SMM interrupt happened and\r
+  it was triggered at boot time, it returns TRUE. Otherwise, it returns FALSE.\r
+\r
+  @retval TRUE   A software SMI triggered at boot time happened.\r
+  @retval FLASE  No software SMI happened or the software SMI was triggered at run time.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsBootServiceSoftwareSmi (\r
+  VOID\r
+  )\r
+{\r
+  return (BOOLEAN) (InternalGetSwSmiData () == BOOT_SERVICE_SOFTWARE_SMI_DATA);\r
+}\r
+\r
+\r
+/**\r
+  Test if a run time software SMI happened.\r
+\r
+  This function tests if a software SMM interrupt happened. If a software SMM interrupt happened and\r
+  it was triggered at run time, it returns TRUE. Otherwise, it returns FALSE.\r
+\r
+  @retval TRUE   A software SMI triggered at run time happened.\r
+  @retval FLASE  No software SMI happened or the software SMI was triggered at boot time.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsRuntimeSoftwareSmi (\r
+  VOID\r
+  )\r
+{\r
+  return (BOOLEAN) (InternalGetSwSmiData () == RUNTIME_SOFTWARE_SMI_DATA);\r
+}\r
+\r
+\r
+\r
+/**\r
+\r
+  Clear APM SMI Status Bit; Set the EOS bit.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+ClearSmi (\r
+  VOID\r
+  )\r
+{\r
+\r
+  UINT16                       GPE0BLK_Base;\r
+\r
+  //\r
+  // Get GpeBase\r
+  //\r
+  GPE0BLK_Base = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF);\r
+\r
+  //\r
+  // Clear the APM SMI Status Bit\r
+  //\r
+  IoOr16 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIS, B_QNC_GPE0BLK_SMIS_APM);\r
+\r
+  //\r
+  // Set the EOS Bit\r
+  //\r
+  IoOr32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIS, B_QNC_GPE0BLK_SMIS_EOS);\r
+}\r
+\r
+/**\r
+  This routine is the chipset code that accepts a request to "open" a region of SMRAM.\r
+  The region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.\r
+  The use of "open" means that the memory is visible from all boot-service\r
+  and SMM agents.\r
+\r
+  @retval FALSE  Cannot open a locked SMRAM region\r
+  @retval TRUE   Success to open SMRAM region.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+QNCOpenSmramRegion (\r
+  VOID\r
+  )\r
+{\r
+  UINT32                     Smram;\r
+\r
+  // Read the SMRAM register\r
+  Smram = QncHsmmcRead ();\r
+\r
+  //\r
+  //  Is the platform locked?\r
+  //\r
+  if (Smram & SMM_LOCKED) {\r
+    // Cannot Open a locked region\r
+    DEBUG ((EFI_D_WARN, "Cannot open a locked SMRAM region\n"));\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Open all SMRAM regions for Host access only\r
+  //\r
+  Smram |= (SMM_WRITE_OPEN | SMM_READ_OPEN);  // Open for Host.\r
+  Smram &= ~(NON_HOST_SMM_WR_OPEN | NON_HOST_SMM_RD_OPEN);  // Not for others.\r
+\r
+  //\r
+  // Write the SMRAM register\r
+  //\r
+  QncHsmmcWrite (Smram);\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  This routine is the chipset code that accepts a request to "close" a region of SMRAM.\r
+  The region could be legacy AB or TSEG near top of physical memory.\r
+  The use of "close" means that the memory is only visible from SMM agents,\r
+  not from BS or RT code.\r
+\r
+  @retval FALSE  Cannot open a locked SMRAM region\r
+  @retval TRUE   Success to open SMRAM region.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+QNCCloseSmramRegion (\r
+  VOID\r
+  )\r
+{\r
+  UINT32                    Smram;\r
+\r
+  // Read the SMRAM register.\r
+  Smram = QncHsmmcRead ();\r
+\r
+  //\r
+  //  Is the platform locked?\r
+  //\r
+  if(Smram & SMM_LOCKED) {\r
+    // Cannot Open a locked region\r
+    DEBUG ((EFI_D_WARN, "Cannot close a locked SMRAM region\n"));\r
+    return FALSE;\r
+  }\r
+\r
+  Smram &= (~(SMM_WRITE_OPEN | SMM_READ_OPEN | NON_HOST_SMM_WR_OPEN | NON_HOST_SMM_RD_OPEN));\r
+\r
+  QncHsmmcWrite (Smram);\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  This routine is the chipset code that accepts a request to "lock" SMRAM.\r
+  The region could be legacy AB or TSEG near top of physical memory.\r
+  The use of "lock" means that the memory can no longer be opened\r
+  to BS state.\r
+**/\r
+VOID\r
+EFIAPI\r
+QNCLockSmramRegion (\r
+  VOID\r
+  )\r
+{\r
+  UINT32                    Smram;\r
+\r
+  // Read the SMRAM register.\r
+  Smram = QncHsmmcRead ();\r
+  if(Smram & SMM_LOCKED) {\r
+    DEBUG ((EFI_D_WARN, "SMRAM region already locked!\n"));\r
+  }\r
+  Smram |= SMM_LOCKED;\r
+\r
+  QncHsmmcWrite (Smram);\r
+\r
+  return;\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.inf b/QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.inf
new file mode 100644 (file)
index 0000000..00f8031
--- /dev/null
@@ -0,0 +1,51 @@
+## @file\r
+# Component description file for Intel QNC SMM Library.\r
+#\r
+# QNC SMM Library that layers on top of the I/O Library to directly\r
+# access SMM power management registers.\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = QNCSmmLib\r
+  FILE_GUID                      = 8A9A62F5-758B-4965-A28B-0AAC292FBD89\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = SmmLib\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  QNCSmmLib.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  PcdLib\r
+  IoLib\r
+  DebugLib\r
+  QNCAccessLib\r
+\r
+[Pcd]\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmDataPort\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmActivationPort\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmActivationData\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/ResetSystemLib/ResetSystemLib.c b/QuarkSocPkg/QuarkNorthCluster/Library/ResetSystemLib/ResetSystemLib.c
new file mode 100644 (file)
index 0000000..c2ad7f3
--- /dev/null
@@ -0,0 +1,322 @@
+/** @file\r
+System reset Library Services.  This library class provides a set of\r
+methods to reset whole system with manipulate QNC.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Base.h>\r
+#include <IntelQNCBase.h>\r
+#include <QNCAccess.h>\r
+\r
+#include <Uefi/UefiBaseType.h>\r
+\r
+#include <Library/ResetSystemLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/CpuLib.h>\r
+#include <Library/QNCAccessLib.h>\r
+\r
+//\r
+// Amount of time (seconds) before RTC alarm fires\r
+// This must be < BCD_BASE\r
+//\r
+#define PLATFORM_WAKE_SECONDS_BUFFER 0x06\r
+\r
+//\r
+// RTC 'seconds' above which we will not read to avoid potential rollover\r
+//\r
+#define PLATFORM_RTC_ROLLOVER_LIMIT 0x47\r
+\r
+//\r
+// BCD is base 10\r
+//\r
+#define BCD_BASE 0x0A\r
+\r
+#define PCAT_RTC_ADDRESS_REGISTER 0x70\r
+#define PCAT_RTC_DATA_REGISTER    0x71\r
+\r
+//\r
+// Dallas DS12C887 Real Time Clock\r
+//\r
+#define RTC_ADDRESS_SECONDS           0   // R/W  Range 0..59\r
+#define RTC_ADDRESS_SECONDS_ALARM     1   // R/W  Range 0..59\r
+#define RTC_ADDRESS_MINUTES           2   // R/W  Range 0..59\r
+#define RTC_ADDRESS_MINUTES_ALARM     3   // R/W  Range 0..59\r
+#define RTC_ADDRESS_HOURS             4   // R/W  Range 1..12 or 0..23 Bit 7 is AM/PM\r
+#define RTC_ADDRESS_HOURS_ALARM       5   // R/W  Range 1..12 or 0..23 Bit 7 is AM/PM\r
+#define RTC_ADDRESS_DAY_OF_THE_WEEK   6   // R/W  Range 1..7\r
+#define RTC_ADDRESS_DAY_OF_THE_MONTH  7   // R/W  Range 1..31\r
+#define RTC_ADDRESS_MONTH             8   // R/W  Range 1..12\r
+#define RTC_ADDRESS_YEAR              9   // R/W  Range 0..99\r
+#define RTC_ADDRESS_REGISTER_A        10  // R/W[0..6]  R0[7]\r
+#define RTC_ADDRESS_REGISTER_B        11  // R/W\r
+#define RTC_ADDRESS_REGISTER_C        12  // RO\r
+#define RTC_ADDRESS_REGISTER_D        13  // RO\r
+#define RTC_ADDRESS_CENTURY           50  // R/W  Range 19..20 Bit 8 is R/W\r
+\r
+/**\r
+  Wait for an RTC update to happen\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+WaitForRTCUpdate (\r
+VOID\r
+)\r
+{\r
+  UINT8   Data8;\r
+\r
+  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_A);\r
+  Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);\r
+  if ((Data8 & BIT7) == BIT7) {\r
+    while ((Data8 & BIT7) == BIT7) {\r
+      IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_A);\r
+      Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);\r
+    }\r
+\r
+  } else {\r
+    while ((Data8 & BIT7) == 0) {\r
+      IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_A);\r
+      Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);\r
+    }\r
+\r
+    while ((Data8 & BIT7) == BIT7) {\r
+      IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_A);\r
+      Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Calling this function causes a system-wide reset. This sets\r
+  all circuitry within the system to its initial state. This type of reset\r
+  is asynchronous to system operation and operates without regard to\r
+  cycle boundaries.\r
+\r
+  System reset should not return, if it returns, it means the system does\r
+  not support cold reset.\r
+**/\r
+VOID\r
+EFIAPI\r
+ResetCold (\r
+VOID\r
+)\r
+{\r
+  //\r
+  // Reference to QuarkNcSocId BWG\r
+  // Setting bit 1 will generate a warm reset, driving only RSTRDY# low\r
+  //\r
+  IoWrite8 (RST_CNT, B_RST_CNT_COLD_RST);\r
+}\r
+\r
+/**\r
+  Calling this function causes a system-wide initialization. The processors\r
+  are set to their initial state, and pending cycles are not corrupted.\r
+\r
+  System reset should not return, if it returns, it means the system does\r
+  not support warm reset.\r
+**/\r
+VOID\r
+EFIAPI\r
+ResetWarm (\r
+VOID\r
+)\r
+{\r
+  //\r
+  // Reference to QuarkNcSocId BWG\r
+  // Setting bit 1 will generate a warm reset, driving only RSTRDY# low\r
+  //\r
+  IoWrite8 (RST_CNT, B_RST_CNT_WARM_RST);\r
+}\r
+\r
+/**\r
+  Calling this function causes the system to enter a power state equivalent\r
+  to the ACPI G2/S5 or G3 states.\r
+\r
+  System shutdown should not return, if it returns, it means the system does\r
+  not support shut down reset.\r
+**/\r
+VOID\r
+EFIAPI\r
+ResetShutdown (\r
+VOID\r
+)\r
+{\r
+  //\r
+  // Reference to QuarkNcSocId BWG\r
+  //  Disable RTC Alarm :  (RTC Enable at PM1BLK + 02h[10]))\r
+  //\r
+  IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E, 0);\r
+\r
+  //\r
+  // Firstly, GPE0_EN should be disabled to\r
+  // avoid any GPI waking up the system from S5\r
+  //\r
+  IoWrite32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0E, 0);\r
+\r
+  //\r
+  // Reference to QuarkNcSocId BWG\r
+  //  Disable Resume Well GPIO :  (GPIO bits in GPIOBASE + 34h[8:0])\r
+  //\r
+  IoWrite32 (PcdGet16 (PcdGbaIoBaseAddress) + R_QNC_GPIO_RGGPE_RESUME_WELL, 0);\r
+\r
+  //\r
+  // No power button status bit to clear for our platform, go to next step.\r
+  //\r
+\r
+  //\r
+  // Finally, transform system into S5 sleep state\r
+  //\r
+  IoAndThenOr32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, 0xffffc3ff, B_QNC_PM1BLK_PM1C_SLPEN | V_S5);\r
+}\r
+\r
+/**\r
+  Calling this function causes the system to enter a power state for capsule\r
+  update.\r
+\r
+  Reset update should not return, if it returns, it means the system does\r
+  not support capsule update.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+EnterS3WithImmediateWake (\r
+VOID\r
+)\r
+{\r
+  UINT8     Data8;\r
+  UINT16    Data16;\r
+  UINT32    Data32;\r
+  UINTN     Eflags;\r
+  UINTN     RegCr0;\r
+  EFI_TIME  EfiTime;\r
+  UINT32    SmiEnSave;\r
+\r
+  Eflags  = AsmReadEflags ();\r
+  if ( (Eflags & 0x200) ) {\r
+     DisableInterrupts ();\r
+  }\r
+\r
+  //\r
+  //  Write all cache data to memory because processor will lost power\r
+  //\r
+  AsmWbinvd();\r
+  RegCr0 = AsmReadCr0();\r
+  AsmWriteCr0 (RegCr0 | 0x060000000);\r
+\r
+  SmiEnSave = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);\r
+  QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, (SmiEnSave & ~SMI_EN));\r
+\r
+  //\r
+  // Pogram RTC alarm for immediate WAKE\r
+  //\r
+\r
+  //\r
+  // Disable SMI sources\r
+  //\r
+  IoWrite16 (PcdGet16 (PcdGpe0blkIoBaseAddress) + R_QNC_GPE0BLK_SMIE, 0);\r
+\r
+  //\r
+  // Disable RTC alarm interrupt\r
+  //\r
+  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_B);\r
+  Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);\r
+  IoWrite8 (PCAT_RTC_DATA_REGISTER, (Data8 & ~BIT5));\r
+\r
+  //\r
+  // Clear RTC alarm if already set\r
+  //\r
+  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_C);\r
+  Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);              // Read clears alarm status\r
+\r
+  //\r
+  // Disable all WAKE events\r
+  //\r
+  IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E, B_QNC_PM1BLK_PM1E_PWAKED);\r
+\r
+  //\r
+  // Clear all WAKE status bits\r
+  //\r
+  IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1S, B_QNC_PM1BLK_PM1S_ALL);\r
+\r
+  //\r
+  // Avoid RTC rollover\r
+  //\r
+  do {\r
+    WaitForRTCUpdate();\r
+    IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_SECONDS);\r
+    EfiTime.Second = IoRead8 (PCAT_RTC_DATA_REGISTER);\r
+  } while (EfiTime.Second > PLATFORM_RTC_ROLLOVER_LIMIT);\r
+\r
+  //\r
+  // Read RTC time\r
+  //\r
+  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_HOURS);\r
+  EfiTime.Hour = IoRead8 (PCAT_RTC_DATA_REGISTER);\r
+  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_MINUTES);\r
+  EfiTime.Minute = IoRead8 (PCAT_RTC_DATA_REGISTER);\r
+  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_SECONDS);\r
+  EfiTime.Second = IoRead8 (PCAT_RTC_DATA_REGISTER);\r
+\r
+  //\r
+  // Set RTC alarm\r
+  //\r
+\r
+  //\r
+  // Add PLATFORM_WAKE_SECONDS_BUFFER to current EfiTime.Second\r
+  // The maths is to allow for the fact we are adding to a BCD number and require the answer to be BCD (EfiTime.Second)\r
+  //\r
+  if ((BCD_BASE - (EfiTime.Second & 0x0F)) <= PLATFORM_WAKE_SECONDS_BUFFER) {\r
+    Data8 = (((EfiTime.Second & 0xF0) + 0x10) + (PLATFORM_WAKE_SECONDS_BUFFER - (BCD_BASE - (EfiTime.Second & 0x0F))));\r
+  } else {\r
+    Data8 = EfiTime.Second + PLATFORM_WAKE_SECONDS_BUFFER;\r
+  }\r
+\r
+  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_HOURS_ALARM);\r
+  IoWrite8 (PCAT_RTC_DATA_REGISTER, EfiTime.Hour);\r
+  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_MINUTES_ALARM);\r
+  IoWrite8 (PCAT_RTC_DATA_REGISTER, EfiTime.Minute);\r
+  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_SECONDS_ALARM);\r
+  IoWrite8 (PCAT_RTC_DATA_REGISTER, Data8);\r
+\r
+  //\r
+  // Enable RTC alarm interrupt\r
+  //\r
+  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_B);\r
+  Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);\r
+  IoWrite8 (PCAT_RTC_DATA_REGISTER, (Data8 | BIT5));\r
+\r
+  //\r
+  // Enable RTC alarm as WAKE event\r
+  //\r
+  Data16 = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E);\r
+  IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E, (Data16 | B_QNC_PM1BLK_PM1E_RTC));\r
+\r
+  //\r
+  // Enter S3\r
+  //\r
+  Data32 = IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);\r
+  Data32  = (UINT32) ((Data32 & 0xffffc3fe) | V_S3 | B_QNC_PM1BLK_PM1C_SCIEN);\r
+  IoWrite32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, Data32);\r
+  Data32 = Data32 | B_QNC_PM1BLK_PM1C_SLPEN;\r
+  IoWrite32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, Data32);\r
+\r
+  //\r
+  // Enable Interrupt if it's enabled before\r
+  //\r
+  if ( (Eflags & 0x200) ) {\r
+     EnableInterrupts ();\r
+  }\r
+}\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/ResetSystemLib/ResetSystemLib.inf b/QuarkSocPkg/QuarkNorthCluster/Library/ResetSystemLib/ResetSystemLib.inf
new file mode 100644 (file)
index 0000000..f82fd49
--- /dev/null
@@ -0,0 +1,52 @@
+## @file\r
+# Component description file for Intel QuarkNcSocId Reset System Library.\r
+#\r
+# Reset System Library implementation that bases on QNC.\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = ResetSystemLib\r
+  FILE_GUID                      = AD33A56E-3AAD-40ac-91B1-FA861E8D9D85\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = ResetSystemLib\r
+\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources]\r
+  ResetSystemLib.c\r
+\r
+\r
+[Packages]\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+  PcdLib\r
+  IoLib\r
+  BaseLib\r
+  CpuLib\r
+  QNCAccessLib\r
+\r
+[Pcd]\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdGbaIoBaseAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/CommonHeader.h b/QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/CommonHeader.h
new file mode 100644 (file)
index 0000000..11eaa0f
--- /dev/null
@@ -0,0 +1,31 @@
+/** @file\r
+Common header file shared by all source files.\r
+\r
+This file includes package header files, library classes and protocol, PPI & GUID definitions.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#ifndef __COMMON_HEADER_H_\r
+#define __COMMON_HEADER_H_\r
+\r
+\r
+#include <Uefi.h>\r
+#include <Base.h>\r
+\r
+#include <Library/SmbusLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PciLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/QNCAccessLib.h>\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.c b/QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.c
new file mode 100644 (file)
index 0000000..c80348b
--- /dev/null
@@ -0,0 +1,803 @@
+/** @file\r
+Intel QNC SMBUS library implementation built upon I/O library.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+/**\r
+  Gets Io port base address of Smbus Host Controller.\r
+\r
+  This internal function depends on a feature flag named PcdIchSmbusFixedIoPortBaseAddress\r
+  to retrieve Smbus Io port base. If that feature flag is true, it will get Smbus Io port base\r
+  address from a preset Pcd entry named PcdIchSmbusIoPortBaseAddress; otherwise, it will always\r
+  read Pci configuration space to get that value in each Smbus bus transaction.\r
+\r
+  @return The Io port base address of Smbus host controller.\r
+\r
+**/\r
+UINTN\r
+InternalGetSmbusIoPortBaseAddress (\r
+  VOID\r
+  )\r
+{\r
+  UINTN     IoPortBaseAddress;\r
+\r
+  if (FeaturePcdGet (PcdSmbaIoBaseAddressFixed)) {\r
+    IoPortBaseAddress = (UINTN) PcdGet16 (PcdSmbaIoBaseAddress);\r
+  } else {\r
+    IoPortBaseAddress = (UINTN) LpcPciCfg32 (R_QNC_LPC_SMBUS_BASE) & B_QNC_LPC_SMBUS_BASE_MASK;\r
+  }\r
+\r
+  //\r
+  // Make sure that the IO port base address has been properly set.\r
+  //\r
+  ASSERT (IoPortBaseAddress != 0);\r
+\r
+  return IoPortBaseAddress;\r
+}\r
+\r
+\r
+/**\r
+  Acquires the ownership of SMBUS.\r
+\r
+  This internal function reads the host state register.\r
+  If the SMBUS is not available, RETURN_TIMEOUT is returned;\r
+  Otherwise, it performs some basic initializations and returns\r
+  RETURN_SUCCESS.\r
+\r
+  @param  IoPortBaseAddress The Io port base address of Smbus Host controller.\r
+\r
+  @retval RETURN_SUCCESS    The SMBUS command was executed successfully.\r
+  @retval RETURN_TIMEOUT    A timeout occurred while executing the SMBUS command.\r
+\r
+**/\r
+RETURN_STATUS\r
+InternalSmBusAcquire (\r
+  UINTN                     IoPortBaseAddress\r
+  )\r
+{\r
+\r
+  //\r
+  // Clear host status register and exit.\r
+  //\r
+  IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HCTL, 0);\r
+  IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HD0, 0);\r
+  IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HD1, 0);\r
+  IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS, B_QNC_SMBUS_HSTS_ALL);\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Starts the SMBUS transaction and waits until the end.\r
+\r
+  This internal function start the SMBUS transaction and waits until the transaction\r
+  of SMBUS is over by polling the INTR bit of Host status register.\r
+  If the SMBUS is not available, RETURN_TIMEOUT is returned;\r
+  Otherwise, it performs some basic initializations and returns\r
+  RETURN_SUCCESS.\r
+\r
+  @param  IoPortBaseAddress   The Io port base address of Smbus Host controller.\r
+  @param  HostControl         The Host control command to start SMBUS transaction.\r
+\r
+  @retval RETURN_SUCCESS      The SMBUS command was executed successfully.\r
+  @retval RETURN_CRC_ERROR    The checksum is not correct (PEC is incorrect).\r
+  @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected\r
+                              in the Host Status Register bit.  Device errors are\r
+                              a result of a transaction collision, illegal command field,\r
+                              unclaimed cycle (host initiated), or bus errors (collisions).\r
+\r
+**/\r
+RETURN_STATUS\r
+InternalSmBusStart (\r
+  IN  UINTN                   IoPortBaseAddress,\r
+  IN  UINT8                   HostControl\r
+  )\r
+{\r
+  UINT8   HostStatus;\r
+\r
+  //\r
+  // Set Host Control Register (Initiate Operation, Interrupt disabled).\r
+  //\r
+  IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HCTL, HostControl + B_QNC_SMBUS_START);\r
+\r
+  do {\r
+    //\r
+    // Poll INTR bit of Host Status Register.\r
+    //\r
+    HostStatus = IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS);\r
+  } while ((HostStatus & (B_QNC_SMBUS_BYTE_DONE_STS | B_QNC_SMBUS_DERR | B_QNC_SMBUS_BERR)) == 0);\r
+\r
+  if ((HostStatus & (B_QNC_SMBUS_DERR | B_QNC_SMBUS_BERR)) == 0) {\r
+    return RETURN_SUCCESS;\r
+  }\r
+  //\r
+  // Clear error bits of Host Status Register.\r
+  //\r
+  IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS, (B_QNC_SMBUS_DERR | B_QNC_SMBUS_BERR));\r
+\r
+  return RETURN_DEVICE_ERROR;\r
+}\r
+\r
+/**\r
+  Executes an SMBUS quick, byte or word command.\r
+\r
+  This internal function executes an SMBUS quick, byte or word commond.\r
+  If Status is not NULL, then the status of the executed command is returned in Status.\r
+\r
+  @param  HostControl     The value of Host Control Register to set.\r
+  @param  SmBusAddress    Address that encodes the SMBUS Slave Address,\r
+                          SMBUS Command, SMBUS Data Length, and PEC.\r
+  @param  Value           The byte/word write to the SMBUS.\r
+  @param  Status          Return status for the executed command.\r
+                          This is an optional parameter and may be NULL.\r
+\r
+  @return The byte/word read from the SMBUS.\r
+\r
+**/\r
+UINT16\r
+InternalSmBusNonBlock (\r
+  IN  UINT8                     HostControl,\r
+  IN  UINTN                     SmBusAddress,\r
+  IN  UINT16                    Value,\r
+  OUT RETURN_STATUS             *Status\r
+  )\r
+{\r
+  RETURN_STATUS                 ReturnStatus;\r
+  UINTN                         IoPortBaseAddress;\r
+\r
+  IoPortBaseAddress = InternalGetSmbusIoPortBaseAddress ();\r
+\r
+  //\r
+  // Try to acquire the ownership of QNC SMBUS.\r
+  //\r
+  ReturnStatus = InternalSmBusAcquire (IoPortBaseAddress);\r
+  if (RETURN_ERROR (ReturnStatus)) {\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Set Host Commond Register.\r
+  //\r
+  IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HCMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress));\r
+  //\r
+  // Write value to Host Data 0 and Host Data 1 Registers.\r
+  //\r
+  IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HD0, (UINT8) Value);\r
+  IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HD1, (UINT8) (Value >> 8));\r
+\r
+\r
+  //\r
+  // Set SMBUS slave address for the device to send/receive from.\r
+  //\r
+  IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_TSA, (UINT8) SmBusAddress);\r
+  //\r
+  // Start the SMBUS transaction and wait for the end.\r
+  //\r
+  ReturnStatus = InternalSmBusStart (IoPortBaseAddress, HostControl);\r
+  //\r
+  // Read value from Host Data 0 and Host Data 1 Registers.\r
+  //\r
+  Value = (UINT16)(IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HD1) << 8);\r
+  Value = (UINT16)(Value | IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HD0));\r
+\r
+  //\r
+  // Clear Host Status Register and Auxiliary Status Register.\r
+  //\r
+  IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS, B_QNC_SMBUS_HSTS_ALL);\r
+\r
+Done:\r
+  if (Status != NULL) {\r
+    *Status = ReturnStatus;\r
+  }\r
+\r
+  return Value;\r
+}\r
+\r
+/**\r
+  Executes an SMBUS quick read command.\r
+\r
+  Executes an SMBUS quick read command on the SMBUS device specified by SmBusAddress.\r
+  Only the SMBUS slave address field of SmBusAddress is required.\r
+  If Status is not NULL, then the status of the executed command is returned in Status.\r
+  If PEC is set in SmBusAddress, then ASSERT().\r
+  If Command in SmBusAddress is not zero, then ASSERT().\r
+  If Length in SmBusAddress is not zero, then ASSERT().\r
+  If any reserved bits of SmBusAddress are set, then ASSERT().\r
+\r
+  @param  SmBusAddress    Address that encodes the SMBUS Slave Address,\r
+                          SMBUS Command, SMBUS Data Length, and PEC.\r
+  @param  Status          Return status for the executed command.\r
+                          This is an optional parameter and may be NULL.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SmBusQuickRead (\r
+  IN  UINTN                     SmBusAddress,\r
+  OUT RETURN_STATUS             *Status       OPTIONAL\r
+  )\r
+{\r
+  ASSERT (!SMBUS_LIB_PEC (SmBusAddress));\r
+  ASSERT (SMBUS_LIB_COMMAND (SmBusAddress)   == 0);\r
+  ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);\r
+  ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);\r
+\r
+  InternalSmBusNonBlock (\r
+    V_QNC_SMBUS_HCTL_CMD_QUICK,\r
+    SmBusAddress | V_QNC_SMBUS_RW_SEL_READ,\r
+    0,\r
+    Status\r
+    );\r
+\r
+}\r
+\r
+/**\r
+  Executes an SMBUS quick write command.\r
+\r
+  Executes an SMBUS quick write command on the SMBUS device specified by SmBusAddress.\r
+  Only the SMBUS slave address field of SmBusAddress is required.\r
+  If Status is not NULL, then the status of the executed command is returned in Status.\r
+  If PEC is set in SmBusAddress, then ASSERT().\r
+  If Command in SmBusAddress is not zero, then ASSERT().\r
+  If Length in SmBusAddress is not zero, then ASSERT().\r
+  If any reserved bits of SmBusAddress are set, then ASSERT().\r
+\r
+  @param  SmBusAddress    Address that encodes the SMBUS Slave Address,\r
+                          SMBUS Command, SMBUS Data Length, and PEC.\r
+  @param  Status          Return status for the executed command.\r
+                          This is an optional parameter and may be NULL.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SmBusQuickWrite (\r
+  IN  UINTN                     SmBusAddress,\r
+  OUT RETURN_STATUS             *Status       OPTIONAL\r
+  )\r
+{\r
+  ASSERT (!SMBUS_LIB_PEC (SmBusAddress));\r
+  ASSERT (SMBUS_LIB_COMMAND (SmBusAddress)   == 0);\r
+  ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);\r
+  ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);\r
+\r
+  InternalSmBusNonBlock (\r
+    V_QNC_SMBUS_HCTL_CMD_QUICK,\r
+    SmBusAddress & V_QNC_SMBUS_RW_SEL_WRITE,\r
+    0,\r
+    Status\r
+    );\r
+\r
+}\r
+\r
+/**\r
+  Executes an SMBUS receive byte command.\r
+\r
+  Executes an SMBUS receive byte command on the SMBUS device specified by SmBusAddress.\r
+  Only the SMBUS slave address field of SmBusAddress is required.\r
+  The byte received from the SMBUS is returned.\r
+  If Status is not NULL, then the status of the executed command is returned in Status.\r
+  If Command in SmBusAddress is not zero, then ASSERT().\r
+  If Length in SmBusAddress is not zero, then ASSERT().\r
+  If any reserved bits of SmBusAddress are set, then ASSERT().\r
+\r
+  @param  SmBusAddress    Address that encodes the SMBUS Slave Address,\r
+                          SMBUS Command, SMBUS Data Length, and PEC.\r
+  @param  Status          Return status for the executed command.\r
+                          This is an optional parameter and may be NULL.\r
+\r
+  @return The byte received from the SMBUS.\r
+\r
+**/\r
+UINT8\r
+EFIAPI\r
+SmBusReceiveByte (\r
+  IN  UINTN          SmBusAddress,\r
+  OUT RETURN_STATUS  *Status        OPTIONAL\r
+  )\r
+{\r
+  ASSERT (SMBUS_LIB_COMMAND (SmBusAddress)   == 0);\r
+  ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);\r
+  ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);\r
+\r
+  return (UINT8) InternalSmBusNonBlock (\r
+                   V_QNC_SMBUS_HCTL_CMD_BYTE,\r
+                   SmBusAddress | V_QNC_SMBUS_RW_SEL_READ,\r
+                   0,\r
+                   Status\r
+                   );\r
+\r
+}\r
+\r
+/**\r
+  Executes an SMBUS send byte command.\r
+\r
+  Executes an SMBUS send byte command on the SMBUS device specified by SmBusAddress.\r
+  The byte specified by Value is sent.\r
+  Only the SMBUS slave address field of SmBusAddress is required.  Value is returned.\r
+  If Status is not NULL, then the status of the executed command is returned in Status.\r
+  If Command in SmBusAddress is not zero, then ASSERT().\r
+  If Length in SmBusAddress is not zero, then ASSERT().\r
+  If any reserved bits of SmBusAddress are set, then ASSERT().\r
+\r
+  @param  SmBusAddress    Address that encodes the SMBUS Slave Address,\r
+                          SMBUS Command, SMBUS Data Length, and PEC.\r
+  @param  Value           The 8-bit value to send.\r
+  @param  Status          Return status for the executed command.\r
+                          This is an optional parameter and may be NULL.\r
+\r
+  @return The parameter of Value.\r
+\r
+**/\r
+UINT8\r
+EFIAPI\r
+SmBusSendByte (\r
+  IN  UINTN          SmBusAddress,\r
+  IN  UINT8          Value,\r
+  OUT RETURN_STATUS  *Status        OPTIONAL\r
+  )\r
+{\r
+  ASSERT (SMBUS_LIB_COMMAND (SmBusAddress)   == 0);\r
+  ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);\r
+  ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);\r
+\r
+  return (UINT8) InternalSmBusNonBlock (\r
+                   V_QNC_SMBUS_HCTL_CMD_BYTE,\r
+                   SmBusAddress & V_QNC_SMBUS_RW_SEL_WRITE,\r
+                   Value,\r
+                   Status\r
+                   );\r
+\r
+}\r
+\r
+/**\r
+  Executes an SMBUS read data byte command.\r
+\r
+  Executes an SMBUS read data byte command on the SMBUS device specified by SmBusAddress.\r
+  Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.\r
+  The 8-bit value read from the SMBUS is returned.\r
+  If Status is not NULL, then the status of the executed command is returned in Status.\r
+  If Length in SmBusAddress is not zero, then ASSERT().\r
+  If any reserved bits of SmBusAddress are set, then ASSERT().\r
+\r
+  @param  SmBusAddress    Address that encodes the SMBUS Slave Address,\r
+                          SMBUS Command, SMBUS Data Length, and PEC.\r
+  @param  Status          Return status for the executed command.\r
+                          This is an optional parameter and may be NULL.\r
+\r
+  @return The byte read from the SMBUS.\r
+\r
+**/\r
+UINT8\r
+EFIAPI\r
+SmBusReadDataByte (\r
+  IN  UINTN          SmBusAddress,\r
+  OUT RETURN_STATUS  *Status        OPTIONAL\r
+  )\r
+{\r
+  ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);\r
+  ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);\r
+\r
+  return (UINT8) InternalSmBusNonBlock (\r
+                   V_QNC_SMBUS_HCTL_CMD_BYTE_DATA,\r
+                   SmBusAddress | V_QNC_SMBUS_RW_SEL_READ,\r
+                   0,\r
+                   Status\r
+                   );\r
+}\r
+\r
+/**\r
+  Executes an SMBUS write data byte command.\r
+\r
+  Executes an SMBUS write data byte command on the SMBUS device specified by SmBusAddress.\r
+  The 8-bit value specified by Value is written.\r
+  Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.\r
+  Value is returned.\r
+  If Status is not NULL, then the status of the executed command is returned in Status.\r
+  If Length in SmBusAddress is not zero, then ASSERT().\r
+  If any reserved bits of SmBusAddress are set, then ASSERT().\r
+\r
+  @param  SmBusAddress    Address that encodes the SMBUS Slave Address,\r
+                          SMBUS Command, SMBUS Data Length, and PEC.\r
+  @param  Value           The 8-bit value to write.\r
+  @param  Status          Return status for the executed command.\r
+                          This is an optional parameter and may be NULL.\r
+\r
+  @return The parameter of Value.\r
+\r
+**/\r
+UINT8\r
+EFIAPI\r
+SmBusWriteDataByte (\r
+  IN  UINTN          SmBusAddress,\r
+  IN  UINT8          Value,\r
+  OUT RETURN_STATUS  *Status        OPTIONAL\r
+  )\r
+{\r
+  ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);\r
+  ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);\r
+\r
+  return (UINT8) InternalSmBusNonBlock (\r
+                   V_QNC_SMBUS_HCTL_CMD_BYTE_DATA,\r
+                   SmBusAddress | V_QNC_SMBUS_RW_SEL_WRITE,\r
+                   Value,\r
+                   Status\r
+                   );\r
+}\r
+\r
+/**\r
+  Executes an SMBUS read data word command.\r
+\r
+  Executes an SMBUS read data word command on the SMBUS device specified by SmBusAddress.\r
+  Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.\r
+  The 16-bit value read from the SMBUS is returned.\r
+  If Status is not NULL, then the status of the executed command is returned in Status.\r
+  If Length in SmBusAddress is not zero, then ASSERT().\r
+  If any reserved bits of SmBusAddress are set, then ASSERT().\r
+\r
+  @param  SmBusAddress    Address that encodes the SMBUS Slave Address,\r
+                          SMBUS Command, SMBUS Data Length, and PEC.\r
+  @param  Status          Return status for the executed command.\r
+                          This is an optional parameter and may be NULL.\r
+\r
+  @return The byte read from the SMBUS.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+SmBusReadDataWord (\r
+  IN  UINTN          SmBusAddress,\r
+  OUT RETURN_STATUS  *Status        OPTIONAL\r
+  )\r
+{\r
+  ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 2);\r
+  ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);\r
+\r
+  return InternalSmBusNonBlock (\r
+           V_QNC_SMBUS_HCTL_CMD_WORD_DATA,\r
+           SmBusAddress | V_QNC_SMBUS_RW_SEL_READ,\r
+           0,\r
+           Status\r
+           );\r
+\r
+}\r
+\r
+/**\r
+  Executes an SMBUS write data word command.\r
+\r
+  Executes an SMBUS write data word command on the SMBUS device specified by SmBusAddress.\r
+  The 16-bit value specified by Value is written.\r
+  Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.\r
+  Value is returned.\r
+  If Status is not NULL, then the status of the executed command is returned in Status.\r
+  If Length in SmBusAddress is not zero, then ASSERT().\r
+  If any reserved bits of SmBusAddress are set, then ASSERT().\r
+\r
+  @param  SmBusAddress    Address that encodes the SMBUS Slave Address,\r
+                          SMBUS Command, SMBUS Data Length, and PEC.\r
+  @param  Value           The 16-bit value to write.\r
+  @param  Status          Return status for the executed command.\r
+                          This is an optional parameter and may be NULL.\r
+\r
+  @return The parameter of Value.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+SmBusWriteDataWord (\r
+  IN  UINTN          SmBusAddress,\r
+  IN  UINT16         Value,\r
+  OUT RETURN_STATUS  *Status        OPTIONAL\r
+  )\r
+{\r
+  ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 2);\r
+  ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);\r
+\r
+  return InternalSmBusNonBlock (\r
+         V_QNC_SMBUS_HCTL_CMD_WORD_DATA,\r
+         SmBusAddress | V_QNC_SMBUS_RW_SEL_WRITE,\r
+         Value,\r
+         Status\r
+         );\r
+}\r
+\r
+/**\r
+  Executes an SMBUS process call command.\r
+\r
+  Executes an SMBUS process call command on the SMBUS device specified by SmBusAddress.\r
+  The 16-bit value specified by Value is written.\r
+  Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.\r
+  The 16-bit value returned by the process call command is returned.\r
+  If Status is not NULL, then the status of the executed command is returned in Status.\r
+  If Length in SmBusAddress is not zero, then ASSERT().\r
+  If any reserved bits of SmBusAddress are set, then ASSERT().\r
+\r
+  @param  SmBusAddress    Address that encodes the SMBUS Slave Address,\r
+                          SMBUS Command, SMBUS Data Length, and PEC.\r
+  @param  Value           The 16-bit value to write.\r
+  @param  Status          Return status for the executed command.\r
+                          This is an optional parameter and may be NULL.\r
+\r
+  @return The 16-bit value returned by the process call command.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+SmBusProcessCall (\r
+  IN  UINTN          SmBusAddress,\r
+  IN  UINT16         Value,\r
+  OUT RETURN_STATUS  *Status        OPTIONAL\r
+  )\r
+{\r
+  ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);\r
+  ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);\r
+\r
+  return InternalSmBusNonBlock (\r
+           V_QNC_SMBUS_HCTL_CMD_PROCESS_CALL,\r
+           SmBusAddress & V_QNC_SMBUS_RW_SEL_WRITE,\r
+           Value,\r
+           Status\r
+           );\r
+\r
+}\r
+\r
+/**\r
+  Executes an SMBUS block command.\r
+\r
+  Executes an SMBUS block read, block write and block write-block read command\r
+  on the SMBUS device specified by SmBusAddress.\r
+  Bytes are read from the SMBUS and stored in Buffer.\r
+  The number of bytes read is returned, and will never return a value larger than 32-bytes.\r
+  If Status is not NULL, then the status of the executed command is returned in Status.\r
+  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.\r
+  SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.\r
+\r
+  @param  HostControl     The value of Host Control Register to set.\r
+  @param  SmBusAddress    Address that encodes the SMBUS Slave Address,\r
+                          SMBUS Command, SMBUS Data Length, and PEC.\r
+  @param  WriteBuffer     Pointer to the buffer of bytes to write to the SMBUS.\r
+  @param  ReadBuffer      Pointer to the buffer of bytes to read from the SMBUS.\r
+  @param  Status          Return status for the executed command.\r
+                          This is an optional parameter and may be NULL.\r
+\r
+  @return The number of bytes read from the SMBUS.\r
+\r
+**/\r
+UINTN\r
+InternalSmBusBlock (\r
+  IN  UINT8                     HostControl,\r
+  IN  UINTN                     SmBusAddress,\r
+  IN  UINT8                     *WriteBuffer,\r
+  OUT UINT8                     *ReadBuffer,\r
+  OUT RETURN_STATUS             *Status\r
+  )\r
+{\r
+  RETURN_STATUS                 ReturnStatus;\r
+  UINTN                         Index;\r
+  UINTN                         BytesCount;\r
+  UINTN                         IoPortBaseAddress;\r
+\r
+  IoPortBaseAddress = InternalGetSmbusIoPortBaseAddress ();\r
+\r
+  BytesCount = SMBUS_LIB_LENGTH (SmBusAddress);\r
+\r
+  //\r
+  // Try to acquire the ownership of ICH SMBUS.\r
+  //\r
+  ReturnStatus = InternalSmBusAcquire (IoPortBaseAddress);\r
+  if (RETURN_ERROR (ReturnStatus)) {\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Set Host Command Register.\r
+  //\r
+  IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HCMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress));\r
+\r
+  //\r
+  // Clear byte pointer of 32-byte buffer.\r
+  //\r
+  IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HCTL);\r
+\r
+  if (WriteBuffer != NULL) {\r
+    //\r
+    // Write the number of block to Host Block Data Byte Register.\r
+    //\r
+    IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HD0, (UINT8) BytesCount);\r
+    //\r
+    // Write data block to Host Block Data Register.\r
+    //\r
+    for (Index = 0; Index < BytesCount; Index++) {\r
+      IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HBD + (UINT8)Index, WriteBuffer[Index]);\r
+    }\r
+  }\r
+  //\r
+  // Set SMBUS slave address for the device to send/receive from.\r
+  //\r
+  IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_TSA, (UINT8) SmBusAddress);\r
+  //\r
+  // Start the SMBUS transaction and wait for the end.\r
+  //\r
+  ReturnStatus = InternalSmBusStart (IoPortBaseAddress, HostControl);\r
+  if (RETURN_ERROR (ReturnStatus)) {\r
+    goto Done;\r
+  }\r
+\r
+  if (ReadBuffer != NULL) {\r
+    //\r
+    // Read the number of block from host block data byte register.\r
+    //\r
+    BytesCount = IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HD0);\r
+    //\r
+    // Write data block from Host Block Data Register.\r
+    //\r
+    for (Index = 0; Index < BytesCount; Index++) {\r
+      ReadBuffer[Index] = IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HBD + (UINT8)Index);\r
+    }\r
+  }\r
+\r
+Done:\r
+  //\r
+  // Clear Host Status Register and Auxiliary Status Register.\r
+  //\r
+  IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS, B_QNC_SMBUS_HSTS_ALL);\r
+\r
+  if (Status != NULL) {\r
+    *Status = ReturnStatus;\r
+  }\r
+\r
+  return BytesCount;\r
+}\r
+\r
+/**\r
+  Executes an SMBUS read block command.\r
+\r
+  Executes an SMBUS read block command on the SMBUS device specified by SmBusAddress.\r
+  Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.\r
+  Bytes are read from the SMBUS and stored in Buffer.\r
+  The number of bytes read is returned, and will never return a value larger than 32-bytes.\r
+  If Status is not NULL, then the status of the executed command is returned in Status.\r
+  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.\r
+  SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.\r
+  If Length in SmBusAddress is not zero, then ASSERT().\r
+  If Buffer is NULL, then ASSERT().\r
+  If any reserved bits of SmBusAddress are set, then ASSERT().\r
+\r
+  @param  SmBusAddress    Address that encodes the SMBUS Slave Address,\r
+                          SMBUS Command, SMBUS Data Length, and PEC.\r
+  @param  Buffer          Pointer to the buffer to store the bytes read from the SMBUS.\r
+  @param  Status          Return status for the executed command.\r
+                          This is an optional parameter and may be NULL.\r
+\r
+  @return The number of bytes read.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+SmBusReadBlock (\r
+  IN  UINTN          SmBusAddress,\r
+  OUT VOID           *Buffer,\r
+  OUT RETURN_STATUS  *Status        OPTIONAL\r
+  )\r
+{\r
+  ASSERT (Buffer != NULL);\r
+  ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1);\r
+  ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32);\r
+  ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);\r
+\r
+  return InternalSmBusBlock (\r
+           V_QNC_SMBUS_HCTL_CMD_BLOCK,\r
+           SmBusAddress | V_QNC_SMBUS_RW_SEL_READ,\r
+           NULL,\r
+           Buffer,\r
+           Status\r
+           );\r
+}\r
+\r
+/**\r
+  Executes an SMBUS write block command.\r
+\r
+  Executes an SMBUS write block command on the SMBUS device specified by SmBusAddress.\r
+  The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required.\r
+  Bytes are written to the SMBUS from Buffer.\r
+  The number of bytes written is returned, and will never return a value larger than 32-bytes.\r
+  If Status is not NULL, then the status of the executed command is returned in Status.\r
+  If Length in SmBusAddress is zero or greater than 32, then ASSERT().\r
+  If Buffer is NULL, then ASSERT().\r
+  If any reserved bits of SmBusAddress are set, then ASSERT().\r
+\r
+  @param  SmBusAddress    Address that encodes the SMBUS Slave Address,\r
+                          SMBUS Command, SMBUS Data Length, and PEC.\r
+  @param  Buffer          Pointer to the buffer to store the bytes read from the SMBUS.\r
+  @param  Status          Return status for the executed command.\r
+                          This is an optional parameter and may be NULL.\r
+\r
+  @return The number of bytes written.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+SmBusWriteBlock (\r
+  IN  UINTN          SmBusAddress,\r
+  OUT VOID           *Buffer,\r
+  OUT RETURN_STATUS  *Status        OPTIONAL\r
+  )\r
+{\r
+  ASSERT (Buffer != NULL);\r
+  ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1);\r
+  ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32);\r
+  ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);\r
+\r
+  return InternalSmBusBlock (\r
+           V_QNC_SMBUS_HCTL_CMD_BLOCK,\r
+           SmBusAddress | V_QNC_SMBUS_RW_SEL_WRITE,\r
+           Buffer,\r
+           NULL,\r
+           Status\r
+           );\r
+}\r
+\r
+/**\r
+  Executes an SMBUS block process call command.\r
+\r
+  Executes an SMBUS block process call command on the SMBUS device specified by SmBusAddress.\r
+  The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required.\r
+  Bytes are written to the SMBUS from WriteBuffer.  Bytes are then read from the SMBUS into ReadBuffer.\r
+  If Status is not NULL, then the status of the executed command is returned in Status.\r
+  It is the caller's responsibility to make sure ReadBuffer is large enough for the total number of bytes read.\r
+  SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.\r
+  If Length in SmBusAddress is zero or greater than 32, then ASSERT().\r
+  If WriteBuffer is NULL, then ASSERT().\r
+  If ReadBuffer is NULL, then ASSERT().\r
+  If any reserved bits of SmBusAddress are set, then ASSERT().\r
+\r
+  @param  SmBusAddress  Address that encodes the SMBUS Slave Address,\r
+                        SMBUS Command, SMBUS Data Length, and PEC.\r
+  @param  WriteBuffer   Pointer to the buffer of bytes to write to the SMBUS.\r
+  @param  ReadBuffer    Pointer to the buffer of bytes to read from the SMBUS.\r
+  @param  Status        Return status for the executed command.\r
+                        This is an optional parameter and may be NULL.\r
+                        RETURN_TIMEOUT A timeout occurred while executing the SMBUS command.\r
+                        RETURN_DEVICE_ERROR  The request was not completed because a failure\r
+                        reflected in the Host Status Register bit.  Device errors are a result\r
+                        of a transaction collision, illegal command field, unclaimed cycle\r
+                        (host initiated), or bus errors (collisions).\r
+                        RETURN_CRC_ERROR  The checksum is not correct (PEC is incorrect)\r
+                        RETURN_UNSUPPORTED  The SMBus operation is not supported.\r
+\r
+  @return The number of bytes written.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+SmBusBlockProcessCall (\r
+  IN  UINTN          SmBusAddress,\r
+  IN  VOID           *WriteBuffer,\r
+  OUT VOID           *ReadBuffer,\r
+  OUT RETURN_STATUS  *Status        OPTIONAL\r
+  )\r
+{\r
+  ASSERT (WriteBuffer != NULL);\r
+  ASSERT (ReadBuffer  != NULL);\r
+  ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1);\r
+  ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32);\r
+  ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);\r
+  if (Status != NULL) {\r
+    *Status = RETURN_UNSUPPORTED;\r
+  }\r
+  return 0;\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.inf b/QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.inf
new file mode 100644 (file)
index 0000000..fef03aa
--- /dev/null
@@ -0,0 +1,53 @@
+## @file\r
+# Component description file for Intel QNC Smbus Library.\r
+#\r
+# SMBUS Library that layers on top of the I/O Library to directly\r
+# access a standard SMBUS host controller.\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = SmbusLib\r
+  FILE_GUID                      = 6F2F36B3-936B-4eb2-83C7-2987B4F9D4EB\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = SmbusLib\r
+\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  SmbusLib.c\r
+  CommonHeader.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  PcdLib\r
+  DebugLib\r
+  PciLib\r
+  IoLib\r
+  QNCAccessLib\r
+\r
+[FeaturePcd]\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmbaIoBaseAddressFixed\r
+\r
+[Pcd]\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmbaIoBaseAddress\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c b/QuarkSocPkg/QuarkNorthCluster/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c
new file mode 100644 (file)
index 0000000..6c46645
--- /dev/null
@@ -0,0 +1,438 @@
+/** @file\r
+The Quark CPU specific programming for PiSmmCpuDxeSmm module.\r
+\r
+Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiSmm.h>\r
+#include <Library/SmmCpuFeaturesLib.h>\r
+#include <Register/SmramSaveStateMap.h>\r
+#include <Library/QNCAccessLib.h>\r
+\r
+#define  EFI_MSR_SMRR_PHYS_MASK_VALID          BIT11\r
+#define  EFI_MSR_SMRR_MASK                     0xFFFFF000\r
+\r
+/**\r
+  Called during the very first SMI into System Management Mode to initialize\r
+  CPU features, including SMBASE, for the currently executing CPU.  Since this\r
+  is the first SMI, the SMRAM Save State Map is at the default address of\r
+  SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET.  The currently executing\r
+  CPU is specified by CpuIndex and CpuIndex can be used to access information\r
+  about the currently executing CPU in the ProcessorInfo array and the\r
+  HotPlugCpuData data structure.\r
+\r
+  @param[in] CpuIndex        The index of the CPU to initialize.  The value\r
+                             must be between 0 and the NumberOfCpus field in\r
+                             the System Management System Table (SMST).\r
+  @param[in] IsMonarch       TRUE if the CpuIndex is the index of the CPU that\r
+                             was elected as monarch during System Management\r
+                             Mode initialization.\r
+                             FALSE if the CpuIndex is not the index of the CPU\r
+                             that was elected as monarch during System\r
+                             Management Mode initialization.\r
+  @param[in] ProcessorInfo   Pointer to an array of EFI_PROCESSOR_INFORMATION\r
+                             structures.  ProcessorInfo[CpuIndex] contains the\r
+                             information for the currently executing CPU.\r
+  @param[in] CpuHotPlugData  Pointer to the CPU_HOT_PLUG_DATA structure that\r
+                             contains the ApidId and SmBase arrays.\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmCpuFeaturesInitializeProcessor (\r
+  IN UINTN                      CpuIndex,\r
+  IN BOOLEAN                    IsMonarch,\r
+  IN EFI_PROCESSOR_INFORMATION  *ProcessorInfo,\r
+  IN CPU_HOT_PLUG_DATA          *CpuHotPlugData\r
+  )\r
+{\r
+  SMRAM_SAVE_STATE_MAP  *CpuState;\r
+\r
+  //\r
+  // Configure SMBASE.\r
+  //\r
+  CpuState = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);\r
+  CpuState->x86.SMBASE = CpuHotPlugData->SmBase[CpuIndex];\r
+\r
+  //\r
+  // Use QNC to initialize SMRR on Quark\r
+  //\r
+  QNCPortWrite(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_IA32_MTRR_SMRR_PHYSBASE, CpuHotPlugData->SmrrBase);\r
+  QNCPortWrite(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_IA32_MTRR_SMRR_PHYSMASK, (~(CpuHotPlugData->SmrrSize - 1) & EFI_MSR_SMRR_MASK) | EFI_MSR_SMRR_PHYS_MASK_VALID);\r
+}\r
+\r
+/**\r
+  This function updates the SMRAM save state on the currently executing CPU\r
+  to resume execution at a specific address after an RSM instruction.  This\r
+  function must evaluate the SMRAM save state to determine the execution mode\r
+  the RSM instruction resumes and update the resume execution address with\r
+  either NewInstructionPointer32 or NewInstructionPoint.  The auto HALT restart\r
+  flag in the SMRAM save state must always be cleared.  This function returns\r
+  the value of the instruction pointer from the SMRAM save state that was\r
+  replaced.  If this function returns 0, then the SMRAM save state was not\r
+  modified.\r
+\r
+  This function is called during the very first SMI on each CPU after\r
+  SmmCpuFeaturesInitializeProcessor() to set a flag in normal execution mode\r
+  to signal that the SMBASE of each CPU has been updated before the default\r
+  SMBASE address is used for the first SMI to the next CPU.\r
+\r
+  @param[in] CpuIndex                 The index of the CPU to hook.  The value\r
+                                      must be between 0 and the NumberOfCpus\r
+                                      field in the System Management System Table\r
+                                      (SMST).\r
+  @param[in] CpuState                 Pointer to SMRAM Save State Map for the\r
+                                      currently executing CPU.\r
+  @param[in] NewInstructionPointer32  Instruction pointer to use if resuming to\r
+                                      32-bit execution mode from 64-bit SMM.\r
+  @param[in] NewInstructionPointer    Instruction pointer to use if resuming to\r
+                                      same execution mode as SMM.\r
+\r
+  @retval 0    This function did modify the SMRAM save state.\r
+  @retval > 0  The original instruction pointer value from the SMRAM save state\r
+               before it was replaced.\r
+**/\r
+UINT64\r
+EFIAPI\r
+SmmCpuFeaturesHookReturnFromSmm (\r
+  IN UINTN                 CpuIndex,\r
+  IN SMRAM_SAVE_STATE_MAP  *CpuState,\r
+  IN UINT64                NewInstructionPointer32,\r
+  IN UINT64                NewInstructionPointer\r
+  )\r
+{\r
+  return 0;\r
+}\r
+\r
+/**\r
+  Hook point in normal execution mode that allows the one CPU that was elected\r
+  as monarch during System Management Mode initialization to perform additional\r
+  initialization actions immediately after all of the CPUs have processed their\r
+  first SMI and called SmmCpuFeaturesInitializeProcessor() relocating SMBASE\r
+  into a buffer in SMRAM and called SmmCpuFeaturesHookReturnFromSmm().\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmCpuFeaturesSmmRelocationComplete (\r
+  VOID\r
+  )\r
+{\r
+}\r
+\r
+/**\r
+  Return the size, in bytes, of a custom SMI Handler in bytes.  If 0 is\r
+  returned, then a custom SMI handler is not provided by this library,\r
+  and the default SMI handler must be used.\r
+\r
+  @retval 0    Use the default SMI handler.\r
+  @retval > 0  Use the SMI handler installed by SmmCpuFeaturesInstallSmiHandler()\r
+               The caller is required to allocate enough SMRAM for each CPU to\r
+               support the size of the custom SMI handler.\r
+**/\r
+UINTN\r
+EFIAPI\r
+SmmCpuFeaturesGetSmiHandlerSize (\r
+  VOID\r
+  )\r
+{\r
+  return 0;\r
+}\r
+\r
+/**\r
+  Install a custom SMI handler for the CPU specified by CpuIndex.  This function\r
+  is only called if SmmCpuFeaturesGetSmiHandlerSize() returns a size is greater\r
+  than zero and is called by the CPU that was elected as monarch during System\r
+  Management Mode initialization.\r
+\r
+  @param[in] CpuIndex   The index of the CPU to install the custom SMI handler.\r
+                        The value must be between 0 and the NumberOfCpus field\r
+                        in the System Management System Table (SMST).\r
+  @param[in] SmBase     The SMBASE address for the CPU specified by CpuIndex.\r
+  @param[in] SmiStack   The stack to use when an SMI is processed by the\r
+                        the CPU specified by CpuIndex.\r
+  @param[in] StackSize  The size, in bytes, if the stack used when an SMI is\r
+                        processed by the CPU specified by CpuIndex.\r
+  @param[in] GdtBase    The base address of the GDT to use when an SMI is\r
+                        processed by the CPU specified by CpuIndex.\r
+  @param[in] GdtSize    The size, in bytes, of the GDT used when an SMI is\r
+                        processed by the CPU specified by CpuIndex.\r
+  @param[in] IdtBase    The base address of the IDT to use when an SMI is\r
+                        processed by the CPU specified by CpuIndex.\r
+  @param[in] IdtSize    The size, in bytes, of the IDT used when an SMI is\r
+                        processed by the CPU specified by CpuIndex.\r
+  @param[in] Cr3        The base address of the page tables to use when an SMI\r
+                        is processed by the CPU specified by CpuIndex.\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmCpuFeaturesInstallSmiHandler (\r
+  IN UINTN   CpuIndex,\r
+  IN UINT32  SmBase,\r
+  IN VOID    *SmiStack,\r
+  IN UINTN   StackSize,\r
+  IN UINTN   GdtBase,\r
+  IN UINTN   GdtSize,\r
+  IN UINTN   IdtBase,\r
+  IN UINTN   IdtSize,\r
+  IN UINT32  Cr3\r
+  )\r
+{\r
+}\r
+\r
+/**\r
+  Determines if MTRR registers must be configured to set SMRAM cache-ability\r
+  when executing in System Management Mode.\r
+\r
+  @retval TRUE   MTRR registers must be configured to set SMRAM cache-ability.\r
+  @retval FALSE  MTRR registers do not need to be configured to set SMRAM\r
+                   cache-ability.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+SmmCpuFeaturesNeedConfigureMtrrs (\r
+  VOID\r
+  )\r
+{\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Disable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()\r
+  returns TRUE.\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmCpuFeaturesDisableSmrr (\r
+  VOID\r
+  )\r
+{\r
+  //\r
+  // Use QNC to disable SMRR on Quark\r
+  //\r
+  QNCPortWrite(\r
+    QUARK_NC_HOST_BRIDGE_SB_PORT_ID,\r
+    QUARK_NC_HOST_BRIDGE_IA32_MTRR_SMRR_PHYSMASK,\r
+    QNCPortRead(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_IA32_MTRR_SMRR_PHYSMASK) & ~EFI_MSR_SMRR_PHYS_MASK_VALID\r
+    );\r
+}\r
+\r
+/**\r
+  Enable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()\r
+  returns TRUE.\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmCpuFeaturesReenableSmrr (\r
+  VOID\r
+  )\r
+{\r
+  //\r
+  // Use QNC to enable SMRR on Quark\r
+  //\r
+  QNCPortWrite(\r
+    QUARK_NC_HOST_BRIDGE_SB_PORT_ID,\r
+    QUARK_NC_HOST_BRIDGE_IA32_MTRR_SMRR_PHYSMASK,\r
+    QNCPortRead(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_IA32_MTRR_SMRR_PHYSMASK) | EFI_MSR_SMRR_PHYS_MASK_VALID\r
+    );\r
+}\r
+\r
+/**\r
+  Processor specific hook point each time a CPU enters System Management Mode.\r
+\r
+  @param[in] CpuIndex  The index of the CPU that has entered SMM.  The value\r
+                       must be between 0 and the NumberOfCpus field in the\r
+                       System Management System Table (SMST).\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmCpuFeaturesRendezvousEntry (\r
+  IN UINTN  CpuIndex\r
+  )\r
+{\r
+}\r
+\r
+/**\r
+  Processor specific hook point each time a CPU exits System Management Mode.\r
+\r
+  @param[in] CpuIndex  The index of the CPU that is exiting SMM.  The value must\r
+                       be between 0 and the NumberOfCpus field in the System\r
+                       Management System Table (SMST).\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmCpuFeaturesRendezvousExit (\r
+  IN UINTN  CpuIndex\r
+  )\r
+{\r
+}\r
+\r
+/**\r
+  Check to see if an SMM register is supported by a specified CPU.\r
+\r
+  @param[in] CpuIndex  The index of the CPU to check for SMM register support.\r
+                       The value must be between 0 and the NumberOfCpus field\r
+                       in the System Management System Table (SMST).\r
+  @param[in] RegName   Identifies the SMM register to check for support.\r
+\r
+  @retval TRUE   The SMM register specified by RegName is supported by the CPU\r
+                 specified by CpuIndex.\r
+  @retval FALSE  The SMM register specified by RegName is not supported by the\r
+                 CPU specified by CpuIndex.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+SmmCpuFeaturesIsSmmRegisterSupported (\r
+  IN UINTN         CpuIndex,\r
+  IN SMM_REG_NAME  RegName\r
+  )\r
+{\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Returns the current value of the SMM register for the specified CPU.\r
+  If the SMM register is not supported, then 0 is returned.\r
+\r
+  @param[in] CpuIndex  The index of the CPU to read the SMM register.  The\r
+                       value must be between 0 and the NumberOfCpus field in\r
+                       the System Management System Table (SMST).\r
+  @param[in] RegName   Identifies the SMM register to read.\r
+\r
+  @return  The value of the SMM register specified by RegName from the CPU\r
+           specified by CpuIndex.\r
+**/\r
+UINT64\r
+EFIAPI\r
+SmmCpuFeaturesGetSmmRegister (\r
+  IN UINTN         CpuIndex,\r
+  IN SMM_REG_NAME  RegName\r
+  )\r
+{\r
+  return 0;\r
+}\r
+\r
+/**\r
+  Sets the value of an SMM register on a specified CPU.\r
+  If the SMM register is not supported, then no action is performed.\r
+\r
+  @param[in] CpuIndex  The index of the CPU to write the SMM register.  The\r
+                       value must be between 0 and the NumberOfCpus field in\r
+                       the System Management System Table (SMST).\r
+  @param[in] RegName   Identifies the SMM register to write.\r
+                       registers are read-only.\r
+  @param[in] Value     The value to write to the SMM register.\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmCpuFeaturesSetSmmRegister (\r
+  IN UINTN         CpuIndex,\r
+  IN SMM_REG_NAME  RegName,\r
+  IN UINT64        Value\r
+  )\r
+{\r
+}\r
+\r
+/**\r
+  Read an SMM Save State register on the target processor.  If this function\r
+  returns EFI_UNSUPPORTED, then the caller is responsible for reading the\r
+  SMM Save Sate register.\r
+\r
+  @param[in]  CpuIndex  The index of the CPU to read the SMM Save State.  The\r
+                        value must be between 0 and the NumberOfCpus field in\r
+                        the System Management System Table (SMST).\r
+  @param[in]  Register  The SMM Save State register to read.\r
+  @param[in]  Width     The number of bytes to read from the CPU save state.\r
+  @param[out] Buffer    Upon return, this holds the CPU register value read\r
+                        from the save state.\r
+\r
+  @retval EFI_SUCCESS           The register was read from Save State.\r
+  @retval EFI_INVALID_PARAMTER  Buffer is NULL.\r
+  @retval EFI_UNSUPPORTED       This function does not support reading Register.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmCpuFeaturesReadSaveStateRegister (\r
+  IN  UINTN                        CpuIndex,\r
+  IN  EFI_SMM_SAVE_STATE_REGISTER  Register,\r
+  IN  UINTN                        Width,\r
+  OUT VOID                         *Buffer\r
+  )\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+  Writes an SMM Save State register on the target processor.  If this function\r
+  returns EFI_UNSUPPORTED, then the caller is responsible for writing the\r
+  SMM Save Sate register.\r
+\r
+  @param[in] CpuIndex  The index of the CPU to write the SMM Save State.  The\r
+                       value must be between 0 and the NumberOfCpus field in\r
+                       the System Management System Table (SMST).\r
+  @param[in] Register  The SMM Save State register to write.\r
+  @param[in] Width     The number of bytes to write to the CPU save state.\r
+  @param[in] Buffer    Upon entry, this holds the new CPU register value.\r
+\r
+  @retval EFI_SUCCESS           The register was written to Save State.\r
+  @retval EFI_INVALID_PARAMTER  Buffer is NULL.\r
+  @retval EFI_UNSUPPORTED       This function does not support writing Register.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmCpuFeaturesWriteSaveStateRegister (\r
+  IN UINTN                        CpuIndex,\r
+  IN EFI_SMM_SAVE_STATE_REGISTER  Register,\r
+  IN UINTN                        Width,\r
+  IN CONST VOID                   *Buffer\r
+  )\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+  This function is hook point called after the gEfiSmmReadyToLockProtocolGuid\r
+  notification is completely processed.\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmCpuFeaturesCompleteSmmReadyToLock (\r
+  VOID\r
+  )\r
+{\r
+}\r
+\r
+/**\r
+  This API provides a method for a CPU to allocate a specific region for storing page tables.\r
+\r
+  This API can be called more once to allocate memory for page tables.\r
+\r
+  Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the\r
+  allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL\r
+  is returned.  If there is not enough memory remaining to satisfy the request, then NULL is\r
+  returned.\r
+\r
+  This function can also return NULL if there is no preference on where the page tables are allocated in SMRAM.\r
+\r
+  @param  Pages                 The number of 4 KB pages to allocate.\r
+\r
+  @return A pointer to the allocated buffer for page tables.\r
+  @retval NULL      Fail to allocate a specific region for storing page tables,\r
+                    Or there is no preference on where the page tables are allocated in SMRAM.\r
+\r
+**/\r
+VOID *\r
+EFIAPI\r
+SmmCpuFeaturesAllocatePageTableMemory (\r
+  IN UINTN           Pages\r
+  )\r
+{\r
+  return NULL;\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf b/QuarkSocPkg/QuarkNorthCluster/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf
new file mode 100644 (file)
index 0000000..473ece0
--- /dev/null
@@ -0,0 +1,34 @@
+## @file\r
+#  The CPU specific programming for PiSmmCpuDxeSmm module.\r
+#\r
+#  Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution.  The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = SmmCpuFeaturesLib\r
+  MODULE_UNI_FILE                = SmmCpuFeaturesLib.uni\r
+  FILE_GUID                      = 34001BF4-1E93-4e08-B90E-52F2418A5026\r
+  MODULE_TYPE                    = DXE_SMM_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = SmmCpuFeaturesLib\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  UefiCpuPkg/UefiCpuPkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[Sources]\r
+  SmmCpuFeaturesLib.c\r
+\r
+[LibraryClasses]\r
+  QNCAccessLib\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.uni b/QuarkSocPkg/QuarkNorthCluster/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.uni
new file mode 100644 (file)
index 0000000..322aa8b
--- /dev/null
@@ -0,0 +1,18 @@
+// /** @file\r
+// The CPU specific programming for PiSmmCpuDxeSmm module.\r
+//\r
+// Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
+//\r
+// This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution.  The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+//\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+// **/\r
+\r
+#string STR_MODULE_ABSTRACT             #language en-US "The CPU specific programming for PiSmmCpuDxeSmm module."\r
+\r
+#string STR_MODULE_DESCRIPTION          #language en-US "The CPU specific programming for PiSmmCpuDxeSmm module."\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInit.c b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInit.c
new file mode 100644 (file)
index 0000000..782a2d1
--- /dev/null
@@ -0,0 +1,65 @@
+/** @file\r
+Framework PEIM to initialize memory on a QuarkNcSocId Memory Controller.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "MemoryInit.h"\r
+\r
+static PEI_QNC_MEMORY_INIT_PPI mPeiQNCMemoryInitPpi =\r
+{ MrcStart };\r
+\r
+static EFI_PEI_PPI_DESCRIPTOR PpiListPeiQNCMemoryInit =\r
+{\r
+    (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+    &gQNCMemoryInitPpiGuid,\r
+    &mPeiQNCMemoryInitPpi\r
+};\r
+\r
+void Mrc( MRCParams_t *MrcData);\r
+\r
+/**\r
+\r
+ Do memory initialization for QuarkNcSocId DDR3 SDRAM Controller\r
+\r
+ @param  FfsHeader    Not used.\r
+ @param  PeiServices  General purpose services available to every PEIM.\r
+\r
+ @return EFI_SUCCESS  Memory initialization completed successfully.\r
+ All other error conditions encountered result in an ASSERT.\r
+\r
+ **/\r
+EFI_STATUS\r
+PeimMemoryInit(\r
+    IN EFI_PEI_FILE_HANDLE FileHandle,\r
+    IN CONST EFI_PEI_SERVICES **PeiServices\r
+    )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  Status = (**PeiServices).InstallPpi(PeiServices, &PpiListPeiQNCMemoryInit);\r
+\r
+  return Status;\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+MrcStart(\r
+    IN OUT MRCParams_t *MrcData\r
+    )\r
+{\r
+\r
+  Mrc(MrcData);\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInit.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInit.h
new file mode 100644 (file)
index 0000000..5d61c4d
--- /dev/null
@@ -0,0 +1,41 @@
+/** @file\r
+Framework PEIM to initialize memory on an DDR2 SDRAM Memory Controller.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#ifndef _PEI_QNC_MEMORY_INIT_H_\r
+#define _PEI_QNC_MEMORY_INIT_H_\r
+\r
+//\r
+// The package level header files this module uses\r
+//\r
+#include <PiPei.h>\r
+#include <IntelQNCPeim.h>\r
+//\r
+// The protocols, PPI and GUID defintions for this module\r
+//\r
+#include <Ppi/QNCMemoryInit.h>\r
+//\r
+// The Library classes this module consumes\r
+//\r
+#include <Library/DebugLib.h>\r
+#include <Library/PeimEntryPoint.h>\r
+#include <Library/BaseMemoryLib.h>\r
+\r
+\r
+VOID\r
+EFIAPI\r
+MrcStart (\r
+  IN OUT MRCParams_t  *MrcData\r
+  );\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInitPei.inf b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInitPei.inf
new file mode 100644 (file)
index 0000000..e327684
--- /dev/null
@@ -0,0 +1,76 @@
+## @file\r
+# This is the Memory Initialization Driver for Quark\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+################################################################################\r
+#\r
+# Defines Section - statements that will be processed to create a Makefile.\r
+#\r
+################################################################################\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = MemoryInitPei\r
+  FILE_GUID                      = D2C69B26-82E1-4a1b-AD35-ED0261B9F347\r
+  MODULE_TYPE                    = PEIM\r
+  VERSION_STRING                 = 1.0\r
+\r
+  ENTRY_POINT                    = PeimMemoryInit\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[BuildOptions]\r
+  GCC:DEBUG_*_*_CC_FLAGS               = -DGCC -Wno-unused-function\r
+  GCC:RELEASE_*_*_CC_FLAGS             = -DNDEBUG -DGCC -Wno-unused-function\r
+  INTEL:RELEASE_*_*_CC_FLAGS           = /D NDEBUG\r
+  MSFT:RELEASE_*_*_CC_FLAGS            = /D NDEBUG\r
+\r
+[Sources]\r
+  memory_options.h\r
+  platform.c\r
+  lprint.c\r
+  meminit.h\r
+  meminit.c\r
+  meminit_utils.h\r
+  meminit_utils.c\r
+  gen5_iosf_sb_definitions.h\r
+  general_definitions.h\r
+  io.h\r
+  core_types.h\r
+  prememinit.h\r
+  prememinit.c\r
+  mrc.h\r
+  mrc.c\r
+  hte.c\r
+  hte.h\r
+  MemoryInit.h\r
+  MemoryInit.c\r
+\r
+[Packages]\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+  MdePkg/MdePkg.dec\r
+\r
+[LibraryClasses]\r
+  PeimEntryPoint\r
+  DebugLib\r
+  BaseMemoryLib\r
+\r
+[Ppis]\r
+  gQNCMemoryInitPpiGuid                        # PPI ALWAYS_PRODUCED\r
+\r
+[Depex]\r
+  TRUE\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/core_types.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/core_types.h
new file mode 100644 (file)
index 0000000..78807a0
--- /dev/null
@@ -0,0 +1,49 @@
+/** @file\r
+Core types used in Mrc.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#ifndef __MRC_CORE_TYPES_H\r
+#define __MRC_CORE_TYPES_H\r
+\r
+typedef char char_t;\r
+typedef unsigned char uint8_t;\r
+typedef short int16_t;\r
+typedef unsigned short uint16_t;\r
+typedef int int32_t;\r
+typedef unsigned int uint32_t;\r
+typedef unsigned char bool;\r
+typedef unsigned int size_t;\r
+\r
+#ifdef ASM_INC\r
+// Unfortunately h2inc has issue with long long\r
+typedef struct uint64_s\r
+{\r
+  uint32_t lo;\r
+  uint32_t hi;\r
+}uint64_t;\r
+#else\r
+typedef unsigned long long uint64_t;\r
+#endif\r
+\r
+#ifdef SIM\r
+// Native word length is 64bit in simulation environment\r
+typedef uint64_t uintn_t;\r
+#else\r
+// Quark is 32bit\r
+typedef uint32_t uintn_t;\r
+#endif\r
+\r
+#define PTR32(a)  ((volatile uint32_t*)(uintn_t)(a))\r
+\r
+#endif\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/gen5_iosf_sb_definitions.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/gen5_iosf_sb_definitions.h
new file mode 100644 (file)
index 0000000..a8083a1
--- /dev/null
@@ -0,0 +1,744 @@
+/************************************************************************\r
+ *\r
+ * Copyright (c) 2013-2015 Intel Corporation.\r
+ *\r
+* This program and the accompanying materials\r
+* are licensed and made available under the terms and conditions of the BSD License\r
+* which accompanies this distribution.  The full text of the license may be found at\r
+* http://opensource.org/licenses/bsd-license.php\r
+*\r
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ *\r
+ * MCU register definition\r
+ *\r
+ ************************************************************************/\r
+#ifndef __IOSF_DEFINITIONS_H\r
+#define __IOSF_DEFINITIONS_H\r
+\r
+// Define each of the IOSF-SB register offsets used by MRC.\r
+\r
+\r
+// MCU registers (DUNIT):\r
+// ====\r
+#define DRP                 0x0000\r
+#define DTR0                0x0001\r
+#define DTR1                0x0002\r
+#define DTR2                0x0003\r
+#define DTR3                0x0004\r
+#define DTR4                0x0005\r
+#define DPMC0               0x0006\r
+#define DPMC1               0x0007\r
+#define DRFC                0x0008\r
+#define DSCH                0x0009\r
+#define DCAL                0x000A\r
+#define DRMC                0x000B\r
+#define PMSTS               0x000C\r
+#define DCO                 0x000F\r
+#define DSTAT               0x0020\r
+#define DECCCTRL            0x0060\r
+#define DFUSESTAT           0x0070\r
+#define SCRMSEED            0x0080\r
+#define SCRMLO              0x0081\r
+#define SCRMHI              0x0082\r
+\r
+#define MCU_CH_OFFSET       0x0040\r
+#define MCU_RK_OFFSET       0x0020\r
+\r
+////\r
+//\r
+// BEGIN DUnit register definition\r
+//\r
+#pragma pack(1)\r
+typedef union {\r
+    uint32_t    raw;\r
+    struct {\r
+        uint32_t rank0Enabled       :1;             /**< BIT [0]   Rank 0 Enable */\r
+        uint32_t rank1Enabled       :1;             /**< BIT [1]   Rank 1 Enable */\r
+        uint32_t reserved0          :2;\r
+        uint32_t dimm0DevWidth      :2;             /**< BIT [5:4] DIMM 0 Device Width (Rank0&1)  */\r
+        uint32_t dimm0DevDensity    :2;             /**< BIT [7:6] DIMM 0 Device Density          */\r
+        uint32_t reserved1          :1;\r
+        uint32_t dimm1DevWidth      :2;             /**< BIT [10:9]  DIMM 1 Device Width (Rank2&3)  */\r
+        uint32_t dimm1DevDensity    :2;             /**< BIT [12:11] DIMM 1 Device Density          */\r
+        uint32_t split64            :1;             /**< BIT [13] split 64B transactions */\r
+        uint32_t addressMap         :2;             /**< BIT [15:14] Address Map select */\r
+        uint32_t reserved3          :14;\r
+        uint32_t mode32             :1;             /**< BIT [30] Select 32bit data interface*/\r
+        uint32_t reserved4          :1;\r
+    } field;\r
+} RegDRP;                                           /**< DRAM Rank Population and Interface Register */\r
+#pragma pack()\r
+\r
+\r
+#pragma pack(1)\r
+typedef union {\r
+    uint32_t    raw;\r
+    struct {\r
+        uint32_t dramFrequency      :2;             /**< DRAM Frequency (000=800,001=1033,010=1333) */\r
+        uint32_t reserved1          :2;\r
+        uint32_t tRP                :4;             /**< bit [7:4]   Precharge to Activate Delay  */\r
+        uint32_t tRCD               :4;             /**< bit [11:8]  Activate to CAS Delay  */\r
+        uint32_t tCL                :3;             /**< bit [14:12] CAS Latency  */\r
+        uint32_t reserved4          :1;\r
+        uint32_t tXS                :1;             /**< SRX Delay  */\r
+        uint32_t reserved5          :1;\r
+        uint32_t tXSDLL             :1;             /**< SRX To DLL Delay  */\r
+        uint32_t reserved6          :1;\r
+        uint32_t tZQCS              :1;             /**< bit [20] ZQTS recovery Latncy  */\r
+        uint32_t reserved7          :1;\r
+        uint32_t tZQCL              :1;             /**< bit [22] ZQCL recovery Latncy  */\r
+        uint32_t reserved8          :1;\r
+        uint32_t pmeDelay           :2;             /**< bit [25:24] Power mode entry delay  */\r
+        uint32_t reserved9          :2;\r
+        uint32_t CKEDLY             :4;               /**< bit [31:28]  */\r
+    } field;\r
+} RegDTR0;                                          /**< DRAM Timing Register 0 */\r
+#pragma pack()\r
+\r
+#pragma pack(1)\r
+typedef union {\r
+    uint32_t    raw;\r
+    struct {\r
+        uint32_t tWCL               :3;             /**< bit [2:0] CAS Write Latency */\r
+        uint32_t reserved1          :1;\r
+        uint32_t tCMD               :2;             /**< bit [5:4] Command transport duration */\r
+        uint32_t reserved2          :2;\r
+        uint32_t tWTP               :4;             /**< Write to Precharge */\r
+        uint32_t tCCD               :2;             /**< CAS to CAS delay */\r
+        uint32_t reserved4          :2;\r
+        uint32_t tFAW               :4;             /**< Four bank Activation Window*/\r
+        uint32_t tRAS               :4;             /**< Row Activation Period: */\r
+        uint32_t tRRD               :2;             /**<Row activation to Row activation Delay */\r
+        uint32_t reserved5          :2;\r
+        uint32_t tRTP               :3;             /**<Read to Precharge Delay */\r
+        uint32_t reserved6          :1;\r
+    } field;\r
+} RegDTR1;                                          /**< DRAM Timing Register 1 */\r
+#pragma pack()\r
+\r
+#pragma pack(1)\r
+typedef union {\r
+    uint32_t    raw;\r
+    struct {\r
+        uint32_t tRRDR              :3;             /**< RD to RD from different ranks, same DIMM */\r
+        uint32_t reserved1          :5;\r
+        uint32_t tWWDR              :3;             /**< WR to WR from different ranks, same DIMM. */\r
+        uint32_t reserved3          :5;\r
+        uint32_t tRWDR              :4;             /**< bit [19:16] RD to WR from different ranks, same DIMM. */\r
+        uint32_t reserved5          :12;\r
+    } field;\r
+} RegDTR2;                                          /**< DRAM Timing Register 2 */\r
+#pragma pack()\r
+\r
+#pragma pack(1)\r
+typedef union {\r
+    uint32_t    raw;\r
+    struct {\r
+        uint32_t tWRDR              :3;             /**< WR to RD from different ranks, same DIMM. */\r
+        uint32_t reserved1          :1;\r
+        uint32_t tWRDD              :3;             /**< WR to RD from different DIMM. */\r
+        uint32_t reserved2          :1;\r
+        uint32_t tRWSR              :4;             /**< RD to WR Same Rank. */\r
+        uint32_t reserved3          :1;\r
+        uint32_t tWRSR              :4;             /**< WR to RD Same Rank. */\r
+        uint32_t reserved4          :5;\r
+        uint32_t tXP                :2;             /**< Time from CKE set on to any command. */\r
+        uint32_t PWD_DLY            :4;             /**< Extended Power-Down Delay. */\r
+        uint32_t EnDeRate           :1;\r
+        uint32_t DeRateOvr          :1;\r
+        uint32_t DeRateStat         :1;\r
+        uint32_t reserved5          :1;\r
+    } field;\r
+} RegDTR3;                                          /**< DRAM Timing Register 3 */\r
+#pragma pack()\r
+\r
+\r
+#pragma pack(1)\r
+typedef union {\r
+    uint32_t    raw;\r
+    struct {\r
+        uint32_t WRODTSTRT          :2;             /**< WR command to ODT assert delay */\r
+        uint32_t reserved1          :2;\r
+        uint32_t WRODTSTOP          :3;             /**< Write command to ODT de-assert delay. */\r
+        uint32_t reserved2          :1;\r
+        uint32_t RDODTSTRT          :3;             /**< Read command to ODT assert delay */\r
+        uint32_t reserved3          :1;\r
+        uint32_t RDODTSTOP          :3;             /**< Read command to ODT de-assert delay */\r
+        uint32_t ODTDIS             :1;             /**< ODT disable */\r
+        uint32_t TRGSTRDIS          :1;             /**< Write target rank is not stretched */\r
+        uint32_t RDODTDIS           :1;             /**< Disable Read ODT */\r
+        uint32_t WRBODTDIS          :1;             /**< Disable Write ODT */\r
+        uint32_t reserved5          :13;\r
+    } field;\r
+} RegDTR4;                                          /**< DRAM Timing Register 3 */\r
+#pragma pack()\r
+\r
+#pragma pack(1)\r
+typedef union {\r
+    uint32_t    raw;\r
+    struct {\r
+        uint32_t SREntryDelay       :8;             /**< Self-Refresh Entry Delay: */\r
+        uint32_t powerModeOpCode    :5;             /**< SPID Power Mode Opcode */\r
+        uint32_t reserved1          :3;\r
+        uint32_t PCLSTO             :3;             /**< Page Close Timeout Period */\r
+        uint32_t reserved2          :1;\r
+        uint32_t PCLSWKOK           :1;             /**< Wake Allowed For Page Close Timeout */\r
+        uint32_t PREAPWDEN          :1;             /**< Send Precharge All to rank before entering Power-Down mode. */\r
+        uint32_t reserved3          :1;\r
+        uint32_t DYNSREN            :1;             /**< Dynamic Self-Refresh */\r
+        uint32_t CLKGTDIS           :1;             /**< Clock Gating Disabled*/\r
+        uint32_t DISPWRDN           :1;             /**< Disable Power Down*/\r
+        uint32_t reserved4          :2;\r
+        uint32_t REUTCLKGTDIS       :1;\r
+        uint32_t ENPHYCLKGATE       :1;\r
+        uint32_t reserved5          :2;\r
+    } field;\r
+} RegDPMC0;                                           /**< DRAM Power Management Control Register 0 */\r
+#pragma pack()\r
+\r
+#pragma pack(1)\r
+typedef union {\r
+    uint32_t    raw;\r
+    struct {\r
+        uint32_t REFWMLO            :4;             /**< Refresh Opportunistic Watermark */\r
+        uint32_t REFWMHI            :4;             /**< Refresh High Watermark*/\r
+        uint32_t REFWMPNC           :4;             /**< Refresh Panic Watermark */\r
+        uint32_t tREFI              :3;             /**< bit [14:12] Refresh Period */\r
+        uint32_t reserved1          :1;\r
+        uint32_t REFCNTMAX          :2;             /**< Refresh Max tREFI Interval */\r
+        uint32_t reserved2          :2;\r
+        uint32_t REFSKEWDIS         :1;             /**< tREFI counters */\r
+        uint32_t REFDBTCLR          :1;\r
+        uint32_t reserved3          :2;\r
+        uint32_t CuRefRate          :3;\r
+        uint32_t DisRefBW           :1;\r
+        uint32_t reserved4          :4;\r
+    } field;\r
+} RegDRCF;                                           /**< DRAM Refresh Control Register*/\r
+#pragma pack()\r
+\r
+#pragma pack(1)\r
+typedef union {\r
+    uint32_t    raw;\r
+    struct {\r
+        uint32_t reserved1          :8;\r
+        uint32_t ZQCINT             :3;             /**< ZQ Calibration Short Interval: */\r
+        uint32_t reserved2          :1;\r
+        uint32_t SRXZQCL            :2;             /** < ZQ Calibration Length */\r
+        uint32_t ZQCalType          :1;\r
+        uint32_t ZQCalStart         :1;\r
+        uint32_t TQPollStart        :1;\r
+        uint32_t TQPollRS           :2;\r
+        uint32_t reserved3          :5;\r
+        uint32_t MRRData            :8;             /**< bit[31:24] */\r
+    } field;\r
+} RegDCAL;                                          /**< DRAM Calibration Control*/\r
+#pragma pack()\r
+\r
+#pragma pack(1)\r
+typedef union {\r
+    uint32_t    raw;\r
+    struct {\r
+        uint32_t OOOAGETRH          :5;             /**< Out-of-Order Aging Threshold */\r
+        uint32_t reserved1          :3;\r
+        uint32_t OOODIS             :1;             /**< Out-of-Order Disable */\r
+        uint32_t OOOST3DIS          :1;             /**< Out-of-Order Disabled when RequestBD_Status is 3. */\r
+        uint32_t reserved2          :2;\r
+        uint32_t NEWBYPDIS          :1;\r
+        uint32_t reserved3          :3;\r
+        uint32_t IPREQMAX           :3;             /** < Max In-Progress Requests stored in MC */\r
+        uint32_t reserved4          :13;\r
+    } field;\r
+} RegDSCH;                                           /**< DRAM Scheduler Control Register */\r
+#pragma pack()\r
+\r
+#pragma pack(1)\r
+typedef union {\r
+    uint32_t    raw;\r
+    struct {\r
+        uint32_t DRPLOCK            :1;             /**< DRP lock bit */\r
+        uint32_t reserved1          :7;\r
+        uint32_t REUTLOCK           :1;             /**< REUT lock bit */\r
+        uint32_t reserved2          :19;\r
+        uint32_t PMICTL             :1;             /**< PRI Control Select: 0-memory_manager, 1-hte */\r
+        uint32_t PMIDIS             :1;             /**< PMIDIS Should be set is using IOSF-SB RW */\r
+        uint32_t DIOIC              :1;             /**< DDRIO initialization is complete */\r
+        uint32_t IC                 :1;             /**< D-unit Initialization Complete */\r
+    } field;\r
+} RegDCO;                                           /**< DRAM Controller Operation Register*/\r
+#pragma pack()\r
+\r
+#pragma pack(1)\r
+typedef union {\r
+    uint32_t    raw;\r
+    struct {\r
+        uint32_t SBEEN       :1;             /**< Enable Single Bit Error Detection and Correction */\r
+        uint32_t DBEEN       :1;             /**< Enable Double Bit Error Detection */\r
+        uint32_t CBOEN       :3;             /**< Enable ECC Check Bits Override */\r
+        uint32_t SYNSEL      :2;             /**< ECC Syndrome Bits Select for Observation */\r
+    uint32_t CLRSBECNT   :1;             /**< Clear ECC Single Bit Error Count */\r
+        uint32_t CBOV        :8;             /**< ECC Check Bits Override Value */\r
+        uint32_t reserved1   :1;             /**<  */\r
+        uint32_t ENCBGEN     :1;             /**< Enable Generation of ECC Check Bits */\r
+        uint32_t ENCBGESWIZ  :1;             /**< Enable Same Chip ECC Byte Lane Swizzle */\r
+\r
+    } field;\r
+} RegDECCCTRL;                                      /**< DRAM ECC Control Register */\r
+#pragma pack()\r
+\r
+\r
+#pragma pack(1)\r
+typedef union {\r
+    uint32_t    raw;\r
+    struct {\r
+        uint32_t FUS_DUN_ECC_DIS              :1;\r
+    uint32_t FUS_DUN_MAX_SUPPORTED_MEMORY :3;\r
+    uint32_t FUS_DUN_MAX_DEVDEN           :2;\r
+    uint32_t RESERVED1                    :1;\r
+    uint32_t FUS_DUN_RANK2_DIS            :1;\r
+    uint32_t FUS_DUN_OOO_DIS              :1;\r
+    uint32_t FUS_DUN_MEMX8_DIS            :1;\r
+    uint32_t FUS_DUN_MEMX16_DIS           :1;\r
+    uint32_t RESERVED2                    :1;\r
+    uint32_t FUS_DUN_1N_DIS               :1;\r
+    uint32_t FUS_DUN_DQ_SCRAMBLER_DIS     :1;\r
+    uint32_t RESERVED3                    :1;\r
+    uint32_t FUS_DUN_32BIT_DRAM_IFC       :1;\r
+    } field;\r
+} RegDFUSESTAT;\r
+#pragma pack()\r
+\r
+//\r
+// END DUnit register definition\r
+//\r
+////\r
+\r
+\r
+\r
+////\r
+//\r
+// DRAM Initialization Structures used in JEDEC Message Bus Commands\r
+//\r
+\r
+#pragma pack(1)\r
+typedef union {\r
+        uint32_t      raw;\r
+    struct {\r
+        unsigned    command         :3;             /**< Command: 000-MRS,001-Refresh,010-Pre-charge,011-Activate,110-ZQ,111-NOP */\r
+        unsigned    bankAddress     :3;             /**< Bank Address (BA[2:0]) */\r
+        unsigned    BL              :2;             /**< Burst Length, CDV:1*/\r
+        unsigned    CL              :1;             /**< CL Reserved CDV:0 */\r
+        unsigned    RBT             :1;             /**< Read Burst Type */\r
+        unsigned    casLatency      :3;             /**< cas Latency */\r
+        unsigned    TM              :1;             /**< Test mode */\r
+        unsigned    dllReset        :1;             /**< DLL Reset */\r
+        unsigned    writeRecovery   :3;             /**< Write Recovery for Auto Pre-Charge: 001=2,010=3,011=4,100=5,101=6 */\r
+        unsigned    PPD             :1;             /**< DLL Control for Precharge Power-Down CDV:1 */\r
+        unsigned    reserved1       :3;\r
+        unsigned    rankSelect      :4;             /**< Rank Select */\r
+        unsigned    reserved2       :6;\r
+    } field;\r
+} DramInitDDR3MRS0;                                 /**< DDR3 Mode Register Set (MRS) Command */\r
+#pragma pack()\r
+\r
+#pragma pack(1)\r
+typedef union {\r
+        uint32_t      raw;\r
+    struct {\r
+        unsigned    command         :3;             /**< Command: 000-MRS,001-Refresh,010-Pre-charge,011-Activate,110-ZQ,111-NOP */\r
+        unsigned    bankAddress     :3;             /**< Bank Address (BA[2:0]) */\r
+        unsigned    dllEnabled      :1;             /**< CDV=0 */\r
+        unsigned    DIC0            :1;             /**< Output Driver Impedance Control */\r
+        unsigned    rttNom0         :1;             /**< RTT_nom[0] */\r
+        unsigned    MRC_AL          :2;             /**< Additive Latency = 0 */\r
+        unsigned    DIC1            :1;             /**< Reserved */\r
+        unsigned    rttNom1         :1;             /**< RTT_nom[1] */\r
+        unsigned    wlEnabled       :1;             /**< Write Leveling Enable */\r
+        unsigned    reserved1       :1;\r
+        unsigned    rttNom2         :1;             /** < RTT_nom[2] */\r
+        unsigned    reserved2       :1;\r
+        unsigned    TDQS            :1;             /**< TDQS Enable */\r
+        unsigned    Qoff            :1;             /**< Output Buffers Disabled */\r
+        unsigned    reserved3       :3;\r
+        unsigned    rankSelect      :4;             /**< Rank Select */\r
+        unsigned    reserved4       :6;\r
+    } field;\r
+} DramInitDDR3EMR1;                                 /**< DDR3 Extended Mode Register 1 Set (EMRS1) Command */\r
+#pragma pack()\r
+\r
+#pragma pack(1)\r
+typedef union {\r
+        uint32_t      raw;\r
+    struct {\r
+        uint32_t    command         :3;             /**< Command: 000-MRS,001-Refresh,010-Pre-charge,011-Activate,110-ZQ,111-NOP */\r
+        uint32_t    bankAddress     :3;             /**< Bank Address (BA[2:0]) */\r
+        uint32_t    PASR            :3;             /**< Partial Array Self-Refresh */\r
+        uint32_t    CWL             :3;             /**< CAS Write Latency */\r
+        uint32_t    ASR             :1;             /**< Auto Self-Refresh */\r
+        uint32_t    SRT             :1;             /**< SR Temperature Range = 0*/\r
+        uint32_t    reserved1       :1;\r
+        uint32_t    rtt_WR          :2;             /**< Rtt_WR */\r
+        uint32_t    reserved2       :5;\r
+        uint32_t    rankSelect      :4;             /**< Rank Select */\r
+        uint32_t    reserved3       :6;\r
+    } field;\r
+} DramInitDDR3EMR2;                                 /**< DDR3 Extended Mode Register 2 Set (EMRS2) Command */\r
+#pragma pack()\r
+\r
+#pragma pack(1)\r
+typedef union {\r
+        uint32_t      raw;\r
+    struct {\r
+        uint32_t    command         :3;             /**< Command: 000-MRS,001-Refresh,010-Pre-charge,011-Activate,110-ZQ,111-NOP */\r
+        uint32_t    bankAddress     :3;             /**< Bank Address (BA[2:0]) */\r
+        uint32_t    MPR_Location    :2;             /**< MPR Location */\r
+        uint32_t    MPR             :1;             /**< MPR: Multi Purpose Register */\r
+        uint32_t    reserved1       :13;\r
+        uint32_t    rankSelect      :4;             /**< Rank Select */\r
+        uint32_t    reserved2       :6;\r
+    } field;\r
+} DramInitDDR3EMR3;                                 /**< DDR3 Extended Mode Register 2 Set (EMRS2) Command */\r
+#pragma pack()\r
+\r
+#pragma pack(1)\r
+typedef union {\r
+    uint32_t    raw;\r
+    struct {\r
+        uint32_t    command         :3;             /**< Command: 000-MRS,001-Refresh,010-Pre-charge,011-Activate,110 - ZQ Calibration,111-NOP */\r
+        uint32_t    bankAddress     :3;             /**< Bank Address (BA[2:0]) */\r
+        uint32_t    multAddress     :16;            /**< Multiplexed Address (MA[14:0]) */\r
+        uint32_t    rankSelect      :2;             /**< Rank Select */\r
+        uint32_t    reserved3       :8;\r
+    } field;\r
+} DramInitMisc;                                     /**< Miscellaneous DDRx Initialization Command */\r
+#pragma pack()\r
+\r
+//\r
+// Construct DRAM init command using DramInitXxxx pattern\r
+//\r
+#define DCMD_MRS1(rnk,dat) (0 | ((rnk)<<22) | (1<<3) | ((dat)<<6))\r
+#define DCMD_REF(rnk)      (1 | ((rnk)<<22))\r
+#define DCMD_PRE(rnk)      (2 | ((rnk)<<22))\r
+#define DCMD_PREA(rnk)     (2 | ((rnk)<<22) | (BIT10<<6))\r
+#define DCMD_ACT(rnk,row)  (3 | ((rnk)<<22) | ((row)<<6))\r
+#define DCMD_WR(rnk,col)   (4 | ((rnk)<<22) | ((col)<<6))\r
+#define DCMD_RD(rnk,col)   (5 | ((rnk)<<22) | ((col)<<6))\r
+#define DCMD_ZQCS(rnk)     (6 | ((rnk)<<22))\r
+#define DCMD_ZQCL(rnk)     (6 | ((rnk)<<22) | (BIT10<<6))\r
+#define DCMD_NOP(rnk)      (7 | ((rnk)<<22))\r
+\r
+\r
+\r
+\r
+#define DDR3_EMRS1_DIC_40       (0)\r
+#define DDR3_EMRS1_DIC_34       (1)\r
+\r
+#define DDR3_EMRS2_RTTWR_60     (BIT9)\r
+#define DDR3_EMRS2_RTTWR_120    (BIT10)\r
+\r
+#define DDR3_EMRS1_RTTNOM_0     (0)\r
+#define DDR3_EMRS1_RTTNOM_60    (BIT2)\r
+#define DDR3_EMRS1_RTTNOM_120   (BIT6)\r
+#define DDR3_EMRS1_RTTNOM_40    (BIT6|BIT2)\r
+#define DDR3_EMRS1_RTTNOM_20    (BIT9)\r
+#define DDR3_EMRS1_RTTNOM_30    (BIT9|BIT2)\r
+\r
+\r
+//\r
+// END DRAM Init...\r
+//\r
+////\r
+\r
+\r
+// HOST_BRIDGE registers:\r
+#define HMBOUND             0x0020  //ok\r
+\r
+// MEMORY_MANAGER registers:\r
+#define BCTRL               0x0004\r
+#define BWFLUSH             0x0008\r
+#define BDEBUG1             0x00C4\r
+\r
+////\r
+//\r
+// BEGIN DDRIO registers\r
+//\r
+\r
+// DDR IOs & COMPs:\r
+#define DDRIODQ_BL_OFFSET   0x0800\r
+#define DDRIODQ_CH_OFFSET   ((NUM_BYTE_LANES/2) * DDRIODQ_BL_OFFSET)\r
+#define DDRIOCCC_CH_OFFSET  0x0800\r
+#define DDRCOMP_CH_OFFSET   0x0100\r
+\r
+// CH0-BL01-DQ\r
+#define DQOBSCKEBBCTL       0x0000\r
+#define DQDLLTXCTL          0x0004\r
+#define DQDLLRXCTL          0x0008\r
+#define DQMDLLCTL           0x000C\r
+#define B0RXIOBUFCTL        0x0010\r
+#define B0VREFCTL           0x0014\r
+#define B0RXOFFSET1         0x0018\r
+#define B0RXOFFSET0         0x001C\r
+#define B1RXIOBUFCTL        0x0020\r
+#define B1VREFCTL           0x0024\r
+#define B1RXOFFSET1         0x0028\r
+#define B1RXOFFSET0         0x002C\r
+#define DQDFTCTL            0x0030\r
+#define DQTRAINSTS          0x0034\r
+#define B1DLLPICODER0       0x0038\r
+#define B0DLLPICODER0       0x003C\r
+#define B1DLLPICODER1       0x0040\r
+#define B0DLLPICODER1       0x0044\r
+#define B1DLLPICODER2       0x0048\r
+#define B0DLLPICODER2       0x004C\r
+#define B1DLLPICODER3       0x0050\r
+#define B0DLLPICODER3       0x0054\r
+#define B1RXDQSPICODE       0x0058\r
+#define B0RXDQSPICODE       0x005C\r
+#define B1RXDQPICODER32     0x0060\r
+#define B1RXDQPICODER10     0x0064\r
+#define B0RXDQPICODER32     0x0068\r
+#define B0RXDQPICODER10     0x006C\r
+#define B01PTRCTL0          0x0070\r
+#define B01PTRCTL1          0x0074\r
+#define B01DBCTL0           0x0078\r
+#define B01DBCTL1           0x007C\r
+#define B0LATCTL0           0x0080\r
+#define B1LATCTL0           0x0084\r
+#define B01LATCTL1          0x0088\r
+#define B0ONDURCTL          0x008C\r
+#define B1ONDURCTL          0x0090\r
+#define B0OVRCTL            0x0094\r
+#define B1OVRCTL            0x0098\r
+#define DQCTL               0x009C\r
+#define B0RK2RKCHGPTRCTRL   0x00A0\r
+#define B1RK2RKCHGPTRCTRL   0x00A4\r
+#define DQRK2RKCTL          0x00A8\r
+#define DQRK2RKPTRCTL       0x00AC\r
+#define B0RK2RKLAT          0x00B0\r
+#define B1RK2RKLAT          0x00B4\r
+#define DQCLKALIGNREG0      0x00B8\r
+#define DQCLKALIGNREG1      0x00BC\r
+#define DQCLKALIGNREG2      0x00C0\r
+#define DQCLKALIGNSTS0      0x00C4\r
+#define DQCLKALIGNSTS1      0x00C8\r
+#define DQCLKGATE           0x00CC\r
+#define B0COMPSLV1          0x00D0\r
+#define B1COMPSLV1          0x00D4\r
+#define B0COMPSLV2          0x00D8\r
+#define B1COMPSLV2          0x00DC\r
+#define B0COMPSLV3          0x00E0\r
+#define B1COMPSLV3          0x00E4\r
+#define DQVISALANECR0TOP    0x00E8\r
+#define DQVISALANECR1TOP    0x00EC\r
+#define DQVISACONTROLCRTOP  0x00F0\r
+#define DQVISALANECR0BL     0x00F4\r
+#define DQVISALANECR1BL     0x00F8\r
+#define DQVISACONTROLCRBL   0x00FC\r
+#define DQTIMINGCTRL        0x010C\r
+// CH0-ECC\r
+#define ECCDLLTXCTL         0x2004\r
+#define ECCDLLRXCTL         0x2008\r
+#define ECCMDLLCTL          0x200C\r
+#define ECCB1DLLPICODER0    0x2038\r
+#define ECCB1DLLPICODER1    0x2040\r
+#define ECCB1DLLPICODER2    0x2048\r
+#define ECCB1DLLPICODER3    0x2050\r
+#define ECCB01DBCTL0        0x2078\r
+#define ECCB01DBCTL1        0x207C\r
+#define ECCCLKALIGNREG0     0x20B8\r
+#define ECCCLKALIGNREG1     0x20BC\r
+#define ECCCLKALIGNREG2     0x20C0\r
+// CH0-CMD\r
+#define CMDOBSCKEBBCTL      0x4800\r
+#define CMDDLLTXCTL         0x4808\r
+#define CMDDLLRXCTL         0x480C\r
+#define CMDMDLLCTL          0x4810\r
+#define CMDRCOMPODT         0x4814\r
+#define CMDDLLPICODER0      0x4820\r
+#define CMDDLLPICODER1      0x4824\r
+#define CMDCFGREG0          0x4840\r
+#define CMDPTRREG           0x4844\r
+#define CMDCLKALIGNREG0     0x4850\r
+#define CMDCLKALIGNREG1     0x4854\r
+#define CMDCLKALIGNREG2     0x4858\r
+#define CMDPMCONFIG0        0x485C\r
+#define CMDPMDLYREG0        0x4860\r
+#define CMDPMDLYREG1        0x4864\r
+#define CMDPMDLYREG2        0x4868\r
+#define CMDPMDLYREG3        0x486C\r
+#define CMDPMDLYREG4        0x4870\r
+#define CMDCLKALIGNSTS0     0x4874\r
+#define CMDCLKALIGNSTS1     0x4878\r
+#define CMDPMSTS0           0x487C\r
+#define CMDPMSTS1           0x4880\r
+#define CMDCOMPSLV          0x4884\r
+#define CMDBONUS0           0x488C\r
+#define CMDBONUS1           0x4890\r
+#define CMDVISALANECR0      0x4894\r
+#define CMDVISALANECR1      0x4898\r
+#define CMDVISACONTROLCR    0x489C\r
+#define CMDCLKGATE          0x48A0\r
+#define CMDTIMINGCTRL       0x48A4\r
+// CH0-CLK-CTL\r
+#define CCOBSCKEBBCTL       0x5800\r
+#define CCRCOMPIO           0x5804\r
+#define CCDLLTXCTL          0x5808\r
+#define CCDLLRXCTL          0x580C\r
+#define CCMDLLCTL           0x5810\r
+#define CCRCOMPODT          0x5814\r
+#define CCDLLPICODER0       0x5820\r
+#define CCDLLPICODER1       0x5824\r
+#define CCDDR3RESETCTL      0x5830\r
+#define CCCFGREG0           0x5838\r
+#define CCCFGREG1           0x5840\r
+#define CCPTRREG            0x5844\r
+#define CCCLKALIGNREG0      0x5850\r
+#define CCCLKALIGNREG1      0x5854\r
+#define CCCLKALIGNREG2      0x5858\r
+#define CCPMCONFIG0         0x585C\r
+#define CCPMDLYREG0         0x5860\r
+#define CCPMDLYREG1         0x5864\r
+#define CCPMDLYREG2         0x5868\r
+#define CCPMDLYREG3         0x586C\r
+#define CCPMDLYREG4         0x5870\r
+#define CCCLKALIGNSTS0      0x5874\r
+#define CCCLKALIGNSTS1      0x5878\r
+#define CCPMSTS0            0x587C\r
+#define CCPMSTS1            0x5880\r
+#define CCCOMPSLV1          0x5884\r
+#define CCCOMPSLV2          0x5888\r
+#define CCCOMPSLV3          0x588C\r
+#define CCBONUS0            0x5894\r
+#define CCBONUS1            0x5898\r
+#define CCVISALANECR0       0x589C\r
+#define CCVISALANECR1       0x58A0\r
+#define CCVISACONTROLCR     0x58A4\r
+#define CCCLKGATE           0x58A8\r
+#define CCTIMINGCTL         0x58AC\r
+// COMP\r
+#define CMPCTRL             0x6800\r
+#define SOFTRSTCNTL         0x6804\r
+#define MSCNTR              0x6808\r
+#define NMSCNTRL            0x680C\r
+#define LATCH1CTL           0x6814\r
+#define COMPVISALANECR0     0x681C\r
+#define COMPVISALANECR1     0x6820\r
+#define COMPVISACONTROLCR   0x6824\r
+#define COMPBONUS0          0x6830\r
+#define TCOCNTCTRL          0x683C\r
+#define DQANAODTPUCTL       0x6840\r
+#define DQANAODTPDCTL       0x6844\r
+#define DQANADRVPUCTL       0x6848\r
+#define DQANADRVPDCTL       0x684C\r
+#define DQANADLYPUCTL       0x6850\r
+#define DQANADLYPDCTL       0x6854\r
+#define DQANATCOPUCTL       0x6858\r
+#define DQANATCOPDCTL       0x685C\r
+#define CMDANADRVPUCTL      0x6868\r
+#define CMDANADRVPDCTL      0x686C\r
+#define CMDANADLYPUCTL      0x6870\r
+#define CMDANADLYPDCTL      0x6874\r
+#define CLKANAODTPUCTL      0x6880\r
+#define CLKANAODTPDCTL      0x6884\r
+#define CLKANADRVPUCTL      0x6888\r
+#define CLKANADRVPDCTL      0x688C\r
+#define CLKANADLYPUCTL      0x6890\r
+#define CLKANADLYPDCTL      0x6894\r
+#define CLKANATCOPUCTL      0x6898\r
+#define CLKANATCOPDCTL      0x689C\r
+#define DQSANAODTPUCTL      0x68A0\r
+#define DQSANAODTPDCTL      0x68A4\r
+#define DQSANADRVPUCTL      0x68A8\r
+#define DQSANADRVPDCTL      0x68AC\r
+#define DQSANADLYPUCTL      0x68B0\r
+#define DQSANADLYPDCTL      0x68B4\r
+#define DQSANATCOPUCTL      0x68B8\r
+#define DQSANATCOPDCTL      0x68BC\r
+#define CTLANADRVPUCTL      0x68C8\r
+#define CTLANADRVPDCTL      0x68CC\r
+#define CTLANADLYPUCTL      0x68D0\r
+#define CTLANADLYPDCTL      0x68D4\r
+#define CHNLBUFSTATIC       0x68F0\r
+#define COMPOBSCNTRL        0x68F4\r
+#define COMPBUFFDBG0        0x68F8\r
+#define COMPBUFFDBG1        0x68FC\r
+#define CFGMISCCH0          0x6900\r
+#define COMPEN0CH0          0x6904\r
+#define COMPEN1CH0          0x6908\r
+#define COMPEN2CH0          0x690C\r
+#define STATLEGEN0CH0       0x6910\r
+#define STATLEGEN1CH0       0x6914\r
+#define DQVREFCH0           0x6918\r
+#define CMDVREFCH0          0x691C\r
+#define CLKVREFCH0          0x6920\r
+#define DQSVREFCH0          0x6924\r
+#define CTLVREFCH0          0x6928\r
+#define TCOVREFCH0          0x692C\r
+#define DLYSELCH0           0x6930\r
+#define TCODRAMBUFODTCH0    0x6934\r
+#define CCBUFODTCH0         0x6938\r
+#define RXOFFSETCH0         0x693C\r
+#define DQODTPUCTLCH0       0x6940\r
+#define DQODTPDCTLCH0       0x6944\r
+#define DQDRVPUCTLCH0       0x6948\r
+#define DQDRVPDCTLCH0       0x694C\r
+#define DQDLYPUCTLCH0       0x6950\r
+#define DQDLYPDCTLCH0       0x6954\r
+#define DQTCOPUCTLCH0       0x6958\r
+#define DQTCOPDCTLCH0       0x695C\r
+#define CMDDRVPUCTLCH0      0x6968\r
+#define CMDDRVPDCTLCH0      0x696C\r
+#define CMDDLYPUCTLCH0      0x6970\r
+#define CMDDLYPDCTLCH0      0x6974\r
+#define CLKODTPUCTLCH0      0x6980\r
+#define CLKODTPDCTLCH0      0x6984\r
+#define CLKDRVPUCTLCH0      0x6988\r
+#define CLKDRVPDCTLCH0      0x698C\r
+#define CLKDLYPUCTLCH0      0x6990\r
+#define CLKDLYPDCTLCH0      0x6994\r
+#define CLKTCOPUCTLCH0      0x6998\r
+#define CLKTCOPDCTLCH0      0x699C\r
+#define DQSODTPUCTLCH0      0x69A0\r
+#define DQSODTPDCTLCH0      0x69A4\r
+#define DQSDRVPUCTLCH0      0x69A8\r
+#define DQSDRVPDCTLCH0      0x69AC\r
+#define DQSDLYPUCTLCH0      0x69B0\r
+#define DQSDLYPDCTLCH0      0x69B4\r
+#define DQSTCOPUCTLCH0      0x69B8\r
+#define DQSTCOPDCTLCH0      0x69BC\r
+#define CTLDRVPUCTLCH0      0x69C8\r
+#define CTLDRVPDCTLCH0      0x69CC\r
+#define CTLDLYPUCTLCH0      0x69D0\r
+#define CTLDLYPDCTLCH0      0x69D4\r
+#define FNLUPDTCTLCH0       0x69F0\r
+// PLL\r
+#define MPLLCTRL0           0x7800\r
+#define MPLLCTRL1           0x7808\r
+#define MPLLCSR0            0x7810\r
+#define MPLLCSR1            0x7814\r
+#define MPLLCSR2            0x7820\r
+#define MPLLDFT             0x7828\r
+#define MPLLMON0CTL         0x7830\r
+#define MPLLMON1CTL         0x7838\r
+#define MPLLMON2CTL         0x783C\r
+#define SFRTRIM             0x7850\r
+#define MPLLDFTOUT0         0x7858\r
+#define MPLLDFTOUT1         0x785C\r
+#define MASTERRSTN          0x7880\r
+#define PLLLOCKDEL          0x7884\r
+#define SFRDEL              0x7888\r
+#define CRUVISALANECR0      0x78F0\r
+#define CRUVISALANECR1      0x78F4\r
+#define CRUVISACONTROLCR    0x78F8\r
+#define IOSFVISALANECR0     0x78FC\r
+#define IOSFVISALANECR1     0x7900\r
+#define IOSFVISACONTROLCR   0x7904\r
+\r
+//\r
+// END DDRIO registers\r
+//\r
+////\r
+\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/general_definitions.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/general_definitions.h
new file mode 100644 (file)
index 0000000..c5f92b3
--- /dev/null
@@ -0,0 +1,90 @@
+/************************************************************************\r
+ *\r
+ * Copyright (c) 2013-2015 Intel Corporation.\r
+ *\r
+* This program and the accompanying materials\r
+* are licensed and made available under the terms and conditions of the BSD License\r
+* which accompanies this distribution.  The full text of the license may be found at\r
+* http://opensource.org/licenses/bsd-license.php\r
+*\r
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ *\r
+ ************************************************************************/\r
+#ifndef __GENERAL_DEFINITIONS_H\r
+#define __GENERAL_DEFINITIONS_H\r
+\r
+#undef BIT0\r
+#undef BIT1\r
+#undef BIT2\r
+#undef BIT3\r
+#undef BIT4\r
+#undef BIT5\r
+#undef BIT6\r
+#undef BIT7\r
+#undef BIT8\r
+#undef BIT9\r
+#undef BIT10\r
+#undef BIT11\r
+#undef BIT12\r
+#undef BIT13\r
+#undef BIT14\r
+#undef BIT15\r
+#undef BIT16\r
+#undef BIT17\r
+#undef BIT18\r
+#undef BIT19\r
+#undef BIT20\r
+#undef BIT21\r
+#undef BIT22\r
+#undef BIT23\r
+#undef BIT24\r
+#undef BIT25\r
+#undef BIT26\r
+#undef BIT27\r
+#undef BIT28\r
+#undef BIT29\r
+#undef BIT30\r
+#undef BIT31\r
+\r
+\r
+\r
+// defines\r
+#define BIT0  0x00000001U\r
+#define BIT1  0x00000002U\r
+#define BIT2  0x00000004U\r
+#define BIT3  0x00000008U\r
+#define BIT4  0x00000010U\r
+#define BIT5  0x00000020U\r
+#define BIT6  0x00000040U\r
+#define BIT7  0x00000080U\r
+#define BIT8  0x00000100U\r
+#define BIT9  0x00000200U\r
+#define BIT10 0x00000400U\r
+#define BIT11 0x00000800U\r
+#define BIT12 0x00001000U\r
+#define BIT13 0x00002000U\r
+#define BIT14 0x00004000U\r
+#define BIT15 0x00008000U\r
+#define BIT16 0x00010000U\r
+#define BIT17 0x00020000U\r
+#define BIT18 0x00040000U\r
+#define BIT19 0x00080000U\r
+#define BIT20 0x00100000U\r
+#define BIT21 0x00200000U\r
+#define BIT22 0x00400000U\r
+#define BIT23 0x00800000U\r
+#define BIT24 0x01000000U\r
+#define BIT25 0x02000000U\r
+#define BIT26 0x04000000U\r
+#define BIT27 0x08000000U\r
+#define BIT28 0x10000000U\r
+#define BIT29 0x20000000U\r
+#define BIT30 0x40000000U\r
+#define BIT31 0x80000000U\r
+\r
+\r
+#define true  0x01\r
+#define false 0x00\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/hte.c b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/hte.c
new file mode 100644 (file)
index 0000000..92ec4ba
--- /dev/null
@@ -0,0 +1,542 @@
+/** @file\r
+HTE handling routines for MRC use.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "mrc.h"\r
+#include "memory_options.h"\r
+#include "io.h"\r
+\r
+#include "hte.h"\r
+\r
+\r
+#ifdef SIM\r
+VOID delay_n(UINT32 nanoseconds);\r
+#define MySimStall(a)   delay_n(a/1000)\r
+#endif\r
+\r
+STATIC VOID EnableAllHteErrors(\r
+    UINT8 Mask)\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ This function enables to HTE to detect all possible errors for\r
+ the given training parameters (per-bit or full byte lane).\r
+\r
+ Returns:\r
+\r
+ None\r
+\r
+ --*/\r
+{\r
+  isbW32m(HTE, 0x000200A2, 0xFFFFFFFF);\r
+  isbW32m(HTE, 0x000200A3, 0x000000FF);\r
+  isbW32m(HTE, 0x000200A4, 0x00000000);\r
+}\r
+\r
+STATIC UINT32 CheckHteErrors(\r
+    VOID)\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ This function goes and reads the HTE register in order to find any error\r
+\r
+ Returns:\r
+\r
+ The errors detected in the HTE status register\r
+\r
+ --*/\r
+{\r
+  return isbR32m(HTE, 0x000200A7);\r
+}\r
+\r
+STATIC VOID WaitForHteComplete(\r
+    VOID)\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ This function waits until HTE finishes\r
+\r
+ Returns:\r
+\r
+ None\r
+\r
+ --*/\r
+{\r
+  UINT32 Tmp;\r
+\r
+  ENTERFN();\r
+\r
+  //\r
+  // Is the test done?\r
+  //\r
+  do\r
+  {\r
+#ifdef SIM\r
+    MySimStall (35000); // 35 ns delay\r
+#endif\r
+  } while (0 != (isbR32m(HTE, 0x00020012) & BIT30));\r
+\r
+  Tmp = isbR32m(HTE, 0x00020011);\r
+  Tmp = Tmp | BIT9;\r
+  Tmp = Tmp & ~(BIT13 | BIT12);\r
+  isbW32m(HTE, 0x00020011, Tmp);\r
+\r
+  LEAVEFN();\r
+}\r
+\r
+STATIC VOID ClearHteErrorRegisters(\r
+    VOID)\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ Clears registers related with errors in the HTE.\r
+\r
+ Returns:\r
+\r
+ None\r
+\r
+ --*/\r
+{\r
+  UINT32 Tmp;\r
+\r
+  //\r
+  // Clear all HTE errors and enable error checking\r
+  // for burst and chunk.\r
+  //\r
+  Tmp = isbR32m(HTE, 0x000200A1);\r
+  Tmp |= BIT8;\r
+  isbW32m(HTE, 0x000200A1, Tmp);\r
+}\r
+\r
+UINT32 HteMemInit(\r
+    MRC_PARAMS *CurrentMrcData,\r
+    UINT8 MemInitFlag,\r
+    UINT8 HaltHteEngineOnError)\r
+\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ Uses HW HTE engine to initialize or test all memory attached to a given DUNIT.\r
+ If MemInitFlag is 1, this routine writes 0s to all memory locations to initialize\r
+ ECC.\r
+ If MemInitFlag is 0, this routine will send an 5AA55AA5 pattern to all memory\r
+ locations on the RankMask and then read it back.  Then it sends an A55AA55A\r
+ pattern to all memory locations on the RankMask and reads it back.\r
+\r
+ Arguments:\r
+\r
+ CurrentMrcData: Host struture for all MRC global data.\r
+ MemInitFlag: 0 for memtest, 1 for meminit.\r
+ HaltHteEngineOnError:  Halt the HTE engine on first error observed, or keep\r
+ running to see how many errors are found.\r
+\r
+ Returns:\r
+ Errors register showing HTE failures.\r
+ Also prints out which rank failed the HTE test if failure occurs.\r
+ For rank detection to work, the address map must be left in its default\r
+ state.  If MRC changes the address map, this function must be modified\r
+ to change it back to default at the beginning, then restore it at the end.\r
+\r
+ --*/\r
+{\r
+  UINT32 Offset;\r
+  UINT8 TestNum;\r
+  UINT8 i;\r
+\r
+  //\r
+  // Clear out the error registers at the start of each memory\r
+  // init or memory test run.\r
+  //\r
+  ClearHteErrorRegisters();\r
+\r
+  isbW32m(HTE, 0x00020062, 0x00000015);\r
+\r
+  for (Offset = 0x80; Offset <= 0x8F; Offset++)\r
+  {\r
+    isbW32m(HTE, Offset, ((Offset & 1) ? 0xA55A : 0x5AA5));\r
+  }\r
+\r
+  isbW32m(HTE, 0x00020021, 0x00000000);\r
+#ifdef QUICKSIM\r
+  // Just do 4 cache lines for simulation memtest to save time.\r
+  isbW32m(HTE, 0x00020022, 4-1);\r
+#else\r
+  isbW32m(HTE, 0x00020022, (CurrentMrcData->mem_size >> 6) - 1);\r
+#endif\r
+\r
+  isbW32m(HTE, 0x00020063, 0xAAAAAAAA);\r
+  isbW32m(HTE, 0x00020064, 0xCCCCCCCC);\r
+  isbW32m(HTE, 0x00020065, 0xF0F0F0F0);\r
+  isbW32m(HTE, 0x00020066, 0x03000000);\r
+\r
+  switch (MemInitFlag)\r
+  {\r
+  case MrcMemInit:\r
+    TestNum = 1; // Only 1 write pass through memory is needed to initialize ECC.\r
+    break;\r
+  case MrcMemTest:\r
+    TestNum = 4; // Write/read then write/read with inverted pattern.\r
+    break;\r
+  default:\r
+    DPF(D_INFO, "Unknown parameter for MemInitFlag: %d\n", MemInitFlag);\r
+    return 0xFFFFFFFF;\r
+    break;\r
+  }\r
+\r
+  DPF(D_INFO, "HteMemInit");\r
+  for (i = 0; i < TestNum; i++)\r
+  {\r
+    DPF(D_INFO, ".");\r
+\r
+    if (i == 0)\r
+    {\r
+      isbW32m(HTE, 0x00020061, 0x00000000);\r
+      isbW32m(HTE, 0x00020020, 0x00110010);\r
+    }\r
+    else if (i == 1)\r
+    {\r
+      isbW32m(HTE, 0x00020061, 0x00000000);\r
+      isbW32m(HTE, 0x00020020, 0x00010010);\r
+    }\r
+    else if (i == 2)\r
+    {\r
+      isbW32m(HTE, 0x00020061, 0x00010100);\r
+      isbW32m(HTE, 0x00020020, 0x00110010);\r
+    }\r
+    else\r
+    {\r
+      isbW32m(HTE, 0x00020061, 0x00010100);\r
+      isbW32m(HTE, 0x00020020, 0x00010010);\r
+    }\r
+\r
+    isbW32m(HTE, 0x00020011, 0x00111000);\r
+    isbW32m(HTE, 0x00020011, 0x00111100);\r
+\r
+    WaitForHteComplete();\r
+\r
+    //\r
+    // If this is a READ pass, check for errors at the end.\r
+    //\r
+    if ((i % 2) == 1)\r
+    {\r
+      //\r
+      // Return immediately if  error.\r
+      //\r
+      if (CheckHteErrors())\r
+      {\r
+        break;\r
+      }\r
+    }\r
+  }\r
+\r
+  DPF(D_INFO, "done\n", i);\r
+  return CheckHteErrors();\r
+}\r
+\r
+STATIC UINT16 BasicDataCompareHte(\r
+    MRC_PARAMS *CurrentMrcData,\r
+    UINT32 Address,\r
+    UINT8 FirstRun,\r
+    UINT8 Mode)\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ Execute basic single cache line memory write/read/verify test using simple constant\r
+ pattern (different for READ_RAIN and WRITE_TRAIN modes.\r
+ See BasicWriteReadHTE which is external visible wrapper.\r
+\r
+ Arguments:\r
+\r
+ CurrentMrcData: Host struture for all MRC global data.\r
+ Address: memory adress being tested (must hit specific channel/rank)\r
+ FirstRun: If set then hte registers are configured, otherwise\r
+ it is assumed configuration is done and just re-run the test.\r
+ Mode: READ_TRAIN or WRITE_TRAIN (the difference is in the pattern)\r
+\r
+ Returns:\r
+ Returns byte lane failure on each bit (for Quark only bit0 and bit1)\r
+\r
+ --*/\r
+{\r
+  UINT32 Pattern;\r
+  UINT32 Offset;\r
+\r
+  if (FirstRun)\r
+  {\r
+    isbW32m(HTE, 0x00020020, 0x01B10021);\r
+    isbW32m(HTE, 0x00020021, 0x06000000);\r
+    isbW32m(HTE, 0x00020022, Address >> 6);\r
+    isbW32m(HTE, 0x00020062, 0x00800015);\r
+    isbW32m(HTE, 0x00020063, 0xAAAAAAAA);\r
+    isbW32m(HTE, 0x00020064, 0xCCCCCCCC);\r
+    isbW32m(HTE, 0x00020065, 0xF0F0F0F0);\r
+    isbW32m(HTE, 0x00020061, 0x00030008);\r
+\r
+    if (Mode == WRITE_TRAIN)\r
+    {\r
+      Pattern = 0xC33C0000;\r
+    }\r
+    else // READ_TRAIN\r
+    {\r
+      Pattern = 0xAA5555AA;\r
+    }\r
+\r
+    for (Offset = 0x80; Offset <= 0x8F; Offset++)\r
+    {\r
+      isbW32m(HTE, Offset, Pattern);\r
+    }\r
+  }\r
+\r
+  isbW32m(HTE, 0x000200A1, 0xFFFF1000);\r
+\r
+  isbW32m(HTE, 0x00020011, 0x00011000);\r
+  isbW32m(HTE, 0x00020011, 0x00011100);\r
+\r
+  WaitForHteComplete();\r
+\r
+  //\r
+  // Return bits 15:8 of HTE_CH0_ERR_XSTAT to check for any bytelane errors.\r
+  //\r
+  return ((CheckHteErrors() >> 8) & 0xFF);\r
+}\r
+\r
+STATIC UINT16 ReadWriteDataCompareHte(\r
+    MRC_PARAMS *CurrentMrcData,\r
+    UINT32 Address,\r
+    UINT8 LoopCount,\r
+    UINT32 LfsrSeedVictim,\r
+    UINT32 LfsrSeedAggressor,\r
+    UINT8 VictimBit,\r
+    UINT8 FirstRun)\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ Examines single cache line memory with write/read/verify test using\r
+ multiple data patterns (victim-aggressor algorithm).\r
+ See WriteStressBitLanesHTE which is external visible wrapper.\r
+\r
+ Arguments:\r
+\r
+ CurrentMrcData: host struture for all MRC global data.\r
+ Address: memory adress being tested (must hit specific channel/rank)\r
+ LoopCount: number of test iterations\r
+ LfsrSeedXxx: victim aggressor data pattern seed\r
+ VictimBit: should be 0 as auto rotate feature is in use.\r
+ FirstRun: If set then hte registers are configured, otherwise\r
+ it is assumed configuration is done and just re-run the test.\r
+\r
+ Returns:\r
+ Returns byte lane failure on each bit (for Quark only bit0 and bit1)\r
+\r
+ --*/\r
+{\r
+  UINT32 Offset;\r
+  UINT32 Tmp;\r
+\r
+  if (FirstRun)\r
+  {\r
+    isbW32m(HTE, 0x00020020, 0x00910024);\r
+    isbW32m(HTE, 0x00020023, 0x00810024);\r
+    isbW32m(HTE, 0x00020021, 0x06070000);\r
+    isbW32m(HTE, 0x00020024, 0x06070000);\r
+    isbW32m(HTE, 0x00020022, Address >> 6);\r
+    isbW32m(HTE, 0x00020025, Address >> 6);\r
+    isbW32m(HTE, 0x00020062, 0x0000002A);\r
+    isbW32m(HTE, 0x00020063, LfsrSeedVictim);\r
+    isbW32m(HTE, 0x00020064, LfsrSeedAggressor);\r
+    isbW32m(HTE, 0x00020065, LfsrSeedVictim);\r
+\r
+    //\r
+    // Write the pattern buffers to select the victim bit. Start with bit0.\r
+    //\r
+    for (Offset = 0x80; Offset <= 0x8F; Offset++)\r
+    {\r
+      if ((Offset % 8) == VictimBit)\r
+      {\r
+        isbW32m(HTE, Offset, 0x55555555);\r
+      }\r
+      else\r
+      {\r
+        isbW32m(HTE, Offset, 0xCCCCCCCC);\r
+      }\r
+    }\r
+\r
+    isbW32m(HTE, 0x00020061, 0x00000000);\r
+    isbW32m(HTE, 0x00020066, 0x03440000);\r
+    isbW32m(HTE, 0x000200A1, 0xFFFF1000);\r
+  }\r
+\r
+  Tmp = 0x10001000 | (LoopCount << 16);\r
+  isbW32m(HTE, 0x00020011, Tmp);\r
+  isbW32m(HTE, 0x00020011, Tmp | BIT8);\r
+\r
+  WaitForHteComplete();\r
+\r
+  return (CheckHteErrors() >> 8) & 0xFF;\r
+}\r
+\r
+UINT16 BasicWriteReadHTE(\r
+    MRC_PARAMS *CurrentMrcData,\r
+    UINT32 Address,\r
+    UINT8 FirstRun,\r
+    UINT8 Mode)\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ Execute basic single cache line memory write/read/verify test using simple constant\r
+ pattern (different for READ_RAIN and WRITE_TRAIN modes.\r
+\r
+ Arguments:\r
+\r
+ CurrentMrcData: Host struture for all MRC global data.\r
+ Address: memory adress being tested (must hit specific channel/rank)\r
+ FirstRun: If set then hte registers are configured, otherwise\r
+ it is assumed configuration is done and just re-run the test.\r
+ Mode: READ_TRAIN or WRITE_TRAIN (the difference is in the pattern)\r
+\r
+ Returns:\r
+ Returns byte lane failure on each bit (for Quark only bit0 and bit1)\r
+\r
+ --*/\r
+{\r
+  UINT16 ByteLaneErrors;\r
+\r
+  ENTERFN();\r
+\r
+  //\r
+  // Enable all error reporting in preparation for HTE test.\r
+  //\r
+  EnableAllHteErrors(0xFF);\r
+  ClearHteErrorRegisters();\r
+\r
+  ByteLaneErrors = BasicDataCompareHte(CurrentMrcData, Address, FirstRun,\r
+      Mode);\r
+\r
+  LEAVEFN();\r
+  return ByteLaneErrors;\r
+}\r
+\r
+UINT16 WriteStressBitLanesHTE(\r
+    MRC_PARAMS *CurrentMrcData,\r
+    UINT32 Address,\r
+    UINT8 FirstRun)\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ Examines single cache line memory with write/read/verify test using\r
+ multiple data patterns (victim-aggressor algorithm).\r
+\r
+ Arguments:\r
+\r
+ CurrentMrcData: host struture for all MRC global data.\r
+ Address: memory adress being tested (must hit specific channel/rank)\r
+ FirstRun: If set then hte registers are configured, otherwise\r
+ it is assumed configuration is done and just re-run the test.\r
+\r
+ Returns:\r
+ Returns byte lane failure on each bit (for Quark only bit0 and bit1)\r
+\r
+ --*/\r
+{\r
+  UINT16 ByteLaneErrors;\r
+  UINT8 VictimBit = 0;\r
+\r
+  ENTERFN();\r
+\r
+  //\r
+  // Enable all error reporting in preparation for HTE test.\r
+  //\r
+  EnableAllHteErrors(0xFF);\r
+  ClearHteErrorRegisters();\r
+\r
+  //\r
+  // Loop through each bit in the bytelane.  Each pass creates a victim bit\r
+  // while keeping all other bits the same - as aggressors.\r
+  // AVN HTE adds an auto-rotate feature which allows us to program the entire victim/aggressor\r
+  // sequence in 1 step. The victim bit rotates on each pass so no need to have software implement\r
+  // a victim bit loop like on VLV.\r
+  //\r
+  ByteLaneErrors = ReadWriteDataCompareHte(CurrentMrcData, Address,\r
+      HTE_LOOP_CNT, HTE_LFSR_VICTIM_SEED, HTE_LFSR_AGRESSOR_SEED, VictimBit,\r
+      FirstRun);\r
+\r
+  LEAVEFN();\r
+  return ByteLaneErrors;\r
+}\r
+\r
+VOID HteMemOp(\r
+    UINT32 Address,\r
+    UINT8 FirstRun,\r
+    UINT8 IsWrite)\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ Execute basic single cache line memory write or read.\r
+ This is just for receive enable / fine write levelling purpose.\r
+\r
+ Arguments:\r
+\r
+ CurrentMrcData: Host structure for all MRC global data.\r
+ Address: memory address used (must hit specific channel/rank)\r
+ FirstRun: If set then hte registers are configured, otherwise\r
+ it is assumed configuration is done and just re-run the test.\r
+ IsWrite: When non-zero memory write operation executed, otherwise read\r
+\r
+ Returns:\r
+ None\r
+\r
+ --*/\r
+{\r
+  UINT32 Offset;\r
+  UINT32 Tmp;\r
+\r
+  EnableAllHteErrors(0xFF);\r
+  ClearHteErrorRegisters();\r
+\r
+  if (FirstRun)\r
+  {\r
+    Tmp = IsWrite ? 0x01110021 : 0x01010021;\r
+    isbW32m(HTE, 0x00020020, Tmp);\r
+\r
+    isbW32m(HTE, 0x00020021, 0x06000000);\r
+    isbW32m(HTE, 0x00020022, Address >> 6);\r
+    isbW32m(HTE, 0x00020062, 0x00800015);\r
+    isbW32m(HTE, 0x00020063, 0xAAAAAAAA);\r
+    isbW32m(HTE, 0x00020064, 0xCCCCCCCC);\r
+    isbW32m(HTE, 0x00020065, 0xF0F0F0F0);\r
+    isbW32m(HTE, 0x00020061, 0x00030008);\r
+\r
+    for (Offset = 0x80; Offset <= 0x8F; Offset++)\r
+    {\r
+      isbW32m(HTE, Offset, 0xC33C0000);\r
+    }\r
+  }\r
+\r
+  isbW32m(HTE, 0x000200A1, 0xFFFF1000);\r
+  isbW32m(HTE, 0x00020011, 0x00011000);\r
+  isbW32m(HTE, 0x00020011, 0x00011100);\r
+\r
+  WaitForHteComplete();\r
+}\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/hte.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/hte.h
new file mode 100644 (file)
index 0000000..eeb6192
--- /dev/null
@@ -0,0 +1,72 @@
+/** @file\r
+HTE handling routines for MRC use.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#ifndef __HTE_H\r
+#define __HTE_H\r
+\r
+#define STATIC   static\r
+#define VOID     void\r
+\r
+#if !defined(__GNUC__) && (__STDC_VERSION__ < 199901L)\r
+typedef uint32_t UINT32;\r
+typedef uint16_t UINT16;\r
+typedef uint8_t UINT8;\r
+#endif\r
+\r
+typedef enum\r
+{\r
+  MrcNoHaltSystemOnError,\r
+  MrcHaltSystemOnError,\r
+  MrcHaltHteEngineOnError,\r
+  MrcNoHaltHteEngineOnError\r
+} HALT_TYPE;\r
+\r
+typedef enum\r
+{\r
+  MrcMemInit, MrcMemTest\r
+} MEM_INIT_OR_TEST;\r
+\r
+#define READ_TRAIN      1\r
+#define WRITE_TRAIN     2\r
+\r
+#define HTE_MEMTEST_NUM                 2\r
+#define HTE_LOOP_CNT                    5  // EXP_LOOP_CNT field of HTE_CMD_CTL. This CANNOT be less than 4\r
+#define HTE_LFSR_VICTIM_SEED   0xF294BA21  // Random seed for victim.\r
+#define HTE_LFSR_AGRESSOR_SEED 0xEBA7492D  // Random seed for aggressor.\r
+UINT32\r
+HteMemInit(\r
+    MRC_PARAMS *CurrentMrcData,\r
+    UINT8 MemInitFlag,\r
+    UINT8 HaltHteEngineOnError);\r
+\r
+UINT16\r
+BasicWriteReadHTE(\r
+    MRC_PARAMS *CurrentMrcData,\r
+    UINT32 Address,\r
+    UINT8 FirstRun,\r
+    UINT8 Mode);\r
+\r
+UINT16\r
+WriteStressBitLanesHTE(\r
+    MRC_PARAMS *CurrentMrcData,\r
+    UINT32 Address,\r
+    UINT8 FirstRun);\r
+\r
+VOID\r
+HteMemOp(\r
+    UINT32 Address,\r
+    UINT8 FirstRun,\r
+    UINT8 IsWrite);\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/io.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/io.h
new file mode 100644 (file)
index 0000000..7419c59
--- /dev/null
@@ -0,0 +1,138 @@
+/** @file\r
+Declaration of IO handling routines.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#ifndef __IO_H\r
+#define __IO_H\r
+\r
+#include "core_types.h"\r
+\r
+#include "general_definitions.h"\r
+#include "gen5_iosf_sb_definitions.h"\r
+\r
+// Instruction not present on Quark\r
+#define SFENCE()\r
+\r
+#define DEAD_LOOP()   for(;;);\r
+\r
+////\r
+// Define each of the IOSF_SB ports used by MRC\r
+//\r
+\r
+//\r
+// Has to be 0 because of emulation static data\r
+// initialisation:\r
+//   Space_t EmuSpace[ SPACE_COUNT] = {0};\r
+//\r
+#define FREE                0x000\r
+\r
+// Pseudo side-band ports for access abstraction\r
+// See Wr32/Rd32 functions\r
+#define MEM                 0x101\r
+#define MMIO                0x102\r
+#define DCMD                0x0A0\r
+\r
+// Real side-band ports\r
+// See Wr32/Rd32 functions\r
+#define MCU                 0x001\r
+#define HOST_BRIDGE               0x003\r
+#define MEMORY_MANAGER               0x005\r
+#define HTE                0x011\r
+#define DDRPHY              0x012\r
+#define FUSE                0x033\r
+\r
+// End of IOSF_SB ports\r
+////\r
+\r
+// Pciexbar address\r
+#define EC_BASE          0xE0000000\r
+\r
+#define PCIADDR(bus,dev,fn,reg) ( \\r
+        (EC_BASE) + \\r
+    ((bus) << 20) + \\r
+    ((dev) << 15) + \\r
+    ((fn)  << 12) + \\r
+    (reg))\r
+\r
+// Various offsets used in the building sideband commands.\r
+#define SB_OPCODE_OFFSET      24\r
+#define SB_PORT_OFFSET        16\r
+#define SB_REG_OFFEST          8\r
+\r
+// Sideband opcodes\r
+#define SB_REG_READ_OPCODE        0x10\r
+#define SB_REG_WRITE_OPCODE       0x11\r
+\r
+#define SB_FUSE_REG_READ_OPCODE    0x06\r
+#define SB_FUSE_REG_WRITE_OPCODE  0x07\r
+\r
+#define SB_DDRIO_REG_READ_OPCODE  0x06\r
+#define SB_DDRIO_REG_WRITE_OPCODE 0x07\r
+\r
+#define SB_DRAM_CMND_OPCODE       0x68\r
+#define SB_WAKE_CMND_OPCODE       0xCA\r
+#define SB_SUSPEND_CMND_OPCODE    0xCC\r
+\r
+// Register addresses for sideband command and data.\r
+#define SB_PACKET_REG        0x00D0\r
+#define SB_DATA_REG          0x00D4\r
+#define SB_HADR_REG          0x00D8\r
+\r
+// We always flag all 4 bytes in the register reads/writes as required.\r
+#define SB_ALL_BYTES_ENABLED  0xF0\r
+\r
+#define SB_COMMAND(Opcode, Port, Reg)  \\r
+ ((Opcode << SB_OPCODE_OFFSET) |  \\r
+  (Port   << SB_PORT_OFFSET) |  \\r
+  (Reg    << SB_REG_OFFEST) |  \\r
+   SB_ALL_BYTES_ENABLED)\r
+\r
+// iosf\r
+#define isbM32m   WrMask32\r
+#define isbW32m   Wr32\r
+#define isbR32m   Rd32\r
+\r
+// pci\r
+\r
+void pciwrite32(\r
+    uint32_t bus,\r
+    uint32_t dev,\r
+    uint32_t fn,\r
+    uint32_t reg,\r
+    uint32_t data);\r
+\r
+uint32_t pciread32(\r
+    uint32_t bus,\r
+    uint32_t dev,\r
+    uint32_t fn,\r
+    uint32_t reg);\r
+\r
+// general\r
+\r
+uint32_t Rd32(\r
+    uint32_t unit,\r
+    uint32_t addr);\r
+\r
+void Wr32(\r
+    uint32_t unit,\r
+    uint32_t addr,\r
+    uint32_t data);\r
+\r
+void WrMask32(\r
+    uint32_t unit,\r
+    uint32_t addr,\r
+    uint32_t data,\r
+    uint32_t mask);\r
+\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/lprint.c b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/lprint.c
new file mode 100644 (file)
index 0000000..f77db8b
--- /dev/null
@@ -0,0 +1,388 @@
+/** @file\r
+Serial conole output and string formating.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include "memory_options.h"\r
+#include "general_definitions.h"\r
+\r
+// Resource programmed to PCI bridge, 1MB bound alignment is needed.\r
+// The default value is overwritten by MRC parameter, assuming code\r
+// relocated to eSRAM.\r
+uint32_t UartMmioBase = 0;\r
+\r
+// Serial port registers based on SerialPortLib.c\r
+#define R_UART_BAUD_THR       0\r
+#define R_UART_LSR            20\r
+\r
+#define   B_UART_LSR_RXRDY    BIT0\r
+#define   B_UART_LSR_TXRDY    BIT5\r
+#define   B_UART_LSR_TEMT     BIT6\r
+\r
+// Print mask see DPF and D_Xxxx\r
+#define DPF_MASK  DpfPrintMask\r
+\r
+// Select class of messages enabled for printing\r
+uint32_t DpfPrintMask =\r
+    D_ERROR |\r
+    D_INFO |\r
+    // D_REGRD |\r
+    // D_REGWR |\r
+    // D_FCALL |\r
+    // D_TRN |\r
+    0;\r
+\r
+#ifdef NDEBUG\r
+// Don't generate debug code\r
+void dpf( uint32_t mask, char_t* bla, ...)\r
+{\r
+  return;\r
+}\r
+\r
+uint8_t mgetc(void)\r
+{\r
+  return 0;\r
+}\r
+\r
+uint8_t mgetch(void)\r
+{\r
+  return 0;\r
+}\r
+\r
+#else\r
+\r
+#ifdef SIM\r
+// Use Vpi console in simulation environment\r
+#include <vpi_user.h>\r
+\r
+void dpf( uint32_t mask, char_t* bla, ...)\r
+{\r
+  va_list va;\r
+\r
+  if( 0 == (mask & DPF_MASK)) return;\r
+\r
+  va_start( va, bla);\r
+  vpi_vprintf( bla, va);\r
+  va_end(va);\r
+}\r
+\r
+#else\r
+\r
+#ifdef EMU\r
+// Use standard console in windows environment\r
+#include <stdio.h>\r
+#endif\r
+\r
+// Read character from serial port\r
+uint8_t mgetc(void)\r
+{\r
+#ifdef EMU\r
+\r
+  // Emulation in Windows environment uses console\r
+  getchar();\r
+\r
+#else\r
+  uint8_t c;\r
+\r
+  while ((*(volatile uint8_t*) (UartMmioBase + R_UART_LSR) & B_UART_LSR_RXRDY) == 0);\r
+  c = *(volatile uint8_t*) (UartMmioBase + R_UART_BAUD_THR);\r
+\r
+  return c;\r
+#endif\r
+}\r
+\r
+\r
+uint8_t mgetch(void)\r
+{\r
+#ifdef EMU\r
+  return 0;\r
+#else\r
+  uint8_t c = 0;\r
+\r
+  if((*(volatile uint8_t*) (UartMmioBase + R_UART_LSR) & B_UART_LSR_RXRDY) != 0)\r
+  {\r
+    c = *(volatile uint8_t*) (UartMmioBase + R_UART_BAUD_THR);\r
+  }\r
+\r
+  return c;\r
+#endif\r
+}\r
+\r
+// Print single character\r
+static void printc(\r
+    uint8_t c)\r
+{\r
+#ifdef EMU\r
+\r
+  // Emulation in Windows environment uses console output\r
+  putchar(c);\r
+\r
+#else\r
+\r
+  //\r
+  // Use MMIO access to serial port on PCI\r
+  //   while( 0 == (0x20 & inp(0x3f8 + 5)));\r
+  //   outp(0x3f8 + 0, c);\r
+  //\r
+  while (0\r
+      == (B_UART_LSR_TEMT & *((volatile uint8_t*) (UartMmioBase + R_UART_LSR))))\r
+    ;\r
+  *((volatile uint8_t*) (UartMmioBase + R_UART_BAUD_THR)) = c;\r
+#endif\r
+}\r
+\r
+// Print 0 terminated string on serial console\r
+static void printstr(\r
+    char_t *str)\r
+{\r
+  while (*str)\r
+  {\r
+    printc(*str++);\r
+  }\r
+}\r
+// Print 64bit number as hex string on serial console\r
+// the width parameters allows skipping leading zeros\r
+static void printhexx(\r
+    uint64_t val,\r
+    uint32_t width)\r
+{\r
+  uint32_t i;\r
+  uint8_t c;\r
+  uint8_t empty = 1;\r
+\r
+  // 64bit number has 16 characters in hex representation\r
+  for (i = 16; i > 0; i--)\r
+  {\r
+    c = *(((uint8_t *)&val) + ((i - 1) >> 1));\r
+    if (((i - 1) & 1) != 0)\r
+      c = c >> 4;\r
+    c = c & 0x0F;\r
+\r
+    if (c > 9)\r
+      c += 'A' - 10;\r
+    else\r
+      c += '0';\r
+\r
+    if (c != '0')\r
+    {\r
+      // end of leading zeros\r
+      empty = 0;\r
+    }\r
+\r
+    // don't print leading zero\r
+    if (!empty || i <= width)\r
+    {\r
+      printc(c);\r
+    }\r
+  }\r
+}\r
+// Print 32bit number as hex string on serial console\r
+// the width parameters allows skipping leading zeros\r
+static void printhex(\r
+    uint32_t val,\r
+    uint32_t width)\r
+{\r
+  uint32_t i;\r
+  uint8_t c;\r
+  uint8_t empty = 1;\r
+\r
+  // 32bit number has 8 characters in hex representation\r
+  for (i = 8; i > 0; i--)\r
+  {\r
+    c = (uint8_t) ((val >> 28) & 0x0F);\r
+    if (c > 9)\r
+      c += 'A' - 10;\r
+    else\r
+      c += '0';\r
+\r
+    val = val << 4;\r
+\r
+    if (c != '0')\r
+    {\r
+      // end of leading zeros\r
+      empty = 0;\r
+    }\r
+\r
+    // don't print leading zero\r
+    if (!empty || i <= width)\r
+    {\r
+      printc(c);\r
+    }\r
+  }\r
+}\r
+// Print 32bit number as decimal string on serial console\r
+// the width parameters allows skipping leading zeros\r
+static void printdec(\r
+    uint32_t val,\r
+    uint32_t width)\r
+{\r
+  uint32_t i;\r
+  uint8_t c = 0;\r
+  uint8_t empty = 1;\r
+\r
+  // Ten digits is enough for 32bit number in decimal\r
+  uint8_t buf[10];\r
+\r
+  for (i = 0; i < sizeof(buf); i++)\r
+  {\r
+    c = (uint8_t) (val % 10);\r
+    buf[i] = c + '0';\r
+    val = val / 10;\r
+  }\r
+\r
+  while (i > 0)\r
+  {\r
+    c = buf[--i];\r
+\r
+    if (c != '0')\r
+    {\r
+      // end of leading zeros\r
+      empty = 0;\r
+    }\r
+\r
+    // don't print leading zero\r
+    if (!empty || i < width)\r
+    {\r
+      printc(c);\r
+    }\r
+  }\r
+}\r
+\r
+// Consume numeric substring leading the given string\r
+// Return pointer to the first non-numeric character\r
+// Buffer reference by width is updated with number\r
+// converted from the numeric substring.\r
+static char_t *getwidth(\r
+    char_t *bla,\r
+    uint32_t *width)\r
+{\r
+  uint32_t val = 0;\r
+\r
+  while (*bla >= '0' && *bla <= '9')\r
+  {\r
+    val = val * 10 + *bla - '0';\r
+    bla += 1;\r
+  }\r
+\r
+  if (val > 0)\r
+  {\r
+    *width = val;\r
+  }\r
+  return bla;\r
+}\r
+\r
+// Consume print format designator from the head of given string\r
+// Return pointer to first character after format designator\r
+// input fmt\r
+// ----- ---\r
+//  s   -> s\r
+//  d   -> d\r
+//  X   -> X\r
+//  llX -> L\r
+static char_t *getformat(\r
+    char_t *bla,\r
+    uint8_t *fmt)\r
+{\r
+  if (bla[0] == 's')\r
+  {\r
+    bla += 1;\r
+    *fmt = 's';\r
+  }\r
+  else if (bla[0] == 'd')\r
+  {\r
+    bla += 1;\r
+    *fmt = 'd';\r
+  }\r
+  else if (bla[0] == 'X' || bla[0] == 'x')\r
+  {\r
+    bla += 1;\r
+    *fmt = 'X';\r
+  }\r
+  else if (bla[0] == 'l' && bla[1] == 'l' && bla[2] == 'X')\r
+  {\r
+    bla += 3;\r
+    *fmt = 'L';\r
+  }\r
+\r
+  return bla;\r
+}\r
+\r
+// Simplified implementation of standard printf function\r
+// The output is directed to serial console. Only selected\r
+// class of messages is printed (mask has to match DpfPrintMask)\r
+// Supported print formats: %[n]s,%[n]d,%[n]X,,%[n]llX\r
+// The width is ignored for %s format.\r
+void dpf(\r
+    uint32_t mask,\r
+    char_t* bla,\r
+    ...)\r
+{\r
+  uint32_t* arg = (uint32_t*) (&bla + 1);\r
+\r
+  // Check UART MMIO base configured\r
+  if (0 == UartMmioBase)\r
+    return;\r
+\r
+  // Check event not masked\r
+  if (0 == (mask & DPF_MASK))\r
+    return;\r
+\r
+  for (;;)\r
+  {\r
+    uint8_t x = *bla++;\r
+    if (x == 0)\r
+      break;\r
+\r
+    if (x == '\n')\r
+    {\r
+      printc('\r');\r
+      printc('\n');\r
+    }\r
+    else if (x == '%')\r
+    {\r
+      uint8_t fmt = 0;\r
+      uint32_t width = 1;\r
+\r
+      bla = getwidth(bla, &width);\r
+      bla = getformat(bla, &fmt);\r
+\r
+      // Print value\r
+      if (fmt == 'd')\r
+      {\r
+        printdec(*arg, width);\r
+        arg += 1;\r
+      }\r
+      else if (fmt == 'X')\r
+      {\r
+        printhex(*arg, width);\r
+        arg += 1;\r
+      }\r
+      else if (fmt == 'L')\r
+      {\r
+        printhexx(*(uint64_t*) arg, width);\r
+        arg += 2;\r
+      }\r
+      else if (fmt == 's')\r
+      {\r
+        printstr(*(char**) arg);\r
+        arg += 1;\r
+      }\r
+    }\r
+    else\r
+    {\r
+      printc(x);\r
+    }\r
+  }\r
+}\r
+\r
+#endif  //SIM\r
+#endif  //NDEBUG\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit.c b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit.c
new file mode 100644 (file)
index 0000000..26c56e6
--- /dev/null
@@ -0,0 +1,2645 @@
+/************************************************************************\r
+ *\r
+ * Copyright (c) 2013-2015 Intel Corporation.\r
+ *\r
+* This program and the accompanying materials\r
+* are licensed and made available under the terms and conditions of the BSD License\r
+* which accompanies this distribution.  The full text of the license may be found at\r
+* http://opensource.org/licenses/bsd-license.php\r
+*\r
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ *\r
+ * This file contains all of the Cat Mountain Memory Reference Code (MRC).\r
+ *\r
+ * These functions are generic and should work for any Cat Mountain config.\r
+ *\r
+ * MRC requires two data structures to be passed in which are initialised by "PreMemInit()".\r
+ *\r
+ * The basic flow is as follows:\r
+ * 01) Check for supported DDR speed configuration\r
+ * 02) Set up MEMORY_MANAGER buffer as pass-through (POR)\r
+ * 03) Set Channel Interleaving Mode and Channel Stride to the most aggressive setting possible\r
+ * 04) Set up the MCU logic\r
+ * 05) Set up the DDR_PHY logic\r
+ * 06) Initialise the DRAMs (JEDEC)\r
+ * 07) Perform the Receive Enable Calibration algorithm\r
+ * 08) Perform the Write Leveling algorithm\r
+ * 09) Perform the Read Training algorithm (includes internal Vref)\r
+ * 10) Perform the Write Training algorithm\r
+ * 11) Set Channel Interleaving Mode and Channel Stride to the desired settings\r
+ *\r
+ * Dunit configuration based on Valleyview MRC.\r
+ *\r
+ ***************************************************************************/\r
+\r
+#include "mrc.h"\r
+#include "memory_options.h"\r
+\r
+#include "meminit.h"\r
+#include "meminit_utils.h"\r
+#include "hte.h"\r
+#include "io.h"\r
+\r
+// Override ODT to off state if requested\r
+#define DRMC_DEFAULT    (mrc_params->rd_odt_value==0?BIT12:0)\r
+\r
+\r
+// tRFC values (in picoseconds) per density\r
+const uint32_t tRFC[5] =\r
+{\r
+    90000,  // 512Mb\r
+    110000, // 1Gb\r
+    160000, // 2Gb\r
+    300000, // 4Gb\r
+    350000, // 8Gb\r
+    };\r
+\r
+// tCK clock period in picoseconds per speed index 800, 1066, 1333\r
+const uint32_t tCK[3] =\r
+{\r
+    2500,\r
+    1875,\r
+    1500\r
+};\r
+\r
+#ifdef SIM\r
+// Select static timings specific to simulation environment\r
+#define PLATFORM_ID    0\r
+#else\r
+// Select static timings specific to ClantonPeek platform\r
+#define PLATFORM_ID    1\r
+#endif\r
+\r
+\r
+// Global variables\r
+const uint16_t ddr_wclk[] =\r
+    {193, 158};\r
+\r
+const uint16_t ddr_wctl[] =\r
+    {  1, 217};\r
+\r
+const uint16_t ddr_wcmd[] =\r
+    {  1, 220};\r
+\r
+\r
+#ifdef BACKUP_RCVN\r
+const uint16_t ddr_rcvn[] =\r
+    {129, 498};\r
+#endif // BACKUP_RCVN\r
+\r
+#ifdef BACKUP_WDQS\r
+const uint16_t ddr_wdqs[] =\r
+    { 65, 289};\r
+#endif // BACKUP_WDQS\r
+\r
+#ifdef BACKUP_RDQS\r
+const uint8_t ddr_rdqs[] =\r
+    { 32,  24};\r
+#endif // BACKUP_RDQS\r
+\r
+#ifdef BACKUP_WDQ\r
+const uint16_t ddr_wdq[] =\r
+    { 32, 257};\r
+#endif // BACKUP_WDQ\r
+\r
+\r
+\r
+// Select MEMORY_MANAGER as the source for PRI interface\r
+static void select_memory_manager(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  RegDCO Dco;\r
+\r
+  ENTERFN();\r
+\r
+  Dco.raw = isbR32m(MCU, DCO);\r
+  Dco.field.PMICTL = 0;          //0 - PRI owned by MEMORY_MANAGER\r
+  isbW32m(MCU, DCO, Dco.raw);\r
+\r
+  LEAVEFN();\r
+}\r
+\r
+// Select HTE as the source for PRI interface\r
+void select_hte(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  RegDCO Dco;\r
+\r
+  ENTERFN();\r
+\r
+  Dco.raw = isbR32m(MCU, DCO);\r
+  Dco.field.PMICTL = 1;          //1 - PRI owned by HTE\r
+  isbW32m(MCU, DCO, Dco.raw);\r
+\r
+  LEAVEFN();\r
+}\r
+\r
+// Send DRAM command, data should be formated\r
+// using DCMD_Xxxx macro or emrsXCommand structure.\r
+static void dram_init_command(\r
+    uint32_t data)\r
+{\r
+  Wr32(DCMD, 0, data);\r
+}\r
+\r
+// Send DRAM wake command using special MCU side-band WAKE opcode\r
+static void dram_wake_command(\r
+    void)\r
+{\r
+  ENTERFN();\r
+\r
+  Wr32(MMIO, PCIADDR(0,0,0,SB_PACKET_REG),\r
+      (uint32_t) SB_COMMAND(SB_WAKE_CMND_OPCODE, MCU, 0));\r
+\r
+  LEAVEFN();\r
+}\r
+\r
+// Stop self refresh driven by MCU\r
+static void clear_self_refresh(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  ENTERFN();\r
+\r
+  // clear the PMSTS Channel Self Refresh bits\r
+  isbM32m(MCU, PMSTS, BIT0, BIT0);\r
+\r
+  LEAVEFN();\r
+}\r
+\r
+// Configure MCU before jedec init sequence\r
+static void prog_decode_before_jedec(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  RegDRP Drp;\r
+  RegDRCF Drfc;\r
+  RegDCAL Dcal;\r
+  RegDSCH Dsch;\r
+  RegDPMC0 Dpmc0;\r
+\r
+  ENTERFN();\r
+\r
+  // Disable power saving features\r
+  Dpmc0.raw = isbR32m(MCU, DPMC0);\r
+  Dpmc0.field.CLKGTDIS = 1;\r
+  Dpmc0.field.DISPWRDN = 1;\r
+  Dpmc0.field.DYNSREN = 0;\r
+  Dpmc0.field.PCLSTO = 0;\r
+  isbW32m(MCU, DPMC0, Dpmc0.raw);\r
+\r
+  // Disable out of order transactions\r
+  Dsch.raw = isbR32m(MCU, DSCH);\r
+  Dsch.field.OOODIS = 1;\r
+  Dsch.field.NEWBYPDIS = 1;\r
+  isbW32m(MCU, DSCH, Dsch.raw);\r
+\r
+  // Disable issuing the REF command\r
+  Drfc.raw = isbR32m(MCU, DRFC);\r
+  Drfc.field.tREFI = 0;\r
+  isbW32m(MCU, DRFC, Drfc.raw);\r
+\r
+  // Disable ZQ calibration short\r
+  Dcal.raw = isbR32m(MCU, DCAL);\r
+  Dcal.field.ZQCINT = 0;\r
+  Dcal.field.SRXZQCL = 0;\r
+  isbW32m(MCU, DCAL, Dcal.raw);\r
+\r
+  // Training performed in address mode 0, rank population has limited impact, however\r
+  // simulator complains if enabled non-existing rank.\r
+  Drp.raw = 0;\r
+  if (mrc_params->rank_enables & 1)\r
+    Drp.field.rank0Enabled = 1;\r
+  if (mrc_params->rank_enables & 2)\r
+    Drp.field.rank1Enabled = 1;\r
+  isbW32m(MCU, DRP, Drp.raw);\r
+\r
+  LEAVEFN();\r
+}\r
+\r
+// After Cold Reset, BIOS should set COLDWAKE bit to 1 before\r
+// sending the WAKE message to the Dunit.\r
+// For Standby Exit, or any other mode in which the DRAM is in\r
+// SR, this bit must be set to 0.\r
+static void perform_ddr_reset(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  ENTERFN();\r
+\r
+  // Set COLDWAKE bit before sending the WAKE message\r
+  isbM32m(MCU, DRMC, BIT16, BIT16);\r
+\r
+  // Send wake command to DUNIT (MUST be done before JEDEC)\r
+  dram_wake_command();\r
+\r
+  // Set default value\r
+  isbW32m(MCU, DRMC, DRMC_DEFAULT);\r
+\r
+  LEAVEFN();\r
+}\r
+\r
+// Dunit Initialisation Complete.\r
+// Indicates that initialisation of the Dunit has completed.\r
+// Memory accesses are permitted and maintenance operation\r
+// begins. Until this bit is set to a 1, the memory controller will\r
+// not accept DRAM requests from the MEMORY_MANAGER or HTE.\r
+static void set_ddr_init_complete(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  RegDCO Dco;\r
+\r
+  ENTERFN();\r
+\r
+  Dco.raw = isbR32m(MCU, DCO);\r
+  Dco.field.PMICTL = 0;          //0 - PRI owned by MEMORY_MANAGER\r
+  Dco.field.IC = 1;              //1 - initialisation complete\r
+  isbW32m(MCU, DCO, Dco.raw);\r
+\r
+  LEAVEFN();\r
+}\r
+\r
+static void prog_page_ctrl(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  RegDPMC0 Dpmc0;\r
+\r
+  ENTERFN();\r
+\r
+  Dpmc0.raw = isbR32m(MCU, DPMC0);\r
+\r
+  Dpmc0.field.PCLSTO = 0x4;\r
+  Dpmc0.field.PREAPWDEN = 1;\r
+\r
+  isbW32m(MCU, DPMC0, Dpmc0.raw);\r
+}\r
+\r
+// Configure MCU Power Management Control Register\r
+// and Scheduler Control Register.\r
+static void prog_ddr_control(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  RegDSCH Dsch;\r
+  RegDPMC0 Dpmc0;\r
+\r
+  ENTERFN();\r
+\r
+  Dpmc0.raw = isbR32m(MCU, DPMC0);\r
+  Dsch.raw = isbR32m(MCU, DSCH);\r
+\r
+  Dpmc0.field.DISPWRDN = mrc_params->power_down_disable;\r
+  Dpmc0.field.CLKGTDIS = 0;\r
+  Dpmc0.field.PCLSTO = 4;\r
+  Dpmc0.field.PREAPWDEN = 1;\r
+\r
+  Dsch.field.OOODIS = 0;\r
+  Dsch.field.OOOST3DIS = 0;\r
+  Dsch.field.NEWBYPDIS = 0;\r
+\r
+  isbW32m(MCU, DSCH, Dsch.raw);\r
+  isbW32m(MCU, DPMC0, Dpmc0.raw);\r
+\r
+  // CMDTRIST = 2h - CMD/ADDR are tristated when no valid command\r
+  isbM32m(MCU, DPMC1, 2 << 4, BIT5|BIT4);\r
+\r
+  LEAVEFN();\r
+}\r
+\r
+// After training complete configure MCU Rank Population Register\r
+// specifying: ranks enabled, device width, density, address mode.\r
+static void prog_dra_drb(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  RegDRP Drp;\r
+  RegDCO Dco;\r
+\r
+  ENTERFN();\r
+\r
+  Dco.raw = isbR32m(MCU, DCO);\r
+  Dco.field.IC = 0;\r
+  isbW32m(MCU, DCO, Dco.raw);\r
+\r
+  Drp.raw = 0;\r
+  if (mrc_params->rank_enables & 1)\r
+    Drp.field.rank0Enabled = 1;\r
+  if (mrc_params->rank_enables & 2)\r
+    Drp.field.rank1Enabled = 1;\r
+  if (mrc_params->dram_width == x16)\r
+  {\r
+    Drp.field.dimm0DevWidth = 1;\r
+    Drp.field.dimm1DevWidth = 1;\r
+  }\r
+  // Density encoding in DRAMParams_t 0=512Mb, 1=Gb, 2=2Gb, 3=4Gb\r
+  // has to be mapped RANKDENSx encoding (0=1Gb)\r
+  Drp.field.dimm0DevDensity = mrc_params->params.DENSITY - 1;\r
+  Drp.field.dimm1DevDensity = mrc_params->params.DENSITY - 1;\r
+\r
+  // Address mode can be overwritten if ECC enabled\r
+  Drp.field.addressMap = mrc_params->address_mode;\r
+\r
+  isbW32m(MCU, DRP, Drp.raw);\r
+\r
+  Dco.field.PMICTL = 0;          //0 - PRI owned by MEMORY_MANAGER\r
+  Dco.field.IC = 1;              //1 - initialisation complete\r
+  isbW32m(MCU, DCO, Dco.raw);\r
+\r
+  LEAVEFN();\r
+}\r
+\r
+// Configure refresh rate and short ZQ calibration interval.\r
+// Activate dynamic self refresh.\r
+static void change_refresh_period(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  RegDRCF Drfc;\r
+  RegDCAL Dcal;\r
+  RegDPMC0 Dpmc0;\r
+\r
+  ENTERFN();\r
+\r
+  Drfc.raw = isbR32m(MCU, DRFC);\r
+  Drfc.field.tREFI = mrc_params->refresh_rate;\r
+  Drfc.field.REFDBTCLR = 1;\r
+  isbW32m(MCU, DRFC, Drfc.raw);\r
+\r
+  Dcal.raw = isbR32m(MCU, DCAL);\r
+  Dcal.field.ZQCINT = 3; // 63ms\r
+  isbW32m(MCU, DCAL, Dcal.raw);\r
+\r
+  Dpmc0.raw = isbR32m(MCU, DPMC0);\r
+  Dpmc0.field.ENPHYCLKGATE = 1;\r
+  Dpmc0.field.DYNSREN = 1;\r
+  isbW32m(MCU, DPMC0, Dpmc0.raw);\r
+\r
+  LEAVEFN();\r
+}\r
+\r
+// Send DRAM wake command\r
+static void perform_wake(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  ENTERFN();\r
+\r
+  dram_wake_command();\r
+\r
+  LEAVEFN();\r
+}\r
+\r
+// prog_ddr_timing_control (aka mcu_init):\r
+// POST_CODE[major] == 0x02\r
+//\r
+// It will initialise timing registers in the MCU (DTR0..DTR4).\r
+static void prog_ddr_timing_control(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  uint8_t TCL, WL;\r
+  uint8_t TRP, TRCD, TRAS, TRFC, TWR, TWTR, TRRD, TRTP, TFAW;\r
+  uint32_t TCK;\r
+\r
+  RegDTR0 Dtr0;\r
+  RegDTR1 Dtr1;\r
+  RegDTR2 Dtr2;\r
+  RegDTR3 Dtr3;\r
+  RegDTR4 Dtr4;\r
+\r
+  ENTERFN();\r
+\r
+  // mcu_init starts\r
+  post_code(0x02, 0x00);\r
+\r
+  Dtr0.raw = isbR32m(MCU, DTR0);\r
+  Dtr1.raw = isbR32m(MCU, DTR1);\r
+  Dtr2.raw = isbR32m(MCU, DTR2);\r
+  Dtr3.raw = isbR32m(MCU, DTR3);\r
+  Dtr4.raw = isbR32m(MCU, DTR4);\r
+\r
+  TCK = tCK[mrc_params->ddr_speed];  // Clock in picoseconds\r
+  TCL = mrc_params->params.tCL;      // CAS latency in clocks\r
+  TRP = TCL;  // Per CAT MRC\r
+  TRCD = TCL;  // Per CAT MRC\r
+  TRAS = MCEIL(mrc_params->params.tRAS, TCK);\r
+  TRFC = MCEIL(tRFC[mrc_params->params.DENSITY], TCK);\r
+  TWR = MCEIL(15000, TCK);   // Per JEDEC: tWR=15000ps DDR2/3 from 800-1600\r
+\r
+  TWTR = MCEIL(mrc_params->params.tWTR, TCK);\r
+  TRRD = MCEIL(mrc_params->params.tRRD, TCK);\r
+  TRTP = 4;  // Valid for 800 and 1066, use 5 for 1333\r
+  TFAW = MCEIL(mrc_params->params.tFAW, TCK);\r
+\r
+  WL = 5 + mrc_params->ddr_speed;\r
+\r
+  Dtr0.field.dramFrequency = mrc_params->ddr_speed;\r
+\r
+  Dtr0.field.tCL = TCL - 5;            //Convert from TCL (DRAM clocks) to VLV indx\r
+  Dtr0.field.tRP = TRP - 5;            //5 bit DRAM Clock\r
+  Dtr0.field.tRCD = TRCD - 5;          //5 bit DRAM Clock\r
+\r
+  Dtr1.field.tWCL = WL - 3;            //Convert from WL (DRAM clocks)  to VLV indx\r
+  Dtr1.field.tWTP = WL + 4 + TWR - 14;  //Change to tWTP\r
+  Dtr1.field.tRTP = MMAX(TRTP, 4) - 3;  //4 bit DRAM Clock\r
+  Dtr1.field.tRRD = TRRD - 4;        //4 bit DRAM Clock\r
+  Dtr1.field.tCMD = 1;             //2N\r
+  Dtr1.field.tRAS = TRAS - 14;      //6 bit DRAM Clock\r
+\r
+  Dtr1.field.tFAW = ((TFAW + 1) >> 1) - 5;    //4 bit DRAM Clock\r
+  Dtr1.field.tCCD = 0;                        //Set 4 Clock CAS to CAS delay (multi-burst)\r
+  Dtr2.field.tRRDR = 1;\r
+  Dtr2.field.tWWDR = 2;\r
+  Dtr2.field.tRWDR = 2;\r
+  Dtr3.field.tWRDR = 2;\r
+  Dtr3.field.tWRDD = 2;\r
+\r
+  if (mrc_params->ddr_speed == DDRFREQ_800)\r
+  {\r
+     // Extended RW delay (+1)\r
+     Dtr3.field.tRWSR = TCL - 5 + 1;\r
+  }\r
+  else if(mrc_params->ddr_speed == DDRFREQ_1066)\r
+  {\r
+     // Extended RW delay (+1)\r
+     Dtr3.field.tRWSR = TCL - 5 + 1;\r
+  }\r
+\r
+  Dtr3.field.tWRSR = 4 + WL + TWTR - 11;\r
+\r
+  if (mrc_params->ddr_speed == DDRFREQ_800)\r
+  {\r
+    Dtr3.field.tXP = MMAX(0, 1 - Dtr1.field.tCMD);\r
+  }\r
+  else\r
+  {\r
+    Dtr3.field.tXP = MMAX(0, 2 - Dtr1.field.tCMD);\r
+  }\r
+\r
+  Dtr4.field.WRODTSTRT = Dtr1.field.tCMD;\r
+  Dtr4.field.WRODTSTOP = Dtr1.field.tCMD;\r
+  Dtr4.field.RDODTSTRT = Dtr1.field.tCMD + Dtr0.field.tCL - Dtr1.field.tWCL + 2; //Convert from WL (DRAM clocks)  to VLV indx\r
+  Dtr4.field.RDODTSTOP = Dtr1.field.tCMD + Dtr0.field.tCL - Dtr1.field.tWCL + 2;\r
+  Dtr4.field.TRGSTRDIS = 0;\r
+  Dtr4.field.ODTDIS = 0;\r
+\r
+  isbW32m(MCU, DTR0, Dtr0.raw);\r
+  isbW32m(MCU, DTR1, Dtr1.raw);\r
+  isbW32m(MCU, DTR2, Dtr2.raw);\r
+  isbW32m(MCU, DTR3, Dtr3.raw);\r
+  isbW32m(MCU, DTR4, Dtr4.raw);\r
+\r
+  LEAVEFN();\r
+}\r
+\r
+// ddrphy_init:\r
+// POST_CODE[major] == 0x03\r
+//\r
+// This function performs some initialisation on the DDRIO unit.\r
+// This function is dependent on BOARD_ID, DDR_SPEED, and CHANNEL_ENABLES.\r
+static void ddrphy_init(MRCParams_t *mrc_params)\r
+{\r
+  uint32_t tempD; // temporary DWORD\r
+  uint8_t channel_i; // channel counter\r
+  uint8_t rank_i; // rank counter\r
+  uint8_t bl_grp_i; // byte lane group counter (2 BLs per module)\r
+\r
+  uint8_t bl_divisor = /*(mrc_params->channel_width==x16)?2:*/1; // byte lane divisor\r
+  uint8_t speed = mrc_params->ddr_speed & (BIT1|BIT0); // For DDR3 --> 0 == 800, 1 == 1066, 2 == 1333\r
+  uint8_t tCAS;\r
+  uint8_t tCWL;\r
+\r
+  ENTERFN();\r
+\r
+  tCAS = mrc_params->params.tCL;\r
+  tCWL = 5 + mrc_params->ddr_speed;\r
+\r
+  // ddrphy_init starts\r
+  post_code(0x03, 0x00);\r
+\r
+  // HSD#231531\r
+  // Make sure IOBUFACT is deasserted before initialising the DDR PHY.\r
+  // HSD#234845\r
+  // Make sure WRPTRENABLE is deasserted before initialising the DDR PHY.\r
+  for (channel_i=0; channel_i<NUM_CHANNELS; channel_i++) {\r
+    if (mrc_params->channel_enables & (1<<channel_i)) {\r
+      // Deassert DDRPHY Initialisation Complete\r
+      isbM32m(DDRPHY, (CMDPMCONFIG0 + (channel_i * DDRIOCCC_CH_OFFSET)), ~BIT20, BIT20); // SPID_INIT_COMPLETE=0\r
+      // Deassert IOBUFACT\r
+      isbM32m(DDRPHY, (CMDCFGREG0 + (channel_i * DDRIOCCC_CH_OFFSET)), ~BIT2, BIT2); // IOBUFACTRST_N=0\r
+      // Disable WRPTR\r
+      isbM32m(DDRPHY, (CMDPTRREG + (channel_i * DDRIOCCC_CH_OFFSET)), ~BIT0, BIT0); // WRPTRENABLE=0\r
+    } // if channel enabled\r
+  } // channel_i loop\r
+\r
+  // Put PHY in reset\r
+  isbM32m(DDRPHY, MASTERRSTN, 0, BIT0); // PHYRSTN=0\r
+\r
+  // Initialise DQ01,DQ23,CMD,CLK-CTL,COMP modules\r
+  // STEP0:\r
+  post_code(0x03, 0x10);\r
+  for (channel_i=0; channel_i<NUM_CHANNELS; channel_i++) {\r
+    if (mrc_params->channel_enables & (1<<channel_i)) {\r
+\r
+      // DQ01-DQ23\r
+      for (bl_grp_i=0; bl_grp_i<((NUM_BYTE_LANES/bl_divisor)/2); bl_grp_i++) {\r
+        isbM32m(DDRPHY, (DQOBSCKEBBCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), ((bl_grp_i) ? (0x00) : (BIT22)), (BIT22)); // Analog MUX select - IO2xCLKSEL\r
+\r
+        // ODT Strength\r
+        switch (mrc_params->rd_odt_value) {\r
+          case 1: tempD = 0x3; break; // 60 ohm\r
+          case 2: tempD = 0x3; break; // 120 ohm\r
+          case 3: tempD = 0x3; break; // 180 ohm\r
+          default: tempD = 0x3; break; // 120 ohm\r
+        }\r
+        isbM32m(DDRPHY, (B0RXIOBUFCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (tempD<<5), (BIT6|BIT5)); // ODT strength\r
+        isbM32m(DDRPHY, (B1RXIOBUFCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (tempD<<5), (BIT6|BIT5)); // ODT strength\r
+        // Dynamic ODT/DIFFAMP\r
+        tempD = (((tCAS)<<24)|((tCAS)<<16)|((tCAS)<<8)|((tCAS)<<0));\r
+        switch (speed) {\r
+          case 0: tempD -= 0x01010101; break; // 800\r
+          case 1: tempD -= 0x02020202; break; // 1066\r
+          case 2: tempD -= 0x03030303; break; // 1333\r
+          case 3: tempD -= 0x04040404; break; // 1600\r
+        }\r
+        isbM32m(DDRPHY, (B01LATCTL1 + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), tempD, ((BIT28|BIT27|BIT26|BIT25|BIT24)|(BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT4|BIT3|BIT2|BIT1|BIT0))); // Launch Time: ODT, DIFFAMP, ODT, DIFFAMP\r
+        switch (speed) {\r
+          // HSD#234715\r
+          case 0: tempD = ((0x06<<16)|(0x07<<8)); break; // 800\r
+          case 1: tempD = ((0x07<<16)|(0x08<<8)); break; // 1066\r
+          case 2: tempD = ((0x09<<16)|(0x0A<<8)); break; // 1333\r
+          case 3: tempD = ((0x0A<<16)|(0x0B<<8)); break; // 1600\r
+        }\r
+        isbM32m(DDRPHY, (B0ONDURCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), tempD, ((BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT13|BIT12|BIT11|BIT10|BIT9|BIT8))); // On Duration: ODT, DIFFAMP\r
+        isbM32m(DDRPHY, (B1ONDURCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), tempD, ((BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT13|BIT12|BIT11|BIT10|BIT9|BIT8))); // On Duration: ODT, DIFFAMP\r
+\r
+        switch (mrc_params->rd_odt_value) {\r
+          case 0:  tempD = ((0x3F<<16)|(0x3f<<10)); break; // override DIFFAMP=on, ODT=off\r
+          default: tempD = ((0x3F<<16)|(0x2A<<10)); break; // override DIFFAMP=on, ODT=on\r
+        }\r
+        isbM32m(DDRPHY, (B0OVRCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), tempD, ((BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12|BIT11|BIT10))); // Override: DIFFAMP, ODT\r
+        isbM32m(DDRPHY, (B1OVRCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), tempD, ((BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12|BIT11|BIT10))); // Override: DIFFAMP, ODT\r
+\r
+        // DLL Setup\r
+        // 1xCLK Domain Timings: tEDP,RCVEN,WDQS (PO)\r
+        isbM32m(DDRPHY, (B0LATCTL0 + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (((tCAS+7)<<16)|((tCAS-4)<<8)|((tCWL-2)<<0)), ((BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT4|BIT3|BIT2|BIT1|BIT0))); // 1xCLK: tEDP, RCVEN, WDQS\r
+        isbM32m(DDRPHY, (B1LATCTL0 + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (((tCAS+7)<<16)|((tCAS-4)<<8)|((tCWL-2)<<0)), ((BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT4|BIT3|BIT2|BIT1|BIT0))); // 1xCLK: tEDP, RCVEN, WDQS\r
+\r
+        // RCVEN Bypass (PO)\r
+        isbM32m(DDRPHY, (B0RXIOBUFCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), ((0x0<<7)|(0x0<<0)), (BIT7|BIT0)); // AFE Bypass, RCVEN DIFFAMP\r
+        isbM32m(DDRPHY, (B1RXIOBUFCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), ((0x0<<7)|(0x0<<0)), (BIT7|BIT0)); // AFE Bypass, RCVEN DIFFAMP\r
+        // TX\r
+        isbM32m(DDRPHY, (DQCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (BIT16), (BIT16)); // 0 means driving DQ during DQS-preamble\r
+        isbM32m(DDRPHY, (B01PTRCTL1 + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (BIT8), (BIT8)); // WR_LVL mode disable\r
+        // RX (PO)\r
+        isbM32m(DDRPHY, (B0VREFCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), ((0x03<<2)|(0x0<<1)|(0x0<<0)), ((BIT7|BIT6|BIT5|BIT4|BIT3|BIT2)|BIT1|BIT0)); // Internal Vref Code, Enable#, Ext_or_Int (1=Ext)\r
+        isbM32m(DDRPHY, (B1VREFCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), ((0x03<<2)|(0x0<<1)|(0x0<<0)), ((BIT7|BIT6|BIT5|BIT4|BIT3|BIT2)|BIT1|BIT0)); // Internal Vref Code, Enable#, Ext_or_Int (1=Ext)\r
+        isbM32m(DDRPHY, (B0RXIOBUFCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (0), (BIT4)); // Per-Bit De-Skew Enable\r
+        isbM32m(DDRPHY, (B1RXIOBUFCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (0), (BIT4)); // Per-Bit De-Skew Enable\r
+      }\r
+      // CLKEBB\r
+      isbM32m(DDRPHY, (CMDOBSCKEBBCTL + (channel_i * DDRIOCCC_CH_OFFSET)), 0, (BIT23));\r
+\r
+      // Enable tristate control of cmd/address bus\r
+      isbM32m(DDRPHY, (CMDCFGREG0 + (channel_i * DDRIOCCC_CH_OFFSET)), 0, (BIT1|BIT0));\r
+\r
+      // ODT RCOMP\r
+      isbM32m(DDRPHY, (CMDRCOMPODT + (channel_i * DDRIOCCC_CH_OFFSET)), ((0x03<<5)|(0x03<<0)), ((BIT9|BIT8|BIT7|BIT6|BIT5)|(BIT4|BIT3|BIT2|BIT1|BIT0)));\r
+\r
+      // CMDPM* registers must be programmed in this order...\r
+      isbM32m(DDRPHY, (CMDPMDLYREG4 + (channel_i * DDRIOCCC_CH_OFFSET)), ((0xFFFFU<<16)|(0xFFFF<<0)), ((BIT31|BIT30|BIT29|BIT28|BIT27|BIT26|BIT25|BIT24|BIT23|BIT22|BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12|BIT11|BIT10|BIT9|BIT8|BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0))); // Turn On Delays: SFR (regulator), MPLL\r
+      isbM32m(DDRPHY, (CMDPMDLYREG3 + (channel_i * DDRIOCCC_CH_OFFSET)), ((0xFU<<28)|(0xFFF<<16)|(0xF<<12)|(0x616<<0)), ((BIT31|BIT30|BIT29|BIT28)|(BIT27|BIT26|BIT25|BIT24|BIT23|BIT22|BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12)|(BIT11|BIT10|BIT9|BIT8|BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0))); // Delays: ASSERT_IOBUFACT_to_ALLON0_for_PM_MSG_3, VREG (MDLL) Turn On, ALLON0_to_DEASSERT_IOBUFACT_for_PM_MSG_gt0, MDLL Turn On\r
+      isbM32m(DDRPHY, (CMDPMDLYREG2 + (channel_i * DDRIOCCC_CH_OFFSET)), ((0xFFU<<24)|(0xFF<<16)|(0xFF<<8)|(0xFF<<0)), ((BIT31|BIT30|BIT29|BIT28|BIT27|BIT26|BIT25|BIT24)|(BIT23|BIT22|BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0))); // MPLL Divider Reset Delays\r
+      isbM32m(DDRPHY, (CMDPMDLYREG1 + (channel_i * DDRIOCCC_CH_OFFSET)), ((0xFFU<<24)|(0xFF<<16)|(0xFF<<8)|(0xFF<<0)), ((BIT31|BIT30|BIT29|BIT28|BIT27|BIT26|BIT25|BIT24)|(BIT23|BIT22|BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0))); // Turn Off Delays: VREG, Staggered MDLL, MDLL, PI\r
+      isbM32m(DDRPHY, (CMDPMDLYREG0 + (channel_i * DDRIOCCC_CH_OFFSET)), ((0xFFU<<24)|(0xFF<<16)|(0xFF<<8)|(0xFF<<0)), ((BIT31|BIT30|BIT29|BIT28|BIT27|BIT26|BIT25|BIT24)|(BIT23|BIT22|BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0))); // Turn On Delays: MPLL, Staggered MDLL, PI, IOBUFACT\r
+      isbM32m(DDRPHY, (CMDPMCONFIG0 + (channel_i * DDRIOCCC_CH_OFFSET)), ((0x6<<8)|BIT6|(0x4<<0)), (BIT31|BIT30|BIT29|BIT28|BIT27|BIT26|BIT25|BIT24|BIT23|BIT22|BIT21|(BIT11|BIT10|BIT9|BIT8)|BIT6|(BIT3|BIT2|BIT1|BIT0))); // Allow PUnit signals\r
+      isbM32m(DDRPHY, (CMDMDLLCTL +   (channel_i * DDRIOCCC_CH_OFFSET)), ((0x3<<4)|(0x7<<0)), ((BIT6|BIT5|BIT4)|(BIT3|BIT2|BIT1|BIT0))); // DLL_VREG Bias Trim, VREF Tuning for DLL_VREG\r
+      // CLK-CTL\r
+      isbM32m(DDRPHY, (CCOBSCKEBBCTL + (channel_i * DDRIOCCC_CH_OFFSET)), 0, (BIT24)); // CLKEBB\r
+      isbM32m(DDRPHY, (CCCFGREG0 +     (channel_i * DDRIOCCC_CH_OFFSET)), ((0x0<<16)|(0x0<<12)|(0x0<<8)|(0xF<<4)|BIT0), ((BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12)|(BIT11|BIT10|BIT9|BIT8)|(BIT7|BIT6|BIT5|BIT4)|BIT0)); // Buffer Enable: CS,CKE,ODT,CLK\r
+      isbM32m(DDRPHY, (CCRCOMPODT +    (channel_i * DDRIOCCC_CH_OFFSET)), ((0x03<<8)|(0x03<<0)), ((BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT4|BIT3|BIT2|BIT1|BIT0))); // ODT RCOMP\r
+      isbM32m(DDRPHY, (CCMDLLCTL +     (channel_i * DDRIOCCC_CH_OFFSET)), ((0x3<<4)|(0x7<<0)), ((BIT6|BIT5|BIT4)|(BIT3|BIT2|BIT1|BIT0))); // DLL_VREG Bias Trim, VREF Tuning for DLL_VREG\r
+\r
+      // COMP (RON channel specific)\r
+      // - DQ/DQS/DM RON: 32 Ohm\r
+      // - CTRL/CMD RON: 27 Ohm\r
+      // - CLK RON: 26 Ohm\r
+      isbM32m(DDRPHY, (DQVREFCH0 +  (channel_i * DDRCOMP_CH_OFFSET)), ((0x08<<24)|(0x03<<16)), ((BIT29|BIT28|BIT27|BIT26|BIT25|BIT24)|(BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)));  // RCOMP Vref PU/PD\r
+      isbM32m(DDRPHY, (CMDVREFCH0 + (channel_i * DDRCOMP_CH_OFFSET)), ((0x0C<<24)|(0x03<<16)), ((BIT29|BIT28|BIT27|BIT26|BIT25|BIT24)|(BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)));  // RCOMP Vref PU/PD\r
+      isbM32m(DDRPHY, (CLKVREFCH0 + (channel_i * DDRCOMP_CH_OFFSET)), ((0x0F<<24)|(0x03<<16)), ((BIT29|BIT28|BIT27|BIT26|BIT25|BIT24)|(BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)));  // RCOMP Vref PU/PD\r
+      isbM32m(DDRPHY, (DQSVREFCH0 + (channel_i * DDRCOMP_CH_OFFSET)), ((0x08<<24)|(0x03<<16)), ((BIT29|BIT28|BIT27|BIT26|BIT25|BIT24)|(BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)));  // RCOMP Vref PU/PD\r
+      isbM32m(DDRPHY, (CTLVREFCH0 + (channel_i * DDRCOMP_CH_OFFSET)), ((0x0C<<24)|(0x03<<16)), ((BIT29|BIT28|BIT27|BIT26|BIT25|BIT24)|(BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)));  // RCOMP Vref PU/PD\r
+\r
+      // DQS Swapped Input Enable\r
+      isbM32m(DDRPHY, (COMPEN1CH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT19|BIT17),           ((BIT31|BIT30)|BIT19|BIT17|(BIT15|BIT14)));\r
+\r
+      // ODT VREF = 1.5 x 274/360+274 = 0.65V (code of ~50)\r
+      isbM32m(DDRPHY, (DQVREFCH0 +  (channel_i * DDRCOMP_CH_OFFSET)), ((0x32<<8)|(0x03<<0)),   ((BIT13|BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT5|BIT4|BIT3|BIT2|BIT1|BIT0))); // ODT Vref PU/PD\r
+      isbM32m(DDRPHY, (DQSVREFCH0 + (channel_i * DDRCOMP_CH_OFFSET)), ((0x32<<8)|(0x03<<0)),   ((BIT13|BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT5|BIT4|BIT3|BIT2|BIT1|BIT0))); // ODT Vref PU/PD\r
+      isbM32m(DDRPHY, (CLKVREFCH0 + (channel_i * DDRCOMP_CH_OFFSET)), ((0x0E<<8)|(0x05<<0)),   ((BIT13|BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT5|BIT4|BIT3|BIT2|BIT1|BIT0))); // ODT Vref PU/PD\r
+\r
+      // Slew rate settings are frequency specific, numbers below are for 800Mhz (speed == 0)\r
+      // - DQ/DQS/DM/CLK SR: 4V/ns,\r
+      // - CTRL/CMD SR: 1.5V/ns\r
+      tempD = (0x0E<<16)|(0x0E<<12)|(0x08<<8)|(0x0B<<4)|(0x0B<<0);\r
+      isbM32m(DDRPHY, (DLYSELCH0 +   (channel_i * DDRCOMP_CH_OFFSET)), (tempD), ((BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12)|(BIT11|BIT10|BIT9|BIT8)|(BIT7|BIT6|BIT5|BIT4)|(BIT3|BIT2|BIT1|BIT0))); // DCOMP Delay Select: CTL,CMD,CLK,DQS,DQ\r
+      isbM32m(DDRPHY, (TCOVREFCH0 +  (channel_i * DDRCOMP_CH_OFFSET)), ((0x05<<16)|(0x05<<8)|(0x05<<0)), ((BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT13|BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT5|BIT4|BIT3|BIT2|BIT1|BIT0))); // TCO Vref CLK,DQS,DQ\r
+      isbM32m(DDRPHY, (CCBUFODTCH0 + (channel_i * DDRCOMP_CH_OFFSET)), ((0x03<<8)|(0x03<<0)), ((BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT4|BIT3|BIT2|BIT1|BIT0))); // ODTCOMP CMD/CTL PU/PD\r
+      isbM32m(DDRPHY, (COMPEN0CH0 +  (channel_i * DDRCOMP_CH_OFFSET)), (0), ((BIT31|BIT30)|BIT8)); // COMP\r
+\r
+      #ifdef BACKUP_COMPS\r
+      // DQ COMP Overrides\r
+      isbM32m(DDRPHY, (DQDRVPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0A<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP PU\r
+      isbM32m(DDRPHY, (DQDRVPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0A<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP PD\r
+      isbM32m(DDRPHY, (DQDLYPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x10<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // DCOMP PU\r
+      isbM32m(DDRPHY, (DQDLYPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x10<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // DCOMP PD\r
+      isbM32m(DDRPHY, (DQODTPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0B<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // ODTCOMP PU\r
+      isbM32m(DDRPHY, (DQODTPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0B<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // ODTCOMP PD\r
+      isbM32m(DDRPHY, (DQTCOPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31), (BIT31)); // TCOCOMP PU\r
+      isbM32m(DDRPHY, (DQTCOPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31), (BIT31)); // TCOCOMP PD\r
+      // DQS COMP Overrides\r
+      isbM32m(DDRPHY, (DQSDRVPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0A<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP PU\r
+      isbM32m(DDRPHY, (DQSDRVPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0A<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP PD\r
+      isbM32m(DDRPHY, (DQSDLYPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x10<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // DCOMP PU\r
+      isbM32m(DDRPHY, (DQSDLYPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x10<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // DCOMP PD\r
+      isbM32m(DDRPHY, (DQSODTPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0B<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // ODTCOMP PU\r
+      isbM32m(DDRPHY, (DQSODTPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0B<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // ODTCOMP PD\r
+      isbM32m(DDRPHY, (DQSTCOPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31), (BIT31)); // TCOCOMP PU\r
+      isbM32m(DDRPHY, (DQSTCOPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31), (BIT31)); // TCOCOMP PD\r
+      // CLK COMP Overrides\r
+      isbM32m(DDRPHY, (CLKDRVPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0C<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP PU\r
+      isbM32m(DDRPHY, (CLKDRVPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0C<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP PD\r
+      isbM32m(DDRPHY, (CLKDLYPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x07<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // DCOMP PU\r
+      isbM32m(DDRPHY, (CLKDLYPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x07<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // DCOMP PD\r
+      isbM32m(DDRPHY, (CLKODTPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0B<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // ODTCOMP PU\r
+      isbM32m(DDRPHY, (CLKODTPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0B<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // ODTCOMP PD\r
+      isbM32m(DDRPHY, (CLKTCOPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31), (BIT31)); // TCOCOMP PU\r
+      isbM32m(DDRPHY, (CLKTCOPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31), (BIT31)); // TCOCOMP PD\r
+      // CMD COMP Overrides\r
+      isbM32m(DDRPHY, (CMDDRVPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0D<<16)), (BIT31|(BIT21|BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP PU\r
+      isbM32m(DDRPHY, (CMDDRVPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0D<<16)), (BIT31|(BIT21|BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP PD\r
+      isbM32m(DDRPHY, (CMDDLYPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0A<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // DCOMP PU\r
+      isbM32m(DDRPHY, (CMDDLYPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0A<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // DCOMP PD\r
+      // CTL COMP Overrides\r
+      isbM32m(DDRPHY, (CTLDRVPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0D<<16)), (BIT31|(BIT21|BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP PU\r
+      isbM32m(DDRPHY, (CTLDRVPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0D<<16)), (BIT31|(BIT21|BIT20|BIT19|BIT18|BIT17|BIT16))); // RCOMP PD\r
+      isbM32m(DDRPHY, (CTLDLYPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0A<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // DCOMP PU\r
+      isbM32m(DDRPHY, (CTLDLYPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x0A<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // DCOMP PD\r
+      #else\r
+      // DQ TCOCOMP Overrides\r
+      isbM32m(DDRPHY, (DQTCOPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x1F<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // TCOCOMP PU\r
+      isbM32m(DDRPHY, (DQTCOPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x1F<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // TCOCOMP PD\r
+      // DQS TCOCOMP Overrides\r
+      isbM32m(DDRPHY, (DQSTCOPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x1F<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // TCOCOMP PU\r
+      isbM32m(DDRPHY, (DQSTCOPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x1F<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // TCOCOMP PD\r
+      // CLK TCOCOMP Overrides\r
+      isbM32m(DDRPHY, (CLKTCOPUCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x1F<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // TCOCOMP PU\r
+      isbM32m(DDRPHY, (CLKTCOPDCTLCH0 + (channel_i * DDRCOMP_CH_OFFSET)), (BIT31|(0x1F<<16)), (BIT31|(BIT20|BIT19|BIT18|BIT17|BIT16))); // TCOCOMP PD\r
+      #endif // BACKUP_COMPS\r
+      // program STATIC delays\r
+      #ifdef BACKUP_WCMD\r
+      set_wcmd(channel_i, ddr_wcmd[PLATFORM_ID]);\r
+      #else\r
+      set_wcmd(channel_i, ddr_wclk[PLATFORM_ID] + HALF_CLK);\r
+      #endif // BACKUP_WCMD\r
+      for (rank_i=0; rank_i<NUM_RANKS; rank_i++) {\r
+        if (mrc_params->rank_enables & (1<<rank_i)) {\r
+          set_wclk(channel_i, rank_i, ddr_wclk[PLATFORM_ID]);\r
+          #ifdef BACKUP_WCTL\r
+          set_wctl(channel_i, rank_i, ddr_wctl[PLATFORM_ID]);\r
+          #else\r
+          set_wctl(channel_i, rank_i, ddr_wclk[PLATFORM_ID] + HALF_CLK);\r
+          #endif // BACKUP_WCTL\r
+        }\r
+      }\r
+    }\r
+  }\r
+  // COMP (non channel specific)\r
+  //isbM32m(DDRPHY, (), (), ());\r
+  isbM32m(DDRPHY, (DQANADRVPUCTL), (BIT30), (BIT30)); // RCOMP: Dither PU Enable\r
+  isbM32m(DDRPHY, (DQANADRVPDCTL), (BIT30), (BIT30)); // RCOMP: Dither PD Enable\r
+  isbM32m(DDRPHY, (CMDANADRVPUCTL), (BIT30), (BIT30)); // RCOMP: Dither PU Enable\r
+  isbM32m(DDRPHY, (CMDANADRVPDCTL), (BIT30), (BIT30)); // RCOMP: Dither PD Enable\r
+  isbM32m(DDRPHY, (CLKANADRVPUCTL), (BIT30), (BIT30)); // RCOMP: Dither PU Enable\r
+  isbM32m(DDRPHY, (CLKANADRVPDCTL), (BIT30), (BIT30)); // RCOMP: Dither PD Enable\r
+  isbM32m(DDRPHY, (DQSANADRVPUCTL), (BIT30), (BIT30)); // RCOMP: Dither PU Enable\r
+  isbM32m(DDRPHY, (DQSANADRVPDCTL), (BIT30), (BIT30)); // RCOMP: Dither PD Enable\r
+  isbM32m(DDRPHY, (CTLANADRVPUCTL), (BIT30), (BIT30)); // RCOMP: Dither PU Enable\r
+  isbM32m(DDRPHY, (CTLANADRVPDCTL), (BIT30), (BIT30)); // RCOMP: Dither PD Enable\r
+  isbM32m(DDRPHY, (DQANAODTPUCTL), (BIT30), (BIT30)); // ODT: Dither PU Enable\r
+  isbM32m(DDRPHY, (DQANAODTPDCTL), (BIT30), (BIT30)); // ODT: Dither PD Enable\r
+  isbM32m(DDRPHY, (CLKANAODTPUCTL), (BIT30), (BIT30)); // ODT: Dither PU Enable\r
+  isbM32m(DDRPHY, (CLKANAODTPDCTL), (BIT30), (BIT30)); // ODT: Dither PD Enable\r
+  isbM32m(DDRPHY, (DQSANAODTPUCTL), (BIT30), (BIT30)); // ODT: Dither PU Enable\r
+  isbM32m(DDRPHY, (DQSANAODTPDCTL), (BIT30), (BIT30)); // ODT: Dither PD Enable\r
+  isbM32m(DDRPHY, (DQANADLYPUCTL), (BIT30), (BIT30)); // DCOMP: Dither PU Enable\r
+  isbM32m(DDRPHY, (DQANADLYPDCTL), (BIT30), (BIT30)); // DCOMP: Dither PD Enable\r
+  isbM32m(DDRPHY, (CMDANADLYPUCTL), (BIT30), (BIT30)); // DCOMP: Dither PU Enable\r
+  isbM32m(DDRPHY, (CMDANADLYPDCTL), (BIT30), (BIT30)); // DCOMP: Dither PD Enable\r
+  isbM32m(DDRPHY, (CLKANADLYPUCTL), (BIT30), (BIT30)); // DCOMP: Dither PU Enable\r
+  isbM32m(DDRPHY, (CLKANADLYPDCTL), (BIT30), (BIT30)); // DCOMP: Dither PD Enable\r
+  isbM32m(DDRPHY, (DQSANADLYPUCTL), (BIT30), (BIT30)); // DCOMP: Dither PU Enable\r
+  isbM32m(DDRPHY, (DQSANADLYPDCTL), (BIT30), (BIT30)); // DCOMP: Dither PD Enable\r
+  isbM32m(DDRPHY, (CTLANADLYPUCTL), (BIT30), (BIT30)); // DCOMP: Dither PU Enable\r
+  isbM32m(DDRPHY, (CTLANADLYPDCTL), (BIT30), (BIT30)); // DCOMP: Dither PD Enable\r
+  isbM32m(DDRPHY, (DQANATCOPUCTL), (BIT30), (BIT30)); // TCO: Dither PU Enable\r
+  isbM32m(DDRPHY, (DQANATCOPDCTL), (BIT30), (BIT30)); // TCO: Dither PD Enable\r
+  isbM32m(DDRPHY, (CLKANATCOPUCTL), (BIT30), (BIT30)); // TCO: Dither PU Enable\r
+  isbM32m(DDRPHY, (CLKANATCOPDCTL), (BIT30), (BIT30)); // TCO: Dither PD Enable\r
+  isbM32m(DDRPHY, (DQSANATCOPUCTL), (BIT30), (BIT30)); // TCO: Dither PU Enable\r
+  isbM32m(DDRPHY, (DQSANATCOPDCTL), (BIT30), (BIT30)); // TCO: Dither PD Enable\r
+  isbM32m(DDRPHY, (TCOCNTCTRL), (0x1<<0), (BIT1|BIT0)); // TCOCOMP: Pulse Count\r
+  isbM32m(DDRPHY, (CHNLBUFSTATIC), ((0x03<<24)|(0x03<<16)), ((BIT28|BIT27|BIT26|BIT25|BIT24)|(BIT20|BIT19|BIT18|BIT17|BIT16))); // ODT: CMD/CTL PD/PU\r
+  isbM32m(DDRPHY, (MSCNTR), (0x64<<0), (BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0)); // Set 1us counter\r
+  isbM32m(DDRPHY, (LATCH1CTL), (0x1<<28), (BIT30|BIT29|BIT28)); // ???\r
+\r
+  // Release PHY from reset\r
+  isbM32m(DDRPHY, MASTERRSTN, BIT0, BIT0); // PHYRSTN=1\r
+\r
+  // STEP1:\r
+  post_code(0x03, 0x11);\r
+  for (channel_i=0; channel_i<NUM_CHANNELS; channel_i++) {\r
+    if (mrc_params->channel_enables & (1<<channel_i)) {\r
+      // DQ01-DQ23\r
+      for (bl_grp_i=0; bl_grp_i<((NUM_BYTE_LANES/bl_divisor)/2); bl_grp_i++) {\r
+        isbM32m(DDRPHY, (DQMDLLCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (BIT13), (BIT13)); // Enable VREG\r
+        delay_n(3);\r
+      }\r
+      // ECC\r
+      isbM32m(DDRPHY, (ECCMDLLCTL), (BIT13), (BIT13)); // Enable VREG\r
+      delay_n(3);\r
+      // CMD\r
+      isbM32m(DDRPHY, (CMDMDLLCTL + (channel_i * DDRIOCCC_CH_OFFSET)), (BIT13), (BIT13)); // Enable VREG\r
+      delay_n(3);\r
+      // CLK-CTL\r
+      isbM32m(DDRPHY, (CCMDLLCTL + (channel_i * DDRIOCCC_CH_OFFSET)), (BIT13), (BIT13)); // Enable VREG\r
+      delay_n(3);\r
+    }\r
+  }\r
+\r
+  // STEP2:\r
+  post_code(0x03, 0x12);\r
+  delay_n(200);\r
+  for (channel_i=0; channel_i<NUM_CHANNELS; channel_i++) {\r
+    if (mrc_params->channel_enables & (1<<channel_i)) {\r
+      // DQ01-DQ23\r
+      for (bl_grp_i=0; bl_grp_i<((NUM_BYTE_LANES/bl_divisor)/2); bl_grp_i++) {\r
+        isbM32m(DDRPHY, (DQMDLLCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (BIT17), (BIT17)); // Enable MCDLL\r
+        delay_n(50);\r
+      }\r
+      // ECC\r
+      isbM32m(DDRPHY, (ECCMDLLCTL), (BIT17), (BIT17)); // Enable MCDLL\r
+      delay_n(50);\r
+      // CMD\r
+      isbM32m(DDRPHY, (CMDMDLLCTL + (channel_i * DDRIOCCC_CH_OFFSET)), (BIT18), (BIT18)); // Enable MCDLL\r
+      delay_n(50);\r
+      // CLK-CTL\r
+      isbM32m(DDRPHY, (CCMDLLCTL + (channel_i * DDRIOCCC_CH_OFFSET)), (BIT18), (BIT18)); // Enable MCDLL\r
+      delay_n(50);\r
+    }\r
+  }\r
+\r
+  // STEP3:\r
+  post_code(0x03, 0x13);\r
+  delay_n(100);\r
+  for (channel_i=0; channel_i<NUM_CHANNELS; channel_i++) {\r
+    if (mrc_params->channel_enables & (1<<channel_i)) {\r
+      // DQ01-DQ23\r
+      for (bl_grp_i=0; bl_grp_i<((NUM_BYTE_LANES/bl_divisor)/2); bl_grp_i++) {\r
+#ifdef FORCE_16BIT_DDRIO\r
+        tempD = ((bl_grp_i) && (mrc_params->channel_width == x16)) ? ((0x1<<12)|(0x1<<8)|(0xF<<4)|(0xF<<0)) : ((0xF<<12)|(0xF<<8)|(0xF<<4)|(0xF<<0));\r
+#else\r
+        tempD = ((0xF<<12)|(0xF<<8)|(0xF<<4)|(0xF<<0));\r
+#endif\r
+        isbM32m(DDRPHY, (DQDLLTXCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (tempD), ((BIT15|BIT14|BIT13|BIT12)|(BIT11|BIT10|BIT9|BIT8)|(BIT7|BIT6|BIT5|BIT4)|(BIT3|BIT2|BIT1|BIT0))); // Enable TXDLL\r
+        delay_n(3);\r
+        isbM32m(DDRPHY, (DQDLLRXCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (BIT3|BIT2|BIT1|BIT0), (BIT3|BIT2|BIT1|BIT0)); // Enable RXDLL\r
+        delay_n(3);\r
+        isbM32m(DDRPHY, (B0OVRCTL + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), (BIT3|BIT2|BIT1|BIT0), (BIT3|BIT2|BIT1|BIT0)); // Enable RXDLL Overrides BL0\r
+      }\r
+\r
+      // ECC\r
+      tempD = ((0xF<<12)|(0xF<<8)|(0xF<<4)|(0xF<<0));\r
+      isbM32m(DDRPHY, (ECCDLLTXCTL), (tempD), ((BIT15|BIT14|BIT13|BIT12)|(BIT11|BIT10|BIT9|BIT8)|(BIT7|BIT6|BIT5|BIT4)|(BIT3|BIT2|BIT1|BIT0))); // Enable TXDLL\r
+      delay_n(3);\r
+\r
+      // CMD (PO)\r
+      isbM32m(DDRPHY, (CMDDLLTXCTL + (channel_i * DDRIOCCC_CH_OFFSET)), ((0xF<<12)|(0xF<<8)|(0xF<<4)|(0xF<<0)), ((BIT15|BIT14|BIT13|BIT12)|(BIT11|BIT10|BIT9|BIT8)|(BIT7|BIT6|BIT5|BIT4)|(BIT3|BIT2|BIT1|BIT0))); // Enable TXDLL\r
+      delay_n(3);\r
+    }\r
+  }\r
+\r
+\r
+  // STEP4:\r
+  post_code(0x03, 0x14);\r
+  for (channel_i=0; channel_i<NUM_CHANNELS; channel_i++) {\r
+    if (mrc_params->channel_enables & (1<<channel_i)) {\r
+      // Host To Memory Clock Alignment (HMC) for 800/1066\r
+      for (bl_grp_i=0; bl_grp_i<((NUM_BYTE_LANES/bl_divisor)/2); bl_grp_i++) {\r
+        isbM32m(DDRPHY, (DQCLKALIGNREG2 + (bl_grp_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), ((bl_grp_i)?(0x3):(0x1)), (BIT3|BIT2|BIT1|BIT0)); // CLK_ALIGN_MOD_ID\r
+      }\r
+      isbM32m(DDRPHY, (ECCCLKALIGNREG2 + (channel_i * DDRIODQ_CH_OFFSET)), 0x2, (BIT3|BIT2|BIT1|BIT0)); // CLK_ALIGN_MOD_ID\r
+      isbM32m(DDRPHY, (CMDCLKALIGNREG2 + (channel_i * DDRIODQ_CH_OFFSET)), 0x0, (BIT3|BIT2|BIT1|BIT0)); // CLK_ALIGN_MOD_ID\r
+      isbM32m(DDRPHY, (CCCLKALIGNREG2 + (channel_i * DDRIODQ_CH_OFFSET)), 0x2, (BIT3|BIT2|BIT1|BIT0)); // CLK_ALIGN_MOD_ID\r
+      isbM32m(DDRPHY, (CMDCLKALIGNREG0 + (channel_i * DDRIOCCC_CH_OFFSET)), (0x2<<4), (BIT5|BIT4)); // CLK_ALIGN_MODE\r
+      isbM32m(DDRPHY, (CMDCLKALIGNREG1 + (channel_i * DDRIOCCC_CH_OFFSET)), ((0x18<<16)|(0x10<<8)|(0x8<<2)|(0x1<<0)), ((BIT22|BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT14|BIT13|BIT12|BIT11|BIT10|BIT9|BIT8)|(BIT7|BIT6|BIT5|BIT4|BIT3|BIT2)|(BIT1|BIT0))); // NUM_SAMPLES, MAX_SAMPLES, MACRO_PI_STEP, MICRO_PI_STEP\r
+      isbM32m(DDRPHY, (CMDCLKALIGNREG2 + (channel_i * DDRIOCCC_CH_OFFSET)), ((0x10<<16)|(0x4<<8)|(0x2<<4)), ((BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT11|BIT10|BIT9|BIT8)|(BIT7|BIT6|BIT5|BIT4))); // ???, TOTAL_NUM_MODULES, FIRST_U_PARTITION\r
+      #ifdef HMC_TEST\r
+      isbM32m(DDRPHY, (CMDCLKALIGNREG0 + (channel_i * DDRIOCCC_CH_OFFSET)), BIT24, BIT24); // START_CLK_ALIGN=1\r
+      while (isbR32m(DDRPHY, (CMDCLKALIGNREG0 + (channel_i * DDRIOCCC_CH_OFFSET))) & BIT24); // wait for START_CLK_ALIGN=0\r
+      #endif // HMC_TEST\r
+\r
+      // Set RD/WR Pointer Seperation & COUNTEN & FIFOPTREN\r
+      isbM32m(DDRPHY, (CMDPTRREG + (channel_i * DDRIOCCC_CH_OFFSET)), BIT0, BIT0); // WRPTRENABLE=1\r
+\r
+\r
+#ifdef SIM\r
+      // comp is not working on simulator\r
+#else\r
+      // COMP initial\r
+      isbM32m(DDRPHY, (COMPEN0CH0 + (channel_i * DDRCOMP_CH_OFFSET)), BIT5, BIT5); // enable bypass for CLK buffer (PO)\r
+      isbM32m(DDRPHY, (CMPCTRL), (BIT0), (BIT0)); // Initial COMP Enable\r
+      while (isbR32m(DDRPHY, (CMPCTRL)) & BIT0); // wait for Initial COMP Enable = 0\r
+      isbM32m(DDRPHY, (COMPEN0CH0 + (channel_i * DDRCOMP_CH_OFFSET)), ~BIT5, BIT5); // disable bypass for CLK buffer (PO)\r
+#endif\r
+\r
+      // IOBUFACT\r
+      // STEP4a\r
+      isbM32m(DDRPHY, (CMDCFGREG0 + (channel_i * DDRIOCCC_CH_OFFSET)), BIT2, BIT2); // IOBUFACTRST_N=1\r
+\r
+      // DDRPHY initialisation complete\r
+      isbM32m(DDRPHY, (CMDPMCONFIG0 + (channel_i * DDRIOCCC_CH_OFFSET)), BIT20, BIT20); // SPID_INIT_COMPLETE=1\r
+    }\r
+  }\r
+\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
+// jedec_init (aka PerformJedecInit):\r
+// This function performs JEDEC initialisation on all enabled channels.\r
+static void jedec_init(\r
+    MRCParams_t *mrc_params,\r
+    uint32_t silent)\r
+{\r
+  uint8_t TWR, WL, Rank;\r
+  uint32_t TCK;\r
+\r
+  RegDTR0 DTR0reg;\r
+\r
+  DramInitDDR3MRS0 mrs0Command;\r
+  DramInitDDR3EMR1 emrs1Command;\r
+  DramInitDDR3EMR2 emrs2Command;\r
+  DramInitDDR3EMR3 emrs3Command;\r
+\r
+  ENTERFN();\r
+\r
+  // jedec_init starts\r
+  if (!silent)\r
+  {\r
+    post_code(0x04, 0x00);\r
+  }\r
+\r
+  // Assert RESET# for 200us\r
+  isbM32m(DDRPHY, CCDDR3RESETCTL, BIT1, (BIT8|BIT1)); // DDR3_RESET_SET=0, DDR3_RESET_RESET=1\r
+#ifdef QUICKSIM\r
+      // Don't waste time during simulation\r
+      delay_u(2);\r
+#else\r
+  delay_u(200);\r
+#endif\r
+  isbM32m(DDRPHY, CCDDR3RESETCTL, BIT8, (BIT8|BIT1)); // DDR3_RESET_SET=1, DDR3_RESET_RESET=0\r
+\r
+  DTR0reg.raw = isbR32m(MCU, DTR0);\r
+\r
+  // Set CKEVAL for populated ranks\r
+  // then send NOP to each rank (#4550197)\r
+  {\r
+    uint32_t DRPbuffer;\r
+    uint32_t DRMCbuffer;\r
+\r
+    DRPbuffer = isbR32m(MCU, DRP);\r
+    DRPbuffer &= 0x3;\r
+    DRMCbuffer = isbR32m(MCU, DRMC);\r
+    DRMCbuffer &= 0xFFFFFFFC;\r
+    DRMCbuffer |= (BIT4 | DRPbuffer);\r
+\r
+    isbW32m(MCU, DRMC, DRMCbuffer);\r
+\r
+    for (Rank = 0; Rank < NUM_RANKS; Rank++)\r
+    {\r
+      // Skip to next populated rank\r
+      if ((mrc_params->rank_enables & (1 << Rank)) == 0)\r
+      {\r
+        continue;\r
+      }\r
+\r
+      dram_init_command(DCMD_NOP(Rank));\r
+    }\r
+\r
+    isbW32m(MCU, DRMC, DRMC_DEFAULT);\r
+  }\r
+\r
+  // setup for emrs 2\r
+  // BIT[15:11] --> Always "0"\r
+  // BIT[10:09] --> Rtt_WR: want "Dynamic ODT Off" (0)\r
+  // BIT[08]    --> Always "0"\r
+  // BIT[07]    --> SRT: use sr_temp_range\r
+  // BIT[06]    --> ASR: want "Manual SR Reference" (0)\r
+  // BIT[05:03] --> CWL: use oem_tCWL\r
+  // BIT[02:00] --> PASR: want "Full Array" (0)\r
+  emrs2Command.raw = 0;\r
+  emrs2Command.field.bankAddress = 2;\r
+\r
+  WL = 5 + mrc_params->ddr_speed;\r
+  emrs2Command.field.CWL = WL - 5;\r
+  emrs2Command.field.SRT = mrc_params->sr_temp_range;\r
+\r
+  // setup for emrs 3\r
+  // BIT[15:03] --> Always "0"\r
+  // BIT[02]    --> MPR: want "Normal Operation" (0)\r
+  // BIT[01:00] --> MPR_Loc: want "Predefined Pattern" (0)\r
+  emrs3Command.raw = 0;\r
+  emrs3Command.field.bankAddress = 3;\r
+\r
+  // setup for emrs 1\r
+  // BIT[15:13]     --> Always "0"\r
+  // BIT[12:12]     --> Qoff: want "Output Buffer Enabled" (0)\r
+  // BIT[11:11]     --> TDQS: want "Disabled" (0)\r
+  // BIT[10:10]     --> Always "0"\r
+  // BIT[09,06,02]  --> Rtt_nom: use rtt_nom_value\r
+  // BIT[08]        --> Always "0"\r
+  // BIT[07]        --> WR_LVL: want "Disabled" (0)\r
+  // BIT[05,01]     --> DIC: use ron_value\r
+  // BIT[04:03]     --> AL: additive latency want "0" (0)\r
+  // BIT[00]        --> DLL: want "Enable" (0)\r
+  //\r
+  // (BIT5|BIT1) set Ron value\r
+  // 00 --> RZQ/6 (40ohm)\r
+  // 01 --> RZQ/7 (34ohm)\r
+  // 1* --> RESERVED\r
+  //\r
+  // (BIT9|BIT6|BIT2) set Rtt_nom value\r
+  // 000 --> Disabled\r
+  // 001 --> RZQ/4 ( 60ohm)\r
+  // 010 --> RZQ/2 (120ohm)\r
+  // 011 --> RZQ/6 ( 40ohm)\r
+  // 1** --> RESERVED\r
+  emrs1Command.raw = 0;\r
+  emrs1Command.field.bankAddress = 1;\r
+  emrs1Command.field.dllEnabled = 0; // 0 = Enable , 1 = Disable\r
+\r
+  if (mrc_params->ron_value == 0)\r
+  {\r
+    emrs1Command.field.DIC0 = DDR3_EMRS1_DIC_34;\r
+  }\r
+  else\r
+  {\r
+    emrs1Command.field.DIC0 = DDR3_EMRS1_DIC_40;\r
+  }\r
+\r
+\r
+  if (mrc_params->rtt_nom_value == 0)\r
+  {\r
+    emrs1Command.raw |= (DDR3_EMRS1_RTTNOM_40 << 6);\r
+  }\r
+  else if (mrc_params->rtt_nom_value == 1)\r
+  {\r
+    emrs1Command.raw |= (DDR3_EMRS1_RTTNOM_60 << 6);\r
+  }\r
+  else if (mrc_params->rtt_nom_value == 2)\r
+  {\r
+    emrs1Command.raw |= (DDR3_EMRS1_RTTNOM_120 << 6);\r
+  }\r
+\r
+  // save MRS1 value (excluding control fields)\r
+  mrc_params->mrs1 = emrs1Command.raw >> 6;\r
+\r
+  // setup for mrs 0\r
+  // BIT[15:13]     --> Always "0"\r
+  // BIT[12]        --> PPD: for Quark (1)\r
+  // BIT[11:09]     --> WR: use oem_tWR\r
+  // BIT[08]        --> DLL: want "Reset" (1, self clearing)\r
+  // BIT[07]        --> MODE: want "Normal" (0)\r
+  // BIT[06:04,02]  --> CL: use oem_tCAS\r
+  // BIT[03]        --> RD_BURST_TYPE: want "Interleave" (1)\r
+  // BIT[01:00]     --> BL: want "8 Fixed" (0)\r
+  // WR:\r
+  // 0 --> 16\r
+  // 1 --> 5\r
+  // 2 --> 6\r
+  // 3 --> 7\r
+  // 4 --> 8\r
+  // 5 --> 10\r
+  // 6 --> 12\r
+  // 7 --> 14\r
+  // CL:\r
+  // BIT[02:02] "0" if oem_tCAS <= 11 (1866?)\r
+  // BIT[06:04] use oem_tCAS-4\r
+  mrs0Command.raw = 0;\r
+  mrs0Command.field.bankAddress = 0;\r
+  mrs0Command.field.dllReset = 1;\r
+  mrs0Command.field.BL = 0;\r
+  mrs0Command.field.PPD = 1;\r
+  mrs0Command.field.casLatency = DTR0reg.field.tCL + 1;\r
+\r
+  TCK = tCK[mrc_params->ddr_speed];\r
+  TWR = MCEIL(15000, TCK);   // Per JEDEC: tWR=15000ps DDR2/3 from 800-1600\r
+  mrs0Command.field.writeRecovery = TWR - 4;\r
+\r
+  for (Rank = 0; Rank < NUM_RANKS; Rank++)\r
+  {\r
+    // Skip to next populated rank\r
+    if ((mrc_params->rank_enables & (1 << Rank)) == 0)\r
+    {\r
+      continue;\r
+    }\r
+\r
+    emrs2Command.field.rankSelect = Rank;\r
+    dram_init_command(emrs2Command.raw);\r
+\r
+    emrs3Command.field.rankSelect = Rank;\r
+    dram_init_command(emrs3Command.raw);\r
+\r
+    emrs1Command.field.rankSelect = Rank;\r
+    dram_init_command(emrs1Command.raw);\r
+\r
+    mrs0Command.field.rankSelect = Rank;\r
+    dram_init_command(mrs0Command.raw);\r
+\r
+    dram_init_command(DCMD_ZQCL(Rank));\r
+  }\r
+\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
+// rcvn_cal:\r
+// POST_CODE[major] == 0x05\r
+//\r
+// This function will perform our RCVEN Calibration Algorithm.\r
+// We will only use the 2xCLK domain timings to perform RCVEN Calibration.\r
+// All byte lanes will be calibrated "simultaneously" per channel per rank.\r
+static void rcvn_cal(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  uint8_t channel_i; // channel counter\r
+  uint8_t rank_i; // rank counter\r
+  uint8_t bl_i; // byte lane counter\r
+  uint8_t bl_divisor = (mrc_params->channel_width == x16) ? 2 : 1; // byte lane divisor\r
+\r
+#ifdef R2R_SHARING\r
+  uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES]; // used to find placement for rank2rank sharing configs\r
+#ifndef BACKUP_RCVN\r
+  uint32_t num_ranks_enabled = 0; // used to find placement for rank2rank sharing configs\r
+#endif // BACKUP_RCVN\r
+#endif // R2R_SHARING\r
+\r
+#ifdef BACKUP_RCVN\r
+#else\r
+  uint32_t tempD; // temporary DWORD\r
+  uint32_t delay[NUM_BYTE_LANES]; // absolute PI value to be programmed on the byte lane\r
+  RegDTR1 dtr1;\r
+  RegDTR1 dtr1save;\r
+#endif // BACKUP_RCVN\r
+  ENTERFN();\r
+\r
+  // rcvn_cal starts\r
+  post_code(0x05, 0x00);\r
+\r
+#ifndef BACKUP_RCVN\r
+  // need separate burst to sample DQS preamble\r
+  dtr1.raw = dtr1save.raw = isbR32m(MCU, DTR1);\r
+  dtr1.field.tCCD = 1;\r
+  isbW32m(MCU, DTR1, dtr1.raw);\r
+#endif\r
+\r
+#ifdef R2R_SHARING\r
+  // need to set "final_delay[][]" elements to "0"\r
+  memset((void *) (final_delay), 0x00, (size_t) sizeof(final_delay));\r
+#endif // R2R_SHARING\r
+\r
+  // loop through each enabled channel\r
+  for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)\r
+  {\r
+    if (mrc_params->channel_enables & (1 << channel_i))\r
+    {\r
+      // perform RCVEN Calibration on a per rank basis\r
+      for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)\r
+      {\r
+        if (mrc_params->rank_enables & (1 << rank_i))\r
+        {\r
+          // POST_CODE here indicates the current channel and rank being calibrated\r
+          post_code(0x05, (0x10 + ((channel_i << 4) | rank_i)));\r
+\r
+#ifdef BACKUP_RCVN\r
+          // set hard-coded timing values\r
+          for (bl_i=0; bl_i<(NUM_BYTE_LANES/bl_divisor); bl_i++)\r
+          {\r
+            set_rcvn(channel_i, rank_i, bl_i, ddr_rcvn[PLATFORM_ID]);\r
+          }\r
+#else\r
+          // enable FIFORST\r
+          for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i += 2)\r
+          {\r
+            isbM32m(DDRPHY, (B01PTRCTL1 + ((bl_i >> 1) * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), 0,\r
+                BIT8); // 0 is enabled\r
+          } // bl_i loop\r
+          // initialise the starting delay to 128 PI (tCAS +1 CLK)\r
+          for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+          {\r
+#ifdef SIM\r
+            // Original value was late at the end of DQS sequence\r
+            delay[bl_i] = 3 * FULL_CLK;\r
+#else\r
+            delay[bl_i] = (4 + 1) * FULL_CLK; // 1x CLK domain timing is tCAS-4\r
+#endif\r
+\r
+            set_rcvn(channel_i, rank_i, bl_i, delay[bl_i]);\r
+          } // bl_i loop\r
+\r
+          // now find the rising edge\r
+          find_rising_edge(mrc_params, delay, channel_i, rank_i, true);\r
+          // Now increase delay by 32 PI (1/4 CLK) to place in center of high pulse.\r
+          for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+          {\r
+            delay[bl_i] += QRTR_CLK;\r
+            set_rcvn(channel_i, rank_i, bl_i, delay[bl_i]);\r
+          } // bl_i loop\r
+          // Now decrement delay by 128 PI (1 CLK) until we sample a "0"\r
+          do\r
+          {\r
+\r
+            tempD = sample_dqs(mrc_params, channel_i, rank_i, true);\r
+            for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+            {\r
+              if (tempD & (1 << bl_i))\r
+              {\r
+                if (delay[bl_i] >= FULL_CLK)\r
+                {\r
+                  delay[bl_i] -= FULL_CLK;\r
+                  set_rcvn(channel_i, rank_i, bl_i, delay[bl_i]);\r
+                }\r
+                else\r
+                {\r
+                  // not enough delay\r
+                  training_message(channel_i, rank_i, bl_i);\r
+                  post_code(0xEE, 0x50);\r
+                }\r
+              }\r
+            } // bl_i loop\r
+          } while (tempD & 0xFF);\r
+\r
+#ifdef R2R_SHARING\r
+          // increment "num_ranks_enabled"\r
+          num_ranks_enabled++;\r
+          // Finally increment delay by 32 PI (1/4 CLK) to place in center of preamble.\r
+          for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+          {\r
+            delay[bl_i] += QRTR_CLK;\r
+            // add "delay[]" values to "final_delay[][]" for rolling average\r
+            final_delay[channel_i][bl_i] += delay[bl_i];\r
+            // set timing based on rolling average values\r
+            set_rcvn(channel_i, rank_i, bl_i, ((final_delay[channel_i][bl_i]) / num_ranks_enabled));\r
+          } // bl_i loop\r
+#else\r
+          // Finally increment delay by 32 PI (1/4 CLK) to place in center of preamble.\r
+          for (bl_i=0; bl_i<(NUM_BYTE_LANES/bl_divisor); bl_i++)\r
+          {\r
+            delay[bl_i] += QRTR_CLK;\r
+            set_rcvn(channel_i, rank_i, bl_i, delay[bl_i]);\r
+          } // bl_i loop\r
+\r
+#endif // R2R_SHARING\r
+\r
+          // disable FIFORST\r
+          for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i += 2)\r
+          {\r
+            isbM32m(DDRPHY, (B01PTRCTL1 + ((bl_i >> 1) * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)), BIT8,\r
+                BIT8); // 1 is disabled\r
+          } // bl_i loop\r
+\r
+#endif // BACKUP_RCVN\r
+\r
+        } // if rank is enabled\r
+      } // rank_i loop\r
+    } // if channel is enabled\r
+  } // channel_i loop\r
+\r
+#ifndef BACKUP_RCVN\r
+  // restore original\r
+  isbW32m(MCU, DTR1, dtr1save.raw);\r
+#endif\r
+\r
+#ifdef MRC_SV\r
+  if (mrc_params->tune_rcvn)\r
+  {\r
+    uint32_t rcven, val;\r
+    uint32_t rdcmd2rcven;\r
+\r
+    /*\r
+     Formulas for RDCMD2DATAVALID & DIFFAMP dynamic timings\r
+\r
+     1. Set after RCVEN training\r
+\r
+     //Tune RDCMD2DATAVALID\r
+\r
+     x80/x84[21:16]\r
+     MAX OF 2 RANKS : round up (rdcmd2rcven (rcven 1x) + 2x x 2 + PI/128) + 5\r
+\r
+     //rdcmd2rcven x80/84[12:8]\r
+     //rcven 2x x70[23:20] & [11:8]\r
+\r
+     //Tune DIFFAMP Timings\r
+\r
+     //diffampen launch x88[20:16] & [4:0]  -- B01LATCTL1\r
+     MIN OF 2 RANKS : round down (rcven 1x + 2x x 2 + PI/128) - 1\r
+\r
+     //diffampen length x8C/x90 [13:8]   -- B0ONDURCTL B1ONDURCTL\r
+     MAX OF 2 RANKS : roundup (rcven 1x + 2x x 2 + PI/128) + 5\r
+\r
+\r
+     2. need to do a fiforst after settings these values\r
+    */\r
+\r
+    DPF(D_INFO, "BEFORE\n");\r
+    DPF(D_INFO, "### %x\n", isbR32m(DDRPHY, B0LATCTL0));\r
+    DPF(D_INFO, "### %x\n", isbR32m(DDRPHY, B01LATCTL1));\r
+    DPF(D_INFO, "### %x\n", isbR32m(DDRPHY, B0ONDURCTL));\r
+\r
+    DPF(D_INFO, "### %x\n", isbR32m(DDRPHY, B1LATCTL0));\r
+    DPF(D_INFO, "### %x\n", isbR32m(DDRPHY, B1ONDURCTL));\r
+\r
+    rcven = get_rcvn(0, 0, 0) / 128;\r
+    rdcmd2rcven = (isbR32m(DDRPHY, B0LATCTL0) >> 8) & 0x1F;\r
+    val = rdcmd2rcven + rcven + 6;\r
+    isbM32m(DDRPHY, B0LATCTL0, val << 16, (BIT21|BIT20|BIT19|BIT18|BIT17|BIT16));\r
+\r
+    val = rdcmd2rcven + rcven - 1;\r
+    isbM32m(DDRPHY, B01LATCTL1, val << 0, (BIT4|BIT3|BIT2|BIT1|BIT0));\r
+\r
+    val = rdcmd2rcven + rcven + 5;\r
+    isbM32m(DDRPHY, B0ONDURCTL, val << 8, (BIT13|BIT12|BIT11|BIT10|BIT9|BIT8));\r
+\r
+    rcven = get_rcvn(0, 0, 1) / 128;\r
+    rdcmd2rcven = (isbR32m(DDRPHY, B1LATCTL0) >> 8) & 0x1F;\r
+    val = rdcmd2rcven + rcven + 6;\r
+    isbM32m(DDRPHY, B1LATCTL0, val << 16, (BIT21|BIT20|BIT19|BIT18|BIT17|BIT16));\r
+\r
+    val = rdcmd2rcven + rcven - 1;\r
+    isbM32m(DDRPHY, B01LATCTL1, val << 16, (BIT20|BIT19|BIT18|BIT17|BIT16));\r
+\r
+    val = rdcmd2rcven + rcven + 5;\r
+    isbM32m(DDRPHY, B1ONDURCTL, val << 8, (BIT13|BIT12|BIT11|BIT10|BIT9|BIT8));\r
+\r
+    DPF(D_INFO, "AFTER\n");\r
+    DPF(D_INFO, "### %x\n", isbR32m(DDRPHY, B0LATCTL0));\r
+    DPF(D_INFO, "### %x\n", isbR32m(DDRPHY, B01LATCTL1));\r
+    DPF(D_INFO, "### %x\n", isbR32m(DDRPHY, B0ONDURCTL));\r
+\r
+    DPF(D_INFO, "### %x\n", isbR32m(DDRPHY, B1LATCTL0));\r
+    DPF(D_INFO, "### %x\n", isbR32m(DDRPHY, B1ONDURCTL));\r
+\r
+    DPF(D_INFO, "\nPress a key\n");\r
+    mgetc();\r
+\r
+    // fifo reset\r
+    isbM32m(DDRPHY, B01PTRCTL1, 0, BIT8); // 0 is enabled\r
+    delay_n(3);\r
+    isbM32m(DDRPHY, B01PTRCTL1, BIT8, BIT8); // 1 is disabled\r
+  }\r
+#endif\r
+\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
+// Check memory executing write/read/verify of many data patterns\r
+// at the specified address. Bits in the result indicate failure\r
+// on specific byte lane.\r
+static uint32_t check_bls_ex(\r
+    MRCParams_t *mrc_params,\r
+    uint32_t address)\r
+{\r
+  uint32_t result;\r
+  uint8_t first_run = 0;\r
+\r
+  if (mrc_params->hte_setup)\r
+  {\r
+    mrc_params->hte_setup = 0;\r
+\r
+    first_run = 1;\r
+    select_hte(mrc_params);\r
+  }\r
+\r
+  result = WriteStressBitLanesHTE(mrc_params, address, first_run);\r
+\r
+  DPF(D_TRN, "check_bls_ex result is %x\n", result);\r
+  return result;\r
+}\r
+\r
+// Check memory executing simple write/read/verify at\r
+// the specified address. Bits in the result indicate failure\r
+// on specific byte lane.\r
+static uint32_t check_rw_coarse(\r
+    MRCParams_t *mrc_params,\r
+    uint32_t address)\r
+{\r
+  uint32_t result = 0;\r
+  uint8_t first_run = 0;\r
+\r
+  if (mrc_params->hte_setup)\r
+  {\r
+    mrc_params->hte_setup = 0;\r
+\r
+    first_run = 1;\r
+    select_hte(mrc_params);\r
+  }\r
+\r
+  result = BasicWriteReadHTE(mrc_params, address, first_run, WRITE_TRAIN);\r
+\r
+  DPF(D_TRN, "check_rw_coarse result is %x\n", result);\r
+  return result;\r
+}\r
+\r
+// wr_level:\r
+// POST_CODE[major] == 0x06\r
+//\r
+// This function will perform the Write Levelling algorithm (align WCLK and WDQS).\r
+// This algorithm will act on each rank in each channel separately.\r
+static void wr_level(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  uint8_t channel_i; // channel counter\r
+  uint8_t rank_i; // rank counter\r
+  uint8_t bl_i; // byte lane counter\r
+  uint8_t bl_divisor = (mrc_params->channel_width == x16) ? 2 : 1; // byte lane divisor\r
+\r
+#ifdef R2R_SHARING\r
+  uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES]; // used to find placement for rank2rank sharing configs\r
+#ifndef BACKUP_WDQS\r
+  uint32_t num_ranks_enabled = 0; // used to find placement for rank2rank sharing configs\r
+#endif // BACKUP_WDQS\r
+#endif // R2R_SHARING\r
+\r
+#ifdef BACKUP_WDQS\r
+#else\r
+  bool all_edges_found; // determines stop condition for CRS_WR_LVL\r
+  uint32_t delay[NUM_BYTE_LANES]; // absolute PI value to be programmed on the byte lane\r
+  // static makes it so the data is loaded in the heap once by shadow(), where\r
+  // non-static copies the data onto the stack every time this function is called.\r
+\r
+  uint32_t address; // address to be checked during COARSE_WR_LVL\r
+  RegDTR4 dtr4;\r
+  RegDTR4 dtr4save;\r
+#endif // BACKUP_WDQS\r
+\r
+  ENTERFN();\r
+\r
+  // wr_level starts\r
+  post_code(0x06, 0x00);\r
+\r
+#ifdef R2R_SHARING\r
+  // need to set "final_delay[][]" elements to "0"\r
+  memset((void *) (final_delay), 0x00, (size_t) sizeof(final_delay));\r
+#endif // R2R_SHARING\r
+  // loop through each enabled channel\r
+  for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)\r
+  {\r
+    if (mrc_params->channel_enables & (1 << channel_i))\r
+    {\r
+      // perform WRITE LEVELING algorithm on a per rank basis\r
+      for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)\r
+      {\r
+        if (mrc_params->rank_enables & (1 << rank_i))\r
+        {\r
+          // POST_CODE here indicates the current rank and channel being calibrated\r
+          post_code(0x06, (0x10 + ((channel_i << 4) | rank_i)));\r
+\r
+#ifdef BACKUP_WDQS\r
+          for (bl_i=0; bl_i<(NUM_BYTE_LANES/bl_divisor); bl_i++)\r
+          {\r
+            set_wdqs(channel_i, rank_i, bl_i, ddr_wdqs[PLATFORM_ID]);\r
+            set_wdq(channel_i, rank_i, bl_i, (ddr_wdqs[PLATFORM_ID] - QRTR_CLK));\r
+          }\r
+#else\r
+\r
+          { // Begin product specific code\r
+\r
+            // perform a single PRECHARGE_ALL command to make DRAM state machine go to IDLE state\r
+            dram_init_command(DCMD_PREA(rank_i));\r
+\r
+            // enable Write Levelling Mode (EMRS1 w/ Write Levelling Mode Enable)\r
+            dram_init_command(DCMD_MRS1(rank_i,0x0082));\r
+\r
+            // set ODT DRAM Full Time Termination disable in MCU\r
+            dtr4.raw = dtr4save.raw = isbR32m(MCU, DTR4);\r
+            dtr4.field.ODTDIS = 1;\r
+            isbW32m(MCU, DTR4, dtr4.raw);\r
+\r
+            for (bl_i = 0; bl_i < ((NUM_BYTE_LANES / bl_divisor) / 2); bl_i++)\r
+            {\r
+              isbM32m(DDRPHY, DQCTL + (DDRIODQ_BL_OFFSET * bl_i) + (DDRIODQ_CH_OFFSET * channel_i),\r
+                  (BIT28 | (0x1 << 8) | (0x1 << 6) | (0x1 << 4) | (0x1 << 2)),\r
+                  (BIT28 | (BIT9|BIT8) | (BIT7|BIT6) | (BIT5|BIT4) | (BIT3|BIT2))); // Enable Sandy Bridge Mode (WDQ Tri-State) & Ensure 5 WDQS pulses during Write Leveling\r
+            }\r
+\r
+            isbM32m(DDRPHY, CCDDR3RESETCTL + (DDRIOCCC_CH_OFFSET * channel_i), (BIT16), (BIT16)); // Write Leveling Mode enabled in IO\r
+          } // End product specific code\r
+          // Initialise the starting delay to WCLK\r
+          for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+          {\r
+            { // Begin product specific code\r
+              // CLK0 --> RK0\r
+              // CLK1 --> RK1\r
+              delay[bl_i] = get_wclk(channel_i, rank_i);\r
+            } // End product specific code\r
+            set_wdqs(channel_i, rank_i, bl_i, delay[bl_i]);\r
+          } // bl_i loop\r
+          // now find the rising edge\r
+          find_rising_edge(mrc_params, delay, channel_i, rank_i, false);\r
+          { // Begin product specific code\r
+            // disable Write Levelling Mode\r
+            isbM32m(DDRPHY, CCDDR3RESETCTL + (DDRIOCCC_CH_OFFSET * channel_i), (0), (BIT16)); // Write Leveling Mode disabled in IO\r
+\r
+            for (bl_i = 0; bl_i < ((NUM_BYTE_LANES / bl_divisor) / 2); bl_i++)\r
+            {\r
+              isbM32m(DDRPHY, DQCTL + (DDRIODQ_BL_OFFSET * bl_i) + (DDRIODQ_CH_OFFSET * channel_i),\r
+                  ((0x1 << 8) | (0x1 << 6) | (0x1 << 4) | (0x1 << 2)),\r
+                  (BIT28 | (BIT9|BIT8) | (BIT7|BIT6) | (BIT5|BIT4) | (BIT3|BIT2))); // Disable Sandy Bridge Mode & Ensure 4 WDQS pulses during normal operation\r
+            } // bl_i loop\r
+\r
+            // restore original DTR4\r
+            isbW32m(MCU, DTR4, dtr4save.raw);\r
+\r
+            // restore original value (Write Levelling Mode Disable)\r
+            dram_init_command(DCMD_MRS1(rank_i, mrc_params->mrs1));\r
+\r
+            // perform a single PRECHARGE_ALL command to make DRAM state machine go to IDLE state\r
+            dram_init_command(DCMD_PREA(rank_i));\r
+          } // End product specific code\r
+\r
+          post_code(0x06, (0x30 + ((channel_i << 4) | rank_i)));\r
+\r
+          // COARSE WRITE LEVEL:\r
+          // check that we're on the correct clock edge\r
+\r
+          // hte reconfiguration request\r
+          mrc_params->hte_setup = 1;\r
+\r
+          // start CRS_WR_LVL with WDQS = WDQS + 128 PI\r
+          for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+          {\r
+            delay[bl_i] = get_wdqs(channel_i, rank_i, bl_i) + FULL_CLK;\r
+            set_wdqs(channel_i, rank_i, bl_i, delay[bl_i]);\r
+            // program WDQ timings based on WDQS (WDQ = WDQS - 32 PI)\r
+            set_wdq(channel_i, rank_i, bl_i, (delay[bl_i] - QRTR_CLK));\r
+          } // bl_i loop\r
+\r
+          // get an address in the targeted channel/rank\r
+          address = get_addr(mrc_params, channel_i, rank_i);\r
+          do\r
+          {\r
+            uint32_t coarse_result = 0x00;\r
+            uint32_t coarse_result_mask = byte_lane_mask(mrc_params);\r
+            all_edges_found = true; // assume pass\r
+\r
+#ifdef SIM\r
+            // need restore memory to idle state as write can be in bad sync\r
+            dram_init_command (DCMD_PREA(rank_i));\r
+#endif\r
+\r
+            mrc_params->hte_setup = 1;\r
+            coarse_result = check_rw_coarse(mrc_params, address);\r
+\r
+            // check for failures and margin the byte lane back 128 PI (1 CLK)\r
+            for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+            {\r
+              if (coarse_result & (coarse_result_mask << bl_i))\r
+              {\r
+                all_edges_found = false;\r
+                delay[bl_i] -= FULL_CLK;\r
+                set_wdqs(channel_i, rank_i, bl_i, delay[bl_i]);\r
+                // program WDQ timings based on WDQS (WDQ = WDQS - 32 PI)\r
+                set_wdq(channel_i, rank_i, bl_i, (delay[bl_i] - QRTR_CLK));\r
+              }\r
+            } // bl_i loop\r
+\r
+          } while (!all_edges_found);\r
+\r
+#ifdef R2R_SHARING\r
+          // increment "num_ranks_enabled"\r
+          num_ranks_enabled++;\r
+          // accumulate "final_delay[][]" values from "delay[]" values for rolling average\r
+          for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+          {\r
+            final_delay[channel_i][bl_i] += delay[bl_i];\r
+            set_wdqs(channel_i, rank_i, bl_i, ((final_delay[channel_i][bl_i]) / num_ranks_enabled));\r
+            // program WDQ timings based on WDQS (WDQ = WDQS - 32 PI)\r
+            set_wdq(channel_i, rank_i, bl_i, ((final_delay[channel_i][bl_i]) / num_ranks_enabled) - QRTR_CLK);\r
+          } // bl_i loop\r
+#endif // R2R_SHARING\r
+#endif // BACKUP_WDQS\r
+\r
+        } // if rank is enabled\r
+      } // rank_i loop\r
+    } // if channel is enabled\r
+  } // channel_i loop\r
+\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
+// rd_train:\r
+// POST_CODE[major] == 0x07\r
+//\r
+// This function will perform the READ TRAINING Algorithm on all channels/ranks/byte_lanes simultaneously to minimize execution time.\r
+// The idea here is to train the VREF and RDQS (and eventually RDQ) values to achieve maximum READ margins.\r
+// The algorithm will first determine the X coordinate (RDQS setting).\r
+// This is done by collapsing the VREF eye until we find a minimum required RDQS eye for VREF_MIN and VREF_MAX.\r
+// Then we take the averages of the RDQS eye at VREF_MIN and VREF_MAX, then average those; this will be the final X coordinate.\r
+// The algorithm will then determine the Y coordinate (VREF setting).\r
+// This is done by collapsing the RDQS eye until we find a minimum required VREF eye for RDQS_MIN and RDQS_MAX.\r
+// Then we take the averages of the VREF eye at RDQS_MIN and RDQS_MAX, then average those; this will be the final Y coordinate.\r
+// NOTE: this algorithm assumes the eye curves have a one-to-one relationship, meaning for each X the curve has only one Y and vice-a-versa.\r
+static void rd_train(\r
+    MRCParams_t *mrc_params)\r
+{\r
+\r
+#define MIN_RDQS_EYE 10 // in PI Codes\r
+#define MIN_VREF_EYE 10 // in VREF Codes\r
+#define RDQS_STEP 1     // how many RDQS codes to jump while margining\r
+#define VREF_STEP 1     // how many VREF codes to jump while margining\r
+#define VREF_MIN (0x00) // offset into "vref_codes[]" for minimum allowed VREF setting\r
+#define VREF_MAX (0x3F) // offset into "vref_codes[]" for maximum allowed VREF setting\r
+#define RDQS_MIN (0x00) // minimum RDQS delay value\r
+#define RDQS_MAX (0x3F) // maximum RDQS delay value\r
+#define B 0 // BOTTOM VREF\r
+#define T 1 // TOP VREF\r
+#define L 0 // LEFT RDQS\r
+#define R 1 // RIGHT RDQS\r
+\r
+  uint8_t channel_i; // channel counter\r
+  uint8_t rank_i; // rank counter\r
+  uint8_t bl_i; // byte lane counter\r
+  uint8_t bl_divisor = (mrc_params->channel_width == x16) ? 2 : 1; // byte lane divisor\r
+#ifdef BACKUP_RDQS\r
+#else\r
+  uint8_t side_x; // tracks LEFT/RIGHT approach vectors\r
+  uint8_t side_y; // tracks BOTTOM/TOP approach vectors\r
+  uint8_t x_coordinate[2/*side_x*/][2/*side_y*/][NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES]; // X coordinate data (passing RDQS values) for approach vectors\r
+  uint8_t y_coordinate[2/*side_x*/][2/*side_y*/][NUM_CHANNELS][NUM_BYTE_LANES]; // Y coordinate data (passing VREF values) for approach vectors\r
+  uint8_t x_center[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES]; // centered X (RDQS)\r
+  uint8_t y_center[NUM_CHANNELS][NUM_BYTE_LANES]; // centered Y (VREF)\r
+  uint32_t address; // target address for "check_bls_ex()"\r
+  uint32_t result; // result of "check_bls_ex()"\r
+  uint32_t bl_mask; // byte lane mask for "result" checking\r
+#ifdef R2R_SHARING\r
+  uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES]; // used to find placement for rank2rank sharing configs\r
+  uint32_t num_ranks_enabled = 0; // used to find placement for rank2rank sharing configs\r
+#endif // R2R_SHARING\r
+#endif // BACKUP_RDQS\r
+  // rd_train starts\r
+  post_code(0x07, 0x00);\r
+\r
+  ENTERFN();\r
+\r
+#ifdef BACKUP_RDQS\r
+  for (channel_i=0; channel_i<NUM_CHANNELS; channel_i++)\r
+  {\r
+    if (mrc_params->channel_enables & (1<<channel_i))\r
+    {\r
+      for (rank_i=0; rank_i<NUM_RANKS; rank_i++)\r
+      {\r
+        if (mrc_params->rank_enables & (1<<rank_i))\r
+        {\r
+          for (bl_i=0; bl_i<(NUM_BYTE_LANES/bl_divisor); bl_i++)\r
+          {\r
+            set_rdqs(channel_i, rank_i, bl_i, ddr_rdqs[PLATFORM_ID]);\r
+          } // bl_i loop\r
+        } // if rank is enabled\r
+      } // rank_i loop\r
+    } // if channel is enabled\r
+  } // channel_i loop\r
+#else\r
+  // initialise x/y_coordinate arrays\r
+  for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)\r
+  {\r
+    if (mrc_params->channel_enables & (1 << channel_i))\r
+    {\r
+      for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)\r
+      {\r
+        if (mrc_params->rank_enables & (1 << rank_i))\r
+        {\r
+          for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+          {\r
+            // x_coordinate:\r
+            x_coordinate[L][B][channel_i][rank_i][bl_i] = RDQS_MIN;\r
+            x_coordinate[R][B][channel_i][rank_i][bl_i] = RDQS_MAX;\r
+            x_coordinate[L][T][channel_i][rank_i][bl_i] = RDQS_MIN;\r
+            x_coordinate[R][T][channel_i][rank_i][bl_i] = RDQS_MAX;\r
+            // y_coordinate:\r
+            y_coordinate[L][B][channel_i][bl_i] = VREF_MIN;\r
+            y_coordinate[R][B][channel_i][bl_i] = VREF_MIN;\r
+            y_coordinate[L][T][channel_i][bl_i] = VREF_MAX;\r
+            y_coordinate[R][T][channel_i][bl_i] = VREF_MAX;\r
+          } // bl_i loop\r
+        } // if rank is enabled\r
+      } // rank_i loop\r
+    } // if channel is enabled\r
+  } // channel_i loop\r
+\r
+  // initialise other variables\r
+  bl_mask = byte_lane_mask(mrc_params);\r
+  address = get_addr(mrc_params, 0, 0);\r
+\r
+#ifdef R2R_SHARING\r
+  // need to set "final_delay[][]" elements to "0"\r
+  memset((void *) (final_delay), 0x00, (size_t) sizeof(final_delay));\r
+#endif // R2R_SHARING\r
+\r
+  // look for passing coordinates\r
+  for (side_y = B; side_y <= T; side_y++)\r
+  {\r
+    for (side_x = L; side_x <= R; side_x++)\r
+    {\r
+\r
+      post_code(0x07, (0x10 + (side_y * 2) + (side_x)));\r
+\r
+      // find passing values\r
+      for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)\r
+      {\r
+        if (mrc_params->channel_enables & (0x1 << channel_i))\r
+        {\r
+          for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)\r
+          {\r
+\r
+            if (mrc_params->rank_enables & (0x1 << rank_i))\r
+            {\r
+              // set x/y_coordinate search starting settings\r
+              for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+              {\r
+                set_rdqs(channel_i, rank_i, bl_i, x_coordinate[side_x][side_y][channel_i][rank_i][bl_i]);\r
+                set_vref(channel_i, bl_i, y_coordinate[side_x][side_y][channel_i][bl_i]);\r
+              } // bl_i loop\r
+              // get an address in the target channel/rank\r
+              address = get_addr(mrc_params, channel_i, rank_i);\r
+\r
+              // request HTE reconfiguration\r
+              mrc_params->hte_setup = 1;\r
+\r
+              // test the settings\r
+              do\r
+              {\r
+\r
+                // result[07:00] == failing byte lane (MAX 8)\r
+                result = check_bls_ex( mrc_params, address);\r
+\r
+                // check for failures\r
+                if (result & 0xFF)\r
+                {\r
+                  // at least 1 byte lane failed\r
+                  for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+                  {\r
+                    if (result & (bl_mask << bl_i))\r
+                    {\r
+                      // adjust the RDQS values accordingly\r
+                      if (side_x == L)\r
+                      {\r
+                        x_coordinate[L][side_y][channel_i][rank_i][bl_i] += RDQS_STEP;\r
+                      }\r
+                      else\r
+                      {\r
+                        x_coordinate[R][side_y][channel_i][rank_i][bl_i] -= RDQS_STEP;\r
+                      }\r
+                      // check that we haven't closed the RDQS_EYE too much\r
+                      if ((x_coordinate[L][side_y][channel_i][rank_i][bl_i] > (RDQS_MAX - MIN_RDQS_EYE)) ||\r
+                          (x_coordinate[R][side_y][channel_i][rank_i][bl_i] < (RDQS_MIN + MIN_RDQS_EYE))\r
+                          ||\r
+                          (x_coordinate[L][side_y][channel_i][rank_i][bl_i]\r
+                              == x_coordinate[R][side_y][channel_i][rank_i][bl_i]))\r
+                      {\r
+                        // not enough RDQS margin available at this VREF\r
+                        // update VREF values accordingly\r
+                        if (side_y == B)\r
+                        {\r
+                          y_coordinate[side_x][B][channel_i][bl_i] += VREF_STEP;\r
+                        }\r
+                        else\r
+                        {\r
+                          y_coordinate[side_x][T][channel_i][bl_i] -= VREF_STEP;\r
+                        }\r
+                        // check that we haven't closed the VREF_EYE too much\r
+                        if ((y_coordinate[side_x][B][channel_i][bl_i] > (VREF_MAX - MIN_VREF_EYE)) ||\r
+                            (y_coordinate[side_x][T][channel_i][bl_i] < (VREF_MIN + MIN_VREF_EYE)) ||\r
+                            (y_coordinate[side_x][B][channel_i][bl_i] == y_coordinate[side_x][T][channel_i][bl_i]))\r
+                        {\r
+                          // VREF_EYE collapsed below MIN_VREF_EYE\r
+                          training_message(channel_i, rank_i, bl_i);\r
+                          post_code(0xEE, (0x70 + (side_y * 2) + (side_x)));\r
+                        }\r
+                        else\r
+                        {\r
+                          // update the VREF setting\r
+                          set_vref(channel_i, bl_i, y_coordinate[side_x][side_y][channel_i][bl_i]);\r
+                          // reset the X coordinate to begin the search at the new VREF\r
+                          x_coordinate[side_x][side_y][channel_i][rank_i][bl_i] =\r
+                              (side_x == L) ? (RDQS_MIN) : (RDQS_MAX);\r
+                        }\r
+                      }\r
+                      // update the RDQS setting\r
+                      set_rdqs(channel_i, rank_i, bl_i, x_coordinate[side_x][side_y][channel_i][rank_i][bl_i]);\r
+                    } // if bl_i failed\r
+                  } // bl_i loop\r
+                } // at least 1 byte lane failed\r
+              } while (result & 0xFF);\r
+            } // if rank is enabled\r
+          } // rank_i loop\r
+        } // if channel is enabled\r
+      } // channel_i loop\r
+    } // side_x loop\r
+  } // side_y loop\r
+\r
+  post_code(0x07, 0x20);\r
+\r
+  // find final RDQS (X coordinate) & final VREF (Y coordinate)\r
+  for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)\r
+  {\r
+    if (mrc_params->channel_enables & (1 << channel_i))\r
+    {\r
+      for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)\r
+      {\r
+        if (mrc_params->rank_enables & (1 << rank_i))\r
+        {\r
+          for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+          {\r
+            uint32_t tempD1;\r
+            uint32_t tempD2;\r
+\r
+            // x_coordinate:\r
+            DPF(D_INFO, "RDQS T/B eye rank%d lane%d : %d-%d %d-%d\n", rank_i, bl_i,\r
+                x_coordinate[L][T][channel_i][rank_i][bl_i],\r
+                x_coordinate[R][T][channel_i][rank_i][bl_i],\r
+                x_coordinate[L][B][channel_i][rank_i][bl_i],\r
+                x_coordinate[R][B][channel_i][rank_i][bl_i]);\r
+\r
+            tempD1 = (x_coordinate[R][T][channel_i][rank_i][bl_i] + x_coordinate[L][T][channel_i][rank_i][bl_i]) / 2; // average the TOP side LEFT & RIGHT values\r
+            tempD2 = (x_coordinate[R][B][channel_i][rank_i][bl_i] + x_coordinate[L][B][channel_i][rank_i][bl_i]) / 2; // average the BOTTOM side LEFT & RIGHT values\r
+            x_center[channel_i][rank_i][bl_i] = (uint8_t) ((tempD1 + tempD2) / 2); // average the above averages\r
+\r
+            // y_coordinate:\r
+            DPF(D_INFO, "VREF R/L eye lane%d : %d-%d %d-%d\n", bl_i,\r
+                y_coordinate[R][B][channel_i][bl_i],\r
+                y_coordinate[R][T][channel_i][bl_i],\r
+                y_coordinate[L][B][channel_i][bl_i],\r
+                y_coordinate[L][T][channel_i][bl_i]);\r
+\r
+            tempD1 = (y_coordinate[R][T][channel_i][bl_i] + y_coordinate[R][B][channel_i][bl_i]) / 2; // average the RIGHT side TOP & BOTTOM values\r
+            tempD2 = (y_coordinate[L][T][channel_i][bl_i] + y_coordinate[L][B][channel_i][bl_i]) / 2; // average the LEFT side TOP & BOTTOM values\r
+            y_center[channel_i][bl_i] = (uint8_t) ((tempD1 + tempD2) / 2); // average the above averages\r
+          } // bl_i loop\r
+        } // if rank is enabled\r
+      } // rank_i loop\r
+    } // if channel is enabled\r
+  } // channel_i loop\r
+\r
+#ifdef RX_EYE_CHECK\r
+  // perform an eye check\r
+  for (side_y=B; side_y<=T; side_y++)\r
+  {\r
+    for (side_x=L; side_x<=R; side_x++)\r
+    {\r
+\r
+      post_code(0x07, (0x30 + (side_y * 2) + (side_x)));\r
+\r
+      // update the settings for the eye check\r
+      for (channel_i=0; channel_i<NUM_CHANNELS; channel_i++)\r
+      {\r
+        if (mrc_params->channel_enables & (1<<channel_i))\r
+        {\r
+          for (rank_i=0; rank_i<NUM_RANKS; rank_i++)\r
+          {\r
+            if (mrc_params->rank_enables & (1<<rank_i))\r
+            {\r
+              for (bl_i=0; bl_i<(NUM_BYTE_LANES/bl_divisor); bl_i++)\r
+              {\r
+                if (side_x == L)\r
+                {\r
+                  set_rdqs(channel_i, rank_i, bl_i, (x_center[channel_i][rank_i][bl_i] - (MIN_RDQS_EYE / 2)));\r
+                }\r
+                else\r
+                {\r
+                  set_rdqs(channel_i, rank_i, bl_i, (x_center[channel_i][rank_i][bl_i] + (MIN_RDQS_EYE / 2)));\r
+                }\r
+                if (side_y == B)\r
+                {\r
+                  set_vref(channel_i, bl_i, (y_center[channel_i][bl_i] - (MIN_VREF_EYE / 2)));\r
+                }\r
+                else\r
+                {\r
+                  set_vref(channel_i, bl_i, (y_center[channel_i][bl_i] + (MIN_VREF_EYE / 2)));\r
+                }\r
+              } // bl_i loop\r
+            } // if rank is enabled\r
+          } // rank_i loop\r
+        } // if channel is enabled\r
+      } // channel_i loop\r
+\r
+      // request HTE reconfiguration\r
+      mrc_params->hte_setup = 1;\r
+\r
+      // check the eye\r
+      if (check_bls_ex( mrc_params, address) & 0xFF)\r
+      {\r
+        // one or more byte lanes failed\r
+        post_code(0xEE, (0x74 + (side_x * 2) + (side_y)));\r
+      }\r
+    } // side_x loop\r
+  } // side_y loop\r
+#endif // RX_EYE_CHECK\r
+\r
+  post_code(0x07, 0x40);\r
+\r
+  // set final placements\r
+  for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)\r
+  {\r
+    if (mrc_params->channel_enables & (1 << channel_i))\r
+    {\r
+      for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)\r
+      {\r
+        if (mrc_params->rank_enables & (1 << rank_i))\r
+        {\r
+#ifdef R2R_SHARING\r
+          // increment "num_ranks_enabled"\r
+          num_ranks_enabled++;\r
+#endif // R2R_SHARING\r
+          for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+          {\r
+            // x_coordinate:\r
+#ifdef R2R_SHARING\r
+            final_delay[channel_i][bl_i] += x_center[channel_i][rank_i][bl_i];\r
+            set_rdqs(channel_i, rank_i, bl_i, ((final_delay[channel_i][bl_i]) / num_ranks_enabled));\r
+#else\r
+            set_rdqs(channel_i, rank_i, bl_i, x_center[channel_i][rank_i][bl_i]);\r
+#endif // R2R_SHARING\r
+            // y_coordinate:\r
+            set_vref(channel_i, bl_i, y_center[channel_i][bl_i]);\r
+          } // bl_i loop\r
+        } // if rank is enabled\r
+      } // rank_i loop\r
+    } // if channel is enabled\r
+  } // channel_i loop\r
+#endif // BACKUP_RDQS\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
+// wr_train:\r
+// POST_CODE[major] == 0x08\r
+//\r
+// This function will perform the WRITE TRAINING Algorithm on all channels/ranks/byte_lanes simultaneously to minimize execution time.\r
+// The idea here is to train the WDQ timings to achieve maximum WRITE margins.\r
+// The algorithm will start with WDQ at the current WDQ setting (tracks WDQS in WR_LVL) +/- 32 PIs (+/- 1/4 CLK) and collapse the eye until all data patterns pass.\r
+// This is because WDQS will be aligned to WCLK by the Write Leveling algorithm and WDQ will only ever have a 1/2 CLK window of validity.\r
+static void wr_train(\r
+    MRCParams_t *mrc_params)\r
+{\r
+\r
+#define WDQ_STEP 1 // how many WDQ codes to jump while margining\r
+#define L 0 // LEFT side loop value definition\r
+#define R 1 // RIGHT side loop value definition\r
+\r
+  uint8_t channel_i; // channel counter\r
+  uint8_t rank_i; // rank counter\r
+  uint8_t bl_i; // byte lane counter\r
+  uint8_t bl_divisor = (mrc_params->channel_width == x16) ? 2 : 1; // byte lane divisor\r
+#ifdef BACKUP_WDQ\r
+#else\r
+  uint8_t side_i; // LEFT/RIGHT side indicator (0=L, 1=R)\r
+  uint32_t tempD; // temporary DWORD\r
+  uint32_t delay[2/*side_i*/][NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES]; // 2 arrays, for L & R side passing delays\r
+  uint32_t address; // target address for "check_bls_ex()"\r
+  uint32_t result; // result of "check_bls_ex()"\r
+  uint32_t bl_mask; // byte lane mask for "result" checking\r
+#ifdef R2R_SHARING\r
+  uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES]; // used to find placement for rank2rank sharing configs\r
+  uint32_t num_ranks_enabled = 0; // used to find placement for rank2rank sharing configs\r
+#endif // R2R_SHARING\r
+#endif // BACKUP_WDQ\r
+\r
+  // wr_train starts\r
+  post_code(0x08, 0x00);\r
+\r
+  ENTERFN();\r
+\r
+#ifdef BACKUP_WDQ\r
+  for (channel_i=0; channel_i<NUM_CHANNELS; channel_i++)\r
+  {\r
+    if (mrc_params->channel_enables & (1<<channel_i))\r
+    {\r
+      for (rank_i=0; rank_i<NUM_RANKS; rank_i++)\r
+      {\r
+        if (mrc_params->rank_enables & (1<<rank_i))\r
+        {\r
+          for (bl_i=0; bl_i<(NUM_BYTE_LANES/bl_divisor); bl_i++)\r
+          {\r
+            set_wdq(channel_i, rank_i, bl_i, ddr_wdq[PLATFORM_ID]);\r
+          } // bl_i loop\r
+        } // if rank is enabled\r
+      } // rank_i loop\r
+    } // if channel is enabled\r
+  } // channel_i loop\r
+#else\r
+  // initialise "delay"\r
+  for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)\r
+  {\r
+    if (mrc_params->channel_enables & (1 << channel_i))\r
+    {\r
+      for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)\r
+      {\r
+        if (mrc_params->rank_enables & (1 << rank_i))\r
+        {\r
+          for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+          {\r
+            // want to start with WDQ = (WDQS - QRTR_CLK) +/- QRTR_CLK\r
+            tempD = get_wdqs(channel_i, rank_i, bl_i) - QRTR_CLK;\r
+            delay[L][channel_i][rank_i][bl_i] = tempD - QRTR_CLK;\r
+            delay[R][channel_i][rank_i][bl_i] = tempD + QRTR_CLK;\r
+          } // bl_i loop\r
+        } // if rank is enabled\r
+      } // rank_i loop\r
+    } // if channel is enabled\r
+  } // channel_i loop\r
+\r
+  // initialise other variables\r
+  bl_mask = byte_lane_mask(mrc_params);\r
+  address = get_addr(mrc_params, 0, 0);\r
+\r
+#ifdef R2R_SHARING\r
+  // need to set "final_delay[][]" elements to "0"\r
+  memset((void *) (final_delay), 0x00, (size_t) sizeof(final_delay));\r
+#endif // R2R_SHARING\r
+\r
+  // start algorithm on the LEFT side and train each channel/bl until no failures are observed, then repeat for the RIGHT side.\r
+  for (side_i = L; side_i <= R; side_i++)\r
+  {\r
+    post_code(0x08, (0x10 + (side_i)));\r
+\r
+    // set starting values\r
+    for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)\r
+    {\r
+      if (mrc_params->channel_enables & (1 << channel_i))\r
+      {\r
+        for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)\r
+        {\r
+          if (mrc_params->rank_enables & (1 << rank_i))\r
+          {\r
+            for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+            {\r
+              set_wdq(channel_i, rank_i, bl_i, delay[side_i][channel_i][rank_i][bl_i]);\r
+            } // bl_i loop\r
+          } // if rank is enabled\r
+        } // rank_i loop\r
+      } // if channel is enabled\r
+    } // channel_i loop\r
+\r
+    // find passing values\r
+    for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)\r
+    {\r
+      if (mrc_params->channel_enables & (0x1 << channel_i))\r
+      {\r
+        for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)\r
+        {\r
+          if (mrc_params->rank_enables & (0x1 << rank_i))\r
+          {\r
+            // get an address in the target channel/rank\r
+            address = get_addr(mrc_params, channel_i, rank_i);\r
+\r
+            // request HTE reconfiguration\r
+            mrc_params->hte_setup = 1;\r
+\r
+            // check the settings\r
+            do\r
+            {\r
+\r
+#ifdef SIM\r
+              // need restore memory to idle state as write can be in bad sync\r
+              dram_init_command (DCMD_PREA(rank_i));\r
+#endif\r
+\r
+              // result[07:00] == failing byte lane (MAX 8)\r
+              result = check_bls_ex( mrc_params, address);\r
+              // check for failures\r
+              if (result & 0xFF)\r
+              {\r
+                // at least 1 byte lane failed\r
+                for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+                {\r
+                  if (result & (bl_mask << bl_i))\r
+                  {\r
+                    if (side_i == L)\r
+                    {\r
+                      delay[L][channel_i][rank_i][bl_i] += WDQ_STEP;\r
+                    }\r
+                    else\r
+                    {\r
+                      delay[R][channel_i][rank_i][bl_i] -= WDQ_STEP;\r
+                    }\r
+                    // check for algorithm failure\r
+                    if (delay[L][channel_i][rank_i][bl_i] != delay[R][channel_i][rank_i][bl_i])\r
+                    {\r
+                      // margin available, update delay setting\r
+                      set_wdq(channel_i, rank_i, bl_i, delay[side_i][channel_i][rank_i][bl_i]);\r
+                    }\r
+                    else\r
+                    {\r
+                      // no margin available, notify the user and halt\r
+                      training_message(channel_i, rank_i, bl_i);\r
+                      post_code(0xEE, (0x80 + side_i));\r
+                    }\r
+                  } // if bl_i failed\r
+                } // bl_i loop\r
+              } // at least 1 byte lane failed\r
+            } while (result & 0xFF); // stop when all byte lanes pass\r
+          } // if rank is enabled\r
+        } // rank_i loop\r
+      } // if channel is enabled\r
+    } // channel_i loop\r
+  } // side_i loop\r
+\r
+  // program WDQ to the middle of passing window\r
+  for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)\r
+  {\r
+    if (mrc_params->channel_enables & (1 << channel_i))\r
+    {\r
+      for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)\r
+      {\r
+        if (mrc_params->rank_enables & (1 << rank_i))\r
+        {\r
+#ifdef R2R_SHARING\r
+          // increment "num_ranks_enabled"\r
+          num_ranks_enabled++;\r
+#endif // R2R_SHARING\r
+          for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+          {\r
+\r
+            DPF(D_INFO, "WDQ eye rank%d lane%d : %d-%d\n", rank_i, bl_i,\r
+                delay[L][channel_i][rank_i][bl_i],\r
+                delay[R][channel_i][rank_i][bl_i]);\r
+\r
+            tempD = (delay[R][channel_i][rank_i][bl_i] + delay[L][channel_i][rank_i][bl_i]) / 2;\r
+\r
+#ifdef R2R_SHARING\r
+            final_delay[channel_i][bl_i] += tempD;\r
+            set_wdq(channel_i, rank_i, bl_i, ((final_delay[channel_i][bl_i]) / num_ranks_enabled));\r
+#else\r
+            set_wdq(channel_i, rank_i, bl_i, tempD);\r
+#endif // R2R_SHARING\r
+\r
+          } // bl_i loop\r
+        } // if rank is enabled\r
+      } // rank_i loop\r
+    } // if channel is enabled\r
+  } // channel_i loop\r
+#endif // BACKUP_WDQ\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
+// Wrapper for jedec initialisation routine\r
+static void perform_jedec_init(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  jedec_init(mrc_params, 0);\r
+}\r
+\r
+// Configure DDRPHY for Auto-Refresh, Periodic Compensations,\r
+// Dynamic Diff-Amp, ZQSPERIOD, Auto-Precharge, CKE Power-Down\r
+static void set_auto_refresh(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  uint32_t channel_i;\r
+  uint32_t rank_i;\r
+  uint32_t bl_i;\r
+  uint32_t bl_divisor = /*(mrc_params->channel_width==x16)?2:*/1;\r
+  uint32_t tempD;\r
+\r
+  ENTERFN();\r
+\r
+  // enable Auto-Refresh, Periodic Compensations, Dynamic Diff-Amp, ZQSPERIOD, Auto-Precharge, CKE Power-Down\r
+  for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)\r
+  {\r
+    if (mrc_params->channel_enables & (1 << channel_i))\r
+    {\r
+      // Enable Periodic RCOMPS\r
+      isbM32m(DDRPHY, CMPCTRL, (BIT1), (BIT1));\r
+\r
+\r
+      // Enable Dynamic DiffAmp & Set Read ODT Value\r
+      switch (mrc_params->rd_odt_value)\r
+      {\r
+        case 0: tempD = 0x3F; break;  // OFF\r
+        default: tempD = 0x00; break; // Auto\r
+      } // rd_odt_value switch\r
+\r
+      for (bl_i=0; bl_i<((NUM_BYTE_LANES/bl_divisor)/2); bl_i++)\r
+      {\r
+        isbM32m(DDRPHY, (B0OVRCTL + (bl_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)),\r
+            ((0x00<<16)|(tempD<<10)),\r
+            ((BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12|BIT11|BIT10))); // Override: DIFFAMP, ODT\r
+\r
+        isbM32m(DDRPHY, (B1OVRCTL + (bl_i * DDRIODQ_BL_OFFSET) + (channel_i * DDRIODQ_CH_OFFSET)),\r
+            ((0x00<<16)|(tempD<<10)),\r
+            ((BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)|(BIT15|BIT14|BIT13|BIT12|BIT11|BIT10)));// Override: DIFFAMP, ODT\r
+      } // bl_i loop\r
+\r
+      // Issue ZQCS command\r
+      for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)\r
+      {\r
+        if (mrc_params->rank_enables & (1 << rank_i))\r
+        {\r
+          dram_init_command(DCMD_ZQCS(rank_i));\r
+        } // if rank_i enabled\r
+      } // rank_i loop\r
+\r
+    } // if channel_i enabled\r
+  } // channel_i loop\r
+\r
+  clear_pointers();\r
+\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
+// Depending on configuration enables ECC support.\r
+// Available memory size is decresed, and updated with 0s\r
+// in order to clear error status. Address mode 2 forced.\r
+static void ecc_enable(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  RegDRP Drp;\r
+  RegDSCH Dsch;\r
+  RegDECCCTRL Ctr;\r
+\r
+  if (mrc_params->ecc_enables == 0) return;\r
+\r
+  ENTERFN();\r
+\r
+  // Configuration required in ECC mode\r
+  Drp.raw = isbR32m(MCU, DRP);\r
+  Drp.field.addressMap = 2;\r
+  Drp.field.split64 = 1;\r
+  isbW32m(MCU, DRP, Drp.raw);\r
+\r
+  // Disable new request bypass\r
+  Dsch.raw = isbR32m(MCU, DSCH);\r
+  Dsch.field.NEWBYPDIS = 1;\r
+  isbW32m(MCU, DSCH, Dsch.raw);\r
+\r
+  // Enable ECC\r
+  Ctr.raw = 0;\r
+  Ctr.field.SBEEN = 1;\r
+  Ctr.field.DBEEN = 1;\r
+  Ctr.field.ENCBGEN = 1;\r
+  isbW32m(MCU, DECCCTRL, Ctr.raw);\r
+\r
+#ifdef SIM\r
+  // Read back to be sure writing took place\r
+  Ctr.raw = isbR32m(MCU, DECCCTRL);\r
+#endif\r
+\r
+  // Assume 8 bank memory, one bank is gone for ECC\r
+  mrc_params->mem_size -= mrc_params->mem_size / 8;\r
+\r
+  // For S3 resume memory content has to be preserved\r
+  if (mrc_params->boot_mode != bmS3)\r
+  {\r
+    select_hte(mrc_params);\r
+    HteMemInit(mrc_params, MrcMemInit, MrcHaltHteEngineOnError);\r
+    select_memory_manager(mrc_params);\r
+  }\r
+\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
+// Lock MCU registers at the end of initialisation sequence.\r
+static void lock_registers(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  RegDCO Dco;\r
+\r
+  ENTERFN();\r
+\r
+  Dco.raw = isbR32m(MCU, DCO);\r
+  Dco.field.PMIDIS = 0;          //0 - PRI enabled\r
+  Dco.field.PMICTL = 0;          //0 - PRI owned by MEMORY_MANAGER\r
+  Dco.field.DRPLOCK = 1;\r
+  Dco.field.REUTLOCK = 1;\r
+  isbW32m(MCU, DCO, Dco.raw);\r
+\r
+  LEAVEFN();\r
+\r
+}\r
+\r
+#ifdef MRC_SV\r
+\r
+// cache write back invalidate\r
+static void asm_wbinvd(void)\r
+{\r
+#if defined (SIM) || defined (GCC)\r
+  asm(\r
+    "wbinvd;"\r
+  );\r
+#else\r
+  __asm wbinvd;\r
+#endif\r
+}\r
+\r
+// cache invalidate\r
+static void asm_invd(void)\r
+{\r
+#if defined (SIM) || defined (GCC)\r
+  asm(\r
+      "invd;"\r
+  );\r
+#else\r
+  __asm invd;\r
+#endif\r
+}\r
+\r
+\r
+static void cpu_read(void)\r
+{\r
+  uint32_t adr, dat, limit;\r
+\r
+  asm_invd();\r
+\r
+  limit = 8 * 1024;\r
+  for (adr = 0; adr < limit; adr += 4)\r
+  {\r
+    dat = *(uint32_t*) adr;\r
+    if ((adr & 0x0F) == 0)\r
+    {\r
+      DPF(D_INFO, "\n%x : ", adr);\r
+    }\r
+    DPF(D_INFO, "%x ", dat);\r
+  }\r
+  DPF(D_INFO, "\n");\r
+\r
+  DPF(D_INFO, "CPU read done\n");\r
+}\r
+\r
+\r
+static void cpu_write(void)\r
+{\r
+  uint32_t adr, limit;\r
+\r
+  limit = 8 * 1024;\r
+  for (adr = 0; adr < limit; adr += 4)\r
+  {\r
+    *(uint32_t*) adr = 0xDEAD0000 + adr;\r
+  }\r
+\r
+  asm_wbinvd();\r
+\r
+  DPF(D_INFO, "CPU write done\n");\r
+}\r
+\r
+\r
+static void cpu_memory_test(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  uint32_t result = 0;\r
+  uint32_t val, dat, adr, adr0, step, limit;\r
+  uint64_t my_tsc;\r
+\r
+  ENTERFN();\r
+\r
+  asm_invd();\r
+\r
+  adr0 = 1 * 1024 * 1024;\r
+  limit = 256 * 1024 * 1024;\r
+\r
+  for (step = 0; step <= 4; step++)\r
+  {\r
+    DPF(D_INFO, "Mem test step %d starting from %xh\n", step, adr0);\r
+\r
+    my_tsc = read_tsc();\r
+    for (adr = adr0; adr < limit; adr += sizeof(uint32_t))\r
+    {\r
+      if (step == 0)      dat = adr;\r
+      else if (step == 1) dat = (1 << ((adr >> 2) & 0x1f));\r
+      else if (step == 2) dat = ~(1 << ((adr >> 2) & 0x1f));\r
+      else if (step == 3) dat = 0x5555AAAA;\r
+      else if (step == 4) dat = 0xAAAA5555;\r
+\r
+      *(uint32_t*) adr = dat;\r
+    }\r
+    DPF(D_INFO, "Write time %llXh\n", read_tsc() - my_tsc);\r
+\r
+    my_tsc = read_tsc();\r
+    for (adr = adr0; adr < limit; adr += sizeof(uint32_t))\r
+    {\r
+      if (step == 0)      dat = adr;\r
+      else if (step == 1) dat = (1 << ((adr >> 2) & 0x1f));\r
+      else if (step == 2) dat = ~(1 << ((adr >> 2) & 0x1f));\r
+      else if (step == 3) dat = 0x5555AAAA;\r
+      else if (step == 4) dat = 0xAAAA5555;\r
+\r
+      val = *(uint32_t*) adr;\r
+\r
+      if (val != dat)\r
+      {\r
+        DPF(D_INFO, "%x vs. %x@%x\n", dat, val, adr);\r
+        result = adr|BIT31;\r
+      }\r
+    }\r
+    DPF(D_INFO, "Read time %llXh\n", read_tsc() - my_tsc);\r
+  }\r
+\r
+  DPF( D_INFO, "Memory test result %x\n", result);\r
+  LEAVEFN();\r
+}\r
+#endif // MRC_SV\r
+\r
+\r
+// Execute memory test, if error dtected it is\r
+// indicated in mrc_params->status.\r
+static void memory_test(\r
+  MRCParams_t *mrc_params)\r
+{\r
+  uint32_t result = 0;\r
+\r
+  ENTERFN();\r
+\r
+  select_hte(mrc_params);\r
+  result = HteMemInit(mrc_params, MrcMemTest, MrcHaltHteEngineOnError);\r
+  select_memory_manager(mrc_params);\r
+\r
+  DPF(D_INFO, "Memory test result %x\n", result);\r
+  mrc_params->status = ((result == 0) ? MRC_SUCCESS : MRC_E_MEMTEST);\r
+  LEAVEFN();\r
+}\r
+\r
+\r
+// Force same timings as with backup settings\r
+static void static_timings(\r
+  MRCParams_t *mrc_params)\r
+\r
+{\r
+  uint8_t ch, rk, bl;\r
+\r
+  for (ch = 0; ch < NUM_CHANNELS; ch++)\r
+  {\r
+    for (rk = 0; rk < NUM_RANKS; rk++)\r
+    {\r
+      for (bl = 0; bl < NUM_BYTE_LANES; bl++)\r
+      {\r
+        set_rcvn(ch, rk, bl, 498);  // RCVN\r
+        set_rdqs(ch, rk, bl,  24);  // RDQS\r
+        set_wdqs(ch, rk, bl, 292);  // WDQS\r
+        set_wdq( ch, rk, bl, 260);  // WDQ\r
+        if (rk == 0)\r
+        {\r
+          set_vref(ch, bl, 32); // VREF (RANK0 only)\r
+        }\r
+      }\r
+      set_wctl(ch, rk, 217); // WCTL\r
+    }\r
+    set_wcmd(ch, 220); // WCMD\r
+  }\r
+\r
+  return;\r
+}\r
+\r
+//\r
+// Initialise system memory.\r
+//\r
+void MemInit(\r
+  MRCParams_t *mrc_params)\r
+{\r
+  static const MemInit_t init[] =\r
+  {\r
+    { 0x0101, bmCold|bmFast|bmWarm|bmS3, clear_self_refresh       }, //0\r
+    { 0x0200, bmCold|bmFast|bmWarm|bmS3, prog_ddr_timing_control  }, //1  initialise the MCU\r
+    { 0x0103, bmCold|bmFast            , prog_decode_before_jedec }, //2\r
+    { 0x0104, bmCold|bmFast            , perform_ddr_reset        }, //3\r
+    { 0x0300, bmCold|bmFast       |bmS3, ddrphy_init              }, //4  initialise the DDRPHY\r
+    { 0x0400, bmCold|bmFast            , perform_jedec_init       }, //5  perform JEDEC initialisation of DRAMs\r
+    { 0x0105, bmCold|bmFast            , set_ddr_init_complete    }, //6\r
+    { 0x0106,        bmFast|bmWarm|bmS3, restore_timings          }, //7\r
+    { 0x0106, bmCold                   , default_timings          }, //8\r
+    { 0x0500, bmCold                   , rcvn_cal                 }, //9  perform RCVN_CAL algorithm\r
+    { 0x0600, bmCold                   , wr_level                 }, //10  perform WR_LEVEL algorithm\r
+    { 0x0120, bmCold                   , prog_page_ctrl           }, //11\r
+    { 0x0700, bmCold                   , rd_train                 }, //12  perform RD_TRAIN algorithm\r
+    { 0x0800, bmCold                   , wr_train                 }, //13  perform WR_TRAIN algorithm\r
+    { 0x010B, bmCold                   , store_timings            }, //14\r
+    { 0x010C, bmCold|bmFast|bmWarm|bmS3, enable_scrambling        }, //15\r
+    { 0x010D, bmCold|bmFast|bmWarm|bmS3, prog_ddr_control         }, //16\r
+    { 0x010E, bmCold|bmFast|bmWarm|bmS3, prog_dra_drb             }, //17\r
+    { 0x010F,               bmWarm|bmS3, perform_wake             }, //18\r
+    { 0x0110, bmCold|bmFast|bmWarm|bmS3, change_refresh_period    }, //19\r
+    { 0x0111, bmCold|bmFast|bmWarm|bmS3, set_auto_refresh         }, //20\r
+    { 0x0112, bmCold|bmFast|bmWarm|bmS3, ecc_enable               }, //21\r
+    { 0x0113, bmCold|bmFast            , memory_test              }, //22\r
+    { 0x0114, bmCold|bmFast|bmWarm|bmS3, lock_registers           }  //23 set init done\r
+  };\r
+\r
+  uint32_t i;\r
+\r
+  ENTERFN();\r
+\r
+  DPF(D_INFO, "Meminit build %s %s\n", __DATE__, __TIME__);\r
+\r
+  // MRC started\r
+  post_code(0x01, 0x00);\r
+\r
+  if (mrc_params->boot_mode != bmCold)\r
+  {\r
+    if (mrc_params->ddr_speed != mrc_params->timings.ddr_speed)\r
+    {\r
+      // full training required as frequency changed\r
+      mrc_params->boot_mode = bmCold;\r
+    }\r
+  }\r
+\r
+  for (i = 0; i < MCOUNT(init); i++)\r
+  {\r
+    uint64_t my_tsc;\r
+\r
+#ifdef MRC_SV\r
+    if (mrc_params->menu_after_mrc && i > 14)\r
+    {\r
+      uint8_t ch;\r
+\r
+      mylop:\r
+\r
+      DPF(D_INFO, "-- c - continue --\n");\r
+      DPF(D_INFO, "-- j - move to jedec init --\n");\r
+      DPF(D_INFO, "-- m - memory test --\n");\r
+      DPF(D_INFO, "-- r - cpu read --\n");\r
+      DPF(D_INFO, "-- w - cpu write --\n");\r
+      DPF(D_INFO, "-- b - hte base test --\n");\r
+      DPF(D_INFO, "-- g - hte extended test --\n");\r
+\r
+      ch = mgetc();\r
+      switch (ch)\r
+      {\r
+      case 'c':\r
+        break;\r
+      case 'j':  //move to jedec init\r
+        i = 5;\r
+        break;\r
+\r
+      case 'M':\r
+      case 'N':\r
+        {\r
+    uint32_t n, res, cnt=0;\r
+\r
+    for(n=0; mgetch()==0; n++)\r
+    {\r
+      if( ch == 'M' || n % 256 == 0)\r
+      {\r
+        DPF(D_INFO, "n=%d e=%d\n", n, cnt);\r
+      }\r
+\r
+      res = 0;\r
+\r
+      if( ch == 'M')\r
+      {\r
+        memory_test(mrc_params);\r
+        res |= mrc_params->status;\r
+            }\r
+\r
+      mrc_params->hte_setup = 1;\r
+            res |= check_bls_ex(mrc_params, 0x00000000);\r
+            res |= check_bls_ex(mrc_params, 0x00000000);\r
+            res |= check_bls_ex(mrc_params, 0x00000000);\r
+            res |= check_bls_ex(mrc_params, 0x00000000);\r
+\r
+      if( mrc_params->rank_enables & 2)\r
+      {\r
+        mrc_params->hte_setup = 1;\r
+              res |= check_bls_ex(mrc_params, 0x40000000);\r
+              res |= check_bls_ex(mrc_params, 0x40000000);\r
+              res |= check_bls_ex(mrc_params, 0x40000000);\r
+              res |= check_bls_ex(mrc_params, 0x40000000);\r
+      }\r
+\r
+      if( res != 0)\r
+      {\r
+              DPF(D_INFO, "###########\n");\r
+              DPF(D_INFO, "#\n");\r
+              DPF(D_INFO, "# Error count %d\n", ++cnt);\r
+              DPF(D_INFO, "#\n");\r
+              DPF(D_INFO, "###########\n");\r
+      }\r
+\r
+    } // for\r
+\r
+          select_memory_manager(mrc_params);\r
+  }\r
+        goto mylop;\r
+      case 'm':\r
+        memory_test(mrc_params);\r
+        goto mylop;\r
+      case 'n':\r
+        cpu_memory_test(mrc_params);\r
+        goto mylop;\r
+\r
+      case 'l':\r
+        ch = mgetc();\r
+        if (ch <= '9') DpfPrintMask ^= (ch - '0') << 3;\r
+        DPF(D_INFO, "Log mask %x\n", DpfPrintMask);\r
+        goto mylop;\r
+      case 'p':\r
+        print_timings(mrc_params);\r
+        goto mylop;\r
+      case 'R':\r
+        rd_train(mrc_params);\r
+        goto mylop;\r
+      case 'W':\r
+        wr_train(mrc_params);\r
+        goto mylop;\r
+\r
+      case 'r':\r
+        cpu_read();\r
+        goto mylop;\r
+      case 'w':\r
+        cpu_write();\r
+        goto mylop;\r
+\r
+      case 'g':\r
+        {\r
+        uint32_t result;\r
+        select_hte(mrc_params);\r
+        mrc_params->hte_setup = 1;\r
+        result = check_bls_ex(mrc_params, 0);\r
+        DPF(D_INFO, "Extended test result %x\n", result);\r
+        select_memory_manager(mrc_params);\r
+        }\r
+        goto mylop;\r
+      case 'b':\r
+        {\r
+        uint32_t result;\r
+        select_hte(mrc_params);\r
+        mrc_params->hte_setup = 1;\r
+        result = check_rw_coarse(mrc_params, 0);\r
+        DPF(D_INFO, "Base test result %x\n", result);\r
+        select_memory_manager(mrc_params);\r
+        }\r
+        goto mylop;\r
+      case 'B':\r
+        select_hte(mrc_params);\r
+        HteMemOp(0x2340, 1, 1);\r
+        select_memory_manager(mrc_params);\r
+        goto mylop;\r
+\r
+      case '3':\r
+        {\r
+        RegDPMC0 DPMC0reg;\r
+\r
+        DPF( D_INFO, "===>> Start suspend\n");\r
+        isbR32m(MCU, DSTAT);\r
+\r
+        DPMC0reg.raw = isbR32m(MCU, DPMC0);\r
+        DPMC0reg.field.DYNSREN = 0;\r
+        DPMC0reg.field.powerModeOpCode = 0x05;    // Disable Master DLL\r
+        isbW32m(MCU, DPMC0, DPMC0reg.raw);\r
+\r
+        // Should be off for negative test case verification\r
+        #if 1\r
+        Wr32(MMIO, PCIADDR(0,0,0,SB_PACKET_REG),\r
+            (uint32_t)SB_COMMAND(SB_SUSPEND_CMND_OPCODE, MCU, 0));\r
+        #endif\r
+\r
+        DPF( D_INFO, "press key\n");\r
+        mgetc();\r
+        DPF( D_INFO, "===>> Start resume\n");\r
+        isbR32m(MCU, DSTAT);\r
+\r
+        mrc_params->boot_mode = bmS3;\r
+        i = 0;\r
+        }\r
+\r
+      } // switch\r
+\r
+    } // if( menu\r
+#endif //MRC_SV\r
+\r
+    if (mrc_params->boot_mode & init[i].boot_path)\r
+    {\r
+      uint8_t major = init[i].post_code >> 8 & 0xFF;\r
+      uint8_t minor = init[i].post_code >> 0 & 0xFF;\r
+      post_code(major, minor);\r
+\r
+      my_tsc = read_tsc();\r
+      init[i].init_fn(mrc_params);\r
+      DPF(D_TIME, "Execution time %llX", read_tsc() - my_tsc);\r
+    }\r
+  }\r
+\r
+  // display the timings\r
+  print_timings(mrc_params);\r
+\r
+  // MRC is complete.\r
+  post_code(0x01, 0xFF);\r
+\r
+  LEAVEFN();\r
+  return;\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit.h
new file mode 100644 (file)
index 0000000..e2c1266
--- /dev/null
@@ -0,0 +1,28 @@
+/************************************************************************\r
+ *\r
+ * Copyright (c) 2013-2015 Intel Corporation.\r
+ *\r
+* This program and the accompanying materials\r
+* are licensed and made available under the terms and conditions of the BSD License\r
+* which accompanies this distribution.  The full text of the license may be found at\r
+* http://opensource.org/licenses/bsd-license.php\r
+*\r
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ *\r
+ ************************************************************************/\r
+#ifndef _MEMINIT_H_\r
+#define _MEMINIT_H_\r
+\r
+// function prototypes\r
+void MemInit(MRCParams_t *mrc_params);\r
+\r
+typedef void (*MemInitFn_t)(MRCParams_t *mrc_params);\r
+\r
+typedef struct MemInit_s {\r
+  uint16_t    post_code;\r
+  uint16_t    boot_path;\r
+  MemInitFn_t init_fn;\r
+} MemInit_t;\r
+\r
+#endif // _MEMINIT_H_\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit_utils.c b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit_utils.c
new file mode 100644 (file)
index 0000000..f0c8757
--- /dev/null
@@ -0,0 +1,1580 @@
+/************************************************************************\r
+ *\r
+ * Copyright (c) 2013-2015 Intel Corporation.\r
+ *\r
+* This program and the accompanying materials\r
+* are licensed and made available under the terms and conditions of the BSD License\r
+* which accompanies this distribution.  The full text of the license may be found at\r
+* http://opensource.org/licenses/bsd-license.php\r
+*\r
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ *\r
+ ***************************************************************************/\r
+\r
+#include "mrc.h"\r
+#include "memory_options.h"\r
+\r
+#include "meminit_utils.h"\r
+#include "hte.h"\r
+#include "io.h"\r
+\r
+void select_hte(\r
+    MRCParams_t *mrc_params);\r
+\r
+static uint8_t first_run = 0;\r
+\r
+const uint8_t vref_codes[64] =\r
+{ // lowest to highest\r
+    0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, // 00 - 15\r
+    0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, // 16 - 31\r
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, // 32 - 47\r
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F  // 48 - 63\r
+};\r
+\r
+#ifdef EMU\r
+// Track current post code for debugging purpose\r
+uint32_t PostCode;\r
+#endif\r
+\r
+// set_rcvn:\r
+//\r
+// This function will program the RCVEN delays.\r
+// (currently doesn't comprehend rank)\r
+void set_rcvn(\r
+    uint8_t channel,\r
+    uint8_t rank,\r
+    uint8_t byte_lane,\r
+    uint32_t pi_count)\r
+{\r
+  uint32_t reg;\r
+  uint32_t msk;\r
+  uint32_t tempD;\r
+\r
+  ENTERFN();\r
+  DPF(D_TRN, "Rcvn ch%d rnk%d ln%d : pi=%03X\n", channel, rank, byte_lane, pi_count);\r
+\r
+  // RDPTR (1/2 MCLK, 64 PIs)\r
+  // BL0 -> B01PTRCTL0[11:08] (0x0-0xF)\r
+  // BL1 -> B01PTRCTL0[23:20] (0x0-0xF)\r
+  reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);\r
+  msk = (byte_lane & BIT0) ? (BIT23 | BIT22 | BIT21 | BIT20) : (BIT11 | BIT10 | BIT9 | BIT8);\r
+  tempD = (byte_lane & BIT0) ? ((pi_count / HALF_CLK) << 20) : ((pi_count / HALF_CLK) << 8);\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+\r
+  // Adjust PI_COUNT\r
+  pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;\r
+\r
+  // PI (1/64 MCLK, 1 PIs)\r
+  // BL0 -> B0DLLPICODER0[29:24] (0x00-0x3F)\r
+  // BL1 -> B1DLLPICODER0[29:24] (0x00-0x3F)\r
+  reg = (byte_lane & BIT0) ? (B1DLLPICODER0) : (B0DLLPICODER0);\r
+  reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));\r
+  msk = (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24);\r
+  tempD = pi_count << 24;\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+\r
+  // DEADBAND\r
+  // BL0/1 -> B01DBCTL1[08/11] (+1 select)\r
+  // BL0/1 -> B01DBCTL1[02/05] (enable)\r
+  reg = B01DBCTL1 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);\r
+  msk = 0x00;\r
+  tempD = 0x00;\r
+  // enable\r
+  msk |= (byte_lane & BIT0) ? (BIT5) : (BIT2);\r
+  if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))\r
+  {\r
+    tempD |= msk;\r
+  }\r
+  // select\r
+  msk |= (byte_lane & BIT0) ? (BIT11) : (BIT8);\r
+  if (pi_count < EARLY_DB)\r
+  {\r
+    tempD |= msk;\r
+  }\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+\r
+  // error check\r
+  if (pi_count > 0x3F)\r
+  {\r
+    training_message(channel, rank, byte_lane);\r
+    post_code(0xEE, 0xE0);\r
+  }\r
+\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
+// get_rcvn:\r
+//\r
+// This function will return the current RCVEN delay on the given channel, rank, byte_lane as an absolute PI count.\r
+// (currently doesn't comprehend rank)\r
+uint32_t get_rcvn(\r
+    uint8_t channel,\r
+    uint8_t rank,\r
+    uint8_t byte_lane)\r
+{\r
+  uint32_t reg;\r
+  uint32_t tempD;\r
+  uint32_t pi_count;\r
+\r
+  ENTERFN();\r
+\r
+  // RDPTR (1/2 MCLK, 64 PIs)\r
+  // BL0 -> B01PTRCTL0[11:08] (0x0-0xF)\r
+  // BL1 -> B01PTRCTL0[23:20] (0x0-0xF)\r
+  reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);\r
+  tempD = isbR32m(DDRPHY, reg);\r
+  tempD >>= (byte_lane & BIT0) ? (20) : (8);\r
+  tempD &= 0xF;\r
+\r
+  // Adjust PI_COUNT\r
+  pi_count = tempD * HALF_CLK;\r
+\r
+  // PI (1/64 MCLK, 1 PIs)\r
+  // BL0 -> B0DLLPICODER0[29:24] (0x00-0x3F)\r
+  // BL1 -> B1DLLPICODER0[29:24] (0x00-0x3F)\r
+  reg = (byte_lane & BIT0) ? (B1DLLPICODER0) : (B0DLLPICODER0);\r
+  reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));\r
+  tempD = isbR32m(DDRPHY, reg);\r
+  tempD >>= 24;\r
+  tempD &= 0x3F;\r
+\r
+  // Adjust PI_COUNT\r
+  pi_count += tempD;\r
+\r
+  LEAVEFN();\r
+  return pi_count;\r
+}\r
+\r
+// set_rdqs:\r
+//\r
+// This function will program the RDQS delays based on an absolute amount of PIs.\r
+// (currently doesn't comprehend rank)\r
+void set_rdqs(\r
+    uint8_t channel,\r
+    uint8_t rank,\r
+    uint8_t byte_lane,\r
+    uint32_t pi_count)\r
+{\r
+  uint32_t reg;\r
+  uint32_t msk;\r
+  uint32_t tempD;\r
+\r
+  ENTERFN();\r
+  DPF(D_TRN, "Rdqs ch%d rnk%d ln%d : pi=%03X\n", channel, rank, byte_lane, pi_count);\r
+\r
+  // PI (1/128 MCLK)\r
+  // BL0 -> B0RXDQSPICODE[06:00] (0x00-0x47)\r
+  // BL1 -> B1RXDQSPICODE[06:00] (0x00-0x47)\r
+  reg = (byte_lane & BIT0) ? (B1RXDQSPICODE) : (B0RXDQSPICODE);\r
+  reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));\r
+  msk = (BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0);\r
+  tempD = pi_count << 0;\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+\r
+  // error check (shouldn't go above 0x3F)\r
+  if (pi_count > 0x47)\r
+  {\r
+    training_message(channel, rank, byte_lane);\r
+    post_code(0xEE, 0xE1);\r
+  }\r
+\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
+// get_rdqs:\r
+//\r
+// This function will return the current RDQS delay on the given channel, rank, byte_lane as an absolute PI count.\r
+// (currently doesn't comprehend rank)\r
+uint32_t get_rdqs(\r
+    uint8_t channel,\r
+    uint8_t rank,\r
+    uint8_t byte_lane)\r
+{\r
+  uint32_t reg;\r
+  uint32_t tempD;\r
+  uint32_t pi_count;\r
+\r
+  ENTERFN();\r
+\r
+  // PI (1/128 MCLK)\r
+  // BL0 -> B0RXDQSPICODE[06:00] (0x00-0x47)\r
+  // BL1 -> B1RXDQSPICODE[06:00] (0x00-0x47)\r
+  reg = (byte_lane & BIT0) ? (B1RXDQSPICODE) : (B0RXDQSPICODE);\r
+  reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));\r
+  tempD = isbR32m(DDRPHY, reg);\r
+\r
+  // Adjust PI_COUNT\r
+  pi_count = tempD & 0x7F;\r
+\r
+  LEAVEFN();\r
+  return pi_count;\r
+}\r
+\r
+// set_wdqs:\r
+//\r
+// This function will program the WDQS delays based on an absolute amount of PIs.\r
+// (currently doesn't comprehend rank)\r
+void set_wdqs(\r
+    uint8_t channel,\r
+    uint8_t rank,\r
+    uint8_t byte_lane,\r
+    uint32_t pi_count)\r
+{\r
+  uint32_t reg;\r
+  uint32_t msk;\r
+  uint32_t tempD;\r
+\r
+  ENTERFN();\r
+  DPF(D_TRN, "Wdqs ch%d rnk%d ln%d : pi=%03X\n", channel, rank, byte_lane, pi_count);\r
+\r
+  // RDPTR (1/2 MCLK, 64 PIs)\r
+  // BL0 -> B01PTRCTL0[07:04] (0x0-0xF)\r
+  // BL1 -> B01PTRCTL0[19:16] (0x0-0xF)\r
+  reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);\r
+  msk = (byte_lane & BIT0) ? (BIT19 | BIT18 | BIT17 | BIT16) : (BIT7 | BIT6 | BIT5 | BIT4);\r
+  tempD = pi_count / HALF_CLK;\r
+  tempD <<= (byte_lane & BIT0) ? (16) : (4);\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+\r
+  // Adjust PI_COUNT\r
+  pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;\r
+\r
+  // PI (1/64 MCLK, 1 PIs)\r
+  // BL0 -> B0DLLPICODER0[21:16] (0x00-0x3F)\r
+  // BL1 -> B1DLLPICODER0[21:16] (0x00-0x3F)\r
+  reg = (byte_lane & BIT0) ? (B1DLLPICODER0) : (B0DLLPICODER0);\r
+  reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));\r
+  msk = (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16);\r
+  tempD = pi_count << 16;\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+\r
+  // DEADBAND\r
+  // BL0/1 -> B01DBCTL1[07/10] (+1 select)\r
+  // BL0/1 -> B01DBCTL1[01/04] (enable)\r
+  reg = B01DBCTL1 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);\r
+  msk = 0x00;\r
+  tempD = 0x00;\r
+  // enable\r
+  msk |= (byte_lane & BIT0) ? (BIT4) : (BIT1);\r
+  if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))\r
+  {\r
+    tempD |= msk;\r
+  }\r
+  // select\r
+  msk |= (byte_lane & BIT0) ? (BIT10) : (BIT7);\r
+  if (pi_count < EARLY_DB)\r
+  {\r
+    tempD |= msk;\r
+  }\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+\r
+  // error check\r
+  if (pi_count > 0x3F)\r
+  {\r
+    training_message(channel, rank, byte_lane);\r
+    post_code(0xEE, 0xE2);\r
+  }\r
+\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
+// get_wdqs:\r
+//\r
+// This function will return the amount of WDQS delay on the given channel, rank, byte_lane as an absolute PI count.\r
+// (currently doesn't comprehend rank)\r
+uint32_t get_wdqs(\r
+    uint8_t channel,\r
+    uint8_t rank,\r
+    uint8_t byte_lane)\r
+{\r
+  uint32_t reg;\r
+  uint32_t tempD;\r
+  uint32_t pi_count;\r
+\r
+  ENTERFN();\r
+\r
+  // RDPTR (1/2 MCLK, 64 PIs)\r
+  // BL0 -> B01PTRCTL0[07:04] (0x0-0xF)\r
+  // BL1 -> B01PTRCTL0[19:16] (0x0-0xF)\r
+  reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);\r
+  tempD = isbR32m(DDRPHY, reg);\r
+  tempD >>= (byte_lane & BIT0) ? (16) : (4);\r
+  tempD &= 0xF;\r
+\r
+  // Adjust PI_COUNT\r
+  pi_count = (tempD * HALF_CLK);\r
+\r
+  // PI (1/64 MCLK, 1 PIs)\r
+  // BL0 -> B0DLLPICODER0[21:16] (0x00-0x3F)\r
+  // BL1 -> B1DLLPICODER0[21:16] (0x00-0x3F)\r
+  reg = (byte_lane & BIT0) ? (B1DLLPICODER0) : (B0DLLPICODER0);\r
+  reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));\r
+  tempD = isbR32m(DDRPHY, reg);\r
+  tempD >>= 16;\r
+  tempD &= 0x3F;\r
+\r
+  // Adjust PI_COUNT\r
+  pi_count += tempD;\r
+\r
+  LEAVEFN();\r
+  return pi_count;\r
+}\r
+\r
+// set_wdq:\r
+//\r
+// This function will program the WDQ delays based on an absolute number of PIs.\r
+// (currently doesn't comprehend rank)\r
+void set_wdq(\r
+    uint8_t channel,\r
+    uint8_t rank,\r
+    uint8_t byte_lane,\r
+    uint32_t pi_count)\r
+{\r
+  uint32_t reg;\r
+  uint32_t msk;\r
+  uint32_t tempD;\r
+\r
+  ENTERFN();\r
+  DPF(D_TRN, "Wdq ch%d rnk%d ln%d : pi=%03X\n", channel, rank, byte_lane, pi_count);\r
+\r
+  // RDPTR (1/2 MCLK, 64 PIs)\r
+  // BL0 -> B01PTRCTL0[03:00] (0x0-0xF)\r
+  // BL1 -> B01PTRCTL0[15:12] (0x0-0xF)\r
+  reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);\r
+  msk = (byte_lane & BIT0) ? (BIT15 | BIT14 | BIT13 | BIT12) : (BIT3 | BIT2 | BIT1 | BIT0);\r
+  tempD = pi_count / HALF_CLK;\r
+  tempD <<= (byte_lane & BIT0) ? (12) : (0);\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+\r
+  // Adjust PI_COUNT\r
+  pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;\r
+\r
+  // PI (1/64 MCLK, 1 PIs)\r
+  // BL0 -> B0DLLPICODER0[13:08] (0x00-0x3F)\r
+  // BL1 -> B1DLLPICODER0[13:08] (0x00-0x3F)\r
+  reg = (byte_lane & BIT0) ? (B1DLLPICODER0) : (B0DLLPICODER0);\r
+  reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));\r
+  msk = (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8);\r
+  tempD = pi_count << 8;\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+\r
+  // DEADBAND\r
+  // BL0/1 -> B01DBCTL1[06/09] (+1 select)\r
+  // BL0/1 -> B01DBCTL1[00/03] (enable)\r
+  reg = B01DBCTL1 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);\r
+  msk = 0x00;\r
+  tempD = 0x00;\r
+  // enable\r
+  msk |= (byte_lane & BIT0) ? (BIT3) : (BIT0);\r
+  if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))\r
+  {\r
+    tempD |= msk;\r
+  }\r
+  // select\r
+  msk |= (byte_lane & BIT0) ? (BIT9) : (BIT6);\r
+  if (pi_count < EARLY_DB)\r
+  {\r
+    tempD |= msk;\r
+  }\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+\r
+  // error check\r
+  if (pi_count > 0x3F)\r
+  {\r
+    training_message(channel, rank, byte_lane);\r
+    post_code(0xEE, 0xE3);\r
+  }\r
+\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
+// get_wdq:\r
+//\r
+// This function will return the amount of WDQ delay on the given channel, rank, byte_lane as an absolute PI count.\r
+// (currently doesn't comprehend rank)\r
+uint32_t get_wdq(\r
+    uint8_t channel,\r
+    uint8_t rank,\r
+    uint8_t byte_lane)\r
+{\r
+  uint32_t reg;\r
+  uint32_t tempD;\r
+  uint32_t pi_count;\r
+\r
+  ENTERFN();\r
+\r
+  // RDPTR (1/2 MCLK, 64 PIs)\r
+  // BL0 -> B01PTRCTL0[03:00] (0x0-0xF)\r
+  // BL1 -> B01PTRCTL0[15:12] (0x0-0xF)\r
+  reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);\r
+  tempD = isbR32m(DDRPHY, reg);\r
+  tempD >>= (byte_lane & BIT0) ? (12) : (0);\r
+  tempD &= 0xF;\r
+\r
+  // Adjust PI_COUNT\r
+  pi_count = (tempD * HALF_CLK);\r
+\r
+  // PI (1/64 MCLK, 1 PIs)\r
+  // BL0 -> B0DLLPICODER0[13:08] (0x00-0x3F)\r
+  // BL1 -> B1DLLPICODER0[13:08] (0x00-0x3F)\r
+  reg = (byte_lane & BIT0) ? (B1DLLPICODER0) : (B0DLLPICODER0);\r
+  reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));\r
+  tempD = isbR32m(DDRPHY, reg);\r
+  tempD >>= 8;\r
+  tempD &= 0x3F;\r
+\r
+  // Adjust PI_COUNT\r
+  pi_count += tempD;\r
+\r
+  LEAVEFN();\r
+  return pi_count;\r
+}\r
+\r
+// set_wcmd:\r
+//\r
+// This function will program the WCMD delays based on an absolute number of PIs.\r
+void set_wcmd(\r
+    uint8_t channel,\r
+    uint32_t pi_count)\r
+{\r
+  uint32_t reg;\r
+  uint32_t msk;\r
+  uint32_t tempD;\r
+\r
+  ENTERFN();\r
+  // RDPTR (1/2 MCLK, 64 PIs)\r
+  // CMDPTRREG[11:08] (0x0-0xF)\r
+  reg = CMDPTRREG + (channel * DDRIOCCC_CH_OFFSET);\r
+  msk = (BIT11 | BIT10 | BIT9 | BIT8);\r
+  tempD = pi_count / HALF_CLK;\r
+  tempD <<= 8;\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+\r
+  // Adjust PI_COUNT\r
+  pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;\r
+\r
+  // PI (1/64 MCLK, 1 PIs)\r
+  // CMDDLLPICODER0[29:24] -> CMDSLICE R3 (unused)\r
+  // CMDDLLPICODER0[21:16] -> CMDSLICE L3 (unused)\r
+  // CMDDLLPICODER0[13:08] -> CMDSLICE R2 (unused)\r
+  // CMDDLLPICODER0[05:00] -> CMDSLICE L2 (unused)\r
+  // CMDDLLPICODER1[29:24] -> CMDSLICE R1 (unused)\r
+  // CMDDLLPICODER1[21:16] -> CMDSLICE L1 (0x00-0x3F)\r
+  // CMDDLLPICODER1[13:08] -> CMDSLICE R0 (unused)\r
+  // CMDDLLPICODER1[05:00] -> CMDSLICE L0 (unused)\r
+  reg = CMDDLLPICODER1 + (channel * DDRIOCCC_CH_OFFSET);\r
+\r
+  msk = (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24) | (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16)\r
+      | (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8) | (BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0);\r
+\r
+  tempD = (pi_count << 24) | (pi_count << 16) | (pi_count << 8) | (pi_count << 0);\r
+\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+  reg = CMDDLLPICODER0 + (channel * DDRIOCCC_CH_OFFSET); // PO\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+\r
+  // DEADBAND\r
+  // CMDCFGREG0[17] (+1 select)\r
+  // CMDCFGREG0[16] (enable)\r
+  reg = CMDCFGREG0 + (channel * DDRIOCCC_CH_OFFSET);\r
+  msk = 0x00;\r
+  tempD = 0x00;\r
+  // enable\r
+  msk |= BIT16;\r
+  if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))\r
+  {\r
+    tempD |= msk;\r
+  }\r
+  // select\r
+  msk |= BIT17;\r
+  if (pi_count < EARLY_DB)\r
+  {\r
+    tempD |= msk;\r
+  }\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+\r
+  // error check\r
+  if (pi_count > 0x3F)\r
+  {\r
+    post_code(0xEE, 0xE4);\r
+  }\r
+\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
+// get_wcmd:\r
+//\r
+// This function will return the amount of WCMD delay on the given channel as an absolute PI count.\r
+uint32_t get_wcmd(\r
+    uint8_t channel)\r
+{\r
+  uint32_t reg;\r
+  uint32_t tempD;\r
+  uint32_t pi_count;\r
+\r
+  ENTERFN();\r
+  // RDPTR (1/2 MCLK, 64 PIs)\r
+  // CMDPTRREG[11:08] (0x0-0xF)\r
+  reg = CMDPTRREG + (channel * DDRIOCCC_CH_OFFSET);\r
+  tempD = isbR32m(DDRPHY, reg);\r
+  tempD >>= 8;\r
+  tempD &= 0xF;\r
+\r
+  // Adjust PI_COUNT\r
+  pi_count = tempD * HALF_CLK;\r
+\r
+  // PI (1/64 MCLK, 1 PIs)\r
+  // CMDDLLPICODER0[29:24] -> CMDSLICE R3 (unused)\r
+  // CMDDLLPICODER0[21:16] -> CMDSLICE L3 (unused)\r
+  // CMDDLLPICODER0[13:08] -> CMDSLICE R2 (unused)\r
+  // CMDDLLPICODER0[05:00] -> CMDSLICE L2 (unused)\r
+  // CMDDLLPICODER1[29:24] -> CMDSLICE R1 (unused)\r
+  // CMDDLLPICODER1[21:16] -> CMDSLICE L1 (0x00-0x3F)\r
+  // CMDDLLPICODER1[13:08] -> CMDSLICE R0 (unused)\r
+  // CMDDLLPICODER1[05:00] -> CMDSLICE L0 (unused)\r
+  reg = CMDDLLPICODER1 + (channel * DDRIOCCC_CH_OFFSET);\r
+  tempD = isbR32m(DDRPHY, reg);\r
+  tempD >>= 16;\r
+  tempD &= 0x3F;\r
+\r
+  // Adjust PI_COUNT\r
+  pi_count += tempD;\r
+\r
+  LEAVEFN();\r
+  return pi_count;\r
+}\r
+\r
+// set_wclk:\r
+//\r
+// This function will program the WCLK delays based on an absolute number of PIs.\r
+void set_wclk(\r
+    uint8_t channel,\r
+    uint8_t rank,\r
+    uint32_t pi_count)\r
+{\r
+  uint32_t reg;\r
+  uint32_t msk;\r
+  uint32_t tempD;\r
+\r
+  ENTERFN();\r
+  // RDPTR (1/2 MCLK, 64 PIs)\r
+  // CCPTRREG[15:12] -> CLK1 (0x0-0xF)\r
+  // CCPTRREG[11:08] -> CLK0 (0x0-0xF)\r
+  reg = CCPTRREG + (channel * DDRIOCCC_CH_OFFSET);\r
+  msk = (BIT15 | BIT14 | BIT13 | BIT12) | (BIT11 | BIT10 | BIT9 | BIT8);\r
+  tempD = ((pi_count / HALF_CLK) << 12) | ((pi_count / HALF_CLK) << 8);\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+\r
+  // Adjust PI_COUNT\r
+  pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;\r
+\r
+  // PI (1/64 MCLK, 1 PIs)\r
+  // ECCB1DLLPICODER0[13:08] -> CLK0 (0x00-0x3F)\r
+  // ECCB1DLLPICODER0[21:16] -> CLK1 (0x00-0x3F)\r
+  reg = (rank) ? (ECCB1DLLPICODER0) : (ECCB1DLLPICODER0);\r
+  reg += (channel * DDRIOCCC_CH_OFFSET);\r
+  msk = (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16) | (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8);\r
+  tempD = (pi_count << 16) | (pi_count << 8);\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+  reg = (rank) ? (ECCB1DLLPICODER1) : (ECCB1DLLPICODER1);\r
+  reg += (channel * DDRIOCCC_CH_OFFSET);\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+  reg = (rank) ? (ECCB1DLLPICODER2) : (ECCB1DLLPICODER2);\r
+  reg += (channel * DDRIOCCC_CH_OFFSET);\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+  reg = (rank) ? (ECCB1DLLPICODER3) : (ECCB1DLLPICODER3);\r
+  reg += (channel * DDRIOCCC_CH_OFFSET);\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+\r
+  // DEADBAND\r
+  // CCCFGREG1[11:08] (+1 select)\r
+  // CCCFGREG1[03:00] (enable)\r
+  reg = CCCFGREG1 + (channel * DDRIOCCC_CH_OFFSET);\r
+  msk = 0x00;\r
+  tempD = 0x00;\r
+  // enable\r
+  msk |= (BIT3 | BIT2 | BIT1 | BIT0); // only ??? matters\r
+  if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))\r
+  {\r
+    tempD |= msk;\r
+  }\r
+  // select\r
+  msk |= (BIT11 | BIT10 | BIT9 | BIT8); // only ??? matters\r
+  if (pi_count < EARLY_DB)\r
+  {\r
+    tempD |= msk;\r
+  }\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+\r
+  // error check\r
+  if (pi_count > 0x3F)\r
+  {\r
+    post_code(0xEE, 0xE5);\r
+  }\r
+\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
+// get_wclk:\r
+//\r
+// This function will return the amout of WCLK delay on the given channel, rank as an absolute PI count.\r
+uint32_t get_wclk(\r
+    uint8_t channel,\r
+    uint8_t rank)\r
+{\r
+  uint32_t reg;\r
+  uint32_t tempD;\r
+  uint32_t pi_count;\r
+\r
+  ENTERFN();\r
+  // RDPTR (1/2 MCLK, 64 PIs)\r
+  // CCPTRREG[15:12] -> CLK1 (0x0-0xF)\r
+  // CCPTRREG[11:08] -> CLK0 (0x0-0xF)\r
+  reg = CCPTRREG + (channel * DDRIOCCC_CH_OFFSET);\r
+  tempD = isbR32m(DDRPHY, reg);\r
+  tempD >>= (rank) ? (12) : (8);\r
+  tempD &= 0xF;\r
+\r
+  // Adjust PI_COUNT\r
+  pi_count = tempD * HALF_CLK;\r
+\r
+  // PI (1/64 MCLK, 1 PIs)\r
+  // ECCB1DLLPICODER0[13:08] -> CLK0 (0x00-0x3F)\r
+  // ECCB1DLLPICODER0[21:16] -> CLK1 (0x00-0x3F)\r
+  reg = (rank) ? (ECCB1DLLPICODER0) : (ECCB1DLLPICODER0);\r
+  reg += (channel * DDRIOCCC_CH_OFFSET);\r
+  tempD = isbR32m(DDRPHY, reg);\r
+  tempD >>= (rank) ? (16) : (8);\r
+  tempD &= 0x3F;\r
+\r
+  pi_count += tempD;\r
+\r
+  LEAVEFN();\r
+  return pi_count;\r
+}\r
+\r
+// set_wctl:\r
+//\r
+// This function will program the WCTL delays based on an absolute number of PIs.\r
+// (currently doesn't comprehend rank)\r
+void set_wctl(\r
+    uint8_t channel,\r
+    uint8_t rank,\r
+    uint32_t pi_count)\r
+{\r
+  uint32_t reg;\r
+  uint32_t msk;\r
+  uint32_t tempD;\r
+\r
+  ENTERFN();\r
+\r
+  // RDPTR (1/2 MCLK, 64 PIs)\r
+  // CCPTRREG[31:28] (0x0-0xF)\r
+  // CCPTRREG[27:24] (0x0-0xF)\r
+  reg = CCPTRREG + (channel * DDRIOCCC_CH_OFFSET);\r
+  msk = (BIT31 | BIT30 | BIT29 | BIT28) | (BIT27 | BIT26 | BIT25 | BIT24);\r
+  tempD = ((pi_count / HALF_CLK) << 28) | ((pi_count / HALF_CLK) << 24);\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+\r
+  // Adjust PI_COUNT\r
+  pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;\r
+\r
+  // PI (1/64 MCLK, 1 PIs)\r
+  // ECCB1DLLPICODER?[29:24] (0x00-0x3F)\r
+  // ECCB1DLLPICODER?[29:24] (0x00-0x3F)\r
+  reg = ECCB1DLLPICODER0 + (channel * DDRIOCCC_CH_OFFSET);\r
+  msk = (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24);\r
+  tempD = (pi_count << 24);\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+  reg = ECCB1DLLPICODER1 + (channel * DDRIOCCC_CH_OFFSET);\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+  reg = ECCB1DLLPICODER2 + (channel * DDRIOCCC_CH_OFFSET);\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+  reg = ECCB1DLLPICODER3 + (channel * DDRIOCCC_CH_OFFSET);\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+\r
+  // DEADBAND\r
+  // CCCFGREG1[13:12] (+1 select)\r
+  // CCCFGREG1[05:04] (enable)\r
+  reg = CCCFGREG1 + (channel * DDRIOCCC_CH_OFFSET);\r
+  msk = 0x00;\r
+  tempD = 0x00;\r
+  // enable\r
+  msk |= (BIT5 | BIT4); // only ??? matters\r
+  if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))\r
+  {\r
+    tempD |= msk;\r
+  }\r
+  // select\r
+  msk |= (BIT13 | BIT12); // only ??? matters\r
+  if (pi_count < EARLY_DB)\r
+  {\r
+    tempD |= msk;\r
+  }\r
+  isbM32m(DDRPHY, reg, tempD, msk);\r
+\r
+  // error check\r
+  if (pi_count > 0x3F)\r
+  {\r
+    post_code(0xEE, 0xE6);\r
+  }\r
+\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
+// get_wctl:\r
+//\r
+// This function will return the amount of WCTL delay on the given channel, rank as an absolute PI count.\r
+// (currently doesn't comprehend rank)\r
+uint32_t get_wctl(\r
+    uint8_t channel,\r
+    uint8_t rank)\r
+{\r
+  uint32_t reg;\r
+  uint32_t tempD;\r
+  uint32_t pi_count;\r
+\r
+  ENTERFN();\r
+\r
+  // RDPTR (1/2 MCLK, 64 PIs)\r
+  // CCPTRREG[31:28] (0x0-0xF)\r
+  // CCPTRREG[27:24] (0x0-0xF)\r
+  reg = CCPTRREG + (channel * DDRIOCCC_CH_OFFSET);\r
+  tempD = isbR32m(DDRPHY, reg);\r
+  tempD >>= 24;\r
+  tempD &= 0xF;\r
+\r
+  // Adjust PI_COUNT\r
+  pi_count = tempD * HALF_CLK;\r
+\r
+  // PI (1/64 MCLK, 1 PIs)\r
+  // ECCB1DLLPICODER?[29:24] (0x00-0x3F)\r
+  // ECCB1DLLPICODER?[29:24] (0x00-0x3F)\r
+  reg = ECCB1DLLPICODER0 + (channel * DDRIOCCC_CH_OFFSET);\r
+  tempD = isbR32m(DDRPHY, reg);\r
+  tempD >>= 24;\r
+  tempD &= 0x3F;\r
+\r
+  // Adjust PI_COUNT\r
+  pi_count += tempD;\r
+\r
+  LEAVEFN();\r
+  return pi_count;\r
+}\r
+\r
+// set_vref:\r
+//\r
+// This function will program the internal Vref setting in a given byte lane in a given channel.\r
+void set_vref(\r
+    uint8_t channel,\r
+    uint8_t byte_lane,\r
+    uint32_t setting)\r
+{\r
+  uint32_t reg = (byte_lane & 0x1) ? (B1VREFCTL) : (B0VREFCTL);\r
+\r
+  ENTERFN();\r
+  DPF(D_TRN, "Vref ch%d ln%d : val=%03X\n", channel, byte_lane, setting);\r
+\r
+  isbM32m(DDRPHY, (reg + (channel * DDRIODQ_CH_OFFSET) + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET)),\r
+      (vref_codes[setting] << 2), (BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2));\r
+  //isbM32m(DDRPHY, (reg + (channel * DDRIODQ_CH_OFFSET) + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET)), (setting<<2), (BIT7|BIT6|BIT5|BIT4|BIT3|BIT2));\r
+  // need to wait ~300ns for Vref to settle (check that this is necessary)\r
+  delay_n(300);\r
+  // ??? may need to clear pointers ???\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
+// get_vref:\r
+//\r
+// This function will return the internal Vref setting for the given channel, byte_lane;\r
+uint32_t get_vref(\r
+    uint8_t channel,\r
+    uint8_t byte_lane)\r
+{\r
+  uint8_t j;\r
+  uint32_t ret_val = sizeof(vref_codes) / 2;\r
+  uint32_t reg = (byte_lane & 0x1) ? (B1VREFCTL) : (B0VREFCTL);\r
+\r
+  uint32_t tempD;\r
+\r
+  ENTERFN();\r
+  tempD = isbR32m(DDRPHY, (reg + (channel * DDRIODQ_CH_OFFSET) + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET)));\r
+  tempD >>= 2;\r
+  tempD &= 0x3F;\r
+  for (j = 0; j < sizeof(vref_codes); j++)\r
+  {\r
+    if (vref_codes[j] == tempD)\r
+    {\r
+      ret_val = j;\r
+      break;\r
+    }\r
+  }\r
+  LEAVEFN();\r
+  return ret_val;\r
+}\r
+\r
+// clear_pointers:\r
+//\r
+// This function will be used to clear the pointers in a given byte lane in a given channel.\r
+void clear_pointers(\r
+    void)\r
+{\r
+  uint8_t channel_i;\r
+  uint8_t bl_i;\r
+\r
+  ENTERFN();\r
+  for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)\r
+  {\r
+    for (bl_i = 0; bl_i < NUM_BYTE_LANES; bl_i++)\r
+    {\r
+      isbM32m(DDRPHY, (B01PTRCTL1 + (channel_i * DDRIODQ_CH_OFFSET) + ((bl_i >> 1) * DDRIODQ_BL_OFFSET)), ~(BIT8),\r
+          (BIT8));\r
+      //delay_m(1); // DEBUG\r
+      isbM32m(DDRPHY, (B01PTRCTL1 + (channel_i * DDRIODQ_CH_OFFSET) + ((bl_i >> 1) * DDRIODQ_BL_OFFSET)), (BIT8),\r
+          (BIT8));\r
+    }\r
+  }\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
+// void enable_cache:\r
+void enable_cache(\r
+    void)\r
+{\r
+  // Cache control not used in Quark MRC\r
+  return;\r
+}\r
+\r
+// void disable_cache:\r
+void disable_cache(\r
+    void)\r
+{\r
+  // Cache control not used in Quark MRC\r
+  return;\r
+}\r
+\r
+// Send DRAM command, data should be formated\r
+// using DCMD_Xxxx macro or emrsXCommand structure.\r
+static void dram_init_command(\r
+    uint32_t data)\r
+{\r
+  Wr32(DCMD, 0, data);\r
+}\r
+\r
+// find_rising_edge:\r
+//\r
+// This function will find the rising edge transition on RCVN or WDQS.\r
+void find_rising_edge(\r
+    MRCParams_t *mrc_params,\r
+    uint32_t delay[],\r
+    uint8_t channel,\r
+    uint8_t rank,\r
+    bool rcvn)\r
+{\r
+\r
+#define SAMPLE_CNT 3   // number of sample points\r
+#define SAMPLE_DLY 26  // number of PIs to increment per sample\r
+#define FORWARD true   // indicates to increase delays when looking for edge\r
+#define BACKWARD false // indicates to decrease delays when looking for edge\r
+\r
+  bool all_edges_found; // determines stop condition\r
+  bool direction[NUM_BYTE_LANES]; // direction indicator\r
+  uint8_t sample_i; // sample counter\r
+  uint8_t bl_i; // byte lane counter\r
+  uint8_t bl_divisor = (mrc_params->channel_width == x16) ? 2 : 1; // byte lane divisor\r
+  uint32_t sample_result[SAMPLE_CNT]; // results of "sample_dqs()"\r
+  uint32_t tempD; // temporary DWORD\r
+  uint32_t transition_pattern;\r
+\r
+  ENTERFN();\r
+\r
+  // select hte and request initial configuration\r
+  select_hte(mrc_params);\r
+  first_run = 1;\r
+\r
+  // Take 3 sample points (T1,T2,T3) to obtain a transition pattern.\r
+  for (sample_i = 0; sample_i < SAMPLE_CNT; sample_i++)\r
+  {\r
+    // program the desired delays for sample\r
+    for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+    {\r
+      // increase sample delay by 26 PI (0.2 CLK)\r
+      if (rcvn)\r
+      {\r
+        set_rcvn(channel, rank, bl_i, delay[bl_i] + (sample_i * SAMPLE_DLY));\r
+      }\r
+      else\r
+      {\r
+        set_wdqs(channel, rank, bl_i, delay[bl_i] + (sample_i * SAMPLE_DLY));\r
+      }\r
+    } // bl_i loop\r
+    // take samples (Tsample_i)\r
+    sample_result[sample_i] = sample_dqs(mrc_params, channel, rank, rcvn);\r
+\r
+    DPF(D_TRN, "Find rising edge %s ch%d rnk%d: #%d dly=%d dqs=%02X\n",\r
+        (rcvn ? "RCVN" : "WDQS"), channel, rank,\r
+        sample_i, sample_i * SAMPLE_DLY, sample_result[sample_i]);\r
+\r
+  } // sample_i loop\r
+\r
+  // This pattern will help determine where we landed and ultimately how to place RCVEN/WDQS.\r
+  for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+  {\r
+    // build "transition_pattern" (MSB is 1st sample)\r
+    transition_pattern = 0x00;\r
+    for (sample_i = 0; sample_i < SAMPLE_CNT; sample_i++)\r
+    {\r
+      transition_pattern |= ((sample_result[sample_i] & (1 << bl_i)) >> bl_i) << (SAMPLE_CNT - 1 - sample_i);\r
+    } // sample_i loop\r
+\r
+    DPF(D_TRN, "=== transition pattern %d\n", transition_pattern);\r
+\r
+    // set up to look for rising edge based on "transition_pattern"\r
+    switch (transition_pattern)\r
+    {\r
+    case 0x00: // sampled 0->0->0\r
+      // move forward from T3 looking for 0->1\r
+      delay[bl_i] += 2 * SAMPLE_DLY;\r
+      direction[bl_i] = FORWARD;\r
+      break;\r
+    case 0x01: // sampled 0->0->1\r
+    case 0x05: // sampled 1->0->1 (bad duty cycle) *HSD#237503*\r
+      // move forward from T2 looking for 0->1\r
+      delay[bl_i] += 1 * SAMPLE_DLY;\r
+      direction[bl_i] = FORWARD;\r
+      break;\r
+// HSD#237503\r
+//      case 0x02: // sampled 0->1->0 (bad duty cycle)\r
+//        training_message(channel, rank, bl_i);\r
+//        post_code(0xEE, 0xE8);\r
+//        break;\r
+    case 0x02: // sampled 0->1->0 (bad duty cycle) *HSD#237503*\r
+    case 0x03: // sampled 0->1->1\r
+      // move forward from T1 looking for 0->1\r
+      delay[bl_i] += 0 * SAMPLE_DLY;\r
+      direction[bl_i] = FORWARD;\r
+      break;\r
+    case 0x04: // sampled 1->0->0 (assumes BL8, HSD#234975)\r
+      // move forward from T3 looking for 0->1\r
+      delay[bl_i] += 2 * SAMPLE_DLY;\r
+      direction[bl_i] = FORWARD;\r
+      break;\r
+// HSD#237503\r
+//      case 0x05: // sampled 1->0->1 (bad duty cycle)\r
+//        training_message(channel, rank, bl_i);\r
+//        post_code(0xEE, 0xE9);\r
+//        break;\r
+    case 0x06: // sampled 1->1->0\r
+    case 0x07: // sampled 1->1->1\r
+      // move backward from T1 looking for 1->0\r
+      delay[bl_i] += 0 * SAMPLE_DLY;\r
+      direction[bl_i] = BACKWARD;\r
+      break;\r
+    default:\r
+      post_code(0xEE, 0xEE);\r
+      break;\r
+    } // transition_pattern switch\r
+    // program delays\r
+    if (rcvn)\r
+    {\r
+      set_rcvn(channel, rank, bl_i, delay[bl_i]);\r
+    }\r
+    else\r
+    {\r
+      set_wdqs(channel, rank, bl_i, delay[bl_i]);\r
+    }\r
+  } // bl_i loop\r
+\r
+  // Based on the observed transition pattern on the byte lane,\r
+  // begin looking for a rising edge with single PI granularity.\r
+  do\r
+  {\r
+    all_edges_found = true; // assume all byte lanes passed\r
+    tempD = sample_dqs(mrc_params, channel, rank, rcvn); // take a sample\r
+    // check all each byte lane for proper edge\r
+    for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+    {\r
+      if (tempD & (1 << bl_i))\r
+      {\r
+        // sampled "1"\r
+        if (direction[bl_i] == BACKWARD)\r
+        {\r
+          // keep looking for edge on this byte lane\r
+          all_edges_found = false;\r
+          delay[bl_i] -= 1;\r
+          if (rcvn)\r
+          {\r
+            set_rcvn(channel, rank, bl_i, delay[bl_i]);\r
+          }\r
+          else\r
+          {\r
+            set_wdqs(channel, rank, bl_i, delay[bl_i]);\r
+          }\r
+        }\r
+      }\r
+      else\r
+      {\r
+        // sampled "0"\r
+        if (direction[bl_i] == FORWARD)\r
+        {\r
+          // keep looking for edge on this byte lane\r
+          all_edges_found = false;\r
+          delay[bl_i] += 1;\r
+          if (rcvn)\r
+          {\r
+            set_rcvn(channel, rank, bl_i, delay[bl_i]);\r
+          }\r
+          else\r
+          {\r
+            set_wdqs(channel, rank, bl_i, delay[bl_i]);\r
+          }\r
+        }\r
+      }\r
+    } // bl_i loop\r
+  } while (!all_edges_found);\r
+\r
+  // restore DDR idle state\r
+  dram_init_command(DCMD_PREA(rank));\r
+\r
+  DPF(D_TRN, "Delay %03X %03X %03X %03X\n",\r
+      delay[0], delay[1], delay[2], delay[3]);\r
+\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
+// sample_dqs:\r
+//\r
+// This function will sample the DQTRAINSTS registers in the given channel/rank SAMPLE_SIZE times looking for a valid '0' or '1'.\r
+// It will return an encoded DWORD in which each bit corresponds to the sampled value on the byte lane.\r
+uint32_t sample_dqs(\r
+    MRCParams_t *mrc_params,\r
+    uint8_t channel,\r
+    uint8_t rank,\r
+    bool rcvn)\r
+{\r
+  uint8_t j; // just a counter\r
+  uint8_t bl_i; // which BL in the module (always 2 per module)\r
+  uint8_t bl_grp; // which BL module\r
+  uint8_t bl_divisor = (mrc_params->channel_width == x16) ? 2 : 1; // byte lane divisor\r
+  uint32_t msk[2]; // BLx in module\r
+  uint32_t sampled_val[SAMPLE_SIZE]; // DQTRAINSTS register contents for each sample\r
+  uint32_t num_0s; // tracks the number of '0' samples\r
+  uint32_t num_1s; // tracks the number of '1' samples\r
+  uint32_t ret_val = 0x00; // assume all '0' samples\r
+  uint32_t address = get_addr(mrc_params, channel, rank);\r
+\r
+  // initialise "msk[]"\r
+  msk[0] = (rcvn) ? (BIT1) : (BIT9); // BL0\r
+  msk[1] = (rcvn) ? (BIT0) : (BIT8); // BL1\r
+\r
+\r
+  // cycle through each byte lane group\r
+  for (bl_grp = 0; bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2; bl_grp++)\r
+  {\r
+    // take SAMPLE_SIZE samples\r
+    for (j = 0; j < SAMPLE_SIZE; j++)\r
+    {\r
+      HteMemOp(address, first_run, rcvn?0:1);\r
+      first_run = 0;\r
+\r
+      // record the contents of the proper DQTRAINSTS register\r
+      sampled_val[j] = isbR32m(DDRPHY, (DQTRAINSTS + (bl_grp * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET)));\r
+    }\r
+    // look for a majority value ( (SAMPLE_SIZE/2)+1 ) on the byte lane\r
+    // and set that value in the corresponding "ret_val" bit\r
+    for (bl_i = 0; bl_i < 2; bl_i++)\r
+    {\r
+      num_0s = 0x00; // reset '0' tracker for byte lane\r
+      num_1s = 0x00; // reset '1' tracker for byte lane\r
+      for (j = 0; j < SAMPLE_SIZE; j++)\r
+      {\r
+        if (sampled_val[j] & msk[bl_i])\r
+        {\r
+          num_1s++;\r
+        }\r
+        else\r
+        {\r
+          num_0s++;\r
+        }\r
+      }\r
+      if (num_1s > num_0s)\r
+      {\r
+        ret_val |= (1 << (bl_i + (bl_grp * 2)));\r
+      }\r
+    }\r
+  }\r
+\r
+  // "ret_val.0" contains the status of BL0\r
+  // "ret_val.1" contains the status of BL1\r
+  // "ret_val.2" contains the status of BL2\r
+  // etc.\r
+  return ret_val;\r
+}\r
+\r
+// get_addr:\r
+//\r
+// This function will return a 32 bit address in the desired channel and rank.\r
+uint32_t get_addr(\r
+    MRCParams_t *mrc_params,\r
+    uint8_t channel,\r
+    uint8_t rank)\r
+{\r
+  uint32_t offset = 0x02000000; // 32MB\r
+\r
+  // Begin product specific code\r
+  if (channel > 0)\r
+  {\r
+    DPF(D_ERROR, "ILLEGAL CHANNEL\n");\r
+    DEAD_LOOP();\r
+  }\r
+\r
+  if (rank > 1)\r
+  {\r
+    DPF(D_ERROR, "ILLEGAL RANK\n");\r
+    DEAD_LOOP();\r
+  }\r
+\r
+  // use 256MB lowest density as per DRP == 0x0003\r
+  offset += rank * (256 * 1024 * 1024);\r
+\r
+  return offset;\r
+}\r
+\r
+// byte_lane_mask:\r
+//\r
+// This function will return a 32 bit mask that will be used to check for byte lane failures.\r
+uint32_t byte_lane_mask(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  uint32_t j;\r
+  uint32_t ret_val = 0x00;\r
+\r
+  // set "ret_val" based on NUM_BYTE_LANES such that you will check only BL0 in "result"\r
+  // (each bit in "result" represents a byte lane)\r
+  for (j = 0; j < MAX_BYTE_LANES; j += NUM_BYTE_LANES)\r
+  {\r
+    ret_val |= (1 << ((j / NUM_BYTE_LANES) * NUM_BYTE_LANES));\r
+  }\r
+\r
+  // HSD#235037\r
+  // need to adjust the mask for 16-bit mode\r
+  if (mrc_params->channel_width == x16)\r
+  {\r
+    ret_val |= (ret_val << 2);\r
+  }\r
+\r
+  return ret_val;\r
+}\r
+\r
+\r
+// read_tsc:\r
+//\r
+// This function will do some assembly to return TSC register contents as a uint64_t.\r
+uint64_t read_tsc(\r
+    void)\r
+{\r
+  volatile uint64_t tsc;  // EDX:EAX\r
+\r
+#if defined (SIM) || defined (GCC)\r
+  volatile uint32_t tscH; // EDX\r
+  volatile uint32_t tscL;// EAX\r
+\r
+  asm("rdtsc":"=a"(tscL),"=d"(tscH));\r
+  tsc = tscH;\r
+  tsc = (tsc<<32)|tscL;\r
+#else\r
+  tsc = __rdtsc();\r
+#endif\r
+\r
+  return tsc;\r
+}\r
+\r
+// get_tsc_freq:\r
+//\r
+// This function returns the TSC frequency in MHz\r
+uint32_t get_tsc_freq(\r
+    void)\r
+{\r
+  static uint32_t freq[] =\r
+  { 533, 400, 200, 100 };\r
+  uint32_t fuse;\r
+#if 0\r
+  fuse = (isbR32m(FUSE, 0) >> 12) & (BIT1|BIT0);\r
+#else\r
+  // todo!!! Fixed 533MHz for emulation or debugging\r
+  fuse = 0;\r
+#endif\r
+  return freq[fuse];\r
+}\r
+\r
+#ifndef SIM\r
+// delay_n:\r
+//\r
+// This is a simple delay function.\r
+// It takes "nanoseconds" as a parameter.\r
+void delay_n(\r
+    uint32_t nanoseconds)\r
+{\r
+  // 1000 MHz clock has 1ns period --> no conversion required\r
+  uint64_t final_tsc = read_tsc();\r
+  final_tsc += ((get_tsc_freq() * (nanoseconds)) / 1000);\r
+\r
+  while (read_tsc() < final_tsc)\r
+    ;\r
+  return;\r
+}\r
+#endif\r
+\r
+// delay_u:\r
+//\r
+// This is a simple delay function.\r
+// It takes "microseconds as a parameter.\r
+void delay_u(\r
+    uint32_t microseconds)\r
+{\r
+  // 64 bit math is not an option, just use loops\r
+  while (microseconds--)\r
+  {\r
+    delay_n(1000);\r
+  }\r
+  return;\r
+}\r
+\r
+// delay_m:\r
+//\r
+// This is a simple delay function.\r
+// It takes "milliseconds" as a parameter.\r
+void delay_m(\r
+    uint32_t milliseconds)\r
+{\r
+  // 64 bit math is not an option, just use loops\r
+  while (milliseconds--)\r
+  {\r
+    delay_u(1000);\r
+  }\r
+  return;\r
+}\r
+\r
+// delay_s:\r
+//\r
+// This is a simple delay function.\r
+// It takes "seconds" as a parameter.\r
+void delay_s(\r
+    uint32_t seconds)\r
+{\r
+  // 64 bit math is not an option, just use loops\r
+  while (seconds--)\r
+  {\r
+    delay_m(1000);\r
+  }\r
+  return;\r
+}\r
+\r
+// post_code:\r
+//\r
+// This function will output the POST CODE to the four 7-Segment LED displays.\r
+void post_code(\r
+    uint8_t major,\r
+    uint8_t minor)\r
+{\r
+#ifdef EMU\r
+  // Update global variable for execution tracking in debug env\r
+  PostCode = ((major << 8) | minor);\r
+#endif\r
+\r
+  // send message to UART\r
+  DPF(D_INFO, "POST: 0x%01X%02X\n", major, minor);\r
+\r
+  // error check:\r
+  if (major == 0xEE)\r
+  {\r
+    // todo!!! Consider updating error status and exit MRC\r
+#ifdef SIM\r
+    // enable Ctrl-C handling\r
+    for(;;) delay_n(100);\r
+#else\r
+    DEAD_LOOP();\r
+#endif\r
+  }\r
+}\r
+\r
+void training_message(\r
+    uint8_t channel,\r
+    uint8_t rank,\r
+    uint8_t byte_lane)\r
+{\r
+  // send message to UART\r
+  DPF(D_INFO, "CH%01X RK%01X BL%01X\n", channel, rank, byte_lane);\r
+  return;\r
+}\r
+\r
+void print_timings(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  uint8_t algo_i;\r
+  uint8_t channel_i;\r
+  uint8_t rank_i;\r
+  uint8_t bl_i;\r
+  uint8_t bl_divisor = (mrc_params->channel_width == x16) ? 2 : 1;\r
+\r
+  DPF(D_INFO, "\n---------------------------");\r
+  DPF(D_INFO, "\nALGO[CH:RK] BL0 BL1 BL2 BL3");\r
+  DPF(D_INFO, "\n===========================");\r
+  for (algo_i = 0; algo_i < eMAX_ALGOS; algo_i++)\r
+  {\r
+    for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)\r
+    {\r
+      if (mrc_params->channel_enables & (1 << channel_i))\r
+      {\r
+        for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)\r
+        {\r
+          if (mrc_params->rank_enables & (1 << rank_i))\r
+          {\r
+            switch (algo_i)\r
+            {\r
+            case eRCVN:\r
+              DPF(D_INFO, "\nRCVN[%02d:%02d]", channel_i, rank_i);\r
+              break;\r
+            case eWDQS:\r
+              DPF(D_INFO, "\nWDQS[%02d:%02d]", channel_i, rank_i);\r
+              break;\r
+            case eWDQx:\r
+              DPF(D_INFO, "\nWDQx[%02d:%02d]", channel_i, rank_i);\r
+              break;\r
+            case eRDQS:\r
+              DPF(D_INFO, "\nRDQS[%02d:%02d]", channel_i, rank_i);\r
+              break;\r
+            case eVREF:\r
+              DPF(D_INFO, "\nVREF[%02d:%02d]", channel_i, rank_i);\r
+              break;\r
+            case eWCMD:\r
+              DPF(D_INFO, "\nWCMD[%02d:%02d]", channel_i, rank_i);\r
+              break;\r
+            case eWCTL:\r
+              DPF(D_INFO, "\nWCTL[%02d:%02d]", channel_i, rank_i);\r
+              break;\r
+            case eWCLK:\r
+              DPF(D_INFO, "\nWCLK[%02d:%02d]", channel_i, rank_i);\r
+              break;\r
+            default:\r
+              break;\r
+            } // algo_i switch\r
+            for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)\r
+            {\r
+              switch (algo_i)\r
+              {\r
+              case eRCVN:\r
+                DPF(D_INFO, " %03d", get_rcvn(channel_i, rank_i, bl_i));\r
+                break;\r
+              case eWDQS:\r
+                DPF(D_INFO, " %03d", get_wdqs(channel_i, rank_i, bl_i));\r
+                break;\r
+              case eWDQx:\r
+                DPF(D_INFO, " %03d", get_wdq(channel_i, rank_i, bl_i));\r
+                break;\r
+              case eRDQS:\r
+                DPF(D_INFO, " %03d", get_rdqs(channel_i, rank_i, bl_i));\r
+                break;\r
+              case eVREF:\r
+                DPF(D_INFO, " %03d", get_vref(channel_i, bl_i));\r
+                break;\r
+              case eWCMD:\r
+                DPF(D_INFO, " %03d", get_wcmd(channel_i));\r
+                break;\r
+              case eWCTL:\r
+                DPF(D_INFO, " %03d", get_wctl(channel_i, rank_i));\r
+                break;\r
+              case eWCLK:\r
+                DPF(D_INFO, " %03d", get_wclk(channel_i, rank_i));\r
+                break;\r
+              default:\r
+                break;\r
+              } // algo_i switch\r
+            } // bl_i loop\r
+          } // if rank_i enabled\r
+        } // rank_i loop\r
+      } // if channel_i enabled\r
+    } // channel_i loop\r
+  } // algo_i loop\r
+  DPF(D_INFO, "\n---------------------------");\r
+  DPF(D_INFO, "\n");\r
+  return;\r
+}\r
+\r
+// 32 bit LFSR with characteristic polynomial:  X^32 + X^22 +X^2 + X^1\r
+// The function takes pointer to previous 32 bit value and modifies it to next value.\r
+void lfsr32(\r
+    uint32_t *lfsr_ptr)\r
+{\r
+  uint32_t bit;\r
+  uint32_t lfsr;\r
+  uint32_t i;\r
+\r
+  lfsr = *lfsr_ptr;\r
+\r
+  for (i = 0; i < 32; i++)\r
+  {\r
+    bit = 1 ^ (lfsr & BIT0);\r
+    bit = bit ^ ((lfsr & BIT1) >> 1);\r
+    bit = bit ^ ((lfsr & BIT2) >> 2);\r
+    bit = bit ^ ((lfsr & BIT22) >> 22);\r
+\r
+    lfsr = ((lfsr >> 1) | (bit << 31));\r
+  }\r
+\r
+  *lfsr_ptr = lfsr;\r
+  return;\r
+}\r
+\r
+// The purpose of this function is to ensure the SEC comes out of reset\r
+// and IA initiates the SEC enabling Memory Scrambling.\r
+void enable_scrambling(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  uint32_t lfsr = 0;\r
+  uint8_t i;\r
+\r
+  if (mrc_params->scrambling_enables == 0)\r
+    return;\r
+\r
+  ENTERFN();\r
+\r
+  // 32 bit seed is always stored in BIOS NVM.\r
+  lfsr = mrc_params->timings.scrambler_seed;\r
+\r
+  if (mrc_params->boot_mode == bmCold)\r
+  {\r
+    // factory value is 0 and in first boot, a clock based seed is loaded.\r
+    if (lfsr == 0)\r
+    {\r
+      lfsr = read_tsc() & 0x0FFFFFFF; // get seed from system clock and make sure it is not all 1's\r
+    }\r
+    // need to replace scrambler\r
+    // get next 32bit LFSR 16 times which is the last part of the previous scrambler vector.\r
+    else\r
+    {\r
+      for (i = 0; i < 16; i++)\r
+      {\r
+        lfsr32(&lfsr);\r
+      }\r
+    }\r
+    mrc_params->timings.scrambler_seed = lfsr;  // save new seed.\r
+  } // if (cold_boot)\r
+\r
+  // In warm boot or S3 exit, we have the previous seed.\r
+  // In cold boot, we have the last 32bit LFSR which is the new seed.\r
+  lfsr32(&lfsr); // shift to next value\r
+  isbW32m(MCU, SCRMSEED, (lfsr & 0x0003FFFF));\r
+  for (i = 0; i < 2; i++)\r
+  {\r
+    isbW32m(MCU, SCRMLO + i, (lfsr & 0xAAAAAAAA));\r
+  }\r
+\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
+// This function will store relevant timing data\r
+// This data will be used on subsequent boots to speed up boot times\r
+// and is required for Suspend To RAM capabilities.\r
+void store_timings(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  uint8_t ch, rk, bl;\r
+  MrcTimings_t *mt = &mrc_params->timings;\r
+\r
+  for (ch = 0; ch < NUM_CHANNELS; ch++)\r
+  {\r
+    for (rk = 0; rk < NUM_RANKS; rk++)\r
+    {\r
+      for (bl = 0; bl < NUM_BYTE_LANES; bl++)\r
+      {\r
+        mt->rcvn[ch][rk][bl] = get_rcvn(ch, rk, bl); // RCVN\r
+        mt->rdqs[ch][rk][bl] = get_rdqs(ch, rk, bl); // RDQS\r
+        mt->wdqs[ch][rk][bl] = get_wdqs(ch, rk, bl); // WDQS\r
+        mt->wdq[ch][rk][bl] = get_wdq(ch, rk, bl);  // WDQ\r
+        if (rk == 0)\r
+        {\r
+          mt->vref[ch][bl] = get_vref(ch, bl);  // VREF (RANK0 only)\r
+        }\r
+      }\r
+      mt->wctl[ch][rk] = get_wctl(ch, rk); // WCTL\r
+    }\r
+    mt->wcmd[ch] = get_wcmd(ch); // WCMD\r
+  }\r
+\r
+  // need to save for a case of changing frequency after warm reset\r
+  mt->ddr_speed = mrc_params->ddr_speed;\r
+\r
+  return;\r
+}\r
+\r
+// This function will retrieve relevant timing data\r
+// This data will be used on subsequent boots to speed up boot times\r
+// and is required for Suspend To RAM capabilities.\r
+void restore_timings(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  uint8_t ch, rk, bl;\r
+  const MrcTimings_t *mt = &mrc_params->timings;\r
+\r
+  for (ch = 0; ch < NUM_CHANNELS; ch++)\r
+  {\r
+    for (rk = 0; rk < NUM_RANKS; rk++)\r
+    {\r
+      for (bl = 0; bl < NUM_BYTE_LANES; bl++)\r
+      {\r
+        set_rcvn(ch, rk, bl, mt->rcvn[ch][rk][bl]); // RCVN\r
+        set_rdqs(ch, rk, bl, mt->rdqs[ch][rk][bl]); // RDQS\r
+        set_wdqs(ch, rk, bl, mt->wdqs[ch][rk][bl]); // WDQS\r
+        set_wdq(ch, rk, bl, mt->wdq[ch][rk][bl]);  // WDQ\r
+        if (rk == 0)\r
+        {\r
+          set_vref(ch, bl, mt->vref[ch][bl]); // VREF (RANK0 only)\r
+        }\r
+      }\r
+      set_wctl(ch, rk, mt->wctl[ch][rk]); // WCTL\r
+    }\r
+    set_wcmd(ch, mt->wcmd[ch]); // WCMD\r
+  }\r
+\r
+  return;\r
+}\r
+\r
+// Configure default settings normally set as part of read training\r
+// Some defaults have to be set earlier as they may affect earlier\r
+// training steps.\r
+void default_timings(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  uint8_t ch, rk, bl;\r
+\r
+  for (ch = 0; ch < NUM_CHANNELS; ch++)\r
+  {\r
+    for (rk = 0; rk < NUM_RANKS; rk++)\r
+    {\r
+      for (bl = 0; bl < NUM_BYTE_LANES; bl++)\r
+      {\r
+        set_rdqs(ch, rk, bl, 24); // RDQS\r
+        if (rk == 0)\r
+        {\r
+          set_vref(ch, bl, 32); // VREF (RANK0 only)\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  return;\r
+}\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit_utils.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/meminit_utils.h
new file mode 100644 (file)
index 0000000..04c59f5
--- /dev/null
@@ -0,0 +1,97 @@
+/************************************************************************\r
+ *\r
+ * Copyright (c) 2013-2015 Intel Corporation.\r
+ *\r
+* This program and the accompanying materials\r
+* are licensed and made available under the terms and conditions of the BSD License\r
+* which accompanies this distribution.  The full text of the license may be found at\r
+* http://opensource.org/licenses/bsd-license.php\r
+*\r
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ *\r
+ ***************************************************************************/\r
+#ifndef _MEMINIT_UTILS_H_\r
+#define _MEMINIT_UTILS_H_\r
+\r
+// General Definitions:\r
+#ifdef QUICKSIM\r
+#define SAMPLE_SIZE     4   // reduce number of training samples in simulation env\r
+#else\r
+#define SAMPLE_SIZE     6   // must be odd number\r
+#endif\r
+\r
+#define EARLY_DB    (0x12)  // must be less than this number to enable early deadband\r
+#define LATE_DB     (0x34)  // must be greater than this number to enable late deadband\r
+#define CHX_REGS    (11*4)\r
+#define FULL_CLK      128\r
+#define HALF_CLK       64\r
+#define QRTR_CLK       32\r
+\r
+\r
+\r
+#define MCEIL(num,den) ((uint8_t)((num+den-1)/den))\r
+#define MMAX(a,b)      ((((int32_t)(a))>((int32_t)(b)))?(a):(b))\r
+#define MCOUNT(a)      (sizeof(a)/sizeof(*a))\r
+\r
+typedef enum ALGOS_enum {\r
+  eRCVN = 0,\r
+  eWDQS,\r
+  eWDQx,\r
+  eRDQS,\r
+  eVREF,\r
+  eWCMD,\r
+  eWCTL,\r
+  eWCLK,\r
+  eMAX_ALGOS,\r
+} ALGOs_t;\r
+\r
+\r
+// Prototypes:\r
+void set_rcvn(uint8_t channel, uint8_t rank, uint8_t byte_lane, uint32_t pi_count);\r
+void set_rdqs(uint8_t channel, uint8_t rank, uint8_t byte_lane, uint32_t pi_count);\r
+void set_wdqs(uint8_t channel, uint8_t rank, uint8_t byte_lane, uint32_t pi_count);\r
+void set_wdq(uint8_t channel, uint8_t rank, uint8_t byte_lane, uint32_t pi_count);\r
+void set_wcmd(uint8_t channel, uint32_t pi_count);\r
+void set_wclk(uint8_t channel, uint8_t grp, uint32_t pi_count);\r
+void set_wctl(uint8_t channel, uint8_t rank, uint32_t pi_count);\r
+void set_vref(uint8_t channel, uint8_t byte_lane, uint32_t setting);\r
+uint32_t get_rcvn(uint8_t channel, uint8_t rank, uint8_t byte_lane);\r
+uint32_t get_rdqs(uint8_t channel, uint8_t rank, uint8_t byte_lane);\r
+uint32_t get_wdqs(uint8_t channel, uint8_t rank, uint8_t byte_lane);\r
+uint32_t get_wdq(uint8_t channel, uint8_t rank, uint8_t byte_lane);\r
+uint32_t get_wcmd(uint8_t channel);\r
+uint32_t get_wclk(uint8_t channel, uint8_t group);\r
+uint32_t get_wctl(uint8_t channel, uint8_t rank);\r
+uint32_t get_vref(uint8_t channel, uint8_t byte_lane);\r
+\r
+void clear_pointers(void);\r
+void enable_cache(void);\r
+void disable_cache(void);\r
+void find_rising_edge(MRCParams_t *mrc_params, uint32_t delay[], uint8_t channel, uint8_t rank, bool rcvn);\r
+uint32_t sample_dqs(MRCParams_t *mrc_params, uint8_t channel, uint8_t rank, bool rcvn);\r
+uint32_t get_addr(MRCParams_t *mrc_params, uint8_t channel, uint8_t rank);\r
+uint32_t byte_lane_mask(MRCParams_t *mrc_params);\r
+\r
+uint64_t read_tsc(void);\r
+uint32_t get_tsc_freq(void);\r
+void delay_n(uint32_t nanoseconds);\r
+void delay_u(uint32_t microseconds);\r
+void delay_m(uint32_t milliseconds);\r
+void delay_s(uint32_t seconds);\r
+\r
+void post_code(uint8_t major, uint8_t minor);\r
+void training_message(uint8_t channel, uint8_t rank, uint8_t byte_lane);\r
+void print_timings(MRCParams_t *mrc_params);\r
+\r
+void enable_scrambling(MRCParams_t *mrc_params);\r
+void store_timings(MRCParams_t *mrc_params);\r
+void restore_timings(MRCParams_t *mrc_params);\r
+void default_timings(MRCParams_t *mrc_params);\r
+\r
+#ifndef SIM\r
+void *memset(void *d, int c, size_t n);\r
+void *memcpy(void *d, const void *s, size_t n);\r
+#endif\r
+\r
+#endif // _MEMINIT_UTILS_H_\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/memory_options.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/memory_options.h
new file mode 100644 (file)
index 0000000..8452b98
--- /dev/null
@@ -0,0 +1,83 @@
+/** @file\r
+Common definitions and compilation switches for MRC\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#ifndef __MEMORY_OPTIONS_H\r
+#define __MEMORY_OPTIONS_H\r
+\r
+#include "core_types.h"\r
+\r
+// MRC COMPILE TIME SWITCHES:\r
+// ==========================\r
+\r
+\r
+\r
+//#define MRC_SV              // enable some validation opitons\r
+\r
+#if defined (SIM) || defined(EMU)\r
+#define QUICKSIM              // reduce execution time using shorter rd/wr sequences\r
+#endif\r
+\r
+#define CLT                   // required for Quark project\r
+\r
+\r
+\r
+//#define BACKUP_RCVN           // enable STATIC timing settings for RCVN (BACKUP_MODE)\r
+//#define BACKUP_WDQS           // enable STATIC timing settings for WDQS (BACKUP_MODE)\r
+//#define BACKUP_RDQS           // enable STATIC timing settings for RDQS (BACKUP_MODE)\r
+//#define BACKUP_WDQ            // enable STATIC timing settings for WDQ (BACKUP_MODE)\r
+\r
+\r
+\r
+//#define BACKUP_COMPS          // enable *COMP overrides (BACKUP_MODE)\r
+//#define RX_EYE_CHECK          // enable the RD_TRAIN eye check\r
+#define HMC_TEST              // enable Host to Memory Clock Alignment\r
+#define R2R_SHARING           // enable multi-rank support via rank2rank sharing\r
+\r
+#define FORCE_16BIT_DDRIO     // disable signals not used in 16bit mode of DDRIO\r
+\r
+\r
+\r
+//\r
+// Debug support\r
+//\r
+\r
+#ifdef NDEBUG\r
+#define DPF        if(0) dpf\r
+#else\r
+#define DPF        dpf\r
+#endif\r
+\r
+void dpf( uint32_t mask, char_t *bla, ...);\r
+\r
+\r
+uint8_t mgetc(void);\r
+uint8_t mgetch(void);\r
+\r
+\r
+// Debug print type\r
+#define D_ERROR      0x0001\r
+#define D_INFO       0x0002\r
+#define D_REGRD      0x0004\r
+#define D_REGWR      0x0008\r
+#define D_FCALL      0x0010\r
+#define D_TRN        0x0020\r
+#define D_TIME       0x0040\r
+\r
+#define ENTERFN()     DPF(D_FCALL, "<%s>\n", __FUNCTION__)\r
+#define LEAVEFN()     DPF(D_FCALL, "</%s>\n", __FUNCTION__)\r
+#define REPORTFN()    DPF(D_FCALL, "<%s/>\n", __FUNCTION__)\r
+\r
+extern uint32_t DpfPrintMask;\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/mrc.c b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/mrc.c
new file mode 100644 (file)
index 0000000..ae7e239
--- /dev/null
@@ -0,0 +1,46 @@
+/************************************************************************\r
+ *\r
+ * Copyright (c) 2013-2015 Intel Corporation.\r
+ *\r
+* This program and the accompanying materials\r
+* are licensed and made available under the terms and conditions of the BSD License\r
+* which accompanies this distribution.  The full text of the license may be found at\r
+* http://opensource.org/licenses/bsd-license.php\r
+*\r
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ *\r
+ ************************************************************************/\r
+#include "mrc.h"\r
+#include "memory_options.h"\r
+\r
+#include "meminit.h"\r
+#include "meminit_utils.h"\r
+#include "prememinit.h"\r
+#include "io.h"\r
+\r
+// Base address for UART registers\r
+extern uint32_t UartMmioBase;\r
+\r
+//\r
+// Memory Reference Code entry point when executing from BIOS\r
+//\r
+void Mrc( MRCParams_t *mrc_params)\r
+{\r
+  // configure uart base address assuming code relocated to eSRAM\r
+  UartMmioBase = mrc_params->uart_mmio_base;\r
+\r
+  ENTERFN();\r
+\r
+  DPF(D_INFO, "MRC Version %04X %s %s\n", MRC_VERSION, __DATE__, __TIME__);\r
+\r
+  // this will set up the data structures used by MemInit()\r
+  PreMemInit(mrc_params);\r
+\r
+  // this will initialize system memory\r
+  MemInit(mrc_params);\r
+\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/mrc.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/mrc.h
new file mode 100644 (file)
index 0000000..05055db
--- /dev/null
@@ -0,0 +1,166 @@
+/************************************************************************\r
+ *\r
+ * Copyright (c) 2013-2015 Intel Corporation.\r
+ *\r
+* This program and the accompanying materials\r
+* are licensed and made available under the terms and conditions of the BSD License\r
+* which accompanies this distribution.  The full text of the license may be found at\r
+* http://opensource.org/licenses/bsd-license.php\r
+*\r
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ *\r
+ ************************************************************************/\r
+#ifndef _MRC_H_\r
+#define _MRC_H_\r
+\r
+#include "core_types.h"\r
+\r
+// define the MRC Version\r
+#define MRC_VERSION 0x0112\r
+\r
+\r
+// architectural definitions\r
+#define NUM_CHANNELS   1 // number of channels\r
+#define NUM_RANKS      2 // number of ranks per channel\r
+#define NUM_BYTE_LANES 4 // number of byte lanes per channel\r
+\r
+// software limitations\r
+#define MAX_CHANNELS   1\r
+#define MAX_RANKS      2\r
+#define MAX_BYTE_LANES 4\r
+\r
+// only to mock MrcWrapper\r
+#define MAX_SOCKETS    1\r
+#define MAX_SIDES      1\r
+#define MAX_ROWS       (MAX_SIDES * MAX_SOCKETS)\r
+// end\r
+\r
+\r
+// Specify DRAM of nenory channel width\r
+enum {\r
+  x8,   // DRAM width\r
+  x16,  // DRAM width & Channel Width\r
+  x32   // Channel Width\r
+};\r
+\r
+// Specify DRAM speed\r
+enum {\r
+  DDRFREQ_800,\r
+  DDRFREQ_1066\r
+};\r
+\r
+// Specify DRAM type\r
+enum {\r
+  DDR3,\r
+  DDR3L\r
+};\r
+\r
+// Delay configuration for individual signals\r
+// Vref setting\r
+// Scrambler seed\r
+typedef struct MrcTimings_s\r
+{\r
+  uint32_t rcvn[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];\r
+  uint32_t rdqs[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];\r
+  uint32_t wdqs[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];\r
+  uint32_t wdq [NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];\r
+  uint32_t vref[NUM_CHANNELS][NUM_BYTE_LANES];\r
+  uint32_t wctl[NUM_CHANNELS][NUM_RANKS];\r
+  uint32_t wcmd[NUM_CHANNELS];\r
+\r
+  uint32_t scrambler_seed;\r
+  uint8_t  ddr_speed;            // need to save for the case of frequency change\r
+} MrcTimings_t;\r
+\r
+\r
+// DENSITY: 0=512Mb, 1=Gb, 2=2Gb, 3=4Gb\r
+// tCL is DRAM CAS Latency in clocks.\r
+// All other timings are in picoseconds.\r
+// Refer to JEDEC spec (or DRAM datasheet) when changing these values.\r
+typedef struct DRAMParams_s {\r
+  uint8_t  DENSITY;\r
+  uint8_t  tCL;   // CAS latency in clocks\r
+  uint32_t tRAS;  // ACT to PRE command period\r
+  uint32_t tWTR;  // Delay from start of internal write transaction to internal read command\r
+  uint32_t tRRD;  // ACT to ACT command period (JESD79 specific to page size 1K/2K)\r
+  uint32_t tFAW;  // Four activate window (JESD79 specific to page size 1K/2K)\r
+} DRAMParams_t;\r
+\r
+\r
+// Boot mode defined as bit mask (1<<n)\r
+#define bmCold     1    // full training\r
+#define bmFast     2    // restore timing parameters\r
+#define bmS3       4    // resume from S3\r
+#define bmWarm     8\r
+#define bmUnknown  0\r
+\r
+\r
+// MRC execution status\r
+#define MRC_SUCCESS     0      // initialization ok\r
+#define MRC_E_MEMTEST   1      // memtest failed\r
+\r
+\r
+//\r
+// Input/output/context parameters for Memory Reference Code\r
+//\r
+typedef struct MRCParams_s\r
+{\r
+  //\r
+  // Global settings\r
+  //\r
+\r
+  uint32_t boot_mode;           // bmCold, bmFast, bmWarm, bmS3\r
+  uint32_t uart_mmio_base;      // pcie serial port base address (force 0 to disable debug)\r
+\r
+  uint8_t  dram_width;          // x8, x16\r
+  uint8_t  ddr_speed;           // DDRFREQ_800, DDRFREQ_1066\r
+  uint8_t  ddr_type;            // DDR3, DDR3L\r
+  uint8_t  ecc_enables;         // 0, 1 (memory size reduced to 7/8)\r
+  uint8_t  scrambling_enables;  // 0, 1\r
+  uint32_t rank_enables;        // 1, 3 (1'st rank has to be populated if 2'nd rank present)\r
+  uint32_t channel_enables;     // 1 only\r
+  uint32_t channel_width;       // x16 only\r
+  uint32_t address_mode;        // 0, 1, 2 (mode 2 forced if ecc enabled)\r
+\r
+  // memConfig_t begin\r
+  uint8_t refresh_rate;         // REFRESH_RATE       : 1=1.95us, 2=3.9us, 3=7.8us, others=RESERVED\r
+  uint8_t sr_temp_range;        // SR_TEMP_RANGE      : 0=normal, 1=extended, others=RESERVED\r
+  uint8_t ron_value;            // RON_VALUE          : 0=34ohm, 1=40ohm, others=RESERVED (select MRS1.DIC driver impedance control)\r
+  uint8_t rtt_nom_value;        // RTT_NOM_VALUE      : 0=40ohm, 1=60ohm, 2=120ohm, others=RESERVED\r
+  uint8_t rd_odt_value;         // RD_ODT_VALUE       : 0=off, 1=60ohm, 2=120ohm, 3=180ohm, others=RESERVED\r
+  // memConfig_t end\r
+\r
+  DRAMParams_t params;\r
+\r
+  //\r
+  // Internally used\r
+  //\r
+\r
+  uint32_t board_id;            // internally used for board layout (use x8 or x16 memory)\r
+  uint32_t hte_setup : 1;       // when set hte reconfiguration requested\r
+  uint32_t menu_after_mrc : 1;\r
+  uint32_t power_down_disable :1;\r
+  uint32_t tune_rcvn :1;\r
+\r
+  uint32_t channel_size[NUM_CHANNELS];\r
+  uint32_t column_bits[NUM_CHANNELS];\r
+  uint32_t row_bits[NUM_CHANNELS];\r
+\r
+  uint32_t mrs1;                // register content saved during training\r
+\r
+  //\r
+  // Output\r
+  //\r
+\r
+  uint32_t status;              // initialization result (non zero specifies error code)\r
+  uint32_t mem_size;            // total memory size in bytes (excludes ECC banks)\r
+\r
+  MrcTimings_t timings;         // training results (also used on input)\r
+\r
+} MRCParams_t;\r
+\r
+// Alternative type name for consistent naming convention\r
+#define MRC_PARAMS    MRCParams_t\r
+\r
+#endif // _MRC_H_\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/platform.c b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/platform.c
new file mode 100644 (file)
index 0000000..cb6eb99
--- /dev/null
@@ -0,0 +1,192 @@
+/** @file\r
+The interface layer for memory controller access.\r
+It is supporting both real hardware platform and simulation environment.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include "mrc.h"\r
+#include "memory_options.h"\r
+#include "meminit_utils.h"\r
+#include "io.h"\r
+\r
+#ifdef SIM\r
+\r
+void SimMmio32Write (\r
+    uint32_t be,\r
+    uint32_t address,\r
+    uint32_t data );\r
+\r
+void SimMmio32Read (\r
+    uint32_t be,\r
+    uint32_t address,\r
+    uint32_t *data );\r
+\r
+void SimDelayClk (\r
+    uint32_t x2clk );\r
+\r
+// This is a simple delay function.\r
+// It takes "nanoseconds" as a parameter.\r
+void delay_n(uint32_t nanoseconds)\r
+{\r
+  SimDelayClk( 800*nanoseconds/1000);\r
+}\r
+#endif\r
+\r
+/****\r
+ *\r
+ ***/\r
+uint32_t Rd32(\r
+    uint32_t unit,\r
+    uint32_t addr)\r
+{\r
+  uint32_t data;\r
+\r
+  switch (unit)\r
+  {\r
+  case MEM:\r
+    case MMIO:\r
+#ifdef SIM\r
+    SimMmio32Read( 1, addr, &data);\r
+#else\r
+    data = *PTR32(addr);\r
+#endif\r
+    break;\r
+\r
+  case MCU:\r
+    case HOST_BRIDGE:\r
+    case MEMORY_MANAGER:\r
+    case HTE:\r
+    // Handle case addr bigger than 8bit\r
+    pciwrite32(0, 0, 0, SB_HADR_REG, addr & 0xFFF00);\r
+    addr &= 0x00FF;\r
+\r
+    pciwrite32(0, 0, 0, SB_PACKET_REG,\r
+        SB_COMMAND(SB_REG_READ_OPCODE, unit, addr));\r
+    data = pciread32(0, 0, 0, SB_DATA_REG);\r
+    break;\r
+\r
+  case DDRPHY:\r
+    // Handle case addr bigger than 8bit\r
+    pciwrite32(0, 0, 0, SB_HADR_REG, addr & 0xFFF00);\r
+    addr &= 0x00FF;\r
+\r
+    pciwrite32(0, 0, 0, SB_PACKET_REG,\r
+        SB_COMMAND(SB_DDRIO_REG_READ_OPCODE, unit, addr));\r
+    data = pciread32(0, 0, 0, SB_DATA_REG);\r
+    break;\r
+\r
+  default:\r
+    DEAD_LOOP()\r
+    ;\r
+  }\r
+\r
+  if (unit < MEM)\r
+    DPF(D_REGRD, "RD32 %03X %08X %08X\n", unit, addr, data);\r
+\r
+  return data;\r
+}\r
+\r
+/****\r
+ *\r
+ ***/\r
+void Wr32(\r
+    uint32_t unit,\r
+    uint32_t addr,\r
+    uint32_t data)\r
+{\r
+  if (unit < MEM)\r
+    DPF(D_REGWR, "WR32 %03X %08X %08X\n", unit, addr, data);\r
+\r
+  switch (unit)\r
+  {\r
+  case MEM:\r
+    case MMIO:\r
+#ifdef SIM\r
+    SimMmio32Write( 1, addr, data);\r
+#else\r
+    *PTR32(addr) = data;\r
+#endif\r
+    break;\r
+\r
+  case MCU:\r
+    case HOST_BRIDGE:\r
+    case MEMORY_MANAGER:\r
+    case HTE:\r
+    // Handle case addr bigger than 8bit\r
+    pciwrite32(0, 0, 0, SB_HADR_REG, addr & 0xFFF00);\r
+    addr &= 0x00FF;\r
+\r
+    pciwrite32(0, 0, 0, SB_DATA_REG, data);\r
+    pciwrite32(0, 0, 0, SB_PACKET_REG,\r
+        SB_COMMAND(SB_REG_WRITE_OPCODE, unit, addr));\r
+    break;\r
+\r
+  case DDRPHY:\r
+    // Handle case addr bigger than 8bit\r
+    pciwrite32(0, 0, 0, SB_HADR_REG, addr & 0xFFF00);\r
+    addr &= 0x00FF;\r
+\r
+    pciwrite32(0, 0, 0, SB_DATA_REG, data);\r
+    pciwrite32(0, 0, 0, SB_PACKET_REG,\r
+        SB_COMMAND(SB_DDRIO_REG_WRITE_OPCODE, unit, addr));\r
+    break;\r
+\r
+  case DCMD:\r
+    pciwrite32(0, 0, 0, SB_HADR_REG, 0);\r
+    pciwrite32(0, 0, 0, SB_DATA_REG, data);\r
+    pciwrite32(0, 0, 0, SB_PACKET_REG,\r
+        SB_COMMAND(SB_DRAM_CMND_OPCODE, MCU, 0));\r
+    break;\r
+\r
+  default:\r
+    DEAD_LOOP()\r
+    ;\r
+  }\r
+}\r
+\r
+/****\r
+ *\r
+ ***/\r
+void WrMask32(\r
+    uint32_t unit,\r
+    uint32_t addr,\r
+    uint32_t data,\r
+    uint32_t mask)\r
+{\r
+  Wr32(unit, addr, ((Rd32(unit, addr) & ~mask) | (data & mask)));\r
+}\r
+\r
+/****\r
+ *\r
+ ***/\r
+void pciwrite32(\r
+    uint32_t bus,\r
+    uint32_t dev,\r
+    uint32_t fn,\r
+    uint32_t reg,\r
+    uint32_t data)\r
+{\r
+  Wr32(MMIO, PCIADDR(bus,dev,fn,reg), data);\r
+}\r
+\r
+/****\r
+ *\r
+ ***/\r
+uint32_t pciread32(\r
+    uint32_t bus,\r
+    uint32_t dev,\r
+    uint32_t fn,\r
+    uint32_t reg)\r
+{\r
+  return Rd32(MMIO, PCIADDR(bus,dev,fn,reg));\r
+}\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/prememinit.c b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/prememinit.c
new file mode 100644 (file)
index 0000000..f34eb4a
--- /dev/null
@@ -0,0 +1,193 @@
+/************************************************************************\r
+ *\r
+ * Copyright (c) 2013-2015 Intel Corporation.\r
+ *\r
+* This program and the accompanying materials\r
+* are licensed and made available under the terms and conditions of the BSD License\r
+* which accompanies this distribution.  The full text of the license may be found at\r
+* http://opensource.org/licenses/bsd-license.php\r
+*\r
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ *\r
+ ************************************************************************/\r
+\r
+#include "mrc.h"\r
+#include "memory_options.h"\r
+\r
+#include "meminit_utils.h"\r
+#include "prememinit.h"\r
+#include "io.h"\r
+\r
+// Read character from serial console\r
+uint8_t mgetc(void);\r
+\r
+extern uint32_t DpfPrintMask;\r
+\r
+// Adjust configuration parameters before initialisation\r
+// sequence.\r
+void PreMemInit(\r
+    MRCParams_t *mrc_params)\r
+{\r
+  const DRAMParams_t *dram_params;\r
+\r
+  uint8_t dram_width;\r
+  uint32_t dram_cfg_index;\r
+  uint32_t channel_i;\r
+\r
+  ENTERFN();\r
+\r
+#ifdef MRC_SV\r
+  {\r
+    uint8_t ch;\r
+\r
+    myloop:\r
+\r
+    DPF(D_INFO, "- c - continue\n");\r
+    DPF(D_INFO, "- f - boot mode [%d]\n", mrc_params->boot_mode);\r
+    DPF(D_INFO, "- r - rank enable [%d]\n", mrc_params->rank_enables);\r
+    DPF(D_INFO, "- e - ecc switch [%d]\n", mrc_params->ecc_enables);\r
+    DPF(D_INFO, "- b - scrambling switch [%d]\n", mrc_params->scrambling_enables);\r
+    DPF(D_INFO, "- a - adr mode [%d]\n", mrc_params->address_mode);\r
+    DPF(D_INFO, "- m - menu after mrc [%d]\n", mrc_params->menu_after_mrc);\r
+    DPF(D_INFO, "- t - tune to rcvn [%d]\n", mrc_params->tune_rcvn);\r
+    DPF(D_INFO, "- o - odt switch [%d]\n", mrc_params->rd_odt_value);\r
+    DPF(D_INFO, "- d - dram density [%d]\n", mrc_params->params.DENSITY);\r
+    DPF(D_INFO, "- p - power down disable [%d]\n", mrc_params->power_down_disable);\r
+    DPF(D_INFO, "- l - log switch 0x%x\n", DpfPrintMask);\r
+    ch = mgetc();\r
+\r
+    switch (ch)\r
+    {\r
+    case 'f':\r
+      mrc_params->boot_mode >>= 1;\r
+      if(mrc_params->boot_mode == bmUnknown)\r
+      {\r
+         mrc_params->boot_mode = bmWarm;\r
+      }\r
+      DPF(D_INFO, "Boot mode %d\n", mrc_params->boot_mode);\r
+      break;\r
+\r
+    case 'p':\r
+      mrc_params->power_down_disable ^= 1;\r
+      DPF(D_INFO, "Power down disable %d\n", mrc_params->power_down_disable);\r
+      break;\r
+\r
+    case 'r':\r
+      mrc_params->rank_enables ^= 2;\r
+      DPF(D_INFO, "Rank enable %d\n", mrc_params->rank_enables);\r
+      break;\r
+\r
+    case 'e':\r
+      mrc_params->ecc_enables ^= 1;\r
+      DPF(D_INFO, "Ecc enable %d\n", mrc_params->ecc_enables);\r
+      break;\r
+\r
+    case 'b':\r
+      mrc_params->scrambling_enables ^= 1;\r
+      DPF(D_INFO, "Scrambler enable %d\n", mrc_params->scrambling_enables);\r
+      break;\r
+\r
+    case 'a':\r
+      mrc_params->address_mode = (mrc_params->address_mode + 1) % 3;\r
+      DPF(D_INFO, "Adr mode %d\n", mrc_params->address_mode);\r
+      break;\r
+\r
+    case 'm':\r
+       mrc_params->menu_after_mrc ^= 1;\r
+      DPF(D_INFO, "Menu after mrc %d\n", mrc_params->menu_after_mrc);\r
+      break;\r
+\r
+    case 't':\r
+      mrc_params->tune_rcvn ^= 1;\r
+      DPF(D_INFO, "Tune to rcvn %d\n", mrc_params->tune_rcvn);\r
+      break;\r
+\r
+    case 'o':\r
+      mrc_params->rd_odt_value = (mrc_params->rd_odt_value + 1) % 4;\r
+      DPF(D_INFO, "Rd_odt_value %d\n", mrc_params->rd_odt_value);\r
+      break;\r
+\r
+    case 'd':\r
+      mrc_params->params.DENSITY = (mrc_params->params.DENSITY + 1) % 4;\r
+      DPF(D_INFO, "Dram density %d\n", mrc_params->params.DENSITY);\r
+      break;\r
+\r
+    case 'l':\r
+      DpfPrintMask ^= 0x30;\r
+      DPF(D_INFO, "Log mask %x\n", DpfPrintMask);\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+\r
+    if (ch != 'c')\r
+      goto myloop;\r
+\r
+  }\r
+#endif\r
+\r
+  // initially expect success\r
+  mrc_params->status = MRC_SUCCESS;\r
+\r
+  // todo!!! Setup board layout (must be reviewed as is selecting static timings)\r
+  // 0 == R0 (DDR3 x16), 1 == R1 (DDR3 x16), 2 == DV (DDR3 x8), 3 == SV (DDR3 x8)\r
+  if (mrc_params->dram_width == x8)\r
+  {\r
+    mrc_params->board_id = 2;  // select x8 layout\r
+  }\r
+  else\r
+  {\r
+    mrc_params->board_id = 0;  // select x16 layout\r
+  }\r
+\r
+  // initially no memory\r
+  mrc_params->mem_size = 0;\r
+  channel_i = 0;\r
+\r
+  // begin of channel settings\r
+  dram_width = mrc_params->dram_width;\r
+  dram_params = &mrc_params->params;\r
+  dram_cfg_index = 0;\r
+\r
+  // Determine Column & Row Bits:\r
+  // Column:\r
+  // 11 for 8Gbx8, else 10\r
+  mrc_params->column_bits[channel_i] = ((dram_params[dram_cfg_index].DENSITY == 4) && (dram_width == x8)) ? (11) : (10);\r
+\r
+  // Row:\r
+  // 512Mbx16=12 512Mbx8=13\r
+  //   1Gbx16=13   1Gbx8=14\r
+  //   2Gbx16=14   2Gbx8=15\r
+  //   4Gbx16=15   4Gbx8=16\r
+  //   8Gbx16=16   8Gbx8=16\r
+  mrc_params->row_bits[channel_i] = 12 + (dram_params[dram_cfg_index].DENSITY)\r
+      + (((dram_params[dram_cfg_index].DENSITY < 4) && (dram_width == x8)) ? (1) : (0));\r
+\r
+  // Determine Per Channel Memory Size:\r
+  // (For 2 RANKs, multiply by 2)\r
+  // (For 16 bit data bus, divide by 2)\r
+  // DENSITY  WIDTH   MEM_AVAILABLE\r
+  // 512Mb    x16     0x008000000 ( 128MB)\r
+  // 512Mb    x8      0x010000000 ( 256MB)\r
+  // 1Gb      x16     0x010000000 ( 256MB)\r
+  // 1Gb      x8      0x020000000 ( 512MB)\r
+  // 2Gb      x16     0x020000000 ( 512MB)\r
+  // 2Gb      x8      0x040000000 (1024MB)\r
+  // 4Gb      x16     0x040000000 (1024MB)\r
+  // 4Gb      x8      0x080000000 (2048MB)\r
+  mrc_params->channel_size[channel_i] = (1 << dram_params[dram_cfg_index].DENSITY);\r
+  mrc_params->channel_size[channel_i] *= ((dram_width == x8) ? (2) : (1));\r
+  mrc_params->channel_size[channel_i] *= (mrc_params->rank_enables == 0x3) ? (2) : (1);\r
+  mrc_params->channel_size[channel_i] *= (mrc_params->channel_width == x16) ? (1) : (2);\r
+\r
+  // Determine memory size (convert number of 64MB/512Mb units)\r
+  mrc_params->mem_size += mrc_params->channel_size[channel_i] << 26;\r
+\r
+  // end of channel settings\r
+\r
+  LEAVEFN();\r
+  return;\r
+}\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/prememinit.h b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/prememinit.h
new file mode 100644 (file)
index 0000000..78cca36
--- /dev/null
@@ -0,0 +1,21 @@
+/************************************************************************\r
+ *\r
+ * Copyright (c) 2013-2015 Intel Corporation.\r
+ *\r
+* This program and the accompanying materials\r
+* are licensed and made available under the terms and conditions of the BSD License\r
+* which accompanies this distribution.  The full text of the license may be found at\r
+* http://opensource.org/licenses/bsd-license.php\r
+*\r
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ *\r
+ ************************************************************************/\r
+#ifndef __PREMEMINIT_H_\r
+#define __PREMEMINIT_H_\r
+\r
+// Function prototypes\r
+void PreMemInit(MRCParams_t *mrc_params);\r
+\r
+\r
+#endif // _PREMEMINIT_H_\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/CommonHeader.h b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/CommonHeader.h
new file mode 100644 (file)
index 0000000..e0fa485
--- /dev/null
@@ -0,0 +1,55 @@
+/** @file\r
+Common header file shared by all source files.\r
+\r
+This file includes package header files, library classes and protocol, PPI & GUID definitions.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#ifndef __COMMON_HEADER_H_\r
+#define __COMMON_HEADER_H_\r
+\r
+//\r
+// The package level header files this module uses\r
+//\r
+#include <PiDxe.h>\r
+#include <IntelQNCDxe.h>\r
+\r
+//\r
+// The protocols, PPI and GUID definitions for this module\r
+//\r
+#include <Protocol/PciHostBridgeResourceAllocation.h>\r
+#include <Protocol/LegacyRegion2.h>\r
+#include <Protocol/SmbusHc.h>\r
+#include <Protocol/QncS3Support.h>\r
+\r
+//\r
+// The Library classes this module consumes\r
+//\r
+#include <Library/BaseLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/MtrrLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/SmbusLib.h>\r
+#include <Library/S3IoLib.h>\r
+#include <Library/S3BootScriptLib.h>\r
+#include <Library/IntelQNCLib.h>\r
+#include <Library/QNCAccessLib.h>\r
+#include <AcpiCpuData.h>\r
+\r
+extern EFI_HANDLE gQNCInitImageHandle;\r
+extern QNC_DEVICE_ENABLES mQNCDeviceEnables;\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/DxeQNCSmbus.c b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/DxeQNCSmbus.c
new file mode 100644 (file)
index 0000000..a5927ec
--- /dev/null
@@ -0,0 +1,618 @@
+/** @file\r
+Implementation for SMBus DXE driver entry point and SMBus Host\r
+Controller protocol.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include "CommonHeader.h"\r
+\r
+#include "DxeQNCSmbus.h"\r
+\r
+//\r
+// Interface defintion of SMBUS Host Controller Protocol.\r
+//\r
+EFI_SMBUS_HC_PROTOCOL mSmbusHc = {\r
+  SmbusExecute,\r
+  SmbusArpDevice,\r
+  SmbusGetArpMap,\r
+  SmbusNotify\r
+};\r
+\r
+//\r
+// Handle to install SMBus Host Controller protocol.\r
+//\r
+EFI_HANDLE                   mSmbusHcHandle = NULL;\r
+UINT8                        mDeviceMapEntries = 0;\r
+EFI_SMBUS_DEVICE_MAP         mDeviceMap[MAX_SMBUS_DEVICES];\r
+UINT8                        mPlatformNumRsvd = 0;\r
+UINT8                        *mPlatformAddrRsvd = NULL;\r
+\r
+//\r
+// These addresses are reserved by the SMBus 2.0 specification\r
+//\r
+UINT8    mReservedAddress[SMBUS_NUM_RESERVED] = {\r
+  0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x18, 0x50, 0x6E, 0xC2,\r
+  0xF0, 0xF2, 0xF4, 0xF6, 0xF8, 0xFA, 0xFC, 0xFE\r
+};\r
+\r
+\r
+/**\r
+  Gets Io port base address of Smbus Host Controller.\r
+\r
+  This internal function depends on a feature flag named PcdIchSmbusFixedIoPortBaseAddress\r
+  to retrieve Smbus Io port base. If that feature flag is true, it will get Smbus Io port base\r
+  address from a preset Pcd entry named PcdIchSmbusIoPortBaseAddress; otherwise, it will always\r
+  read Pci configuration space to get that value in each Smbus bus transaction.\r
+\r
+  @return The Io port base address of Smbus host controller.\r
+\r
+**/\r
+UINTN\r
+GetSmbusIoPortBaseAddress (\r
+  VOID\r
+  )\r
+{\r
+  UINTN     IoPortBaseAddress;\r
+\r
+  if (FeaturePcdGet (PcdSmbaIoBaseAddressFixed)) {\r
+    IoPortBaseAddress = (UINTN) PcdGet16 (PcdSmbaIoBaseAddress);\r
+  } else {\r
+    IoPortBaseAddress = (UINTN) LpcPciCfg32 (R_QNC_LPC_SMBUS_BASE) & B_QNC_LPC_SMBUS_BASE_MASK;\r
+  }\r
+\r
+  //\r
+  // Make sure that the IO port base address has been properly set.\r
+  //\r
+  ASSERT (IoPortBaseAddress != 0);\r
+\r
+  return IoPortBaseAddress;\r
+}\r
+\r
+\r
+VOID\r
+InitializeInternal (\r
+  )\r
+{\r
+  UINTN     IoPortBaseAddress;\r
+\r
+  IoPortBaseAddress = GetSmbusIoPortBaseAddress ();\r
+\r
+  //\r
+  // Step1: Enable QNC SMBUS I/O space.\r
+  //\r
+  LpcPciCfg32Or(R_QNC_LPC_SMBUS_BASE, B_QNC_LPC_SMBUS_BASE_EN);\r
+\r
+  //\r
+  // Step2: Clear Status Register before anyone uses the interfaces.\r
+  //\r
+  IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS, B_QNC_SMBUS_HSTS_ALL);\r
+\r
+  //\r
+  // Step3: Program the correct smbus clock\r
+  //\r
+  IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HCLK, V_QNC_SMBUS_HCLK_100KHZ);\r
+}\r
+\r
+\r
+\r
+\r
+BOOLEAN\r
+IsAddressAvailable (\r
+  IN      EFI_SMBUS_DEVICE_ADDRESS  SlaveAddress\r
+  )\r
+{\r
+  UINT8         Index;\r
+\r
+  //\r
+  // See if we have already assigned this address to a device\r
+  //\r
+  for (Index = 0; Index < mDeviceMapEntries; Index++) {\r
+    if (SlaveAddress.SmbusDeviceAddress ==\r
+         mDeviceMap[Index].SmbusDeviceAddress.SmbusDeviceAddress) {\r
+      return FALSE;\r
+    }\r
+  }\r
+\r
+  //\r
+  // See if this address is claimed by a platform non-ARP-capable device\r
+  //\r
+  for (Index = 0; Index < mPlatformNumRsvd; Index++) {\r
+    if ((SlaveAddress.SmbusDeviceAddress << 1) == mPlatformAddrRsvd[Index]) {\r
+      return FALSE;\r
+    }\r
+  }\r
+\r
+  //\r
+  // See if this is a reserved address\r
+  //\r
+  for (Index = 0; Index < SMBUS_NUM_RESERVED; Index++) {\r
+    if (SlaveAddress.SmbusDeviceAddress == (UINTN) mReservedAddress[Index]) {\r
+      return FALSE;\r
+    }\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+GetNextAvailableAddress (\r
+  IN EFI_SMBUS_DEVICE_ADDRESS  *SlaveAddress\r
+  )\r
+{\r
+  for (SlaveAddress->SmbusDeviceAddress = 0x03;\r
+    SlaveAddress->SmbusDeviceAddress < 0x7F;\r
+    SlaveAddress->SmbusDeviceAddress++\r
+    ) {\r
+    if (IsAddressAvailable (*SlaveAddress)) {\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_OUT_OF_RESOURCES;\r
+}\r
+\r
+EFI_STATUS\r
+SmbusPrepareToArp (\r
+  )\r
+{\r
+  EFI_SMBUS_DEVICE_ADDRESS  SlaveAddress;\r
+  EFI_STATUS                Status;\r
+  UINTN                     Length;\r
+  UINT8                     Buffer;\r
+\r
+  SlaveAddress.SmbusDeviceAddress = SMBUS_ADDRESS_ARP;\r
+  Length = 1;\r
+  Buffer = SMBUS_DATA_PREPARE_TO_ARP;\r
+\r
+  Status = Execute (\r
+             SlaveAddress,\r
+             0,\r
+             EfiSmbusSendByte,\r
+             TRUE,\r
+             &Length,\r
+             &Buffer\r
+             );\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+SmbusGetUdidGeneral (\r
+  IN OUT  EFI_SMBUS_DEVICE_MAP  *DeviceMap\r
+  )\r
+{\r
+  EFI_SMBUS_DEVICE_ADDRESS      SlaveAddress;\r
+  EFI_STATUS                    Status;\r
+  UINTN                         Length;\r
+  UINT8                         Buffer[SMBUS_GET_UDID_LENGTH];\r
+\r
+  SlaveAddress.SmbusDeviceAddress = SMBUS_ADDRESS_ARP;\r
+  Length = SMBUS_GET_UDID_LENGTH;\r
+\r
+  Status = Execute (\r
+             SlaveAddress,\r
+             SMBUS_DATA_GET_UDID_GENERAL,\r
+             EfiSmbusReadBlock,\r
+             TRUE,\r
+             &Length,\r
+             Buffer\r
+             );\r
+\r
+  if (!EFI_ERROR(Status)) {\r
+    if (Length == SMBUS_GET_UDID_LENGTH) {\r
+      DeviceMap->SmbusDeviceUdid.DeviceCapabilities = Buffer[0];\r
+      DeviceMap->SmbusDeviceUdid.VendorRevision = Buffer[1];\r
+      DeviceMap->SmbusDeviceUdid.VendorId = (UINT16)((Buffer[2] << 8) + Buffer[3]);\r
+      DeviceMap->SmbusDeviceUdid.DeviceId = (UINT16)((Buffer[4] << 8) + Buffer[5]);\r
+      DeviceMap->SmbusDeviceUdid.Interface = (UINT16)((Buffer[6] << 8) + Buffer[7]);\r
+      DeviceMap->SmbusDeviceUdid.SubsystemVendorId = (UINT16)((Buffer[8] << 8) + Buffer[9]);\r
+      DeviceMap->SmbusDeviceUdid.SubsystemDeviceId = (UINT16)((Buffer[10] << 8) + Buffer[11]);\r
+      DeviceMap->SmbusDeviceUdid.VendorSpecificId = (UINT32)((Buffer[12] << 24) + (Buffer[13] << 16) + (Buffer[14] << 8) + Buffer[15]);\r
+      DeviceMap->SmbusDeviceAddress.SmbusDeviceAddress = (UINT8)(Buffer[16] >> 1);\r
+    } else {\r
+      Status = EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+SmbusAssignAddress (\r
+  IN OUT  EFI_SMBUS_DEVICE_MAP  *DeviceMap\r
+  )\r
+{\r
+  EFI_SMBUS_DEVICE_ADDRESS      SlaveAddress;\r
+  EFI_STATUS                    Status;\r
+  UINTN                         Length;\r
+  UINT8                         Buffer[SMBUS_GET_UDID_LENGTH];\r
+\r
+  Buffer[0] = DeviceMap->SmbusDeviceUdid.DeviceCapabilities;\r
+  Buffer[1] = DeviceMap->SmbusDeviceUdid.VendorRevision;\r
+  Buffer[2] = (UINT8)(DeviceMap->SmbusDeviceUdid.VendorId >> 8);\r
+  Buffer[3] = (UINT8)(DeviceMap->SmbusDeviceUdid.VendorId);\r
+  Buffer[4] = (UINT8)(DeviceMap->SmbusDeviceUdid.DeviceId >> 8);\r
+  Buffer[5] = (UINT8)(DeviceMap->SmbusDeviceUdid.DeviceId);\r
+  Buffer[6] = (UINT8)(DeviceMap->SmbusDeviceUdid.Interface >> 8);\r
+  Buffer[7] = (UINT8)(DeviceMap->SmbusDeviceUdid.Interface);\r
+  Buffer[8] = (UINT8)(DeviceMap->SmbusDeviceUdid.SubsystemVendorId >> 8);\r
+  Buffer[9] = (UINT8)(DeviceMap->SmbusDeviceUdid.SubsystemVendorId);\r
+  Buffer[10] = (UINT8)(DeviceMap->SmbusDeviceUdid.SubsystemDeviceId >> 8);\r
+  Buffer[11] = (UINT8)(DeviceMap->SmbusDeviceUdid.SubsystemDeviceId);\r
+  Buffer[12] = (UINT8)(DeviceMap->SmbusDeviceUdid.VendorSpecificId >> 24);\r
+  Buffer[13] = (UINT8)(DeviceMap->SmbusDeviceUdid.VendorSpecificId >> 16);\r
+  Buffer[14] = (UINT8)(DeviceMap->SmbusDeviceUdid.VendorSpecificId >> 8);\r
+  Buffer[15] = (UINT8)(DeviceMap->SmbusDeviceUdid.VendorSpecificId);\r
+  Buffer[16] = (UINT8)(DeviceMap->SmbusDeviceAddress.SmbusDeviceAddress << 1);\r
+\r
+  SlaveAddress.SmbusDeviceAddress = SMBUS_ADDRESS_ARP;\r
+  Length = SMBUS_GET_UDID_LENGTH;\r
+\r
+  Status = Execute (\r
+             SlaveAddress,\r
+             SMBUS_DATA_ASSIGN_ADDRESS,\r
+             EfiSmbusWriteBlock,\r
+             TRUE,\r
+             &Length,\r
+             Buffer\r
+             );\r
+  return Status;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+SmbusFullArp (\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_SMBUS_DEVICE_MAP    *CurrentDeviceMap;\r
+\r
+  Status = SmbusPrepareToArp ();\r
+  if (EFI_ERROR(Status)) {\r
+    if (Status == EFI_DEVICE_ERROR) {\r
+      //\r
+      //  ARP is complete\r
+      //\r
+      return EFI_SUCCESS;\r
+    } else {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Main loop to ARP all ARP-capable devices\r
+  //\r
+  do {\r
+    CurrentDeviceMap = &mDeviceMap[mDeviceMapEntries];\r
+    Status = SmbusGetUdidGeneral (CurrentDeviceMap);\r
+    if (EFI_ERROR(Status)) {\r
+      break;\r
+    }\r
+\r
+    if (CurrentDeviceMap->SmbusDeviceAddress.SmbusDeviceAddress == (0xFF >> 1)) {\r
+      //\r
+      // If address is unassigned, assign it\r
+      //\r
+      Status = GetNextAvailableAddress (\r
+                 &CurrentDeviceMap->SmbusDeviceAddress\r
+                 );\r
+      if (EFI_ERROR(Status)) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+    } else if (((CurrentDeviceMap->SmbusDeviceUdid.DeviceCapabilities) & 0xC0) != 0) {\r
+      //\r
+      // if address is not fixed, check if the current address is available\r
+      //\r
+      if (!IsAddressAvailable (\r
+             CurrentDeviceMap->SmbusDeviceAddress\r
+             )) {\r
+        //\r
+        // if currently assigned address is already used, get a new one\r
+        //\r
+        Status = GetNextAvailableAddress (\r
+                   &CurrentDeviceMap->SmbusDeviceAddress\r
+                   );\r
+        if (EFI_ERROR(Status)) {\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+      }\r
+    }\r
+\r
+    Status = SmbusAssignAddress (CurrentDeviceMap);\r
+    if (EFI_ERROR(Status)) {\r
+      //\r
+      // If there was a device error, just continue on and try again.\r
+      // Other errors should be reported.\r
+      //\r
+      if (Status != EFI_DEVICE_ERROR) {\r
+        return Status;\r
+      }\r
+    } else {\r
+      //\r
+      // If there was no error, the address was assigned and we must update our\r
+      // records.\r
+      //\r
+      mDeviceMapEntries++;\r
+    }\r
+\r
+  } while (mDeviceMapEntries < MAX_SMBUS_DEVICES);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+SmbusDirectedArp (\r
+  IN      EFI_SMBUS_UDID            *SmbusUdid,\r
+  IN OUT  EFI_SMBUS_DEVICE_ADDRESS  *SlaveAddress\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_SMBUS_DEVICE_MAP              *CurrentDeviceMap;\r
+\r
+  if (mDeviceMapEntries >= MAX_SMBUS_DEVICES) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  CurrentDeviceMap = &mDeviceMap[mDeviceMapEntries];\r
+\r
+  //\r
+  // Find an available address to assign\r
+  //\r
+  Status = GetNextAvailableAddress (\r
+             &CurrentDeviceMap->SmbusDeviceAddress\r
+             );\r
+  if (EFI_ERROR(Status)) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  CurrentDeviceMap->SmbusDeviceUdid.DeviceCapabilities  = SmbusUdid->DeviceCapabilities;\r
+  CurrentDeviceMap->SmbusDeviceUdid.DeviceId            = SmbusUdid->DeviceId;\r
+  CurrentDeviceMap->SmbusDeviceUdid.Interface           = SmbusUdid->Interface;\r
+  CurrentDeviceMap->SmbusDeviceUdid.SubsystemDeviceId   = SmbusUdid->SubsystemDeviceId;\r
+  CurrentDeviceMap->SmbusDeviceUdid.SubsystemVendorId   = SmbusUdid->SubsystemVendorId;\r
+  CurrentDeviceMap->SmbusDeviceUdid.VendorId            = SmbusUdid->VendorId;\r
+  CurrentDeviceMap->SmbusDeviceUdid.VendorRevision      = SmbusUdid->VendorRevision;\r
+  CurrentDeviceMap->SmbusDeviceUdid.VendorSpecificId    = SmbusUdid->VendorSpecificId;\r
+\r
+  Status = SmbusAssignAddress (CurrentDeviceMap);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  mDeviceMapEntries++;\r
+  SlaveAddress->SmbusDeviceAddress = CurrentDeviceMap->SmbusDeviceAddress.SmbusDeviceAddress;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+/**\r
+  Executes an SMBus operation to an SMBus controller. Returns when either the command has been\r
+  executed or an error is encountered in doing the operation.\r
+\r
+  The Execute() function provides a standard way to execute an operation as defined in the System\r
+  Management Bus (SMBus) Specification. The resulting transaction will be either that the SMBus\r
+  slave devices accept this transaction or that this function returns with error.\r
+\r
+  @param  This                    A pointer to the EFI_SMBUS_HC_PROTOCOL instance.\r
+  @param  SlaveAddress            The SMBus slave address of the device with which to communicate.\r
+  @param  Command                 This command is transmitted by the SMBus host controller to the\r
+                                  SMBus slave device and the interpretation is SMBus slave device\r
+                                  specific. It can mean the offset to a list of functions inside an\r
+                                  SMBus slave device. Not all operations or slave devices support\r
+                                  this command's registers.\r
+  @param  Operation               Signifies which particular SMBus hardware protocol instance that\r
+                                  it will use to execute the SMBus transactions. This SMBus\r
+                                  hardware protocol is defined by the SMBus Specification and is\r
+                                  not related to EFI.\r
+  @param  PecCheck                Defines if Packet Error Code (PEC) checking is required for this\r
+                                  operation.\r
+  @param  Length                  Signifies the number of bytes that this operation will do. The\r
+                                  maximum number of bytes can be revision specific and operation\r
+                                  specific. This field will contain the actual number of bytes that\r
+                                  are executed for this operation. Not all operations require this\r
+                                  argument.\r
+  @param  Buffer                  Contains the value of data to execute to the SMBus slave device.\r
+                                  Not all operations require this argument. The length of this\r
+                                  buffer is identified by Length.\r
+\r
+  @retval EFI_SUCCESS             The last data that was returned from the access matched the poll\r
+                                  exit criteria.\r
+  @retval EFI_CRC_ERROR           Checksum is not correct (PEC is incorrect).\r
+  @retval EFI_TIMEOUT             Timeout expired before the operation was completed. Timeout is\r
+                                  determined by the SMBus host controller device.\r
+  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to a lack of resources.\r
+  @retval EFI_DEVICE_ERROR        The request was not completed because a failure that was\r
+                                  reflected in the Host Status Register bit. Device errors are a\r
+                                  result of a transaction collision, illegal command field,\r
+                                  unclaimed cycle (host initiated), or bus errors (collisions).\r
+  @retval EFI_INVALID_PARAMETER   Operation is not defined in EFI_SMBUS_OPERATION.\r
+  @retval EFI_INVALID_PARAMETER   Length/Buffer is NULL for operations except for EfiSmbusQuickRead\r
+                                  and EfiSmbusQuickWrite. Length is outside the range of valid\r
+                                  values.\r
+  @retval EFI_UNSUPPORTED         The SMBus operation or PEC is not supported.\r
+  @retval EFI_BUFFER_TOO_SMALL    Buffer is not sufficient for this operation.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmbusExecute (\r
+  IN CONST  EFI_SMBUS_HC_PROTOCOL     *This,\r
+  IN CONST  EFI_SMBUS_DEVICE_ADDRESS  SlaveAddress,\r
+  IN CONST  EFI_SMBUS_DEVICE_COMMAND  Command,\r
+  IN CONST  EFI_SMBUS_OPERATION       Operation,\r
+  IN CONST  BOOLEAN                   PecCheck,\r
+  IN OUT    UINTN                     *Length,\r
+  IN OUT    VOID                      *Buffer\r
+  )\r
+{\r
+  InitializeInternal ();\r
+  return Execute (\r
+           SlaveAddress,\r
+           Command,\r
+           Operation,\r
+           PecCheck,\r
+           Length,\r
+           Buffer\r
+           );\r
+}\r
+\r
+/**\r
+  Sets the SMBus slave device addresses for the device with a given unique ID or enumerates the\r
+  entire bus.\r
+\r
+  The ArpDevice() function provides a standard way for a device driver to enumerate the entire\r
+  SMBus or specific devices on the bus.\r
+\r
+  @param  This                    A pointer to the EFI_SMBUS_HC_PROTOCOL instance.\r
+  @param  ArpAll                  A Boolean expression that indicates if the host drivers need to\r
+                                  enumerate all the devices or enumerate only the device that is\r
+                                  identified by SmbusUdid. If ArpAll is TRUE, SmbusUdid and\r
+                                  SlaveAddress are optional. If ArpAll is FALSE, ArpDevice will\r
+                                  enumerate SmbusUdid and the address will be at SlaveAddress.\r
+  @param  SmbusUdid               The Unique Device Identifier (UDID) that is associated with this\r
+                                  device.\r
+  @param  SlaveAddress            The SMBus slave address that is associated with an SMBus UDID.\r
+\r
+  @retval EFI_SUCCESS             The last data that was returned from the access matched the poll\r
+                                  exit criteria.\r
+  @retval EFI_CRC_ERROR           Checksum is not correct (PEC is incorrect).\r
+  @retval EFI_TIMEOUT             Timeout expired before the operation was completed. Timeout is\r
+                                  determined by the SMBus host controller device.\r
+  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to a lack of resources.\r
+  @retval EFI_DEVICE_ERROR        The request was not completed because a failure that was\r
+                                  reflected in the Host Status Register bit. Device errors are a\r
+                                  result of a transaction collision, illegal command field,\r
+                                  unclaimed cycle (host initiated), or bus errors (collisions).\r
+  @retval EFI_UNSUPPORTED         The corresponding SMBus operation is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmbusArpDevice (\r
+  IN CONST  EFI_SMBUS_HC_PROTOCOL     *This,\r
+  IN        BOOLEAN                   ArpAll,\r
+  IN        EFI_SMBUS_UDID            *SmbusUdid,   OPTIONAL\r
+  IN OUT    EFI_SMBUS_DEVICE_ADDRESS  *SlaveAddress OPTIONAL\r
+  )\r
+{\r
+    InitializeInternal ();\r
+\r
+    if (ArpAll) {\r
+    return SmbusFullArp ();\r
+  } else {\r
+    if ((SmbusUdid == NULL) || (SlaveAddress == NULL)) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    return SmbusDirectedArp ((EFI_SMBUS_UDID *)SmbusUdid, SlaveAddress);\r
+  }\r
+}\r
+\r
+/**\r
+  Returns a pointer to the Address Resolution Protocol (ARP) map that contains the ID/address pair\r
+  of the slave devices that were enumerated by the SMBus host controller driver.\r
+\r
+  The GetArpMap() function returns the mapping of all the SMBus devices that were enumerated by the\r
+  SMBus host driver.\r
+\r
+  @param  This                    A pointer to the EFI_SMBUS_HC_PROTOCOL instance.\r
+  @param  Length                  Size of the buffer that contains the SMBus device map.\r
+  @param  SmbusDeviceMap          The pointer to the device map as enumerated by the SMBus\r
+                                  controller driver.\r
+\r
+  @retval EFI_SUCCESS             The SMBus returned the current device map.\r
+  @retval EFI_UNSUPPORTED         The corresponding operation is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmbusGetArpMap (\r
+  IN CONST  EFI_SMBUS_HC_PROTOCOL   *This,\r
+  IN OUT    UINTN                   *Length,\r
+  IN OUT    EFI_SMBUS_DEVICE_MAP    **SmbusDeviceMap\r
+  )\r
+{\r
+  *Length = mDeviceMapEntries;\r
+  *SmbusDeviceMap = mDeviceMap;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Allows a device driver to register for a callback when the bus driver detects a state that it\r
+  needs to propagate to other drivers that are registered for a callback.\r
+\r
+  The Notify() function registers all the callback functions to allow the bus driver to call these\r
+  functions when the SlaveAddress/Data pair happens.\r
+  If NotifyFunction is NULL, then ASSERT ().\r
+\r
+  @param  This                    A pointer to the EFI_SMBUS_HC_PROTOCOL instance.\r
+  @param  SlaveAddress            The SMBUS hardware address to which the SMBUS device is\r
+                                  preassigned or allocated.\r
+  @param  Data                    Data of the SMBus host notify command that the caller wants to be\r
+                                  called.\r
+  @param  NotifyFunction          The function to call when the bus driver detects the SlaveAddress\r
+                                  and Data pair.\r
+\r
+  @retval EFI_SUCCESS             NotifyFunction was registered.\r
+  @retval EFI_UNSUPPORTED         The corresponding operation is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmbusNotify (\r
+  IN CONST  EFI_SMBUS_HC_PROTOCOL     *This,\r
+  IN CONST  EFI_SMBUS_DEVICE_ADDRESS  SlaveAddress,\r
+  IN CONST  UINTN                     Data,\r
+  IN CONST  EFI_SMBUS_NOTIFY_FUNCTION NotifyFunction\r
+  )\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+  Entry point to the DXE Driver that produces the SMBus Host Controller Protocol.\r
+\r
+  @param  ImageHandle      ImageHandle of the loaded driver.\r
+  @param  SystemTable      Pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS      The entry point of SMBus DXE driver is executed successfully.\r
+  @retval !EFI_SUCESS      Some error occurs in the entry point of SMBus DXE driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeQNCSmbus (\r
+  IN EFI_HANDLE            ImageHandle,\r
+  IN EFI_SYSTEM_TABLE      *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+\r
+  mPlatformNumRsvd = (UINT8)PcdGet32 (PcdPlatformSmbusAddrNum);\r
+  mPlatformAddrRsvd = (UINT8 *)(UINTN) PcdGet64 (PcdPlatformSmbusAddrTable);\r
+\r
+  //\r
+  // Install SMBus Host Controller protocol interface.\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &mSmbusHcHandle,\r
+                  &gEfiSmbusHcProtocolGuid,\r
+                  &mSmbusHc,\r
+                  NULL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/DxeQNCSmbus.h b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/DxeQNCSmbus.h
new file mode 100644 (file)
index 0000000..306576b
--- /dev/null
@@ -0,0 +1,211 @@
+/** @file\r
+Header file for the defintions used in SMBus DXE driver.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#ifndef _DXE_QNC_SMBUS_H_\r
+#define _DXE_QNC_SMBUS_H_\r
+#include "CommonHeader.h"\r
+\r
+#include "QNCSmbus.h"\r
+\r
+#define MAX_SMBUS_DEVICES   107     // Max number of SMBus devices (7 bit\r
+                                    //   address yields 128 combinations but 21\r
+                                    //   of those are reserved)\r
+\r
+#define MICROSECOND     10\r
+#define MILLISECOND     (1000 * MICROSECOND)\r
+#define ONESECOND       (1000 * MILLISECOND)\r
+\r
+#define STALL_TIME          1000000 // 1,000,000 microseconds = 1 second\r
+#define BUS_TRIES           3       // How many times to retry on Bus Errors\r
+#define SMBUS_NUM_RESERVED  21      // Number of device addresses that are\r
+                                    //   reserved by the SMBus spec.\r
+#define SMBUS_ADDRESS_ARP   0xC2 >> 1\r
+#define   SMBUS_DATA_PREPARE_TO_ARP   0x01\r
+#define   SMBUS_DATA_RESET_DEVICE     0x02\r
+#define   SMBUS_DATA_GET_UDID_GENERAL 0x03\r
+#define   SMBUS_DATA_ASSIGN_ADDRESS   0x04\r
+#define SMBUS_GET_UDID_LENGTH 17    // 16 byte UDID + 1 byte address\r
+\r
+/**\r
+  Executes an SMBus operation to an SMBus controller. Returns when either the command has been\r
+  executed or an error is encountered in doing the operation.\r
+\r
+  The Execute() function provides a standard way to execute an operation as defined in the System\r
+  Management Bus (SMBus) Specification. The resulting transaction will be either that the SMBus\r
+  slave devices accept this transaction or that this function returns with error.\r
+\r
+  @param  This                    A pointer to the EFI_SMBUS_HC_PROTOCOL instance.\r
+  @param  SlaveAddress            The SMBus slave address of the device with which to communicate.\r
+  @param  Command                 This command is transmitted by the SMBus host controller to the\r
+                                  SMBus slave device and the interpretation is SMBus slave device\r
+                                  specific. It can mean the offset to a list of functions inside an\r
+                                  SMBus slave device. Not all operations or slave devices support\r
+                                  this command's registers.\r
+  @param  Operation               Signifies which particular SMBus hardware protocol instance that\r
+                                  it will use to execute the SMBus transactions. This SMBus\r
+                                  hardware protocol is defined by the SMBus Specification and is\r
+                                  not related to EFI.\r
+  @param  PecCheck                Defines if Packet Error Code (PEC) checking is required for this\r
+                                  operation.\r
+  @param  Length                  Signifies the number of bytes that this operation will do. The\r
+                                  maximum number of bytes can be revision specific and operation\r
+                                  specific. This field will contain the actual number of bytes that\r
+                                  are executed for this operation. Not all operations require this\r
+                                  argument.\r
+  @param  Buffer                  Contains the value of data to execute to the SMBus slave device.\r
+                                  Not all operations require this argument. The length of this\r
+                                  buffer is identified by Length.\r
+\r
+  @retval EFI_SUCCESS             The last data that was returned from the access matched the poll\r
+                                  exit criteria.\r
+  @retval EFI_CRC_ERROR           Checksum is not correct (PEC is incorrect).\r
+  @retval EFI_TIMEOUT             Timeout expired before the operation was completed. Timeout is\r
+                                  determined by the SMBus host controller device.\r
+  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to a lack of resources.\r
+  @retval EFI_DEVICE_ERROR        The request was not completed because a failure that was\r
+                                  reflected in the Host Status Register bit. Device errors are a\r
+                                  result of a transaction collision, illegal command field,\r
+                                  unclaimed cycle (host initiated), or bus errors (collisions).\r
+  @retval EFI_INVALID_PARAMETER   Operation is not defined in EFI_SMBUS_OPERATION.\r
+  @retval EFI_INVALID_PARAMETER   Length/Buffer is NULL for operations except for EfiSmbusQuickRead\r
+                                  and EfiSmbusQuickWrite. Length is outside the range of valid\r
+                                  values.\r
+  @retval EFI_UNSUPPORTED         The SMBus operation or PEC is not supported.\r
+  @retval EFI_BUFFER_TOO_SMALL    Buffer is not sufficient for this operation.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmbusExecute (\r
+  IN CONST  EFI_SMBUS_HC_PROTOCOL     *This,\r
+  IN CONST  EFI_SMBUS_DEVICE_ADDRESS  SlaveAddress,\r
+  IN CONST  EFI_SMBUS_DEVICE_COMMAND  Command,\r
+  IN CONST  EFI_SMBUS_OPERATION       Operation,\r
+  IN CONST  BOOLEAN                   PecCheck,\r
+  IN OUT    UINTN                     *Length,\r
+  IN OUT    VOID                      *Buffer\r
+  );\r
+\r
+/**\r
+  Sets the SMBus slave device addresses for the device with a given unique ID or enumerates the\r
+  entire bus.\r
+\r
+  The ArpDevice() function provides a standard way for a device driver to enumerate the entire\r
+  SMBus or specific devices on the bus.\r
+\r
+  @param  This                    A pointer to the EFI_SMBUS_HC_PROTOCOL instance.\r
+  @param  ArpAll                  A Boolean expression that indicates if the host drivers need to\r
+                                  enumerate all the devices or enumerate only the device that is\r
+                                  identified by SmbusUdid. If ArpAll is TRUE, SmbusUdid and\r
+                                  SlaveAddress are optional. If ArpAll is FALSE, ArpDevice will\r
+                                  enumerate SmbusUdid and the address will be at SlaveAddress.\r
+  @param  SmbusUdid               The Unique Device Identifier (UDID) that is associated with this\r
+                                  device.\r
+  @param  SlaveAddress            The SMBus slave address that is associated with an SMBus UDID.\r
+\r
+  @retval EFI_SUCCESS             The last data that was returned from the access matched the poll\r
+                                  exit criteria.\r
+  @retval EFI_CRC_ERROR           Checksum is not correct (PEC is incorrect).\r
+  @retval EFI_TIMEOUT             Timeout expired before the operation was completed. Timeout is\r
+                                  determined by the SMBus host controller device.\r
+  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to a lack of resources.\r
+  @retval EFI_DEVICE_ERROR        The request was not completed because a failure that was\r
+                                  reflected in the Host Status Register bit. Device errors are a\r
+                                  result of a transaction collision, illegal command field,\r
+                                  unclaimed cycle (host initiated), or bus errors (collisions).\r
+  @retval EFI_UNSUPPORTED         The corresponding operation is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmbusArpDevice (\r
+  IN CONST  EFI_SMBUS_HC_PROTOCOL     *This,\r
+  IN        BOOLEAN                   ArpAll,\r
+  IN        EFI_SMBUS_UDID            *SmbusUdid,   OPTIONAL\r
+  IN OUT    EFI_SMBUS_DEVICE_ADDRESS  *SlaveAddress OPTIONAL\r
+  );\r
+\r
+/**\r
+  Returns a pointer to the Address Resolution Protocol (ARP) map that contains the ID/address pair\r
+  of the slave devices that were enumerated by the SMBus host controller driver.\r
+\r
+  The GetArpMap() function returns the mapping of all the SMBus devices that were enumerated by the\r
+  SMBus host driver.\r
+\r
+  @param  This                    A pointer to the EFI_SMBUS_HC_PROTOCOL instance.\r
+  @param  Length                  Size of the buffer that contains the SMBus device map.\r
+  @param  SmbusDeviceMap          The pointer to the device map as enumerated by the SMBus\r
+                                  controller driver.\r
+\r
+  @retval EFI_SUCCESS             The SMBus returned the current device map.\r
+  @retval EFI_UNSUPPORTED         The corresponding operation is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmbusGetArpMap (\r
+  IN CONST  EFI_SMBUS_HC_PROTOCOL   *This,\r
+  IN OUT    UINTN                   *Length,\r
+  IN OUT    EFI_SMBUS_DEVICE_MAP    **SmbusDeviceMap\r
+  );\r
+\r
+/**\r
+  Allows a device driver to register for a callback when the bus driver detects a state that it\r
+  needs to propagate to other drivers that are registered for a callback.\r
+\r
+  The Notify() function registers all the callback functions to allow the bus driver to call these\r
+  functions when the SlaveAddress/Data pair happens.\r
+  If NotifyFunction is NULL, then ASSERT ().\r
+\r
+  @param  This                    A pointer to the EFI_SMBUS_HC_PROTOCOL instance.\r
+  @param  SlaveAddress            The SMBUS hardware address to which the SMBUS device is\r
+                                  preassigned or allocated.\r
+  @param  Data                    Data of the SMBus host notify command that the caller wants to be\r
+                                  called.\r
+  @param  NotifyFunction          The function to call when the bus driver detects the SlaveAddress\r
+                                  and Data pair.\r
+\r
+  @retval EFI_SUCCESS             NotifyFunction was registered.\r
+  @retval EFI_UNSUPPORTED         The corresponding operation is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmbusNotify (\r
+  IN CONST  EFI_SMBUS_HC_PROTOCOL     *This,\r
+  IN CONST  EFI_SMBUS_DEVICE_ADDRESS  SlaveAddress,\r
+  IN CONST  UINTN                     Data,\r
+  IN CONST  EFI_SMBUS_NOTIFY_FUNCTION NotifyFunction\r
+  );\r
+\r
+/**\r
+  Entry point to the DXE Driver that produces the SMBus Host Controller Protocol.\r
+\r
+  @param  ImageHandle      ImageHandle of the loaded driver.\r
+  @param  SystemTable      Pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS      The entry point of SMBus DXE driver is executed successfully.\r
+  @retval !EFI_SUCESS      Some error occurs in the entry point of SMBus DXE driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeQNCSmbus (\r
+  IN EFI_HANDLE            ImageHandle,\r
+  IN EFI_SYSTEM_TABLE      *SystemTable\r
+  );\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyRegion.c b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyRegion.c
new file mode 100644 (file)
index 0000000..28c79b0
--- /dev/null
@@ -0,0 +1,243 @@
+/** @file\r
+QNC Legacy Region Driver\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "CommonHeader.h"\r
+#include "LegacyRegion.h"\r
+\r
+//\r
+// Handle used to install the Legacy Region Protocol\r
+//\r
+EFI_HANDLE  mLegacyRegion2Handle = NULL;\r
+\r
+//\r
+// Instance of the Legacy Region Protocol to install into the handle database\r
+//\r
+EFI_LEGACY_REGION2_PROTOCOL  mLegacyRegion2 = {\r
+  LegacyRegion2Decode,\r
+  LegacyRegion2Lock,\r
+  LegacyRegion2BootLock,\r
+  LegacyRegion2Unlock,\r
+  LegacyRegionGetInfo\r
+};\r
+\r
+\r
+/**\r
+  Modify the hardware to allow (decode) or disallow (not decode) memory reads in a region.\r
+\r
+  If the On parameter evaluates to TRUE, this function enables memory reads in the address range\r
+  Start to (Start + Length - 1).\r
+  If the On parameter evaluates to FALSE, this function disables memory reads in the address range\r
+  Start to (Start + Length - 1).\r
+\r
+  @param  This[in]              Indicates the EFI_LEGACY_REGION_PROTOCOL instance.\r
+  @param  Start[in]             The beginning of the physical address of the region whose attributes\r
+                                should be modified.\r
+  @param  Length[in]            The number of bytes of memory whose attributes should be modified.\r
+                                The actual number of bytes modified may be greater than the number\r
+                                specified.\r
+  @param  Granularity[out]      The number of bytes in the last region affected. This may be less\r
+                                than the total number of bytes affected if the starting address\r
+                                was not aligned to a region's starting address or if the length\r
+                                was greater than the number of bytes in the first region.\r
+  @param  On[in]                Decode / Non-Decode flag.\r
+\r
+  @retval EFI_SUCCESS           The region's attributes were successfully modified.\r
+  @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyRegion2Decode (\r
+  IN  EFI_LEGACY_REGION2_PROTOCOL  *This,\r
+  IN  UINT32                       Start,\r
+  IN  UINT32                       Length,\r
+  OUT UINT32                       *Granularity,\r
+  IN  BOOLEAN                      *On\r
+  )\r
+{\r
+  return QNCLegacyRegionManipulation (Start, Length, On, NULL, Granularity);\r
+}\r
+\r
+\r
+/**\r
+  Modify the hardware to disallow memory attribute changes in a region.\r
+\r
+  This function makes the attributes of a region read only. Once a region is boot-locked with this\r
+  function, the read and write attributes of that region cannot be changed until a power cycle has\r
+  reset the boot-lock attribute. Calls to Decode(), Lock() and Unlock() will have no effect.\r
+\r
+  @param  This[in]              Indicates the EFI_LEGACY_REGION_PROTOCOL instance.\r
+  @param  Start[in]             The beginning of the physical address of the region whose\r
+                                attributes should be modified.\r
+  @param  Length[in]            The number of bytes of memory whose attributes should be modified.\r
+                                The actual number of bytes modified may be greater than the number\r
+                                specified.\r
+  @param  Granularity[out]      The number of bytes in the last region affected. This may be less\r
+                                than the total number of bytes affected if the starting address was\r
+                                not aligned to a region's starting address or if the length was\r
+                                greater than the number of bytes in the first region.\r
+\r
+  @retval EFI_SUCCESS           The region's attributes were successfully modified.\r
+  @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.\r
+  @retval EFI_UNSUPPORTED       The chipset does not support locking the configuration registers in\r
+                                a way that will not affect memory regions outside the legacy memory\r
+                                region.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyRegion2BootLock (\r
+  IN  EFI_LEGACY_REGION2_PROTOCOL         *This,\r
+  IN  UINT32                              Start,\r
+  IN  UINT32                              Length,\r
+  OUT UINT32                              *Granularity\r
+  )\r
+{\r
+  if ((Start < 0xC0000) || ((Start + Length - 1) > 0xFFFFF)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+\r
+/**\r
+  Modify the hardware to disallow memory writes in a region.\r
+\r
+  This function changes the attributes of a memory range to not allow writes.\r
+\r
+  @param  This[in]              Indicates the EFI_LEGACY_REGION_PROTOCOL instance.\r
+  @param  Start[in]             The beginning of the physical address of the region whose\r
+                                attributes should be modified.\r
+  @param  Length[in]            The number of bytes of memory whose attributes should be modified.\r
+                                The actual number of bytes modified may be greater than the number\r
+                                specified.\r
+  @param  Granularity[out]      The number of bytes in the last region affected. This may be less\r
+                                than the total number of bytes affected if the starting address was\r
+                                not aligned to a region's starting address or if the length was\r
+                                greater than the number of bytes in the first region.\r
+\r
+  @retval EFI_SUCCESS           The region's attributes were successfully modified.\r
+  @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyRegion2Lock (\r
+  IN  EFI_LEGACY_REGION2_PROTOCOL *This,\r
+  IN  UINT32                      Start,\r
+  IN  UINT32                      Length,\r
+  OUT UINT32                      *Granularity\r
+  )\r
+{\r
+  BOOLEAN  WriteEnable;\r
+\r
+  WriteEnable = FALSE;\r
+  return QNCLegacyRegionManipulation (Start, Length, NULL, &WriteEnable, Granularity);\r
+}\r
+\r
+\r
+/**\r
+  Modify the hardware to allow memory writes in a region.\r
+\r
+  This function changes the attributes of a memory range to allow writes.\r
+\r
+  @param  This[in]              Indicates the EFI_LEGACY_REGION_PROTOCOL instance.\r
+  @param  Start[in]             The beginning of the physical address of the region whose\r
+                                attributes should be modified.\r
+  @param  Length[in]            The number of bytes of memory whose attributes should be modified.\r
+                                The actual number of bytes modified may be greater than the number\r
+                                specified.\r
+  @param  Granularity[out]      The number of bytes in the last region affected. This may be less\r
+                                than the total number of bytes affected if the starting address was\r
+                                not aligned to a region's starting address or if the length was\r
+                                greater than the number of bytes in the first region.\r
+\r
+  @retval EFI_SUCCESS           The region's attributes were successfully modified.\r
+  @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyRegion2Unlock (\r
+  IN  EFI_LEGACY_REGION2_PROTOCOL  *This,\r
+  IN  UINT32                       Start,\r
+  IN  UINT32                       Length,\r
+  OUT UINT32                       *Granularity\r
+  )\r
+{\r
+  BOOLEAN  WriteEnable;\r
+\r
+  WriteEnable = TRUE;\r
+  return QNCLegacyRegionManipulation (Start, Length, NULL, &WriteEnable, Granularity);\r
+}\r
+\r
+/**\r
+  Get region information for the attributes of the Legacy Region.\r
+\r
+  This function is used to discover the granularity of the attributes for the memory in the legacy\r
+  region. Each attribute may have a different granularity and the granularity may not be the same\r
+  for all memory ranges in the legacy region.\r
+\r
+  @param  This[in]              Indicates the EFI_LEGACY_REGION_PROTOCOL instance.\r
+  @param  DescriptorCount[out]  The number of region descriptor entries returned in the Descriptor\r
+                                buffer.\r
+  @param  Descriptor[out]       A pointer to a pointer used to return a buffer where the legacy\r
+                                region information is deposited. This buffer will contain a list of\r
+                                DescriptorCount number of region descriptors.  This function will\r
+                                provide the memory for the buffer.\r
+\r
+  @retval EFI_SUCCESS           The region's attributes were successfully modified.\r
+  @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyRegionGetInfo (\r
+  IN  EFI_LEGACY_REGION2_PROTOCOL   *This,\r
+  OUT UINT32                        *DescriptorCount,\r
+  OUT EFI_LEGACY_REGION_DESCRIPTOR  **Descriptor\r
+  )\r
+{\r
+\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+  Entry point to the DXE Driver that produces the Legacy Region Protocol.\r
+\r
+  @retval  EFI_SUCCESS One or more of the drivers returned a success code.\r
+  @retval  !EFI_SUCESS The return status from the last driver entry point in the list.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyRegionInit (\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Install the Legacy Region Protocol on a new handle\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &mLegacyRegion2Handle,\r
+                  &gEfiLegacyRegion2ProtocolGuid, &mLegacyRegion2,\r
+                  NULL\r
+                  );\r
+\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyRegion.h b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/LegacyRegion.h
new file mode 100644 (file)
index 0000000..7bcb884
--- /dev/null
@@ -0,0 +1,204 @@
+/** @file\r
+The header file legacy region initialization in QNC DXE component.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _LEGACY_REGION_H_\r
+#define _LEGACY_REGION_H_\r
+#include "CommonHeader.h"\r
+\r
+#include <IndustryStandard/Pci.h>\r
+\r
+#define LEGACY_REGION_INSTANCE_SIGNATURE   SIGNATURE_32('R','E','G','N')\r
+\r
+typedef struct {\r
+  UINT32                          Signature;\r
+\r
+  EFI_HANDLE                      Handle;\r
+  EFI_LEGACY_REGION2_PROTOCOL     LegacyRegion2;\r
+  EFI_HANDLE                      ImageHandle;\r
+\r
+  //\r
+  // Protocol for PAM register access\r
+  //\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *PciRootBridgeIo;\r
+} LEGACY_REGION_INSTANCE;\r
+\r
+#define LEGACY_REGION_INSTANCE_FROM_THIS(this) \\r
+  CR(this, LEGACY_REGION_INSTANCE, LegacyRegion2, LEGACY_REGION_INSTANCE_SIGNATURE)\r
+\r
+\r
+EFI_STATUS\r
+LegacyRegionManipluateRegion (\r
+  IN  LEGACY_REGION_INSTANCE    *Private\r
+  );\r
+\r
+EFI_STATUS\r
+LegacyRegionInit (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Modify the hardware to allow (decode) or disallow (not decode) memory reads in a region.\r
+\r
+  If the On parameter evaluates to TRUE, this function enables memory reads in the address range\r
+  Start to (Start + Length - 1).\r
+  If the On parameter evaluates to FALSE, this function disables memory reads in the address range\r
+  Start to (Start + Length - 1).\r
+\r
+  @param  This[in]              Indicates the EFI_LEGACY_REGION_PROTOCOL instance.\r
+  @param  Start[in]             The beginning of the physical address of the region whose attributes\r
+                                should be modified.\r
+  @param  Length[in]            The number of bytes of memory whose attributes should be modified.\r
+                                The actual number of bytes modified may be greater than the number\r
+                                specified.\r
+  @param  Granularity[out]      The number of bytes in the last region affected. This may be less\r
+                                than the total number of bytes affected if the starting address\r
+                                was not aligned to a region's starting address or if the length\r
+                                was greater than the number of bytes in the first region.\r
+  @param  On[in]                Decode / Non-Decode flag.\r
+\r
+  @retval EFI_SUCCESS           The region's attributes were successfully modified.\r
+  @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyRegion2Decode (\r
+  IN  EFI_LEGACY_REGION2_PROTOCOL  *This,\r
+  IN  UINT32                       Start,\r
+  IN  UINT32                       Length,\r
+  OUT UINT32                       *Granularity,\r
+  IN  BOOLEAN                      *On\r
+  );\r
+\r
+/**\r
+  Modify the hardware to disallow memory writes in a region.\r
+\r
+  This function changes the attributes of a memory range to not allow writes.\r
+\r
+  @param  This[in]              Indicates the EFI_LEGACY_REGION_PROTOCOL instance.\r
+  @param  Start[in]             The beginning of the physical address of the region whose\r
+                                attributes should be modified.\r
+  @param  Length[in]            The number of bytes of memory whose attributes should be modified.\r
+                                The actual number of bytes modified may be greater than the number\r
+                                specified.\r
+  @param  Granularity[out]      The number of bytes in the last region affected. This may be less\r
+                                than the total number of bytes affected if the starting address was\r
+                                not aligned to a region's starting address or if the length was\r
+                                greater than the number of bytes in the first region.\r
+\r
+  @retval EFI_SUCCESS           The region's attributes were successfully modified.\r
+  @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyRegion2Lock (\r
+  IN  EFI_LEGACY_REGION2_PROTOCOL *This,\r
+  IN  UINT32                      Start,\r
+  IN  UINT32                      Length,\r
+  OUT UINT32                      *Granularity\r
+  );\r
+\r
+/**\r
+  Modify the hardware to disallow memory attribute changes in a region.\r
+\r
+  This function makes the attributes of a region read only. Once a region is boot-locked with this\r
+  function, the read and write attributes of that region cannot be changed until a power cycle has\r
+  reset the boot-lock attribute. Calls to Decode(), Lock() and Unlock() will have no effect.\r
+\r
+  @param  This[in]              Indicates the EFI_LEGACY_REGION_PROTOCOL instance.\r
+  @param  Start[in]             The beginning of the physical address of the region whose\r
+                                attributes should be modified.\r
+  @param  Length[in]            The number of bytes of memory whose attributes should be modified.\r
+                                The actual number of bytes modified may be greater than the number\r
+                                specified.\r
+  @param  Granularity[out]      The number of bytes in the last region affected. This may be less\r
+                                than the total number of bytes affected if the starting address was\r
+                                not aligned to a region's starting address or if the length was\r
+                                greater than the number of bytes in the first region.\r
+\r
+  @retval EFI_SUCCESS           The region's attributes were successfully modified.\r
+  @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.\r
+  @retval EFI_UNSUPPORTED       The chipset does not support locking the configuration registers in\r
+                                a way that will not affect memory regions outside the legacy memory\r
+                                region.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyRegion2BootLock (\r
+  IN EFI_LEGACY_REGION2_PROTOCOL          *This,\r
+  IN  UINT32                              Start,\r
+  IN  UINT32                              Length,\r
+  OUT UINT32                              *Granularity\r
+  );\r
+\r
+/**\r
+  Modify the hardware to allow memory writes in a region.\r
+\r
+  This function changes the attributes of a memory range to allow writes.\r
+\r
+  @param  This[in]              Indicates the EFI_LEGACY_REGION_PROTOCOL instance.\r
+  @param  Start[in]             The beginning of the physical address of the region whose\r
+                                attributes should be modified.\r
+  @param  Length[in]            The number of bytes of memory whose attributes should be modified.\r
+                                The actual number of bytes modified may be greater than the number\r
+                                specified.\r
+  @param  Granularity[out]      The number of bytes in the last region affected. This may be less\r
+                                than the total number of bytes affected if the starting address was\r
+                                not aligned to a region's starting address or if the length was\r
+                                greater than the number of bytes in the first region.\r
+\r
+  @retval EFI_SUCCESS           The region's attributes were successfully modified.\r
+  @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyRegion2Unlock (\r
+  IN  EFI_LEGACY_REGION2_PROTOCOL  *This,\r
+  IN  UINT32                       Start,\r
+  IN  UINT32                       Length,\r
+  OUT UINT32                       *Granularity\r
+  );\r
+\r
+/**\r
+  Get region information for the attributes of the Legacy Region.\r
+\r
+  This function is used to discover the granularity of the attributes for the memory in the legacy\r
+  region. Each attribute may have a different granularity and the granularity may not be the same\r
+  for all memory ranges in the legacy region.\r
+\r
+  @param  This[in]              Indicates the EFI_LEGACY_REGION_PROTOCOL instance.\r
+  @param  DescriptorCount[out]  The number of region descriptor entries returned in the Descriptor\r
+                                buffer.\r
+  @param  Descriptor[out]       A pointer to a pointer used to return a buffer where the legacy\r
+                                region information is deposited. This buffer will contain a list of\r
+                                DescriptorCount number of region descriptors.  This function will\r
+                                provide the memory for the buffer.\r
+\r
+  @retval EFI_SUCCESS           The region's attributes were successfully modified.\r
+  @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyRegionGetInfo (\r
+  IN  EFI_LEGACY_REGION2_PROTOCOL   *This,\r
+  OUT UINT32                        *DescriptorCount,\r
+  OUT EFI_LEGACY_REGION_DESCRIPTOR  **Descriptor\r
+  );\r
+\r
+#endif //_QNC_LEGACY_REGION_H_\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInit.c b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInit.c
new file mode 100644 (file)
index 0000000..c434067
--- /dev/null
@@ -0,0 +1,527 @@
+/** @file\r
+QuarkNcSocId module initialization module\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include "CommonHeader.h"\r
+\r
+#include "LegacyRegion.h"\r
+#include "DxeQNCSmbus.h"\r
+\r
+#include "QNCInit.h"\r
+\r
+//\r
+// Definitions\r
+//\r
+#define QNC_RESERVED_ITEM_IO         0\r
+#define QNC_RESERVED_ITEM_MEMORYIO   1\r
+#define DXE_DEVICE_DISABLED 0\r
+#define DXE_DEVICE_ENABLED 1\r
+\r
+typedef struct _QNC_SPACE_TABLE_ITEM {\r
+   UINTN                   IoOrMemory;\r
+   UINTN                   Type;\r
+   EFI_PHYSICAL_ADDRESS    BaseAddress;\r
+   UINT64                  Length;\r
+   UINTN                   Alignment;\r
+   BOOLEAN                 RuntimeOrNot;\r
+} QNC_SPACE_TABLE_ITEM;\r
+\r
+typedef struct {\r
+  ACPI_CPU_DATA       AcpuCpuData;\r
+  MTRR_SETTINGS       MtrrTable;\r
+  IA32_DESCRIPTOR     GdtrProfile;\r
+  IA32_DESCRIPTOR     IdtrProfile;\r
+  CPU_REGISTER_TABLE  RegisterTable;\r
+  CPU_REGISTER_TABLE  PreSmmInitRegisterTable;\r
+} ACPI_CPU_DATA_EX;\r
+\r
+//\r
+// Spaces to be reserved in GCD\r
+// Expand it to add more\r
+//\r
+const QNC_SPACE_TABLE_ITEM  mQNCReservedSpaceTable[] = {\r
+  {\r
+    QNC_RESERVED_ITEM_MEMORYIO,\r
+    EfiGcdMemoryTypeMemoryMappedIo,\r
+    FixedPcdGet64 (PcdIoApicBaseAddress),\r
+    FixedPcdGet64 (PcdIoApicSize),\r
+    0,\r
+    FALSE\r
+  },\r
+  {\r
+    QNC_RESERVED_ITEM_MEMORYIO,\r
+    EfiGcdMemoryTypeMemoryMappedIo,\r
+    FixedPcdGet64 (PcdHpetBaseAddress),\r
+    FixedPcdGet64 (PcdHpetSize),\r
+    0,\r
+    FALSE\r
+  }\r
+};\r
+\r
+//\r
+// Global variable for ImageHandle of QNCInit driver\r
+//\r
+EFI_HANDLE gQNCInitImageHandle;\r
+QNC_DEVICE_ENABLES    mQNCDeviceEnables;\r
+\r
+\r
+VOID\r
+QNCInitializeResource (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+InitializeQNCPolicy (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Allocate EfiACPIMemoryNVS below 4G memory address.\r
+\r
+  This function allocates EfiACPIMemoryNVS below 4G memory address.\r
+\r
+  @param Size   Size of memory to allocate.\r
+\r
+  @return       Allocated address for output.\r
+\r
+**/\r
+VOID *\r
+AllocateAcpiNvsMemoryBelow4G (\r
+  IN UINTN  Size\r
+  )\r
+{\r
+  UINTN                 Pages;\r
+  EFI_PHYSICAL_ADDRESS  Address;\r
+  EFI_STATUS            Status;\r
+  VOID*                 Buffer;\r
+\r
+  Pages = EFI_SIZE_TO_PAGES (Size);\r
+  Address = 0xffffffff;\r
+\r
+  Status  = gBS->AllocatePages (\r
+                   AllocateMaxAddress,\r
+                   EfiACPIMemoryNVS,\r
+                   Pages,\r
+                   &Address\r
+                   );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  Buffer = (VOID *) (UINTN) Address;\r
+  ZeroMem (Buffer, Size);\r
+\r
+  return Buffer;\r
+}\r
+\r
+/**\r
+  Prepare ACPI NVS memory below 4G memory for use of S3 resume.\r
+\r
+  This function allocates ACPI NVS memory below 4G memory for use of S3 resume,\r
+  and saves data into the memory region.\r
+\r
+**/\r
+VOID\r
+SaveCpuS3Data (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS        Status;\r
+  ACPI_CPU_DATA_EX  *AcpiCpuDataEx;\r
+  ACPI_CPU_DATA     *AcpiCpuData;\r
+  UINTN             GdtSize;\r
+  UINTN             IdtSize;\r
+  VOID              *Gdt;\r
+  VOID              *Idt;\r
+\r
+  //\r
+  // Allocate ACPI NVS memory below 4G memory for use of S3 resume.\r
+  //\r
+  AcpiCpuDataEx = AllocateAcpiNvsMemoryBelow4G (sizeof (ACPI_CPU_DATA_EX));\r
+  AcpiCpuData = &AcpiCpuDataEx->AcpuCpuData;\r
+\r
+  //\r
+  //\r
+  //\r
+  AcpiCpuData->NumberOfCpus              = 1;\r
+  AcpiCpuData->StackSize                 = PcdGet32 (PcdCpuApStackSize);\r
+  AcpiCpuData->ApMachineCheckHandlerBase = 0;\r
+  AcpiCpuData->ApMachineCheckHandlerSize = 0;\r
+  AcpiCpuData->GdtrProfile               = (EFI_PHYSICAL_ADDRESS) (UINTN) &AcpiCpuDataEx->GdtrProfile;\r
+  AcpiCpuData->IdtrProfile               = (EFI_PHYSICAL_ADDRESS) (UINTN) &AcpiCpuDataEx->IdtrProfile;\r
+  AcpiCpuData->MtrrTable                 = (EFI_PHYSICAL_ADDRESS) (UINTN) &AcpiCpuDataEx->MtrrTable;\r
+  AcpiCpuData->RegisterTable             = (EFI_PHYSICAL_ADDRESS) (UINTN) &AcpiCpuDataEx->RegisterTable;\r
+  AcpiCpuData->PreSmmInitRegisterTable   = (EFI_PHYSICAL_ADDRESS) (UINTN) &AcpiCpuDataEx->PreSmmInitRegisterTable;\r
+\r
+  //\r
+  // Allocate stack space for all CPUs\r
+  //\r
+  AcpiCpuData->StackAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocateAcpiNvsMemoryBelow4G (AcpiCpuData->NumberOfCpus * AcpiCpuData->StackSize);\r
+\r
+  //\r
+  // Get MTRR settings from currently executing CPU\r
+  //\r
+  MtrrGetAllMtrrs (&AcpiCpuDataEx->MtrrTable);\r
+\r
+  //\r
+  // Get the BSP's data of GDT and IDT\r
+  //\r
+  AsmReadGdtr ((IA32_DESCRIPTOR *) &AcpiCpuDataEx->GdtrProfile);\r
+  AsmReadIdtr ((IA32_DESCRIPTOR *) &AcpiCpuDataEx->IdtrProfile);\r
+\r
+  //\r
+  // Allocate GDT and IDT in ACPI NVS and copy in current GDT and IDT contents\r
+  //\r
+  GdtSize = AcpiCpuDataEx->GdtrProfile.Limit + 1;\r
+  IdtSize = AcpiCpuDataEx->IdtrProfile.Limit + 1;\r
+  Gdt = AllocateAcpiNvsMemoryBelow4G (GdtSize + IdtSize);\r
+  Idt = (VOID *)((UINTN)Gdt + GdtSize);\r
+  CopyMem (Gdt, (VOID *)AcpiCpuDataEx->GdtrProfile.Base, GdtSize);\r
+  CopyMem (Idt, (VOID *)AcpiCpuDataEx->IdtrProfile.Base, IdtSize);\r
+  AcpiCpuDataEx->GdtrProfile.Base = (UINTN)Gdt;\r
+  AcpiCpuDataEx->IdtrProfile.Base = (UINTN)Idt;\r
+\r
+  //\r
+  // No RegisterTable entries\r
+  //\r
+  AcpiCpuDataEx->RegisterTable.TableLength = 0;\r
+\r
+  //\r
+  // No PreSmmInitRegisterTable entries\r
+  //\r
+  AcpiCpuDataEx->PreSmmInitRegisterTable.TableLength = 0;\r
+\r
+  //\r
+  // Set the base address of CPU S3 data to PcdCpuS3DataAddress\r
+  //\r
+  Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+   The entry function for QNCInit driver.\r
+\r
+   This function just call initialization function for PciHostBridge,\r
+   LegacyRegion and QNCSmmAccess module.\r
+\r
+   @param ImageHandle   The driver image handle for GmchInit driver\r
+   @param SystemTable   The pointer to System Table\r
+\r
+   @retval EFI_SUCCESS  Success to initialize every module for GMCH driver.\r
+   @return EFI_STATUS   The status of initialization work.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+QNCInit (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  S3BootScriptSaveInformationAsciiString (\r
+    "QNCInitDxeEntryBegin"\r
+    );\r
+\r
+  gQNCInitImageHandle = ImageHandle;\r
+\r
+  mQNCDeviceEnables.Uint32 = PcdGet32 (PcdDeviceEnables);\r
+\r
+\r
+  //\r
+  // Initialize PCIE root ports\r
+  //\r
+  Status = QncInitRootPorts ();\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "QNC Root Port initialization is failed!\n"));\r
+    return Status;\r
+  }\r
+\r
+  Status = LegacyRegionInit ();\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "QNC LegacyRegion initialization is failed!\n"));\r
+    return Status;\r
+  }\r
+\r
+\r
+  Status = InitializeQNCPolicy ();\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "QNC Policy initialization is failed!\n"));\r
+    return Status;\r
+  }\r
+\r
+  Status = InitializeQNCSmbus (ImageHandle,SystemTable);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "QNC Smbus driver is failed!\n"));\r
+    return Status;\r
+  }\r
+\r
+  QNCInitializeResource ();\r
+\r
+  SaveCpuS3Data ();\r
+\r
+  S3BootScriptSaveInformationAsciiString (\r
+    "QNCInitDxeEntryEnd"\r
+    );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Reserve I/O or memory space in GCD\r
+\r
+  @param  IoOrMemory    Switch of I/O or memory.\r
+  @param  GcdType       Type of the space.\r
+  @param  BaseAddress   Base address of the space.\r
+  @param  Length        Length of the space.\r
+  @param  Alignment     Align with 2^Alignment\r
+  @param  RuntimeOrNot  For runtime usage or not\r
+  @param  ImageHandle   Handle for the image of this driver.\r
+\r
+  @retval EFI_SUCCESS   Reserve successful\r
+**/\r
+EFI_STATUS\r
+QNCReserveSpaceInGcd(\r
+  IN UINTN                 IoOrMemory,\r
+  IN UINTN                 GcdType,\r
+  IN EFI_PHYSICAL_ADDRESS  BaseAddress,\r
+  IN UINT64                Length,\r
+  IN UINTN                 Alignment,\r
+  IN BOOLEAN               RuntimeOrNot,\r
+  IN EFI_HANDLE            ImageHandle\r
+  )\r
+{\r
+  EFI_STATUS               Status;\r
+\r
+  if (IoOrMemory == QNC_RESERVED_ITEM_MEMORYIO) {\r
+    Status = gDS->AddMemorySpace (\r
+                    GcdType,\r
+                    BaseAddress,\r
+                    Length,\r
+                    EFI_MEMORY_UC\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((\r
+        EFI_D_ERROR,\r
+        "Failed to add memory space :0x%x 0x%x\n",\r
+        BaseAddress,\r
+        Length\r
+        ));\r
+    }\r
+    ASSERT_EFI_ERROR (Status);\r
+    Status = gDS->AllocateMemorySpace (\r
+                    EfiGcdAllocateAddress,\r
+                    GcdType,\r
+                    Alignment,\r
+                    Length,\r
+                    &BaseAddress,\r
+                    ImageHandle,\r
+                    NULL\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+    if (RuntimeOrNot) {\r
+      Status = gDS->SetMemorySpaceAttributes (\r
+                      BaseAddress,\r
+                      Length,\r
+                      EFI_MEMORY_RUNTIME | EFI_MEMORY_UC\r
+                     );\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+  } else {\r
+    Status = gDS->AddIoSpace (\r
+                    GcdType,\r
+                    BaseAddress,\r
+                    Length\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+    Status = gDS->AllocateIoSpace (\r
+                    EfiGcdAllocateAddress,\r
+                    GcdType,\r
+                    Alignment,\r
+                    Length,\r
+                    &BaseAddress,\r
+                    ImageHandle,\r
+                    NULL\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Initialize the memory and io resource which belong to QNC.\r
+  1) Report and allocate all BAR's memory to GCD.\r
+  2) Report PCI memory and I/O space to GCD.\r
+  3) Set memory attribute for <1M memory space.\r
+**/\r
+VOID\r
+QNCInitializeResource (\r
+  )\r
+{\r
+  EFI_PHYSICAL_ADDRESS            BaseAddress;\r
+  EFI_STATUS                      Status;\r
+  UINT64                          ExtraRegionLength;\r
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
+  UINTN                           Index;\r
+\r
+  // Report TSEG range\r
+  // This range maybe has been reportted in PEI phase via Resource Hob.\r
+  //\r
+  QNCGetTSEGMemoryRange (&BaseAddress, &ExtraRegionLength);\r
+  if (ExtraRegionLength != 0) {\r
+    Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &Descriptor);\r
+    if (Status == EFI_NOT_FOUND) {\r
+      Status = gDS->AddMemorySpace (\r
+                      EfiGcdMemoryTypeReserved,\r
+                      BaseAddress,\r
+                      ExtraRegionLength,\r
+                      EFI_MEMORY_UC\r
+                      );\r
+    }\r
+  }\r
+\r
+  //\r
+  // < 1M resource setting. The memory ranges <1M has been added into GCD via\r
+  // resource hob produced by PEI phase. Here will set memory attribute of these\r
+  // ranges for DXE phase.\r
+  //\r
+\r
+  //\r
+  // Dos Area (0 ~ 0x9FFFFh)\r
+  //\r
+  Status = gDS->GetMemorySpaceDescriptor (0, &Descriptor);\r
+  DEBUG ((\r
+    EFI_D_INFO,\r
+    "DOS Area Memory: base = 0x%x, length = 0x%x, attribute = 0x%x\n",\r
+    Descriptor.BaseAddress,\r
+    Descriptor.Length,\r
+    Descriptor.Attributes\r
+    ));\r
+  ASSERT_EFI_ERROR (Status);\r
+  Status = gDS->SetMemorySpaceAttributes(\r
+                  0,\r
+                  0xA0000,\r
+                  EFI_MEMORY_WB\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Default SMRAM UnCachable until SMBASE relocated.\r
+  //\r
+  Status = gDS->SetMemorySpaceAttributes(\r
+                  0x30000,\r
+                  0x10000,\r
+                  EFI_MEMORY_UC\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Default SMM ABSEG area. (0xA0000 ~ 0xBFFFF)\r
+  //\r
+  Status = gDS->GetMemorySpaceDescriptor (0xA0000, &Descriptor);\r
+  DEBUG ((\r
+    EFI_D_INFO,\r
+    "ABSEG Memory: base = 0x%x, length = 0x%x, attribute = 0x%x\n",\r
+    Descriptor.BaseAddress,\r
+    Descriptor.Length,\r
+    Descriptor.Attributes\r
+    ));\r
+  ASSERT_EFI_ERROR (Status);\r
+  Status = gDS->SetMemorySpaceAttributes(\r
+                  0xA0000,\r
+                  0x20000,\r
+                  EFI_MEMORY_UC\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Expansion BIOS area.\r
+  //\r
+  Status = gDS->GetMemorySpaceDescriptor (0xC0000, &Descriptor);\r
+  DEBUG ((\r
+    EFI_D_INFO,\r
+    "Memory base = 0x%x, length = 0x%x, attribute = 0x%x\n",\r
+    Descriptor.BaseAddress,\r
+    Descriptor.Length,\r
+    Descriptor.Attributes\r
+    ));\r
+  ASSERT_EFI_ERROR (Status);\r
+  Status = gDS->SetMemorySpaceAttributes(\r
+                  0xC0000,\r
+                  0x30000,\r
+                  EFI_MEMORY_UC\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Report other IO resources from mQNCReservedSpaceTable in GCD\r
+  //\r
+  for (Index = 0; Index < sizeof (mQNCReservedSpaceTable) / sizeof (QNC_SPACE_TABLE_ITEM); Index++) {\r
+    Status = QNCReserveSpaceInGcd (\r
+               mQNCReservedSpaceTable[Index].IoOrMemory,\r
+               mQNCReservedSpaceTable[Index].Type,\r
+               mQNCReservedSpaceTable[Index].BaseAddress,\r
+               mQNCReservedSpaceTable[Index].Length,\r
+               mQNCReservedSpaceTable[Index].Alignment,\r
+               mQNCReservedSpaceTable[Index].RuntimeOrNot,\r
+               gQNCInitImageHandle\r
+               );\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  //\r
+  // Report unused PCIe config space as reserved.\r
+  //\r
+  if (PcdGet64 (PcdPciExpressSize) < SIZE_256MB) {\r
+    Status = QNCReserveSpaceInGcd (\r
+               QNC_RESERVED_ITEM_MEMORYIO,\r
+               EfiGcdMemoryTypeMemoryMappedIo,\r
+               (PcdGet64(PcdPciExpressBaseAddress) + PcdGet64(PcdPciExpressSize)),\r
+               (SIZE_256MB - PcdGet64(PcdPciExpressSize)),\r
+               0,\r
+               FALSE,\r
+               gQNCInitImageHandle\r
+               );\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+}\r
+\r
+/**\r
+  Use the platform PCD to initialize devices in the QNC\r
+\r
+  @param  ImageHandle   Handle for the image of this driver.\r
+  @retval EFI_SUCCESS   Initialize successful\r
+**/\r
+EFI_STATUS\r
+InitializeQNCPolicy (\r
+  )\r
+{\r
+  UINT8        RevisionID;\r
+  UINT32       PciD31F0RegBase;  // LPC\r
+\r
+  RevisionID = LpcPciCfg8(R_QNC_LPC_REV_ID);\r
+\r
+  PciD31F0RegBase = PciDeviceMmBase (PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, PCI_FUNCTION_NUMBER_QNC_LPC);\r
+\r
+  //\r
+  // Disable for smbus\r
+  //\r
+  if (mQNCDeviceEnables.Bits.Smbus == DXE_DEVICE_DISABLED) {\r
+    S3MmioAnd32 (PciD31F0RegBase + R_QNC_LPC_SMBUS_BASE, (~B_QNC_LPC_SMBUS_BASE_EN));\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInit.h b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInit.h
new file mode 100644 (file)
index 0000000..c6d8592
--- /dev/null
@@ -0,0 +1,55 @@
+/** @file\r
+Header file for QNC Initialization Driver.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+#ifndef _QNC_INITIALIZATION_DRIVER_H_\r
+#define _QNC_INITIALIZATION_DRIVER_H_\r
+\r
+EFI_STATUS\r
+QncInitRootPorts (\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Perform Initialization of the Downstream Root Ports.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  EFI_STATUS\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+SetInitRootPortDownstreamS3Item (\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Set an Init Root Port Downstream devices S3 dispatch item, this function may assert if any error happend\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             The function completed successfully\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInitDxe.inf b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInitDxe.inf
new file mode 100644 (file)
index 0000000..0bafdd8
--- /dev/null
@@ -0,0 +1,98 @@
+## @file\r
+# Component description file for QNCInit driver.\r
+#\r
+# QNCInit driver implement QuarkNcSocId related drivers, includes:\r
+# PciHostBridge, PciExpress, SmmAccess driver and LegacyRegion driver.\r
+#\r
+# This driver mainly do full initialization for the QNC chipet includes:\r
+# 1. Initialize the PCI Express device.\r
+# 2. Initialize the PciHostBridge, and allocate the I/O and memory space from GCD service.\r
+# 3. Initialize the SmmAccess module and install EFI_SMM_ACCESS_PROTOCOL\r
+# 4. Initialize the LegacyRegion module, install EFI_LEGACY_REGION_PROTOCOL and set below 1M\r
+#    memory attribute from MTRR.\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = QNCInitDxe\r
+  FILE_GUID                      = 74D3B506-EE9C-47ed-B749-41261401DA78\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = QNCInit\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  LegacyRegion.h\r
+  LegacyRegion.c\r
+  DxeQNCSmbus.c\r
+  DxeQNCSmbus.h\r
+  QNCSmbusExec.c\r
+  QNCSmbus.h\r
+  QNCInit.c\r
+  QNCInit.h\r
+  CommonHeader.h\r
+  QNCRootPorts.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  UefiCpuPkg/UefiCpuPkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  UefiDriverEntryPoint\r
+  BaseLib\r
+  UefiBootServicesTableLib\r
+  DxeServicesTableLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  PcdLib\r
+  MtrrLib\r
+  IoLib\r
+  SmbusLib\r
+  S3IoLib\r
+  S3BootScriptLib\r
+  IntelQNCLib\r
+  QNCAccessLib\r
+\r
+[Protocols]\r
+  gEfiLegacyRegion2ProtocolGuid                 # PROTOCOL ALWAYS_PRODUCED\r
+  gEfiSmbusHcProtocolGuid                       # PROTOCOL ALWAYS_PRODUCED\r
+  gEfiQncS3SupportProtocolGuid                  # PROTOCOL ALWAYS_CONSUMED\r
+\r
+[FeaturePcd]\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmbaIoBaseAddressFixed\r
+\r
+[FixedPcd]\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdIoApicBaseAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdIoApicSize\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdHpetBaseAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdHpetSize\r
+\r
+[Pcd]\r
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize                           ## CONSUMES\r
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuS3DataAddress|0x0|UINT64|0x60000010   ## PRODUCES\r
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress                     ## CONSUMES\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciExpressSize                      ## CONSUMES\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmbaIoBaseAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdDeviceEnables\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPlatformSmbusAddrNum\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPlatformSmbusAddrTable\r
+\r
+[Depex]\r
+  gEfiPlatformPolicyProtocolGuid AND gEfiQncS3SupportProtocolGuid\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCRootPorts.c b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCRootPorts.c
new file mode 100644 (file)
index 0000000..e87d1f4
--- /dev/null
@@ -0,0 +1,82 @@
+/** @file\r
+PciHostBridge driver module, part of QNC module.\r
+\r
+Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include "CommonHeader.h"\r
+#include "QNCInit.h"\r
+\r
+UINT32  mS3ParameterRootPortDownstream = 0;\r
+EFI_QNC_S3_DISPATCH_ITEM  mS3DispatchItem = {\r
+    QncS3ItemTypeInitPcieRootPortDownstream,\r
+    &mS3ParameterRootPortDownstream\r
+  };\r
+\r
+EFI_STATUS\r
+QncInitRootPorts (\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Perform Initialization of the Downstream Root Ports\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             The function completed successfully\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_QNC_S3_SUPPORT_PROTOCOL  *QncS3Support;\r
+  VOID                         *Context;\r
+  VOID                         *S3DispatchEntryPoint;\r
+\r
+  Status = PciExpressInit ();\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Get the QNC S3 Support Protocol\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiQncS3SupportProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &QncS3Support\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get the QNC S3 Support Protocol\r
+  //\r
+  Status = QncS3Support->SetDispatchItem (\r
+                          QncS3Support,\r
+                          &mS3DispatchItem,\r
+                          &S3DispatchEntryPoint,\r
+                          &Context\r
+                          );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Save the script dispatch item in the Boot Script\r
+  //\r
+  Status = S3BootScriptSaveDispatch2 (S3DispatchEntryPoint, Context);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCSmbus.h b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCSmbus.h
new file mode 100644 (file)
index 0000000..d0c3e57
--- /dev/null
@@ -0,0 +1,86 @@
+/** @file\r
+Common definitons for SMBus PEIM/DXE driver. Smbus PEI and DXE\r
+modules share the same version of this file.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _QNC_SMBUS_H_\r
+#define _QNC_SMBUS_H_\r
+\r
+#include "CommonHeader.h"\r
+\r
+//\r
+// Minimum and maximum length for SMBus bus block protocols defined in SMBus spec 2.0.\r
+//\r
+#define MIN_SMBUS_BLOCK_LEN               1\r
+#define MAX_SMBUS_BLOCK_LEN               32\r
+#define ADD_LENGTH(SmbusAddress, Length)  ((SmbusAddress) + SMBUS_LIB_ADDRESS (0, 0, (Length), FALSE))\r
+\r
+/**\r
+  Executes an SMBus operation to an SMBus controller. Returns when either the command has been\r
+  executed or an error is encountered in doing the operation.\r
+\r
+  The internal worker function provides a standard way to execute an operation as defined in the\r
+  System Management Bus (SMBus) Specification. The resulting transaction will be either that the\r
+  SMBus slave devices accept this transaction or that this function returns with error.\r
+\r
+  @param  SlaveAddress            The SMBus slave address of the device with which to communicate.\r
+  @param  Command                 This command is transmitted by the SMBus host controller to the\r
+                                  SMBus slave device and the interpretation is SMBus slave device\r
+                                  specific. It can mean the offset to a list of functions inside an\r
+                                  SMBus slave device. Not all operations or slave devices support\r
+                                  this command's registers.\r
+  @param  Operation               Signifies which particular SMBus hardware protocol instance that\r
+                                  it will use to execute the SMBus transactions. This SMBus\r
+                                  hardware protocol is defined by the SMBus Specification and is\r
+                                  not related to EFI.\r
+  @param  PecCheck                Defines if Packet Error Code (PEC) checking is required for this\r
+                                  operation.\r
+  @param  Length                  Signifies the number of bytes that this operation will do. The\r
+                                  maximum number of bytes can be revision specific and operation\r
+                                  specific. This field will contain the actual number of bytes that\r
+                                  are executed for this operation. Not all operations require this\r
+                                  argument.\r
+  @param  Buffer                  Contains the value of data to execute to the SMBus slave device.\r
+                                  Not all operations require this argument. The length of this\r
+                                  buffer is identified by Length.\r
+\r
+  @retval EFI_SUCCESS             The last data that was returned from the access matched the poll\r
+                                  exit criteria.\r
+  @retval EFI_CRC_ERROR           Checksum is not correct (PEC is incorrect).\r
+  @retval EFI_TIMEOUT             Timeout expired before the operation was completed. Timeout is\r
+                                  determined by the SMBus host controller device.\r
+  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to a lack of resources.\r
+  @retval EFI_DEVICE_ERROR        The request was not completed because a failure that was\r
+                                  reflected in the Host Status Register bit. Device errors are a\r
+                                  result of a transaction collision, illegal command field,\r
+                                  unclaimed cycle (host initiated), or bus errors (collisions).\r
+  @retval EFI_INVALID_PARAMETER   Operation is not defined in EFI_SMBUS_OPERATION.\r
+  @retval EFI_INVALID_PARAMETER   Length/Buffer is NULL for operations except for EfiSmbusQuickRead\r
+                                  and EfiSmbusQuickWrite. Length is outside the range of valid\r
+                                  values.\r
+  @retval EFI_UNSUPPORTED         The SMBus operation or PEC is not supported.\r
+  @retval EFI_BUFFER_TOO_SMALL    Buffer is not sufficient for this operation.\r
+\r
+**/\r
+EFI_STATUS\r
+Execute (\r
+  IN     EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,\r
+  IN     EFI_SMBUS_DEVICE_COMMAND Command,\r
+  IN     EFI_SMBUS_OPERATION      Operation,\r
+  IN     BOOLEAN                  PecCheck,\r
+  IN OUT UINTN                    *Length,\r
+  IN OUT VOID                     *Buffer\r
+  );\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCSmbusExec.c b/QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCSmbusExec.c
new file mode 100644 (file)
index 0000000..3fda2a3
--- /dev/null
@@ -0,0 +1,252 @@
+/** @file\r
+Common code to implement SMBus bus protocols. Smbus PEI and DXE modules\r
+share the same version of this file.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include "CommonHeader.h"\r
+\r
+#include "QNCSmbus.h"\r
+\r
+/**\r
+  Checks the parameter of SmbusExecute().\r
+\r
+  This function checks the input parameters of SmbusExecute().  If the input parameters are valid\r
+  for certain SMBus bus protocol, it will return EFI_SUCCESS; otherwise, it will return certain\r
+  error code based on the input SMBus bus protocol.\r
+\r
+  @param  SlaveAddress            The SMBus slave address of the device with which to communicate.\r
+  @param  Command                 This command is transmitted by the SMBus host controller to the\r
+                                  SMBus slave device and the interpretation is SMBus slave device\r
+                                  specific. It can mean the offset to a list of functions inside an\r
+                                  SMBus slave device. Not all operations or slave devices support\r
+                                  this command's registers.\r
+  @param  Operation               Signifies which particular SMBus hardware protocol instance that\r
+                                  it will use to execute the SMBus transactions. This SMBus\r
+                                  hardware protocol is defined by the SMBus Specification and is\r
+                                  not related to EFI.\r
+  @param  PecCheck                Defines if Packet Error Code (PEC) checking is required for this\r
+                                  operation.\r
+  @param  Length                  Signifies the number of bytes that this operation will do. The\r
+                                  maximum number of bytes can be revision specific and operation\r
+                                  specific. This field will contain the actual number of bytes that\r
+                                  are executed for this operation. Not all operations require this\r
+                                  argument.\r
+  @param  Buffer                  Contains the value of data to execute to the SMBus slave device.\r
+                                  Not all operations require this argument. The length of this\r
+                                  buffer is identified by Length.\r
+\r
+  @retval EFI_SUCCESS             All the parameters are valid for the corresponding SMBus bus\r
+                                  protocol.\r
+  @retval EFI_INVALID_PARAMETER   Operation is not defined in EFI_SMBUS_OPERATION.\r
+  @retval EFI_INVALID_PARAMETER   Length/Buffer is NULL for operations except for EfiSmbusQuickRead\r
+                                  and EfiSmbusQuickWrite. Length is outside the range of valid\r
+                                  values.\r
+  @retval EFI_UNSUPPORTED         The SMBus operation or PEC is not supported.\r
+  @retval EFI_BUFFER_TOO_SMALL    Buffer is not sufficient for this operation.\r
+\r
+**/\r
+EFI_STATUS\r
+QncSmbusExecCheckParameters (\r
+  IN     EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,\r
+  IN     EFI_SMBUS_DEVICE_COMMAND Command,\r
+  IN     EFI_SMBUS_OPERATION      Operation,\r
+  IN     BOOLEAN                  PecCheck,\r
+  IN OUT UINTN                    *Length,\r
+  IN OUT VOID                     *Buffer\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       RequiredLen;\r
+\r
+  //\r
+  // Set default value to be 2:\r
+  // for SmbusReadWord, SmbusWriteWord and SmbusProcessCall.\r
+  //\r
+  RequiredLen = 2;\r
+  Status      = EFI_SUCCESS;\r
+  switch (Operation) {\r
+  case EfiSmbusQuickRead:\r
+  case EfiSmbusQuickWrite:\r
+    if (PecCheck || Command != 0) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+    break;\r
+  case EfiSmbusReceiveByte:\r
+  case EfiSmbusSendByte:\r
+    if (Command != 0) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+    //\r
+    // Cascade to check length parameter.\r
+    //\r
+  case EfiSmbusReadByte:\r
+  case EfiSmbusWriteByte:\r
+    RequiredLen = 1;\r
+    //\r
+    // Cascade to check length parameter.\r
+    //\r
+  case EfiSmbusReadWord:\r
+  case EfiSmbusWriteWord:\r
+  case EfiSmbusProcessCall:\r
+    if (Buffer == NULL || Length == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    } else if (*Length < RequiredLen) {\r
+      Status = EFI_BUFFER_TOO_SMALL;\r
+    }\r
+    *Length = RequiredLen;\r
+    break;\r
+  case EfiSmbusReadBlock:\r
+  case EfiSmbusWriteBlock:\r
+    if ((Buffer == NULL) ||\r
+        (Length == NULL) ||\r
+        (*Length < MIN_SMBUS_BLOCK_LEN) ||\r
+        (*Length > MAX_SMBUS_BLOCK_LEN)) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    break;\r
+  case EfiSmbusBWBRProcessCall:\r
+    return EFI_UNSUPPORTED;\r
+  default:\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Executes an SMBus operation to an SMBus controller. Returns when either the command has been\r
+  executed or an error is encountered in doing the operation.\r
+\r
+  The internal worker function provides a standard way to execute an operation as defined in the\r
+  System Management Bus (SMBus) Specification. The resulting transaction will be either that the\r
+  SMBus slave devices accept this transaction or that this function returns with error.\r
+\r
+  @param  SlaveAddress            The SMBus slave address of the device with which to communicate.\r
+  @param  Command                 This command is transmitted by the SMBus host controller to the\r
+                                  SMBus slave device and the interpretation is SMBus slave device\r
+                                  specific. It can mean the offset to a list of functions inside an\r
+                                  SMBus slave device. Not all operations or slave devices support\r
+                                  this command's registers.\r
+  @param  Operation               Signifies which particular SMBus hardware protocol instance that\r
+                                  it will use to execute the SMBus transactions. This SMBus\r
+                                  hardware protocol is defined by the SMBus Specification and is\r
+                                  not related to EFI.\r
+  @param  PecCheck                Defines if Packet Error Code (PEC) checking is required for this\r
+                                  operation.\r
+  @param  Length                  Signifies the number of bytes that this operation will do. The\r
+                                  maximum number of bytes can be revision specific and operation\r
+                                  specific. This field will contain the actual number of bytes that\r
+                                  are executed for this operation. Not all operations require this\r
+                                  argument.\r
+  @param  Buffer                  Contains the value of data to execute to the SMBus slave device.\r
+                                  Not all operations require this argument. The length of this\r
+                                  buffer is identified by Length.\r
+\r
+  @retval EFI_SUCCESS             The last data that was returned from the access matched the poll\r
+                                  exit criteria.\r
+  @retval EFI_CRC_ERROR           Checksum is not correct (PEC is incorrect).\r
+  @retval EFI_TIMEOUT             Timeout expired before the operation was completed. Timeout is\r
+                                  determined by the SMBus host controller device.\r
+  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to a lack of resources.\r
+  @retval EFI_DEVICE_ERROR        The request was not completed because a failure that was\r
+                                  reflected in the Host Status Register bit. Device errors are a\r
+                                  result of a transaction collision, illegal command field,\r
+                                  unclaimed cycle (host initiated), or bus errors (collisions).\r
+  @retval EFI_INVALID_PARAMETER   Operation is not defined in EFI_SMBUS_OPERATION.\r
+  @retval EFI_INVALID_PARAMETER   Length/Buffer is NULL for operations except for EfiSmbusQuickRead\r
+                                  and EfiSmbusQuickWrite. Length is outside the range of valid\r
+                                  values.\r
+  @retval EFI_UNSUPPORTED         The SMBus operation or PEC is not supported.\r
+  @retval EFI_BUFFER_TOO_SMALL    Buffer is not sufficient for this operation.\r
+\r
+**/\r
+EFI_STATUS\r
+Execute (\r
+  IN     EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,\r
+  IN     EFI_SMBUS_DEVICE_COMMAND Command,\r
+  IN     EFI_SMBUS_OPERATION      Operation,\r
+  IN     BOOLEAN                  PecCheck,\r
+  IN OUT UINTN                    *Length,\r
+  IN OUT VOID                     *Buffer\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  UINTN                           SmbusAddress;\r
+  UINTN                           WorkBufferLen;\r
+  UINT8                           WorkBuffer[MAX_SMBUS_BLOCK_LEN];\r
+\r
+  Status = QncSmbusExecCheckParameters (\r
+             SlaveAddress,\r
+             Command,\r
+             Operation,\r
+             PecCheck,\r
+             Length,\r
+             Buffer);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  SmbusAddress = SMBUS_LIB_ADDRESS (SlaveAddress.SmbusDeviceAddress, Command, *Length, PecCheck);\r
+\r
+  switch (Operation) {\r
+  case EfiSmbusQuickRead:\r
+    SmBusQuickRead (SmbusAddress, &Status);\r
+    break;\r
+  case EfiSmbusQuickWrite:\r
+    SmBusQuickWrite (SmbusAddress, &Status);\r
+    break;\r
+  case EfiSmbusReceiveByte:\r
+    *(UINT8 *) Buffer = SmBusReceiveByte (SmbusAddress, &Status);\r
+    break;\r
+  case EfiSmbusSendByte:\r
+    SmBusSendByte (SmbusAddress, *(UINT8 *) Buffer, &Status);\r
+    break;\r
+  case EfiSmbusReadByte:\r
+    *(UINT8 *) Buffer = SmBusReadDataByte (SmbusAddress, &Status);\r
+    break;\r
+  case EfiSmbusWriteByte:\r
+    SmBusWriteDataByte (SmbusAddress, *(UINT8 *) Buffer, &Status);\r
+    break;\r
+  case EfiSmbusReadWord:\r
+    *(UINT16 *) Buffer = SmBusReadDataWord (SmbusAddress, &Status);\r
+    break;\r
+  case EfiSmbusWriteWord:\r
+    SmBusWriteDataWord (SmbusAddress, *(UINT16 *) Buffer, &Status);\r
+    break;\r
+  case EfiSmbusProcessCall:\r
+    *(UINT16 *) Buffer = SmBusProcessCall (SmbusAddress, *(UINT16 *) Buffer, &Status);\r
+    break;\r
+  case EfiSmbusReadBlock:\r
+    WorkBufferLen = SmBusReadBlock (SmbusAddress, WorkBuffer, &Status);\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Read block transaction is complete successfully, and then\r
+      // check whether the output buffer is large enough.\r
+      //\r
+      if (*Length >= WorkBufferLen) {\r
+        CopyMem (Buffer, WorkBuffer, WorkBufferLen);\r
+      } else {\r
+        Status = EFI_BUFFER_TOO_SMALL;\r
+      }\r
+      *Length = WorkBufferLen;\r
+    }\r
+    break;\r
+  case EfiSmbusWriteBlock:\r
+    SmBusWriteBlock (ADD_LENGTH (SmbusAddress, *Length), Buffer, &Status);\r
+    break;\r
+  default:\r
+    break;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.c b/QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.c
new file mode 100644 (file)
index 0000000..9290311
--- /dev/null
@@ -0,0 +1,423 @@
+/** @file\r
+This is the driver that implements the QNC S3 Support protocol\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include "QncS3Support.h"\r
+\r
+//\r
+// Global Variables\r
+//\r
+EFI_QNC_S3_SUPPORT_PROTOCOL mQncS3SupportProtocol;\r
+QNC_S3_PARAMETER_HEADER     *mS3Parameter;\r
+UINT32                      mQncS3ImageEntryPoint;\r
+VOID                        *mQncS3ImageAddress;\r
+UINTN                       mQncS3ImageSize;\r
+\r
+extern EFI_GUID gQncS3CodeInLockBoxGuid;\r
+extern EFI_GUID gQncS3ContextInLockBoxGuid;\r
+\r
+/**\r
+\r
+    Create a buffer that is used to store context information for use with\r
+    dispatch functions.\r
+\r
+    @retval EFI_SUCCESS - Buffer allocated and initialized.\r
+\r
+**/\r
+EFI_STATUS\r
+CreateContextBuffer (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  EFI_PHYSICAL_ADDRESS  Address;\r
+  UINT32                ContextStoreSize;\r
+\r
+  ContextStoreSize = EFI_PAGE_SIZE;\r
+\r
+  //\r
+  // Allcoate <4G EfiReservedMemory\r
+  //\r
+  Address = 0xFFFFFFFF;\r
+  Status = gBS->AllocatePages (AllocateMaxAddress, EfiReservedMemoryType, EFI_SIZE_TO_PAGES (ContextStoreSize), &Address);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  mS3Parameter  = (QNC_S3_PARAMETER_HEADER *) (UINTN) Address;\r
+\r
+  //\r
+  // Determine the maximum number of context entries that can be stored in this\r
+  // table.\r
+  //\r
+  mS3Parameter->MaxContexts = ((ContextStoreSize - sizeof(QNC_S3_PARAMETER_HEADER)) / sizeof(EFI_DISPATCH_CONTEXT_UNION)) + 1;\r
+  mS3Parameter->StorePosition = 0;\r
+\r
+  return Status;\r
+}\r
+\r
+//\r
+// Functions\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+QncS3SupportEntryPoint (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+\r
+    QNC S3 support driver entry point\r
+\r
+  Arguments:\r
+\r
+    ImageHandle     - Handle for the image of this driver\r
+    SystemTable     - Pointer to the EFI System Table\r
+\r
+  Returns:\r
+\r
+    EFI_STATUS\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  VOID        *TmpPtr;\r
+  EFI_EVENT   Event;\r
+\r
+  //\r
+  // If the protocol is found execution is happening in ACPI NVS memory.  If it\r
+  // is not found copy the driver into ACPI NVS memory and pass control to it.\r
+  //\r
+  Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &TmpPtr);\r
+\r
+  //\r
+  // Load the QNC S3 image\r
+  //\r
+  if (EFI_ERROR (Status)) {\r
+    Status = LoadQncS3Image (SystemTable);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+  } else {\r
+    DEBUG ((DEBUG_INFO, "QncS3SupportEntryPoint() in reserved memory - Begin\n"));\r
+    //\r
+    // Allocate and initialize context buffer.\r
+    //\r
+    Status = CreateContextBuffer ();\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    //\r
+    // Install the QNC S3 Support protocol\r
+    //\r
+    mQncS3SupportProtocol.SetDispatchItem = QncS3SetDispatchItem;\r
+    Status = gBS->InstallMultipleProtocolInterfaces (\r
+                    &ImageHandle,\r
+                    &gEfiQncS3SupportProtocolGuid,\r
+                    &mQncS3SupportProtocol,\r
+                    NULL\r
+                    );\r
+\r
+    mQncS3ImageAddress = (VOID *)(UINTN)PcdGet64(PcdQncS3CodeInLockBoxAddress);\r
+    mQncS3ImageSize    = (UINTN)PcdGet64(PcdQncS3CodeInLockBoxSize);\r
+    DEBUG ((DEBUG_INFO, "QncS3SupportEntry Code = %08x, Size = %08x\n", (UINTN)mQncS3ImageAddress, mQncS3ImageSize));\r
+    DEBUG ((DEBUG_INFO, "QncS3SupportEntry Contex = %08x, Size = %08x\n", (UINTN)mS3Parameter, EFI_PAGE_SIZE));\r
+    ASSERT (mQncS3ImageAddress != 0);\r
+\r
+    //\r
+    // Register EFI_END_OF_DXE_EVENT_GROUP_GUID event.\r
+    //\r
+    Status = gBS->CreateEventEx (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_CALLBACK,\r
+                    QncS3BootEvent,\r
+                    NULL,\r
+                    &gEfiEndOfDxeEventGroupGuid,\r
+                    &Event\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    DEBUG ((DEBUG_INFO, "QncS3SupportEntryPoint() in reserved memory - End\n"));\r
+  }\r
+\r
+\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+QncS3SetDispatchItem (\r
+  IN     EFI_QNC_S3_SUPPORT_PROTOCOL   *This,\r
+  IN     EFI_QNC_S3_DISPATCH_ITEM      *DispatchItem,\r
+  OUT  VOID                            **S3DispatchEntryPoint,\r
+  OUT  VOID                            **Context\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Set an item to be dispatched at S3 resume time. At the same time, the entry point\r
+  of the QNC S3 support image is returned to be used in subsequent boot script save\r
+  call\r
+\r
+Arguments:\r
+\r
+  This                    - Pointer to the protocol instance.\r
+  DispatchItem            - The item to be dispatched.\r
+  S3DispatchEntryPoint    - The entry point of the QNC S3 support image.\r
+\r
+Returns:\r
+\r
+  EFI_STATUS              - Successfully completed.\r
+  EFI_OUT_OF_RESOURCES    - Out of resources.\r
+\r
+--*/\r
+{\r
+\r
+  DEBUG ((DEBUG_INFO, "QncS3SetDispatchItem() Start\n"));\r
+\r
+  //\r
+  // Set default values.\r
+  //\r
+  *S3DispatchEntryPoint = NULL;\r
+  *Context = NULL;\r
+\r
+  //\r
+  // Determine if this entry will fit.\r
+  //\r
+  if (mS3Parameter->StorePosition >= mS3Parameter->MaxContexts) {\r
+    DEBUG ((DEBUG_INFO, "QncS3SetDispatchItem exceeds max length - 0x%08x\n", (UINTN)mS3Parameter->MaxContexts));\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // Calculate the size required;\r
+  // ** Always round up to be 8 byte aligned\r
+  //\r
+  switch (DispatchItem->Type) {\r
+    case QncS3ItemTypeInitPcieRootPortDownstream:\r
+      *S3DispatchEntryPoint = (VOID*) (UINTN)QncS3InitPcieRootPortDownstream;\r
+      *Context = &mS3Parameter->Contexts[mS3Parameter->StorePosition];\r
+       CopyMem (&mS3Parameter->Contexts[mS3Parameter->StorePosition], DispatchItem->Parameter, sizeof(UINT32));\r
+      DEBUG ((DEBUG_INFO, "QncS3InitPcieRootPortDownstream @ 0x%08x - context  0x%08x\n", (UINTN)*S3DispatchEntryPoint, (UINTN)*Context));\r
+       break;\r
+\r
+    default:\r
+      return EFI_UNSUPPORTED;\r
+\r
+  }\r
+\r
+  mS3Parameter->StorePosition ++;\r
+  DEBUG ((DEBUG_INFO, "QncS3SetDispatchItem() End\n"));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+LoadQncS3Image (\r
+  IN  EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Load the QNC S3 Image into Efi Reserved Memory below 4G.\r
+\r
+Arguments:\r
+\r
+  ImageEntryPoint     the ImageEntryPoint after success loading\r
+\r
+Returns:\r
+\r
+  EFI_STATUS\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                                    Status;\r
+  UINT8                                         *Buffer;\r
+  UINTN                                         BufferSize;\r
+  VOID                                          *FfsBuffer;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT                  ImageContext;\r
+  EFI_HANDLE                                    NewImageHandle;\r
+\r
+  //\r
+  // Install NULL protocol on module file handle to indicate that the entry point\r
+  // has been called for the first time.\r
+  //\r
+  NewImageHandle = NULL;\r
+  Status = gBS->InstallProtocolInterface (\r
+    &NewImageHandle,\r
+    &gEfiCallerIdGuid,\r
+    EFI_NATIVE_INTERFACE,\r
+    NULL\r
+    );\r
+\r
+\r
+  //\r
+  // Find this module so it can be loaded again.\r
+  //\r
+  Status = GetSectionFromAnyFv  (\r
+             &gEfiCallerIdGuid,\r
+             EFI_SECTION_PE32,\r
+             0,\r
+             (VOID**) &Buffer,\r
+             &BufferSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+\r
+  //\r
+  // Get information about the image being loaded.\r
+  //\r
+  ImageContext.Handle = Buffer;\r
+  ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;\r
+\r
+  //\r
+  // Get information about the image being loaded\r
+  //\r
+  Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
+  ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->AllocatePool (\r
+                EfiReservedMemoryType,\r
+                BufferSize + ImageContext.SectionAlignment,\r
+                &FfsBuffer\r
+                );\r
+  ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_INFO, "LoadQncS3Image failed for no enough space! \n"));\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  mQncS3ImageAddress = FfsBuffer;\r
+  mQncS3ImageSize    = BufferSize + ImageContext.SectionAlignment;\r
+  Status = PcdSet64S (PcdQncS3CodeInLockBoxAddress, (UINT64)(UINTN)mQncS3ImageAddress);\r
+  ASSERT_EFI_ERROR (Status);\r
+  Status = PcdSet64S (PcdQncS3CodeInLockBoxSize, (UINT64)mQncS3ImageSize);\r
+  ASSERT_EFI_ERROR (Status);\r
+  //\r
+  // Align buffer on section boundry\r
+  //\r
+  ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer;\r
+  if (ImageContext.SectionAlignment != 0) {\r
+    ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;\r
+    ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);\r
+  }\r
+\r
+  //\r
+  // Load the image to our new buffer\r
+  //\r
+  Status = PeCoffLoaderLoadImage (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->FreePool (FfsBuffer);\r
+    DEBUG ((DEBUG_INFO, "LoadQncS3Image failed for PeCoffLoaderLoadImage failure! \n"));\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Relocate the image in our new buffer\r
+  //\r
+  Status = PeCoffLoaderRelocateImage (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    PeCoffLoaderUnloadImage (&ImageContext);\r
+    gBS->FreePool (FfsBuffer);\r
+    DEBUG ((DEBUG_INFO, "LoadQncS3Image failed for PeCoffLoaderRelocateImage failure! \n"));\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Invalidate instruction cache and pass control to the image.  This will perform\r
+  // the initialization of the module and publish the supporting protocols.\r
+  //\r
+  InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
+  Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, SystemTable);\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->FreePool (FfsBuffer);\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+QncS3InitPcieRootPortDownstream (\r
+  IN EFI_HANDLE ImageHandle,\r
+  IN VOID       *Context\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Perform Init Root Port Downstream devices on S3 resume\r
+\r
+  Arguments:\r
+    Parameter         Parameters passed in from DXE\r
+\r
+  Returns:\r
+    EFI_STATUS\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  DEBUG ((DEBUG_INFO, "QncS3InitPcieRootPortDownstream() Begin\n"));\r
+\r
+  //\r
+  // Initialize the device behind the root port.\r
+  //\r
+  Status = PciExpressInit ();\r
+\r
+  //\r
+  // Not checking the error status here - downstream device not present does not\r
+  // mean an error of this root port. Our return status of EFI_SUCCESS means this\r
+  // port is enabled and outer function depends on this return status to do\r
+  // subsequent initializations.\r
+  //\r
+\r
+  if (Status != EFI_SUCCESS){\r
+    DEBUG ((DEBUG_INFO, "QncS3InitPcieRootPortDownstream() failed\n"));\r
+  }\r
+\r
+  DEBUG ((DEBUG_INFO, "QncS3InitPcieRootPortDownstream() End\n"));\r
+  return Status;\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+QncS3BootEvent (\r
+  IN EFI_EVENT    Event,\r
+  IN VOID         *Context\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // These 2 boxes will be restored by RestoreAllLockBoxInPlace in S3Resume automatically\r
+  //\r
+  DEBUG ((DEBUG_INFO, "SaveLockBox QncS3Code = %08x, Size = %08x\n", (UINTN)mQncS3ImageAddress, mQncS3ImageSize));\r
+  SaveLockBox(&gQncS3CodeInLockBoxGuid, mQncS3ImageAddress, mQncS3ImageSize);\r
+  Status = SetLockBoxAttributes (&gQncS3CodeInLockBoxGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  DEBUG ((DEBUG_INFO, "SaveLockBox QncS3Context = %08x, Size = %08x\n", (UINTN)mS3Parameter, EFI_PAGE_SIZE));\r
+  SaveLockBox(&gQncS3ContextInLockBoxGuid, (VOID *)mS3Parameter, EFI_PAGE_SIZE);\r
+  Status = SetLockBoxAttributes (&gQncS3ContextInLockBoxGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.h b/QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.h
new file mode 100644 (file)
index 0000000..140167e
--- /dev/null
@@ -0,0 +1,123 @@
+/** @file\r
+Header file for QNC S3 Support driver\r
+\r
+This file includes package header files, library classes and protocol, PPI & GUID definitions.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#ifndef _QNC_S3_SUPPORT_H_\r
+#define _QNC_S3_SUPPORT_H_\r
+\r
+//\r
+// External include files do NOT need to be explicitly specified in real EDKII\r
+// environment\r
+//\r
+//\r
+// Driver Consumed Protocol Prototypes\r
+//\r
+#include <Protocol/FirmwareVolume2.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/DxeServicesLib.h>\r
+#include <Library/S3BootScriptLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/PeCoffLib.h>\r
+#include <Library/LockBoxLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+//\r
+// Driver Produced Protocol Prototypes\r
+//\r
+#include <Protocol/LoadedImage.h>\r
+#include <Protocol/QncS3Support.h>\r
+\r
+#include <Library/CacheMaintenanceLib.h>\r
+#include <Library/IntelQNCLib.h>\r
+//\r
+// Define the header of the context region.\r
+//\r
+typedef struct {\r
+  UINT32                      MaxContexts;\r
+  UINT32                      StorePosition;\r
+  EFI_DISPATCH_CONTEXT_UNION  Contexts[1];\r
+} QNC_S3_PARAMETER_HEADER;\r
+//\r
+// Function prototypes\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+QncS3SetDispatchItem (\r
+  IN     EFI_QNC_S3_SUPPORT_PROTOCOL   *This,\r
+  IN     EFI_QNC_S3_DISPATCH_ITEM      *DispatchItem,\r
+  OUT    VOID                          **S3DispatchEntryPoint,\r
+  OUT    VOID                          **Context\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Set an item to be dispatched at S3 resume time. At the same time, the entry point\r
+  of the QNC S3 support image is returned to be used in subsequent boot script save\r
+  call\r
+\r
+Arguments:\r
+\r
+  This                    - Pointer to the protocol instance.\r
+  DispatchItem            - The item to be dispatched.\r
+  S3DispatchEntryPoint    - The entry point of the QNC S3 support image.\r
+\r
+Returns:\r
+\r
+  EFI_STATUS              - Successfully completed.\r
+  EFI_OUT_OF_RESOURCES    - Out of resources.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+LoadQncS3Image (\r
+  IN  EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Load the QNC S3 Image into Efi Reserved Memory below 4G.\r
+\r
+Arguments:\r
+\r
+  ImageEntryPoint     the ImageEntryPoint after success loading\r
+\r
+Returns:\r
+\r
+  EFI_STATUS\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+QncS3InitPcieRootPortDownstream (\r
+  IN EFI_HANDLE ImageHandle,\r
+  IN VOID       *Context\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+QncS3BootEvent (\r
+  IN EFI_EVENT    Event,\r
+  IN VOID         *Context\r
+  );\r
+\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.inf b/QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.inf
new file mode 100644 (file)
index 0000000..f9d3c69
--- /dev/null
@@ -0,0 +1,70 @@
+## @file\r
+#    Component description file for Qnc Initialization driver\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = QncS3Support\r
+  FILE_GUID                      = C7EA9787-CA0A-43b4-B1E5-25EF87391F8D\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = QncS3SupportEntryPoint\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources]\r
+  QncS3Support.h\r
+  QncS3Support.c\r
+\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  IoLib\r
+  DebugLib\r
+  DxeServicesLib\r
+  BaseMemoryLib\r
+  UefiDriverEntryPoint\r
+  PeCoffLib\r
+  LockBoxLib\r
+  S3BootScriptLib\r
+  UefiBootServicesTableLib\r
+  UefiRuntimeServicesTableLib\r
+  CacheMaintenanceLib\r
+  IntelQNCLib\r
+\r
+[Protocols]\r
+  gEfiQncS3SupportProtocolGuid     ## PRODUCES\r
+  gEfiLoadPeImageProtocolGuid      ## CONSUMES\r
+  gEfiFirmwareVolume2ProtocolGuid  ## CONSUMES\r
+\r
+[Guids]\r
+  gQncS3CodeInLockBoxGuid\r
+  gQncS3ContextInLockBoxGuid\r
+  gEfiEndOfDxeEventGroupGuid\r
+\r
+[Pcd]\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdQncS3CodeInLockBoxAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdQncS3CodeInLockBoxSize\r
+\r
+[Depex]\r
+  gEfiFirmwareVolume2ProtocolGuid AND\r
+  gEfiVariableArchProtocolGuid AND\r
+  gEfiVariableWriteArchProtocolGuid\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccess.inf b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccess.inf
new file mode 100644 (file)
index 0000000..c50ac53
--- /dev/null
@@ -0,0 +1,54 @@
+## @file\r
+# Component description file for SmmAccess module\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = SmmAccess\r
+  FILE_GUID                      = 274F0C8F-9E57-41d8-9966-29CCD48D31C2\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = SmmAccessDriverEntryPoint\r
+\r
+[Sources]\r
+  SmmAccessDriver.h\r
+  SmmAccessDriver.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  HobLib\r
+  DebugLib\r
+  UefiLib\r
+  BaseLib\r
+  BaseMemoryLib\r
+  S3BootScriptLib\r
+  UefiDriverEntryPoint\r
+  UefiBootServicesTableLib\r
+  PcdLib\r
+  SmmLib\r
+\r
+[Protocols]\r
+  gEfiPciRootBridgeIoProtocolGuid\r
+  gEfiSmmAccess2ProtocolGuid\r
+\r
+[Guids]\r
+  gEfiSmmPeiSmramMemoryReserveGuid\r
+\r
+[Depex]\r
+  gEfiPciRootBridgeIoProtocolGuid\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccessDriver.c b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccessDriver.c
new file mode 100644 (file)
index 0000000..51432b6
--- /dev/null
@@ -0,0 +1,395 @@
+/** @file\r
+This is the driver that publishes the SMM Access Protocol\r
+instance for the Tylersburg chipset.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "SmmAccessDriver.h"\r
+\r
+\r
+\r
+SMM_ACCESS_PRIVATE_DATA  mSmmAccess;\r
+\r
+VOID\r
+SmmAccessOnBoot (\r
+  IN EFI_EVENT                          Event,\r
+  IN VOID                               *Context\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SmmAccessDriverEntryPoint (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Installs an SMM Access Protocol.\r
+\r
+Arguments:\r
+\r
+  ImageHandle  -  Handle for the image of this driver.\r
+  SystemTable  -  Pointer to the EFI System Table.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS     -  Protocol successfully started and installed.\r
+  EFI_UNSUPPORTED -  Protocol can't be started.\r
+  EFI_NOT_FOUND   -  Protocol not found.\r
+--*/\r
+{\r
+\r
+  EFI_STATUS                      Status;\r
+  EFI_EVENT                       BootEvent;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+  UINTN                           Index;\r
+  EFI_SMRAM_HOB_DESCRIPTOR_BLOCK  *DescriptorBlock;\r
+  EFI_HOB_GUID_TYPE               *GuidHob;\r
+\r
+\r
+  //\r
+  // Initialize private data\r
+  //\r
+  ZeroMem (&mSmmAccess, sizeof (mSmmAccess));\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiPciRootBridgeIoProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &PciRootBridgeIo\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Build SMM related information\r
+  //\r
+  mSmmAccess.Signature        = SMM_ACCESS_PRIVATE_DATA_SIGNATURE;\r
+  mSmmAccess.Handle           = NULL;\r
+  mSmmAccess.PciRootBridgeIo  = PciRootBridgeIo;\r
+\r
+  //\r
+  // Get Hob list\r
+  //\r
+  GuidHob    = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);\r
+  DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);\r
+  ASSERT (DescriptorBlock);\r
+\r
+\r
+  //\r
+  // Get CPU Max bus number\r
+  //\r
+  mSmmAccess.MaxBusNumber         = PCI_BUS_NUMBER_QNC;\r
+  for (Index = 0; Index < MAX_CPU_SOCKET; Index++) {\r
+    mSmmAccess.SocketPopulated[Index] = TRUE;\r
+  }\r
+\r
+  //\r
+  // Use the hob to publish SMRAM capabilities\r
+  //\r
+  ASSERT (DescriptorBlock->NumberOfSmmReservedRegions <= MAX_SMRAM_RANGES);\r
+  for (Index = 0; Index < DescriptorBlock->NumberOfSmmReservedRegions; Index++) {\r
+    mSmmAccess.SmramDesc[Index].PhysicalStart = DescriptorBlock->Descriptor[Index].PhysicalStart;\r
+    mSmmAccess.SmramDesc[Index].CpuStart      = DescriptorBlock->Descriptor[Index].CpuStart;\r
+    mSmmAccess.SmramDesc[Index].PhysicalSize  = DescriptorBlock->Descriptor[Index].PhysicalSize;\r
+    mSmmAccess.SmramDesc[Index].RegionState   = DescriptorBlock->Descriptor[Index].RegionState;\r
+    DEBUG ((EFI_D_INFO, "SM RAM index[%d] startaddr:%08X Size :%08X\n", Index, mSmmAccess.SmramDesc[Index].CpuStart,\r
+      mSmmAccess.SmramDesc[Index].PhysicalSize));\r
+  }\r
+\r
+  mSmmAccess.NumberRegions              = Index;\r
+  mSmmAccess.SmmAccess.Open             = Open;\r
+  mSmmAccess.SmmAccess.Close            = Close;\r
+  mSmmAccess.SmmAccess.Lock             = Lock;\r
+  mSmmAccess.SmmAccess.GetCapabilities  = GetCapabilities;\r
+  mSmmAccess.SmmAccess.LockState        = FALSE;\r
+  mSmmAccess.SmmAccess.OpenState        = FALSE;\r
+  mSmmAccess.SMMRegionState             = EFI_SMRAM_CLOSED;\r
+\r
+  //\r
+  // Install our protocol interfaces on the device's handle\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                &mSmmAccess.Handle,\r
+                &gEfiSmmAccess2ProtocolGuid,\r
+                &mSmmAccess.SmmAccess,\r
+                NULL\r
+                );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  DEBUG ((EFI_D_INFO, "SMM  Base: %08X\n", (UINT32)(mSmmAccess.SmramDesc[mSmmAccess.NumberRegions-1].PhysicalStart)));\r
+  DEBUG ((EFI_D_INFO, "SMM  Size: %08X\n", (UINT32)(mSmmAccess.SmramDesc[mSmmAccess.NumberRegions-1].PhysicalSize)));\r
+\r
+  mSmmAccess.TsegSize = (UINT8)(mSmmAccess.SmramDesc[mSmmAccess.NumberRegions-1].PhysicalSize);\r
+  //\r
+  // T Seg setting done in QPI RC\r
+  //\r
+\r
+  //\r
+  // Prior ReadyToBoot, lock CSEG\r
+  //\r
+  Status = EfiCreateEventReadyToBootEx(\r
+           TPL_NOTIFY,\r
+           SmmAccessOnBoot,\r
+           NULL,\r
+           &BootEvent );\r
+  ASSERT (!EFI_ERROR (Status));\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Open (\r
+  IN EFI_SMM_ACCESS2_PROTOCOL    *This\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine accepts a request to "open" a region of SMRAM.  The\r
+  region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.\r
+  The use of "open" means that the memory is visible from all boot-service\r
+  and SMM agents.\r
+\r
+Arguments:\r
+\r
+  This             -  Pointer to the SMM Access Interface.\r
+  DescriptorIndex  -  Region of SMRAM to Open.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS            -  The region was successfully opened.\r
+  EFI_DEVICE_ERROR       -  The region could not be opened because locked by\r
+                            chipset.\r
+  EFI_INVALID_PARAMETER  -  The descriptor index was out of bounds.\r
+\r
+--*/\r
+{\r
+  SMM_ACCESS_PRIVATE_DATA *SmmAccess;\r
+\r
+  SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  if (mSmmAccess.SMMRegionState & EFI_SMRAM_LOCKED) {\r
+    DEBUG ((EFI_D_ERROR, "Cannot open a locked SMRAM region\n"));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Open TSEG\r
+  //\r
+  if (!QNCOpenSmramRegion ()) {\r
+    mSmmAccess.SMMRegionState |= EFI_SMRAM_LOCKED;\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  mSmmAccess.SMMRegionState &= ~(EFI_SMRAM_CLOSED | EFI_ALLOCATED);\r
+  SyncRegionState2SmramDesc(FALSE, (UINT64)(UINTN)(~(EFI_SMRAM_CLOSED | EFI_ALLOCATED)));\r
+  mSmmAccess.SMMRegionState |= EFI_SMRAM_OPEN;\r
+  SyncRegionState2SmramDesc(TRUE, EFI_SMRAM_OPEN);\r
+  SmmAccess->SmmAccess.OpenState = TRUE;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Close (\r
+  IN EFI_SMM_ACCESS2_PROTOCOL *This\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine accepts a request to "close" a region of SMRAM.  This is valid for\r
+  compatible SMRAM region.\r
+\r
+Arguments:\r
+\r
+  This             -  Pointer to the SMM Access Interface.\r
+  DescriptorIndex  -  Region of SMRAM to Close.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS            -  The region was successfully closed.\r
+  EFI_DEVICE_ERROR       -  The region could not be closed because locked by\r
+                            chipset.\r
+  EFI_INVALID_PARAMETER  -  The descriptor index was out of bounds.\r
+\r
+--*/\r
+{\r
+  SMM_ACCESS_PRIVATE_DATA *SmmAccess;\r
+  BOOLEAN                 OpenState;\r
+  UINTN                   Index;\r
+\r
+  SmmAccess     = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  if (mSmmAccess.SMMRegionState & EFI_SMRAM_LOCKED) {\r
+    //\r
+    // Cannot close a "locked" region\r
+    //\r
+    DEBUG ((EFI_D_WARN, "Cannot close the locked SMRAM Region\n"));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  if (mSmmAccess.SMMRegionState & EFI_SMRAM_CLOSED) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Close TSEG\r
+  //\r
+  if (!QNCCloseSmramRegion ()) {\r
+    mSmmAccess.SMMRegionState |= EFI_SMRAM_LOCKED;\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  mSmmAccess.SMMRegionState &= ~EFI_SMRAM_OPEN;\r
+  SyncRegionState2SmramDesc(FALSE, (UINT64)(UINTN)(~EFI_SMRAM_OPEN));\r
+  mSmmAccess.SMMRegionState |= (EFI_SMRAM_CLOSED | EFI_ALLOCATED);\r
+  SyncRegionState2SmramDesc(TRUE, EFI_SMRAM_CLOSED | EFI_ALLOCATED);\r
+\r
+  //\r
+  // Find out if any regions are still open\r
+  //\r
+  OpenState = FALSE;\r
+  for (Index = 0; Index < mSmmAccess.NumberRegions; Index++) {\r
+    if ((SmmAccess->SmramDesc[Index].RegionState & EFI_SMRAM_OPEN) == EFI_SMRAM_OPEN) {\r
+      OpenState = TRUE;\r
+    }\r
+  }\r
+\r
+  SmmAccess->SmmAccess.OpenState = OpenState;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Lock (\r
+  IN EFI_SMM_ACCESS2_PROTOCOL   *This\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine accepts a request to "lock" SMRAM.  The\r
+  region could be legacy AB or TSEG near top of physical memory.\r
+  The use of "lock" means that the memory can no longer be opened\r
+  to BS state..\r
+\r
+Arguments:\r
+\r
+  This             -  Pointer to the SMM Access Interface.\r
+  DescriptorIndex  -  Region of SMRAM to Lock.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS            -  The region was successfully locked.\r
+  EFI_DEVICE_ERROR       -  The region could not be locked because at least\r
+                            one range is still open.\r
+  EFI_INVALID_PARAMETER  -  The descriptor index was out of bounds.\r
+\r
+--*/\r
+{\r
+  SMM_ACCESS_PRIVATE_DATA *SmmAccess;\r
+\r
+  SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  if (SmmAccess->SmmAccess.OpenState) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  mSmmAccess.SMMRegionState |= EFI_SMRAM_LOCKED;\r
+  SyncRegionState2SmramDesc(TRUE, EFI_SMRAM_LOCKED);\r
+  SmmAccess->SmmAccess.LockState                     = TRUE;\r
+\r
+  //\r
+  // Lock TSEG\r
+  //\r
+  QNCLockSmramRegion ();\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+GetCapabilities (\r
+  IN CONST  EFI_SMM_ACCESS2_PROTOCOL *This,\r
+  IN OUT UINTN                       *SmramMapSize,\r
+  IN OUT EFI_SMRAM_DESCRIPTOR        *SmramMap\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine services a user request to discover the SMRAM\r
+  capabilities of this platform.  This will report the possible\r
+  ranges that are possible for SMRAM access, based upon the\r
+  memory controller capabilities.\r
+\r
+Arguments:\r
+\r
+  This          -  Pointer to the SMRAM Access Interface.\r
+  SmramMapSize  -  Pointer to the variable containing size of the\r
+                   buffer to contain the description information.\r
+  SmramMap      -  Buffer containing the data describing the Smram\r
+                   region descriptors.\r
+Returns:\r
+\r
+  EFI_BUFFER_TOO_SMALL  -  The user did not provide a sufficient buffer.\r
+  EFI_SUCCESS           -  The user provided a sufficiently-sized buffer.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                Status;\r
+  SMM_ACCESS_PRIVATE_DATA  *SmmAccess;\r
+  UINTN                     BufferSize;\r
+\r
+  SmmAccess           = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);\r
+  BufferSize          = SmmAccess->NumberRegions * sizeof (EFI_SMRAM_DESCRIPTOR);\r
+\r
+  if (*SmramMapSize < BufferSize) {\r
+    Status = EFI_BUFFER_TOO_SMALL;\r
+  } else {\r
+    CopyMem (SmramMap, SmmAccess->SmramDesc, *SmramMapSize);\r
+    Status = EFI_SUCCESS;\r
+  }\r
+  *SmramMapSize = BufferSize;\r
+\r
+  return Status;\r
+}\r
+\r
+VOID\r
+SmmAccessOnBoot (\r
+  IN EFI_EVENT                          Event,\r
+  IN VOID                               *Context\r
+)\r
+{\r
+\r
+}\r
+VOID\r
+SyncRegionState2SmramDesc(\r
+  IN BOOLEAN  OrAnd,\r
+  IN UINT64   Value\r
+  )\r
+{\r
+  UINT32 Index;\r
+\r
+  for (Index = 0; Index < mSmmAccess.NumberRegions; Index++) {\r
+    if (OrAnd) {\r
+      mSmmAccess.SmramDesc[Index].RegionState |= Value;\r
+    } else {\r
+      mSmmAccess.SmramDesc[Index].RegionState &= Value;\r
+    }\r
+  }\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccessDriver.h b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccessDriver.h
new file mode 100644 (file)
index 0000000..26db976
--- /dev/null
@@ -0,0 +1,235 @@
+/** @file\r
+Header file for SMM Access Driver.\r
+\r
+This file includes package header files, library classes and protocol, PPI & GUID definitions.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#ifndef _SMM_ACCESS_DRIVER_H\r
+#define _SMM_ACCESS_DRIVER_H\r
+\r
+#include <PiDxe.h>\r
+#include <IndustryStandard/Pci.h>\r
+\r
+#include <Library/HobLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+//\r
+// Driver Consumed Protocol Prototypes\r
+//\r
+#include <Protocol/PciRootBridgeIo.h>\r
+\r
+//\r
+// Driver Consumed GUID Prototypes\r
+//\r
+#include <Guid/SmramMemoryReserve.h>\r
+\r
+//\r
+// Driver produced protocol\r
+//\r
+#include <Protocol/SmmAccess2.h>\r
+\r
+#include <Library/QNCSmmLib.h>\r
+#include <QNCAccess.h>\r
+\r
+#define MAX_CPU_SOCKET      1\r
+#define MAX_SMRAM_RANGES    4\r
+\r
+//\r
+// Private data structure\r
+//\r
+#define  SMM_ACCESS_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('i', 's', 'm', 'a')\r
+\r
+typedef struct {\r
+  UINTN                            Signature;\r
+  EFI_HANDLE                       Handle;\r
+  EFI_SMM_ACCESS2_PROTOCOL          SmmAccess;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo;\r
+  UINTN                            NumberRegions;\r
+  EFI_SMRAM_DESCRIPTOR             SmramDesc[MAX_SMRAM_RANGES];\r
+  UINT8                            TsegSize;\r
+  UINT8                            MaxBusNumber;\r
+  UINT8                            SocketPopulated[MAX_CPU_SOCKET];\r
+  UINT64                           SMMRegionState;\r
+  UINT8                            ActualNLIioBusNumber;\r
+} SMM_ACCESS_PRIVATE_DATA;\r
+\r
+\r
+#define SMM_ACCESS_PRIVATE_DATA_FROM_THIS(a) \\r
+  CR ( \\r
+  a, \\r
+  SMM_ACCESS_PRIVATE_DATA, \\r
+  SmmAccess, \\r
+  SMM_ACCESS_PRIVATE_DATA_SIGNATURE \\r
+  )\r
+\r
+\r
+//\r
+// Prototypes\r
+// Driver model protocol interface\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+SmmAccessDriverEntryPoint (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This is the standard EFI driver point that detects\r
+  whether there is an proper chipset in the system\r
+  and if so, installs an SMM Access Protocol.\r
+\r
+Arguments:\r
+\r
+  ImageHandle  -  Handle for the image of this driver.\r
+  SystemTable  -  Pointer to the EFI System Table.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS      -  Protocol successfully started and installed.\r
+  EFI_UNSUPPORTED  -  Protocol can't be started.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Open (\r
+  IN EFI_SMM_ACCESS2_PROTOCOL *This\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine accepts a request to "open" a region of SMRAM.  The\r
+  region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.\r
+  The use of "open" means that the memory is visible from all boot-service\r
+  and SMM agents.\r
+\r
+Arguments:\r
+\r
+  This             -  Pointer to the SMM Access Interface.\r
+  DescriptorIndex  -  Region of SMRAM to Open.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS            -  The region was successfully opened.\r
+  EFI_DEVICE_ERROR       -  The region could not be opened because locked by\r
+                            chipset.\r
+  EFI_INVALID_PARAMETER  -  The descriptor index was out of bounds.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Close (\r
+  IN EFI_SMM_ACCESS2_PROTOCOL *This\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine accepts a request to "close" a region of SMRAM.  This is valid for\r
+  compatible SMRAM region.\r
+\r
+Arguments:\r
+\r
+  This             -  Pointer to the SMM Access Interface.\r
+  DescriptorIndex  -  Region of SMRAM to Close.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS            -  The region was successfully closed.\r
+  EFI_DEVICE_ERROR       -  The region could not be closed because locked by\r
+                            chipset.\r
+  EFI_INVALID_PARAMETER  -  The descriptor index was out of bounds.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Lock (\r
+  IN EFI_SMM_ACCESS2_PROTOCOL *This\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine accepts a request to "lock" SMRAM.  The\r
+  region could be legacy AB or TSEG near top of physical memory.\r
+  The use of "lock" means that the memory can no longer be opened\r
+  to BS state..\r
+\r
+Arguments:\r
+\r
+  This             -  Pointer to the SMM Access Interface.\r
+  DescriptorIndex  -  Region of SMRAM to Lock.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS            -  The region was successfully locked.\r
+  EFI_DEVICE_ERROR       -  The region could not be locked because at least\r
+                            one range is still open.\r
+  EFI_INVALID_PARAMETER  -  The descriptor index was out of bounds.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+GetCapabilities (\r
+  IN CONST EFI_SMM_ACCESS2_PROTOCOL     *This,\r
+  IN OUT UINTN                   *SmramMapSize,\r
+  IN OUT EFI_SMRAM_DESCRIPTOR    *SmramMap\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine services a user request to discover the SMRAM\r
+  capabilities of this platform.  This will report the possible\r
+  ranges that are possible for SMRAM access, based upon the\r
+  memory controller capabilities.\r
+\r
+Arguments:\r
+\r
+  This          -  Pointer to the SMRAM Access Interface.\r
+  SmramMapSize  -  Pointer to the variable containing size of the\r
+                   buffer to contain the description information.\r
+  SmramMap      -  Buffer containing the data describing the Smram\r
+                   region descriptors.\r
+\r
+Returns:\r
+\r
+  EFI_BUFFER_TOO_SMALL  -  The user did not provide a sufficient buffer.\r
+  EFI_SUCCESS           -  The user provided a sufficiently-sized buffer.\r
+\r
+--*/\r
+;\r
+VOID\r
+SyncRegionState2SmramDesc(\r
+  IN BOOLEAN  OrAnd,\r
+  IN UINT64    Value\r
+  );\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmControlDxe/SmmControlDriver.c b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmControlDxe/SmmControlDriver.c
new file mode 100644 (file)
index 0000000..72ba797
--- /dev/null
@@ -0,0 +1,366 @@
+/** @file\r
+This module produces the SMM COntrol2 Protocol for QNC\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <Protocol/SmmControl2.h>\r
+#include <IndustryStandard/Pci.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PciLib.h>\r
+#include <IntelQNCDxe.h>\r
+#include <Library/QNCAccessLib.h>\r
+#include <Uefi/UefiBaseType.h>\r
+\r
+#define EFI_INTERNAL_POINTER  0x00000004\r
+\r
+extern EFI_GUID gEfiEventVirtualAddressChangeGuid;\r
+\r
+/**\r
+  Generates an SMI using the parameters passed in.\r
+\r
+  @param  This                A pointer to an instance of\r
+                              EFI_SMM_CONTROL2_PROTOCOL\r
+  @param  ArgumentBuffer      The argument buffer\r
+  @param  ArgumentBufferSize  The size of the argument buffer\r
+  @param  Periodic            TRUE to indicate a periodical SMI\r
+  @param  ActivationInterval  Interval of the periodical SMI\r
+\r
+  @retval EFI_INVALID_PARAMETER Periodic is TRUE or ArgumentBufferSize > 1\r
+  @return Return value from SmmTrigger().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Activate (\r
+  IN CONST EFI_SMM_CONTROL2_PROTOCOL     *This,\r
+  IN OUT  UINT8                          *CommandPort       OPTIONAL,\r
+  IN OUT  UINT8                          *DataPort          OPTIONAL,\r
+  IN      BOOLEAN                        Periodic           OPTIONAL,\r
+  IN      EFI_SMM_PERIOD                 ActivationInterval OPTIONAL\r
+                  );\r
+\r
+/**\r
+  Clears an SMI.\r
+\r
+  @param  This      Pointer to an instance of EFI_SMM_CONTROL2_PROTOCOL\r
+  @param  Periodic  TRUE to indicate a periodical SMI\r
+\r
+  @return Return value from SmmClear()\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Deactivate (\r
+  IN CONST     EFI_SMM_CONTROL2_PROTOCOL  *This,\r
+  IN      BOOLEAN                         Periodic OPTIONAL\r
+  );\r
+\r
+///\r
+/// Handle for the SMM Control2 Protocol\r
+///\r
+EFI_HANDLE  mSmmControl2Handle = NULL;\r
+\r
+///\r
+/// SMM COntrol2 Protocol instance\r
+///\r
+EFI_SMM_CONTROL2_PROTOCOL mSmmControl2 = {\r
+  Activate,\r
+  Deactivate,\r
+  0\r
+};\r
+\r
+VOID\r
+EFIAPI\r
+SmmControlVirtualddressChangeEvent (\r
+  IN EFI_EVENT                  Event,\r
+  IN VOID                       *Context\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Fixup internal data pointers so that the services can be called in virtual mode.\r
+\r
+Arguments:\r
+\r
+  Event                         The event registered.\r
+  Context                       Event context.\r
+\r
+Returns:\r
+\r
+  None.\r
+\r
+--*/\r
+{\r
+  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSmmControl2.Trigger));\r
+  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSmmControl2.Clear));\r
+}\r
+\r
+/**\r
+  Clear SMI related chipset status and re-enable SMI by setting the EOS bit.\r
+\r
+  @retval EFI_SUCCESS The requested operation has been carried out successfully\r
+  @retval EFI_DEVICE_ERROR  The EOS bit could not be set.\r
+\r
+**/\r
+EFI_STATUS\r
+SmmClear (\r
+  VOID\r
+  )\r
+{\r
+  UINT16                       PM1BLK_Base;\r
+  UINT16                       GPE0BLK_Base;\r
+\r
+  //\r
+  // Get PM1BLK_Base & GPE0BLK_Base\r
+  //\r
+  PM1BLK_Base  = PcdGet16 (PcdPm1blkIoBaseAddress);\r
+  GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress);\r
+\r
+  //\r
+  // Clear the Power Button Override Status Bit, it gates EOS from being set.\r
+  // In QuarkNcSocId - Bit is read only. Handled by external SMC, do nothing.\r
+  //\r
+\r
+  //\r
+  // Clear the APM SMI Status Bit\r
+  //\r
+  IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_APM);\r
+\r
+  //\r
+  // Set the EOS Bit\r
+  //\r
+  IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Generates an SMI using the parameters passed in.\r
+\r
+  @param  This                A pointer to an instance of\r
+                              EFI_SMM_CONTROL_PROTOCOL\r
+  @param  ArgumentBuffer      The argument buffer\r
+  @param  ArgumentBufferSize  The size of the argument buffer\r
+  @param  Periodic            TRUE to indicate a periodical SMI\r
+  @param  ActivationInterval  Interval of the periodical SMI\r
+\r
+  @retval EFI_INVALID_PARAMETER Periodic is TRUE or ArgumentBufferSize > 1\r
+  @retval EFI_SUCCESS            SMI generated\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Activate (\r
+  IN CONST EFI_SMM_CONTROL2_PROTOCOL     *This,\r
+  IN OUT  UINT8                          *CommandPort       OPTIONAL,\r
+  IN OUT  UINT8                          *DataPort          OPTIONAL,\r
+  IN      BOOLEAN                        Periodic           OPTIONAL,\r
+  IN      EFI_SMM_PERIOD                 ActivationInterval OPTIONAL\r
+  )\r
+{\r
+  UINT16        GPE0BLK_Base;\r
+  UINT32        NewValue;\r
+\r
+  //\r
+  // Get GPE0BLK_Base\r
+  //\r
+  GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress);\r
+\r
+  if (Periodic) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Clear any pending the APM SMI\r
+  //\r
+  if (EFI_ERROR (SmmClear())) {\r
+    return EFI_DEVICE_ERROR;\r
+    }\r
+\r
+  //\r
+  // Enable the APMC SMI\r
+  //\r
+  IoOr32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIE, B_QNC_GPE0BLK_SMIE_APM);\r
+\r
+  //\r
+  // Enable SMI globally\r
+  //\r
+  NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);\r
+  NewValue |= SMI_EN;\r
+  QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);\r
+\r
+\r
+  //\r
+  // Set APMC_STS\r
+  //\r
+  if (DataPort == NULL) {\r
+    IoWrite8 (PcdGet16 (PcdSmmDataPort), 0xFF);\r
+  } else {\r
+    IoWrite8 (PcdGet16 (PcdSmmDataPort), *DataPort);\r
+  }\r
+\r
+  //\r
+  // Generate the APMC SMI\r
+  //\r
+  if (CommandPort == NULL) {\r
+    IoWrite8 (PcdGet16 (PcdSmmActivationPort), 0xFF);\r
+  } else {\r
+    IoWrite8 (PcdGet16 (PcdSmmActivationPort), *CommandPort);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Clears an SMI.\r
+\r
+  @param  This      Pointer to an instance of EFI_SMM_CONTROL_PROTOCOL\r
+  @param  Periodic  TRUE to indicate a periodical SMI\r
+\r
+  @return Return value from SmmClear()\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Deactivate (\r
+  IN CONST EFI_SMM_CONTROL2_PROTOCOL     *This,\r
+  IN      BOOLEAN                   Periodic\r
+  )\r
+{\r
+  if (Periodic) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  return SmmClear();\r
+}\r
+\r
+/**\r
+  This is the constructor for the SMM Control protocol.\r
+\r
+  This function installs EFI_SMM_CONTROL2_PROTOCOL.\r
+\r
+  @param  ImageHandle Handle for the image of this driver\r
+  @param  SystemTable Pointer to the EFI System Table\r
+\r
+  @retval EFI_UNSUPPORTED There's no Intel ICH on this platform\r
+  @return The status returned from InstallProtocolInterface().\r
+\r
+--*/\r
+EFI_STATUS\r
+SmmControl2Init (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  EFI_EVENT   Event;\r
+  UINT16      PM1BLK_Base;\r
+  UINT16      GPE0BLK_Base;\r
+  BOOLEAN     SciEn;\r
+  UINT32      NewValue;\r
+\r
+  //\r
+  // Get PM1BLK_Base & GPE0BLK_Base\r
+  //\r
+  PM1BLK_Base  = PcdGet16 (PcdPm1blkIoBaseAddress);\r
+  GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress);\r
+\r
+  //\r
+  // Install our protocol interfaces on the device's handle\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &mSmmControl2Handle,\r
+                  &gEfiSmmControl2ProtocolGuid,  &mSmmControl2,\r
+                  NULL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Determine whether an ACPI OS is present (via the SCI_EN bit)\r
+  //\r
+  SciEn = (BOOLEAN)((IoRead16 (PM1BLK_Base + R_QNC_PM1BLK_PM1C) & B_QNC_PM1BLK_PM1C_SCIEN) != 0);\r
+  if (!SciEn) {\r
+    //\r
+    // Clear any SMIs that double as SCIs (when SCI_EN==0)\r
+    //\r
+    IoWrite16 ((PM1BLK_Base + R_QNC_PM1BLK_PM1S), B_QNC_PM1BLK_PM1S_ALL);\r
+    IoWrite16 ((PM1BLK_Base + R_QNC_PM1BLK_PM1E), 0x00000000);\r
+    IoWrite32 ((PM1BLK_Base + R_QNC_PM1BLK_PM1C),  0x00000000);\r
+    IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_GPE0S), B_QNC_GPE0BLK_GPE0S_ALL);\r
+    IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_GPE0E), 0x00000000);\r
+  }\r
+\r
+  //\r
+  // Clear and disable all SMIs that are unaffected by SCI_EN\r
+  // Set EOS\r
+  //\r
+  IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIE), 0x00000000);\r
+  IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), (B_QNC_GPE0BLK_SMIS_EOS + B_QNC_GPE0BLK_SMIS_ALL));\r
+\r
+  //\r
+  // Enable SMI globally\r
+  //\r
+  NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);\r
+  NewValue |= SMI_EN;\r
+  QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);\r
+\r
+  //\r
+  // Make sure to write this register last -- EOS re-enables SMIs for the QNC\r
+  //\r
+  IoAndThenOr32 (\r
+    GPE0BLK_Base + R_QNC_GPE0BLK_SMIE,\r
+    (UINT32)(~B_QNC_GPE0BLK_SMIE_ALL),\r
+    B_QNC_GPE0BLK_SMIE_APM\r
+    );\r
+\r
+  //\r
+  // Make sure EOS bit cleared\r
+  //\r
+  DEBUG_CODE_BEGIN ();\r
+  if (IoRead32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIS) & B_QNC_GPE0BLK_SMIS_EOS) {\r
+    DEBUG ((\r
+      EFI_D_ERROR,\r
+      "******************************************************************************\n"\r
+      "BIG ERROR: SmmControl constructor couldn't properly initialize the ACPI table.\n"\r
+      "           SmmControl->Clear will probably hang.                              \n"\r
+      "              NOTE: SCI_EN = %d                                               \n"\r
+      "******************************************************************************\n",\r
+      SciEn\r
+      ));\r
+\r
+    //\r
+    // If we want the system to stop, then keep the ASSERT(FALSE).\r
+    // Otherwise, comment it out.\r
+    //\r
+    ASSERT (FALSE);\r
+  }\r
+  DEBUG_CODE_END ();\r
+\r
+  Status = gBS->CreateEventEx (\r
+                EVT_NOTIFY_SIGNAL,\r
+                TPL_NOTIFY,\r
+                SmmControlVirtualddressChangeEvent,\r
+                NULL,\r
+                &gEfiEventVirtualAddressChangeGuid,\r
+                &Event\r
+                );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmControlDxe/SmmControlDxe.inf b/QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmControlDxe/SmmControlDxe.inf
new file mode 100644 (file)
index 0000000..e498463
--- /dev/null
@@ -0,0 +1,61 @@
+## @file\r
+# QNC SmmControl driver to install EFI_SMM_CONTROL_PROTOCOL.\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = SmmControlDxe\r
+  FILE_GUID                      = A03A9429-C570-4ef9-9E00-C7A673976E5F\r
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = SmmControl2Init\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources]\r
+  SmmControlDriver.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  UefiDriverEntryPoint\r
+  DebugLib\r
+  UefiBootServicesTableLib\r
+  UefiRuntimeServicesTableLib\r
+  PcdLib\r
+  IoLib\r
+  PciLib\r
+  QNCAccessLib\r
+\r
+[Protocols]\r
+  gEfiSmmControl2ProtocolGuid             # PROTOCOL ALWAYS_PRODUCED\r
+\r
+[Pcd]\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmDataPort\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmActivationPort\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdGbaIoBaseAddress\r
+\r
+[Guids]\r
+  gEfiEventVirtualAddressChangeGuid\r
+\r
+[Depex]\r
+  TRUE\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/CommonHeader.h b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/CommonHeader.h
new file mode 100644 (file)
index 0000000..3a5b152
--- /dev/null
@@ -0,0 +1,51 @@
+/** @file\r
+Common header file shared by all source files.\r
+\r
+This file includes package header files, library classes and protocol, PPI & GUID definitions.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#ifndef __COMMON_HEADER_H_\r
+#define __COMMON_HEADER_H_\r
+\r
+\r
+\r
+#include <PiSmm.h>\r
+#include <IntelQNCDxe.h>\r
+\r
+#include <Protocol/SmmUsbDispatch2.h>\r
+#include <Protocol/SmmPeriodicTimerDispatch2.h>\r
+#include <Protocol/SmmIchnDispatch2.h>\r
+#include <Protocol/SmmPowerButtonDispatch2.h>\r
+#include <Protocol/SmmGpiDispatch2.h>\r
+#include <Protocol/SmmSxDispatch2.h>\r
+#include <Protocol/SmmSwDispatch2.h>\r
+#include <Protocol/SmmIoTrapDispatch2.h>\r
+#include <Protocol/SmmCpu.h>\r
+\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/SmmServicesTableLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/PciLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/S3IoLib.h>\r
+#include <Library/QNCAccessLib.h>\r
+\r
+#include <Uefi/UefiBaseType.h>\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmGpi.c b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmGpi.c
new file mode 100644 (file)
index 0000000..eb9c6df
--- /dev/null
@@ -0,0 +1,38 @@
+/** @file\r
+File to contain all the hardware specific stuff for the Smm Gpi dispatch protocol.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+#include "QNCSmmHelpers.h"\r
+\r
+CONST QNC_SMM_SOURCE_DESC GPI_SOURCE_DESC = {\r
+  QNC_SMM_NO_FLAGS,\r
+  {\r
+    {\r
+      {GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIE}}, S_QNC_GPE0BLK_SMIE, N_QNC_GPE0BLK_SMIE_GPIO\r
+    },\r
+    NULL_BIT_DESC_INITIALIZER\r
+  },\r
+  {\r
+    {\r
+      {GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIS}}, S_QNC_GPE0BLK_SMIS, N_QNC_GPE0BLK_SMIS_GPIO\r
+  }\r
+  }\r
+};\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmHelpers.c b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmHelpers.c
new file mode 100644 (file)
index 0000000..9784359
--- /dev/null
@@ -0,0 +1,555 @@
+/** @file\r
+\r
+This driver is responsible for the registration of child drivers\r
+and the abstraction of the QNC SMI sources.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+#include "QNCSmmHelpers.h"\r
+\r
+//\r
+// Help handle porting bit shifts to IA-64.\r
+//\r
+#define BIT_ZERO 0x00000001\r
+\r
+\r
+VOID\r
+QNCSmmPublishDispatchProtocols(\r
+  VOID\r
+  )\r
+{\r
+  UINTN      Index;\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  // Install protocol interfaces.\r
+  //\r
+  for (Index = 0; Index < NUM_PROTOCOLS; Index++) {\r
+    Status = gSmst->SmmInstallProtocolInterface (\r
+                 &mPrivateData.InstallMultProtHandle,\r
+                      mPrivateData.Protocols[Index].Guid,\r
+                      EFI_NATIVE_INTERFACE,\r
+                      &mPrivateData.Protocols[Index].Protocols.Generic\r
+                 );\r
+\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+}\r
+\r
+EFI_STATUS\r
+QNCSmmInitHardware(\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Initialize bits that aren't necessarily related to an SMI source.\r
+\r
+Dependencies:\r
+\r
+  gSmst - SMM System Table; contains an entry for SMM CPU IO\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS.  Asserts, otherwise.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  // Clear all SMIs\r
+  //\r
+  QNCSmmClearSmi();\r
+\r
+  Status = QNCSmmEnableGlobalSmiBit ();\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Be *really* sure to clear all SMIs\r
+  //\r
+  QNCSmmClearSmi ();\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+QNCSmmEnableGlobalSmiBit (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Enables the QNC to generate SMIs. Note that no SMIs will be generated\r
+  if no SMI sources are enabled. Conversely, no enabled SMI source will\r
+  generate SMIs if SMIs are not globally enabled. This is the main\r
+  switchbox for SMI generation.\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS.\r
+  Asserts, otherwise.\r
+\r
+--*/\r
+{\r
+  UINT32        NewValue;\r
+\r
+  //\r
+  // Enable SMI globally\r
+  //\r
+  NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);\r
+  NewValue |= SMI_EN;\r
+  QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+QNCSmmClearSmi(\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Clears the SMI after all SMI source have been processed.\r
+  Note that this function will not work correctly (as it is\r
+  written) unless all SMI sources have been processed.\r
+  A revision of this function could manually clear all SMI\r
+  status bits to guarantee success.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS.\r
+  Asserts, otherwise.\r
+\r
+--*/\r
+{\r
+  BOOLEAN EosSet;\r
+  BOOLEAN SciEn;\r
+\r
+  UINT32 Pm1Cnt = 0;\r
+  UINT16 Pm1Sts = 0;\r
+  UINT32 Gpe0Sts = 0;\r
+  UINT32 SmiSts  = 0;\r
+\r
+  //\r
+  // Determine whether an ACPI OS is present (via the SCI_EN bit)\r
+  //\r
+  Pm1Cnt = IoRead32(PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);\r
+  SciEn = (BOOLEAN)((Pm1Cnt & B_QNC_PM1BLK_PM1C_SCIEN) == B_QNC_PM1BLK_PM1C_SCIEN);\r
+\r
+  if (SciEn == FALSE) {\r
+\r
+    //\r
+    // Clear any SMIs that double as SCIs (when SCI_EN==0)\r
+    //\r
+    Pm1Sts = (B_QNC_PM1BLK_PM1S_WAKE | B_QNC_PM1BLK_PM1S_PCIEWSTS | B_QNC_PM1BLK_PM1S_RTC | B_QNC_PM1BLK_PM1S_GLOB | B_QNC_PM1BLK_PM1S_TO);\r
+\r
+    Gpe0Sts = B_QNC_GPE0BLK_GPE0S_ALL;\r
+\r
+    IoOr16((PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1S), Pm1Sts);\r
+    IoOr32(((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0S), Gpe0Sts);\r
+  }\r
+\r
+  //\r
+  // Clear all SMIs that are unaffected by SCI_EN\r
+  //\r
+  SmiSts = IoRead32((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS);\r
+  SmiSts |= B_QNC_GPE0BLK_SMIS_ALL;\r
+  IoWrite32(((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS), SmiSts);\r
+\r
+  //\r
+  // Try to clear the EOS bit. ASSERT on an error\r
+  //\r
+  EosSet = QNCSmmSetAndCheckEos();\r
+  ASSERT (EosSet);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+QNCSmmSetAndCheckEos(\r
+  VOID\r
+  )\r
+{\r
+  //\r
+  // Reset the QNC to generate subsequent SMIs\r
+  //\r
+  IoOr32(((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS);\r
+    return TRUE;\r
+}\r
+\r
+BOOLEAN\r
+QNCSmmGetSciEn(\r
+  )\r
+{\r
+  BOOLEAN SciEn;\r
+  UINT32 Pm1Cnt;\r
+\r
+  //\r
+  // Determine whether an ACPI OS is present (via the SCI_EN bit)\r
+  //\r
+  Pm1Cnt = IoRead32(PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);\r
+\r
+  SciEn = (BOOLEAN)((Pm1Cnt & B_QNC_PM1BLK_PM1C_SCIEN) == B_QNC_PM1BLK_PM1C_SCIEN);\r
+\r
+  return SciEn;\r
+}\r
+\r
+//\r
+// These may or may not need to change w/ the QNC version; they're highly IA-32 dependent, though.\r
+//\r
+\r
+BOOLEAN\r
+ReadBitDesc (\r
+  CONST QNC_SMM_BIT_DESC  *BitDesc\r
+  )\r
+{\r
+  UINT64           Register;\r
+  UINT32           PciBus;\r
+  UINT32           PciDev;\r
+  UINT32           PciFun;\r
+  UINT32           PciReg;\r
+  BOOLEAN          BitWasOne;\r
+\r
+  ASSERT (BitDesc != NULL );\r
+  ASSERT (!IS_BIT_DESC_NULL( *BitDesc ) );\r
+\r
+  Register  = 0;\r
+  BitWasOne = FALSE;\r
+\r
+  switch (BitDesc->Reg.Type) {\r
+\r
+  case ACPI_ADDR_TYPE:\r
+    //\r
+    // Double check that we correctly read in the acpi base address\r
+    //\r
+    ASSERT ((PcdGet16 (PcdPm1blkIoBaseAddress) != 0x0) && ((PcdGet16 (PcdPm1blkIoBaseAddress) & 0x1) != 0x1) );\r
+\r
+    switch (BitDesc->SizeInBytes) {\r
+\r
+    case 0:\r
+      //\r
+      // Chances are that this field didn't get initialized.\r
+      // Check your assignments to bit descriptions.\r
+      //\r
+      ASSERT (FALSE );\r
+      break;\r
+\r
+      case 1:\r
+      Register = (UINT64) IoRead8 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi);\r
+        break;\r
+\r
+      case 2:\r
+      Register = (UINT64) IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi);\r
+        break;\r
+\r
+      case 4:\r
+      Register = (UINT64) IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi);\r
+        break;\r
+\r
+      default:\r
+        //\r
+        // Unsupported or invalid register size\r
+        //\r
+        ASSERT (FALSE );\r
+        break;\r
+      };\r
+\r
+    if ((Register & LShiftU64 (BIT_ZERO, BitDesc->Bit)) != 0) {\r
+        BitWasOne = TRUE;\r
+      } else {\r
+        BitWasOne = FALSE;\r
+      }\r
+    break;\r
+\r
+  case GPE_ADDR_TYPE:\r
+      //\r
+    // Double check that we correctly read in the gpe base address\r
+      //\r
+    ASSERT (((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) != 0x0) && (((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) & 0x1) != 0x1) );\r
+\r
+    switch (BitDesc->SizeInBytes) {\r
+\r
+    case 0:\r
+      //\r
+      // Chances are that this field didn't get initialized.\r
+      // Check your assignments to bit descriptions.\r
+      //\r
+      ASSERT (FALSE );\r
+      break;\r
+\r
+    case 1:\r
+      Register = (UINT64) IoRead8 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe);\r
+      break;\r
+\r
+    case 2:\r
+      Register = (UINT64) IoRead16 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe);\r
+      break;\r
+\r
+    case 4:\r
+      Register = (UINT64) IoRead32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe);\r
+      break;\r
+\r
+    default:\r
+      //\r
+      // Unsupported or invalid register size\r
+      //\r
+      ASSERT (FALSE );\r
+      break;\r
+    };\r
+\r
+    if ((Register & LShiftU64 (BIT_ZERO, BitDesc->Bit)) != 0) {\r
+        BitWasOne = TRUE;\r
+      } else {\r
+        BitWasOne = FALSE;\r
+      }\r
+    break;\r
+\r
+  case MEMORY_MAPPED_IO_ADDRESS_TYPE:\r
+    //\r
+    // Read the register, and it with the bit to read\r
+    //\r
+\r
+    //\r
+    // This code does not support reads greater then 64 bits\r
+    //\r
+    ASSERT (BitDesc->SizeInBytes <= 8);\r
+    CopyMem (&Register, BitDesc->Reg.Data.Mmio, BitDesc->SizeInBytes);\r
+    Register &= LShiftU64 (BIT0, BitDesc->Bit);\r
+    if (Register) {\r
+      BitWasOne = TRUE;\r
+    } else {\r
+      BitWasOne = FALSE;\r
+    }\r
+    break;\r
+\r
+  case PCI_ADDR_TYPE:\r
+    PciBus = BitDesc->Reg.Data.pci.Fields.Bus;\r
+    PciDev = BitDesc->Reg.Data.pci.Fields.Dev;\r
+    PciFun = BitDesc->Reg.Data.pci.Fields.Fnc;\r
+    PciReg = BitDesc->Reg.Data.pci.Fields.Reg;\r
+    switch (BitDesc->SizeInBytes) {\r
+\r
+    case 0:\r
+      //\r
+      // Chances are that this field didn't get initialized.\r
+      // Check your assignments to bit descriptions.\r
+      ASSERT (FALSE );\r
+      break;\r
+\r
+    case 1:\r
+      Register = (UINT64) PciRead8 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg));\r
+      break;\r
+\r
+    case 2:\r
+      Register = (UINT64) PciRead16 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg));\r
+      break;\r
+\r
+    case 4:\r
+      Register = (UINT64) PciRead32 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg));\r
+      break;\r
+\r
+    default:\r
+      //\r
+      // Unsupported or invalid register size\r
+      //\r
+      ASSERT (FALSE );\r
+      break;\r
+    };\r
+\r
+    if ((Register & LShiftU64 (BIT_ZERO, BitDesc->Bit)) != 0) {\r
+        BitWasOne = TRUE;\r
+    } else {\r
+      BitWasOne = FALSE;\r
+    }\r
+    break;\r
+\r
+  default:\r
+    //\r
+    // This address type is not yet implemented\r
+    //\r
+    ASSERT (FALSE );\r
+    break;\r
+  };\r
+\r
+  return BitWasOne;\r
+}\r
+\r
+VOID\r
+WriteBitDesc (\r
+  CONST QNC_SMM_BIT_DESC   *BitDesc,\r
+  CONST BOOLEAN           ValueToWrite\r
+  )\r
+{\r
+  UINT64           Register;\r
+  UINT64           AndVal;\r
+  UINT64           OrVal;\r
+  UINT32           PciBus;\r
+  UINT32           PciDev;\r
+  UINT32           PciFun;\r
+  UINT32           PciReg;\r
+\r
+  ASSERT (BitDesc != NULL);\r
+  ASSERT (!IS_BIT_DESC_NULL(*BitDesc));\r
+\r
+  AndVal = ~(BIT_ZERO << (BitDesc->Bit));\r
+  OrVal  = ((UINT32)ValueToWrite) << (BitDesc->Bit);\r
+\r
+  switch (BitDesc->Reg.Type) {\r
+\r
+  case ACPI_ADDR_TYPE:\r
+    //\r
+    // Double check that we correctly read in the acpi base address\r
+    //\r
+    ASSERT ((PcdGet16 (PcdPm1blkIoBaseAddress) != 0x0) && ((PcdGet16 (PcdPm1blkIoBaseAddress) & 0x1) != 0x1));\r
+\r
+    switch (BitDesc->SizeInBytes) {\r
+\r
+    case 0:\r
+      //\r
+      // Chances are that this field didn't get initialized.\r
+      // Check your assignments to bit descriptions.\r
+      //\r
+      ASSERT (FALSE );\r
+      break;\r
+\r
+    case 1:\r
+      IoAndThenOr8 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi, (UINT8)AndVal, (UINT8)OrVal);\r
+      break;\r
+\r
+    case 2:\r
+      IoAndThenOr16 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi, (UINT16)AndVal, (UINT16)OrVal);\r
+      break;\r
+\r
+    case 4:\r
+      IoAndThenOr32 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi, (UINT32)AndVal, (UINT32)OrVal);\r
+      break;\r
+\r
+    default:\r
+      //\r
+      // Unsupported or invalid register size\r
+      //\r
+      ASSERT (FALSE );\r
+      break;\r
+    };\r
+    break;\r
+\r
+  case GPE_ADDR_TYPE:\r
+    //\r
+    // Double check that we correctly read in the gpe base address\r
+    //\r
+    ASSERT (((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) != 0x0) && (((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) & 0x1) != 0x1));\r
+\r
+    switch (BitDesc->SizeInBytes) {\r
+\r
+    case 0:\r
+      //\r
+      // Chances are that this field didn't get initialized.\r
+      // Check your assignments to bit descriptions.\r
+      //\r
+      ASSERT (FALSE );\r
+      break;\r
+\r
+    case 1:\r
+      IoAndThenOr8 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe, (UINT8)AndVal, (UINT8)OrVal);\r
+      break;\r
+\r
+    case 2:\r
+      IoAndThenOr16 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe, (UINT16)AndVal, (UINT16)OrVal);\r
+      break;\r
+\r
+    case 4:\r
+      IoAndThenOr32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe, (UINT32)AndVal, (UINT32)OrVal);\r
+      break;\r
+\r
+    default:\r
+      //\r
+      // Unsupported or invalid register size\r
+      //\r
+      ASSERT (FALSE );\r
+      break;\r
+    };\r
+      break;\r
+\r
+  case MEMORY_MAPPED_IO_ADDRESS_TYPE:\r
+    //\r
+    // Read the register, or it with the bit to set, then write it back.\r
+    //\r
+\r
+    //\r
+    // This code does not support writes greater then 64 bits\r
+    //\r
+    ASSERT (BitDesc->SizeInBytes <= 8);\r
+    CopyMem (&Register, BitDesc->Reg.Data.Mmio, BitDesc->SizeInBytes);\r
+    Register &= AndVal;\r
+    Register |= OrVal;\r
+    CopyMem (BitDesc->Reg.Data.Mmio, &Register, BitDesc->SizeInBytes);\r
+    break;\r
+\r
+  case PCI_ADDR_TYPE:\r
+    PciBus = BitDesc->Reg.Data.pci.Fields.Bus;\r
+    PciDev = BitDesc->Reg.Data.pci.Fields.Dev;\r
+    PciFun = BitDesc->Reg.Data.pci.Fields.Fnc;\r
+    PciReg = BitDesc->Reg.Data.pci.Fields.Reg;\r
+    switch (BitDesc->SizeInBytes) {\r
+\r
+    case 0:\r
+      //\r
+      // Chances are that this field didn't get initialized -- check your assignments\r
+      // to bit descriptions.\r
+      //\r
+      ASSERT (FALSE );\r
+      break;\r
+\r
+    case 1:\r
+      PciAndThenOr8 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg), (UINT8) AndVal, (UINT8) OrVal);\r
+      break;\r
+\r
+    case 2:\r
+      PciAndThenOr16 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg), (UINT16) AndVal, (UINT16) OrVal);\r
+      break;\r
+\r
+    case 4:\r
+      PciAndThenOr32 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg), (UINT32) AndVal, (UINT32) OrVal);\r
+      break;\r
+\r
+    default:\r
+      //\r
+      // Unsupported or invalid register size\r
+      //\r
+      ASSERT (FALSE );\r
+      break;\r
+    };\r
+    break;\r
+\r
+    default:\r
+    //\r
+    // This address type is not yet implemented\r
+    //\r
+    ASSERT (FALSE );\r
+    break;\r
+  };\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmPeriodicTimer.c b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmPeriodicTimer.c
new file mode 100644 (file)
index 0000000..1d1030c
--- /dev/null
@@ -0,0 +1,430 @@
+/** @file\r
+File to contain all the hardware specific stuff for the Periodical Timer dispatch protocol.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+#include "QNCSmmHelpers.h"\r
+\r
+typedef enum {\r
+  PERIODIC_TIMER = 0,\r
+  NUM_TIMERS\r
+} SUPPORTED_TIMER;\r
+\r
+typedef struct _TIMER_INTERVAL\r
+{\r
+  UINT64    Interval;\r
+  UINT8     AssociatedTimer;\r
+} TIMER_INTERVAL;\r
+\r
+//\r
+// Time constants, in 100 nano-second units\r
+//\r
+#define TIME_64s   640000000 /* 64   s  */\r
+#define TIME_32s   320000000 /* 32   s  */\r
+#define TIME_16s   160000000 /* 16   s  */\r
+#define TIME_8s     80000000 /*  8   s  */\r
+#define TIME_64ms     640000 /* 64   ms */\r
+#define TIME_32ms     320000 /* 32   ms */\r
+#define TIME_16ms     160000 /* 16   ms */\r
+#define TIME_1_5ms     15000 /*  1.5 ms */\r
+\r
+// PMCW (GPE+28h) [2:0] Periodic SMI Rate selection\r
+// 000 1.5ms\r
+// 001 16ms\r
+// 010 32ms\r
+// 011 64ms\r
+// 100 8s\r
+// 101 16s\r
+// 110 32s\r
+// 111 64s\r
+\r
+typedef enum {\r
+  INDEX_TIME_1_5ms = 0,\r
+  INDEX_TIME_16ms,\r
+  INDEX_TIME_32ms,\r
+  INDEX_TIME_64ms,\r
+  INDEX_TIME_8s,\r
+  INDEX_TIME_16s,\r
+  INDEX_TIME_32s,\r
+  INDEX_TIME_64s,\r
+  INDEX_TIME_MAX\r
+} TIMER_INTERVAL_INDEX;\r
+\r
+TIMER_INTERVAL mSmmPeriodicTimerIntervals[INDEX_TIME_MAX] = {\r
+  {TIME_1_5ms, PERIODIC_TIMER},\r
+  {TIME_16ms,  PERIODIC_TIMER},\r
+  {TIME_32ms,  PERIODIC_TIMER},\r
+  {TIME_64ms,  PERIODIC_TIMER},\r
+  { TIME_8s,    PERIODIC_TIMER },\r
+  {TIME_16s,   PERIODIC_TIMER},\r
+  {TIME_32s,   PERIODIC_TIMER},\r
+  {TIME_64s,   PERIODIC_TIMER}\r
+};\r
+\r
+typedef struct _TIMER_INFO {\r
+  UINTN     NumChildren;      // number of children using this timer\r
+  UINT64    MinReqInterval;   // minimum interval required by children\r
+  UINTN     CurrentSetting;   // interval this timer is set at right now (index into interval table)\r
+} TIMER_INFO;\r
+\r
+TIMER_INFO  mTimers[NUM_TIMERS];\r
+\r
+QNC_SMM_SOURCE_DESC mTIMER_SOURCE_DESCS[NUM_TIMERS] = {\r
+  {\r
+    QNC_SMM_NO_FLAGS,\r
+    {\r
+      {{GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIE}}, S_QNC_GPE0BLK_SMIE, N_QNC_GPE0BLK_SMIE_SWT},\r
+      NULL_BIT_DESC_INITIALIZER\r
+    },\r
+    {\r
+      {{GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIS}}, S_QNC_GPE0BLK_SMIS, N_QNC_GPE0BLK_SMIS_SWT}\r
+    }\r
+  }\r
+};\r
+\r
+VOID\r
+QNCSmmPeriodicTimerProgramTimers(\r
+  VOID\r
+  );\r
+\r
+\r
+TIMER_INTERVAL *\r
+ContextToTimerInterval (\r
+  IN  QNC_SMM_CONTEXT     *RegisterContext\r
+  )\r
+{\r
+  UINTN loopvar;\r
+\r
+  //\r
+  // Determine which timer this child is using\r
+  //\r
+  for (loopvar = 0; loopvar < INDEX_TIME_MAX; loopvar++) {\r
+    if (((RegisterContext->PeriodicTimer.SmiTickInterval == 0) && (RegisterContext->PeriodicTimer.Period >= mSmmPeriodicTimerIntervals[loopvar].Interval)) ||\r
+        (RegisterContext->PeriodicTimer.SmiTickInterval == mSmmPeriodicTimerIntervals[loopvar].Interval)\r
+       ) {\r
+        return &mSmmPeriodicTimerIntervals[loopvar];\r
+      }\r
+  }\r
+\r
+  //\r
+  // If this assertion fires, then either:\r
+  //    (1) the context contains an invalid interval\r
+  //    (2) the timer interval table is corrupt\r
+  //\r
+  // ASSERT (FALSE);\r
+\r
+  return NULL;\r
+}\r
+\r
+EFI_STATUS\r
+MapPeriodicTimerToSrcDesc (\r
+  IN  QNC_SMM_CONTEXT             *RegisterContext,\r
+  OUT QNC_SMM_SOURCE_DESC         *SrcDesc\r
+  )\r
+{\r
+  TIMER_INTERVAL  *TimerInterval;\r
+\r
+  //\r
+  // Figure out which timer the child is requesting and\r
+  // send back the source description\r
+  //\r
+  TimerInterval = ContextToTimerInterval (RegisterContext);\r
+  if (TimerInterval == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  CopyMem (SrcDesc, &mTIMER_SOURCE_DESCS[TimerInterval->AssociatedTimer], sizeof (QNC_SMM_SOURCE_DESC));;\r
+\r
+  //\r
+  // Program the value of the interval into hardware\r
+  //\r
+  QNCSmmPeriodicTimerProgramTimers ();\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+PeriodicTimerGetContext (\r
+  IN  DATABASE_RECORD    *Record,\r
+  OUT QNC_SMM_CONTEXT    *HwContext\r
+  )\r
+{\r
+  TIMER_INTERVAL    *TimerInterval;\r
+\r
+  ASSERT (Record->ProtocolType == PeriodicTimerType);\r
+\r
+  TimerInterval = ContextToTimerInterval (&Record->ChildContext);\r
+\r
+  if (TimerInterval != NULL) {\r
+    //\r
+    // Ignore the hardware context. It's not required for this protocol.\r
+    // Instead, just increment the child's context.\r
+    // Update the elapsed time w/ the data from our tables\r
+    //\r
+    Record->CommBuffer.PeriodicTimer.ElapsedTime += TimerInterval->Interval;\r
+    *HwContext = Record->ChildContext;\r
+  }\r
+}\r
+\r
+BOOLEAN\r
+PeriodicTimerCmpContext (\r
+  IN QNC_SMM_CONTEXT     *HwContext,\r
+  IN QNC_SMM_CONTEXT     *ChildContext\r
+  )\r
+{\r
+  DATABASE_RECORD    *Record;\r
+\r
+  Record = DATABASE_RECORD_FROM_CONTEXT (ChildContext);\r
+\r
+  if (Record->CommBuffer.PeriodicTimer.ElapsedTime >= ChildContext->PeriodicTimer.Period) {\r
+    //\r
+    // This child should be dispatched\r
+    // The timer will be restarted on the "ClearSource" call.\r
+    //\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+VOID\r
+PeriodicTimerGetBuffer (\r
+  IN  DATABASE_RECORD     * Record\r
+  )\r
+{\r
+  //\r
+  // CommBuffer has been updated by PeriodicTimerGetContext, so return directly\r
+  //\r
+  return;\r
+}\r
+\r
+VOID\r
+QNCSmmPeriodicTimerProgramTimers (\r
+  VOID\r
+  )\r
+{\r
+  UINT32            GpePmcwValue;\r
+  SUPPORTED_TIMER   Timer;\r
+  DATABASE_RECORD   *RecordInDb;\r
+  LIST_ENTRY        *LinkInDb;\r
+  TIMER_INTERVAL    *TimerInterval;\r
+\r
+  //\r
+  // Find the minimum required interval for each timer\r
+  //\r
+  for (Timer = (SUPPORTED_TIMER)0; Timer < NUM_TIMERS; Timer++) {\r
+    mTimers[Timer].MinReqInterval = ~(UINT64)0x0;\r
+    mTimers[Timer].NumChildren = 0;\r
+  }\r
+  LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);\r
+  while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {\r
+    RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);\r
+    if (RecordInDb->ProtocolType == PeriodicTimerType) {\r
+      //\r
+      // This child is registerd with the PeriodicTimer protocol\r
+      //\r
+      TimerInterval = ContextToTimerInterval (&RecordInDb->ChildContext);\r
+\r
+      if(TimerInterval != NULL) {\r
+        Timer = (SUPPORTED_TIMER)((TIMER_INTERVAL *) (TimerInterval))->AssociatedTimer;\r
+\r
+        ASSERT (Timer >= 0 && Timer < NUM_TIMERS);\r
+\r
+        if (mTimers[Timer].MinReqInterval > RecordInDb->ChildContext.PeriodicTimer.SmiTickInterval) {\r
+          mTimers[Timer].MinReqInterval = RecordInDb->ChildContext.PeriodicTimer.SmiTickInterval;\r
+        }\r
+        mTimers[Timer].NumChildren++;\r
+      }\r
+    }\r
+    LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);\r
+  }\r
+\r
+  //\r
+  // Program the hardware\r
+  //\r
+  GpePmcwValue = 0;\r
+  if (mTimers[PERIODIC_TIMER].NumChildren > 0) {\r
+    switch (mTimers[PERIODIC_TIMER].MinReqInterval) {\r
+\r
+    case TIME_64s:\r
+      GpePmcwValue = INDEX_TIME_64s;\r
+      mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_64s;\r
+      break;\r
+\r
+    case TIME_32s:\r
+      GpePmcwValue = INDEX_TIME_32s;\r
+      mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_32s;\r
+      break;\r
+\r
+    case TIME_16s:\r
+      GpePmcwValue = INDEX_TIME_16s;\r
+      mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_16s;\r
+      break;\r
+\r
+    case TIME_8s:\r
+      GpePmcwValue = INDEX_TIME_8s;\r
+      mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_8s;\r
+      break;\r
+\r
+    case TIME_64ms:\r
+      GpePmcwValue = INDEX_TIME_64ms;\r
+      mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_64ms;\r
+      break;\r
+\r
+    case TIME_32ms:\r
+      GpePmcwValue = INDEX_TIME_32ms;\r
+      mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_32ms;\r
+      break;\r
+\r
+    case TIME_16ms:\r
+      GpePmcwValue = INDEX_TIME_16ms;\r
+      mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_16ms;\r
+      break;\r
+\r
+    case TIME_1_5ms:\r
+      GpePmcwValue = INDEX_TIME_1_5ms;\r
+      mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_1_5ms;\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+      break;\r
+    };\r
+\r
+    GpePmcwValue |= B_QNC_GPE0BLK_PMCW_PSE;\r
+\r
+    IoOr32(((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_PMCW), GpePmcwValue);\r
+\r
+    //\r
+    // Restart the timer here, just need to clear the SMI\r
+    //\r
+    QNCSmmClearSource (&mTIMER_SOURCE_DESCS[PERIODIC_TIMER]);\r
+  } else {\r
+    QNCSmmDisableSource (&mTIMER_SOURCE_DESCS[PERIODIC_TIMER]);\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+QNCSmmPeriodicTimerDispatchGetNextShorterInterval (\r
+  IN CONST EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL  *This,\r
+  IN OUT   UINT64                                    **SmiTickInterval\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This services returns the next SMI tick period that is supported by the chipset.\r
+  The order returned is from longest to shortest interval period.\r
+\r
+Arguments:\r
+\r
+  This              - Pointer to the EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL instance.\r
+  SmiTickInterval   - Pointer to pointer of the next shorter SMI interval period that is supported by the child.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS              - The service returned successfully.\r
+  EFI_INVALID_PARAMETER   - The parameter SmiTickInterval is invalid.\r
+\r
+--*/\r
+{\r
+  TIMER_INTERVAL    *IntervalPointer;\r
+\r
+  ASSERT (SmiTickInterval != NULL);\r
+\r
+  IntervalPointer = (TIMER_INTERVAL*)*SmiTickInterval;\r
+\r
+  if (IntervalPointer == NULL) {\r
+    //\r
+    // The first time child requesting an interval\r
+    //\r
+    IntervalPointer = &mSmmPeriodicTimerIntervals[0];\r
+  } else if (IntervalPointer == &mSmmPeriodicTimerIntervals[INDEX_TIME_MAX - 1]) {\r
+    //\r
+    // At end of the list\r
+    //\r
+    IntervalPointer = NULL;\r
+  } else {\r
+    if ((IntervalPointer >= &mSmmPeriodicTimerIntervals[0]) &&\r
+        (IntervalPointer < &mSmmPeriodicTimerIntervals[INDEX_TIME_MAX - 1])) {\r
+      //\r
+      // Get the next interval in the list\r
+      //\r
+      IntervalPointer++;\r
+    } else {\r
+      //\r
+      // Input is out of range\r
+      //\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+\r
+  if (IntervalPointer != NULL) {\r
+  *SmiTickInterval = &IntervalPointer->Interval;\r
+  } else {\r
+    *SmiTickInterval = NULL;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+QNCSmmPeriodicTimerClearSource (\r
+  IN QNC_SMM_SOURCE_DESC     *SrcDesc\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function is responsible for calculating and enabling any timers that are required\r
+  to dispatch messages to children. The SrcDesc argument isn't acutally used.\r
+\r
+Arguments:\r
+\r
+  SrcDesc - Pointer to the QNC_SMM_SOURCE_DESC instance.\r
+\r
+Returns:\r
+\r
+  None.\r
+\r
+--*/\r
+{\r
+  DATABASE_RECORD   *RecordInDb;\r
+  LIST_ENTRY        *LinkInDb;\r
+\r
+  QNCSmmPeriodicTimerProgramTimers ();\r
+\r
+  //\r
+  // Reset Elapsed time\r
+  //\r
+  LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);\r
+  while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {\r
+    RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);\r
+    if (RecordInDb->ProtocolType == PeriodicTimerType) {\r
+      //\r
+      // This child is registerd with the PeriodicTimer protocol and Callback\r
+      // has been invoked, so reset the ElapsedTime to 0\r
+      //\r
+      if (RecordInDb->CommBuffer.PeriodicTimer.ElapsedTime >= RecordInDb->ChildContext.PeriodicTimer.Period) {\r
+        RecordInDb->CommBuffer.PeriodicTimer.ElapsedTime = 0;\r
+      }\r
+    }\r
+    LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);\r
+  }\r
+}\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmQncn.c b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmQncn.c
new file mode 100644 (file)
index 0000000..53ee3ea
--- /dev/null
@@ -0,0 +1,217 @@
+/** @file\r
+File to contain all the hardware specific stuff for the Smm QNCn dispatch protocol.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+#include "QNCSmmHelpers.h"\r
+\r
+QNC_SMM_SOURCE_DESC QNCN_SOURCE_DESCS[NUM_ICHN_TYPES] = {\r
+\r
+  // QNCnMch (0)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnPme (1)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnRtcAlarm (2)\r
+  {\r
+    QNC_SMM_NO_FLAGS,\r
+    {\r
+      {{ACPI_ADDR_TYPE, {R_QNC_PM1BLK_PM1E}}, S_QNC_PM1BLK_PM1E, N_QNC_PM1BLK_PM1E_RTC},\r
+      NULL_BIT_DESC_INITIALIZER\r
+    },\r
+    {\r
+      {{ACPI_ADDR_TYPE, {R_QNC_PM1BLK_PM1S}}, S_QNC_PM1BLK_PM1S, N_QNC_PM1BLK_PM1S_RTC}\r
+    }\r
+  },\r
+\r
+  // QNCnRingIndicate (3)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnAc97Wake (4)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnSerialIrq (5)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnY2KRollover (6)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnTcoTimeout (7)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnOsTco (8)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnNmi (9)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnIntruderDetect (10)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnBiosWp (11)\r
+  {\r
+    QNC_SMM_CLEAR_WITH_ZERO,\r
+    {\r
+      {\r
+        {\r
+          PCI_ADDR_TYPE,\r
+          {\r
+            (\r
+              (PCI_BUS_NUMBER_QNC << 24) |\r
+              (PCI_DEVICE_NUMBER_QNC_LPC << 16) |\r
+              (PCI_FUNCTION_NUMBER_QNC_LPC << 8) |\r
+              R_QNC_LPC_BIOS_CNTL\r
+            )\r
+          }\r
+        },\r
+        S_QNC_LPC_BIOS_CNTL,\r
+        N_QNC_LPC_BIOS_CNTL_BLE\r
+      },\r
+      NULL_BIT_DESC_INITIALIZER\r
+    },\r
+    {\r
+      {\r
+        {\r
+          PCI_ADDR_TYPE,\r
+          {\r
+            (\r
+              (PCI_BUS_NUMBER_QNC << 24) |\r
+              (PCI_DEVICE_NUMBER_QNC_LPC << 16) |\r
+              (PCI_FUNCTION_NUMBER_QNC_LPC << 8) |\r
+              R_QNC_LPC_BIOS_CNTL\r
+            )\r
+          }\r
+        },\r
+        S_QNC_LPC_BIOS_CNTL,\r
+        N_QNC_LPC_BIOS_CNTL_BIOSWE\r
+      }\r
+    }\r
+  },\r
+\r
+  // QNCnMcSmi (12)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnPmeB0 (13)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnThrmSts (14)\r
+  {\r
+    QNC_SMM_SCI_EN_DEPENDENT,\r
+    {\r
+      {{GPE_ADDR_TYPE, {R_QNC_GPE0BLK_GPE0E}}, S_QNC_GPE0BLK_GPE0E, N_QNC_GPE0BLK_GPE0E_THRM},\r
+      NULL_BIT_DESC_INITIALIZER\r
+    },\r
+    {\r
+      {{GPE_ADDR_TYPE, {R_QNC_GPE0BLK_GPE0S}}, S_QNC_GPE0BLK_GPE0S, N_QNC_GPE0BLK_GPE0S_THRM}\r
+    }\r
+  },\r
+\r
+  // QNCnSmBus (15)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnIntelUsb2 (16)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnMonSmi7 (17)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnMonSmi6 (18)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnMonSmi5 (19)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnMonSmi4 (20)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnDevTrap13 (21)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnDevTrap12 (22)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnDevTrap11 (23)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnDevTrap10 (24)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnDevTrap9 (25)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnDevTrap8 (26)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnDevTrap7 (27)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnDevTrap6 (28)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnDevTrap5 (29)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnDevTrap3 (30)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnDevTrap2 (31)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnDevTrap1 (32)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnDevTrap0 (33)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnIoTrap3 (34)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnIoTrap2 (35)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnIoTrap1 (36)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnIoTrap0 (37)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnPciExpress (38)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnMonitor (39)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnSpi (40)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnQRT (41)\r
+  NULL_SOURCE_DESC_INITIALIZER,\r
+\r
+  // QNCnGpioUnlock (42)\r
+  NULL_SOURCE_DESC_INITIALIZER\r
+};\r
+\r
+VOID\r
+QNCSmmQNCnClearSource(\r
+  QNC_SMM_SOURCE_DESC   *SrcDesc\r
+  )\r
+{\r
+    QNCSmmClearSource (SrcDesc);\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmSw.c b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmSw.c
new file mode 100644 (file)
index 0000000..b4f56e8
--- /dev/null
@@ -0,0 +1,96 @@
+/** @file\r
+File to contain all the hardware specific stuff for the Smm Sw dispatch protocol.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+#include "QNCSmmHelpers.h"\r
+\r
+EFI_SMM_CPU_PROTOCOL  *mSmmCpu = NULL;\r
+\r
+CONST QNC_SMM_SOURCE_DESC SW_SOURCE_DESC = {\r
+  QNC_SMM_NO_FLAGS,\r
+  {\r
+    {\r
+      {GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIE}}, S_QNC_GPE0BLK_SMIE, N_QNC_GPE0BLK_SMIE_APM\r
+    },\r
+    NULL_BIT_DESC_INITIALIZER\r
+  },\r
+  {\r
+    {\r
+      {GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIS}}, S_QNC_GPE0BLK_SMIS, N_QNC_GPE0BLK_SMIS_APM\r
+    }\r
+  }\r
+};\r
+\r
+VOID\r
+SwGetContext(\r
+  IN  DATABASE_RECORD    *Record,\r
+  OUT QNC_SMM_CONTEXT    *Context\r
+  )\r
+{\r
+  Context->Sw.SwSmiInputValue = IoRead8 (R_APM_CNT);\r
+}\r
+\r
+BOOLEAN\r
+SwCmpContext (\r
+  IN QNC_SMM_CONTEXT     *Context1,\r
+  IN QNC_SMM_CONTEXT     *Context2\r
+  )\r
+{\r
+  return (BOOLEAN)( Context1->Sw.SwSmiInputValue == Context2->Sw.SwSmiInputValue );\r
+}\r
+\r
+VOID\r
+SwGetBuffer (\r
+  IN  DATABASE_RECORD     * Record\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  UINTN                      Index;\r
+  UINTN                      CpuIndex;\r
+  EFI_SMM_SAVE_STATE_IO_INFO IoState;\r
+\r
+  //\r
+  // Locate SMM CPU protocol to retrieve the CPU save state\r
+  //\r
+  if (mSmmCpu == NULL) {\r
+    Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **) &mSmmCpu);\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  //\r
+  // Find the CPU which generated the software SMI\r
+  //\r
+  CpuIndex = 0;\r
+  for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {\r
+    Status = mSmmCpu->ReadSaveState (\r
+                        mSmmCpu,\r
+                        sizeof (EFI_SMM_SAVE_STATE_IO_INFO),\r
+                        EFI_SMM_SAVE_STATE_REGISTER_IO,\r
+                        Index,\r
+                        &IoState\r
+                        );\r
+    if (!EFI_ERROR (Status) && (IoState.IoPort == R_APM_CNT)) {\r
+      CpuIndex = Index;\r
+      break;\r
+    }\r
+  }\r
+\r
+  Record->CommBuffer.Sw.SwSmiCpuIndex = CpuIndex;\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmSx.c b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmSx.c
new file mode 100644 (file)
index 0000000..9d0de36
--- /dev/null
@@ -0,0 +1,153 @@
+/** @file\r
+File to contain all the hardware specific stuff for the Smm Sx dispatch protocol.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+#include "QNCSmmHelpers.h"\r
+\r
+CONST QNC_SMM_SOURCE_DESC SX_SOURCE_DESC = {\r
+  QNC_SMM_NO_FLAGS,\r
+  {\r
+    {\r
+      {GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIE}}, S_QNC_GPE0BLK_SMIE, N_QNC_GPE0BLK_SMIE_SLP\r
+    },\r
+    NULL_BIT_DESC_INITIALIZER\r
+  },\r
+  {\r
+    {\r
+      {GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIS}}, S_QNC_GPE0BLK_SMIS, N_QNC_GPE0BLK_SMIS_SLP\r
+    }\r
+  }\r
+};\r
+\r
+VOID\r
+SxGetContext(\r
+  IN  DATABASE_RECORD    *Record,\r
+  OUT QNC_SMM_CONTEXT    *Context\r
+  )\r
+{\r
+  UINT32        Pm1Cnt;\r
+\r
+  Pm1Cnt = IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);\r
+\r
+  //\r
+  // By design, the context phase will always be ENTRY\r
+  //\r
+  Context->Sx.Phase = SxEntry;\r
+\r
+  //\r
+  // Map the PM1_CNT register's SLP_TYP bits to the context type\r
+  //\r
+  switch (Pm1Cnt & B_QNC_PM1BLK_PM1C_SLPTP) {\r
+\r
+  case V_S0:\r
+    Context->Sx.Type = SxS0;\r
+    break;\r
+\r
+  case V_S3:\r
+    Context->Sx.Type = SxS3;\r
+    break;\r
+\r
+  case V_S4:\r
+    Context->Sx.Type = SxS4;\r
+    break;\r
+\r
+  case V_S5:\r
+    Context->Sx.Type = SxS5;\r
+    break;\r
+\r
+  default:\r
+    ASSERT (FALSE);\r
+    break;\r
+  };\r
+}\r
+\r
+BOOLEAN\r
+SxCmpContext (\r
+  IN QNC_SMM_CONTEXT     *Context1,\r
+  IN QNC_SMM_CONTEXT     *Context2\r
+  )\r
+{\r
+  return (BOOLEAN)(Context1->Sx.Type == Context2->Sx.Type);\r
+}\r
+\r
+VOID\r
+QNCSmmSxGoToSleep(\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  When we get an SMI that indicates that we are transitioning to a sleep state,\r
+  we need to actually transition to that state.  We do this by disabling the\r
+  "SMI on sleep enable" feature, which generates an SMI when the operating system\r
+  tries to put the system to sleep, and then physically putting the system to sleep.\r
+\r
+Returns:\r
+\r
+  None.\r
+\r
+--*/\r
+{\r
+  UINT32        Pm1Cnt;\r
+\r
+  //\r
+  // Flush cache into memory before we go to sleep. It is necessary for S3 sleep\r
+  // because we may update memory in SMM Sx sleep handlers -- the updates are in cache now\r
+  //\r
+  AsmWbinvd();\r
+\r
+  //\r
+  // Disable SMIs\r
+  //\r
+  QNCSmmClearSource (&SX_SOURCE_DESC );\r
+  QNCSmmDisableSource (&SX_SOURCE_DESC);\r
+\r
+  //\r
+  // Clear Sleep Type Enable\r
+  //\r
+  IoAnd16 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIE, (UINT16)(~B_QNC_GPE0BLK_SMIE_SLP));\r
+\r
+  // clear sleep SMI status\r
+  IoAnd16 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS, (UINT16)(S_QNC_GPE0BLK_SMIS));\r
+\r
+  //\r
+  // Now that SMIs are disabled, write to the SLP_EN bit again to trigger the sleep\r
+  //\r
+  Pm1Cnt = IoOr32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, B_QNC_PM1BLK_PM1C_SLPEN);\r
+\r
+  //\r
+  // The system just went to sleep. If the sleep state was S1, then code execution will resume\r
+  // here when the system wakes up.\r
+  //\r
+  Pm1Cnt = IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);\r
+  if ((Pm1Cnt & B_QNC_PM1BLK_PM1C_SCIEN) == 0) {\r
+    //\r
+    // An ACPI OS isn't present, clear the sleep information\r
+    //\r
+    Pm1Cnt &= ~B_QNC_PM1BLK_PM1C_SLPTP;\r
+    Pm1Cnt |= V_S0;\r
+\r
+    IoWrite32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, Pm1Cnt);\r
+  }\r
+\r
+  QNCSmmClearSource (&SX_SOURCE_DESC);\r
+  QNCSmmEnableSource (&SX_SOURCE_DESC);\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmm.h b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmm.h
new file mode 100644 (file)
index 0000000..892294f
--- /dev/null
@@ -0,0 +1,871 @@
+/** @file\r
+Prototypes and defines for the QNC SMM Dispatcher.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef QNC_SMM_H\r
+#define QNC_SMM_H\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+#include "QNCSmmRegisters.h"\r
+\r
+extern EFI_HANDLE  mQNCSmmDispatcherImageHandle;\r
+\r
+\r
+//\r
+// /////////////////////////////////////////////////////////////////////////////\r
+// SUPPORTED PROTOCOLS\r
+//\r
+\r
+//\r
+// Define an enumeration for all the supported protocols\r
+//\r
+typedef enum {\r
+  // UsbType,    DELETE:on QuarkNcSocId, there is no usb smi supported\r
+  SxType,\r
+  SwType,\r
+  GpiType,\r
+  QNCnType,\r
+  PowerButtonType,\r
+  PeriodicTimerType,\r
+  NUM_PROTOCOLS\r
+} QNC_SMM_PROTOCOL_TYPE;\r
+\r
+//\r
+// /////////////////////////////////////////////////////////////////////////////\r
+// SPECIFYING A REGISTER\r
+// We want a general way of referring to addresses.  For this case, we'll only\r
+// need addresses in the ACPI table (and the TCO entries within the ACPI table).\r
+// However, it's interesting to consider what it would take to support other types\r
+// of addresses.  To address Will's concern, I think it prudent to accommodate it\r
+// early on in the design.\r
+//\r
+// Addresses we need to consider:\r
+//\r
+//  Type:                           Required:\r
+//  I/O                             Yes\r
+//    ACPI (special case of I/O)    Only if we want to\r
+//    TCO  (special case of ACPI)   Only if we want to\r
+//  Memory (or Memory Mapped I/O)   Only if we want to\r
+//  PCI                             Yes, for BiosWp\r
+//\r
+typedef enum {\r
+  //\r
+  //  IO_ADDR_TYPE, // unimplemented\r
+  //\r
+  ACPI_ADDR_TYPE,\r
+  GPE_ADDR_TYPE,\r
+  //\r
+  //  MEMORY_ADDR_TYPE, // unimplemented\r
+  //\r
+  MEMORY_MAPPED_IO_ADDRESS_TYPE,\r
+  PCI_ADDR_TYPE,\r
+  NUM_ADDR_TYPES,                     // count of items in this enum\r
+  QNC_SMM_ADDR_TYPE_NULL        = -1  // sentinel to indicate NULL or to signal end of arrays\r
+} ADDR_TYPE;\r
+\r
+//\r
+// Assumption: 32-bits -- enum's evaluate to integer\r
+// Assumption: This code will only run on IA-32.  Justification: IA-64 doesn't have SMIs.\r
+// We don't have to worry about 64-bit addresses.\r
+// Typedef the size of addresses in case the numbers I'm using are wrong or in case\r
+// this changes.  This is a good idea because PCI_ADDR will change, for example, when\r
+// we add support for PciExpress.\r
+//\r
+typedef UINT16 IO_ADDR;\r
+typedef IO_ADDR ACPI_ADDR;  // can omit\r
+typedef IO_ADDR GPE_ADDR;  // can omit\r
+typedef IO_ADDR TCO_ADDR;   // can omit\r
+typedef VOID *MEM_ADDR;\r
+typedef MEM_ADDR MEMORY_MAPPED_IO_ADDRESS;\r
+typedef union {\r
+  UINT32  Raw;\r
+  struct {\r
+    UINT8 Reg;\r
+    UINT8 Fnc;\r
+    UINT8 Dev;\r
+    UINT8 Bus;\r
+  } Fields;\r
+} PCI_ADDR;\r
+\r
+typedef struct {\r
+  ADDR_TYPE Type;\r
+  union {\r
+    //\r
+    // used to initialize during declaration/definition\r
+    //\r
+    UINTN                     raw;\r
+\r
+    //\r
+    // used to access useful data\r
+    //\r
+    IO_ADDR                   io;\r
+    ACPI_ADDR                 acpi;\r
+    GPE_ADDR                  gpe;\r
+    TCO_ADDR                  tco;\r
+    MEM_ADDR                  mem;\r
+    MEMORY_MAPPED_IO_ADDRESS  Mmio;\r
+    PCI_ADDR                  pci;\r
+\r
+  } Data;\r
+\r
+} QNC_SMM_ADDRESS;\r
+//\r
+// Assumption: total size is 64 bits (32 for type and 32 for data) or 8 bytes\r
+//\r
+#define EFI_PCI_ADDRESS_PORT  0xcf8\r
+#define EFI_PCI_DATA_PORT     0xcfc\r
+\r
+//\r
+// /////////////////////////////////////////////////////////////////////////////\r
+// SPECIFYING BITS WITHIN A REGISTER\r
+// Here's a struct that helps us specify a source or enable bit.\r
+//\r
+typedef struct {\r
+  QNC_SMM_ADDRESS Reg;\r
+  UINT8           SizeInBytes;  // of the register\r
+  UINT8           Bit;\r
+} QNC_SMM_BIT_DESC;\r
+\r
+//\r
+// Sometimes, we'll have bit descriptions that are unused.  It'd be great to have a\r
+// way to easily identify them:\r
+//\r
+#define IS_BIT_DESC_NULL(BitDesc)   ((BitDesc).Reg.Type == QNC_SMM_ADDR_TYPE_NULL)  // "returns" true when BitDesc is NULL\r
+#define NULL_THIS_BIT_DESC(BitDesc) ((BitDesc).Reg.Type = QNC_SMM_ADDR_TYPE_NULL)   // will "return" an integer w/ value of 0\r
+#define NULL_BIT_DESC_INITIALIZER \\r
+  { \\r
+    { \\r
+      QNC_SMM_ADDR_TYPE_NULL, \\r
+      { \\r
+        0 \\r
+      } \\r
+    }, \\r
+    0, 0 \\r
+  }\r
+//\r
+// I'd like a type to specify the callback's Sts & En bits because they'll\r
+// be commonly used together:\r
+//\r
+#define NUM_EN_BITS   2\r
+#define NUM_STS_BITS  1\r
+\r
+//\r
+// Flags\r
+//\r
+typedef UINT8 QNC_SMM_SOURCE_FLAGS;\r
+\r
+//\r
+// Flags required today\r
+//\r
+#define QNC_SMM_NO_FLAGS               0\r
+#define QNC_SMM_SCI_EN_DEPENDENT      (BIT0)\r
+#define QNC_SMM_CLEAR_WITH_ZERO       (BIT6)\r
+\r
+//\r
+// Flags that might be required tomorrow\r
+// #define QNC_SMM_CLEAR_WITH_ONE 2 // may need to support bits that clear by writing 0\r
+// #define QNC_SMM_MULTIBIT_FIELD 3 // may need to support status/enable fields 2 bits wide\r
+//\r
+typedef struct {\r
+  QNC_SMM_SOURCE_FLAGS  Flags;\r
+  QNC_SMM_BIT_DESC      En[NUM_EN_BITS];\r
+  QNC_SMM_BIT_DESC      Sts[NUM_STS_BITS];\r
+} QNC_SMM_SOURCE_DESC;\r
+//\r
+// 31 bytes, I think\r
+//\r
+#define NULL_SOURCE_DESC_INITIALIZER \\r
+  { \\r
+    QNC_SMM_NO_FLAGS, \\r
+    { \\r
+      NULL_BIT_DESC_INITIALIZER, NULL_BIT_DESC_INITIALIZER \\r
+    }, \\r
+    { \\r
+      NULL_BIT_DESC_INITIALIZER \\r
+    } \\r
+  }\r
+\r
+//\r
+// /////////////////////////////////////////////////////////////////////////////\r
+// CHILD CONTEXTS\r
+// To keep consistent w/ the architecture, we'll need to provide the context\r
+// to the child when we call its callback function.  After talking with Will,\r
+// we agreed that we'll need functions to "dig" the context out of the hardware\r
+// in many cases (Sx, Trap, Gpi, etc), and we'll need a function to compare those\r
+// contexts to prevent unnecessary dispatches.  I'd like a general type for these\r
+// "GetContext" functions, so I'll need a union of all the protocol contexts for\r
+// our internal use:\r
+//\r
+typedef union {\r
+  //\r
+  // (in no particular order)\r
+  //\r
+  EFI_SMM_ICHN_REGISTER_CONTEXT           QNCn;\r
+  EFI_SMM_SX_REGISTER_CONTEXT             Sx;\r
+  EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT PeriodicTimer;\r
+  EFI_SMM_SW_REGISTER_CONTEXT             Sw;\r
+  EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT   PowerButton;\r
+  // EFI_SMM_USB_REGISTER_CONTEXT            Usb; DELETE:on QuarkNcSocId, there is no usb smi supported\r
+  EFI_SMM_GPI_REGISTER_CONTEXT            Gpi;\r
+} QNC_SMM_CONTEXT;\r
+\r
+typedef union {\r
+  //\r
+  // (in no particular order)\r
+  //\r
+  EFI_SMM_SW_CONTEXT                      Sw;\r
+  EFI_SMM_PERIODIC_TIMER_CONTEXT          PeriodicTimer;\r
+} QNC_SMM_BUFFER;\r
+\r
+//\r
+// Assumption: PeriodicTimer largest at 3x64-bits or 24 bytes\r
+//\r
+typedef struct _DATABASE_RECORD DATABASE_RECORD;\r
+\r
+typedef\r
+VOID\r
+(EFIAPI *GET_CONTEXT) (\r
+  IN  DATABASE_RECORD    * Record,\r
+  OUT QNC_SMM_CONTEXT    * Context\r
+  );\r
+//\r
+// Assumption: the GET_CONTEXT function will be as small and simple as possible.\r
+// Assumption: We don't need to pass in an enumeration for the protocol because each\r
+//    GET_CONTEXT function is written for only one protocol.\r
+// We also need a function to compare contexts to see if the child should be dispatched\r
+//\r
+typedef\r
+BOOLEAN\r
+(EFIAPI *CMP_CONTEXT) (\r
+  IN QNC_SMM_CONTEXT     * Context1,\r
+  IN QNC_SMM_CONTEXT     * Context2\r
+  );\r
+\r
+/*\r
+    Returns: True when contexts are equivalent; False otherwise\r
+*/\r
+\r
+//\r
+// This function is used to get the content of CommBuffer that will be passed\r
+// to Callback function\r
+//\r
+typedef\r
+VOID\r
+(EFIAPI *GET_BUFFER) (\r
+  IN  DATABASE_RECORD     * Record\r
+  );\r
+\r
+//\r
+// Finally, every protocol will require a "Get Context", "Compare Context"\r
+// and "Get CommBuffer" call, so we may as well wrap that up in a table, too.\r
+//\r
+typedef struct {\r
+  GET_CONTEXT GetContext;\r
+  CMP_CONTEXT CmpContext;\r
+  GET_BUFFER  GetBuffer;\r
+} CONTEXT_FUNCTIONS;\r
+\r
+extern CONTEXT_FUNCTIONS          ContextFunctions[NUM_PROTOCOLS];\r
+\r
+//\r
+// /////////////////////////////////////////////////////////////////////////////\r
+// MAPPING CONTEXT TO BIT DESCRIPTIONS\r
+// I'd like to have a general approach to mapping contexts to bit descriptions.\r
+// Sometimes, we'll find that we can use table lookups or CONSTant assignments;\r
+// other times, we'll find that we'll need to use a function to perform the mapping.\r
+// If we define a macro to mask that process, we'll never have to change the code.\r
+// I don't know if this is desirable or not -- if it isn't, then we can get rid\r
+// of the macros and just use function calls or variable assignments.  Doesn't matter\r
+// to me.\r
+// Mapping complex contexts requires a function\r
+//\r
+// DELETE:on QuarkNcSocId, there is no usb smi supported\r
+//EFI_STATUS\r
+//EFIAPI\r
+//MapUsbToSrcDesc (\r
+//  IN  QNC_SMM_CONTEXT                                          *RegisterContext,\r
+//  OUT QNC_SMM_SOURCE_DESC                                      *SrcDesc\r
+//  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  RegisterContext - GC_TODO: add argument description\r
+  SrcDesc         - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+MapPeriodicTimerToSrcDesc (\r
+  IN  QNC_SMM_CONTEXT                                          *RegisterContext,\r
+  OUT QNC_SMM_SOURCE_DESC                                     *SrcDesc\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  RegisterContext - GC_TODO: add argument description\r
+  SrcDesc         - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+//\r
+// Mapping simple contexts can be done by assignment or lookup table\r
+//\r
+extern CONST QNC_SMM_SOURCE_DESC  SW_SOURCE_DESC;\r
+extern CONST QNC_SMM_SOURCE_DESC  SX_SOURCE_DESC;\r
+\r
+//\r
+// With the changes we've made to the protocols, we can now use table\r
+// lookups for the following protocols:\r
+//\r
+extern CONST QNC_SMM_SOURCE_DESC  GPI_SOURCE_DESC;\r
+\r
+extern QNC_SMM_SOURCE_DESC        QNCN_SOURCE_DESCS[NUM_ICHN_TYPES];\r
+\r
+\r
+//\r
+// For QNCx, APMC is UINT8 port, so the MAX SWI Value is 0xFF.\r
+//\r
+#define MAXIMUM_SWI_VALUE   0xFF\r
+\r
+\r
+//\r
+// Open: Need to make sure this kind of type cast will actually work.\r
+//   May need an intermediate form w/ two VOID* arguments.  I'll figure\r
+//   that out when I start compiling.\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+typedef\r
+VOID\r
+(EFIAPI *QNC_SMM_CLEAR_SOURCE) (\r
+  QNC_SMM_SOURCE_DESC * SrcDesc\r
+  );\r
+\r
+//\r
+// /////////////////////////////////////////////////////////////////////////////\r
+// "DATABASE" RECORD\r
+// Linked list data structures\r
+//\r
+#define DATABASE_RECORD_SIGNATURE SIGNATURE_32 ('D', 'B', 'R', 'C')\r
+\r
+struct _DATABASE_RECORD {\r
+  UINT32                Signature;\r
+  LIST_ENTRY            Link;\r
+\r
+  //\r
+  // Status and Enable bit description\r
+  //\r
+  QNC_SMM_SOURCE_DESC   SrcDesc;\r
+\r
+  //\r
+  // Callback function\r
+  //\r
+  EFI_SMM_HANDLER_ENTRY_POINT2      Callback;\r
+  QNC_SMM_CONTEXT       ChildContext;\r
+  QNC_SMM_BUFFER                     CommBuffer;\r
+  UINTN                             BufferSize;\r
+\r
+  //\r
+  // Special handling hooks -- init them to NULL if unused/unneeded\r
+  //\r
+  QNC_SMM_CLEAR_SOURCE  ClearSource;  // needed for SWSMI timer\r
+  // Functions required to make callback code general\r
+  //\r
+  CONTEXT_FUNCTIONS     ContextFunctions;\r
+\r
+  //\r
+  // The protocol that this record dispatches\r
+  //\r
+  QNC_SMM_PROTOCOL_TYPE ProtocolType;\r
+\r
+};\r
+\r
+#define DATABASE_RECORD_FROM_LINK(_record)  CR (_record, DATABASE_RECORD, Link, DATABASE_RECORD_SIGNATURE)\r
+#define DATABASE_RECORD_FROM_CONTEXT(_record)  CR (_record, DATABASE_RECORD, ChildContext, DATABASE_RECORD_SIGNATURE)\r
+\r
+//\r
+// /////////////////////////////////////////////////////////////////////////////\r
+// HOOKING INTO THE ARCHITECTURE\r
+//\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *QNC_SMM_GENERIC_REGISTER) (\r
+  IN  VOID                                    **This,\r
+  IN  VOID                                    *DispatchFunction,\r
+  IN  VOID                                    *RegisterContext,\r
+  OUT EFI_HANDLE                              * DispatchHandle\r
+  );\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *QNC_SMM_GENERIC_UNREGISTER) (\r
+  IN  VOID                                    **This,\r
+  IN  EFI_HANDLE                              DispatchHandle\r
+  );\r
+\r
+//\r
+// Define a memory "stamp" equivalent in size and function to most of the protocols\r
+//\r
+typedef struct {\r
+  QNC_SMM_GENERIC_REGISTER    Register;\r
+  QNC_SMM_GENERIC_UNREGISTER  Unregister;\r
+  UINTN                       Extra1;\r
+  UINTN                       Extra2; // may not need this one\r
+} QNC_SMM_GENERIC_PROTOCOL;\r
+\r
+EFI_STATUS\r
+QNCSmmCoreRegister (\r
+  IN  QNC_SMM_GENERIC_PROTOCOL                          *This,\r
+  IN  EFI_SMM_HANDLER_ENTRY_POINT2                      DispatchFunction,\r
+  IN  QNC_SMM_CONTEXT                                    *RegisterContext,\r
+  OUT EFI_HANDLE                                        *DispatchHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  This              - GC_TODO: add argument description\r
+  DispatchFunction  - GC_TODO: add argument description\r
+  RegisterContext   - GC_TODO: add argument description\r
+  DispatchHandle    - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+EFI_STATUS\r
+QNCSmmCoreUnRegister (\r
+  IN  QNC_SMM_GENERIC_PROTOCOL                         *This,\r
+  IN EFI_HANDLE                                        DispatchHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  This            - GC_TODO: add argument description\r
+  DispatchHandle  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+typedef union {\r
+  QNC_SMM_GENERIC_PROTOCOL                  Generic;\r
+\r
+  // EFI_SMM_USB_DISPATCH2_PROTOCOL             Usb;  DELETE:on QuarkNcSocId, there is no usb smi supported\r
+  EFI_SMM_SX_DISPATCH2_PROTOCOL              Sx;\r
+  EFI_SMM_SW_DISPATCH2_PROTOCOL              Sw;\r
+  EFI_SMM_GPI_DISPATCH2_PROTOCOL             Gpi;\r
+  EFI_SMM_ICHN_DISPATCH2_PROTOCOL            QNCn;\r
+  EFI_SMM_POWER_BUTTON_DISPATCH2_PROTOCOL    PowerButton;\r
+  EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL  PeriodicTimer;\r
+} QNC_SMM_PROTOCOL;\r
+\r
+//\r
+// Define a structure to help us identify the generic protocol\r
+//\r
+#define PROTOCOL_SIGNATURE  SIGNATURE_32 ('P', 'R', 'O', 'T')\r
+\r
+typedef struct {\r
+  UINTN                 Signature;\r
+\r
+  QNC_SMM_PROTOCOL_TYPE Type;\r
+  EFI_GUID              *Guid;\r
+  QNC_SMM_PROTOCOL      Protocols;\r
+} QNC_SMM_QUALIFIED_PROTOCOL;\r
+\r
+#define QUALIFIED_PROTOCOL_FROM_GENERIC(_generic) \\r
+  CR (_generic, \\r
+      QNC_SMM_QUALIFIED_PROTOCOL, \\r
+      Protocols, \\r
+      PROTOCOL_SIGNATURE \\r
+      )\r
+\r
+//\r
+// Create private data for the protocols that we'll publish\r
+//\r
+typedef struct {\r
+  LIST_ENTRY                  CallbackDataBase;\r
+  EFI_HANDLE                  SmiHandle;\r
+  EFI_HANDLE                  InstallMultProtHandle;\r
+  QNC_SMM_QUALIFIED_PROTOCOL  Protocols[NUM_PROTOCOLS];\r
+} PRIVATE_DATA;\r
+\r
+extern PRIVATE_DATA           mPrivateData;\r
+\r
+//\r
+// /////////////////////////////////////////////////////////////////////////////\r
+//\r
+VOID\r
+EFIAPI\r
+SwGetContext (\r
+  IN  DATABASE_RECORD    *Record,\r
+  OUT QNC_SMM_CONTEXT    *Context\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Record  - GC_TODO: add argument description\r
+  Context - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+BOOLEAN\r
+EFIAPI\r
+SwCmpContext (\r
+  IN QNC_SMM_CONTEXT     *Context1,\r
+  IN QNC_SMM_CONTEXT     *Context2\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Context1  - GC_TODO: add argument description\r
+  Context2  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+SwGetBuffer (\r
+  IN  DATABASE_RECORD     * Record\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Record  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+EFIAPI\r
+SxGetContext (\r
+  IN  DATABASE_RECORD    *Record,\r
+  OUT QNC_SMM_CONTEXT    *Context\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Record  - GC_TODO: add argument description\r
+  Context - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+BOOLEAN\r
+EFIAPI\r
+SxCmpContext (\r
+  IN QNC_SMM_CONTEXT     *Context1,\r
+  IN QNC_SMM_CONTEXT     *Context2\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Context1  - GC_TODO: add argument description\r
+  Context2  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+EFIAPI\r
+PeriodicTimerGetContext (\r
+  IN  DATABASE_RECORD    *Record,\r
+  OUT QNC_SMM_CONTEXT    *Context\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Record  - GC_TODO: add argument description\r
+  Context - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+BOOLEAN\r
+EFIAPI\r
+PeriodicTimerCmpContext (\r
+  IN QNC_SMM_CONTEXT     *Context1,\r
+  IN QNC_SMM_CONTEXT     *Context2\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Context1  - GC_TODO: add argument description\r
+  Context2  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+PeriodicTimerGetBuffer (\r
+  IN  DATABASE_RECORD     * Record\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Record  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+EFIAPI\r
+PowerButtonGetContext (\r
+  IN  DATABASE_RECORD    *Record,\r
+  OUT QNC_SMM_CONTEXT     *Context\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Record  - GC_TODO: add argument description\r
+  Context - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+BOOLEAN\r
+EFIAPI\r
+PowerButtonCmpContext (\r
+  IN QNC_SMM_CONTEXT     *Context1,\r
+  IN QNC_SMM_CONTEXT     *Context2\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Context1  - GC_TODO: add argument description\r
+  Context2  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+//\r
+// /////////////////////////////////////////////////////////////////////////////\r
+//\r
+VOID\r
+EFIAPI\r
+QNCSmmPeriodicTimerClearSource (\r
+  QNC_SMM_SOURCE_DESC *SrcDesc\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  SrcDesc - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+QNCSmmPeriodicTimerDispatchGetNextShorterInterval (\r
+  IN CONST EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL    *This,\r
+  IN OUT UINT64                                         **SmiTickInterval\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  This            - GC_TODO: add argument description\r
+  SmiTickInterval - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+QNCSmmSxGoToSleep (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+EFIAPI\r
+QNCSmmQNCnClearSource (\r
+  QNC_SMM_SOURCE_DESC *SrcDesc\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  SrcDesc - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmCore.c b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmCore.c
new file mode 100644 (file)
index 0000000..ba8c721
--- /dev/null
@@ -0,0 +1,800 @@
+/** @file\r
+This driver is responsible for the registration of child drivers\r
+and the abstraction of the QNC SMI sources.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+#include "QNCSmm.h"\r
+#include "QNCSmmHelpers.h"\r
+\r
+//\r
+// /////////////////////////////////////////////////////////////////////////////\r
+// MODULE / GLOBAL DATA\r
+//\r
+// Module variables used by the both the main dispatcher and the source dispatchers\r
+// Declared in QNCSmmSources.h\r
+//\r
+UINT32                    mPciData;\r
+UINT32                    mPciAddress;\r
+\r
+PRIVATE_DATA              mPrivateData = {  // for the structure\r
+  {\r
+    NULL\r
+  },                                        // CallbackDataBase linked list head\r
+  NULL,                                     // Handler returned whan calling SmiHandlerRegister\r
+  NULL,                                     // EFI handle returned when calling InstallMultipleProtocolInterfaces\r
+  {                                         // protocol arrays\r
+    // elements within the array\r
+    //\r
+    {\r
+      PROTOCOL_SIGNATURE,\r
+      SxType,\r
+      &gEfiSmmSxDispatch2ProtocolGuid,\r
+      {\r
+        {\r
+          (QNC_SMM_GENERIC_REGISTER) QNCSmmCoreRegister,\r
+          (QNC_SMM_GENERIC_UNREGISTER) QNCSmmCoreUnRegister\r
+        }\r
+      }\r
+    },\r
+    {\r
+      PROTOCOL_SIGNATURE,\r
+      SwType,\r
+      &gEfiSmmSwDispatch2ProtocolGuid,\r
+      {\r
+        {\r
+          (QNC_SMM_GENERIC_REGISTER) QNCSmmCoreRegister,\r
+          (QNC_SMM_GENERIC_UNREGISTER) QNCSmmCoreUnRegister,\r
+          (UINTN) MAXIMUM_SWI_VALUE\r
+        }\r
+      }\r
+    },\r
+    {\r
+      PROTOCOL_SIGNATURE,\r
+      GpiType,\r
+      &gEfiSmmGpiDispatch2ProtocolGuid,\r
+      {\r
+        {\r
+          (QNC_SMM_GENERIC_REGISTER) QNCSmmCoreRegister,\r
+          (QNC_SMM_GENERIC_UNREGISTER) QNCSmmCoreUnRegister,\r
+          (UINTN) 1\r
+        }\r
+      }\r
+    },\r
+    {\r
+      PROTOCOL_SIGNATURE,\r
+      QNCnType,\r
+      &gEfiSmmIchnDispatch2ProtocolGuid,\r
+      {\r
+        {\r
+          (QNC_SMM_GENERIC_REGISTER) QNCSmmCoreRegister,\r
+          (QNC_SMM_GENERIC_UNREGISTER) QNCSmmCoreUnRegister\r
+        }\r
+      }\r
+    },\r
+    {\r
+      PROTOCOL_SIGNATURE,\r
+      PowerButtonType,\r
+      &gEfiSmmPowerButtonDispatch2ProtocolGuid,\r
+      {\r
+        {\r
+          (QNC_SMM_GENERIC_REGISTER) QNCSmmCoreRegister,\r
+          (QNC_SMM_GENERIC_UNREGISTER) QNCSmmCoreUnRegister\r
+        }\r
+      }\r
+    },\r
+    {\r
+      PROTOCOL_SIGNATURE,\r
+      PeriodicTimerType,\r
+      &gEfiSmmPeriodicTimerDispatch2ProtocolGuid,\r
+      {\r
+        {\r
+          (QNC_SMM_GENERIC_REGISTER) QNCSmmCoreRegister,\r
+          (QNC_SMM_GENERIC_UNREGISTER) QNCSmmCoreUnRegister,\r
+          (UINTN) QNCSmmPeriodicTimerDispatchGetNextShorterInterval\r
+        }\r
+      }\r
+    },\r
+  }\r
+};\r
+\r
+CONTEXT_FUNCTIONS         mContextFunctions[NUM_PROTOCOLS] = {\r
+  {\r
+    SxGetContext,\r
+    SxCmpContext,\r
+    NULL\r
+  },\r
+  {\r
+    SwGetContext,\r
+    SwCmpContext,\r
+    SwGetBuffer\r
+  },\r
+  {\r
+    NULL,\r
+    NULL,\r
+    NULL\r
+  },\r
+  {\r
+    NULL,\r
+    NULL,\r
+    NULL\r
+  },\r
+  {\r
+    NULL,\r
+    NULL,\r
+    NULL\r
+  },\r
+  {\r
+    PeriodicTimerGetContext,\r
+    PeriodicTimerCmpContext,\r
+    PeriodicTimerGetBuffer,\r
+  },\r
+};\r
+\r
+//\r
+// /////////////////////////////////////////////////////////////////////////////\r
+// PROTOTYPES\r
+//\r
+// Functions use only in this file\r
+//\r
+EFI_STATUS\r
+QNCSmmCoreDispatcher (\r
+  IN     EFI_HANDLE               DispatchHandle,\r
+  IN     CONST VOID               *Context,        OPTIONAL\r
+  IN OUT VOID                     *CommBuffer,     OPTIONAL\r
+  IN OUT UINTN                    *CommBufferSize  OPTIONAL\r
+  );\r
+\r
+\r
+UINTN\r
+DevicePathSize (\r
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
+  );\r
+\r
+//\r
+// /////////////////////////////////////////////////////////////////////////////\r
+// FUNCTIONS\r
+//\r
+// Driver entry point\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeQNCSmmDispatcher (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Initializes the QNC SMM Dispatcher\r
+\r
+Arguments:\r
+\r
+  ImageHandle   - Pointer to the loaded image protocol for this driver\r
+  SystemTable   - Pointer to the EFI System Table\r
+\r
+Returns:\r
+  Status        - EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                Status;\r
+\r
+  QNCSmmPublishDispatchProtocols ();\r
+\r
+  //\r
+  // Register a callback function to handle subsequent SMIs.  This callback\r
+  // will be called by SmmCoreDispatcher.\r
+  //\r
+  Status = gSmst->SmiHandlerRegister (QNCSmmCoreDispatcher, NULL, &mPrivateData.SmiHandle);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Initialize Callback DataBase\r
+  //\r
+  InitializeListHead (&mPrivateData.CallbackDataBase);\r
+\r
+  //\r
+  // Enable SMIs on the QNC now that we have a callback\r
+  //\r
+  QNCSmmInitHardware ();\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+SaveState (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Save Index registers to avoid corrupting the foreground environment\r
+\r
+Arguments:\r
+  None\r
+\r
+Returns:\r
+  Status - EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+  mPciAddress = IoRead32 (EFI_PCI_ADDRESS_PORT);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+RestoreState (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Restore Index registers to avoid corrupting the foreground environment\r
+\r
+Arguments:\r
+  None\r
+\r
+Returns:\r
+  Status - EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+  IoWrite32 (EFI_PCI_ADDRESS_PORT, mPciAddress);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+SmiInputValueDuplicateCheck (\r
+  UINTN           FedSwSmiInputValue\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Check the Fed SwSmiInputValue to see if there is a duplicated one in the database\r
+\r
+Arguments:\r
+  None\r
+\r
+Returns:\r
+  Status - EFI_SUCCESS, EFI_INVALID_PARAMETER\r
+\r
+--*/\r
+// GC_TODO:    FedSwSmiInputValue - add argument and description to function comment\r
+{\r
+\r
+  DATABASE_RECORD *RecordInDb;\r
+  LIST_ENTRY      *LinkInDb;\r
+\r
+  LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);\r
+  while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {\r
+    RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);\r
+\r
+    if (RecordInDb->ProtocolType == SwType) {\r
+      if (RecordInDb->ChildContext.Sw.SwSmiInputValue == FedSwSmiInputValue) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+    }\r
+\r
+    LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+QNCSmmCoreRegister (\r
+  IN  QNC_SMM_GENERIC_PROTOCOL                          *This,\r
+  IN  EFI_SMM_HANDLER_ENTRY_POINT2                      DispatchFunction,\r
+  IN  QNC_SMM_CONTEXT                                    *RegisterContext,\r
+  OUT EFI_HANDLE                                        *DispatchHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+// GC_TODO:    This - add argument and description to function comment\r
+// GC_TODO:    DispatchFunction - add argument and description to function comment\r
+// GC_TODO:    RegisterContext - add argument and description to function comment\r
+// GC_TODO:    DispatchHandle - add argument and description to function comment\r
+// GC_TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO:    EFI_INVALID_PARAMETER - add return value to function comment\r
+// GC_TODO:    EFI_SUCCESS - add return value to function comment\r
+// GC_TODO:    EFI_INVALID_PARAMETER - add return value to function comment\r
+{\r
+  EFI_STATUS                  Status;\r
+  DATABASE_RECORD             *Record;\r
+  QNC_SMM_QUALIFIED_PROTOCOL  *Qualified;\r
+  INTN                        Index;\r
+\r
+  //\r
+  // Check for invalid parameter\r
+  //\r
+  if (This == NULL || RegisterContext == NULL || DispatchHandle == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Create database record and add to database\r
+  //\r
+  Record = (DATABASE_RECORD *) AllocateZeroPool (sizeof (DATABASE_RECORD));\r
+  if (Record == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Gather information about the registration request\r
+  //\r
+  Record->Callback          = DispatchFunction;\r
+  Record->ChildContext      = *RegisterContext;\r
+\r
+  Qualified                 = QUALIFIED_PROTOCOL_FROM_GENERIC (This);\r
+\r
+  Record->ProtocolType      = Qualified->Type;\r
+\r
+  CopyMem (&Record->ContextFunctions, &mContextFunctions[Qualified->Type], sizeof (Record->ContextFunctions));\r
+  //\r
+  // Perform linked list housekeeping\r
+  //\r
+  Record->Signature = DATABASE_RECORD_SIGNATURE;\r
+\r
+  switch (Qualified->Type) {\r
+  //\r
+  // By the end of this switch statement, we'll know the\r
+  // source description the child is registering for\r
+  //\r
+  case SxType:\r
+    //\r
+    // Check the validity of Context Type and Phase\r
+    //\r
+    if ((Record->ChildContext.Sx.Type < SxS0) ||\r
+        (Record->ChildContext.Sx.Type >= EfiMaximumSleepType) ||\r
+        (Record->ChildContext.Sx.Phase < SxEntry) ||\r
+        (Record->ChildContext.Sx.Phase >= EfiMaximumPhase)\r
+        ) {\r
+      goto Error;\r
+    }\r
+\r
+    InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);\r
+    CopyMem (&Record->SrcDesc, &SX_SOURCE_DESC, sizeof (Record->SrcDesc));\r
+    //\r
+    // use default clear source function\r
+    //\r
+    break;\r
+\r
+  case SwType:\r
+    if (RegisterContext->Sw.SwSmiInputValue == (UINTN)-1) {\r
+      //\r
+      // If SwSmiInputValue is set to (UINTN) -1 then a unique value will be assigned and returned in the structure.\r
+      //\r
+      Status = EFI_NOT_FOUND;\r
+      for (Index = 1; Index < MAXIMUM_SWI_VALUE; Index++) {\r
+        Status = SmiInputValueDuplicateCheck (Index);\r
+        if (!EFI_ERROR (Status)) {\r
+          RegisterContext->Sw.SwSmiInputValue = Index;\r
+          break;\r
+        }\r
+      }\r
+      if (RegisterContext->Sw.SwSmiInputValue == (UINTN)-1) {\r
+        Status = gSmst->SmmFreePool (Record);\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+      //\r
+      // Update ChildContext again as SwSmiInputValue has been changed\r
+      //\r
+      Record->ChildContext = *RegisterContext;\r
+    }\r
+\r
+    //\r
+    // Check the validity of Context Value\r
+    //\r
+    if (Record->ChildContext.Sw.SwSmiInputValue > MAXIMUM_SWI_VALUE) {\r
+      goto Error;\r
+    }\r
+\r
+    if (EFI_ERROR (SmiInputValueDuplicateCheck (Record->ChildContext.Sw.SwSmiInputValue))) {\r
+      goto Error;\r
+    }\r
+\r
+    InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);\r
+    CopyMem (&Record->SrcDesc, &SW_SOURCE_DESC, sizeof (Record->SrcDesc));\r
+    Record->BufferSize = sizeof (EFI_SMM_SW_REGISTER_CONTEXT);\r
+    //\r
+    // use default clear source function\r
+    //\r
+    break;\r
+\r
+  case GpiType:\r
+\r
+    InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);\r
+    CopyMem (&Record->SrcDesc, &GPI_SOURCE_DESC, sizeof (Record->SrcDesc));\r
+    //\r
+    // use default clear source function\r
+    //\r
+    break;\r
+\r
+  case QNCnType:\r
+    //\r
+    // Check the validity of Context Type\r
+    //\r
+    if ((Record->ChildContext.QNCn.Type < IchnMch) || (Record->ChildContext.QNCn.Type >= NUM_ICHN_TYPES)) {\r
+      goto Error;\r
+    }\r
+\r
+    InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);\r
+    CopyMem (&Record->SrcDesc, &QNCN_SOURCE_DESCS[Record->ChildContext.QNCn.Type], sizeof (Record->SrcDesc));\r
+    Record->ClearSource = QNCSmmQNCnClearSource;\r
+    break;\r
+\r
+  case PeriodicTimerType:\r
+\r
+    Status = MapPeriodicTimerToSrcDesc (RegisterContext, &(Record->SrcDesc));\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
+    }\r
+\r
+    InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);\r
+    Record->BufferSize = sizeof (EFI_SMM_PERIODIC_TIMER_CONTEXT);\r
+    Record->ClearSource = QNCSmmPeriodicTimerClearSource;\r
+    break;\r
+\r
+  default:\r
+    goto Error;\r
+    break;\r
+  };\r
+\r
+  if (Record->ClearSource == NULL) {\r
+    //\r
+    // Clear the SMI associated w/ the source using the default function\r
+    //\r
+    QNCSmmClearSource (&Record->SrcDesc);\r
+  } else {\r
+    //\r
+    // This source requires special handling to clear\r
+    //\r
+    Record->ClearSource (&Record->SrcDesc);\r
+  }\r
+\r
+  QNCSmmEnableSource (&Record->SrcDesc);\r
+\r
+  //\r
+  // Child's handle will be the address linked list link in the record\r
+  //\r
+  *DispatchHandle = (EFI_HANDLE) (&Record->Link);\r
+\r
+  return EFI_SUCCESS;\r
+\r
+Error:\r
+  FreePool (Record);\r
+  //\r
+  // DEBUG((EFI_D_ERROR,"Free pool status %d\n", Status ));\r
+  //\r
+  return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+EFI_STATUS\r
+QNCSmmCoreUnRegister (\r
+  IN QNC_SMM_GENERIC_PROTOCOL                         *This,\r
+  IN EFI_HANDLE                                        DispatchHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+// GC_TODO:    This - add argument and description to function comment\r
+// GC_TODO:    DispatchHandle - add argument and description to function comment\r
+// GC_TODO:    EFI_INVALID_PARAMETER - add return value to function comment\r
+// GC_TODO:    EFI_INVALID_PARAMETER - add return value to function comment\r
+// GC_TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  BOOLEAN         SafeToDisable;\r
+  DATABASE_RECORD *RecordToDelete;\r
+  DATABASE_RECORD *RecordInDb;\r
+  LIST_ENTRY      *LinkInDb;\r
+\r
+  if (DispatchHandle == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (BASE_CR (DispatchHandle, DATABASE_RECORD, Link)->Signature != DATABASE_RECORD_SIGNATURE) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);\r
+\r
+  RemoveEntryList (&RecordToDelete->Link);\r
+  RecordToDelete->Signature = 0;\r
+\r
+  //\r
+  // See if we can disable the source, reserved for future use since this might\r
+  //  not be the only criteria to disable\r
+  //\r
+  SafeToDisable = TRUE;\r
+  LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);\r
+  while(!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {\r
+    RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);\r
+    if (CompareEnables (&RecordToDelete->SrcDesc, &RecordInDb->SrcDesc)) {\r
+      SafeToDisable = FALSE;\r
+      break;\r
+    }\r
+    LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);\r
+  }\r
+  if (SafeToDisable) {\r
+    QNCSmmDisableSource( &RecordToDelete->SrcDesc );\r
+}\r
+\r
+  FreePool (RecordToDelete);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function is the main entry point for an SMM handler dispatch\r
+  or communicate-based callback.\r
+\r
+  @param  DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().\r
+  @param  RegisterContext Points to an optional handler context which was specified when the handler was registered.\r
+  @param  CommBuffer      A pointer to a collection of data in memory that will\r
+                          be conveyed from a non-SMM environment into an SMM environment.\r
+  @param  CommBufferSize  The size of the CommBuffer.\r
+\r
+  @return Status Code\r
+\r
+**/\r
+EFI_STATUS\r
+QNCSmmCoreDispatcher (\r
+  IN     EFI_HANDLE               DispatchHandle,\r
+  IN     CONST VOID               *RegisterContext,\r
+  IN OUT VOID                     *CommBuffer,\r
+  IN OUT UINTN                    *CommBufferSize\r
+  )\r
+{\r
+  //\r
+  // Used to prevent infinite loops\r
+  //\r
+  UINTN               EscapeCount;\r
+\r
+  BOOLEAN             ContextsMatch;\r
+  BOOLEAN             ResetListSearch;\r
+  BOOLEAN             EosSet;\r
+  BOOLEAN             SxChildWasDispatched;\r
+  BOOLEAN             ChildWasDispatched;\r
+\r
+  DATABASE_RECORD     *RecordInDb;\r
+  LIST_ENTRY          *LinkInDb;\r
+  DATABASE_RECORD     *RecordToExhaust;\r
+  LIST_ENTRY          *LinkToExhaust;\r
+\r
+  QNC_SMM_CONTEXT     Context;\r
+  VOID                *CommunicationBuffer;\r
+  UINTN               BufferSize;\r
+\r
+  EFI_STATUS          Status;\r
+  UINT32              NewValue;\r
+\r
+  QNC_SMM_SOURCE_DESC ActiveSource = NULL_SOURCE_DESC_INITIALIZER;\r
+\r
+  EscapeCount           = 100;\r
+  ContextsMatch         = FALSE;\r
+  ResetListSearch       = FALSE;\r
+  EosSet                = FALSE;\r
+  SxChildWasDispatched  = FALSE;\r
+  Status                = EFI_WARN_INTERRUPT_SOURCE_PENDING;\r
+  ChildWasDispatched    = FALSE;\r
+\r
+  //\r
+  // Preserve Index registers\r
+  //\r
+  SaveState ();\r
+\r
+  if (!IsListEmpty (&mPrivateData.CallbackDataBase)) {\r
+    //\r
+    // We have children registered w/ us -- continue\r
+    //\r
+    while ((!EosSet) && (EscapeCount > 0)) {\r
+      EscapeCount--;\r
+\r
+      //\r
+      // Reset this flag in order to be able to process multiple SMI Sources in one loop.\r
+      //\r
+      ResetListSearch = FALSE;\r
+\r
+      LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);\r
+\r
+      while ((!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) && (ResetListSearch == FALSE)) {\r
+        RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);\r
+\r
+        //\r
+        // look for the first active source\r
+        //\r
+        if (!SourceIsActive (&RecordInDb->SrcDesc)) {\r
+          //\r
+          // Didn't find the source yet, keep looking\r
+          //\r
+          LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);\r
+\r
+        } else {\r
+          //\r
+          // We found a source. If this is a sleep type, we have to go to\r
+          // appropriate sleep state anyway.No matter there is sleep child or not\r
+          //\r
+          if (RecordInDb->ProtocolType == SxType) {\r
+            SxChildWasDispatched = TRUE;\r
+          }\r
+          //\r
+          // "cache" the source description and don't query I/O anymore\r
+          //\r
+          CopyMem (&ActiveSource, &RecordInDb->SrcDesc, sizeof (ActiveSource));\r
+          LinkToExhaust = LinkInDb;\r
+\r
+          //\r
+          // exhaust the rest of the queue looking for the same source\r
+          //\r
+          while (!IsNull (&mPrivateData.CallbackDataBase, LinkToExhaust)) {\r
+            RecordToExhaust = DATABASE_RECORD_FROM_LINK (LinkToExhaust);\r
+\r
+            if (CompareSources (&RecordToExhaust->SrcDesc, &ActiveSource)) {\r
+              //\r
+              // These source descriptions are equal, so this callback should be\r
+              // dispatched.\r
+              //\r
+              if (RecordToExhaust->ContextFunctions.GetContext != NULL) {\r
+                //\r
+                // This child requires that we get a calling context from\r
+                // hardware and compare that context to the one supplied\r
+                // by the child.\r
+                //\r
+                ASSERT (RecordToExhaust->ContextFunctions.CmpContext != NULL);\r
+\r
+                //\r
+                // Make sure contexts match before dispatching event to child\r
+                //\r
+                RecordToExhaust->ContextFunctions.GetContext (RecordToExhaust, &Context);\r
+                ContextsMatch = RecordToExhaust->ContextFunctions.CmpContext (&Context, &RecordToExhaust->ChildContext);\r
+\r
+              } else {\r
+                //\r
+                // This child doesn't require any more calling context beyond what\r
+                // it supplied in registration.  Simply pass back what it gave us.\r
+                //\r
+                ASSERT (RecordToExhaust->Callback != NULL);\r
+                Context       = RecordToExhaust->ChildContext;\r
+                ContextsMatch = TRUE;\r
+              }\r
+\r
+              if (ContextsMatch) {\r
+\r
+                if (RecordToExhaust->BufferSize != 0) {\r
+                  ASSERT (RecordToExhaust->ContextFunctions.GetBuffer != NULL);\r
+\r
+                  RecordToExhaust->ContextFunctions.GetBuffer (RecordToExhaust);\r
+\r
+                  CommunicationBuffer = &RecordToExhaust->CommBuffer;\r
+                  BufferSize = RecordToExhaust->BufferSize;\r
+                } else {\r
+                  CommunicationBuffer = NULL;\r
+                  BufferSize = 0;\r
+                }\r
+\r
+                ASSERT (RecordToExhaust->Callback != NULL);\r
+\r
+                RecordToExhaust->Callback (\r
+                                   (EFI_HANDLE) & RecordToExhaust->Link,\r
+                                   &Context,\r
+                                   CommunicationBuffer,\r
+                                   &BufferSize\r
+                                   );\r
+\r
+                ChildWasDispatched = TRUE;\r
+                if (RecordToExhaust->ProtocolType == SxType) {\r
+                  SxChildWasDispatched = TRUE;\r
+                }\r
+              }\r
+            }\r
+            //\r
+            // Get next record in DB\r
+            //\r
+            LinkToExhaust = GetNextNode (&mPrivateData.CallbackDataBase, &RecordToExhaust->Link);\r
+          }\r
+\r
+          if (RecordInDb->ClearSource == NULL) {\r
+            //\r
+            // Clear the SMI associated w/ the source using the default function\r
+            //\r
+            QNCSmmClearSource (&ActiveSource);\r
+          } else {\r
+            //\r
+            // This source requires special handling to clear\r
+            //\r
+            RecordInDb->ClearSource (&ActiveSource);\r
+          }\r
+\r
+          if (ChildWasDispatched) {\r
+            //\r
+            // The interrupt was handled and quiesced\r
+            //\r
+            Status = EFI_SUCCESS;\r
+          } else {\r
+            //\r
+            // The interrupt was not handled but quiesced\r
+            //\r
+            Status = EFI_WARN_INTERRUPT_SOURCE_QUIESCED;\r
+          }\r
+\r
+          //\r
+          // Queue is empty, reset the search\r
+          //\r
+          ResetListSearch = TRUE;\r
+\r
+        }\r
+      }\r
+      EosSet = QNCSmmSetAndCheckEos ();\r
+    }\r
+  }\r
+  //\r
+  // If you arrive here, there are two possible reasons:\r
+  // (1) you've got problems with clearing the SMI status bits in the\r
+  // ACPI table.  If you don't properly clear the SMI bits, then you won't be able to set the\r
+  // EOS bit.  If this happens too many times, the loop exits.\r
+  // (2) there was a SMM communicate for callback messages that was received prior\r
+  // to this driver.\r
+  // If there is an asynchronous SMI that occurs while processing the Callback, let\r
+  // all of the drivers (including this one) have an opportunity to scan for the SMI\r
+  // and handle it.\r
+  // If not, we don't want to exit and have the foreground app. clear EOS without letting\r
+  // these other sources get serviced.\r
+  //\r
+  ASSERT (EscapeCount > 0);\r
+\r
+  //\r
+  // Restore Index registers\r
+  //\r
+  RestoreState ();\r
+\r
+  if (SxChildWasDispatched) {\r
+    //\r
+    // A child of the SmmSxDispatch protocol was dispatched during this call;\r
+    // put the system to sleep.\r
+    //\r
+    QNCSmmSxGoToSleep ();\r
+  }\r
+\r
+  //\r
+  // Ensure that SMI signal pin indicator is clear at the end of SMM handling.\r
+  //\r
+  NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_HLEGACY_REG);\r
+  NewValue &= ~(HLEGACY_SMI_PIN_VALUE);\r
+  QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_HLEGACY_REG, NewValue);\r
+\r
+  return Status;\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmDispatcher.inf b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmDispatcher.inf
new file mode 100644 (file)
index 0000000..ed94825
--- /dev/null
@@ -0,0 +1,87 @@
+## @file\r
+# Component description file for QuarkNcSocId SmmDispatcher module.\r
+#\r
+# This driver is responsible for the registration of child drivers\r
+#  and the abstraction of the ICH SMI sources.\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = QNCSmmDispatcher\r
+  FILE_GUID                      = 2480271C-09C6-4f36-AD75-5E1390BD9929\r
+  MODULE_TYPE                    = DXE_SMM_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  PI_SPECIFICATION_VERSION       = 0x0001000A\r
+  ENTRY_POINT                    = InitializeQNCSmmDispatcher\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  QNC/QNCSmmPeriodicTimer.c\r
+  QNC/QNCSmmQncn.c\r
+  QNC/QNCSmmSx.c\r
+  QNC/QNCSmmSw.c\r
+  QNC/QNCSmmGpi.c\r
+  QNC/QNCSmmHelpers.c\r
+  QNCSmmHelpers.c\r
+  QNCSmmCore.c\r
+  QNCSmmHelpers.h\r
+  QNCxSmmHelpers.h\r
+  QNCSmmRegisters.h\r
+  QNCSmm.h\r
+  CommonHeader.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+\r
+[LibraryClasses]\r
+  UefiDriverEntryPoint\r
+  SmmServicesTableLib\r
+  UefiBootServicesTableLib\r
+  DxeServicesTableLib\r
+  MemoryAllocationLib\r
+  PciLib\r
+  PcdLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  BaseLib\r
+  IoLib\r
+  DevicePathLib\r
+  S3IoLib\r
+  QNCAccessLib\r
+\r
+[Protocols]\r
+  gEfiSmmCpuProtocolGuid                        # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiSmmReadyToLockProtocolGuid                # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiSmmPeriodicTimerDispatch2ProtocolGuid     # PROTOCOL ALWAYS_PRODUCED\r
+  gEfiSmmPowerButtonDispatch2ProtocolGuid       # PROTOCOL ALWAYS_PRODUCED\r
+  gEfiSmmIchnDispatch2ProtocolGuid              # PROTOCOL ALWAYS_PRODUCED\r
+  gEfiSmmGpiDispatch2ProtocolGuid               # PROTOCOL ALWAYS_PRODUCED\r
+  gEfiSmmSwDispatch2ProtocolGuid                # PROTOCOL ALWAYS_PRODUCED\r
+  gEfiSmmSxDispatch2ProtocolGuid                # PROTOCOL ALWAYS_PRODUCED\r
+  gEfiSmmUsbDispatch2ProtocolGuid               # PROTOCOL ALWAYS_PRODUCED\r
+  gEfiSmmIoTrapDispatch2ProtocolGuid            # PROTOCOL ALWAYS_PRODUCED\r
+\r
+[Pcd]\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress\r
+\r
+[Depex]\r
+  gEfiSmmCpuProtocolGuid AND gEfiPciRootBridgeIoProtocolGuid\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmHelpers.c b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmHelpers.c
new file mode 100644 (file)
index 0000000..db61029
--- /dev/null
@@ -0,0 +1,373 @@
+/** @file\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+#include "QNCSmm.h"\r
+#include "QNCSmmHelpers.h"\r
+\r
+//\r
+// #define BIT_ZERO 0x00000001\r
+//\r
+CONST UINT32  BIT_ZERO = 0x00000001;\r
+\r
+//\r
+// /////////////////////////////////////////////////////////////////////////////\r
+// SUPPORT / HELPER FUNCTIONS (QNC version-independent)\r
+//\r
+BOOLEAN\r
+CompareEnables (\r
+  CONST IN QNC_SMM_SOURCE_DESC *Src1,\r
+  CONST IN QNC_SMM_SOURCE_DESC *Src2\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Src1  - GC_TODO: add argument description\r
+  Src2  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  BOOLEAN IsEqual;\r
+  UINTN   loopvar;\r
+\r
+  IsEqual = TRUE;\r
+  for (loopvar = 0; loopvar < NUM_EN_BITS; loopvar++) {\r
+    //\r
+    // It's okay to compare a NULL bit description to a non-NULL bit description.\r
+    // They are unequal and these tests will generate the correct result.\r
+    //\r
+    if (Src1->En[loopvar].Bit != Src2->En[loopvar].Bit ||\r
+        Src1->En[loopvar].Reg.Type != Src2->En[loopvar].Reg.Type ||\r
+        Src1->En[loopvar].Reg.Data.raw != Src2->En[loopvar].Reg.Data.raw\r
+        ) {\r
+      IsEqual = FALSE;\r
+      break;\r
+      //\r
+      // out of for loop\r
+      //\r
+    }\r
+  }\r
+\r
+  return IsEqual;\r
+}\r
+\r
+BOOLEAN\r
+CompareStatuses (\r
+  CONST IN QNC_SMM_SOURCE_DESC *Src1,\r
+  CONST IN QNC_SMM_SOURCE_DESC *Src2\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Src1  - GC_TODO: add argument description\r
+  Src2  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  BOOLEAN IsEqual;\r
+  UINTN   loopvar;\r
+\r
+  IsEqual = TRUE;\r
+\r
+  for (loopvar = 0; loopvar < NUM_STS_BITS; loopvar++) {\r
+    //\r
+    // It's okay to compare a NULL bit description to a non-NULL bit description.\r
+    // They are unequal and these tests will generate the correct result.\r
+    //\r
+    if (Src1->Sts[loopvar].Bit != Src2->Sts[loopvar].Bit ||\r
+        Src1->Sts[loopvar].Reg.Type != Src2->Sts[loopvar].Reg.Type ||\r
+        Src1->Sts[loopvar].Reg.Data.raw != Src2->Sts[loopvar].Reg.Data.raw\r
+        ) {\r
+      IsEqual = FALSE;\r
+      break;\r
+      //\r
+      // out of for loop\r
+      //\r
+    }\r
+  }\r
+\r
+  return IsEqual;\r
+}\r
+\r
+BOOLEAN\r
+CompareSources (\r
+  CONST IN QNC_SMM_SOURCE_DESC *Src1,\r
+  CONST IN QNC_SMM_SOURCE_DESC *Src2\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Src1  - GC_TODO: add argument description\r
+  Src2  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  return (BOOLEAN) (CompareEnables (Src1, Src2) && CompareStatuses (Src1, Src2));\r
+}\r
+\r
+BOOLEAN\r
+SourceIsActive (\r
+  CONST IN QNC_SMM_SOURCE_DESC *Src\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Src - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  BOOLEAN IsActive;\r
+  UINTN   loopvar;\r
+\r
+  BOOLEAN SciEn;\r
+\r
+  IsActive  = TRUE;\r
+\r
+  SciEn     = QNCSmmGetSciEn ();\r
+\r
+  if ((Src->Flags & QNC_SMM_SCI_EN_DEPENDENT) && (SciEn)) {\r
+    //\r
+    // This source is dependent on SciEn, and SciEn == 1.  An ACPI OS is present,\r
+    // so we shouldn't do anything w/ this source until SciEn == 0.\r
+    //\r
+    IsActive = FALSE;\r
+\r
+  } else {\r
+    //\r
+    // Read each bit desc from hardware and make sure it's a one\r
+    //\r
+    for (loopvar = 0; loopvar < NUM_EN_BITS; loopvar++) {\r
+\r
+      if (!IS_BIT_DESC_NULL (Src->En[loopvar])) {\r
+\r
+        if (ReadBitDesc (&Src->En[loopvar]) == 0) {\r
+          IsActive = FALSE;\r
+          break;\r
+          //\r
+          // out of for loop\r
+          //\r
+        }\r
+\r
+      }\r
+    }\r
+\r
+    if (IsActive) {\r
+      //\r
+      // Read each bit desc from hardware and make sure it's a one\r
+      //\r
+      for (loopvar = 0; loopvar < NUM_STS_BITS; loopvar++) {\r
+\r
+        if (!IS_BIT_DESC_NULL (Src->Sts[loopvar])) {\r
+\r
+          if (ReadBitDesc (&Src->Sts[loopvar]) == 0) {\r
+            IsActive = FALSE;\r
+            break;\r
+            //\r
+            // out of for loop\r
+            //\r
+          }\r
+\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  return IsActive;\r
+}\r
+\r
+VOID\r
+QNCSmmEnableSource (\r
+  CONST QNC_SMM_SOURCE_DESC *SrcDesc\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  SrcDesc - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  UINTN loopvar;\r
+\r
+  //\r
+  // Set enables to 1 by writing a 1\r
+  //\r
+  for (loopvar = 0; loopvar < NUM_EN_BITS; loopvar++) {\r
+    if (!IS_BIT_DESC_NULL (SrcDesc->En[loopvar])) {\r
+      WriteBitDesc (&SrcDesc->En[loopvar], 1);\r
+    }\r
+  }\r
+\r
+  QNCSmmClearSource (SrcDesc);\r
+\r
+}\r
+\r
+VOID\r
+QNCSmmDisableSource (\r
+  CONST QNC_SMM_SOURCE_DESC *SrcDesc\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  SrcDesc - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  UINTN loopvar;\r
+\r
+  for (loopvar = 0; loopvar < NUM_EN_BITS; loopvar++) {\r
+    if (!IS_BIT_DESC_NULL (SrcDesc->En[loopvar])) {\r
+      WriteBitDesc (&SrcDesc->En[loopvar], 0);\r
+    }\r
+  }\r
+}\r
+\r
+VOID\r
+QNCSmmClearSource (\r
+  CONST QNC_SMM_SOURCE_DESC *SrcDesc\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  SrcDesc - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  UINTN loopvar;\r
+  BOOLEAN ValueToWrite;\r
+\r
+  ValueToWrite =\r
+    ((SrcDesc->Flags & QNC_SMM_CLEAR_WITH_ZERO) == 0) ? TRUE : FALSE;\r
+\r
+  for (loopvar = 0; loopvar < NUM_STS_BITS; loopvar++) {\r
+    if (!IS_BIT_DESC_NULL (SrcDesc->Sts[loopvar])) {\r
+      WriteBitDesc (&SrcDesc->Sts[loopvar], ValueToWrite);\r
+    }\r
+  }\r
+}\r
+\r
+VOID\r
+QNCSmmClearSourceAndBlock (\r
+  CONST QNC_SMM_SOURCE_DESC *SrcDesc\r
+  )\r
+// GC_TODO: function comment should start with '/*++'\r
+/*\r
+  Sets the source to a 1 or 0 and then waits for it to clear.\r
+  Be very careful when calling this function -- it will not\r
+  ASSERT.  An acceptable case to call the function is when\r
+  waiting for the NEWCENTURY_STS bit to clear (which takes\r
+  3 RTCCLKs).\r
+*/\r
+// GC_TODO: function comment should end with '--*/'\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO:    SrcDesc - add argument and description to function comment\r
+{\r
+  UINTN   loopvar;\r
+  BOOLEAN IsSet;\r
+  BOOLEAN ValueToWrite;\r
+\r
+  ValueToWrite =\r
+    ((SrcDesc->Flags & QNC_SMM_CLEAR_WITH_ZERO) == 0) ? TRUE : FALSE;\r
+\r
+  for (loopvar = 0; loopvar < NUM_STS_BITS; loopvar++) {\r
+\r
+    if (!IS_BIT_DESC_NULL (SrcDesc->Sts[loopvar])) {\r
+      //\r
+      // Write the bit\r
+      //\r
+      WriteBitDesc (&SrcDesc->Sts[loopvar], ValueToWrite);\r
+\r
+      //\r
+      // Don't return until the bit actually clears.\r
+      //\r
+      IsSet = TRUE;\r
+      while (IsSet) {\r
+        IsSet = ReadBitDesc (&SrcDesc->Sts[loopvar]);\r
+        //\r
+        // IsSet will eventually clear -- or else we'll have\r
+        // an infinite loop.\r
+        //\r
+      }\r
+    }\r
+  }\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmHelpers.h b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmHelpers.h
new file mode 100644 (file)
index 0000000..d2572d3
--- /dev/null
@@ -0,0 +1,225 @@
+/** @file\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef QNC_SMM_HELPERS_H\r
+#define QNC_SMM_HELPERS_H\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+#include "QNCSmm.h"\r
+#include "QNCxSmmHelpers.h"\r
+\r
+//\r
+// /////////////////////////////////////////////////////////////////////////////\r
+// SUPPORT / HELPER FUNCTIONS (QNC version-independent)\r
+//\r
+VOID\r
+QNCSmmPublishDispatchProtocols (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+BOOLEAN\r
+CompareEnables (\r
+  CONST IN QNC_SMM_SOURCE_DESC *Src1,\r
+  CONST IN QNC_SMM_SOURCE_DESC *Src2\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Src1  - GC_TODO: add argument description\r
+  Src2  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+BOOLEAN\r
+CompareStatuses (\r
+  CONST IN QNC_SMM_SOURCE_DESC *Src1,\r
+  CONST IN QNC_SMM_SOURCE_DESC *Src2\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Src1  - GC_TODO: add argument description\r
+  Src2  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+BOOLEAN\r
+CompareSources (\r
+  CONST IN QNC_SMM_SOURCE_DESC *Src1,\r
+  CONST IN QNC_SMM_SOURCE_DESC *Src2\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Src1  - GC_TODO: add argument description\r
+  Src2  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+BOOLEAN\r
+SourceIsActive (\r
+  CONST IN QNC_SMM_SOURCE_DESC *Src\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Src - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+QNCSmmEnableSource (\r
+  CONST QNC_SMM_SOURCE_DESC *SrcDesc\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  SrcDesc - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+QNCSmmDisableSource (\r
+  CONST QNC_SMM_SOURCE_DESC *SrcDesc\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  SrcDesc - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+QNCSmmClearSource (\r
+  CONST QNC_SMM_SOURCE_DESC *SrcDesc\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  SrcDesc - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+QNCSmmClearSourceAndBlock (\r
+  CONST QNC_SMM_SOURCE_DESC *SrcDesc\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  SrcDesc - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmRegisters.h b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmRegisters.h
new file mode 100644 (file)
index 0000000..3474c56
--- /dev/null
@@ -0,0 +1,19 @@
+/** @file\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef QNC_SMM_REGISTERS_H\r
+#define QNC_SMM_REGISTERS_H\r
+#include "CommonHeader.h"\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCxSmmHelpers.h b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCxSmmHelpers.h
new file mode 100644 (file)
index 0000000..53027c4
--- /dev/null
@@ -0,0 +1,184 @@
+/** @file\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef QNCX_SMM_HELPERS_H\r
+#define QNCX_SMM_HELPERS_H\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+#include "QNCSmm.h"\r
+\r
+EFI_STATUS\r
+QNCSmmInitHardware (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+QNCSmmEnableGlobalSmiBit (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Enables the QNC to generate SMIs. Note that no SMIs will be generated\r
+  if no SMI sources are enabled. Conversely, no enabled SMI source will\r
+  generate SMIs if SMIs are not globally enabled. This is the main\r
+  switchbox for SMI generation.\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS.\r
+  Asserts, otherwise.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+QNCSmmClearSmi (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+BOOLEAN\r
+QNCSmmSetAndCheckEos (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+BOOLEAN\r
+QNCSmmGetSciEn (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+//\r
+// ///////////////////////////////////////////////////////////////////////////\r
+//\r
+// These may or may not need to change w/ the QNC version;\r
+// they're here because they're highly IA-32 dependent.\r
+//\r
+BOOLEAN\r
+ReadBitDesc (\r
+  CONST QNC_SMM_BIT_DESC *BitDesc\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  BitDesc - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+WriteBitDesc (\r
+  CONST QNC_SMM_BIT_DESC  *BitDesc,\r
+  CONST BOOLEAN          ValueToWrite\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  BitDesc       - GC_TODO: add argument description\r
+  ValueToWrite  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.c b/QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.c
new file mode 100644 (file)
index 0000000..70fdf09
--- /dev/null
@@ -0,0 +1,382 @@
+/** @file\r
+This is the driver that publishes the SMM Access Ppi\r
+instance for the Quark SOC.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include <PiPei.h>\r
+#include <Ppi/SmmAccess.h>\r
+#include <Guid/SmramMemoryReserve.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/PciLib.h>\r
+#include <Library/PeiServicesLib.h>\r
+#include <Library/QNCSmmLib.h>\r
+#include <QNCAccess.h>\r
+\r
+#define SMM_ACCESS_PRIVATE_DATA_FROM_THIS(a) \\r
+  CR ( \\r
+  a, \\r
+  SMM_ACCESS_PRIVATE_DATA, \\r
+  SmmAccess, \\r
+  SMM_ACCESS_PRIVATE_DATA_SIGNATURE \\r
+  )\r
+\r
+#define MAX_CPU_SOCKET      1\r
+#define MAX_SMRAM_RANGES    4\r
+\r
+typedef struct {\r
+  UINTN                            Signature;\r
+  EFI_HANDLE                       Handle;\r
+  PEI_SMM_ACCESS_PPI               SmmAccess;\r
+  UINTN                            NumberRegions;\r
+  EFI_SMRAM_DESCRIPTOR             SmramDesc[MAX_SMRAM_RANGES];\r
+  UINT8                            TsegSize;\r
+  UINT8                            MaxBusNumber;\r
+  UINT8                            SocketPopulated[MAX_CPU_SOCKET];\r
+  UINT8                            SocketBusNum[MAX_CPU_SOCKET];\r
+} SMM_ACCESS_PRIVATE_DATA;\r
+\r
+#define  SMM_ACCESS_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('i', 's', 'm', 'a')\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Open (\r
+  IN EFI_PEI_SERVICES           **PeiServices,\r
+  IN PEI_SMM_ACCESS_PPI         *This,\r
+  IN UINTN                      DescriptorIndex\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine accepts a request to "open" a region of SMRAM.  The\r
+  region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.\r
+  The use of "open" means that the memory is visible from all PEIM\r
+  and SMM agents.\r
+\r
+Arguments:\r
+\r
+  PeiServices      - General purpose services available to every PEIM.\r
+  This             -  Pointer to the SMM Access Interface.\r
+  DescriptorIndex  -  Region of SMRAM to Open.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS            -  The region was successfully opened.\r
+  EFI_DEVICE_ERROR       -  The region could not be opened because locked by\r
+                            chipset.\r
+  EFI_INVALID_PARAMETER  -  The descriptor index was out of bounds.\r
+\r
+--*/\r
+{\r
+  SMM_ACCESS_PRIVATE_DATA *SmmAccess;\r
+\r
+  SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  if (DescriptorIndex >= SmmAccess->NumberRegions) {\r
+    return EFI_INVALID_PARAMETER;\r
+  } else if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_LOCKED) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Open TSEG\r
+  //\r
+  if (!QNCOpenSmramRegion ()) {\r
+    SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED;\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  SmmAccess->SmramDesc[DescriptorIndex].RegionState &= ~(EFI_SMRAM_CLOSED | EFI_ALLOCATED);\r
+  SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_OPEN;\r
+  SmmAccess->SmmAccess.OpenState = TRUE;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Close (\r
+  IN EFI_PEI_SERVICES        **PeiServices,\r
+  IN PEI_SMM_ACCESS_PPI      *This,\r
+  IN UINTN                   DescriptorIndex\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine accepts a request to "close" a region of SMRAM.  This is valid for\r
+  compatible SMRAM region.\r
+\r
+Arguments:\r
+\r
+  PeiServices      - General purpose services available to every PEIM.\r
+  This             -  Pointer to the SMM Access Interface.\r
+  DescriptorIndex  -  Region of SMRAM to Close.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS            -  The region was successfully closed.\r
+  EFI_DEVICE_ERROR       -  The region could not be closed because locked by\r
+                            chipset.\r
+  EFI_INVALID_PARAMETER  -  The descriptor index was out of bounds.\r
+\r
+--*/\r
+{\r
+  SMM_ACCESS_PRIVATE_DATA *SmmAccess;\r
+  BOOLEAN                 OpenState;\r
+  UINTN                   Index;\r
+\r
+\r
+  SmmAccess     = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  if (DescriptorIndex >= SmmAccess->NumberRegions) {\r
+    return EFI_INVALID_PARAMETER;\r
+  } else if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_LOCKED) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_CLOSED) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Close TSEG\r
+  //\r
+  if (!QNCCloseSmramRegion ()) {\r
+    SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED;\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  SmmAccess->SmramDesc[DescriptorIndex].RegionState &= ~EFI_SMRAM_OPEN;\r
+  SmmAccess->SmramDesc[DescriptorIndex].RegionState |= (EFI_SMRAM_CLOSED | EFI_ALLOCATED);\r
+\r
+  //\r
+  // Find out if any regions are still open\r
+  //\r
+  OpenState = FALSE;\r
+  for (Index = 0; Index < SmmAccess->NumberRegions; Index++) {\r
+    if ((SmmAccess->SmramDesc[Index].RegionState & EFI_SMRAM_OPEN) == EFI_SMRAM_OPEN) {\r
+      OpenState = TRUE;\r
+    }\r
+  }\r
+\r
+  SmmAccess->SmmAccess.OpenState = OpenState;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Lock (\r
+  IN EFI_PEI_SERVICES          **PeiServices,\r
+  IN PEI_SMM_ACCESS_PPI        *This,\r
+  IN UINTN                     DescriptorIndex\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine accepts a request to "lock" SMRAM.  The\r
+  region could be legacy AB or TSEG near top of physical memory.\r
+  The use of "lock" means that the memory can no longer be opened\r
+  to PEIM.\r
+\r
+Arguments:\r
+\r
+  PeiServices      - General purpose services available to every PEIM.\r
+  This             -  Pointer to the SMM Access Interface.\r
+  DescriptorIndex  -  Region of SMRAM to Lock.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS            -  The region was successfully locked.\r
+  EFI_DEVICE_ERROR       -  The region could not be locked because at least\r
+                            one range is still open.\r
+  EFI_INVALID_PARAMETER  -  The descriptor index was out of bounds.\r
+\r
+--*/\r
+{\r
+  SMM_ACCESS_PRIVATE_DATA *SmmAccess;\r
+\r
+  SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  if (DescriptorIndex >= SmmAccess->NumberRegions) {\r
+    return EFI_INVALID_PARAMETER;\r
+  } else if (SmmAccess->SmmAccess.OpenState) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED;\r
+  SmmAccess->SmmAccess.LockState                     = TRUE;\r
+\r
+  //\r
+  // Lock TSEG\r
+  //\r
+  QNCLockSmramRegion ();\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+GetCapabilities (\r
+  IN EFI_PEI_SERVICES                **PeiServices,\r
+  IN PEI_SMM_ACCESS_PPI              *This,\r
+  IN OUT UINTN                       *SmramMapSize,\r
+  IN OUT EFI_SMRAM_DESCRIPTOR        *SmramMap\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine services a user request to discover the SMRAM\r
+  capabilities of this platform.  This will report the possible\r
+  ranges that are possible for SMRAM access, based upon the\r
+  memory controller capabilities.\r
+\r
+Arguments:\r
+\r
+  PeiServices   - General purpose services available to every PEIM.\r
+  This          -  Pointer to the SMRAM Access Interface.\r
+  SmramMapSize  -  Pointer to the variable containing size of the\r
+                   buffer to contain the description information.\r
+  SmramMap      -  Buffer containing the data describing the Smram\r
+                   region descriptors.\r
+Returns:\r
+\r
+  EFI_BUFFER_TOO_SMALL  -  The user did not provide a sufficient buffer.\r
+  EFI_SUCCESS           -  The user provided a sufficiently-sized buffer.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                Status;\r
+  SMM_ACCESS_PRIVATE_DATA  *SmmAccess;\r
+  UINTN                     BufferSize;\r
+\r
+  SmmAccess           = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);\r
+  BufferSize          = SmmAccess->NumberRegions * sizeof (EFI_SMRAM_DESCRIPTOR);\r
+\r
+  if (*SmramMapSize < BufferSize) {\r
+    Status = EFI_BUFFER_TOO_SMALL;\r
+  } else {\r
+    CopyMem (SmramMap, SmmAccess->SmramDesc, *SmramMapSize);\r
+    Status = EFI_SUCCESS;\r
+  }\r
+\r
+  *SmramMapSize = BufferSize;\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SmmAccessPeiEntryPoint (\r
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,\r
+  IN CONST EFI_PEI_SERVICES     **PeiServices\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    This is the constructor for the SMM Access Ppi\r
+\r
+Arguments:\r
+\r
+    FfsHeader       - FfsHeader.\r
+    PeiServices     - General purpose services available to every PEIM.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS     -  Protocol successfully started and installed.\r
+  EFI_UNSUPPORTED -  Protocol can't be started.\r
+--*/\r
+{\r
+\r
+  EFI_STATUS                      Status;\r
+  UINTN                           Index;\r
+  EFI_SMRAM_HOB_DESCRIPTOR_BLOCK  *DescriptorBlock;\r
+  SMM_ACCESS_PRIVATE_DATA         *SmmAccessPrivate;\r
+  EFI_PEI_PPI_DESCRIPTOR          *PpiList;\r
+  EFI_HOB_GUID_TYPE               *GuidHob;\r
+\r
+  //\r
+  // Initialize private data\r
+  //\r
+  SmmAccessPrivate = AllocatePool (sizeof(*SmmAccessPrivate));\r
+  ASSERT(SmmAccessPrivate);\r
+\r
+  PpiList = AllocatePool (sizeof(*PpiList));\r
+  ASSERT (PpiList);\r
+\r
+  //\r
+  // Build SMM related information\r
+  //\r
+  SmmAccessPrivate->Signature = SMM_ACCESS_PRIVATE_DATA_SIGNATURE;\r
+\r
+  //\r
+  // Get Hob list\r
+  //\r
+  GuidHob    = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);\r
+  DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);\r
+  ASSERT (DescriptorBlock);\r
+\r
+  // Get CPU Max bus number\r
+\r
+  SmmAccessPrivate->MaxBusNumber = PCI_BUS_NUMBER_QNC;\r
+  for (Index = 0; Index < MAX_CPU_SOCKET; Index++) {\r
+    SmmAccessPrivate->SocketPopulated[Index] = TRUE;\r
+    SmmAccessPrivate->SocketBusNum[Index]    = PCI_BUS_NUMBER_QNC;\r
+  }\r
+\r
+  //\r
+  // Use the hob to publish SMRAM capabilities\r
+  //\r
+  ASSERT (DescriptorBlock->NumberOfSmmReservedRegions <= MAX_SMRAM_RANGES);\r
+  for (Index = 0; Index < DescriptorBlock->NumberOfSmmReservedRegions; Index++) {\r
+    SmmAccessPrivate->SmramDesc[Index].PhysicalStart = DescriptorBlock->Descriptor[Index].PhysicalStart;\r
+    SmmAccessPrivate->SmramDesc[Index].CpuStart      = DescriptorBlock->Descriptor[Index].CpuStart;\r
+    SmmAccessPrivate->SmramDesc[Index].PhysicalSize  = DescriptorBlock->Descriptor[Index].PhysicalSize;\r
+    SmmAccessPrivate->SmramDesc[Index].RegionState   = DescriptorBlock->Descriptor[Index].RegionState;\r
+  }\r
+\r
+  SmmAccessPrivate->NumberRegions              = Index;\r
+  SmmAccessPrivate->SmmAccess.Open             = Open;\r
+  SmmAccessPrivate->SmmAccess.Close            = Close;\r
+  SmmAccessPrivate->SmmAccess.Lock             = Lock;\r
+  SmmAccessPrivate->SmmAccess.GetCapabilities  = GetCapabilities;\r
+  SmmAccessPrivate->SmmAccess.LockState        = FALSE;\r
+  SmmAccessPrivate->SmmAccess.OpenState        = FALSE;\r
+\r
+  PpiList->Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);\r
+  PpiList->Guid  = &gPeiSmmAccessPpiGuid;\r
+  PpiList->Ppi   = &SmmAccessPrivate->SmmAccess;\r
+\r
+  Status      = (**PeiServices).InstallPpi (PeiServices, PpiList);\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  DEBUG (\r
+    (EFI_D_INFO, "SMM Base:Size %08X:%08X\n",\r
+    (UINTN)(SmmAccessPrivate->SmramDesc[SmmAccessPrivate->NumberRegions-1].PhysicalStart),\r
+    (UINTN)(SmmAccessPrivate->SmramDesc[SmmAccessPrivate->NumberRegions-1].PhysicalSize)\r
+    ));\r
+\r
+  SmmAccessPrivate->TsegSize = (UINT8)(SmmAccessPrivate->SmramDesc[SmmAccessPrivate->NumberRegions-1].PhysicalSize);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.inf b/QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.inf
new file mode 100644 (file)
index 0000000..a1e4af7
--- /dev/null
@@ -0,0 +1,51 @@
+## @file\r
+# Component description file for SmmAccessPei module\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+INF_VERSION          = 0x00010005\r
+BASE_NAME            = SmmAccessPei\r
+FILE_GUID            = B4E0CDFC-30CD-4b29-A445-B0AA95A532E4\r
+MODULE_TYPE          = PEIM\r
+VERSION_STRING       = 1.0\r
+ENTRY_POINT          = SmmAccessPeiEntryPoint\r
+\r
+[Sources]\r
+  SmmAccessPei.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  PeimEntryPoint\r
+  BaseMemoryLib\r
+  MemoryAllocationLib\r
+  DebugLib\r
+  HobLib\r
+  PeiServicesLib\r
+  PciLib\r
+  SmmLib\r
+\r
+[Guids]\r
+  gEfiSmmPeiSmramMemoryReserveGuid             # ALWAYS_CONSUMED\r
+\r
+[Ppis]\r
+  gPeiSmmAccessPpiGuid                         # ALWAYS_PRODUCED\r
+  gEfiPeiMemoryDiscoveredPpiGuid               # ALWAYS_CONSUMED\r
+\r
+[Depex]\r
+  gEfiPeiMemoryDiscoveredPpiGuid\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmControlPei/SmmControlPei.c b/QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmControlPei/SmmControlPei.c
new file mode 100644 (file)
index 0000000..8c82611
--- /dev/null
@@ -0,0 +1,282 @@
+/** @file\r
+This module provides an implementation of the SMM Control PPI for use with\r
+the QNC.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+\r
+#include <Ppi/SmmControl.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/PeiServicesLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PciLib.h>\r
+\r
+#include <IntelQNCPeim.h>\r
+#include <Library/QNCAccessLib.h>\r
+#include <Uefi/UefiBaseType.h>\r
+\r
+/**\r
+  Generates an SMI using the parameters passed in.\r
+\r
+  @param  PeiServices         Describes the list of possible PEI Services.\r
+  @param  This                A pointer to an instance of\r
+                              EFI_SMM_CONTROL_PPI\r
+  @param  ArgumentBuffer      The argument buffer\r
+  @param  ArgumentBufferSize  The size of the argument buffer\r
+  @param  Periodic            TRUE to indicate a periodical SMI\r
+  @param  ActivationInterval  Interval of the periodical SMI\r
+\r
+  @retval EFI_INVALID_PARAMETER  Periodic is TRUE or ArgumentBufferSize > 1\r
+  @retval EFI_SUCCESS            SMI generated\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeiActivate (\r
+  IN      EFI_PEI_SERVICES           **PeiServices,\r
+  IN      PEI_SMM_CONTROL_PPI        *This,\r
+  IN OUT  INT8                       *ArgumentBuffer OPTIONAL,\r
+  IN OUT  UINTN                      *ArgumentBufferSize OPTIONAL,\r
+  IN      BOOLEAN                    Periodic OPTIONAL,\r
+  IN      UINTN                      ActivationInterval OPTIONAL\r
+  );\r
+\r
+/**\r
+  Clears an SMI.\r
+\r
+  @param  PeiServices         Describes the list of possible PEI Services.\r
+  @param  This                Pointer to an instance of EFI_SMM_CONTROL_PPI\r
+  @param  Periodic            TRUE to indicate a periodical SMI\r
+\r
+  @return Return value from SmmClear()\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeiDeactivate (\r
+  IN  EFI_PEI_SERVICES            **PeiServices,\r
+  IN  PEI_SMM_CONTROL_PPI         *This,\r
+  IN  BOOLEAN                     Periodic OPTIONAL\r
+  );\r
+\r
+PEI_SMM_CONTROL_PPI      mSmmControlPpi = {\r
+  PeiActivate,\r
+  PeiDeactivate\r
+};\r
+\r
+EFI_PEI_PPI_DESCRIPTOR   mPpiList = {\r
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+  &gPeiSmmControlPpiGuid,\r
+  &mSmmControlPpi\r
+};\r
+\r
+/**\r
+  Clear SMI related chipset status and re-enable SMI by setting the EOS bit.\r
+\r
+  @retval EFI_SUCCESS       The requested operation has been carried out successfully\r
+  @retval EFI_DEVICE_ERROR  The EOS bit could not be set.\r
+\r
+**/\r
+EFI_STATUS\r
+SmmClear (\r
+  VOID\r
+  )\r
+{\r
+  UINT16                       PM1BLK_Base;\r
+  UINT16                       GPE0BLK_Base;\r
+\r
+  //\r
+  // Get PM1BLK_Base & GPE0BLK_Base\r
+  //\r
+  PM1BLK_Base  = PcdGet16 (PcdPm1blkIoBaseAddress);\r
+  GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress);\r
+\r
+  //\r
+  // Clear the Power Button Override Status Bit, it gates EOS from being set.\r
+  // In QuarkNcSocId - Bit is read only. Handled by external SMC, do nothing.\r
+  //\r
+\r
+  //\r
+  // Clear the APM SMI Status Bit\r
+  //\r
+  IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_APM);\r
+\r
+  //\r
+  // Set the EOS Bit\r
+  //\r
+  IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SmmTrigger (\r
+  IN UINT8   Data\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Trigger the software SMI\r
+\r
+Arguments:\r
+\r
+  Data                          The value to be set on the software SMI data port\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS                   Function completes successfully\r
+\r
+--*/\r
+{\r
+  UINT16        GPE0BLK_Base;\r
+  UINT32        NewValue;\r
+\r
+  //\r
+  // Get GPE0BLK_Base\r
+  //\r
+  GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress);\r
+\r
+  //\r
+  // Enable the APMC SMI\r
+  //\r
+  IoOr32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIE, B_QNC_GPE0BLK_SMIE_APM);\r
+\r
+  //\r
+  // Enable SMI globally\r
+  //\r
+  NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);\r
+  NewValue |= SMI_EN;\r
+  QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);\r
+\r
+\r
+  //\r
+  // Generate the APMC SMI\r
+  //\r
+  IoWrite8 (PcdGet16 (PcdSmmActivationPort), Data);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Generates an SMI using the parameters passed in.\r
+\r
+  @param  PeiServices         Describes the list of possible PEI Services.\r
+  @param  This                A pointer to an instance of\r
+                              EFI_SMM_CONTROL_PPI\r
+  @param  ArgumentBuffer      The argument buffer\r
+  @param  ArgumentBufferSize  The size of the argument buffer\r
+  @param  Periodic            TRUE to indicate a periodical SMI\r
+  @param  ActivationInterval  Interval of the periodical SMI\r
+\r
+  @retval EFI_INVALID_PARAMETER  Periodic is TRUE or ArgumentBufferSize > 1\r
+  @retval EFI_SUCCESS            SMI generated\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeiActivate (\r
+  IN      EFI_PEI_SERVICES           **PeiServices,\r
+  IN      PEI_SMM_CONTROL_PPI        *This,\r
+  IN OUT  INT8                       *ArgumentBuffer OPTIONAL,\r
+  IN OUT  UINTN                      *ArgumentBufferSize OPTIONAL,\r
+  IN      BOOLEAN                    Periodic OPTIONAL,\r
+  IN      UINTN                      ActivationInterval OPTIONAL\r
+  )\r
+{\r
+  INT8       Data;\r
+  EFI_STATUS Status;\r
+  //\r
+  // Periodic SMI not supported.\r
+  //\r
+  if (Periodic) {\r
+    DEBUG ((DEBUG_WARN, "Invalid parameter\n"));\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (ArgumentBuffer == NULL) {\r
+    Data = 0xFF;\r
+  } else {\r
+    if (ArgumentBufferSize == NULL || *ArgumentBufferSize != 1) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    Data = *ArgumentBuffer;\r
+  }\r
+  //\r
+  // Clear any pending the APM SMI\r
+  //\r
+  Status = SmmClear ();\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return SmmTrigger (Data);\r
+}\r
+\r
+/**\r
+  Clears an SMI.\r
+\r
+  @param  PeiServices         Describes the list of possible PEI Services.\r
+  @param  This                Pointer to an instance of EFI_SMM_CONTROL_PPI\r
+  @param  Periodic            TRUE to indicate a periodical SMI\r
+\r
+  @return Return value from SmmClear()\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeiDeactivate (\r
+  IN  EFI_PEI_SERVICES            **PeiServices,\r
+  IN  PEI_SMM_CONTROL_PPI         *This,\r
+  IN  BOOLEAN                     Periodic OPTIONAL\r
+  )\r
+{\r
+  if (Periodic) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  return SmmClear ();\r
+}\r
+\r
+/**\r
+  This is the constructor for the SMM Control Ppi.\r
+\r
+  This function installs EFI_SMM_CONTROL_PPI.\r
+\r
+  @param   FileHandle       Handle of the file being invoked.\r
+  @param   PeiServices      Describes the list of possible PEI Services.\r
+\r
+  @retval EFI_UNSUPPORTED There's no Intel ICH on this platform\r
+  @return The status returned from InstallPpi().\r
+\r
+--*/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmControlPeiEntry (\r
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,\r
+  IN CONST EFI_PEI_SERVICES     **PeiServices\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status      = (**PeiServices).InstallPpi (PeiServices, &mPpiList);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmControlPei/SmmControlPei.inf b/QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmControlPei/SmmControlPei.inf
new file mode 100644 (file)
index 0000000..6b1dd1b
--- /dev/null
@@ -0,0 +1,57 @@
+## @file\r
+# Component description file for SmmControlPei module.\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = SmmControlPei\r
+  FILE_GUID                      = 60EC7720-512B-4490-9FD1-A336769AE01F\r
+  MODULE_TYPE                    = PEIM\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = SmmControlPeiEntry\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources]\r
+  SmmControlPei.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  PeimEntryPoint\r
+  DebugLib\r
+  PeiServicesLib\r
+  PcdLib\r
+  IoLib\r
+  PciLib\r
+  QNCAccessLib\r
+\r
+[Ppis]\r
+  gPeiSmmControlPpiGuid                        # ALWAYS_PRODUCED\r
+\r
+[Pcd]\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmActivationPort\r
+\r
+[Depex]\r
+  TRUE\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Spi/Common/SpiCommon.c b/QuarkSocPkg/QuarkNorthCluster/Spi/Common/SpiCommon.c
new file mode 100644 (file)
index 0000000..e3d9b8f
--- /dev/null
@@ -0,0 +1,956 @@
+/** @file\r
+PCH SPI Common Driver implements the SPI Host Controller Compatibility Interface.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PchSpi.h"\r
+\r
+VOID\r
+FillOutPublicInfoStruct (\r
+  SPI_INSTANCE          *SpiInstance\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Fillout SpiInstance->InitInfo;\r
+\r
+Arguments:\r
+\r
+  SpiInstance   - Pointer to SpiInstance to initialize\r
+\r
+Returns:\r
+\r
+  NONE\r
+\r
+--*/\r
+{\r
+  UINT8         Index;\r
+\r
+  SpiInstance->InitInfo.InitTable = &SpiInstance->SpiInitTable;\r
+\r
+  //\r
+  // Give invalid index in case operation not supported.\r
+  //\r
+  SpiInstance->InitInfo.JedecIdOpcodeIndex = 0xff;\r
+  SpiInstance->InitInfo.OtherOpcodeIndex = 0xff;\r
+  SpiInstance->InitInfo.WriteStatusOpcodeIndex = 0xff;\r
+  SpiInstance->InitInfo.ProgramOpcodeIndex = 0xff;\r
+  SpiInstance->InitInfo.ReadOpcodeIndex = 0xff;\r
+  SpiInstance->InitInfo.EraseOpcodeIndex = 0xff;\r
+  SpiInstance->InitInfo.ReadStatusOpcodeIndex = 0xff;\r
+  SpiInstance->InitInfo.FullChipEraseOpcodeIndex = 0xff;\r
+  for (Index = 0; Index < SPI_NUM_OPCODE; Index++) {\r
+    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationJedecId) {\r
+      SpiInstance->InitInfo.JedecIdOpcodeIndex = Index;\r
+    }\r
+    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationOther) {\r
+      SpiInstance->InitInfo.OtherOpcodeIndex = Index;\r
+    }\r
+    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationWriteStatus) {\r
+      SpiInstance->InitInfo.WriteStatusOpcodeIndex = Index;\r
+    }\r
+    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationProgramData_1_Byte ||\r
+        SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationProgramData_64_Byte) {\r
+      SpiInstance->InitInfo.ProgramOpcodeIndex = Index;\r
+    }\r
+    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationReadData ||\r
+        SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationFastRead ||\r
+        SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationDualOutputFastRead) {\r
+      SpiInstance->InitInfo.ReadOpcodeIndex = Index;\r
+    }\r
+    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationErase_256_Byte ||\r
+        SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationErase_4K_Byte ||\r
+        SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationErase_8K_Byte ||\r
+        SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationErase_64K_Byte) {\r
+      SpiInstance->InitInfo.EraseOpcodeIndex = Index;\r
+    }\r
+    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationReadStatus) {\r
+      SpiInstance->InitInfo.ReadStatusOpcodeIndex = Index;\r
+    }\r
+    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationFullChipErase) {\r
+      SpiInstance->InitInfo.FullChipEraseOpcodeIndex = Index;\r
+    }\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+SpiProtocolConstructor (\r
+  SPI_INSTANCE          *SpiInstance\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Initialize an SPI protocol instance.\r
+  The function will assert in debug if PCH RCBA has not been initialized\r
+\r
+Arguments:\r
+\r
+  SpiInstance   - Pointer to SpiInstance to initialize\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS     The protocol instance was properly initialized\r
+  EFI_UNSUPPORTED The PCH is not supported by this module\r
+\r
+--*/\r
+{\r
+  SpiInstance->InitDone = FALSE;  // Indicate NOT READY.\r
+\r
+  //\r
+  // Check if the current PCH is known and supported by this code\r
+  //\r
+  if (!IsQncSupported ()) {\r
+    DEBUG ((DEBUG_ERROR, "PCH SPI Protocol not supported due to no proper QNC LPC found!\n"));\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  //\r
+  // Initialize the SPI protocol instance\r
+  //\r
+  SpiInstance->Signature            = PCH_SPI_PRIVATE_DATA_SIGNATURE;\r
+  SpiInstance->Handle               = NULL;\r
+  SpiInstance->SpiProtocol.Init     = SpiProtocolInit;\r
+  SpiInstance->SpiProtocol.Lock     = SpiProtocolLock;\r
+  SpiInstance->SpiProtocol.Execute  = SpiProtocolExecute;\r
+  SpiInstance->SpiProtocol.Info     = SpiProtocolInfo;\r
+\r
+  //\r
+  // Sanity check to ensure PCH RCBA initialization has occurred previously.\r
+  //\r
+  SpiInstance->PchRootComplexBar = MmioRead32 (\r
+                                    PciDeviceMmBase (PCI_BUS_NUMBER_QNC,\r
+                                    PCI_DEVICE_NUMBER_QNC_LPC,\r
+                                    PCI_FUNCTION_NUMBER_QNC_LPC) + R_QNC_LPC_RCBA\r
+                                    ) & B_QNC_LPC_RCBA_MASK;\r
+  ASSERT (SpiInstance->PchRootComplexBar != 0);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+UnlockFlashComponents (\r
+  IN      EFI_SPI_PROTOCOL      *This,\r
+  IN      UINT8                 UnlockCmdOpcodeIndex\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Issue unlock command to disable block protection, this only needs to be done once per SPI power on\r
+\r
+Arguments:\r
+\r
+  This                      A pointer to "EFI_SPI_PROTOCOL" for issuing commands\r
+  UnlockCmdOpcodeIndex      The index of the Unlock command\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS               UnLock operation succeed.\r
+  EFI_DEVICE_ERROR          Device error, operation failed.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  SPI_INSTANCE  *SpiInstance;\r
+  UINT8         SpiStatus;\r
+  UINTN         PchRootComplexBar;\r
+\r
+  if (UnlockCmdOpcodeIndex >= SPI_NUM_OPCODE) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);\r
+  PchRootComplexBar = SpiInstance->PchRootComplexBar;\r
+\r
+  //\r
+  // Issue unlock command to disable block protection, this only needs to be done once per SPI power on\r
+  //\r
+  SpiStatus = 0;\r
+  //\r
+  // Issue unlock command to the flash component 1 at first\r
+  //\r
+  Status = SpiProtocolExecute (\r
+            This,\r
+            UnlockCmdOpcodeIndex,\r
+            SpiInstance->SpiInitTable.PrefixOpcode[0] == PCH_SPI_COMMAND_WRITE_ENABLE ? 0 : 1,\r
+            TRUE,\r
+            TRUE,\r
+            TRUE,\r
+            (UINTN) 0,\r
+            sizeof (SpiStatus),\r
+            &SpiStatus,\r
+            EnumSpiRegionAll\r
+            );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "Unlock flash component 1 fail!\n"));\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SpiProtocolInit (\r
+  IN EFI_SPI_PROTOCOL       *This,\r
+  IN SPI_INIT_TABLE         *InitTable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Initialize the host controller to execute SPI command.\r
+\r
+Arguments:\r
+\r
+  This                    Pointer to the EFI_SPI_PROTOCOL instance.\r
+  InitTable               Initialization data to be programmed into the SPI host controller.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             Initialization completed.\r
+  EFI_ACCESS_DENIED       The SPI static configuration interface has been locked-down.\r
+  EFI_INVALID_PARAMETER   Bad input parameters.\r
+  EFI_UNSUPPORTED         Can't get Descriptor mode VSCC values\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  UINT8         Index;\r
+  UINT16        OpcodeType;\r
+  SPI_INSTANCE  *SpiInstance;\r
+  BOOLEAN       MultiPartitionIsSupported;\r
+  UINTN         PchRootComplexBar;\r
+  UINT8         SFDPCmdOpcodeIndex;\r
+  UINT8         UnlockCmdOpcodeIndex;\r
+  UINT8         ReadDataCmdOpcodeIndex;\r
+  UINT8         FlashPartId[3];\r
+\r
+  SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);\r
+  PchRootComplexBar = SpiInstance->PchRootComplexBar;\r
+\r
+  if (InitTable != NULL) {\r
+    //\r
+    // Copy table into SPI driver Private data structure\r
+    //\r
+    CopyMem (\r
+      &SpiInstance->SpiInitTable,\r
+      InitTable,\r
+      sizeof (SPI_INIT_TABLE)\r
+      );\r
+  } else {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Check if the SPI interface has been locked-down.\r
+  //\r
+  if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) != 0) {\r
+    ASSERT_EFI_ERROR (EFI_ACCESS_DENIED);\r
+    return EFI_ACCESS_DENIED;\r
+  }\r
+  //\r
+  // Clear all the status bits for status regs.\r
+  //\r
+  MmioOr16 (\r
+    (UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS),\r
+    (UINT16) ((B_QNC_RCRB_SPIS_CDS | B_QNC_RCRB_SPIS_BAS))\r
+    );\r
+  MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS);\r
+\r
+  //\r
+  // Set the Prefix Opcode registers.\r
+  //\r
+  MmioWrite16 (\r
+    PchRootComplexBar + R_QNC_RCRB_SPIPREOP,\r
+    (SpiInstance->SpiInitTable.PrefixOpcode[1] << 8) | InitTable->PrefixOpcode[0]\r
+    );\r
+  MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIPREOP);\r
+\r
+  //\r
+  // Set Opcode Type Configuration registers.\r
+  //\r
+  for (Index = 0, OpcodeType = 0; Index < SPI_NUM_OPCODE; Index++) {\r
+    switch (SpiInstance->SpiInitTable.OpcodeMenu[Index].Type) {\r
+    case EnumSpiOpcodeRead:\r
+      OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_ADD_READ << (Index * 2));\r
+      break;\r
+    case EnumSpiOpcodeWrite:\r
+      OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_ADD_WRITE << (Index * 2));\r
+      break;\r
+    case EnumSpiOpcodeWriteNoAddr:\r
+      OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_NOADD_WRITE << (Index * 2));\r
+      break;\r
+    default:\r
+      OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_NOADD_READ << (Index * 2));\r
+      break;\r
+    }\r
+  }\r
+  MmioWrite16 (PchRootComplexBar + R_QNC_RCRB_SPIOPTYPE, OpcodeType);\r
+  MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIOPTYPE);\r
+\r
+  //\r
+  // Setup the Opcode Menu registers.\r
+  //\r
+  ReadDataCmdOpcodeIndex = SPI_NUM_OPCODE;\r
+  SFDPCmdOpcodeIndex = SPI_NUM_OPCODE;\r
+  UnlockCmdOpcodeIndex = SPI_NUM_OPCODE;\r
+  for (Index = 0; Index < SPI_NUM_OPCODE; Index++) {\r
+    MmioWrite8 (\r
+      PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + Index,\r
+      SpiInstance->SpiInitTable.OpcodeMenu[Index].Code\r
+      );\r
+    MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + Index);\r
+    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationJedecId) {\r
+      Status = SpiProtocolExecute (\r
+                This,\r
+                Index,\r
+                0,\r
+                TRUE,\r
+                TRUE,\r
+                FALSE,\r
+                (UINTN) 0,\r
+                3,\r
+                FlashPartId,\r
+                EnumSpiRegionDescriptor\r
+                );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      if (FlashPartId[0] != SpiInstance->SpiInitTable.VendorId  ||\r
+          FlashPartId[1] != SpiInstance->SpiInitTable.DeviceId0 ||\r
+          FlashPartId[2] != SpiInstance->SpiInitTable.DeviceId1) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+    }\r
+\r
+    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationReadData ||\r
+        SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationFastRead ||\r
+        SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationDualOutputFastRead) {\r
+      ReadDataCmdOpcodeIndex = Index;\r
+    }\r
+\r
+    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationDiscoveryParameters) {\r
+      SFDPCmdOpcodeIndex = Index;\r
+    }\r
+\r
+    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationWriteStatus) {\r
+      UnlockCmdOpcodeIndex = Index;\r
+    }\r
+  }\r
+\r
+  MultiPartitionIsSupported = FALSE;\r
+\r
+  Status = UnlockFlashComponents (\r
+            This,\r
+            UnlockCmdOpcodeIndex\r
+            );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "Unlock flash components fail!\n"));\r
+  }\r
+\r
+  SpiPhaseInit ();\r
+  FillOutPublicInfoStruct (SpiInstance);\r
+  SpiInstance->InitDone = TRUE;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SpiProtocolLock (\r
+  IN EFI_SPI_PROTOCOL     *This\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Lock the SPI Static Configuration Interface.\r
+  Once locked, the interface can not be changed and can only be clear by system reset.\r
+\r
+Arguments:\r
+\r
+  This      Pointer to the EFI_SPI_PROTOCOL instance.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             Lock operation succeed.\r
+  EFI_DEVICE_ERROR        Device error, operation failed.\r
+  EFI_ACCESS_DENIED       The interface has already been locked.\r
+\r
+--*/\r
+{\r
+  SPI_INSTANCE  *SpiInstance;\r
+  UINTN         PchRootComplexBar;\r
+\r
+  SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);\r
+  PchRootComplexBar = SpiInstance->PchRootComplexBar;\r
+\r
+  //\r
+  // Check if the SPI interface has been locked-down.\r
+  //\r
+  if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) != 0) {\r
+    return EFI_ACCESS_DENIED;\r
+  }\r
+\r
+  //\r
+  // Lock-down the configuration interface.\r
+  //\r
+  MmioOr16 ((UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS), (UINT16) (B_QNC_RCRB_SPIS_SCL));\r
+\r
+  //\r
+  // Verify if it's really locked.\r
+  //\r
+  if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) == 0) {\r
+    return EFI_DEVICE_ERROR;\r
+  } else {\r
+    //\r
+    // Save updated register in S3 Boot script.\r
+    //\r
+    S3BootScriptSaveMemWrite (\r
+      S3BootScriptWidthUint16,\r
+        (UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS),\r
+        1,\r
+        (VOID *) (UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS)\r
+        );\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SpiProtocolExecute (\r
+  IN     EFI_SPI_PROTOCOL   *This,\r
+  IN     UINT8              OpcodeIndex,\r
+  IN     UINT8              PrefixOpcodeIndex,\r
+  IN     BOOLEAN            DataCycle,\r
+  IN     BOOLEAN            Atomic,\r
+  IN     BOOLEAN            ShiftOut,\r
+  IN     UINTN              Address,\r
+  IN     UINT32             DataByteCount,\r
+  IN OUT UINT8              *Buffer,\r
+  IN     SPI_REGION_TYPE    SpiRegionType\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Execute SPI commands from the host controller.\r
+  This function would be called by runtime driver, please do not use any MMIO marco here\r
+\r
+Arguments:\r
+\r
+  This              Pointer to the EFI_SPI_PROTOCOL instance.\r
+  OpcodeIndex       Index of the command in the OpCode Menu.\r
+  PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.\r
+  DataCycle         TRUE if the SPI cycle contains data\r
+  Atomic            TRUE if the SPI cycle is atomic and interleave cycles are not allowed.\r
+  ShiftOut          If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.\r
+  Address           In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform\r
+                    Region, this value specifies the offset from the Region Base; for BIOS Region,\r
+                    this value specifies the offset from the start of the BIOS Image. In Non\r
+                    Descriptor Mode, this value specifies the offset from the start of the BIOS Image.\r
+                    Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor\r
+                    Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is\r
+                    supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or\r
+                    the flash (in Non Descriptor Mode)\r
+  DataByteCount     Number of bytes in the data portion of the SPI cycle. This function may break the\r
+                    data transfer into multiple operations. This function ensures each operation does\r
+                    not cross 256 byte flash address boundary.\r
+                    *NOTE: if there is some SPI chip that has a stricter address boundary requirement\r
+                    (e.g., its write page size is < 256 byte), then the caller cannot rely on this\r
+                    function to cut the data transfer at proper address boundaries, and it's the\r
+                    caller's reponsibility to pass in a properly cut DataByteCount parameter.\r
+  Buffer            Pointer to caller-allocated buffer containing the dada received or sent during the\r
+                    SPI cycle.\r
+  SpiRegionType     SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,\r
+                    EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in\r
+                    Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode\r
+                    and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative\r
+                    to base of the 1st flash device (i.e., it is a Flash Linear Address).\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             Command succeed.\r
+  EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+  EFI_UNSUPPORTED         Command not supported.\r
+  EFI_DEVICE_ERROR        Device error, command aborts abnormally.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT16      BiosCtlSave;\r
+  UINT32      SmiEnSave;\r
+\r
+  BiosCtlSave = 0;\r
+  SmiEnSave   = 0;\r
+\r
+  //\r
+  // Check if the parameters are valid.\r
+  //\r
+  if ((OpcodeIndex >= SPI_NUM_OPCODE) || (PrefixOpcodeIndex >= SPI_NUM_PREFIX_OPCODE)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Make sure it's safe to program the command.\r
+  //\r
+  if (!WaitForSpiCycleComplete (This, FALSE)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Acquire access to the SPI interface is not required any more.\r
+  //\r
+  //\r
+  // Disable SMIs to make sure normal mode flash access is not interrupted by an SMI\r
+  // whose SMI handler accesses flash (e.g. for error logging)\r
+  //\r
+  SmiEnSave = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);\r
+  QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, (SmiEnSave & ~SMI_EN));\r
+\r
+  //\r
+  // Save BIOS Ctrl register\r
+  //\r
+  BiosCtlSave = PciRead16 (\r
+                  PCI_LIB_ADDRESS (PCI_BUS_NUMBER_QNC,\r
+                  PCI_DEVICE_NUMBER_QNC_LPC,\r
+                  PCI_FUNCTION_NUMBER_QNC_LPC,\r
+                  R_QNC_LPC_BIOS_CNTL)\r
+                  ) & (B_QNC_LPC_BIOS_CNTL_BCD | B_QNC_LPC_BIOS_CNTL_PFE | B_QNC_LPC_BIOS_CNTL_BIOSWE | B_QNC_LPC_BIOS_CNTL_SMM_BWP);\r
+\r
+  //\r
+  // Enable flash writing\r
+  //\r
+  PciOr16 (\r
+    PCI_LIB_ADDRESS (PCI_BUS_NUMBER_QNC,\r
+    PCI_DEVICE_NUMBER_QNC_LPC,\r
+    PCI_FUNCTION_NUMBER_QNC_LPC,\r
+    R_QNC_LPC_BIOS_CNTL),\r
+    (UINT16) (B_QNC_LPC_BIOS_CNTL_BIOSWE | B_QNC_LPC_BIOS_CNTL_SMM_BWP)\r
+    );\r
+\r
+  //\r
+  // If shifts the data out, disable Prefetching and Caching.\r
+  //\r
+  if (ShiftOut) {\r
+    PciAndThenOr16 (\r
+      PCI_LIB_ADDRESS (PCI_BUS_NUMBER_QNC,\r
+      PCI_DEVICE_NUMBER_QNC_LPC,\r
+      PCI_FUNCTION_NUMBER_QNC_LPC,\r
+      R_QNC_LPC_BIOS_CNTL),\r
+      (UINT16) (~(B_QNC_LPC_BIOS_CNTL_BCD | B_QNC_LPC_BIOS_CNTL_PFE)),\r
+      (UINT16) ((B_QNC_LPC_BIOS_CNTL_BCD))\r
+      );\r
+  }\r
+  //\r
+  // Sends the command to the SPI interface to execute.\r
+  //\r
+  Status = SendSpiCmd (\r
+            This,\r
+            OpcodeIndex,\r
+            PrefixOpcodeIndex,\r
+            DataCycle,\r
+            Atomic,\r
+            ShiftOut,\r
+            Address,\r
+            DataByteCount,\r
+            Buffer,\r
+            SpiRegionType\r
+            );\r
+\r
+  //\r
+  // Restore BIOS Ctrl register\r
+  //\r
+  PciAndThenOr16 (\r
+    PCI_LIB_ADDRESS (PCI_BUS_NUMBER_QNC,\r
+    PCI_DEVICE_NUMBER_QNC_LPC,\r
+    PCI_FUNCTION_NUMBER_QNC_LPC,\r
+    R_QNC_LPC_BIOS_CNTL),\r
+    (UINT16) (~(B_QNC_LPC_BIOS_CNTL_BCD | B_QNC_LPC_BIOS_CNTL_PFE | B_QNC_LPC_BIOS_CNTL_BIOSWE | B_QNC_LPC_BIOS_CNTL_SMM_BWP)),\r
+    (UINT16) (BiosCtlSave)\r
+      );\r
+  //\r
+  // Restore SMIs.\r
+  //\r
+  QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, SmiEnSave);\r
+\r
+  return Status;\r
+}\r
+\r
+VOID\r
+SpiOffset2Physical (\r
+  IN      EFI_SPI_PROTOCOL  *This,\r
+  IN      UINTN             SpiRegionOffset,\r
+  IN      SPI_REGION_TYPE   SpiRegionType,\r
+  OUT     UINTN             *HardwareSpiAddress,\r
+  OUT     UINTN             *BaseAddress,\r
+  OUT     UINTN             *LimitAddress\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Convert SPI offset to Physical address of SPI hardware\r
+\r
+Arguments:\r
+\r
+  This               Pointer to the EFI_SPI_PROTOCOL instance.\r
+  SpiRegionOffset    In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform\r
+                     Region, this value specifies the offset from the Region Base; for BIOS Region,\r
+                     this value specifies the offset from the start of the BIOS Image. In Non\r
+                     Descriptor Mode, this value specifies the offset from the start of the BIOS Image.\r
+                     Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor\r
+                     Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is\r
+                     supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or\r
+                     the flash (in Non Descriptor Mode)\r
+  BaseAddress        Base Address of the region.\r
+  SpiRegionType      SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,\r
+                     EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in\r
+                     Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode\r
+                     and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative\r
+                     to base of the 1st flash device (i.e., it is a Flash Linear Address).\r
+  HardwareSpiAddress Return absolution SPI address (i.e., Flash Linear Address)\r
+  BaseAddress        Return base address of the region type\r
+  LimitAddress       Return limit address of the region type\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             Command succeed.\r
+\r
+--*/\r
+{\r
+  SPI_INSTANCE  *SpiInstance;\r
+  UINTN         PchRootComplexBar;\r
+\r
+  SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);\r
+  PchRootComplexBar = SpiInstance->PchRootComplexBar;\r
+\r
+  if (SpiRegionType == EnumSpiRegionAll) {\r
+    //\r
+    // EnumSpiRegionAll indicates address is relative to flash device (i.e., address is Flash\r
+    // Linear Address)\r
+    //\r
+    *HardwareSpiAddress = SpiRegionOffset;\r
+  } else {\r
+    //\r
+    // Otherwise address is relative to BIOS image\r
+    //\r
+    *HardwareSpiAddress = SpiRegionOffset + SpiInstance->SpiInitTable.BiosStartOffset;\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+SendSpiCmd (\r
+  IN     EFI_SPI_PROTOCOL   *This,\r
+  IN     UINT8              OpcodeIndex,\r
+  IN     UINT8              PrefixOpcodeIndex,\r
+  IN     BOOLEAN            DataCycle,\r
+  IN     BOOLEAN            Atomic,\r
+  IN     BOOLEAN            ShiftOut,\r
+  IN     UINTN              Address,\r
+  IN     UINT32             DataByteCount,\r
+  IN OUT UINT8              *Buffer,\r
+  IN     SPI_REGION_TYPE    SpiRegionType\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function sends the programmed SPI command to the slave device.\r
+\r
+Arguments:\r
+\r
+  OpcodeIndex       Index of the command in the OpCode Menu.\r
+  PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.\r
+  DataCycle         TRUE if the SPI cycle contains data\r
+  Atomic            TRUE if the SPI cycle is atomic and interleave cycles are not allowed.\r
+  ShiftOut          If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.\r
+  Address           In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform\r
+                    Region, this value specifies the offset from the Region Base; for BIOS Region,\r
+                    this value specifies the offset from the start of the BIOS Image. In Non\r
+                    Descriptor Mode, this value specifies the offset from the start of the BIOS Image.\r
+                    Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor\r
+                    Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is\r
+                    supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or\r
+                    the flash (in Non Descriptor Mode)\r
+  DataByteCount     Number of bytes in the data portion of the SPI cycle. This function may break the\r
+                    data transfer into multiple operations. This function ensures each operation does\r
+                    not cross 256 byte flash address boundary.\r
+                    *NOTE: if there is some SPI chip that has a stricter address boundary requirement\r
+                    (e.g., its write page size is < 256 byte), then the caller cannot rely on this\r
+                    function to cut the data transfer at proper address boundaries, and it's the\r
+                    caller's reponsibility to pass in a properly cut DataByteCount parameter.\r
+  Buffer            Data received or sent during the SPI cycle.\r
+  SpiRegionType     SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,\r
+                    EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in\r
+                    Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode\r
+                    and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative\r
+                    to base of the 1st flash device (i.e., it is a Flash Linear Address).\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             SPI command completes successfully.\r
+  EFI_DEVICE_ERROR        Device error, the command aborts abnormally.\r
+  EFI_ACCESS_DENIED       Some unrecognized command encountered in hardware sequencing mode\r
+  EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+\r
+--*/\r
+{\r
+  UINT32        Index;\r
+  SPI_INSTANCE  *SpiInstance;\r
+  UINTN         HardwareSpiAddr;\r
+  UINTN         SpiBiosSize;\r
+  UINTN         BaseAddress;\r
+  UINTN         LimitAddress;\r
+  UINT32        SpiDataCount;\r
+  UINT8         OpCode;\r
+  SPI_OPERATION Operation;\r
+  UINTN         PchRootComplexBar;\r
+\r
+  SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);\r
+  PchRootComplexBar = SpiInstance->PchRootComplexBar;\r
+  SpiBiosSize       = SpiInstance->SpiInitTable.BiosSize;\r
+  Operation         = SpiInstance->SpiInitTable.OpcodeMenu[OpcodeIndex].Operation;\r
+  OpCode            = MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + OpcodeIndex);\r
+\r
+  //\r
+  // Check if the value of opcode register is 0 or the BIOS Size of SpiInitTable is 0\r
+  //\r
+  if (OpCode == 0 || SpiBiosSize == 0) {\r
+    ASSERT (FALSE);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  SpiOffset2Physical (This, Address, SpiRegionType, &HardwareSpiAddr, &BaseAddress, &LimitAddress);\r
+  //\r
+  // Have direct access to BIOS region in Descriptor mode,\r
+  //\r
+  if (SpiInstance->SpiInitTable.OpcodeMenu[OpcodeIndex].Type == EnumSpiOpcodeRead &&\r
+      SpiRegionType == EnumSpiRegionBios) {\r
+    CopyMem (\r
+      Buffer,\r
+      (UINT8 *) ((HardwareSpiAddr - BaseAddress) + (UINT32) (~(SpiBiosSize - 1))),\r
+      DataByteCount\r
+      );\r
+    return EFI_SUCCESS;\r
+  }\r
+  //\r
+  // DEBUG((EFI_D_ERROR, "SPIADDR %x, %x, %x, %x\n", Address, HardwareSpiAddr, BaseAddress,\r
+  // LimitAddress));\r
+  //\r
+  if ((DataCycle == FALSE) && (DataByteCount > 0)) {\r
+    DataByteCount = 0;\r
+  }\r
+\r
+  do {\r
+    //\r
+    // Trim at 256 byte boundary per operation,\r
+    // - PCH SPI controller requires trimming at 4KB boundary\r
+    // - Some SPI chips require trimming at 256 byte boundary for write operation\r
+    // - Trimming has limited performance impact as we can read / write atmost 64 byte\r
+    //   per operation\r
+    //\r
+    if (HardwareSpiAddr + DataByteCount > ((HardwareSpiAddr + BIT8) &~(BIT8 - 1))) {\r
+      SpiDataCount = (((UINT32) (HardwareSpiAddr) + BIT8) &~(BIT8 - 1)) - (UINT32) (HardwareSpiAddr);\r
+    } else {\r
+      SpiDataCount = DataByteCount;\r
+    }\r
+    //\r
+    // Calculate the number of bytes to shift in/out during the SPI data cycle.\r
+    // Valid settings for the number of bytes duing each data portion of the\r
+    // PCH SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48, 56, 64\r
+    //\r
+    if (SpiDataCount >= 64) {\r
+      SpiDataCount = 64;\r
+    } else if ((SpiDataCount &~0x07) != 0) {\r
+      SpiDataCount = SpiDataCount &~0x07;\r
+    }\r
+    //\r
+    // If shifts data out, load data into the SPI data buffer.\r
+    //\r
+    if (ShiftOut) {\r
+      for (Index = 0; Index < SpiDataCount; Index++) {\r
+        MmioWrite8 (PchRootComplexBar + R_QNC_RCRB_SPID0 + Index, Buffer[Index]);\r
+        MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPID0 + Index);\r
+      }\r
+    }\r
+\r
+    MmioWrite32 (\r
+      (PchRootComplexBar + R_QNC_RCRB_SPIA),\r
+      (UINT32) (HardwareSpiAddr & B_QNC_RCRB_SPIA_MASK)\r
+      );\r
+    MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIA);\r
+\r
+    //\r
+    // Execute the command on the SPI compatible mode\r
+    //\r
+\r
+    //\r
+    // Clear error flags\r
+    //\r
+    MmioOr16 ((PchRootComplexBar + R_QNC_RCRB_SPIS), B_QNC_RCRB_SPIS_BAS);\r
+\r
+    //\r
+    // Initialte the SPI cycle\r
+    //\r
+    if (DataCycle) {\r
+      MmioWrite16 (\r
+        (PchRootComplexBar + R_QNC_RCRB_SPIC),\r
+        ( (UINT16) (B_QNC_RCRB_SPIC_DC) | (UINT16) (((SpiDataCount - 1) << 8) & B_QNC_RCRB_SPIC_DBC) |\r
+          (UINT16) ((OpcodeIndex << 4) & B_QNC_RCRB_SPIC_COP) |\r
+          (UINT16) ((PrefixOpcodeIndex << 3) & B_QNC_RCRB_SPIC_SPOP) |\r
+          (UINT16) (Atomic ? B_QNC_RCRB_SPIC_ACS : 0) |\r
+          (UINT16) (B_QNC_RCRB_SPIC_SCGO)));\r
+    } else {\r
+      MmioWrite16 (\r
+        (PchRootComplexBar + R_QNC_RCRB_SPIC),\r
+        ( (UINT16) ((OpcodeIndex << 4) & B_QNC_RCRB_SPIC_COP) |\r
+          (UINT16) ((PrefixOpcodeIndex << 3) & B_QNC_RCRB_SPIC_SPOP) |\r
+          (UINT16) (Atomic ? B_QNC_RCRB_SPIC_ACS : 0) |\r
+          (UINT16) (B_QNC_RCRB_SPIC_SCGO)));\r
+    }\r
+\r
+    MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIC);\r
+\r
+    //\r
+    // end of command execution\r
+    //\r
+    // Wait the SPI cycle to complete.\r
+    //\r
+    if (!WaitForSpiCycleComplete (This, TRUE)) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+    //\r
+    // If shifts data in, get data from the SPI data buffer.\r
+    //\r
+    if (!ShiftOut) {\r
+      for (Index = 0; Index < SpiDataCount; Index++) {\r
+        Buffer[Index] = MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPID0 + Index);\r
+      }\r
+    }\r
+\r
+    HardwareSpiAddr += SpiDataCount;\r
+    Buffer += SpiDataCount;\r
+    DataByteCount -= SpiDataCount;\r
+  } while (DataByteCount > 0);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+WaitForSpiCycleComplete (\r
+  IN     EFI_SPI_PROTOCOL   *This,\r
+  IN     BOOLEAN            ErrorCheck\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Wait execution cycle to complete on the SPI interface. Check both Hardware\r
+  and Software Sequencing status registers\r
+\r
+Arguments:\r
+\r
+  This                - The SPI protocol instance\r
+  UseSoftwareSequence - TRUE if this is a Hardware Sequencing operation\r
+  ErrorCheck          - TRUE if the SpiCycle needs to do the error check\r
+\r
+Returns:\r
+\r
+  TRUE       SPI cycle completed on the interface.\r
+  FALSE      Time out while waiting the SPI cycle to complete.\r
+             It's not safe to program the next command on the SPI interface.\r
+\r
+--*/\r
+{\r
+  UINT64        WaitTicks;\r
+  UINT64        WaitCount;\r
+  UINT16        Data16;\r
+  SPI_INSTANCE  *SpiInstance;\r
+  UINTN         PchRootComplexBar;\r
+\r
+  SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);\r
+  PchRootComplexBar = SpiInstance->PchRootComplexBar;\r
+\r
+  //\r
+  // Convert the wait period allowed into to tick count\r
+  //\r
+  WaitCount = WAIT_TIME / WAIT_PERIOD;\r
+\r
+  //\r
+  // Wait for the SPI cycle to complete.\r
+  //\r
+  for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {\r
+    Data16 = MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS);\r
+    if ((Data16 & B_QNC_RCRB_SPIS_SCIP) == 0) {\r
+      MmioWrite16 (PchRootComplexBar + R_QNC_RCRB_SPIS, (B_QNC_RCRB_SPIS_BAS | B_QNC_RCRB_SPIS_CDS));\r
+      if ((Data16 & B_QNC_RCRB_SPIS_BAS) && (ErrorCheck == TRUE)) {\r
+        return FALSE;\r
+      } else {\r
+        return TRUE;\r
+      }\r
+    }\r
+\r
+    MicroSecondDelay (WAIT_PERIOD);\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SpiProtocolInfo (\r
+  IN EFI_SPI_PROTOCOL     *This,\r
+  OUT SPI_INIT_INFO      **InitInfoPtr\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Return info about SPI host controller, to help callers usage of Execute\r
+  service.\r
+\r
+  If 0xff is returned as an opcode index in init info struct\r
+  then device does not support the operation.\r
+\r
+Arguments:\r
+\r
+  This                    Pointer to the EFI_SPI_PROTOCOL instance.\r
+  InitInfoPtr             Pointer to init info written to this memory location.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             Information returned.\r
+  EFI_INVALID_PARAMETER   Invalid parameter.\r
+  EFI_NOT_READY           Required resources not setup.\r
+  Others                  Unexpected error happened.\r
+\r
+--*/\r
+{\r
+  SPI_INSTANCE  *SpiInstance;\r
+\r
+  if (This == NULL || InitInfoPtr == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);\r
+  if (SpiInstance->Signature != PCH_SPI_PRIVATE_DATA_SIGNATURE) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (!SpiInstance->InitDone) {\r
+    *InitInfoPtr = NULL;\r
+    return EFI_NOT_READY;\r
+  }\r
+  *InitInfoPtr = &SpiInstance->InitInfo;\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Spi/Common/SpiCommon.h b/QuarkSocPkg/QuarkNorthCluster/Spi/Common/SpiCommon.h
new file mode 100644 (file)
index 0000000..b8c1903
--- /dev/null
@@ -0,0 +1,323 @@
+/** @file\r
+Header file for the PCH SPI Common Driver.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#ifndef _SPI_COMMON_H_\r
+#define _SPI_COMMON_H_\r
+\r
+#include "Protocol/Spi.h"\r
+#include <Library/PciLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/IntelQNCLib.h>\r
+#include <Library/QNCAccessLib.h>\r
+#include <Uefi/UefiBaseType.h>\r
+\r
+//\r
+// Maximum time allowed while waiting the SPI cycle to complete\r
+//  Wait Time = 6 seconds = 6000000 microseconds\r
+//  Wait Period = 10 microseconds\r
+//\r
+#define WAIT_TIME   6000000\r
+#define WAIT_PERIOD 10\r
+//\r
+// PCH Required SPI Commands -------- COMMAND SET I ------------\r
+// SPI flash device must support in order to be compatible with PCH\r
+//\r
+#define PCH_SPI_COMMAND_PROGRAM_BYTE          0x02\r
+#define PCH_SPI_COMMAND_READ_DATA             0x03\r
+#define PCH_SPI_COMMAND_WRITE_DISABLE         0x04\r
+#define PCH_SPI_COMMAND_READ_STATUS           0x05\r
+#define PCH_SPI_COMMAND_WRITE_ENABLE          0x06\r
+#define PCH_SPI_COMMAND_FAST_READ             0x0B\r
+#define PCH_SPI_COMMAND_READ_ID               0x9F\r
+#define PCH_SPI_COMMAND_DUAL_FAST_READ        0x3B  // Dual Output Fast Read\r
+\r
+//\r
+// Need to support at least one of the following two kinds of size of sector for erasing\r
+//\r
+#define PCH_SPI_COMMAND_4KB_ERASE   0x20\r
+#define PCH_SPI_COMMAND_64KB_ERASE  0xD8\r
+//\r
+// Recommended SPI Commands -------- COMMAND SET II ------------\r
+// SPI flash device best to support\r
+//\r
+#define PCH_SPI_COMMAND_WRITE_STATUS    0x01\r
+#define PCH_SPI_COMMAND_FULL_CHIP_ERASE 0xC7\r
+\r
+//\r
+// Private data structure definitions for the driver\r
+//\r
+#define PCH_SPI_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('P', 'S', 'P', 'I')\r
+\r
+typedef struct {\r
+  UINTN             Signature;\r
+  EFI_HANDLE        Handle;\r
+  EFI_SPI_PROTOCOL  SpiProtocol;\r
+  SPI_INIT_TABLE    SpiInitTable;\r
+  UINTN             PchRootComplexBar;\r
+  BOOLEAN           InitDone; // Set to TRUE on SpiProtocolInit SUCCESS.\r
+  SPI_INIT_INFO     InitInfo;\r
+} SPI_INSTANCE;\r
+\r
+#define SPI_INSTANCE_FROM_SPIPROTOCOL(a)  CR (a, SPI_INSTANCE, SpiProtocol, PCH_SPI_PRIVATE_DATA_SIGNATURE)\r
+\r
+//\r
+// Function prototypes used by the SPI protocol.\r
+//\r
+EFI_STATUS\r
+SpiProtocolConstructor (\r
+  SPI_INSTANCE          *SpiInstance\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Initialize an SPI protocol instance.\r
+  The function will assert in debug if PCH RCBA has not been initialized\r
+\r
+Arguments:\r
+\r
+  SpiInstance   - Pointer to SpiInstance to initialize\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS     The protocol instance was properly initialized\r
+  EFI_UNSUPPORTED The PCH is not supported by this module\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SpiProtocolInit (\r
+  IN EFI_SPI_PROTOCOL       *This,\r
+  IN SPI_INIT_TABLE         *InitTable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Initialize the host controller to execute SPI command.\r
+\r
+Arguments:\r
+\r
+  This                    Pointer to the EFI_SPI_PROTOCOL instance.\r
+  InitTable               Initialization data to be programmed into the SPI host controller.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             Initialization completed.\r
+  EFI_ACCESS_DENIED       The SPI static configuration interface has been locked-down.\r
+  EFI_INVALID_PARAMETER   Bad input parameters.\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SpiProtocolLock (\r
+  IN EFI_SPI_PROTOCOL       *This\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Lock the SPI Static Configuration Interface.\r
+  Once locked, the interface can not be changed and can only be clear by system reset.\r
+\r
+Arguments:\r
+\r
+  This      Pointer to the EFI_SPI_PROTOCOL instance.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             Lock operation succeed.\r
+  EFI_DEVICE_ERROR        Device error, operation failed.\r
+  EFI_ACCESS_DENIED       The interface has already been locked.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SpiProtocolExecute (\r
+  IN     EFI_SPI_PROTOCOL   *This,\r
+  IN     UINT8              OpcodeIndex,\r
+  IN     UINT8              PrefixOpcodeIndex,\r
+  IN     BOOLEAN            DataCycle,\r
+  IN     BOOLEAN            Atomic,\r
+  IN     BOOLEAN            ShiftOut,\r
+  IN     UINTN              Address,\r
+  IN     UINT32             DataByteCount,\r
+  IN OUT UINT8              *Buffer,\r
+  IN     SPI_REGION_TYPE    SpiRegionType\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Execute SPI commands from the host controller.\r
+\r
+Arguments:\r
+\r
+  This                    Pointer to the EFI_SPI_PROTOCOL instance.\r
+  OpcodeIndex             Index of the command in the OpCode Menu.\r
+  PrefixOpcodeIndex       Index of the first command to run when in an atomic cycle sequence.\r
+  DataCycle               TRUE if the SPI cycle contains data\r
+  Atomic                  TRUE if the SPI cycle is atomic and interleave cycles are not allowed.\r
+  ShiftOut                If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.\r
+  Address                 In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform\r
+                          Region, this value specifies the offset from the Region Base; for BIOS Region,\r
+                          this value specifies the offset from the start of the BIOS Image. In Non\r
+                          Descriptor Mode, this value specifies the offset from the start of the BIOS Image.\r
+                          Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor\r
+                          Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is\r
+                          supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or\r
+                          the flash (in Non Descriptor Mode)\r
+  DataByteCount           Number of bytes in the data portion of the SPI cycle.\r
+  Buffer                  Pointer to caller-allocated buffer containing the dada received or sent during the SPI cycle.\r
+  SpiRegionType           SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,\r
+                          EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in\r
+                          Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode\r
+                          and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative\r
+                          to base of the 1st flash device (i.e., it is a Flash Linear Address).\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             Command succeed.\r
+  EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+  EFI_UNSUPPORTED         Command not supported.\r
+  EFI_DEVICE_ERROR        Device error, command aborts abnormally.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+SendSpiCmd (\r
+  IN     EFI_SPI_PROTOCOL   *This,\r
+  IN     UINT8              OpcodeIndex,\r
+  IN     UINT8              PrefixOpcodeIndex,\r
+  IN     BOOLEAN            DataCycle,\r
+  IN     BOOLEAN            Atomic,\r
+  IN     BOOLEAN            ShiftOut,\r
+  IN     UINTN              Address,\r
+  IN     UINT32             DataByteCount,\r
+  IN OUT UINT8              *Buffer,\r
+  IN     SPI_REGION_TYPE    SpiRegionType\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function sends the programmed SPI command to the slave device.\r
+\r
+Arguments:\r
+\r
+  OpcodeIndex       Index of the command in the OpCode Menu.\r
+  PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.\r
+  DataCycle         TRUE if the SPI cycle contains data\r
+  Atomic            TRUE if the SPI cycle is atomic and interleave cycles are not allowed.\r
+  ShiftOut          If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.\r
+  Address           In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform\r
+                    Region, this value specifies the offset from the Region Base; for BIOS Region,\r
+                    this value specifies the offset from the start of the BIOS Image. In Non\r
+                    Descriptor Mode, this value specifies the offset from the start of the BIOS Image.\r
+                    Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor\r
+                    Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is\r
+                    supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or\r
+                    the flash (in Non Descriptor Mode)\r
+  DataByteCount     Number of bytes in the data portion of the SPI cycle. This function may break the\r
+                    data transfer into multiple operations. This function ensures each operation does\r
+                    not cross 256 byte flash address boundary.\r
+                    *NOTE: if there is some SPI chip that has a stricter address boundary requirement\r
+                    (e.g., its write page size is < 256 byte), then the caller cannot rely on this\r
+                    function to cut the data transfer at proper address boundaries, and it's the\r
+                    caller's reponsibility to pass in a properly cut DataByteCount parameter.\r
+  Buffer            Data received or sent during the SPI cycle.\r
+  SpiRegionType     SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,\r
+                    EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in\r
+                    Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode\r
+                    and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative\r
+                    to base of the 1st flash device (i.e., it is a Flash Linear Address).\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             SPI command completes successfully.\r
+  EFI_DEVICE_ERROR        Device error, the command aborts abnormally.\r
+  EFI_ACCESS_DENIED       Some unrecognized command encountered in hardware sequencing mode\r
+  EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+\r
+--*/\r
+;\r
+\r
+BOOLEAN\r
+WaitForSpiCycleComplete (\r
+  IN     EFI_SPI_PROTOCOL   *This,\r
+  IN     BOOLEAN            ErrorCheck\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Wait execution cycle to complete on the SPI interface. Check both Hardware\r
+  and Software Sequencing status registers\r
+\r
+Arguments:\r
+\r
+  This                - The SPI protocol instance\r
+  UseSoftwareSequence - TRUE if this is a Hardware Sequencing operation\r
+  ErrorCheck          - TRUE if the SpiCycle needs to do the error check\r
+\r
+Returns:\r
+\r
+  TRUE       SPI cycle completed on the interface.\r
+  FALSE      Time out while waiting the SPI cycle to complete.\r
+             It's not safe to program the next command on the SPI interface.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SpiProtocolInfo (\r
+  IN EFI_SPI_PROTOCOL     *This,\r
+  OUT SPI_INIT_INFO      **InitInfoPtr\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Return info about SPI host controller, to help callers usage of Execute\r
+  service.\r
+\r
+  If 0xff is returned as an opcode index in init info struct\r
+  then device does not support the operation.\r
+\r
+Arguments:\r
+\r
+  This                    Pointer to the EFI_SPI_PROTOCOL instance.\r
+  InitInfoPtr             Pointer to init info written to this memory location.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             Information returned.\r
+  EFI_INVALID_PARAMETER   Invalid parameter.\r
+  EFI_NOT_READY           Required resources not setup.\r
+  Others                  Unexpected error happened.\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Spi/PchSpiRuntime.inf b/QuarkSocPkg/QuarkNorthCluster/Spi/PchSpiRuntime.inf
new file mode 100644 (file)
index 0000000..0a9beee
--- /dev/null
@@ -0,0 +1,90 @@
+## @file\r
+#    Component description file for the SPI Runtime driver.\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+################################################################################\r
+#\r
+# Defines Section - statements that will be processed to create a Makefile.\r
+#\r
+################################################################################\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = PchSpiRuntime\r
+  FILE_GUID                      = C194C6EA-B68C-4981-B64B-9BD271474B20\r
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+\r
+  ENTRY_POINT                    = InstallPchSpi\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 EBC\r
+################################################################################\r
+#\r
+# Sources Section - list of files that are required for the build to succeed.\r
+#\r
+################################################################################\r
+[Sources]\r
+  RuntimeDxe/PchSpi.h\r
+  RuntimeDxe/PchSpi.c\r
+  Common/SpiCommon.c\r
+  Common/SpiCommon.h\r
+\r
+################################################################################\r
+#\r
+# Package Dependency Section - list of Package files that are required for\r
+#                              this module.\r
+#\r
+################################################################################\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+################################################################################\r
+#\r
+# Library Class Section - list of Library Classes that are required for\r
+#                         this module.\r
+#\r
+################################################################################\r
+[LibraryClasses]\r
+  UefiRuntimeServicesTableLib\r
+  UefiRuntimeLib\r
+  UefiBootServicesTableLib\r
+  UefiDriverEntryPoint\r
+  IntelQNCLib\r
+  QNCAccessLib\r
+  TimerLib\r
+  DxeServicesTableLib\r
+  UefiLib\r
+  DebugLib\r
+  MemoryAllocationLib\r
+  S3BootScriptLib\r
+  PciExpressLib\r
+\r
+################################################################################\r
+#\r
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names\r
+#                           that this module uses or produces.\r
+#\r
+################################################################################\r
+[Protocols]\r
+  gEfiSpiProtocolGuid\r
+\r
+[Pcd]\r
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdRcbaMmioSize\r
+\r
+[Depex]\r
+  TRUE\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Spi/PchSpiSmm.inf b/QuarkSocPkg/QuarkNorthCluster/Spi/PchSpiSmm.inf
new file mode 100644 (file)
index 0000000..3fde4fd
--- /dev/null
@@ -0,0 +1,56 @@
+## @file\r
+# Spi smm driver\r
+#\r
+# Component description file for the SPI SMM driver.\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[defines]\r
+  INF_VERSION                 = 0x00010005\r
+  BASE_NAME                       = PchSpiSmm\r
+  FILE_GUID                       = 27F4917B-A707-4aad-9676-26DF168CBF0D\r
+  MODULE_TYPE                     = DXE_SMM_DRIVER\r
+  VERSION_STRING                  = 1.0\r
+  PI_SPECIFICATION_VERSION        = 0x0001000A\r
+  ENTRY_POINT                     = InstallPchSpi\r
+\r
+[Sources]\r
+  Smm/PchSpi.h\r
+  Smm/PchSpi.c\r
+  Common/SpiCommon.c\r
+  Common/SpiCommon.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  DebugLib\r
+  IoLib\r
+  IntelQNCLib\r
+  QNCAccessLib\r
+  TimerLib\r
+  S3BootScriptLib\r
+  UefiDriverEntryPoint\r
+  UefiBootServicesTableLib\r
+  BaseLib\r
+  SmmServicesTableLib\r
+\r
+[Protocols]\r
+  gEfiSmmSpiProtocolGuid      # PRODUCES\r
+\r
+[Pcd]\r
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress\r
+\r
+[Depex]\r
+  gEfiSmmBase2ProtocolGuid\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpi.c b/QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpi.c
new file mode 100644 (file)
index 0000000..bf52732
--- /dev/null
@@ -0,0 +1,211 @@
+/** @file\r
+PCH SPI Runtime Driver implements the SPI Host Controller Compatibility Interface.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include "PchSpi.h"\r
+\r
+extern EFI_GUID gEfiEventVirtualAddressChangeGuid;\r
+\r
+//\r
+// Global variables\r
+//\r
+SPI_INSTANCE  *mSpiInstance;\r
+CONST UINT32 mSpiRegister[] = {\r
+  R_QNC_RCRB_SPIS,\r
+  R_QNC_RCRB_SPIPREOP,\r
+  R_QNC_RCRB_SPIOPMENU,\r
+  R_QNC_RCRB_SPIOPMENU + 4\r
+  };\r
+\r
+//\r
+// Function implementations\r
+//\r
+VOID\r
+PchSpiVirtualddressChangeEvent (\r
+  IN EFI_EVENT        Event,\r
+  IN VOID             *Context\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Fixup internal data pointers so that the services can be called in virtual mode.\r
+\r
+Arguments:\r
+\r
+  Event     The event registered.\r
+  Context   Event context. Not used in this event handler.\r
+\r
+Returns:\r
+\r
+  None.\r
+\r
+--*/\r
+{\r
+  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->PchRootComplexBar));\r
+  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->SpiProtocol.Init));\r
+  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->SpiProtocol.Lock));\r
+  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->SpiProtocol.Execute));\r
+  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance));\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InstallPchSpi (\r
+  IN EFI_HANDLE            ImageHandle,\r
+  IN EFI_SYSTEM_TABLE      *SystemTable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Entry point for the SPI host controller driver.\r
+\r
+Arguments:\r
+\r
+  ImageHandle       Image handle of this driver.\r
+  SystemTable       Global system service table.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS           Initialization complete.\r
+  EFI_UNSUPPORTED       The chipset is unsupported by this driver.\r
+  EFI_OUT_OF_RESOURCES  Do not have enough resources to initialize the driver.\r
+  EFI_DEVICE_ERROR      Device error, driver exits abnormally.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                      Status;\r
+  UINT64                          BaseAddress;\r
+  UINT64                          Length;\r
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdMemorySpaceDescriptor;\r
+  UINT64                          Attributes;\r
+  EFI_EVENT                       Event;\r
+\r
+  DEBUG ((DEBUG_INFO, "InstallPchSpi() Start\n"));\r
+\r
+  //\r
+  // Allocate Runtime memory for the SPI protocol instance.\r
+  //\r
+  mSpiInstance = AllocateRuntimeZeroPool (sizeof (SPI_INSTANCE));\r
+  if (mSpiInstance == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // Initialize the SPI protocol instance\r
+  //\r
+  Status = SpiProtocolConstructor (mSpiInstance);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Install the EFI_SPI_PROTOCOL interface\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &(mSpiInstance->Handle),\r
+                  &gEfiSpiProtocolGuid,\r
+                  &(mSpiInstance->SpiProtocol),\r
+                  NULL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (mSpiInstance);\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  //\r
+  // Set RCBA space in GCD to be RUNTIME so that the range will be supported in\r
+  // virtual address mode in EFI aware OS runtime.\r
+  // It will assert if RCBA Memory Space is not allocated\r
+  // The caller is responsible for the existence and allocation of the RCBA Memory Spaces\r
+  //\r
+  BaseAddress = (EFI_PHYSICAL_ADDRESS) (mSpiInstance->PchRootComplexBar);\r
+  Length      = PcdGet64 (PcdRcbaMmioSize);\r
+\r
+  Status      = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdMemorySpaceDescriptor);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Attributes = GcdMemorySpaceDescriptor.Attributes | EFI_MEMORY_RUNTIME;\r
+\r
+  Status = gDS->AddMemorySpace (\r
+                  EfiGcdMemoryTypeMemoryMappedIo,\r
+                  BaseAddress,\r
+                  Length,\r
+                  EFI_MEMORY_RUNTIME | EFI_MEMORY_UC\r
+                  );\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  Status = gDS->SetMemorySpaceAttributes (\r
+                  BaseAddress,\r
+                  Length,\r
+                  Attributes\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = gBS->CreateEventEx (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  PchSpiVirtualddressChangeEvent,\r
+                  NULL,\r
+                  &gEfiEventVirtualAddressChangeGuid,\r
+                  &Event\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  DEBUG ((DEBUG_INFO, "InstallPchSpi() End\n"));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+SpiPhaseInit (\r
+  VOID\r
+  )\r
+/*++\r
+Routine Description:\r
+\r
+  This function is a a hook for Spi Dxe phase specific initialization\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINTN  Index;\r
+\r
+  //\r
+  // Disable SMM BIOS write protect if it's not a SMM protocol\r
+  //\r
+  MmioAnd8 (\r
+    PciDeviceMmBase (PCI_BUS_NUMBER_QNC,\r
+    PCI_DEVICE_NUMBER_QNC_LPC,\r
+    PCI_FUNCTION_NUMBER_QNC_LPC) + R_QNC_LPC_BIOS_CNTL,\r
+    (UINT8) (~B_QNC_LPC_BIOS_CNTL_SMM_BWP)\r
+    );\r
+\r
+    //\r
+    // Save SPI Registers for S3 resume usage\r
+    //\r
+    for (Index = 0; Index < sizeof (mSpiRegister) / sizeof (UINT32); Index++) {\r
+    S3BootScriptSaveMemWrite (\r
+      S3BootScriptWidthUint32,\r
+        (UINTN) (mSpiInstance->PchRootComplexBar + mSpiRegister[Index]),\r
+        1,\r
+        (VOID *) (UINTN) (mSpiInstance->PchRootComplexBar + mSpiRegister[Index])\r
+        );\r
+    }\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpi.h b/QuarkSocPkg/QuarkNorthCluster/Spi/RuntimeDxe/PchSpi.h
new file mode 100644 (file)
index 0000000..50dd60c
--- /dev/null
@@ -0,0 +1,85 @@
+/** @file\r
+Header file for the PCH SPI Runtime Driver.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _PCH_SPI_H_\r
+#define _PCH_SPI_H_\r
+\r
+#include <Library/PcdLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiRuntimeLib.h>\r
+#include <Library/S3BootScriptLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Protocol/Spi.h>\r
+#include "SpiCommon.h"\r
+#include <Library/PciExpressLib.h>\r
+#include <IntelQNCRegs.h>\r
+#include <Library/IntelQNCLib.h>\r
+#include <Library/QNCAccessLib.h>\r
+#include <Library/TimerLib.h>\r
+\r
+#define EFI_INTERNAL_POINTER  0x00000004\r
+\r
+\r
+//\r
+// Function prototypes used by the SPI protocol.\r
+//\r
+VOID\r
+PchSpiVirtualddressChangeEvent (\r
+  IN EFI_EVENT              Event,\r
+  IN VOID                   *Context\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Fixup internal data pointers so that the services can be called in virtual mode.\r
+\r
+Arguments:\r
+\r
+  Event     The event registered.\r
+  Context   Event context. Not used in this event handler.\r
+\r
+Returns:\r
+\r
+  None.\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+EFIAPI\r
+SpiPhaseInit (\r
+  VOID\r
+  )\r
+/*++\r
+Routine Description:\r
+\r
+  This function is a hook for Spi Dxe phase specific initialization\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+;\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpi.c b/QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpi.c
new file mode 100644 (file)
index 0000000..3b11fdf
--- /dev/null
@@ -0,0 +1,129 @@
+/** @file\r
+\r
+PCH SPI SMM Driver implements the SPI Host Controller Compatibility Interface.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+#include "PchSpi.h"\r
+\r
+SPI_INSTANCE          *mSpiInstance;\r
+\r
+CONST UINT32  mSpiRegister[] = {\r
+    R_QNC_RCRB_SPIS,\r
+    R_QNC_RCRB_SPIPREOP,\r
+    R_QNC_RCRB_SPIOPMENU,\r
+    R_QNC_RCRB_SPIOPMENU + 4\r
+  };\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InstallPchSpi (\r
+  IN EFI_HANDLE            ImageHandle,\r
+  IN EFI_SYSTEM_TABLE      *SystemTable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Entry point for the SPI host controller driver.\r
+\r
+Arguments:\r
+\r
+  ImageHandle       Image handle of this driver.\r
+  SystemTable       Global system service table.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS           Initialization complete.\r
+  EFI_UNSUPPORTED       The chipset is unsupported by this driver.\r
+  EFI_OUT_OF_RESOURCES  Do not have enough resources to initialize the driver.\r
+  EFI_DEVICE_ERROR      Device error, driver exits abnormally.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+\r
+  //\r
+  // Allocate pool for SPI protocol instance\r
+  //\r
+  Status = gSmst->SmmAllocatePool (\r
+                    EfiRuntimeServicesData, // MemoryType don't care\r
+                    sizeof (SPI_INSTANCE),\r
+                    (VOID **) &mSpiInstance\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  if (mSpiInstance == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  ZeroMem ((VOID *) mSpiInstance, sizeof (SPI_INSTANCE));\r
+  //\r
+  // Initialize the SPI protocol instance\r
+  //\r
+  Status = SpiProtocolConstructor (mSpiInstance);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Install the SMM EFI_SPI_PROTOCOL interface\r
+  //\r
+  Status = gSmst->SmmInstallProtocolInterface (\r
+            &(mSpiInstance->Handle),\r
+            &gEfiSmmSpiProtocolGuid,\r
+            EFI_NATIVE_INTERFACE,\r
+            &(mSpiInstance->SpiProtocol)\r
+            );\r
+  if (EFI_ERROR (Status)) {\r
+    gSmst->SmmFreePool (mSpiInstance);\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+SpiPhaseInit (\r
+  VOID\r
+  )\r
+/*++\r
+Routine Description:\r
+\r
+  This function is a a hook for Spi Smm phase specific initialization\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINTN  Index;\r
+\r
+  //\r
+  // Save SPI Registers for S3 resume usage\r
+  //\r
+  for (Index = 0; Index < sizeof (mSpiRegister) / sizeof (UINT32); Index++) {\r
+    S3BootScriptSaveMemWrite (\r
+      S3BootScriptWidthUint32,\r
+      (UINTN) (mSpiInstance->PchRootComplexBar + mSpiRegister[Index]),\r
+      1,\r
+      (VOID *) (UINTN) (mSpiInstance->PchRootComplexBar + mSpiRegister[Index])\r
+      );\r
+  }\r
+}\r
diff --git a/QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpi.h b/QuarkSocPkg/QuarkNorthCluster/Spi/Smm/PchSpi.h
new file mode 100644 (file)
index 0000000..64831ee
--- /dev/null
@@ -0,0 +1,53 @@
+/** @file\r
+Header file for the PCH SPI SMM Driver.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _PCH_SPI_H_\r
+#define _PCH_SPI_H_\r
+\r
+#include <Library/IoLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/S3BootScriptLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Protocol/Spi.h>\r
+#include "SpiCommon.h"\r
+#include <Library/SmmServicesTableLib.h>\r
+#include <IntelQNCRegs.h>\r
+#include <Library/IntelQNCLib.h>\r
+#include <Library/QNCAccessLib.h>\r
+#include <Library/TimerLib.h>\r
+\r
+VOID\r
+EFIAPI\r
+SpiPhaseInit (\r
+  VOID\r
+  )\r
+/*++\r
+Routine Description:\r
+\r
+  This function is a hook for Spi Smm phase specific initialization\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+;\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSocPkg.dec b/QuarkSocPkg/QuarkSocPkg.dec
new file mode 100644 (file)
index 0000000..ee25d12
--- /dev/null
@@ -0,0 +1,240 @@
+## @file\r
+# INTEL Quark SoC Module Package Reference Implementations\r
+#\r
+# This Module provides FRAMEWORK reference implementation for INTEL Quark SoC.\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+\r
+################################################################################\r
+#\r
+# Defines Section - statements that will be processed to create a Makefile.\r
+#\r
+################################################################################\r
+\r
+[Defines]\r
+  DEC_SPECIFICATION              = 0x00010005\r
+  PACKAGE_NAME                   = QuarkSocPkg\r
+  PACKAGE_GUID                   = 28DECF17-6C75-448f-87DC-BDE4BD579919\r
+  PACKAGE_VERSION                = 0.1\r
+\r
+\r
+\r
+################################################################################\r
+#\r
+# Include Section - list of Include Paths that are provided by this package.\r
+#                   Comments are used for Keywords and Module Types.\r
+#\r
+# Supported Module Types:\r
+#  SEC PEIM DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER BASE\r
+#\r
+################################################################################\r
+[Includes]\r
+  #\r
+  # North Cluster\r
+  #\r
+  QuarkNorthCluster/Include\r
+  QuarkNorthCluster/MemoryInit/Pei\r
+\r
+  #\r
+  # South Cluster\r
+  #\r
+  QuarkSouthCluster/Include\r
+\r
+################################################################################\r
+#\r
+# Library Class Header section - list of Library Class header files that are\r
+#                                provided by this package.\r
+#\r
+################################################################################\r
+[LibraryClasses]\r
+  #\r
+  # North Cluster\r
+  #\r
+  QNCAccessLib|QuarkNorthCluster/Include/Library/QNCAccessLib.h\r
+  IntelQNCLib|QuarkNorthCluster/Include/Library/IntelQNCLib.h\r
+  IohLib|QuarkSouthCluster/Include/Library/IohLib.h\r
+  I2cLib|QuarkSouthCluster/Include/Library/I2cLib.h\r
+\r
+################################################################################\r
+#\r
+# Global Guid Definition section - list of Global Guid C Name Data Structures\r
+#                                  that are provided by this package.\r
+#\r
+################################################################################\r
+[Guids]\r
+  #\r
+  # North Cluster\r
+  #\r
+  gEfiQuarkNcSocIdTokenSpaceGuid  = { 0xca452c6a, 0xdf0c, 0x4dc9, { 0x82, 0xfb, 0xea, 0xe2, 0xab, 0x31, 0x29, 0x46 }}\r
+  gQncS3CodeInLockBoxGuid   =  { 0x1f18c5b3, 0x29ed, 0x4d9e, {0xa5, 0x4, 0x6d, 0x97, 0x8e, 0x7e, 0xd5, 0x69}}\r
+  gQncS3ContextInLockBoxGuid = { 0xe5769ea9, 0xe706, 0x454b, {0x95, 0x7f, 0xaf, 0xc6, 0xdb, 0x4b, 0x8a, 0xd}}\r
+\r
+  #\r
+  # South Cluster\r
+  #\r
+  gEfiQuarkSCSocIdTokenSpaceGuid  = { 0xef251b71, 0xceed, 0x484e, { 0x82, 0xe3, 0x3a, 0x1f, 0x34, 0xf5, 0x12, 0xe2 }}\r
+\r
+################################################################################\r
+#\r
+# Global Ppi Definition section - list of Global Ppi C Name Data Structures\r
+#                                  that are provided by this package.\r
+#\r
+################################################################################\r
+[Ppis]\r
+  #\r
+  # North Cluster\r
+  #\r
+  gQNCMemoryInitPpiGuid = { 0x21ff1fee, 0xd33a, 0x4fce, { 0xa6, 0x5e, 0x95, 0x5e, 0xa3, 0xc4, 0x1f, 0x40}}\r
+\r
+################################################################################\r
+#\r
+# Global Protocols Definition section - list of Global Protocols C Name Data\r
+#                                  Structures that are provided by this package.\r
+#\r
+################################################################################\r
+[Protocols]\r
+  #\r
+  # North Cluster\r
+  #\r
+  gEfiPlatformPolicyProtocolGuid = { 0x2977064F, 0xAB96, 0x4FA9, { 0x85, 0x45, 0xF9, 0xC4, 0x02, 0x51, 0xE0, 0x7F }}\r
+  gEfiSmmIchnDispatch2ProtocolGuid = { 0xadf3a128, 0x416d, 0x4060, { 0x8d, 0xdf, 0x30, 0xa1, 0xd7, 0xaa, 0xb6, 0x99 }}\r
+  gEfiSpiProtocolGuid = { 0x1156efc6, 0xea32, 0x4396, { 0xb5, 0xd5, 0x26, 0x93, 0x2e, 0x83, 0xc3, 0x13 }}\r
+  gEfiSmmSpiProtocolGuid  = { 0xD9072C35, 0xEB8F, 0x43ad, { 0xA2, 0x20, 0x34, 0xD4, 0x0E, 0x2A, 0x82, 0x85 }}\r
+  gEfiQncS3SupportProtocolGuid  = { 0xe287d20b, 0xd897, 0x4e1e, { 0xa5, 0xd9, 0x97, 0x77, 0x63, 0x93, 0x6a, 0x4 }}\r
+\r
+  #\r
+  # South Cluster\r
+  #\r
+  gEfiSDHostIoProtocolGuid = {0xb63f8ec7, 0xa9c9, 0x4472, {0xa4, 0xc0, 0x4d, 0x8b, 0xf3, 0x65, 0xcc, 0x51}}\r
+\r
+################################################################################\r
+#\r
+# PCD Declarations section - list of all PCDs Declared by this Package\r
+#                            Only this package should be providing the\r
+#                            declaration, other packages should not.\r
+#\r
+################################################################################\r
+\r
+[PcdsFeatureFlag]\r
+  #\r
+  # North Cluster\r
+  #\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmbaIoBaseAddressFixed|TRUE|BOOLEAN|0x10000001\r
+\r
+  #\r
+  # South Cluster\r
+  #\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdEhciRecoveryEnabled|FALSE|BOOLEAN|0x10000003\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdI2CFastModeEnabled|FALSE|BOOLEAN|0x10000005\r
+\r
+  #\r
+  # Feature Flag equivalent to linux SDHCI_QUIRK_NO_HISPD_BIT to stop\r
+  # setting of SD HCI hi_spd_en bit in HOST_CTL register.\r
+  #\r
+  # Alway TRUE ie high speed enable bit must never\r
+  # be set so we stay within SD interface Setup/Hold time.\r
+  #\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdSdHciQuirkNoHiSpd|TRUE|BOOLEAN|0x10000004\r
+\r
+[PcdsFixedAtBuild]\r
+  #\r
+  # North Cluster\r
+  #\r
+\r
+  # Values of Io Port Base Address, MMIO base address and space size.\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress|0x1000|UINT16|0x10000200\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPmbaIoBaseAddress|0x1010|UINT16|0x10000201\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPmbaIoLVL2|0x1014|UINT16|0x10000202\r
+\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdGbaIoBaseAddress|0x1080|UINT16|0x10000205\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress|0x1100|UINT16|0x10000206\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmbaIoBaseAddress|0x1040|UINT16|0x10000207\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdWdtbaIoBaseAddress|0x1140|UINT16|0x10000209\r
+\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdRcbaMmioBaseAddress|0xFED1C000|UINT64|0x1000020B\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdIoApicBaseAddress|0xFEC00000|UINT64|0x1000020C\r
+\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdIoApicSize|0x1000|UINT64|0x1000020D\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdRcbaMmioSize|0x4000|UINT64|0x1000020E\r
+\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciExpressSize|0x02000000|UINT64|0x1000020F\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdHpetBaseAddress|0xFED00000|UINT64|0x10000210\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdHpetSize|0x400|UINT64|0x10000211\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdTSegSize|0x200000|UINT32|0x10000212\r
+\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciHostBridgeIoBase|0x2000|UINT16|0x10000214\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciHostBridgeIoSize|0xE000|UINT16|0x10000215\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciHostBridgeMemory32Base|0x90000000|UINT32|0x1000021B\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciHostBridgeMemory32Size|0x20000000|UINT32|0x1000021C\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciHostBridgeMemory64Base|0xB0000000|UINT64|0x1000021D\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPciHostBridgeMemory64Size|0x30000000|UINT64|0x1000021E\r
+\r
+  # Values for programming Interrupt Route Configuration Registers:\r
+  # Indicates which interrupt routing is connected to the INTA/B/C/D pins reported in the\r
+  # "DxIP" register fields. This will be the internal routing, the device interrupt is connected\r
+  # to the interrupt controller.\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdQuarkAgent0IR|0x0000|UINT16|0x10000223\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdQuarkAgent1IR|0x7654|UINT16|0x10000224\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdQuarkAgent2IR|0x0000|UINT16|0x10000225\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdQuarkAgent3IR|0x3210|UINT16|0x10000226\r
+\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmActivationPort|0xb2|UINT16|0x10000232\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmDataPort|0xb3|UINT16|0x10000233\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmActivationData|0x55|UINT8|0x10000234\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPlatformSmbusAddrNum|0x0|UINT32|0x10000235\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPlatformSmbusAddrTable|0x0|UINT64|0x10000236\r
+\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdESramMemorySize|0x00080000|UINT32|0x10000240\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdDeviceEnables|0x03|UINT32|0x10000237\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdPcieRootPortConfiguration|{0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00}|VOID*|0x10000239\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdQuarkMicrocodeFile |{ 0x8B, 0xEA, 0x5E, 0xD7, 0xD2, 0x23, 0xD4, 0x4E, 0xBC, 0x4F, 0x57, 0x51, 0xD4, 0xA1, 0x8D, 0xCF }|VOID*|0x1000023A\r
+\r
+  #\r
+  # South Cluster\r
+  #\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohI2cMmioBase|0xA001F000|UINT64|0x20000005\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdPeiP2PMemoryBaseAddress|0xA0000000|UINT32|0x20000006\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdPeiQNCUsbControllerMemoryBaseAddress|0xA0010000|UINT32|0x20000007\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohGpioMmioBase|0xA0020000|UINT64|0x20000008\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohMac0MmioBase|0xA0024000|UINT64|0x20000009\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohMac1MmioBase|0xA0028000|UINT64|0x2000000A\r
+\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartBusNumber|0x00|UINT8|0x20000013\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartDevNumber|0x14|UINT8|0x20000014\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartFunctionNumber|0x5|UINT8|0x20000001\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohGpioBusNumber|0x00|UINT8|0x20000029\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohGpioDevNumber|0x15|UINT8|0x2000002A\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohGpioFunctionNumber|0x2|UINT8|0x2000002B\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohGpioBarRegister|0x14|UINT8|0x2000002D\r
+\r
+[PcdsDynamic, PcdsDynamicEx]\r
+  #\r
+  # North Cluster\r
+  #\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdQncS3CodeInLockBoxAddress|0|UINT64|0x30000026\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdQncS3CodeInLockBoxSize|0|UINT64|0x30000027\r
+\r
+  ## Intel(R) Quark(TM) Soc X1000 processor MRC Parameters.  Default is for Galileo Gen 2 platform.<BR><BR>\r
+  # @Prompt Intel(R) Quark(TM) Soc X1000 processor MRC Parameters.\r
+  gEfiQuarkNcSocIdTokenSpaceGuid.PcdMrcParameters|{0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x7c, 0x92, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x40, 0x9c, 0x00, 0x00, 0x06}|VOID*|0x40000001\r
+\r
+  #\r
+  # South Cluster\r
+  #\r
+  ## MAC0 address for the Ethernet Controller in Intel(R) Quark(TM) Soc X1000 processor.  Default is 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff.<BR><BR>\r
+  # @Prompt Ethernet MAC 0 Address.\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohEthernetMac0|{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}|VOID*|0x50000001\r
+\r
+  ## MAC1 address for the Ethernet Controller in Intel(R) Quark(TM) Soc X1000 processor.  Default is 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff.<BR><BR>\r
+  # @Prompt Ethernet MAC 1 Address.\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohEthernetMac1|{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}|VOID*|0x50000002\r
diff --git a/QuarkSocPkg/QuarkSocPkg.dsc b/QuarkSocPkg/QuarkSocPkg.dsc
new file mode 100644 (file)
index 0000000..3c8dfca
--- /dev/null
@@ -0,0 +1,259 @@
+## @file\r
+# INTEL Quark SoC Module Package Reference Implementations\r
+#\r
+# This DSC file is used for Package Level build.\r
+#\r
+# This Module provides FRAMEWORK reference implementation for INTEL Quark SoC.\r
+#   Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+#   This program and the accompanying materials\r
+#   are licensed and made available under the terms and conditions of the BSD License\r
+#   which accompanies this distribution.  The full text of the license may be found at\r
+#   http://opensource.org/licenses/bsd-license.php\r
+#\r
+#   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+################################################################################\r
+#\r
+# Defines Section - statements that will be processed to create a Makefile.\r
+#\r
+################################################################################\r
+[Defines]\r
+  PLATFORM_NAME                  = QuarkSocPkg\r
+  PLATFORM_GUID                  = 5F9864F4-EAFB-4ded-A41A-CA501EE50502\r
+  PLATFORM_VERSION               = 0.1\r
+  DSC_SPECIFICATION              = 0x00010005\r
+  OUTPUT_DIRECTORY               = Build/QuarkSocPkg\r
+  SUPPORTED_ARCHITECTURES        = IA32|X64\r
+  BUILD_TARGETS                  = DEBUG|RELEASE\r
+  SKUID_IDENTIFIER               = DEFAULT\r
+\r
+################################################################################\r
+#\r
+# SKU Identification section - list of all SKU IDs supported by this\r
+#                              Platform.\r
+#\r
+################################################################################\r
+[SkuIds]\r
+  0|DEFAULT              # The entry: 0|DEFAULT is reserved and always required.\r
+\r
+################################################################################\r
+#\r
+# Library Class section - list of all Library Classes needed by this Platform.\r
+#\r
+################################################################################\r
+[LibraryClasses]\r
+  #\r
+  # Entry point\r
+  #\r
+  PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf\r
+  UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf\r
+  #\r
+  # Basic\r
+  #\r
+  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf\r
+  BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf\r
+  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf\r
+  CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf\r
+  IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf\r
+  PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf\r
+  PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf\r
+  PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf\r
+  CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf\r
+  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf\r
+!if $(CFG_SOURCE_DEBUG) == 1\r
+  PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf\r
+!else\r
+  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf\r
+!endif\r
+  #\r
+  # UEFI & PI\r
+  #\r
+  UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf\r
+  UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf\r
+  UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf\r
+  UefiLib|MdePkg/Library/UefiLib/UefiLib.inf\r
+  DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf\r
+  PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf\r
+  PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf\r
+  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf\r
+  DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf\r
+  UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf\r
+  #\r
+  # Framework\r
+  #\r
+  S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf\r
+  S3IoLib|MdePkg/Library/BaseS3IoLib/BaseS3IoLib.inf\r
+  S3PciLib|MdePkg/Library/BaseS3PciLib/BaseS3PciLib.inf\r
+  #\r
+  # Generic Modules\r
+  #\r
+  OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf\r
+\r
+  #\r
+  # CPU\r
+  #\r
+  MtrrLib|QuarkSocPkg/QuarkNorthCluster/Library/MtrrLib/MtrrLib.inf\r
+  #\r
+  # Quark North Cluster\r
+  #\r
+  SmmLib|QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.inf\r
+  SmbusLib|QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.inf\r
+  TimerLib|PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf\r
+  ResetSystemLib|QuarkSocPkg/QuarkNorthCluster/Library/ResetSystemLib/ResetSystemLib.inf\r
+  IntelQNCLib|QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/IntelQNCLib.inf\r
+  QNCAccessLib|QuarkSocPkg/QuarkNorthCluster/Library/QNCAccessLib/QNCAccessLib.inf\r
+  #\r
+  # Quark South Cluster\r
+  #\r
+  IohLib|QuarkSocPkg/QuarkSouthCluster/Library/IohLib/IohLib.inf\r
+  SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf\r
+  PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf\r
+  #\r
+  # Misc\r
+  #\r
+  DebugLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf\r
+  DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf\r
+  PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf\r
+  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf\r
+!if $(CFG_SOURCE_DEBUG) == TRUE\r
+  DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf\r
+!else\r
+  DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf\r
+!endif\r
+\r
+[LibraryClasses.IA32.PEIM,LibraryClasses.IA32.PEI_CORE]\r
+  #\r
+  # SEC and PEI phase common\r
+  #\r
+  PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf\r
+  HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf\r
+  MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf\r
+  ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf\r
+  LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf\r
+  PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf\r
+!if $(CFG_SOURCE_DEBUG) == TRUE\r
+  DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf\r
+!endif\r
+  TimerLib|PcAtChipsetPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.inf\r
+\r
+[LibraryClasses.IA32.SEC]\r
+  #\r
+  # SEC specific phase\r
+  #\r
+  ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf\r
+  DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf\r
+  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf\r
+  TimerLib|PcAtChipsetPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.inf\r
+\r
+[LibraryClasses.IA32]\r
+  #\r
+  # DXE phase common\r
+  #\r
+  PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf\r
+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf\r
+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf\r
+  ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf\r
+  LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf\r
+!if $(CFG_SOURCE_DEBUG) == 1\r
+  DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf\r
+!endif\r
+\r
+[LibraryClasses.IA32.DXE_SMM_DRIVER]\r
+  SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf\r
+  ReportStatusCodeLib|MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf\r
+  MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf\r
+  LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf\r
+!if $(CFG_SOURCE_DEBUG) == TRUE\r
+  DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf\r
+!endif\r
+\r
+[LibraryClasses.IA32.SMM_CORE]\r
+  ReportStatusCodeLib|MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf\r
+\r
+[LibraryClasses.IA32.DXE_RUNTIME_DRIVER]\r
+  ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf\r
+\r
+[LibraryClasses.IA32.UEFI_DRIVER,LibraryClasses.IA32.UEFI_APPLICATION]\r
+  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf\r
+\r
+################################################################################\r
+#\r
+# Pcd Section - list of all EDK II PCD Entries defined by this Platform\r
+#\r
+################################################################################\r
+\r
+[PcdsFixedAtBuild]\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialLineControl|0x03\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialFifoControl|0x07\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialDetectCable|FALSE\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate|44236800\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialPciDeviceInfo|{0x14, 0x05, 0x84, 0x00, 0xFF}\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride|4\r
+\r
+  gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciBusNumber           |0\r
+  gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciDeviceNumber        |31\r
+  gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciFunctionNumber      |0\r
+  gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciEnableRegisterOffset|0x4b\r
+  gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoBarEnableMask          |0x80\r
+  gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciBarRegisterOffset   |0x48\r
+  gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPortBaseAddress        |0x1000\r
+  gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiPm1TmrOffset             |0x0008\r
+\r
+[PcdsFeatureFlag]\r
+\r
+################################################################################\r
+#\r
+# Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform\r
+#\r
+################################################################################\r
+\r
+[PcdsDynamicDefault.common.DEFAULT]\r
+\r
+###################################################################################################\r
+#\r
+# Components Section - list of the modules and components that will be processed by compilation\r
+#                      tools and the EDK II tools to generate PE32/PE32+/Coff image files.\r
+#\r
+# Note: The EDK II DSC file is not used to specify how compiled binary images get placed\r
+#       into firmware volume images. This section is just a list of modules to compile from\r
+#       source into UEFI-compliant binaries.\r
+#       It is the FDF file that contains information on combining binary files into firmware\r
+#       volume images, whose concept is beyond UEFI and is described in PI specification.\r
+#       Binary modules do not need to be listed in this section, as they should be\r
+#       specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi),\r
+#       Logo (Logo.bmp), and etc.\r
+#       There may also be modules listed in this section that are not required in the FDF file,\r
+#       When a module listed here is excluded from FDF file, then UEFI-compliant binary will be\r
+#       generated for it, but the binary will not be put into any firmware volume.\r
+#\r
+###################################################################################################\r
+\r
+[Components]\r
+  QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/MemoryInitPei.inf\r
+  QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.inf\r
+  QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmControlPei/SmmControlPei.inf\r
+  QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInitDxe.inf\r
+  QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccess.inf\r
+  QuarkSocPkg/QuarkNorthCluster/Spi/PchSpiRuntime.inf {\r
+    <LibraryClasses>\r
+      PciExpressLib|MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.inf\r
+  }\r
+  QuarkSocPkg/QuarkNorthCluster/Spi/PchSpiSmm.inf\r
+  QuarkSocPkg/QuarkNorthCluster/S3Support/Dxe/QncS3Support.inf {\r
+    <LibraryClasses>\r
+    DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf\r
+    PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf\r
+  }\r
+  QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmControlDxe/SmmControlDxe.inf\r
+  QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmDispatcher.inf\r
+\r
+  QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.inf\r
+  QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciPei.inf\r
+  QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInitDxe.inf\r
+  QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDxe.inf\r
+  QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDControllerDxe.inf\r
+  QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDeviceDxe.inf\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Include/CEATA.h b/QuarkSocPkg/QuarkSouthCluster/Include/CEATA.h
new file mode 100644 (file)
index 0000000..741e7dd
--- /dev/null
@@ -0,0 +1,120 @@
+/** @file\r
+\r
+Header file for chipset CE-AT spec.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _CE_ATA_H\r
+#define _CE_ATA_H\r
+\r
+#pragma pack(1)\r
+\r
+\r
+#define  DATA_UNIT_SIZE       512\r
+\r
+\r
+#define  CMD60                60\r
+#define  CMD61                61\r
+\r
+\r
+#define RW_MULTIPLE_REGISTER  CMD60\r
+#define RW_MULTIPLE_BLOCK     CMD61\r
+\r
+\r
+#define CE_ATA_SIG_CE         0xCE\r
+#define CE_ATA_SIG_AA         0xAA\r
+\r
+\r
+#define Reg_Features_Exp      01\r
+#define Reg_SectorCount_Exp   02\r
+#define Reg_LBALow_Exp        03\r
+#define Reg_LBAMid_Exp        04\r
+#define Reg_LBAHigh_Exp       05\r
+#define Reg_Control           06\r
+#define Reg_Features_Error    09\r
+#define Reg_SectorCount       10\r
+#define Reg_LBALow            11\r
+#define Reg_LBAMid            12\r
+#define Reg_LBAHigh           13\r
+#define Reg_Device_Head       14\r
+#define Reg_Command_Status    15\r
+\r
+#define Reg_scrTempC          0x80\r
+#define Reg_scrTempMaxP       0x84\r
+#define Reg_scrTempMinP       0x88\r
+#define Reg_scrStatus         0x8C\r
+#define Reg_scrReallocsA      0x90\r
+#define Reg_scrERetractsA     0x94\r
+#define Reg_scrCapabilities   0x98\r
+#define Reg_scrControl        0xC0\r
+\r
+\r
+\r
+typedef struct {\r
+  UINT8  Reserved0;\r
+  UINT8  Features_Exp;\r
+  UINT8  SectorCount_Exp;\r
+  UINT8  LBALow_Exp;\r
+  UINT8  LBAMid_Exp;\r
+  UINT8  LBAHigh_Exp;\r
+  UINT8  Control;\r
+  UINT8  Reserved1[2];\r
+  UINT8  Features_Error;\r
+  UINT8  SectorCount;\r
+  UINT8  LBALow;\r
+  UINT8  LBAMid;\r
+  UINT8  LBAHigh;\r
+  UINT8  Device_Head;\r
+  UINT8  Command_Status;\r
+}TASK_FILE;\r
+\r
+\r
+//\r
+//Reduced ATA command set\r
+//\r
+#define IDENTIFY_DEVICE       0xEC\r
+#define READ_DMA_EXT          0x25\r
+#define WRITE_DMA_EXT         0x35\r
+#define STANDBY_IMMEDIATE     0xE0\r
+#define FLUSH_CACHE_EXT       0xEA\r
+\r
+\r
+\r
+typedef struct {\r
+  UINT16  Reserved0[10];\r
+  UINT16  SerialNumber[10];\r
+  UINT16  Reserved1[3];\r
+  UINT16  FirmwareRevision[4];\r
+  UINT16  ModelNumber[20];\r
+  UINT16  Reserved2[33];\r
+  UINT16  MajorVersion;\r
+  UINT16  Reserved3[19];\r
+  UINT16  MaximumLBA[4];\r
+  UINT16  Reserved4[2];\r
+  UINT16  Sectorsize;\r
+  UINT16  Reserved5;\r
+  UINT16  DeviceGUID[4];\r
+  UINT16  Reserved6[94];\r
+  UINT16  Features;\r
+  UINT16  MaxWritesPerAddress;\r
+  UINT16  Reserved7[47];\r
+  UINT16  IntegrityWord;\r
+}IDENTIFY_DEVICE_DATA;\r
+\r
+\r
+\r
+\r
+\r
+#pragma pack()\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Include/I2cRegs.h b/QuarkSocPkg/QuarkSouthCluster/Include/I2cRegs.h
new file mode 100644 (file)
index 0000000..eb0766f
--- /dev/null
@@ -0,0 +1,101 @@
+/** @file\r
+Include file for I2C DXE Driver register definitions (PCIe config. space and memory space).\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _I2C_REGS_H_\r
+#define _I2C_REGS_H_\r
+\r
+\r
+//----------------------------------------------------------------------------\r
+/// I2C Device Address\r
+//----------------------------------------------------------------------------\r
+typedef struct {\r
+  ///\r
+  /// The I2C hardware address to which the I2C device is preassigned or allocated.\r
+  ///\r
+  UINTN I2CDeviceAddress : 10;\r
+} EFI_I2C_DEVICE_ADDRESS;\r
+\r
+//----------------------------------------------------------------------------\r
+/// I2C Addressing Mode (7-bit or 10 bit)\r
+//----------------------------------------------------------------------------\r
+typedef enum _EFI_I2C_ADDR_MODE {\r
+  EfiI2CSevenBitAddrMode,\r
+  EfiI2CTenBitAddrMode,\r
+} EFI_I2C_ADDR_MODE;\r
+\r
+\r
+//----------------------------------------------------------------------------\r
+// I2C Controller B:D:F\r
+//----------------------------------------------------------------------------\r
+#define I2C_Bus     0x00\r
+#define I2C_Device  0x15\r
+#define I2C_Func    0x02\r
+\r
+//----------------------------------------------------------------------------\r
+// Memory Mapped Registers\r
+//----------------------------------------------------------------------------\r
+#define I2C_REG_CON                        0x00          // Control Register\r
+#define   B_I2C_REG_CON_SPEED                (BIT2+BIT1)   // standard mode (01) or fast mode (10)\r
+#define   B_I2C_REG_CON_10BITADD_MASTER      (BIT4)        // 7-bit addressing (0) or 10-bit addressing (1)\r
+#define I2C_REG_TAR                        0x04          // Master Target Address Register\r
+#define   B_I2C_REG_TAR                      (BIT9+BIT8+BIT7+BIT6+BIT5+BIT4+BIT3+BIT2+BIT1+BIT0) // Master Target Address bits\r
+#define I2C_REG_DATA_CMD                   0x10          // Data Buffer and Command Register\r
+#define   B_I2C_REG_DATA_CMD_RW              (BIT8)      // Data Buffer and Command Register Read/Write bit\r
+#define   B_I2C_REG_DATA_CMD_STOP            (BIT9)      // Data Buffer and Command Register STOP bit\r
+#define   B_I2C_REG_DATA_CMD_RESTART         (BIT10)     // Data Buffer and Command Register RESTART bit\r
+#define I2C_REG_SS_SCL_HCNT                0x14          // Standard Speed Clock SCL High Count Register\r
+#define I2C_REG_SS_SCL_LCNT                0x18          // Standard Speed Clock SCL Low Count Register\r
+#define I2C_REG_FS_SCL_HCNT                0x1C          // Fast Speed Clock SCL High Count Register\r
+#define I2C_REG_FS_SCL_LCNT                0x20          // Fast Speed Clock SCL Low Count Register\r
+#define I2C_REG_INTR_STAT                  0x2C          // Interrupt Status Register\r
+#define   B_I2C_REG_INTR_STAT_STOP_DET       (BIT9)        // Interrupt Status Register STOP_DET signal status\r
+#define I2C_REG_INTR_MASK                  0x30          // Interrupt Status Mask Register\r
+#define I2C_REG_RAW_INTR_STAT              0x34          // Raw Interrupt Status Register\r
+#define   I2C_REG_RAW_INTR_STAT_STOP_DET    (BIT9)         // Raw Interrupt Status Register STOP_DET signal status.\r
+#define   I2C_REG_RAW_INTR_STAT_TX_ABRT     (BIT6)         // Raw Interrupt Status Register TX Abort status.\r
+#define   I2C_REG_RAW_INTR_STAT_TX_OVER     (BIT3)         // Raw Interrupt Status Register TX Overflow signal status.\r
+#define   I2C_REG_RAW_INTR_STAT_RX_OVER     (BIT1)         // Raw Interrupt Status Register RX Overflow signal status.\r
+#define   I2C_REG_RAW_INTR_STAT_RX_UNDER    (BIT0)         // Raw Interrupt Status Register RX Underflow signal status.\r
+#define I2C_REG_RX_TL                      0x38          // Receive FIFO Threshold Level Register\r
+#define I2C_REG_TX_TL                      0x3C          // Transmit FIFO Threshold Level Register\r
+#define I2C_REG_CLR_INT                    0x40          // Clear Combined and Individual Interrupt Register\r
+#define I2C_REG_CLR_RX_UNDER               0x44          // Clear RX Under Interrupt Register\r
+#define I2C_REG_CLR_RX_OVER                0x48          // Clear RX Over Interrupt Register\r
+#define I2C_REG_CLR_TX_OVER                0x4C          // Clear TX Over Interrupt Register\r
+#define I2C_REG_CLR_RD_REQ                 0x50          // Clear RD REQ Interrupt Register\r
+#define I2C_REG_CLR_TX_ABRT                0x54          // Clear TX ABRT Interrupt Register\r
+#define I2C_REG_CLR_ACTIVITY               0x5C          // Clear Activity Interrupt Register\r
+#define I2C_REG_CLR_STOP_DET               0x60          // Clear STOP DET Interrupt Register\r
+#define   B_I2C_REG_CLR_STOP_DET             (BIT0)        // Clear STOP DET Interrupt Register\r
+#define I2C_REG_CLR_START_DET              0x64          // Clear START DET Interrupt Register\r
+#define   B_I2C_REG_CLR_START_DET          (BIT0)          // Clear START DET Interrupt Register\r
+#define I2C_REG_ENABLE                     0x6C          // Enable Register\r
+#define   B_I2C_REG_ENABLE                   (BIT0)        // Enable (1) or disable (0) I2C Controller\r
+#define I2C_REG_STATUS                     0x70          // Status Register\r
+#define I2C_REG_TXFLR                      0x74          // Transmit FIFO Level Register\r
+#define   B_I2C_REG_TXFLR                   (BIT3+BIT2+BIT1+BIT0)  // Transmit FIFO Level Register bits\r
+#define I2C_REG_RXFLR                      0x78          // Receive FIFO Level Register\r
+#define   B_I2C_REG_RXFLR                   (BIT3+BIT2+BIT1+BIT0)  // Receive FIFO Level Register bits\r
+#define I2C_REG_SDA_HOLD                   0x7C          // SDA HOLD Register\r
+#define I2C_REG_TX_ABRT_SOURCE             0x80          // Transmit Abort Source Register\r
+#define I2C_REG_ENABLE_STATUS              0x9C          // Enable Status Register\r
+#define I2C_REG_FS_SPKLEN                  0xA0          // SS and FS Spike Suppression Limit Register\r
+\r
+//\r
+// Features.\r
+//\r
+#define I2C_FIFO_SIZE                      16\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Include/Ioh.h b/QuarkSocPkg/QuarkSouthCluster/Include/Ioh.h
new file mode 100644 (file)
index 0000000..3ac2a45
--- /dev/null
@@ -0,0 +1,254 @@
+/** @file\r
+Header file for QuarkSCSocId Ioh.\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+#ifndef _IOH_H_\r
+#define _IOH_H_\r
+\r
+#ifndef BIT0\r
+#define BIT0    0x01\r
+#define BIT1    0x02\r
+#define BIT2    0x04\r
+#define BIT3    0x08\r
+#define BIT4    0x10\r
+#define BIT5    0x20\r
+#define BIT6    0x40\r
+#define BIT7    0x80\r
+#define BIT8    0x100\r
+#define BIT9    0x200\r
+#define BIT00   0x00000001\r
+#define BIT01   0x00000002\r
+#define BIT02   0x00000004\r
+#define BIT03   0x00000008\r
+#define BIT04   0x00000010\r
+#define BIT05   0x00000020\r
+#define BIT06   0x00000040\r
+#define BIT07   0x00000080\r
+#define BIT08   0x00000100\r
+#define BIT09   0x00000200\r
+#define BIT10   0x00000400\r
+#define BIT11   0x00000800\r
+#define BIT12   0x00001000\r
+#define BIT13   0x00002000\r
+#define BIT14   0x00004000\r
+#define BIT15   0x00008000\r
+#define BIT16   0x00010000\r
+#define BIT17   0x00020000\r
+#define BIT18   0x00040000\r
+#define BIT19   0x00080000\r
+#define BIT20   0x00100000\r
+#define BIT21   0x00200000\r
+#define BIT22   0x00400000\r
+#define BIT23   0x00800000\r
+#define BIT24   0x01000000\r
+#define BIT25   0x02000000\r
+#define BIT26   0x04000000\r
+#define BIT27   0x08000000\r
+#define BIT28   0x10000000\r
+#define BIT29   0x20000000\r
+#define BIT30   0x40000000\r
+#define BIT31   0x80000000\r
+#endif\r
+\r
+#define IOH_PCI_CFG_ADDRESS(bus,dev,func,reg) \\r
+    ((UINT32) ( (((UINTN)bus) << 24) + (((UINTN)dev) << 16) + \\r
+    (((UINTN)func) << 8) + ((UINTN)reg) ))& 0x00000000ffffffff\r
+\r
+//----------------------------------------------------------------------------\r
+\r
+#define INTEL_VENDOR_ID         0x8086  // Intel Vendor ID\r
+\r
+//----------------------------------------------------------------------------\r
+// Pci Configuration Map Register Offsets\r
+//----------------------------------------------------------------------------\r
+#define PCI_REG_VID             0x00    // Vendor ID Register\r
+#define PCI_REG_DID             0x02    // Device ID Register\r
+#define PCI_REG_PCICMD          0x04    // PCI Command Register\r
+#define PCI_REG_PCISTS          0x06    // PCI Status Register\r
+#define PCI_REG_RID             0x08    // PCI Revision ID Register\r
+#define PCI_REG_PI              0x09    // Programming Interface\r
+#define PCI_REG_SCC             0x0a    // Sub Class Code Register\r
+#define PCI_REG_BCC             0x0b    // Base Class Code Register\r
+#define PCI_REG_PMLT            0x0d    // Primary Master Latnecy Timer\r
+#define PCI_REG_HDR             0x0e    // Header Type Register\r
+#define PCI_REG_PBUS            0x18    // Primary Bus Number Register\r
+#define PCI_REG_SBUS            0x19    // Secondary Bus Number Register\r
+#define PCI_REG_SUBUS           0x1a    // Subordinate Bus Number Register\r
+#define PCI_REG_SMLT            0x1b    // Secondary Master Latnecy Timer\r
+#define PCI_REG_IOBASE          0x1c    // I/O base Register\r
+#define PCI_REG_IOLIMIT         0x1d    // I/O Limit Register\r
+#define PCI_REG_SECSTATUS       0x1e    // Secondary Status Register\r
+#define PCI_REG_MEMBASE         0x20    // Memory Base Register\r
+#define PCI_REG_MEMLIMIT        0x22    // Memory Limit Register\r
+#define PCI_REG_PRE_MEMBASE     0x24    // Prefretchable memory Base register\r
+#define PCI_REG_PRE_MEMLIMIT    0x26    // Prefretchable memory Limit register\r
+#define PCI_REG_SVID0           0x2c    // Subsystem Vendor ID low byte\r
+#define PCI_REG_SVID1           0x2d    // Subsystem Vendor ID high byte\r
+#define PCI_REG_SID0            0x2e    // Subsystem ID low byte\r
+#define PCI_REG_SID1            0x2f    // Subsystem ID high byte\r
+#define PCI_REG_IOBASE_U        0x30    // I/O base Upper Register\r
+#define PCI_REG_IOLIMIT_U       0x32    // I/O Limit Upper Register\r
+#define PCI_REG_INTLINE         0x3c    // Interrupt Line Register\r
+#define PCI_REG_BRIDGE_CNTL     0x3e    // Bridge Control Register\r
+\r
+//---------------------------------------------------------------------------\r
+// QuarkSCSocId Packet Hub definitions\r
+//---------------------------------------------------------------------------\r
+\r
+#define PCIE_BRIDGE_VID_DID     0x88008086\r
+\r
+//---------------------------------------------------------------------------\r
+// Quark South Cluster definitions.\r
+//---------------------------------------------------------------------------\r
+\r
+#define IOH_BUS                           0\r
+#define IOH_PCI_IOSF2AHB_0_DEV_NUM        0x14\r
+#define IOH_PCI_IOSF2AHB_0_MAX_FUNCS      7\r
+#define IOH_PCI_IOSF2AHB_1_DEV_NUM        0x15\r
+#define IOH_PCI_IOSF2AHB_1_MAX_FUNCS      3\r
+\r
+//---------------------------------------------------------------------------\r
+// Quark South Cluster USB definitions.\r
+//---------------------------------------------------------------------------\r
+\r
+#define IOH_USB_BUS_NUMBER                IOH_BUS\r
+#define IOH_USB_CONTROLLER_MMIO_RANGE     0x1000\r
+#define IOH_MAX_OHCI_USB_CONTROLLERS      1\r
+#define IOH_MAX_EHCI_USB_CONTROLLERS      1\r
+#define IOH_MAX_USBDEVICE_USB_CONTROLLERS 1\r
+\r
+#define R_IOH_USB_VENDOR_ID               0x00\r
+#define   V_IOH_USB_VENDOR_ID               INTEL_VENDOR_ID\r
+#define R_IOH_USB_DEVICE_ID               0x02\r
+#define R_IOH_USB_COMMAND                 0x04\r
+#define   B_IOH_USB_COMMAND_BME             BIT2\r
+#define   B_IOH_USB_COMMAND_MSE             BIT1\r
+#define   B_IOH_USB_COMMAND_ISE             BIT0\r
+#define R_IOH_USB_MEMBAR                  0x10\r
+#define   B_IOH_USB_MEMBAR_ADDRESS_MASK     0xFFFFF000  // [31:12].\r
+#define R_IOH_USB_OHCI_HCCABAR            0x18\r
+\r
+//---------------------------------------------------------------------------\r
+// Quark South Cluster OHCI definitions\r
+//---------------------------------------------------------------------------\r
+#define IOH_USB_OHCI_DEVICE_NUMBER        IOH_PCI_IOSF2AHB_0_DEV_NUM\r
+#define IOH_OHCI_FUNCTION_NUMBER          0x04\r
+\r
+//---------------------------------------------------------------------------\r
+// Quark South Cluster EHCI definitions\r
+//---------------------------------------------------------------------------\r
+#define IOH_USB_EHCI_DEVICE_NUMBER        IOH_PCI_IOSF2AHB_0_DEV_NUM\r
+#define IOH_EHCI_FUNCTION_NUMBER          0x03\r
+\r
+//\r
+// EHCI memory mapped registers offset from memory BAR0.\r
+//\r
+#define R_IOH_EHCI_CAPLENGTH              0x00\r
+#define R_IOH_EHCI_INSNREG01              0x94\r
+#define   B_IOH_EHCI_INSNREG01_OUT_THRESHOLD_BP    (16)\r
+#define   B_IOH_EHCI_INSNREG01_OUT_THRESHOLD_MASK  (0xff << B_IOH_EHCI_INSNREG01_OUT_THRESHOLD_BP)\r
+#define   B_IOH_EHCI_INSNREG01_IN_THRESHOLD_BP     (0)\r
+#define   B_IOH_EHCI_INSNREG01_IN_THRESHOLD_MASK   (0xff << B_IOH_EHCI_INSNREG01_IN_THRESHOLD_BP)\r
+\r
+//\r
+// EHCI memory mapped registers offset from memory BAR0 + Cap length value.\r
+//\r
+#define R_IOH_EHCI_CONFIGFLAGS            0x40\r
+\r
+//---------------------------------------------------------------------------\r
+// Quark South Cluster USB Device definitions\r
+//---------------------------------------------------------------------------\r
+#define IOH_USBDEVICE_DEVICE_NUMBER       IOH_PCI_IOSF2AHB_0_DEV_NUM\r
+#define IOH_USBDEVICE_FUNCTION_NUMBER     0x02\r
+\r
+//\r
+// USB Device memory mapped registers offset from memory BAR0.\r
+//\r
+#define R_IOH_USBDEVICE_D_INTR_UDC_REG                      0x40c\r
+#define R_IOH_USBDEVICE_D_INTR_MSK_UDC_REG                  0x410\r
+#define   B_IOH_USBDEVICE_D_INTR_MSK_UDC_REG_MASK1_MASK       0xff\r
+#define R_IOH_USBDEVICE_EP_INTR_UDC_REG                     0x414\r
+#define R_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG                 0x418\r
+#define   B_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG_OUT_EP_MASK     0x000f0000\r
+#define   B_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG_IN_EP_MASK      0x0000000f\r
+\r
+//---------------------------------------------------------------------------\r
+// Quark South Cluster 10/100 Mbps Ethernet Device definitions.\r
+//---------------------------------------------------------------------------\r
+#define IOH_MAC0_BUS_NUMBER                                 IOH_BUS\r
+#define IOH_MAC0_DEVICE_NUMBER                              IOH_PCI_IOSF2AHB_0_DEV_NUM\r
+#define IOH_MAC0_FUNCTION_NUMBER                            0x06\r
+#define IOH_MAC1_BUS_NUMBER                                 IOH_BUS\r
+#define IOH_MAC1_DEVICE_NUMBER                              IOH_PCI_IOSF2AHB_0_DEV_NUM\r
+#define IOH_MAC1_FUNCTION_NUMBER                            0x07\r
+\r
+//\r
+// MAC Device PCI config registers.\r
+//\r
+#define R_IOH_MAC_DEVICE_ID                                 0x02\r
+#define   V_IOH_MAC_VENDOR_ID                                 INTEL_VENDOR_ID\r
+#define R_IOH_MAC_DEVICE_ID                                 0x02\r
+#define   V_IOH_MAC_DEVICE_ID                                 0x0937\r
+#define R_IOH_MAC_COMMAND                                   0x04\r
+#define   B_IOH_MAC_COMMAND_BME                               BIT2\r
+#define   B_IOH_MAC_COMMAND_MSE                               BIT1\r
+#define   B_IOH_MAC_COMMAND_ISE                               BIT0\r
+#define R_IOH_MAC_MEMBAR                                    0x10\r
+#define   B_IOH_MAC_MEMBAR_ADDRESS_MASK                       0xFFFFF000\r
+\r
+//\r
+// LAN Device memory mapped registers offset from memory BAR0.\r
+//\r
+#define R_IOH_MAC_GMAC_REG_8                                0x20\r
+#define   B_IOH_MAC_USERVER_MASK                              0x0000FF00\r
+#define   B_IOH_MAC_SNPSVER_MASK                              0x000000FF\r
+#define R_IOH_MAC_GMAC_REG_16                               0x40\r
+#define   B_IOH_MAC_ADDRHI_MASK                               0x0000FFFF\r
+#define   B_IOH_MAC_AE                                        BIT31\r
+#define R_IOH_MAC_GMAC_REG_17                               0x44\r
+#define   B_IOH_MAC_ADDRLO_MASK                               0xFFFFFFFF\r
+\r
+//---------------------------------------------------------------------------\r
+// Quark I2C / GPIO definitions\r
+//---------------------------------------------------------------------------\r
+\r
+#define   V_IOH_I2C_GPIO_VENDOR_ID          INTEL_VENDOR_ID\r
+#define   V_IOH_I2C_GPIO_DEVICE_ID          0x0934\r
+\r
+#define R_IOH_I2C_MEMBAR                  0x10\r
+#define   B_IOH_I2C_GPIO_MEMBAR_ADDR_MASK   0xFFFFF000  // [31:12].\r
+\r
+#define GPIO_SWPORTA_DR                   0x00\r
+#define GPIO_SWPORTA_DDR                  0x04\r
+#define GPIO_INTEN                        0x30\r
+#define GPIO_INTMASK                      0x34\r
+#define GPIO_INTTYPE_LEVEL                0x38\r
+#define GPIO_INT_POLARITY                 0x3C\r
+#define GPIO_INTSTATUS                    0x40\r
+#define GPIO_RAW_INTSTATUS                0x44\r
+#define GPIO_DEBOUNCE                     0x48\r
+#define GPIO_PORTA_EOI                    0x4C\r
+#define GPIO_EXT_PORTA                    0x50\r
+#define GPIO_EXT_PORTB                    0x54\r
+#define GPIO_LS_SYNC                      0x60\r
+#define GPIO_CONFIG_REG2                  0x70\r
+#define GPIO_CONFIG_REG1                  0x74\r
+\r
+//---------------------------------------------------------------------------\r
+// Quark South Cluster UART definitions.\r
+//---------------------------------------------------------------------------\r
+\r
+#define R_IOH_UART_MEMBAR                 0x10\r
+#define   B_IOH_UART_MEMBAR_ADDRESS_MASK    0xFFFFF000  // [31:12].\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Include/IohAccess.h b/QuarkSocPkg/QuarkSouthCluster/Include/IohAccess.h
new file mode 100644 (file)
index 0000000..7b462af
--- /dev/null
@@ -0,0 +1,24 @@
+/** @file\r
+Macros to simplify and abstract the interface to PCI configuration.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+\r
+#ifndef _IOH_ACCESS_H_\r
+#define _IOH_ACCESS_H_\r
+\r
+#include "Ioh.h"\r
+#include "IohCommonDefinitions.h"\r
+\r
+#endif\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Include/IohCommonDefinitions.h b/QuarkSocPkg/QuarkSouthCluster/Include/IohCommonDefinitions.h
new file mode 100644 (file)
index 0000000..8a359b4
--- /dev/null
@@ -0,0 +1,348 @@
+/** @file\r
+This header file provides common definitions just for MCH using to avoid including extra module's file.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _IOH_COMMON_DEFINITIONS_H_\r
+#define _IOH_COMMON_DEFINITIONS_H_\r
+\r
+//\r
+// PCI CONFIGURATION MAP REGISTER OFFSETS\r
+//\r
+#ifndef PCI_VID\r
+#define PCI_VID             0x0000        // Vendor ID Register\r
+#define PCI_DID             0x0002        // Device ID Register\r
+#define PCI_CMD             0x0004        // PCI Command Register\r
+#define PCI_STS             0x0006        // PCI Status Register\r
+#define PCI_RID             0x0008        // Revision ID Register\r
+#define PCI_IFT             0x0009        // Interface Type\r
+#define PCI_SCC             0x000A        // Sub Class Code Register\r
+#define PCI_BCC             0x000B        // Base Class Code Register\r
+#define PCI_CLS             0x000C        // Cache Line Size\r
+#define PCI_PMLT            0x000D        // Primary Master Latency Timer\r
+#define PCI_HDR             0x000E        // Header Type Register\r
+#define PCI_BIST            0x000F        // Built in Self Test Register\r
+#define PCI_BAR0            0x0010        // Base Address Register 0\r
+#define PCI_BAR1            0x0014        // Base Address Register 1\r
+#define PCI_BAR2            0x0018        // Base Address Register 2\r
+#define PCI_PBUS            0x0018        // Primary Bus Number Register\r
+#define PCI_SBUS            0x0019        // Secondary Bus Number Register\r
+#define PCI_SUBUS           0x001A        // Subordinate Bus Number Register\r
+#define PCI_SMLT            0x001B        // Secondary Master Latency Timer\r
+#define PCI_BAR3            0x001C        // Base Address Register 3\r
+#define PCI_IOBASE          0x001C        // I/O base Register\r
+#define PCI_IOLIMIT         0x001D        // I/O Limit Register\r
+#define PCI_SECSTATUS       0x001E        // Secondary Status Register\r
+#define PCI_BAR4            0x0020        // Base Address Register 4\r
+#define PCI_MEMBASE         0x0020        // Memory Base Register\r
+#define PCI_MEMLIMIT        0x0022        // Memory Limit Register\r
+#define PCI_BAR5            0x0024        // Base Address Register 5\r
+#define PCI_PRE_MEMBASE     0x0024        // Prefetchable memory Base register\r
+#define PCI_PRE_MEMLIMIT    0x0026        // Prefetchable memory Limit register\r
+#define PCI_PRE_MEMBASE_U   0x0028        // Prefetchable memory base upper 32 bits\r
+#define PCI_PRE_MEMLIMIT_U  0x002C        // Prefetchable memory limit upper 32 bits\r
+#define PCI_SVID            0x002C        // Subsystem Vendor ID\r
+#define PCI_SID             0x002E        // Subsystem ID\r
+#define PCI_IOBASE_U        0x0030        // I/O base Upper Register\r
+#define PCI_IOLIMIT_U       0x0032        // I/O Limit Upper Register\r
+#define PCI_CAPP            0x0034        // Capabilities Pointer\r
+#define PCI_EROM            0x0038        // Expansion ROM Base Address\r
+#define PCI_INTLINE         0x003C        // Interrupt Line Register\r
+#define PCI_INTPIN          0x003D        // Interrupt Pin Register\r
+#define PCI_MAXGNT          0x003E        // Max Grant Register\r
+#define PCI_BRIDGE_CNTL     0x003E        // Bridge Control Register\r
+#define PCI_MAXLAT          0x003F        // Max Latency Register\r
+#endif\r
+//\r
+// Bit Difinitions\r
+//\r
+#ifndef BIT0\r
+#define BIT0                     0x0001\r
+#define BIT1                     0x0002\r
+#define BIT2                     0x0004\r
+#define BIT3                     0x0008\r
+#define BIT4                     0x0010\r
+#define BIT5                     0x0020\r
+#define BIT6                     0x0040\r
+#define BIT7                     0x0080\r
+#define BIT8                     0x0100\r
+#define BIT9                     0x0200\r
+#define BIT10                    0x0400\r
+#define BIT11                    0x0800\r
+#define BIT12                    0x1000\r
+#define BIT13                    0x2000\r
+#define BIT14                    0x4000\r
+#define BIT15                    0x8000\r
+#define BIT16                0x00010000\r
+#define BIT17                0x00020000\r
+#define BIT18                0x00040000\r
+#define BIT19                0x00080000\r
+#define BIT20                0x00100000\r
+#define BIT21                0x00200000\r
+#define BIT22                0x00400000\r
+#define BIT23                0x00800000\r
+#define BIT24                0x01000000\r
+#define BIT25                0x02000000\r
+#define BIT26                0x04000000\r
+#define BIT27                0x08000000\r
+#define BIT28                0x10000000\r
+#define BIT29                0x20000000\r
+#define BIT30                0x40000000\r
+#define BIT31                0x80000000\r
+#endif\r
+\r
+\r
+//\r
+//  Common Memory mapped Io access macros ------------------------------------------\r
+//\r
+#define IohMmioAddress( BaseAddr, Register ) \\r
+    ( (UINTN)BaseAddr + \\r
+      (UINTN)(Register) \\r
+    )\r
+\r
+//\r
+// UINT64\r
+//\r
+#define IohMmio64Ptr( BaseAddr, Register ) \\r
+    ( (volatile UINT64 *)IohMmioAddress( BaseAddr, Register ) )\r
+\r
+#define IohMmio64( BaseAddr, Register ) \\r
+    *IohMmio64Ptr( BaseAddr, Register )\r
+\r
+#define IohMmio64Or( BaseAddr, Register, OrData ) \\r
+    IohMmio64( BaseAddr, Register ) = \\r
+      (UINT64) ( \\r
+        IohMmio64( BaseAddr, Register ) | \\r
+        (UINT64)(OrData) \\r
+      )\r
+\r
+#define IohMmio64And( BaseAddr, Register, AndData ) \\r
+    IohMmio64( BaseAddr, Register ) = \\r
+      (UINT64) ( \\r
+        IohMmio64( BaseAddr, Register ) & \\r
+        (UINT64)(AndData) \\r
+      )\r
+\r
+#define IohMmio64AndThenOr( BaseAddr, Register, AndData, OrData ) \\r
+    IohMmio64( BaseAddr, Register ) = \\r
+      (UINT64) ( \\r
+        ( IohMmio64( BaseAddr, Register ) & \\r
+            (UINT64)(AndData) \\r
+        ) | \\r
+        (UINT64)(OrData) \\r
+      )\r
+\r
+//\r
+// UINT32\r
+//\r
+#define IohMmio32Ptr( BaseAddr, Register ) \\r
+    ( (volatile UINT32 *)IohMmioAddress( BaseAddr, Register ) )\r
+\r
+#define IohMmio32( BaseAddr, Register ) \\r
+    *IohMmio32Ptr( BaseAddr, Register )\r
+\r
+#define IohMmio32Or( BaseAddr, Register, OrData ) \\r
+    IohMmio32( BaseAddr, Register ) = \\r
+      (UINT32) ( \\r
+        IohMmio32( BaseAddr, Register ) | \\r
+        (UINT32)(OrData) \\r
+      )\r
+\r
+#define IohMmio32And( BaseAddr, Register, AndData ) \\r
+    IohMmio32( BaseAddr, Register ) = \\r
+      (UINT32) ( \\r
+        IohMmio32( BaseAddr, Register ) & \\r
+        (UINT32)(AndData) \\r
+      )\r
+\r
+#define IohMmio32AndThenOr( BaseAddr, Register, AndData, OrData ) \\r
+    IohMmio32( BaseAddr, Register ) = \\r
+      (UINT32) ( \\r
+        ( IohMmio32( BaseAddr, Register ) & \\r
+            (UINT32)(AndData) \\r
+        ) | \\r
+        (UINT32)(OrData) \\r
+      )\r
+//\r
+// UINT16\r
+//\r
+\r
+#define IohMmio16Ptr( BaseAddr, Register ) \\r
+    ( (volatile UINT16 *)IohMmioAddress( BaseAddr, Register ) )\r
+\r
+#define IohMmio16( BaseAddr, Register ) \\r
+    *IohMmio16Ptr( BaseAddr, Register )\r
+\r
+#define IohMmio16Or( BaseAddr, Register, OrData ) \\r
+    IohMmio16( BaseAddr, Register ) = \\r
+      (UINT16) ( \\r
+        IohMmio16( BaseAddr, Register ) | \\r
+        (UINT16)(OrData) \\r
+      )\r
+\r
+#define IohMmio16And( BaseAddr, Register, AndData ) \\r
+    IohMmio16( BaseAddr, Register ) = \\r
+      (UINT16) ( \\r
+        IohMmio16( BaseAddr, Register ) & \\r
+        (UINT16)(AndData) \\r
+      )\r
+\r
+#define IohMmio16AndThenOr( BaseAddr, Register, AndData, OrData ) \\r
+    IohMmio16( BaseAddr, Register ) = \\r
+      (UINT16) ( \\r
+        ( IohMmio16( BaseAddr, Register ) & \\r
+            (UINT16)(AndData) \\r
+        ) | \\r
+        (UINT16)(OrData) \\r
+      )\r
+//\r
+// UINT8\r
+//\r
+#define IohMmio8Ptr( BaseAddr, Register ) \\r
+    ( (volatile UINT8 *)IohMmioAddress( BaseAddr, Register ) )\r
+\r
+#define IohMmio8( BaseAddr, Register ) \\r
+    *IohMmio8Ptr( BaseAddr, Register )\r
+\r
+#define IohMmio8Or( BaseAddr, Register, OrData ) \\r
+    IohMmio8( BaseAddr, Register ) = \\r
+      (UINT8) ( \\r
+        IohMmio8( BaseAddr, Register ) | \\r
+        (UINT8)(OrData) \\r
+      )\r
+\r
+#define IohMmio8And( BaseAddr, Register, AndData ) \\r
+    IohMmio8( BaseAddr, Register ) = \\r
+      (UINT8) ( \\r
+        IohMmio8( BaseAddr, Register ) & \\r
+        (UINT8)(AndData) \\r
+      )\r
+\r
+#define IohMmio8AndThenOr( BaseAddr, Register, AndData, OrData ) \\r
+    IohMmio8( BaseAddr, Register ) = \\r
+      (UINT8) ( \\r
+        ( IohMmio8( BaseAddr, Register ) & \\r
+            (UINT8)(AndData) \\r
+          ) | \\r
+        (UINT8)(OrData) \\r
+      )\r
+\r
+//\r
+//  Common Memory mapped Pci access macros ------------------------------------------\r
+//\r
+#define Ioh_PCI_EXPRESS_BASE_ADDRESS  0xE0000000\r
+\r
+\r
+#define IohMmPciAddress( Segment, Bus, Device, Function, Register ) \\r
+  ( (UINTN)Ioh_PCI_EXPRESS_BASE_ADDRESS + \\r
+    (UINTN)(Bus << 20) + \\r
+    (UINTN)(Device << 15) + \\r
+    (UINTN)(Function << 12) + \\r
+    (UINTN)(Register) \\r
+  )\r
+\r
+//\r
+// UINT32\r
+//\r
+#define IohMmPci32Ptr( Segment, Bus, Device, Function, Register ) \\r
+  ( (volatile UINT32 *)IohMmPciAddress( Segment, Bus, Device, Function, Register ) )\r
+\r
+#define IohMmPci32( Segment, Bus, Device, Function, Register ) \\r
+  *IohMmPci32Ptr( Segment, Bus, Device, Function, Register )\r
+\r
+#define IohMmPci32Or( Segment, Bus, Device, Function, Register, OrData ) \\r
+  IohMmPci32( Segment, Bus, Device, Function, Register ) = \\r
+    (UINT32) ( \\r
+      IohMmPci32( Segment, Bus, Device, Function, Register ) | \\r
+      (UINT32)(OrData) \\r
+    )\r
+\r
+#define IohMmPci32And( Segment, Bus, Device, Function, Register, AndData ) \\r
+  IohMmPci32( Segment, Bus, Device, Function, Register ) = \\r
+    (UINT32) ( \\r
+      IohMmPci32( Segment, Bus, Device, Function, Register ) & \\r
+      (UINT32)(AndData) \\r
+    )\r
+\r
+#define IohMmPci32AndThenOr( Segment, Bus, Device, Function, Register, AndData, OrData ) \\r
+  IohMmPci32( Segment, Bus, Device, Function, Register ) = \\r
+    (UINT32) ( \\r
+      ( IohMmPci32( Segment, Bus, Device, Function, Register ) & \\r
+          (UINT32)(AndData) \\r
+      ) | \\r
+      (UINT32)(OrData) \\r
+    )\r
+//\r
+// UINT16\r
+//\r
+#define IohMmPci16Ptr( Segment, Bus, Device, Function, Register ) \\r
+  ( (volatile UINT16 *)IohMmPciAddress( Segment, Bus, Device, Function, Register ) )\r
+\r
+#define IohMmPci16( Segment, Bus, Device, Function, Register ) \\r
+  *IohMmPci16Ptr( Segment, Bus, Device, Function, Register )\r
+\r
+#define IohMmPci16Or( Segment, Bus, Device, Function, Register, OrData ) \\r
+  IohMmPci16( Segment, Bus, Device, Function, Register ) = \\r
+    (UINT16) ( \\r
+      IohMmPci16( Segment, Bus, Device, Function, Register ) | \\r
+      (UINT16)(OrData) \\r
+    )\r
+\r
+#define IohMmPci16And( Segment, Bus, Device, Function, Register, AndData ) \\r
+  IohMmPci16( Segment, Bus, Device, Function, Register ) = \\r
+    (UINT16) ( \\r
+      IohMmPci16( Segment, Bus, Device, Function, Register ) & \\r
+      (UINT16)(AndData) \\r
+    )\r
+\r
+#define IohMmPci16AndThenOr( Segment, Bus, Device, Function, Register, AndData, OrData ) \\r
+  IohMmPci16( Segment, Bus, Device, Function, Register ) = \\r
+    (UINT16) ( \\r
+      ( IohMmPci16( Segment, Bus, Device, Function, Register ) & \\r
+          (UINT16)(AndData) \\r
+      ) | \\r
+      (UINT16)(OrData) \\r
+    )\r
+//\r
+// UINT8\r
+//\r
+#define IohMmPci8Ptr( Segment, Bus, Device, Function, Register ) \\r
+  ( (volatile UINT8 *)IohMmPciAddress( Segment, Bus, Device, Function, Register ) )\r
+\r
+#define IohMmPci8( Segment, Bus, Device, Function, Register ) \\r
+  *IohMmPci8Ptr( Segment, Bus, Device, Function, Register )\r
+\r
+#define IohMmPci8Or( Segment, Bus, Device, Function, Register, OrData ) \\r
+  IohMmPci8( Segment, Bus, Device, Function, Register ) = \\r
+    (UINT8) ( \\r
+      IohMmPci8( Segment, Bus, Device, Function, Register ) | \\r
+      (UINT8)(OrData) \\r
+    )\r
+\r
+#define IohMmPci8And( Segment, Bus, Device, Function, Register, AndData ) \\r
+  IohMmPci8( Segment, Bus, Device, Function, Register ) = \\r
+    (UINT8) ( \\r
+      IohMmPci8( Segment, Bus, Device, Function, Register ) & \\r
+      (UINT8)(AndData) \\r
+    )\r
+\r
+#define IohMmPci8AndThenOr( Segment, Bus, Device, Function, Register, AndData, OrData ) \\r
+  IohMmPci8( Segment, Bus, Device, Function, Register ) = \\r
+    (UINT8) ( \\r
+      ( IohMmPci8( Segment, Bus, Device, Function, Register ) & \\r
+          (UINT8)(AndData) \\r
+        ) | \\r
+      (UINT8)(OrData) \\r
+    )\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Include/Library/I2cLib.h b/QuarkSocPkg/QuarkSouthCluster/Include/Library/I2cLib.h
new file mode 100644 (file)
index 0000000..b494a3b
--- /dev/null
@@ -0,0 +1,158 @@
+/** @file\r
+\r
+Intel I2C library implementation built upon I/O library\r
+\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _I2C_LIB_H_\r
+#define _I2C_LIB_H_\r
+\r
+#include "I2cRegs.h"\r
+\r
+/**\r
+\r
+  The I2cWriteByte() function is a wrapper function for the WriteByte() function.\r
+  Provides a standard way to execute a standard single byte write to an IC2 device\r
+  (without accessing sub-addresses), as defined in the I2C Specification.\r
+\r
+  @param SlaveAddress The I2C slave address of the device\r
+                      with which to communicate.\r
+\r
+  @param AddrMode     I2C Addressing Mode: 7-bit or 10-bit address.\r
+\r
+  @param Buffer       Contains the value of byte data to execute to the\r
+                      I2C slave device.\r
+\r
+\r
+  @retval EFI_SUCCESS           Transfer success.\r
+  @retval EFI_INVALID_PARAMETER  This or Buffer pointers are invalid.\r
+  @retval EFI_TIMEOUT           Timeout while waiting xfer.\r
+  @retval EFI_ABORTED           Controller aborted xfer.\r
+  @retval EFI_DEVICE_ERROR      Device error detected by controller.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+I2cWriteByte (\r
+  IN        EFI_I2C_DEVICE_ADDRESS  SlaveAddress,\r
+  IN        EFI_I2C_ADDR_MODE       AddrMode,\r
+  IN OUT VOID                       *Buffer\r
+  );\r
+\r
+/**\r
+\r
+  The I2cReadByte() function is a wrapper function for the ReadByte() function.\r
+  Provides a standard way to execute a standard single byte read to an I2C device\r
+  (without accessing sub-addresses), as defined in the I2C Specification.\r
+\r
+  @param SlaveAddress The I2C slave address of the device\r
+                      with which to communicate.\r
+\r
+  @param AddrMode     I2C Addressing Mode: 7-bit or 10-bit address.\r
+\r
+  @param Buffer       Contains the value of byte data read from the\r
+                      I2C slave device.\r
+\r
+\r
+  @retval EFI_SUCCESS           Transfer success.\r
+  @retval EFI_INVALID_PARAMETER This or Buffer pointers are invalid.\r
+  @retval EFI_TIMEOUT           Timeout while waiting xfer.\r
+  @retval EFI_ABORTED           Controller aborted xfer.\r
+  @retval EFI_DEVICE_ERROR      Device error detected by controller.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+I2cReadByte (\r
+  IN        EFI_I2C_DEVICE_ADDRESS  SlaveAddress,\r
+  IN        EFI_I2C_ADDR_MODE       AddrMode,\r
+  IN OUT VOID                       *Buffer\r
+  );\r
+\r
+/**\r
+\r
+  The I2cWriteMultipleByte() function is a wrapper function for the WriteMultipleByte()\r
+  function. Provides a standard way to execute multiple byte writes to an I2C device (e.g. when\r
+  accessing sub-addresses or writing block of data), as defined in the I2C Specification.\r
+\r
+  @param SlaveAddress The I2C slave address of the device\r
+                      with which to communicate.\r
+\r
+  @param AddrMode     I2C Addressing Mode: 7-bit or 10-bit address.\r
+\r
+  @param Length       No. of bytes to be written.\r
+\r
+  @param Buffer       Contains the value of byte to be written to the\r
+                      I2C slave device.\r
+\r
+  @retval EFI_SUCCESS            Transfer success.\r
+  @retval EFI_INVALID_PARAMETER  This, Length or Buffer pointers are invalid.\r
+  @retval EFI_UNSUPPORTED        Unsupported input param.\r
+  @retval EFI_TIMEOUT            Timeout while waiting xfer.\r
+  @retval EFI_ABORTED            Controller aborted xfer.\r
+  @retval EFI_DEVICE_ERROR       Device error detected by controller.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+I2cWriteMultipleByte (\r
+  IN        EFI_I2C_DEVICE_ADDRESS  SlaveAddress,\r
+  IN        EFI_I2C_ADDR_MODE       AddrMode,\r
+  IN UINTN                          *Length,\r
+  IN OUT VOID                       *Buffer\r
+  );\r
+\r
+/**\r
+\r
+  The I2cReadMultipleByte() function is a wrapper function for the ReadMultipleByte\r
+  function. Provides a standard way to execute multiple byte writes to an IC2 device\r
+  (e.g. when accessing sub-addresses or when reading block of data), as defined\r
+  in the I2C Specification (I2C combined write/read protocol).\r
+\r
+  @param SlaveAddress The I2C slave address of the device\r
+                      with which to communicate.\r
+\r
+  @param AddrMode     I2C Addressing Mode: 7-bit or 10-bit address.\r
+\r
+  @param WriteLength  No. of bytes to be written. In this case data\r
+                      written typically contains sub-address or sub-addresses\r
+                      in Hi-Lo format, that need to be read (I2C combined\r
+                      write/read protocol).\r
+\r
+  @param ReadLength   No. of bytes to be read from I2C slave device.\r
+                      need to be read.\r
+\r
+  @param Buffer       Contains the value of byte data read from the\r
+                      I2C slave device.\r
+\r
+  @retval EFI_SUCCESS            Transfer success.\r
+  @retval EFI_INVALID_PARAMETER  This, WriteLength, ReadLength or Buffer\r
+                                 pointers are invalid.\r
+  @retval EFI_UNSUPPORTED        Unsupported input param.\r
+  @retval EFI_TIMEOUT            Timeout while waiting xfer.\r
+  @retval EFI_ABORTED            Controller aborted xfer.\r
+  @retval EFI_DEVICE_ERROR       Device error detected by controller.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+I2cReadMultipleByte (\r
+  IN        EFI_I2C_DEVICE_ADDRESS  SlaveAddress,\r
+  IN        EFI_I2C_ADDR_MODE       AddrMode,\r
+  IN UINTN                          *WriteLength,\r
+  IN UINTN                          *ReadLength,\r
+  IN OUT VOID                       *Buffer\r
+  );\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Include/Library/IohLib.h b/QuarkSocPkg/QuarkSouthCluster/Include/Library/IohLib.h
new file mode 100644 (file)
index 0000000..87aced6
--- /dev/null
@@ -0,0 +1,42 @@
+/** @file\r
+Library that provides Soc specific library services for SouthCluster devices.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __IOH_LIB_H__\r
+#define __IOH_LIB_H__\r
+\r
+#include "Ioh.h"\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeIohSsvidSsid (\r
+   IN UINT8   Bus,\r
+   IN UINT8   Device,\r
+   IN UINT8   Func\r
+   );\r
+\r
+VOID\r
+EFIAPI\r
+EnableUsbMemIoBusMaster (\r
+   IN UINT8   UsbBusNumber\r
+  );\r
+\r
+UINT32\r
+EFIAPI\r
+ReadIohGpioValues (\r
+  VOID\r
+  );\r
+\r
+#endif\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Include/MMC.h b/QuarkSocPkg/QuarkSouthCluster/Include/MMC.h
new file mode 100644 (file)
index 0000000..ac34930
--- /dev/null
@@ -0,0 +1,280 @@
+/** @file\r
+\r
+Header file for Industry MMC 4.2 spec.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _MMC_H\r
+#define _MMC_H\r
+\r
+#pragma pack(1)\r
+//\r
+//Command definition\r
+//\r
+\r
+#define  CMD0              0\r
+#define  CMD1              1\r
+#define  CMD2              2\r
+#define  CMD3              3\r
+#define  CMD4              4\r
+#define  CMD6              6\r
+#define  CMD7              7\r
+#define  CMD8              8\r
+#define  CMD9              9\r
+#define  CMD10             10\r
+#define  CMD11             11\r
+#define  CMD12             12\r
+#define  CMD13             13\r
+#define  CMD14             14\r
+#define  CMD15             15\r
+#define  CMD16             16\r
+#define  CMD17             17\r
+#define  CMD18             18\r
+#define  CMD19             19\r
+#define  CMD20             20\r
+#define  CMD23             23\r
+#define  CMD24             24\r
+#define  CMD25             25\r
+#define  CMD26             26\r
+#define  CMD27             27\r
+#define  CMD28             28\r
+#define  CMD29             29\r
+#define  CMD30             30\r
+#define  CMD35             35\r
+#define  CMD36             36\r
+#define  CMD38             38\r
+#define  CMD39             39\r
+#define  CMD40             40\r
+#define  CMD42             42\r
+#define  CMD55             55\r
+#define  CMD56             56\r
+\r
+\r
+\r
+#define  GO_IDLE_STATE           CMD0\r
+#define  SEND_OP_COND            CMD1\r
+#define  ALL_SEND_CID            CMD2\r
+#define  SET_RELATIVE_ADDR       CMD3\r
+#define  SET_DSR                 CMD4\r
+#define  SWITCH                  CMD6\r
+#define  SELECT_DESELECT_CARD    CMD7\r
+#define  SEND_EXT_CSD            CMD8\r
+#define  SEND_CSD                CMD9\r
+#define  SEND_CID                CMD10\r
+#define  READ_DAT_UNTIL_STOP     CMD11\r
+#define  STOP_TRANSMISSION       CMD12\r
+#define  SEND_STATUS             CMD13\r
+#define  BUSTEST_R               CMD14\r
+#define  GO_INACTIVE_STATE       CMD15\r
+#define  SET_BLOCKLEN            CMD16\r
+#define  READ_SINGLE_BLOCK       CMD17\r
+#define  READ_MULTIPLE_BLOCK     CMD18\r
+#define  BUSTEST_W               CMD19\r
+#define  WRITE_DAT_UNTIL_STOP    CMD20\r
+#define  SET_BLOCK_COUNT         CMD23\r
+#define  WRITE_BLOCK             CMD24\r
+#define  WRITE_MULTIPLE_BLOCK    CMD25\r
+#define  PROGRAM_CID             CMD26\r
+#define  PROGRAM_CSD             CMD27\r
+#define  SET_WRITE_PROT          CMD28\r
+#define  CLR_WRITE_PROT          CMD29\r
+#define  SEND_WRITE_PROT         CMD30\r
+#define  ERASE_GROUP_START       CMD35\r
+#define  ERASE_GROUP_END         CMD36\r
+#define  ERASE                   CMD38\r
+#define  FAST_IO                 CMD39\r
+#define  GO_IRQ_STATE            CMD40\r
+#define  LOCK_UNLOCK             CMD42\r
+#define  APP_CMD                 CMD55\r
+#define  GEN_CMD                 CMD56\r
+\r
+\r
+#define CMD_INDEX_MASK           0x3F\r
+#define AUTO_CMD12_ENABLE        BIT6\r
+#define AUTO_CMD23_ENABLE        BIT7\r
+\r
+#define FREQUENCY_OD            (400 * 1000)\r
+#define FREQUENCY_MMC_PP        (26 * 1000 * 1000)\r
+#define FREQUENCY_MMC_PP_HIGH   (52 * 1000 * 1000)\r
+\r
+#define DEFAULT_DSR_VALUE        0x404\r
+\r
+//\r
+//Registers definition\r
+//\r
+\r
+typedef struct {\r
+  UINT32  Reserved0:   7;  // 0\r
+  UINT32  V170_V195:   1;  // 1.70V - 1.95V\r
+  UINT32  V200_V260:   7;  // 2.00V - 2.60V\r
+  UINT32  V270_V360:   9;  // 2.70V - 3.60V\r
+  UINT32  Reserved1:   5;  // 0\r
+  UINT32  AccessMode:  2;  // 00b (byte mode), 10b (sector mode)\r
+  UINT32  Busy:        1;  // This bit is set to LOW if the card has not finished the power up routine\r
+}OCR;\r
+\r
+\r
+typedef struct {\r
+  UINT8   NotUsed:     1; //  1\r
+  UINT8   CRC:         7; //  CRC7 checksum\r
+  UINT8   MDT;            //  Manufacturing date\r
+  UINT32  PSN;            //  Product serial number\r
+  UINT8   PRV;            //  Product revision\r
+  UINT8   PNM[6];         //  Product name\r
+  UINT16  OID;            //  OEM/Application ID\r
+  UINT8   MID;            //  Manufacturer ID\r
+}CID;\r
+\r
+\r
+typedef struct {\r
+  UINT8   NotUsed:            1; //  1 [0:0]\r
+  UINT8   CRC:                7; //  CRC [7:1]\r
+  UINT8   ECC:                2; //  ECC code [9:8]\r
+  UINT8   FILE_FORMAT:        2; //  File format [11:10]\r
+  UINT8   TMP_WRITE_PROTECT:  1; //  Temporary write protection [12:12]\r
+  UINT8   PERM_WRITE_PROTECT: 1; //  Permanent write protection [13:13]\r
+  UINT8   COPY:               1; //  Copy flag (OTP) [14:14]\r
+  UINT8   FILE_FORMAT_GRP:    1; //  File format group [15:15]\r
+  UINT16  CONTENT_PROT_APP:   1; //  Content protection application [16:16]\r
+  UINT16  Reserved0:          4; //  0 [20:17]\r
+  UINT16  WRITE_BL_PARTIAL:   1; //  Partial blocks for write allowed [21:21]\r
+  UINT16  WRITE_BL_LEN:       4; //  Max. write data block length [25:22]\r
+  UINT16  R2W_FACTOR:         3; //  Write speed factor [28:26]\r
+  UINT16  DEFAULT_ECC:        2; //  Manufacturer default ECC [30:29]\r
+  UINT16  WP_GRP_ENABLE:      1; //  Write protect group enable [31:31]\r
+  UINT32  WP_GRP_SIZE:        5; //  Write protect group size [36:32]\r
+  UINT32  ERASE_GRP_MULT:     5; //  Erase group size multiplier [41:37]\r
+  UINT32  ERASE_GRP_SIZE:     5; //  Erase group size [46:42]\r
+  UINT32  C_SIZE_MULT:        3; //  Device size multiplier [49:47]\r
+  UINT32  VDD_W_CURR_MAX:     3; //  Max. write current @ VDD max [52:50]\r
+  UINT32  VDD_W_CURR_MIN:     3; //  Max. write current @ VDD min [55:53]\r
+  UINT32  VDD_R_CURR_MAX:     3; //  Max. read current @ VDD max [58:56]\r
+  UINT32  VDD_R_CURR_MIN:     3; //  Max. read current @ VDD min [61:59]\r
+  UINT32  C_SIZELow2:         2;//  Device size [73:62]\r
+  UINT32  C_SIZEHigh10:       10;//  Device size [73:62]\r
+  UINT32  Reserved1:          2; //  0 [75:74]\r
+  UINT32  DSR_IMP:            1; //  DSR implemented [76:76]\r
+  UINT32  READ_BLK_MISALIGN:  1; //  Read block misalignment [77:77]\r
+  UINT32  WRITE_BLK_MISALIGN: 1; //  Write block misalignment [78:78]\r
+  UINT32  READ_BL_PARTIAL:    1; //  Partial blocks for read allowed [79:79]\r
+  UINT32  READ_BL_LEN:        4; //  Max. read data block length [83:80]\r
+  UINT32  CCC:                12;//  Card command classes [95:84]\r
+  UINT8   TRAN_SPEED          ; //  Max. bus clock frequency [103:96]\r
+  UINT8   NSAC                ; //  Data read access-time 2 in CLK cycles (NSAC*100) [111:104]\r
+  UINT8   TAAC                ; //  Data read access-time 1 [119:112]\r
+  UINT8   Reserved2:          2; //  0 [121:120]\r
+  UINT8   SPEC_VERS:          4; //  System specification version [125:122]\r
+  UINT8   CSD_STRUCTURE:      2; //  CSD structure [127:126]\r
+}CSD;\r
+\r
+typedef struct {\r
+  UINT8  Reserved0[181];         //  0 [0:180]\r
+  UINT8  ERASED_MEM_CONT;        //  Erased Memory Content [181]\r
+  UINT8  Reserved2;              //  Erased Memory Content [182]\r
+  UINT8  BUS_WIDTH;              //  Bus Width Mode [183]\r
+  UINT8  Reserved3;              //  0 [184]\r
+  UINT8  HS_TIMING;              //  High Speed Interface Timing [185]\r
+  UINT8  Reserved4;              //  0 [186]\r
+  UINT8  POWER_CLASS;            //  Power Class [187]\r
+  UINT8  Reserved5;              //  0 [188]\r
+  UINT8  CMD_SET_REV;            //  Command Set Revision [189]\r
+  UINT8  Reserved6;              //  0 [190]\r
+  UINT8  CMD_SET;                //  Command Set [191]\r
+  UINT8  EXT_CSD_REV;            //  Extended CSD Revision [192]\r
+  UINT8  Reserved7;              //  0 [193]\r
+  UINT8  CSD_STRUCTURE;          //  CSD Structure Version [194]\r
+  UINT8  Reserved8;              //  0 [195]\r
+  UINT8  CARD_TYPE;              //  Card Type [196]\r
+  UINT8  Reserved9[3];           //  0 [199:197]\r
+  UINT8  PWR_CL_52_195;          //  Power Class for 52MHz @ 1.95V [200]\r
+  UINT8  PWR_CL_26_195;          //  Power Class for 26MHz @ 1.95V [201]\r
+  UINT8  PWR_CL_52_360;          //  Power Class for 52MHz @ 3.6V [202]\r
+  UINT8  PWR_CL_26_360;          //  Power Class for 26MHz @ 3.6V [203]\r
+  UINT8  Reserved10;             //  0 [204]\r
+  UINT8  MIN_PERF_R_4_26;        //  Minimum Read Performance for 4bit @26MHz [205]\r
+  UINT8  MIN_PERF_W_4_26;        //  Minimum Write Performance for 4bit @26MHz [206]\r
+  UINT8  MIN_PERF_R_8_26_4_52;   //  Minimum Read Performance for 8bit @26MHz/4bit @52MHz [207]\r
+  UINT8  MIN_PERF_W_8_26_4_52;   //  Minimum Write Performance for 8bit @26MHz/4bit @52MHz [208]\r
+  UINT8  MIN_PERF_R_8_52;        //  Minimum Read Performance for 8bit @52MHz [209]\r
+  UINT8  MIN_PERF_W_8_52;        //  Minimum Write Performance for 8bit @52MHz [210]\r
+  UINT8  Reserved11;             //  0 [211]\r
+  UINT8  SEC_COUNT[4];           //  Sector Count [215:212]\r
+  UINT8  Reserved12[288];        //  0 [503:216]\r
+  UINT8  S_CMD_SET;              //  Sector Count [504]\r
+  UINT8  Reserved13[7];          //  Sector Count [511:505]\r
+}EXT_CSD;\r
+\r
+\r
+//\r
+//Card Status definition\r
+//\r
+typedef struct {\r
+  UINT32  Reserved0:           2; //Reserved for Manufacturer Test Mode\r
+  UINT32  Reserved1:           2; //Reserved for Application Specific commands\r
+  UINT32  Reserved2:           1; //\r
+  UINT32  SAPP_CMD:            1; //\r
+  UINT32  Reserved3:           1; //Reserved\r
+  UINT32  SWITCH_ERROR:        1; //\r
+  UINT32  READY_FOR_DATA:      1; //\r
+  UINT32  CURRENT_STATE:       4; //\r
+  UINT32  ERASE_RESET:         1; //\r
+  UINT32  Reserved4:           1; //Reserved\r
+  UINT32  WP_ERASE_SKIP:       1; //\r
+  UINT32  CID_CSD_OVERWRITE:   1; //\r
+  UINT32  OVERRUN:             1; //\r
+  UINT32  UNDERRUN:            1; //\r
+  UINT32  ERROR:               1; //\r
+  UINT32  CC_ERROR:            1; //\r
+  UINT32  CARD_ECC_FAILED:     1; //\r
+  UINT32  ILLEGAL_COMMAND:     1; //\r
+  UINT32  COM_CRC_ERROR:       1; //\r
+  UINT32  LOCK_UNLOCK_FAILED:  1; //\r
+  UINT32  CARD_IS_LOCKED:      1; //\r
+  UINT32  WP_VIOLATION:        1; //\r
+  UINT32  ERASE_PARAM:         1; //\r
+  UINT32  ERASE_SEQ_ERROR:     1; //\r
+  UINT32  BLOCK_LEN_ERROR:     1; //\r
+  UINT32  ADDRESS_MISALIGN:    1; //\r
+  UINT32  ADDRESS_OUT_OF_RANGE:1; //\r
+}CARD_STATUS;\r
+\r
+typedef struct {\r
+  UINT32  CmdSet:              3;\r
+  UINT32  Reserved0:           5;\r
+  UINT32  Value:               8;\r
+  UINT32  Index:               8;\r
+  UINT32  Access:              2;\r
+  UINT32  Reserved1:           6;\r
+}SWITCH_ARGUMENT;\r
+\r
+#define CommandSet_Mode          0\r
+#define SetBits_Mode             1\r
+#define ClearBits_Mode           2\r
+#define WriteByte_Mode           3\r
+\r
+\r
+#define  Idle_STATE              0\r
+#define  Ready_STATE             1\r
+#define  Ident_STATE             2\r
+#define  Stby_STATE              3\r
+#define  Tran_STATE              4\r
+#define  Data_STATE              5\r
+#define  Rcv_STATE               6\r
+#define  Prg_STATE               7\r
+#define  Dis_STATE               8\r
+#define  Btst_STATE              9\r
+\r
+\r
+\r
+#pragma pack()\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Include/SDCard.h b/QuarkSocPkg/QuarkSouthCluster/Include/SDCard.h
new file mode 100644 (file)
index 0000000..8d9fdb5
--- /dev/null
@@ -0,0 +1,152 @@
+/** @file\r
+\r
+Header file for Industry SD Card 2.0 spec.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _SD_CARD_H\r
+#define _SD_CARD_H\r
+\r
+#include "MMC.h"\r
+\r
+#pragma pack(1)\r
+\r
+#define CHECK_PATTERN     0xAA  ///< Physical Layer Simplified Specification Version 3.01 recommended 0xAA\r
+\r
+#define ACMD6             6\r
+#define ACMD13            13\r
+#define ACMD23            23\r
+#define ACMD41            41\r
+#define ACMD42            42\r
+#define ACMD51            51\r
+\r
+\r
+#define SWITCH_FUNC              CMD6\r
+#define SEND_IF_COND             CMD8\r
+\r
+\r
+#define SET_BUS_WIDTH            ACMD6\r
+#define SD_STATUS                ACMD13\r
+#define SET_WR_BLK_ERASE_COUNT   ACMD23\r
+#define SD_SEND_OP_COND          ACMD41\r
+#define SET_CLR_CARD_DETECT      ACMD42\r
+#define SEND_SCR                 ACMD51\r
+\r
+\r
+\r
+#define SD_BUS_WIDTH_1              0\r
+#define SD_BUS_WIDTH_4              2\r
+\r
+\r
+\r
+#define FREQUENCY_SD_PP        (25 * 1000 * 1000)\r
+#define FREQUENCY_SD_PP_HIGH   (50 * 1000 * 1000)\r
+\r
+\r
+#define SD_SPEC_10                  0\r
+#define SD_SPEC_11                  1\r
+#define SD_SPEC_20                  2\r
+\r
+\r
+#define VOLTAGE_27_36               0x1\r
+\r
+typedef struct {\r
+  UINT8   NotUsed:            1; //  1 [0:0]\r
+  UINT8   CRC:                7; //  CRC [7:1]\r
+  UINT8   ECC:                2; //  ECC code [9:8]\r
+  UINT8   FILE_FORMAT:        2; //  File format [11:10]\r
+  UINT8   TMP_WRITE_PROTECT:  1; //  Temporary write protection [12:12]\r
+  UINT8   PERM_WRITE_PROTECT: 1; //  Permanent write protection [13:13]\r
+  UINT8   COPY:               1; //  Copy flag (OTP) [14:14]\r
+  UINT8   FILE_FORMAT_GRP:    1; //  File format group [15:15]\r
+  UINT16  Reserved0:          5; //  0 [20:16]\r
+  UINT16  WRITE_BL_PARTIAL:   1; //  Partial blocks for write allowed [21:21]\r
+  UINT16  WRITE_BL_LEN:       4; //  Max. write data block length [25:22]\r
+  UINT16  R2W_FACTOR:         3; //  Write speed factor [28:26]\r
+  UINT16  DEFAULT_ECC:        2; //  Manufacturer default ECC [30:29]\r
+  UINT16  WP_GRP_ENABLE:      1; //  Write protect group enable [31:31]\r
+  UINT16  WP_GRP_SIZE:        7; //  Write protect group size [38:32]\r
+  UINT16  SECTOR_SIZE:        7; //  Erase sector size [45:39]\r
+  UINT16  ERASE_BLK_EN:       1; //  Erase single block enable [46:46]\r
+  UINT16  Reserved1:          1; //  0 [47:47]\r
+\r
+  UINT32  C_SIZE:             22; //  Device size [69:48]\r
+  UINT32  Reserved2:          6;  //  0 [75:70]\r
+  UINT32  DSR_IMP:            1;  //  DSR implemented [76:76]\r
+  UINT32  READ_BLK_MISALIGN:  1;  //  Read block misalignment [77:77]\r
+  UINT32  WRITE_BLK_MISALIGN: 1;  //  Write block misalignment [78:78]\r
+  UINT32  READ_BL_PARTIAL:    1;  //  Partial blocks for read allowed [79:79]\r
+\r
+  UINT16  READ_BL_LEN:        4;  //  Max. read data block length [83:80]\r
+  UINT16  CCC:                12; //  Card command classes [95:84]\r
+  UINT8   TRAN_SPEED          ;   //  Max. bus clock frequency [103:96]\r
+  UINT8   NSAC                ;   //  Data read access-time 2 in CLK cycles (NSAC*100) [111:104]\r
+  UINT8   TAAC                ;   //  Data read access-time 1 [119:112]\r
+  UINT8   Reserved3:          6;  //  0 [125:120]\r
+  UINT8   CSD_STRUCTURE:      2;  //  CSD structure [127:126]\r
+}CSD_SDV2;\r
+\r
+typedef struct {\r
+  UINT32  Reserved0;\r
+  UINT32  Reserved1:               16;\r
+  UINT32  SD_BUS_WIDTH:            4;\r
+  UINT32  SD_SECURITY:             3;\r
+  UINT32  DATA_STAT_AFTER_ERASE:   1;\r
+  UINT32  SD_SPEC:                 4;\r
+  UINT32  SCR_STRUCT:              4;\r
+}SCR;\r
+\r
+\r
+typedef struct {\r
+  UINT8   Reserved0[50];\r
+  UINT8   ERASE_OFFSET:               2;\r
+  UINT8   ERASE_TIMEOUT:              6;\r
+  UINT16  ERASE_SIZE;\r
+  UINT8   Reserved1:                  4;\r
+  UINT8   AU_SIZE:                    4;\r
+  UINT8   PERFORMANCE_MOVE;\r
+  UINT8   SPEED_CLASS;\r
+  UINT32  SIZE_OF_PROTECTED_AREA;\r
+  UINT32  SD_CARD_TYPE:              16;\r
+  UINT32  Reserved2:                 13;\r
+  UINT32  SECURED_MODE:               1;\r
+  UINT32  DAT_BUS_WIDTH:              2;\r
+}SD_STATUS_REG;\r
+\r
+\r
+\r
+typedef struct {\r
+  UINT8   Reserved0[34];\r
+  UINT16  Group1BusyStatus;\r
+  UINT16  Group2BusyStatus;\r
+  UINT16  Group3BusyStatus;\r
+  UINT16  Group4BusyStatus;\r
+  UINT16  Group5BusyStatus;\r
+  UINT16  Group6BusyStatus;\r
+  UINT8   DataStructureVersion;\r
+  UINT8   Group21Status;\r
+  UINT8   Group43Status;\r
+  UINT8   Group65Status;\r
+  UINT16  Group1Function;\r
+  UINT16  Group2Function;\r
+  UINT16  Group3Function;\r
+  UINT16  Group4Function;\r
+  UINT16  Group5Function;\r
+  UINT16  Group6Function;\r
+  UINT16  MaxCurrent;\r
+}SWITCH_STATUS;\r
+\r
+\r
+#pragma pack()\r
+#endif\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Include/SDHostIo.h b/QuarkSocPkg/QuarkSouthCluster/Include/SDHostIo.h
new file mode 100644 (file)
index 0000000..42ff841
--- /dev/null
@@ -0,0 +1,339 @@
+/** @file\r
+\r
+Interface definition for EFI_SD_HOST_IO_PROTOCOL.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _SD_HOST_IO_H\r
+#define _SD_HOST_IO_H\r
+\r
+#include "SDCard.h"\r
+#include "CEATA.h"\r
+\r
+\r
+#define EFI_SD_HOST_IO_PROTOCOL_GUID  \\r
+  { \\r
+    0xb63f8ec7, 0xa9c9, 0x4472, {0xa4, 0xc0, 0x4d, 0x8b, 0xf3, 0x65, 0xcc, 0x51} \\r
+  }\r
+\r
+///\r
+/// Forward reference for pure ANSI compatability\r
+///\r
+typedef struct _EFI_SD_HOST_IO_PROTOCOL EFI_SD_HOST_IO_PROTOCOL;\r
+\r
+\r
+\r
+typedef enum {\r
+  ResponseNo = 0,\r
+  ResponseR1,\r
+  ResponseR1b,\r
+  ResponseR2,\r
+  ResponseR3,\r
+  ResponseR4,\r
+  ResponseR5,\r
+  ResponseR5b,\r
+  ResponseR6,\r
+  ResponseR7\r
+}RESPONSE_TYPE;\r
+\r
+typedef enum {\r
+  NoData = 0,\r
+  InData,\r
+  OutData\r
+}TRANSFER_TYPE;\r
+\r
+typedef enum {\r
+  Reset_Auto = 0,\r
+  Reset_DAT,\r
+  Reset_CMD,\r
+  Reset_DAT_CMD,\r
+  Reset_All\r
+}RESET_TYPE;\r
+\r
+#define PCI_SUBCLASS_SD_HOST_CONTROLLER           0x05\r
+#define PCI_IF_STANDARD_HOST_NO_DMA               0x00\r
+#define PCI_IF_STANDARD_HOST_SUPPORT_DMA          0x01\r
+\r
+#define   SDHCI_SPEC_100                          0\r
+#define   SDHCI_SPEC_200                          1\r
+#define   SDHCI_SPEC_300                          2\r
+\r
+//\r
+//MMIO Registers definition for MMC/SDIO controller\r
+//\r
+#define  MMIO_DMAADR                              0x00\r
+#define  MMIO_BLKSZ                               0x04\r
+#define  MMIO_BLKCNT                              0x06\r
+#define  MMIO_CMDARG                              0x08\r
+#define  MMIO_XFRMODE                             0x0C\r
+#define  MMIO_SDCMD                               0x0E\r
+#define  MMIO_RESP                                0x10\r
+#define  MMIO_BUFDATA                             0x20\r
+#define  MMIO_PSTATE                              0x24\r
+#define  MMIO_HOSTCTL                             0x28\r
+#define  MMIO_PWRCTL                              0x29\r
+#define  MMIO_BLKGAPCTL                           0x2A\r
+#define  MMIO_WAKECTL                             0x2B\r
+#define  MMIO_CLKCTL                              0x2C\r
+#define   V_MMIO_CLKCTL_MAX_8BIT_FREQ_SEL           0x80\r
+#define   V_MMIO_CLKCTL_MAX_10BIT_FREQ_SEL          0x3FF\r
+#define   B_MMIO_CLKCTL_UPR_SDCLK_FREQ_SEL_MASK     0xC0\r
+\r
+#define  MMIO_TOCTL                               0x2E\r
+#define  MMIO_SWRST                               0x2F\r
+#define  MMIO_NINTSTS                             0x30\r
+#define  MMIO_ERINTSTS                            0x32\r
+#define  MMIO_NINTEN                              0x34\r
+#define  MMIO_ERINTEN                             0x36\r
+#define  MMIO_NINTSIGEN                           0x38\r
+#define  MMIO_ERINTSIGEN                          0x3A\r
+#define  MMIO_AC12ERRSTS                          0x3C\r
+#define  MMIO_HOSTCTL2                            0x3E\r
+#define  MMIO_CAP                                 0x40\r
+#define  MMIO_MCCAP                               0x48\r
+#define  MMIO_SLTINTSTS                           0xFC\r
+#define  MMIO_CTRLRVER                            0xFE\r
+#define  MMIO_SRST                                0x1FC\r
+\r
+//\r
+// Protocol definitions\r
+//\r
+\r
+/**\r
+  The main function used to send the command to the card inserted into the SD host slot.\r
+  It will assemble the arguments to set the command register and wait for the command\r
+  and transfer completed until timeout. Then it will read the response register to fill\r
+  the ResponseData.\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  CommandIndex          The command index to set the command index field of command register.\r
+  @param  Argument              Command argument to set the argument field of command register.\r
+  @param  DataType              TRANSFER_TYPE, indicates no data, data in or data out.\r
+  @param  Buffer                Contains the data read from / write to the device.\r
+  @param  BufferSize            The size of the buffer.\r
+  @param  ResponseType          RESPONSE_TYPE.\r
+  @param  TimeOut               Time out value in 1 ms unit.\r
+  @param  ResponseData          Depending on the ResponseType, such as CSD or card status.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_INVALID_PARAMETER\r
+  @retval EFI_OUT_OF_RESOURCES\r
+  @retval EFI_TIMEOUT\r
+  @retval EFI_DEVICE_ERROR\r
+\r
+**/\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_SEND_COMMAND) (\r
+  IN   EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN   UINT16                     CommandIndex,\r
+  IN   UINT32                     Argument,\r
+  IN   TRANSFER_TYPE              DataType,\r
+  IN   UINT8                      *Buffer, OPTIONAL\r
+  IN   UINT32                     BufferSize,\r
+  IN   RESPONSE_TYPE              ResponseType,\r
+  IN   UINT32                     TimeOut,\r
+  OUT  UINT32                     *ResponseData OPTIONAL\r
+  );\r
+\r
+/**\r
+  Set max clock frequency of the host, the actual frequency may not be the same as MaxFrequency.\r
+  It depends on the max frequency the host can support, divider, and host speed mode.\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  MaxFrequency          Max frequency in HZ.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_TIMEOUT\r
+\r
+**/\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_SET_CLOCK_FREQUENCY) (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  UINT32                     MaxFrequency\r
+  );\r
+\r
+\r
+/**\r
+  Set bus width of the host controller\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  BusWidth              Bus width in 1, 4, 8 bits.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_INVALID_PARAMETER\r
+\r
+**/\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_SET_BUS_WIDTH) (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  UINT32                     BusWidth\r
+  );\r
+\r
+/**\r
+  Set voltage which could supported by the host controller.\r
+  Support 0(Power off the host), 1.8V, 3.0V, 3.3V\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  Voltage               Units in 0.1 V.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_INVALID_PARAMETER\r
+\r
+**/\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_SET_HOST_VOLTAGE) (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  UINT32                     Voltage\r
+  );\r
+\r
+/**\r
+  Reset the host controller.\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  ResetAll              TRUE to reset all.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_TIMEOUT\r
+\r
+**/\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_RESET_SD_HOST) (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  RESET_TYPE                 ResetType\r
+  );\r
+\r
+/**\r
+  Enable auto stop on the host controller.\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  Enable                TRUE to enable, FALSE to disable.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_TIMEOUT\r
+\r
+**/\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_ENABLE_AUTO_STOP_CMD) (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  BOOLEAN                    Enable\r
+  );\r
+\r
+/**\r
+  Find whether these is a card inserted into the slot. If so init the host.\r
+  If not, return EFI_NOT_FOUND.\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_NOT_FOUND\r
+\r
+**/\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_DETECT_CARD_AND_INIT_HOST) (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This\r
+  );\r
+\r
+/**\r
+  Set the Block length on the host controller.\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  BlockLength           card supportes block length.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_TIMEOUT\r
+\r
+**/\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_SET_BLOCK_LENGTH) (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  UINT32                     BlockLength\r
+  );\r
+\r
+/**\r
+  Enable/Disable High Speed transfer mode\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  Enable                TRUE to Enable, FALSE to Disable\r
+\r
+  @return EFI_SUCCESS\r
+**/\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_HIGH_SPEED_MODE) (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  BOOLEAN                    Enable\r
+  );\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_DUAL_DATARATE_MODE) (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  BOOLEAN                    Enable\r
+  );\r
+\r
+\r
+\r
+#define EFI_SD_HOST_IO_PROTOCOL_REVISION_01          0x02\r
+\r
+\r
+typedef struct {\r
+  UINT32  HighSpeedSupport:    1;  //High speed supported\r
+  UINT32  V18Support:          1;  //1.8V supported\r
+  UINT32  V30Support:          1;  //3.0V supported\r
+  UINT32  V33Support:          1;  //3.3V supported\r
+  UINT32  Reserved0:           4;\r
+  UINT32  HostVersion:         8;\r
+  UINT32  BusWidth4:           1;  // 4 bit width\r
+  UINT32  BusWidth8:           1;  // 8 bit width\r
+  UINT32  Reserved1:           14;\r
+  UINT32  BoundarySize;\r
+}HOST_CAPABILITY;\r
+\r
+\r
+//\r
+// Interface structure for the SD HOST I/O Protocol\r
+//\r
+struct _EFI_SD_HOST_IO_PROTOCOL {\r
+  UINT32                                             Revision;\r
+  HOST_CAPABILITY                                    HostCapability;\r
+  EFI_SD_HOST_IO_PROTOCOL_SEND_COMMAND               SendCommand;\r
+  EFI_SD_HOST_IO_PROTOCOL_SET_CLOCK_FREQUENCY        SetClockFrequency;\r
+  EFI_SD_HOST_IO_PROTOCOL_SET_BUS_WIDTH              SetBusWidth;\r
+  EFI_SD_HOST_IO_PROTOCOL_SET_HOST_VOLTAGE           SetHostVoltage;\r
+  EFI_SD_HOST_IO_PROTOCOL_RESET_SD_HOST              ResetSDHost;\r
+  EFI_SD_HOST_IO_PROTOCOL_ENABLE_AUTO_STOP_CMD       EnableAutoStopCmd;\r
+  EFI_SD_HOST_IO_PROTOCOL_DETECT_CARD_AND_INIT_HOST  DetectCardAndInitHost;\r
+  EFI_SD_HOST_IO_PROTOCOL_SET_BLOCK_LENGTH           SetBlockLength;\r
+  EFI_SD_HOST_IO_PROTOCOL_HIGH_SPEED_MODE            SetHighSpeedMode;\r
+  EFI_SD_HOST_IO_PROTOCOL_DUAL_DATARATE_MODE         SetDDRMode;\r
+};\r
+\r
+extern EFI_GUID gEfiSDHostIoProtocolGuid;\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/CommonHeader.h b/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/CommonHeader.h
new file mode 100644 (file)
index 0000000..0d56b71
--- /dev/null
@@ -0,0 +1,61 @@
+/** @file\r
+Common header file shared by all source files.\r
+\r
+This file includes package header files, library classes and protocol, PPI & GUID definitions.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#ifndef __COMMON_HEADER_H_\r
+#define __COMMON_HEADER_H_\r
+\r
+//\r
+// The package level header files this module uses\r
+//\r
+#include <PiDxe.h>\r
+#include <Ioh.h>\r
+#include <IohCommonDefinitions.h>\r
+\r
+//\r
+// The protocols, PPI and GUID defintions for this module\r
+//\r
+#include <Protocol/PciRootBridgeIo.h>\r
+\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/DevicePath.h>\r
+\r
+//\r
+// The Library classes this module consumes\r
+//\r
+#include <Library/BaseLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/S3PciLib.h>\r
+#include <Library/S3IoLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/PciLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/S3BootScriptLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/IohLib.h>\r
+\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <IndustryStandard/Pci.h>\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohBds.h b/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohBds.h
new file mode 100644 (file)
index 0000000..789f18b
--- /dev/null
@@ -0,0 +1,89 @@
+/** @file\r
+Head file for BDS Platform specific code\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _IOH_BDS_H\r
+#define _IOH_BDS_H\r
+\r
+#include <Ioh.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Library/DevicePathLib.h>\r
+\r
+extern EFI_DEVICE_PATH_PROTOCOL  *gDeviceConnectOption [];\r
+\r
+#define PCI_DEVICE_PATH_NODE(Func, Dev) \\r
+  { \\r
+    { \\r
+      HARDWARE_DEVICE_PATH, \\r
+      HW_PCI_DP, \\r
+      { \\r
+        (UINT8) (sizeof (PCI_DEVICE_PATH)), \\r
+        (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \\r
+      } \\r
+    }, \\r
+    (Func), \\r
+    (Dev) \\r
+  }\r
+\r
+#define PNPID_DEVICE_PATH_NODE(PnpId) \\r
+  { \\r
+    { \\r
+      ACPI_DEVICE_PATH, \\r
+      ACPI_DP, \\r
+      { \\r
+        (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \\r
+        (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \\r
+      } \\r
+    }, \\r
+    EISA_PNP_ID((PnpId)), \\r
+    0 \\r
+  }\r
+\r
+\r
+\r
+#define gEndEntire \\r
+  { \\r
+    END_DEVICE_PATH_TYPE, \\r
+    END_ENTIRE_DEVICE_PATH_SUBTYPE, \\r
+    { \\r
+      END_DEVICE_PATH_LENGTH, \\r
+      0 \\r
+    } \\r
+  }\r
+\r
+#define gPciRootBridge \\r
+  PNPID_DEVICE_PATH_NODE(0x0A03)\r
+\r
+\r
+//\r
+// Platform Root Bridge\r
+//\r
+typedef struct {\r
+  ACPI_HID_DEVICE_PATH      PciRootBridge;\r
+  EFI_DEVICE_PATH_PROTOCOL  End;\r
+} PLATFORM_ROOT_BRIDGE_DEVICE_PATH;\r
+\r
+\r
+typedef struct {\r
+  ACPI_HID_DEVICE_PATH      PciRootBridge;\r
+  PCI_DEVICE_PATH           IohDevice;\r
+  EFI_DEVICE_PATH_PROTOCOL  End;\r
+} IOH_PCI_USB_DEVICE_PATH;\r
+\r
+//\r
+// Ioh BDS Functions\r
+//\r
+\r
+\r
+#endif // _IOH_BDS_H\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohData.c b/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohData.c
new file mode 100644 (file)
index 0000000..432a86f
--- /dev/null
@@ -0,0 +1,48 @@
+/** @file\r
+Defined the Ioh device path which will be used by\r
+platform Bbd to perform the platform policy connect.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "IohBds.h"\r
+\r
+//\r
+// Predefined platform root bridge\r
+//\r
+PLATFORM_ROOT_BRIDGE_DEVICE_PATH gPlatformRootBridge0 = {\r
+  gPciRootBridge,\r
+  gEndEntire\r
+};\r
+\r
+EFI_DEVICE_PATH_PROTOCOL* gPlatformRootBridges [] = {\r
+  (EFI_DEVICE_PATH_PROTOCOL*)&gPlatformRootBridge0,\r
+  NULL\r
+};\r
+\r
+//\r
+// Ioh USB EHCI controller device path\r
+//\r
+IOH_PCI_USB_DEVICE_PATH gIohUsbDevicePath0 = {\r
+  gPciRootBridge,\r
+  PCI_DEVICE_PATH_NODE(IOH_EHCI_FUNCTION_NUMBER, IOH_USB_EHCI_DEVICE_NUMBER),\r
+  gEndEntire\r
+};\r
+\r
+//\r
+// Ioh predefined device connecting option\r
+//\r
+EFI_DEVICE_PATH_PROTOCOL* gDeviceConnectOption [] = {\r
+  //  (EFI_DEVICE_PATH_PROTOCOL*)&gIohUsbDevicePath0,\r
+  NULL\r
+};\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInit.c b/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInit.c
new file mode 100644 (file)
index 0000000..8ab48bc
--- /dev/null
@@ -0,0 +1,43 @@
+/** @file\r
+QuarkSCSocId module initialization module\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include "CommonHeader.h"\r
+#include "IohBds.h"\r
+\r
+/**\r
+   The entry function for IohInit driver.\r
+\r
+   This function just call initialization function.\r
+\r
+   @param ImageHandle   The driver image handle for GmchInit driver\r
+   @param SystemTable   The pointer to System Table\r
+\r
+   @retval EFI_SUCCESS  Success to initialize every module.\r
+   @return EFI_STATUS   The status of initialization work.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IohInit (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+{\r
+\r
+  InitializeIohSsvidSsid(IOH_BUS, IOH_PCI_IOSF2AHB_0_DEV_NUM, 0);\r
+\r
+  InitializeIohSsvidSsid(IOH_BUS, IOH_PCI_IOSF2AHB_1_DEV_NUM, 0);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInitDxe.inf b/QuarkSocPkg/QuarkSouthCluster/IohInit/Dxe/IohInitDxe.inf
new file mode 100644 (file)
index 0000000..4ac1609
--- /dev/null
@@ -0,0 +1,82 @@
+## @file\r
+# Component description file for Quark South Cluster Init driver.\r
+#\r
+# IohInit driver implement QuarkSCSocId related drivers, includes:\r
+# PciHostBridge, PciExpress, SmmAccess driver and LegacyRegion driver.\r
+#\r
+# This driver mainly do full initialization for the Soc chipet includes:\r
+# 1. Initialize the PCI Express device.\r
+# 2. Initialize the PciHostBridge, and allocate the I/O and memory space from GCD service.\r
+# 3. Initialize the SmmAccess module and install EFI_SMM_ACCESS_PROTOCOL\r
+# 4. Initialize the LegacyRegion module, install EFI_LEGACY_REGION_PROTOCOL and set below 1M\r
+#    memory attribute from MTRR.\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = IohInitDxe\r
+  FILE_GUID                      = 3FE2A8A3-C400-48F8-832F-7881A394C250\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = IohInit\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  IohInit.c\r
+  IohBds.h\r
+  IohData.c\r
+  CommonHeader.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  S3BootScriptLib\r
+  PcdLib\r
+  HobLib\r
+  PciLib\r
+  BaseMemoryLib\r
+  MemoryAllocationLib\r
+  S3PciLib\r
+  UefiLib\r
+  DebugLib\r
+  UefiRuntimeServicesTableLib\r
+  UefiBootServicesTableLib\r
+  DxeServicesTableLib\r
+  UefiDriverEntryPoint\r
+  BaseLib\r
+  S3IoLib\r
+  IoLib\r
+  DevicePathLib\r
+  IohLib\r
+\r
+[Protocols]\r
+  gEfiPciRootBridgeIoProtocolGuid               # PROTOCOL ALWAYS_PRODUCED\r
+  gEfiDevicePathProtocolGuid                    # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiPciIoProtocolGuid\r
+\r
+[Pcd]\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartBusNumber\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartDevNumber\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohUartFunctionNumber\r
+\r
+[Depex]\r
+  TRUE\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Library/I2cLib/CommonHeader.h b/QuarkSocPkg/QuarkSouthCluster/Library/I2cLib/CommonHeader.h
new file mode 100644 (file)
index 0000000..facc00f
--- /dev/null
@@ -0,0 +1,220 @@
+/** @file\r
+Provides definition of entry point to the common I2C module that produces\r
+common I2C Controller functions used by I2C library services.\r
+\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#ifndef _I2CCOMMON_H_\r
+#define _I2CCOMMON_H_\r
+\r
+#include <Uefi.h>\r
+#include <Base.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/I2cLib.h>\r
+#include <IohAccess.h>\r
+#include <IohCommonDefinitions.h>\r
+#include "I2cRegs.h"\r
+\r
+//\r
+// Constants that define I2C Controller timeout and max. polling time.\r
+//\r
+#define MAX_T_POLL_COUNT         100\r
+#define TI2C_POLL                25  // microseconds\r
+#define MAX_STOP_DET_POLL_COUNT ((1000 * 1000) / TI2C_POLL)  // Extreme for expected Stop detect.\r
+\r
+/**\r
+  The GetI2CIoPortBaseAddress() function gets IO port base address of I2C Controller.\r
+\r
+  Always reads PCI configuration space to get MMIO base address of I2C Controller.\r
+\r
+  @return The IO port base address of I2C controller.\r
+\r
+**/\r
+UINTN\r
+GetI2CIoPortBaseAddress (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  The EnableI2CMmioSpace() function enables access to I2C MMIO space.\r
+\r
+**/\r
+VOID\r
+EnableI2CMmioSpace (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  The DisableI2CController() functions disables I2C Controller.\r
+\r
+**/\r
+VOID\r
+DisableI2CController (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  The EnableI2CController() function enables the I2C Controller.\r
+\r
+**/\r
+VOID\r
+EnableI2CController (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  The WaitForStopDet() function waits until I2C STOP Condition occurs,\r
+  indicating transfer completion.\r
+\r
+  @retval EFI_SUCCESS           Stop detected.\r
+  @retval EFI_TIMEOUT           Timeout while waiting for stop condition.\r
+  @retval EFI_ABORTED           Tx abort signaled in HW status register.\r
+  @retval EFI_DEVICE_ERROR      Tx or Rx overflow detected.\r
+\r
+**/\r
+EFI_STATUS\r
+WaitForStopDet (\r
+  VOID\r
+  );\r
+\r
+/**\r
+\r
+  The InitializeInternal() function initialises internal I2C Controller\r
+  register values that are commonly required for I2C Write and Read transfers.\r
+\r
+  @param AddrMode     I2C Addressing Mode: 7-bit or 10-bit address.\r
+\r
+  @retval EFI_SUCCESS           I2C Operation completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeInternal (\r
+  IN EFI_I2C_ADDR_MODE  AddrMode\r
+  );\r
+\r
+/**\r
+\r
+  The WriteByte() function provides a standard way to execute a\r
+  standard single byte write to an IC2 device (without accessing\r
+  sub-addresses), as defined in the I2C Specification.\r
+\r
+  @param  I2CAddress      I2C Slave device address\r
+  @param  Value           The 8-bit value to write.\r
+\r
+  @retval EFI_SUCCESS           Transfer success.\r
+  @retval EFI_UNSUPPORTED       Unsupported input param.\r
+  @retval EFI_TIMEOUT           Timeout while waiting xfer.\r
+  @retval EFI_ABORTED           Controller aborted xfer.\r
+  @retval EFI_DEVICE_ERROR      Device error detected by controller.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+WriteByte (\r
+  IN  UINTN          I2CAddress,\r
+  IN  UINT8          Value\r
+  );\r
+\r
+/**\r
+\r
+  The ReadByte() function provides a standard way to execute a\r
+  standard single byte read to an IC2 device (without accessing\r
+  sub-addresses), as defined in the I2C Specification.\r
+\r
+  @param  I2CAddress      I2C Slave device address\r
+  @param  ReturnDataPtr   Pointer to location to receive read byte.\r
+\r
+  @retval EFI_SUCCESS           Transfer success.\r
+  @retval EFI_UNSUPPORTED       Unsupported input param.\r
+  @retval EFI_TIMEOUT           Timeout while waiting xfer.\r
+  @retval EFI_ABORTED           Controller aborted xfer.\r
+  @retval EFI_DEVICE_ERROR      Device error detected by controller.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ReadByte (\r
+  IN  UINTN          I2CAddress,\r
+  OUT UINT8          *ReturnDataPtr\r
+  );\r
+\r
+/**\r
+\r
+  The WriteMultipleByte() function provides a standard way to execute\r
+  multiple byte writes to an IC2 device (e.g. when accessing sub-addresses or\r
+  when writing block of data), as defined in the I2C Specification.\r
+\r
+  @param I2CAddress   The I2C slave address of the device\r
+                      with which to communicate.\r
+\r
+  @param WriteBuffer  Contains the value of byte to be written to the\r
+                      I2C slave device.\r
+\r
+  @param Length       No. of bytes to be written.\r
+\r
+  @retval EFI_SUCCESS           Transfer success.\r
+  @retval EFI_UNSUPPORTED       Unsupported input param.\r
+  @retval EFI_TIMEOUT           Timeout while waiting xfer.\r
+  @retval EFI_ABORTED           Tx abort signaled in HW status register.\r
+  @retval EFI_DEVICE_ERROR      Tx overflow detected.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+WriteMultipleByte (\r
+  IN  UINTN          I2CAddress,\r
+  IN  UINT8          *WriteBuffer,\r
+  IN  UINTN          Length\r
+  );\r
+\r
+/**\r
+\r
+  The ReadMultipleByte() function provides a standard way to execute\r
+  multiple byte writes to an IC2 device (e.g. when accessing sub-addresses or\r
+  when reading block of data), as defined in the I2C Specification (I2C combined\r
+  write/read protocol).\r
+\r
+  @param I2CAddress   The I2C slave address of the device\r
+                      with which to communicate.\r
+\r
+  @param Buffer       Contains the value of byte data written or read from the\r
+                      I2C slave device.\r
+\r
+  @param WriteLength  No. of bytes to be written. In this case data\r
+                      written typically contains sub-address or sub-addresses\r
+                      in Hi-Lo format, that need to be read (I2C combined\r
+                      write/read protocol).\r
+\r
+  @param ReadLength   No. of bytes to be read from I2C slave device.\r
+\r
+  @retval EFI_SUCCESS           Transfer success.\r
+  @retval EFI_UNSUPPORTED       Unsupported input param.\r
+  @retval EFI_TIMEOUT           Timeout while waiting xfer.\r
+  @retval EFI_ABORTED           Tx abort signaled in HW status register.\r
+  @retval EFI_DEVICE_ERROR      Rx underflow or Rx/Tx overflow detected.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ReadMultipleByte (\r
+  IN  UINTN          I2CAddress,\r
+  IN  OUT UINT8      *Buffer,\r
+  IN  UINTN          WriteLength,\r
+  IN  UINTN          ReadLength\r
+  );\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Library/I2cLib/I2cLib.c b/QuarkSocPkg/QuarkSouthCluster/Library/I2cLib/I2cLib.c
new file mode 100644 (file)
index 0000000..80f03ea
--- /dev/null
@@ -0,0 +1,1004 @@
+/** @file\r
+I2C Library for Quark I2C Controller.\r
+Follows I2C Controller setup instructions as detailed in\r
+Quark DataSheet (doc id: 329676) Section 19.1/19.1.3.\r
+\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "CommonHeader.h"\r
+\r
+/**\r
+  The Called to Common Service Entry.\r
+\r
+  @return None.\r
+\r
+**/\r
+\r
+VOID\r
+I2cCommonServiceEntry  (\r
+  OUT UINT16 *SaveCmdPtr,\r
+  OUT UINT32 *SaveBar0Ptr\r
+  )\r
+{\r
+  *SaveBar0Ptr = IohMmPci32 (0, I2C_Bus, I2C_Device, I2C_Func, PCI_BAR0);\r
+  if (((*SaveBar0Ptr) & B_IOH_I2C_GPIO_MEMBAR_ADDR_MASK) == 0) {\r
+\r
+    IohMmPci32(0, I2C_Bus, I2C_Device, I2C_Func, PCI_BAR0) =\r
+      FixedPcdGet32 (PcdIohI2cMmioBase) & B_IOH_I2C_GPIO_MEMBAR_ADDR_MASK;\r
+\r
+    //\r
+    // also Save Cmd Register, Setup by InitializeInternal later during xfers.\r
+    //\r
+    *SaveCmdPtr = IohMmPci16 (0, I2C_Bus, I2C_Device, I2C_Func, PCI_CMD);\r
+  }\r
+}\r
+\r
+/**\r
+  The Called on Common Service Exit.\r
+\r
+  @return None.\r
+\r
+**/\r
+VOID\r
+I2cCommonServiceExit  (\r
+  IN CONST UINT16 SaveCmd,\r
+  IN CONST UINT32 SaveBar0\r
+\r
+  )\r
+{\r
+  if ((SaveBar0 & B_IOH_I2C_GPIO_MEMBAR_ADDR_MASK) == 0) {\r
+    IohMmPci16 (0, I2C_Bus, I2C_Device, I2C_Func, PCI_CMD) = SaveCmd;\r
+    IohMmPci32 (0, I2C_Bus, I2C_Device, I2C_Func, PCI_BAR0) = SaveBar0;\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  The GetI2CIoPortBaseAddress() function gets IO port base address of I2C Controller.\r
+\r
+  Always reads PCI configuration space to get MMIO base address of I2C Controller.\r
+\r
+  @return The IO port base address of I2C controller.\r
+\r
+**/\r
+UINTN\r
+GetI2CIoPortBaseAddress (\r
+  VOID\r
+  )\r
+{\r
+  UINTN     I2CIoPortBaseAddress;\r
+\r
+  //\r
+  // Get I2C Memory Mapped registers base address.\r
+  //\r
+  I2CIoPortBaseAddress = IohMmPci32(0, I2C_Bus, I2C_Device, I2C_Func, PCI_BAR0);\r
+\r
+  //\r
+  // Make sure that the IO port base address has been properly set.\r
+  //\r
+  ASSERT (I2CIoPortBaseAddress != 0);\r
+  ASSERT (I2CIoPortBaseAddress != 0xFF);\r
+\r
+  return I2CIoPortBaseAddress;\r
+}\r
+\r
+\r
+/**\r
+  The EnableI2CMmioSpace() function enables access to I2C MMIO space.\r
+\r
+**/\r
+VOID\r
+EnableI2CMmioSpace (\r
+  VOID\r
+  )\r
+{\r
+  UINT8 PciCmd;\r
+\r
+  //\r
+  // Read PCICMD.  Bus=0, Dev=0, Func=0, Reg=0x4\r
+  //\r
+  PciCmd = IohMmPci8(0, I2C_Bus, I2C_Device, I2C_Func, PCI_REG_PCICMD);\r
+\r
+  //\r
+  // Enable Bus Master(Bit2), MMIO Space(Bit1) & I/O Space(Bit0)\r
+  //\r
+  PciCmd |= 0x7;\r
+  IohMmPci8(0, I2C_Bus, I2C_Device, I2C_Func, PCI_REG_PCICMD) = PciCmd;\r
+\r
+}\r
+\r
+/**\r
+  The DisableI2CController() functions disables I2C Controller.\r
+\r
+**/\r
+VOID\r
+DisableI2CController (\r
+  VOID\r
+  )\r
+{\r
+  UINTN       I2CIoPortBaseAddress;\r
+  UINT32      Addr;\r
+  UINT32      Data;\r
+  UINT8       PollCount;\r
+\r
+  PollCount = 0;\r
+\r
+  //\r
+  // Get I2C Memory Mapped registers base address.\r
+  //\r
+  I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();\r
+\r
+  //\r
+  // Disable the I2C Controller by setting IC_ENABLE.ENABLE to zero\r
+  //\r
+  Addr = I2CIoPortBaseAddress + I2C_REG_ENABLE;\r
+  Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+  Data &= ~B_I2C_REG_ENABLE;\r
+  *((volatile UINT32 *) (UINTN)(Addr)) = Data;\r
+\r
+  //\r
+  // Read the IC_ENABLE_STATUS.IC_EN Bit to check if Controller is disabled\r
+  //\r
+  Data = 0xFF;\r
+  Addr = I2CIoPortBaseAddress + I2C_REG_ENABLE_STATUS;\r
+  Data = *((volatile UINT32 *) (UINTN)(Addr)) & I2C_REG_ENABLE_STATUS;\r
+  while (Data != 0) {\r
+    //\r
+    // Poll the IC_ENABLE_STATUS.IC_EN Bit to check if Controller is disabled, until timeout (TI2C_POLL*MAX_T_POLL_COUNT).\r
+    //\r
+    PollCount++;\r
+    if (PollCount >= MAX_T_POLL_COUNT) {\r
+      break;\r
+    }\r
+    MicroSecondDelay(TI2C_POLL);\r
+    Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+    Data &= I2C_REG_ENABLE_STATUS;\r
+  }\r
+\r
+  //\r
+  // Asset if controller does not enter Disabled state.\r
+  //\r
+  ASSERT (PollCount < MAX_T_POLL_COUNT);\r
+\r
+  //\r
+  // Read IC_CLR_INTR register to automatically clear the combined interrupt,\r
+  // all individual interrupts and the IC_TX_ABRT_SOURCE register.\r
+  //\r
+  Addr = I2CIoPortBaseAddress + I2C_REG_CLR_INT;\r
+  Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+\r
+}\r
+\r
+/**\r
+  The EnableI2CController() function enables the I2C Controller.\r
+\r
+**/\r
+VOID\r
+EnableI2CController (\r
+  VOID\r
+  )\r
+{\r
+  UINTN   I2CIoPortBaseAddress;\r
+  UINT32  Addr;\r
+  UINT32  Data;\r
+\r
+  //\r
+  // Get I2C Memory Mapped registers base address.\r
+  //\r
+  I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();\r
+\r
+  //\r
+  // Enable the I2C Controller by setting IC_ENABLE.ENABLE to 1\r
+  //\r
+  Addr = I2CIoPortBaseAddress + I2C_REG_ENABLE;\r
+  Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+  Data |= B_I2C_REG_ENABLE;\r
+  *((volatile UINT32 *) (UINTN)(Addr)) = Data;\r
+\r
+  //\r
+  // Clear overflow and abort error status bits before transactions.\r
+  //\r
+  Addr = I2CIoPortBaseAddress + I2C_REG_CLR_RX_OVER;\r
+  Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+  Addr = I2CIoPortBaseAddress + I2C_REG_CLR_TX_OVER;\r
+  Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+  Addr = I2CIoPortBaseAddress + I2C_REG_CLR_TX_ABRT;\r
+  Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+\r
+}\r
+\r
+/**\r
+  The WaitForStopDet() function waits until I2C STOP Condition occurs,\r
+  indicating transfer completion.\r
+\r
+  @retval EFI_SUCCESS           Stop detected.\r
+  @retval EFI_TIMEOUT           Timeout while waiting for stop condition.\r
+  @retval EFI_ABORTED           Tx abort signaled in HW status register.\r
+  @retval EFI_DEVICE_ERROR      Tx or Rx overflow detected.\r
+\r
+**/\r
+EFI_STATUS\r
+WaitForStopDet (\r
+  VOID\r
+  )\r
+{\r
+  UINTN       I2CIoPortBaseAddress;\r
+  UINT32      Addr;\r
+  UINT32      Data;\r
+  UINT32      PollCount;\r
+  EFI_STATUS  Status;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  PollCount = 0;\r
+\r
+  //\r
+  // Get I2C Memory Mapped registers base address.\r
+  //\r
+  I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();\r
+\r
+  //\r
+  // Wait for STOP Detect.\r
+  //\r
+  Addr = I2CIoPortBaseAddress + I2C_REG_RAW_INTR_STAT;\r
+\r
+  do {\r
+    Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+    if ((Data & I2C_REG_RAW_INTR_STAT_TX_ABRT) != 0) {\r
+      Status = EFI_ABORTED;\r
+      break;\r
+    }\r
+    if ((Data & I2C_REG_RAW_INTR_STAT_TX_OVER) != 0) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      break;\r
+    }\r
+    if ((Data & I2C_REG_RAW_INTR_STAT_RX_OVER) != 0) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      break;\r
+    }\r
+    if ((Data & I2C_REG_RAW_INTR_STAT_STOP_DET) != 0) {\r
+      Status = EFI_SUCCESS;\r
+      break;\r
+    }\r
+    MicroSecondDelay(TI2C_POLL);\r
+    PollCount++;\r
+    if (PollCount >= MAX_STOP_DET_POLL_COUNT) {\r
+      Status = EFI_TIMEOUT;\r
+      break;\r
+    }\r
+\r
+  } while (TRUE);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  The InitializeInternal() function initialises internal I2C Controller\r
+  register values that are commonly required for I2C Write and Read transfers.\r
+\r
+  @param AddrMode     I2C Addressing Mode: 7-bit or 10-bit address.\r
+\r
+  @retval EFI_SUCCESS           I2C Operation completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeInternal (\r
+  IN  EFI_I2C_ADDR_MODE  AddrMode\r
+  )\r
+{\r
+  UINTN       I2CIoPortBaseAddress;\r
+  UINTN       Addr;\r
+  UINT32      Data;\r
+  EFI_STATUS  Status;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  // Enable access to I2C Controller MMIO space.\r
+  //\r
+  EnableI2CMmioSpace ();\r
+\r
+  //\r
+  // Disable I2C Controller initially\r
+  //\r
+  DisableI2CController ();\r
+\r
+  //\r
+  // Get I2C Memory Mapped registers base address.\r
+  //\r
+  I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();\r
+\r
+  //\r
+  // Clear START_DET\r
+  //\r
+  Addr = I2CIoPortBaseAddress + I2C_REG_CLR_START_DET;\r
+  Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+  Data &= ~B_I2C_REG_CLR_START_DET;\r
+  *((volatile UINT32 *) (UINTN)(Addr)) = Data;\r
+\r
+  //\r
+  // Clear STOP_DET\r
+  //\r
+  Addr = I2CIoPortBaseAddress + I2C_REG_CLR_STOP_DET;\r
+  Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+  Data &= ~B_I2C_REG_CLR_STOP_DET;\r
+  *((volatile UINT32 *) (UINTN)(Addr)) = Data;\r
+\r
+  //\r
+  // Set addressing mode to user defined (7 or 10 bit) and\r
+  // speed mode to that defined by PCD (standard mode default).\r
+  //\r
+  Addr = I2CIoPortBaseAddress + I2C_REG_CON;\r
+  Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+  // Set Addressing Mode\r
+  if (AddrMode == EfiI2CSevenBitAddrMode) {\r
+    Data &= ~B_I2C_REG_CON_10BITADD_MASTER;\r
+  } else {\r
+    Data |= B_I2C_REG_CON_10BITADD_MASTER;\r
+  }\r
+  // Set Speed Mode\r
+  Data &= ~B_I2C_REG_CON_SPEED;\r
+  if (FeaturePcdGet (PcdI2CFastModeEnabled)) {\r
+    Data |= BIT2;\r
+  } else {\r
+    Data |= BIT1;\r
+  }\r
+  *((volatile UINT32 *) (UINTN)(Addr)) = Data;\r
+\r
+  Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+\r
+  return Status;\r
+\r
+}\r
+\r
+/**\r
+\r
+  The WriteByte() function provides a standard way to execute a\r
+  standard single byte write to an IC2 device (without accessing\r
+  sub-addresses), as defined in the I2C Specification.\r
+\r
+  @param  I2CAddress      I2C Slave device address\r
+  @param  Value           The 8-bit value to write.\r
+\r
+  @retval EFI_SUCCESS           Transfer success.\r
+  @retval EFI_UNSUPPORTED       Unsupported input param.\r
+  @retval EFI_TIMEOUT           Timeout while waiting xfer.\r
+  @retval EFI_ABORTED           Controller aborted xfer.\r
+  @retval EFI_DEVICE_ERROR      Device error detected by controller.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+WriteByte (\r
+  IN  UINTN          I2CAddress,\r
+  IN  UINT8          Value\r
+  )\r
+{\r
+  UINTN       I2CIoPortBaseAddress;\r
+  UINTN       Addr;\r
+  UINT32      Data;\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Get I2C Memory Mapped registers base address\r
+  //\r
+  I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();\r
+\r
+  //\r
+  // Write to the IC_TAR register the address of the slave device to be addressed\r
+  //\r
+  Addr = I2CIoPortBaseAddress + I2C_REG_TAR;\r
+  Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+  Data &= ~B_I2C_REG_TAR;\r
+  Data |= I2CAddress;\r
+  *((volatile UINT32 *) (UINTN)(Addr)) = Data;\r
+\r
+  //\r
+  // Enable the I2C Controller\r
+  //\r
+  EnableI2CController ();\r
+\r
+  //\r
+  // Write the data and transfer direction to the IC_DATA_CMD register.\r
+  // Also specify that transfer should be terminated by STOP condition.\r
+  //\r
+  Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;\r
+  Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+  Data &= 0xFFFFFF00;\r
+  Data |= (UINT8)Value;\r
+  Data &= ~B_I2C_REG_DATA_CMD_RW;\r
+  Data |= B_I2C_REG_DATA_CMD_STOP;\r
+  *((volatile UINT32 *) (UINTN)(Addr)) = Data;\r
+\r
+  //\r
+  // Wait for transfer completion.\r
+  //\r
+  Status = WaitForStopDet ();\r
+\r
+  //\r
+  // Ensure I2C Controller disabled.\r
+  //\r
+  DisableI2CController();\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  The ReadByte() function provides a standard way to execute a\r
+  standard single byte read to an IC2 device (without accessing\r
+  sub-addresses), as defined in the I2C Specification.\r
+\r
+  @param  I2CAddress      I2C Slave device address\r
+  @param  ReturnDataPtr   Pointer to location to receive read byte.\r
+\r
+  @retval EFI_SUCCESS           Transfer success.\r
+  @retval EFI_UNSUPPORTED       Unsupported input param.\r
+  @retval EFI_TIMEOUT           Timeout while waiting xfer.\r
+  @retval EFI_ABORTED           Controller aborted xfer.\r
+  @retval EFI_DEVICE_ERROR      Device error detected by controller.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ReadByte (\r
+  IN  UINTN          I2CAddress,\r
+  OUT UINT8          *ReturnDataPtr\r
+  )\r
+{\r
+  UINTN       I2CIoPortBaseAddress;\r
+  UINTN       Addr;\r
+  UINT32      Data;\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Get I2C Memory Mapped registers base address.\r
+  //\r
+  I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();\r
+\r
+  //\r
+  // Write to the IC_TAR register the address of the slave device to be addressed\r
+  //\r
+  Addr = I2CIoPortBaseAddress + I2C_REG_TAR;\r
+  Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+  Data &= ~B_I2C_REG_TAR;\r
+  Data |= I2CAddress;\r
+  *((volatile UINT32 *) (UINTN)(Addr)) = Data;\r
+\r
+  //\r
+  // Enable the I2C Controller\r
+  //\r
+  EnableI2CController ();\r
+\r
+  //\r
+  // Write transfer direction to the IC_DATA_CMD register and\r
+  // specify that transfer should be terminated by STOP condition.\r
+  //\r
+  Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;\r
+  Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+  Data &= 0xFFFFFF00;\r
+  Data |= B_I2C_REG_DATA_CMD_RW;\r
+  Data |= B_I2C_REG_DATA_CMD_STOP;\r
+  *((volatile UINT32 *) (UINTN)(Addr)) = Data;\r
+\r
+  //\r
+  // Wait for transfer completion\r
+  //\r
+  Status = WaitForStopDet ();\r
+  if (!EFI_ERROR(Status)) {\r
+\r
+    //\r
+    // Clear RX underflow before reading IC_DATA_CMD.\r
+    //\r
+    Addr = I2CIoPortBaseAddress + I2C_REG_CLR_RX_UNDER;\r
+    Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+\r
+    //\r
+    // Obtain and return read data byte from RX buffer (IC_DATA_CMD[7:0]).\r
+    //\r
+    Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;\r
+    Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+    Data &= 0x000000FF;\r
+    *ReturnDataPtr = (UINT8) Data;\r
+\r
+    Addr = I2CIoPortBaseAddress + I2C_REG_RAW_INTR_STAT;\r
+    Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+    Data &= I2C_REG_RAW_INTR_STAT_RX_UNDER;\r
+    if (Data != 0) {\r
+      Status = EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Ensure I2C Controller disabled.\r
+  //\r
+  DisableI2CController ();\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  The WriteMultipleByte() function provides a standard way to execute\r
+  multiple byte writes to an IC2 device (e.g. when accessing sub-addresses or\r
+  when writing block of data), as defined in the I2C Specification.\r
+\r
+  @param I2CAddress   The I2C slave address of the device\r
+                      with which to communicate.\r
+\r
+  @param WriteBuffer  Contains the value of byte to be written to the\r
+                      I2C slave device.\r
+\r
+  @param Length       No. of bytes to be written.\r
+\r
+  @retval EFI_SUCCESS           Transfer success.\r
+  @retval EFI_UNSUPPORTED       Unsupported input param.\r
+  @retval EFI_TIMEOUT           Timeout while waiting xfer.\r
+  @retval EFI_ABORTED           Tx abort signaled in HW status register.\r
+  @retval EFI_DEVICE_ERROR      Tx overflow detected.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+WriteMultipleByte (\r
+  IN  UINTN          I2CAddress,\r
+  IN  UINT8          *WriteBuffer,\r
+  IN  UINTN          Length\r
+  )\r
+{\r
+  UINTN       I2CIoPortBaseAddress;\r
+  UINTN       Index;\r
+  UINTN       Addr;\r
+  UINT32      Data;\r
+  EFI_STATUS  Status;\r
+\r
+  if (Length > I2C_FIFO_SIZE) {\r
+    return EFI_UNSUPPORTED;  // Routine does not handle xfers > fifo size.\r
+  }\r
+\r
+  I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();\r
+\r
+  //\r
+  // Write to the IC_TAR register the address of the slave device to be addressed\r
+  //\r
+  Addr = I2CIoPortBaseAddress + I2C_REG_TAR;\r
+  Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+  Data &= ~B_I2C_REG_TAR;\r
+  Data |= I2CAddress;\r
+  *((volatile UINT32 *) (UINTN)(Addr)) = Data;\r
+\r
+  //\r
+  // Enable the I2C Controller\r
+  //\r
+  EnableI2CController ();\r
+\r
+  //\r
+  // Write the data and transfer direction to the IC_DATA_CMD register.\r
+  // Also specify that transfer should be terminated by STOP condition.\r
+  //\r
+  Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;\r
+  for (Index = 0; Index < Length; Index++) {\r
+    Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+    Data &= 0xFFFFFF00;\r
+    Data |= (UINT8)WriteBuffer[Index];\r
+    Data &= ~B_I2C_REG_DATA_CMD_RW;\r
+    if (Index == (Length-1)) {\r
+      Data |= B_I2C_REG_DATA_CMD_STOP;\r
+    }\r
+    *((volatile UINT32 *) (UINTN)(Addr)) = Data;\r
+  }\r
+\r
+  //\r
+  // Wait for transfer completion\r
+  //\r
+  Status = WaitForStopDet ();\r
+\r
+  //\r
+  // Ensure I2C Controller disabled.\r
+  //\r
+  DisableI2CController ();\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  The ReadMultipleByte() function provides a standard way to execute\r
+  multiple byte writes to an IC2 device (e.g. when accessing sub-addresses or\r
+  when reading block of data), as defined in the I2C Specification (I2C combined\r
+  write/read protocol).\r
+\r
+  @param I2CAddress   The I2C slave address of the device\r
+                      with which to communicate.\r
+\r
+  @param Buffer       Contains the value of byte data written or read from the\r
+                      I2C slave device.\r
+\r
+  @param WriteLength  No. of bytes to be written. In this case data\r
+                      written typically contains sub-address or sub-addresses\r
+                      in Hi-Lo format, that need to be read (I2C combined\r
+                      write/read protocol).\r
+\r
+  @param ReadLength   No. of bytes to be read from I2C slave device.\r
+\r
+  @retval EFI_SUCCESS           Transfer success.\r
+  @retval EFI_UNSUPPORTED       Unsupported input param.\r
+  @retval EFI_TIMEOUT           Timeout while waiting xfer.\r
+  @retval EFI_ABORTED           Tx abort signaled in HW status register.\r
+  @retval EFI_DEVICE_ERROR      Rx underflow or Rx/Tx overflow detected.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ReadMultipleByte (\r
+  IN  UINTN          I2CAddress,\r
+  IN  OUT UINT8      *Buffer,\r
+  IN  UINTN          WriteLength,\r
+  IN  UINTN          ReadLength\r
+  )\r
+{\r
+  UINTN       I2CIoPortBaseAddress;\r
+  UINTN       Index;\r
+  UINTN       Addr;\r
+  UINT32      Data;\r
+  UINT8       PollCount;\r
+  EFI_STATUS  Status;\r
+\r
+  if (WriteLength > I2C_FIFO_SIZE || ReadLength > I2C_FIFO_SIZE) {\r
+    return EFI_UNSUPPORTED;  // Routine does not handle xfers > fifo size.\r
+  }\r
+\r
+  I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();\r
+\r
+  //\r
+  // Write to the IC_TAR register the address of the slave device to be addressed\r
+  //\r
+  Addr = I2CIoPortBaseAddress + I2C_REG_TAR;\r
+  Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+  Data &= ~B_I2C_REG_TAR;\r
+  Data |= I2CAddress;\r
+  *((volatile UINT32 *) (UINTN)(Addr)) = Data;\r
+\r
+  //\r
+  // Enable the I2C Controller\r
+  //\r
+  EnableI2CController ();\r
+\r
+  //\r
+  // Write the data (sub-addresses) to the IC_DATA_CMD register.\r
+  //\r
+  Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;\r
+  for (Index = 0; Index < WriteLength; Index++) {\r
+    Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+    Data &= 0xFFFFFF00;\r
+    Data |= (UINT8)Buffer[Index];\r
+    Data &= ~B_I2C_REG_DATA_CMD_RW;\r
+    *((volatile UINT32 *) (UINTN)(Addr)) = Data;\r
+  }\r
+\r
+  //\r
+  // Issue Read Transfers for each byte (Restart issued when write/read bit changed).\r
+  //\r
+  for (Index = 0; Index < ReadLength; Index++) {\r
+    Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+    Data |= B_I2C_REG_DATA_CMD_RW;\r
+    // Issue a STOP for last read transfer.\r
+    if (Index == (ReadLength-1)) {\r
+      Data |= B_I2C_REG_DATA_CMD_STOP;\r
+    }\r
+    *((volatile UINT32 *) (UINTN)(Addr)) = Data;\r
+  }\r
+\r
+  //\r
+  // Wait for STOP condition.\r
+  //\r
+  Status = WaitForStopDet ();\r
+  if (!EFI_ERROR(Status)) {\r
+\r
+    //\r
+    // Poll Receive FIFO Buffer Level register until valid (upto MAX_T_POLL_COUNT times).\r
+    //\r
+    Data = 0;\r
+    PollCount = 0;\r
+    Addr = I2CIoPortBaseAddress + I2C_REG_RXFLR;\r
+    Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+    while ((Data != ReadLength) && (PollCount < MAX_T_POLL_COUNT)) {\r
+      MicroSecondDelay(TI2C_POLL);\r
+      PollCount++;\r
+      Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+    }\r
+\r
+    Addr = I2CIoPortBaseAddress + I2C_REG_RAW_INTR_STAT;\r
+    Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+\r
+    //\r
+    // If no timeout or device error then read rx data.\r
+    //\r
+    if (PollCount == MAX_T_POLL_COUNT) {\r
+      Status = EFI_TIMEOUT;\r
+    } else if ((Data & I2C_REG_RAW_INTR_STAT_RX_OVER) != 0) {\r
+      Status = EFI_DEVICE_ERROR;\r
+    } else {\r
+\r
+      //\r
+      // Clear RX underflow before reading IC_DATA_CMD.\r
+      //\r
+      Addr = I2CIoPortBaseAddress + I2C_REG_CLR_RX_UNDER;\r
+      Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+\r
+      //\r
+      // Read data.\r
+      //\r
+      Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;\r
+      for (Index = 0; Index < ReadLength; Index++) {\r
+        Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+        Data &= 0x000000FF;\r
+        *(Buffer+Index) = (UINT8)Data;\r
+      }\r
+      Addr = I2CIoPortBaseAddress + I2C_REG_RAW_INTR_STAT;\r
+      Data = *((volatile UINT32 *) (UINTN)(Addr));\r
+      Data &= I2C_REG_RAW_INTR_STAT_RX_UNDER;\r
+      if (Data != 0) {\r
+        Status = EFI_DEVICE_ERROR;\r
+      } else {\r
+        Status = EFI_SUCCESS;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Ensure I2C Controller disabled.\r
+  //\r
+  DisableI2CController ();\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  The I2cWriteByte() function is a wrapper function for the WriteByte function.\r
+  Provides a standard way to execute a standard single byte write to an IC2 device\r
+  (without accessing sub-addresses), as defined in the I2C Specification.\r
+\r
+  @param SlaveAddress The I2C slave address of the device\r
+                      with which to communicate.\r
+\r
+  @param AddrMode     I2C Addressing Mode: 7-bit or 10-bit address.\r
+\r
+  @param Buffer       Contains the value of byte data to execute to the\r
+                      I2C slave device.\r
+\r
+\r
+  @retval EFI_SUCCESS           Transfer success.\r
+  @retval EFI_INVALID_PARAMETER  This or Buffer pointers are invalid.\r
+  @retval EFI_UNSUPPORTED       Unsupported input param.\r
+  @retval EFI_TIMEOUT           Timeout while waiting xfer.\r
+  @retval EFI_ABORTED           Controller aborted xfer.\r
+  @retval EFI_DEVICE_ERROR      Device error detected by controller.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+I2cWriteByte (\r
+  IN        EFI_I2C_DEVICE_ADDRESS  SlaveAddress,\r
+  IN        EFI_I2C_ADDR_MODE       AddrMode,\r
+  IN OUT VOID                       *Buffer\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+  UINTN      I2CAddress;\r
+  UINT16            SaveCmd;\r
+  UINT32            SaveBar0;\r
+\r
+  if (Buffer == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  SaveCmd = 0;\r
+  SaveBar0 = 0;\r
+\r
+  I2cCommonServiceEntry (&SaveCmd, &SaveBar0);\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  I2CAddress = SlaveAddress.I2CDeviceAddress;\r
+  Status = InitializeInternal (AddrMode);\r
+  if (!EFI_ERROR(Status)) {\r
+    Status = WriteByte (I2CAddress, *(UINT8 *) Buffer);\r
+  }\r
+\r
+  I2cCommonServiceExit (SaveCmd, SaveBar0);\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  The I2cReadByte() function is a wrapper function for the ReadByte function.\r
+  Provides a standard way to execute a standard single byte read to an I2C device\r
+  (without accessing sub-addresses), as defined in the I2C Specification.\r
+\r
+  @param SlaveAddress The I2C slave address of the device\r
+                      with which to communicate.\r
+\r
+  @param AddrMode     I2C Addressing Mode: 7-bit or 10-bit address.\r
+\r
+  @param Buffer       Contains the value of byte data read from the\r
+                      I2C slave device.\r
+\r
+\r
+  @retval EFI_SUCCESS           Transfer success.\r
+  @retval EFI_INVALID_PARAMETER This or Buffer pointers are invalid.\r
+  @retval EFI_TIMEOUT           Timeout while waiting xfer.\r
+  @retval EFI_ABORTED           Controller aborted xfer.\r
+  @retval EFI_DEVICE_ERROR      Device error detected by controller.\r
+\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+I2cReadByte (\r
+  IN        EFI_I2C_DEVICE_ADDRESS  SlaveAddress,\r
+  IN        EFI_I2C_ADDR_MODE       AddrMode,\r
+  IN OUT    VOID                    *Buffer\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+  UINTN      I2CAddress;\r
+  UINT16     SaveCmd;\r
+  UINT32     SaveBar0;\r
+\r
+  if (Buffer == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  SaveCmd = 0;\r
+  SaveBar0 =0;\r
+\r
+  I2cCommonServiceEntry (&SaveCmd, &SaveBar0);\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  I2CAddress = SlaveAddress.I2CDeviceAddress;\r
+\r
+  Status = InitializeInternal (AddrMode);\r
+  if (!EFI_ERROR(Status)) {\r
+    Status = ReadByte (I2CAddress, (UINT8 *) Buffer);\r
+  }\r
+  I2cCommonServiceExit (SaveCmd, SaveBar0);\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  The I2cWriteMultipleByte() function is a wrapper function for the\r
+  WriteMultipleByte() function. Provides a standard way to execute multiple\r
+  byte writes to an I2C device (e.g. when accessing sub-addresses or writing\r
+  block of data), as defined in the I2C Specification.\r
+\r
+  @param SlaveAddress The I2C slave address of the device\r
+                      with which to communicate.\r
+\r
+  @param AddrMode     I2C Addressing Mode: 7-bit or 10-bit address.\r
+\r
+  @param Length       No. of bytes to be written.\r
+\r
+  @param Buffer       Contains the value of byte to be written to the\r
+                      I2C slave device.\r
+\r
+  @retval EFI_SUCCESS            Transfer success.\r
+  @retval EFI_INVALID_PARAMETER  This, Length or Buffer pointers are invalid.\r
+  @retval EFI_UNSUPPORTED        Unsupported input param.\r
+  @retval EFI_TIMEOUT            Timeout while waiting xfer.\r
+  @retval EFI_ABORTED            Controller aborted xfer.\r
+  @retval EFI_DEVICE_ERROR       Device error detected by controller.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+I2cWriteMultipleByte (\r
+  IN        EFI_I2C_DEVICE_ADDRESS  SlaveAddress,\r
+  IN        EFI_I2C_ADDR_MODE       AddrMode,\r
+  IN UINTN                          *Length,\r
+  IN OUT    VOID                    *Buffer\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+  UINTN      I2CAddress;\r
+  UINT16     SaveCmd;\r
+  UINT32     SaveBar0;\r
+\r
+    if (Buffer == NULL || Length == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  SaveCmd = 0;\r
+  SaveBar0 =0;\r
+\r
+  I2cCommonServiceEntry (&SaveCmd, &SaveBar0);\r
+  Status = EFI_SUCCESS;\r
+\r
+  I2CAddress = SlaveAddress.I2CDeviceAddress;\r
+\r
+  Status = InitializeInternal (AddrMode);\r
+  if (!EFI_ERROR(Status)) {\r
+    Status = WriteMultipleByte (I2CAddress, Buffer, (*Length));\r
+  }\r
+\r
+  I2cCommonServiceExit (SaveCmd, SaveBar0);\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  The I2cReadMultipleByte() function is a wrapper function for the ReadMultipleByte() function.\r
+  Provides a standard way to execute multiple byte writes to an I2C device\r
+  (e.g. when accessing sub-addresses or when reading block of data), as defined\r
+  in the I2C Specification (I2C combined write/read protocol).\r
+\r
+  @param SlaveAddress The I2C slave address of the device\r
+                      with which to communicate.\r
+\r
+  @param AddrMode     I2C Addressing Mode: 7-bit or 10-bit address.\r
+\r
+  @param WriteLength  No. of bytes to be written. In this case data\r
+                      written typically contains sub-address or sub-addresses\r
+                      in Hi-Lo format, that need to be read (I2C combined\r
+                      write/read protocol).\r
+\r
+  @param ReadLength   No. of bytes to be read from I2C slave device.\r
+\r
+  @param Buffer       Contains the value of byte data read from the\r
+                      I2C slave device.\r
+\r
+  @retval EFI_SUCCESS            Transfer success.\r
+  @retval EFI_INVALID_PARAMETER  This, WriteLength, ReadLength or Buffer\r
+                                 pointers are invalid.\r
+  @retval EFI_UNSUPPORTED        Unsupported input param.\r
+  @retval EFI_TIMEOUT            Timeout while waiting xfer.\r
+  @retval EFI_ABORTED            Controller aborted xfer.\r
+  @retval EFI_DEVICE_ERROR       Device error detected by controller.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+I2cReadMultipleByte (\r
+  IN        EFI_I2C_DEVICE_ADDRESS  SlaveAddress,\r
+  IN        EFI_I2C_ADDR_MODE       AddrMode,\r
+  IN UINTN                          *WriteLength,\r
+  IN UINTN                          *ReadLength,\r
+  IN OUT    VOID                    *Buffer\r
+  )\r
+{\r
+  EFI_STATUS        Status;\r
+  UINTN             I2CAddress;\r
+  UINT16            SaveCmd;\r
+  UINT32            SaveBar0;\r
+\r
+  if (Buffer == NULL || WriteLength == NULL || ReadLength == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  SaveCmd = 0;\r
+  SaveBar0 =0;\r
+\r
+  I2cCommonServiceEntry (&SaveCmd, &SaveBar0);\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  I2CAddress = SlaveAddress.I2CDeviceAddress;\r
+  Status = InitializeInternal (AddrMode);\r
+  if (!EFI_ERROR(Status)) {\r
+    Status = ReadMultipleByte (I2CAddress, Buffer, (*WriteLength), (*ReadLength));\r
+  }\r
+  I2cCommonServiceExit (SaveCmd, SaveBar0);\r
+  return Status;\r
+}\r
+\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Library/I2cLib/I2cLib.inf b/QuarkSocPkg/QuarkSouthCluster/Library/I2cLib/I2cLib.inf
new file mode 100644 (file)
index 0000000..8251756
--- /dev/null
@@ -0,0 +1,68 @@
+## @file\r
+# Component description file for Quark South Cluster I2C library.\r
+#\r
+# I2C library implement QuarkSCSocId related drivers, includes:\r
+# PciHostBridge, PciExpress, SmmAccess driver and LegacyRegion driver.\r
+#\r
+# This driver contains I2C bus access routines:\r
+# 1. I2C Read (byte, multi-byte)\r
+# 2. I2C Write (byte, multi-byte)\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = I2cLib\r
+  FILE_GUID                      = 462d127a-c143-469e-8449-b6e36beb04a8\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = I2cLib\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  CommonHeader.h\r
+  I2cLib.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+  IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  PcdLib\r
+  PciLib\r
+  BaseMemoryLib\r
+  MemoryAllocationLib\r
+  DebugLib\r
+  BaseLib\r
+  TimerLib\r
+  IoLib\r
+  IohLib\r
+\r
+[FeaturePcd]\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdI2CFastModeEnabled\r
+\r
+[FixedPcd]\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohI2cMmioBase\r
+\r
+[Pcd]\r
+\r
+[Depex]\r
+  TRUE\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Library/IohLib/CommonHeader.h b/QuarkSocPkg/QuarkSouthCluster/Library/IohLib/CommonHeader.h
new file mode 100644 (file)
index 0000000..9f4c6f2
--- /dev/null
@@ -0,0 +1,35 @@
+/** @file\r
+Common header file shared by all source files.\r
+\r
+This file includes package header files, library classes and protocol, PPI & GUID definitions.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#ifndef __COMMON_HEADER_H_\r
+#define __COMMON_HEADER_H_\r
+\r
+#include <PiPei.h>\r
+#include <Ioh.h>\r
+#include <IohCommonDefinitions.h>\r
+\r
+#include <Library/IohLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/CpuLib.h>\r
+#include <Library/PciCf8Lib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PciLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <IndustryStandard/Pci22.h>\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Library/IohLib/IohLib.c b/QuarkSocPkg/QuarkSouthCluster/Library/IohLib/IohLib.c
new file mode 100644 (file)
index 0000000..a48a2a4
--- /dev/null
@@ -0,0 +1,105 @@
+/** @file\r
+Lib function for Pei Quark South Cluster.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include "CommonHeader.h"\r
+\r
+/**\r
+  Program SVID/SID the same as VID/DID*\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeIohSsvidSsid (\r
+   IN UINT8   Bus,\r
+   IN UINT8   Device,\r
+   IN UINT8   Func\r
+   )\r
+{\r
+  UINTN       Index;\r
+\r
+  for (Index = 0; Index <= IOH_PCI_IOSF2AHB_0_MAX_FUNCS; Index++) {\r
+    if (((Device == IOH_PCI_IOSF2AHB_1_DEV_NUM) && (Index >= IOH_PCI_IOSF2AHB_1_MAX_FUNCS))) {\r
+      continue;\r
+    }\r
+\r
+    IohMmPci32(0, Bus, Device, Index, PCI_REG_SVID0) = IohMmPci32(0, Bus, Device, Index, PCI_REG_VID);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/* Enable memory, io, and bus master for USB controller */\r
+VOID\r
+EFIAPI\r
+EnableUsbMemIoBusMaster (\r
+  IN UINT8   UsbBusNumber\r
+  )\r
+{\r
+  UINT16 CmdReg;\r
+\r
+  CmdReg = PciRead16 (PCI_LIB_ADDRESS (UsbBusNumber, IOH_USB_OHCI_DEVICE_NUMBER, IOH_OHCI_FUNCTION_NUMBER, PCI_REG_PCICMD));\r
+  CmdReg = (UINT16) (CmdReg | EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_IO_SPACE | EFI_PCI_COMMAND_BUS_MASTER);\r
+  PciWrite16 (PCI_LIB_ADDRESS (UsbBusNumber, IOH_USB_OHCI_DEVICE_NUMBER, IOH_OHCI_FUNCTION_NUMBER, PCI_REG_PCICMD), CmdReg);\r
+\r
+  CmdReg = PciRead16 (PCI_LIB_ADDRESS (UsbBusNumber, IOH_USB_EHCI_DEVICE_NUMBER, IOH_EHCI_FUNCTION_NUMBER, PCI_REG_PCICMD));\r
+  CmdReg = (UINT16) (CmdReg | EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_IO_SPACE | EFI_PCI_COMMAND_BUS_MASTER);\r
+  PciWrite16 (PCI_LIB_ADDRESS (UsbBusNumber, IOH_USB_EHCI_DEVICE_NUMBER, IOH_EHCI_FUNCTION_NUMBER, PCI_REG_PCICMD), CmdReg);\r
+}\r
+\r
+/**\r
+  Read south cluster GPIO input from Port A.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+ReadIohGpioValues (\r
+  VOID\r
+  )\r
+{\r
+  UINT32  GipData;\r
+  UINT32  GipAddr;\r
+  UINT32  TempBarAddr;\r
+  UINT16  SaveCmdReg;\r
+  UINT32  SaveBarReg;\r
+\r
+  TempBarAddr = (UINT32) PcdGet64(PcdIohGpioMmioBase);\r
+\r
+  GipAddr = PCI_LIB_ADDRESS(\r
+      PcdGet8 (PcdIohGpioBusNumber),\r
+      PcdGet8 (PcdIohGpioDevNumber),\r
+      PcdGet8 (PcdIohGpioFunctionNumber), 0);\r
+\r
+  //\r
+  // Save current settings for PCI CMD/BAR registers.\r
+  //\r
+  SaveCmdReg = PciRead16 (GipAddr + PCI_COMMAND_OFFSET);\r
+  SaveBarReg = PciRead32 (GipAddr + PcdGet8 (PcdIohGpioBarRegister));\r
+\r
+  DEBUG ((EFI_D_INFO, "SC GPIO temporary enable  at %08X\n", TempBarAddr));\r
+\r
+  // Use predefined tempory memory resource.\r
+  PciWrite32 ( GipAddr + PcdGet8 (PcdIohGpioBarRegister), TempBarAddr);\r
+  PciWrite8 ( GipAddr + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);\r
+\r
+  // Read GPIO configuration\r
+  GipData = MmioRead32(TempBarAddr + GPIO_EXT_PORTA);\r
+\r
+  //\r
+  // Restore settings for PCI CMD/BAR registers.\r
+  //\r
+  PciWrite32 ((GipAddr + PcdGet8 (PcdIohGpioBarRegister)), SaveBarReg);\r
+  PciWrite16 (GipAddr + PCI_COMMAND_OFFSET, SaveCmdReg);\r
+\r
+  // Only 8 bits valid.\r
+  return GipData & 0x000000FF;\r
+}\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Library/IohLib/IohLib.inf b/QuarkSocPkg/QuarkSouthCluster/Library/IohLib/IohLib.inf
new file mode 100644 (file)
index 0000000..eb7a4cb
--- /dev/null
@@ -0,0 +1,55 @@
+## @file\r
+# Intel Soc Library Instance\r
+#\r
+# Intel Soc Library Instance\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = IohLib\r
+  FILE_GUID                      = B4C12297-7B19-4523-B165-81374D96716B\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = IohLib\r
+\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  IohLib.c\r
+  CommonHeader.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  DebugLib\r
+  PciLib\r
+  IoLib\r
+  PciCf8Lib\r
+  BaseLib\r
+  CpuLib\r
+\r
+[Pcd]\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohGpioBusNumber\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohGpioBusNumber\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohGpioDevNumber\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohGpioFunctionNumber\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohGpioBarRegister\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdIohGpioMmioBase\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/ComponentName.c b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/ComponentName.c
new file mode 100644 (file)
index 0000000..6cc80d3
--- /dev/null
@@ -0,0 +1,233 @@
+/** @file\r
+\r
+UEFI Component Name(2) protocol implementation for SD controller driver.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "SDController.h"\r
+\r
+\r
+//\r
+// EFI Component Name Protocol\r
+//\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  gSDControllerName = {\r
+  SDControllerGetDriverName,\r
+  SDControllerGetControllerName,\r
+  "eng"\r
+};\r
+\r
+//\r
+// EFI Component Name 2 Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gSDControllerName2 = {\r
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) SDControllerGetDriverName,\r
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) SDControllerGetControllerName,\r
+  "en"\r
+};\r
+\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSDControllerDriverNameTable[] = {\r
+  { "eng;en", L"EFI SD Host Controller Driver" },\r
+  { NULL, NULL }\r
+};\r
+\r
+\r
+//\r
+// EFI Component Name Functions\r
+//\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+  This function retrieves the user readable name of a driver in the form of a\r
+  Unicode string. If the driver specified by This has a user readable name in\r
+  the language specified by Language, then a pointer to the driver name is\r
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+  by This does not support the language specified by Language,\r
+  then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language. This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified\r
+                                in RFC 3066 or ISO 639-2 language code format.\r
+\r
+  @param  DriverName[out]       A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                driver specified by This in the language\r
+                                specified by Language.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by\r
+                                This and the language specified by Language was\r
+                                returned in DriverName.\r
+\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SDControllerGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **DriverName\r
+  )\r
+{\r
+  return LookupUnicodeString2 (\r
+           Language,\r
+           This->SupportedLanguages,\r
+           mSDControllerDriverNameTable,\r
+           DriverName,\r
+           (BOOLEAN)(This == &gSDControllerName)\r
+           );\r
+}\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the controller\r
+  that is being managed by a driver.\r
+\r
+  This function retrieves the user readable name of the controller specified by\r
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+  driver specified by This has a user readable name in the language specified by\r
+  Language, then a pointer to the controller name is returned in ControllerName,\r
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently\r
+  managing the controller specified by ControllerHandle and ChildHandle,\r
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not\r
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  ControllerHandle[in]  The handle of a controller that the driver\r
+                                specified by This is managing.  This handle\r
+                                specifies the controller whose name is to be\r
+                                returned.\r
+\r
+  @param  ChildHandle[in]       The handle of the child controller to retrieve\r
+                                the name of.  This is an optional parameter that\r
+                                may be NULL.  It will be NULL for device\r
+                                drivers.  It will also be NULL for a bus drivers\r
+                                that wish to retrieve the name of the bus\r
+                                controller.  It will not be NULL for a bus\r
+                                driver that wishes to retrieve the name of a\r
+                                child controller.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language.  This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified in\r
+                                RFC 3066 or ISO 639-2 language code format.\r
+\r
+  @param  ControllerName[out]   A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                controller specified by ControllerHandle and\r
+                                ChildHandle in the language specified by\r
+                                Language from the point of view of the driver\r
+                                specified by This.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in\r
+                                the language specified by Language for the\r
+                                driver specified by This was returned in\r
+                                DriverName.\r
+\r
+  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+\r
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+                                EFI_HANDLE.\r
+\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently\r
+                                managing the controller specified by\r
+                                ControllerHandle and ChildHandle.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SDControllerGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,\r
+  IN  EFI_HANDLE                                      ControllerHandle,\r
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,\r
+  IN  CHAR8                                           *Language,\r
+  OUT CHAR16                                          **ControllerName\r
+  )\r
+{\r
+  EFI_STATUS           Status;\r
+  EFI_SD_HOST_IO_PROTOCOL  *SDHostIo;\r
+  SDHOST_DATA              *SDHostData;\r
+\r
+  //\r
+  // This is a device driver, so ChildHandle must be NULL.\r
+  //\r
+  if (ChildHandle != NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Make sure this driver is currently managing ControllerHandle\r
+  //\r
+  Status = EfiTestManagedDevice (\r
+             ControllerHandle,\r
+             gSDControllerDriverBinding.DriverBindingHandle,\r
+             &gEfiPciIoProtocolGuid\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get the device context\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiSDHostIoProtocolGuid,\r
+                  (VOID **) &SDHostIo,\r
+                  gSDControllerDriverBinding.DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  SDHostData  = SDHOST_DATA_FROM_THIS(SDHostIo);\r
+\r
+  return LookupUnicodeString2 (\r
+           Language,\r
+           This->SupportedLanguages,\r
+           SDHostData->ControllerNameTable,\r
+           ControllerName,\r
+           (BOOLEAN)(This == &gSDControllerName)\r
+           );\r
+\r
+}\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/ComponentName.h b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/ComponentName.h
new file mode 100644 (file)
index 0000000..afb690f
--- /dev/null
@@ -0,0 +1,147 @@
+/** @file\r
+\r
+This file contains the delarations for componet name routines.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#ifndef _COMPONENT_NAME_H_\r
+#define _COMPONENT_NAME_H_\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+  This function retrieves the user readable name of a driver in the form of a\r
+  Unicode string. If the driver specified by This has a user readable name in\r
+  the language specified by Language, then a pointer to the driver name is\r
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+  by This does not support the language specified by Language,\r
+  then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language. This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified\r
+                                in RFC 3066 or ISO 639-2 language code format.\r
+\r
+  @param  DriverName[out]       A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                driver specified by This in the language\r
+                                specified by Language.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by\r
+                                This and the language specified by Language was\r
+                                returned in DriverName.\r
+\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SDControllerGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **DriverName\r
+  );\r
+\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the controller\r
+  that is being managed by a driver.\r
+\r
+  This function retrieves the user readable name of the controller specified by\r
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+  driver specified by This has a user readable name in the language specified by\r
+  Language, then a pointer to the controller name is returned in ControllerName,\r
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently\r
+  managing the controller specified by ControllerHandle and ChildHandle,\r
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not\r
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  ControllerHandle[in]  The handle of a controller that the driver\r
+                                specified by This is managing.  This handle\r
+                                specifies the controller whose name is to be\r
+                                returned.\r
+\r
+  @param  ChildHandle[in]       The handle of the child controller to retrieve\r
+                                the name of.  This is an optional parameter that\r
+                                may be NULL.  It will be NULL for device\r
+                                drivers.  It will also be NULL for a bus drivers\r
+                                that wish to retrieve the name of the bus\r
+                                controller.  It will not be NULL for a bus\r
+                                driver that wishes to retrieve the name of a\r
+                                child controller.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language.  This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified in\r
+                                RFC 3066 or ISO 639-2 language code format.\r
+\r
+  @param  ControllerName[out]   A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                controller specified by ControllerHandle and\r
+                                ChildHandle in the language specified by\r
+                                Language from the point of view of the driver\r
+                                specified by This.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in\r
+                                the language specified by Language for the\r
+                                driver specified by This was returned in\r
+                                DriverName.\r
+\r
+  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+\r
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+                                EFI_HANDLE.\r
+\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently\r
+                                managing the controller specified by\r
+                                ControllerHandle and ChildHandle.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SDControllerGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,\r
+  IN  EFI_HANDLE                                      ControllerHandle,\r
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,\r
+  IN  CHAR8                                           *Language,\r
+  OUT CHAR16                                          **ControllerName\r
+  );\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDController.c b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDController.c
new file mode 100644 (file)
index 0000000..18e85c8
--- /dev/null
@@ -0,0 +1,1789 @@
+/** @file\r
+\r
+The SD host controller driver model and HC protocol routines.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+\r
+#include "SDController.h"\r
+\r
+\r
+EFI_DRIVER_BINDING_PROTOCOL gSDControllerDriverBinding = {\r
+  SDControllerSupported,\r
+  SDControllerStart,\r
+  SDControllerStop,\r
+  0x20,\r
+  NULL,\r
+  NULL\r
+};\r
+\r
+\r
+EFI_SD_HOST_IO_PROTOCOL  mSDHostIo = {\r
+  EFI_SD_HOST_IO_PROTOCOL_REVISION_01,\r
+  {\r
+    0, // HighSpeedSupport\r
+    0, // V18Support\r
+    0, // V30Support\r
+    0, // V33Support\r
+    0, // Reserved0\r
+    0, // BusWidth4\r
+    0, // BusWidth8\r
+    0, // Reserved1\r
+    0, // Reserved1\r
+    (512 * 1024) //BoundarySize\r
+  },\r
+  SendCommand,\r
+  SetClockFrequency,\r
+  SetBusWidth,\r
+  SetHostVoltage,\r
+  ResetSDHost,\r
+  EnableAutoStopCmd,\r
+  DetectCardAndInitHost,\r
+  SetBlockLength,\r
+  SetHighSpeedMode,\r
+  SetDDRMode\r
+};\r
+\r
+/**\r
+  Find sdclk_freq_sel and upr_sdclk_freq_sel bits\r
+  for Clock Control Register (CLK_CTL)Offset 2Ch when using 8bit or 10bit\r
+  divided clock mode.\r
+\r
+  @param  BaseClockFreg        Base Clock Frequency in Hz For SD Clock in the\r
+                               Capabilities register.\r
+  @param  TargetFreq           Target Frequency in Hz to reach.\r
+  @param  Is8BitMode           True if 8-bit Divided Clock Mode else 10bit mode.\r
+  @param  Bits                 sdclk_freq_sel and upr_sdclk_freq_sel bits for\r
+                               TargetFreq.\r
+\r
+  @return EFI_SUCCESS          // Bits setup.\r
+  @return EFI_UNSUPPORTED      // Cannot divide base clock to reach target clock.\r
+**/\r
+EFI_STATUS\r
+DividedClockModeBits (\r
+  IN CONST UINTN                          BaseClockFreg,\r
+  IN CONST UINTN                          TargetFreq,\r
+  IN CONST BOOLEAN                        Is8BitMode,\r
+  OUT UINT16                              *Bits\r
+  )\r
+{\r
+  UINTN                             N;\r
+  UINTN                             CurrFreq;\r
+\r
+ *Bits = 0;\r
+  CurrFreq = BaseClockFreg;\r
+  N = 0;\r
+  //\r
+  // N == 0 same for 8bit & 10bit mode i.e. BaseClockFreg of controller.\r
+  //\r
+  if (TargetFreq < CurrFreq) {\r
+    if (Is8BitMode) {\r
+      N = 1;\r
+      do {\r
+        //\r
+        // N values for 8bit mode when N > 0.\r
+        //  Bit[15:8] SDCLK Frequency Select at offset 2Ch\r
+        //    80h - base clock divided by 256\r
+        //    40h - base clock divided by 128\r
+        //    20h - base clock divided by 64\r
+        //    10h - base clock divided by 32\r
+        //    08h - base clock divided by 16\r
+        //    04h - base clock divided by 8\r
+        //    02h - base clock divided by 4\r
+        //    01h - base clock divided by 2\r
+        //\r
+        CurrFreq = BaseClockFreg / (2 * N);\r
+        if (TargetFreq >= CurrFreq) {\r
+          break;\r
+        }\r
+        N *= 2;\r
+        if (N > V_MMIO_CLKCTL_MAX_8BIT_FREQ_SEL) {\r
+          return EFI_UNSUPPORTED;\r
+        }\r
+      } while (TRUE);\r
+    } else {\r
+      N = 1;\r
+      CurrFreq = BaseClockFreg / (2 * N);\r
+      //\r
+      // (try N = 0 or 1 first since don't want divide by 0).\r
+      //\r
+      if (TargetFreq < CurrFreq) {\r
+        //\r
+        // If still no match then calculate it for 10bit.\r
+        // N values for 10bit mode.\r
+        // N 1/2N Divided Clock (Duty 50%).\r
+        // from Spec "The length of divider is extended to 10 bits and all\r
+        // divider values shall be supported.\r
+        //\r
+        N = (BaseClockFreg / TargetFreq) / 2;\r
+\r
+        //\r
+        // Can only be N or N+1;\r
+        //\r
+        CurrFreq = BaseClockFreg / (2 * N);\r
+        if (TargetFreq < CurrFreq) {\r
+          N++;\r
+          CurrFreq = BaseClockFreg / (2 * N);\r
+        }\r
+\r
+        if (N > V_MMIO_CLKCTL_MAX_10BIT_FREQ_SEL) {\r
+          return EFI_UNSUPPORTED;\r
+        }\r
+\r
+        //\r
+        // Set upper bits of SDCLK Frequency Select (bits 7:6 of reg 0x2c).\r
+        //\r
+        *Bits |= ((UINT16) ((N >> 2) & B_MMIO_CLKCTL_UPR_SDCLK_FREQ_SEL_MASK));\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Set lower bits of SDCLK Frequency Select (bits 15:8 of reg 0x2c).\r
+  //\r
+  *Bits |= ((UINT16) ((UINT8) N) << 8);\r
+  DEBUG (\r
+    (EFI_D_INFO,\r
+    "SDIO:DividedClockModeBits: %dbit mode Want %dHz Got %dHz bits = %04x\r\n",\r
+    (Is8BitMode) ? 8 : 10,\r
+    TargetFreq,\r
+    CurrFreq,\r
+    (UINTN) *Bits\r
+     ));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Print type of error and command index\r
+\r
+  @param  CommandIndex         Command index to set the command index field of command register.\r
+  @param  ErrorCode            Error interrupt status read from host controller\r
+\r
+  @return EFI_DEVICE_ERROR\r
+  @return EFI_TIMEOUT\r
+  @return EFI_CRC_ERROR\r
+\r
+**/\r
+EFI_STATUS\r
+GetErrorReason (\r
+  IN  UINT16    CommandIndex,\r
+  IN  UINT16    ErrorCode\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+\r
+  Status = EFI_DEVICE_ERROR;\r
+\r
+  DEBUG((EFI_D_ERROR, "[%2d] -- ", CommandIndex));\r
+\r
+  if (ErrorCode & BIT0) {\r
+    Status = EFI_TIMEOUT;\r
+    DEBUG((EFI_D_ERROR, "Command Timeout Erro"));\r
+  }\r
+\r
+  if (ErrorCode & BIT1) {\r
+    Status = EFI_CRC_ERROR;\r
+    DEBUG((EFI_D_ERROR, "Command CRC Error"));\r
+  }\r
+\r
+  if (ErrorCode & BIT2) {\r
+    DEBUG((EFI_D_ERROR, "Command End Bit Error"));\r
+  }\r
+\r
+  if (ErrorCode & BIT3) {\r
+    DEBUG((EFI_D_ERROR, "Command Index Error"));\r
+  }\r
+  if (ErrorCode & BIT4) {\r
+    Status = EFI_TIMEOUT;\r
+    DEBUG((EFI_D_ERROR, "Data Timeout Error"));\r
+  }\r
+\r
+  if (ErrorCode & BIT5) {\r
+    Status = EFI_CRC_ERROR;\r
+    DEBUG((EFI_D_ERROR, "Data CRC Error"));\r
+  }\r
+\r
+  if (ErrorCode & BIT6) {\r
+    DEBUG((EFI_D_ERROR, "Data End Bit Error"));\r
+  }\r
+\r
+  if (ErrorCode & BIT7) {\r
+    DEBUG((EFI_D_ERROR, "Current Limit Error"));\r
+  }\r
+\r
+  if (ErrorCode & BIT8) {\r
+    DEBUG((EFI_D_ERROR, "Auto CMD12 Error"));\r
+  }\r
+\r
+  if (ErrorCode & BIT9) {\r
+    DEBUG((EFI_D_ERROR, "ADMA Error"));\r
+  }\r
+\r
+  DEBUG((EFI_D_ERROR, "\n"));\r
+\r
+  return Status;\r
+}\r
+/**\r
+  Enable/Disable High Speed transfer mode\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  Enable                TRUE to Enable, FALSE to Disable\r
+\r
+  @return EFI_SUCCESS\r
+**/\r
+EFI_STATUS\r
+SetHighSpeedMode (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  BOOLEAN                    Enable\r
+  )\r
+{\r
+  UINT32                 Data;\r
+  SDHOST_DATA            *SDHostData;\r
+  EFI_PCI_IO_PROTOCOL    *PciIo;\r
+\r
+  SDHostData = SDHOST_DATA_FROM_THIS (This);\r
+  PciIo      = SDHostData->PciIo;\r
+\r
+  PciIo->Mem.Read (\r
+               PciIo,\r
+               EfiPciIoWidthUint8,\r
+               0,\r
+               (UINT64)MMIO_HOSTCTL,\r
+               1,\r
+               &Data\r
+               );\r
+\r
+  if (Enable) {\r
+    if (PcdGetBool(PcdSdHciQuirkNoHiSpd)) {\r
+      DEBUG ((EFI_D_INFO, "SDIO: Quirk never set High Speed Enable bit\r\n"));\r
+      return EFI_SUCCESS;\r
+    }\r
+    DEBUG ((EFI_D_INFO, "Enable High Speed transfer mode ... \r\n"));\r
+    Data |= BIT2;\r
+  } else {\r
+    Data &= ~BIT2;\r
+  }\r
+  PciIo->Mem.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint8,\r
+               0,\r
+              (UINT64)MMIO_HOSTCTL,\r
+               1,\r
+               &Data\r
+              );\r
+  return EFI_SUCCESS;\r
+}\r
+EFI_STATUS\r
+EFIAPI\r
+SetDDRMode (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  BOOLEAN                    Enable\r
+  )\r
+{\r
+  UINT16                 Data;\r
+  SDHOST_DATA            *SDHostData;\r
+  EFI_PCI_IO_PROTOCOL    *PciIo;\r
+  SDHostData = SDHOST_DATA_FROM_THIS (This);\r
+  PciIo      = SDHostData->PciIo;\r
+  PciIo->Mem.Read (\r
+               PciIo,\r
+               EfiPciIoWidthUint16,\r
+               0,\r
+               (UINT64)MMIO_HOSTCTL2,\r
+               1,\r
+               &Data\r
+               );\r
+  Data &= 0xFFF0;\r
+  if (Enable) {\r
+    Data |= 0x0004; // Enable DDR50 by default, later should enable other mode like HS200/400\r
+    Data |= BIT3;   // Enable 1.8V Signaling\r
+  }\r
+  PciIo->Mem.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint16,\r
+               0,\r
+              (UINT64)MMIO_HOSTCTL2,\r
+               1,\r
+               &Data\r
+              );\r
+  return EFI_SUCCESS;\r
+}\r
+/**\r
+  Power on/off the LED associated with the slot\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  Enable                TRUE to set LED on, FALSE to set LED off\r
+\r
+  @return EFI_SUCCESS\r
+**/\r
+EFI_STATUS\r
+HostLEDEnable (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  BOOLEAN                    Enable\r
+  )\r
+{\r
+  SDHOST_DATA            *SDHostData;\r
+  EFI_PCI_IO_PROTOCOL    *PciIo;\r
+  UINT32                 Data;\r
+\r
+  SDHostData = SDHOST_DATA_FROM_THIS (This);\r
+  PciIo      = SDHostData->PciIo;\r
+\r
+  PciIo->Mem.Read (\r
+               PciIo,\r
+               EfiPciIoWidthUint8,\r
+               0,\r
+               (UINT64)MMIO_HOSTCTL,\r
+               1,\r
+               &Data\r
+               );\r
+\r
+  if (Enable) {\r
+    //\r
+    //LED On\r
+    //\r
+    Data |= BIT0;\r
+  } else {\r
+    //\r
+    //LED Off\r
+    //\r
+    Data &= ~BIT0;\r
+  }\r
+\r
+  PciIo->Mem.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint8,\r
+               0,\r
+               (UINT64)MMIO_HOSTCTL,\r
+               1,\r
+               &Data\r
+               );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  The main function used to send the command to the card inserted into the SD host slot.\r
+  It will assemble the arguments to set the command register and wait for the command\r
+  and transfer completed until timeout. Then it will read the response register to fill\r
+  the ResponseData.\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  CommandIndex          The command index to set the command index field of command register.\r
+  @param  Argument              Command argument to set the argument field of command register.\r
+  @param  DataType              TRANSFER_TYPE, indicates no data, data in or data out.\r
+  @param  Buffer                Contains the data read from / write to the device.\r
+  @param  BufferSize            The size of the buffer.\r
+  @param  ResponseType          RESPONSE_TYPE.\r
+  @param  TimeOut               Time out value in 1 ms unit.\r
+  @param  ResponseData          Depending on the ResponseType, such as CSD or card status.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_INVALID_PARAMETER\r
+  @retval EFI_OUT_OF_RESOURCES\r
+  @retval EFI_TIMEOUT\r
+  @retval EFI_DEVICE_ERROR\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SendCommand (\r
+  IN   EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN   UINT16                     CommandIndex,\r
+  IN   UINT32                     Argument,\r
+  IN   TRANSFER_TYPE              DataType,\r
+  IN   UINT8                      *Buffer, OPTIONAL\r
+  IN   UINT32                     BufferSize,\r
+  IN   RESPONSE_TYPE              ResponseType,\r
+  IN   UINT32                     TimeOut,\r
+  OUT  UINT32                     *ResponseData OPTIONAL\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    The main function used to send the command to the card inserted into the SD host\r
+    slot.\r
+    It will assemble the arguments to set the command register and wait for the command\r
+    and transfer completed until timeout. Then it will read the response register to fill\r
+    the ResponseData\r
+\r
+  Arguments:\r
+    This           - Pointer to EFI_SD_HOST_IO_PROTOCOL\r
+    CommandIndex   - The command index to set the command index field of command register\r
+    Argument       - Command argument to set the argument field of command register\r
+    DataType       - TRANSFER_TYPE, indicates no data, data in or data out\r
+    Buffer         - Contains the data read from / write to the device\r
+    BufferSize     - The size of the buffer\r
+    ResponseType   - RESPONSE_TYPE\r
+    TimeOut        - Time out value in 1 ms unit\r
+    ResponseData   - Depending on the ResponseType, such as CSD or card status\r
+\r
+  Returns:\r
+    EFI_SUCCESS\r
+    EFI_INVALID_PARAMETER\r
+    EFI_OUT_OF_RESOURCES\r
+    EFI_TIMEOUT\r
+    EFI_DEVICE_ERROR\r
+\r
+--*/\r
+{\r
+  EFI_STATUS            Status;\r
+  SDHOST_DATA           *SDHostData;\r
+  EFI_PCI_IO_PROTOCOL   *PciIo;\r
+  UINT32                ResponseDataCount;\r
+  UINT32                Data;\r
+  UINT64                Data64;\r
+  UINT8                 Index;\r
+  INTN                  TimeOut2;\r
+  BOOLEAN               AutoCMD12Enable = FALSE;\r
+\r
+\r
+  Status             = EFI_SUCCESS;\r
+  ResponseDataCount  = 1;\r
+  SDHostData         = SDHOST_DATA_FROM_THIS (This);\r
+  PciIo              = SDHostData->PciIo;\r
+  AutoCMD12Enable    =  (CommandIndex & AUTO_CMD12_ENABLE) ? TRUE : FALSE;\r
+  CommandIndex       = CommandIndex & CMD_INDEX_MASK;\r
+\r
+  if (Buffer != NULL && DataType == NoData) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n"));\r
+    goto Exit;\r
+  }\r
+\r
+  if (((UINTN)Buffer & (This->HostCapability.BoundarySize - 1)) != (UINTN)NULL) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n"));\r
+    goto Exit;\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "SendCommand: Command Index = %d \r\n", CommandIndex));\r
+  //\r
+  TimeOut2 = 1000; // 10 ms\r
+  do {\r
+    PciIo->Mem.Read (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 0,\r
+                 (UINT64)MMIO_PSTATE,\r
+                 1,\r
+                 &Data\r
+                 );\r
+     gBS->Stall (10);\r
+  }while ((TimeOut2-- > 0) && (Data & BIT0));\r
+  TimeOut2 = 1000; // 10 ms\r
+  do {\r
+    PciIo->Mem.Read (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 0,\r
+                 (UINT64)MMIO_PSTATE,\r
+                 1,\r
+                 &Data\r
+                 );\r
+    gBS->Stall (10);\r
+  }while ((TimeOut2-- > 0) && (Data & BIT1));\r
+  //Clear status bits\r
+  //\r
+  Data = 0xFFFF;\r
+  PciIo->Mem.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint16,\r
+               0,\r
+               (UINT64)MMIO_NINTSTS,\r
+               1,\r
+               &Data\r
+               );\r
+\r
+  Data = 0xFFFF;\r
+  PciIo->Mem.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint16,\r
+               0,\r
+               (UINT64)MMIO_ERINTSTS,\r
+               1,\r
+               &Data\r
+               );\r
+\r
+\r
+  if (Buffer != NULL) {\r
+     PciIo->Mem.Write (\r
+                  PciIo,\r
+                  EfiPciIoWidthUint32,\r
+                  0,\r
+                  (UINT64)MMIO_DMAADR,\r
+                  1,\r
+                  &Buffer\r
+                  );\r
+\r
+     PciIo->Mem.Read (\r
+                  PciIo,\r
+                  EfiPciIoWidthUint16,\r
+                  0,\r
+                  (UINT64)MMIO_BLKSZ,\r
+                  1,\r
+                  &Data\r
+                  );\r
+     Data &= ~(0xFFF);\r
+     if (BufferSize <= SDHostData->BlockLength) {\r
+       Data |= (BufferSize | 0x7000);\r
+     } else {\r
+       Data |= (SDHostData->BlockLength | 0x7000);\r
+     }\r
+\r
+\r
+     PciIo->Mem.Write (\r
+                  PciIo,\r
+                  EfiPciIoWidthUint16,\r
+                  0,\r
+                  (UINT64)MMIO_BLKSZ,\r
+                  1,\r
+                  &Data\r
+                  );\r
+     if (BufferSize <= SDHostData->BlockLength) {\r
+       Data = 1;\r
+     } else {\r
+       Data = BufferSize / SDHostData->BlockLength;\r
+     }\r
+     PciIo->Mem.Write (\r
+                  PciIo,\r
+                  EfiPciIoWidthUint16,\r
+                  0,\r
+                  (UINT64)MMIO_BLKCNT,\r
+                  1,\r
+                  &Data\r
+                  );\r
+\r
+  } else {\r
+    Data = 0;\r
+    PciIo->Mem.Write (\r
+                  PciIo,\r
+                  EfiPciIoWidthUint16,\r
+                  0,\r
+                  (UINT64)MMIO_BLKSZ,\r
+                  1,\r
+                  &Data\r
+                  );\r
+    PciIo->Mem.Write (\r
+                  PciIo,\r
+                  EfiPciIoWidthUint16,\r
+                  0,\r
+                  (UINT64)MMIO_BLKCNT,\r
+                  1,\r
+                  &Data\r
+                  );\r
+  }\r
+\r
+  //\r
+  //Argument\r
+  //\r
+  Data = Argument;\r
+  PciIo->Mem.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint32,\r
+               0,\r
+               (UINT64)MMIO_CMDARG,\r
+               1,\r
+               &Data\r
+               );\r
+\r
+\r
+  PciIo->Mem.Read (\r
+               PciIo,\r
+               EfiPciIoWidthUint16,\r
+               0,\r
+               (UINT64)MMIO_XFRMODE,\r
+               1,\r
+               &Data\r
+               );\r
+\r
+\r
+  DEBUG ((EFI_D_INFO, "Transfer mode read  = 0x%x \r\n", (Data & 0xFFFF)));\r
+  //\r
+  //BIT0 - DMA Enable\r
+  //BIT2 - Auto Cmd12\r
+  //\r
+  if (DataType == InData) {\r
+    Data |= BIT4 | BIT0;\r
+  } else if (DataType == OutData){\r
+    Data &= ~BIT4;\r
+    Data |= BIT0;\r
+  } else {\r
+    Data &= ~(BIT4 | BIT0);\r
+  }\r
+\r
+  if (BufferSize <= SDHostData->BlockLength) {\r
+    Data &= ~ (BIT5 | BIT1 | BIT2);\r
+    Data |= BIT1; // Enable block count always\r
+  } else {\r
+     if (SDHostData->IsAutoStopCmd && AutoCMD12Enable) {\r
+      Data |= (BIT5 | BIT1 | BIT2);\r
+     } else {\r
+      Data |= (BIT5 | BIT1);\r
+     }\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "Transfer mode write = 0x%x \r\n", (Data & 0xffff)));\r
+  PciIo->Mem.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint16,\r
+               0,\r
+               (UINT64)MMIO_XFRMODE,\r
+               1,\r
+               &Data\r
+               );\r
+  //\r
+  //Command\r
+  //\r
+  //ResponseTypeSelect    IndexCheck    CRCCheck    ResponseType\r
+  //  00                     0            0           NoResponse\r
+  //  01                     0            1           R2\r
+  //  10                     0            0           R3, R4\r
+  //  10                     1            1           R1, R5, R6, R7\r
+  //  11                     1            1           R1b, R5b\r
+  //\r
+  switch (ResponseType) {\r
+    case ResponseNo:\r
+      Data = (CommandIndex << 8);\r
+      ResponseDataCount = 0;\r
+      break;\r
+\r
+    case ResponseR1:\r
+    case ResponseR5:\r
+    case ResponseR6:\r
+    case ResponseR7:\r
+      Data = (CommandIndex << 8) | BIT1 | BIT4| BIT3;\r
+      ResponseDataCount = 1;\r
+      break;\r
+\r
+    case ResponseR1b:\r
+    case ResponseR5b:\r
+      Data = (CommandIndex << 8) | BIT0 | BIT1 | BIT4| BIT3;\r
+      ResponseDataCount = 1;\r
+      break;\r
+\r
+    case ResponseR2:\r
+      Data = (CommandIndex << 8) | BIT0 | BIT3;\r
+      ResponseDataCount = 4;\r
+      break;\r
+\r
+    case ResponseR3:\r
+    case ResponseR4:\r
+      Data = (CommandIndex << 8) | BIT1;\r
+      ResponseDataCount = 1;\r
+      break;\r
+\r
+    default:\r
+      ASSERT (0);\r
+      Status = EFI_INVALID_PARAMETER;\r
+      DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n"));\r
+      goto Exit;\r
+  }\r
+\r
+  if (DataType != NoData) {\r
+    Data |= BIT5;\r
+  }\r
+\r
+  HostLEDEnable (This, TRUE);\r
+\r
+\r
+  PciIo->Mem.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint16,\r
+               0,\r
+               (UINT64)MMIO_SDCMD,\r
+               1,\r
+               &Data\r
+               );\r
+\r
+\r
+  Data = 0;\r
+  do {\r
+    PciIo->Mem.Read (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint16,\r
+                 0,\r
+                 (UINT64)MMIO_ERINTSTS,\r
+                 1,\r
+                 &Data\r
+                 );\r
+\r
+    if ((Data & 0x07FF) != 0) {\r
+      Status = GetErrorReason (CommandIndex, (UINT16)Data);\r
+      DEBUG ((EFI_D_ERROR, "SendCommand: Error happens \r\n"));\r
+      goto Exit;\r
+    }\r
+\r
+    PciIo->Mem.Read (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint16,\r
+                 0,\r
+                 (UINT64)MMIO_NINTSTS,\r
+                 1,\r
+                 &Data\r
+                 );\r
+\r
+    if ((Data & BIT0) == BIT0) {\r
+       //\r
+       //Command completed, can read response\r
+       //\r
+       if (DataType == NoData) {\r
+         break;\r
+       } else {\r
+         //\r
+         //Transfer completed\r
+         //\r
+         if ((Data & BIT1) == BIT1) {\r
+           break;\r
+         }\r
+       }\r
+    }\r
+\r
+    gBS->Stall (1 * 1000);\r
+\r
+    TimeOut --;\r
+\r
+  } while (TimeOut > 0);\r
+\r
+  if (TimeOut == 0) {\r
+    Status = EFI_TIMEOUT;\r
+    DEBUG ((EFI_D_ERROR, "SendCommand: Time out \r\n"));\r
+    goto Exit;\r
+  }\r
+\r
+  if (ResponseData != NULL) {\r
+    PciIo->Mem.Read (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 0,\r
+                 (UINT64)MMIO_RESP,\r
+                 ResponseDataCount,\r
+                 ResponseData\r
+                 );\r
+    if (ResponseType == ResponseR2) {\r
+      //\r
+      // Adjustment for R2 response\r
+      //\r
+      Data = 1;\r
+      for (Index = 0; Index < ResponseDataCount; Index++) {\r
+        Data64 = LShiftU64(*ResponseData, 8);\r
+        *ResponseData = (UINT32)((Data64 & 0xFFFFFFFF) | Data);\r
+        Data =  (UINT32)RShiftU64 (Data64, 32);\r
+        ResponseData++;\r
+      }\r
+    }\r
+  }\r
+\r
+Exit:\r
+  HostLEDEnable (This, FALSE);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Set max clock frequency of the host, the actual frequency may not be the same as MaxFrequency.\r
+  It depends on the max frequency the host can support, divider, and host speed mode.\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  MaxFrequency          Max frequency in HZ.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_TIMEOUT\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetClockFrequency (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  UINT32                     MaxFrequency\r
+  )\r
+{\r
+  UINT32                 Data;\r
+  UINT16                 FreqSelBits;\r
+  EFI_STATUS             Status;\r
+  SDHOST_DATA            *SDHostData;\r
+  EFI_PCI_IO_PROTOCOL    *PciIo;\r
+  UINT32                 TimeOutCount;\r
+  UINT32                 Revision;\r
+\r
+  SDHostData = SDHOST_DATA_FROM_THIS (This);\r
+  PciIo      = SDHostData->PciIo;\r
+  Data = 0;\r
+  PciIo->Mem.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint16,\r
+               0,\r
+               (UINT64)MMIO_CLKCTL,\r
+               1,\r
+               &Data\r
+               );\r
+\r
+  PciIo->Mem.Read (\r
+                PciIo,\r
+                EfiPciIoWidthUint8,\r
+                0,\r
+                (UINT64)MMIO_CTRLRVER,\r
+                1,\r
+                &Revision\r
+                );\r
+  Revision &= 0x000000FF;\r
+\r
+  Status = DividedClockModeBits (\r
+             SDHostData->BaseClockInMHz * 1000 * 1000,\r
+             MaxFrequency,\r
+             (Revision < SDHCI_SPEC_300),\r
+             &FreqSelBits\r
+             );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Cannot reach MaxFrequency with SDHostData->BaseClockInMHz.\r
+    //\r
+    ASSERT_EFI_ERROR (Status);\r
+    return Status;\r
+  }\r
+\r
+  Data = 0;\r
+\r
+  //\r
+  //Enable internal clock and Stop Clock Enable\r
+  //\r
+  Data = BIT0;\r
+  PciIo->Mem.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint16,\r
+               0,\r
+               (UINT64)MMIO_CLKCTL,\r
+               1,\r
+               &Data\r
+               );\r
+\r
+  TimeOutCount = TIME_OUT_1S;\r
+  do {\r
+    PciIo->Mem.Read (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint16,\r
+                 0,\r
+                 (UINT64)MMIO_CLKCTL,\r
+                 1,\r
+                 &Data\r
+                 );\r
+    gBS->Stall (1 * 1000);\r
+    TimeOutCount --;\r
+    if (TimeOutCount == 0) {\r
+      DEBUG ((EFI_D_ERROR, "SetClockFrequency: Time out \r\n"));\r
+      return EFI_TIMEOUT;\r
+    }\r
+  } while ((Data & BIT1) != BIT1);\r
+\r
+  DEBUG ((EFI_D_INFO, "Base Clock In MHz: %d\r\n", SDHostData->BaseClockInMHz));\r
+\r
+  Data = (BIT0 | ((UINT32) FreqSelBits));\r
+  DEBUG ((EFI_D_INFO, "Data write to MMIO_CLKCTL: 0x%04x \r\n", Data));\r
+  PciIo->Mem.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint16,\r
+               0,\r
+               (UINT64)MMIO_CLKCTL,\r
+               1,\r
+               &Data\r
+               );\r
+\r
+  TimeOutCount = TIME_OUT_1S;\r
+  do {\r
+    PciIo->Mem.Read (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint16,\r
+                 0,\r
+                 (UINT64)MMIO_CLKCTL,\r
+                 1,\r
+                 &Data\r
+                 );\r
+    gBS->Stall (1 * 1000);\r
+    TimeOutCount --;\r
+    if (TimeOutCount == 0) {\r
+      DEBUG ((EFI_D_ERROR, "SetClockFrequency: Time out \r\n"));\r
+      return EFI_TIMEOUT;\r
+    }\r
+  } while ((Data & BIT1) != BIT1);\r
+  gBS->Stall (20 * 1000);\r
+  Data |= BIT2;\r
+  PciIo->Mem.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint16,\r
+               0,\r
+               (UINT64)MMIO_CLKCTL,\r
+               1,\r
+               &Data\r
+               );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Set bus width of the host controller\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  BusWidth              Bus width in 1, 4, 8 bits.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_INVALID_PARAMETER\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetBusWidth (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  UINT32                     BusWidth\r
+  )\r
+{\r
+  SDHOST_DATA            *SDHostData;\r
+  EFI_PCI_IO_PROTOCOL    *PciIo;\r
+  UINT8                  Data;\r
+\r
+  SDHostData = SDHOST_DATA_FROM_THIS (This);\r
+\r
+\r
+  if ((BusWidth != 1) && (BusWidth != 4) && (BusWidth != 8)) {\r
+    DEBUG ((EFI_D_ERROR, "SetBusWidth: Invalid parameter \r\n"));\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((SDHostData->SDHostIo.HostCapability.BusWidth8 == FALSE) && (BusWidth == 8)) {\r
+     DEBUG ((EFI_D_ERROR, "SetBusWidth: Invalid parameter \r\n"));\r
+     return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  PciIo      = SDHostData->PciIo;\r
+\r
+  PciIo->Mem.Read (\r
+               PciIo,\r
+               EfiPciIoWidthUint8,\r
+               0,\r
+               (UINT64)MMIO_HOSTCTL,\r
+               1,\r
+               &Data\r
+               );\r
+  //\r
+  // BIT5 8-bit MMC Support (MMC8):\r
+  // If set, IOH supports 8-bit MMC. When cleared, IOH does not support this feature\r
+  //\r
+  if (BusWidth == 8) {\r
+    DEBUG ((EFI_D_INFO, "Bus Width is 8-bit ... \r\n"));\r
+    Data |= BIT5;\r
+  } else if (BusWidth == 4) {\r
+    DEBUG ((EFI_D_INFO, "Bus Width is 4-bit ... \r\n"));\r
+    Data &= ~BIT5;\r
+    Data |= BIT1;\r
+  } else {\r
+    DEBUG ((EFI_D_INFO, "Bus Width is 1-bit ... \r\n"));\r
+    Data &= ~BIT5;\r
+    Data &= ~BIT1;\r
+  }\r
+\r
+  PciIo->Mem.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint8,\r
+               0,\r
+               (UINT64)MMIO_HOSTCTL,\r
+               1,\r
+               &Data\r
+               );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Set voltage which could supported by the host controller.\r
+  Support 0(Power off the host), 1.8V, 3.0V, 3.3V\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  Voltage               Units in 0.1 V.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_INVALID_PARAMETER\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetHostVoltage (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  UINT32                     Voltage\r
+  )\r
+{\r
+  SDHOST_DATA            *SDHostData;\r
+  EFI_PCI_IO_PROTOCOL    *PciIo;\r
+  UINT8                  Data;\r
+  EFI_STATUS             Status;\r
+\r
+  SDHostData = SDHOST_DATA_FROM_THIS (This);\r
+  PciIo      = SDHostData->PciIo;\r
+  Status     = EFI_SUCCESS;\r
+\r
+  PciIo->Mem.Read (\r
+               PciIo,\r
+               EfiPciIoWidthUint8,\r
+               0,\r
+               (UINT64)MMIO_PWRCTL,\r
+               1,\r
+               &Data\r
+               );\r
+\r
+  if (Voltage == 0) {\r
+    //\r
+    //Power Off the host\r
+    //\r
+    Data &= ~BIT0;\r
+  } else if (Voltage <= 18 && This->HostCapability.V18Support) {\r
+     //\r
+     //1.8V\r
+     //\r
+     Data |= (BIT1 | BIT3 | BIT0);\r
+  } else if (Voltage > 18 &&  Voltage <= 30 && This->HostCapability.V30Support) {\r
+     //\r
+     //3.0V\r
+     //\r
+     Data |= (BIT2 | BIT3 | BIT0);\r
+  } else if (Voltage > 30 && Voltage <= 33 && This->HostCapability.V33Support) {\r
+     //\r
+     //3.3V\r
+     //\r
+     Data |= (BIT1 | BIT2 | BIT3 | BIT0);\r
+  } else {\r
+     Status = EFI_UNSUPPORTED;\r
+     goto Exit;\r
+  }\r
+\r
+  PciIo->Mem.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint8,\r
+               0,\r
+               (UINT64)MMIO_PWRCTL,\r
+               1,\r
+               &Data\r
+               );\r
+  gBS->Stall (10 * 1000);\r
+\r
+Exit:\r
+  return Status;\r
+}\r
+\r
+\r
+\r
+/**\r
+  Reset the host controller.\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  ResetAll              TRUE to reset all.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_TIMEOUT\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ResetSDHost (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  RESET_TYPE                 ResetType\r
+  )\r
+{\r
+  SDHOST_DATA            *SDHostData;\r
+  EFI_PCI_IO_PROTOCOL    *PciIo;\r
+  UINT32                 Data;\r
+  UINT16                 ErrStatus;\r
+  UINT32                 Mask;\r
+  UINT32                 TimeOutCount;\r
+  UINT16                 SaveClkCtl;\r
+  UINT16                 ZeroClkCtl;\r
+\r
+  SDHostData = SDHOST_DATA_FROM_THIS (This);\r
+  PciIo      = SDHostData->PciIo;\r
+  Mask       = 0;\r
+  ErrStatus  = 0;\r
+\r
+  if (ResetType == Reset_Auto) {\r
+    PciIo->Mem.Read (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint16,\r
+                 0,\r
+                 (UINT64)MMIO_ERINTSTS,\r
+                 1,\r
+                 &ErrStatus\r
+                 );\r
+    if ((ErrStatus & 0xF) != 0) {\r
+      //\r
+      //Command Line\r
+      //\r
+      Mask |= BIT1;\r
+    }\r
+    if ((ErrStatus & 0x70) != 0) {\r
+      //\r
+      //Data Line\r
+      //\r
+      Mask |= BIT2;\r
+    }\r
+  }\r
+\r
+\r
+  if (ResetType == Reset_DAT || ResetType == Reset_DAT_CMD) {\r
+    Mask |= BIT2;\r
+  }\r
+  if (ResetType == Reset_CMD || ResetType == Reset_DAT_CMD) {\r
+    Mask |= BIT1;\r
+  }\r
+  if (ResetType == Reset_All) {\r
+    Mask = BIT0;\r
+  }\r
+\r
+  if (Mask == 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // To improve SD stability, we zero the MMIO_CLKCTL register and\r
+  // stall for 50 microseconds before reseting the controller.  We\r
+  // restore the register setting following the reset operation.\r
+  //\r
+  PciIo->Mem.Read (\r
+               PciIo,\r
+               EfiPciIoWidthUint16,\r
+               0,\r
+               (UINT64)MMIO_CLKCTL,\r
+               1,\r
+               &SaveClkCtl\r
+               );\r
+\r
+  ZeroClkCtl = (UINT16) 0;\r
+  PciIo->Mem.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint16,\r
+               0,\r
+               (UINT64)MMIO_CLKCTL,\r
+               1,\r
+               &ZeroClkCtl\r
+               );\r
+\r
+  gBS->Stall (50);\r
+\r
+  //\r
+  // Reset the SD host controller\r
+  //\r
+  PciIo->Mem.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint8,\r
+               0,\r
+               (UINT64)MMIO_SWRST,\r
+               1,\r
+               &Mask\r
+               );\r
+\r
+  Data          = 0;\r
+  TimeOutCount  = TIME_OUT_1S;\r
+  do {\r
+\r
+    gBS->Stall (1 * 1000);\r
+\r
+    TimeOutCount --;\r
+\r
+    PciIo->Mem.Read (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint8,\r
+                 0,\r
+                 (UINT64)MMIO_SWRST,\r
+                 1,\r
+                 &Data\r
+                 );\r
+    if ((Data & Mask) == 0) {\r
+      break;\r
+    }\r
+  } while (TimeOutCount > 0);\r
+\r
+  //\r
+  // We now restore the MMIO_CLKCTL register which we set to 0 above.\r
+  //\r
+  PciIo->Mem.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint16,\r
+               0,\r
+               (UINT64)MMIO_CLKCTL,\r
+               1,\r
+               &SaveClkCtl\r
+               );\r
+\r
+  if (TimeOutCount == 0) {\r
+    DEBUG ((EFI_D_ERROR, "ResetSDHost: Time out \r\n"));\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Enable auto stop on the host controller.\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  Enable                TRUE to enable, FALSE to disable.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_TIMEOUT\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EnableAutoStopCmd (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  BOOLEAN                    Enable\r
+  )\r
+{\r
+  SDHOST_DATA            *SDHostData;\r
+\r
+  SDHostData = SDHOST_DATA_FROM_THIS (This);\r
+\r
+  SDHostData->IsAutoStopCmd = Enable;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Set the Block length on the host controller.\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  BlockLength           card supportes block length.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_TIMEOUT\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetBlockLength (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  UINT32                     BlockLength\r
+  )\r
+{\r
+  SDHOST_DATA            *SDHostData;\r
+\r
+  SDHostData = SDHOST_DATA_FROM_THIS (This);\r
+\r
+  DEBUG ((EFI_D_INFO, "Block length on the host controller: %d \r\n", BlockLength));\r
+  SDHostData->BlockLength = BlockLength;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Find whether these is a card inserted into the slot. If so init the host.\r
+  If not, return EFI_NOT_FOUND.\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_NOT_FOUND\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DetectCardAndInitHost (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This\r
+  )\r
+{\r
+  SDHOST_DATA            *SDHostData;\r
+  EFI_PCI_IO_PROTOCOL    *PciIo;\r
+  UINT32                 Data;\r
+  EFI_STATUS             Status;\r
+  UINT8                  Voltages[] = { 33, 30, 18 };\r
+  UINTN                  Loop;\r
+\r
+  SDHostData = SDHOST_DATA_FROM_THIS (This);\r
+  PciIo      = SDHostData->PciIo;\r
+  Status     = EFI_NOT_FOUND;\r
+\r
+  Data = 0;\r
+  PciIo->Mem.Read (\r
+               PciIo,\r
+               EfiPciIoWidthUint32,\r
+               0,\r
+               (UINT64)MMIO_PSTATE,\r
+               1,\r
+               &Data\r
+               );\r
+\r
+  if ((Data & (BIT16 | BIT17 | BIT18)) != (BIT16 | BIT17 | BIT18)) {\r
+    //\r
+    // Has no card inserted\r
+    //\r
+    DEBUG ((EFI_D_INFO, "DetectCardAndInitHost: No Cards \r\n"));\r
+    Status =  EFI_NOT_FOUND;\r
+    goto Exit;\r
+  }\r
+  DEBUG ((EFI_D_INFO, "DetectCardAndInitHost: Find Cards \r\n"));\r
+\r
+  Status =  EFI_NOT_FOUND;\r
+  for (Loop = 0; Loop < sizeof (Voltages); Loop++) {\r
+    DEBUG ((\r
+      EFI_D_INFO,\r
+      "DetectCardAndInitHost: SetHostVoltage %d.%dV \r\n",\r
+      Voltages[Loop] / 10,\r
+      Voltages[Loop] % 10\r
+      ));\r
+    Status = SetHostVoltage (This, Voltages[Loop]);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_INFO, "DetectCardAndInitHost set voltages: [failed]\n"));\r
+    } else {\r
+      DEBUG ((EFI_D_INFO, "DetectCardAndInitHost set voltages: [success]\n"));\r
+      break;\r
+    }\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "DetectCardAndInitHost: Fail to set voltage \r\n"));\r
+    goto Exit;\r
+  }\r
+\r
+  Status = SetClockFrequency (This, FREQUENCY_OD);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "DetectCardAndInitHost: Fail to set frequency \r\n"));\r
+    goto Exit;\r
+  }\r
+  SetBusWidth (This, 1);\r
+\r
+  //\r
+  //Enable normal status change\r
+  //\r
+\r
+  Data = (BIT0 | BIT1);\r
+\r
+  PciIo->Mem.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint16,\r
+               0,\r
+               (UINT64)MMIO_NINTEN,\r
+               1,\r
+               &Data\r
+               );\r
+\r
+  //\r
+  //Enable error status change\r
+  //\r
+  PciIo->Mem.Read (\r
+               PciIo,\r
+               EfiPciIoWidthUint16,\r
+               0,\r
+               (UINT64)MMIO_ERINTEN,\r
+               1,\r
+               &Data\r
+               );\r
+\r
+  Data |= (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7 | BIT8);\r
+\r
+  PciIo->Mem.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint16,\r
+               0,\r
+               (UINT64)MMIO_ERINTEN,\r
+               1,\r
+               &Data\r
+               );\r
+\r
+  //\r
+  //Data transfer Timeout control\r
+  //\r
+  Data = 0x0E;\r
+\r
+  PciIo->Mem.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint8,\r
+               0,\r
+               (UINT64)MMIO_TOCTL,\r
+               1,\r
+               &Data\r
+               );\r
+  //\r
+  //Set Default Bus width as 1 bit\r
+  //\r
+\r
+Exit:\r
+  return Status;\r
+\r
+}\r
+\r
+/**\r
+  Entry point for EFI drivers.\r
+\r
+  @param  ImageHandle      EFI_HANDLE.\r
+  @param  SystemTable      EFI_SYSTEM_TABLE.\r
+\r
+  @retval EFI_SUCCESS      Driver is successfully loaded.\r
+  @return Others           Failed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeSDController (\r
+  IN EFI_HANDLE           ImageHandle,\r
+  IN EFI_SYSTEM_TABLE     *SystemTable\r
+  )\r
+{\r
+  return EfiLibInstallDriverBindingComponentName2 (\r
+           ImageHandle,\r
+           SystemTable,\r
+           &gSDControllerDriverBinding,\r
+           ImageHandle,\r
+           &gSDControllerName,\r
+           &gSDControllerName2\r
+           );\r
+}\r
+\r
+\r
+/**\r
+  Test to see if this driver supports ControllerHandle. Any\r
+  ControllerHandle that has SDHostIoProtocol installed will be supported.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  Controller           Handle of device to test.\r
+  @param  RemainingDevicePath  Not used.\r
+\r
+  @return EFI_SUCCESS          This driver supports this device.\r
+  @return EFI_UNSUPPORTED      This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SDControllerSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL     *This,\r
+  IN EFI_HANDLE                      Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS            OpenStatus;\r
+  EFI_STATUS            Status;\r
+  EFI_PCI_IO_PROTOCOL   *PciIo;\r
+  PCI_CLASSC            PciClass;\r
+  EFI_SD_HOST_IO_PROTOCOL   *SdHostIo;\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiSDHostIoProtocolGuid,\r
+                  (VOID **)&SdHostIo,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    DEBUG (( DEBUG_INFO, "SdHost controller is already started\n"));\r
+    return EFI_ALREADY_STARTED;\r
+  }\r
+\r
+  //\r
+  // Test whether there is PCI IO Protocol attached on the controller handle.\r
+  //\r
+  OpenStatus = gBS->OpenProtocol (\r
+                      Controller,\r
+                      &gEfiPciIoProtocolGuid,\r
+                      (VOID **) &PciIo,\r
+                      This->DriverBindingHandle,\r
+                      Controller,\r
+                      EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                      );\r
+\r
+  if (EFI_ERROR (OpenStatus)) {\r
+    return OpenStatus;\r
+  }\r
+\r
+  Status = PciIo->Pci.Read (\r
+                        PciIo,\r
+                        EfiPciIoWidthUint8,\r
+                        PCI_CLASSCODE_OFFSET,\r
+                        sizeof (PCI_CLASSC) / sizeof (UINT8),\r
+                        &PciClass\r
+                        );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_UNSUPPORTED;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Test whether the controller belongs to SD type\r
+  //\r
+  if ((PciClass.BaseCode != PCI_CLASS_SYSTEM_PERIPHERAL) ||\r
+      (PciClass.SubClassCode != PCI_SUBCLASS_SD_HOST_CONTROLLER) ||\r
+      ((PciClass.PI != PCI_IF_STANDARD_HOST_NO_DMA) && (PciClass.PI != PCI_IF_STANDARD_HOST_SUPPORT_DMA))\r
+      ) {\r
+\r
+    Status = EFI_UNSUPPORTED;\r
+  }\r
+\r
+ON_EXIT:\r
+  gBS->CloseProtocol (\r
+         Controller,\r
+         &gEfiPciIoProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+\r
+  return Status;\r
+}\r
+/**\r
+  Starting the SD Host Controller Driver.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  Controller           Handle of device to test.\r
+  @param  RemainingDevicePath  Not used.\r
+\r
+  @retval EFI_SUCCESS          This driver supports this device.\r
+  @retval EFI_UNSUPPORTED      This driver does not support this device.\r
+  @retval EFI_DEVICE_ERROR     This driver cannot be started due to device Error.\r
+                               EFI_OUT_OF_RESOURCES- Failed due to resource shortage.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SDControllerStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL     *This,\r
+  IN EFI_HANDLE                      Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  EFI_PCI_IO_PROTOCOL   *PciIo;\r
+  SDHOST_DATA           *SDHostData;\r
+  UINT32                Data;\r
+\r
+\r
+  SDHostData = NULL;\r
+  Data       = 0;\r
+\r
+  //\r
+  // Open PCI I/O Protocol and save pointer to open protocol\r
+  // in private data area.\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  (VOID **) &PciIo,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+\r
+  //\r
+  // Enable the SD Host Controller MMIO space\r
+  //\r
+  Status = PciIo->Attributes (\r
+                    PciIo,\r
+                    EfiPciIoAttributeOperationEnable,\r
+                    EFI_PCI_DEVICE_ENABLE,\r
+                    NULL\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Exit;\r
+  }\r
+\r
+\r
+  SDHostData = (SDHOST_DATA*)AllocateZeroPool(sizeof (SDHOST_DATA));\r
+  if (SDHostData == NULL) {\r
+    Status =  EFI_OUT_OF_RESOURCES;\r
+    goto Exit;\r
+  }\r
+\r
+  SDHostData->Signature   = SDHOST_DATA_SIGNATURE;\r
+  SDHostData->PciIo       = PciIo;\r
+\r
+  CopyMem (&SDHostData->SDHostIo, &mSDHostIo, sizeof (EFI_SD_HOST_IO_PROTOCOL));\r
+\r
+  ResetSDHost (&SDHostData->SDHostIo, Reset_All);\r
+\r
+  PciIo->Mem.Read (\r
+              PciIo,\r
+              EfiPciIoWidthUint16,\r
+              0,\r
+              (UINT64)MMIO_CTRLRVER,\r
+              1,\r
+              &Data\r
+              );\r
+  SDHostData->SDHostIo.HostCapability.HostVersion = Data & 0xFF;\r
+  DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: HostVersion 0x%x \r\n", SDHostData->SDHostIo.HostCapability.HostVersion));\r
+\r
+  PciIo->Mem.Read (\r
+               PciIo,\r
+               EfiPciIoWidthUint32,\r
+               0,\r
+               (UINT64)MMIO_CAP,\r
+               1,\r
+               &Data\r
+               );\r
+  DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: MMIO_CAP 0x%x \r\n", Data));\r
+  if ((Data & BIT18) != 0) {\r
+    SDHostData->SDHostIo.HostCapability.BusWidth8 = TRUE;\r
+  }\r
+\r
+  if ((Data & BIT21) != 0) {\r
+    SDHostData->SDHostIo.HostCapability.HighSpeedSupport = TRUE;\r
+  }\r
+\r
+  if ((Data & BIT24) != 0) {\r
+    SDHostData->SDHostIo.HostCapability.V33Support = TRUE;\r
+  }\r
+\r
+  if ((Data & BIT25) != 0) {\r
+    SDHostData->SDHostIo.HostCapability.V30Support = TRUE;\r
+  }\r
+\r
+  if ((Data & BIT26) != 0) {\r
+    SDHostData->SDHostIo.HostCapability.V18Support = TRUE;\r
+  }\r
+\r
+  SDHostData->SDHostIo.HostCapability.BusWidth4 = TRUE;\r
+\r
+  if(SDHostData->SDHostIo.HostCapability.HostVersion < SDHCI_SPEC_300) {\r
+\r
+\r
+\r
+      SDHostData->BaseClockInMHz = (Data >> 8) & 0x3F;\r
+   }\r
+   else {\r
+      SDHostData->BaseClockInMHz = (Data >> 8) & 0xFF;\r
+\r
+   }\r
+\r
+  SDHostData->BlockLength = 512 << ((Data >> 16) & 0x03);\r
+  DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: BlockLength 0x%x \r\n", SDHostData->BlockLength));\r
+  SDHostData->IsAutoStopCmd  = TRUE;\r
+\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &Controller,\r
+                  &gEfiSDHostIoProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &SDHostData->SDHostIo\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+\r
+  //\r
+  // Install the component name protocol\r
+  //\r
+  SDHostData->ControllerNameTable = NULL;\r
+\r
+  AddUnicodeString2 (\r
+    "eng",\r
+    gSDControllerName.SupportedLanguages,\r
+    &SDHostData->ControllerNameTable,\r
+    L"SD Host Controller",\r
+    TRUE\r
+    );\r
+  AddUnicodeString2 (\r
+    "en",\r
+    gSDControllerName2.SupportedLanguages,\r
+    &SDHostData->ControllerNameTable,\r
+    L"SD Host Controller",\r
+    FALSE\r
+    );\r
+\r
+Exit:\r
+  if (EFI_ERROR (Status)) {\r
+    if (SDHostData != NULL) {\r
+      FreePool (SDHostData);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Stop this driver on ControllerHandle. Support stoping any child handles\r
+  created by this driver.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  Controller           Handle of device to stop driver on.\r
+  @param  NumberOfChildren     Number of Children in the ChildHandleBuffer.\r
+  @param  ChildHandleBuffer    List of handles for the children we need to stop.\r
+\r
+  @return EFI_SUCCESS\r
+  @return others\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SDControllerStop (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL     *This,\r
+  IN EFI_HANDLE                      Controller,\r
+  IN UINTN                           NumberOfChildren,\r
+  IN EFI_HANDLE                      *ChildHandleBuffer\r
+  )\r
+{\r
+  EFI_STATUS               Status;\r
+  EFI_SD_HOST_IO_PROTOCOL  *SDHostIo;\r
+  SDHOST_DATA              *SDHostData;\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiSDHostIoProtocolGuid,\r
+                  (VOID **) &SDHostIo,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+\r
+  //\r
+  // Test whether the Controller handler passed in is a valid\r
+  // Usb controller handle that should be supported, if not,\r
+  // return the error status directly\r
+  //\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  SetHostVoltage (SDHostIo, 0);\r
+\r
+  SDHostData  = SDHOST_DATA_FROM_THIS(SDHostIo);\r
+\r
+  //\r
+  // Uninstall Block I/O protocol from the device handle\r
+  //\r
+  Status = gBS->UninstallProtocolInterface (\r
+                  Controller,\r
+                  &gEfiSDHostIoProtocolGuid,\r
+                  SDHostIo\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  FreeUnicodeStringTable (SDHostData->ControllerNameTable);\r
+\r
+  FreePool (SDHostData);\r
+\r
+  gBS->CloseProtocol (\r
+         Controller,\r
+         &gEfiPciIoProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDController.h b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDController.h
new file mode 100644 (file)
index 0000000..d5302ba
--- /dev/null
@@ -0,0 +1,322 @@
+/** @file\r
+\r
+The definition for SD host controller driver model and HC protocol routines.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _SD_CONTROLLER_H_\r
+#define _SD_CONTROLLER_H_\r
+\r
+\r
+#include <Uefi.h>\r
+\r
+\r
+#include <Protocol/PciIo.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <IndustryStandard/Pci22.h>\r
+\r
+\r
+#include "ComponentName.h"\r
+#include "SDHostIo.h"\r
+\r
+\r
+extern EFI_DRIVER_BINDING_PROTOCOL   gSDControllerDriverBinding;\r
+extern EFI_COMPONENT_NAME_PROTOCOL   gSDControllerName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL  gSDControllerName2;\r
+\r
+\r
+#define SDHOST_DATA_SIGNATURE  SIGNATURE_32 ('s', 'd', 'h', 's')\r
+\r
+#define BLOCK_SIZE   0x200\r
+#define TIME_OUT_1S  1000\r
+\r
+#pragma pack(1)\r
+//\r
+// PCI Class Code structure\r
+//\r
+typedef struct {\r
+  UINT8 PI;\r
+  UINT8 SubClassCode;\r
+  UINT8 BaseCode;\r
+} PCI_CLASSC;\r
+\r
+#pragma pack()\r
+\r
+\r
+typedef struct {\r
+  UINTN                      Signature;\r
+  EFI_SD_HOST_IO_PROTOCOL    SDHostIo;\r
+  EFI_PCI_IO_PROTOCOL        *PciIo;\r
+  BOOLEAN                    IsAutoStopCmd;\r
+  UINT32                     BaseClockInMHz;\r
+  UINT32                     CurrentClockInKHz;\r
+  UINT32                     BlockLength;\r
+  EFI_UNICODE_STRING_TABLE   *ControllerNameTable;\r
+}SDHOST_DATA;\r
+\r
+#define SDHOST_DATA_FROM_THIS(a) \\r
+    CR(a, SDHOST_DATA, SDHostIo, SDHOST_DATA_SIGNATURE)\r
+\r
+/**\r
+  Test to see if this driver supports ControllerHandle. Any\r
+  ControllerHandle that has SDHostIoProtocol installed will be supported.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  Controller           Handle of device to test.\r
+  @param  RemainingDevicePath  Not used.\r
+\r
+  @return EFI_SUCCESS          This driver supports this device.\r
+  @return EFI_UNSUPPORTED      This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SDControllerSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL     *This,\r
+  IN EFI_HANDLE                      Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
+  );\r
+\r
+/**\r
+  Starting the SD Host Controller Driver.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  Controller           Handle of device to test.\r
+  @param  RemainingDevicePath  Not used.\r
+\r
+  @retval EFI_SUCCESS          This driver supports this device.\r
+  @retval EFI_UNSUPPORTED      This driver does not support this device.\r
+  @retval EFI_DEVICE_ERROR     This driver cannot be started due to device Error.\r
+                               EFI_OUT_OF_RESOURCES- Failed due to resource shortage.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SDControllerStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL     *This,\r
+  IN EFI_HANDLE                      Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
+  );\r
+\r
+/**\r
+  Stop this driver on ControllerHandle. Support stoping any child handles\r
+  created by this driver.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  Controller           Handle of device to stop driver on.\r
+  @param  NumberOfChildren     Number of Children in the ChildHandleBuffer.\r
+  @param  ChildHandleBuffer    List of handles for the children we need to stop.\r
+\r
+  @return EFI_SUCCESS\r
+  @return others\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SDControllerStop (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL     *This,\r
+  IN EFI_HANDLE                      Controller,\r
+  IN UINTN                           NumberOfChildren,\r
+  IN EFI_HANDLE                      *ChildHandleBuffer\r
+  );\r
+\r
+/**\r
+  The main function used to send the command to the card inserted into the SD host slot.\r
+  It will assemble the arguments to set the command register and wait for the command\r
+  and transfer completed until timeout. Then it will read the response register to fill\r
+  the ResponseData.\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  CommandIndex          The command index to set the command index field of command register.\r
+  @param  Argument              Command argument to set the argument field of command register.\r
+  @param  DataType              TRANSFER_TYPE, indicates no data, data in or data out.\r
+  @param  Buffer                Contains the data read from / write to the device.\r
+  @param  BufferSize            The size of the buffer.\r
+  @param  ResponseType          RESPONSE_TYPE.\r
+  @param  TimeOut               Time out value in 1 ms unit.\r
+  @param  ResponseData          Depending on the ResponseType, such as CSD or card status.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_INVALID_PARAMETER\r
+  @retval EFI_OUT_OF_RESOURCES\r
+  @retval EFI_TIMEOUT\r
+  @retval EFI_DEVICE_ERROR\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SendCommand (\r
+  IN   EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN   UINT16                     CommandIndex,\r
+  IN   UINT32                     Argument,\r
+  IN   TRANSFER_TYPE              DataType,\r
+  IN   UINT8                      *Buffer, OPTIONAL\r
+  IN   UINT32                     BufferSize,\r
+  IN   RESPONSE_TYPE              ResponseType,\r
+  IN   UINT32                     TimeOut,\r
+  OUT  UINT32                     *ResponseData OPTIONAL\r
+  );\r
+\r
+/**\r
+  Set max clock frequency of the host, the actual frequency may not be the same as MaxFrequency.\r
+  It depends on the max frequency the host can support, divider, and host speed mode.\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  MaxFrequency          Max frequency in HZ.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_TIMEOUT\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetClockFrequency (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  UINT32                     MaxFrequencyInKHz\r
+  );\r
+\r
+/**\r
+  Set bus width of the host controller\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  BusWidth              Bus width in 1, 4, 8 bits.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_INVALID_PARAMETER\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetBusWidth (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  UINT32                     BusWidth\r
+  );\r
+\r
+\r
+/**\r
+  Set voltage which could supported by the host controller.\r
+  Support 0(Power off the host), 1.8V, 3.0V, 3.3V\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  Voltage               Units in 0.1 V.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_INVALID_PARAMETER\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetHostVoltage (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  UINT32                     Voltage\r
+  );\r
+\r
+\r
+/**\r
+  Reset the host controller.\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  ResetAll              TRUE to reset all.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_TIMEOUT\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ResetSDHost (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  RESET_TYPE                 ResetType\r
+  );\r
+\r
+\r
+/**\r
+  Enable auto stop on the host controller.\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  Enable                TRUE to enable, FALSE to disable.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_TIMEOUT\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EnableAutoStopCmd (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  BOOLEAN                    Enable\r
+  );\r
+\r
+/**\r
+  Find whether these is a card inserted into the slot. If so init the host.\r
+  If not, return EFI_NOT_FOUND.\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_NOT_FOUND\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DetectCardAndInitHost (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This\r
+  );\r
+\r
+/**\r
+  Set the Block length on the host controller.\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  BlockLength           card supportes block length.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_TIMEOUT\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetBlockLength (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  UINT32                     BlockLength\r
+  );\r
+\r
+/**\r
+  Enable/Disable High Speed transfer mode\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  Enable                TRUE to Enable, FALSE to Disable\r
+\r
+  @return EFI_SUCCESS\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetHighSpeedMode (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  BOOLEAN                    Enable\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SetDDRMode (\r
+  IN  EFI_SD_HOST_IO_PROTOCOL    *This,\r
+  IN  BOOLEAN                    Enable\r
+  );\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDControllerDxe.inf b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDControllerDxe.inf
new file mode 100644 (file)
index 0000000..3cbe233
--- /dev/null
@@ -0,0 +1,62 @@
+## @file\r
+#\r
+#  Component Description File For SDControllerDxe Module.\r
+#\r
+#  Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution.  The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = SDController\r
+  FILE_GUID                      = 90A330BD-6F89-4900-933A-C25EB4356348\r
+  MODULE_TYPE                    = UEFI_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = InitializeSDController\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+#  DRIVER_BINDING                =  gSDControllerDriverBinding\r
+#  COMPONENT_NAME                =  gSDControllerName\r
+#  COMPONENT_NAME2               =  gSDControllerName2\r
+#\r
+\r
+[Sources]\r
+  SDController.c\r
+  SDController.h\r
+  ComponentName.c\r
+  ComponentName.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  MemoryAllocationLib\r
+  BaseLib\r
+  UefiLib\r
+  UefiBootServicesTableLib\r
+  UefiDriverEntryPoint\r
+  BaseMemoryLib\r
+  DebugLib\r
+  PcdLib\r
+\r
+[Protocols]\r
+  gEfiPciIoProtocolGuid                         ## TO_START\r
+  gEfiSDHostIoProtocolGuid                      ## BY_START\r
+\r
+[FeaturePcd]\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdSdHciQuirkNoHiSpd\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATA.c b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATA.c
new file mode 100644 (file)
index 0000000..0261295
--- /dev/null
@@ -0,0 +1,656 @@
+/** @file\r
+\r
+CEATA specific functions implementation\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "SDMediaDevice.h"\r
+\r
+/**\r
+  Send RW_MULTIPLE_REGISTER command\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+  @param  Address              Register address.\r
+  @param  ByteCount            Buffer size.\r
+  @param  Write                TRUE means write, FALSE means read.\r
+  @param  Buffer               Buffer pointer.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+ReadWriteMultipleRegister (\r
+  IN  CARD_DATA   *CardData,\r
+  IN  UINT16      Address,\r
+  IN  UINT8       ByteCount,\r
+  IN  BOOLEAN     Write,\r
+  IN  UINT8       *Buffer\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  UINT32                     Argument;\r
+\r
+  Status   = EFI_SUCCESS;\r
+\r
+  if ((Address % 4 != 0) || (ByteCount % 4 != 0)) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Exit;\r
+  }\r
+\r
+  Argument = (Address << 16) | ByteCount;\r
+  if (Write) {\r
+    Argument |= BIT31;\r
+  }\r
+\r
+\r
+  if (Write) {\r
+    CopyMem (CardData->AlignedBuffer, Buffer, ByteCount);\r
+\r
+    Status = SendCommand (\r
+               CardData,\r
+               RW_MULTIPLE_REGISTER,\r
+               Argument,\r
+               OutData,\r
+               CardData->AlignedBuffer,\r
+               ByteCount,\r
+               ResponseR1b,\r
+               TIMEOUT_DATA,\r
+               (UINT32*)&(CardData->CardStatus)\r
+               );\r
+  } else {\r
+    Status = SendCommand (\r
+               CardData,\r
+               RW_MULTIPLE_REGISTER,\r
+               Argument,\r
+               InData,\r
+               CardData->AlignedBuffer,\r
+               ByteCount,\r
+               ResponseR1,\r
+               TIMEOUT_DATA,\r
+               (UINT32*)&(CardData->CardStatus)\r
+               );\r
+    if (!EFI_ERROR (Status)) {\r
+      CopyMem (Buffer, CardData->AlignedBuffer, ByteCount);\r
+    }\r
+\r
+  }\r
+Exit:\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Send ReadWriteMultipleBlock command with RW_MULTIPLE_REGISTER command\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+  @param  DataUnitCount        Buffer size in 512 bytes unit.\r
+  @param  Write                TRUE means write, FALSE means read.\r
+  @param  Buffer               Buffer pointer.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+ReadWriteMultipleBlock (\r
+  IN  CARD_DATA   *CardData,\r
+  IN  UINT16      DataUnitCount,\r
+  IN  BOOLEAN     Write,\r
+  IN  UINT8       *Buffer\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  EFI_SD_HOST_IO_PROTOCOL    *SDHostIo;\r
+  UINT32                     TransferLength;\r
+\r
+  Status   = EFI_SUCCESS;\r
+  SDHostIo = CardData->SDHostIo;\r
+\r
+  TransferLength = DataUnitCount * DATA_UNIT_SIZE;\r
+  if (TransferLength > SDHostIo->HostCapability.BoundarySize) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Write) {\r
+    CopyMem (CardData->AlignedBuffer, Buffer, TransferLength);\r
+\r
+    Status = SendCommand (\r
+               CardData,\r
+               RW_MULTIPLE_BLOCK,\r
+               (DataUnitCount | BIT31),\r
+               OutData,\r
+               CardData->AlignedBuffer,\r
+               TransferLength,\r
+               ResponseR1b,\r
+               TIMEOUT_DATA,\r
+               (UINT32*)&(CardData->CardStatus)\r
+               );\r
+   } else {\r
+      Status = SendCommand (\r
+                 CardData,\r
+                 RW_MULTIPLE_BLOCK,\r
+                 DataUnitCount,\r
+                 InData,\r
+                 CardData->AlignedBuffer,\r
+                 TransferLength,\r
+                 ResponseR1,\r
+                 TIMEOUT_DATA,\r
+                 (UINT32*)&(CardData->CardStatus)\r
+                 );\r
+      if (!EFI_ERROR (Status)) {\r
+        CopyMem (Buffer, CardData->AlignedBuffer, TransferLength);\r
+      }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Send software reset\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+SoftwareReset (\r
+  IN  CARD_DATA    *CardData\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  UINT8         Data;\r
+  UINT32        TimeOut;\r
+\r
+  Data = BIT2;\r
+\r
+  Status = FastIO (CardData, Reg_Control, &Data, TRUE);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+\r
+  TimeOut = 5 * 1000;\r
+\r
+  do {\r
+    gBS->Stall (1 * 1000);\r
+    Status = FastIO (CardData, Reg_Control, &Data, FALSE);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Exit;\r
+    }\r
+    if ((Data & BIT2) == BIT2) {\r
+      break;\r
+    }\r
+\r
+    TimeOut--;\r
+  } while (TimeOut > 0);\r
+\r
+  if (TimeOut == 0) {\r
+   Status = EFI_TIMEOUT;\r
+   goto Exit;\r
+  }\r
+\r
+  Data &= ~BIT2;\r
+  Status = FastIO (CardData, Reg_Control, &Data, TRUE);\r
+\r
+  TimeOut = 5 * 1000;\r
+\r
+  do {\r
+    gBS->Stall (1 * 1000);\r
+    Status = FastIO (CardData, Reg_Control, &Data, FALSE);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Exit;\r
+    }\r
+    if ((Data & BIT2) != BIT2) {\r
+      break;\r
+    }\r
+\r
+    TimeOut--;\r
+  } while (TimeOut > 0);\r
+\r
+\r
+  if (TimeOut == 0) {\r
+   Status = EFI_TIMEOUT;\r
+   goto Exit;\r
+  }\r
+\r
+\r
+Exit:\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  SendATACommand specificed in Taskfile\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+  @param  TaskFile             Pointer to TASK_FILE.\r
+  @param  Write                TRUE means write, FALSE means read.\r
+  @param  Buffer               If NULL, means no data transfer, neither read nor write.\r
+  @param  SectorCount          Buffer size in 512 bytes unit.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+SendATACommand (\r
+  IN  CARD_DATA   *CardData,\r
+  IN  TASK_FILE   *TaskFile,\r
+  IN  BOOLEAN     Write,\r
+  IN  UINT8       *Buffer,\r
+  IN  UINT16      SectorCount\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  EFI_SD_HOST_IO_PROTOCOL    *SDHostIo;\r
+  UINT8                      Data;\r
+  UINT32                     TimeOut;\r
+\r
+  SDHostIo = CardData->SDHostIo;\r
+\r
+  //\r
+  //Write register\r
+  //\r
+  Status = ReadWriteMultipleRegister (\r
+             CardData,\r
+             0,\r
+             sizeof (TASK_FILE),\r
+             TRUE,\r
+             (UINT8*)TaskFile\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG((EFI_D_ERROR, "ReadWriteMultipleRegister 0x%x\n", Status));\r
+    goto Exit;\r
+  }\r
+\r
+  TimeOut = 5000;\r
+  do {\r
+    gBS->Stall (1 * 1000);\r
+    Data = 0;\r
+    Status = FastIO (\r
+               CardData,\r
+               Reg_Command_Status,\r
+               &Data,\r
+               FALSE\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    if (((Data & BIT7) == 0) && ((Data & BIT6) == BIT6)) {\r
+      break;\r
+    }\r
+\r
+    TimeOut --;\r
+  } while (TimeOut > 0);\r
+\r
+  if (TimeOut == 0) {\r
+    DEBUG((EFI_D_ERROR, "ReadWriteMultipleRegister FastIO EFI_TIMEOUT 0x%x\n", Data));\r
+    Status = EFI_TIMEOUT;\r
+    goto Exit;\r
+  }\r
+\r
+\r
+  if (Buffer != NULL) {\r
+    Status = ReadWriteMultipleBlock (\r
+               CardData,\r
+               SectorCount,\r
+               Write,\r
+               (UINT8*)Buffer\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG((EFI_D_ERROR, "ReadWriteMultipleBlock EFI_TIMEOUT 0x%x\n", Status));\r
+      goto Exit;\r
+    }\r
+\r
+    TimeOut = 5 * 1000;\r
+    do {\r
+      gBS->Stall (1 * 1000);\r
+\r
+      Data = 0;\r
+      Status = FastIO (\r
+                 CardData,\r
+                 Reg_Command_Status,\r
+                 &Data,\r
+                 FALSE\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      if (((Data & BIT7) == 0) && ((Data & BIT3) == 0)) {\r
+        break;\r
+      }\r
+\r
+      TimeOut --;\r
+    } while (TimeOut > 0);\r
+    if (TimeOut == 0) {\r
+      DEBUG((EFI_D_ERROR, "ReadWriteMultipleBlock FastIO EFI_TIMEOUT 0x%x\n", Data));\r
+      Status = EFI_TIMEOUT;\r
+      goto Exit;\r
+    }\r
+\r
+\r
+    if (((Data & BIT6) == BIT6) && (Data & BIT0) == 0) {\r
+      Status = EFI_SUCCESS;\r
+    } else {\r
+      Status = EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+\r
+Exit:\r
+  if (EFI_ERROR (Status)) {\r
+    SoftwareReset (CardData);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  IDENTIFY_DEVICE command\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+IndentifyDevice (\r
+  IN  CARD_DATA    *CardData\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+\r
+  ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));\r
+\r
+  //\r
+  //The host only supports nIEN = 0\r
+  //\r
+  CardData->TaskFile.Command_Status = IDENTIFY_DEVICE;\r
+\r
+\r
+  Status = SendATACommand (\r
+             CardData,\r
+             &CardData->TaskFile,\r
+             FALSE,\r
+             (UINT8*)&(CardData->IndentifyDeviceData),\r
+             1\r
+             );\r
+\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  FLUSH_CACHE_EXT command\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+FlushCache (\r
+  IN  CARD_DATA    *CardData\r
+  )\r
+{\r
+\r
+  //\r
+  //Hitachi CE-ATA will always make the busy high after\r
+  //receving this command\r
+  //\r
+/*\r
+  EFI_STATUS  Status;\r
+  ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));\r
+  //\r
+  //The host only supports nIEN = 0\r
+  //\r
+  CardData->TaskFile.Command_Status = FLUSH_CACHE_EXT;\r
+\r
+  Status = SendATACommand (\r
+             CardData,\r
+             &CardData->TaskFile,\r
+             FALSE,\r
+             NULL,\r
+             0\r
+             );\r
+*/\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  STANDBY_IMMEDIATE command\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+StandByImmediate (\r
+  IN  CARD_DATA    *CardData\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));\r
+  //\r
+  //The host only supports nIEN = 0\r
+  //\r
+  CardData->TaskFile.Command_Status = STANDBY_IMMEDIATE;\r
+\r
+\r
+  Status = SendATACommand (\r
+             CardData,\r
+             &CardData->TaskFile,\r
+             FALSE,\r
+             NULL,\r
+             0\r
+             );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  READ_DMA_EXT command\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+  @param  LBA                  The starting logical block address to read from on the device.\r
+  @param  Buffer               A pointer to the destination buffer for the data. The caller\r
+                               is responsible for either having implicit or explicit ownership\r
+                               of the buffer.\r
+  @param  SectorCount          Size in 512 bytes unit.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+ReadDMAExt (\r
+  IN  CARD_DATA   *CardData,\r
+  IN  EFI_LBA     LBA,\r
+  IN  UINT8       *Buffer,\r
+  IN  UINT16      SectorCount\r
+  )\r
+{\r
+\r
+  EFI_STATUS  Status;\r
+\r
+  ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));\r
+  //\r
+  //The host only supports nIEN = 0\r
+  //\r
+  CardData->TaskFile.Command_Status = READ_DMA_EXT;\r
+\r
+  CardData->TaskFile.SectorCount     = (UINT8)SectorCount;\r
+  CardData->TaskFile.SectorCount_Exp = (UINT8)(SectorCount >> 8);\r
+\r
+  CardData->TaskFile.LBALow          = (UINT8)LBA;\r
+  CardData->TaskFile.LBAMid          = (UINT8)RShiftU64(LBA, 8);\r
+  CardData->TaskFile.LBAHigh         = (UINT8)RShiftU64(LBA, 16);\r
+\r
+  CardData->TaskFile.LBALow_Exp      = (UINT8)RShiftU64(LBA, 24);\r
+  CardData->TaskFile.LBAMid_Exp      = (UINT8)RShiftU64(LBA, 32);\r
+  CardData->TaskFile.LBAHigh_Exp     = (UINT8)RShiftU64(LBA, 40);\r
+\r
+  Status = SendATACommand (\r
+             CardData,\r
+             &CardData->TaskFile,\r
+             FALSE,\r
+             Buffer,\r
+             SectorCount\r
+             );\r
+  return Status;\r
+\r
+}\r
+\r
+/**\r
+  WRITE_DMA_EXT command\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+  @param  LBA                  The starting logical block address to read from on the device.\r
+  @param  Buffer               A pointer to the destination buffer for the data. The caller\r
+                               is responsible for either having implicit or explicit ownership\r
+                               of the buffer.\r
+  @param  SectorCount          Size in 512 bytes unit.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+WriteDMAExt (\r
+  IN  CARD_DATA   *CardData,\r
+  IN  EFI_LBA     LBA,\r
+  IN  UINT8       *Buffer,\r
+  IN  UINT16      SectorCount\r
+  )\r
+{\r
+\r
+  EFI_STATUS  Status;\r
+\r
+  ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));\r
+  //\r
+  //The host only supports nIEN = 0\r
+  //\r
+  CardData->TaskFile.Command_Status = WRITE_DMA_EXT;\r
+\r
+  CardData->TaskFile.SectorCount     = (UINT8)SectorCount;\r
+  CardData->TaskFile.SectorCount_Exp = (UINT8)(SectorCount >> 8);\r
+\r
+  CardData->TaskFile.LBALow          = (UINT8)LBA;\r
+  CardData->TaskFile.LBAMid          = (UINT8)RShiftU64(LBA, 8);\r
+  CardData->TaskFile.LBAHigh         = (UINT8)RShiftU64(LBA, 16);\r
+\r
+  CardData->TaskFile.LBALow_Exp      = (UINT8)RShiftU64(LBA, 24);\r
+  CardData->TaskFile.LBAMid_Exp      = (UINT8)RShiftU64(LBA, 32);\r
+  CardData->TaskFile.LBAHigh_Exp     = (UINT8)RShiftU64(LBA, 40);\r
+\r
+  Status = SendATACommand (\r
+             CardData,\r
+             &CardData->TaskFile,\r
+             TRUE,\r
+             Buffer,\r
+             SectorCount\r
+             );\r
+  return Status;\r
+\r
+}\r
+\r
+\r
+/**\r
+  Judge whether it is CE-ATA device or not.\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+\r
+  @retval TRUE\r
+  @retval FALSE\r
+\r
+**/\r
+BOOLEAN\r
+IsCEATADevice (\r
+  IN  CARD_DATA    *CardData\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+\r
+  Status = ReadWriteMultipleRegister (\r
+             CardData,\r
+             0,\r
+             sizeof (TASK_FILE),\r
+             FALSE,\r
+             (UINT8*)&CardData->TaskFile\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    //To bring back the normal MMC card to work\r
+    //\r
+    CardData->SDHostIo->ResetSDHost (CardData->SDHostIo, Reset_DAT_CMD);\r
+    return FALSE;\r
+  }\r
+\r
+  if (CardData->TaskFile.LBAMid == CE_ATA_SIG_CE &&\r
+      CardData->TaskFile.LBAHigh == CE_ATA_SIG_AA\r
+    ) {\r
+    //\r
+    //Disable Auto CMD for CE-ATA\r
+    //\r
+    CardData->SDHostIo->EnableAutoStopCmd (CardData->SDHostIo, FALSE);\r
+\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATABlockIo.c b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATABlockIo.c
new file mode 100644 (file)
index 0000000..a9addec
--- /dev/null
@@ -0,0 +1,396 @@
+/** @file\r
+\r
+Block I/O protocol for CE-ATA device\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "SDMediaDevice.h"\r
+\r
+/**\r
+  Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.\r
+\r
+  @param  This                   The EFI_BLOCK_IO_PROTOCOL instance.\r
+  @param  ExtendedVerification   Indicates that the driver may perform a more exhaustive.\r
+                                 verification operation of the device during reset.\r
+                                 (This parameter is ingored in this driver.)\r
+\r
+  @retval EFI_SUCCESS                Success\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CEATABlockReset (\r
+  IN  EFI_BLOCK_IO_PROTOCOL   *This,\r
+  IN  BOOLEAN                 ExtendedVerification\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  CARD_DATA                  *CardData;\r
+  EFI_SD_HOST_IO_PROTOCOL    *SDHostIo;\r
+\r
+  CardData  = CARD_DATA_FROM_THIS(This);\r
+  SDHostIo = CardData->SDHostIo;\r
+\r
+  if (!ExtendedVerification) {\r
+    Status = SoftwareReset (CardData);\r
+  } else {\r
+    Status = SDHostIo->ResetSDHost (SDHostIo, Reset_DAT_CMD);\r
+    if (EFI_ERROR (Status)) {\r
+    DEBUG((EFI_D_ERROR, "CEATABlockReset: Fail to ResetSDHost\n" ));\r
+      return Status;\r
+    }\r
+    Status = MMCSDCardInit (CardData);\r
+  }\r
+\r
+\r
+  return Status;\r
+\r
+ }\r
+\r
+/**\r
+  Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.\r
+\r
+  @param  This                   The EFI_BLOCK_IO_PROTOCOL instance.\r
+  @param  MediaId                The media id that the write request is for.\r
+  @param  LBA                    The starting logical block address to read from on the device.\r
+                                 The caller is responsible for writing to only legitimate locations.\r
+  @param  BufferSize             The size of the Buffer in bytes. This must be a multiple of the\r
+                                 intrinsic block size of the device.\r
+  @param  Buffer                 A pointer to the destination buffer for the data. The caller\r
+                                 is responsible for either having implicit or explicit ownership\r
+                                 of the buffer.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CEATABlockReadBlocks (\r
+  IN  EFI_BLOCK_IO_PROTOCOL   *This,\r
+  IN  UINT32                  MediaId,\r
+  IN  EFI_LBA                 LBA,\r
+  IN  UINTN                   BufferSize,\r
+  OUT VOID                    *Buffer\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  CARD_DATA                   *CardData;\r
+  UINT32                      TransferSize;\r
+  UINT8                       *pBuf;\r
+  UINT32                      Index;\r
+  UINT64                      Address;\r
+  UINT32                      Remainder;\r
+  UINT64                      CEATALBA;\r
+  UINT32                      BoundarySize;\r
+\r
+  Status       = EFI_SUCCESS;\r
+  CardData     = CARD_DATA_FROM_THIS(This);\r
+  pBuf         = Buffer;\r
+  Index        = 0;\r
+  Address      = MultU64x32(LBA, CardData->BlockIoMedia.BlockSize);\r
+  BoundarySize = CardData->SDHostIo->HostCapability.BoundarySize;\r
+\r
+  if (!Buffer) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Invalid parameter\n" ));\r
+    goto Exit;\r
+  }\r
+\r
+  if (MediaId != CardData->BlockIoMedia.MediaId) {\r
+    Status = EFI_MEDIA_CHANGED;\r
+  DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Media changed\n" ));\r
+    goto Exit;\r
+  }\r
+\r
+  if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {\r
+    Status = EFI_BAD_BUFFER_SIZE;\r
+  DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Bad buffer size\n" ));\r
+    goto Exit;\r
+  }\r
+\r
+  if (BufferSize == 0) {\r
+    Status = EFI_SUCCESS;\r
+    goto Exit;\r
+  }\r
+\r
+  if ((Address + BufferSize) > MultU64x32 (CardData->BlockIoMedia.LastBlock + 1, CardData->BlockIoMedia.BlockSize)) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Invalid parameter\n" ));\r
+    goto Exit;\r
+  }\r
+\r
+\r
+  do {\r
+    if (BufferSize < BoundarySize) {\r
+      TransferSize = (UINT32)BufferSize;\r
+    } else {\r
+      TransferSize = BoundarySize;\r
+    }\r
+\r
+    Address += Index * TransferSize;\r
+    CEATALBA = DivU64x32Remainder (Address, DATA_UNIT_SIZE, &Remainder);\r
+    ASSERT(Remainder == 0);\r
+\r
+    Status = ReadDMAExt (\r
+               CardData,\r
+               CEATALBA,\r
+               pBuf,\r
+               (UINT16)(TransferSize / DATA_UNIT_SIZE)\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+     DEBUG((EFI_D_ERROR, "Read Failed at 0x%x, Index %d, Size 0x%x\n", Address, Index, TransferSize));\r
+     This->Reset (This, TRUE);\r
+     goto Exit;\r
+    }\r
+    BufferSize -= TransferSize;\r
+    pBuf       += TransferSize;\r
+    Index ++;\r
+  } while (BufferSize != 0);\r
+\r
+\r
+Exit:\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.\r
+\r
+  @param  This                   The EFI_BLOCK_IO_PROTOCOL instance.\r
+  @param  MediaId                The media id that the write request is for.\r
+  @param  LBA                    The starting logical block address to read from on the device.\r
+                                 The caller is responsible for writing to only legitimate locations.\r
+  @param  BufferSize             The size of the Buffer in bytes. This must be a multiple of the\r
+                                 intrinsic block size of the device.\r
+  @param  Buffer                 A pointer to the destination buffer for the data. The caller\r
+                                 is responsible for either having implicit or explicit ownership\r
+                                 of the buffer.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CEATABlockWriteBlocks (\r
+  IN  EFI_BLOCK_IO_PROTOCOL   *This,\r
+  IN  UINT32                  MediaId,\r
+  IN  EFI_LBA                 LBA,\r
+  IN  UINTN                   BufferSize,\r
+  IN  VOID                    *Buffer\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  CARD_DATA                   *CardData;\r
+  UINT32                      TransferSize;\r
+  UINT8                       *pBuf;\r
+  UINT32                      Index;\r
+  UINT64                      Address;\r
+  UINT32                      Remainder;\r
+  UINT64                      CEATALBA;\r
+  UINT32                      BoundarySize;\r
+\r
+\r
+  Status       = EFI_SUCCESS;\r
+  CardData     = CARD_DATA_FROM_THIS(This);\r
+  pBuf         = Buffer;\r
+  Index        = 0;\r
+  Address      = MultU64x32(LBA, CardData->BlockIoMedia.BlockSize);\r
+  BoundarySize = CardData->SDHostIo->HostCapability.BoundarySize;\r
+\r
+\r
+  if (!Buffer) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Exit;\r
+  }\r
+\r
+  if (MediaId != CardData->BlockIoMedia.MediaId) {\r
+    Status = EFI_MEDIA_CHANGED;\r
+    goto Exit;\r
+  }\r
+\r
+  if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {\r
+    Status = EFI_BAD_BUFFER_SIZE;\r
+    goto Exit;\r
+  }\r
+\r
+  if (BufferSize == 0) {\r
+    Status = EFI_SUCCESS;\r
+    goto Exit;\r
+  }\r
+\r
+  if (CardData->BlockIoMedia.ReadOnly) {\r
+    Status = EFI_WRITE_PROTECTED;\r
+    goto Exit;\r
+  }\r
+\r
+  if ((Address + BufferSize) > MultU64x32 (CardData->BlockIoMedia.LastBlock + 1, CardData->BlockIoMedia.BlockSize)) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Exit;\r
+  }\r
+\r
+  CardData->NeedFlush = TRUE;\r
+\r
+  do {\r
+    if (BufferSize < BoundarySize) {\r
+      TransferSize = (UINT32)BufferSize;\r
+    } else {\r
+      TransferSize = BoundarySize;\r
+    }\r
+\r
+    Address += Index * TransferSize;\r
+    CEATALBA = DivU64x32Remainder (Address, DATA_UNIT_SIZE, &Remainder);\r
+    ASSERT(Remainder == 0);\r
+\r
+    Status = WriteDMAExt (\r
+               CardData,\r
+               CEATALBA,\r
+               pBuf,\r
+               (UINT16)(TransferSize / DATA_UNIT_SIZE)\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+     DEBUG((EFI_D_ERROR, "Write Failed at 0x%x, Index %d, Size 0x%x\n", Address, Index, TransferSize));\r
+     This->Reset (This, TRUE);\r
+     goto Exit;\r
+    }\r
+    BufferSize -= TransferSize;\r
+    pBuf       += TransferSize;\r
+    Index ++;\r
+  } while (BufferSize != 0);\r
+\r
+\r
+Exit:\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.\r
+    (In this driver, this function just returns EFI_SUCCESS.)\r
+\r
+  @param  This                   The EFI_BLOCK_IO_PROTOCOL instance.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval Others\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CEATABlockFlushBlocks (\r
+  IN  EFI_BLOCK_IO_PROTOCOL   *This\r
+  )\r
+{\r
+\r
+  EFI_STATUS                  Status;\r
+  CARD_DATA                   *CardData;\r
+\r
+  CardData  = CARD_DATA_FROM_THIS(This);\r
+\r
+  if (CardData->NeedFlush) {\r
+    CardData->NeedFlush = FALSE;\r
+    Status = FlushCache (CardData);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  CEATA card BlockIo init function.\r
+\r
+  @param  CardData               Pointer to CARD_DATA.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval Others\r
+**/\r
+EFI_STATUS\r
+CEATABlockIoInit (\r
+  IN  CARD_DATA    *CardData\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    CEATA card BlockIo init function\r
+\r
+  Arguments:\r
+    CardData  -   Pointer to CARD_DATA\r
+\r
+  Returns:\r
+    EFI_SUCCESS - Success\r
+--*/\r
+{\r
+  EFI_STATUS   Status;\r
+  UINT64       MaxSize;\r
+  UINT32       Remainder;\r
+  //\r
+  //BlockIO protocol\r
+  //\r
+  CardData->BlockIo.Revision    = EFI_BLOCK_IO_PROTOCOL_REVISION;\r
+  CardData->BlockIo.Media       = &(CardData->BlockIoMedia);\r
+  CardData->BlockIo.Reset       = CEATABlockReset;\r
+  CardData->BlockIo.ReadBlocks  = CEATABlockReadBlocks ;\r
+  CardData->BlockIo.WriteBlocks = CEATABlockWriteBlocks;\r
+  CardData->BlockIo.FlushBlocks = CEATABlockFlushBlocks;\r
+\r
+  CardData->BlockIoMedia.MediaId          = 0;\r
+  CardData->BlockIoMedia.RemovableMedia   = FALSE;\r
+  CardData->BlockIoMedia.MediaPresent     = TRUE;\r
+  CardData->BlockIoMedia.LogicalPartition = FALSE;\r
+\r
+  if (CardData->CSDRegister.PERM_WRITE_PROTECT | CardData->CSDRegister.TMP_WRITE_PROTECT) {\r
+    CardData->BlockIoMedia.ReadOnly       = TRUE;\r
+  } else {\r
+    CardData->BlockIoMedia.ReadOnly       = FALSE;\r
+  }\r
+\r
+\r
+  CardData->BlockIoMedia.WriteCaching     = FALSE;\r
+  CardData->BlockIoMedia.IoAlign          = 1;\r
+\r
+  Status = IndentifyDevice (CardData);\r
+  if (EFI_ERROR (Status)) {\r
+   goto Exit;\r
+  }\r
+\r
+  //\r
+  //Some device does not support this feature\r
+  //\r
+\r
+  if (CardData->IndentifyDeviceData.MaxWritesPerAddress == 0) {\r
+    CardData->BlockIoMedia.ReadOnly       = TRUE;\r
+  }\r
+\r
+  CardData->BlockIoMedia.BlockSize        = (1 << CardData->IndentifyDeviceData.Sectorsize);\r
+  ASSERT(CardData->BlockIoMedia.BlockSize >= 12);\r
+\r
+\r
+  MaxSize = *(UINT64*)(CardData->IndentifyDeviceData.MaximumLBA);\r
+  MaxSize = MultU64x32 (MaxSize, 512);\r
+\r
+  Remainder = 0;\r
+  CardData->BlockNumber = DivU64x32Remainder (MaxSize, CardData->BlockIoMedia.BlockSize, &Remainder);\r
+  ASSERT(Remainder == 0);\r
+\r
+  CardData->BlockIoMedia.LastBlock        = (EFI_LBA)(CardData->BlockNumber - 1);\r
+\r
+\r
+Exit:\r
+  return Status;\r
+\r
+}\r
+\r
+\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/ComponentName.c b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/ComponentName.c
new file mode 100644 (file)
index 0000000..a047e85
--- /dev/null
@@ -0,0 +1,221 @@
+/** @file\r
+\r
+UEFI Component Name(2) protocol implementation for SD media device driver.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "SDMediaDevice.h"\r
+\r
+\r
+//\r
+// EFI Component Name Protocol\r
+//\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  gSDMediaDeviceName = {\r
+  SDMediaDeviceGetDriverName,\r
+  SDMediaDeviceGetControllerName,\r
+  "eng"\r
+};\r
+\r
+//\r
+// EFI Component Name 2 Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gSDMediaDeviceName2 = {\r
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) SDMediaDeviceGetDriverName,\r
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) SDMediaDeviceGetControllerName,\r
+  "en"\r
+};\r
+\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSDMediaDeviceDriverNameTable[] = {\r
+  { "eng;en", L"UEFI MMC/SD Media Device Driver" },\r
+  { NULL, NULL }\r
+};\r
+\r
+\r
+//\r
+// EFI Component Name Functions\r
+//\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+  This function retrieves the user readable name of a driver in the form of a\r
+  Unicode string. If the driver specified by This has a user readable name in\r
+  the language specified by Language, then a pointer to the driver name is\r
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+  by This does not support the language specified by Language,\r
+  then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language. This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified\r
+                                in RFC 3066 or ISO 639-2 language code format.\r
+\r
+  @param  DriverName[out]       A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                driver specified by This in the language\r
+                                specified by Language.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by\r
+                                This and the language specified by Language was\r
+                                returned in DriverName.\r
+\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SDMediaDeviceGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **DriverName\r
+  )\r
+{\r
+  return LookupUnicodeString2 (\r
+           Language,\r
+           This->SupportedLanguages,\r
+           mSDMediaDeviceDriverNameTable,\r
+           DriverName,\r
+           (BOOLEAN)(This == &gSDMediaDeviceName)\r
+           );\r
+}\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the controller\r
+  that is being managed by a driver.\r
+\r
+  This function retrieves the user readable name of the controller specified by\r
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+  driver specified by This has a user readable name in the language specified by\r
+  Language, then a pointer to the controller name is returned in ControllerName,\r
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently\r
+  managing the controller specified by ControllerHandle and ChildHandle,\r
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not\r
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  ControllerHandle[in]  The handle of a controller that the driver\r
+                                specified by This is managing.  This handle\r
+                                specifies the controller whose name is to be\r
+                                returned.\r
+\r
+  @param  ChildHandle[in]       The handle of the child controller to retrieve\r
+                                the name of.  This is an optional parameter that\r
+                                may be NULL.  It will be NULL for device\r
+                                drivers.  It will also be NULL for a bus drivers\r
+                                that wish to retrieve the name of the bus\r
+                                controller.  It will not be NULL for a bus\r
+                                driver that wishes to retrieve the name of a\r
+                                child controller.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language.  This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified in\r
+                                RFC 3066 or ISO 639-2 language code format.\r
+\r
+  @param  ControllerName[out]   A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                controller specified by ControllerHandle and\r
+                                ChildHandle in the language specified by\r
+                                Language from the point of view of the driver\r
+                                specified by This.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in\r
+                                the language specified by Language for the\r
+                                driver specified by This was returned in\r
+                                DriverName.\r
+\r
+  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+\r
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+                                EFI_HANDLE.\r
+\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently\r
+                                managing the controller specified by\r
+                                ControllerHandle and ChildHandle.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SDMediaDeviceGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,\r
+  IN  EFI_HANDLE                                      ControllerHandle,\r
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,\r
+  IN  CHAR8                                           *Language,\r
+  OUT CHAR16                                          **ControllerName\r
+  )\r
+{\r
+  EFI_STATUS           Status;\r
+  EFI_BLOCK_IO_PROTOCOL    *BlockIo;\r
+  CARD_DATA                *CardData;\r
+\r
+  //\r
+  // This is a device driver, so ChildHandle must be NULL.\r
+  //\r
+  if (ChildHandle != NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Get the device context\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiBlockIoProtocolGuid,\r
+                  (VOID **) &BlockIo,\r
+                  gSDMediaDeviceDriverBinding.DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  CardData  = CARD_DATA_FROM_THIS (BlockIo);\r
+\r
+  return LookupUnicodeString2 (\r
+           Language,\r
+           This->SupportedLanguages,\r
+           CardData->ControllerNameTable,\r
+           ControllerName,\r
+           (BOOLEAN)(This == &gSDMediaDeviceName)\r
+           );\r
+\r
+}\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/ComponentName.h b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/ComponentName.h
new file mode 100644 (file)
index 0000000..5182038
--- /dev/null
@@ -0,0 +1,145 @@
+/** @file\r
+\r
+This file contains the delarations for componet name routines.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _COMPONENT_NAME_H_\r
+#define _COMPONENT_NAME_H_\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+  This function retrieves the user readable name of a driver in the form of a\r
+  Unicode string. If the driver specified by This has a user readable name in\r
+  the language specified by Language, then a pointer to the driver name is\r
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+  by This does not support the language specified by Language,\r
+  then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language. This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified\r
+                                in RFC 3066 or ISO 639-2 language code format.\r
+\r
+  @param  DriverName[out]       A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                driver specified by This in the language\r
+                                specified by Language.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by\r
+                                This and the language specified by Language was\r
+                                returned in DriverName.\r
+\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SDMediaDeviceGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **DriverName\r
+  );\r
+\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the controller\r
+  that is being managed by a driver.\r
+\r
+  This function retrieves the user readable name of the controller specified by\r
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+  driver specified by This has a user readable name in the language specified by\r
+  Language, then a pointer to the controller name is returned in ControllerName,\r
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently\r
+  managing the controller specified by ControllerHandle and ChildHandle,\r
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not\r
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  ControllerHandle[in]  The handle of a controller that the driver\r
+                                specified by This is managing.  This handle\r
+                                specifies the controller whose name is to be\r
+                                returned.\r
+\r
+  @param  ChildHandle[in]       The handle of the child controller to retrieve\r
+                                the name of.  This is an optional parameter that\r
+                                may be NULL.  It will be NULL for device\r
+                                drivers.  It will also be NULL for a bus drivers\r
+                                that wish to retrieve the name of the bus\r
+                                controller.  It will not be NULL for a bus\r
+                                driver that wishes to retrieve the name of a\r
+                                child controller.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language.  This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified in\r
+                                RFC 3066 or ISO 639-2 language code format.\r
+\r
+  @param  ControllerName[out]   A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                controller specified by ControllerHandle and\r
+                                ChildHandle in the language specified by\r
+                                Language from the point of view of the driver\r
+                                specified by This.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in\r
+                                the language specified by Language for the\r
+                                driver specified by This was returned in\r
+                                DriverName.\r
+\r
+  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+\r
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+                                EFI_HANDLE.\r
+\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently\r
+                                managing the controller specified by\r
+                                ControllerHandle and ChildHandle.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SDMediaDeviceGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,\r
+  IN  EFI_HANDLE                                      ControllerHandle,\r
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,\r
+  IN  CHAR8                                           *Language,\r
+  OUT CHAR16                                          **ControllerName\r
+  );\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDBlockIo.c b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDBlockIo.c
new file mode 100644 (file)
index 0000000..584c541
--- /dev/null
@@ -0,0 +1,544 @@
+/** @file\r
+\r
+Block I/O protocol for MMC/SD device\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "SDMediaDevice.h"\r
+\r
+/**\r
+  Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.\r
+\r
+  @param  This                   The EFI_BLOCK_IO_PROTOCOL instance.\r
+  @param  ExtendedVerification   Indicates that the driver may perform a more exhaustive.\r
+                                 verification operation of the device during reset.\r
+                                 (This parameter is ingored in this driver.)\r
+\r
+  @retval EFI_SUCCESS                Success\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MMCSDBlockReset (\r
+  IN  EFI_BLOCK_IO_PROTOCOL   *This,\r
+  IN  BOOLEAN                 ExtendedVerification\r
+  )\r
+{\r
+  CARD_DATA                  *CardData;\r
+  EFI_SD_HOST_IO_PROTOCOL    *SDHostIo;\r
+\r
+  CardData  = CARD_DATA_FROM_THIS(This);\r
+  SDHostIo = CardData->SDHostIo;\r
+\r
+  return SDHostIo->ResetSDHost (SDHostIo, Reset_DAT_CMD);\r
+ }\r
+\r
+/**\r
+  Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.\r
+\r
+  @param  This                   The EFI_BLOCK_IO_PROTOCOL instance.\r
+  @param  MediaId                The media id that the write request is for.\r
+  @param  LBA                    The starting logical block address to read from on the device.\r
+                                 The caller is responsible for writing to only legitimate locations.\r
+  @param  BufferSize             The size of the Buffer in bytes. This must be a multiple of the\r
+                                 intrinsic block size of the device.\r
+  @param  Buffer                 A pointer to the destination buffer for the data. The caller\r
+                                 is responsible for either having implicit or explicit ownership\r
+                                 of the buffer.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MMCSDBlockReadBlocks (\r
+  IN  EFI_BLOCK_IO_PROTOCOL   *This,\r
+  IN  UINT32                  MediaId,\r
+  IN  EFI_LBA                 LBA,\r
+  IN  UINTN                   BufferSize,\r
+  OUT VOID                    *Buffer\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  UINT32                      Address;\r
+  CARD_DATA                   *CardData;\r
+  EFI_SD_HOST_IO_PROTOCOL     *SDHostIo;\r
+  UINT32                      RemainingLength;\r
+  UINT32                      TransferLength;\r
+  UINT8                       *BufferPointer;\r
+  BOOLEAN                     SectorAddressing;\r
+  UINTN                       TotalBlock;\r
+\r
+  DEBUG((EFI_D_INFO, "Read(LBA=%08lx, Buffer=%08x, Size=%08x)\n", LBA, Buffer, BufferSize));\r
+  Status   = EFI_SUCCESS;\r
+  CardData  = CARD_DATA_FROM_THIS(This);\r
+  SDHostIo = CardData->SDHostIo;\r
+  if (MediaId != CardData->BlockIoMedia.MediaId) {\r
+    return EFI_MEDIA_CHANGED;\r
+  }\r
+\r
+  if (ModU64x32 (BufferSize,CardData->BlockIoMedia.BlockSize) != 0) {\r
+    return EFI_BAD_BUFFER_SIZE;\r
+  }\r
+  if ((CardData->CardType == SDMemoryCard2High) || (CardData->CardType == MMCCardHighCap)) {\r
+    SectorAddressing = TRUE;\r
+  } else {\r
+    SectorAddressing = FALSE;\r
+  }\r
+  if (SectorAddressing) {\r
+    //\r
+    //Block Address\r
+    //\r
+    Address = (UINT32)DivU64x32 (MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize), 512);\r
+  } else {\r
+    //\r
+    //Byte Address\r
+    //\r
+    Address  = (UINT32)MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize);\r
+  }\r
+  TotalBlock = (UINTN) DivU64x32 (BufferSize, CardData->BlockIoMedia.BlockSize);\r
+  if (LBA + TotalBlock > CardData->BlockIoMedia.LastBlock + 1) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+\r
+  if (!Buffer) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks:Invalid parameter \r\n"));\r
+    goto Done;\r
+  }\r
+\r
+  if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {\r
+    Status = EFI_BAD_BUFFER_SIZE;\r
+    DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: Bad buffer size \r\n"));\r
+    goto Done;\r
+  }\r
+\r
+  if (BufferSize == 0) {\r
+    Status = EFI_SUCCESS;\r
+    goto Done;\r
+  }\r
+\r
+\r
+\r
+\r
+    BufferPointer   = Buffer;\r
+    RemainingLength = (UINT32)BufferSize;\r
+\r
+    while (RemainingLength > 0) {\r
+    if ((BufferSize > CardData->BlockIoMedia.BlockSize)) {\r
+      if (RemainingLength > SDHostIo->HostCapability.BoundarySize) {\r
+        TransferLength = SDHostIo->HostCapability.BoundarySize;\r
+      } else {\r
+        TransferLength = RemainingLength;\r
+      }\r
+\r
+      if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) {\r
+        if (!(CardData->ExtCSDRegister.CARD_TYPE & (BIT2 | BIT3))) {\r
+      Status = SendCommand (\r
+                     CardData,\r
+                     SET_BLOCKLEN,\r
+                     CardData->BlockIoMedia.BlockSize,\r
+                     NoData,\r
+                     NULL,\r
+                     0,\r
+                     ResponseR1,\r
+                     TIMEOUT_COMMAND,\r
+                     (UINT32*)&(CardData->CardStatus)\r
+                     );\r
+          if (EFI_ERROR (Status)) {\r
+            break;\r
+          }\r
+        }\r
+        Status = SendCommand (\r
+                   CardData,\r
+                   SET_BLOCK_COUNT,\r
+                   TransferLength / CardData->BlockIoMedia.BlockSize,\r
+                   NoData,\r
+                   NULL,\r
+                   0,\r
+                   ResponseR1,\r
+                   TIMEOUT_COMMAND,\r
+                   (UINT32*)&(CardData->CardStatus)\r
+                   );\r
+        if (EFI_ERROR (Status)) {\r
+          break;\r
+        }\r
+      }\r
+      Status = SendCommand (\r
+                 CardData,\r
+                 READ_MULTIPLE_BLOCK,\r
+                 Address,\r
+                 InData,\r
+                 CardData->AlignedBuffer,\r
+                 TransferLength,\r
+                 ResponseR1,\r
+                 TIMEOUT_DATA,\r
+                 (UINT32*)&(CardData->CardStatus)\r
+                 );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: READ_MULTIPLE_BLOCK -> Fail\n"));\r
+        break;\r
+      }\r
+    } else {\r
+      if (RemainingLength > CardData->BlockIoMedia.BlockSize) {\r
+        TransferLength = CardData->BlockIoMedia.BlockSize;\r
+      } else {\r
+        TransferLength = RemainingLength;\r
+      }\r
+\r
+      Status = SendCommand (\r
+                 CardData,\r
+                 READ_SINGLE_BLOCK,\r
+                 Address,\r
+                 InData,\r
+                 CardData->AlignedBuffer,\r
+                 (UINT32)TransferLength,\r
+                 ResponseR1,\r
+                 TIMEOUT_DATA,\r
+                 (UINT32*)&(CardData->CardStatus)\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: READ_SINGLE_BLOCK -> Fail\n"));\r
+        break;\r
+      }\r
+    }\r
+      CopyMem (BufferPointer, CardData->AlignedBuffer, TransferLength);\r
+\r
+    if (SectorAddressing) {\r
+        //\r
+        //Block Address\r
+        //\r
+        Address += TransferLength / 512;\r
+      } else {\r
+        //\r
+        //Byte Address\r
+        //\r
+        Address += TransferLength;\r
+      }\r
+      BufferPointer   += TransferLength;\r
+      RemainingLength -= TransferLength;\r
+   }\r
+\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    if ((CardData->CardType == SDMemoryCard) ||\r
+        (CardData->CardType == SDMemoryCard2)||\r
+        (CardData->CardType == SDMemoryCard2High)) {\r
+         SendCommand (\r
+           CardData,\r
+           STOP_TRANSMISSION,\r
+           0,\r
+           NoData,\r
+           NULL,\r
+           0,\r
+           ResponseR1b,\r
+           TIMEOUT_COMMAND,\r
+           (UINT32*)&(CardData->CardStatus)\r
+           );\r
+    } else {\r
+       SendCommand (\r
+         CardData,\r
+         STOP_TRANSMISSION,\r
+         0,\r
+         NoData,\r
+         NULL,\r
+         0,\r
+         ResponseR1,\r
+         TIMEOUT_COMMAND,\r
+         (UINT32*)&(CardData->CardStatus)\r
+         );\r
+    }\r
+\r
+  }\r
+\r
+\r
+Done:\r
+  DEBUG((EFI_D_INFO, "MMCSDBlockReadBlocks: Status = %r\n", Status));\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.\r
+\r
+  @param  This                   The EFI_BLOCK_IO_PROTOCOL instance.\r
+  @param  MediaId                The media id that the write request is for.\r
+  @param  LBA                    The starting logical block address to read from on the device.\r
+                                 The caller is responsible for writing to only legitimate locations.\r
+  @param  BufferSize             The size of the Buffer in bytes. This must be a multiple of the\r
+                                 intrinsic block size of the device.\r
+  @param  Buffer                 A pointer to the destination buffer for the data. The caller\r
+                                 is responsible for either having implicit or explicit ownership\r
+                                 of the buffer.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MMCSDBlockWriteBlocks (\r
+  IN  EFI_BLOCK_IO_PROTOCOL   *This,\r
+  IN  UINT32                  MediaId,\r
+  IN  EFI_LBA                 LBA,\r
+  IN  UINTN                   BufferSize,\r
+  IN  VOID                    *Buffer\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  UINT32                      Address;\r
+  CARD_DATA                   *CardData;\r
+  EFI_SD_HOST_IO_PROTOCOL     *SDHostIo;\r
+  UINT32                      RemainingLength;\r
+  UINT32                      TransferLength;\r
+  UINT8                       *BufferPointer;\r
+  BOOLEAN                     SectorAddressing;\r
+\r
+  DEBUG((EFI_D_INFO, "Write(LBA=%08lx, Buffer=%08x, Size=%08x)\n", LBA, Buffer, BufferSize));\r
+  Status   = EFI_SUCCESS;\r
+  CardData  = CARD_DATA_FROM_THIS(This);\r
+  SDHostIo = CardData->SDHostIo;\r
+  if ((CardData->CardType == SDMemoryCard2High) || (CardData->CardType == MMCCardHighCap)) {\r
+    SectorAddressing = TRUE;\r
+  } else {\r
+    SectorAddressing = FALSE;\r
+  }\r
+  if (SectorAddressing) {\r
+    //\r
+    //Block Address\r
+    //\r
+    Address = (UINT32)DivU64x32 (MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize), 512);\r
+  } else {\r
+    //\r
+    //Byte Address\r
+    //\r
+    Address = (UINT32)MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize);\r
+  }\r
+\r
+  if (!Buffer) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Invalid parameter \r\n"));\r
+    goto Done;\r
+  }\r
+\r
+  if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {\r
+    Status = EFI_BAD_BUFFER_SIZE;\r
+    DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Bad buffer size \r\n"));\r
+    goto Done;\r
+  }\r
+\r
+  if (BufferSize == 0) {\r
+    Status = EFI_SUCCESS;\r
+    goto Done;\r
+  }\r
+\r
+  if (This->Media->ReadOnly == TRUE) {\r
+    Status = EFI_WRITE_PROTECTED;\r
+    DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Write protected \r\n"));\r
+    goto Done;\r
+  }\r
+\r
+\r
+\r
+    BufferPointer   = Buffer;\r
+    RemainingLength = (UINT32)BufferSize;\r
+\r
+    while (RemainingLength > 0) {\r
+    if ((BufferSize > CardData->BlockIoMedia.BlockSize) ) {\r
+      if (RemainingLength > SDHostIo->HostCapability.BoundarySize) {\r
+        TransferLength = SDHostIo->HostCapability.BoundarySize;\r
+      } else {\r
+        TransferLength = RemainingLength;\r
+      }\r
+\r
+      if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) {\r
+\r
+        if (!(CardData->ExtCSDRegister.CARD_TYPE & (BIT2 | BIT3)))  {\r
+            Status = SendCommand (\r
+                       CardData,\r
+                       SET_BLOCKLEN,\r
+                       CardData->BlockIoMedia.BlockSize,\r
+                       NoData,\r
+                       NULL,\r
+                       0,\r
+                       ResponseR1,\r
+                       TIMEOUT_COMMAND,\r
+                       (UINT32*)&(CardData->CardStatus)\r
+                       );\r
+            if (EFI_ERROR (Status)) {\r
+              break;\r
+            }\r
+        }\r
+        Status = SendCommand (\r
+                      CardData,\r
+                   SET_BLOCK_COUNT,\r
+                   TransferLength / CardData->BlockIoMedia.BlockSize,\r
+                      NoData,\r
+                      NULL,\r
+                      0,\r
+                      ResponseR1,\r
+                      TIMEOUT_COMMAND,\r
+                      (UINT32*)&(CardData->CardStatus)\r
+                      );\r
+        if (EFI_ERROR (Status)) {\r
+          break;\r
+        }\r
+      }\r
+\r
+      CopyMem (CardData->AlignedBuffer, BufferPointer, TransferLength);\r
+\r
+      Status = SendCommand (\r
+                 CardData,\r
+                 WRITE_MULTIPLE_BLOCK,\r
+                 Address,\r
+                 OutData,\r
+                 CardData->AlignedBuffer,\r
+                 (UINT32)TransferLength,\r
+                 ResponseR1,\r
+                 TIMEOUT_DATA,\r
+                 (UINT32*)&(CardData->CardStatus)\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: WRITE_MULTIPLE_BLOCK -> Fail\n"));\r
+        break;\r
+      }\r
+    } else {\r
+      if (RemainingLength > CardData->BlockIoMedia.BlockSize) {\r
+        TransferLength = CardData->BlockIoMedia.BlockSize;\r
+      } else {\r
+        TransferLength = RemainingLength;\r
+      }\r
+\r
+      CopyMem (CardData->AlignedBuffer, BufferPointer, TransferLength);\r
+\r
+      Status = SendCommand (\r
+                 CardData,\r
+                 WRITE_BLOCK,\r
+                 Address,\r
+                 OutData,\r
+                 CardData->AlignedBuffer,\r
+                 (UINT32)TransferLength,\r
+                 ResponseR1,\r
+                 TIMEOUT_DATA,\r
+                 (UINT32*)&(CardData->CardStatus)\r
+                 );\r
+    }\r
+    if (SectorAddressing) {\r
+        //\r
+        //Block Address\r
+        //\r
+        Address += TransferLength / 512;\r
+      } else {\r
+        //\r
+        //Byte Address\r
+        //\r
+        Address += TransferLength;\r
+      }\r
+      BufferPointer   += TransferLength;\r
+      RemainingLength -= TransferLength;\r
+\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    SendCommand (\r
+      CardData,\r
+      STOP_TRANSMISSION,\r
+      0,\r
+      NoData,\r
+      NULL,\r
+      0,\r
+      ResponseR1b,\r
+      TIMEOUT_COMMAND,\r
+      (UINT32*)&(CardData->CardStatus)\r
+      );\r
+\r
+  }\r
+\r
+\r
+Done:\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.\r
+    (In this driver, this function just returns EFI_SUCCESS.)\r
+\r
+  @param  This                   The EFI_BLOCK_IO_PROTOCOL instance.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval Others\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MMCSDBlockFlushBlocks (\r
+  IN  EFI_BLOCK_IO_PROTOCOL   *This\r
+  )\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  MMC/SD card BlockIo init function.\r
+\r
+  @param  CardData               Pointer to CARD_DATA.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval Others\r
+**/\r
+EFI_STATUS\r
+MMCSDBlockIoInit (\r
+  IN  CARD_DATA    *CardData\r
+  )\r
+{\r
+  //\r
+  //BlockIO protocol\r
+  //\r
+  CardData->BlockIo.Revision    = EFI_BLOCK_IO_PROTOCOL_REVISION;\r
+  CardData->BlockIo.Media       = &(CardData->BlockIoMedia);\r
+  CardData->BlockIo.Reset       = MMCSDBlockReset;\r
+  CardData->BlockIo.ReadBlocks  = MMCSDBlockReadBlocks ;\r
+  CardData->BlockIo.WriteBlocks = MMCSDBlockWriteBlocks;\r
+  CardData->BlockIo.FlushBlocks = MMCSDBlockFlushBlocks;\r
+\r
+  CardData->BlockIoMedia.MediaId          = 0;\r
+  CardData->BlockIoMedia.RemovableMedia   = FALSE;\r
+  CardData->BlockIoMedia.MediaPresent     = TRUE;\r
+  CardData->BlockIoMedia.LogicalPartition = FALSE;\r
+\r
+  if (CardData->CSDRegister.PERM_WRITE_PROTECT || CardData->CSDRegister.TMP_WRITE_PROTECT) {\r
+    CardData->BlockIoMedia.ReadOnly         = TRUE;\r
+  } else {\r
+    CardData->BlockIoMedia.ReadOnly         = FALSE;\r
+  }\r
+\r
+\r
+  CardData->BlockIoMedia.WriteCaching     = FALSE;\r
+  CardData->BlockIoMedia.BlockSize        = CardData->BlockLen;\r
+  CardData->BlockIoMedia.IoAlign          = 1;\r
+  CardData->BlockIoMedia.LastBlock        = (EFI_LBA)(CardData->BlockNumber - 1);\r
+\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDTransfer.c b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDTransfer.c
new file mode 100644 (file)
index 0000000..5d34332
--- /dev/null
@@ -0,0 +1,1716 @@
+/** @file\r
+\r
+MMC/SD transfer specific functions\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "SDMediaDevice.h"\r
+\r
+/**\r
+  Check card status, print the debug info and check the error\r
+\r
+  @param  Status                Status got from card status register.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_DEVICE_ERROR\r
+\r
+**/\r
+EFI_STATUS\r
+CheckCardStatus (\r
+  IN  UINT32    Status\r
+  )\r
+{\r
+  CARD_STATUS    *CardStatus;\r
+  CardStatus = (CARD_STATUS*)(&Status);\r
+\r
+  if (CardStatus->ADDRESS_OUT_OF_RANGE) {\r
+    DEBUG ((EFI_D_ERROR, "CardStatus: ADDRESS_OUT_OF_RANGE\n"));\r
+  }\r
+\r
+  if (CardStatus->ADDRESS_MISALIGN) {\r
+    DEBUG ((EFI_D_ERROR, "CardStatus: ADDRESS_MISALIGN\n"));\r
+  }\r
+\r
+  if (CardStatus->BLOCK_LEN_ERROR) {\r
+    DEBUG ((EFI_D_ERROR, "CardStatus: BLOCK_LEN_ERROR\n"));\r
+  }\r
+\r
+  if (CardStatus->ERASE_SEQ_ERROR) {\r
+    DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_SEQ_ERROR\n"));\r
+  }\r
+\r
+  if (CardStatus->ERASE_PARAM) {\r
+    DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_PARAM\n"));\r
+  }\r
+\r
+  if (CardStatus->WP_VIOLATION) {\r
+    DEBUG ((EFI_D_ERROR, "CardStatus: WP_VIOLATION\n"));\r
+  }\r
+\r
+  if (CardStatus->CARD_IS_LOCKED) {\r
+    DEBUG ((EFI_D_ERROR, "CardStatus: CARD_IS_LOCKED\n"));\r
+  }\r
+\r
+  if (CardStatus->LOCK_UNLOCK_FAILED) {\r
+    DEBUG ((EFI_D_ERROR, "CardStatus: LOCK_UNLOCK_FAILED\n"));\r
+  }\r
+\r
+  if (CardStatus->COM_CRC_ERROR) {\r
+    DEBUG ((EFI_D_ERROR, "CardStatus: COM_CRC_ERROR\n"));\r
+  }\r
+\r
+  if (CardStatus->ILLEGAL_COMMAND) {\r
+    DEBUG ((EFI_D_ERROR, "CardStatus: ILLEGAL_COMMAND\n"));\r
+  }\r
+\r
+  if (CardStatus->CARD_ECC_FAILED) {\r
+    DEBUG ((EFI_D_ERROR, "CardStatus: CARD_ECC_FAILED\n"));\r
+  }\r
+\r
+  if (CardStatus->CC_ERROR) {\r
+    DEBUG ((EFI_D_ERROR, "CardStatus: CC_ERROR\n"));\r
+  }\r
+\r
+  if (CardStatus->ERROR) {\r
+    DEBUG ((EFI_D_ERROR, "CardStatus: ERROR\n"));\r
+  }\r
+\r
+  if (CardStatus->UNDERRUN) {\r
+    DEBUG ((EFI_D_ERROR, "CardStatus: UNDERRUN\n"));\r
+  }\r
+\r
+  if (CardStatus->OVERRUN) {\r
+    DEBUG ((EFI_D_ERROR, "CardStatus: OVERRUN\n"));\r
+  }\r
+\r
+  if (CardStatus->CID_CSD_OVERWRITE) {\r
+    DEBUG ((EFI_D_ERROR, "CardStatus: CID_CSD_OVERWRITE\n"));\r
+  }\r
+\r
+  if (CardStatus->WP_ERASE_SKIP) {\r
+    DEBUG ((EFI_D_ERROR, "CardStatus: WP_ERASE_SKIP\n"));\r
+  }\r
+\r
+  if (CardStatus->ERASE_RESET) {\r
+    DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_RESET\n"));\r
+  }\r
+\r
+  if (CardStatus->SWITCH_ERROR) {\r
+    DEBUG ((EFI_D_ERROR, "CardStatus: SWITCH_ERROR\n"));\r
+  }\r
+\r
+  if ((Status & 0xFCFFA080) != 0) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Send command by using Host IO protocol\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  CommandIndex          The command index to set the command index field of command register.\r
+  @param  Argument              Command argument to set the argument field of command register.\r
+  @param  DataType              TRANSFER_TYPE, indicates no data, data in or data out.\r
+  @param  Buffer                Contains the data read from / write to the device.\r
+  @param  BufferSize            The size of the buffer.\r
+  @param  ResponseType          RESPONSE_TYPE.\r
+  @param  TimeOut               Time out value in 1 ms unit.\r
+  @param  ResponseData          Depending on the ResponseType, such as CSD or card status.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_INVALID_PARAMETER\r
+  @retval EFI_UNSUPPORTED\r
+  @retval EFI_DEVICE_ERROR\r
+\r
+**/\r
+EFI_STATUS\r
+SendCommand (\r
+  IN   CARD_DATA                  *CardData,\r
+  IN   UINT16                     CommandIndex,\r
+  IN   UINT32                     Argument,\r
+  IN   TRANSFER_TYPE              DataType,\r
+  IN   UINT8                      *Buffer, OPTIONAL\r
+  IN   UINT32                     BufferSize,\r
+  IN   RESPONSE_TYPE              ResponseType,\r
+  IN   UINT32                     TimeOut,\r
+  OUT  UINT32                     *ResponseData\r
+  )\r
+{\r
+\r
+  EFI_STATUS    Status;\r
+  EFI_SD_HOST_IO_PROTOCOL    *SDHostIo;\r
+  SDHostIo = CardData->SDHostIo;\r
+  if (CardData->CardType != MMCCard && CardData->CardType != MMCCardHighCap) {\r
+    CommandIndex |= AUTO_CMD12_ENABLE;\r
+  }\r
+\r
+  Status = SDHostIo->SendCommand (\r
+                   SDHostIo,\r
+                   CommandIndex,\r
+                   Argument,\r
+                   DataType,\r
+                   Buffer,\r
+                   BufferSize,\r
+                   ResponseType,\r
+                   TimeOut,\r
+                   ResponseData\r
+                   );\r
+  if (!EFI_ERROR (Status)) {\r
+    if (ResponseType == ResponseR1 || ResponseType == ResponseR1b) {\r
+      ASSERT(ResponseData != NULL);\r
+      Status = CheckCardStatus (*ResponseData);\r
+    }\r
+  } else {\r
+    SDHostIo->ResetSDHost (SDHostIo, Reset_DAT_CMD);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Send the card APP_CMD command with the following command indicated by CommandIndex\r
+\r
+  @param  CardData              Pointer to CARD_DATA.\r
+  @param  CommandIndex          The command index to set the command index field of command register.\r
+  @param  Argument              Command argument to set the argument field of command register.\r
+  @param  DataType              TRANSFER_TYPE, indicates no data, data in or data out.\r
+  @param  Buffer                Contains the data read from / write to the device.\r
+  @param  BufferSize            The size of the buffer.\r
+  @param  ResponseType          RESPONSE_TYPE.\r
+  @param  TimeOut               Time out value in 1 ms unit.\r
+  @param  ResponseData          Depending on the ResponseType, such as CSD or card status.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_INVALID_PARAMETER\r
+  @retval EFI_UNSUPPORTED\r
+  @retval EFI_DEVICE_ERROR\r
+\r
+**/\r
+EFI_STATUS\r
+SendAppCommand (\r
+  IN   CARD_DATA                  *CardData,\r
+  IN   UINT16                     CommandIndex,\r
+  IN   UINT32                     Argument,\r
+  IN   TRANSFER_TYPE              DataType,\r
+  IN   UINT8                      *Buffer, OPTIONAL\r
+  IN   UINT32                     BufferSize,\r
+  IN   RESPONSE_TYPE              ResponseType,\r
+  IN   UINT32                     TimeOut,\r
+  OUT  UINT32                     *ResponseData\r
+  )\r
+{\r
+\r
+  EFI_STATUS                 Status;\r
+  EFI_SD_HOST_IO_PROTOCOL    *SDHostIo;\r
+  UINT8                      Index;\r
+\r
+  SDHostIo = CardData->SDHostIo;\r
+  Status = EFI_SUCCESS;\r
+\r
+  for (Index = 0; Index < 2; Index++) {\r
+    Status = SDHostIo->SendCommand (\r
+                         SDHostIo,\r
+                         APP_CMD,\r
+                         (CardData->Address << 16),\r
+                         NoData,\r
+                         NULL,\r
+                         0,\r
+                         ResponseR1,\r
+                         TIMEOUT_COMMAND,\r
+                         (UINT32*)&(CardData->CardStatus)\r
+                         );\r
+    if (!EFI_ERROR (Status)) {\r
+        Status = CheckCardStatus (*(UINT32*)&(CardData->CardStatus));\r
+        if (CardData->CardStatus.SAPP_CMD != 1) {\r
+          Status = EFI_DEVICE_ERROR;\r
+        }\r
+        if (!EFI_ERROR (Status)) {\r
+           break;\r
+        }\r
+    } else {\r
+       SDHostIo->ResetSDHost (SDHostIo, Reset_Auto);\r
+    }\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  if (CardData->CardType != MMCCard && CardData->CardType != MMCCardHighCap) {\r
+    CommandIndex |= AUTO_CMD12_ENABLE;\r
+  }\r
+\r
+  Status = SDHostIo->SendCommand (\r
+                       SDHostIo,\r
+                       CommandIndex,\r
+                       Argument,\r
+                       DataType,\r
+                       Buffer,\r
+                       BufferSize,\r
+                       ResponseType,\r
+                       TimeOut,\r
+                       ResponseData\r
+                       );\r
+  if (!EFI_ERROR (Status)) {\r
+    if (ResponseType == ResponseR1 || ResponseType == ResponseR1b) {\r
+      ASSERT(ResponseData != NULL);\r
+      Status = CheckCardStatus (*ResponseData);\r
+    }\r
+  } else {\r
+    SDHostIo->ResetSDHost (SDHostIo, Reset_Auto);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Send the card FAST_IO command\r
+\r
+  @param  CardData               Pointer to CARD_DATA.\r
+  @param  RegisterAddress        Register Address.\r
+  @param  RegisterData           Pointer to register Data.\r
+  @param  Write                  TRUE for write, FALSE for read.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_UNSUPPORTED\r
+  @retval EFI_INVALID_PARAMETER\r
+  @retval EFI_DEVICE_ERROR\r
+\r
+**/\r
+EFI_STATUS\r
+FastIO (\r
+  IN      CARD_DATA   *CardData,\r
+  IN      UINT8       RegisterAddress,\r
+  IN  OUT UINT8       *RegisterData,\r
+  IN      BOOLEAN     Write\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  UINT32                     Argument;\r
+  UINT32                     Data;\r
+\r
+  Status   = EFI_SUCCESS;\r
+\r
+  if (RegisterData == NULL) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Exit;\r
+  }\r
+\r
+  Argument = (CardData->Address << 16) | (RegisterAddress << 8);\r
+  if (Write) {\r
+    Argument |= BIT15 | (*RegisterData);\r
+  }\r
+\r
+  Status = SendCommand (\r
+             CardData,\r
+             FAST_IO,\r
+             Argument,\r
+             NoData,\r
+             NULL,\r
+             0,\r
+             ResponseR4,\r
+             TIMEOUT_COMMAND,\r
+             &Data\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+\r
+  if ((Data & BIT15) == 0) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if (!Write) {\r
+   *RegisterData = (UINT8)Data;\r
+  }\r
+\r
+Exit:\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Send the card GO_INACTIVE_STATE command.\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+\r
+  @return EFI_SUCCESS\r
+  @return others\r
+\r
+**/\r
+EFI_STATUS\r
+PutCardInactive (\r
+  IN  CARD_DATA   *CardData\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+\r
+\r
+  Status = SendCommand (\r
+             CardData,\r
+             GO_INACTIVE_STATE,\r
+             (CardData->Address << 16),\r
+             NoData,\r
+             NULL,\r
+             0,\r
+             ResponseNo,\r
+             TIMEOUT_COMMAND,\r
+             NULL\r
+             );\r
+\r
+  return Status;\r
+\r
+}\r
+\r
+/**\r
+  Get card interested information for CSD rergister\r
+\r
+  @param  CardData               Pointer to CARD_DATA.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_UNSUPPORTED\r
+  @retval EFI_INVALID_PARAMETER\r
+\r
+**/\r
+EFI_STATUS\r
+CaculateCardParameter (\r
+  IN  CARD_DATA    *CardData\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  UINT32         Frequency;\r
+  UINT32         Multiple;\r
+  UINT32         CSize;\r
+  CSD_SDV2       *CsdSDV2;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  switch (CardData->CSDRegister.TRAN_SPEED & 0x7) {\r
+    case 0:\r
+      Frequency = 100 * 1000;\r
+      break;\r
+\r
+    case 1:\r
+      Frequency = 1 * 1000 * 1000;\r
+      break;\r
+\r
+    case 2:\r
+      Frequency = 10 * 1000 * 1000;\r
+      break;\r
+\r
+    case 3:\r
+      Frequency = 100 * 1000 * 1000;\r
+      break;\r
+\r
+    default:\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Exit;\r
+  }\r
+\r
+  switch ((CardData->CSDRegister.TRAN_SPEED >> 3) & 0xF) {\r
+    case 1:\r
+      Multiple = 10;\r
+      break;\r
+\r
+    case 2:\r
+      Multiple = 12;\r
+      break;\r
+\r
+    case 3:\r
+      Multiple = 13;\r
+      break;\r
+\r
+    case 4:\r
+      Multiple = 15;\r
+      break;\r
+\r
+    case 5:\r
+      Multiple = 20;\r
+      break;\r
+\r
+    case 6:\r
+      if (CardData->CardType == MMCCard  || CardData->CardType == MMCCardHighCap) {\r
+        Multiple = 26;\r
+      } else {\r
+        Multiple = 25;\r
+      }\r
+      break;\r
+\r
+    case 7:\r
+      Multiple = 30;\r
+      break;\r
+\r
+    case 8:\r
+      Multiple = 35;\r
+      break;\r
+\r
+    case 9:\r
+      Multiple = 40;\r
+      break;\r
+\r
+    case 10:\r
+      Multiple = 45;\r
+      break;\r
+\r
+    case 11:\r
+      if (CardData->CardType == MMCCard  || CardData->CardType == MMCCardHighCap) {\r
+        Multiple = 52;\r
+      } else {\r
+        Multiple = 50;\r
+      }\r
+      break;\r
+\r
+    case 12:\r
+      Multiple = 55;\r
+      break;\r
+\r
+    case 13:\r
+      Multiple = 60;\r
+      break;\r
+\r
+    case 14:\r
+      Multiple = 70;\r
+      break;\r
+\r
+    case 15:\r
+      Multiple = 80;\r
+      break;\r
+\r
+    default:\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Exit;\r
+  }\r
+\r
+  Frequency = Frequency * Multiple / 10;\r
+  CardData->MaxFrequency = Frequency;\r
+\r
+  CardData->BlockLen = 1 << CardData->CSDRegister.READ_BL_LEN;\r
+\r
+  if (CardData->CardType == SDMemoryCard2High) {\r
+    ASSERT(CardData->CSDRegister.CSD_STRUCTURE == 1);\r
+    CsdSDV2 = (CSD_SDV2*)&CardData->CSDRegister;\r
+    //\r
+    // The SD Spec 2.0 says (CSize + 1) * 512K is the total size, so block numbber is (CSize + 1) * 1K\r
+    // the K here means 1024 not 1000\r
+    //\r
+    CardData->BlockNumber = DivU64x32 (MultU64x32 (CsdSDV2->C_SIZE + 1, 512 * 1024) , CardData->BlockLen);\r
+  } else {\r
+    //\r
+    // For MMC card > 2G, the block number will be recaculate later\r
+    //\r
+    CSize = CardData->CSDRegister.C_SIZELow2 | (CardData->CSDRegister.C_SIZEHigh10 << 2);\r
+    CardData->BlockNumber = MultU64x32 (LShiftU64 (1, CardData->CSDRegister.C_SIZE_MULT + 2), CSize + 1);\r
+  }\r
+\r
+  //\r
+  //For >= 2G card, BlockLen may be 1024, but the transfer size is still 512 bytes\r
+  //\r
+  if (CardData->BlockLen > 512) {\r
+    CardData->BlockNumber = DivU64x32 (MultU64x32 (CardData->BlockNumber, CardData->BlockLen), 512);\r
+    CardData->BlockLen    = 512;\r
+  }\r
+\r
+  DEBUG((\r
+    EFI_D_INFO,\r
+          "CalculateCardParameter: Card Size: 0x%lx\n", MultU64x32 (CardData->BlockNumber, CardData->BlockLen)\r
+    ));\r
+\r
+Exit:\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Test the bus width setting for MMC card.It is used only for verification purpose.\r
+\r
+  @param  CardData               Pointer to CARD_DATA.\r
+  @param  Width                  1, 4, 8 bits.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_UNSUPPORTED\r
+  @retval EFI_INVALID_PARAMETER\r
+\r
+**/\r
+EFI_STATUS\r
+MMCCardBusWidthTest (\r
+  IN  CARD_DATA             *CardData,\r
+  IN  UINT32                Width\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  UINT64                     Data;\r
+  UINT64                     Value;\r
+\r
+  ASSERT(CardData != NULL);\r
+\r
+\r
+  Value = 0;\r
+\r
+  switch (Width) {\r
+    case 1:\r
+      Data = 0x80;\r
+      break;\r
+\r
+    case 4:\r
+      Data = 0x5A;\r
+      break;\r
+\r
+    case 8:\r
+      Data = 0xAA55;\r
+      break;\r
+\r
+    default:\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Exit;\r
+  }\r
+\r
+  CopyMem (CardData->AlignedBuffer, &Data, Width);\r
+  Status  = SendCommand (\r
+              CardData,\r
+              BUSTEST_W,\r
+              0,\r
+              OutData,\r
+              CardData->AlignedBuffer,\r
+              Width,\r
+              ResponseR1,\r
+              TIMEOUT_COMMAND,\r
+              (UINT32*)&(CardData->CardStatus)\r
+              );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG((EFI_D_ERROR, "MMCCardBusWidthTest:SendCommand BUSTEST_W 0x%x\n", *(UINT32*)&(CardData->CardStatus)));\r
+    goto Exit;\r
+  }\r
+\r
+  gBS->Stall (10 * 1000);\r
+\r
+  Data = 0;\r
+\r
+  Status  = SendCommand (\r
+              CardData,\r
+              BUSTEST_R,\r
+              0,\r
+              InData,\r
+              CardData->AlignedBuffer,\r
+              Width,\r
+              ResponseR1,\r
+              TIMEOUT_COMMAND,\r
+              (UINT32*)&(CardData->CardStatus)\r
+              );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG((EFI_D_ERROR, "MMCCardBusWidthTest:SendCommand BUSTEST_R 0x%x\n", *(UINT32*)&(CardData->CardStatus)));\r
+    goto Exit;\r
+  }\r
+  CopyMem (&Data, CardData->AlignedBuffer, Width);\r
+\r
+  switch (Width) {\r
+    case 1:\r
+      Value = (~(Data ^ 0x80)) & 0xC0;\r
+      break;\r
+    case 4:\r
+      Value = (~(Data ^ 0x5A)) & 0xFF;\r
+      break;\r
+    case 8:\r
+      Value = (~(Data ^ 0xAA55)) & 0xFFFF;\r
+      break;\r
+  }\r
+\r
+  if (Value == 0) {\r
+    Status = EFI_SUCCESS;\r
+  } else {\r
+    Status = EFI_UNSUPPORTED;\r
+  }\r
+\r
+\r
+Exit:\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This function can detect these card types:\r
+    1. MMC card\r
+    2. SD 1.1 card\r
+    3. SD 2.0 standard card\r
+    3. SD 2.0 high capacity card\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+\r
+  @return EFI_SUCCESS\r
+  @return others\r
+\r
+**/\r
+EFI_STATUS\r
+GetCardType (\r
+  IN  CARD_DATA              *CardData\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  EFI_SD_HOST_IO_PROTOCOL    *SDHostIo;\r
+  UINT32                     Argument;\r
+  UINT32                     ResponseData;\r
+  UINT32                     Count;\r
+  BOOLEAN                    SDCommand8Support;\r
+\r
+\r
+  SDHostIo = CardData->SDHostIo;\r
+\r
+  //\r
+  // Reset the card\r
+  //\r
+  Status  = SendCommand (\r
+              CardData,\r
+              GO_IDLE_STATE,\r
+              0,\r
+              NoData,\r
+              NULL,\r
+              0,\r
+              ResponseNo,\r
+              TIMEOUT_COMMAND,\r
+              NULL\r
+              );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG((EFI_D_ERROR, "GO_IDLE_STATE Fail Status = 0x%x\n", Status));\r
+    goto Exit;\r
+  }\r
+\r
+  //\r
+  //No spec requirment, can be adjusted\r
+  //\r
+  gBS->Stall (10 * 1000);\r
+\r
+\r
+  //\r
+  // Only 2.7V - 3.6V is supported for SD2.0, only SD 2.0 card can pass\r
+  // MMC and SD1.1 card will fail this command\r
+  //\r
+  Argument          = (VOLTAGE_27_36 << 8) | CHECK_PATTERN;\r
+  ResponseData      = 0;\r
+  SDCommand8Support = FALSE;\r
+\r
+  Status  = SendCommand (\r
+              CardData,\r
+              SEND_IF_COND,\r
+              Argument,\r
+              NoData,\r
+              NULL,\r
+              0,\r
+              ResponseR7,\r
+              TIMEOUT_COMMAND,\r
+              &ResponseData\r
+              );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    if (Status != EFI_TIMEOUT) {\r
+       DEBUG((EFI_D_ERROR, "SEND_IF_COND Fail, none time out error\n"));\r
+       goto Exit;\r
+    }\r
+  } else {\r
+     if (ResponseData != Argument) {\r
+       DEBUG((EFI_D_ERROR, "SEND_IF_COND Fail, respond data does not match send data\n"));\r
+       Status = EFI_DEVICE_ERROR;\r
+       goto Exit;\r
+    }\r
+    SDCommand8Support = TRUE;\r
+  }\r
+\r
+\r
+  Argument = 0;\r
+  if (SDHostIo->HostCapability.V30Support == TRUE) {\r
+    Argument |= BIT17 | BIT18;\r
+  } else if (SDHostIo->HostCapability.V33Support == TRUE) {\r
+    Argument |= BIT20 | BIT21;\r
+  }\r
+\r
+  if (SDCommand8Support) {\r
+    //\r
+    //If command SD_SEND_OP_COND sucessed, it should be set.\r
+    // SD 1.1 card will ignore it\r
+    // SD 2.0 standard card will repsond with CCS 0, SD high capacity card will respond with CCS 1\r
+    // CCS is BIT30 of OCR\r
+    Argument |= BIT30;\r
+  }\r
+\r
+\r
+  Count        = 20;\r
+  //\r
+  //Only SD card will respond to this command, and spec says the card only checks condition at first ACMD41 command\r
+  //\r
+  do {\r
+    Status  = SendAppCommand (\r
+                CardData,\r
+                SD_SEND_OP_COND,\r
+                Argument,\r
+                NoData,\r
+                NULL,\r
+                0,\r
+                ResponseR3,\r
+                TIMEOUT_COMMAND,\r
+                (UINT32*)&(CardData->OCRRegister)\r
+                );\r
+    if (EFI_ERROR (Status)) {\r
+      if ((Status == EFI_TIMEOUT) && (!SDCommand8Support)) {\r
+        CardData->CardType = MMCCard;\r
+        Status = EFI_SUCCESS;\r
+        DEBUG((EFI_D_INFO, "SD_SEND_OP_COND, MMC card was identified\n"));\r
+      } else {\r
+        //\r
+        // Not as expected, MMC card should has no response, which means timeout.\r
+        // SD card should pass this command\r
+        //\r
+        DEBUG((EFI_D_ERROR, "SD_SEND_OP_COND Fail, check whether it is neither a MMC card nor a SD card\n"));\r
+      }\r
+      goto Exit;\r
+    }\r
+    //\r
+    //Avoid waiting if sucess. Busy bit 0 means not ready\r
+    //\r
+    if (CardData->OCRRegister.Busy == 1) {\r
+      break;\r
+    }\r
+\r
+    gBS->Stall (50 * 1000);\r
+    Count--;\r
+    if (Count == 0) {\r
+      DEBUG((EFI_D_ERROR, "Card is always in busy state\n"));\r
+      Status = EFI_TIMEOUT;\r
+      goto Exit;\r
+    }\r
+  } while (1);\r
+\r
+  //\r
+  //Check supported voltage\r
+  //\r
+  Argument = 0;\r
+  if (SDHostIo->HostCapability.V30Support == TRUE) {\r
+    if ((CardData->OCRRegister.V270_V360 & BIT2) == BIT2) {\r
+      Argument |= BIT17;\r
+    } else if ((CardData->OCRRegister.V270_V360 & BIT3) == BIT3) {\r
+      Argument |= BIT18;\r
+    }\r
+  } else if (SDHostIo->HostCapability.V33Support == TRUE) {\r
+     if ((CardData->OCRRegister.V270_V360 & BIT5) == BIT5) {\r
+       Argument |= BIT20;\r
+     } else if ((CardData->OCRRegister.V270_V360 & BIT6) == BIT6) {\r
+       Argument |= BIT21;\r
+     }\r
+  }\r
+\r
+  if (Argument == 0) {\r
+     //\r
+     //No matched support voltage\r
+     //\r
+     PutCardInactive (CardData);\r
+     DEBUG((EFI_D_ERROR, "No matched voltage for this card\n"));\r
+     Status = EFI_UNSUPPORTED;\r
+     goto Exit;\r
+  }\r
+\r
+  CardData->CardType = SDMemoryCard;\r
+  if (SDCommand8Support == TRUE) {\r
+   CardData->CardType = SDMemoryCard2;\r
+   DEBUG((EFI_D_INFO, "SD_SEND_OP_COND, SD 2.0 or above standard card was identified\n"));\r
+  }\r
+\r
+  if ((CardData->OCRRegister.AccessMode & BIT1) == BIT1) {\r
+    CardData->CardType = SDMemoryCard2High;\r
+    DEBUG((EFI_D_INFO, "SD_SEND_OP_COND, SD 2.0 or above high capacity card was identified\n"));\r
+  }\r
+\r
+\r
+\r
+Exit:\r
+  return Status;\r
+}\r
+\r
+/**\r
+  MMC card high/low voltage selection function\r
+\r
+  @param  CardData               Pointer to CARD_DATA.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_INVALID_PARAMETER\r
+  @retval EFI_UNSUPPORTED\r
+  @retval EFI_BAD_BUFFER_SIZE\r
+\r
+**/\r
+EFI_STATUS\r
+MMCCardVoltageSelection (\r
+  IN  CARD_DATA              *CardData\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  EFI_SD_HOST_IO_PROTOCOL    *SDHostIo;\r
+  UINT8                      Retry;\r
+  UINT32                     TimeOut;\r
+\r
+  Status   = EFI_SUCCESS;\r
+  SDHostIo = CardData->SDHostIo;\r
+  //\r
+  //First try the high voltage, then if supported choose the low voltage\r
+  //\r
+\r
+    for (Retry = 0; Retry < 3; Retry++) {\r
+      //\r
+      // To bring back the normal MMC card to work\r
+      // after sending the SD command. Otherwise some\r
+      // card could not work\r
+\r
+      Status  = SendCommand (\r
+                CardData,\r
+                  GO_IDLE_STATE,\r
+                  0,\r
+                  NoData,\r
+                  NULL,\r
+                  0,\r
+                  ResponseNo,\r
+                  TIMEOUT_COMMAND,\r
+                  NULL\r
+                  );\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG((EFI_D_ERROR, "GO_IDLE_STATE Fail Status = 0x%x\n", Status));\r
+        continue;\r
+      }\r
+      //\r
+      //CE-ATA device needs long delay\r
+      //\r
+      gBS->Stall ((Retry + 1) * 50 * 1000);\r
+\r
+      //\r
+      //Get OCR register to check voltage support, first time the OCR is 0\r
+      //\r
+      Status  = SendCommand (\r
+                CardData,\r
+                  SEND_OP_COND,\r
+                  0,\r
+                  NoData,\r
+                  NULL,\r
+                  0,\r
+                  ResponseR3,\r
+                  TIMEOUT_COMMAND,\r
+                  (UINT32*)&(CardData->OCRRegister)\r
+                  );\r
+      if (!EFI_ERROR (Status)) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (Retry == 3) {\r
+      DEBUG((EFI_D_ERROR, "SEND_OP_COND Fail Status = 0x%x\n", Status));\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto Exit;\r
+    }\r
+\r
+    //\r
+    //TimeOut Value, 5000 * 100 * 1000 = 5 s\r
+    //\r
+    TimeOut = 5000;\r
+\r
+    do {\r
+      Status  = SendCommand (\r
+                CardData,\r
+                  SEND_OP_COND,\r
+                  0x40300000,\r
+                  NoData,\r
+                  NULL,\r
+                  0,\r
+                  ResponseR3,\r
+                  TIMEOUT_COMMAND,\r
+                  (UINT32*)&(CardData->OCRRegister)\r
+                  );\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG((EFI_D_ERROR, "SEND_OP_COND Fail Status = 0x%x\n", Status));\r
+        goto Exit;\r
+      }\r
+\r
+      gBS->Stall (1 * 1000);\r
+      TimeOut--;\r
+      if (TimeOut == 0) {\r
+        Status = EFI_TIMEOUT;\r
+      DEBUG((EFI_D_ERROR, "Card is always in busy state\n"));\r
+        goto Exit;\r
+      }\r
+    } while (CardData->OCRRegister.Busy != 1);\r
+\r
+  if (CardData->OCRRegister.AccessMode == 2) // eMMC Card uses Sector Addressing - High Capacity\r
+    {\r
+    DEBUG((EFI_D_INFO, "eMMC Card is High Capacity\n"));\r
+    CardData->CardType = MMCCardHighCap;\r
+  }\r
+\r
+Exit:\r
+  return Status;\r
+\r
+}\r
+\r
+/**\r
+  This function set the bus and device width for MMC card\r
+\r
+  @param  CardData               Pointer to CARD_DATA.\r
+  @param  Width                  1, 4, 8 bits.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_UNSUPPORTED\r
+  @retval EFI_INVALID_PARAMETER\r
+\r
+**/\r
+EFI_STATUS\r
+MMCCardSetBusWidth (\r
+  IN  CARD_DATA              *CardData,\r
+  IN  UINT8                  BusWidth,\r
+  IN  BOOLEAN                EnableDDRMode\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  EFI_SD_HOST_IO_PROTOCOL    *SDHostIo;\r
+  SWITCH_ARGUMENT            SwitchArgument;\r
+  UINT8                      Value;\r
+\r
+  SDHostIo = CardData->SDHostIo;\r
+  Value = 0;\r
+  switch (BusWidth) {\r
+    case 8:\r
+      if (EnableDDRMode)\r
+        Value = 6;\r
+      else\r
+      Value = 2;\r
+      break;\r
+\r
+    case 4:\r
+      if (EnableDDRMode)\r
+        Value = 5;\r
+      else\r
+      Value = 1;\r
+      break;\r
+\r
+    case 1:\r
+      if (EnableDDRMode)    // Bus width 1 is not supported in ddr mode\r
+        return EFI_UNSUPPORTED;\r
+      Value = 0;\r
+      break;\r
+\r
+    default:\r
+     ASSERT(0);\r
+  }\r
+\r
+\r
+  ZeroMem(&SwitchArgument, sizeof (SWITCH_ARGUMENT));\r
+  SwitchArgument.CmdSet = 0;\r
+  SwitchArgument.Value  = Value;\r
+  SwitchArgument.Index  = (UINT32)((UINTN)\r
+  (&(CardData->ExtCSDRegister.BUS_WIDTH)) - (UINTN)(&(CardData->ExtCSDRegister)));\r
+  SwitchArgument.Access = WriteByte_Mode;\r
+  Status  = SendCommand (\r
+              CardData,\r
+              SWITCH,\r
+              *(UINT32*)&SwitchArgument,\r
+              NoData,\r
+              NULL,\r
+              0,\r
+              ResponseR1b,\r
+              TIMEOUT_COMMAND,\r
+              (UINT32*)&(CardData->CardStatus)\r
+              );\r
+  if (!EFI_ERROR (Status)) {\r
+     Status  = SendCommand (\r
+                 CardData,\r
+                 SEND_STATUS,\r
+                 (CardData->Address << 16),\r
+                 NoData,\r
+                 NULL,\r
+                 0,\r
+                 ResponseR1,\r
+                 TIMEOUT_COMMAND,\r
+                 (UINT32*)&(CardData->CardStatus)\r
+                 );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG((EFI_D_ERROR, "SWITCH %d bits Fail\n", BusWidth));\r
+      goto Exit;\r
+    } else {\r
+      DEBUG((EFI_D_ERROR, "MMCCardSetBusWidth:SWITCH Card Status:0x%x\n", *(UINT32*)&(CardData->CardStatus)));\r
+      Status = SDHostIo->SetBusWidth (SDHostIo, BusWidth);\r
+      if (EFI_ERROR (Status)) {\r
+         DEBUG((EFI_D_ERROR, "SWITCH set %d bits Fail\n", BusWidth));\r
+         goto Exit;\r
+      }\r
+      gBS->Stall (5 * 1000);\r
+    }\r
+  }\r
+\r
+  if (!EnableDDRMode) {     // CMD19 and CMD14 are illegal commands in ddr mode\r
+  //if (EFI_ERROR (Status)) {\r
+  //  DEBUG((EFI_D_ERROR, "MMCCardBusWidthTest: Fail to enable high speed mode\n"));\r
+  //  goto Exit;\r
+  //}\r
+\r
+  Status = MMCCardBusWidthTest (CardData, BusWidth);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG((EFI_D_ERROR, "MMCCardBusWidthTest %d bit Fail\n", BusWidth));\r
+    goto Exit;\r
+    }\r
+  }\r
+\r
+  CardData->CurrentBusWidth = BusWidth;\r
+\r
+Exit:\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  MMC/SD card init function\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+\r
+  @return EFI_SUCCESS\r
+  @return others\r
+\r
+**/\r
+EFI_STATUS\r
+MMCSDCardInit (\r
+  IN  CARD_DATA              *CardData\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  EFI_SD_HOST_IO_PROTOCOL    *SDHostIo;\r
+  SWITCH_ARGUMENT            SwitchArgument;\r
+  UINT32                     Data;\r
+  UINT32                     Argument;\r
+  UINT32                     nIndex;\r
+  UINT8                      PowerValue;\r
+  BOOLEAN                    EnableDDRMode;\r
+\r
+  ASSERT(CardData != NULL);\r
+  SDHostIo                  = CardData->SDHostIo;\r
+  EnableDDRMode             = FALSE;\r
+\r
+  CardData->CardType = UnknownCard;\r
+  Status = GetCardType (CardData);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+  DEBUG((DEBUG_INFO, "CardData->CardType  0x%x\n", CardData->CardType));\r
+\r
+  ASSERT (CardData->CardType != UnknownCard);\r
+  //\r
+  //MMC, SD card need host auto stop command support\r
+  //\r
+  SDHostIo->EnableAutoStopCmd (SDHostIo, TRUE);\r
+\r
+  if (CardData->CardType == MMCCard) {\r
+    Status = MMCCardVoltageSelection (CardData);\r
+    if (EFI_ERROR(Status)) {\r
+      goto Exit;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Get CID Register\r
+  //\r
+  Status  = SendCommand (\r
+              CardData,\r
+              ALL_SEND_CID,\r
+              0,\r
+              NoData,\r
+              NULL,\r
+              0,\r
+              ResponseR2,\r
+              TIMEOUT_COMMAND,\r
+              (UINT32*)&(CardData->CIDRegister)\r
+              );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG((EFI_D_ERROR, "ALL_SEND_CID Fail Status = 0x%x\n", Status));\r
+    goto Exit;\r
+  } else {\r
+    // Dump out the Card ID data\r
+    DEBUG((EFI_D_INFO, "Product Name: "));\r
+    for ( nIndex=0; nIndex<6; nIndex++ ) {\r
+      DEBUG((EFI_D_INFO, "%c", CardData->CIDRegister.PNM[nIndex]));\r
+    }\r
+    DEBUG((EFI_D_INFO, "\nApplication ID : %d\n", CardData->CIDRegister.OID));\r
+    DEBUG((EFI_D_INFO, "Manufacturer ID: %d\n", CardData->CIDRegister.MID));\r
+    DEBUG((EFI_D_INFO, "Revision ID    : %d\n", CardData->CIDRegister.PRV));\r
+    DEBUG((EFI_D_INFO, "Serial Number  : %d\n", CardData->CIDRegister.PSN));\r
+  }\r
+\r
+  //\r
+  //SET_RELATIVE_ADDR\r
+  //\r
+  if (CardData->CardType == MMCCard  || CardData->CardType == MMCCardHighCap) {\r
+    //\r
+    //Hard code the RCA address\r
+    //\r
+    CardData->Address = 1;\r
+\r
+    //\r
+    // Set RCA Register\r
+    //\r
+    Status  = SendCommand (\r
+                CardData,\r
+                SET_RELATIVE_ADDR,\r
+                (CardData->Address << 16),\r
+                NoData,\r
+                NULL,\r
+                0,\r
+                ResponseR1,\r
+                TIMEOUT_COMMAND,\r
+                (UINT32*)&(CardData->CardStatus)\r
+                );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG((EFI_D_ERROR, "SET_RELATIVE_ADDR Fail Status = 0x%x\n", Status));\r
+      goto Exit;\r
+    }\r
+  } else {\r
+    Data = 0;\r
+    Status  = SendCommand (\r
+                CardData,\r
+                SET_RELATIVE_ADDR,\r
+                0,\r
+                NoData,\r
+                NULL,\r
+                0,\r
+                ResponseR6,\r
+                TIMEOUT_COMMAND,\r
+                &Data\r
+                );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG((EFI_D_ERROR, "SET_RELATIVE_ADDR Fail Status = 0x%x\n", Status));\r
+      goto Exit;\r
+    }\r
+\r
+    CardData->Address = (UINT16)(Data >> 16);\r
+    *(UINT32*)&CardData->CardStatus      = Data & 0x1FFF;\r
+    CardData->CardStatus.ERROR           = (Data >> 13) & 0x1;\r
+    CardData->CardStatus.ILLEGAL_COMMAND = (Data >> 14) & 0x1;\r
+    CardData->CardStatus.COM_CRC_ERROR   = (Data >> 15) & 0x1;\r
+    Status = CheckCardStatus (*(UINT32*)&CardData->CardStatus);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG((EFI_D_ERROR, "SET_RELATIVE_ADDR Fail Status = 0x%x\n", Status));\r
+      goto Exit;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Get CSD Register\r
+  //\r
+  Status  = SendCommand (\r
+              CardData,\r
+              SEND_CSD,\r
+              (CardData->Address << 16),\r
+              NoData,\r
+              NULL,\r
+              0,\r
+              ResponseR2,\r
+              TIMEOUT_COMMAND,\r
+              (UINT32*)&(CardData->CSDRegister)\r
+              );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG((EFI_D_ERROR, "SEND_CSD Fail Status = 0x%x\n", Status));\r
+    goto Exit;\r
+  }\r
+\r
+  DEBUG((EFI_D_INFO, "CardData->CSDRegister.SPEC_VERS = 0x%x\n", CardData->CSDRegister.SPEC_VERS));\r
+  DEBUG((EFI_D_INFO, "CardData->CSDRegister.CSD_STRUCTURE = 0x%x\n", CardData->CSDRegister.CSD_STRUCTURE));\r
+\r
+  Status = CaculateCardParameter (CardData);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+\r
+\r
+  //\r
+  // It is platform and hardware specific, need hadrware engineer input\r
+  //\r
+  if (CardData->CSDRegister.DSR_IMP == 1) {\r
+    //\r
+    // Default is 0x404\r
+    //\r
+    Status  = SendCommand (\r
+                CardData,\r
+                SET_DSR,\r
+                (DEFAULT_DSR_VALUE << 16),\r
+                NoData,\r
+                NULL,\r
+                0,\r
+                ResponseNo,\r
+                TIMEOUT_COMMAND,\r
+                NULL\r
+                );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG((EFI_D_ERROR, "SET_DSR Fail Status = 0x%x\n", Status));\r
+      //\r
+      // Assume can operate even fail\r
+      //\r
+    }\r
+  }\r
+  //\r
+  //Change clock frequency from 400KHz to max supported when not in high speed mode\r
+  //\r
+  Status = SDHostIo->SetClockFrequency (SDHostIo, CardData->MaxFrequency);\r
+  if (EFI_ERROR (Status)) {\r
+  DEBUG((EFI_D_ERROR, "MMCSDCardInit:Fail to SetClockFrequency \n"));\r
+  goto Exit;\r
+  }\r
+\r
+  //\r
+  //Put the card into tran state\r
+  //\r
+  Status = SendCommand (\r
+             CardData,\r
+             SELECT_DESELECT_CARD,\r
+             (CardData->Address << 16),\r
+             NoData,\r
+             NULL,\r
+             0,\r
+             ResponseR1,\r
+             TIMEOUT_COMMAND,\r
+             (UINT32*)&(CardData->CardStatus)\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG((EFI_D_ERROR, "SELECT_DESELECT_CARD Fail Status = 0x%x\n", Status));\r
+    goto Exit;\r
+  }\r
+\r
+  //\r
+  // No spec requirment, can be adjusted\r
+  //\r
+  gBS->Stall (5 * 1000);\r
+  //\r
+  // No need to do so\r
+  //\r
+  //\r
+  Status  = SendCommand (\r
+              CardData,\r
+              SEND_STATUS,\r
+              (CardData->Address << 16),\r
+              NoData,\r
+              NULL,\r
+              0,\r
+              ResponseR1,\r
+              TIMEOUT_COMMAND,\r
+              (UINT32*)&(CardData->CardStatus)\r
+              );\r
+  if (EFI_ERROR (Status)) {\r
+     DEBUG((EFI_D_ERROR, "SELECT_DESELECT_CARD SEND_STATUS Fail Status = 0x%x\n", Status));\r
+     goto Exit;\r
+  }\r
+  //\r
+  //if the SPEC_VERS indicates a version 4.0 or higher\r
+  //The card is a high speed card and support Switch\r
+  //and Send_ext_csd command\r
+  //otherwise it is an old card\r
+  //\r
+\r
+  if (CardData->CardType == MMCCard  || CardData->CardType == MMCCardHighCap) {\r
+    //\r
+    //Only V4.0 and above supports more than 1 bits and high speed\r
+    //\r
+    if (CardData->CSDRegister.SPEC_VERS >= 4) {\r
+    //\r
+      //Get ExtCSDRegister\r
+      //\r
+      Status  = SendCommand (\r
+                  CardData,\r
+                  SEND_EXT_CSD,\r
+                  0x0,\r
+                  InData,\r
+                  CardData->AlignedBuffer,\r
+                  sizeof (EXT_CSD),\r
+                  ResponseR1,\r
+                  TIMEOUT_DATA,\r
+                  (UINT32*)&(CardData->CardStatus)\r
+                  );\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG((EFI_D_ERROR, "SEND_EXT_CSD Fail Status = 0x%x\n", Status));\r
+        goto Exit;\r
+      }\r
+\r
+      CopyMem (&(CardData->ExtCSDRegister), CardData->AlignedBuffer, sizeof (EXT_CSD));\r
+\r
+      //\r
+      // Recaculate the block number for >2G MMC card\r
+      //\r
+      Data  = (CardData->ExtCSDRegister.SEC_COUNT[0]) |\r
+              (CardData->ExtCSDRegister.SEC_COUNT[1] << 8) |\r
+              (CardData->ExtCSDRegister.SEC_COUNT[2] << 16) |\r
+              (CardData->ExtCSDRegister.SEC_COUNT[3] << 24);\r
+\r
+      if (Data != 0) {\r
+        CardData->BlockNumber = Data;\r
+      }\r
+      DEBUG((DEBUG_INFO, "CardData->BlockNumber  %d\n", Data));\r
+      DEBUG((EFI_D_ERROR, "CardData->ExtCSDRegister.CARD_TYPE -> %d\n", (UINTN)CardData->ExtCSDRegister.CARD_TYPE));\r
+      if ((CardData->ExtCSDRegister.CARD_TYPE & BIT2)||\r
+          (CardData->ExtCSDRegister.CARD_TYPE & BIT3)) {\r
+          //DEBUG((DEBUG_INFO, "To enable DDR mode\n"));\r
+          //EnableDDRMode = TRUE;\r
+      }\r
+      //\r
+      // Check current chipset capability and the plugged-in card\r
+      // whether supports HighSpeed\r
+      //\r
+      if (SDHostIo->HostCapability.HighSpeedSupport) {\r
+\r
+        //\r
+        //Change card timing to high speed interface timing\r
+        //\r
+        ZeroMem(&SwitchArgument, sizeof (SWITCH_ARGUMENT));\r
+        SwitchArgument.CmdSet = 0;\r
+        SwitchArgument.Value  = 1;\r
+        SwitchArgument.Index  = (UINT32)((UINTN)\r
+        (&(CardData->ExtCSDRegister.HS_TIMING)) - (UINTN)(&(CardData->ExtCSDRegister)));\r
+        SwitchArgument.Access = WriteByte_Mode;\r
+        Status  = SendCommand (\r
+                    CardData,\r
+                    SWITCH,\r
+                    *(UINT32*)&SwitchArgument,\r
+                    NoData,\r
+                    NULL,\r
+                    0,\r
+                    ResponseR1b,\r
+                    TIMEOUT_COMMAND,\r
+                    (UINT32*)&(CardData->CardStatus)\r
+                    );\r
+        if (EFI_ERROR (Status)) {\r
+          DEBUG((EFI_D_ERROR, "MMCSDCardInit:SWITCH frequency Fail Status = 0x%x\n", Status));\r
+        }\r
+\r
+        gBS->Stall (5 * 1000);\r
+\r
+\r
+        if (!EFI_ERROR (Status)) {\r
+          Status  = SendCommand (\r
+                      CardData,\r
+                      SEND_STATUS,\r
+                      (CardData->Address << 16),\r
+                      NoData,\r
+                      NULL,\r
+                      0,\r
+                      ResponseR1,\r
+                      TIMEOUT_COMMAND,\r
+                      (UINT32*)&(CardData->CardStatus)\r
+                      );\r
+          if (!EFI_ERROR (Status)) {\r
+            if (EnableDDRMode) {\r
+              DEBUG((EFI_D_ERROR, "Enable ddr mode on host controller\n"));\r
+              SDHostIo->SetDDRMode (SDHostIo, TRUE);\r
+            } else  {\r
+              DEBUG((EFI_D_ERROR, "Enable high speed mode on host controller\n"));\r
+              SDHostIo->SetHighSpeedMode (SDHostIo, TRUE);\r
+            }\r
+          //\r
+          // Change host clock to support high speed and enable chispet to\r
+          // support speed\r
+          //\r
+            if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) {\r
+              Status = SDHostIo->SetClockFrequency (SDHostIo, FREQUENCY_MMC_PP_HIGH);\r
+            } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) {\r
+              Status = SDHostIo->SetClockFrequency (SDHostIo, FREQUENCY_MMC_PP);\r
+            } else {\r
+              Status = EFI_UNSUPPORTED;\r
+            }\r
+            if (EFI_ERROR (Status)) {\r
+              DEBUG((EFI_D_ERROR, "MMCSDCardInit:Fail to SetClockFrequency \n"));\r
+              goto Exit;\r
+            }\r
+            //\r
+            // It seems no need to stall after changing bus freqeuncy.\r
+            // It is said that the freqeuncy can be changed at any time. Just appends 8 clocks after command.\r
+            // But SetClock alreay has delay.\r
+            //\r
+          }\r
+        }\r
+\r
+      }\r
+\r
+\r
+\r
+      //\r
+      // Prefer wide bus width for performance\r
+      //\r
+      //\r
+      // Set to BusWidth bits mode, only version 4.0 or above support more than 1 bits\r
+      //\r
+      if (SDHostIo->HostCapability.BusWidth8 == TRUE) {\r
+         Status = MMCCardSetBusWidth (CardData, 8, EnableDDRMode);\r
+         if (EFI_ERROR (Status)) {\r
+            //\r
+            // CE-ATA may support 8 bits and 4 bits, but has no software method for detection\r
+            //\r
+            Status = MMCCardSetBusWidth (CardData, 4, EnableDDRMode);\r
+            if (EFI_ERROR (Status)) {\r
+              goto Exit;\r
+            }\r
+         }\r
+      } else if (SDHostIo->HostCapability.BusWidth4 == TRUE) {\r
+         Status = MMCCardSetBusWidth (CardData, 4, EnableDDRMode);\r
+         if (EFI_ERROR (Status)) {\r
+           goto Exit;\r
+         }\r
+      }\r
+\r
+      PowerValue = 0;\r
+\r
+      if (CardData->CurrentBusWidth == 8) {\r
+        if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) {\r
+          PowerValue = CardData->ExtCSDRegister.PWR_CL_52_360;\r
+          PowerValue = PowerValue >> 4;\r
+        } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) {\r
+          PowerValue = CardData->ExtCSDRegister.PWR_CL_26_360;\r
+          PowerValue = PowerValue >> 4;\r
+        }\r
+      } else if (CardData->CurrentBusWidth == 4) {\r
+         if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) {\r
+          PowerValue = CardData->ExtCSDRegister.PWR_CL_52_360;\r
+          PowerValue = PowerValue & 0xF;\r
+         } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) {\r
+           PowerValue = CardData->ExtCSDRegister.PWR_CL_26_360;\r
+           PowerValue = PowerValue & 0xF;\r
+         }\r
+      }\r
+\r
+      if (PowerValue != 0) {\r
+        //\r
+        //Update Power Class\r
+        //\r
+        ZeroMem(&SwitchArgument, sizeof (SWITCH_ARGUMENT));\r
+        SwitchArgument.CmdSet = 0;\r
+        SwitchArgument.Value  = PowerValue;\r
+        SwitchArgument.Index  = (UINT32)((UINTN)\r
+        (&(CardData->ExtCSDRegister.POWER_CLASS)) - (UINTN)(&(CardData->ExtCSDRegister)));\r
+        SwitchArgument.Access = WriteByte_Mode;\r
+        Status  = SendCommand (\r
+                    CardData,\r
+                    SWITCH,\r
+                    *(UINT32*)&SwitchArgument,\r
+                    NoData,\r
+                    NULL,\r
+                    0,\r
+                    ResponseR1b,\r
+                    TIMEOUT_COMMAND,\r
+                    (UINT32*)&(CardData->CardStatus)\r
+                    );\r
+         if (!EFI_ERROR (Status)) {\r
+           Status  = SendCommand (\r
+                       CardData,\r
+                       SEND_STATUS,\r
+                       (CardData->Address << 16),\r
+                       NoData,\r
+                       NULL,\r
+                       0,\r
+                       ResponseR1,\r
+                       TIMEOUT_COMMAND,\r
+                       (UINT32*)&(CardData->CardStatus)\r
+                       );\r
+           if (EFI_ERROR (Status)) {\r
+             DEBUG((EFI_D_ERROR, "SWITCH Power Class Fail Status = 0x%x\n", Status));\r
+           }\r
+           //gBS->Stall (10 * 1000);\r
+         }\r
+      }\r
+\r
+\r
+\r
+    } else {\r
+\r
+\r
+      DEBUG((EFI_D_ERROR, "MMC Card version %d only supportes 1 bits at lower transfer speed\n",CardData->CSDRegister.SPEC_VERS));\r
+    }\r
+  } else {\r
+      //\r
+      // Pin 1, at power up this line has a 50KOhm pull up enabled in the card.\r
+      // This pull-up should be disconnected by the user, during regular data transfer,\r
+      // with SET_CLR_CARD_DETECT (ACMD42) command\r
+      //\r
+      Status  = SendAppCommand (\r
+                  CardData,\r
+                  SET_CLR_CARD_DETECT,\r
+                  0,\r
+                  NoData,\r
+                  NULL,\r
+                  0,\r
+                  ResponseR1,\r
+                  TIMEOUT_COMMAND,\r
+                  (UINT32*)&(CardData->CardStatus)\r
+                  );\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG((EFI_D_ERROR, "SET_CLR_CARD_DETECT Fail Status = 0x%x\n", Status));\r
+        goto Exit;\r
+      }\r
+\r
+      /*\r
+      //\r
+      // Don't rely on SCR and SD status, some cards have unexpected SCR.\r
+      // It only sets private section, the other bits are 0\r
+      // such as Sandisk Ultra II 4.0G, KinSton mini SD 128M, Toshiba 2.0GB\r
+      // Some card even fail this command, KinSton SD 4GB\r
+      //\r
+      Status  = SendAppCommand (\r
+                  CardData,\r
+                  SEND_SCR,\r
+                  0,\r
+                  InData,\r
+                  (UINT8*)&(CardData->SCRRegister),\r
+                  sizeof(SCR),\r
+                  ResponseR1,\r
+                  TIMEOUT_COMMAND,\r
+                  (UINT32*)&(CardData->CardStatus)\r
+                  );\r
+      if (EFI_ERROR (Status)) {\r
+        goto Exit;\r
+      }\r
+\r
+      //\r
+      // SD memory card at least supports 1 and 4 bits.\r
+      //\r
+      // ASSERT ((CardData->SCRRegister.SD_BUS_WIDTH & (BIT0 | BIT2)) == (BIT0 | BIT2));\r
+      */\r
+\r
+      //\r
+      // Set Bus Width to 4\r
+      //\r
+      Status  = SendAppCommand (\r
+                  CardData,\r
+                  SET_BUS_WIDTH,\r
+                  SD_BUS_WIDTH_4,\r
+                  NoData,\r
+                  NULL,\r
+                  0,\r
+                  ResponseR1,\r
+                  TIMEOUT_COMMAND,\r
+                  (UINT32*)&(CardData->CardStatus)\r
+                  );\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG((EFI_D_ERROR, "SET_BUS_WIDTH 4 bits Fail Status = 0x%x\n", Status));\r
+        goto Exit;\r
+      }\r
+\r
+      Status = SDHostIo->SetBusWidth (SDHostIo, 4);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Exit;\r
+      }\r
+      CardData->CurrentBusWidth = 4;\r
+\r
+\r
+      if ((SDHostIo->HostCapability.HighSpeedSupport == FALSE) ||\r
+          ((CardData->CSDRegister.CCC & BIT10) != BIT10)) {\r
+        //\r
+        // Host must support high speed\r
+        // Card must support Switch function\r
+        //\r
+        goto Exit;\r
+      }\r
+\r
+      //\r
+      //Mode = 0, group 1, function 1, check operation\r
+      //\r
+      Argument    = 0xFFFF01;\r
+      ZeroMem (&CardData->SwitchStatus, sizeof (SWITCH_STATUS));\r
+\r
+      Status  = SendCommand (\r
+                  CardData,\r
+                  SWITCH_FUNC,\r
+                  Argument,\r
+                  InData,\r
+                  CardData->AlignedBuffer,\r
+                  sizeof (SWITCH_STATUS),\r
+                  ResponseR1,\r
+                  TIMEOUT_COMMAND,\r
+                  (UINT32*)&(CardData->CardStatus)\r
+                  );\r
+      if (EFI_ERROR (Status)) {\r
+        goto Exit;\r
+      }\r
+      CopyMem (&(CardData->SwitchStatus), CardData->AlignedBuffer, sizeof (SWITCH_STATUS));\r
+\r
+      if ((CardData->SwitchStatus.DataStructureVersion == 0x0) ||\r
+          ((CardData->SwitchStatus.Group1BusyStatus & BIT1) != BIT1)) {\r
+        //\r
+        // 1. SD 1.1 card does not suppport busy bit\r
+        // 2. Ready state\r
+        //\r
+        //\r
+\r
+        //\r
+        //Mode = 1, group 1, function 1, BIT31 set means set mode\r
+        //\r
+        Argument = 0xFFFF01 | BIT31;\r
+        ZeroMem (&CardData->SwitchStatus, sizeof (SWITCH_STATUS));\r
+\r
+        Status  = SendCommand (\r
+                    CardData,\r
+                    SWITCH_FUNC,\r
+                    Argument,\r
+                    InData,\r
+                    CardData->AlignedBuffer,\r
+                    sizeof (SWITCH_STATUS),\r
+                    ResponseR1,\r
+                    TIMEOUT_COMMAND,\r
+                   (UINT32*)&(CardData->CardStatus)\r
+                   );\r
+         if (EFI_ERROR (Status)) {\r
+            goto Exit;\r
+         }\r
+         CopyMem (&(CardData->SwitchStatus), CardData->AlignedBuffer, sizeof (SWITCH_STATUS));\r
+\r
+         if ((CardData->SwitchStatus.DataStructureVersion == 0x0) ||\r
+            ((CardData->SwitchStatus.Group1BusyStatus & BIT1) != BIT1)) {\r
+          //\r
+          // 1. SD 1.1 card does not suppport busy bit\r
+          // 2. Ready state\r
+          //\r
+\r
+          //\r
+          // 8 clocks, (1/ 25M) * 8 ==> 320 us, so 1ms > 0.32 ms\r
+          //\r
+          gBS->Stall (1000);\r
+\r
+          //\r
+          //Change host clock\r
+          //\r
+          Status = SDHostIo->SetClockFrequency (SDHostIo, FREQUENCY_SD_PP_HIGH);\r
+          if (EFI_ERROR (Status)) {\r
+            goto Exit;\r
+          }\r
+\r
+         }\r
+      }\r
+  }\r
+  if (!((CardData->ExtCSDRegister.CARD_TYPE & BIT2) ||\r
+      (CardData->ExtCSDRegister.CARD_TYPE & BIT3))) {\r
+\r
+  //\r
+  // Set Block Length, to improve compatibility in case of some cards\r
+  //\r
+  Status  = SendCommand (\r
+                CardData,\r
+              SET_BLOCKLEN,\r
+              512,\r
+              NoData,\r
+              NULL,\r
+              0,\r
+              ResponseR1,\r
+              TIMEOUT_COMMAND,\r
+              (UINT32*)&(CardData->CardStatus)\r
+              );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG((EFI_D_ERROR, "SET_BLOCKLEN Fail Status = 0x%x\n", Status));\r
+    goto Exit;\r
+  }\r
+  }\r
+  SDHostIo->SetBlockLength (SDHostIo, 512);\r
+\r
+\r
+Exit:\r
+  return Status;\r
+}\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDevice.c b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDevice.c
new file mode 100644 (file)
index 0000000..1a0682c
--- /dev/null
@@ -0,0 +1,323 @@
+/** @file\r
+\r
+The definition for SD media device driver model and blkio protocol routines.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include "SDMediaDevice.h"\r
+\r
+\r
+EFI_DRIVER_BINDING_PROTOCOL gSDMediaDeviceDriverBinding = {\r
+  SDMediaDeviceSupported,\r
+  SDMediaDeviceStart,\r
+  SDMediaDeviceStop,\r
+  0x20,\r
+  NULL,\r
+  NULL\r
+};\r
+\r
+/**\r
+  Entry point for EFI drivers.\r
+\r
+  @param  ImageHandle      EFI_HANDLE.\r
+  @param  SystemTable      EFI_SYSTEM_TABLE.\r
+\r
+  @retval EFI_SUCCESS      Driver is successfully loaded.\r
+  @return Others           Failed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeSDMediaDevice (\r
+  IN EFI_HANDLE           ImageHandle,\r
+  IN EFI_SYSTEM_TABLE     *SystemTable\r
+  )\r
+{\r
+  return EfiLibInstallDriverBindingComponentName2 (\r
+           ImageHandle,\r
+           SystemTable,\r
+           &gSDMediaDeviceDriverBinding,\r
+           ImageHandle,\r
+           &gSDMediaDeviceName,\r
+           &gSDMediaDeviceName2\r
+           );\r
+}\r
+\r
+\r
+/**\r
+  Test to see if this driver supports ControllerHandle. Any\r
+  ControllerHandle that has BlockIoProtocol installed will be supported.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  Controller           Handle of device to test.\r
+  @param  RemainingDevicePath  Not used.\r
+\r
+  @return EFI_SUCCESS          This driver supports this device.\r
+  @return EFI_UNSUPPORTED      This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SDMediaDeviceSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL     *This,\r
+  IN EFI_HANDLE                      Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_SD_HOST_IO_PROTOCOL   *SDHostIo;\r
+\r
+  //\r
+  // Test whether there is PCI IO Protocol attached on the controller handle.\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiSDHostIoProtocolGuid,\r
+                  (VOID **)&SDHostIo,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+\r
+  gBS->CloseProtocol (\r
+         Controller,\r
+         &gEfiSDHostIoProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+\r
+Exit:\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Starting the SD Media Device Driver.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  Controller           Handle of device to test.\r
+  @param  RemainingDevicePath  Not used.\r
+\r
+  @retval EFI_SUCCESS          This driver supports this device.\r
+  @retval EFI_UNSUPPORTED      This driver does not support this device.\r
+  @retval EFI_DEVICE_ERROR     This driver cannot be started due to device Error.\r
+                               EFI_OUT_OF_RESOURCES- Failed due to resource shortage.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SDMediaDeviceStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL     *This,\r
+  IN EFI_HANDLE                      Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_SD_HOST_IO_PROTOCOL   *SDHostIo;\r
+  CARD_DATA                 *CardData;\r
+\r
+  CardData = NULL;\r
+\r
+  //\r
+  // Open PCI I/O Protocol and save pointer to open protocol\r
+  // in private data area.\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiSDHostIoProtocolGuid,\r
+                  (VOID **) &SDHostIo,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to open gEfiSDHostIoProtocolGuid \r\n"));\r
+    goto Exit;\r
+  }\r
+\r
+  Status = SDHostIo->DetectCardAndInitHost (SDHostIo);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_INFO, "SDMediaDeviceStart: Fail to DetectCardAndInitHost \r\n"));\r
+    goto Exit;\r
+  }\r
+\r
+  CardData = (CARD_DATA*)AllocateZeroPool(sizeof (CARD_DATA));\r
+  if (CardData == NULL) {\r
+    Status =  EFI_OUT_OF_RESOURCES;\r
+    DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to AllocateZeroPool(CARD_DATA) \r\n"));\r
+    goto Exit;\r
+  }\r
+\r
+  ASSERT (SDHostIo->HostCapability.BoundarySize >= 4 * 1024);\r
+  CardData->RawBufferPointer = (UINT8*)((UINTN)DMA_MEMORY_TOP);\r
+  Status = gBS->AllocatePages (\r
+                  AllocateMaxAddress,\r
+                  EfiBootServicesData,\r
+                  EFI_SIZE_TO_PAGES (2 * SDHostIo->HostCapability.BoundarySize),\r
+                  (EFI_PHYSICAL_ADDRESS *)(&CardData->RawBufferPointer)\r
+                  );\r
+\r
+  if (CardData->RawBufferPointer == NULL) {\r
+    DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to AllocateZeroPool(2*x) \r\n"));\r
+    Status =  EFI_OUT_OF_RESOURCES;\r
+    goto Exit;\r
+  }\r
+  CardData->AlignedBuffer = CardData->RawBufferPointer - ((UINTN)(CardData->RawBufferPointer) & (SDHostIo->HostCapability.BoundarySize - 1)) + SDHostIo->HostCapability.BoundarySize;\r
+\r
+  CardData->Signature = CARD_DATA_SIGNATURE;\r
+  CardData->SDHostIo  = SDHostIo;\r
+\r
+  Status = MMCSDCardInit (CardData);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to MMCSDCardInit \r\n"));\r
+    goto Exit;\r
+  }\r
+  DEBUG ((EFI_D_INFO, "SDMediaDeviceStart: MMCSDCardInit SuccessFul\n"));\r
+\r
+  if (CardData->CardType == CEATACard) {\r
+    Status = CEATABlockIoInit (CardData);\r
+  } else {\r
+    Status = MMCSDBlockIoInit (CardData);\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to BlockIoInit \r\n"));\r
+    goto Exit;\r
+  }\r
+  DEBUG ((EFI_D_INFO, "SDMediaDeviceStart: BlockIo is successfully installed\n"));\r
+\r
+\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &Controller,\r
+                  &gEfiBlockIoProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &CardData->BlockIo\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to install gEfiBlockIoProtocolGuid \r\n"));\r
+    goto Exit;\r
+  }\r
+\r
+  //\r
+  // Install the component name protocol\r
+  //\r
+  CardData->ControllerNameTable = NULL;\r
+\r
+  AddUnicodeString2 (\r
+    "eng",\r
+    gSDMediaDeviceName.SupportedLanguages,\r
+    &CardData->ControllerNameTable,\r
+    L"MMC/SD Media Device",\r
+    TRUE\r
+    );\r
+  AddUnicodeString2 (\r
+    "en",\r
+    gSDMediaDeviceName2.SupportedLanguages,\r
+    &CardData->ControllerNameTable,\r
+    L"MMC/SD Media Device",\r
+    FALSE\r
+    );\r
+\r
+Exit:\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_INFO, "SDMediaDeviceStart: End with failure\r\n"));\r
+    if (CardData != NULL) {\r
+      if (CardData->RawBufferPointer != NULL) {\r
+        gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) CardData->RawBufferPointer, EFI_SIZE_TO_PAGES (2 * SDHostIo->HostCapability.BoundarySize));\r
+      }\r
+      FreePool (CardData);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Stop this driver on ControllerHandle. Support stoping any child handles\r
+  created by this driver.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  Controller           Handle of device to stop driver on.\r
+  @param  NumberOfChildren     Number of Children in the ChildHandleBuffer.\r
+  @param  ChildHandleBuffer    List of handles for the children we need to stop.\r
+\r
+  @return EFI_SUCCESS\r
+  @return others\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SDMediaDeviceStop (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL     *This,\r
+  IN EFI_HANDLE                      Controller,\r
+  IN UINTN                           NumberOfChildren,\r
+  IN EFI_HANDLE                      *ChildHandleBuffer\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  CARD_DATA                 *CardData;\r
+  EFI_BLOCK_IO_PROTOCOL     *BlockIo;\r
+\r
+  //\r
+  // First find BlockIo Protocol\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiBlockIoProtocolGuid,\r
+                  (VOID **)&BlockIo,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  CardData  = CARD_DATA_FROM_THIS(BlockIo);\r
+\r
+  //\r
+  // Uninstall Block I/O protocol from the device handle\r
+  //\r
+  Status = gBS->UninstallProtocolInterface (\r
+                  Controller,\r
+                  &gEfiBlockIoProtocolGuid,\r
+                  BlockIo\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (CardData != NULL) {\r
+    if (CardData->RawBufferPointer != NULL) {\r
+      gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) CardData->RawBufferPointer, EFI_SIZE_TO_PAGES (2 * CardData->SDHostIo->HostCapability.BoundarySize));\r
+    }\r
+    FreeUnicodeStringTable (CardData->ControllerNameTable);\r
+    FreePool (CardData);\r
+  }\r
+\r
+  gBS->CloseProtocol (\r
+         Controller,\r
+         &gEfiSDHostIoProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDevice.h b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDevice.h
new file mode 100644 (file)
index 0000000..1550429
--- /dev/null
@@ -0,0 +1,468 @@
+/** @file\r
+\r
+The definition for SD media device driver model and blkio protocol routines.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _SD_MEDIA_DEVICE_H_\r
+#define _SD_MEDIA_DEVICE_H_\r
+\r
+\r
+#include <Uefi.h>\r
+\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/BlockIo.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <IndustryStandard/Pci22.h>\r
+\r
+#include "ComponentName.h"\r
+#include "SDHostIo.h"\r
+\r
+\r
+extern EFI_DRIVER_BINDING_PROTOCOL   gSDMediaDeviceDriverBinding;\r
+extern EFI_COMPONENT_NAME_PROTOCOL   gSDMediaDeviceName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL  gSDMediaDeviceName2;\r
+\r
+//\r
+// Define the region of memory used for DMA memory\r
+//\r
+#define DMA_MEMORY_TOP          0x0000000001FFFFFFULL\r
+\r
+#define CARD_DATA_SIGNATURE  SIGNATURE_32 ('c', 'a', 'r', 'd')\r
+\r
+//\r
+// Command timeout will be max 100 ms\r
+//\r
+#define  TIMEOUT_COMMAND     100\r
+#define  TIMEOUT_DATA        5000\r
+\r
+typedef enum{\r
+  UnknownCard = 0,\r
+  MMCCard,                // MMC card\r
+  MMCCardHighCap,          // MMC Card High Capacity\r
+  CEATACard,              // CE-ATA device\r
+  SDMemoryCard,           // SD 1.1 card\r
+  SDMemoryCard2,          // SD 2.0 or above standard card\r
+  SDMemoryCard2High       // SD 2.0 or above high capacity card\r
+}CARD_TYPE;\r
+\r
+\r
+typedef struct {\r
+  //\r
+  //BlockIO\r
+  //\r
+  UINTN                     Signature;\r
+  EFI_BLOCK_IO_PROTOCOL     BlockIo;\r
+\r
+  EFI_BLOCK_IO_MEDIA        BlockIoMedia;\r
+\r
+  EFI_SD_HOST_IO_PROTOCOL   *SDHostIo;\r
+  EFI_UNICODE_STRING_TABLE  *ControllerNameTable;\r
+  CARD_TYPE                 CardType;\r
+\r
+  UINT8                     CurrentBusWidth;\r
+  BOOLEAN                   DualVoltage;\r
+  BOOLEAN                   NeedFlush;\r
+  UINT8                     Reserved[3];\r
+\r
+  UINT16                    Address;\r
+  UINT32                    BlockLen;\r
+  UINT32                    MaxFrequency;\r
+  UINT64                    BlockNumber;\r
+  //\r
+  //Common used\r
+  //\r
+  CARD_STATUS               CardStatus;\r
+  OCR                       OCRRegister;\r
+  CID                       CIDRegister;\r
+  CSD                       CSDRegister;\r
+  EXT_CSD                   ExtCSDRegister;\r
+  UINT8                     *RawBufferPointer;\r
+  UINT8                     *AlignedBuffer;\r
+  //\r
+  //CE-ATA specific\r
+  //\r
+  TASK_FILE                 TaskFile;\r
+  IDENTIFY_DEVICE_DATA      IndentifyDeviceData;\r
+  //\r
+  //SD specific\r
+  //\r
+  SCR                       SCRRegister;\r
+  SD_STATUS_REG             SDSattus;\r
+  SWITCH_STATUS             SwitchStatus;\r
+}CARD_DATA;\r
+\r
+#define CARD_DATA_FROM_THIS(a) \\r
+    CR(a, CARD_DATA, BlockIo, CARD_DATA_SIGNATURE)\r
+\r
+/**\r
+  Test to see if this driver supports ControllerHandle. Any\r
+  ControllerHandle that has BlockIoProtocol installed will be supported.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  Controller           Handle of device to test.\r
+  @param  RemainingDevicePath  Not used.\r
+\r
+  @return EFI_SUCCESS          This driver supports this device.\r
+  @return EFI_UNSUPPORTED      This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SDMediaDeviceSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL     *This,\r
+  IN EFI_HANDLE                      Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
+  );\r
+\r
+/**\r
+  Starting the SD Media Device Driver.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  Controller           Handle of device to test.\r
+  @param  RemainingDevicePath  Not used.\r
+\r
+  @retval EFI_SUCCESS          This driver supports this device.\r
+  @retval EFI_UNSUPPORTED      This driver does not support this device.\r
+  @retval EFI_DEVICE_ERROR     This driver cannot be started due to device Error.\r
+                               EFI_OUT_OF_RESOURCES- Failed due to resource shortage.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SDMediaDeviceStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL     *This,\r
+  IN EFI_HANDLE                      Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
+  );\r
+\r
+/**\r
+  Stop this driver on ControllerHandle. Support stoping any child handles\r
+  created by this driver.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  Controller           Handle of device to stop driver on.\r
+  @param  NumberOfChildren     Number of Children in the ChildHandleBuffer.\r
+  @param  ChildHandleBuffer    List of handles for the children we need to stop.\r
+\r
+  @return EFI_SUCCESS\r
+  @return others\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SDMediaDeviceStop (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL     *This,\r
+  IN EFI_HANDLE                      Controller,\r
+  IN UINTN                           NumberOfChildren,\r
+  IN EFI_HANDLE                      *ChildHandleBuffer\r
+  );\r
+\r
+/**\r
+  MMC/SD card init function\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+\r
+  @return EFI_SUCCESS\r
+  @return others\r
+\r
+**/\r
+EFI_STATUS\r
+MMCSDCardInit (\r
+  IN  CARD_DATA    *CardData\r
+  );\r
+\r
+/**\r
+  Send command by using Host IO protocol\r
+\r
+  @param  This                  A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
+  @param  CommandIndex          The command index to set the command index field of command register.\r
+  @param  Argument              Command argument to set the argument field of command register.\r
+  @param  DataType              TRANSFER_TYPE, indicates no data, data in or data out.\r
+  @param  Buffer                Contains the data read from / write to the device.\r
+  @param  BufferSize            The size of the buffer.\r
+  @param  ResponseType          RESPONSE_TYPE.\r
+  @param  TimeOut               Time out value in 1 ms unit.\r
+  @param  ResponseData          Depending on the ResponseType, such as CSD or card status.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_INVALID_PARAMETER\r
+  @retval EFI_UNSUPPORTED\r
+  @retval EFI_DEVICE_ERROR\r
+\r
+**/\r
+EFI_STATUS\r
+SendCommand (\r
+  IN   CARD_DATA                  *CardData,\r
+  IN   UINT16                     CommandIndex,\r
+  IN   UINT32                     Argument,\r
+  IN   TRANSFER_TYPE              DataType,\r
+  IN   UINT8                      *Buffer, OPTIONAL\r
+  IN   UINT32                     BufferSize,\r
+  IN   RESPONSE_TYPE              ResponseType,\r
+  IN   UINT32                     TimeOut,\r
+  OUT  UINT32                     *ResponseData\r
+  );\r
+\r
+/**\r
+  Send the card APP_CMD command with the following command indicated by CommandIndex\r
+\r
+  @param  CardData              Pointer to CARD_DATA.\r
+  @param  CommandIndex          The command index to set the command index field of command register.\r
+  @param  Argument              Command argument to set the argument field of command register.\r
+  @param  DataType              TRANSFER_TYPE, indicates no data, data in or data out.\r
+  @param  Buffer                Contains the data read from / write to the device.\r
+  @param  BufferSize            The size of the buffer.\r
+  @param  ResponseType          RESPONSE_TYPE.\r
+  @param  TimeOut               Time out value in 1 ms unit.\r
+  @param  ResponseData          Depending on the ResponseType, such as CSD or card status.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_INVALID_PARAMETER\r
+  @retval EFI_UNSUPPORTED\r
+  @retval EFI_DEVICE_ERROR\r
+\r
+**/\r
+EFI_STATUS\r
+SendAppCommand (\r
+  IN   CARD_DATA                  *CardData,\r
+  IN   UINT16                     CommandIndex,\r
+  IN   UINT32                     Argument,\r
+  IN   TRANSFER_TYPE              DataType,\r
+  IN   UINT8                      *Buffer, OPTIONAL\r
+  IN   UINT32                     BufferSize,\r
+  IN   RESPONSE_TYPE              ResponseType,\r
+  IN   UINT32                     TimeOut,\r
+  OUT  UINT32                     *ResponseData\r
+  );\r
+\r
+/**\r
+  Send the card FAST_IO command\r
+\r
+  @param  CardData               Pointer to CARD_DATA.\r
+  @param  RegisterAddress        Register Address.\r
+  @param  RegisterData           Pointer to register Data.\r
+  @param  Write                  TRUE for write, FALSE for read.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval EFI_UNSUPPORTED\r
+  @retval EFI_INVALID_PARAMETER\r
+  @retval EFI_DEVICE_ERROR\r
+\r
+**/\r
+EFI_STATUS\r
+FastIO (\r
+  IN      CARD_DATA   *CardData,\r
+  IN      UINT8       RegisterAddress,\r
+  IN  OUT UINT8       *RegisterData,\r
+  IN      BOOLEAN     Write\r
+  );\r
+\r
+/**\r
+  Judge whether it is CE-ATA device or not.\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+\r
+  @retval TRUE\r
+  @retval FALSE\r
+\r
+**/\r
+BOOLEAN\r
+IsCEATADevice (\r
+  IN  CARD_DATA    *CardData\r
+  );\r
+\r
+/**\r
+  Send software reset\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+SoftwareReset (\r
+  IN  CARD_DATA    *CardData\r
+  );\r
+\r
+/**\r
+  SendATACommand specificed in Taskfile\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+  @param  TaskFile             Pointer to TASK_FILE.\r
+  @param  Write                TRUE means write, FALSE means read.\r
+  @param  Buffer               If NULL, means no data transfer, neither read nor write.\r
+  @param  SectorCount          Buffer size in 512 bytes unit.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+SendATACommand (\r
+  IN  CARD_DATA   *CardData,\r
+  IN  TASK_FILE   *TaskFile,\r
+  IN  BOOLEAN     Write,\r
+  IN  UINT8       *Buffer,\r
+  IN  UINT16      SectorCount\r
+  );\r
+\r
+/**\r
+  IDENTIFY_DEVICE command\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+IndentifyDevice (\r
+  IN  CARD_DATA    *CardData\r
+  );\r
+\r
+/**\r
+  FLUSH_CACHE_EXT command\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+FlushCache (\r
+  IN  CARD_DATA    *CardData\r
+  );\r
+\r
+/**\r
+  STANDBY_IMMEDIATE command\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+StandByImmediate (\r
+  IN  CARD_DATA    *CardData\r
+  );\r
+\r
+/**\r
+  READ_DMA_EXT command\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+  @param  LBA                  The starting logical block address to read from on the device.\r
+  @param  Buffer               A pointer to the destination buffer for the data. The caller\r
+                               is responsible for either having implicit or explicit ownership\r
+                               of the buffer.\r
+  @param  SectorCount          Size in 512 bytes unit.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+ReadDMAExt (\r
+  IN  CARD_DATA   *CardData,\r
+  IN  EFI_LBA     LBA,\r
+  IN  UINT8       *Buffer,\r
+  IN  UINT16      SectorCount\r
+  );\r
+\r
+/**\r
+  WRITE_DMA_EXT command\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+  @param  LBA                  The starting logical block address to read from on the device.\r
+  @param  Buffer               A pointer to the destination buffer for the data. The caller\r
+                               is responsible for either having implicit or explicit ownership\r
+                               of the buffer.\r
+  @param  SectorCount          Size in 512 bytes unit.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+WriteDMAExt (\r
+  IN  CARD_DATA   *CardData,\r
+  IN  EFI_LBA     LBA,\r
+  IN  UINT8       *Buffer,\r
+  IN  UINT16      SectorCount\r
+  );\r
+\r
+/**\r
+  CEATA card BlockIo init function.\r
+\r
+  @param  CardData               Pointer to CARD_DATA.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval Others\r
+**/\r
+EFI_STATUS\r
+CEATABlockIoInit (\r
+  IN  CARD_DATA    *CardData\r
+  );\r
+\r
+/**\r
+  MMC/SD card BlockIo init function.\r
+\r
+  @param  CardData               Pointer to CARD_DATA.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval Others\r
+**/\r
+EFI_STATUS\r
+MMCSDBlockIoInit (\r
+  IN  CARD_DATA    *CardData\r
+  );\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDeviceDxe.inf b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDeviceDxe.inf
new file mode 100644 (file)
index 0000000..812436e
--- /dev/null
@@ -0,0 +1,66 @@
+## @file\r
+#\r
+#  Component Description File For SDMediaDeviceDxe Module.\r
+#\r
+#  Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution.  The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = SDMediaDevice\r
+  FILE_GUID                      = 80897901-91F6-4efe-9579-3353A0C02DAB\r
+  MODULE_TYPE                    = UEFI_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = InitializeSDMediaDevice\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+#  DRIVER_BINDING                =  gSDMediaDeviceDriverBinding\r
+#  COMPONENT_NAME                =  gSDMediaDeviceName\r
+#  COMPONENT_NAME2               =  gSDMediaDeviceName2\r
+#\r
+\r
+[Sources]\r
+  SDMediaDevice.c\r
+  SDMediaDevice.h\r
+  MMCSDTransfer.c\r
+  CEATA.c\r
+  CEATABlockIo.c\r
+  MMCSDBlockIo.c\r
+  ComponentName.c\r
+  ComponentName.h\r
+\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  MemoryAllocationLib\r
+  BaseLib\r
+  UefiLib\r
+  UefiBootServicesTableLib\r
+  UefiDriverEntryPoint\r
+  BaseMemoryLib\r
+  DebugLib\r
+  PcdLib\r
+\r
+[Protocols]\r
+  gEfiPciIoProtocolGuid                         ## TO_START\r
+  gEfiSDHostIoProtocolGuid                      ## TO_START\r
+  gEfiBlockIoProtocolGuid                       ## BY_START\r
+\r
+[Pcd.common]\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.c
new file mode 100644 (file)
index 0000000..41fb544
--- /dev/null
@@ -0,0 +1,326 @@
+/** @file\r
+Implementation of Usb Controller PPI.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+#include <Ppi/UsbController.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PeimEntryPoint.h>\r
+#include <Library/PeiServicesLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/PciLib.h>\r
+#include <Library/IoLib.h>\r
+\r
+#include "UsbPei.h"\r
+\r
+//\r
+// Globals\r
+//\r
+//\r
+\r
+EFI_PEI_PPI_DESCRIPTOR mPpiList = {\r
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+  &gPeiUsbControllerPpiGuid,\r
+  NULL\r
+};\r
+\r
+UINTN mIohOhciPciReg[IOH_MAX_OHCI_USB_CONTROLLERS] = {\r
+  PCI_LIB_ADDRESS (IOH_USB_BUS_NUMBER, IOH_USB_OHCI_DEVICE_NUMBER, IOH_OHCI_FUNCTION_NUMBER, 0)\r
+};\r
+\r
+UINTN mIohEhciPciReg[IOH_MAX_EHCI_USB_CONTROLLERS] = {\r
+  PCI_LIB_ADDRESS (IOH_USB_BUS_NUMBER, IOH_USB_EHCI_DEVICE_NUMBER, IOH_EHCI_FUNCTION_NUMBER, 0),\r
+};\r
+\r
+/**\r
+  When EHCI get started in DXE, OHCI couldn't get the ownership\r
+  of roothub after warm reset because CF@EHCI hasn't been cleared.\r
+  We should clear that reg before UpdateBootMode. But Reg@EHCI is\r
+  memory-mapped, so need assume a range of space without conflict\r
+  in PCI memory space.\r
+\r
+  @param[in]  PeiServices     The pointer of EFI_PEI_SERVICES\r
+\r
+**/\r
+\r
+VOID\r
+SwitchConfigFlag (\r
+  IN EFI_PEI_SERVICES          **PeiServices\r
+  )\r
+{\r
+  UINT32             SavBaseAddr;\r
+  UINT32             UsbBaseAddr;\r
+  UINT16             SaveCmdData;\r
+  UINT8              EhciCapLen;\r
+  UINT8              Index;\r
+  UsbBaseAddr = 0;\r
+\r
+  for (Index = 0; Index < IOH_MAX_EHCI_USB_CONTROLLERS; Index++) {\r
+    UsbBaseAddr = PcdGet32(PcdPeiQNCUsbControllerMemoryBaseAddress);\r
+    //\r
+    // Manage EHCI on IOH, set UsbBaseAddr\r
+    //\r
+    SavBaseAddr = PciRead32 (mIohEhciPciReg[Index] | R_IOH_USB_MEMBAR);\r
+    PciWrite32 (mIohEhciPciReg[Index] | R_IOH_USB_MEMBAR, UsbBaseAddr);\r
+    //\r
+    // Save Cmd register\r
+    //\r
+    SaveCmdData = PciRead16 (mIohEhciPciReg[Index] | R_IOH_USB_COMMAND);\r
+    //\r
+    // Enable EHCI on IOH\r
+    //\r
+    PciOr16 (mIohEhciPciReg[Index] | R_IOH_USB_COMMAND, B_IOH_USB_COMMAND_BME | B_IOH_USB_COMMAND_MSE );\r
+    //\r
+    // Clear CF register on EHCI\r
+    //\r
+    EhciCapLen = MmioRead8 (UsbBaseAddr + R_IOH_EHCI_CAPLENGTH);\r
+    MmioWrite32 (UsbBaseAddr + EhciCapLen + R_IOH_EHCI_CONFIGFLAGS, 0);\r
+\r
+    DEBUG ((EFI_D_INFO, "CF@EHCI = %x \n", UsbBaseAddr + EhciCapLen + R_IOH_EHCI_CONFIGFLAGS));\r
+    //\r
+    // Restore EHCI UsbBaseAddr in PCI space\r
+    //\r
+    PciWrite32 (mIohEhciPciReg[Index] | R_IOH_USB_MEMBAR, SavBaseAddr);\r
+    //\r
+    // Restore EHCI Command register in PCI space\r
+    //\r
+    PciWrite16(mIohEhciPciReg[Index] | R_IOH_USB_COMMAND, SaveCmdData);\r
+  }\r
+}\r
+/**\r
+  Retrieved specified the USB controller information.\r
+\r
+  @param  PeiServices           The pointer of EFI_PEI_SERVICES.\r
+  @param  This                  This PEI_USB_CONTROLLER_PPI instance.\r
+  @param  UsbControllerId       Indicate which usb controller information will be retrieved.\r
+  @param  ControllerType        Indicate the controller is Ehci, Ohci, OHCI\r
+  @param  BaseAddress           Indicate the memory bar of the controller\r
+\r
+  @retval EFI_SUCCESS           The reset operation succeeded.\r
+  @retval EFI_INVALID_PARAMETER Attributes is not valid.\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+GetOhciController (\r
+  IN EFI_PEI_SERVICES               **PeiServices,\r
+  IN PEI_USB_CONTROLLER_PPI         *This,\r
+  IN UINT8                          UsbControllerId,\r
+  IN UINTN                          *ControllerType,\r
+  IN UINTN                          *BaseAddress\r
+  )\r
+{\r
+  IOH_OHCI_DEVICE         *PeiIohOhciDev;\r
+\r
+  PeiIohOhciDev = IOH_OHCI_DEVICE_FROM_THIS (This);\r
+\r
+  if (UsbControllerId >= IOH_MAX_OHCI_USB_CONTROLLERS) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  *ControllerType = PEI_OHCI_CONTROLLER;\r
+  *BaseAddress = PeiIohOhciDev->MmioBase[UsbControllerId];\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+/**\r
+  Retrieved specified the USB controller information.\r
+\r
+  @param  PeiServices           The pointer of EFI_PEI_SERVICES.\r
+  @param  This                  This PEI_USB_CONTROLLER_PPI instance.\r
+  @param  UsbControllerId       Indicate which usb controller information will be retrieved.\r
+  @param  ControllerType        Indicate the controller is Ehci, Ohci, OHCI\r
+  @param  BaseAddress           Indicate the memory bar of the controller\r
+\r
+  @retval EFI_SUCCESS           The reset operation succeeded.\r
+  @retval EFI_INVALID_PARAMETER Attributes is not valid.\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+GetEhciController (\r
+  IN EFI_PEI_SERVICES               **PeiServices,\r
+  IN PEI_USB_CONTROLLER_PPI         *This,\r
+  IN UINT8                          UsbControllerId,\r
+  IN UINTN                          *ControllerType,\r
+  IN UINTN                          *BaseAddress\r
+  )\r
+{\r
+  IOH_EHCI_DEVICE         *PeiIohEhciDev;\r
+\r
+  PeiIohEhciDev = IOH_EHCI_DEVICE_FROM_THIS (This);\r
+\r
+  if (UsbControllerId >= IOH_MAX_EHCI_USB_CONTROLLERS) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  *ControllerType = PEI_EHCI_CONTROLLER;\r
+  *BaseAddress = PeiIohEhciDev->MmioBase[UsbControllerId];\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Retrieved specified the USB controller information.\r
+\r
+  @param  IohOhciPciReg         Ohci device address list.\r
+  @param  OhciCount             The count of the OHCI\r
+  @param  IohEhciPciReg         Ehci device address list.\r
+  @param  EhciCount             The count of the EHCI\r
+\r
+**/\r
+\r
+VOID\r
+EnableBusMaster (\r
+  IN UINTN IohOhciPciReg[],\r
+  IN UINT8 OhciCount,\r
+  IN UINTN IohEhciPciReg[],\r
+  IN UINT8 EhciCount\r
+  )\r
+{\r
+  UINT8  Index;\r
+  UINT16 CmdReg;\r
+  for (Index = 0; Index < OhciCount; Index ++) {\r
+    CmdReg = PciRead16 (IohOhciPciReg[Index] | R_IOH_USB_COMMAND);\r
+    CmdReg = (UINT16) (CmdReg | B_IOH_USB_COMMAND_BME );\r
+    PciWrite16 (IohOhciPciReg[Index] | R_IOH_USB_COMMAND, CmdReg);\r
+  }\r
+  for (Index = 0; Index < EhciCount; Index ++) {\r
+    CmdReg = PciRead16 (IohEhciPciReg[Index] | R_IOH_USB_COMMAND);\r
+    CmdReg = (UINT16) (CmdReg | B_IOH_USB_COMMAND_BME );\r
+    PciWrite16 (IohEhciPciReg[Index] | R_IOH_USB_COMMAND, CmdReg);\r
+  }\r
+}\r
+\r
+PEI_USB_CONTROLLER_PPI mUsbControllerPpi[2] = { {GetOhciController}, {GetEhciController}};\r
+\r
+/**\r
+  @param  FileHandle  Handle of the file being invoked.\r
+  @param  PeiServices Describes the list of possible PEI Services.\r
+\r
+  @retval EFI_SUCCESS            PPI successfully installed\r
+\r
+**/\r
+EFI_STATUS\r
+PeimInitializeIchUsb (\r
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,\r
+  IN CONST EFI_PEI_SERVICES     **PeiServices\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  UINTN                   i;\r
+  EFI_PHYSICAL_ADDRESS    AllocateAddress;\r
+  IOH_OHCI_DEVICE         *PeiIohOhciDev;\r
+  IOH_EHCI_DEVICE         *PeiIohEhciDev;\r
+  UINT16                  CmdReg;\r
+\r
+  Status = PeiServicesAllocatePages (\r
+             EfiBootServicesCode,\r
+             1,\r
+             &AllocateAddress\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  EnableBusMaster (\r
+    mIohOhciPciReg,\r
+    IOH_MAX_OHCI_USB_CONTROLLERS,\r
+    mIohEhciPciReg,\r
+    IOH_MAX_EHCI_USB_CONTROLLERS\r
+    );\r
+\r
+  if (FeaturePcdGet (PcdEhciRecoveryEnabled)) {\r
+    DEBUG ((EFI_D_INFO, "UsbPei:EHCI is used for recovery\n"));\r
+    //\r
+    // EHCI recovery is enabled\r
+    //\r
+    PeiIohEhciDev = (IOH_EHCI_DEVICE *)((UINTN)AllocateAddress);\r
+    ZeroMem (PeiIohEhciDev, sizeof(IOH_EHCI_DEVICE));\r
+\r
+    PeiIohEhciDev->Signature            = PEI_IOH_EHCI_SIGNATURE;\r
+    CopyMem(&(PeiIohEhciDev->UsbControllerPpi), &mUsbControllerPpi[1], sizeof(PEI_USB_CONTROLLER_PPI));\r
+    CopyMem(&(PeiIohEhciDev->PpiList), &mPpiList, sizeof(mPpiList));\r
+    PeiIohEhciDev->PpiList.Ppi          = &PeiIohEhciDev->UsbControllerPpi;\r
+\r
+    //\r
+    // Assign resources and enable Ehci controllers\r
+    //\r
+    for (i = 0; i < IOH_MAX_EHCI_USB_CONTROLLERS; i++) {\r
+      DEBUG ((EFI_D_INFO, "UsbPei:Enable the %dth EHCI controller for recovery\n", i));\r
+      PeiIohEhciDev->MmioBase[i] = PcdGet32(PcdPeiQNCUsbControllerMemoryBaseAddress) + IOH_USB_CONTROLLER_MMIO_RANGE * i;\r
+      //\r
+      // Assign base address register, Enable Bus Master and Memory Io\r
+      //\r
+      PciWrite32 (mIohEhciPciReg[i] | R_IOH_USB_MEMBAR, PeiIohEhciDev->MmioBase[i]);\r
+      CmdReg = PciRead16 (mIohEhciPciReg[i] | R_IOH_USB_COMMAND);\r
+      CmdReg = (UINT16) (CmdReg | B_IOH_USB_COMMAND_MSE | B_IOH_USB_COMMAND_BME );\r
+      PciWrite16 (mIohEhciPciReg[i] | R_IOH_USB_COMMAND, CmdReg);\r
+    }\r
+    //\r
+    // Install USB Controller PPI\r
+    //\r
+    Status = (**PeiServices).InstallPpi (\r
+                               PeiServices,\r
+                               &PeiIohEhciDev->PpiList\r
+                               );\r
+\r
+    ASSERT_EFI_ERROR (Status);\r
+  } else {\r
+    DEBUG ((EFI_D_INFO, "UsbPei:OHCI is used for recovery\n"));\r
+    //\r
+    // OHCI recovery is enabled\r
+    //\r
+    SwitchConfigFlag ((EFI_PEI_SERVICES**)PeiServices);\r
+    PeiIohOhciDev = (IOH_OHCI_DEVICE *)((UINTN)AllocateAddress);\r
+    ZeroMem (PeiIohOhciDev, sizeof(IOH_OHCI_DEVICE));\r
+\r
+    PeiIohOhciDev->Signature            = PEI_IOH_OHCI_SIGNATURE;\r
+    CopyMem(&(PeiIohOhciDev->UsbControllerPpi), &mUsbControllerPpi[0], sizeof(PEI_USB_CONTROLLER_PPI));\r
+    CopyMem(&(PeiIohOhciDev->PpiList), &mPpiList, sizeof(mPpiList));\r
+    PeiIohOhciDev->PpiList.Ppi          = &PeiIohOhciDev->UsbControllerPpi;\r
+    //\r
+    // Assign resources and enable OHCI controllers\r
+    //\r
+    for (i = 0; i < IOH_MAX_OHCI_USB_CONTROLLERS; i++) {\r
+      DEBUG ((EFI_D_INFO, "UsbPei:Enable the %dth OHCI controller for recovery\n", i));\r
+      PeiIohOhciDev->MmioBase[i] = PcdGet32(PcdPeiQNCUsbControllerMemoryBaseAddress) + IOH_USB_CONTROLLER_MMIO_RANGE * i;\r
+      //\r
+      // Assign base address register, Enable Bus Master and Memory Io\r
+      //\r
+      PciWrite32 (mIohOhciPciReg[i] | R_IOH_USB_MEMBAR, PeiIohOhciDev->MmioBase[i]);\r
+\r
+      Status = PeiServicesAllocatePages (\r
+                 EfiBootServicesCode,\r
+                 1,\r
+                 &AllocateAddress\r
+                 );\r
+      ASSERT_EFI_ERROR (Status);\r
+      MmioWrite32(PeiIohOhciDev->MmioBase[i] + R_IOH_USB_OHCI_HCCABAR, (UINT32)AllocateAddress);\r
+\r
+      CmdReg = PciRead16 (mIohOhciPciReg[i] | R_IOH_USB_COMMAND);\r
+      CmdReg = (UINT16) (CmdReg | B_IOH_USB_COMMAND_MSE | B_IOH_USB_COMMAND_BME );\r
+      PciWrite16 (mIohOhciPciReg[i] | R_IOH_USB_COMMAND, CmdReg);\r
+    }\r
+    //\r
+    // Install USB Controller PPI\r
+    //\r
+    Status = (**PeiServices).InstallPpi (\r
+                               PeiServices,\r
+                               &PeiIohOhciDev->PpiList\r
+                               );\r
+\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.h
new file mode 100644 (file)
index 0000000..5910a0b
--- /dev/null
@@ -0,0 +1,44 @@
+/** @file\r
+Define private data structure for UHCI and EHCI.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _USB_PEI_H\r
+#define _USB_PEI_H\r
+\r
+#include "Ioh.h"\r
+\r
+#define PEI_IOH_OHCI_SIGNATURE          SIGNATURE_32 ('O', 'H', 'C', 'I')\r
+#define PEI_IOH_EHCI_SIGNATURE          SIGNATURE_32 ('E', 'H', 'C', 'I')\r
+\r
+typedef struct {\r
+  UINTN                   Signature;\r
+  PEI_USB_CONTROLLER_PPI  UsbControllerPpi;\r
+  EFI_PEI_PPI_DESCRIPTOR  PpiList;\r
+  UINTN                   MmioBase[IOH_MAX_OHCI_USB_CONTROLLERS];\r
+} IOH_OHCI_DEVICE;\r
+\r
+typedef struct {\r
+  UINTN                   Signature;\r
+  PEI_USB_CONTROLLER_PPI  UsbControllerPpi;\r
+  EFI_PEI_PPI_DESCRIPTOR  PpiList;\r
+  UINTN                   MmioBase[IOH_MAX_EHCI_USB_CONTROLLERS];\r
+} IOH_EHCI_DEVICE;\r
+\r
+#define IOH_OHCI_DEVICE_FROM_THIS(a) \\r
+  CR(a, IOH_OHCI_DEVICE, UsbControllerPpi, PEI_IOH_OHCI_SIGNATURE)\r
+\r
+#define IOH_EHCI_DEVICE_FROM_THIS(a) \\r
+  CR (a, IOH_EHCI_DEVICE, UsbControllerPpi, PEI_IOH_EHCI_SIGNATURE)\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.inf b/QuarkSocPkg/QuarkSouthCluster/Usb/Common/Pei/UsbPei.inf
new file mode 100644 (file)
index 0000000..f06e21c
--- /dev/null
@@ -0,0 +1,59 @@
+## @file\r
+# Component description file for UsbPei module.\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = UsbPei\r
+  FILE_GUID                      = 73E6F6B4-D029-4e87-8405-6067C8BD02A6\r
+  MODULE_TYPE                    = PEIM\r
+  VERSION_STRING                 = 1.0\r
+\r
+  ENTRY_POINT                    = PeimInitializeIchUsb\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  UsbPei.c\r
+  UsbPei.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  IoLib\r
+  PciLib\r
+  PcdLib\r
+  BaseMemoryLib\r
+  PeimEntryPoint\r
+  DebugLib\r
+\r
+[Ppis]\r
+  gPeiUsbControllerPpiGuid                      # PPI ALWAYS_PRODUCED\r
+\r
+[FeaturePcd]\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdEhciRecoveryEnabled\r
+\r
+[Pcd]\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdPeiQNCUsbControllerMemoryBaseAddress\r
+  gEfiQuarkSCSocIdTokenSpaceGuid.PcdPeiP2PMemoryBaseAddress\r
+\r
+[Depex]\r
+  gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/ComponentName.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/ComponentName.c
new file mode 100644 (file)
index 0000000..31f8d59
--- /dev/null
@@ -0,0 +1,225 @@
+/** @file\r
+UEFI Component Name and Name2 protocol for OHCI driver.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include "Ohci.h"\r
+\r
+\r
+//\r
+// EFI Component Name Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  gOhciComponentName = {\r
+  OhciComponentNameGetDriverName,\r
+  OhciComponentNameGetControllerName,\r
+  "eng"\r
+};\r
+\r
+//\r
+// EFI Component Name 2 Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gOhciComponentName2 = {\r
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) OhciComponentNameGetDriverName,\r
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) OhciComponentNameGetControllerName,\r
+  "en"\r
+};\r
+\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mOhciDriverNameTable[] = {\r
+  { "eng;en", L"Usb Ohci Driver" },\r
+  { NULL, NULL }\r
+};\r
+\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+  This function retrieves the user readable name of a driver in the form of a\r
+  Unicode string. If the driver specified by This has a user readable name in\r
+  the language specified by Language, then a pointer to the driver name is\r
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+  by This does not support the language specified by Language,\r
+  then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language. This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified\r
+                                in RFC 4646 or ISO 639-2 language code format.\r
+\r
+  @param  DriverName[out]       A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                driver specified by This in the language\r
+                                specified by Language.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by\r
+                                This and the language specified by Language was\r
+                                returned in DriverName.\r
+\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OhciComponentNameGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **DriverName\r
+  )\r
+{\r
+  return LookupUnicodeString2 (\r
+           Language,\r
+           This->SupportedLanguages,\r
+           mOhciDriverNameTable,\r
+           DriverName,\r
+           (BOOLEAN)(This == &gOhciComponentName)\r
+           );\r
+}\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the controller\r
+  that is being managed by a driver.\r
+\r
+  This function retrieves the user readable name of the controller specified by\r
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+  driver specified by This has a user readable name in the language specified by\r
+  Language, then a pointer to the controller name is returned in ControllerName,\r
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently\r
+  managing the controller specified by ControllerHandle and ChildHandle,\r
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not\r
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  ControllerHandle[in]  The handle of a controller that the driver\r
+                                specified by This is managing.  This handle\r
+                                specifies the controller whose name is to be\r
+                                returned.\r
+\r
+  @param  ChildHandle[in]       The handle of the child controller to retrieve\r
+                                the name of.  This is an optional parameter that\r
+                                may be NULL.  It will be NULL for device\r
+                                drivers.  It will also be NULL for a bus drivers\r
+                                that wish to retrieve the name of the bus\r
+                                controller.  It will not be NULL for a bus\r
+                                driver that wishes to retrieve the name of a\r
+                                child controller.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language.  This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified in\r
+                                RFC 4646 or ISO 639-2 language code format.\r
+\r
+  @param  ControllerName[out]   A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                controller specified by ControllerHandle and\r
+                                ChildHandle in the language specified by\r
+                                Language from the point of view of the driver\r
+                                specified by This.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in\r
+                                the language specified by Language for the\r
+                                driver specified by This was returned in\r
+                                DriverName.\r
+\r
+  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+\r
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+                                EFI_HANDLE.\r
+\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently\r
+                                managing the controller specified by\r
+                                ControllerHandle and ChildHandle.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OhciComponentNameGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,\r
+  IN  EFI_HANDLE                                      ControllerHandle,\r
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,\r
+  IN  CHAR8                                           *Language,\r
+  OUT CHAR16                                          **ControllerName\r
+  )\r
+{\r
+  EFI_STATUS           Status;\r
+  USB_OHCI_HC_DEV      *OhciDev;\r
+  EFI_USB_HC_PROTOCOL  *UsbHc;\r
+\r
+  //\r
+  // This is a device driver, so ChildHandle must be NULL.\r
+  //\r
+  if (ChildHandle != NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  //\r
+  // Make sure this driver is currently managing ControllerHandle\r
+  //\r
+  Status = EfiTestManagedDevice (\r
+             ControllerHandle,\r
+             gOhciDriverBinding.DriverBindingHandle,\r
+             &gEfiPciIoProtocolGuid\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Get the device context\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiUsbHcProtocolGuid,\r
+                  (VOID **) &UsbHc,\r
+                  gOhciDriverBinding.DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  OhciDev = USB_OHCI_HC_DEV_FROM_THIS (UsbHc);\r
+\r
+  return LookupUnicodeString2 (\r
+           Language,\r
+           This->SupportedLanguages,\r
+           OhciDev->ControllerNameTable,\r
+           ControllerName,\r
+           (BOOLEAN)(This == &gOhciComponentName)\r
+           );\r
+\r
+}\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/ComponentName.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/ComponentName.h
new file mode 100644 (file)
index 0000000..4d6b499
--- /dev/null
@@ -0,0 +1,147 @@
+/** @file\r
+This file contains the delarations for componet name routines.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _COMPONENT_NAME_H_\r
+#define _COMPONENT_NAME_H_\r
+\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+  This function retrieves the user readable name of a driver in the form of a\r
+  Unicode string. If the driver specified by This has a user readable name in\r
+  the language specified by Language, then a pointer to the driver name is\r
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+  by This does not support the language specified by Language,\r
+  then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language. This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified\r
+                                in RFC 4646 or ISO 639-2 language code format.\r
+\r
+  @param  DriverName[out]       A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                driver specified by This in the language\r
+                                specified by Language.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by\r
+                                This and the language specified by Language was\r
+                                returned in DriverName.\r
+\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OhciComponentNameGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **DriverName\r
+  );\r
+\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the controller\r
+  that is being managed by a driver.\r
+\r
+  This function retrieves the user readable name of the controller specified by\r
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+  driver specified by This has a user readable name in the language specified by\r
+  Language, then a pointer to the controller name is returned in ControllerName,\r
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently\r
+  managing the controller specified by ControllerHandle and ChildHandle,\r
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not\r
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  ControllerHandle[in]  The handle of a controller that the driver\r
+                                specified by This is managing.  This handle\r
+                                specifies the controller whose name is to be\r
+                                returned.\r
+\r
+  @param  ChildHandle[in]       The handle of the child controller to retrieve\r
+                                the name of.  This is an optional parameter that\r
+                                may be NULL.  It will be NULL for device\r
+                                drivers.  It will also be NULL for a bus drivers\r
+                                that wish to retrieve the name of the bus\r
+                                controller.  It will not be NULL for a bus\r
+                                driver that wishes to retrieve the name of a\r
+                                child controller.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language.  This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified in\r
+                                RFC 4646 or ISO 639-2 language code format.\r
+\r
+  @param  ControllerName[out]   A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                controller specified by ControllerHandle and\r
+                                ChildHandle in the language specified by\r
+                                Language from the point of view of the driver\r
+                                specified by This.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in\r
+                                the language specified by Language for the\r
+                                driver specified by This was returned in\r
+                                DriverName.\r
+\r
+  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+\r
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+                                EFI_HANDLE.\r
+\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently\r
+                                managing the controller specified by\r
+                                ControllerHandle and ChildHandle.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OhciComponentNameGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,\r
+  IN  EFI_HANDLE                                      ControllerHandle,\r
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,\r
+  IN  CHAR8                                           *Language,\r
+  OUT CHAR16                                          **ControllerName\r
+  );\r
+\r
+#endif\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Descriptor.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Descriptor.h
new file mode 100644 (file)
index 0000000..ca8baf5
--- /dev/null
@@ -0,0 +1,138 @@
+/** @file\r
+This file contains the descriptor definination of OHCI spec\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+\r
+#ifndef _DESCRIPTOR_H\r
+#define _DESCRIPTOR_H\r
+\r
+#define ED_FUNC_ADD     0x0001\r
+#define ED_ENDPT_NUM    0x0002\r
+#define ED_DIR          0x0004\r
+#define ED_SPEED        0x0008\r
+#define ED_SKIP         0x0010\r
+#define ED_FORMAT       0x0020\r
+#define ED_MAX_PACKET   0x0040\r
+#define ED_TDTAIL_PTR   0x0080\r
+#define ED_HALTED       0x0100\r
+#define ED_DTTOGGLE     0x0200\r
+#define ED_TDHEAD_PTR   0x0400\r
+#define ED_NEXT_EDPTR   0x0800\r
+#define ED_PDATA        0x1000\r
+#define ED_ZERO         0x2000\r
+\r
+#define TD_BUFFER_ROUND     0x0001\r
+#define TD_DIR_PID          0x0002\r
+#define TD_DELAY_INT        0x0004\r
+#define TD_DT_TOGGLE        0x0008\r
+#define TD_ERROR_CNT        0x0010\r
+#define TD_COND_CODE        0x0020\r
+#define TD_CURR_BUFFER_PTR  0x0040\r
+#define TD_NEXT_PTR         0x0080\r
+#define TD_BUFFER_END_PTR   0x0100\r
+#define TD_PDATA            0x0200\r
+\r
+#define ED_FROM_TD_DIR        0x0\r
+#define ED_OUT_DIR            0x1\r
+#define ED_IN_DIR             0x2\r
+#define ED_FROM_TD_ALSO_DIR   0x3\r
+\r
+#define TD_SETUP_PID          0x00\r
+#define TD_OUT_PID            0x01\r
+#define TD_IN_PID             0x02\r
+#define TD_NODATA_PID         0x03\r
+\r
+#define HI_SPEED              0\r
+#define LO_SPEED              1\r
+\r
+#define TD_NO_ERROR           0x00\r
+#define TD_CRC_ERROR          0x01\r
+#define TD_BITSTUFFING_ERROR  0x02\r
+#define TD_TOGGLE_ERROR       0x03\r
+#define TD_DEVICE_STALL       0x04\r
+#define TD_NO_RESPONSE        0x05\r
+#define TD_PIDCHK_FAIL        0x06\r
+#define TD_PID_UNEXPECTED     0x07\r
+#define TD_DATA_OVERRUN       0x08\r
+#define TD_DATA_UNDERRUN      0x09\r
+#define TD_BUFFER_OVERRUN     0x0C\r
+#define TD_BUFFER_UNDERRUN    0x0D\r
+#define TD_TOBE_PROCESSED     0x0E\r
+#define TD_TOBE_PROCESSED_2   0x0F\r
+\r
+#define TD_NO_DELAY           0x7\r
+\r
+#define TD_INT                0x1\r
+#define TD_CTL                0x2\r
+#define TD_BLK                0x3\r
+\r
+typedef struct {\r
+  UINT32 Reserved:18;\r
+  UINT32 BufferRounding:1;\r
+  UINT32 DirPID:2;\r
+  UINT32 DelayInterrupt:3;\r
+  UINT32 DataToggle:2;\r
+  UINT32 ErrorCount:2;\r
+  UINT32 ConditionCode:4;\r
+} TD_DESCRIPTOR_WORD0;\r
+\r
+typedef struct _TD_DESCRIPTOR {\r
+  TD_DESCRIPTOR_WORD0     Word0;\r
+  UINT32                  CurrBufferPointer;          // 32-bit Physical Address of buffer\r
+  UINT32                  NextTD;                     // 32-bit Physical Address of TD_DESCRIPTOR\r
+  UINT32                  BufferEndPointer;           // 32-bit Physical Address of buffer\r
+  UINT32                  NextTDPointer;              // 32-bit Physical Address of TD_DESCRIPTOR\r
+  UINT32                  DataBuffer;                 // 32-bit Physical Address of buffer\r
+  UINT32                  ActualSendLength;\r
+  UINT32                  Reserved;\r
+} TD_DESCRIPTOR;\r
+\r
+typedef struct {\r
+  UINT32 FunctionAddress:7;\r
+  UINT32 EndPointNum:4;\r
+  UINT32 Direction:2;\r
+  UINT32 Speed:1;\r
+  UINT32 Skip:1;\r
+  UINT32 Format:1;\r
+  UINT32 MaxPacketSize:11;\r
+  UINT32 FreeSpace:5;\r
+} ED_DESCRIPTOR_WORD0;\r
+\r
+typedef struct {\r
+  UINT32 Halted:1;\r
+  UINT32 ToggleCarry:1;\r
+  UINT32 Zero:2;\r
+  UINT32 TdHeadPointer:28;\r
+} ED_DESCRIPTOR_WORD2;\r
+\r
+typedef struct _ED_DESCRIPTOR {\r
+  ED_DESCRIPTOR_WORD0     Word0;\r
+  UINT32                  TdTailPointer;    // 32-bit Physical Address of TD_DESCRIPTOR\r
+  ED_DESCRIPTOR_WORD2     Word2;\r
+  UINT32                  NextED;           // 32-bit Physical Address of ED_DESCRIPTOR\r
+} ED_DESCRIPTOR;\r
+\r
+#define TD_PTR(p)            ((TD_DESCRIPTOR *)(UINTN)((p) << 4))\r
+#define ED_PTR(p)            ((ED_DESCRIPTOR *)(UINTN)((p) << 4))\r
+#define RIGHT_SHIFT_4(p)     ((UINT32)(p) >> 4)\r
+\r
+typedef enum {\r
+  CONTROL_LIST,\r
+  BULK_LIST,\r
+  INTERRUPT_LIST,\r
+  ISOCHRONOUS_LIST\r
+} DESCRIPTOR_LIST_TYPE;\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Ohci.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Ohci.c
new file mode 100644 (file)
index 0000000..f73a09b
--- /dev/null
@@ -0,0 +1,2488 @@
+/** @file\r
+This file contains the implementation of Usb Hc Protocol.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include "Ohci.h"\r
+\r
+/**\r
+  Provides software reset for the USB host controller.\r
+\r
+  @param  This                  This EFI_USB_HC_PROTOCOL instance.\r
+  @param  Attributes            A bit mask of the reset operation to perform.\r
+\r
+  @retval EFI_SUCCESS           The reset operation succeeded.\r
+  @retval EFI_INVALID_PARAMETER Attributes is not valid.\r
+  @retval EFI_UNSUPPOURTED      The type of reset specified by Attributes is\r
+                                not currently supported by the host controller.\r
+  @retval EFI_DEVICE_ERROR      Host controller isn't halted to reset.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OhciReset (\r
+  IN EFI_USB_HC_PROTOCOL  *This,\r
+  IN UINT16               Attributes\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  USB_OHCI_HC_DEV         *Ohc;\r
+  UINT8                   Index;\r
+  UINT8                   NumOfPorts;\r
+  UINT32                  PowerOnGoodTime;\r
+  UINT32                  Data32;\r
+  BOOLEAN                 Flag = FALSE;\r
+\r
+  if ((Attributes & ~(EFI_USB_HC_RESET_GLOBAL | EFI_USB_HC_RESET_HOST_CONTROLLER)) != 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+  Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);\r
+\r
+  if ((Attributes & EFI_USB_HC_RESET_HOST_CONTROLLER) != 0) {\r
+    gBS->Stall (50 * 1000);\r
+    Status = OhciSetHcCommandStatus (Ohc, HC_RESET, HC_RESET);\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+    gBS->Stall (50 * 1000);\r
+    //\r
+    // Wait for host controller reset.\r
+    //\r
+    PowerOnGoodTime = 50;\r
+    do {\r
+      gBS->Stall (1 * 1000);\r
+      Data32 = OhciGetOperationalReg (Ohc->PciIo, HC_COMMAND_STATUS );\r
+      if (EFI_ERROR (Status)) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      if ((Data32 & HC_RESET) == 0) {\r
+        Flag = TRUE;\r
+        break;\r
+      }\r
+    }while(PowerOnGoodTime--);\r
+    if (!Flag){\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+  OhciFreeIntTransferMemory (Ohc);\r
+  Status = OhciInitializeInterruptList (Ohc);\r
+  OhciSetFrameInterval (Ohc, FRAME_INTERVAL, 0x2edf);\r
+  if ((Attributes &  EFI_USB_HC_RESET_GLOBAL) != 0) {\r
+    Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_RESET);\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+    gBS->Stall (50 * 1000);\r
+  }\r
+  //\r
+  // Initialize host controller operational registers\r
+  //\r
+  OhciSetFrameInterval (Ohc, FS_LARGEST_DATA_PACKET, 0x2778);\r
+  OhciSetFrameInterval (Ohc, FRAME_INTERVAL, 0x2edf);\r
+  OhciSetPeriodicStart (Ohc, 0x2a2f);\r
+  OhciSetHcControl (Ohc, CONTROL_BULK_RATIO, 0x3);\r
+  OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED | BULK_LIST_FILLED, 0);\r
+  OhciSetRootHubDescriptor (Ohc, RH_PSWITCH_MODE, 0);\r
+  OhciSetRootHubDescriptor (Ohc, RH_NO_PSWITCH | RH_NOC_PROT, 1);\r
+  //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NO_PSWITCH, 0);\r
+  //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NOC_PROT, 1);\r
+\r
+  OhciSetRootHubDescriptor (Ohc, RH_DEV_REMOVABLE, 0);\r
+  OhciSetRootHubDescriptor (Ohc, RH_PORT_PWR_CTRL_MASK, 0xffff);\r
+  OhciSetRootHubStatus (Ohc, RH_LOCAL_PSTAT_CHANGE);\r
+  OhciSetRootHubPortStatus (Ohc, 0, RH_SET_PORT_POWER);\r
+  OhciGetRootHubNumOfPorts (This, &NumOfPorts);\r
+  for (Index = 0; Index < NumOfPorts; Index++) {\r
+    if (!EFI_ERROR (OhciSetRootHubPortFeature (This, Index, EfiUsbPortReset))) {\r
+      gBS->Stall (200 * 1000);\r
+      OhciClearRootHubPortFeature (This, Index, EfiUsbPortReset);\r
+      gBS->Stall (1000);\r
+      OhciSetRootHubPortFeature (This, Index, EfiUsbPortEnable);\r
+      gBS->Stall (1000);\r
+    }\r
+  }\r
+  OhciSetMemoryPointer (Ohc, HC_HCCA, Ohc->HccaMemoryBlock);\r
+  OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);\r
+  OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);\r
+  OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | BULK_ENABLE, 1); /*ISOCHRONOUS_ENABLE*/\r
+  OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_OPERATIONAL);\r
+  gBS->Stall (50*1000);\r
+  //\r
+  // Wait till first SOF occurs, and then clear it\r
+  //\r
+  while (OhciGetHcInterruptStatus (Ohc, START_OF_FRAME) == 0);\r
+  OhciClearInterruptStatus (Ohc, START_OF_FRAME);\r
+  gBS->Stall (1000);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Retrieve the current state of the USB host controller.\r
+\r
+  @param  This                  This EFI_USB_HC_PROTOCOL instance.\r
+  @param  State                 Variable to return the current host controller\r
+                                state.\r
+\r
+  @retval EFI_SUCCESS           Host controller state was returned in State.\r
+  @retval EFI_INVALID_PARAMETER State is NULL.\r
+  @retval EFI_DEVICE_ERROR      An error was encountered while attempting to\r
+                                retrieve the host controller's current state.\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciGetState (\r
+  IN  EFI_USB_HC_PROTOCOL  *This,\r
+  OUT EFI_USB_HC_STATE     *State\r
+  )\r
+{\r
+  USB_OHCI_HC_DEV         *Ohc;\r
+  UINT32                  FuncState;\r
+\r
+  if (State == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);\r
+\r
+  FuncState = OhciGetHcControl (Ohc, HC_FUNCTIONAL_STATE);\r
+\r
+  switch (FuncState) {\r
+    case HC_STATE_RESET:\r
+    case HC_STATE_RESUME:\r
+      *State = EfiUsbHcStateHalt;\r
+      break;\r
+\r
+    case HC_STATE_OPERATIONAL:\r
+      *State = EfiUsbHcStateOperational;\r
+      break;\r
+\r
+    case HC_STATE_SUSPEND:\r
+      *State = EfiUsbHcStateSuspend;\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Sets the USB host controller to a specific state.\r
+\r
+  @param  This                  This EFI_USB_HC_PROTOCOL instance.\r
+  @param  State                 The state of the host controller that will be set.\r
+\r
+  @retval EFI_SUCCESS           The USB host controller was successfully placed\r
+                                in the state specified by State.\r
+  @retval EFI_INVALID_PARAMETER State is invalid.\r
+  @retval EFI_DEVICE_ERROR      Failed to set the state due to device error.\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciSetState(\r
+  IN EFI_USB_HC_PROTOCOL  *This,\r
+  IN EFI_USB_HC_STATE     State\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  USB_OHCI_HC_DEV         *Ohc;\r
+\r
+  Ohc = USB_OHCI_HC_DEV_FROM_THIS(This);\r
+\r
+  switch (State) {\r
+    case EfiUsbHcStateHalt:\r
+      Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_RESET);\r
+      break;\r
+\r
+    case EfiUsbHcStateOperational:\r
+      Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_OPERATIONAL);\r
+      break;\r
+\r
+    case EfiUsbHcStateSuspend:\r
+      Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_SUSPEND);\r
+      break;\r
+\r
+    default:\r
+      Status = EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  gBS->Stall (1000);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Submits control transfer to a target USB device.\r
+\r
+  @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.\r
+  @param  DeviceAddress         Represents the address of the target device on the USB,\r
+                                which is assigned during USB enumeration.\r
+  @param  IsSlowDevice          Indicates whether the target device is slow device\r
+                                or full-speed device.\r
+  @param  MaxPaketLength        Indicates the maximum packet size that the\r
+                                default control transfer endpoint is capable of\r
+                                sending or receiving.\r
+  @param  Request               A pointer to the USB device request that will be sent\r
+                                to the USB device.\r
+  @param  TransferDirection     Specifies the data direction for the transfer.\r
+                                There are three values available, DataIn, DataOut\r
+                                and NoData.\r
+  @param  Data                  A pointer to the buffer of data that will be transmitted\r
+                                to USB device or received from USB device.\r
+  @param  DataLength            Indicates the size, in bytes, of the data buffer\r
+                                specified by Data.\r
+  @param  TimeOut               Indicates the maximum time, in microseconds,\r
+                                which the transfer is allowed to complete.\r
+  @param  TransferResult        A pointer to the detailed result information generated\r
+                                by this control transfer.\r
+\r
+  @retval EFI_SUCCESS           The control transfer was completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  The control transfer could not be completed due to a lack of resources.\r
+  @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
+  @retval EFI_TIMEOUT           The control transfer failed due to timeout.\r
+  @retval EFI_DEVICE_ERROR      The control transfer failed due to host controller or device error.\r
+                                Caller should check TranferResult for detailed error information.\r
+\r
+--*/\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciControlTransfer (\r
+  IN     EFI_USB_HC_PROTOCOL     *This,\r
+  IN     UINT8                   DeviceAddress,\r
+  IN     BOOLEAN                 IsSlowDevice,\r
+  IN     UINT8                   MaxPacketLength,\r
+  IN     EFI_USB_DEVICE_REQUEST  *Request,\r
+  IN     EFI_USB_DATA_DIRECTION  TransferDirection,\r
+  IN OUT VOID                    *Data                 OPTIONAL,\r
+  IN OUT UINTN                   *DataLength           OPTIONAL,\r
+  IN     UINTN                   TimeOut,\r
+  OUT    UINT32                  *TransferResult\r
+  )\r
+{\r
+  USB_OHCI_HC_DEV                *Ohc;\r
+  ED_DESCRIPTOR                  *HeadEd;\r
+  ED_DESCRIPTOR                  *Ed;\r
+  TD_DESCRIPTOR                  *HeadTd;\r
+  TD_DESCRIPTOR                  *SetupTd;\r
+  TD_DESCRIPTOR                  *DataTd;\r
+  TD_DESCRIPTOR                  *StatusTd;\r
+  TD_DESCRIPTOR                  *EmptyTd;\r
+  EFI_STATUS                     Status;\r
+  UINT32                         DataPidDir;\r
+  UINT32                         StatusPidDir;\r
+  UINTN                          TimeCount;\r
+  OHCI_ED_RESULT                 EdResult;\r
+\r
+  EFI_PCI_IO_PROTOCOL_OPERATION  MapOp;\r
+\r
+  UINTN                          ActualSendLength;\r
+  UINTN                          LeftLength;\r
+  UINT8                          DataToggle;\r
+\r
+  VOID                           *ReqMapping = NULL;\r
+  UINTN                          ReqMapLength = 0;\r
+  EFI_PHYSICAL_ADDRESS           ReqMapPhyAddr = 0;\r
+\r
+  VOID                           *DataMapping = NULL;\r
+  UINTN                          DataMapLength = 0;\r
+  EFI_PHYSICAL_ADDRESS           DataMapPhyAddr = 0;\r
+\r
+  HeadTd = NULL;\r
+  DataTd = NULL;\r
+\r
+  if ((TransferDirection != EfiUsbDataOut && TransferDirection != EfiUsbDataIn &&\r
+       TransferDirection != EfiUsbNoData) ||\r
+      Request == NULL || DataLength == NULL || TransferResult == NULL ||\r
+      (TransferDirection == EfiUsbNoData && (*DataLength != 0 || Data != NULL)) ||\r
+      (TransferDirection != EfiUsbNoData && (*DataLength == 0 || Data == NULL)) ||\r
+      (IsSlowDevice && MaxPacketLength != 8) ||\r
+      (MaxPacketLength != 8 && MaxPacketLength != 16 &&\r
+       MaxPacketLength != 32 && MaxPacketLength != 64)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (*DataLength > MAX_BYTES_PER_TD) {\r
+    DEBUG ((EFI_D_ERROR, "OhciControlTransfer: Request data size is too large\r\n"));\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Ohc = USB_OHCI_HC_DEV_FROM_THIS(This);\r
+\r
+  if (TransferDirection == EfiUsbDataIn) {\r
+    DataPidDir = TD_IN_PID;\r
+    StatusPidDir = TD_OUT_PID;\r
+  } else {\r
+    DataPidDir = TD_OUT_PID;\r
+    StatusPidDir = TD_IN_PID;\r
+  }\r
+\r
+  Status = OhciSetHcControl (Ohc, CONTROL_ENABLE, 0);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable CONTROL_ENABLE\r\n"));\r
+    *TransferResult = EFI_USB_ERR_SYSTEM;\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  Status = OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED, 0);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable CONTROL_LIST_FILLED\r\n"));\r
+    *TransferResult = EFI_USB_ERR_SYSTEM;\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  gBS->Stall(20 * 1000);\r
+\r
+  OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);\r
+  Ed = OhciCreateED (Ohc);\r
+  if (Ed == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate ED buffer\r\n"));\r
+    goto CTRL_EXIT;\r
+  }\r
+  OhciSetEDField (Ed, ED_SKIP, 1);\r
+  OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);\r
+  OhciSetEDField (Ed, ED_ENDPT_NUM, 0);\r
+  OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);\r
+  OhciSetEDField (Ed, ED_SPEED, IsSlowDevice);\r
+  OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0);\r
+  OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);\r
+  OhciSetEDField (Ed, ED_PDATA, 0);\r
+  OhciSetEDField (Ed, ED_ZERO, 0);\r
+  OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);\r
+  OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);\r
+  OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);\r
+  HeadEd = OhciAttachEDToList (Ohc, CONTROL_LIST, Ed, NULL);\r
+  //\r
+  // Setup Stage\r
+  //\r
+  if(Request != NULL) {\r
+    ReqMapLength = sizeof(EFI_USB_DEVICE_REQUEST);\r
+    MapOp = EfiPciIoOperationBusMasterRead;\r
+    Status = Ohc->PciIo->Map (Ohc->PciIo, MapOp, (UINT8 *)Request, &ReqMapLength, &ReqMapPhyAddr, &ReqMapping);\r
+    if (EFI_ERROR(Status)) {\r
+      DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to Map Request Buffer\r\n"));\r
+      goto FREE_ED_BUFF;\r
+    }\r
+  }\r
+  SetupTd = OhciCreateTD (Ohc);\r
+  if (SetupTd == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Setup TD buffer\r\n"));\r
+    goto UNMAP_SETUP_BUFF;\r
+  }\r
+  HeadTd = SetupTd;\r
+  OhciSetTDField (SetupTd, TD_PDATA, 0);\r
+  OhciSetTDField (SetupTd, TD_BUFFER_ROUND, 1);\r
+  OhciSetTDField (SetupTd, TD_DIR_PID, TD_SETUP_PID);\r
+  OhciSetTDField (SetupTd, TD_DELAY_INT, TD_NO_DELAY);\r
+  OhciSetTDField (SetupTd, TD_DT_TOGGLE, 2);\r
+  OhciSetTDField (SetupTd, TD_ERROR_CNT, 0);\r
+  OhciSetTDField (SetupTd, TD_COND_CODE, TD_TOBE_PROCESSED);\r
+  OhciSetTDField (SetupTd, TD_CURR_BUFFER_PTR, (UINT32)ReqMapPhyAddr);\r
+  OhciSetTDField (SetupTd, TD_NEXT_PTR, 0);\r
+  OhciSetTDField (SetupTd, TD_BUFFER_END_PTR, (UINT32)(ReqMapPhyAddr + sizeof (EFI_USB_DEVICE_REQUEST) - 1));\r
+  SetupTd->ActualSendLength = sizeof (EFI_USB_DEVICE_REQUEST);\r
+  SetupTd->DataBuffer = (UINT32)ReqMapPhyAddr;\r
+  SetupTd->NextTDPointer = 0;\r
+\r
+  if (TransferDirection == EfiUsbDataIn) {\r
+    MapOp = EfiPciIoOperationBusMasterWrite;\r
+  } else {\r
+    MapOp = EfiPciIoOperationBusMasterRead;\r
+  }\r
+  DataMapLength = *DataLength;\r
+  if ((Data != NULL) && (DataMapLength != 0)) {\r
+    Status = Ohc->PciIo->Map (Ohc->PciIo, MapOp, Data, &DataMapLength, &DataMapPhyAddr, &DataMapping);\r
+    if (EFI_ERROR(Status)) {\r
+      DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail To Map Data Buffer\r\n"));\r
+      goto FREE_TD_BUFF;\r
+    }\r
+  }\r
+  //\r
+  //Data Stage\r
+  //\r
+  LeftLength = DataMapLength;\r
+  ActualSendLength = DataMapLength;\r
+  DataToggle = 1;\r
+  while (LeftLength > 0) {\r
+    ActualSendLength = LeftLength;\r
+    if (LeftLength > MaxPacketLength) {\r
+      ActualSendLength = MaxPacketLength;\r
+    }\r
+    DataTd = OhciCreateTD (Ohc);\r
+    if (DataTd == NULL) {\r
+      DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate buffer for Data Stage TD\r\n"));\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto UNMAP_DATA_BUFF;\r
+    }\r
+    OhciSetTDField (DataTd, TD_PDATA, 0);\r
+    OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);\r
+    OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);\r
+    OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);\r
+    OhciSetTDField (DataTd, TD_DT_TOGGLE, DataToggle);\r
+    OhciSetTDField (DataTd, TD_ERROR_CNT, 0);\r
+    OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);\r
+    OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) DataMapPhyAddr);\r
+    OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(DataMapPhyAddr + ActualSendLength - 1));\r
+    OhciSetTDField (DataTd, TD_NEXT_PTR, 0);\r
+    DataTd->ActualSendLength = (UINT32)ActualSendLength;\r
+    DataTd->DataBuffer = (UINT32)DataMapPhyAddr;\r
+    DataTd->NextTDPointer = 0;\r
+    OhciLinkTD (HeadTd, DataTd);\r
+    DataToggle ^= 1;\r
+    DataMapPhyAddr += ActualSendLength;\r
+    LeftLength -= ActualSendLength;\r
+  }\r
+  //\r
+  // Status Stage\r
+  //\r
+  StatusTd = OhciCreateTD (Ohc);\r
+  if (StatusTd == NULL) {\r
+    DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate buffer for Status Stage TD\r\n"));\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto UNMAP_DATA_BUFF;\r
+  }\r
+  OhciSetTDField (StatusTd, TD_PDATA, 0);\r
+  OhciSetTDField (StatusTd, TD_BUFFER_ROUND, 1);\r
+  OhciSetTDField (StatusTd, TD_DIR_PID, StatusPidDir);\r
+  OhciSetTDField (StatusTd, TD_DELAY_INT, 7);\r
+  OhciSetTDField (StatusTd, TD_DT_TOGGLE, 3);\r
+  OhciSetTDField (StatusTd, TD_ERROR_CNT, 0);\r
+  OhciSetTDField (StatusTd, TD_COND_CODE, TD_TOBE_PROCESSED);\r
+  OhciSetTDField (StatusTd, TD_CURR_BUFFER_PTR, 0);\r
+  OhciSetTDField (StatusTd, TD_NEXT_PTR, 0);\r
+  OhciSetTDField (StatusTd, TD_BUFFER_END_PTR, 0);\r
+  StatusTd->ActualSendLength = 0;\r
+  StatusTd->DataBuffer = 0;\r
+  StatusTd->NextTDPointer = 0;\r
+  OhciLinkTD (HeadTd, StatusTd);\r
+  //\r
+  // Empty Stage\r
+  //\r
+  EmptyTd = OhciCreateTD (Ohc);\r
+  if (EmptyTd == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto UNMAP_DATA_BUFF;\r
+  }\r
+  OhciSetTDField (EmptyTd, TD_PDATA, 0);\r
+  OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0);\r
+  OhciSetTDField (EmptyTd, TD_DIR_PID, 0);\r
+  OhciSetTDField (EmptyTd, TD_DELAY_INT, 0);\r
+  //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);\r
+  EmptyTd->Word0.DataToggle = 0;\r
+  OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0);\r
+  OhciSetTDField (EmptyTd, TD_COND_CODE, 0);\r
+  OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0);\r
+  OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0);\r
+  OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0);\r
+  EmptyTd->ActualSendLength = 0;\r
+  EmptyTd->DataBuffer = 0;\r
+  EmptyTd->NextTDPointer = 0;\r
+  OhciLinkTD (HeadTd, EmptyTd);\r
+  Ed->TdTailPointer = (UINT32)(UINTN)EmptyTd;\r
+  OhciAttachTDListToED (Ed, HeadTd);\r
+  //\r
+  // For debugging,  dump ED & TD buffer befor transferring\r
+  //\r
+  //\r
+  //OhciDumpEdTdInfo (Ohc, Ed, HeadTd, TRUE);\r
+  //\r
+  OhciSetEDField (Ed, ED_SKIP, 0);\r
+  Status = OhciSetHcControl (Ohc, CONTROL_ENABLE, 1);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to enable CONTROL_ENABLE\r\n"));\r
+    *TransferResult = EFI_USB_ERR_SYSTEM;\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto UNMAP_DATA_BUFF;\r
+  }\r
+  Status = OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED, 1);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to enable CONTROL_LIST_FILLED\r\n"));\r
+    *TransferResult = EFI_USB_ERR_SYSTEM;\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto UNMAP_DATA_BUFF;\r
+  }\r
+  gBS->Stall(20 * 1000);\r
+\r
+\r
+  TimeCount = 0;\r
+  Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &EdResult);\r
+\r
+  while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {\r
+    gBS->Stall (1000);\r
+    TimeCount++;\r
+    Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &EdResult);\r
+  }\r
+  //\r
+  // For debugging, dump ED & TD buffer after transferring\r
+  //\r
+  //OhciDumpEdTdInfo (Ohc, Ed, HeadTd, FALSE);\r
+  //\r
+  *TransferResult = ConvertErrorCode (EdResult.ErrorCode);\r
+\r
+  if (EdResult.ErrorCode != TD_NO_ERROR) {\r
+    if (EdResult.ErrorCode == TD_TOBE_PROCESSED) {\r
+      DEBUG ((EFI_D_INFO, "Control pipe timeout, > %d mS\r\n", TimeOut));\r
+    } else {\r
+      DEBUG ((EFI_D_INFO, "Control pipe broken\r\n"));\r
+    }\r
+    *DataLength = 0;\r
+  } else {\r
+    DEBUG ((EFI_D_INFO, "Control transfer successed\r\n"));\r
+  }\r
+\r
+UNMAP_DATA_BUFF:\r
+  OhciSetEDField (Ed, ED_SKIP, 1);\r
+  if (HeadEd == Ed) {\r
+    OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);\r
+  } else {\r
+    HeadEd->NextED = Ed->NextED;\r
+  }\r
+  if(DataMapping != NULL) {\r
+    Ohc->PciIo->Unmap(Ohc->PciIo, DataMapping);\r
+  }\r
+\r
+FREE_TD_BUFF:\r
+  while (HeadTd) {\r
+    DataTd = HeadTd;\r
+    HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);\r
+    UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));\r
+  }\r
+\r
+UNMAP_SETUP_BUFF:\r
+  if(ReqMapping != NULL) {\r
+    Ohc->PciIo->Unmap(Ohc->PciIo, ReqMapping);\r
+  }\r
+\r
+FREE_ED_BUFF:\r
+  UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));\r
+\r
+CTRL_EXIT:\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Submits bulk transfer to a bulk endpoint of a USB device.\r
+\r
+  @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.\r
+  @param  DeviceAddress         Represents the address of the target device on the USB,\r
+                                which is assigned during USB enumeration.\r
+  @param  EndPointAddress       The combination of an endpoint number and an\r
+                                endpoint direction of the target USB device.\r
+                                Each endpoint address supports data transfer in\r
+                                one direction except the control endpoint\r
+                                (whose default endpoint address is 0).\r
+                                It is the caller's responsibility to make sure that\r
+                                the EndPointAddress represents a bulk endpoint.\r
+  @param  MaximumPacketLength   Indicates the maximum packet size the target endpoint\r
+                                is capable of sending or receiving.\r
+  @param  Data                  A pointer to the buffer of data that will be transmitted\r
+                                to USB device or received from USB device.\r
+  @param  DataLength            When input, indicates the size, in bytes, of the data buffer\r
+                                specified by Data. When output, indicates the actually\r
+                                transferred data size.\r
+  @param  DataToggle            A pointer to the data toggle value. On input, it indicates\r
+                                the initial data toggle value the bulk transfer should adopt;\r
+                                on output, it is updated to indicate the data toggle value\r
+                                of the subsequent bulk transfer.\r
+  @param  TimeOut               Indicates the maximum time, in microseconds, which the\r
+                                transfer is allowed to complete.\r
+  TransferResult                A pointer to the detailed result information of the\r
+                                bulk transfer.\r
+\r
+  @retval EFI_SUCCESS           The bulk transfer was completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  The bulk transfer could not be submitted due to lack of resource.\r
+  @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
+  @retval EFI_TIMEOUT           The bulk transfer failed due to timeout.\r
+  @retval EFI_DEVICE_ERROR      The bulk transfer failed due to host controller or device error.\r
+                                Caller should check TranferResult for detailed error information.\r
+\r
+**/\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciBulkTransfer(\r
+  IN     EFI_USB_HC_PROTOCOL  *This,\r
+  IN     UINT8                DeviceAddress,\r
+  IN     UINT8                EndPointAddress,\r
+  IN     UINT8                MaxPacketLength,\r
+  IN OUT VOID                 *Data,\r
+  IN OUT UINTN                *DataLength,\r
+  IN OUT UINT8                *DataToggle,\r
+  IN     UINTN                TimeOut,\r
+  OUT    UINT32               *TransferResult\r
+  )\r
+{\r
+  USB_OHCI_HC_DEV                *Ohc;\r
+  ED_DESCRIPTOR                  *HeadEd;\r
+  ED_DESCRIPTOR                  *Ed;\r
+  UINT8                          EdDir;\r
+  UINT32                         DataPidDir;\r
+  TD_DESCRIPTOR                  *HeadTd;\r
+  TD_DESCRIPTOR                  *DataTd;\r
+  TD_DESCRIPTOR                  *EmptyTd;\r
+  EFI_STATUS                     Status;\r
+  EFI_USB_DATA_DIRECTION         TransferDirection;\r
+  UINT8                          EndPointNum;\r
+  UINTN                          TimeCount;\r
+  OHCI_ED_RESULT                 EdResult;\r
+\r
+  EFI_PCI_IO_PROTOCOL_OPERATION  MapOp;\r
+  VOID                           *Mapping;\r
+  UINTN                          MapLength;\r
+  EFI_PHYSICAL_ADDRESS           MapPyhAddr;\r
+  UINTN                          LeftLength;\r
+  UINTN                          ActualSendLength;\r
+  BOOLEAN                        FirstTD;\r
+\r
+  Mapping = NULL;\r
+  MapLength = 0;\r
+  MapPyhAddr = 0;\r
+  LeftLength = 0;\r
+  Status = EFI_SUCCESS;\r
+\r
+  if (Data == NULL || DataLength == NULL || DataToggle == NULL || TransferResult == NULL ||\r
+      *DataLength == 0 || (*DataToggle != 0 && *DataToggle != 1) ||\r
+      (MaxPacketLength != 8 && MaxPacketLength != 16 &&\r
+       MaxPacketLength != 32 && MaxPacketLength != 64)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);\r
+\r
+  if ((EndPointAddress & 0x80) != 0) {\r
+    TransferDirection = EfiUsbDataIn;\r
+    EdDir = ED_IN_DIR;\r
+    DataPidDir = TD_IN_PID;\r
+    MapOp = EfiPciIoOperationBusMasterWrite;\r
+  } else {\r
+    TransferDirection = EfiUsbDataOut;\r
+    EdDir = ED_OUT_DIR;\r
+    DataPidDir = TD_OUT_PID;\r
+    MapOp = EfiPciIoOperationBusMasterRead;\r
+  }\r
+\r
+  EndPointNum = (EndPointAddress & 0xF);\r
+  EdResult.NextToggle = *DataToggle;\r
+\r
+  Status = OhciSetHcControl (Ohc, BULK_ENABLE, 0);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable BULK_ENABLE\r\n"));\r
+    *TransferResult = EFI_USB_ERR_SYSTEM;\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  Status = OhciSetHcCommandStatus (Ohc, BULK_LIST_FILLED, 0);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable BULK_LIST_FILLED\r\n"));\r
+    *TransferResult = EFI_USB_ERR_SYSTEM;\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  gBS->Stall(20 * 1000);\r
+\r
+  OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);\r
+\r
+  Ed = OhciCreateED (Ohc);\r
+  if (Ed == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  OhciSetEDField (Ed, ED_SKIP, 1);\r
+  OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);\r
+  OhciSetEDField (Ed, ED_ENDPT_NUM, EndPointNum);\r
+  OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);\r
+  OhciSetEDField (Ed, ED_SPEED, HI_SPEED);\r
+  OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0);\r
+  OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);\r
+  OhciSetEDField (Ed, ED_PDATA, 0);\r
+  OhciSetEDField (Ed, ED_ZERO, 0);\r
+  OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);\r
+  OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);\r
+  OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);\r
+  HeadEd = OhciAttachEDToList (Ohc, BULK_LIST, Ed, NULL);\r
+\r
+  if(Data != NULL) {\r
+    MapLength = *DataLength;\r
+    Status = Ohc->PciIo->Map (Ohc->PciIo, MapOp, (UINT8 *)Data, &MapLength, &MapPyhAddr, &Mapping);\r
+    if (EFI_ERROR(Status)) {\r
+      DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to Map Data Buffer for Bulk\r\n"));\r
+      goto FREE_ED_BUFF;\r
+    }\r
+  }\r
+  //\r
+  //Data Stage\r
+  //\r
+  LeftLength = MapLength;\r
+  ActualSendLength = MapLength;\r
+  HeadTd = NULL;\r
+  FirstTD = TRUE;\r
+  while (LeftLength > 0) {\r
+    ActualSendLength = LeftLength;\r
+    if (LeftLength > MaxPacketLength) {\r
+      ActualSendLength = MaxPacketLength;\r
+    }\r
+    DataTd = OhciCreateTD (Ohc);\r
+    if (DataTd == NULL) {\r
+      DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to allocate buffer for Data Stage TD\r\n"));\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto FREE_OHCI_TDBUFF;\r
+    }\r
+    OhciSetTDField (DataTd, TD_PDATA, 0);\r
+    OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);\r
+    OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);\r
+    OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);\r
+    OhciSetTDField (DataTd, TD_DT_TOGGLE, *DataToggle);\r
+    OhciSetTDField (DataTd, TD_ERROR_CNT, 0);\r
+    OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);\r
+    OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) MapPyhAddr);\r
+    OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(MapPyhAddr + ActualSendLength - 1));\r
+    OhciSetTDField (DataTd, TD_NEXT_PTR, 0);\r
+    DataTd->ActualSendLength = (UINT32)ActualSendLength;\r
+    DataTd->DataBuffer = (UINT32)MapPyhAddr;\r
+    DataTd->NextTDPointer = 0;\r
+    if (FirstTD) {\r
+      HeadTd = DataTd;\r
+      FirstTD = FALSE;\r
+    } else {\r
+      OhciLinkTD (HeadTd, DataTd);\r
+    }\r
+    *DataToggle ^= 1;\r
+    MapPyhAddr += ActualSendLength;\r
+    LeftLength -= ActualSendLength;\r
+  }\r
+  //\r
+  // Empty Stage\r
+  //\r
+  EmptyTd = OhciCreateTD (Ohc);\r
+  if (EmptyTd == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to allocate buffer for Empty TD\r\n"));\r
+    goto FREE_OHCI_TDBUFF;\r
+  }\r
+  OhciSetTDField (EmptyTd, TD_PDATA, 0);\r
+  OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0);\r
+  OhciSetTDField (EmptyTd, TD_DIR_PID, 0);\r
+  OhciSetTDField (EmptyTd, TD_DELAY_INT, 0);\r
+  //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);\r
+  EmptyTd->Word0.DataToggle = 0;\r
+  OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0);\r
+  OhciSetTDField (EmptyTd, TD_COND_CODE, 0);\r
+  OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0);\r
+  OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0);\r
+  OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0);\r
+  EmptyTd->ActualSendLength = 0;\r
+  EmptyTd->DataBuffer = 0;\r
+  EmptyTd->NextTDPointer = 0;\r
+  OhciLinkTD (HeadTd, EmptyTd);\r
+  Ed->TdTailPointer = (UINT32)(UINTN)EmptyTd;\r
+  OhciAttachTDListToED (Ed, HeadTd);\r
+\r
+  OhciSetEDField (Ed, ED_SKIP, 0);\r
+  Status = OhciSetHcCommandStatus (Ohc, BULK_LIST_FILLED, 1);\r
+  if (EFI_ERROR(Status)) {\r
+    *TransferResult = EFI_USB_ERR_SYSTEM;\r
+    Status = EFI_DEVICE_ERROR;\r
+    DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to enable BULK_LIST_FILLED\r\n"));\r
+    goto FREE_OHCI_TDBUFF;\r
+  }\r
+  Status = OhciSetHcControl (Ohc, BULK_ENABLE, 1);\r
+  if (EFI_ERROR(Status)) {\r
+    *TransferResult = EFI_USB_ERR_SYSTEM;\r
+    Status = EFI_DEVICE_ERROR;\r
+    DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to enable BULK_ENABLE\r\n"));\r
+    goto FREE_OHCI_TDBUFF;\r
+  }\r
+  gBS->Stall(20 * 1000);\r
+\r
+  TimeCount = 0;\r
+  Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &EdResult);\r
+  while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {\r
+    gBS->Stall (1000);\r
+    TimeCount++;\r
+    Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &EdResult);\r
+  }\r
+\r
+  *TransferResult = ConvertErrorCode (EdResult.ErrorCode);\r
+\r
+  if (EdResult.ErrorCode != TD_NO_ERROR) {\r
+    if (EdResult.ErrorCode == TD_TOBE_PROCESSED) {\r
+      DEBUG ((EFI_D_INFO, "Bulk pipe timeout, > %d mS\r\n", TimeOut));\r
+    } else {\r
+      DEBUG ((EFI_D_INFO, "Bulk pipe broken\r\n"));\r
+      *DataToggle = EdResult.NextToggle;\r
+    }\r
+    *DataLength = 0;\r
+  } else {\r
+    DEBUG ((EFI_D_INFO, "Bulk transfer successed\r\n"));\r
+  }\r
+  //*DataToggle = (UINT8) OhciGetEDField (Ed, ED_DTTOGGLE);\r
+\r
+FREE_OHCI_TDBUFF:\r
+  OhciSetEDField (Ed, ED_SKIP, 1);\r
+  if (HeadEd == Ed) {\r
+    OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);\r
+  }else {\r
+    HeadEd->NextED = Ed->NextED;\r
+  }\r
+  while (HeadTd) {\r
+    DataTd = HeadTd;\r
+    HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);\r
+    UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));\r
+  }\r
+\r
+  if(Mapping != NULL) {\r
+    Ohc->PciIo->Unmap(Ohc->PciIo, Mapping);\r
+  }\r
+\r
+FREE_ED_BUFF:\r
+  UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));\r
+\r
+  return Status;\r
+}\r
+/**\r
+\r
+  Submits an interrupt transfer to an interrupt endpoint of a USB device.\r
+\r
+  @param  Ohc                   Device private data\r
+  @param  DeviceAddress         Represents the address of the target device on the USB,\r
+                                which is assigned during USB enumeration.\r
+  @param  EndPointAddress       The combination of an endpoint number and an endpoint\r
+                                direction of the target USB device. Each endpoint address\r
+                                supports data transfer in one direction except the\r
+                                control endpoint (whose default endpoint address is 0).\r
+                                It is the caller's responsibility to make sure that\r
+                                the EndPointAddress represents an interrupt endpoint.\r
+  @param  IsSlowDevice          Indicates whether the target device is slow device\r
+                                or full-speed device.\r
+  @param  MaxPacketLength       Indicates the maximum packet size the target endpoint\r
+                                is capable of sending or receiving.\r
+  @param  IsNewTransfer         If TRUE, an asynchronous interrupt pipe is built between\r
+                                the host and the target interrupt endpoint.\r
+                                If FALSE, the specified asynchronous interrupt pipe\r
+                                is canceled.\r
+  @param  DataToggle            A pointer to the data toggle value.  On input, it is valid\r
+                                when IsNewTransfer is TRUE, and it indicates the initial\r
+                                data toggle value the asynchronous interrupt transfer\r
+                                should adopt.\r
+                                On output, it is valid when IsNewTransfer is FALSE,\r
+                                and it is updated to indicate the data toggle value of\r
+                                the subsequent asynchronous interrupt transfer.\r
+  @param  PollingInterval       Indicates the interval, in milliseconds, that the\r
+                                asynchronous interrupt transfer is polled.\r
+                                This parameter is required when IsNewTransfer is TRUE.\r
+  @param  UCBuffer              Uncacheable buffer\r
+  @param  DataLength            Indicates the length of data to be received at the\r
+                                rate specified by PollingInterval from the target\r
+                                asynchronous interrupt endpoint.  This parameter\r
+                                is only required when IsNewTransfer is TRUE.\r
+  @param  CallBackFunction      The Callback function.This function is called at the\r
+                                rate specified by PollingInterval.This parameter is\r
+                                only required when IsNewTransfer is TRUE.\r
+  @param  Context               The context that is passed to the CallBackFunction.\r
+                                This is an optional parameter and may be NULL.\r
+  @param  IsPeriodic            Periodic interrupt or not\r
+  @param  OutputED              The correspoding ED carried out\r
+  @param  OutputTD              The correspoding TD carried out\r
+\r
+\r
+  @retval EFI_SUCCESS           The asynchronous interrupt transfer request has been successfully\r
+                                submitted or canceled.\r
+  @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciInterruptTransfer (\r
+  IN     USB_OHCI_HC_DEV                  *Ohc,\r
+  IN     UINT8                            DeviceAddress,\r
+  IN     UINT8                            EndPointAddress,\r
+  IN     BOOLEAN                          IsSlowDevice,\r
+  IN     UINT8                            MaxPacketLength,\r
+  IN     BOOLEAN                          IsNewTransfer,\r
+  IN OUT UINT8                            *DataToggle        OPTIONAL,\r
+  IN     UINTN                            PollingInterval    OPTIONAL,\r
+  IN     VOID                             *UCBuffer          OPTIONAL,\r
+  IN     UINTN                            DataLength         OPTIONAL,\r
+  IN     EFI_ASYNC_USB_TRANSFER_CALLBACK  CallBackFunction   OPTIONAL,\r
+  IN     VOID                             *Context           OPTIONAL,\r
+  IN     BOOLEAN                          IsPeriodic         OPTIONAL,\r
+  OUT    ED_DESCRIPTOR                    **OutputED         OPTIONAL,\r
+  OUT    TD_DESCRIPTOR                    **OutputTD         OPTIONAL\r
+  )\r
+{\r
+  ED_DESCRIPTOR            *Ed;\r
+  UINT8                    EdDir;\r
+  ED_DESCRIPTOR            *HeadEd;\r
+  TD_DESCRIPTOR            *HeadTd;\r
+  TD_DESCRIPTOR            *DataTd;\r
+  TD_DESCRIPTOR            *EmptTd;\r
+  UINTN                    Depth;\r
+  UINTN                    Index;\r
+  EFI_STATUS               Status;\r
+  UINT8                    EndPointNum;\r
+  UINT32                   DataPidDir;\r
+  EFI_USB_DATA_DIRECTION   TransferDirection;\r
+  INTERRUPT_CONTEXT_ENTRY  *Entry;\r
+  EFI_TPL                  OldTpl;\r
+  BOOLEAN                  FirstTD;\r
+\r
+ VOID                      *Mapping;\r
+ UINTN                     MapLength;\r
+ EFI_PHYSICAL_ADDRESS      MapPyhAddr;\r
+ UINTN                     LeftLength;\r
+ UINTN                     ActualSendLength;\r
+\r
+\r
+  if (DataLength > MAX_BYTES_PER_TD) {\r
+    DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Error param\r\n"));\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((EndPointAddress & 0x80) != 0) {\r
+    TransferDirection = EfiUsbDataIn;\r
+    EdDir = ED_IN_DIR;\r
+    DataPidDir = TD_IN_PID;\r
+  } else {\r
+    TransferDirection = EfiUsbDataOut;\r
+    EdDir = ED_OUT_DIR;\r
+    DataPidDir = TD_OUT_PID;\r
+  }\r
+\r
+  EndPointNum = (EndPointAddress & 0xF);\r
+\r
+  if (!IsNewTransfer) {\r
+    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+    OhciSetHcControl (Ohc, PERIODIC_ENABLE, 0);\r
+    OhciFreeInterruptContext (Ohc, DeviceAddress, EndPointAddress, DataToggle);\r
+    Status = OhciFreeInterruptEdByAddr (Ohc, DeviceAddress, EndPointNum);\r
+    OhciSetHcControl (Ohc, PERIODIC_ENABLE, 1);\r
+    gBS->RestoreTPL (OldTpl);\r
+    return Status;\r
+  }\r
+  MapLength = DataLength;\r
+  Status = Ohc->PciIo->Map(\r
+                         Ohc->PciIo,\r
+                         EfiPciIoOperationBusMasterWrite,\r
+                         UCBuffer,\r
+                         &MapLength,\r
+                         &MapPyhAddr,\r
+                         &Mapping\r
+                         );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Failt to PciIo->Map buffer \r\n"));\r
+    goto EXIT;\r
+  }\r
+  Depth = 5;\r
+  Index = 1;\r
+  while (PollingInterval >= Index * 2 && Depth > 0) {\r
+    Index *= 2;\r
+    Depth--;\r
+  }\r
+  //\r
+  //ED Stage\r
+  //\r
+  HeadEd = OhciFindMinInterruptEDList (Ohc, (UINT32)Depth);\r
+  if ((Ed = OhciFindWorkingEd (HeadEd, DeviceAddress, EndPointNum, EdDir)) != NULL) {\r
+    OhciSetEDField (Ed, ED_SKIP, 1);\r
+  } else {\r
+    Ed = OhciCreateED (Ohc);\r
+    if (Ed == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for ED\r\n"));\r
+      goto UNMAP_OHCI_XBUFF;\r
+    }\r
+    OhciSetEDField (Ed, ED_SKIP, 1);\r
+    OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);\r
+    OhciSetEDField (Ed, ED_ENDPT_NUM, EndPointNum);\r
+    OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);\r
+    OhciSetEDField (Ed, ED_SPEED, IsSlowDevice);\r
+    OhciSetEDField (Ed, ED_FORMAT, 0);\r
+    OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);\r
+    OhciSetEDField (Ed, ED_PDATA | ED_ZERO | ED_HALTED | ED_DTTOGGLE, 0);\r
+    OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);\r
+    OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);\r
+    OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);\r
+    OhciAttachEDToList (Ohc, INTERRUPT_LIST, Ed, HeadEd);\r
+  }\r
+  //\r
+  //Data Stage\r
+  //\r
+  LeftLength = MapLength;\r
+  ActualSendLength = MapLength;\r
+  HeadTd = NULL;\r
+  FirstTD = TRUE;\r
+  while (LeftLength > 0) {\r
+    ActualSendLength = LeftLength;\r
+    if (LeftLength > MaxPacketLength) {\r
+      ActualSendLength = MaxPacketLength;\r
+    }\r
+    DataTd = OhciCreateTD (Ohc);\r
+    if (DataTd == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for Data Stage TD\r\n"));\r
+      goto FREE_OHCI_TDBUFF;\r
+    }\r
+    OhciSetTDField (DataTd, TD_PDATA, 0);\r
+    OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);\r
+    OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);\r
+    OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);\r
+    OhciSetTDField (DataTd, TD_DT_TOGGLE, *DataToggle);\r
+    OhciSetTDField (DataTd, TD_ERROR_CNT, 0);\r
+    OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);\r
+    OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) MapPyhAddr);\r
+    OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(MapPyhAddr + ActualSendLength - 1));\r
+    OhciSetTDField (DataTd, TD_NEXT_PTR, 0);\r
+    DataTd->ActualSendLength = (UINT32)ActualSendLength;\r
+    DataTd->DataBuffer = (UINT32)MapPyhAddr;\r
+    DataTd->NextTDPointer = 0;\r
+    if (FirstTD) {\r
+      HeadTd = DataTd;\r
+      FirstTD = FALSE;\r
+    } else {\r
+      OhciLinkTD (HeadTd, DataTd);\r
+    }\r
+    *DataToggle ^= 1;\r
+    MapPyhAddr += ActualSendLength;\r
+    LeftLength -= ActualSendLength;\r
+  }\r
+\r
+  EmptTd = OhciCreateTD (Ohc);\r
+  if (EmptTd == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for Empty Stage TD\r\n"));\r
+    goto FREE_OHCI_TDBUFF;\r
+  }\r
+  OhciSetTDField (EmptTd, TD_PDATA, 0);\r
+  OhciSetTDField (EmptTd, TD_BUFFER_ROUND, 0);\r
+  OhciSetTDField (EmptTd, TD_DIR_PID, 0);\r
+  OhciSetTDField (EmptTd, TD_DELAY_INT, 0);\r
+  //OhciSetTDField (EmptTd, TD_DT_TOGGLE, CurrentToggle);\r
+  EmptTd->Word0.DataToggle = 0;\r
+  OhciSetTDField (EmptTd, TD_ERROR_CNT, 0);\r
+  OhciSetTDField (EmptTd, TD_COND_CODE, 0);\r
+  OhciSetTDField (EmptTd, TD_CURR_BUFFER_PTR, 0);\r
+  OhciSetTDField (EmptTd, TD_BUFFER_END_PTR, 0);\r
+  OhciSetTDField (EmptTd, TD_NEXT_PTR, 0);\r
+  EmptTd->ActualSendLength = 0;\r
+  EmptTd->DataBuffer = 0;\r
+  EmptTd->NextTDPointer = 0;\r
+  OhciLinkTD (HeadTd, EmptTd);\r
+  Ed->TdTailPointer = (UINT32)(UINTN)EmptTd;\r
+  OhciAttachTDListToED (Ed, HeadTd);\r
+\r
+  if (OutputED != NULL) {\r
+    *OutputED = Ed;\r
+  }\r
+  if (OutputTD != NULL) {\r
+    *OutputTD = HeadTd;\r
+  }\r
+\r
+  if (CallBackFunction != NULL) {\r
+    Entry = AllocatePool (sizeof (INTERRUPT_CONTEXT_ENTRY));\r
+    if (Entry == NULL) {\r
+      goto FREE_OHCI_TDBUFF;\r
+    }\r
+\r
+    Entry->DeviceAddress = DeviceAddress;\r
+    Entry->EndPointAddress = EndPointAddress;\r
+    Entry->Ed = Ed;\r
+    Entry->DataTd = HeadTd;\r
+    Entry->IsSlowDevice = IsSlowDevice;\r
+    Entry->MaxPacketLength = MaxPacketLength;\r
+    Entry->PollingInterval = PollingInterval;\r
+    Entry->CallBackFunction = CallBackFunction;\r
+    Entry->Context = Context;\r
+    Entry->IsPeriodic = IsPeriodic;\r
+    Entry->UCBuffer = UCBuffer;\r
+    Entry->UCBufferMapping = Mapping;\r
+    Entry->DataLength = DataLength;\r
+    Entry->Toggle = DataToggle;\r
+    Entry->NextEntry = NULL;\r
+    OhciAddInterruptContextEntry (Ohc, Entry);\r
+  }\r
+  OhciSetEDField (Ed, ED_SKIP, 0);\r
+\r
+  if (OhciGetHcControl (Ohc, PERIODIC_ENABLE) == 0) {\r
+    Status = OhciSetHcControl (Ohc, PERIODIC_ENABLE, 1);\r
+    gBS->Stall (1000);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+FREE_OHCI_TDBUFF:\r
+  while (HeadTd) {\r
+    DataTd = HeadTd;\r
+    HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);\r
+    UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));\r
+  }\r
+\r
+//FREE_OHCI_EDBUFF:\r
+  if ((HeadEd != Ed) && HeadEd && Ed) {\r
+    while(HeadEd->NextED != (UINT32)(UINTN)Ed) {\r
+      HeadEd = (ED_DESCRIPTOR *)(UINTN)(HeadEd->NextED);\r
+    }\r
+  HeadEd->NextED = Ed->NextED;\r
+    UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));\r
+  }\r
+\r
+UNMAP_OHCI_XBUFF:\r
+  Ohc->PciIo->Unmap(Ohc->PciIo, Mapping);\r
+\r
+EXIT:\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device.\r
+\r
+  @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.\r
+  @param  DeviceAddress         Represents the address of the target device on the USB,\r
+                                which is assigned during USB enumeration.\r
+  @param  EndPointAddress       The combination of an endpoint number and an endpoint\r
+                                direction of the target USB device. Each endpoint address\r
+                                supports data transfer in one direction except the\r
+                                control endpoint (whose default endpoint address is 0).\r
+                                It is the caller's responsibility to make sure that\r
+                                the EndPointAddress represents an interrupt endpoint.\r
+  @param  IsSlowDevice          Indicates whether the target device is slow device\r
+                                or full-speed device.\r
+  @param  MaxiumPacketLength    Indicates the maximum packet size the target endpoint\r
+                                is capable of sending or receiving.\r
+  @param  IsNewTransfer         If TRUE, an asynchronous interrupt pipe is built between\r
+                                the host and the target interrupt endpoint.\r
+                                If FALSE, the specified asynchronous interrupt pipe\r
+                                is canceled.\r
+  @param  DataToggle            A pointer to the data toggle value.  On input, it is valid\r
+                                when IsNewTransfer is TRUE, and it indicates the initial\r
+                                data toggle value the asynchronous interrupt transfer\r
+                                should adopt.\r
+                                On output, it is valid when IsNewTransfer is FALSE,\r
+                                and it is updated to indicate the data toggle value of\r
+                                the subsequent asynchronous interrupt transfer.\r
+  @param  PollingInterval       Indicates the interval, in milliseconds, that the\r
+                                asynchronous interrupt transfer is polled.\r
+                                This parameter is required when IsNewTransfer is TRUE.\r
+  @param  DataLength            Indicates the length of data to be received at the\r
+                                rate specified by PollingInterval from the target\r
+                                asynchronous interrupt endpoint.  This parameter\r
+                                is only required when IsNewTransfer is TRUE.\r
+  @param  CallBackFunction      The Callback function.This function is called at the\r
+                                rate specified by PollingInterval.This parameter is\r
+                                only required when IsNewTransfer is TRUE.\r
+  @param  Context               The context that is passed to the CallBackFunction.\r
+                                This is an optional parameter and may be NULL.\r
+\r
+  @retval EFI_SUCCESS           The asynchronous interrupt transfer request has been successfully\r
+                                submitted or canceled.\r
+  @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+\r
+**/\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciAsyncInterruptTransfer (\r
+  IN     EFI_USB_HC_PROTOCOL              *This,\r
+  IN     UINT8                            DeviceAddress,\r
+  IN     UINT8                            EndPointAddress,\r
+  IN     BOOLEAN                          IsSlowDevice,\r
+  IN     UINT8                            MaxPacketLength,\r
+  IN     BOOLEAN                          IsNewTransfer,\r
+  IN OUT UINT8                            *DataToggle        OPTIONAL,\r
+  IN     UINTN                            PollingInterval    OPTIONAL,\r
+  IN     UINTN                            DataLength         OPTIONAL,\r
+  IN     EFI_ASYNC_USB_TRANSFER_CALLBACK  CallBackFunction   OPTIONAL,\r
+  IN     VOID                             *Context           OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  USB_OHCI_HC_DEV         *Ohc;\r
+  VOID                    *UCBuffer;\r
+\r
+  if (DataToggle == NULL || (EndPointAddress & 0x80) == 0 ||\r
+    (IsNewTransfer && (DataLength == 0 ||\r
+    (*DataToggle != 0 && *DataToggle != 1) || (PollingInterval < 1 || PollingInterval > 255)))) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);\r
+  if ( IsNewTransfer ) {\r
+    UCBuffer = AllocatePool(DataLength);\r
+    if (UCBuffer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+  } else {\r
+    UCBuffer = NULL;\r
+  }\r
+  Status = OhciInterruptTransfer (\r
+             Ohc,\r
+             DeviceAddress,\r
+             EndPointAddress,\r
+             IsSlowDevice,\r
+             MaxPacketLength,\r
+             IsNewTransfer,\r
+             DataToggle,\r
+             PollingInterval,\r
+             UCBuffer,\r
+             DataLength,\r
+             CallBackFunction,\r
+             Context,\r
+             TRUE,\r
+             NULL,\r
+             NULL\r
+             );\r
+  if ( IsNewTransfer ) {\r
+    if (EFI_ERROR(Status)) {\r
+      gBS->FreePool (UCBuffer);\r
+    }\r
+  }\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Submits synchronous interrupt transfer to an interrupt endpoint\r
+  of a USB device.\r
+\r
+  @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.\r
+  @param  DeviceAddress         Represents the address of the target device on the USB,\r
+                                which is assigned during USB enumeration.\r
+  @param  EndPointAddress       The combination of an endpoint number and an endpoint\r
+                                direction of the target USB device. Each endpoint\r
+                                address supports data transfer in one direction\r
+                                except the control endpoint (whose default\r
+                                endpoint address is 0). It is the caller's responsibility\r
+                                to make sure that the EndPointAddress represents\r
+                                an interrupt endpoint.\r
+  @param  IsSlowDevice          Indicates whether the target device is slow device\r
+                                or full-speed device.\r
+  @param  MaxPacketLength       Indicates the maximum packet size the target endpoint\r
+                                is capable of sending or receiving.\r
+  @param  Data                  A pointer to the buffer of data that will be transmitted\r
+                                to USB device or received from USB device.\r
+  @param  DataLength            On input, the size, in bytes, of the data buffer specified\r
+                                by Data. On output, the number of bytes transferred.\r
+  @param  DataToggle            A pointer to the data toggle value. On input, it indicates\r
+                                the initial data toggle value the synchronous interrupt\r
+                                transfer should adopt;\r
+                                on output, it is updated to indicate the data toggle value\r
+                                of the subsequent synchronous interrupt transfer.\r
+  @param  TimeOut               Indicates the maximum time, in microseconds, which the\r
+                                transfer is allowed to complete.\r
+  @param  TransferResult        A pointer to the detailed result information from\r
+                                the synchronous interrupt transfer.\r
+\r
+  @retval EFI_UNSUPPORTED       This interface not available.\r
+  @retval EFI_INVALID_PARAMETER Parameters not follow spec\r
+\r
+**/\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciSyncInterruptTransfer (\r
+  IN     EFI_USB_HC_PROTOCOL  *This,\r
+  IN     UINT8                DeviceAddress,\r
+  IN     UINT8                EndPointAddress,\r
+  IN     BOOLEAN              IsSlowDevice,\r
+  IN     UINT8                MaxPacketLength,\r
+  IN OUT VOID                 *Data,\r
+  IN OUT UINTN                *DataLength,\r
+  IN OUT UINT8                *DataToggle,\r
+  IN     UINTN                TimeOut,\r
+  OUT    UINT32               *TransferResult\r
+  )\r
+{\r
+  USB_OHCI_HC_DEV         *Ohc;\r
+  EFI_STATUS              Status;\r
+  ED_DESCRIPTOR           *Ed;\r
+  TD_DESCRIPTOR           *HeadTd;\r
+  OHCI_ED_RESULT          EdResult;\r
+  VOID                    *UCBuffer;\r
+\r
+  if ((EndPointAddress & 0x80) == 0 || Data == NULL || DataLength == NULL || *DataLength == 0 ||\r
+      (IsSlowDevice && MaxPacketLength > 8) || (!IsSlowDevice && MaxPacketLength > 64) ||\r
+      DataToggle == NULL || (*DataToggle != 0 && *DataToggle != 1) || TransferResult == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);\r
+  UCBuffer = AllocatePool (*DataLength);\r
+  if (UCBuffer == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  Status = OhciInterruptTransfer (\r
+             Ohc,\r
+             DeviceAddress,\r
+             EndPointAddress,\r
+             IsSlowDevice,\r
+             MaxPacketLength,\r
+             TRUE,\r
+             DataToggle,\r
+             1,\r
+             UCBuffer,\r
+             *DataLength,\r
+             NULL,\r
+             NULL,\r
+             FALSE,\r
+             &Ed,\r
+             &HeadTd\r
+             );\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = CheckIfDone (Ohc, INTERRUPT_LIST, Ed, HeadTd, &EdResult);\r
+    while (Status == EFI_NOT_READY && TimeOut > 0) {\r
+      gBS->Stall (1000);\r
+      TimeOut--;\r
+      Status = CheckIfDone (Ohc, INTERRUPT_LIST, Ed, HeadTd, &EdResult);\r
+    }\r
+\r
+    *TransferResult = ConvertErrorCode (EdResult.ErrorCode);\r
+  }\r
+  CopyMem(Data, UCBuffer, *DataLength);\r
+  Status = OhciInterruptTransfer (\r
+             Ohc,\r
+             DeviceAddress,\r
+             EndPointAddress,\r
+             IsSlowDevice,\r
+             MaxPacketLength,\r
+             FALSE,\r
+             DataToggle,\r
+             0,\r
+             NULL,\r
+             0,\r
+             NULL,\r
+             NULL,\r
+             FALSE,\r
+             NULL,\r
+             NULL\r
+             );\r
+\r
+  return Status;\r
+}\r
+/**\r
+\r
+  Submits isochronous transfer to a target USB device.\r
+\r
+  @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.\r
+  @param  DeviceAddress         Represents the address of the target device on the USB,\r
+                                which is assigned during USB enumeration.\r
+  @param  EndPointAddress       End point address\r
+  @param  MaximumPacketLength   Indicates the maximum packet size that the\r
+                                default control transfer endpoint is capable of\r
+                                sending or receiving.\r
+  @param  Data                  A pointer to the buffer of data that will be transmitted\r
+                                to USB device or received from USB device.\r
+  @param  DataLength            Indicates the size, in bytes, of the data buffer\r
+                                specified by Data.\r
+  @param  TransferResult        A pointer to the detailed result information generated\r
+                                by this control transfer.\r
+\r
+  @retval EFI_UNSUPPORTED       This interface not available\r
+  @retval EFI_INVALID_PARAMETER Data is NULL or DataLength is 0 or TransferResult is NULL\r
+\r
+**/\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciIsochronousTransfer (\r
+  IN     EFI_USB_HC_PROTOCOL  *This,\r
+  IN     UINT8                DeviceAddress,\r
+  IN     UINT8                EndPointAddress,\r
+  IN     UINT8                MaximumPacketLength,\r
+  IN OUT VOID                 *Data,\r
+  IN OUT UINTN                DataLength,\r
+  OUT    UINT32               *TransferResult\r
+  )\r
+{\r
+  if (Data == NULL || DataLength == 0 || TransferResult == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+\r
+  Submits Async isochronous transfer to a target USB device.\r
+\r
+  @param  his                   A pointer to the EFI_USB_HC_PROTOCOL instance.\r
+  @param  DeviceAddress         Represents the address of the target device on the USB,\r
+                                which is assigned during USB enumeration.\r
+  @param  EndPointAddress       End point address\r
+  @param  MaximumPacketLength   Indicates the maximum packet size that the\r
+                                default control transfer endpoint is capable of\r
+                                sending or receiving.\r
+  @param  Data                  A pointer to the buffer of data that will be transmitted\r
+                                to USB device or received from USB device.\r
+  @param  IsochronousCallBack   When the transfer complete, the call back function will be called\r
+  @param  Context               Pass to the call back function as parameter\r
+\r
+  @retval EFI_UNSUPPORTED       This interface not available\r
+  @retval EFI_INVALID_PARAMETER Data is NULL or Datalength is 0\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciAsyncIsochronousTransfer (\r
+  IN     EFI_USB_HC_PROTOCOL                *This,\r
+  IN     UINT8                              DeviceAddress,\r
+  IN     UINT8                              EndPointAddress,\r
+  IN     UINT8                              MaximumPacketLength,\r
+  IN OUT VOID                               *Data,\r
+  IN OUT UINTN                              DataLength,\r
+  IN     EFI_ASYNC_USB_TRANSFER_CALLBACK    IsochronousCallBack,\r
+  IN     VOID                               *Context OPTIONAL\r
+  )\r
+{\r
+\r
+  if (Data == NULL || DataLength == 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+\r
+  Retrieves the number of root hub ports.\r
+\r
+  @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.\r
+  @param  NumOfPorts            A pointer to the number of the root hub ports.\r
+\r
+  @retval EFI_SUCCESS           The port number was retrieved successfully.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OhciGetRootHubNumOfPorts (\r
+  IN  EFI_USB_HC_PROTOCOL  *This,\r
+  OUT UINT8                *NumOfPorts\r
+  )\r
+{\r
+  USB_OHCI_HC_DEV  *Ohc;\r
+  Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);\r
+\r
+  if (NumOfPorts == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *NumOfPorts = (UINT8)OhciGetRootHubDescriptor(Ohc, RH_NUM_DS_PORTS);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+/**\r
+\r
+  Retrieves the current status of a USB root hub port.\r
+\r
+  @param  This                  A pointer to the EFI_USB_HC_PROTOCOL.\r
+  @param  PortNumber            Specifies the root hub port from which the status\r
+                                is to be retrieved.  This value is zero-based. For example,\r
+                                if a root hub has two ports, then the first port is numbered 0,\r
+                                and the second port is numbered 1.\r
+  @param  PortStatus            A pointer to the current port status bits and\r
+                                port status change bits.\r
+\r
+  @retval EFI_SUCCESS           The status of the USB root hub port specified by PortNumber\r
+                                was returned in PortStatus.\r
+  @retval EFI_INVALID_PARAMETER Port number not valid\r
+**/\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciGetRootHubPortStatus (\r
+  IN  EFI_USB_HC_PROTOCOL  *This,\r
+  IN  UINT8                PortNumber,\r
+  OUT EFI_USB_PORT_STATUS  *PortStatus\r
+  )\r
+{\r
+  USB_OHCI_HC_DEV  *Ohc;\r
+  UINT8            NumOfPorts;\r
+\r
+  Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);\r
+\r
+  OhciGetRootHubNumOfPorts (This, &NumOfPorts);\r
+  if (PortNumber >= NumOfPorts) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  PortStatus->PortStatus = 0;\r
+  PortStatus->PortChangeStatus = 0;\r
+\r
+  if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_CURR_CONNECT_STAT)) {\r
+    PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_ENABLE_STAT)) {\r
+    PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_SUSPEND_STAT)) {\r
+    PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_OC_INDICATOR)) {\r
+    PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_RESET_STAT)) {\r
+    PortStatus->PortStatus |= USB_PORT_STAT_RESET;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_POWER_STAT)) {\r
+    PortStatus->PortStatus |= USB_PORT_STAT_POWER;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_LSDEVICE_ATTACHED)) {\r
+    PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE)) {\r
+    PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE)) {\r
+    PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE)) {\r
+    PortStatus->PortChangeStatus |= USB_PORT_STAT_C_SUSPEND;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE)) {\r
+    PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE)) {\r
+    PortStatus->PortChangeStatus |= USB_PORT_STAT_C_RESET;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+/**\r
+\r
+  Sets a feature for the specified root hub port.\r
+\r
+  @param  This                  A pointer to the EFI_USB_HC_PROTOCOL.\r
+  @param  PortNumber            Specifies the root hub port whose feature\r
+                                is requested to be set.\r
+  @param  PortFeature           Indicates the feature selector associated\r
+                                with the feature set request.\r
+\r
+  @retval EFI_SUCCESS           The feature specified by PortFeature was set for the\r
+                                USB root hub port specified by PortNumber.\r
+  @retval EFI_DEVICE_ERROR      Set feature failed because of hardware issue\r
+  @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OhciSetRootHubPortFeature (\r
+  IN EFI_USB_HC_PROTOCOL   *This,\r
+  IN UINT8                 PortNumber,\r
+  IN EFI_USB_PORT_FEATURE  PortFeature\r
+  )\r
+{\r
+  USB_OHCI_HC_DEV         *Ohc;\r
+  EFI_STATUS              Status;\r
+  UINT8                   NumOfPorts;\r
+  UINTN                   RetryTimes;\r
+\r
+  OhciGetRootHubNumOfPorts (This, &NumOfPorts);\r
+  if (PortNumber >= NumOfPorts) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+\r
+  switch (PortFeature) {\r
+    case EfiUsbPortPower:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_POWER);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        gBS->Stall (1000);\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 0 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+    case EfiUsbPortReset:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_RESET);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        gBS->Stall (1000);\r
+        RetryTimes++;\r
+      } while ((OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 0 ||\r
+                OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT) == 1) &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+\r
+      OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);\r
+      break;\r
+\r
+    case EfiUsbPortEnable:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_ENABLE);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        gBS->Stall (1000);\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 0 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+\r
+    case EfiUsbPortSuspend:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_SUSPEND);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        gBS->Stall (1000);\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 0 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+    default:\r
+      return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Clears a feature for the specified root hub port.\r
+\r
+  @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.\r
+  @param  PortNumber            Specifies the root hub port whose feature\r
+                                is requested to be cleared.\r
+  @param  PortFeature           Indicates the feature selector associated with the\r
+                                feature clear request.\r
+\r
+  @retval EFI_SUCCESS           The feature specified by PortFeature was cleared for the\r
+                                USB root hub port specified by PortNumber.\r
+  @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.\r
+  @retval EFI_DEVICE_ERROR      Some error happened when clearing feature\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OhciClearRootHubPortFeature (\r
+  IN EFI_USB_HC_PROTOCOL   *This,\r
+  IN UINT8                 PortNumber,\r
+  IN EFI_USB_PORT_FEATURE  PortFeature\r
+  )\r
+{\r
+  USB_OHCI_HC_DEV         *Ohc;\r
+  EFI_STATUS              Status;\r
+  UINT8                   NumOfPorts;\r
+  UINTN                   RetryTimes;\r
+\r
+\r
+  OhciGetRootHubNumOfPorts (This, &NumOfPorts);\r
+  if (PortNumber >= NumOfPorts) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  switch (PortFeature) {\r
+    case EfiUsbPortEnable:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_ENABLE);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        gBS->Stall (1000);\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 1 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+    case EfiUsbPortSuspend:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_SUSPEND_STATUS);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        gBS->Stall (1000);\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 1 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+    case EfiUsbPortReset:\r
+      break;\r
+\r
+    case EfiUsbPortPower:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_POWER);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        gBS->Stall (1000);\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 1 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+    case EfiUsbPortConnectChange:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        gBS->Stall (1000);\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE) == 1 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+    case EfiUsbPortResetChange:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        gBS->Stall (1000);\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 1 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+\r
+    case EfiUsbPortEnableChange:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        gBS->Stall (1000);\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE) == 1 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+    case EfiUsbPortSuspendChange:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        gBS->Stall (1000);\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE) == 1 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+    case EfiUsbPortOverCurrentChange:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        gBS->Stall (1000);\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE) == 1 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+    default:\r
+      return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_DRIVER_BINDING_PROTOCOL gOhciDriverBinding = {\r
+  OHCIDriverBindingSupported,\r
+  OHCIDriverBindingStart,\r
+  OHCIDriverBindingStop,\r
+  0x10,\r
+  NULL,\r
+  NULL\r
+};\r
+\r
+\r
+/**\r
+  Entry point for EFI drivers.\r
+\r
+  @param  ImageHandle           EFI_HANDLE.\r
+  @param  SystemTable           EFI_SYSTEM_TABLE.\r
+\r
+  @retval EFI_SUCCESS           Driver is successfully loaded.\r
+  @return Others                Failed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OHCIDriverEntryPoint (\r
+  IN EFI_HANDLE          ImageHandle,\r
+  IN EFI_SYSTEM_TABLE    *SystemTable\r
+  )\r
+{\r
+  return EfiLibInstallDriverBindingComponentName2 (\r
+           ImageHandle,\r
+           SystemTable,\r
+           &gOhciDriverBinding,\r
+           ImageHandle,\r
+           &gOhciComponentName,\r
+           &gOhciComponentName2\r
+           );\r
+}\r
+\r
+\r
+/**\r
+  Test to see if this driver supports ControllerHandle. Any\r
+  ControllerHandle that has UsbHcProtocol installed will be supported.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  Controller           Handle of device to test.\r
+  @param  RemainingDevicePath  Not used.\r
+\r
+  @return EFI_SUCCESS          This driver supports this device.\r
+  @return EFI_UNSUPPORTED      This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OHCIDriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_PCI_IO_PROTOCOL     *PciIo;\r
+  USB_CLASSC              UsbClassCReg;\r
+  //\r
+  // Test whether there is PCI IO Protocol attached on the controller handle.\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  (VOID **) &PciIo,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIo->Pci.Read (\r
+                        PciIo,\r
+                        EfiPciIoWidthUint8,\r
+                        PCI_CLASSCODE_OFFSET,\r
+                        sizeof (USB_CLASSC) / sizeof (UINT8),\r
+                        &UsbClassCReg\r
+                        );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_UNSUPPORTED;\r
+    goto ON_EXIT;\r
+  }\r
+  //\r
+  // Test whether the controller belongs to OHCI type\r
+  //\r
+  if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||\r
+      (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||\r
+      (UsbClassCReg.ProgInterface != PCI_IF_OHCI)\r
+      ) {\r
+\r
+    Status = EFI_UNSUPPORTED;\r
+  }\r
+ON_EXIT:\r
+  gBS->CloseProtocol (\r
+         Controller,\r
+         &gEfiPciIoProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+\r
+  return Status;\r
+\r
+}\r
+\r
+/**\r
+\r
+  Allocate and initialize the empty OHCI device.\r
+\r
+  @param  PciIo                  The PCIIO to use.\r
+  @param  OriginalPciAttributes  The original PCI attributes.\r
+\r
+  @return Allocated OHCI device  If err, return NULL.\r
+\r
+**/\r
+\r
+USB_OHCI_HC_DEV *\r
+OhciAllocateDev (\r
+  IN EFI_PCI_IO_PROTOCOL  *PciIo,\r
+  IN UINT64               OriginalPciAttributes\r
+  )\r
+{\r
+  USB_OHCI_HC_DEV         *Ohc;\r
+  EFI_STATUS              Status;\r
+  VOID                    *Buf;\r
+  EFI_PHYSICAL_ADDRESS    PhyAddr;\r
+  VOID                    *Map;\r
+  UINTN                   Pages;\r
+  UINTN                   Bytes;\r
+\r
+  Ohc = AllocateZeroPool (sizeof (USB_OHCI_HC_DEV));\r
+  if (Ohc == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  Ohc->Signature                      = USB_OHCI_HC_DEV_SIGNATURE;\r
+  Ohc->PciIo                          = PciIo;\r
+\r
+  Ohc->UsbHc.Reset                    = OhciReset;\r
+  Ohc->UsbHc.GetState                 = OhciGetState;\r
+  Ohc->UsbHc.SetState                 = OhciSetState;\r
+  Ohc->UsbHc.ControlTransfer          = OhciControlTransfer;\r
+  Ohc->UsbHc.BulkTransfer             = OhciBulkTransfer;\r
+  Ohc->UsbHc.AsyncInterruptTransfer   = OhciAsyncInterruptTransfer;\r
+  Ohc->UsbHc.SyncInterruptTransfer    = OhciSyncInterruptTransfer;\r
+  Ohc->UsbHc.IsochronousTransfer      = OhciIsochronousTransfer;\r
+  Ohc->UsbHc.AsyncIsochronousTransfer = OhciAsyncIsochronousTransfer;\r
+  Ohc->UsbHc.GetRootHubPortNumber     = OhciGetRootHubNumOfPorts;\r
+  Ohc->UsbHc.GetRootHubPortStatus     = OhciGetRootHubPortStatus;\r
+  Ohc->UsbHc.SetRootHubPortFeature    = OhciSetRootHubPortFeature;\r
+  Ohc->UsbHc.ClearRootHubPortFeature  = OhciClearRootHubPortFeature;\r
+  Ohc->UsbHc.MajorRevision            = 0x1;\r
+  Ohc->UsbHc.MinorRevision            = 0x1;\r
+\r
+  Ohc->OriginalPciAttributes = OriginalPciAttributes;\r
+\r
+  Ohc->HccaMemoryBlock = NULL;\r
+  Ohc->HccaMemoryMapping   = NULL;\r
+  Ohc->HccaMemoryBuf = NULL;\r
+  Ohc->HccaMemoryPages = 0;\r
+  Ohc->InterruptContextList = NULL;\r
+  Ohc->ControllerNameTable = NULL;\r
+  Ohc->HouseKeeperTimer = NULL;\r
+\r
+  Ohc->MemPool = UsbHcInitMemPool(PciIo, TRUE, 0);\r
+  if(Ohc->MemPool == NULL) {\r
+    goto FREE_DEV_BUFFER;\r
+  }\r
+\r
+  Bytes = 4096;\r
+  Pages = EFI_SIZE_TO_PAGES (Bytes);\r
+\r
+  Status = PciIo->AllocateBuffer (\r
+                    PciIo,\r
+                    AllocateAnyPages,\r
+                    EfiBootServicesData,\r
+                    Pages,\r
+                    &Buf,\r
+                    0\r
+                    );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto FREE_MEM_POOL;\r
+  }\r
+\r
+  Status = PciIo->Map (\r
+                    PciIo,\r
+                    EfiPciIoOperationBusMasterCommonBuffer,\r
+                    Buf,\r
+                    &Bytes,\r
+                    &PhyAddr,\r
+                    &Map\r
+                    );\r
+\r
+  if (EFI_ERROR (Status) || (Bytes != 4096)) {\r
+    goto FREE_MEM_PAGE;\r
+  }\r
+\r
+  Ohc->HccaMemoryBlock = (HCCA_MEMORY_BLOCK *)(UINTN)PhyAddr;\r
+  Ohc->HccaMemoryMapping = Map;\r
+  Ohc->HccaMemoryBuf = (VOID *)(UINTN)Buf;\r
+  Ohc->HccaMemoryPages = Pages;\r
+\r
+  return Ohc;\r
+\r
+FREE_MEM_PAGE:\r
+  PciIo->FreeBuffer (PciIo, Pages, Buf);\r
+FREE_MEM_POOL:\r
+  UsbHcFreeMemPool (Ohc->MemPool);\r
+FREE_DEV_BUFFER:\r
+  FreePool(Ohc);\r
+\r
+  return NULL;\r
+}\r
+/**\r
+\r
+  Free the OHCI device and release its associated resources.\r
+\r
+  @param  Ohc                   The OHCI device to release.\r
+\r
+**/\r
+VOID\r
+OhciFreeDev (\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  )\r
+{\r
+  OhciFreeFixedIntMemory (Ohc);\r
+\r
+  if (Ohc->HouseKeeperTimer != NULL) {\r
+    gBS->CloseEvent (Ohc->HouseKeeperTimer);\r
+  }\r
+\r
+  if (Ohc->ExitBootServiceEvent != NULL) {\r
+    gBS->CloseEvent (Ohc->ExitBootServiceEvent);\r
+  }\r
+\r
+  if (Ohc->MemPool != NULL) {\r
+    UsbHcFreeMemPool (Ohc->MemPool);\r
+  }\r
+\r
+  if (Ohc->HccaMemoryMapping != NULL ) {\r
+    Ohc->PciIo->FreeBuffer (Ohc->PciIo, Ohc->HccaMemoryPages, Ohc->HccaMemoryBuf);\r
+  }\r
+\r
+  if (Ohc->ControllerNameTable != NULL) {\r
+    FreeUnicodeStringTable (Ohc->ControllerNameTable);\r
+  }\r
+\r
+  FreePool (Ohc);\r
+}\r
+/**\r
+\r
+  Uninstall all Ohci Interface.\r
+\r
+  @param  Controller            Controller handle.\r
+  @param  This                  Protocol instance pointer.\r
+\r
+**/\r
+VOID\r
+OhciCleanDevUp (\r
+  IN  EFI_HANDLE           Controller,\r
+  IN  EFI_USB_HC_PROTOCOL  *This\r
+  )\r
+{\r
+  USB_OHCI_HC_DEV  *Ohc;\r
+\r
+  //\r
+  // Retrieve private context structure\r
+  //\r
+  Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);\r
+\r
+  //\r
+  // Uninstall the USB_HC and USB_HC2 protocol\r
+  //\r
+  gBS->UninstallProtocolInterface (\r
+         Controller,\r
+         &gEfiUsbHcProtocolGuid,\r
+         &Ohc->UsbHc\r
+         );\r
+\r
+  //\r
+  // Cancel the timer event\r
+  //\r
+  gBS->SetTimer (Ohc->HouseKeeperTimer, TimerCancel, 0);\r
+\r
+  //\r
+  // Stop the host controller\r
+  //\r
+  OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | ISOCHRONOUS_ENABLE | BULK_ENABLE, 0);\r
+  This->Reset (This, EFI_USB_HC_RESET_GLOBAL);\r
+  This->SetState (This, EfiUsbHcStateHalt);\r
+\r
+  //\r
+  // Free resources\r
+  //\r
+  OhciFreeDynamicIntMemory (Ohc);\r
+\r
+  //\r
+  // Restore original PCI attributes\r
+  //\r
+  Ohc->PciIo->Attributes (\r
+                Ohc->PciIo,\r
+                EfiPciIoAttributeOperationSet,\r
+                Ohc->OriginalPciAttributes,\r
+                NULL\r
+                );\r
+\r
+  //\r
+  // Free the private context structure\r
+  //\r
+  OhciFreeDev (Ohc);\r
+}\r
+\r
+/**\r
+\r
+  One notified function to stop the Host Controller when gBS->ExitBootServices() called.\r
+\r
+  @param  Event                 Pointer to this event\r
+  @param  Context               Event hanlder private data\r
+**/\r
+VOID\r
+EFIAPI\r
+OhcExitBootService (\r
+  EFI_EVENT                      Event,\r
+  VOID                           *Context\r
+  )\r
+{\r
+  USB_OHCI_HC_DEV           *Ohc;\r
+  EFI_USB_HC_PROTOCOL       *UsbHc;\r
+  Ohc = (USB_OHCI_HC_DEV *) Context;\r
+\r
+  UsbHc = &Ohc->UsbHc;\r
+  //\r
+  // Stop the Host Controller\r
+  //\r
+  //OhciStopHc (Ohc, OHC_GENERIC_TIMEOUT);\r
+  OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | ISOCHRONOUS_ENABLE | BULK_ENABLE, 0);\r
+  UsbHc->Reset (UsbHc, EFI_USB_HC_RESET_GLOBAL);\r
+  UsbHc->SetState (UsbHc, EfiUsbHcStateHalt);\r
+\r
+  return;\r
+}\r
+\r
+\r
+/**\r
+  Starting the Usb OHCI Driver.\r
+\r
+  @param  This                  Protocol instance pointer.\r
+  @param  Controller            Handle of device to test.\r
+  @param  RemainingDevicePath   Not used.\r
+\r
+  @retval EFI_SUCCESS           This driver supports this device.\r
+  @retval EFI_UNSUPPORTED       This driver does not support this device.\r
+  @retval EFI_DEVICE_ERROR      This driver cannot be started due to device Error.\r
+                                EFI_OUT_OF_RESOURCES- Failed due to resource shortage.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OHCIDriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_PCI_IO_PROTOCOL     *PciIo;\r
+  USB_OHCI_HC_DEV         *Ohc;\r
+  UINT64                  Supports;\r
+  UINT64                  OriginalPciAttributes;\r
+  BOOLEAN                 PciAttributesSaved;\r
+\r
+  //\r
+  // Open PCIIO, then enable the HC device and turn off emulation\r
+  //\r
+  Ohc = NULL;\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  (VOID **) &PciIo,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  PciAttributesSaved = FALSE;\r
+  //\r
+  // Save original PCI attributes\r
+  //\r
+  Status = PciIo->Attributes (\r
+                    PciIo,\r
+                    EfiPciIoAttributeOperationGet,\r
+                    0,\r
+                    &OriginalPciAttributes\r
+                    );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto CLOSE_PCIIO;\r
+  }\r
+  PciAttributesSaved = TRUE;\r
+\r
+  //\r
+  // Robustnesss improvement such as for UoL\r
+  // Default is not required.\r
+  //\r
+  //if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {\r
+  //  OhciTurnOffUsbEmulation (PciIo);\r
+  //}\r
+\r
+  Status = PciIo->Attributes (\r
+                    PciIo,\r
+                    EfiPciIoAttributeOperationSupported,\r
+                    0,\r
+                    &Supports\r
+                    );\r
+  if (!EFI_ERROR (Status)) {\r
+    Supports &= EFI_PCI_DEVICE_ENABLE;\r
+    Status = PciIo->Attributes (\r
+                      PciIo,\r
+                      EfiPciIoAttributeOperationEnable,\r
+                      Supports,\r
+                      NULL\r
+                      );\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto CLOSE_PCIIO;\r
+  }\r
+  //\r
+  //Allocate memory for OHC private data structure\r
+  //\r
+  Ohc = OhciAllocateDev(PciIo, OriginalPciAttributes);\r
+  if (Ohc == NULL){\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto CLOSE_PCIIO;\r
+  }\r
+\r
+  //Status = OhciInitializeInterruptList ( Uhc );\r
+  //if (EFI_ERROR (Status)) {\r
+  //  goto FREE_OHC;\r
+  //}\r
+\r
+  //\r
+  // Set 0.01 s timer\r
+  //\r
+  Status = gBS->CreateEvent (\r
+                  EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  OhciHouseKeeper,\r
+                  Ohc,\r
+                  &Ohc->HouseKeeperTimer\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto FREE_OHC;\r
+  }\r
+\r
+  Status = gBS->SetTimer (Ohc->HouseKeeperTimer, TimerPeriodic, 10 * 1000 * 10);\r
+  if (EFI_ERROR (Status)) {\r
+    goto FREE_OHC;\r
+  }\r
+\r
+  //\r
+  //Install Host Controller Protocol\r
+  //\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &Controller,\r
+                  &gEfiUsbHcProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &Ohc->UsbHc\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_INFO, "Install protocol error"));\r
+    goto FREE_OHC;\r
+  }\r
+  //\r
+  // Create event to stop the HC when exit boot service.\r
+  //\r
+  Status = gBS->CreateEventEx (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  OhcExitBootService,\r
+                  Ohc,\r
+                  &gEfiEventExitBootServicesGuid,\r
+                  &Ohc->ExitBootServiceEvent\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_INFO, "Create exit boot event error"));\r
+    goto UNINSTALL_USBHC;\r
+  }\r
+  AddUnicodeString2 (\r
+    "eng",\r
+    gOhciComponentName.SupportedLanguages,\r
+    &Ohc->ControllerNameTable,\r
+    L"Usb Universal Host Controller",\r
+    TRUE\r
+    );\r
+  AddUnicodeString2 (\r
+    "en",\r
+    gOhciComponentName2.SupportedLanguages,\r
+    &Ohc->ControllerNameTable,\r
+    L"Usb Universal Host Controller",\r
+    FALSE\r
+    );\r
+\r
+  return EFI_SUCCESS;\r
+\r
+UNINSTALL_USBHC:\r
+  gBS->UninstallMultipleProtocolInterfaces (\r
+         Controller,\r
+         &gEfiUsbHcProtocolGuid,\r
+         &Ohc->UsbHc,\r
+         NULL\r
+         );\r
+\r
+FREE_OHC:\r
+  OhciFreeDev (Ohc);\r
+\r
+CLOSE_PCIIO:\r
+  if (PciAttributesSaved) {\r
+  //\r
+  // Restore original PCI attributes\r
+  //\r
+    PciIo->Attributes (\r
+             PciIo,\r
+             EfiPciIoAttributeOperationSet,\r
+             OriginalPciAttributes,\r
+             NULL\r
+             );\r
+  }\r
+\r
+  gBS->CloseProtocol (\r
+         Controller,\r
+         &gEfiPciIoProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Stop this driver on ControllerHandle. Support stoping any child handles\r
+  created by this driver.\r
+\r
+  @param  This                  Protocol instance pointer.\r
+  @param  Controller            Handle of device to stop driver on.\r
+  @param  NumberOfChildren      Number of Children in the ChildHandleBuffer.\r
+  @param  ChildHandleBuffer     List of handles for the children we need to stop.\r
+\r
+  @return EFI_SUCCESS\r
+  @return others\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OHCIDriverBindingStop (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN UINTN                        NumberOfChildren,\r
+  IN EFI_HANDLE                   *ChildHandleBuffer\r
+  )\r
+{\r
+  EFI_STATUS           Status;\r
+  EFI_USB_HC_PROTOCOL  *UsbHc;\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiUsbHcProtocolGuid,\r
+                  (VOID **)&UsbHc,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  OhciCleanDevUp(Controller, UsbHc);\r
+\r
+  gBS->CloseProtocol (\r
+         Controller,\r
+         &gEfiPciIoProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Ohci.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Ohci.h
new file mode 100644 (file)
index 0000000..1bfe4a8
--- /dev/null
@@ -0,0 +1,669 @@
+/** @file\r
+Provides the definition of Usb Hc Protocol and OHCI controller\r
+private data structure.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+\r
+#ifndef _OHCI_H\r
+#define _OHCI_H\r
+\r
+\r
+#include <Uefi.h>\r
+\r
+#include <Protocol/UsbHostController.h>\r
+#include <Protocol/PciIo.h>\r
+\r
+#include <Guid/EventGroup.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+\r
+#include <IndustryStandard/Pci.h>\r
+\r
+\r
+typedef struct _USB_OHCI_HC_DEV USB_OHCI_HC_DEV;\r
+\r
+#include "UsbHcMem.h"\r
+#include "OhciReg.h"\r
+#include "OhciSched.h"\r
+#include "OhciUrb.h"\r
+#include "Descriptor.h"\r
+#include "ComponentName.h"\r
+#include "OhciDebug.h"\r
+\r
+extern EFI_DRIVER_BINDING_PROTOCOL   gOhciDriverBinding;\r
+extern EFI_COMPONENT_NAME_PROTOCOL   gOhciComponentName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL  gOhciComponentName2;\r
+\r
+#define USB_OHCI_HC_DEV_SIGNATURE     SIGNATURE_32('o','h','c','i')\r
+\r
+typedef struct _HCCA_MEMORY_BLOCK{\r
+  UINT32                    HccaInterruptTable[32];    // 32-bit Physical Address to ED_DESCRIPTOR\r
+  UINT16                    HccaFrameNumber;\r
+  UINT16                    HccaPad;\r
+  UINT32                    HccaDoneHead;              // 32-bit Physical Address to TD_DESCRIPTOR\r
+  UINT8                     Reserved[116];\r
+} HCCA_MEMORY_BLOCK;\r
+\r
+\r
+struct _USB_OHCI_HC_DEV {\r
+  UINTN                     Signature;\r
+  EFI_USB_HC_PROTOCOL       UsbHc;\r
+  EFI_USB2_HC_PROTOCOL      Usb2Hc;\r
+  EFI_PCI_IO_PROTOCOL       *PciIo;\r
+  UINT64                    OriginalPciAttributes;\r
+\r
+  HCCA_MEMORY_BLOCK         *HccaMemoryBlock;\r
+  VOID                      *HccaMemoryBuf;\r
+  VOID                      *HccaMemoryMapping;\r
+  UINTN                     HccaMemoryPages;\r
+\r
+  ED_DESCRIPTOR             *IntervalList[6][32];\r
+  INTERRUPT_CONTEXT_ENTRY   *InterruptContextList;\r
+  VOID                      *MemPool;\r
+\r
+  UINT32                    ToggleFlag;\r
+\r
+  EFI_EVENT                 HouseKeeperTimer;\r
+  //\r
+  // ExitBootServicesEvent is used to stop the OHC DMA operation\r
+  // after exit boot service.\r
+  //\r
+  EFI_EVENT                  ExitBootServiceEvent;\r
+\r
+  EFI_UNICODE_STRING_TABLE  *ControllerNameTable;\r
+};\r
+\r
+#define USB_OHCI_HC_DEV_FROM_THIS(a)    CR(a, USB_OHCI_HC_DEV, UsbHc, USB_OHCI_HC_DEV_SIGNATURE)\r
+#define USB2_OHCI_HC_DEV_FROM_THIS(a)    CR(a, USB_OHCI_HC_DEV, Usb2Hc, USB_OHCI_HC_DEV_SIGNATURE)\r
+\r
+//\r
+// Func List\r
+//\r
+\r
+/**\r
+  Provides software reset for the USB host controller.\r
+\r
+  @param  This                  This EFI_USB_HC_PROTOCOL instance.\r
+  @param  Attributes            A bit mask of the reset operation to perform.\r
+\r
+  @retval EFI_SUCCESS           The reset operation succeeded.\r
+  @retval EFI_INVALID_PARAMETER Attributes is not valid.\r
+  @retval EFI_UNSUPPOURTED      The type of reset specified by Attributes is\r
+                                not currently supported by the host controller.\r
+  @retval EFI_DEVICE_ERROR      Host controller isn't halted to reset.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OhciReset (\r
+  IN EFI_USB_HC_PROTOCOL  *This,\r
+  IN UINT16               Attributes\r
+  );\r
+/**\r
+  Retrieve the current state of the USB host controller.\r
+\r
+  @param  This                  This EFI_USB_HC_PROTOCOL instance.\r
+  @param  State                 Variable to return the current host controller\r
+                                state.\r
+\r
+  @retval EFI_SUCCESS           Host controller state was returned in State.\r
+  @retval EFI_INVALID_PARAMETER State is NULL.\r
+  @retval EFI_DEVICE_ERROR      An error was encountered while attempting to\r
+                                retrieve the host controller's current state.\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciGetState (\r
+  IN  EFI_USB_HC_PROTOCOL  *This,\r
+  OUT EFI_USB_HC_STATE     *State\r
+  );\r
+/**\r
+  Sets the USB host controller to a specific state.\r
+\r
+  @param  This                  This EFI_USB_HC_PROTOCOL instance.\r
+  @param  State                 The state of the host controller that will be set.\r
+\r
+  @retval EFI_SUCCESS           The USB host controller was successfully placed\r
+                                in the state specified by State.\r
+  @retval EFI_INVALID_PARAMETER State is invalid.\r
+  @retval EFI_DEVICE_ERROR      Failed to set the state due to device error.\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciSetState(\r
+  IN EFI_USB_HC_PROTOCOL  *This,\r
+  IN EFI_USB_HC_STATE     State\r
+  );\r
+/**\r
+\r
+  Submits control transfer to a target USB device.\r
+\r
+  @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.\r
+  @param  DeviceAddress         Represents the address of the target device on the USB,\r
+                                which is assigned during USB enumeration.\r
+  @param  IsSlowDevice          Indicates whether the target device is slow device\r
+                                or full-speed device.\r
+  @param  MaxPaketLength        Indicates the maximum packet size that the\r
+                                default control transfer endpoint is capable of\r
+                                sending or receiving.\r
+  @param  Request               A pointer to the USB device request that will be sent\r
+                                to the USB device.\r
+  @param  TransferDirection     Specifies the data direction for the transfer.\r
+                                There are three values available, DataIn, DataOut\r
+                                and NoData.\r
+  @param  Data                  A pointer to the buffer of data that will be transmitted\r
+                                to USB device or received from USB device.\r
+  @param  DataLength            Indicates the size, in bytes, of the data buffer\r
+                                specified by Data.\r
+  @param  TimeOut               Indicates the maximum time, in microseconds,\r
+                                which the transfer is allowed to complete.\r
+  @param  TransferResult        A pointer to the detailed result information generated\r
+                                by this control transfer.\r
+\r
+  @retval EFI_SUCCESS           The control transfer was completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  The control transfer could not be completed due to a lack of resources.\r
+  @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
+  @retval EFI_TIMEOUT           The control transfer failed due to timeout.\r
+  @retval EFI_DEVICE_ERROR      The control transfer failed due to host controller or device error.\r
+                                Caller should check TranferResult for detailed error information.\r
+\r
+--*/\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciControlTransfer (\r
+  IN     EFI_USB_HC_PROTOCOL     *This,\r
+  IN     UINT8                   DeviceAddress,\r
+  IN     BOOLEAN                 IsSlowDevice,\r
+  IN     UINT8                   MaxPacketLength,\r
+  IN     EFI_USB_DEVICE_REQUEST  *Request,\r
+  IN     EFI_USB_DATA_DIRECTION  TransferDirection,\r
+  IN OUT VOID                    *Data                 OPTIONAL,\r
+  IN OUT UINTN                   *DataLength           OPTIONAL,\r
+  IN     UINTN                   TimeOut,\r
+  OUT    UINT32                  *TransferResult\r
+  );\r
+/**\r
+\r
+  Submits bulk transfer to a bulk endpoint of a USB device.\r
+\r
+  @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.\r
+  @param  DeviceAddress         Represents the address of the target device on the USB,\r
+                                which is assigned during USB enumeration.\r
+  @param  EndPointAddress       The combination of an endpoint number and an\r
+                                endpoint direction of the target USB device.\r
+                                Each endpoint address supports data transfer in\r
+                                one direction except the control endpoint\r
+                                (whose default endpoint address is 0).\r
+                                It is the caller's responsibility to make sure that\r
+                                the EndPointAddress represents a bulk endpoint.\r
+  @param  MaximumPacketLength   Indicates the maximum packet size the target endpoint\r
+                                is capable of sending or receiving.\r
+  @param  Data                  A pointer to the buffer of data that will be transmitted\r
+                                to USB device or received from USB device.\r
+  @param  DataLength            When input, indicates the size, in bytes, of the data buffer\r
+                                specified by Data. When output, indicates the actually\r
+                                transferred data size.\r
+  @param  DataToggle            A pointer to the data toggle value. On input, it indicates\r
+                                the initial data toggle value the bulk transfer should adopt;\r
+                                on output, it is updated to indicate the data toggle value\r
+                                of the subsequent bulk transfer.\r
+  @param  TimeOut               Indicates the maximum time, in microseconds, which the\r
+                                transfer is allowed to complete.\r
+  TransferResult                A pointer to the detailed result information of the\r
+                                bulk transfer.\r
+\r
+  @retval EFI_SUCCESS           The bulk transfer was completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  The bulk transfer could not be submitted due to lack of resource.\r
+  @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
+  @retval EFI_TIMEOUT           The bulk transfer failed due to timeout.\r
+  @retval EFI_DEVICE_ERROR      The bulk transfer failed due to host controller or device error.\r
+                                Caller should check TranferResult for detailed error information.\r
+\r
+**/\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciBulkTransfer(\r
+  IN     EFI_USB_HC_PROTOCOL  *This,\r
+  IN     UINT8                DeviceAddress,\r
+  IN     UINT8                EndPointAddress,\r
+  IN     UINT8                MaxPacketLength,\r
+  IN OUT VOID                 *Data,\r
+  IN OUT UINTN                *DataLength,\r
+  IN OUT UINT8                *DataToggle,\r
+  IN     UINTN                TimeOut,\r
+  OUT    UINT32               *TransferResult\r
+  );\r
+/**\r
+\r
+  Submits an interrupt transfer to an interrupt endpoint of a USB device.\r
+\r
+  @param  Ohc                   Device private data\r
+  @param  DeviceAddress         Represents the address of the target device on the USB,\r
+                                which is assigned during USB enumeration.\r
+  @param  EndPointAddress       The combination of an endpoint number and an endpoint\r
+                                direction of the target USB device. Each endpoint address\r
+                                supports data transfer in one direction except the\r
+                                control endpoint (whose default endpoint address is 0).\r
+                                It is the caller's responsibility to make sure that\r
+                                the EndPointAddress represents an interrupt endpoint.\r
+  @param  IsSlowDevice          Indicates whether the target device is slow device\r
+                                or full-speed device.\r
+  @param  MaxPacketLength       Indicates the maximum packet size the target endpoint\r
+                                is capable of sending or receiving.\r
+  @param  IsNewTransfer         If TRUE, an asynchronous interrupt pipe is built between\r
+                                the host and the target interrupt endpoint.\r
+                                If FALSE, the specified asynchronous interrupt pipe\r
+                                is canceled.\r
+  @param  DataToggle            A pointer to the data toggle value.  On input, it is valid\r
+                                when IsNewTransfer is TRUE, and it indicates the initial\r
+                                data toggle value the asynchronous interrupt transfer\r
+                                should adopt.\r
+                                On output, it is valid when IsNewTransfer is FALSE,\r
+                                and it is updated to indicate the data toggle value of\r
+                                the subsequent asynchronous interrupt transfer.\r
+  @param  PollingInterval       Indicates the interval, in milliseconds, that the\r
+                                asynchronous interrupt transfer is polled.\r
+                                This parameter is required when IsNewTransfer is TRUE.\r
+  @param  UCBuffer              Uncacheable buffer\r
+  @param  DataLength            Indicates the length of data to be received at the\r
+                                rate specified by PollingInterval from the target\r
+                                asynchronous interrupt endpoint.  This parameter\r
+                                is only required when IsNewTransfer is TRUE.\r
+  @param  CallBackFunction      The Callback function.This function is called at the\r
+                                rate specified by PollingInterval.This parameter is\r
+                                only required when IsNewTransfer is TRUE.\r
+  @param  Context               The context that is passed to the CallBackFunction.\r
+                                This is an optional parameter and may be NULL.\r
+  @param  IsPeriodic            Periodic interrupt or not\r
+  @param  OutputED              The correspoding ED carried out\r
+  @param  OutputTD              The correspoding TD carried out\r
+\r
+\r
+  @retval EFI_SUCCESS           The asynchronous interrupt transfer request has been successfully\r
+                                submitted or canceled.\r
+  @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciInterruptTransfer (\r
+  IN     USB_OHCI_HC_DEV                  *Ohc,\r
+  IN     UINT8                            DeviceAddress,\r
+  IN     UINT8                            EndPointAddress,\r
+  IN     BOOLEAN                          IsSlowDevice,\r
+  IN     UINT8                            MaxPacketLength,\r
+  IN     BOOLEAN                          IsNewTransfer,\r
+  IN OUT UINT8                            *DataToggle        OPTIONAL,\r
+  IN     UINTN                            PollingInterval    OPTIONAL,\r
+  IN     VOID                             *UCBuffer          OPTIONAL,\r
+  IN     UINTN                            DataLength         OPTIONAL,\r
+  IN     EFI_ASYNC_USB_TRANSFER_CALLBACK  CallBackFunction   OPTIONAL,\r
+  IN     VOID                             *Context           OPTIONAL,\r
+  IN     BOOLEAN                          IsPeriodic         OPTIONAL,\r
+  OUT    ED_DESCRIPTOR                    **OutputED         OPTIONAL,\r
+  OUT    TD_DESCRIPTOR                    **OutputTD         OPTIONAL\r
+  );\r
+/**\r
+\r
+  Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device.\r
+\r
+  @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.\r
+  @param  DeviceAddress         Represents the address of the target device on the USB,\r
+                                which is assigned during USB enumeration.\r
+  @param  EndPointAddress       The combination of an endpoint number and an endpoint\r
+                                direction of the target USB device. Each endpoint address\r
+                                supports data transfer in one direction except the\r
+                                control endpoint (whose default endpoint address is 0).\r
+                                It is the caller's responsibility to make sure that\r
+                                the EndPointAddress represents an interrupt endpoint.\r
+  @param  IsSlowDevice          Indicates whether the target device is slow device\r
+                                or full-speed device.\r
+  @param  MaxiumPacketLength    Indicates the maximum packet size the target endpoint\r
+                                is capable of sending or receiving.\r
+  @param  IsNewTransfer         If TRUE, an asynchronous interrupt pipe is built between\r
+                                the host and the target interrupt endpoint.\r
+                                If FALSE, the specified asynchronous interrupt pipe\r
+                                is canceled.\r
+  @param  DataToggle            A pointer to the data toggle value.  On input, it is valid\r
+                                when IsNewTransfer is TRUE, and it indicates the initial\r
+                                data toggle value the asynchronous interrupt transfer\r
+                                should adopt.\r
+                                On output, it is valid when IsNewTransfer is FALSE,\r
+                                and it is updated to indicate the data toggle value of\r
+                                the subsequent asynchronous interrupt transfer.\r
+  @param  PollingInterval       Indicates the interval, in milliseconds, that the\r
+                                asynchronous interrupt transfer is polled.\r
+                                This parameter is required when IsNewTransfer is TRUE.\r
+  @param  DataLength            Indicates the length of data to be received at the\r
+                                rate specified by PollingInterval from the target\r
+                                asynchronous interrupt endpoint.  This parameter\r
+                                is only required when IsNewTransfer is TRUE.\r
+  @param  CallBackFunction      The Callback function.This function is called at the\r
+                                rate specified by PollingInterval.This parameter is\r
+                                only required when IsNewTransfer is TRUE.\r
+  @param  Context               The context that is passed to the CallBackFunction.\r
+                                This is an optional parameter and may be NULL.\r
+\r
+  @retval EFI_SUCCESS           The asynchronous interrupt transfer request has been successfully\r
+                                submitted or canceled.\r
+  @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+\r
+**/\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciAsyncInterruptTransfer (\r
+  IN     EFI_USB_HC_PROTOCOL              *This,\r
+  IN     UINT8                            DeviceAddress,\r
+  IN     UINT8                            EndPointAddress,\r
+  IN     BOOLEAN                          IsSlowDevice,\r
+  IN     UINT8                            MaxPacketLength,\r
+  IN     BOOLEAN                          IsNewTransfer,\r
+  IN OUT UINT8                            *DataToggle        OPTIONAL,\r
+  IN     UINTN                            PollingInterval    OPTIONAL,\r
+  IN     UINTN                            DataLength         OPTIONAL,\r
+  IN     EFI_ASYNC_USB_TRANSFER_CALLBACK  CallBackFunction   OPTIONAL,\r
+  IN     VOID                             *Context           OPTIONAL\r
+  );\r
+/**\r
+\r
+  Submits synchronous interrupt transfer to an interrupt endpoint\r
+  of a USB device.\r
+\r
+  @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.\r
+  @param  DeviceAddress         Represents the address of the target device on the USB,\r
+                                which is assigned during USB enumeration.\r
+  @param  EndPointAddress       The combination of an endpoint number and an endpoint\r
+                                direction of the target USB device. Each endpoint\r
+                                address supports data transfer in one direction\r
+                                except the control endpoint (whose default\r
+                                endpoint address is 0). It is the caller's responsibility\r
+                                to make sure that the EndPointAddress represents\r
+                                an interrupt endpoint.\r
+  @param  IsSlowDevice          Indicates whether the target device is slow device\r
+                                or full-speed device.\r
+  @param  MaxPacketLength       Indicates the maximum packet size the target endpoint\r
+                                is capable of sending or receiving.\r
+  @param  Data                  A pointer to the buffer of data that will be transmitted\r
+                                to USB device or received from USB device.\r
+  @param  DataLength            On input, the size, in bytes, of the data buffer specified\r
+                                by Data. On output, the number of bytes transferred.\r
+  @param  DataToggle            A pointer to the data toggle value. On input, it indicates\r
+                                the initial data toggle value the synchronous interrupt\r
+                                transfer should adopt;\r
+                                on output, it is updated to indicate the data toggle value\r
+                                of the subsequent synchronous interrupt transfer.\r
+  @param  TimeOut               Indicates the maximum time, in microseconds, which the\r
+                                transfer is allowed to complete.\r
+  @param  TransferResult        A pointer to the detailed result information from\r
+                                the synchronous interrupt transfer.\r
+\r
+  @retval EFI_UNSUPPORTED       This interface not available.\r
+  @retval EFI_INVALID_PARAMETER Parameters not follow spec\r
+\r
+**/\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciSyncInterruptTransfer (\r
+  IN     EFI_USB_HC_PROTOCOL  *This,\r
+  IN     UINT8                DeviceAddress,\r
+  IN     UINT8                EndPointAddress,\r
+  IN     BOOLEAN              IsSlowDevice,\r
+  IN     UINT8                MaxPacketLength,\r
+  IN OUT VOID                 *Data,\r
+  IN OUT UINTN                *DataLength,\r
+  IN OUT UINT8                *DataToggle,\r
+  IN     UINTN                TimeOut,\r
+  OUT    UINT32               *TransferResult\r
+  );\r
+/**\r
+\r
+  Submits isochronous transfer to a target USB device.\r
+\r
+  @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.\r
+  @param  DeviceAddress         Represents the address of the target device on the USB,\r
+                                which is assigned during USB enumeration.\r
+  @param  EndPointAddress       End point address\r
+  @param  MaximumPacketLength   Indicates the maximum packet size that the\r
+                                default control transfer endpoint is capable of\r
+                                sending or receiving.\r
+  @param  Data                  A pointer to the buffer of data that will be transmitted\r
+                                to USB device or received from USB device.\r
+  @param  DataLength            Indicates the size, in bytes, of the data buffer\r
+                                specified by Data.\r
+  @param  TransferResult        A pointer to the detailed result information generated\r
+                                by this control transfer.\r
+\r
+  @retval EFI_UNSUPPORTED       This interface not available\r
+  @retval EFI_INVALID_PARAMETER Data is NULL or DataLength is 0 or TransferResult is NULL\r
+\r
+**/\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciIsochronousTransfer (\r
+  IN     EFI_USB_HC_PROTOCOL  *This,\r
+  IN     UINT8                DeviceAddress,\r
+  IN     UINT8                EndPointAddress,\r
+  IN     UINT8                MaximumPacketLength,\r
+  IN OUT VOID                 *Data,\r
+  IN OUT UINTN                DataLength,\r
+  OUT    UINT32               *TransferResult\r
+  );\r
+/**\r
+\r
+  Submits Async isochronous transfer to a target USB device.\r
+\r
+  @param  his                   A pointer to the EFI_USB_HC_PROTOCOL instance.\r
+  @param  DeviceAddress         Represents the address of the target device on the USB,\r
+                                which is assigned during USB enumeration.\r
+  @param  EndPointAddress       End point address\r
+  @param  MaximumPacketLength   Indicates the maximum packet size that the\r
+                                default control transfer endpoint is capable of\r
+                                sending or receiving.\r
+  @param  Data                  A pointer to the buffer of data that will be transmitted\r
+                                to USB device or received from USB device.\r
+  @param  IsochronousCallBack   When the transfer complete, the call back function will be called\r
+  @param  Context               Pass to the call back function as parameter\r
+\r
+  @retval EFI_UNSUPPORTED       This interface not available\r
+  @retval EFI_INVALID_PARAMETER Data is NULL or Datalength is 0\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciAsyncIsochronousTransfer (\r
+  IN     EFI_USB_HC_PROTOCOL                *This,\r
+  IN     UINT8                              DeviceAddress,\r
+  IN     UINT8                              EndPointAddress,\r
+  IN     UINT8                              MaximumPacketLength,\r
+  IN OUT VOID                               *Data,\r
+  IN OUT UINTN                              DataLength,\r
+  IN     EFI_ASYNC_USB_TRANSFER_CALLBACK    IsochronousCallBack,\r
+  IN     VOID                               *Context OPTIONAL\r
+  );\r
+\r
+/**\r
+\r
+  Retrieves the number of root hub ports.\r
+\r
+  @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.\r
+  @param  NumOfPorts            A pointer to the number of the root hub ports.\r
+\r
+  @retval EFI_SUCCESS           The port number was retrieved successfully.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OhciGetRootHubNumOfPorts (\r
+  IN  EFI_USB_HC_PROTOCOL  *This,\r
+  OUT UINT8                *NumOfPorts\r
+  );\r
+/**\r
+\r
+  Retrieves the current status of a USB root hub port.\r
+\r
+  @param  This                  A pointer to the EFI_USB_HC_PROTOCOL.\r
+  @param  PortNumber            Specifies the root hub port from which the status\r
+                                is to be retrieved.  This value is zero-based. For example,\r
+                                if a root hub has two ports, then the first port is numbered 0,\r
+                                and the second port is numbered 1.\r
+  @param  PortStatus            A pointer to the current port status bits and\r
+                                port status change bits.\r
+\r
+  @retval EFI_SUCCESS           The status of the USB root hub port specified by PortNumber\r
+                                was returned in PortStatus.\r
+  @retval EFI_INVALID_PARAMETER Port number not valid\r
+**/\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciGetRootHubPortStatus (\r
+  IN  EFI_USB_HC_PROTOCOL  *This,\r
+  IN  UINT8                PortNumber,\r
+  OUT EFI_USB_PORT_STATUS  *PortStatus\r
+  );\r
+\r
+/**\r
+\r
+  Sets a feature for the specified root hub port.\r
+\r
+  @param  This                  A pointer to the EFI_USB_HC_PROTOCOL.\r
+  @param  PortNumber            Specifies the root hub port whose feature\r
+                                is requested to be set.\r
+  @param  PortFeature           Indicates the feature selector associated\r
+                                with the feature set request.\r
+\r
+  @retval EFI_SUCCESS           The feature specified by PortFeature was set for the\r
+                                USB root hub port specified by PortNumber.\r
+  @retval EFI_DEVICE_ERROR      Set feature failed because of hardware issue\r
+  @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OhciSetRootHubPortFeature (\r
+  IN EFI_USB_HC_PROTOCOL   *This,\r
+  IN UINT8                 PortNumber,\r
+  IN EFI_USB_PORT_FEATURE  PortFeature\r
+  );\r
+/**\r
+\r
+  Clears a feature for the specified root hub port.\r
+\r
+  @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.\r
+  @param  PortNumber            Specifies the root hub port whose feature\r
+                                is requested to be cleared.\r
+  @param  PortFeature           Indicates the feature selector associated with the\r
+                                feature clear request.\r
+\r
+  @retval EFI_SUCCESS           The feature specified by PortFeature was cleared for the\r
+                                USB root hub port specified by PortNumber.\r
+  @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.\r
+  @retval EFI_DEVICE_ERROR      Some error happened when clearing feature\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OhciClearRootHubPortFeature (\r
+  IN EFI_USB_HC_PROTOCOL   *This,\r
+  IN UINT8                 PortNumber,\r
+  IN EFI_USB_PORT_FEATURE  PortFeature\r
+  );\r
+\r
+\r
+/**\r
+  Test to see if this driver supports ControllerHandle. Any\r
+  ControllerHandle that has UsbHcProtocol installed will be supported.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  Controller           Handle of device to test.\r
+  @param  RemainingDevicePath  Not used.\r
+\r
+  @return EFI_SUCCESS          This driver supports this device.\r
+  @return EFI_UNSUPPORTED      This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+\r
+OHCIDriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  );\r
+\r
+/**\r
+  Starting the Usb OHCI Driver.\r
+\r
+  @param  This                  Protocol instance pointer.\r
+  @param  Controller            Handle of device to test.\r
+  @param  RemainingDevicePath   Not used.\r
+\r
+  @retval EFI_SUCCESS           This driver supports this device.\r
+  @retval EFI_UNSUPPORTED       This driver does not support this device.\r
+  @retval EFI_DEVICE_ERROR      This driver cannot be started due to device Error.\r
+                                EFI_OUT_OF_RESOURCES- Failed due to resource shortage.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OHCIDriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  );\r
+\r
+/**\r
+  Stop this driver on ControllerHandle. Support stoping any child handles\r
+  created by this driver.\r
+\r
+  @param  This                  Protocol instance pointer.\r
+  @param  Controller            Handle of device to stop driver on.\r
+  @param  NumberOfChildren      Number of Children in the ChildHandleBuffer.\r
+  @param  ChildHandleBuffer     List of handles for the children we need to stop.\r
+\r
+  @return EFI_SUCCESS\r
+  @return others\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OHCIDriverBindingStop (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN UINTN                        NumberOfChildren,\r
+  IN EFI_HANDLE                   *ChildHandleBuffer\r
+  );\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDebug.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDebug.c
new file mode 100644 (file)
index 0000000..69d268a
--- /dev/null
@@ -0,0 +1,84 @@
+/** @file\r
+This file provides the information dump support for OHCI when in debug mode.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include "Ohci.h"\r
+\r
+\r
+/*++\r
+\r
+  Print the data of ED and the TDs attached to the ED\r
+\r
+  @param  Uhc                   Pointer to OHCI private data\r
+  @param  Ed                    Pointer to a ED to free\r
+  @param  Td                    Pointer to the Td head\r
+\r
+  @retval EFI_SUCCESS           ED\r
+\r
+**/\r
+EFI_STATUS\r
+OhciDumpEdTdInfo (\r
+  IN USB_OHCI_HC_DEV      *Uhc,\r
+  IN ED_DESCRIPTOR        *Ed,\r
+  IN TD_DESCRIPTOR        *Td,\r
+  BOOLEAN                 Stage\r
+  )\r
+{\r
+  UINT32                  Index;\r
+\r
+  if (Stage) {\r
+    DEBUG ((EFI_D_INFO, "\n Before executing command\n"));\r
+  }else{\r
+    DEBUG ((EFI_D_INFO, "\n after executing command\n"));\r
+  }\r
+  if (Ed != NULL) {\r
+    DEBUG ((EFI_D_INFO, "\nED Address:%p, ED buffer:\n", Ed));\r
+    DEBUG ((EFI_D_INFO, "DWord0  :TD Tail :TD Head :Next ED\n"));\r
+    for (Index = 0; Index < sizeof (ED_DESCRIPTOR)/4; Index ++) {\r
+      DEBUG ((EFI_D_INFO, "%8x ", *((UINT32*)(Ed) + Index)  ));\r
+    }\r
+    DEBUG ((EFI_D_INFO, "\nNext TD buffer:%p\n", Td));\r
+  }\r
+  while (Td != NULL) {\r
+    if (Td->Word0.DirPID == TD_SETUP_PID) {\r
+      DEBUG ((EFI_D_INFO, "\nSetup PID "));\r
+    }else if (Td->Word0.DirPID == TD_OUT_PID) {\r
+      DEBUG ((EFI_D_INFO, "\nOut PID "));\r
+    }else if (Td->Word0.DirPID == TD_IN_PID) {\r
+      DEBUG ((EFI_D_INFO, "\nIn PID "));\r
+    }else if (Td->Word0.DirPID == TD_NODATA_PID) {\r
+      DEBUG ((EFI_D_INFO, "\nNo data PID "));\r
+    }\r
+    DEBUG ((EFI_D_INFO, "TD Address:%p, TD buffer:\n", Td));\r
+    DEBUG ((EFI_D_INFO, "DWord0  :CuBuffer:Next TD :Buff End:Next TD :DataBuff:ActLength\n"));\r
+    for (Index = 0; Index < sizeof (TD_DESCRIPTOR)/4; Index ++) {\r
+      DEBUG ((EFI_D_INFO, "%8x ", *((UINT32*)(Td) + Index)  ));\r
+    }\r
+    DEBUG ((EFI_D_INFO, "\nCurrent TD Data buffer(size%d)\n", (UINT32)Td->ActualSendLength));\r
+    for (Index = 0; Index < Td->ActualSendLength; Index ++) {\r
+      DEBUG ((EFI_D_INFO, "%2x ", *(UINT8 *)(UINTN)(Td->DataBuffer + Index) ));\r
+    }\r
+  Td = (TD_DESCRIPTOR *)(UINTN)(Td->NextTDPointer);\r
+  }\r
+  DEBUG ((EFI_D_INFO, "\n TD buffer End\n"));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDebug.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDebug.h
new file mode 100644 (file)
index 0000000..9217157
--- /dev/null
@@ -0,0 +1,48 @@
+/** @file\r
+This file contains the definination for host controller\r
+debug support routines.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Print the data of ED and the TDs attached to the ED\r
+\r
+  @param  Uhc                   Pointer to OHCI private data\r
+  @param  Ed                    Pointer to a ED to free\r
+  @param  Td                    Pointer to the Td head\r
+\r
+  @retval EFI_SUCCESS           ED\r
+\r
+**/\r
+EFI_STATUS\r
+OhciDumpEdTdInfo (\r
+  IN USB_OHCI_HC_DEV          *Uhc,\r
+  IN ED_DESCRIPTOR     *Ed,\r
+  IN TD_DESCRIPTOR     *Td,\r
+  BOOLEAN Stage\r
+  );\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDxe.inf b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciDxe.inf
new file mode 100644 (file)
index 0000000..1d3f950
--- /dev/null
@@ -0,0 +1,77 @@
+## @file\r
+# OHCI USB Host Controller UEFI Driver\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = OhciDxe\r
+  FILE_GUID                      = 4ACA697E-F883-446f-98F7-096416FFFFFF\r
+  MODULE_TYPE                    = UEFI_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = OHCIDriverEntryPoint\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+#  DRIVER_BINDING                =  gOhciDriverBinding\r
+#  COMPONENT_NAME                =  gOhciComponentName\r
+#  COMPONENT_NAME2               =  gOhciComponentName2\r
+#\r
+[Sources]\r
+  Descriptor.h\r
+  Ohci.c\r
+  Ohci.h\r
+  OhciSched.c\r
+  OhciSched.h\r
+  OhciReg.c\r
+  OhciReg.h\r
+  OhciUrb.c\r
+  OhciUrb.h\r
+  OhciDebug.c\r
+  OhciDebug.h\r
+  ComponentName.c\r
+  ComponentName.h\r
+  UsbHcMem.c\r
+  UsbHcMem.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  MemoryAllocationLib\r
+  BaseLib\r
+  UefiLib\r
+  UefiBootServicesTableLib\r
+  UefiDriverEntryPoint\r
+  BaseMemoryLib\r
+  DebugLib\r
+\r
+[Guids]\r
+  gEfiEventExitBootServicesGuid                 ## SOMETIMES_CONSUMES   ## Event\r
+\r
+[Protocols]\r
+  gEfiPciIoProtocolGuid                         ## TO_START\r
+  gEfiUsbHcProtocolGuid                         ## BY_START\r
+\r
+#\r
+# [Event]\r
+#   ##\r
+#   # Periodic timer event for checking the result of interrupt transfer execution.\r
+#   #\r
+#   EVENT_TYPE_PERIODIC_TIMER                   ## CONSUMES\r
+#\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciReg.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciReg.c
new file mode 100644 (file)
index 0000000..09f591d
--- /dev/null
@@ -0,0 +1,1399 @@
+/** @file\r
+The OHCI register operation routines.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include "Ohci.h"\r
+\r
+/**\r
+\r
+  Get OHCI operational reg value\r
+\r
+  @param  PciIo                 PciIo protocol instance\r
+  @param  Offset                Offset of the operational reg\r
+\r
+  @retval                       Value of the register\r
+\r
+**/\r
+UINT32\r
+OhciGetOperationalReg (\r
+  IN EFI_PCI_IO_PROTOCOL  *PciIo,\r
+  IN UINT32               Offset\r
+  )\r
+{\r
+  UINT32                  Value;\r
+  EFI_STATUS              Status;\r
+\r
+  Status = PciIo->Mem.Read(PciIo, EfiPciIoWidthUint32, OHC_BAR_INDEX, Offset, 1, &Value);\r
+\r
+  return Value;\r
+}\r
+/**\r
+\r
+  Set OHCI operational reg value\r
+\r
+  @param  PciIo                  PCI Bus Io protocol instance\r
+  @param  Offset                 Offset of the operational reg\r
+  @param  Value                  Value to set\r
+\r
+  @retval EFI_SUCCESS            Value set to the reg\r
+\r
+**/\r
+\r
+\r
+EFI_STATUS\r
+OhciSetOperationalReg (\r
+  IN EFI_PCI_IO_PROTOCOL  *PciIo,\r
+  IN UINT32               Offset,\r
+  IN VOID                 *Value\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  Status = PciIo->Mem.Write(PciIo, EfiPciIoWidthUint32, OHC_BAR_INDEX, Offset, 1, Value);\r
+\r
+  return Status;\r
+}\r
+/**\r
+\r
+  Get HcRevision reg value\r
+\r
+  @param  PciIo                 PCI Bus Io protocol instance\r
+\r
+  @retval                       Value of the register\r
+\r
+**/\r
+\r
+\r
+UINT32\r
+OhciGetHcRevision (\r
+  IN EFI_PCI_IO_PROTOCOL  *PciIo\r
+  )\r
+{\r
+  return OhciGetOperationalReg (PciIo, HC_REVISION);\r
+}\r
+/**\r
+\r
+  Set HcReset reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval EFI_SUCCESS           Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetHcReset (\r
+  IN USB_OHCI_HC_DEV            *Ohc,\r
+  IN UINT32                     Field,\r
+  IN UINT32                     Value\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  HcRESET                       Reset;\r
+\r
+  Status = EFI_SUCCESS;\r
+  *(UINT32 *) &Reset = OhciGetOperationalReg (Ohc->PciIo, USBHOST_OFFSET_UHCHR);\r
+\r
+  if (Field & RESET_SYSTEM_BUS) {\r
+    Reset.FSBIR = Value;\r
+  }\r
+\r
+  if (Field & RESET_HOST_CONTROLLER) {\r
+    Reset.FHR = Value;\r
+  }\r
+\r
+  if (Field & RESET_CLOCK_GENERATION) {\r
+    Reset.CGR = Value;\r
+  }\r
+\r
+  if (Field & RESET_SSE_GLOBAL) {\r
+    Reset.SSE = Value;\r
+  }\r
+\r
+  if (Field & RESET_PSPL) {\r
+    Reset.PSPL = Value;\r
+  }\r
+\r
+  if (Field & RESET_PCPL) {\r
+    Reset.PCPL = Value;\r
+  }\r
+\r
+  if (Field & RESET_SSEP1) {\r
+    Reset.SSEP1 = Value;\r
+  }\r
+\r
+  if (Field & RESET_SSEP2) {\r
+    Reset.SSEP2 = Value;\r
+  }\r
+\r
+  if (Field & RESET_SSEP3) {\r
+    Reset.SSEP3 = Value;\r
+  }\r
+\r
+  OhciSetOperationalReg (Ohc->PciIo, USBHOST_OFFSET_UHCHR, &Reset);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Get specific field of HcReset reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetHcReset (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Field\r
+  )\r
+{\r
+  HcRESET                 Reset;\r
+  UINT32                  Value;\r
+\r
+\r
+  *(UINT32 *) &Reset = OhciGetOperationalReg (Ohc->PciIo, USBHOST_OFFSET_UHCHR);\r
+  Value = 0;\r
+\r
+  switch (Field) {\r
+  case RESET_SYSTEM_BUS:\r
+    Value = Reset.FSBIR;\r
+    break;\r
+\r
+  case RESET_HOST_CONTROLLER:\r
+    Value = Reset.FHR;\r
+    break;\r
+\r
+  case RESET_CLOCK_GENERATION:\r
+    Value = Reset.CGR;\r
+    break;\r
+\r
+  case RESET_SSE_GLOBAL:\r
+    Value = Reset.SSE;\r
+    break;\r
+\r
+  case RESET_PSPL:\r
+    Value = Reset.PSPL;\r
+    break;\r
+\r
+  case RESET_PCPL:\r
+    Value = Reset.PCPL;\r
+    break;\r
+\r
+  case RESET_SSEP1:\r
+    Value = Reset.SSEP1;\r
+    break;\r
+\r
+  case RESET_SSEP2:\r
+    Value = Reset.SSEP2;\r
+    break;\r
+\r
+  case RESET_SSEP3:\r
+    Value = Reset.SSEP3;\r
+    break;\r
+\r
+  default:\r
+    ASSERT (FALSE);\r
+  }\r
+\r
+\r
+  return Value;\r
+}\r
+\r
+/**\r
+\r
+  Set HcControl reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetHcControl (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  HcCONTROL               Control;\r
+\r
+\r
+\r
+  *(UINT32 *) &Control = OhciGetOperationalReg (Ohc->PciIo, HC_CONTROL);\r
+\r
+  if (Field & CONTROL_BULK_RATIO) {\r
+    Control.ControlBulkRatio = Value;\r
+  }\r
+\r
+  if (Field & HC_FUNCTIONAL_STATE) {\r
+    Control.FunctionalState = Value;\r
+  }\r
+\r
+  if (Field & PERIODIC_ENABLE) {\r
+    Control.PeriodicEnable = Value;\r
+  }\r
+\r
+  if (Field & CONTROL_ENABLE) {\r
+    Control.ControlEnable = Value;\r
+  }\r
+\r
+  if (Field & ISOCHRONOUS_ENABLE) {\r
+    Control.IsochronousEnable = Value;\r
+  }\r
+\r
+  if (Field & BULK_ENABLE) {\r
+    Control.BulkEnable = Value;\r
+  }\r
+\r
+  if (Field & INTERRUPT_ROUTING) {\r
+    Control.InterruptRouting = Value;\r
+  }\r
+\r
+  Status = OhciSetOperationalReg (Ohc->PciIo, HC_CONTROL, &Control);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Get specific field of HcControl reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+\r
+UINT32\r
+OhciGetHcControl (\r
+  IN USB_OHCI_HC_DEV   *Ohc,\r
+  IN UINTN             Field\r
+  )\r
+{\r
+  HcCONTROL     Control;\r
+\r
+  *(UINT32 *) &Control = OhciGetOperationalReg (Ohc->PciIo, HC_CONTROL);\r
+\r
+  switch (Field) {\r
+  case CONTROL_BULK_RATIO:\r
+    return Control.ControlBulkRatio;\r
+    break;\r
+  case PERIODIC_ENABLE:\r
+    return Control.PeriodicEnable;\r
+    break;\r
+  case CONTROL_ENABLE:\r
+    return Control.ControlEnable;\r
+    break;\r
+  case BULK_ENABLE:\r
+    return Control.BulkEnable;\r
+    break;\r
+  case ISOCHRONOUS_ENABLE:\r
+    return Control.IsochronousEnable;\r
+    break;\r
+  case HC_FUNCTIONAL_STATE:\r
+    return Control.FunctionalState;\r
+    break;\r
+  case INTERRUPT_ROUTING:\r
+    return Control.InterruptRouting;\r
+    break;\r
+  default:\r
+    ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+\r
+  Set HcCommand reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval EFI_SUCCESS           Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetHcCommandStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  HcCOMMAND_STATUS        CommandStatus;\r
+\r
+  ZeroMem (&CommandStatus, sizeof (HcCOMMAND_STATUS));\r
+\r
+  if(Field & HC_RESET){\r
+    CommandStatus.HcReset = Value;\r
+  }\r
+\r
+  if(Field & CONTROL_LIST_FILLED){\r
+    CommandStatus.ControlListFilled = Value;\r
+  }\r
+\r
+  if(Field & BULK_LIST_FILLED){\r
+    CommandStatus.BulkListFilled = Value;\r
+  }\r
+\r
+  if(Field & CHANGE_OWNER_REQUEST){\r
+    CommandStatus.ChangeOwnerRequest = Value;\r
+  }\r
+\r
+  if(Field & SCHEDULE_OVERRUN_COUNT){\r
+    CommandStatus.ScheduleOverrunCount = Value;\r
+  }\r
+\r
+  Status = OhciSetOperationalReg (Ohc->PciIo, HC_COMMAND_STATUS, &CommandStatus);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Get specific field of HcCommand reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetHcCommandStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  )\r
+{\r
+  HcCOMMAND_STATUS        CommandStatus;\r
+\r
+  *(UINT32 *) &CommandStatus = OhciGetOperationalReg (Ohc->PciIo, HC_COMMAND_STATUS);\r
+\r
+  switch (Field){\r
+  case HC_RESET:\r
+    return CommandStatus.HcReset;\r
+    break;\r
+  case CONTROL_LIST_FILLED:\r
+    return CommandStatus.ControlListFilled;\r
+    break;\r
+  case BULK_LIST_FILLED:\r
+    return CommandStatus.BulkListFilled;\r
+    break;\r
+  case CHANGE_OWNER_REQUEST:\r
+    return CommandStatus.ChangeOwnerRequest;\r
+    break;\r
+  case SCHEDULE_OVERRUN_COUNT:\r
+    return CommandStatus.ScheduleOverrunCount;\r
+    break;\r
+  default:\r
+    ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+\r
+  Clear specific fields of Interrupt Status\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to clear\r
+\r
+  @retval EFI_SUCCESS           Fields cleared\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciClearInterruptStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  HcINTERRUPT_STATUS      InterruptStatus;\r
+\r
+  ZeroMem (&InterruptStatus, sizeof (HcINTERRUPT_STATUS));\r
+\r
+  if(Field & SCHEDULE_OVERRUN){\r
+    InterruptStatus.SchedulingOverrun = 1;\r
+  }\r
+\r
+  if(Field & WRITEBACK_DONE_HEAD){\r
+    InterruptStatus.WriteBackDone = 1;\r
+  }\r
+  if(Field & START_OF_FRAME){\r
+    InterruptStatus.Sof = 1;\r
+  }\r
+\r
+  if(Field & RESUME_DETECT){\r
+    InterruptStatus.ResumeDetected = 1;\r
+  }\r
+\r
+  if(Field & UNRECOVERABLE_ERROR){\r
+    InterruptStatus.UnrecoverableError = 1;\r
+  }\r
+\r
+  if(Field & FRAME_NUMBER_OVERFLOW){\r
+    InterruptStatus.FrameNumOverflow = 1;\r
+  }\r
+\r
+  if(Field & ROOTHUB_STATUS_CHANGE){\r
+    InterruptStatus.RHStatusChange = 1;\r
+  }\r
+\r
+  if(Field & OWNERSHIP_CHANGE){\r
+    InterruptStatus.OwnerChange = 1;\r
+  }\r
+\r
+  Status = OhciSetOperationalReg (Ohc->PciIo, HC_INTERRUPT_STATUS, &InterruptStatus);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Get fields of HcInterrupt reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetHcInterruptStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  )\r
+{\r
+  HcINTERRUPT_STATUS      InterruptStatus;\r
+\r
+  *(UINT32 *) &InterruptStatus = OhciGetOperationalReg (Ohc->PciIo, HC_INTERRUPT_STATUS);\r
+\r
+  switch (Field){\r
+  case SCHEDULE_OVERRUN:\r
+    return InterruptStatus.SchedulingOverrun;\r
+    break;\r
+\r
+  case  WRITEBACK_DONE_HEAD:\r
+    return InterruptStatus.WriteBackDone;\r
+    break;\r
+\r
+  case START_OF_FRAME:\r
+    return InterruptStatus.Sof;\r
+    break;\r
+\r
+  case RESUME_DETECT:\r
+    return InterruptStatus.ResumeDetected;\r
+    break;\r
+\r
+  case UNRECOVERABLE_ERROR:\r
+    return InterruptStatus.UnrecoverableError;\r
+    break;\r
+\r
+  case FRAME_NUMBER_OVERFLOW:\r
+    return InterruptStatus.FrameNumOverflow;\r
+    break;\r
+\r
+  case ROOTHUB_STATUS_CHANGE:\r
+    return InterruptStatus.RHStatusChange;\r
+    break;\r
+\r
+  case OWNERSHIP_CHANGE:\r
+    return InterruptStatus.OwnerChange;\r
+    break;\r
+\r
+  default:\r
+    ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+\r
+  Set Interrupt Control reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  StatEnable            Enable or Disable\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval EFI_SUCCESS           Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetInterruptControl (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN BOOLEAN              StatEnable,\r
+  IN UINTN                Field,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  HcINTERRUPT_CONTROL     InterruptState;\r
+\r
+\r
+  ZeroMem (&InterruptState, sizeof (HcINTERRUPT_CONTROL));\r
+\r
+  if(Field & SCHEDULE_OVERRUN) {\r
+    InterruptState.SchedulingOverrunInt = Value;\r
+  }\r
+\r
+  if(Field & WRITEBACK_DONE_HEAD) {\r
+    InterruptState.WriteBackDoneInt = Value;\r
+  }\r
+  if(Field & START_OF_FRAME) {\r
+    InterruptState.SofInt = Value;\r
+  }\r
+\r
+  if(Field & RESUME_DETECT) {\r
+    InterruptState.ResumeDetectedInt = Value;\r
+  }\r
+\r
+  if(Field & UNRECOVERABLE_ERROR) {\r
+    InterruptState.UnrecoverableErrorInt = Value;\r
+  }\r
+\r
+  if(Field & FRAME_NUMBER_OVERFLOW) {\r
+    InterruptState.FrameNumOverflowInt = Value;\r
+  }\r
+\r
+  if(Field & ROOTHUB_STATUS_CHANGE) {\r
+    InterruptState.RHStatusChangeInt = Value;\r
+  }\r
+\r
+  if(Field & OWNERSHIP_CHANGE) {\r
+    InterruptState.OwnerChangedInt = Value;\r
+  }\r
+\r
+  if(Field & MASTER_INTERRUPT) {\r
+    InterruptState.MasterInterruptEnable = Value;\r
+  }\r
+\r
+  if (StatEnable) {\r
+    Status = OhciSetOperationalReg (Ohc->PciIo, HC_INTERRUPT_ENABLE, &InterruptState);\r
+  } else {\r
+    Status = OhciSetOperationalReg (Ohc->PciIo, HC_INTERRUPT_DISABLE, &InterruptState);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Get field of HcInterruptControl reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetHcInterruptControl (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  )\r
+{\r
+  HcINTERRUPT_CONTROL     InterruptState;\r
+\r
+  *(UINT32 *) &InterruptState = OhciGetOperationalReg (Ohc->PciIo, HC_INTERRUPT_ENABLE);\r
+\r
+  switch (Field){\r
+    case SCHEDULE_OVERRUN:\r
+      return InterruptState.SchedulingOverrunInt;\r
+      break;\r
+\r
+    case WRITEBACK_DONE_HEAD:\r
+      return InterruptState.WriteBackDoneInt;\r
+      break;\r
+\r
+    case START_OF_FRAME:\r
+      return InterruptState.SofInt;\r
+      break;\r
+\r
+    case RESUME_DETECT:\r
+      return InterruptState.ResumeDetectedInt;\r
+      break;\r
+\r
+    case UNRECOVERABLE_ERROR:\r
+      return InterruptState.UnrecoverableErrorInt;\r
+      break;\r
+\r
+    case FRAME_NUMBER_OVERFLOW:\r
+      return InterruptState.FrameNumOverflowInt;\r
+      break;\r
+\r
+    case ROOTHUB_STATUS_CHANGE:\r
+      return InterruptState.RHStatusChangeInt;\r
+      break;\r
+\r
+    case OWNERSHIP_CHANGE:\r
+      return InterruptState.OwnerChangedInt;\r
+      break;\r
+\r
+    case MASTER_INTERRUPT:\r
+      return InterruptState.MasterInterruptEnable;\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+\r
+  Set memory pointer of specific type\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  PointerType           Type of the pointer to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval EFI_SUCCESS           Memory pointer set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetMemoryPointer(\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               PointerType,\r
+  IN VOID                 *Value\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  UINT32                  Verify;\r
+\r
+  Status = OhciSetOperationalReg (Ohc->PciIo, PointerType, &Value);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Verify = OhciGetOperationalReg (Ohc->PciIo, PointerType);\r
+\r
+  while (Verify != (UINT32)(UINTN) Value) {\r
+    gBS->Stall(1000);\r
+    Verify = OhciGetOperationalReg (Ohc->PciIo, PointerType);\r
+  };\r
+\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Get memory pointer of specific type\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  PointerType           Type of pointer\r
+\r
+  @retval                       Memory pointer of the specific type\r
+\r
+**/\r
+\r
+VOID *\r
+OhciGetMemoryPointer (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               PointerType\r
+  )\r
+{\r
+\r
+  return (VOID *)(UINTN) OhciGetOperationalReg (Ohc->PciIo, PointerType);\r
+}\r
+\r
+\r
+/**\r
+\r
+  Set Frame Interval value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetFrameInterval (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  HcFRM_INTERVAL          FrameInterval;\r
+\r
+\r
+  *(UINT32 *) &FrameInterval = OhciGetOperationalReg(Ohc->PciIo, HC_FRM_INTERVAL);\r
+\r
+  if (Field & FRAME_INTERVAL) {\r
+    FrameInterval.FrmIntervalToggle = !FrameInterval.FrmIntervalToggle;\r
+    FrameInterval.FrameInterval = Value;\r
+  }\r
+\r
+  if (Field & FS_LARGEST_DATA_PACKET) {\r
+    FrameInterval.FSMaxDataPacket = Value;\r
+  }\r
+\r
+  if (Field & FRMINT_TOGGLE) {\r
+    FrameInterval.FrmIntervalToggle = Value;\r
+  }\r
+\r
+  Status = OhciSetOperationalReg (\r
+             Ohc->PciIo,\r
+             HC_FRM_INTERVAL,\r
+             &FrameInterval\r
+             );\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Get field of frame interval reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetFrameInterval (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  )\r
+{\r
+  HcFRM_INTERVAL          FrameInterval;\r
+\r
+  *(UINT32 *) &FrameInterval = OhciGetOperationalReg (Ohc->PciIo, HC_FRM_INTERVAL);\r
+\r
+  switch (Field){\r
+    case FRAME_INTERVAL:\r
+      return FrameInterval.FrameInterval;\r
+      break;\r
+\r
+    case FS_LARGEST_DATA_PACKET:\r
+      return FrameInterval.FSMaxDataPacket;\r
+      break;\r
+\r
+    case FRMINT_TOGGLE:\r
+      return FrameInterval.FrmIntervalToggle;\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+\r
+  Set Frame Remaining reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetFrameRemaining (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  HcFRAME_REMAINING       FrameRemaining;\r
+\r
+\r
+  *(UINT32 *) &FrameRemaining = OhciGetOperationalReg (Ohc->PciIo, HC_FRM_REMAINING);\r
+\r
+  FrameRemaining.FrameRemaining = Value;\r
+  FrameRemaining.FrameRemainingToggle = !FrameRemaining.FrameRemainingToggle;\r
+\r
+  Status = OhciSetOperationalReg (Ohc->PciIo, HC_FRM_REMAINING, &FrameRemaining);\r
+\r
+  return Status;\r
+}\r
+/**\r
+\r
+  Get value of frame remaining reg\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of frame remaining reg\r
+\r
+**/\r
+UINT32\r
+OhciGetFrameRemaining (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  )\r
+\r
+{\r
+  HcFRAME_REMAINING       FrameRemaining;\r
+\r
+\r
+  *(UINT32 *) &FrameRemaining = OhciGetOperationalReg (Ohc->PciIo, HC_FRM_REMAINING);\r
+\r
+  switch (Field){\r
+    case FRAME_REMAINING:\r
+      return FrameRemaining.FrameRemaining;\r
+      break;\r
+\r
+    case FRAME_REMAIN_TOGGLE:\r
+      return FrameRemaining.FrameRemainingToggle;\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+\r
+  Set frame number reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetFrameNumber(\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+\r
+  Status = OhciSetOperationalReg (Ohc->PciIo, HC_FRM_NUMBER, &Value);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Get frame number reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+\r
+  @retval                       Value of frame number reg\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetFrameNumber (\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  )\r
+{\r
+  return OhciGetOperationalReg(Ohc->PciIo, HC_FRM_NUMBER);\r
+}\r
+\r
+/**\r
+\r
+  Set period start reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Value                 Value to set\r
+\r
+  @retval EFI_SUCCESS           Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetPeriodicStart (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+\r
+\r
+  Status = OhciSetOperationalReg (Ohc->PciIo, HC_PERIODIC_START, &Value);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Get periodic start reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+\r
+  @param                        Value of periodic start reg\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetPeriodicStart (\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  )\r
+{\r
+  return OhciGetOperationalReg(Ohc->PciIo, HC_PERIODIC_START);\r
+}\r
+\r
+\r
+/**\r
+\r
+  Set Ls Threshold reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetLsThreshold (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+\r
+\r
+  Status = OhciSetOperationalReg (Ohc->PciIo, HC_LS_THREASHOLD, &Value);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Get Ls Threshold reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+\r
+  @retval                       Value of Ls Threshold reg\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetLsThreshold (\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  )\r
+{\r
+  return OhciGetOperationalReg(Ohc->PciIo, HC_LS_THREASHOLD);\r
+}\r
+\r
+/**\r
+\r
+  Set Root Hub Descriptor reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+EFI_STATUS\r
+OhciSetRootHubDescriptor (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  HcRH_DESC_A             DescriptorA;\r
+  HcRH_DESC_B             DescriptorB;\r
+\r
+\r
+  if (Field & (RH_DEV_REMOVABLE | RH_PORT_PWR_CTRL_MASK)) {\r
+    *(UINT32 *) &DescriptorB = OhciGetOperationalReg (Ohc->PciIo, HC_RH_DESC_B);\r
+\r
+    if(Field & RH_DEV_REMOVABLE) {\r
+      DescriptorB.DeviceRemovable = Value;\r
+    }\r
+    if(Field & RH_PORT_PWR_CTRL_MASK) {\r
+      DescriptorB.PortPowerControlMask = Value;\r
+    }\r
+\r
+    Status = OhciSetOperationalReg (Ohc->PciIo, HC_RH_DESC_B, &DescriptorB);\r
+\r
+    return Status;\r
+  }\r
+\r
+  *(UINT32 *)&DescriptorA = OhciGetOperationalReg (Ohc->PciIo, HC_RH_DESC_A);\r
+\r
+  if(Field & RH_NUM_DS_PORTS) {\r
+    DescriptorA.NumDownStrmPorts = Value;\r
+  }\r
+  if(Field & RH_NO_PSWITCH) {\r
+    DescriptorA.NoPowerSwitch = Value;\r
+  }\r
+  if(Field & RH_PSWITCH_MODE) {\r
+    DescriptorA.PowerSwitchMode = Value;\r
+  }\r
+  if(Field & RH_DEVICE_TYPE) {\r
+    DescriptorA.DeviceType = Value;\r
+  }\r
+  if(Field & RH_OC_PROT_MODE) {\r
+    DescriptorA.OverCurrentProtMode = Value;\r
+  }\r
+  if(Field & RH_NOC_PROT) {\r
+    DescriptorA.NoOverCurrentProtMode = Value;\r
+  }\r
+  if(Field & RH_NO_POTPGT) {\r
+    DescriptorA.PowerOnToPowerGoodTime = Value;\r
+  }\r
+\r
+  Status = OhciSetOperationalReg (Ohc->PciIo, HC_RH_DESC_A, &DescriptorA);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Get Root Hub Descriptor reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetRootHubDescriptor (\r
+  IN USB_OHCI_HC_DEV     *Ohc,\r
+  IN UINTN               Field\r
+  )\r
+{\r
+  HcRH_DESC_A             DescriptorA;\r
+  HcRH_DESC_B             DescriptorB;\r
+\r
+\r
+  *(UINT32 *) &DescriptorA = OhciGetOperationalReg (Ohc->PciIo, HC_RH_DESC_A);\r
+  *(UINT32 *) &DescriptorB = OhciGetOperationalReg (Ohc->PciIo, HC_RH_DESC_B);\r
+\r
+  switch (Field){\r
+    case RH_DEV_REMOVABLE:\r
+      return DescriptorB.DeviceRemovable;\r
+      break;\r
+\r
+    case RH_PORT_PWR_CTRL_MASK:\r
+      return DescriptorB.PortPowerControlMask;\r
+      break;\r
+\r
+    case RH_NUM_DS_PORTS:\r
+      return DescriptorA.NumDownStrmPorts;\r
+      break;\r
+\r
+    case RH_NO_PSWITCH:\r
+      return DescriptorA.NoPowerSwitch;\r
+      break;\r
+\r
+    case RH_PSWITCH_MODE:\r
+      return DescriptorA.PowerSwitchMode;\r
+      break;\r
+\r
+    case RH_DEVICE_TYPE:\r
+      return DescriptorA.DeviceType;\r
+      break;\r
+\r
+    case RH_OC_PROT_MODE:\r
+      return DescriptorA.OverCurrentProtMode;\r
+      break;\r
+\r
+    case RH_NOC_PROT:\r
+      return DescriptorA.NoOverCurrentProtMode;\r
+      break;\r
+\r
+    case RH_NO_POTPGT:\r
+      return DescriptorA.PowerOnToPowerGoodTime;\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Set Root Hub Status reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetRootHubStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  HcRH_STATUS             RootHubStatus;\r
+\r
+\r
+  ZeroMem (&RootHubStatus, sizeof(HcRH_STATUS));\r
+\r
+  if(Field & RH_LOCAL_PSTAT){\r
+    RootHubStatus.LocalPowerStat = 1;\r
+  }\r
+  if(Field & RH_OC_ID){\r
+    RootHubStatus.OverCurrentIndicator = 1;\r
+  }\r
+  if(Field & RH_REMOTE_WK_ENABLE){\r
+    RootHubStatus.DevRemoteWakeupEnable = 1;\r
+  }\r
+  if(Field & RH_LOCAL_PSTAT_CHANGE){\r
+    RootHubStatus.LocalPowerStatChange = 1;\r
+  }\r
+  if(Field & RH_OC_ID_CHANGE){\r
+    RootHubStatus.OverCurrentIndicatorChange = 1;\r
+  }\r
+  if(Field & RH_CLR_RMT_WK_ENABLE){\r
+    RootHubStatus.ClearRemoteWakeupEnable = 1;\r
+  }\r
+\r
+  Status = OhciSetOperationalReg (Ohc->PciIo, HC_RH_STATUS, &RootHubStatus);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Get Root Hub Status reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetRootHubStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  )\r
+{\r
+  HcRH_STATUS             RootHubStatus;\r
+\r
+\r
+  *(UINT32 *) &RootHubStatus = OhciGetOperationalReg (Ohc->PciIo, HC_RH_STATUS);\r
+\r
+  switch (Field) {\r
+    case RH_LOCAL_PSTAT:\r
+      return RootHubStatus.LocalPowerStat;\r
+      break;\r
+    case RH_OC_ID:\r
+      return RootHubStatus.OverCurrentIndicator;\r
+      break;\r
+    case RH_REMOTE_WK_ENABLE:\r
+      return RootHubStatus.DevRemoteWakeupEnable;\r
+      break;\r
+    case RH_LOCAL_PSTAT_CHANGE:\r
+      return RootHubStatus.LocalPowerStatChange;\r
+      break;\r
+    case RH_OC_ID_CHANGE:\r
+      return RootHubStatus.OverCurrentIndicatorChange;\r
+      break;\r
+    case RH_CLR_RMT_WK_ENABLE:\r
+      return RootHubStatus.ClearRemoteWakeupEnable;\r
+      break;\r
+    default:\r
+      ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Set Root Hub Port Status reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Index                 Index of the port\r
+  @param  Field                 Field to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetRootHubPortStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Index,\r
+  IN UINTN                Field\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  HcRHPORT_STATUS         PortStatus;\r
+\r
+\r
+  ZeroMem (&PortStatus, sizeof(HcRHPORT_STATUS));\r
+\r
+  if (Field & RH_CLEAR_PORT_ENABLE) {\r
+    PortStatus.CurrentConnectStat = 1;\r
+  }\r
+  if (Field & RH_SET_PORT_ENABLE) {\r
+    PortStatus.EnableStat = 1;\r
+  }\r
+  if (Field & RH_SET_PORT_SUSPEND) {\r
+    PortStatus.SuspendStat = 1;\r
+  }\r
+  if (Field & RH_CLEAR_SUSPEND_STATUS) {\r
+    PortStatus.OCIndicator = 1;\r
+  }\r
+  if (Field & RH_SET_PORT_RESET) {\r
+    PortStatus.ResetStat = 1;\r
+  }\r
+  if (Field & RH_SET_PORT_POWER) {\r
+    PortStatus.PowerStat = 1;\r
+  }\r
+  if (Field & RH_CLEAR_PORT_POWER) {\r
+    PortStatus.LsDeviceAttached = 1;\r
+  }\r
+  if (Field & RH_CONNECT_STATUS_CHANGE) {\r
+    PortStatus.ConnectStatChange = 1;\r
+  }\r
+  if (Field & RH_PORT_ENABLE_STAT_CHANGE) {\r
+    PortStatus.EnableStatChange = 1;\r
+  }\r
+  if (Field & RH_PORT_SUSPEND_STAT_CHANGE) {\r
+    PortStatus.SuspendStatChange = 1;\r
+  }\r
+  if (Field & RH_OC_INDICATOR_CHANGE) {\r
+    PortStatus.OCIndicatorChange = 1;\r
+  }\r
+  if (Field & RH_PORT_RESET_STAT_CHANGE ) {\r
+    PortStatus.ResetStatChange = 1;\r
+  }\r
+\r
+  Status = OhciSetOperationalReg (Ohc->PciIo, HC_RH_PORT_STATUS + (Index * 4), &PortStatus);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Get Root Hub Port Status reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Index                 Index of the port\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field and index\r
+\r
+**/\r
+\r
+UINT32\r
+OhciReadRootHubPortStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Index,\r
+  IN UINTN                Field\r
+  )\r
+{\r
+  HcRHPORT_STATUS         PortStatus;\r
+\r
+  *(UINT32 *) &PortStatus = OhciGetOperationalReg (\r
+                              Ohc->PciIo,\r
+                              HC_RH_PORT_STATUS + (Index * 4)\r
+                              );\r
+\r
+  switch (Field){\r
+  case RH_CURR_CONNECT_STAT:\r
+    return PortStatus.CurrentConnectStat;\r
+    break;\r
+  case RH_PORT_ENABLE_STAT:\r
+    return PortStatus.EnableStat;\r
+    break;\r
+  case RH_PORT_SUSPEND_STAT:\r
+    return PortStatus.SuspendStat;\r
+    break;\r
+  case RH_PORT_OC_INDICATOR:\r
+    return PortStatus.OCIndicator;\r
+    break;\r
+  case RH_PORT_RESET_STAT:\r
+    return PortStatus.ResetStat;\r
+    break;\r
+  case RH_PORT_POWER_STAT:\r
+    return PortStatus.PowerStat;\r
+    break;\r
+  case RH_LSDEVICE_ATTACHED:\r
+    return PortStatus.LsDeviceAttached;\r
+    break;\r
+  case RH_CONNECT_STATUS_CHANGE:\r
+    return PortStatus.ConnectStatChange;\r
+    break;\r
+  case RH_PORT_ENABLE_STAT_CHANGE:\r
+    return PortStatus.EnableStatChange;\r
+    break;\r
+  case RH_PORT_SUSPEND_STAT_CHANGE:\r
+    return PortStatus.SuspendStatChange;\r
+    break;\r
+  case RH_OC_INDICATOR_CHANGE:\r
+    return PortStatus.OCIndicatorChange;\r
+    break;\r
+  case RH_PORT_RESET_STAT_CHANGE:\r
+    return PortStatus.ResetStatChange;\r
+    break;\r
+  default:\r
+    ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciReg.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciReg.h
new file mode 100644 (file)
index 0000000..4896bad
--- /dev/null
@@ -0,0 +1,926 @@
+/** @file\r
+This file contains the definination for host controller\r
+register operation routines.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+\r
+#ifndef   _OHCI_REG_H\r
+#define   _OHCI_REG_H\r
+\r
+#define   HC_STATE_RESET         0x0\r
+#define   HC_STATE_RESUME        0x1\r
+#define   HC_STATE_OPERATIONAL   0x2\r
+#define   HC_STATE_SUSPEND       0x3\r
+\r
+#define   PERIODIC_ENABLE               0x01\r
+#define   ISOCHRONOUS_ENABLE            0x02\r
+#define   CONTROL_ENABLE                0x04\r
+#define   BULK_ENABLE                   0x08\r
+#define   CONTROL_BULK_RATIO            0x10\r
+\r
+#define   HC_FUNCTIONAL_STATE    0x20\r
+#define   INTERRUPT_ROUTING      0x40\r
+\r
+#define   HC_RESET               0x01\r
+#define   CONTROL_LIST_FILLED    0x02\r
+#define   BULK_LIST_FILLED       0x04\r
+#define   CHANGE_OWNER_REQUEST   0x08\r
+\r
+#define   SCHEDULE_OVERRUN_COUNT 0x10\r
+\r
+#define   SCHEDULE_OVERRUN       0x00001\r
+#define   WRITEBACK_DONE_HEAD    0x00002\r
+#define   START_OF_FRAME         0x00004\r
+#define   RESUME_DETECT          0x00008\r
+#define   UNRECOVERABLE_ERROR    0x00010\r
+#define   FRAME_NUMBER_OVERFLOW  0x00020\r
+#define   ROOTHUB_STATUS_CHANGE  0x00040\r
+#define   OWNERSHIP_CHANGE       0x00080\r
+\r
+#define   MASTER_INTERRUPT       0x00400\r
+\r
+#define   CONTROL_HEAD           0x001\r
+#define   BULK_HEAD              0x002\r
+#define   DONE_HEAD              0x004\r
+\r
+#define   Hc_HCCA                0x001\r
+#define   Hc_PERIODIC_CURRENT    0x002\r
+#define   Hc_CONTOL_HEAD         0x004\r
+#define   Hc_CONTROL_CURRENT_PTR 0x008\r
+#define   Hc_BULK_HEAD           0x010\r
+#define   Hc_BULK_CURRENT_PTR    0x020\r
+#define   Hc_DONE_HEAD           0x040\r
+\r
+#define   FRAME_INTERVAL         0x008\r
+#define   FS_LARGEST_DATA_PACKET 0x010\r
+#define   FRMINT_TOGGLE          0x020\r
+#define   FRAME_REMAINING        0x040\r
+#define   FRAME_REMAIN_TOGGLE    0x080\r
+\r
+#define   RH_DESC_A              0x00001\r
+#define   RH_DESC_B              0x00002\r
+#define   RH_NUM_DS_PORTS        0x00004\r
+#define   RH_NO_PSWITCH          0x00008\r
+#define   RH_PSWITCH_MODE        0x00010\r
+#define   RH_DEVICE_TYPE         0x00020\r
+#define   RH_OC_PROT_MODE        0x00040\r
+#define   RH_NOC_PROT            0x00080\r
+#define   RH_POTPGT              0x00100\r
+#define   RH_NO_POTPGT           0x00200\r
+#define   RH_DEV_REMOVABLE       0x00400\r
+#define   RH_PORT_PWR_CTRL_MASK  0x00800\r
+\r
+#define   RH_LOCAL_PSTAT         0x00001\r
+#define   RH_OC_ID               0x00002\r
+#define   RH_REMOTE_WK_ENABLE    0x00004\r
+#define   RH_LOCAL_PSTAT_CHANGE  0x00008\r
+#define   RH_OC_ID_CHANGE        0x00010\r
+#define   RH_CLR_RMT_WK_ENABLE   0x00020\r
+\r
+#define   RH_CLEAR_PORT_ENABLE        0x0001\r
+#define   RH_SET_PORT_ENABLE          0x0002\r
+#define   RH_SET_PORT_SUSPEND         0x0004\r
+#define   RH_CLEAR_SUSPEND_STATUS     0x0008\r
+#define   RH_SET_PORT_RESET           0x0010\r
+#define   RH_SET_PORT_POWER           0x0020\r
+#define   RH_CLEAR_PORT_POWER         0x0040\r
+#define   RH_CONNECT_STATUS_CHANGE    0x10000\r
+#define   RH_PORT_ENABLE_STAT_CHANGE  0x20000\r
+#define   RH_PORT_SUSPEND_STAT_CHANGE 0x40000\r
+#define   RH_OC_INDICATOR_CHANGE      0x80000\r
+#define   RH_PORT_RESET_STAT_CHANGE   0x100000\r
+\r
+#define   RH_CURR_CONNECT_STAT        0x0001\r
+#define   RH_PORT_ENABLE_STAT         0x0002\r
+#define   RH_PORT_SUSPEND_STAT        0x0004\r
+#define   RH_PORT_OC_INDICATOR        0x0008\r
+#define   RH_PORT_RESET_STAT          0x0010\r
+#define   RH_PORT_POWER_STAT          0x0020\r
+#define   RH_LSDEVICE_ATTACHED        0x0040\r
+\r
+#define   RESET_SYSTEM_BUS            (1 << 0)\r
+#define   RESET_HOST_CONTROLLER       (1 << 1)\r
+#define   RESET_CLOCK_GENERATION      (1 << 2)\r
+#define   RESET_SSE_GLOBAL            (1 << 5)\r
+#define   RESET_PSPL                  (1 << 6)\r
+#define   RESET_PCPL                  (1 << 7)\r
+#define   RESET_SSEP1                 (1 << 9)\r
+#define   RESET_SSEP2                 (1 << 10)\r
+#define   RESET_SSEP3                 (1 << 11)\r
+\r
+#define ONE_SECOND                      1000000\r
+#define ONE_MILLI_SEC                   1000\r
+#define MAX_BYTES_PER_TD                0x1000\r
+#define MAX_RETRY_TIMES                 100\r
+#define PORT_NUMBER_ON_MAINSTONE2       1\r
+\r
+\r
+//\r
+// Operational Register Offsets\r
+//\r
+\r
+//\r
+// Command & Status Registers Offsets\r
+//\r
+#define HC_REVISION             0x00\r
+#define HC_CONTROL              0x04\r
+#define HC_COMMAND_STATUS       0x08\r
+#define HC_INTERRUPT_STATUS     0x0C\r
+#define HC_INTERRUPT_ENABLE     0x10\r
+#define HC_INTERRUPT_DISABLE    0x14\r
+\r
+//\r
+// Memory Pointer Offsets\r
+//\r
+#define HC_HCCA                 0x18\r
+#define HC_PERIODIC_CURRENT     0x1C\r
+#define HC_CONTROL_HEAD         0x20\r
+#define HC_CONTROL_CURRENT_PTR  0x24\r
+#define HC_BULK_HEAD            0x28\r
+#define HC_BULK_CURRENT_PTR     0x2C\r
+#define HC_DONE_HEAD            0x30\r
+\r
+//\r
+// Frame Register Offsets\r
+//\r
+#define HC_FRM_INTERVAL         0x34\r
+#define HC_FRM_REMAINING        0x38\r
+#define HC_FRM_NUMBER           0x3C\r
+#define HC_PERIODIC_START       0x40\r
+#define HC_LS_THREASHOLD        0x44\r
+\r
+//\r
+// Root Hub Register Offsets\r
+//\r
+#define HC_RH_DESC_A            0x48\r
+#define HC_RH_DESC_B            0x4C\r
+#define HC_RH_STATUS            0x50\r
+#define HC_RH_PORT_STATUS       0x54\r
+\r
+#define USBHOST_OFFSET_UHCHR         0x64         // Usb Host reset register\r
+\r
+#define OHC_BAR_INDEX               0\r
+\r
+//\r
+// Usb Host controller register offset\r
+//\r
+#define USBHOST_OFFSET_UHCREV        0x0          // Usb Host revision register\r
+#define USBHOST_OFFSET_UHCHCON       0x4          // Usb Host control register\r
+#define USBHOST_OFFSET_UHCCOMS       0x8          // Usb Host Command Status register\r
+#define USBHOST_OFFSET_UHCINTS       0xC          // Usb Host Interrupt Status register\r
+#define USBHOST_OFFSET_UHCINTE       0x10         // Usb Host Interrupt Enable register\r
+#define USBHOST_OFFSET_UHCINTD       0x14         // Usb Host Interrupt Disable register\r
+#define USBHOST_OFFSET_UHCHCCA       0x18         // Usb Host Controller Communication Area\r
+#define USBHOST_OFFSET_UHCPCED       0x1C         // Usb Host Period Current Endpoint Descriptor\r
+#define USBHOST_OFFSET_UHCCHED       0x20         // Usb Host Control Head Endpoint Descriptor\r
+#define USBHOST_OFFSET_UHCCCED       0x24         // Usb Host Control Current Endpoint Descriptor\r
+#define USBHOST_OFFSET_UHCBHED       0x28         // Usb Host Bulk Head Endpoint Descriptor\r
+#define USBHOST_OFFSET_UHCBCED       0x2C         // Usb Host Bulk Current Endpoint Descriptor\r
+#define USBHOST_OFFSET_UHCDHEAD      0x30         // Usb Host Done Head register\r
+#define USBHOST_OFFSET_UHCFMI        0x34         // Usb Host Frame Interval register\r
+#define USBHOST_OFFSET_UHCFMR        0x38         // Usb Host Frame Remaining register\r
+#define USBHOST_OFFSET_UHCFMN        0x3C         // Usb Host Frame Number register\r
+#define USBHOST_OFFSET_UHCPERS       0x40         // Usb Host Periodic Start register\r
+#define USBHOST_OFFSET_UHCLST        0x44         // Usb Host Low-Speed Threshold register\r
+#define USBHOST_OFFSET_UHCRHDA       0x48         // Usb Host Root Hub Descriptor A register\r
+#define USBHOST_OFFSET_UHCRHDB       0x4C         // Usb Host Root Hub Descriptor B register\r
+#define USBHOST_OFFSET_UHCRHS        0x50         // Usb Host Root Hub Status register\r
+#define USBHOST_OFFSET_UHCRHPS1      0x54         // Usb Host Root Hub Port Status 1 register\r
+\r
+//\r
+// Usb Host controller register bit fields\r
+//\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+  UINT8                   ProgInterface;\r
+  UINT8                   SubClassCode;\r
+  UINT8                   BaseCode;\r
+} USB_CLASSC;\r
+\r
+typedef struct {\r
+    UINT32 Revision:8;\r
+    UINT32 Rsvd:24;\r
+} HcREVISION;\r
+\r
+typedef struct {\r
+    UINT32 ControlBulkRatio:2;\r
+    UINT32 PeriodicEnable:1;\r
+    UINT32 IsochronousEnable:1;\r
+    UINT32 ControlEnable:1;\r
+    UINT32 BulkEnable:1;\r
+    UINT32 FunctionalState:2;\r
+    UINT32 InterruptRouting:1;\r
+    UINT32 RemoteWakeup:1;\r
+    UINT32 RemoteWakeupEnable:1;\r
+    UINT32 Reserved:21;\r
+} HcCONTROL;\r
+\r
+typedef struct {\r
+    UINT32 HcReset:1;\r
+    UINT32 ControlListFilled:1;\r
+    UINT32 BulkListFilled:1;\r
+    UINT32 ChangeOwnerRequest:1;\r
+    UINT32 Reserved1:12;\r
+    UINT32 ScheduleOverrunCount:2;\r
+    UINT32 Reserved:14;\r
+} HcCOMMAND_STATUS;\r
+\r
+typedef struct {\r
+    UINT32 SchedulingOverrun:1;\r
+    UINT32 WriteBackDone:1;\r
+    UINT32 Sof:1;\r
+    UINT32 ResumeDetected:1;\r
+    UINT32 UnrecoverableError:1;\r
+    UINT32 FrameNumOverflow:1;\r
+    UINT32 RHStatusChange:1;\r
+    UINT32 Reserved1:23;\r
+    UINT32 OwnerChange:1;\r
+    UINT32 Reserved2:1;\r
+} HcINTERRUPT_STATUS;\r
+\r
+typedef struct {\r
+    UINT32 SchedulingOverrunInt:1;\r
+    UINT32 WriteBackDoneInt:1;\r
+    UINT32 SofInt:1;\r
+    UINT32 ResumeDetectedInt:1;\r
+    UINT32 UnrecoverableErrorInt:1;\r
+    UINT32 FrameNumOverflowInt:1;\r
+    UINT32 RHStatusChangeInt:1;\r
+    UINT32 Reserved:23;\r
+    UINT32 OwnerChangedInt:1;\r
+    UINT32 MasterInterruptEnable:1;\r
+} HcINTERRUPT_CONTROL;\r
+\r
+typedef struct {\r
+    UINT32 Rerserved:8;\r
+    UINT32 Hcca:24;\r
+} HcHCCA;\r
+\r
+typedef struct {\r
+    UINT32 Reserved:4;\r
+    UINT32 MemoryPtr:28;\r
+} HcMEMORY_PTR;\r
+\r
+typedef struct {\r
+    UINT32 FrameInterval:14;\r
+    UINT32 Reserved:2;\r
+    UINT32 FSMaxDataPacket:15;\r
+    UINT32 FrmIntervalToggle:1;\r
+} HcFRM_INTERVAL;\r
+\r
+typedef struct {\r
+    UINT32 FrameRemaining:14;\r
+    UINT32 Reserved:17;\r
+    UINT32 FrameRemainingToggle:1;\r
+} HcFRAME_REMAINING;\r
+\r
+typedef struct {\r
+    UINT32 FrameNumber:16;\r
+    UINT32 Reserved:16;\r
+} HcFRAME_NUMBER;\r
+\r
+typedef struct {\r
+    UINT32 PeriodicStart:14;\r
+    UINT32 Reserved:18;\r
+} HcPERIODIC_START;\r
+\r
+typedef struct {\r
+    UINT32 LsThreshold:12;\r
+    UINT32 Reserved:20;\r
+} HcLS_THRESHOLD;\r
+\r
+typedef struct {\r
+    UINT32 NumDownStrmPorts:8;\r
+    UINT32 PowerSwitchMode:1;\r
+    UINT32 NoPowerSwitch:1;\r
+    UINT32 DeviceType:1;\r
+    UINT32 OverCurrentProtMode:1;\r
+    UINT32 NoOverCurrentProtMode:1;\r
+    UINT32 Reserved:11;\r
+    UINT32 PowerOnToPowerGoodTime:8;\r
+} HcRH_DESC_A;\r
+\r
+typedef struct {\r
+    UINT32 DeviceRemovable:16;\r
+    UINT32 PortPowerControlMask:16;\r
+} HcRH_DESC_B;\r
+\r
+typedef struct {\r
+    UINT32 LocalPowerStat:1;\r
+    UINT32 OverCurrentIndicator:1;\r
+    UINT32 Reserved1:13;\r
+    UINT32 DevRemoteWakeupEnable:1;\r
+    UINT32 LocalPowerStatChange:1;\r
+    UINT32 OverCurrentIndicatorChange:1;\r
+    UINT32 Reserved2:13;\r
+    UINT32 ClearRemoteWakeupEnable:1;\r
+} HcRH_STATUS;\r
+\r
+typedef struct {\r
+    UINT32 CurrentConnectStat:1;\r
+    UINT32 EnableStat:1;\r
+    UINT32 SuspendStat:1;\r
+    UINT32 OCIndicator:1;\r
+    UINT32 ResetStat:1;\r
+    UINT32 Reserved1:3;\r
+    UINT32 PowerStat:1;\r
+    UINT32 LsDeviceAttached:1;\r
+    UINT32 Reserved2:6;\r
+    UINT32 ConnectStatChange:1;\r
+    UINT32 EnableStatChange:1;\r
+    UINT32 SuspendStatChange:1;\r
+    UINT32 OCIndicatorChange:1;\r
+    UINT32 ResetStatChange:1;\r
+    UINT32 Reserved3:11;\r
+} HcRHPORT_STATUS;\r
+\r
+typedef struct {\r
+    UINT32 FSBIR:1;\r
+    UINT32 FHR:1;\r
+    UINT32 CGR:1;\r
+    UINT32 SSDC:1;\r
+    UINT32 UIT:1;\r
+    UINT32 SSE:1;\r
+    UINT32 PSPL:1;\r
+    UINT32 PCPL:1;\r
+    UINT32 Reserved0:1;\r
+    UINT32 SSEP1:1;\r
+    UINT32 SSEP2:1;\r
+    UINT32 SSEP3:1;\r
+    UINT32 Reserved1:20;\r
+} HcRESET;\r
+\r
+\r
+#pragma pack()\r
+\r
+//\r
+// Func List\r
+//\r
+\r
+\r
+/**\r
+\r
+  Get OHCI operational reg value\r
+\r
+  @param  PciIo                 PciIo protocol instance\r
+  @param  Offset                Offset of the operational reg\r
+\r
+  @retval                       Value of the register\r
+\r
+**/\r
+UINT32\r
+OhciGetOperationalReg (\r
+  IN EFI_PCI_IO_PROTOCOL  *PciIo,\r
+  IN UINT32               Offset\r
+  );\r
+\r
+/**\r
+\r
+  Set OHCI operational reg value\r
+\r
+  @param  PciIo                  PCI Bus Io protocol instance\r
+  @param  Offset                 Offset of the operational reg\r
+  @param  Value                  Value to set\r
+\r
+  @retval EFI_SUCCESS            Value set to the reg\r
+\r
+**/\r
+\r
+\r
+EFI_STATUS\r
+OhciSetOperationalReg (\r
+  IN EFI_PCI_IO_PROTOCOL  *PciIo,\r
+  IN UINT32               Offset,\r
+  IN VOID                 *Value\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Get HcRevision reg value\r
+\r
+  @param  PciIo                 PCI Bus Io protocol instance\r
+\r
+  @retval                       Value of the register\r
+\r
+**/\r
+\r
+\r
+UINT32\r
+OhciGetHcRevision (\r
+  IN EFI_PCI_IO_PROTOCOL  *PciIo\r
+  );\r
+\r
+/**\r
+\r
+  Set HcReset reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval EFI_SUCCESS           Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetHcReset (\r
+  IN USB_OHCI_HC_DEV            *Ohc,\r
+  IN UINT32                     Field,\r
+  IN UINT32                     Value\r
+  );\r
+/**\r
+\r
+  Get specific field of HcReset reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetHcReset (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Field\r
+  );\r
+/**\r
+\r
+  Set HcControl reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetHcControl (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field,\r
+  IN UINT32               Value\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Get specific field of HcControl reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+\r
+UINT32\r
+OhciGetHcControl (\r
+  IN USB_OHCI_HC_DEV   *Ohc,\r
+  IN UINTN             Field\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Set HcCommand reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval EFI_SUCCESS           Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetHcCommandStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field,\r
+  IN UINT32               Value\r
+  );\r
+\r
+/**\r
+\r
+  Get specific field of HcCommand reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetHcCommandStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  );\r
+\r
+/**\r
+\r
+  Clear specific fields of Interrupt Status\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to clear\r
+\r
+  @retval EFI_SUCCESS           Fields cleared\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciClearInterruptStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  );\r
+\r
+/**\r
+\r
+  Get fields of HcInterrupt reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetHcInterruptStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  );\r
+\r
+/**\r
+\r
+  Set Interrupt Control reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  StatEnable            Enable or Disable\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval EFI_SUCCESS           Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetInterruptControl (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN BOOLEAN              StatEnable,\r
+  IN UINTN                Field,\r
+  IN UINT32               Value\r
+  );\r
+\r
+/**\r
+\r
+  Get field of HcInterruptControl reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetHcInterruptControl (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Set memory pointer of specific type\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  PointerType           Type of the pointer to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval EFI_SUCCESS           Memory pointer set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetMemoryPointer(\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               PointerType,\r
+  IN VOID                 *Value\r
+  );\r
+\r
+/**\r
+\r
+  Get memory pointer of specific type\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  PointerType           Type of pointer\r
+\r
+  @retval                       Memory pointer of the specific type\r
+\r
+**/\r
+\r
+VOID *\r
+OhciGetMemoryPointer (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               PointerType\r
+  );\r
+\r
+/**\r
+\r
+  Set Frame Interval value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetFrameInterval (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field,\r
+  IN UINT32               Value\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Get field of frame interval reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetFrameInterval (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Set Frame Remaining reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetFrameRemaining (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Value\r
+  );\r
+\r
+/**\r
+\r
+  Get value of frame remaining reg\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of frame remaining reg\r
+\r
+**/\r
+UINT32\r
+OhciGetFrameRemaining (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  );\r
+\r
+/**\r
+\r
+  Set frame number reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetFrameNumber(\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Value\r
+  );\r
+\r
+/**\r
+\r
+  Get frame number reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+\r
+  @retval                       Value of frame number reg\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetFrameNumber (\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Set period start reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Value                 Value to set\r
+\r
+  @retval EFI_SUCCESS           Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetPeriodicStart (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Value\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Get periodic start reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+\r
+  @param                        Value of periodic start reg\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetPeriodicStart (\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Set Ls Threshold reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetLsThreshold (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Value\r
+  );\r
+\r
+/**\r
+\r
+  Get Ls Threshold reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+\r
+  @retval                       Value of Ls Threshold reg\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetLsThreshold (\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  );\r
+\r
+/**\r
+\r
+  Set Root Hub Descriptor reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+EFI_STATUS\r
+OhciSetRootHubDescriptor (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field,\r
+  IN UINT32               Value\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Get Root Hub Descriptor reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetRootHubDescriptor (\r
+  IN USB_OHCI_HC_DEV     *Ohc,\r
+  IN UINTN               Field\r
+  );\r
+\r
+/**\r
+\r
+  Set Root Hub Status reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetRootHubStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Get Root Hub Status reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetRootHubStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Set Root Hub Port Status reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Index                 Index of the port\r
+  @param  Field                 Field to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetRootHubPortStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Index,\r
+  IN UINTN                Field\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Get Root Hub Port Status reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Index                 Index of the port\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field and index\r
+\r
+**/\r
+\r
+UINT32\r
+OhciReadRootHubPortStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Index,\r
+  IN UINTN                Field\r
+  );\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciSched.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciSched.c
new file mode 100644 (file)
index 0000000..22aa26f
--- /dev/null
@@ -0,0 +1,534 @@
+/** @file\r
+OHCI transfer scheduling routines.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include "Ohci.h"\r
+\r
+/**\r
+\r
+  Add an item of interrupt context\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  NewEntry              New entry to add\r
+\r
+  @retval EFI_SUCCESS           Item successfully added\r
+\r
+**/\r
+EFI_STATUS\r
+OhciAddInterruptContextEntry (\r
+  IN  USB_OHCI_HC_DEV          *Ohc,\r
+  IN  INTERRUPT_CONTEXT_ENTRY  *NewEntry\r
+  )\r
+{\r
+  INTERRUPT_CONTEXT_ENTRY  *Entry;\r
+  EFI_TPL                  OriginalTPL;\r
+\r
+  OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+  if (Ohc->InterruptContextList == NULL) {\r
+    Ohc->InterruptContextList = NewEntry;\r
+  } else {\r
+    Entry = Ohc->InterruptContextList;\r
+    while (Entry->NextEntry != NULL) {\r
+      Entry = Entry->NextEntry;\r
+    }\r
+    Entry->NextEntry = NewEntry;\r
+  }\r
+\r
+  gBS->RestoreTPL (OriginalTPL);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Free a interrupt context entry\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Entry                 Pointer to an interrupt context entry\r
+\r
+  @retval EFI_SUCCESS           Entry freed\r
+  @retval EFI_INVALID_PARAMETER Entry is NULL\r
+\r
+**/\r
+EFI_STATUS\r
+OhciFreeInterruptContextEntry (\r
+  IN USB_OHCI_HC_DEV          *Ohc,\r
+  IN INTERRUPT_CONTEXT_ENTRY  *Entry\r
+  )\r
+{\r
+  TD_DESCRIPTOR           *Td;\r
+  if (Entry == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if (Entry->UCBufferMapping != NULL) {\r
+    Ohc->PciIo->Unmap(Ohc->PciIo, Entry->UCBufferMapping);\r
+  }\r
+  if (Entry->UCBuffer != NULL) {\r
+    FreePool(Entry->UCBuffer);\r
+  }\r
+  while (Entry->DataTd) {\r
+    Td = Entry->DataTd;\r
+    Entry->DataTd = (TD_DESCRIPTOR *)(UINTN)(Entry->DataTd->NextTDPointer);\r
+    UsbHcFreeMem(Ohc->MemPool, Td, sizeof(TD_DESCRIPTOR));\r
+  }\r
+  FreePool(Entry);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Free entries match the device address and endpoint address\r
+\r
+  @Param  Ohc                   UHC private date\r
+  @Param  DeviceAddress         Item to free must match this device address\r
+  @Param  EndPointAddress       Item to free must match this end point address\r
+  @Param  DataToggle            DataToggle for output\r
+\r
+  @retval  EFI_SUCCESS          Items match the requirement removed\r
+\r
+**/\r
+EFI_STATUS\r
+OhciFreeInterruptContext(\r
+  IN  USB_OHCI_HC_DEV     *Ohc,\r
+  IN  UINT8               DeviceAddress,\r
+  IN  UINT8               EndPointAddress,\r
+  OUT UINT8               *DataToggle\r
+  )\r
+{\r
+  INTERRUPT_CONTEXT_ENTRY  *Entry;\r
+  INTERRUPT_CONTEXT_ENTRY  *TempEntry;\r
+  EFI_TPL                  OriginalTPL;\r
+\r
+\r
+  OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+  while (Ohc->InterruptContextList != NULL &&\r
+    Ohc->InterruptContextList->DeviceAddress == DeviceAddress &&\r
+    Ohc->InterruptContextList->EndPointAddress == EndPointAddress) {\r
+    TempEntry = Ohc->InterruptContextList;\r
+    Ohc->InterruptContextList = Ohc->InterruptContextList->NextEntry;\r
+    if (DataToggle != NULL) {\r
+      *DataToggle = (UINT8) (TempEntry->DataTd->Word0.DataToggle & 0x1);\r
+    }\r
+    OhciFreeInterruptContextEntry (Ohc, TempEntry);\r
+  }\r
+\r
+  Entry = Ohc->InterruptContextList;\r
+  if (Entry == NULL) {\r
+    gBS->RestoreTPL (OriginalTPL);\r
+    return EFI_SUCCESS;\r
+  }\r
+  while (Entry->NextEntry != NULL) {\r
+    if (Entry->NextEntry->DeviceAddress == DeviceAddress &&\r
+      Entry->NextEntry->EndPointAddress == EndPointAddress) {\r
+      TempEntry = Entry->NextEntry;\r
+      Entry->NextEntry = Entry->NextEntry->NextEntry;\r
+      if (DataToggle != NULL) {\r
+        *DataToggle = (UINT8) (TempEntry->DataTd->Word0.DataToggle & 0x1);\r
+      }\r
+      OhciFreeInterruptContextEntry (Ohc, TempEntry);\r
+    } else {\r
+      Entry = Entry->NextEntry;\r
+    }\r
+  }\r
+\r
+  gBS->RestoreTPL (OriginalTPL);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Convert Error code from OHCI format to EFI format\r
+\r
+  @Param  ErrorCode             ErrorCode in OHCI format\r
+\r
+  @retval                       ErrorCode in EFI format\r
+\r
+**/\r
+UINT32\r
+ConvertErrorCode (\r
+  IN  UINT32              ErrorCode\r
+  )\r
+{\r
+  UINT32                  TransferResult;\r
+\r
+  switch (ErrorCode) {\r
+    case TD_NO_ERROR:\r
+      TransferResult = EFI_USB_NOERROR;\r
+      break;\r
+\r
+    case TD_TOBE_PROCESSED:\r
+    case TD_TOBE_PROCESSED_2:\r
+      TransferResult = EFI_USB_ERR_NOTEXECUTE;\r
+      break;\r
+\r
+    case TD_DEVICE_STALL:\r
+      TransferResult = EFI_USB_ERR_STALL;\r
+      break;\r
+\r
+    case TD_BUFFER_OVERRUN:\r
+    case TD_BUFFER_UNDERRUN:\r
+      TransferResult = EFI_USB_ERR_BUFFER;\r
+      break;\r
+\r
+    case TD_CRC_ERROR:\r
+      TransferResult = EFI_USB_ERR_CRC;\r
+      break;\r
+\r
+    case TD_NO_RESPONSE:\r
+      TransferResult = EFI_USB_ERR_TIMEOUT;\r
+      break;\r
+\r
+    case TD_BITSTUFFING_ERROR:\r
+      TransferResult = EFI_USB_ERR_BITSTUFF;\r
+      break;\r
+\r
+    default:\r
+      TransferResult = EFI_USB_ERR_SYSTEM;\r
+  }\r
+\r
+  return TransferResult;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Check TDs Results\r
+\r
+  @Param  Ohc                   UHC private data\r
+  @Param  Td                    TD_DESCRIPTOR\r
+  @Param  Result                Result to return\r
+\r
+  @retval TRUE                  means OK\r
+  @retval FLASE                 means Error or Short packet\r
+\r
+**/\r
+BOOLEAN\r
+OhciCheckTDsResults (\r
+  IN  USB_OHCI_HC_DEV     *Ohc,\r
+  IN  TD_DESCRIPTOR       *Td,\r
+  OUT UINT32              *Result\r
+  )\r
+{\r
+  UINT32                  TdCompletionCode;\r
+\r
+  *Result   = EFI_USB_NOERROR;\r
+\r
+  while (Td) {\r
+    TdCompletionCode = Td->Word0.ConditionCode;\r
+\r
+    *Result |= ConvertErrorCode(TdCompletionCode);\r
+    //\r
+    // if any error encountered, stop processing the left TDs.\r
+    //\r
+    if (*Result) {\r
+      return FALSE;\r
+    }\r
+\r
+    Td = (TD_DESCRIPTOR *)(UINTN)(Td->NextTDPointer);\r
+  }\r
+  return TRUE;\r
+\r
+}\r
+\r
+\r
+/**\r
+\r
+  Check the task status on an ED\r
+\r
+  @Param  Ed                    Pointer to the ED task that TD hooked on\r
+  @Param  HeadTd                TD header for current transaction\r
+\r
+  @retval                       Task Status Code\r
+\r
+**/\r
+\r
+UINT32\r
+CheckEDStatus (\r
+  IN  ED_DESCRIPTOR       *Ed,\r
+  IN  TD_DESCRIPTOR       *HeadTd,\r
+  OUT OHCI_ED_RESULT      *EdResult\r
+  )\r
+{\r
+  while(HeadTd != NULL) {\r
+    if (HeadTd->NextTDPointer == 0) {\r
+      return TD_NO_ERROR;\r
+    }\r
+    if (HeadTd->Word0.ConditionCode != 0) {\r
+      return HeadTd->Word0.ConditionCode;\r
+    }\r
+    EdResult->NextToggle = ((UINT8)(HeadTd->Word0.DataToggle) & BIT0) ^ BIT0;\r
+    HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);\r
+  }\r
+  if (OhciGetEDField (Ed, ED_TDHEAD_PTR) != OhciGetEDField (Ed, ED_TDTAIL_PTR)) {\r
+    return TD_TOBE_PROCESSED;\r
+  }\r
+  return TD_NO_ERROR;\r
+}\r
+\r
+/**\r
+\r
+  Check the task status\r
+\r
+  @Param  Ohc                   UHC private data\r
+  @Param  ListType              Pipe type\r
+  @Param  Ed                    Pointer to the ED task hooked on\r
+  @Param  HeadTd                Head of TD corresponding to the task\r
+  @Param  ErrorCode             return the ErrorCode\r
+\r
+  @retval  EFI_SUCCESS          Task done\r
+  @retval  EFI_NOT_READY        Task on processing\r
+  @retval  EFI_DEVICE_ERROR     Some error occured\r
+\r
+**/\r
+EFI_STATUS\r
+CheckIfDone (\r
+  IN  USB_OHCI_HC_DEV       *Ohc,\r
+  IN  DESCRIPTOR_LIST_TYPE  ListType,\r
+  IN  ED_DESCRIPTOR         *Ed,\r
+  IN  TD_DESCRIPTOR         *HeadTd,\r
+  OUT OHCI_ED_RESULT        *EdResult\r
+  )\r
+{\r
+  EdResult->ErrorCode = TD_TOBE_PROCESSED;\r
+\r
+  switch (ListType) {\r
+    case CONTROL_LIST:\r
+      if (OhciGetHcCommandStatus (Ohc, CONTROL_LIST_FILLED) != 0) {\r
+        return EFI_NOT_READY;\r
+      }\r
+      break;\r
+    case BULK_LIST:\r
+      if (OhciGetHcCommandStatus (Ohc, BULK_LIST_FILLED) != 0) {\r
+        return EFI_NOT_READY;\r
+      }\r
+      break;\r
+    default:\r
+      break;\r
+  }\r
+\r
+  EdResult->ErrorCode = CheckEDStatus (Ed, HeadTd, EdResult);\r
+\r
+  if (EdResult->ErrorCode == TD_NO_ERROR) {\r
+    return EFI_SUCCESS;\r
+  } else if (EdResult->ErrorCode == TD_TOBE_PROCESSED) {\r
+    return EFI_NOT_READY;\r
+  } else {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+}\r
+\r
+\r
+/**\r
+\r
+  Convert TD condition code to Efi Status\r
+\r
+  @Param  ConditionCode         Condition code to convert\r
+\r
+  @retval  EFI_SUCCESS          No error occured\r
+  @retval  EFI_NOT_READY        TD still on processing\r
+  @retval  EFI_DEVICE_ERROR     Error occured in processing TD\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciTDConditionCodeToStatus (\r
+  IN  UINT32              ConditionCode\r
+  )\r
+{\r
+  if (ConditionCode == TD_NO_ERROR) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (ConditionCode == TD_TOBE_PROCESSED) {\r
+    return EFI_NOT_READY;\r
+  }\r
+\r
+  return EFI_DEVICE_ERROR;\r
+}\r
+\r
+/**\r
+\r
+  Invoke callbacks hooked on done TDs\r
+\r
+  @Param  Entry                 Interrupt transfer transaction information data structure\r
+  @Param  Context               Ohc private data\r
+\r
+**/\r
+\r
+VOID\r
+OhciInvokeInterruptCallBack(\r
+  IN  INTERRUPT_CONTEXT_ENTRY  *Entry,\r
+  IN  UINT32                   Result\r
+)\r
+{\r
+  //Generally speaking, Keyboard driver should not\r
+  //check the Keyboard buffer if an error happens, it will be robust\r
+  //if we NULLed the buffer once error happens\r
+  if (Result) {\r
+    Entry->CallBackFunction (\r
+             NULL,\r
+             0,\r
+             Entry->Context,\r
+             Result\r
+             );\r
+  }else{\r
+    Entry->CallBackFunction (\r
+             (VOID *)(UINTN)(Entry->DataTd->DataBuffer),\r
+             Entry->DataTd->ActualSendLength,\r
+             Entry->Context,\r
+             Result\r
+             );\r
+  }\r
+}\r
+\r
+\r
+/**\r
+\r
+  Timer to submit periodic interrupt transfer, and invoke callbacks hooked on done TDs\r
+\r
+  @param  Event                 Event handle\r
+  @param  Context               Device private data\r
+\r
+**/\r
+\r
+VOID\r
+EFIAPI\r
+OhciHouseKeeper (\r
+  IN  EFI_EVENT           Event,\r
+  IN  VOID                *Context\r
+  )\r
+{\r
+\r
+  USB_OHCI_HC_DEV          *Ohc;\r
+  INTERRUPT_CONTEXT_ENTRY  *Entry;\r
+  INTERRUPT_CONTEXT_ENTRY  *PreEntry;\r
+  ED_DESCRIPTOR            *Ed;\r
+  TD_DESCRIPTOR            *DataTd;\r
+  TD_DESCRIPTOR            *HeadTd;\r
+\r
+  UINT8                    Toggle;\r
+  EFI_TPL                  OriginalTPL;\r
+  UINT32                   Result;\r
+\r
+  Ohc = (USB_OHCI_HC_DEV *) Context;\r
+  OriginalTPL = gBS->RaiseTPL(TPL_NOTIFY);\r
+\r
+  Entry = Ohc->InterruptContextList;\r
+  PreEntry = NULL;\r
+\r
+  while(Entry != NULL) {\r
+\r
+    OhciCheckTDsResults(Ohc, Entry->DataTd, &Result );\r
+    if (((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) ||\r
+      ((Result & EFI_USB_ERR_NOTEXECUTE) == EFI_USB_ERR_NOTEXECUTE)) {\r
+      PreEntry = Entry;\r
+      Entry = Entry->NextEntry;\r
+      continue;\r
+    }\r
+\r
+    if (Entry->CallBackFunction != NULL) {\r
+      OhciInvokeInterruptCallBack (Entry, Result);\r
+      if (Ohc->InterruptContextList == NULL) {\r
+        gBS->RestoreTPL (OriginalTPL);\r
+        return;\r
+      }\r
+    }\r
+    if (Entry->IsPeriodic) {\r
+\r
+      Ed = Entry->Ed;\r
+      HeadTd = Entry->DataTd;\r
+      DataTd = HeadTd;\r
+      Toggle = 0;\r
+      if (Result == EFI_USB_NOERROR) {\r
+        //\r
+        // Update toggle if there is no error, and re-submit the interrupt Ed&Tds\r
+        //\r
+        if ((Ed != NULL) && (DataTd != NULL)) {\r
+          Ed->Word0.Skip = 1;\r
+        }\r
+        //\r
+        // From hcir1_0a.pdf 4.2.2\r
+        // ToggleCarry:This bit is the data toggle carry bit,\r
+        // Whenever a TD is retired, this bit is written to\r
+        // contain the last data toggle value(LSb of data Toggel\r
+        // file) from the retired TD.\r
+        // This field is not used for Isochronous Endpoints\r
+        //\r
+        if (Ed == NULL) {\r
+          return;\r
+        }\r
+        Toggle = (UINT8) OhciGetEDField (Ed, ED_DTTOGGLE);\r
+        while(DataTd != NULL) {\r
+          if (DataTd->NextTDPointer == 0) {\r
+            DataTd->Word0.DataToggle = 0;\r
+            break;\r
+          } else {\r
+            OhciSetTDField (DataTd, TD_DT_TOGGLE, Toggle);\r
+          }\r
+          DataTd = (TD_DESCRIPTOR *)(UINTN)(DataTd->NextTDPointer);\r
+          Toggle ^= 1;\r
+        }\r
+        //\r
+        // HC will only update DataToggle, ErrorCount, ConditionCode\r
+        // CurrentBufferPointer & NextTD, so we only need to update\r
+        // them once we want to active them again\r
+        //\r
+        DataTd = HeadTd;\r
+        while (DataTd != NULL) {\r
+          if (DataTd->NextTDPointer == 0) {\r
+            OhciSetTDField (DataTd, TD_ERROR_CNT | TD_COND_CODE | TD_CURR_BUFFER_PTR | TD_NEXT_PTR, 0);\r
+            break;\r
+          }\r
+          OhciSetTDField (DataTd, TD_ERROR_CNT, 0);\r
+          OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);\r
+          DataTd->NextTD = DataTd->NextTDPointer;\r
+          DataTd->CurrBufferPointer = DataTd->DataBuffer;\r
+          DataTd = (TD_DESCRIPTOR *)(UINTN)(DataTd->NextTDPointer);\r
+        }\r
+        //\r
+        // Active current Ed,Td\r
+        //\r
+        // HC will only update Halted, ToggleCarry & TDQueueHeadPointer,\r
+        // So we only need to update them once we want to active them again.\r
+        //\r
+        if ((Ed != NULL) && (DataTd != NULL)) {\r
+          Ed->Word2.TdHeadPointer = (UINT32)((UINTN)HeadTd>>4);\r
+          OhciSetEDField (Ed, ED_HALTED | ED_DTTOGGLE, 0);\r
+          Ed->Word0.Skip = 0;\r
+        }\r
+      }\r
+    } else {\r
+      if (PreEntry == NULL) {\r
+        Ohc->InterruptContextList = Entry->NextEntry;\r
+      } else {\r
+        PreEntry = Entry;\r
+        PreEntry->NextEntry = Entry->NextEntry;\r
+      }\r
+      OhciFreeInterruptContextEntry (Ohc, PreEntry);\r
+      gBS->RestoreTPL (OriginalTPL);\r
+      return;\r
+    }\r
+    PreEntry = Entry;\r
+    Entry = Entry->NextEntry;\r
+  }\r
+  gBS->RestoreTPL (OriginalTPL);\r
+}\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciSched.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciSched.h
new file mode 100644 (file)
index 0000000..8a86382
--- /dev/null
@@ -0,0 +1,231 @@
+/** @file\r
+This file contains the definination for host controller schedule routines.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+\r
+#ifndef _OHCI_SCHED_H\r
+#define _OHCI_SCHED_H\r
+\r
+#include "Descriptor.h"\r
+\r
+#define HCCA_MEM_SIZE     256\r
+#define GRID_SIZE         16\r
+#define GRID_SHIFT        4\r
+\r
+typedef struct _INTERRUPT_CONTEXT_ENTRY INTERRUPT_CONTEXT_ENTRY;\r
+\r
+struct _INTERRUPT_CONTEXT_ENTRY{\r
+  UINT8                               DeviceAddress;\r
+  UINT8                               EndPointAddress;\r
+  ED_DESCRIPTOR                       *Ed;\r
+  TD_DESCRIPTOR                       *DataTd;\r
+  BOOLEAN                             IsSlowDevice;\r
+  UINT8                               MaxPacketLength;\r
+  UINTN                               PollingInterval;\r
+  EFI_ASYNC_USB_TRANSFER_CALLBACK     CallBackFunction;\r
+  VOID                                *Context;\r
+  BOOLEAN                             IsPeriodic;\r
+  VOID                                *Buffer;\r
+  UINTN                               DataLength;\r
+  VOID                                *UCBuffer;\r
+  VOID                                *UCBufferMapping;\r
+  UINT8                               *Toggle;\r
+  INTERRUPT_CONTEXT_ENTRY      *NextEntry;\r
+};\r
+\r
+\r
+typedef struct {\r
+  UINT32                  ErrorCode;\r
+  UINT8                   NextToggle;\r
+} OHCI_ED_RESULT;\r
+\r
+/**\r
+\r
+  Add an item of interrupt context\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  NewEntry              New entry to add\r
+\r
+  @retval EFI_SUCCESS           Item successfully added\r
+\r
+**/\r
+EFI_STATUS\r
+OhciAddInterruptContextEntry (\r
+  IN  USB_OHCI_HC_DEV          *Ohc,\r
+  IN  INTERRUPT_CONTEXT_ENTRY  *NewEntry\r
+  );\r
+\r
+/**\r
+\r
+  Free a interrupt context entry\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Entry                 Pointer to an interrupt context entry\r
+\r
+  @retval EFI_SUCCESS           Entry freed\r
+  @retval EFI_INVALID_PARAMETER Entry is NULL\r
+\r
+**/\r
+EFI_STATUS\r
+OhciFreeInterruptContextEntry (\r
+  IN USB_OHCI_HC_DEV          *Ohc,\r
+  IN INTERRUPT_CONTEXT_ENTRY  *Entry\r
+  );\r
+\r
+/**\r
+\r
+  Free entries match the device address and endpoint address\r
+\r
+  @Param  Ohc                   UHC private date\r
+  @Param  DeviceAddress         Item to free must match this device address\r
+  @Param  EndPointAddress       Item to free must match this end point address\r
+  @Param  DataToggle            DataToggle for output\r
+\r
+  @retval  EFI_SUCCESS          Items match the requirement removed\r
+\r
+**/\r
+EFI_STATUS\r
+OhciFreeInterruptContext(\r
+  IN  USB_OHCI_HC_DEV     *Ohc,\r
+  IN  UINT8               DeviceAddress,\r
+  IN  UINT8               EndPointAddress,\r
+  OUT UINT8               *DataToggle\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Convert Error code from OHCI format to EFI format\r
+\r
+  @Param  ErrorCode             ErrorCode in OHCI format\r
+\r
+  @retval                       ErrorCode in EFI format\r
+\r
+**/\r
+UINT32\r
+ConvertErrorCode (\r
+  IN  UINT32              ErrorCode\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Check TDs Results\r
+\r
+  @Param  Ohc                   UHC private data\r
+  @Param  Td                    TD_DESCRIPTOR\r
+  @Param  Result                Result to return\r
+\r
+  @retval TRUE                  means OK\r
+  @retval FLASE                 means Error or Short packet\r
+\r
+**/\r
+BOOLEAN\r
+OhciCheckTDsResults (\r
+  IN  USB_OHCI_HC_DEV     *Ohc,\r
+  IN  TD_DESCRIPTOR       *Td,\r
+  OUT UINT32              *Result\r
+  );\r
+/**\r
+\r
+  Check the task status on an ED\r
+\r
+  @Param  Ed                    Pointer to the ED task that TD hooked on\r
+  @Param  HeadTd                TD header for current transaction\r
+\r
+  @retval                       Task Status Code\r
+\r
+**/\r
+\r
+UINT32\r
+CheckEDStatus (\r
+  IN  ED_DESCRIPTOR       *Ed,\r
+  IN  TD_DESCRIPTOR       *HeadTd,\r
+  OUT OHCI_ED_RESULT      *EdResult\r
+  );\r
+/**\r
+\r
+  Check the task status\r
+\r
+  @Param  Ohc                   UHC private data\r
+  @Param  ListType              Pipe type\r
+  @Param  Ed                    Pointer to the ED task hooked on\r
+  @Param  HeadTd                Head of TD corresponding to the task\r
+  @Param  ErrorCode             return the ErrorCode\r
+\r
+  @retval  EFI_SUCCESS          Task done\r
+  @retval  EFI_NOT_READY        Task on processing\r
+  @retval  EFI_DEVICE_ERROR     Some error occured\r
+\r
+**/\r
+EFI_STATUS\r
+CheckIfDone (\r
+  IN  USB_OHCI_HC_DEV       *Ohc,\r
+  IN  DESCRIPTOR_LIST_TYPE  ListType,\r
+  IN  ED_DESCRIPTOR         *Ed,\r
+  IN  TD_DESCRIPTOR         *HeadTd,\r
+  OUT OHCI_ED_RESULT        *EdResult\r
+  );\r
+\r
+/**\r
+\r
+  Convert TD condition code to Efi Status\r
+\r
+  @Param  ConditionCode         Condition code to convert\r
+\r
+  @retval  EFI_SUCCESS          No error occured\r
+  @retval  EFI_NOT_READY        TD still on processing\r
+  @retval  EFI_DEVICE_ERROR     Error occured in processing TD\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciTDConditionCodeToStatus (\r
+  IN  UINT32              ConditionCode\r
+  );\r
+\r
+/**\r
+\r
+  Invoke callbacks hooked on done TDs\r
+\r
+  @Param  Entry                 Interrupt transfer transaction information data structure\r
+  @Param  Context               Ohc private data\r
+\r
+**/\r
+\r
+VOID\r
+OhciInvokeInterruptCallBack(\r
+  IN  INTERRUPT_CONTEXT_ENTRY  *Entry,\r
+  IN  UINT32                   Result\r
+);\r
+\r
+\r
+/**\r
+\r
+  Timer to submit periodic interrupt transfer, and invoke callbacks hooked on done TDs\r
+\r
+  @param  Event                 Event handle\r
+  @param  Context               Device private data\r
+\r
+**/\r
+\r
+VOID\r
+EFIAPI\r
+OhciHouseKeeper (\r
+  IN  EFI_EVENT           Event,\r
+  IN  VOID                *Context\r
+  );\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciUrb.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciUrb.c
new file mode 100644 (file)
index 0000000..736bab9
--- /dev/null
@@ -0,0 +1,895 @@
+/** @file\r
+This file contains URB request, each request is warpped in a\r
+URB (Usb Request Block).\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+\r
+#include "Ohci.h"\r
+\r
+\r
+/**\r
+\r
+  Create a TD\r
+\r
+  @Param  Ohc                   UHC private data\r
+\r
+  @retval                       TD structure pointer\r
+\r
+**/\r
+TD_DESCRIPTOR *\r
+OhciCreateTD (\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  )\r
+{\r
+  TD_DESCRIPTOR           *Td;\r
+\r
+  Td = UsbHcAllocateMem(Ohc->MemPool, sizeof(TD_DESCRIPTOR));\r
+  if (Td == NULL) {\r
+    DEBUG ((EFI_D_INFO, "STV allocate TD fail !\r\n"));\r
+    return NULL;\r
+  }\r
+  Td->CurrBufferPointer = 0;\r
+  Td->NextTD = 0;\r
+  Td->BufferEndPointer = 0;\r
+  Td->NextTDPointer = 0;\r
+\r
+  return Td;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Free a TD\r
+\r
+  @Param  Ohc                   UHC private data\r
+  @Param  Td                    Pointer to a TD to free\r
+\r
+  @retval  EFI_SUCCESS          TD freed\r
+\r
+**/\r
+EFI_STATUS\r
+OhciFreeTD (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN TD_DESCRIPTOR        *Td\r
+  )\r
+{\r
+  if (Td == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  UsbHcFreeMem(Ohc->MemPool, Td, sizeof(TD_DESCRIPTOR));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Create a ED\r
+\r
+  @Param   Ohc                  Device private data\r
+\r
+  @retval  ED                   descriptor pointer\r
+\r
+**/\r
+ED_DESCRIPTOR *\r
+OhciCreateED (\r
+  USB_OHCI_HC_DEV          *Ohc\r
+  )\r
+{\r
+  ED_DESCRIPTOR   *Ed;\r
+  Ed = UsbHcAllocateMem(Ohc->MemPool, sizeof (ED_DESCRIPTOR));\r
+  if (Ed == NULL) {\r
+    DEBUG ((EFI_D_INFO, "STV allocate ED fail !\r\n"));\r
+    return NULL;\r
+  }\r
+  Ed->Word0.Skip = 1;\r
+  Ed->TdTailPointer = 0;\r
+  Ed->Word2.TdHeadPointer = 0;\r
+  Ed->NextED = 0;\r
+\r
+  return Ed;\r
+}\r
+\r
+/**\r
+\r
+  Free a ED\r
+\r
+  @Param  Ohc                   UHC private data\r
+  @Param  Ed                    Pointer to a ED to free\r
+\r
+  @retval  EFI_SUCCESS          ED freed\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciFreeED (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN ED_DESCRIPTOR        *Ed\r
+  )\r
+{\r
+  if (Ed == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Free  ED\r
+\r
+  @Param  Ohc                    Device private data\r
+  @Param  Ed                     Pointer to a ED to free\r
+\r
+  @retval  EFI_SUCCESS           ED freed\r
+\r
+**/\r
+EFI_STATUS\r
+OhciFreeAllTDFromED (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN ED_DESCRIPTOR        *Ed\r
+  )\r
+{\r
+  TD_DESCRIPTOR           *HeadTd;\r
+  TD_DESCRIPTOR           *TailTd;\r
+  TD_DESCRIPTOR           *Td;\r
+  TD_DESCRIPTOR           *TempTd;\r
+\r
+  if (Ed == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  HeadTd = TD_PTR (Ed->Word2.TdHeadPointer);\r
+  TailTd = (TD_DESCRIPTOR *)(UINTN)(Ed->TdTailPointer);\r
+\r
+  Td = HeadTd;\r
+  while (Td != TailTd) {\r
+    TempTd = Td;\r
+    Td = (TD_DESCRIPTOR *)(UINTN)(Td->NextTDPointer);\r
+    OhciFreeTD (Ohc, TempTd);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Find a working ED match the requirement\r
+\r
+  @Param  EdHead                Head of the ED list\r
+  @Param  DeviceAddress         Device address to search\r
+  @Param  EndPointNum           End point num to search\r
+  @Param  EdDir                 ED Direction to search\r
+\r
+  @retval   ED descriptor searched\r
+\r
+**/\r
+\r
+ED_DESCRIPTOR *\r
+OhciFindWorkingEd (\r
+  IN ED_DESCRIPTOR       *EdHead,\r
+  IN UINT8               DeviceAddress,\r
+  IN UINT8               EndPointNum,\r
+  IN UINT8               EdDir\r
+  )\r
+{\r
+  ED_DESCRIPTOR           *Ed;\r
+\r
+  for (Ed = EdHead; Ed != NULL; Ed = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED)) {\r
+    if (Ed->Word2.Halted == 0 && Ed->Word0.Skip == 0 &&\r
+        Ed->Word0.FunctionAddress == DeviceAddress && Ed->Word0.EndPointNum == EndPointNum &&\r
+        Ed->Word0.Direction == EdDir) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  return Ed;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Initialize interrupt list.\r
+\r
+  @Param Ohc                    Device private data\r
+\r
+  @retval  EFI_SUCCESS          Initialization done\r
+\r
+**/\r
+EFI_STATUS\r
+OhciInitializeInterruptList (\r
+  USB_OHCI_HC_DEV          *Ohc\r
+  )\r
+{\r
+  static UINT32     Leaf[32] = {0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30, 1, 17,\r
+                                9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31};\r
+  UINT32            *HccaInterruptTable;\r
+  UINTN             Index;\r
+  UINTN             Level;\r
+  UINTN             Count;\r
+  ED_DESCRIPTOR     *NewEd;\r
+\r
+  HccaInterruptTable = Ohc->HccaMemoryBlock->HccaInterruptTable;\r
+\r
+  for (Index = 0; Index < 32; Index++) {\r
+    NewEd = OhciCreateED (Ohc);\r
+    if (NewEd == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    HccaInterruptTable[Index] = (UINT32)(UINTN)NewEd;\r
+  }\r
+\r
+  for (Index = 0; Index < 32; Index++) {\r
+    Ohc->IntervalList[0][Index] = (ED_DESCRIPTOR *)(UINTN)HccaInterruptTable[Leaf[Index]];\r
+  }\r
+\r
+  Count = 32;\r
+  for (Level = 1; Level <= 5; Level++) {\r
+    Count = Count >> 1;\r
+\r
+    for (Index = 0; Index < Count; Index++) {\r
+      Ohc->IntervalList[Level][Index] = OhciCreateED (Ohc);\r
+      if (HccaInterruptTable[Index] == 0) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+      Ohc->IntervalList[Level - 1][Index * 2    ]->NextED = (UINT32)(UINTN)Ohc->IntervalList[Level][Index];\r
+      Ohc->IntervalList[Level - 1][Index * 2 + 1]->NextED = (UINT32)(UINTN)Ohc->IntervalList[Level][Index];\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Attach an ED\r
+\r
+  @Param  Ed                    Ed to be attached\r
+  @Param  NewEd                 Ed to attach\r
+\r
+  @retval EFI_SUCCESS           NewEd attached to Ed\r
+  @retval EFI_INVALID_PARAMETER Ed is NULL\r
+\r
+**/\r
+EFI_STATUS\r
+OhciAttachED (\r
+  IN ED_DESCRIPTOR        *Ed,\r
+  IN ED_DESCRIPTOR        *NewEd\r
+  )\r
+{\r
+  ED_DESCRIPTOR           *Temp;\r
+\r
+  if (Ed == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Ed->NextED == 0){\r
+    Ed->NextED = (UINT32)(UINTN)NewEd;\r
+  } else {\r
+    Temp = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);\r
+    Ed->NextED = (UINT32)(UINTN)NewEd;\r
+    NewEd->NextED = (UINT32)(UINTN)Temp;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Count ED number on a ED chain\r
+\r
+  @Param  Ed                    Head of the ED chain\r
+\r
+  @retval                       ED number on the chain\r
+\r
+**/\r
+\r
+UINTN\r
+CountEdNum (\r
+  IN ED_DESCRIPTOR      *Ed\r
+  )\r
+{\r
+  UINTN     Count;\r
+\r
+  Count = 0;\r
+\r
+  while (Ed) {\r
+    Ed = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);\r
+    Count++;\r
+  }\r
+\r
+  return Count;\r
+}\r
+\r
+/**\r
+\r
+  Find the minimal burn ED list on a specific depth level\r
+\r
+  @Param  Ohc                   Device private data\r
+  @Param  Depth                 Depth level\r
+\r
+  @retval                       ED list found\r
+\r
+**/\r
+\r
+ED_DESCRIPTOR *\r
+OhciFindMinInterruptEDList (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Depth\r
+  )\r
+{\r
+  UINTN                   EdNum;\r
+  UINTN                   MinEdNum;\r
+  ED_DESCRIPTOR           *TempEd;\r
+  ED_DESCRIPTOR           *HeadEd;\r
+  UINTN                   Index;\r
+\r
+  if (Depth > 5) {\r
+    return NULL;\r
+  }\r
+\r
+  MinEdNum = 0xFFFFFFFF;\r
+  TempEd = NULL;\r
+  for (Index = 0; Index < (UINTN)(32 >> Depth); Index++) {\r
+    HeadEd = Ohc->IntervalList[Depth][Index];\r
+    EdNum = CountEdNum (HeadEd);\r
+    if (EdNum < MinEdNum) {\r
+      MinEdNum = EdNum;\r
+      TempEd = HeadEd;\r
+    }\r
+  }\r
+\r
+  ASSERT (TempEd != NULL);\r
+\r
+  return TempEd;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Attach an ED to an ED list\r
+\r
+  @Param  OHC                   UHC private data\r
+  @Param  ListType              Type of the ED list\r
+  @Param  Ed                    ED to attach\r
+  @Param  EdList                ED list to be attached\r
+\r
+  @retval  EFI_SUCCESS          ED attached to ED list\r
+\r
+**/\r
+ED_DESCRIPTOR *\r
+OhciAttachEDToList (\r
+  IN USB_OHCI_HC_DEV       *Ohc,\r
+  IN DESCRIPTOR_LIST_TYPE  ListType,\r
+  IN ED_DESCRIPTOR         *Ed,\r
+  IN ED_DESCRIPTOR         *EdList\r
+  )\r
+{\r
+  ED_DESCRIPTOR            *HeadEd;\r
+\r
+  HeadEd = NULL;\r
+  switch(ListType) {\r
+    case CONTROL_LIST:\r
+      HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_CONTROL_HEAD);\r
+      if (HeadEd == NULL) {\r
+        OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, Ed);\r
+        HeadEd = Ed;\r
+      } else {\r
+        OhciAttachED (HeadEd, Ed);\r
+      }\r
+    break;\r
+\r
+    case BULK_LIST:\r
+      HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_BULK_HEAD);\r
+      if (HeadEd == NULL) {\r
+        OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, Ed);\r
+        HeadEd = Ed;\r
+      } else {\r
+        OhciAttachED (HeadEd, Ed);\r
+      }\r
+    break;\r
+\r
+    case INTERRUPT_LIST:\r
+      OhciAttachED (EdList, Ed);\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+  }\r
+\r
+  return HeadEd;\r
+}\r
+\r
+/**\r
+\r
+  Remove interrupt EDs that match requirement\r
+\r
+  @Param  Ohc                   UHC private data\r
+  @Param  IntEd                 The address of Interrupt endpoint\r
+\r
+  @retval  EFI_SUCCESS          EDs match requirement removed\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciFreeInterruptEdByEd (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN ED_DESCRIPTOR        *IntEd\r
+  )\r
+{\r
+  ED_DESCRIPTOR           *Ed;\r
+  ED_DESCRIPTOR           *TempEd;\r
+  UINTN                   Index;\r
+\r
+  if (IntEd == NULL)\r
+    return EFI_SUCCESS;\r
+\r
+  for (Index = 0; Index < 32; Index++) {\r
+    Ed = (ED_DESCRIPTOR *)(UINTN)Ohc->HccaMemoryBlock->HccaInterruptTable[Index];\r
+    if (Ed == NULL) {\r
+      continue;\r
+    }\r
+    while (Ed->NextED != 0) {\r
+      if (Ed->NextED == (UINT32)(UINTN)IntEd ) {\r
+        TempEd = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);\r
+        Ed->NextED = TempEd->NextED;\r
+        OhciFreeED (Ohc, TempEd);\r
+      } else {\r
+        Ed = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);\r
+      }\r
+    }\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Remove interrupt EDs that match requirement\r
+\r
+  @Param  Ohc                   UHC private data\r
+  @Param  FunctionAddress       Requirement on function address\r
+  @Param  EndPointNum           Requirement on end point number\r
+\r
+  @retval  EFI_SUCCESS          EDs match requirement removed\r
+\r
+**/\r
+EFI_STATUS\r
+OhciFreeInterruptEdByAddr (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT8                FunctionAddress,\r
+  IN UINT8                EndPointNum\r
+  )\r
+{\r
+  ED_DESCRIPTOR           *Ed;\r
+  ED_DESCRIPTOR           *TempEd;\r
+  UINTN                   Index;\r
+\r
+  for (Index = 0; Index < 32; Index++) {\r
+    Ed = (ED_DESCRIPTOR *)(UINTN)Ohc->HccaMemoryBlock->HccaInterruptTable[Index];\r
+    if (Ed == NULL) {\r
+      continue;\r
+    }\r
+\r
+    while (Ed->NextED != 0) {\r
+      TempEd = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);\r
+      if (TempEd->Word0.FunctionAddress == FunctionAddress &&\r
+          TempEd->Word0.EndPointNum     == EndPointNum        ) {\r
+        Ed->NextED = TempEd->NextED;\r
+        OhciFreeED (Ohc, TempEd);\r
+      } else {\r
+        Ed = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Link Td2 to the end of Td1\r
+\r
+  @Param Td1                    TD to be linked\r
+  @Param Td2                    TD to link\r
+\r
+  @retval EFI_SUCCESS           TD successfully linked\r
+  @retval EFI_INVALID_PARAMETER Td1 is NULL\r
+\r
+**/\r
+EFI_STATUS\r
+OhciLinkTD (\r
+  IN TD_DESCRIPTOR        *Td1,\r
+  IN TD_DESCRIPTOR        *Td2\r
+  )\r
+{\r
+  TD_DESCRIPTOR           *TempTd;\r
+\r
+  if (Td1 == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Td1 == Td2) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  TempTd = Td1;\r
+  while (TempTd->NextTD != 0) {\r
+    TempTd = (TD_DESCRIPTOR *)(UINTN)(TempTd->NextTD);\r
+  }\r
+\r
+  TempTd->NextTD = (UINT32)(UINTN)Td2;\r
+  TempTd->NextTDPointer = (UINT32)(UINTN)Td2;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Attach TD list to ED\r
+\r
+  @Param  Ed                    ED which TD list attach on\r
+  @Param  HeadTd                Head of the TD list to attach\r
+\r
+  @retval  EFI_SUCCESS          TD list attached on the ED\r
+\r
+**/\r
+EFI_STATUS\r
+OhciAttachTDListToED (\r
+  IN ED_DESCRIPTOR        *Ed,\r
+  IN TD_DESCRIPTOR        *HeadTd\r
+  )\r
+{\r
+  TD_DESCRIPTOR           *TempTd;\r
+\r
+  TempTd = TD_PTR (Ed->Word2.TdHeadPointer);\r
+\r
+  if (TempTd != NULL) {\r
+    while (TempTd->NextTD != 0) {\r
+      TempTd = (TD_DESCRIPTOR *)(UINTN)(TempTd->NextTD);\r
+    }\r
+    TempTd->NextTD = (UINT32)(UINTN)HeadTd;\r
+    TempTd->NextTDPointer = (UINT32)(UINTN)HeadTd;\r
+  } else {\r
+    Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 ((UINT32)(UINTN)HeadTd);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Set value to ED specific field\r
+\r
+  @Param  Ed                    ED to be set\r
+  @Param  Field                 Field to be set\r
+  @Param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+EFI_STATUS\r
+OhciSetEDField (\r
+  IN ED_DESCRIPTOR        *Ed,\r
+  IN UINT32               Field,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  if (Field & ED_FUNC_ADD) {\r
+    Ed->Word0.FunctionAddress = Value;\r
+  }\r
+  if (Field & ED_ENDPT_NUM) {\r
+    Ed->Word0.EndPointNum = Value;\r
+  }\r
+  if (Field & ED_DIR) {\r
+    Ed->Word0.Direction = Value;\r
+  }\r
+  if (Field & ED_SPEED) {\r
+    Ed->Word0.Speed = Value;\r
+  }\r
+  if (Field & ED_SKIP) {\r
+    Ed->Word0.Skip = Value;\r
+  }\r
+  if (Field & ED_FORMAT) {\r
+    Ed->Word0.Format = Value;\r
+  }\r
+  if (Field & ED_MAX_PACKET) {\r
+    Ed->Word0.MaxPacketSize = Value;\r
+  }\r
+  if (Field & ED_PDATA) {\r
+    Ed->Word0.FreeSpace = Value;\r
+  }\r
+  if (Field & ED_ZERO) {\r
+    Ed->Word2.Zero = Value;\r
+  }\r
+  if (Field & ED_TDTAIL_PTR) {\r
+    Ed->TdTailPointer = Value;\r
+  }\r
+\r
+  if (Field & ED_HALTED) {\r
+    Ed->Word2.Halted = Value;\r
+  }\r
+  if (Field & ED_DTTOGGLE) {\r
+    Ed->Word2.ToggleCarry = Value;\r
+  }\r
+  if (Field & ED_TDHEAD_PTR) {\r
+    Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 (Value);\r
+  }\r
+\r
+  if (Field & ED_NEXT_EDPTR) {\r
+    Ed->NextED = Value;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Get value from an ED's specific field\r
+\r
+  @Param  Ed                    ED pointer\r
+  @Param  Field                 Field to get value from\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+UINT32\r
+OhciGetEDField (\r
+  IN ED_DESCRIPTOR        *Ed,\r
+  IN UINT32               Field\r
+  )\r
+{\r
+  switch (Field) {\r
+    case ED_FUNC_ADD:\r
+      return Ed->Word0.FunctionAddress;\r
+      break;\r
+    case ED_ENDPT_NUM:\r
+      return Ed->Word0.EndPointNum;\r
+      break;\r
+    case ED_DIR:\r
+      return Ed->Word0.Direction;\r
+      break;\r
+    case ED_SPEED:\r
+      return Ed->Word0.Speed;\r
+      break;\r
+    case ED_SKIP:\r
+      return Ed->Word0.Skip;\r
+      break;\r
+    case ED_FORMAT:\r
+      return Ed->Word0.Format;\r
+      break;\r
+    case ED_MAX_PACKET:\r
+      return Ed->Word0.MaxPacketSize;\r
+      break;\r
+\r
+    case ED_TDTAIL_PTR:\r
+      return Ed->TdTailPointer;\r
+      break;\r
+\r
+    case ED_HALTED:\r
+      return Ed->Word2.Halted;\r
+      break;\r
+\r
+    case ED_DTTOGGLE:\r
+      return Ed->Word2.ToggleCarry;\r
+      break;\r
+\r
+    case ED_TDHEAD_PTR:\r
+      return Ed->Word2.TdHeadPointer << 4;\r
+      break;\r
+\r
+    case ED_NEXT_EDPTR:\r
+      return Ed->NextED;\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Set value to TD specific field\r
+\r
+  @Param  Td                    TD to be set\r
+  @Param  Field                 Field to be set\r
+  @Param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+EFI_STATUS\r
+OhciSetTDField (\r
+  IN TD_DESCRIPTOR        *Td,\r
+  IN UINT32               Field,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  if (Field & TD_PDATA) {\r
+    Td->Word0.Reserved = Value;\r
+  }\r
+  if (Field & TD_BUFFER_ROUND) {\r
+    Td->Word0.BufferRounding = Value;\r
+  }\r
+  if (Field & TD_DIR_PID) {\r
+    Td->Word0.DirPID = Value;\r
+  }\r
+  if (Field & TD_DELAY_INT) {\r
+    Td->Word0.DelayInterrupt = Value;\r
+  }\r
+  if (Field & TD_DT_TOGGLE) {\r
+    Td->Word0.DataToggle = Value | 0x2;\r
+  }\r
+  if (Field & TD_ERROR_CNT) {\r
+    Td->Word0.ErrorCount = Value;\r
+  }\r
+  if (Field & TD_COND_CODE) {\r
+    Td->Word0.ConditionCode = Value;\r
+  }\r
+\r
+  if (Field & TD_CURR_BUFFER_PTR) {\r
+    Td->CurrBufferPointer = Value;\r
+  }\r
+\r
+\r
+  if (Field & TD_NEXT_PTR) {\r
+    Td->NextTD = Value;\r
+  }\r
+\r
+  if (Field & TD_BUFFER_END_PTR) {\r
+    Td->BufferEndPointer = Value;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Get value from ED specific field\r
+\r
+  @Param  Td                    TD pointer\r
+  @Param  Field                 Field to get value from\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetTDField (\r
+  IN TD_DESCRIPTOR      *Td,\r
+  IN UINT32             Field\r
+  )\r
+{\r
+  switch (Field){\r
+    case TD_BUFFER_ROUND:\r
+      return Td->Word0.BufferRounding;\r
+      break;\r
+    case TD_DIR_PID:\r
+      return Td->Word0.DirPID;\r
+      break;\r
+    case TD_DELAY_INT:\r
+      return Td->Word0.DelayInterrupt;\r
+      break;\r
+    case TD_DT_TOGGLE:\r
+      return Td->Word0.DataToggle;\r
+      break;\r
+    case TD_ERROR_CNT:\r
+      return Td->Word0.ErrorCount;\r
+      break;\r
+    case TD_COND_CODE:\r
+      return Td->Word0.ConditionCode;\r
+      break;\r
+    case TD_CURR_BUFFER_PTR:\r
+      return Td->CurrBufferPointer;\r
+      break;\r
+\r
+    case TD_NEXT_PTR:\r
+      return Td->NextTD;\r
+      break;\r
+\r
+    case TD_BUFFER_END_PTR:\r
+      return Td->BufferEndPointer;\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+\r
+  Free the Ed,Td,buffer that were created during transferring\r
+\r
+  @Param  Ohc                   Device private data\r
+**/\r
+\r
+VOID\r
+OhciFreeDynamicIntMemory(\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  )\r
+{\r
+  INTERRUPT_CONTEXT_ENTRY *Entry;\r
+  if (Ohc != NULL) {\r
+    while (Ohc->InterruptContextList != NULL) {\r
+      Entry = Ohc->InterruptContextList;\r
+      Ohc->InterruptContextList = Ohc->InterruptContextList->NextEntry;\r
+      OhciFreeInterruptEdByEd (Ohc, Entry->Ed);\r
+      OhciFreeInterruptContextEntry (Ohc, Entry);\r
+    }\r
+  }\r
+}\r
+/**\r
+\r
+  Free the Ed that were initilized during driver was starting,\r
+  those memory were used as interrupt ED head\r
+\r
+  @Param  Ohc                   Device private data\r
+\r
+\r
+**/\r
+VOID\r
+OhciFreeFixedIntMemory (\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  )\r
+{\r
+  static UINT32           Leaf[] = {32,16,8,4,2,1};\r
+  UINTN                   Index;\r
+  UINTN                   Level;\r
+\r
+  for (Level = 0; Level < 6; Level++) {\r
+    for (Index = 0; Index < Leaf[Level]; Index++) {\r
+      if (Ohc->IntervalList[Level][Index] != NULL) {\r
+        UsbHcFreeMem(Ohc->MemPool, Ohc->IntervalList[Level][Index], sizeof(ED_DESCRIPTOR));\r
+      }\r
+    }\r
+  }\r
+}\r
+/**\r
+\r
+  Release all OHCI used memory when OHCI going to quit\r
+\r
+  @Param  Ohc                   Device private data\r
+\r
+  @retval EFI_SUCCESS          Memory released\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciFreeIntTransferMemory (\r
+  IN USB_OHCI_HC_DEV           *Ohc\r
+  )\r
+{\r
+  //\r
+  // Free the Ed,Td,buffer that were created during transferring\r
+  //\r
+  OhciFreeDynamicIntMemory (Ohc);\r
+  //\r
+  // Free the Ed that were initilized during driver was starting\r
+  //\r
+  OhciFreeFixedIntMemory (Ohc);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciUrb.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciUrb.h
new file mode 100644 (file)
index 0000000..47851fd
--- /dev/null
@@ -0,0 +1,393 @@
+/** @file\r
+Provides some data struct used by OHCI controller driver.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#ifndef _OHCI_URB_H\r
+#define _OHCI_URB_H\r
+\r
+#include "Descriptor.h"\r
+\r
+\r
+//\r
+// Func List\r
+//\r
+\r
+\r
+/**\r
+\r
+  Create a TD\r
+\r
+  @Param  Ohc                   UHC private data\r
+\r
+  @retval                       TD structure pointer\r
+\r
+**/\r
+TD_DESCRIPTOR *\r
+OhciCreateTD (\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  );\r
+\r
+/**\r
+\r
+  Free a TD\r
+\r
+  @Param  Ohc                   UHC private data\r
+  @Param  Td                    Pointer to a TD to free\r
+\r
+  @retval  EFI_SUCCESS          TD freed\r
+\r
+**/\r
+EFI_STATUS\r
+OhciFreeTD (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN TD_DESCRIPTOR        *Td\r
+  );\r
+\r
+/**\r
+\r
+  Create a ED\r
+\r
+  @Param   Ohc                  Device private data\r
+\r
+  @retval  ED                   descriptor pointer\r
+\r
+**/\r
+ED_DESCRIPTOR *\r
+OhciCreateED (\r
+  USB_OHCI_HC_DEV          *Ohc\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Free a ED\r
+\r
+  @Param  Ohc                   UHC private data\r
+  @Param  Ed                    Pointer to a ED to free\r
+\r
+  @retval  EFI_SUCCESS          ED freed\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciFreeED (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN ED_DESCRIPTOR        *Ed\r
+  );\r
+\r
+/**\r
+\r
+  Free  ED\r
+\r
+  @Param  Ohc                    Device private data\r
+  @Param  Ed                     Pointer to a ED to free\r
+\r
+  @retval  EFI_SUCCESS           ED freed\r
+\r
+**/\r
+EFI_STATUS\r
+OhciFreeAllTDFromED (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN ED_DESCRIPTOR        *Ed\r
+  );\r
+\r
+/**\r
+\r
+  Find a working ED match the requirement\r
+\r
+  @Param  EdHead                Head of the ED list\r
+  @Param  DeviceAddress         Device address to search\r
+  @Param  EndPointNum           End point num to search\r
+  @Param  EdDir                 ED Direction to search\r
+\r
+  @retval   ED descriptor searched\r
+\r
+**/\r
+\r
+ED_DESCRIPTOR *\r
+OhciFindWorkingEd (\r
+  IN ED_DESCRIPTOR       *EdHead,\r
+  IN UINT8               DeviceAddress,\r
+  IN UINT8               EndPointNum,\r
+  IN UINT8               EdDir\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Initialize interrupt list.\r
+\r
+  @Param Ohc                    Device private data\r
+\r
+  @retval  EFI_SUCCESS          Initialization done\r
+\r
+**/\r
+EFI_STATUS\r
+OhciInitializeInterruptList (\r
+  USB_OHCI_HC_DEV          *Ohc\r
+  );\r
+\r
+/**\r
+\r
+  Attach an ED\r
+\r
+  @Param  Ed                    Ed to be attached\r
+  @Param  NewEd                 Ed to attach\r
+\r
+  @retval EFI_SUCCESS           NewEd attached to Ed\r
+  @retval EFI_INVALID_PARAMETER Ed is NULL\r
+\r
+**/\r
+EFI_STATUS\r
+OhciAttachED (\r
+  IN ED_DESCRIPTOR        *Ed,\r
+  IN ED_DESCRIPTOR        *NewEd\r
+  );\r
+\r
+/**\r
+\r
+  Count ED number on a ED chain\r
+\r
+  @Param  Ed                    Head of the ED chain\r
+\r
+  @retval                       ED number on the chain\r
+\r
+**/\r
+\r
+UINTN\r
+CountEdNum (\r
+  IN ED_DESCRIPTOR      *Ed\r
+  );\r
+\r
+/**\r
+\r
+  Find the minimal burn ED list on a specific depth level\r
+\r
+  @Param  Ohc                   Device private data\r
+  @Param  Depth                 Depth level\r
+\r
+  @retval                       ED list found\r
+\r
+**/\r
+\r
+ED_DESCRIPTOR *\r
+OhciFindMinInterruptEDList (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Depth\r
+  );\r
+\r
+/**\r
+\r
+  Attach an ED to an ED list\r
+\r
+  @Param  OHC                   UHC private data\r
+  @Param  ListType              Type of the ED list\r
+  @Param  Ed                    ED to attach\r
+  @Param  EdList                ED list to be attached\r
+\r
+  @retval  EFI_SUCCESS          ED attached to ED list\r
+\r
+**/\r
+ED_DESCRIPTOR *\r
+OhciAttachEDToList (\r
+  IN USB_OHCI_HC_DEV       *Ohc,\r
+  IN DESCRIPTOR_LIST_TYPE  ListType,\r
+  IN ED_DESCRIPTOR         *Ed,\r
+  IN ED_DESCRIPTOR         *EdList\r
+  );\r
+\r
+/**\r
+\r
+  Remove interrupt EDs that match requirement\r
+\r
+  @Param  Ohc                   UHC private data\r
+  @Param  IntEd                 The address of Interrupt endpoint\r
+\r
+  @retval  EFI_SUCCESS          EDs match requirement removed\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciFreeInterruptEdByEd (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN ED_DESCRIPTOR        *IntEd\r
+  );\r
+\r
+/**\r
+\r
+  Remove interrupt EDs that match requirement\r
+\r
+  @Param  Ohc                   UHC private data\r
+  @Param  FunctionAddress       Requirement on function address\r
+  @Param  EndPointNum           Requirement on end point number\r
+\r
+  @retval  EFI_SUCCESS          EDs match requirement removed\r
+\r
+**/\r
+EFI_STATUS\r
+OhciFreeInterruptEdByAddr (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT8                FunctionAddress,\r
+  IN UINT8                EndPointNum\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Link Td2 to the end of Td1\r
+\r
+  @Param Td1                    TD to be linked\r
+  @Param Td2                    TD to link\r
+\r
+  @retval EFI_SUCCESS           TD successfully linked\r
+  @retval EFI_INVALID_PARAMETER Td1 is NULL\r
+\r
+**/\r
+EFI_STATUS\r
+OhciLinkTD (\r
+  IN TD_DESCRIPTOR        *Td1,\r
+  IN TD_DESCRIPTOR        *Td2\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Attach TD list to ED\r
+\r
+  @Param  Ed                    ED which TD list attach on\r
+  @Param  HeadTd                Head of the TD list to attach\r
+\r
+  @retval  EFI_SUCCESS          TD list attached on the ED\r
+\r
+**/\r
+EFI_STATUS\r
+OhciAttachTDListToED (\r
+  IN ED_DESCRIPTOR        *Ed,\r
+  IN TD_DESCRIPTOR        *HeadTd\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Set value to ED specific field\r
+\r
+  @Param  Ed                    ED to be set\r
+  @Param  Field                 Field to be set\r
+  @Param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+EFI_STATUS\r
+OhciSetEDField (\r
+  IN ED_DESCRIPTOR        *Ed,\r
+  IN UINT32               Field,\r
+  IN UINT32               Value\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Get value from an ED's specific field\r
+\r
+  @Param  Ed                    ED pointer\r
+  @Param  Field                 Field to get value from\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+UINT32\r
+OhciGetEDField (\r
+  IN ED_DESCRIPTOR        *Ed,\r
+  IN UINT32               Field\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Set value to TD specific field\r
+\r
+  @Param  Td                    TD to be set\r
+  @Param  Field                 Field to be set\r
+  @Param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+EFI_STATUS\r
+OhciSetTDField (\r
+  IN TD_DESCRIPTOR        *Td,\r
+  IN UINT32               Field,\r
+  IN UINT32               Value\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Get value from ED specific field\r
+\r
+  @Param  Td                    TD pointer\r
+  @Param  Field                 Field to get value from\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetTDField (\r
+  IN TD_DESCRIPTOR      *Td,\r
+  IN UINT32             Field\r
+  );\r
+/**\r
+\r
+  Free the Ed,Td,buffer that were created during transferring\r
+\r
+  @Param  Ohc                   Device private data\r
+**/\r
+\r
+VOID\r
+OhciFreeDynamicIntMemory(\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  );\r
+\r
+/**\r
+\r
+  Free the Ed that were initilized during driver was starting,\r
+  those memory were used as interrupt ED head\r
+\r
+  @Param  Ohc                   Device private data\r
+\r
+\r
+**/\r
+VOID\r
+OhciFreeFixedIntMemory (\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  );\r
+/**\r
+\r
+  Release all OHCI used memory when OHCI going to quit\r
+\r
+  @Param  Ohc                   Device private data\r
+\r
+  @retval EFI_SUCCESS          Memory released\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciFreeIntTransferMemory (\r
+  IN USB_OHCI_HC_DEV           *Ohc\r
+  );\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/UsbHcMem.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/UsbHcMem.c
new file mode 100644 (file)
index 0000000..dd42938
--- /dev/null
@@ -0,0 +1,566 @@
+/** @file\r
+Routine procedures for memory allocate/free.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include "Ohci.h"\r
+\r
+\r
+/**\r
+  Allocate a block of memory to be used by the buffer pool.\r
+\r
+  @param  Pool           The buffer pool to allocate memory for.\r
+  @param  Pages          How many pages to allocate.\r
+\r
+  @return The allocated memory block or NULL if failed.\r
+\r
+**/\r
+USBHC_MEM_BLOCK *\r
+UsbHcAllocMemBlock (\r
+  IN  USBHC_MEM_POOL      *Pool,\r
+  IN  UINTN               Pages\r
+  )\r
+{\r
+  USBHC_MEM_BLOCK         *Block;\r
+  EFI_PCI_IO_PROTOCOL     *PciIo;\r
+  VOID                    *BufHost;\r
+  VOID                    *Mapping;\r
+  EFI_PHYSICAL_ADDRESS    MappedAddr;\r
+  UINTN                   Bytes;\r
+  EFI_STATUS              Status;\r
+\r
+  PciIo = Pool->PciIo;\r
+\r
+  Block = AllocateZeroPool (sizeof (USBHC_MEM_BLOCK));\r
+  if (Block == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // each bit in the bit array represents USBHC_MEM_UNIT\r
+  // bytes of memory in the memory block.\r
+  //\r
+  ASSERT (USBHC_MEM_UNIT * 8 <= EFI_PAGE_SIZE);\r
+\r
+  Block->BufLen   = EFI_PAGES_TO_SIZE (Pages);\r
+  Block->BitsLen  = Block->BufLen / (USBHC_MEM_UNIT * 8);\r
+  Block->Bits     = AllocateZeroPool (Block->BitsLen);\r
+\r
+  if (Block->Bits == NULL) {\r
+    gBS->FreePool (Block);\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Allocate the number of Pages of memory, then map it for\r
+  // bus master read and write.\r
+  //\r
+  Status = PciIo->AllocateBuffer (\r
+                    PciIo,\r
+                    AllocateAnyPages,\r
+                    EfiBootServicesData,\r
+                    Pages,\r
+                    &BufHost,\r
+                    0\r
+                    );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto FREE_BITARRAY;\r
+  }\r
+\r
+  Bytes = EFI_PAGES_TO_SIZE (Pages);\r
+  Status = PciIo->Map (\r
+                    PciIo,\r
+                    EfiPciIoOperationBusMasterCommonBuffer,\r
+                    BufHost,\r
+                    &Bytes,\r
+                    &MappedAddr,\r
+                    &Mapping\r
+                    );\r
+\r
+  if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (Pages))) {\r
+    goto FREE_BUFFER;\r
+  }\r
+\r
+  //\r
+  // Check whether the data structure used by the host controller\r
+  // should be restricted into the same 4G\r
+  //\r
+  if (Pool->Check4G && (Pool->Which4G != USB_HC_HIGH_32BIT (MappedAddr))) {\r
+    PciIo->Unmap (PciIo, Mapping);\r
+    goto FREE_BUFFER;\r
+  }\r
+\r
+  Block->BufHost  = BufHost;\r
+  Block->Buf      = (UINT8 *) ((UINTN) MappedAddr);\r
+  Block->Mapping  = Mapping;\r
+\r
+  return Block;\r
+\r
+FREE_BUFFER:\r
+  PciIo->FreeBuffer (PciIo, Pages, BufHost);\r
+\r
+FREE_BITARRAY:\r
+  gBS->FreePool (Block->Bits);\r
+  gBS->FreePool (Block);\r
+  return NULL;\r
+}\r
+\r
+\r
+/**\r
+  Free the memory block from the memory pool.\r
+\r
+  @param  Pool           The memory pool to free the block from.\r
+  @param  Block          The memory block to free.\r
+\r
+**/\r
+VOID\r
+UsbHcFreeMemBlock (\r
+  IN USBHC_MEM_POOL       *Pool,\r
+  IN USBHC_MEM_BLOCK      *Block\r
+  )\r
+{\r
+  EFI_PCI_IO_PROTOCOL     *PciIo;\r
+\r
+  ASSERT ((Pool != NULL) && (Block != NULL));\r
+\r
+  PciIo = Pool->PciIo;\r
+\r
+  //\r
+  // Unmap the common buffer then free the structures\r
+  //\r
+  PciIo->Unmap (PciIo, Block->Mapping);\r
+  PciIo->FreeBuffer (PciIo, EFI_SIZE_TO_PAGES (Block->BufLen), Block->BufHost);\r
+\r
+  gBS->FreePool (Block->Bits);\r
+  gBS->FreePool (Block);\r
+}\r
+\r
+\r
+/**\r
+  Alloc some memory from the block.\r
+\r
+  @param  Block          The memory block to allocate memory from.\r
+  @param  Units          Number of memory units to allocate.\r
+\r
+  @return The pointer to the allocated memory. If couldn't allocate the needed memory,\r
+          the return value is NULL.\r
+\r
+**/\r
+VOID *\r
+UsbHcAllocMemFromBlock (\r
+  IN  USBHC_MEM_BLOCK     *Block,\r
+  IN  UINTN               Units\r
+  )\r
+{\r
+  UINTN                   Byte;\r
+  UINT8                   Bit;\r
+  UINTN                   StartByte;\r
+  UINT8                   StartBit;\r
+  UINTN                   Available;\r
+  UINTN                   Count;\r
+\r
+  ASSERT ((Block != 0) && (Units != 0));\r
+\r
+  StartByte  = 0;\r
+  StartBit   = 0;\r
+  Available  = 0;\r
+\r
+  for (Byte = 0, Bit = 0; Byte < Block->BitsLen;) {\r
+    //\r
+    // If current bit is zero, the corresponding memory unit is\r
+    // available, otherwise we need to restart our searching.\r
+    // Available counts the consective number of zero bit.\r
+    //\r
+    if (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit)) {\r
+      Available++;\r
+\r
+      if (Available >= Units) {\r
+        break;\r
+      }\r
+\r
+      NEXT_BIT (Byte, Bit);\r
+\r
+    } else {\r
+      NEXT_BIT (Byte, Bit);\r
+\r
+      Available  = 0;\r
+      StartByte  = Byte;\r
+      StartBit   = Bit;\r
+    }\r
+  }\r
+\r
+  if (Available < Units) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Mark the memory as allocated\r
+  //\r
+  Byte  = StartByte;\r
+  Bit   = StartBit;\r
+\r
+  for (Count = 0; Count < Units; Count++) {\r
+    ASSERT (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));\r
+\r
+    Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] | USB_HC_BIT (Bit));\r
+    NEXT_BIT (Byte, Bit);\r
+  }\r
+\r
+  return Block->BufHost + (StartByte * 8 + StartBit) * USBHC_MEM_UNIT;\r
+}\r
+\r
+/**\r
+  Calculate the corresponding pci bus address according to the Mem parameter.\r
+\r
+  @param  Pool           The memory pool of the host controller.\r
+  @param  Mem            The pointer to host memory.\r
+  @param  Size           The size of the memory region.\r
+\r
+  @return the pci memory address\r
+**/\r
+EFI_PHYSICAL_ADDRESS\r
+UsbHcGetPciAddressForHostMem (\r
+  IN USBHC_MEM_POOL       *Pool,\r
+  IN VOID                 *Mem,\r
+  IN UINTN                Size\r
+  )\r
+{\r
+  USBHC_MEM_BLOCK         *Head;\r
+  USBHC_MEM_BLOCK         *Block;\r
+  UINTN                   AllocSize;\r
+  EFI_PHYSICAL_ADDRESS    PhyAddr;\r
+  UINTN                   Offset;\r
+\r
+  Head      = Pool->Head;\r
+  AllocSize = USBHC_MEM_ROUND (Size);\r
+\r
+  if (Mem == NULL) {\r
+    return 0;\r
+  }\r
+\r
+  for (Block = Head; Block != NULL; Block = Block->Next) {\r
+    //\r
+    // scan the memory block list for the memory block that\r
+    // completely contains the allocated memory.\r
+    //\r
+    if ((Block->BufHost <= (UINT8 *) Mem) && (((UINT8 *) Mem + AllocSize) <= (Block->BufHost + Block->BufLen))) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  ASSERT ((Block != NULL));\r
+  //\r
+  // calculate the pci memory address for host memory address.\r
+  //\r
+  Offset = (UINT8 *)Mem - Block->BufHost;\r
+  PhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN) (Block->Buf + Offset);\r
+  return PhyAddr;\r
+}\r
+\r
+\r
+/**\r
+  Insert the memory block to the pool's list of the blocks.\r
+\r
+  @param  Head           The head of the memory pool's block list.\r
+  @param  Block          The memory block to insert.\r
+\r
+**/\r
+VOID\r
+UsbHcInsertMemBlockToPool (\r
+  IN USBHC_MEM_BLOCK      *Head,\r
+  IN USBHC_MEM_BLOCK      *Block\r
+  )\r
+{\r
+  ASSERT ((Head != NULL) && (Block != NULL));\r
+  Block->Next = Head->Next;\r
+  Head->Next  = Block;\r
+}\r
+\r
+\r
+/**\r
+  Is the memory block empty?\r
+\r
+  @param  Block   The memory block to check.\r
+\r
+  @retval TRUE    The memory block is empty.\r
+  @retval FALSE   The memory block isn't empty.\r
+\r
+**/\r
+BOOLEAN\r
+UsbHcIsMemBlockEmpty (\r
+  IN USBHC_MEM_BLOCK     *Block\r
+  )\r
+{\r
+  UINTN                   Index;\r
+\r
+  for (Index = 0; Index < Block->BitsLen; Index++) {\r
+    if (Block->Bits[Index] != 0) {\r
+      return FALSE;\r
+    }\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+\r
+/**\r
+  Unlink the memory block from the pool's list.\r
+\r
+  @param  Head           The block list head of the memory's pool.\r
+  @param  BlockToUnlink  The memory block to unlink.\r
+\r
+**/\r
+VOID\r
+UsbHcUnlinkMemBlock (\r
+  IN USBHC_MEM_BLOCK      *Head,\r
+  IN USBHC_MEM_BLOCK      *BlockToUnlink\r
+  )\r
+{\r
+  USBHC_MEM_BLOCK         *Block;\r
+\r
+  ASSERT ((Head != NULL) && (BlockToUnlink != NULL));\r
+\r
+  for (Block = Head; Block != NULL; Block = Block->Next) {\r
+    if (Block->Next == BlockToUnlink) {\r
+      Block->Next         = BlockToUnlink->Next;\r
+      BlockToUnlink->Next = NULL;\r
+      break;\r
+    }\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Initialize the memory management pool for the host controller.\r
+\r
+  @param  PciIo                The PciIo that can be used to access the host controller.\r
+  @param  Check4G              Whether the host controller requires allocated memory\r
+                               from one 4G address space.\r
+  @param  Which4G              The 4G memory area each memory allocated should be from.\r
+\r
+  @retval EFI_SUCCESS          The memory pool is initialized.\r
+  @retval EFI_OUT_OF_RESOURCE  Fail to init the memory pool.\r
+\r
+**/\r
+USBHC_MEM_POOL *\r
+UsbHcInitMemPool (\r
+  IN EFI_PCI_IO_PROTOCOL  *PciIo,\r
+  IN BOOLEAN              Check4G,\r
+  IN UINT32               Which4G\r
+  )\r
+{\r
+  USBHC_MEM_POOL          *Pool;\r
+\r
+  Pool = AllocatePool (sizeof (USBHC_MEM_POOL));\r
+\r
+  if (Pool == NULL) {\r
+    return Pool;\r
+  }\r
+\r
+  Pool->PciIo   = PciIo;\r
+  Pool->Check4G = Check4G;\r
+  Pool->Which4G = Which4G;\r
+  Pool->Head    = UsbHcAllocMemBlock (Pool, USBHC_MEM_DEFAULT_PAGES);\r
+\r
+  if (Pool->Head == NULL) {\r
+    gBS->FreePool (Pool);\r
+    Pool = NULL;\r
+  }\r
+\r
+  return Pool;\r
+}\r
+\r
+\r
+/**\r
+  Release the memory management pool.\r
+\r
+  @param  Pool              The USB memory pool to free.\r
+\r
+  @retval EFI_SUCCESS       The memory pool is freed.\r
+  @retval EFI_DEVICE_ERROR  Failed to free the memory pool.\r
+\r
+**/\r
+EFI_STATUS\r
+UsbHcFreeMemPool (\r
+  IN USBHC_MEM_POOL       *Pool\r
+  )\r
+{\r
+  USBHC_MEM_BLOCK *Block;\r
+\r
+  ASSERT (Pool->Head != NULL);\r
+\r
+  //\r
+  // Unlink all the memory blocks from the pool, then free them.\r
+  // UsbHcUnlinkMemBlock can't be used to unlink and free the\r
+  // first block.\r
+  //\r
+  for (Block = Pool->Head->Next; Block != NULL; Block = Pool->Head->Next) {\r
+    UsbHcUnlinkMemBlock (Pool->Head, Block);\r
+    UsbHcFreeMemBlock (Pool, Block);\r
+  }\r
+\r
+  UsbHcFreeMemBlock (Pool, Pool->Head);\r
+  gBS->FreePool (Pool);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Allocate some memory from the host controller's memory pool\r
+  which can be used to communicate with host controller.\r
+\r
+  @param  Pool           The host controller's memory pool.\r
+  @param  Size           Size of the memory to allocate.\r
+\r
+  @return The allocated memory or NULL.\r
+\r
+**/\r
+VOID *\r
+UsbHcAllocateMem (\r
+  IN  USBHC_MEM_POOL      *Pool,\r
+  IN  UINTN               Size\r
+  )\r
+{\r
+  USBHC_MEM_BLOCK         *Head;\r
+  USBHC_MEM_BLOCK         *Block;\r
+  USBHC_MEM_BLOCK         *NewBlock;\r
+  VOID                    *Mem;\r
+  UINTN                   AllocSize;\r
+  UINTN                   Pages;\r
+\r
+  Mem       = NULL;\r
+  AllocSize = USBHC_MEM_ROUND (Size);\r
+  Head      = Pool->Head;\r
+  ASSERT (Head != NULL);\r
+\r
+  //\r
+  // First check whether current memory blocks can satisfy the allocation.\r
+  //\r
+  for (Block = Head; Block != NULL; Block = Block->Next) {\r
+    Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT);\r
+\r
+    if (Mem != NULL) {\r
+      ZeroMem (Mem, Size);\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (Mem != NULL) {\r
+    return Mem;\r
+  }\r
+\r
+  //\r
+  // Create a new memory block if there is not enough memory\r
+  // in the pool. If the allocation size is larger than the\r
+  // default page number, just allocate a large enough memory\r
+  // block. Otherwise allocate default pages.\r
+  //\r
+  if (AllocSize > EFI_PAGES_TO_SIZE (USBHC_MEM_DEFAULT_PAGES)) {\r
+    Pages = EFI_SIZE_TO_PAGES (AllocSize) + 1;\r
+  } else {\r
+    Pages = USBHC_MEM_DEFAULT_PAGES;\r
+  }\r
+\r
+  NewBlock = UsbHcAllocMemBlock (Pool, Pages);\r
+\r
+  if (NewBlock == NULL) {\r
+    DEBUG ((EFI_D_INFO, "UsbHcAllocateMem: failed to allocate block\n"));\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Add the new memory block to the pool, then allocate memory from it\r
+  //\r
+  UsbHcInsertMemBlockToPool (Head, NewBlock);\r
+  Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT);\r
+\r
+  if (Mem != NULL) {\r
+    ZeroMem (Mem, Size);\r
+  }\r
+\r
+  return Mem;\r
+}\r
+\r
+\r
+/**\r
+  Free the allocated memory back to the memory pool.\r
+\r
+  @param  Pool           The memory pool of the host controller.\r
+  @param  Mem            The memory to free.\r
+  @param  Size           The size of the memory to free.\r
+\r
+**/\r
+VOID\r
+UsbHcFreeMem (\r
+  IN USBHC_MEM_POOL       *Pool,\r
+  IN VOID                 *Mem,\r
+  IN UINTN                Size\r
+  )\r
+{\r
+  USBHC_MEM_BLOCK         *Head;\r
+  USBHC_MEM_BLOCK         *Block;\r
+  UINT8                   *ToFree;\r
+  UINTN                   AllocSize;\r
+  UINTN                   Byte;\r
+  UINTN                   Bit;\r
+  UINTN                   Count;\r
+\r
+  Head      = Pool->Head;\r
+  AllocSize = USBHC_MEM_ROUND (Size);\r
+  ToFree    = (UINT8 *) Mem;\r
+\r
+  for (Block = Head; Block != NULL; Block = Block->Next) {\r
+    //\r
+    // scan the memory block list for the memory block that\r
+    // completely contains the memory to free.\r
+    //\r
+    if ((Block->BufHost <= ToFree) && ((ToFree + AllocSize) <= (Block->BufHost + Block->BufLen))) {\r
+      //\r
+      // compute the start byte and bit in the bit array\r
+      //\r
+      Byte  = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) / 8;\r
+      Bit   = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) % 8;\r
+\r
+      //\r
+      // reset associated bits in bit arry\r
+      //\r
+      for (Count = 0; Count < (AllocSize / USBHC_MEM_UNIT); Count++) {\r
+        ASSERT (USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));\r
+\r
+        Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] ^ USB_HC_BIT (Bit));\r
+        NEXT_BIT (Byte, Bit);\r
+      }\r
+\r
+      break;\r
+    }\r
+  }\r
+\r
+  //\r
+  // If Block == NULL, it means that the current memory isn't\r
+  // in the host controller's pool. This is critical because\r
+  // the caller has passed in a wrong memory point\r
+  //\r
+  ASSERT (Block != NULL);\r
+\r
+  //\r
+  // Release the current memory block if it is empty and not the head\r
+  //\r
+  if ((Block != Head) && UsbHcIsMemBlockEmpty (Block)) {\r
+    UsbHcUnlinkMemBlock (Head, Block);\r
+    UsbHcFreeMemBlock (Pool, Block);\r
+  }\r
+\r
+  return ;\r
+}\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/UsbHcMem.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/UsbHcMem.h
new file mode 100644 (file)
index 0000000..e16425e
--- /dev/null
@@ -0,0 +1,158 @@
+/** @file\r
+This file contains the definination for host controller memory\r
+management routines.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _USB_HC_MEM_H_\r
+#define _USB_HC_MEM_H_\r
+\r
+#define USB_HC_BIT(a)                  ((UINTN)(1 << (a)))\r
+\r
+#define USB_HC_BIT_IS_SET(Data, Bit)   \\r
+          ((BOOLEAN)(((Data) & USB_HC_BIT(Bit)) == USB_HC_BIT(Bit)))\r
+\r
+#define USB_HC_HIGH_32BIT(Addr64)    \\r
+          ((UINT32)(RShiftU64((UINTN)(Addr64), 32) & 0XFFFFFFFF))\r
+\r
+typedef struct _USBHC_MEM_BLOCK USBHC_MEM_BLOCK;\r
+struct _USBHC_MEM_BLOCK {\r
+  UINT8                   *Bits;    // Bit array to record which unit is allocated\r
+  UINTN                   BitsLen;\r
+  UINT8                   *Buf;\r
+  UINT8                   *BufHost;\r
+  UINTN                   BufLen;   // Memory size in bytes\r
+  VOID                    *Mapping;\r
+  USBHC_MEM_BLOCK         *Next;\r
+};\r
+\r
+//\r
+// USBHC_MEM_POOL is used to manage the memory used by USB\r
+// host controller. EHCI requires the control memory and transfer\r
+// data to be on the same 4G memory.\r
+//\r
+typedef struct _USBHC_MEM_POOL {\r
+  EFI_PCI_IO_PROTOCOL     *PciIo;\r
+  BOOLEAN                 Check4G;\r
+  UINT32                  Which4G;\r
+  USBHC_MEM_BLOCK         *Head;\r
+} USBHC_MEM_POOL;\r
+\r
+//\r
+// Memory allocation unit, must be 2^n, n>4\r
+//\r
+#define USBHC_MEM_UNIT           64\r
+\r
+#define USBHC_MEM_UNIT_MASK      (USBHC_MEM_UNIT - 1)\r
+#define USBHC_MEM_DEFAULT_PAGES  16\r
+\r
+#define USBHC_MEM_ROUND(Len)  (((Len) + USBHC_MEM_UNIT_MASK) & (~USBHC_MEM_UNIT_MASK))\r
+\r
+//\r
+// Advance the byte and bit to the next bit, adjust byte accordingly.\r
+//\r
+#define NEXT_BIT(Byte, Bit)   \\r
+          do {                \\r
+            (Bit)++;          \\r
+            if ((Bit) > 7) {  \\r
+              (Byte)++;       \\r
+              (Bit) = 0;      \\r
+            }                 \\r
+          } while (0)\r
+\r
+\r
+\r
+/**\r
+  Initialize the memory management pool for the host controller.\r
+\r
+  @param  PciIo               The PciIo that can be used to access the host controller.\r
+  @param  Check4G             Whether the host controller requires allocated memory\r
+                              from one 4G address space.\r
+  @param  Which4G             The 4G memory area each memory allocated should be from.\r
+\r
+  @retval EFI_SUCCESS         The memory pool is initialized.\r
+  @retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.\r
+\r
+**/\r
+USBHC_MEM_POOL *\r
+UsbHcInitMemPool (\r
+  IN EFI_PCI_IO_PROTOCOL  *PciIo,\r
+  IN BOOLEAN              Check4G,\r
+  IN UINT32               Which4G\r
+  );\r
+\r
+\r
+/**\r
+  Release the memory management pool.\r
+\r
+  @param   Pool               The USB memory pool to free.\r
+\r
+  @retval EFI_SUCCESS       The memory pool is freed.\r
+  @retval EFI_DEVICE_ERROR  Failed to free the memory pool.\r
+\r
+**/\r
+EFI_STATUS\r
+UsbHcFreeMemPool (\r
+  IN USBHC_MEM_POOL       *Pool\r
+  );\r
+\r
+\r
+/**\r
+  Allocate some memory from the host controller's memory pool\r
+  which can be used to communicate with host controller.\r
+\r
+  @param  Pool  The host controller's memory pool.\r
+  @param  Size  Size of the memory to allocate.\r
+\r
+  @return The allocated memory or NULL.\r
+\r
+**/\r
+VOID *\r
+UsbHcAllocateMem (\r
+  IN  USBHC_MEM_POOL      *Pool,\r
+  IN  UINTN               Size\r
+  );\r
+\r
+\r
+/**\r
+  Free the allocated memory back to the memory pool.\r
+\r
+  @param  Pool  The memory pool of the host controller.\r
+  @param  Mem   The memory to free.\r
+  @param  Size  The size of the memory to free.\r
+\r
+**/\r
+VOID\r
+UsbHcFreeMem (\r
+  IN USBHC_MEM_POOL       *Pool,\r
+  IN VOID                 *Mem,\r
+  IN UINTN                Size\r
+  );\r
+\r
+/**\r
+  Calculate the corresponding pci bus address according to the Mem parameter.\r
+\r
+  @param  Pool           The memory pool of the host controller.\r
+  @param  Mem            The pointer to host memory.\r
+  @param  Size           The size of the memory region.\r
+\r
+  @return the pci memory address\r
+**/\r
+EFI_PHYSICAL_ADDRESS\r
+UsbHcGetPciAddressForHostMem (\r
+  IN USBHC_MEM_POOL       *Pool,\r
+  IN VOID                 *Mem,\r
+  IN UINTN                Size\r
+  );\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/Descriptor.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/Descriptor.h
new file mode 100644 (file)
index 0000000..e7cc319
--- /dev/null
@@ -0,0 +1,137 @@
+/** @file\r
+This file contains the descriptor definination of OHCI spec\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+\r
+#ifndef _DESCRIPTOR_H\r
+#define _DESCRIPTOR_H\r
+\r
+#define ED_FUNC_ADD     0x0001\r
+#define ED_ENDPT_NUM    0x0002\r
+#define ED_DIR          0x0004\r
+#define ED_SPEED        0x0008\r
+#define ED_SKIP         0x0010\r
+#define ED_FORMAT       0x0020\r
+#define ED_MAX_PACKET   0x0040\r
+#define ED_TDTAIL_PTR   0x0080\r
+#define ED_HALTED       0x0100\r
+#define ED_DTTOGGLE     0x0200\r
+#define ED_TDHEAD_PTR   0x0400\r
+#define ED_NEXT_EDPTR   0x0800\r
+#define ED_PDATA        0x1000\r
+#define ED_ZERO         0x2000\r
+\r
+#define TD_BUFFER_ROUND     0x0001\r
+#define TD_DIR_PID          0x0002\r
+#define TD_DELAY_INT        0x0004\r
+#define TD_DT_TOGGLE        0x0008\r
+#define TD_ERROR_CNT        0x0010\r
+#define TD_COND_CODE        0x0020\r
+#define TD_CURR_BUFFER_PTR  0x0040\r
+#define TD_NEXT_PTR         0x0080\r
+#define TD_BUFFER_END_PTR   0x0100\r
+#define TD_PDATA            0x0200\r
+\r
+#define ED_FROM_TD_DIR        0x0\r
+#define ED_OUT_DIR            0x1\r
+#define ED_IN_DIR             0x2\r
+#define ED_FROM_TD_ALSO_DIR   0x3\r
+\r
+#define TD_SETUP_PID          0x00\r
+#define TD_OUT_PID            0x01\r
+#define TD_IN_PID             0x02\r
+#define TD_NODATA_PID         0x03\r
+\r
+#define HI_SPEED              0\r
+#define LO_SPEED              1\r
+\r
+#define TD_NO_ERROR           0x00\r
+#define TD_CRC_ERROR          0x01\r
+#define TD_BITSTUFFING_ERROR  0x02\r
+#define TD_TOGGLE_ERROR       0x03\r
+#define TD_DEVICE_STALL       0x04\r
+#define TD_NO_RESPONSE        0x05\r
+#define TD_PIDCHK_FAIL        0x06\r
+#define TD_PID_UNEXPECTED     0x07\r
+#define TD_DATA_OVERRUN       0x08\r
+#define TD_DATA_UNDERRUN      0x09\r
+#define TD_BUFFER_OVERRUN     0x0C\r
+#define TD_BUFFER_UNDERRUN    0x0D\r
+#define TD_TOBE_PROCESSED     0x0E\r
+#define TD_TOBE_PROCESSED_2   0x0F\r
+\r
+#define TD_NO_DELAY           0x7\r
+\r
+#define TD_INT                0x1\r
+#define TD_CTL                0x2\r
+#define TD_BLK                0x3\r
+\r
+typedef struct {\r
+  UINT32 Reserved:18;\r
+  UINT32 BufferRounding:1;\r
+  UINT32 DirPID:2;\r
+  UINT32 DelayInterrupt:3;\r
+  UINT32 DataToggle:2;\r
+  UINT32 ErrorCount:2;\r
+  UINT32 ConditionCode:4;\r
+} TD_DESCRIPTOR_WORD0;\r
+\r
+typedef struct _TD_DESCRIPTOR {\r
+  TD_DESCRIPTOR_WORD0     Word0;\r
+  VOID                    *CurrBufferPointer;\r
+  struct _TD_DESCRIPTOR   *NextTD;\r
+  VOID                    *BufferEndPointer;\r
+  struct _TD_DESCRIPTOR   *NextTDPointer;\r
+  UINT8                   *DataBuffer;\r
+  UINT32                  ActualSendLength;\r
+} TD_DESCRIPTOR;\r
+\r
+typedef struct {\r
+  UINT32 FunctionAddress:7;\r
+  UINT32 EndPointNum:4;\r
+  UINT32 Direction:2;\r
+  UINT32 Speed:1;\r
+  UINT32 Skip:1;\r
+  UINT32 Format:1;\r
+  UINT32 MaxPacketSize:11;\r
+  UINT32 FreeSpace:5;\r
+} ED_DESCRIPTOR_WORD0;\r
+\r
+typedef struct {\r
+  UINT32 Halted:1;\r
+  UINT32 ToggleCarry:1;\r
+  UINT32 Zero:2;\r
+  UINT32 TdHeadPointer:28;\r
+} ED_DESCRIPTOR_WORD2;\r
+\r
+typedef struct _ED_DESCRIPTOR {\r
+  ED_DESCRIPTOR_WORD0     Word0;\r
+  TD_DESCRIPTOR           *TdTailPointer;\r
+  ED_DESCRIPTOR_WORD2     Word2;\r
+  struct _ED_DESCRIPTOR   *NextED;\r
+} ED_DESCRIPTOR;\r
+\r
+#define TD_PTR(p)            ((TD_DESCRIPTOR *)((p) << 4))\r
+#define ED_PTR(p)            ((ED_DESCRIPTOR *)((p) << 4))\r
+#define RIGHT_SHIFT_4(p)     ((UINT32)(p) >> 4)\r
+\r
+typedef enum {\r
+  CONTROL_LIST,\r
+  BULK_LIST,\r
+  INTERRUPT_LIST,\r
+  ISOCHRONOUS_LIST\r
+} DESCRIPTOR_LIST_TYPE;\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhcPeim.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhcPeim.c
new file mode 100644 (file)
index 0000000..c38d496
--- /dev/null
@@ -0,0 +1,1402 @@
+/** @file\r
+This file contains the implementation of Usb Hc Protocol.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include "OhcPeim.h"\r
+\r
+/**\r
+  Submits control transfer to a target USB device.\r
+\r
+  @param  PeiServices            The pointer of EFI_PEI_SERVICES.\r
+  @param  This                   The pointer of PEI_USB_HOST_CONTROLLER_PPI.\r
+  @param  DeviceAddress          The target device address.\r
+  @param  DeviceSpeed            Target device speed.\r
+  @param  MaximumPacketLength    Maximum packet size the default control transfer\r
+                                 endpoint is capable of sending or receiving.\r
+  @param  Request                USB device request to send.\r
+  @param  TransferDirection      Specifies the data direction for the data stage.\r
+  @param  Data                   Data buffer to be transmitted or received from USB device.\r
+  @param  DataLength             The size (in bytes) of the data buffer.\r
+  @param  TimeOut                Indicates the maximum timeout, in millisecond.\r
+  @param  TransferResult         Return the result of this control transfer.\r
+\r
+  @retval EFI_SUCCESS            Transfer was completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES   The transfer failed due to lack of resources.\r
+  @retval EFI_INVALID_PARAMETER  Some parameters are invalid.\r
+  @retval EFI_TIMEOUT            Transfer failed due to timeout.\r
+  @retval EFI_DEVICE_ERROR       Transfer failed due to host controller or device error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OhciControlTransfer (\r
+  IN  EFI_PEI_SERVICES             **PeiServices,\r
+  IN  PEI_USB_HOST_CONTROLLER_PPI  *This,\r
+  IN  UINT8                        DeviceAddress,\r
+  IN  UINT8                        DeviceSpeed,\r
+  IN  UINT8                        MaxPacketLength,\r
+  IN  EFI_USB_DEVICE_REQUEST       *Request,\r
+  IN  EFI_USB_DATA_DIRECTION       TransferDirection,\r
+  IN  OUT VOID                     *Data,\r
+  IN  OUT UINTN                    *DataLength,\r
+  IN  UINTN                        TimeOut,\r
+  OUT UINT32                       *TransferResult\r
+  )\r
+{\r
+  USB_OHCI_HC_DEV               *Ohc;\r
+  ED_DESCRIPTOR                 *Ed;\r
+  TD_DESCRIPTOR                 *HeadTd;\r
+  TD_DESCRIPTOR                 *SetupTd;\r
+  TD_DESCRIPTOR                 *DataTd;\r
+  TD_DESCRIPTOR                 *StatusTd;\r
+  TD_DESCRIPTOR                 *EmptyTd;\r
+  EFI_STATUS                    Status;\r
+  UINT32                        DataPidDir;\r
+  UINT32                        StatusPidDir;\r
+  UINTN                         TimeCount;\r
+  UINT32                        ErrorCode;\r
+\r
+  UINTN                         ActualSendLength;\r
+  UINTN                         LeftLength;\r
+  UINT8                         DataToggle;\r
+\r
+  UINTN                         ReqMapLength = 0;\r
+  EFI_PHYSICAL_ADDRESS          ReqMapPhyAddr = 0;\r
+\r
+  UINTN                         DataMapLength = 0;\r
+  EFI_PHYSICAL_ADDRESS          DataMapPhyAddr = 0;\r
+\r
+  HeadTd = NULL;\r
+  DataTd = NULL;\r
+\r
+  if ((TransferDirection != EfiUsbDataOut && TransferDirection != EfiUsbDataIn &&\r
+       TransferDirection != EfiUsbNoData) ||\r
+      Request == NULL || DataLength == NULL || TransferResult == NULL ||\r
+      (TransferDirection == EfiUsbNoData && (*DataLength != 0 || Data != NULL)) ||\r
+      (TransferDirection != EfiUsbNoData && (*DataLength == 0 || Data == NULL)) ||\r
+      (DeviceSpeed != EFI_USB_SPEED_LOW && DeviceSpeed != EFI_USB_SPEED_FULL) ||\r
+      (MaxPacketLength != 8 && MaxPacketLength != 16 &&\r
+       MaxPacketLength != 32 && MaxPacketLength != 64)) {\r
+    DEBUG ((EFI_D_INFO, "OhciControlTransfer: EFI_INVALID_PARAMETER\n"));\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (*DataLength > MAX_BYTES_PER_TD) {\r
+    DEBUG ((EFI_D_ERROR, "OhciControlTransfer: Request data size is too large\n"));\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS(This);\r
+\r
+  if (TransferDirection == EfiUsbDataIn) {\r
+    DataPidDir = TD_IN_PID;\r
+    StatusPidDir = TD_OUT_PID;\r
+  } else {\r
+    DataPidDir = TD_OUT_PID;\r
+    StatusPidDir = TD_IN_PID;\r
+  }\r
+\r
+  OhciSetHcControl (Ohc, CONTROL_ENABLE, 0);\r
+  if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 0) {\r
+    MicroSecondDelay (HC_1_MILLISECOND);\r
+    if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 0) {\r
+      *TransferResult = EFI_USB_ERR_SYSTEM;\r
+      DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to disable CONTROL transfer\n"));\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+  OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);\r
+  Ed = OhciCreateED (Ohc);\r
+  if (Ed == NULL) {\r
+    DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate ED buffer\n"));\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  OhciSetEDField (Ed, ED_SKIP, 1);\r
+  OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);\r
+  OhciSetEDField (Ed, ED_ENDPT_NUM, 0);\r
+  OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);\r
+  OhciSetEDField (Ed, ED_SPEED, DeviceSpeed);\r
+  OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0);\r
+  OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);\r
+  OhciSetEDField (Ed, ED_PDATA, 0);\r
+  OhciSetEDField (Ed, ED_ZERO, 0);\r
+  OhciSetEDField (Ed, ED_TDHEAD_PTR, (UINT32) NULL);\r
+  OhciSetEDField (Ed, ED_TDTAIL_PTR, (UINT32) NULL);\r
+  OhciSetEDField (Ed, ED_NEXT_EDPTR, (UINT32) NULL);\r
+  OhciAttachEDToList (Ohc, CONTROL_LIST, Ed, NULL);\r
+  //\r
+  // Setup Stage\r
+  //\r
+  if(Request != NULL) {\r
+    ReqMapLength = sizeof(EFI_USB_DEVICE_REQUEST);\r
+    ReqMapPhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Request;\r
+  }\r
+  SetupTd = OhciCreateTD (Ohc);\r
+  if (SetupTd == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Setup TD buffer\n"));\r
+    goto FREE_ED_BUFF;\r
+  }\r
+  HeadTd = SetupTd;\r
+  OhciSetTDField (SetupTd, TD_PDATA, 0);\r
+  OhciSetTDField (SetupTd, TD_BUFFER_ROUND, 1);\r
+  OhciSetTDField (SetupTd, TD_DIR_PID, TD_SETUP_PID);\r
+  OhciSetTDField (SetupTd, TD_DELAY_INT, TD_NO_DELAY);\r
+  OhciSetTDField (SetupTd, TD_DT_TOGGLE, 2);\r
+  OhciSetTDField (SetupTd, TD_ERROR_CNT, 0);\r
+  OhciSetTDField (SetupTd, TD_COND_CODE, TD_TOBE_PROCESSED);\r
+  OhciSetTDField (SetupTd, TD_CURR_BUFFER_PTR, (UINTN)ReqMapPhyAddr);\r
+  OhciSetTDField (SetupTd, TD_NEXT_PTR, (UINT32) NULL);\r
+  OhciSetTDField (SetupTd, TD_BUFFER_END_PTR, (UINTN)ReqMapPhyAddr + sizeof (EFI_USB_DEVICE_REQUEST) - 1);\r
+  SetupTd->ActualSendLength = 0;\r
+  SetupTd->DataBuffer = NULL;\r
+  SetupTd->NextTDPointer = NULL;\r
+\r
+  DataMapLength = *DataLength;\r
+  if ((Data != NULL) && (DataMapLength != 0)) {\r
+    DataMapPhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Data;\r
+  }\r
+  //\r
+  //Data Stage\r
+  //\r
+  LeftLength = DataMapLength;\r
+  ActualSendLength = DataMapLength;\r
+  DataToggle = 1;\r
+  while (LeftLength > 0) {\r
+    ActualSendLength = LeftLength;\r
+    if (LeftLength > MaxPacketLength) {\r
+      ActualSendLength = MaxPacketLength;\r
+    }\r
+    DataTd = OhciCreateTD (Ohc);\r
+    if (DataTd == NULL) {\r
+      DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Data TD buffer\n"));\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto FREE_TD_BUFF;\r
+    }\r
+    OhciSetTDField (DataTd, TD_PDATA, 0);\r
+    OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);\r
+    OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);\r
+    OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);\r
+    OhciSetTDField (DataTd, TD_DT_TOGGLE, DataToggle);\r
+    OhciSetTDField (DataTd, TD_ERROR_CNT, 0);\r
+    OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);\r
+    OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) DataMapPhyAddr);\r
+    OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32) DataMapPhyAddr + ActualSendLength - 1);\r
+    OhciSetTDField (DataTd, TD_NEXT_PTR, (UINT32) NULL);\r
+    DataTd->ActualSendLength = ActualSendLength;\r
+    DataTd->DataBuffer = (UINT8 *)(UINTN)DataMapPhyAddr;\r
+    DataTd->NextTDPointer = 0;\r
+    OhciLinkTD (HeadTd, DataTd);\r
+    DataToggle ^= 1;\r
+    DataMapPhyAddr += ActualSendLength;\r
+    LeftLength -= ActualSendLength;\r
+  }\r
+  //\r
+  // Status Stage\r
+  //\r
+  StatusTd = OhciCreateTD (Ohc);\r
+  if (StatusTd == NULL) {\r
+    DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Status TD buffer\n"));\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto FREE_TD_BUFF;\r
+  }\r
+  OhciSetTDField (StatusTd, TD_PDATA, 0);\r
+  OhciSetTDField (StatusTd, TD_BUFFER_ROUND, 1);\r
+  OhciSetTDField (StatusTd, TD_DIR_PID, StatusPidDir);\r
+  OhciSetTDField (StatusTd, TD_DELAY_INT, 7);\r
+  OhciSetTDField (StatusTd, TD_DT_TOGGLE, 3);\r
+  OhciSetTDField (StatusTd, TD_ERROR_CNT, 0);\r
+  OhciSetTDField (StatusTd, TD_COND_CODE, TD_TOBE_PROCESSED);\r
+  OhciSetTDField (StatusTd, TD_CURR_BUFFER_PTR, (UINT32) NULL);\r
+  OhciSetTDField (StatusTd, TD_NEXT_PTR, (UINT32) NULL);\r
+  OhciSetTDField (StatusTd, TD_BUFFER_END_PTR, (UINT32) NULL);\r
+  StatusTd->ActualSendLength = 0;\r
+  StatusTd->DataBuffer = NULL;\r
+  StatusTd->NextTDPointer = NULL;\r
+  OhciLinkTD (HeadTd, StatusTd);\r
+  //\r
+  // Empty Stage\r
+  //\r
+  EmptyTd = OhciCreateTD (Ohc);\r
+  if (EmptyTd == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Empty TD buffer\n"));\r
+    goto FREE_TD_BUFF;\r
+  }\r
+  OhciSetTDField (EmptyTd, TD_PDATA, 0);\r
+  OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0);\r
+  OhciSetTDField (EmptyTd, TD_DIR_PID, 0);\r
+  OhciSetTDField (EmptyTd, TD_DELAY_INT, 0);\r
+  //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);\r
+  EmptyTd->Word0.DataToggle = 0;\r
+  OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0);\r
+  OhciSetTDField (EmptyTd, TD_COND_CODE, 0);\r
+  OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0);\r
+  OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0);\r
+  OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0);\r
+  EmptyTd->ActualSendLength = 0;\r
+  EmptyTd->DataBuffer = NULL;\r
+  EmptyTd->NextTDPointer = NULL;\r
+  OhciLinkTD (HeadTd, EmptyTd);\r
+  Ed->TdTailPointer = EmptyTd;\r
+  OhciAttachTDListToED (Ed, HeadTd);\r
+  //\r
+  OhciSetEDField (Ed, ED_SKIP, 0);\r
+  MicroSecondDelay (20 * HC_1_MILLISECOND);\r
+  OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED, 1);\r
+  OhciSetHcControl (Ohc, CONTROL_ENABLE, 1);\r
+  MicroSecondDelay (20 * HC_1_MILLISECOND);\r
+  if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 1) {\r
+  MicroSecondDelay (HC_1_MILLISECOND);\r
+    if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 1) {\r
+      *TransferResult = EFI_USB_ERR_SYSTEM;\r
+      Status = EFI_DEVICE_ERROR;\r
+      DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to enable CONTROL transfer\n"));\r
+      goto FREE_TD_BUFF;\r
+    }\r
+  }\r
+\r
+  TimeCount = 0;\r
+  Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &ErrorCode);\r
+\r
+  while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {\r
+    MicroSecondDelay (HC_1_MILLISECOND);\r
+    TimeCount++;\r
+    Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &ErrorCode);\r
+  }\r
+  //\r
+  *TransferResult = ConvertErrorCode (ErrorCode);\r
+\r
+  if (ErrorCode != TD_NO_ERROR) {\r
+    if (ErrorCode == TD_TOBE_PROCESSED) {\r
+      DEBUG ((EFI_D_INFO, "Control pipe timeout, > %d mS\r\n", TimeOut));\r
+    } else {\r
+      DEBUG ((EFI_D_INFO, "Control pipe broken\r\n"));\r
+    }\r
+\r
+    *DataLength = 0;\r
+  }\r
+\r
+  OhciSetHcControl (Ohc, CONTROL_ENABLE, 0);\r
+  if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 0) {\r
+  MicroSecondDelay (HC_1_MILLISECOND);\r
+    if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 0) {\r
+      *TransferResult = EFI_USB_ERR_SYSTEM;\r
+      DEBUG ((EFI_D_INFO, "OhciControlTransfer: Cannot disable CONTROL_ENABLE transfer\n"));\r
+      goto FREE_TD_BUFF;\r
+    }\r
+  }\r
+\r
+FREE_TD_BUFF:\r
+  while (HeadTd) {\r
+    DataTd = HeadTd;\r
+    HeadTd = HeadTd->NextTDPointer;\r
+    UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));\r
+  }\r
+\r
+FREE_ED_BUFF:\r
+  UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Submits bulk transfer to a bulk endpoint of a USB device.\r
+\r
+  @param  PeiServices           The pointer of EFI_PEI_SERVICES.\r
+  @param  This                  The pointer of PEI_USB_HOST_CONTROLLER_PPI.\r
+  @param  DeviceAddress         Target device address.\r
+  @param  EndPointAddress       Endpoint number and its direction in bit 7.\r
+  @param  MaxiPacketLength      Maximum packet size the endpoint is capable of\r
+                                sending or receiving.\r
+  @param  Data                  A pointers to the buffers of data to transmit\r
+                                from or receive into.\r
+  @param  DataLength            The lenght of the data buffer.\r
+  @param  DataToggle            On input, the initial data toggle for the transfer;\r
+                                On output, it is updated to to next data toggle to use of\r
+                                the subsequent bulk transfer.\r
+  @param  TimeOut               Indicates the maximum time, in millisecond, which the\r
+                                transfer is allowed to complete.\r
+  @param  TransferResult        A pointer to the detailed result information of the\r
+                                bulk transfer.\r
+\r
+  @retval EFI_SUCCESS           The transfer was completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.\r
+  @retval EFI_INVALID_PARAMETER Parameters are invalid.\r
+  @retval EFI_TIMEOUT           The transfer failed due to timeout.\r
+  @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OhciBulkTransfer (\r
+  IN EFI_PEI_SERVICES             **PeiServices,\r
+  IN PEI_USB_HOST_CONTROLLER_PPI  *This,\r
+  IN  UINT8                       DeviceAddress,\r
+  IN  UINT8                       EndPointAddress,\r
+  IN  UINT8                       MaxPacketLength,\r
+  IN  OUT VOID                    *Data,\r
+  IN  OUT UINTN                   *DataLength,\r
+  IN  OUT UINT8                   *DataToggle,\r
+  IN  UINTN                       TimeOut,\r
+  OUT UINT32                      *TransferResult\r
+  )\r
+{\r
+  USB_OHCI_HC_DEV                *Ohc;\r
+  ED_DESCRIPTOR                  *Ed;\r
+  UINT8                          EdDir;\r
+  UINT32                         DataPidDir;\r
+  TD_DESCRIPTOR                  *HeadTd;\r
+  TD_DESCRIPTOR                  *DataTd;\r
+  TD_DESCRIPTOR                  *EmptyTd;\r
+  EFI_STATUS                     Status;\r
+  EFI_USB_DATA_DIRECTION         TransferDirection;\r
+  UINT8                          EndPointNum;\r
+  UINTN                          TimeCount;\r
+  UINT32                         ErrorCode;\r
+\r
+  UINT8                          CurrentToggle;\r
+  VOID                           *Mapping;\r
+  UINTN                          MapLength;\r
+  EFI_PHYSICAL_ADDRESS           MapPyhAddr;\r
+  UINTN                          LeftLength;\r
+  UINTN                          ActualSendLength;\r
+  BOOLEAN                        FirstTD;\r
+\r
+  Mapping = NULL;\r
+  MapLength = 0;\r
+  MapPyhAddr = 0;\r
+  LeftLength = 0;\r
+  Status = EFI_SUCCESS;\r
+\r
+  if (Data == NULL || DataLength == NULL || DataToggle == NULL || TransferResult == NULL ||\r
+      *DataLength == 0 || (*DataToggle != 0 && *DataToggle != 1) ||\r
+      (MaxPacketLength != 8 && MaxPacketLength != 16 &&\r
+       MaxPacketLength != 32 && MaxPacketLength != 64)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);\r
+\r
+  if ((EndPointAddress & 0x80) != 0) {\r
+    TransferDirection = EfiUsbDataIn;\r
+    EdDir = ED_IN_DIR;\r
+    DataPidDir = TD_IN_PID;\r
+  } else {\r
+    TransferDirection = EfiUsbDataOut;\r
+    EdDir = ED_OUT_DIR;\r
+    DataPidDir = TD_OUT_PID;\r
+  }\r
+\r
+  EndPointNum = (EndPointAddress & 0xF);\r
+\r
+  OhciSetHcControl (Ohc, BULK_ENABLE, 0);\r
+  if (OhciGetHcControl (Ohc, BULK_ENABLE) != 0) {\r
+    MicroSecondDelay (HC_1_MILLISECOND);\r
+    if (OhciGetHcControl (Ohc, BULK_ENABLE) != 0) {\r
+      *TransferResult = EFI_USB_ERR_SYSTEM;\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+\r
+  OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);\r
+\r
+  Ed = OhciCreateED (Ohc);\r
+  if (Ed == NULL) {\r
+    DEBUG ((EFI_D_INFO, "OhcBulkTransfer: Fail to allocate ED buffer\r\n"));\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  OhciSetEDField (Ed, ED_SKIP, 1);\r
+  OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);\r
+  OhciSetEDField (Ed, ED_ENDPT_NUM, EndPointNum);\r
+  OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);\r
+  OhciSetEDField (Ed, ED_SPEED, HI_SPEED);\r
+  OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0);\r
+  OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);\r
+  OhciSetEDField (Ed, ED_PDATA, 0);\r
+  OhciSetEDField (Ed, ED_ZERO, 0);\r
+  OhciSetEDField (Ed, ED_TDHEAD_PTR, (UINT32) NULL);\r
+  OhciSetEDField (Ed, ED_TDTAIL_PTR, (UINT32) NULL);\r
+  OhciSetEDField (Ed, ED_NEXT_EDPTR, (UINT32) NULL);\r
+  OhciAttachEDToList (Ohc, BULK_LIST, Ed, NULL);\r
+\r
+  if(Data != NULL) {\r
+    MapLength = *DataLength;\r
+    MapPyhAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Data;\r
+  }\r
+  //\r
+  //Data Stage\r
+  //\r
+  LeftLength = MapLength;\r
+  ActualSendLength = MapLength;\r
+  CurrentToggle = *DataToggle;\r
+  HeadTd = NULL;\r
+  FirstTD = TRUE;\r
+  while (LeftLength > 0) {\r
+    ActualSendLength = LeftLength;\r
+    if (LeftLength > MaxPacketLength) {\r
+      ActualSendLength = MaxPacketLength;\r
+    }\r
+    DataTd = OhciCreateTD (Ohc);\r
+    if (DataTd == NULL) {\r
+      DEBUG ((EFI_D_INFO, "OhcBulkTransfer: Fail to allocate Data TD buffer\r\n"));\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto FREE_TD_BUFF;\r
+    }\r
+    OhciSetTDField (DataTd, TD_PDATA, 0);\r
+    OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);\r
+    OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);\r
+    OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);\r
+    OhciSetTDField (DataTd, TD_DT_TOGGLE, CurrentToggle);\r
+    OhciSetTDField (DataTd, TD_ERROR_CNT, 0);\r
+    OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);\r
+    OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) MapPyhAddr);\r
+    OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32) MapPyhAddr + ActualSendLength - 1);\r
+    OhciSetTDField (DataTd, TD_NEXT_PTR, (UINT32) NULL);\r
+    DataTd->ActualSendLength = ActualSendLength;\r
+    DataTd->DataBuffer = (UINT8 *)(UINTN)MapPyhAddr;\r
+    DataTd->NextTDPointer = 0;\r
+    if (FirstTD) {\r
+      HeadTd = DataTd;\r
+      FirstTD = FALSE;\r
+    } else {\r
+      OhciLinkTD (HeadTd, DataTd);\r
+    }\r
+    CurrentToggle ^= 1;\r
+    MapPyhAddr += ActualSendLength;\r
+    LeftLength -= ActualSendLength;\r
+  }\r
+  //\r
+  // Empty Stage\r
+  //\r
+  EmptyTd = OhciCreateTD (Ohc);\r
+  if (EmptyTd == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+      DEBUG ((EFI_D_INFO, "OhcBulkTransfer: Fail to allocate Empty TD buffer\r\n"));\r
+    goto FREE_TD_BUFF;\r
+  }\r
+  OhciSetTDField (EmptyTd, TD_PDATA, 0);\r
+  OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0);\r
+  OhciSetTDField (EmptyTd, TD_DIR_PID, 0);\r
+  OhciSetTDField (EmptyTd, TD_DELAY_INT, 0);\r
+  //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);\r
+  EmptyTd->Word0.DataToggle = 0;\r
+  OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0);\r
+  OhciSetTDField (EmptyTd, TD_COND_CODE, 0);\r
+  OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0);\r
+  OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0);\r
+  OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0);\r
+  EmptyTd->ActualSendLength = 0;\r
+  EmptyTd->DataBuffer = NULL;\r
+  EmptyTd->NextTDPointer = NULL;\r
+  OhciLinkTD (HeadTd, EmptyTd);\r
+  Ed->TdTailPointer = EmptyTd;\r
+  OhciAttachTDListToED (Ed, HeadTd);\r
+\r
+  OhciSetEDField (Ed, ED_SKIP, 0);\r
+  OhciSetHcCommandStatus (Ohc, BULK_LIST_FILLED, 1);\r
+  OhciSetHcControl (Ohc, BULK_ENABLE, 1);\r
+  if (OhciGetHcControl (Ohc, BULK_ENABLE) != 1) {\r
+    MicroSecondDelay (HC_1_MILLISECOND);\r
+    if (OhciGetHcControl (Ohc, BULK_ENABLE) != 1) {\r
+      *TransferResult = EFI_USB_ERR_SYSTEM;\r
+      goto FREE_TD_BUFF;\r
+    }\r
+  }\r
+\r
+  TimeCount = 0;\r
+  Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &ErrorCode);\r
+\r
+  while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {\r
+    MicroSecondDelay (HC_1_MILLISECOND);\r
+    TimeCount++;\r
+    Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &ErrorCode);\r
+  }\r
+\r
+  *TransferResult = ConvertErrorCode (ErrorCode);\r
+\r
+  if (ErrorCode != TD_NO_ERROR) {\r
+    if (ErrorCode == TD_TOBE_PROCESSED) {\r
+      DEBUG ((EFI_D_INFO, "Bulk pipe timeout, > %d mS\r\n", TimeOut));\r
+    } else {\r
+      DEBUG ((EFI_D_INFO, "Bulk pipe broken\r\n"));\r
+    }\r
+    *DataLength = 0;\r
+  }\r
+    *DataToggle = (UINT8) OhciGetEDField (Ed, ED_DTTOGGLE);\r
+\r
+FREE_TD_BUFF:\r
+  while (HeadTd) {\r
+    DataTd = HeadTd;\r
+    HeadTd = HeadTd->NextTDPointer;\r
+    UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));\r
+  }\r
+  UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));\r
+\r
+  return Status;\r
+}\r
+/**\r
+  Retrieves the number of root hub ports.\r
+\r
+  @param[in]  PeiServices       The pointer to the PEI Services Table.\r
+  @param[in]  This              The pointer to this instance of the\r
+                                PEI_USB_HOST_CONTROLLER_PPI.\r
+  @param[out] NumOfPorts        The pointer to the number of the root hub ports.\r
+\r
+  @retval EFI_SUCCESS           The port number was retrieved successfully.\r
+  @retval EFI_INVALID_PARAMETER PortNumber is NULL.\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciGetRootHubNumOfPorts (\r
+  IN EFI_PEI_SERVICES             **PeiServices,\r
+  IN PEI_USB_HOST_CONTROLLER_PPI  *This,\r
+  OUT UINT8                       *NumOfPorts\r
+  )\r
+{\r
+  USB_OHCI_HC_DEV                *Ohc;\r
+  if (NumOfPorts == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);\r
+  *NumOfPorts = (UINT8)OhciGetRootHubDescriptor(Ohc, RH_NUM_DS_PORTS);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+/**\r
+  Retrieves the current status of a USB root hub port.\r
+\r
+  @param  PeiServices            The pointer of EFI_PEI_SERVICES.\r
+  @param  This                   The pointer of PEI_USB_HOST_CONTROLLER_PPI.\r
+  @param  PortNumber             The root hub port to retrieve the state from.\r
+  @param  PortStatus             Variable to receive the port state.\r
+\r
+  @retval EFI_SUCCESS            The status of the USB root hub port specified.\r
+                                 by PortNumber was returned in PortStatus.\r
+  @retval EFI_INVALID_PARAMETER  PortNumber is invalid.\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciGetRootHubPortStatus (\r
+  IN  EFI_PEI_SERVICES             **PeiServices,\r
+  IN  PEI_USB_HOST_CONTROLLER_PPI  *This,\r
+  IN  UINT8                        PortNumber,\r
+  OUT EFI_USB_PORT_STATUS          *PortStatus\r
+  )\r
+{\r
+  USB_OHCI_HC_DEV  *Ohc;\r
+  UINT8            NumOfPorts;\r
+\r
+  Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);\r
+\r
+  OhciGetRootHubNumOfPorts (PeiServices, This, &NumOfPorts);\r
+  if (PortNumber >= NumOfPorts) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  PortStatus->PortStatus = 0;\r
+  PortStatus->PortChangeStatus = 0;\r
+\r
+  if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_CURR_CONNECT_STAT)) {\r
+    PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_ENABLE_STAT)) {\r
+    PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_SUSPEND_STAT)) {\r
+    PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_OC_INDICATOR)) {\r
+    PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_RESET_STAT)) {\r
+    PortStatus->PortStatus |= USB_PORT_STAT_RESET;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_POWER_STAT)) {\r
+    PortStatus->PortStatus |= USB_PORT_STAT_POWER;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_LSDEVICE_ATTACHED)) {\r
+    PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE)) {\r
+    PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE)) {\r
+    PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE)) {\r
+    PortStatus->PortChangeStatus |= USB_PORT_STAT_C_SUSPEND;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE)) {\r
+    PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT;\r
+  }\r
+  if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE)) {\r
+    PortStatus->PortChangeStatus |= USB_PORT_STAT_C_RESET;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+/**\r
+  Sets a feature for the specified root hub port.\r
+\r
+  @param  PeiServices           The pointer of EFI_PEI_SERVICES\r
+  @param  This                  The pointer of PEI_USB_HOST_CONTROLLER_PPI\r
+  @param  PortNumber            Root hub port to set.\r
+  @param  PortFeature           Feature to set.\r
+\r
+  @retval EFI_SUCCESS            The feature specified by PortFeature was set.\r
+  @retval EFI_INVALID_PARAMETER  PortNumber is invalid or PortFeature is invalid.\r
+  @retval EFI_TIMEOUT            The time out occurred.\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciSetRootHubPortFeature (\r
+  IN EFI_PEI_SERVICES             **PeiServices,\r
+  IN PEI_USB_HOST_CONTROLLER_PPI  *This,\r
+  IN UINT8                        PortNumber,\r
+  IN EFI_USB_PORT_FEATURE         PortFeature\r
+  )\r
+{\r
+  USB_OHCI_HC_DEV         *Ohc;\r
+  EFI_STATUS              Status;\r
+  UINT8                   NumOfPorts;\r
+  UINTN                   RetryTimes;\r
+\r
+  OhciGetRootHubNumOfPorts (PeiServices, This, &NumOfPorts);\r
+  if (PortNumber >= NumOfPorts) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+\r
+  switch (PortFeature) {\r
+    case EfiUsbPortPower:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_POWER);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        MicroSecondDelay (HC_1_MILLISECOND);\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 0 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+    case EfiUsbPortReset:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_RESET);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        MicroSecondDelay (HC_1_MILLISECOND);\r
+        RetryTimes++;\r
+      } while ((OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 0 ||\r
+                OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT) == 1) &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+\r
+      OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);\r
+      break;\r
+\r
+    case EfiUsbPortEnable:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_ENABLE);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        MicroSecondDelay (HC_1_MILLISECOND);;\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 0 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+\r
+    case EfiUsbPortSuspend:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_SUSPEND);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        MicroSecondDelay (HC_1_MILLISECOND);;\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 0 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+    default:\r
+      return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Clears a feature for the specified root hub port.\r
+\r
+  @param  PeiServices           The pointer of EFI_PEI_SERVICES.\r
+  @param  This                  The pointer of PEI_USB_HOST_CONTROLLER_PPI.\r
+  @param  PortNumber            Specifies the root hub port whose feature\r
+                                is requested to be cleared.\r
+  @param  PortFeature           Indicates the feature selector associated with the\r
+                                feature clear request.\r
+\r
+  @retval EFI_SUCCESS            The feature specified by PortFeature was cleared\r
+                                 for the USB root hub port specified by PortNumber.\r
+  @retval EFI_INVALID_PARAMETER  PortNumber is invalid or PortFeature is invalid.\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciClearRootHubPortFeature (\r
+  IN EFI_PEI_SERVICES             **PeiServices,\r
+  IN PEI_USB_HOST_CONTROLLER_PPI  *This,\r
+  IN UINT8                        PortNumber,\r
+  IN EFI_USB_PORT_FEATURE         PortFeature\r
+  )\r
+{\r
+  USB_OHCI_HC_DEV         *Ohc;\r
+  EFI_STATUS              Status;\r
+  UINT8                   NumOfPorts;\r
+  UINTN                   RetryTimes;\r
+\r
+\r
+  OhciGetRootHubNumOfPorts (PeiServices, This, &NumOfPorts);\r
+  if (PortNumber >= NumOfPorts) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  switch (PortFeature) {\r
+    case EfiUsbPortEnable:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_ENABLE);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        MicroSecondDelay (HC_1_MILLISECOND);\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 1 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+    case EfiUsbPortSuspend:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_SUSPEND_STATUS);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        MicroSecondDelay (HC_1_MILLISECOND);\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 1 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+    case EfiUsbPortReset:\r
+      break;\r
+\r
+    case EfiUsbPortPower:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_POWER);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        MicroSecondDelay (HC_1_MILLISECOND);\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 1 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+    case EfiUsbPortConnectChange:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        MicroSecondDelay (HC_1_MILLISECOND);\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE) == 1 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+    case EfiUsbPortResetChange:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        MicroSecondDelay (HC_1_MILLISECOND);\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 1 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+\r
+    case EfiUsbPortEnableChange:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        MicroSecondDelay (HC_1_MILLISECOND);\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE) == 1 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+    case EfiUsbPortSuspendChange:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        MicroSecondDelay (HC_1_MILLISECOND);\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE) == 1 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+    case EfiUsbPortOverCurrentChange:\r
+      Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE);\r
+\r
+      //\r
+      // Verify the state\r
+      //\r
+      RetryTimes = 0;\r
+      do {\r
+        MicroSecondDelay (HC_1_MILLISECOND);\r
+        RetryTimes++;\r
+      } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE) == 1 &&\r
+               RetryTimes < MAX_RETRY_TIMES);\r
+\r
+      if (RetryTimes >= MAX_RETRY_TIMES) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      break;\r
+\r
+    default:\r
+      return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  return Status;\r
+}\r
+/**\r
+  Provides software reset for the USB host controller.\r
+\r
+  @param  This                  This EFI_USB_HC_PROTOCOL instance.\r
+  @param  Attributes            A bit mask of the reset operation to perform.\r
+\r
+  @retval EFI_SUCCESS           The reset operation succeeded.\r
+  @retval EFI_INVALID_PARAMETER Attributes is not valid.\r
+  @retval EFI_UNSUPPOURTED      The type of reset specified by Attributes is\r
+                                not currently supported by the host controller.\r
+  @retval EFI_DEVICE_ERROR      Host controller isn't halted to reset.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeUsbHC (\r
+  IN EFI_PEI_SERVICES           **PeiServices,\r
+  IN USB_OHCI_HC_DEV            *Ohc,\r
+  IN UINT16                     Attributes\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  UINT8                   Index;\r
+  UINT8                   NumOfPorts;\r
+  UINT32                  PowerOnGoodTime;\r
+  UINT32                  Data32;\r
+  BOOLEAN                 Flag = FALSE;\r
+\r
+  if ((Attributes & ~(EFI_USB_HC_RESET_GLOBAL | EFI_USB_HC_RESET_HOST_CONTROLLER)) != 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  Status = EFI_SUCCESS;\r
+\r
+  if ((Attributes & EFI_USB_HC_RESET_HOST_CONTROLLER) != 0) {\r
+    MicroSecondDelay (50 * HC_1_MILLISECOND);\r
+    Status = OhciSetHcCommandStatus (Ohc, HC_RESET, HC_RESET);\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+    MicroSecondDelay (50 * HC_1_MILLISECOND);\r
+    //\r
+    // Wait for host controller reset.\r
+    //\r
+    PowerOnGoodTime = 50;\r
+    do {\r
+      MicroSecondDelay (HC_1_MILLISECOND);\r
+      Data32 = OhciGetOperationalReg (Ohc, HC_COMMAND_STATUS );\r
+      if ((Data32 & HC_RESET) == 0) {\r
+        Flag = TRUE;\r
+        break;\r
+      }\r
+    }while(PowerOnGoodTime--);\r
+    if (!Flag){\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+\r
+  OhciSetFrameInterval (Ohc, FRAME_INTERVAL, 0x2edf);\r
+  if ((Attributes &  EFI_USB_HC_RESET_GLOBAL) != 0) {\r
+    Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_RESET);\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+    MicroSecondDelay (50 * HC_1_MILLISECOND);\r
+  }\r
+  //\r
+  // Initialize host controller operational registers\r
+  //\r
+  OhciSetFrameInterval (Ohc, FS_LARGEST_DATA_PACKET, 0x2778);\r
+  OhciSetFrameInterval (Ohc, FRAME_INTERVAL, 0x2edf);\r
+  OhciSetPeriodicStart (Ohc, 0x2a2f);\r
+  OhciSetHcControl (Ohc, CONTROL_BULK_RATIO, 0x0);\r
+  OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED | BULK_LIST_FILLED, 0);\r
+  OhciSetRootHubDescriptor (Ohc, RH_PSWITCH_MODE, 0);\r
+  OhciSetRootHubDescriptor (Ohc, RH_NO_PSWITCH | RH_NOC_PROT, 1);\r
+  //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NO_PSWITCH, 0);\r
+  //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NOC_PROT, 1);\r
+\r
+  OhciSetRootHubDescriptor (Ohc, RH_DEV_REMOVABLE, 0);\r
+  OhciSetRootHubDescriptor (Ohc, RH_PORT_PWR_CTRL_MASK, 0xffff);\r
+  OhciSetRootHubStatus (Ohc, RH_LOCAL_PSTAT_CHANGE);\r
+  OhciSetRootHubPortStatus (Ohc, 0, RH_SET_PORT_POWER);\r
+  OhciGetRootHubNumOfPorts (PeiServices, &Ohc->UsbHostControllerPpi, &NumOfPorts);\r
+  for (Index = 0; Index < NumOfPorts; Index++) {\r
+    if (!EFI_ERROR (OhciSetRootHubPortFeature (PeiServices, &Ohc->UsbHostControllerPpi, Index, EfiUsbPortReset))) {\r
+      MicroSecondDelay (200 * HC_1_MILLISECOND);\r
+      OhciClearRootHubPortFeature (PeiServices, &Ohc->UsbHostControllerPpi, Index, EfiUsbPortReset);\r
+      MicroSecondDelay (HC_1_MILLISECOND);\r
+      OhciSetRootHubPortFeature (PeiServices, &Ohc->UsbHostControllerPpi, Index, EfiUsbPortEnable);\r
+      MicroSecondDelay (HC_1_MILLISECOND);\r
+    }\r
+  }\r
+\r
+  Ohc->MemPool = UsbHcInitMemPool(TRUE, 0);\r
+  if(Ohc->MemPool == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);\r
+  OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);\r
+  OhciSetHcControl (Ohc, CONTROL_ENABLE | BULK_ENABLE, 1);\r
+  OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_OPERATIONAL);\r
+  MicroSecondDelay (50 * HC_1_MILLISECOND);\r
+  //\r
+  // Wait till first SOF occurs, and then clear it\r
+  //\r
+  while (OhciGetHcInterruptStatus (Ohc, START_OF_FRAME) == 0);\r
+  OhciClearInterruptStatus (Ohc, START_OF_FRAME);\r
+  MicroSecondDelay (HC_1_MILLISECOND);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Submits control transfer to a target USB device.\r
+\r
+  Calls underlying OhciControlTransfer to do work. This wrapper routine required\r
+  on Quark so that USB DMA transfers do not cause an IMR violation.\r
+\r
+  @param  PeiServices            The pointer of EFI_PEI_SERVICES.\r
+  @param  This                   The pointer of PEI_USB_HOST_CONTROLLER_PPI.\r
+  @param  DeviceAddress          The target device address.\r
+  @param  DeviceSpeed            Target device speed.\r
+  @param  MaximumPacketLength    Maximum packet size the default control transfer\r
+                                 endpoint is capable of sending or receiving.\r
+  @param  Request                USB device request to send.\r
+  @param  TransferDirection      Specifies the data direction for the data stage.\r
+  @param  Data                   Data buffer to be transmitted or received from USB device.\r
+  @param  DataLength             The size (in bytes) of the data buffer.\r
+  @param  TimeOut                Indicates the maximum timeout, in millisecond.\r
+  @param  TransferResult         Return the result of this control transfer.\r
+\r
+  @retval EFI_SUCCESS            Transfer was completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES   The transfer failed due to lack of resources.\r
+  @retval EFI_INVALID_PARAMETER  Some parameters are invalid.\r
+  @retval EFI_TIMEOUT            Transfer failed due to timeout.\r
+  @retval EFI_DEVICE_ERROR       Transfer failed due to host controller or device error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RedirectOhciControlTransfer (\r
+  IN  EFI_PEI_SERVICES             **PeiServices,\r
+  IN  PEI_USB_HOST_CONTROLLER_PPI  *This,\r
+  IN  UINT8                        DeviceAddress,\r
+  IN  UINT8                        DeviceSpeed,\r
+  IN  UINT8                        MaxPacketLength,\r
+  IN  EFI_USB_DEVICE_REQUEST       *Request,\r
+  IN  EFI_USB_DATA_DIRECTION       TransferDirection,\r
+  IN  OUT VOID                     *Data,\r
+  IN  OUT UINTN                    *DataLength,\r
+  IN  UINTN                        TimeOut,\r
+  OUT UINT32                       *TransferResult\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_USB_DEVICE_REQUEST  *NewRequest;\r
+  VOID                    *NewData;\r
+  UINT8                   *Alloc;\r
+\r
+  //\r
+  // Allocate memory external to IMR protected region for transfer data.\r
+  //\r
+  Status = PeiServicesAllocatePool (\r
+                             sizeof(EFI_USB_DEVICE_REQUEST) + *DataLength,\r
+                             (VOID **) &Alloc\r
+                             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Setup pointers to transfer buffers.\r
+  //\r
+  NewRequest = (EFI_USB_DEVICE_REQUEST *) Alloc;\r
+  Alloc += sizeof(EFI_USB_DEVICE_REQUEST);\r
+  NewData = (VOID *) Alloc;\r
+\r
+  //\r
+  // Copy callers request packet into transfer request packet.\r
+  //\r
+  if (Request != NULL) {\r
+    CopyMem (NewRequest,Request,sizeof(EFI_USB_DEVICE_REQUEST));\r
+  } else {\r
+    NewRequest = NULL;\r
+  }\r
+  //\r
+  // Copy callers data into transfer data buffer.\r
+  //\r
+  if (Data != NULL) {\r
+    if (DataLength > 0) {\r
+      CopyMem (NewData,Data,*DataLength);\r
+    }\r
+  } else {\r
+    NewData = NULL;\r
+  }\r
+\r
+  //\r
+  // Call underlying OhciControlTransfer to do work.\r
+  //\r
+  Status = OhciControlTransfer (\r
+             PeiServices,\r
+             This,\r
+             DeviceAddress,\r
+             DeviceSpeed,\r
+             MaxPacketLength,\r
+             NewRequest,\r
+             TransferDirection,\r
+             NewData,\r
+             DataLength,\r
+             TimeOut,\r
+             TransferResult\r
+             );\r
+\r
+  //\r
+  // Copy transfer buffer back into callers buffer.\r
+  //\r
+  if (Data != NULL && *DataLength > 0) {\r
+    CopyMem (Data, NewData, *DataLength);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Submits bulk transfer to a bulk endpoint of a USB device.\r
+\r
+  Calls underlying OhciBulkTransfer to do work. This wrapper routine required\r
+  on Quark so that USB DMA transfers do not cause an IMR violation.\r
+\r
+  @param  PeiServices           The pointer of EFI_PEI_SERVICES.\r
+  @param  This                  The pointer of PEI_USB_HOST_CONTROLLER_PPI.\r
+  @param  DeviceAddress         Target device address.\r
+  @param  EndPointAddress       Endpoint number and its direction in bit 7.\r
+  @param  MaxiPacketLength      Maximum packet size the endpoint is capable of\r
+                                sending or receiving.\r
+  @param  Data                  A pointers to the buffers of data to transmit\r
+                                from or receive into.\r
+  @param  DataLength            The lenght of the data buffer.\r
+  @param  DataToggle            On input, the initial data toggle for the transfer;\r
+                                On output, it is updated to to next data toggle to use of\r
+                                the subsequent bulk transfer.\r
+  @param  TimeOut               Indicates the maximum time, in millisecond, which the\r
+                                transfer is allowed to complete.\r
+  @param  TransferResult        A pointer to the detailed result information of the\r
+                                bulk transfer.\r
+\r
+  @retval EFI_SUCCESS           The transfer was completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.\r
+  @retval EFI_INVALID_PARAMETER Parameters are invalid.\r
+  @retval EFI_TIMEOUT           The transfer failed due to timeout.\r
+  @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RedirectOhciBulkTransfer (\r
+  IN EFI_PEI_SERVICES             **PeiServices,\r
+  IN PEI_USB_HOST_CONTROLLER_PPI  *This,\r
+  IN  UINT8                       DeviceAddress,\r
+  IN  UINT8                       EndPointAddress,\r
+  IN  UINT8                       MaxPacketLength,\r
+  IN  OUT VOID                    *Data,\r
+  IN  OUT UINTN                   *DataLength,\r
+  IN  OUT UINT8                   *DataToggle,\r
+  IN  UINTN                       TimeOut,\r
+  OUT UINT32                      *TransferResult\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  UINT8                   *NewData;\r
+\r
+  //\r
+  // Allocate memory external to IMR protected region for transfer data.\r
+  //\r
+  Status = PeiServicesAllocatePool (\r
+                             *DataLength,\r
+                             (VOID **) &NewData\r
+                             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Copy callers data into transfer buffer.\r
+  //\r
+  if (Data != NULL) {\r
+    if (DataLength > 0) {\r
+      CopyMem (NewData,Data,*DataLength);\r
+    }\r
+  } else {\r
+    NewData = NULL;\r
+  }\r
+\r
+  //\r
+  // Call underlying OhciBulkTransfer to do work.\r
+  //\r
+  Status = OhciBulkTransfer (\r
+             PeiServices,\r
+             This,\r
+             DeviceAddress,\r
+             EndPointAddress,\r
+             MaxPacketLength,\r
+             NewData,\r
+             DataLength,\r
+             DataToggle,\r
+             TimeOut,\r
+             TransferResult\r
+             );\r
+\r
+  //\r
+  // Copy transfer buffer back into callers buffer.\r
+  //\r
+  if (Data != NULL && *DataLength > 0) {\r
+    CopyMem (Data, NewData, *DataLength);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  @param  FileHandle  Handle of the file being invoked.\r
+  @param  PeiServices Describes the list of possible PEI Services.\r
+\r
+  @retval EFI_SUCCESS            PPI successfully installed.\r
+\r
+**/\r
+EFI_STATUS\r
+OhcPeimEntry (\r
+  IN EFI_PEI_FILE_HANDLE        FileHandle,\r
+  IN CONST EFI_PEI_SERVICES     **PeiServices\r
+  )\r
+{\r
+\r
+  PEI_USB_CONTROLLER_PPI  *ChipSetUsbControllerPpi;\r
+  EFI_STATUS              Status;\r
+  UINT8                   Index;\r
+  UINTN                   ControllerType;\r
+  UINTN                   BaseAddress;\r
+  UINTN                   MemPages;\r
+  USB_OHCI_HC_DEV         *Ohc;\r
+  EFI_PHYSICAL_ADDRESS    TempPtr;\r
+\r
+\r
+  //\r
+  // Shadow this PEIM to run from memory\r
+  //\r
+  if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  Status = PeiServicesLocatePpi (\r
+             &gPeiUsbControllerPpiGuid,\r
+             0,\r
+             NULL,\r
+             (VOID **) &ChipSetUsbControllerPpi\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Index = 0;\r
+  while (TRUE) {\r
+    Status = ChipSetUsbControllerPpi->GetUsbController (\r
+                                        (EFI_PEI_SERVICES **) PeiServices,\r
+                                        ChipSetUsbControllerPpi,\r
+                                        Index,\r
+                                        &ControllerType,\r
+                                        &BaseAddress\r
+                                        );\r
+    //\r
+    // When status is error, meant no controller is found\r
+    //\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+    //\r
+    // This PEIM is for OHC type controller.\r
+    //\r
+    if (ControllerType != PEI_OHCI_CONTROLLER) {\r
+      Index++;\r
+      continue;\r
+    }\r
+\r
+    MemPages = sizeof (USB_OHCI_HC_DEV) / PAGESIZE + 1;\r
+    Status = PeiServicesAllocatePages (\r
+               EfiBootServicesCode,\r
+               MemPages,\r
+               &TempPtr\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_INFO, "OhcPeimEntry: Fail to allocate buffer for the %dth OHCI ControllerPpi\n", Index));\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    ZeroMem((VOID *)(UINTN)TempPtr, MemPages*PAGESIZE);\r
+    Ohc = (USB_OHCI_HC_DEV *) ((UINTN) TempPtr);\r
+\r
+    Ohc->Signature = USB_OHCI_HC_DEV_SIGNATURE;\r
+\r
+    Ohc->UsbHostControllerBaseAddress = (UINT32) BaseAddress;\r
+\r
+    //\r
+    // Initialize Uhc's hardware\r
+    //\r
+    Status = InitializeUsbHC (\r
+               (EFI_PEI_SERVICES **)PeiServices,\r
+               Ohc,\r
+               EFI_USB_HC_RESET_GLOBAL\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_INFO, "OhcPeimEntry: Fail to init %dth OHCI ControllerPpi\n", Index));\r
+      return Status;\r
+    }\r
+    //\r
+    // Control & Bulk transfer services are accessed via their Redirect\r
+    // routine versions on Quark so that USB DMA transfers do not cause an\r
+    // IMR violation.\r
+    //\r
+    Ohc->UsbHostControllerPpi.ControlTransfer          = RedirectOhciControlTransfer;\r
+    Ohc->UsbHostControllerPpi.BulkTransfer             = RedirectOhciBulkTransfer;\r
+    Ohc->UsbHostControllerPpi.GetRootHubPortNumber     = OhciGetRootHubNumOfPorts;\r
+    Ohc->UsbHostControllerPpi.GetRootHubPortStatus     = OhciGetRootHubPortStatus;\r
+    Ohc->UsbHostControllerPpi.SetRootHubPortFeature    = OhciSetRootHubPortFeature;\r
+    Ohc->UsbHostControllerPpi.ClearRootHubPortFeature  = OhciClearRootHubPortFeature;\r
+\r
+    Ohc->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);\r
+    Ohc->PpiDescriptor.Guid  = &gPeiUsbHostControllerPpiGuid;\r
+    Ohc->PpiDescriptor.Ppi   = &Ohc->UsbHostControllerPpi;\r
+\r
+    Status = PeiServicesInstallPpi (&Ohc->PpiDescriptor);\r
+    if (EFI_ERROR (Status)) {\r
+      Index++;\r
+      continue;\r
+    }\r
+    Index++;\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhcPeim.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhcPeim.h
new file mode 100644 (file)
index 0000000..0fd5302
--- /dev/null
@@ -0,0 +1,258 @@
+/** @file\r
+Provides the definition of Usb Hc Protocol and OHCI controller\r
+private data structure.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+\r
+#ifndef _OHCI_PEIM_H\r
+#define _OHCI_PEIM_H\r
+\r
+#include <PiPei.h>\r
+\r
+#include <Ppi/UsbController.h>\r
+#include <Ppi/UsbHostController.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/PeimEntryPoint.h>\r
+#include <Library/PeiServicesLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/IoLib.h>\r
+\r
+typedef struct _USB_OHCI_HC_DEV USB_OHCI_HC_DEV;\r
+\r
+#include "UsbHcMem.h"\r
+#include "OhciReg.h"\r
+#include "OhciSched.h"\r
+#include "OhciUrb.h"\r
+#include "Descriptor.h"\r
+\r
+#define EFI_USB_SPEED_FULL 0x0000\r
+#define EFI_USB_SPEED_LOW  0x0001\r
+#define EFI_USB_SPEED_HIGH 0x0002\r
+\r
+#define PAGESIZE                    4096\r
+\r
+#define HC_1_MICROSECOND            1\r
+#define HC_1_MILLISECOND            (1000 * HC_1_MICROSECOND)\r
+#define HC_1_SECOND                 (1000 * HC_1_MILLISECOND)\r
+\r
+\r
+#define USB_OHCI_HC_DEV_SIGNATURE   SIGNATURE_32('o','h','c','i')\r
+\r
+struct _USB_OHCI_HC_DEV {\r
+  UINTN                        Signature;\r
+  PEI_USB_HOST_CONTROLLER_PPI  UsbHostControllerPpi;\r
+  EFI_PEI_PPI_DESCRIPTOR       PpiDescriptor;\r
+  UINT32                       UsbHostControllerBaseAddress;\r
+  VOID                         *MemPool;\r
+};\r
+\r
+#define PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS(a)  CR (a, USB_OHCI_HC_DEV, UsbHostControllerPpi, USB_OHCI_HC_DEV_SIGNATURE)\r
+\r
+//\r
+// Func List\r
+//\r
+\r
+/**\r
+  Provides software reset for the USB host controller.\r
+\r
+  @param  PeiServices           The pointer of EFI_PEI_SERVICES.\r
+  @param  This                  The pointer of PEI_USB_HOST_CONTROLLER_PPI.\r
+  @param  Attributes            A bit mask of the reset operation to perform.\r
+\r
+  @retval EFI_SUCCESS           The reset operation succeeded.\r
+  @retval EFI_INVALID_PARAMETER Attributes is not valid.\r
+  @retval EFI_UNSUPPOURTED      The type of reset specified by Attributes is\r
+                                not currently supported by the host controller.\r
+  @retval EFI_DEVICE_ERROR      Host controller isn't halted to reset.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeUsbHC (\r
+  IN EFI_PEI_SERVICES   **PeiServices,\r
+  IN USB_OHCI_HC_DEV    *Ohc,\r
+  IN UINT16             Attributes\r
+  );\r
+\r
+/**\r
+  Submits control transfer to a target USB device.\r
+\r
+  @param  PeiServices            The pointer of EFI_PEI_SERVICES.\r
+  @param  This                   The pointer of PEI_USB_HOST_CONTROLLER_PPI.\r
+  @param  DeviceAddress          The target device address.\r
+  @param  DeviceSpeed            Target device speed.\r
+  @param  MaximumPacketLength    Maximum packet size the default control transfer\r
+                                 endpoint is capable of sending or receiving.\r
+  @param  Request                USB device request to send.\r
+  @param  TransferDirection      Specifies the data direction for the data stage.\r
+  @param  Data                   Data buffer to be transmitted or received from USB device.\r
+  @param  DataLength             The size (in bytes) of the data buffer.\r
+  @param  TimeOut                Indicates the maximum timeout, in millisecond.\r
+  @param  TransferResult         Return the result of this control transfer.\r
+\r
+  @retval EFI_SUCCESS            Transfer was completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES   The transfer failed due to lack of resources.\r
+  @retval EFI_INVALID_PARAMETER  Some parameters are invalid.\r
+  @retval EFI_TIMEOUT            Transfer failed due to timeout.\r
+  @retval EFI_DEVICE_ERROR       Transfer failed due to host controller or device error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OhciControlTransfer (\r
+  IN  EFI_PEI_SERVICES                    **PeiServices,\r
+  IN  PEI_USB_HOST_CONTROLLER_PPI         *This,\r
+  IN  UINT8                               DeviceAddress,\r
+  IN  UINT8                               DeviceSpeed,\r
+  IN  UINT8                               MaxPacketLength,\r
+  IN  EFI_USB_DEVICE_REQUEST              *Request,\r
+  IN  EFI_USB_DATA_DIRECTION              TransferDirection,\r
+  IN  OUT VOID                            *Data,\r
+  IN  OUT UINTN                           *DataLength,\r
+  IN  UINTN                               TimeOut,\r
+  OUT UINT32                              *TransferResult\r
+  );\r
+/**\r
+  Submits bulk transfer to a bulk endpoint of a USB device.\r
+\r
+  @param  PeiServices           The pointer of EFI_PEI_SERVICES.\r
+  @param  This                  The pointer of PEI_USB_HOST_CONTROLLER_PPI.\r
+  @param  DeviceAddress         Target device address.\r
+  @param  EndPointAddress       Endpoint number and its direction in bit 7.\r
+  @param  MaxiPacketLength      Maximum packet size the endpoint is capable of\r
+                                sending or receiving.\r
+  @param  Data                  A pointers to the buffers of data to transmit\r
+                                from or receive into.\r
+  @param  DataLength            The lenght of the data buffer.\r
+  @param  DataToggle            On input, the initial data toggle for the transfer;\r
+                                On output, it is updated to to next data toggle to use of\r
+                                the subsequent bulk transfer.\r
+  @param  TimeOut               Indicates the maximum time, in millisecond, which the\r
+                                transfer is allowed to complete.\r
+  @param  TransferResult        A pointer to the detailed result information of the\r
+                                bulk transfer.\r
+\r
+  @retval EFI_SUCCESS           The transfer was completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.\r
+  @retval EFI_INVALID_PARAMETER Parameters are invalid.\r
+  @retval EFI_TIMEOUT           The transfer failed due to timeout.\r
+  @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OhciBulkTransfer (\r
+  IN EFI_PEI_SERVICES                     **PeiServices,\r
+  IN PEI_USB_HOST_CONTROLLER_PPI          *This,\r
+  IN  UINT8                               DeviceAddress,\r
+  IN  UINT8                               EndPointAddress,\r
+  IN  UINT8                               MaxPacketLength,\r
+  IN  OUT VOID                            *Data,\r
+  IN  OUT UINTN                           *DataLength,\r
+  IN  OUT UINT8                           *DataToggle,\r
+  IN  UINTN                               TimeOut,\r
+  OUT UINT32                              *TransferResult\r
+  );\r
+/**\r
+  Retrieves the number of root hub ports.\r
+\r
+  @param[in]  PeiServices       The pointer to the PEI Services Table.\r
+  @param[in]  This              The pointer to this instance of the\r
+                                PEI_USB_HOST_CONTROLLER_PPI.\r
+  @param[out] NumOfPorts        The pointer to the number of the root hub ports.\r
+\r
+  @retval EFI_SUCCESS           The port number was retrieved successfully.\r
+  @retval EFI_INVALID_PARAMETER PortNumber is NULL.\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciGetRootHubNumOfPorts (\r
+  IN EFI_PEI_SERVICES                       **PeiServices,\r
+  IN PEI_USB_HOST_CONTROLLER_PPI           *This,\r
+  OUT UINT8                *NumOfPorts\r
+  );\r
+/**\r
+  Retrieves the current status of a USB root hub port.\r
+\r
+  @param  PeiServices            The pointer of EFI_PEI_SERVICES.\r
+  @param  This                   The pointer of PEI_USB_HOST_CONTROLLER_PPI.\r
+  @param  PortNumber             The root hub port to retrieve the state from.\r
+  @param  PortStatus             Variable to receive the port state.\r
+\r
+  @retval EFI_SUCCESS            The status of the USB root hub port specified.\r
+                                 by PortNumber was returned in PortStatus.\r
+  @retval EFI_INVALID_PARAMETER  PortNumber is invalid.\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciGetRootHubPortStatus (\r
+  IN  EFI_PEI_SERVICES             **PeiServices,\r
+  IN  PEI_USB_HOST_CONTROLLER_PPI  *This,\r
+  IN  UINT8                        PortNumber,\r
+  OUT EFI_USB_PORT_STATUS          *PortStatus\r
+  );\r
+/**\r
+\r
+  Sets a feature for the specified root hub port.\r
+\r
+  @param  This                  A pointer to the EFI_USB_HC_PROTOCOL.\r
+  @param  PortNumber            Specifies the root hub port whose feature\r
+                                is requested to be set.\r
+  @param  PortFeature           Indicates the feature selector associated\r
+                                with the feature set request.\r
+\r
+  @retval EFI_SUCCESS           The feature specified by PortFeature was set for the\r
+                                USB root hub port specified by PortNumber.\r
+  @retval EFI_DEVICE_ERROR      Set feature failed because of hardware issue\r
+  @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OhciSetRootHubPortFeature (\r
+  IN EFI_PEI_SERVICES             **PeiServices,\r
+  IN PEI_USB_HOST_CONTROLLER_PPI  *This,\r
+  IN UINT8                        PortNumber,\r
+  IN EFI_USB_PORT_FEATURE         PortFeature\r
+  );\r
+/**\r
+  Clears a feature for the specified root hub port.\r
+\r
+  @param  PeiServices           The pointer of EFI_PEI_SERVICES.\r
+  @param  This                  The pointer of PEI_USB_HOST_CONTROLLER_PPI.\r
+  @param  PortNumber            Specifies the root hub port whose feature\r
+                                is requested to be cleared.\r
+  @param  PortFeature           Indicates the feature selector associated with the\r
+                                feature clear request.\r
+\r
+  @retval EFI_SUCCESS            The feature specified by PortFeature was cleared\r
+                                 for the USB root hub port specified by PortNumber.\r
+  @retval EFI_INVALID_PARAMETER  PortNumber is invalid or PortFeature is invalid.\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+OhciClearRootHubPortFeature (\r
+  IN EFI_PEI_SERVICES             **PeiServices,\r
+  IN PEI_USB_HOST_CONTROLLER_PPI  *This,\r
+  IN UINT8                        PortNumber,\r
+  IN EFI_USB_PORT_FEATURE         PortFeature\r
+  );\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciPei.inf b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciPei.inf
new file mode 100644 (file)
index 0000000..d919b18
--- /dev/null
@@ -0,0 +1,62 @@
+## @file\r
+# OHCI USB Host Controller PEIM\r
+#\r
+# Copyright (c) 2013-2015 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = OhciPei\r
+  FILE_GUID                      = 332A0926-429B-4624-9211-A36B23DF0389\r
+  MODULE_TYPE                    = PEIM\r
+  VERSION_STRING                 = 1.0\r
+\r
+  ENTRY_POINT                    = OhcPeimEntry\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  Descriptor.h\r
+  OhcPeim.c\r
+  OhcPeim.h\r
+  OhciSched.c\r
+  OhciSched.h\r
+  OhciReg.c\r
+  OhciReg.h\r
+  OhciUrb.c\r
+  OhciUrb.h\r
+  UsbHcMem.c\r
+  UsbHcMem.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  IoLib\r
+  TimerLib\r
+  BaseMemoryLib\r
+  PeimEntryPoint\r
+  PeiServicesLib\r
+\r
+[Ppis]\r
+  gPeiUsbHostControllerPpiGuid                 # PPI ALWAYS_PRODUCED\r
+  gPeiUsbControllerPpiGuid                      # PPI ALWAYS_CONSUMED\r
+\r
+[Depex]\r
+  gEfiPeiMemoryDiscoveredPpiGuid AND gPeiUsbControllerPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciReg.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciReg.c
new file mode 100644 (file)
index 0000000..b181c3d
--- /dev/null
@@ -0,0 +1,1394 @@
+/** @file\r
+The OHCI register operation routines.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include "OhcPeim.h"\r
+\r
+/**\r
+\r
+  Get OHCI operational reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Offset                Offset of the operational reg\r
+\r
+  @retval                       Value of the register\r
+\r
+**/\r
+UINT32\r
+OhciGetOperationalReg (\r
+  IN USB_OHCI_HC_DEV         *Ohc,\r
+  IN UINT32                  Offset\r
+  )\r
+{\r
+\r
+  return MmioRead32 (Ohc->UsbHostControllerBaseAddress + Offset);\r
+\r
+}\r
+/**\r
+\r
+  Set OHCI operational reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Offset                 Offset of the operational reg\r
+  @param  Value                  Value to set\r
+\r
+  @retval EFI_SUCCESS            Value set to the reg\r
+\r
+**/\r
+\r
+\r
+EFI_STATUS\r
+OhciSetOperationalReg (\r
+  USB_OHCI_HC_DEV         *Ohc,\r
+  IN UINT32               Offset,\r
+  IN UINT32               *Value\r
+  )\r
+{\r
+  MmioWrite32(Ohc->UsbHostControllerBaseAddress + Offset, *Value);\r
+  return EFI_SUCCESS;\r
+}\r
+/**\r
+\r
+  Get HcRevision reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+\r
+  @retval                       Value of the register\r
+\r
+**/\r
+\r
+\r
+UINT32\r
+OhciGetHcRevision (\r
+  USB_OHCI_HC_DEV         *Ohc\r
+  )\r
+{\r
+  return OhciGetOperationalReg (Ohc, HC_REVISION);\r
+}\r
+/**\r
+\r
+  Set HcReset reg value\r
+\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval EFI_SUCCESS           Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetHcReset (\r
+  IN USB_OHCI_HC_DEV            *Ohc,\r
+  IN UINT32                     Field,\r
+  IN UINT32                     Value\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  HcRESET                       Reset;\r
+\r
+  Status = EFI_SUCCESS;\r
+  *(UINT32 *) &Reset = OhciGetOperationalReg (Ohc, USBHOST_OFFSET_UHCHR);\r
+\r
+  if (Field & RESET_SYSTEM_BUS) {\r
+    Reset.FSBIR = Value;\r
+  }\r
+\r
+  if (Field & RESET_HOST_CONTROLLER) {\r
+    Reset.FHR = Value;\r
+  }\r
+\r
+  if (Field & RESET_CLOCK_GENERATION) {\r
+    Reset.CGR = Value;\r
+  }\r
+\r
+  if (Field & RESET_SSE_GLOBAL) {\r
+    Reset.SSE = Value;\r
+  }\r
+\r
+  if (Field & RESET_PSPL) {\r
+    Reset.PSPL = Value;\r
+  }\r
+\r
+  if (Field & RESET_PCPL) {\r
+    Reset.PCPL = Value;\r
+  }\r
+\r
+  if (Field & RESET_SSEP1) {\r
+    Reset.SSEP1 = Value;\r
+  }\r
+\r
+  if (Field & RESET_SSEP2) {\r
+    Reset.SSEP2 = Value;\r
+  }\r
+\r
+  if (Field & RESET_SSEP3) {\r
+    Reset.SSEP3 = Value;\r
+  }\r
+\r
+  OhciSetOperationalReg (Ohc, USBHOST_OFFSET_UHCHR, (UINT32*)&Reset);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Get specific field of HcReset reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetHcReset (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Field\r
+  )\r
+{\r
+  HcRESET                 Reset;\r
+  UINT32                  Value;\r
+\r
+\r
+  *(UINT32 *) &Reset = OhciGetOperationalReg (Ohc, USBHOST_OFFSET_UHCHR);\r
+  Value = 0;\r
+\r
+  switch (Field) {\r
+  case RESET_SYSTEM_BUS:\r
+    Value = Reset.FSBIR;\r
+    break;\r
+\r
+  case RESET_HOST_CONTROLLER:\r
+    Value = Reset.FHR;\r
+    break;\r
+\r
+  case RESET_CLOCK_GENERATION:\r
+    Value = Reset.CGR;\r
+    break;\r
+\r
+  case RESET_SSE_GLOBAL:\r
+    Value = Reset.SSE;\r
+    break;\r
+\r
+  case RESET_PSPL:\r
+    Value = Reset.PSPL;\r
+    break;\r
+\r
+  case RESET_PCPL:\r
+    Value = Reset.PCPL;\r
+    break;\r
+\r
+  case RESET_SSEP1:\r
+    Value = Reset.SSEP1;\r
+    break;\r
+\r
+  case RESET_SSEP2:\r
+    Value = Reset.SSEP2;\r
+    break;\r
+\r
+  case RESET_SSEP3:\r
+    Value = Reset.SSEP3;\r
+    break;\r
+\r
+  default:\r
+    ASSERT (FALSE);\r
+  }\r
+\r
+\r
+  return Value;\r
+}\r
+\r
+/**\r
+\r
+  Set HcControl reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetHcControl (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  HcCONTROL               Control;\r
+\r
+\r
+\r
+  *(UINT32 *) &Control = OhciGetOperationalReg (Ohc, HC_CONTROL);\r
+\r
+  if (Field & CONTROL_BULK_RATIO) {\r
+    Control.ControlBulkRatio = Value;\r
+  }\r
+\r
+  if (Field & HC_FUNCTIONAL_STATE) {\r
+    Control.FunctionalState = Value;\r
+  }\r
+\r
+  if (Field & PERIODIC_ENABLE) {\r
+    Control.PeriodicEnable = Value;\r
+  }\r
+\r
+  if (Field & CONTROL_ENABLE) {\r
+    Control.ControlEnable = Value;\r
+  }\r
+\r
+  if (Field & ISOCHRONOUS_ENABLE) {\r
+    Control.IsochronousEnable = Value;\r
+  }\r
+\r
+  if (Field & BULK_ENABLE) {\r
+    Control.BulkEnable = Value;\r
+  }\r
+\r
+  if (Field & INTERRUPT_ROUTING) {\r
+    Control.InterruptRouting = Value;\r
+  }\r
+\r
+  Status = OhciSetOperationalReg (Ohc, HC_CONTROL, (UINT32*)&Control);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Get specific field of HcControl reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+\r
+UINT32\r
+OhciGetHcControl (\r
+  IN USB_OHCI_HC_DEV   *Ohc,\r
+  IN UINTN             Field\r
+  )\r
+{\r
+  HcCONTROL     Control;\r
+\r
+  *(UINT32 *) &Control = OhciGetOperationalReg (Ohc, HC_CONTROL);\r
+\r
+  switch (Field) {\r
+  case CONTROL_BULK_RATIO:\r
+    return Control.ControlBulkRatio;\r
+    break;\r
+  case PERIODIC_ENABLE:\r
+    return Control.PeriodicEnable;\r
+    break;\r
+  case CONTROL_ENABLE:\r
+    return Control.ControlEnable;\r
+    break;\r
+  case BULK_ENABLE:\r
+    return Control.BulkEnable;\r
+    break;\r
+  case ISOCHRONOUS_ENABLE:\r
+    return Control.IsochronousEnable;\r
+    break;\r
+  case HC_FUNCTIONAL_STATE:\r
+    return Control.FunctionalState;\r
+    break;\r
+  case INTERRUPT_ROUTING:\r
+    return Control.InterruptRouting;\r
+    break;\r
+  default:\r
+    ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+\r
+  Set HcCommand reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval EFI_SUCCESS           Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetHcCommandStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  HcCOMMAND_STATUS        CommandStatus;\r
+\r
+  ZeroMem (&CommandStatus, sizeof (HcCOMMAND_STATUS));\r
+\r
+  if(Field & HC_RESET){\r
+    CommandStatus.HcReset = Value;\r
+  }\r
+\r
+  if(Field & CONTROL_LIST_FILLED){\r
+    CommandStatus.ControlListFilled = Value;\r
+  }\r
+\r
+  if(Field & BULK_LIST_FILLED){\r
+    CommandStatus.BulkListFilled = Value;\r
+  }\r
+\r
+  if(Field & CHANGE_OWNER_REQUEST){\r
+    CommandStatus.ChangeOwnerRequest = Value;\r
+  }\r
+\r
+  if(Field & SCHEDULE_OVERRUN_COUNT){\r
+    CommandStatus.ScheduleOverrunCount = Value;\r
+  }\r
+\r
+  Status = OhciSetOperationalReg (Ohc, HC_COMMAND_STATUS, (UINT32*)&CommandStatus);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Get specific field of HcCommand reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetHcCommandStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  )\r
+{\r
+  HcCOMMAND_STATUS        CommandStatus;\r
+\r
+  *(UINT32 *) &CommandStatus = OhciGetOperationalReg (Ohc, HC_COMMAND_STATUS);\r
+\r
+  switch (Field){\r
+  case HC_RESET:\r
+    return CommandStatus.HcReset;\r
+    break;\r
+  case CONTROL_LIST_FILLED:\r
+    return CommandStatus.ControlListFilled;\r
+    break;\r
+  case BULK_LIST_FILLED:\r
+    return CommandStatus.BulkListFilled;\r
+    break;\r
+  case CHANGE_OWNER_REQUEST:\r
+    return CommandStatus.ChangeOwnerRequest;\r
+    break;\r
+  case SCHEDULE_OVERRUN_COUNT:\r
+    return CommandStatus.ScheduleOverrunCount;\r
+    break;\r
+  default:\r
+    ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+\r
+  Clear specific fields of Interrupt Status\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to clear\r
+\r
+  @retval EFI_SUCCESS           Fields cleared\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciClearInterruptStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  HcINTERRUPT_STATUS      InterruptStatus;\r
+\r
+  ZeroMem (&InterruptStatus, sizeof (HcINTERRUPT_STATUS));\r
+\r
+  if(Field & SCHEDULE_OVERRUN){\r
+    InterruptStatus.SchedulingOverrun = 1;\r
+  }\r
+\r
+  if(Field & WRITEBACK_DONE_HEAD){\r
+    InterruptStatus.WriteBackDone = 1;\r
+  }\r
+  if(Field & START_OF_FRAME){\r
+    InterruptStatus.Sof = 1;\r
+  }\r
+\r
+  if(Field & RESUME_DETECT){\r
+    InterruptStatus.ResumeDetected = 1;\r
+  }\r
+\r
+  if(Field & UNRECOVERABLE_ERROR){\r
+    InterruptStatus.UnrecoverableError = 1;\r
+  }\r
+\r
+  if(Field & FRAME_NUMBER_OVERFLOW){\r
+    InterruptStatus.FrameNumOverflow = 1;\r
+  }\r
+\r
+  if(Field & ROOTHUB_STATUS_CHANGE){\r
+    InterruptStatus.RHStatusChange = 1;\r
+  }\r
+\r
+  if(Field & OWNERSHIP_CHANGE){\r
+    InterruptStatus.OwnerChange = 1;\r
+  }\r
+\r
+  Status = OhciSetOperationalReg (Ohc, HC_INTERRUPT_STATUS, (UINT32*)&InterruptStatus);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Get fields of HcInterrupt reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetHcInterruptStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  )\r
+{\r
+  HcINTERRUPT_STATUS      InterruptStatus;\r
+\r
+  *(UINT32 *) &InterruptStatus = OhciGetOperationalReg (Ohc, HC_INTERRUPT_STATUS);\r
+\r
+  switch (Field){\r
+  case SCHEDULE_OVERRUN:\r
+    return InterruptStatus.SchedulingOverrun;\r
+    break;\r
+\r
+  case  WRITEBACK_DONE_HEAD:\r
+    return InterruptStatus.WriteBackDone;\r
+    break;\r
+\r
+  case START_OF_FRAME:\r
+    return InterruptStatus.Sof;\r
+    break;\r
+\r
+  case RESUME_DETECT:\r
+    return InterruptStatus.ResumeDetected;\r
+    break;\r
+\r
+  case UNRECOVERABLE_ERROR:\r
+    return InterruptStatus.UnrecoverableError;\r
+    break;\r
+\r
+  case FRAME_NUMBER_OVERFLOW:\r
+    return InterruptStatus.FrameNumOverflow;\r
+    break;\r
+\r
+  case ROOTHUB_STATUS_CHANGE:\r
+    return InterruptStatus.RHStatusChange;\r
+    break;\r
+\r
+  case OWNERSHIP_CHANGE:\r
+    return InterruptStatus.OwnerChange;\r
+    break;\r
+\r
+  default:\r
+    ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+\r
+  Set Interrupt Control reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  StatEnable            Enable or Disable\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval EFI_SUCCESS           Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetInterruptControl (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN BOOLEAN              StatEnable,\r
+  IN UINTN                Field,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  HcINTERRUPT_CONTROL     InterruptState;\r
+\r
+\r
+  ZeroMem (&InterruptState, sizeof (HcINTERRUPT_CONTROL));\r
+\r
+  if(Field & SCHEDULE_OVERRUN) {\r
+    InterruptState.SchedulingOverrunInt = Value;\r
+  }\r
+\r
+  if(Field & WRITEBACK_DONE_HEAD) {\r
+    InterruptState.WriteBackDoneInt = Value;\r
+  }\r
+  if(Field & START_OF_FRAME) {\r
+    InterruptState.SofInt = Value;\r
+  }\r
+\r
+  if(Field & RESUME_DETECT) {\r
+    InterruptState.ResumeDetectedInt = Value;\r
+  }\r
+\r
+  if(Field & UNRECOVERABLE_ERROR) {\r
+    InterruptState.UnrecoverableErrorInt = Value;\r
+  }\r
+\r
+  if(Field & FRAME_NUMBER_OVERFLOW) {\r
+    InterruptState.FrameNumOverflowInt = Value;\r
+  }\r
+\r
+  if(Field & ROOTHUB_STATUS_CHANGE) {\r
+    InterruptState.RHStatusChangeInt = Value;\r
+  }\r
+\r
+  if(Field & OWNERSHIP_CHANGE) {\r
+    InterruptState.OwnerChangedInt = Value;\r
+  }\r
+\r
+  if(Field & MASTER_INTERRUPT) {\r
+    InterruptState.MasterInterruptEnable = Value;\r
+  }\r
+\r
+  if (StatEnable) {\r
+    Status = OhciSetOperationalReg (Ohc, HC_INTERRUPT_ENABLE, (UINT32*)&InterruptState);\r
+  } else {\r
+    Status = OhciSetOperationalReg (Ohc, HC_INTERRUPT_DISABLE, (UINT32*)&InterruptState);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Get field of HcInterruptControl reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetHcInterruptControl (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  )\r
+{\r
+  HcINTERRUPT_CONTROL     InterruptState;\r
+\r
+  *(UINT32 *) &InterruptState = OhciGetOperationalReg (Ohc, HC_INTERRUPT_ENABLE);\r
+\r
+  switch (Field){\r
+    case SCHEDULE_OVERRUN:\r
+      return InterruptState.SchedulingOverrunInt;\r
+      break;\r
+\r
+    case WRITEBACK_DONE_HEAD:\r
+      return InterruptState.WriteBackDoneInt;\r
+      break;\r
+\r
+    case START_OF_FRAME:\r
+      return InterruptState.SofInt;\r
+      break;\r
+\r
+    case RESUME_DETECT:\r
+      return InterruptState.ResumeDetectedInt;\r
+      break;\r
+\r
+    case UNRECOVERABLE_ERROR:\r
+      return InterruptState.UnrecoverableErrorInt;\r
+      break;\r
+\r
+    case FRAME_NUMBER_OVERFLOW:\r
+      return InterruptState.FrameNumOverflowInt;\r
+      break;\r
+\r
+    case ROOTHUB_STATUS_CHANGE:\r
+      return InterruptState.RHStatusChangeInt;\r
+      break;\r
+\r
+    case OWNERSHIP_CHANGE:\r
+      return InterruptState.OwnerChangedInt;\r
+      break;\r
+\r
+    case MASTER_INTERRUPT:\r
+      return InterruptState.MasterInterruptEnable;\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+\r
+  Set memory pointer of specific type\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  PointerType           Type of the pointer to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval EFI_SUCCESS           Memory pointer set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetMemoryPointer(\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                PointerType,\r
+  IN VOID                 *Value\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  UINT32                  Verify;\r
+\r
+  Status = OhciSetOperationalReg (Ohc, PointerType, (UINT32*)&Value);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Verify = OhciGetOperationalReg (Ohc, PointerType);\r
+\r
+  while (Verify != (UINT32) Value) {\r
+    MicroSecondDelay (HC_1_MILLISECOND);\r
+    Verify = OhciGetOperationalReg (Ohc, PointerType);\r
+  };\r
+\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Get memory pointer of specific type\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  PointerType           Type of pointer\r
+\r
+  @retval                       Memory pointer of the specific type\r
+\r
+**/\r
+\r
+VOID *\r
+OhciGetMemoryPointer (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                PointerType\r
+  )\r
+{\r
+\r
+  return (VOID *) OhciGetOperationalReg (Ohc, PointerType);\r
+}\r
+\r
+\r
+/**\r
+\r
+  Set Frame Interval value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetFrameInterval (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  HcFRM_INTERVAL          FrameInterval;\r
+\r
+\r
+  *(UINT32 *) &FrameInterval = OhciGetOperationalReg(Ohc, HC_FRM_INTERVAL);\r
+\r
+  if (Field & FRAME_INTERVAL) {\r
+    FrameInterval.FrmIntervalToggle = !FrameInterval.FrmIntervalToggle;\r
+    FrameInterval.FrameInterval = Value;\r
+  }\r
+\r
+  if (Field & FS_LARGEST_DATA_PACKET) {\r
+    FrameInterval.FSMaxDataPacket = Value;\r
+  }\r
+\r
+  if (Field & FRMINT_TOGGLE) {\r
+    FrameInterval.FrmIntervalToggle = Value;\r
+  }\r
+\r
+  Status = OhciSetOperationalReg (\r
+             Ohc,\r
+             HC_FRM_INTERVAL,\r
+             (UINT32*)&FrameInterval\r
+             );\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Get field of frame interval reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetFrameInterval (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  )\r
+{\r
+  HcFRM_INTERVAL          FrameInterval;\r
+\r
+  *(UINT32 *) &FrameInterval = OhciGetOperationalReg (Ohc, HC_FRM_INTERVAL);\r
+\r
+  switch (Field){\r
+    case FRAME_INTERVAL:\r
+      return FrameInterval.FrameInterval;\r
+      break;\r
+\r
+    case FS_LARGEST_DATA_PACKET:\r
+      return FrameInterval.FSMaxDataPacket;\r
+      break;\r
+\r
+    case FRMINT_TOGGLE:\r
+      return FrameInterval.FrmIntervalToggle;\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+\r
+  Set Frame Remaining reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetFrameRemaining (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  HcFRAME_REMAINING       FrameRemaining;\r
+\r
+\r
+  *(UINT32 *) &FrameRemaining = OhciGetOperationalReg (Ohc, HC_FRM_REMAINING);\r
+\r
+  FrameRemaining.FrameRemaining = Value;\r
+  FrameRemaining.FrameRemainingToggle = !FrameRemaining.FrameRemainingToggle;\r
+\r
+  Status = OhciSetOperationalReg (Ohc, HC_FRM_REMAINING, (UINT32*)&FrameRemaining);\r
+\r
+  return Status;\r
+}\r
+/**\r
+\r
+  Get value of frame remaining reg\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of frame remaining reg\r
+\r
+**/\r
+UINT32\r
+OhciGetFrameRemaining (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  )\r
+\r
+{\r
+  HcFRAME_REMAINING       FrameRemaining;\r
+\r
+\r
+  *(UINT32 *) &FrameRemaining = OhciGetOperationalReg (Ohc, HC_FRM_REMAINING);\r
+\r
+  switch (Field){\r
+    case FRAME_REMAINING:\r
+      return FrameRemaining.FrameRemaining;\r
+      break;\r
+\r
+    case FRAME_REMAIN_TOGGLE:\r
+      return FrameRemaining.FrameRemainingToggle;\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+\r
+  Set frame number reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetFrameNumber(\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+\r
+  Status = OhciSetOperationalReg (Ohc, HC_FRM_NUMBER, &Value);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Get frame number reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+\r
+  @retval                       Value of frame number reg\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetFrameNumber (\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  )\r
+{\r
+  return OhciGetOperationalReg(Ohc, HC_FRM_NUMBER);\r
+}\r
+\r
+/**\r
+\r
+  Set period start reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Value                 Value to set\r
+\r
+  @retval EFI_SUCCESS           Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetPeriodicStart (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+\r
+\r
+  Status = OhciSetOperationalReg (Ohc, HC_PERIODIC_START, &Value);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Get periodic start reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+\r
+  @param                        Value of periodic start reg\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetPeriodicStart (\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  )\r
+{\r
+  return OhciGetOperationalReg(Ohc, HC_PERIODIC_START);\r
+}\r
+\r
+\r
+/**\r
+\r
+  Set Ls Threshold reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetLsThreshold (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+\r
+\r
+  Status = OhciSetOperationalReg (Ohc, HC_LS_THREASHOLD, &Value);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Get Ls Threshold reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+\r
+  @retval                       Value of Ls Threshold reg\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetLsThreshold (\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  )\r
+{\r
+  return OhciGetOperationalReg(Ohc, HC_LS_THREASHOLD);\r
+}\r
+\r
+/**\r
+\r
+  Set Root Hub Descriptor reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+EFI_STATUS\r
+OhciSetRootHubDescriptor (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  HcRH_DESC_A             DescriptorA;\r
+  HcRH_DESC_B             DescriptorB;\r
+\r
+\r
+  if (Field & (RH_DEV_REMOVABLE || RH_PORT_PWR_CTRL_MASK)) {\r
+    *(UINT32 *) &DescriptorB = OhciGetOperationalReg (Ohc, HC_RH_DESC_B);\r
+\r
+    if(Field & RH_DEV_REMOVABLE) {\r
+      DescriptorB.DeviceRemovable = Value;\r
+    }\r
+    if(Field & RH_PORT_PWR_CTRL_MASK) {\r
+      DescriptorB.PortPowerControlMask = Value;\r
+    }\r
+\r
+    Status = OhciSetOperationalReg (Ohc, HC_RH_DESC_B, (UINT32*)&DescriptorB);\r
+\r
+    return Status;\r
+  }\r
+\r
+  *(UINT32 *)&DescriptorA = OhciGetOperationalReg (Ohc, HC_RH_DESC_A);\r
+\r
+  if(Field & RH_NUM_DS_PORTS) {\r
+    DescriptorA.NumDownStrmPorts = Value;\r
+  }\r
+  if(Field & RH_NO_PSWITCH) {\r
+    DescriptorA.NoPowerSwitch = Value;\r
+  }\r
+  if(Field & RH_PSWITCH_MODE) {\r
+    DescriptorA.PowerSwitchMode = Value;\r
+  }\r
+  if(Field & RH_DEVICE_TYPE) {\r
+    DescriptorA.DeviceType = Value;\r
+  }\r
+  if(Field & RH_OC_PROT_MODE) {\r
+    DescriptorA.OverCurrentProtMode = Value;\r
+  }\r
+  if(Field & RH_NOC_PROT) {\r
+    DescriptorA.NoOverCurrentProtMode = Value;\r
+  }\r
+  if(Field & RH_NO_POTPGT) {\r
+    DescriptorA.PowerOnToPowerGoodTime = Value;\r
+  }\r
+\r
+  Status = OhciSetOperationalReg (Ohc, HC_RH_DESC_A, (UINT32*)&DescriptorA);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Get Root Hub Descriptor reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetRootHubDescriptor (\r
+  IN USB_OHCI_HC_DEV     *Ohc,\r
+  IN UINTN               Field\r
+  )\r
+{\r
+  HcRH_DESC_A             DescriptorA;\r
+  HcRH_DESC_B             DescriptorB;\r
+\r
+\r
+  *(UINT32 *) &DescriptorA = OhciGetOperationalReg (Ohc, HC_RH_DESC_A);\r
+  *(UINT32 *) &DescriptorB = OhciGetOperationalReg (Ohc, HC_RH_DESC_B);\r
+\r
+  switch (Field){\r
+    case RH_DEV_REMOVABLE:\r
+      return DescriptorB.DeviceRemovable;\r
+      break;\r
+\r
+    case RH_PORT_PWR_CTRL_MASK:\r
+      return DescriptorB.PortPowerControlMask;\r
+      break;\r
+\r
+    case RH_NUM_DS_PORTS:\r
+      return DescriptorA.NumDownStrmPorts;\r
+      break;\r
+\r
+    case RH_NO_PSWITCH:\r
+      return DescriptorA.NoPowerSwitch;\r
+      break;\r
+\r
+    case RH_PSWITCH_MODE:\r
+      return DescriptorA.PowerSwitchMode;\r
+      break;\r
+\r
+    case RH_DEVICE_TYPE:\r
+      return DescriptorA.DeviceType;\r
+      break;\r
+\r
+    case RH_OC_PROT_MODE:\r
+      return DescriptorA.OverCurrentProtMode;\r
+      break;\r
+\r
+    case RH_NOC_PROT:\r
+      return DescriptorA.NoOverCurrentProtMode;\r
+      break;\r
+\r
+    case RH_NO_POTPGT:\r
+      return DescriptorA.PowerOnToPowerGoodTime;\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Set Root Hub Status reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetRootHubStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  HcRH_STATUS             RootHubStatus;\r
+\r
+\r
+  ZeroMem (&RootHubStatus, sizeof(HcRH_STATUS));\r
+\r
+  if(Field & RH_LOCAL_PSTAT){\r
+    RootHubStatus.LocalPowerStat = 1;\r
+  }\r
+  if(Field & RH_OC_ID){\r
+    RootHubStatus.OverCurrentIndicator = 1;\r
+  }\r
+  if(Field & RH_REMOTE_WK_ENABLE){\r
+    RootHubStatus.DevRemoteWakeupEnable = 1;\r
+  }\r
+  if(Field & RH_LOCAL_PSTAT_CHANGE){\r
+    RootHubStatus.LocalPowerStatChange = 1;\r
+  }\r
+  if(Field & RH_OC_ID_CHANGE){\r
+    RootHubStatus.OverCurrentIndicatorChange = 1;\r
+  }\r
+  if(Field & RH_CLR_RMT_WK_ENABLE){\r
+    RootHubStatus.ClearRemoteWakeupEnable = 1;\r
+  }\r
+\r
+  Status = OhciSetOperationalReg (Ohc, HC_RH_STATUS, (UINT32*)&RootHubStatus);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Get Root Hub Status reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetRootHubStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  )\r
+{\r
+  HcRH_STATUS             RootHubStatus;\r
+\r
+\r
+  *(UINT32 *) &RootHubStatus = OhciGetOperationalReg (Ohc, HC_RH_STATUS);\r
+\r
+  switch (Field) {\r
+    case RH_LOCAL_PSTAT:\r
+      return RootHubStatus.LocalPowerStat;\r
+      break;\r
+    case RH_OC_ID:\r
+      return RootHubStatus.OverCurrentIndicator;\r
+      break;\r
+    case RH_REMOTE_WK_ENABLE:\r
+      return RootHubStatus.DevRemoteWakeupEnable;\r
+      break;\r
+    case RH_LOCAL_PSTAT_CHANGE:\r
+      return RootHubStatus.LocalPowerStatChange;\r
+      break;\r
+    case RH_OC_ID_CHANGE:\r
+      return RootHubStatus.OverCurrentIndicatorChange;\r
+      break;\r
+    case RH_CLR_RMT_WK_ENABLE:\r
+      return RootHubStatus.ClearRemoteWakeupEnable;\r
+      break;\r
+    default:\r
+      ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Set Root Hub Port Status reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Index                 Index of the port\r
+  @param  Field                 Field to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetRootHubPortStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Index,\r
+  IN UINTN                Field\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  HcRHPORT_STATUS         PortStatus;\r
+\r
+\r
+  ZeroMem (&PortStatus, sizeof(HcRHPORT_STATUS));\r
+\r
+  if (Field & RH_CLEAR_PORT_ENABLE) {\r
+    PortStatus.CurrentConnectStat = 1;\r
+  }\r
+  if (Field & RH_SET_PORT_ENABLE) {\r
+    PortStatus.EnableStat = 1;\r
+  }\r
+  if (Field & RH_SET_PORT_SUSPEND) {\r
+    PortStatus.SuspendStat = 1;\r
+  }\r
+  if (Field & RH_CLEAR_SUSPEND_STATUS) {\r
+    PortStatus.OCIndicator = 1;\r
+  }\r
+  if (Field & RH_SET_PORT_RESET) {\r
+    PortStatus.ResetStat = 1;\r
+  }\r
+  if (Field & RH_SET_PORT_POWER) {\r
+    PortStatus.PowerStat = 1;\r
+  }\r
+  if (Field & RH_CLEAR_PORT_POWER) {\r
+    PortStatus.LsDeviceAttached = 1;\r
+  }\r
+  if (Field & RH_CONNECT_STATUS_CHANGE) {\r
+    PortStatus.ConnectStatChange = 1;\r
+  }\r
+  if (Field & RH_PORT_ENABLE_STAT_CHANGE) {\r
+    PortStatus.EnableStatChange = 1;\r
+  }\r
+  if (Field & RH_PORT_SUSPEND_STAT_CHANGE) {\r
+    PortStatus.SuspendStatChange = 1;\r
+  }\r
+  if (Field & RH_OC_INDICATOR_CHANGE) {\r
+    PortStatus.OCIndicatorChange = 1;\r
+  }\r
+  if (Field & RH_PORT_RESET_STAT_CHANGE ) {\r
+    PortStatus.ResetStatChange = 1;\r
+  }\r
+\r
+  Status = OhciSetOperationalReg (Ohc, HC_RH_PORT_STATUS + (Index * 4), (UINT32*)&PortStatus);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Get Root Hub Port Status reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Index                 Index of the port\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field and index\r
+\r
+**/\r
+\r
+UINT32\r
+OhciReadRootHubPortStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Index,\r
+  IN UINTN                Field\r
+  )\r
+{\r
+  HcRHPORT_STATUS         PortStatus;\r
+\r
+  *(UINT32 *) &PortStatus = OhciGetOperationalReg (\r
+                              Ohc,\r
+                              HC_RH_PORT_STATUS + (Index * 4)\r
+                              );\r
+\r
+  switch (Field){\r
+  case RH_CURR_CONNECT_STAT:\r
+    return PortStatus.CurrentConnectStat;\r
+    break;\r
+  case RH_PORT_ENABLE_STAT:\r
+    return PortStatus.EnableStat;\r
+    break;\r
+  case RH_PORT_SUSPEND_STAT:\r
+    return PortStatus.SuspendStat;\r
+    break;\r
+  case RH_PORT_OC_INDICATOR:\r
+    return PortStatus.OCIndicator;\r
+    break;\r
+  case RH_PORT_RESET_STAT:\r
+    return PortStatus.ResetStat;\r
+    break;\r
+  case RH_PORT_POWER_STAT:\r
+    return PortStatus.PowerStat;\r
+    break;\r
+  case RH_LSDEVICE_ATTACHED:\r
+    return PortStatus.LsDeviceAttached;\r
+    break;\r
+  case RH_CONNECT_STATUS_CHANGE:\r
+    return PortStatus.ConnectStatChange;\r
+    break;\r
+  case RH_PORT_ENABLE_STAT_CHANGE:\r
+    return PortStatus.EnableStatChange;\r
+    break;\r
+  case RH_PORT_SUSPEND_STAT_CHANGE:\r
+    return PortStatus.SuspendStatChange;\r
+    break;\r
+  case RH_OC_INDICATOR_CHANGE:\r
+    return PortStatus.OCIndicatorChange;\r
+    break;\r
+  case RH_PORT_RESET_STAT_CHANGE:\r
+    return PortStatus.ResetStatChange;\r
+    break;\r
+  default:\r
+    ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciReg.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciReg.h
new file mode 100644 (file)
index 0000000..0f1d033
--- /dev/null
@@ -0,0 +1,881 @@
+/** @file\r
+This file contains the definination for host controller\r
+register operation routines.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+\r
+#ifndef   _OHCI_REGS_H\r
+#define   _OHCI_REGS_H\r
+\r
+#define   HC_STATE_RESET         0x0\r
+#define   HC_STATE_RESUME        0x1\r
+#define   HC_STATE_OPERATIONAL   0x2\r
+#define   HC_STATE_SUSPEND       0x3\r
+\r
+#define   PERIODIC_ENABLE               0x01\r
+#define   ISOCHRONOUS_ENABLE            0x02\r
+#define   CONTROL_ENABLE                0x04\r
+#define   BULK_ENABLE                   0x08\r
+#define   CONTROL_BULK_RATIO            0x10\r
+\r
+#define   HC_FUNCTIONAL_STATE    0x20\r
+#define   INTERRUPT_ROUTING      0x40\r
+\r
+#define   HC_RESET               0x01\r
+#define   CONTROL_LIST_FILLED    0x02\r
+#define   BULK_LIST_FILLED       0x04\r
+#define   CHANGE_OWNER_REQUEST   0x08\r
+\r
+#define   SCHEDULE_OVERRUN_COUNT 0x10\r
+\r
+#define   SCHEDULE_OVERRUN       0x00001\r
+#define   WRITEBACK_DONE_HEAD    0x00002\r
+#define   START_OF_FRAME         0x00004\r
+#define   RESUME_DETECT          0x00008\r
+#define   UNRECOVERABLE_ERROR    0x00010\r
+#define   FRAME_NUMBER_OVERFLOW  0x00020\r
+#define   ROOTHUB_STATUS_CHANGE  0x00040\r
+#define   OWNERSHIP_CHANGE       0x00080\r
+\r
+#define   MASTER_INTERRUPT       0x00400\r
+\r
+#define   CONTROL_HEAD           0x001\r
+#define   BULK_HEAD              0x002\r
+#define   DONE_HEAD              0x004\r
+\r
+#define   Hc_HCCA                0x001\r
+#define   Hc_PERIODIC_CURRENT    0x002\r
+#define   Hc_CONTOL_HEAD         0x004\r
+#define   Hc_CONTROL_CURRENT_PTR 0x008\r
+#define   Hc_BULK_HEAD           0x010\r
+#define   Hc_BULK_CURRENT_PTR    0x020\r
+#define   Hc_DONE_HEAD           0x040\r
+\r
+#define   FRAME_INTERVAL         0x008\r
+#define   FS_LARGEST_DATA_PACKET 0x010\r
+#define   FRMINT_TOGGLE          0x020\r
+#define   FRAME_REMAINING        0x040\r
+#define   FRAME_REMAIN_TOGGLE    0x080\r
+\r
+#define   RH_DESC_A              0x00001\r
+#define   RH_DESC_B              0x00002\r
+#define   RH_NUM_DS_PORTS        0x00004\r
+#define   RH_NO_PSWITCH          0x00008\r
+#define   RH_PSWITCH_MODE        0x00010\r
+#define   RH_DEVICE_TYPE         0x00020\r
+#define   RH_OC_PROT_MODE        0x00040\r
+#define   RH_NOC_PROT            0x00080\r
+#define   RH_POTPGT              0x00100\r
+#define   RH_NO_POTPGT           0x00200\r
+#define   RH_DEV_REMOVABLE       0x00400\r
+#define   RH_PORT_PWR_CTRL_MASK  0x00800\r
+\r
+#define   RH_LOCAL_PSTAT         0x00001\r
+#define   RH_OC_ID               0x00002\r
+#define   RH_REMOTE_WK_ENABLE    0x00004\r
+#define   RH_LOCAL_PSTAT_CHANGE  0x00008\r
+#define   RH_OC_ID_CHANGE        0x00010\r
+#define   RH_CLR_RMT_WK_ENABLE   0x00020\r
+\r
+#define   RH_CLEAR_PORT_ENABLE        0x0001\r
+#define   RH_SET_PORT_ENABLE          0x0002\r
+#define   RH_SET_PORT_SUSPEND         0x0004\r
+#define   RH_CLEAR_SUSPEND_STATUS     0x0008\r
+#define   RH_SET_PORT_RESET           0x0010\r
+#define   RH_SET_PORT_POWER           0x0020\r
+#define   RH_CLEAR_PORT_POWER         0x0040\r
+#define   RH_CONNECT_STATUS_CHANGE    0x10000\r
+#define   RH_PORT_ENABLE_STAT_CHANGE  0x20000\r
+#define   RH_PORT_SUSPEND_STAT_CHANGE 0x40000\r
+#define   RH_OC_INDICATOR_CHANGE      0x80000\r
+#define   RH_PORT_RESET_STAT_CHANGE   0x100000\r
+\r
+#define   RH_CURR_CONNECT_STAT        0x0001\r
+#define   RH_PORT_ENABLE_STAT         0x0002\r
+#define   RH_PORT_SUSPEND_STAT        0x0004\r
+#define   RH_PORT_OC_INDICATOR        0x0008\r
+#define   RH_PORT_RESET_STAT          0x0010\r
+#define   RH_PORT_POWER_STAT          0x0020\r
+#define   RH_LSDEVICE_ATTACHED        0x0040\r
+\r
+#define   RESET_SYSTEM_BUS            (1 << 0)\r
+#define   RESET_HOST_CONTROLLER       (1 << 1)\r
+#define   RESET_CLOCK_GENERATION      (1 << 2)\r
+#define   RESET_SSE_GLOBAL            (1 << 5)\r
+#define   RESET_PSPL                  (1 << 6)\r
+#define   RESET_PCPL                  (1 << 7)\r
+#define   RESET_SSEP1                 (1 << 9)\r
+#define   RESET_SSEP2                 (1 << 10)\r
+#define   RESET_SSEP3                 (1 << 11)\r
+\r
+#define ONE_SECOND                      1000000\r
+#define ONE_MILLI_SEC                   1000\r
+#define MAX_BYTES_PER_TD                0x1000\r
+#define MAX_RETRY_TIMES                 100\r
+#define PORT_NUMBER_ON_MAINSTONE2       1\r
+\r
+\r
+//\r
+// Operational Register Offsets\r
+//\r
+\r
+//\r
+// Command & Status Registers Offsets\r
+//\r
+#define HC_REVISION             0x00\r
+#define HC_CONTROL              0x04\r
+#define HC_COMMAND_STATUS       0x08\r
+#define HC_INTERRUPT_STATUS     0x0C\r
+#define HC_INTERRUPT_ENABLE     0x10\r
+#define HC_INTERRUPT_DISABLE    0x14\r
+\r
+//\r
+// Memory Pointer Offsets\r
+//\r
+#define HC_HCCA                 0x18\r
+#define HC_PERIODIC_CURRENT     0x1C\r
+#define HC_CONTROL_HEAD         0x20\r
+#define HC_CONTROL_CURRENT_PTR  0x24\r
+#define HC_BULK_HEAD            0x28\r
+#define HC_BULK_CURRENT_PTR     0x2C\r
+#define HC_DONE_HEAD            0x30\r
+\r
+//\r
+// Frame Register Offsets\r
+//\r
+#define HC_FRM_INTERVAL         0x34\r
+#define HC_FRM_REMAINING        0x38\r
+#define HC_FRM_NUMBER           0x3C\r
+#define HC_PERIODIC_START       0x40\r
+#define HC_LS_THREASHOLD        0x44\r
+\r
+//\r
+// Root Hub Register Offsets\r
+//\r
+#define HC_RH_DESC_A            0x48\r
+#define HC_RH_DESC_B            0x4C\r
+#define HC_RH_STATUS            0x50\r
+#define HC_RH_PORT_STATUS       0x54\r
+\r
+#define USBHOST_OFFSET_UHCHR         0x64         // Usb Host reset register\r
+\r
+#define OHC_BAR_INDEX               0\r
+\r
+//\r
+// Usb Host controller register offset\r
+//\r
+#define USBHOST_OFFSET_UHCREV        0x0          // Usb Host revision register\r
+#define USBHOST_OFFSET_UHCHCON       0x4          // Usb Host control register\r
+#define USBHOST_OFFSET_UHCCOMS       0x8          // Usb Host Command Status register\r
+#define USBHOST_OFFSET_UHCINTS       0xC          // Usb Host Interrupt Status register\r
+#define USBHOST_OFFSET_UHCINTE       0x10         // Usb Host Interrupt Enable register\r
+#define USBHOST_OFFSET_UHCINTD       0x14         // Usb Host Interrupt Disable register\r
+#define USBHOST_OFFSET_UHCHCCA       0x18         // Usb Host Controller Communication Area\r
+#define USBHOST_OFFSET_UHCPCED       0x1C         // Usb Host Period Current Endpoint Descriptor\r
+#define USBHOST_OFFSET_UHCCHED       0x20         // Usb Host Control Head Endpoint Descriptor\r
+#define USBHOST_OFFSET_UHCCCED       0x24         // Usb Host Control Current Endpoint Descriptor\r
+#define USBHOST_OFFSET_UHCBHED       0x28         // Usb Host Bulk Head Endpoint Descriptor\r
+#define USBHOST_OFFSET_UHCBCED       0x2C         // Usb Host Bulk Current Endpoint Descriptor\r
+#define USBHOST_OFFSET_UHCDHEAD      0x30         // Usb Host Done Head register\r
+#define USBHOST_OFFSET_UHCFMI        0x34         // Usb Host Frame Interval register\r
+#define USBHOST_OFFSET_UHCFMR        0x38         // Usb Host Frame Remaining register\r
+#define USBHOST_OFFSET_UHCFMN        0x3C         // Usb Host Frame Number register\r
+#define USBHOST_OFFSET_UHCPERS       0x40         // Usb Host Periodic Start register\r
+#define USBHOST_OFFSET_UHCLST        0x44         // Usb Host Low-Speed Threshold register\r
+#define USBHOST_OFFSET_UHCRHDA       0x48         // Usb Host Root Hub Descriptor A register\r
+#define USBHOST_OFFSET_UHCRHDB       0x4C         // Usb Host Root Hub Descriptor B register\r
+#define USBHOST_OFFSET_UHCRHS        0x50         // Usb Host Root Hub Status register\r
+#define USBHOST_OFFSET_UHCRHPS1      0x54         // Usb Host Root Hub Port Status 1 register\r
+\r
+//\r
+// Usb Host controller register bit fields\r
+//\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+  UINT8                   ProgInterface;\r
+  UINT8                   SubClassCode;\r
+  UINT8                   BaseCode;\r
+} USB_CLASSC;\r
+\r
+typedef struct {\r
+    UINT32 Revision:8;\r
+    UINT32 Rsvd:24;\r
+} HcREVISION;\r
+\r
+typedef struct {\r
+    UINT32 ControlBulkRatio:2;\r
+    UINT32 PeriodicEnable:1;\r
+    UINT32 IsochronousEnable:1;\r
+    UINT32 ControlEnable:1;\r
+    UINT32 BulkEnable:1;\r
+    UINT32 FunctionalState:2;\r
+    UINT32 InterruptRouting:1;\r
+    UINT32 RemoteWakeup:1;\r
+    UINT32 RemoteWakeupEnable:1;\r
+    UINT32 Reserved:21;\r
+} HcCONTROL;\r
+\r
+typedef struct {\r
+    UINT32 HcReset:1;\r
+    UINT32 ControlListFilled:1;\r
+    UINT32 BulkListFilled:1;\r
+    UINT32 ChangeOwnerRequest:1;\r
+    UINT32 Reserved1:12;\r
+    UINT32 ScheduleOverrunCount:2;\r
+    UINT32 Reserved:14;\r
+} HcCOMMAND_STATUS;\r
+\r
+typedef struct {\r
+    UINT32 SchedulingOverrun:1;\r
+    UINT32 WriteBackDone:1;\r
+    UINT32 Sof:1;\r
+    UINT32 ResumeDetected:1;\r
+    UINT32 UnrecoverableError:1;\r
+    UINT32 FrameNumOverflow:1;\r
+    UINT32 RHStatusChange:1;\r
+    UINT32 Reserved1:23;\r
+    UINT32 OwnerChange:1;\r
+    UINT32 Reserved2:1;\r
+} HcINTERRUPT_STATUS;\r
+\r
+typedef struct {\r
+    UINT32 SchedulingOverrunInt:1;\r
+    UINT32 WriteBackDoneInt:1;\r
+    UINT32 SofInt:1;\r
+    UINT32 ResumeDetectedInt:1;\r
+    UINT32 UnrecoverableErrorInt:1;\r
+    UINT32 FrameNumOverflowInt:1;\r
+    UINT32 RHStatusChangeInt:1;\r
+    UINT32 Reserved:23;\r
+    UINT32 OwnerChangedInt:1;\r
+    UINT32 MasterInterruptEnable:1;\r
+} HcINTERRUPT_CONTROL;\r
+\r
+typedef struct {\r
+    UINT32 Rerserved:8;\r
+    UINT32 Hcca:24;\r
+} HcHCCA;\r
+\r
+typedef struct {\r
+    UINT32 Reserved:4;\r
+    UINT32 MemoryPtr:28;\r
+} HcMEMORY_PTR;\r
+\r
+typedef struct {\r
+    UINT32 FrameInterval:14;\r
+    UINT32 Reserved:2;\r
+    UINT32 FSMaxDataPacket:15;\r
+    UINT32 FrmIntervalToggle:1;\r
+} HcFRM_INTERVAL;\r
+\r
+typedef struct {\r
+    UINT32 FrameRemaining:14;\r
+    UINT32 Reserved:17;\r
+    UINT32 FrameRemainingToggle:1;\r
+} HcFRAME_REMAINING;\r
+\r
+typedef struct {\r
+    UINT32 FrameNumber:16;\r
+    UINT32 Reserved:16;\r
+} HcFRAME_NUMBER;\r
+\r
+typedef struct {\r
+    UINT32 PeriodicStart:14;\r
+    UINT32 Reserved:18;\r
+} HcPERIODIC_START;\r
+\r
+typedef struct {\r
+    UINT32 LsThreshold:12;\r
+    UINT32 Reserved:20;\r
+} HcLS_THRESHOLD;\r
+\r
+typedef struct {\r
+    UINT32 NumDownStrmPorts:8;\r
+    UINT32 PowerSwitchMode:1;\r
+    UINT32 NoPowerSwitch:1;\r
+    UINT32 DeviceType:1;\r
+    UINT32 OverCurrentProtMode:1;\r
+    UINT32 NoOverCurrentProtMode:1;\r
+    UINT32 Reserved:11;\r
+    UINT32 PowerOnToPowerGoodTime:8;\r
+} HcRH_DESC_A;\r
+\r
+typedef struct {\r
+    UINT32 DeviceRemovable:16;\r
+    UINT32 PortPowerControlMask:16;\r
+} HcRH_DESC_B;\r
+\r
+typedef struct {\r
+    UINT32 LocalPowerStat:1;\r
+    UINT32 OverCurrentIndicator:1;\r
+    UINT32 Reserved1:13;\r
+    UINT32 DevRemoteWakeupEnable:1;\r
+    UINT32 LocalPowerStatChange:1;\r
+    UINT32 OverCurrentIndicatorChange:1;\r
+    UINT32 Reserved2:13;\r
+    UINT32 ClearRemoteWakeupEnable:1;\r
+} HcRH_STATUS;\r
+\r
+typedef struct {\r
+    UINT32 CurrentConnectStat:1;\r
+    UINT32 EnableStat:1;\r
+    UINT32 SuspendStat:1;\r
+    UINT32 OCIndicator:1;\r
+    UINT32 ResetStat:1;\r
+    UINT32 Reserved1:3;\r
+    UINT32 PowerStat:1;\r
+    UINT32 LsDeviceAttached:1;\r
+    UINT32 Reserved2:6;\r
+    UINT32 ConnectStatChange:1;\r
+    UINT32 EnableStatChange:1;\r
+    UINT32 SuspendStatChange:1;\r
+    UINT32 OCIndicatorChange:1;\r
+    UINT32 ResetStatChange:1;\r
+    UINT32 Reserved3:11;\r
+} HcRHPORT_STATUS;\r
+\r
+typedef struct {\r
+    UINT32 FSBIR:1;\r
+    UINT32 FHR:1;\r
+    UINT32 CGR:1;\r
+    UINT32 SSDC:1;\r
+    UINT32 UIT:1;\r
+    UINT32 SSE:1;\r
+    UINT32 PSPL:1;\r
+    UINT32 PCPL:1;\r
+    UINT32 Reserved0:1;\r
+    UINT32 SSEP1:1;\r
+    UINT32 SSEP2:1;\r
+    UINT32 SSEP3:1;\r
+    UINT32 Reserved1:20;\r
+} HcRESET;\r
+\r
+#pragma pack()\r
+\r
+//\r
+// Func List\r
+//\r
+/**\r
+\r
+  Get OHCI operational reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Offset                Offset of the operational reg\r
+\r
+  @retval                       Value of the register\r
+\r
+**/\r
+UINT32\r
+OhciGetOperationalReg (\r
+  IN USB_OHCI_HC_DEV         *Ohc,\r
+  IN UINT32                  Offset\r
+  );\r
+/**\r
+\r
+  Set OHCI operational reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Offset                 Offset of the operational reg\r
+  @param  Value                  Value to set\r
+\r
+  @retval EFI_SUCCESS            Value set to the reg\r
+\r
+**/\r
+EFI_STATUS\r
+OhciSetOperationalReg (\r
+  USB_OHCI_HC_DEV         *Ohc,\r
+  IN UINT32               Offset,\r
+  IN UINT32               *Value\r
+  );\r
+/**\r
+\r
+  Get HcRevision reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+\r
+  @retval                       Value of the register\r
+\r
+**/\r
+\r
+\r
+UINT32\r
+OhciGetHcRevision (\r
+  USB_OHCI_HC_DEV         *Ohc\r
+  );\r
+\r
+/**\r
+\r
+  Set HcReset reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval EFI_SUCCESS           Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetHcReset (\r
+  IN USB_OHCI_HC_DEV            *Ohc,\r
+  IN UINT32                     Field,\r
+  IN UINT32                     Value\r
+  );\r
+/**\r
+\r
+  Get specific field of HcReset reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetHcReset (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Field\r
+  );\r
+/**\r
+\r
+  Set HcControl reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetHcControl (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field,\r
+  IN UINT32               Value\r
+  );\r
+/**\r
+\r
+  Get specific field of HcControl reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+\r
+UINT32\r
+OhciGetHcControl (\r
+  IN USB_OHCI_HC_DEV   *Ohc,\r
+  IN UINTN             Field\r
+  );\r
+/**\r
+\r
+  Set HcCommand reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval EFI_SUCCESS           Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetHcCommandStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field,\r
+  IN UINT32               Value\r
+  );\r
+/**\r
+\r
+  Get specific field of HcCommand reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetHcCommandStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  );\r
+/**\r
+\r
+  Clear specific fields of Interrupt Status\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to clear\r
+\r
+  @retval EFI_SUCCESS           Fields cleared\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciClearInterruptStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  );\r
+/**\r
+\r
+  Get fields of HcInterrupt reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetHcInterruptStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  );\r
+/**\r
+\r
+  Set Interrupt Control reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  StatEnable            Enable or Disable\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval EFI_SUCCESS           Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetInterruptControl (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN BOOLEAN              StatEnable,\r
+  IN UINTN                Field,\r
+  IN UINT32               Value\r
+  );\r
+/**\r
+\r
+  Get field of HcInterruptControl reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetHcInterruptControl (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  );\r
+/**\r
+\r
+  Set memory pointer of specific type\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  PointerType           Type of the pointer to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval EFI_SUCCESS           Memory pointer set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetMemoryPointer(\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                PointerType,\r
+  IN VOID                 *Value\r
+  );\r
+/**\r
+\r
+  Get memory pointer of specific type\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  PointerType           Type of pointer\r
+\r
+  @retval                       Memory pointer of the specific type\r
+\r
+**/\r
+\r
+VOID *\r
+OhciGetMemoryPointer (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                PointerType\r
+  );\r
+/**\r
+\r
+  Set Frame Interval value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetFrameInterval (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field,\r
+  IN UINT32               Value\r
+  );\r
+/**\r
+\r
+  Get field of frame interval reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetFrameInterval (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  );\r
+/**\r
+\r
+  Set Frame Remaining reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetFrameRemaining (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Value\r
+  );\r
+/**\r
+\r
+  Get value of frame remaining reg\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of frame remaining reg\r
+\r
+**/\r
+UINT32\r
+OhciGetFrameRemaining (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  );\r
+/**\r
+\r
+  Set frame number reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetFrameNumber(\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Value\r
+  );\r
+/**\r
+\r
+  Get frame number reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+\r
+  @retval                       Value of frame number reg\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetFrameNumber (\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  );\r
+/**\r
+\r
+  Set period start reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Value                 Value to set\r
+\r
+  @retval EFI_SUCCESS           Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetPeriodicStart (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Value\r
+  );\r
+/**\r
+\r
+  Get periodic start reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+\r
+  @param                        Value of periodic start reg\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetPeriodicStart (\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  );\r
+/**\r
+\r
+  Set Ls Threshold reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetLsThreshold (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Value\r
+  );\r
+/**\r
+\r
+  Get Ls Threshold reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+\r
+  @retval                       Value of Ls Threshold reg\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetLsThreshold (\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  );\r
+/**\r
+\r
+  Set Root Hub Descriptor reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+  @param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+EFI_STATUS\r
+OhciSetRootHubDescriptor (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field,\r
+  IN UINT32               Value\r
+  );\r
+/**\r
+\r
+  Get Root Hub Descriptor reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetRootHubDescriptor (\r
+  IN USB_OHCI_HC_DEV     *Ohc,\r
+  IN UINTN               Field\r
+  );\r
+/**\r
+\r
+  Set Root Hub Status reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetRootHubStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  );\r
+/**\r
+\r
+  Get Root Hub Status reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetRootHubStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINTN                Field\r
+  );\r
+/**\r
+\r
+  Set Root Hub Port Status reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Index                 Index of the port\r
+  @param  Field                 Field to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciSetRootHubPortStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Index,\r
+  IN UINTN                Field\r
+  );\r
+/**\r
+\r
+  Get Root Hub Port Status reg value\r
+\r
+  @param  Ohc                   UHC private data\r
+  @param  Index                 Index of the port\r
+  @param  Field                 Field to get\r
+\r
+  @retval                       Value of the field and index\r
+\r
+**/\r
+\r
+UINT32\r
+OhciReadRootHubPortStatus (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN UINT32               Index,\r
+  IN UINTN                Field\r
+  );\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciSched.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciSched.c
new file mode 100644 (file)
index 0000000..49f13b6
--- /dev/null
@@ -0,0 +1,229 @@
+/** @file\r
+OHCI transfer scheduling routines.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include "OhcPeim.h"\r
+\r
+/**\r
+\r
+  Convert Error code from OHCI format to EFI format\r
+\r
+  @Param  ErrorCode             ErrorCode in OHCI format\r
+\r
+  @retval                       ErrorCode in EFI format\r
+\r
+**/\r
+UINT32\r
+ConvertErrorCode (\r
+  IN  UINT32              ErrorCode\r
+  )\r
+{\r
+  UINT32                  TransferResult;\r
+\r
+  switch (ErrorCode) {\r
+    case TD_NO_ERROR:\r
+      TransferResult = EFI_USB_NOERROR;\r
+      break;\r
+\r
+    case TD_TOBE_PROCESSED:\r
+    case TD_TOBE_PROCESSED_2:\r
+      TransferResult = EFI_USB_ERR_NOTEXECUTE;\r
+      break;\r
+\r
+    case TD_DEVICE_STALL:\r
+      TransferResult = EFI_USB_ERR_STALL;\r
+      break;\r
+\r
+    case TD_BUFFER_OVERRUN:\r
+    case TD_BUFFER_UNDERRUN:\r
+      TransferResult = EFI_USB_ERR_BUFFER;\r
+      break;\r
+\r
+    case TD_CRC_ERROR:\r
+      TransferResult = EFI_USB_ERR_CRC;\r
+      break;\r
+\r
+    case TD_NO_RESPONSE:\r
+      TransferResult = EFI_USB_ERR_TIMEOUT;\r
+      break;\r
+\r
+    case TD_BITSTUFFING_ERROR:\r
+      TransferResult = EFI_USB_ERR_BITSTUFF;\r
+      break;\r
+\r
+    default:\r
+      TransferResult = EFI_USB_ERR_SYSTEM;\r
+  }\r
+\r
+  return TransferResult;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Check TDs Results\r
+\r
+  @Param  Ohc                   UHC private data\r
+  @Param  Td                    TD_DESCRIPTOR\r
+  @Param  Result                Result to return\r
+\r
+  @retval TRUE                  means OK\r
+  @retval FLASE                 means Error or Short packet\r
+\r
+**/\r
+BOOLEAN\r
+OhciCheckTDsResults (\r
+  IN  USB_OHCI_HC_DEV     *Ohc,\r
+  IN  TD_DESCRIPTOR       *Td,\r
+  OUT UINT32              *Result\r
+  )\r
+{\r
+  UINT32                  TdCompletionCode;\r
+\r
+  *Result   = EFI_USB_NOERROR;\r
+\r
+  while (Td) {\r
+    TdCompletionCode = Td->Word0.ConditionCode;\r
+\r
+    *Result |= ConvertErrorCode(TdCompletionCode);\r
+    //\r
+    // if any error encountered, stop processing the left TDs.\r
+    //\r
+    if (*Result) {\r
+      return FALSE;\r
+    }\r
+\r
+    Td = Td->NextTDPointer;\r
+  }\r
+  return TRUE;\r
+\r
+}\r
+\r
+\r
+/**\r
+\r
+  Check the task status on an ED\r
+\r
+  @Param  Ed                    Pointer to the ED task that TD hooked on\r
+  @Param  HeadTd                TD header for current transaction\r
+\r
+  @retval                       Task Status Code\r
+\r
+**/\r
+\r
+UINT32\r
+CheckEDStatus (\r
+  IN  ED_DESCRIPTOR       *Ed,\r
+  IN  TD_DESCRIPTOR       *HeadTd\r
+  )\r
+{\r
+  while(HeadTd != NULL) {\r
+    if (HeadTd->Word0.ConditionCode != 0) {\r
+      return HeadTd->Word0.ConditionCode;\r
+    }\r
+    HeadTd = HeadTd->NextTDPointer;\r
+  }\r
+\r
+  if (OhciGetEDField (Ed, ED_TDHEAD_PTR) != OhciGetEDField (Ed, ED_TDTAIL_PTR)) {\r
+    return TD_TOBE_PROCESSED;\r
+  }\r
+\r
+  return TD_NO_ERROR;\r
+}\r
+\r
+/**\r
+\r
+  Check the task status\r
+\r
+  @Param  Ohc                   UHC private data\r
+  @Param  ListType              Pipe type\r
+  @Param  Ed                    Pointer to the ED task hooked on\r
+  @Param  HeadTd                Head of TD corresponding to the task\r
+  @Param  ErrorCode             return the ErrorCode\r
+\r
+  @retval  EFI_SUCCESS          Task done\r
+  @retval  EFI_NOT_READY        Task on processing\r
+  @retval  EFI_DEVICE_ERROR     Some error occured\r
+\r
+**/\r
+EFI_STATUS\r
+CheckIfDone (\r
+  IN  USB_OHCI_HC_DEV       *Ohc,\r
+  IN  DESCRIPTOR_LIST_TYPE  ListType,\r
+  IN  ED_DESCRIPTOR         *Ed,\r
+  IN  TD_DESCRIPTOR         *HeadTd,\r
+  OUT UINT32                *ErrorCode\r
+  )\r
+{\r
+  *ErrorCode = TD_TOBE_PROCESSED;\r
+\r
+  switch (ListType) {\r
+    case CONTROL_LIST:\r
+      if (OhciGetHcCommandStatus (Ohc, CONTROL_LIST_FILLED) != 0) {\r
+        return EFI_NOT_READY;\r
+      }\r
+      break;\r
+\r
+    case BULK_LIST:\r
+      if (OhciGetHcCommandStatus (Ohc, BULK_LIST_FILLED) != 0) {\r
+        return EFI_NOT_READY;\r
+      }\r
+      break;\r
+\r
+    default:\r
+      break;\r
+  }\r
+\r
+  *ErrorCode = CheckEDStatus (Ed, HeadTd);\r
+\r
+\r
+  if (*ErrorCode == TD_NO_ERROR) {\r
+    return EFI_SUCCESS;\r
+  } else if (*ErrorCode == TD_TOBE_PROCESSED) {\r
+    return EFI_NOT_READY;\r
+  } else {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+}\r
+\r
+\r
+/**\r
+\r
+  Convert TD condition code to Efi Status\r
+\r
+  @Param  ConditionCode         Condition code to convert\r
+\r
+  @retval  EFI_SUCCESS          No error occured\r
+  @retval  EFI_NOT_READY        TD still on processing\r
+  @retval  EFI_DEVICE_ERROR     Error occured in processing TD\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciTDConditionCodeToStatus (\r
+  IN  UINT32              ConditionCode\r
+  )\r
+{\r
+  if (ConditionCode == TD_NO_ERROR) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (ConditionCode == TD_TOBE_PROCESSED) {\r
+    return EFI_NOT_READY;\r
+  }\r
+\r
+  return EFI_DEVICE_ERROR;\r
+}\r
+\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciSched.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciSched.h
new file mode 100644 (file)
index 0000000..2fc35f6
--- /dev/null
@@ -0,0 +1,114 @@
+/** @file\r
+This file contains the definination for host controller schedule routines.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+\r
+#ifndef _OHCI_SCHED_H\r
+#define _OHCI_SCHED_H\r
+\r
+#include "Descriptor.h"\r
+\r
+#define HCCA_MEM_SIZE     256\r
+#define GRID_SIZE         16\r
+#define GRID_SHIFT        4\r
+\r
+/**\r
+\r
+  Convert Error code from OHCI format to EFI format\r
+\r
+  @Param  ErrorCode             ErrorCode in OHCI format\r
+\r
+  @retval                       ErrorCode in EFI format\r
+\r
+**/\r
+UINT32\r
+ConvertErrorCode (\r
+  IN  UINT32              ErrorCode\r
+  );\r
+/**\r
+\r
+  Check TDs Results\r
+\r
+  @Param  Ohc                   UHC private data\r
+  @Param  Td                    TD_DESCRIPTOR\r
+  @Param  Result                Result to return\r
+\r
+  @retval TRUE                  means OK\r
+  @retval FLASE                 means Error or Short packet\r
+\r
+**/\r
+BOOLEAN\r
+OhciCheckTDsResults (\r
+  IN  USB_OHCI_HC_DEV     *Ohc,\r
+  IN  TD_DESCRIPTOR       *Td,\r
+  OUT UINT32              *Result\r
+  );\r
+/**\r
+\r
+  Check the task status on an ED\r
+\r
+  @Param  Ed                    Pointer to the ED task that TD hooked on\r
+  @Param  HeadTd                TD header for current transaction\r
+\r
+  @retval                       Task Status Code\r
+\r
+**/\r
+\r
+UINT32\r
+CheckEDStatus (\r
+  IN  ED_DESCRIPTOR       *Ed,\r
+  IN  TD_DESCRIPTOR       *HeadTd\r
+  );\r
+/**\r
+\r
+  Check the task status\r
+\r
+  @Param  Ohc                   UHC private data\r
+  @Param  ListType              Pipe type\r
+  @Param  Ed                    Pointer to the ED task hooked on\r
+  @Param  HeadTd                Head of TD corresponding to the task\r
+  @Param  ErrorCode             return the ErrorCode\r
+\r
+  @retval  EFI_SUCCESS          Task done\r
+  @retval  EFI_NOT_READY        Task on processing\r
+  @retval  EFI_DEVICE_ERROR     Some error occured\r
+\r
+**/\r
+EFI_STATUS\r
+CheckIfDone (\r
+  IN  USB_OHCI_HC_DEV       *Ohc,\r
+  IN  DESCRIPTOR_LIST_TYPE  ListType,\r
+  IN  ED_DESCRIPTOR         *Ed,\r
+  IN  TD_DESCRIPTOR         *HeadTd,\r
+  OUT UINT32                *ErrorCode\r
+  );\r
+/**\r
+\r
+  Convert TD condition code to Efi Status\r
+\r
+  @Param  ConditionCode         Condition code to convert\r
+\r
+  @retval  EFI_SUCCESS          No error occured\r
+  @retval  EFI_NOT_READY        TD still on processing\r
+  @retval  EFI_DEVICE_ERROR     Error occured in processing TD\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciTDConditionCodeToStatus (\r
+  IN  UINT32              ConditionCode\r
+  );\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciUrb.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciUrb.c
new file mode 100644 (file)
index 0000000..09ccb98
--- /dev/null
@@ -0,0 +1,566 @@
+/** @file\r
+This file contains URB request, each request is warpped in a\r
+URB (Usb Request Block).\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+\r
+#include "OhcPeim.h"\r
+\r
+\r
+/**\r
+\r
+  Create a TD\r
+\r
+  @Param  Ohc                   UHC private data\r
+\r
+  @retval                       TD structure pointer\r
+\r
+**/\r
+TD_DESCRIPTOR *\r
+OhciCreateTD (\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  )\r
+{\r
+  TD_DESCRIPTOR           *Td;\r
+\r
+  Td = UsbHcAllocateMem(Ohc->MemPool, sizeof(TD_DESCRIPTOR));\r
+  if (Td == NULL) {\r
+    return NULL;\r
+  }\r
+  Td->CurrBufferPointer = NULL;\r
+  Td->NextTD = NULL;\r
+  Td->BufferEndPointer = NULL;\r
+  Td->NextTDPointer = NULL;\r
+\r
+  return Td;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Free a TD\r
+\r
+  @Param  Ohc                   UHC private data\r
+  @Param  Td                    Pointer to a TD to free\r
+\r
+  @retval  EFI_SUCCESS          TD freed\r
+\r
+**/\r
+EFI_STATUS\r
+OhciFreeTD (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN TD_DESCRIPTOR        *Td\r
+  )\r
+{\r
+  if (Td == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  UsbHcFreeMem(Ohc->MemPool, Td, sizeof(TD_DESCRIPTOR));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Create a ED\r
+\r
+  @Param   Ohc                  Device private data\r
+\r
+  @retval  ED                   descriptor pointer\r
+\r
+**/\r
+ED_DESCRIPTOR *\r
+OhciCreateED (\r
+  USB_OHCI_HC_DEV          *Ohc\r
+  )\r
+{\r
+  ED_DESCRIPTOR   *Ed;\r
+  Ed = UsbHcAllocateMem(Ohc->MemPool, sizeof (ED_DESCRIPTOR));\r
+  if (Ed == NULL) {\r
+    return NULL;\r
+  }\r
+  Ed->Word0.Skip = 1;\r
+  Ed->TdTailPointer = NULL;\r
+  Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 ((UINT32) NULL);\r
+  Ed->NextED = NULL;\r
+\r
+  return Ed;\r
+}\r
+\r
+/**\r
+\r
+  Free a ED\r
+\r
+  @Param  Ohc                   UHC private data\r
+  @Param  Ed                    Pointer to a ED to free\r
+\r
+  @retval  EFI_SUCCESS          ED freed\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciFreeED (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN ED_DESCRIPTOR        *Ed\r
+  )\r
+{\r
+  if (Ed == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Free  ED\r
+\r
+  @Param  Ohc                    Device private data\r
+  @Param  Ed                     Pointer to a ED to free\r
+\r
+  @retval  EFI_SUCCESS           ED freed\r
+\r
+**/\r
+EFI_STATUS\r
+OhciFreeAllTDFromED (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN ED_DESCRIPTOR        *Ed\r
+  )\r
+{\r
+  TD_DESCRIPTOR           *HeadTd;\r
+  TD_DESCRIPTOR           *TailTd;\r
+  TD_DESCRIPTOR           *Td;\r
+  TD_DESCRIPTOR           *TempTd;\r
+\r
+  if (Ed == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  HeadTd = TD_PTR (Ed->Word2.TdHeadPointer);\r
+  TailTd = Ed->TdTailPointer;\r
+\r
+  Td = HeadTd;\r
+  while (Td != TailTd) {\r
+    TempTd = Td;\r
+    Td = Td->NextTDPointer;\r
+    OhciFreeTD (Ohc, TempTd);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Attach an ED\r
+\r
+  @Param  Ed                    Ed to be attached\r
+  @Param  NewEd                 Ed to attach\r
+\r
+  @retval EFI_SUCCESS           NewEd attached to Ed\r
+  @retval EFI_INVALID_PARAMETER Ed is NULL\r
+\r
+**/\r
+EFI_STATUS\r
+OhciAttachED (\r
+  IN ED_DESCRIPTOR        *Ed,\r
+  IN ED_DESCRIPTOR        *NewEd\r
+  )\r
+{\r
+  ED_DESCRIPTOR           *Temp;\r
+\r
+  if (Ed == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Ed->NextED == NULL){\r
+    Ed->NextED = NewEd;\r
+  } else {\r
+    Temp = Ed->NextED;\r
+    Ed->NextED = NewEd;\r
+    NewEd->NextED = Temp;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+/**\r
+\r
+  Attach an ED to an ED list\r
+\r
+  @Param  OHC                   UHC private data\r
+  @Param  ListType              Type of the ED list\r
+  @Param  Ed                    ED to attach\r
+  @Param  EdList                ED list to be attached\r
+\r
+  @retval  EFI_SUCCESS          ED attached to ED list\r
+\r
+**/\r
+EFI_STATUS\r
+OhciAttachEDToList (\r
+  IN USB_OHCI_HC_DEV       *Ohc,\r
+  IN DESCRIPTOR_LIST_TYPE  ListType,\r
+  IN ED_DESCRIPTOR         *Ed,\r
+  IN ED_DESCRIPTOR         *EdList\r
+  )\r
+{\r
+  ED_DESCRIPTOR            *HeadEd;\r
+\r
+  switch(ListType) {\r
+    case CONTROL_LIST:\r
+      HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_CONTROL_HEAD);\r
+      if (HeadEd == NULL) {\r
+        OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, Ed);\r
+      } else {\r
+        OhciAttachED (HeadEd, Ed);\r
+      }\r
+    break;\r
+\r
+    case BULK_LIST:\r
+      HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_BULK_HEAD);\r
+      if (HeadEd == NULL) {\r
+        OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, Ed);\r
+      } else {\r
+        OhciAttachED (HeadEd, Ed);\r
+      }\r
+    break;\r
+\r
+    case INTERRUPT_LIST:\r
+      OhciAttachED (EdList, Ed);\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+/**\r
+\r
+  Link Td2 to the end of Td1\r
+\r
+  @Param Td1                    TD to be linked\r
+  @Param Td2                    TD to link\r
+\r
+  @retval EFI_SUCCESS           TD successfully linked\r
+  @retval EFI_INVALID_PARAMETER Td1 is NULL\r
+\r
+**/\r
+EFI_STATUS\r
+OhciLinkTD (\r
+  IN TD_DESCRIPTOR        *Td1,\r
+  IN TD_DESCRIPTOR        *Td2\r
+  )\r
+{\r
+  TD_DESCRIPTOR           *TempTd;\r
+\r
+  if (Td1 == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Td1 == Td2) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  TempTd = Td1;\r
+  while (TempTd->NextTD != NULL) {\r
+    TempTd = TempTd->NextTD;\r
+  }\r
+\r
+  TempTd->NextTD = Td2;\r
+  TempTd->NextTDPointer = Td2;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Attach TD list to ED\r
+\r
+  @Param  Ed                    ED which TD list attach on\r
+  @Param  HeadTd                Head of the TD list to attach\r
+\r
+  @retval  EFI_SUCCESS          TD list attached on the ED\r
+\r
+**/\r
+EFI_STATUS\r
+OhciAttachTDListToED (\r
+  IN ED_DESCRIPTOR        *Ed,\r
+  IN TD_DESCRIPTOR        *HeadTd\r
+  )\r
+{\r
+  TD_DESCRIPTOR           *TempTd;\r
+\r
+  TempTd = TD_PTR (Ed->Word2.TdHeadPointer);\r
+\r
+  if (TempTd != NULL) {\r
+    while (TempTd->NextTD != NULL) {\r
+      TempTd = TempTd->NextTD;\r
+    }\r
+    TempTd->NextTD = HeadTd;\r
+    TempTd->NextTDPointer = HeadTd;\r
+  } else {\r
+    Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 ((UINT32) HeadTd);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Set value to ED specific field\r
+\r
+  @Param  Ed                    ED to be set\r
+  @Param  Field                 Field to be set\r
+  @Param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+EFI_STATUS\r
+OhciSetEDField (\r
+  IN ED_DESCRIPTOR        *Ed,\r
+  IN UINT32               Field,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  if (Field & ED_FUNC_ADD) {\r
+    Ed->Word0.FunctionAddress = Value;\r
+  }\r
+  if (Field & ED_ENDPT_NUM) {\r
+    Ed->Word0.EndPointNum = Value;\r
+  }\r
+  if (Field & ED_DIR) {\r
+    Ed->Word0.Direction = Value;\r
+  }\r
+  if (Field & ED_SPEED) {\r
+    Ed->Word0.Speed = Value;\r
+  }\r
+  if (Field & ED_SKIP) {\r
+    Ed->Word0.Skip = Value;\r
+  }\r
+  if (Field & ED_FORMAT) {\r
+    Ed->Word0.Format = Value;\r
+  }\r
+  if (Field & ED_MAX_PACKET) {\r
+    Ed->Word0.MaxPacketSize = Value;\r
+  }\r
+  if (Field & ED_PDATA) {\r
+    Ed->Word0.FreeSpace = Value;\r
+  }\r
+  if (Field & ED_ZERO) {\r
+    Ed->Word2.Zero = Value;\r
+  }\r
+  if (Field & ED_TDTAIL_PTR) {\r
+    Ed->TdTailPointer = (VOID *) Value;\r
+  }\r
+\r
+  if (Field & ED_HALTED) {\r
+    Ed->Word2.Halted = Value;\r
+  }\r
+  if (Field & ED_DTTOGGLE) {\r
+    Ed->Word2.ToggleCarry = Value;\r
+  }\r
+  if (Field & ED_TDHEAD_PTR) {\r
+    Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 (Value);\r
+  }\r
+\r
+  if (Field & ED_NEXT_EDPTR) {\r
+    Ed->NextED = (VOID *) Value;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Get value from an ED's specific field\r
+\r
+  @Param  Ed                    ED pointer\r
+  @Param  Field                 Field to get value from\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+UINT32\r
+OhciGetEDField (\r
+  IN ED_DESCRIPTOR        *Ed,\r
+  IN UINT32               Field\r
+  )\r
+{\r
+  switch (Field) {\r
+    case ED_FUNC_ADD:\r
+      return Ed->Word0.FunctionAddress;\r
+      break;\r
+    case ED_ENDPT_NUM:\r
+      return Ed->Word0.EndPointNum;\r
+      break;\r
+    case ED_DIR:\r
+      return Ed->Word0.Direction;\r
+      break;\r
+    case ED_SPEED:\r
+      return Ed->Word0.Speed;\r
+      break;\r
+    case ED_SKIP:\r
+      return Ed->Word0.Skip;\r
+      break;\r
+    case ED_FORMAT:\r
+      return Ed->Word0.Format;\r
+      break;\r
+    case ED_MAX_PACKET:\r
+      return Ed->Word0.MaxPacketSize;\r
+      break;\r
+\r
+    case ED_TDTAIL_PTR:\r
+      return (UINT32) Ed->TdTailPointer;\r
+      break;\r
+\r
+    case ED_HALTED:\r
+      return Ed->Word2.Halted;\r
+      break;\r
+\r
+    case ED_DTTOGGLE:\r
+      return Ed->Word2.ToggleCarry;\r
+      break;\r
+\r
+    case ED_TDHEAD_PTR:\r
+      return Ed->Word2.TdHeadPointer << 4;\r
+      break;\r
+\r
+    case ED_NEXT_EDPTR:\r
+      return (UINT32) Ed->NextED;\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Set value to TD specific field\r
+\r
+  @Param  Td                    TD to be set\r
+  @Param  Field                 Field to be set\r
+  @Param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+EFI_STATUS\r
+OhciSetTDField (\r
+  IN TD_DESCRIPTOR        *Td,\r
+  IN UINT32               Field,\r
+  IN UINT32               Value\r
+  )\r
+{\r
+  if (Field & TD_PDATA) {\r
+    Td->Word0.Reserved = Value;\r
+  }\r
+  if (Field & TD_BUFFER_ROUND) {\r
+    Td->Word0.BufferRounding = Value;\r
+  }\r
+  if (Field & TD_DIR_PID) {\r
+    Td->Word0.DirPID = Value;\r
+  }\r
+  if (Field & TD_DELAY_INT) {\r
+    Td->Word0.DelayInterrupt = Value;\r
+  }\r
+  if (Field & TD_DT_TOGGLE) {\r
+    Td->Word0.DataToggle = Value | 0x2;\r
+  }\r
+  if (Field & TD_ERROR_CNT) {\r
+    Td->Word0.ErrorCount = Value;\r
+  }\r
+  if (Field & TD_COND_CODE) {\r
+    Td->Word0.ConditionCode = Value;\r
+  }\r
+\r
+  if (Field & TD_CURR_BUFFER_PTR) {\r
+    Td->CurrBufferPointer = (VOID *) Value;\r
+  }\r
+\r
+\r
+  if (Field & TD_NEXT_PTR) {\r
+    Td->NextTD = (VOID *) Value;\r
+  }\r
+\r
+  if (Field & TD_BUFFER_END_PTR) {\r
+    Td->BufferEndPointer = (VOID *) Value;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+\r
+  Get value from ED specific field\r
+\r
+  @Param  Td                    TD pointer\r
+  @Param  Field                 Field to get value from\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetTDField (\r
+  IN TD_DESCRIPTOR      *Td,\r
+  IN UINT32             Field\r
+  )\r
+{\r
+  switch (Field){\r
+    case TD_BUFFER_ROUND:\r
+      return Td->Word0.BufferRounding;\r
+      break;\r
+    case TD_DIR_PID:\r
+      return Td->Word0.DirPID;\r
+      break;\r
+    case TD_DELAY_INT:\r
+      return Td->Word0.DelayInterrupt;\r
+      break;\r
+    case TD_DT_TOGGLE:\r
+      return Td->Word0.DataToggle;\r
+      break;\r
+    case TD_ERROR_CNT:\r
+      return Td->Word0.ErrorCount;\r
+      break;\r
+    case TD_COND_CODE:\r
+      return Td->Word0.ConditionCode;\r
+      break;\r
+    case TD_CURR_BUFFER_PTR:\r
+      return (UINT32) Td->CurrBufferPointer;\r
+      break;\r
+\r
+    case TD_NEXT_PTR:\r
+      return (UINT32) Td->NextTD;\r
+      break;\r
+\r
+    case TD_BUFFER_END_PTR:\r
+      return (UINT32) Td->BufferEndPointer;\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+  }\r
+\r
+  return 0;\r
+}\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciUrb.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhciUrb.h
new file mode 100644 (file)
index 0000000..8376b0a
--- /dev/null
@@ -0,0 +1,237 @@
+/** @file\r
+Provides some data struct used by OHCI controller driver.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#ifndef _OHCI_URB_H\r
+#define _OHCI_URB_H\r
+\r
+#include "Descriptor.h"\r
+\r
+\r
+//\r
+// Func List\r
+//\r
+\r
+\r
+/**\r
+\r
+  Create a TD\r
+\r
+  @Param  Ohc                   UHC private data\r
+\r
+  @retval                       TD structure pointer\r
+\r
+**/\r
+TD_DESCRIPTOR *\r
+OhciCreateTD (\r
+  IN USB_OHCI_HC_DEV      *Ohc\r
+  );\r
+\r
+/**\r
+\r
+  Free a TD\r
+\r
+  @Param  Ohc                   UHC private data\r
+  @Param  Td                    Pointer to a TD to free\r
+\r
+  @retval  EFI_SUCCESS          TD freed\r
+\r
+**/\r
+EFI_STATUS\r
+OhciFreeTD (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN TD_DESCRIPTOR        *Td\r
+  );\r
+\r
+/**\r
+\r
+  Create a ED\r
+\r
+  @Param   Ohc                  Device private data\r
+\r
+  @retval  ED                   descriptor pointer\r
+\r
+**/\r
+ED_DESCRIPTOR *\r
+OhciCreateED (\r
+  USB_OHCI_HC_DEV          *Ohc\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Free a ED\r
+\r
+  @Param  Ohc                   UHC private data\r
+  @Param  Ed                    Pointer to a ED to free\r
+\r
+  @retval  EFI_SUCCESS          ED freed\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+OhciFreeED (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN ED_DESCRIPTOR        *Ed\r
+  );\r
+\r
+/**\r
+\r
+  Free  ED\r
+\r
+  @Param  Ohc                    Device private data\r
+  @Param  Ed                     Pointer to a ED to free\r
+\r
+  @retval  EFI_SUCCESS           ED freed\r
+\r
+**/\r
+EFI_STATUS\r
+OhciFreeAllTDFromED (\r
+  IN USB_OHCI_HC_DEV      *Ohc,\r
+  IN ED_DESCRIPTOR        *Ed\r
+  );\r
+\r
+/**\r
+\r
+  Attach an ED\r
+\r
+  @Param  Ed                    Ed to be attached\r
+  @Param  NewEd                 Ed to attach\r
+\r
+  @retval EFI_SUCCESS           NewEd attached to Ed\r
+  @retval EFI_INVALID_PARAMETER Ed is NULL\r
+\r
+**/\r
+EFI_STATUS\r
+OhciAttachED (\r
+  IN ED_DESCRIPTOR        *Ed,\r
+  IN ED_DESCRIPTOR        *NewEd\r
+  );\r
+/**\r
+\r
+  Attach an ED to an ED list\r
+\r
+  @Param  OHC                   UHC private data\r
+  @Param  ListType              Type of the ED list\r
+  @Param  Ed                    ED to attach\r
+  @Param  EdList                ED list to be attached\r
+\r
+  @retval  EFI_SUCCESS          ED attached to ED list\r
+\r
+**/\r
+EFI_STATUS\r
+OhciAttachEDToList (\r
+  IN USB_OHCI_HC_DEV       *Ohc,\r
+  IN DESCRIPTOR_LIST_TYPE  ListType,\r
+  IN ED_DESCRIPTOR         *Ed,\r
+  IN ED_DESCRIPTOR         *EdList\r
+  );\r
+EFI_STATUS\r
+OhciLinkTD (\r
+  IN TD_DESCRIPTOR        *Td1,\r
+  IN TD_DESCRIPTOR        *Td2\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Attach TD list to ED\r
+\r
+  @Param  Ed                    ED which TD list attach on\r
+  @Param  HeadTd                Head of the TD list to attach\r
+\r
+  @retval  EFI_SUCCESS          TD list attached on the ED\r
+\r
+**/\r
+EFI_STATUS\r
+OhciAttachTDListToED (\r
+  IN ED_DESCRIPTOR        *Ed,\r
+  IN TD_DESCRIPTOR        *HeadTd\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Set value to ED specific field\r
+\r
+  @Param  Ed                    ED to be set\r
+  @Param  Field                 Field to be set\r
+  @Param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+EFI_STATUS\r
+OhciSetEDField (\r
+  IN ED_DESCRIPTOR        *Ed,\r
+  IN UINT32               Field,\r
+  IN UINT32               Value\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Get value from an ED's specific field\r
+\r
+  @Param  Ed                    ED pointer\r
+  @Param  Field                 Field to get value from\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+UINT32\r
+OhciGetEDField (\r
+  IN ED_DESCRIPTOR        *Ed,\r
+  IN UINT32               Field\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Set value to TD specific field\r
+\r
+  @Param  Td                    TD to be set\r
+  @Param  Field                 Field to be set\r
+  @Param  Value                 Value to set\r
+\r
+  @retval  EFI_SUCCESS          Value set\r
+\r
+**/\r
+EFI_STATUS\r
+OhciSetTDField (\r
+  IN TD_DESCRIPTOR        *Td,\r
+  IN UINT32               Field,\r
+  IN UINT32               Value\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Get value from ED specific field\r
+\r
+  @Param  Td                    TD pointer\r
+  @Param  Field                 Field to get value from\r
+\r
+  @retval                       Value of the field\r
+\r
+**/\r
+\r
+UINT32\r
+OhciGetTDField (\r
+  IN TD_DESCRIPTOR      *Td,\r
+  IN UINT32             Field\r
+  );\r
+\r
+#endif\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/UsbHcMem.c b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/UsbHcMem.c
new file mode 100644 (file)
index 0000000..10c2049
--- /dev/null
@@ -0,0 +1,497 @@
+/** @file\r
+Routine procedures for memory allocate/free.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include "OhcPeim.h"\r
+\r
+\r
+/**\r
+  Allocate a block of memory to be used by the buffer pool.\r
+\r
+  Use Redirect memory services to allocate memmory so that USB DMA transfers do\r
+  not cause IMR violations on Quark.\r
+\r
+  @param  Pool           The buffer pool to allocate memory for.\r
+  @param  Pages          How many pages to allocate.\r
+\r
+  @return The allocated memory block or NULL if failed.\r
+\r
+**/\r
+USBHC_MEM_BLOCK *\r
+UsbHcAllocMemBlock (\r
+  IN  USBHC_MEM_POOL      *Pool,\r
+  IN  UINTN               Pages\r
+  )\r
+{\r
+  USBHC_MEM_BLOCK         *Block;\r
+  VOID                    *BufHost;\r
+  VOID                    *Mapping;\r
+  EFI_PHYSICAL_ADDRESS    MappedAddr;\r
+  EFI_STATUS              Status;\r
+  UINTN                   PageNumber;\r
+  EFI_PHYSICAL_ADDRESS    TempPtr;\r
+\r
+  Mapping = NULL;\r
+  PageNumber =  sizeof(USBHC_MEM_BLOCK)/PAGESIZE +1;\r
+  Status = PeiServicesAllocatePages (\r
+             EfiBootServicesCode,\r
+             PageNumber,\r
+             &TempPtr\r
+             );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+  ZeroMem ((VOID   *)(UINTN)TempPtr, PageNumber*EFI_PAGE_SIZE);\r
+\r
+  //\r
+  // each bit in the bit array represents USBHC_MEM_UNIT\r
+  // bytes of memory in the memory block.\r
+  //\r
+  ASSERT (USBHC_MEM_UNIT * 8 <= EFI_PAGE_SIZE);\r
+\r
+  Block = (USBHC_MEM_BLOCK*)(UINTN)TempPtr;\r
+  Block->BufLen   = EFI_PAGES_TO_SIZE (Pages);\r
+  Block->BitsLen  = Block->BufLen / (USBHC_MEM_UNIT * 8);\r
+\r
+  PageNumber =  (Block->BitsLen)/PAGESIZE +1;\r
+  Status = PeiServicesAllocatePages (\r
+             EfiBootServicesCode,\r
+             PageNumber,\r
+             &TempPtr\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+  ZeroMem ((VOID   *)(UINTN)TempPtr, PageNumber*EFI_PAGE_SIZE);\r
+\r
+  Block->Bits  = (UINT8 *)(UINTN)TempPtr;\r
+\r
+  Status = PeiServicesAllocatePages (\r
+             EfiBootServicesCode,\r
+             Pages,\r
+             &TempPtr\r
+             );\r
+  ZeroMem ((VOID   *)(UINTN)TempPtr, Pages*EFI_PAGE_SIZE);\r
+\r
+  BufHost  = (VOID *)(UINTN)TempPtr;\r
+  MappedAddr = (EFI_PHYSICAL_ADDRESS) (UINTN) BufHost;\r
+  //\r
+  // Check whether the data structure used by the host controller\r
+  // should be restricted into the same 4G\r
+  //\r
+  if (Pool->Check4G && (Pool->Which4G != USB_HC_HIGH_32BIT (MappedAddr))) {\r
+    return NULL;\r
+  }\r
+\r
+  Block->BufHost  = BufHost;\r
+  Block->Buf      = (UINT8 *) ((UINTN) MappedAddr);\r
+  Block->Mapping  = Mapping;\r
+  Block->Next     = NULL;\r
+\r
+  return Block;\r
+\r
+}\r
+\r
+\r
+/**\r
+  Free the memory block from the memory pool.\r
+\r
+  @param  Pool           The memory pool to free the block from.\r
+  @param  Block          The memory block to free.\r
+\r
+**/\r
+VOID\r
+UsbHcFreeMemBlock (\r
+  IN USBHC_MEM_POOL       *Pool,\r
+  IN USBHC_MEM_BLOCK      *Block\r
+  )\r
+{\r
+\r
+  ASSERT ((Pool != NULL) && (Block != NULL));\r
+}\r
+\r
+\r
+/**\r
+  Alloc some memory from the block.\r
+\r
+  @param  Block          The memory block to allocate memory from.\r
+  @param  Units          Number of memory units to allocate.\r
+\r
+  @return The pointer to the allocated memory. If couldn't allocate the needed memory,\r
+          the return value is NULL.\r
+\r
+**/\r
+VOID *\r
+UsbHcAllocMemFromBlock (\r
+  IN  USBHC_MEM_BLOCK     *Block,\r
+  IN  UINTN               Units\r
+  )\r
+{\r
+  UINTN                   Byte;\r
+  UINT8                   Bit;\r
+  UINTN                   StartByte;\r
+  UINT8                   StartBit;\r
+  UINTN                   Available;\r
+  UINTN                   Count;\r
+\r
+  ASSERT ((Block != 0) && (Units != 0));\r
+\r
+  StartByte  = 0;\r
+  StartBit   = 0;\r
+  Available  = 0;\r
+\r
+  for (Byte = 0, Bit = 0; Byte < Block->BitsLen;) {\r
+    //\r
+    // If current bit is zero, the corresponding memory unit is\r
+    // available, otherwise we need to restart our searching.\r
+    // Available counts the consective number of zero bit.\r
+    //\r
+    if (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit)) {\r
+      Available++;\r
+\r
+      if (Available >= Units) {\r
+        break;\r
+      }\r
+\r
+      NEXT_BIT (Byte, Bit);\r
+\r
+    } else {\r
+      NEXT_BIT (Byte, Bit);\r
+\r
+      Available  = 0;\r
+      StartByte  = Byte;\r
+      StartBit   = Bit;\r
+    }\r
+  }\r
+\r
+  if (Available < Units) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Mark the memory as allocated\r
+  //\r
+  Byte  = StartByte;\r
+  Bit   = StartBit;\r
+\r
+  for (Count = 0; Count < Units; Count++) {\r
+    ASSERT (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));\r
+\r
+    Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] | (UINT8) USB_HC_BIT (Bit));\r
+    NEXT_BIT (Byte, Bit);\r
+  }\r
+\r
+  return Block->BufHost + (StartByte * 8 + StartBit) * USBHC_MEM_UNIT;\r
+}\r
+\r
+/**\r
+  Insert the memory block to the pool's list of the blocks.\r
+\r
+  @param  Head           The head of the memory pool's block list.\r
+  @param  Block          The memory block to insert.\r
+\r
+**/\r
+VOID\r
+UsbHcInsertMemBlockToPool (\r
+  IN USBHC_MEM_BLOCK      *Head,\r
+  IN USBHC_MEM_BLOCK      *Block\r
+  )\r
+{\r
+  ASSERT ((Head != NULL) && (Block != NULL));\r
+  Block->Next = Head->Next;\r
+  Head->Next  = Block;\r
+}\r
+\r
+\r
+/**\r
+  Is the memory block empty?\r
+\r
+  @param  Block   The memory block to check.\r
+\r
+  @retval TRUE    The memory block is empty.\r
+  @retval FALSE   The memory block isn't empty.\r
+\r
+**/\r
+BOOLEAN\r
+UsbHcIsMemBlockEmpty (\r
+  IN USBHC_MEM_BLOCK     *Block\r
+  )\r
+{\r
+  UINTN                   Index;\r
+\r
+  for (Index = 0; Index < Block->BitsLen; Index++) {\r
+    if (Block->Bits[Index] != 0) {\r
+      return FALSE;\r
+    }\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+\r
+/**\r
+  Unlink the memory block from the pool's list.\r
+\r
+  @param  Head           The block list head of the memory's pool.\r
+  @param  BlockToUnlink  The memory block to unlink.\r
+\r
+**/\r
+VOID\r
+UsbHcUnlinkMemBlock (\r
+  IN USBHC_MEM_BLOCK      *Head,\r
+  IN USBHC_MEM_BLOCK      *BlockToUnlink\r
+  )\r
+{\r
+  USBHC_MEM_BLOCK         *Block;\r
+\r
+  ASSERT ((Head != NULL) && (BlockToUnlink != NULL));\r
+\r
+  for (Block = Head; Block != NULL; Block = Block->Next) {\r
+    if (Block->Next == BlockToUnlink) {\r
+      Block->Next         = BlockToUnlink->Next;\r
+      BlockToUnlink->Next = NULL;\r
+      break;\r
+    }\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Initialize the memory management pool for the host controller.\r
+\r
+  @param  PciIo                The PciIo that can be used to access the host controller.\r
+  @param  Check4G              Whether the host controller requires allocated memory\r
+                               from one 4G address space.\r
+  @param  Which4G              The 4G memory area each memory allocated should be from.\r
+\r
+  @retval EFI_SUCCESS          The memory pool is initialized.\r
+  @retval EFI_OUT_OF_RESOURCE  Fail to init the memory pool.\r
+\r
+**/\r
+USBHC_MEM_POOL *\r
+UsbHcInitMemPool (\r
+  IN BOOLEAN              Check4G,\r
+  IN UINT32               Which4G\r
+  )\r
+{\r
+  USBHC_MEM_POOL          *Pool;\r
+  UINTN                   PageNumber;\r
+  EFI_STATUS              Status;\r
+  EFI_PHYSICAL_ADDRESS    TempPtr;\r
+\r
+  PageNumber =  sizeof(USBHC_MEM_POOL)/PAGESIZE +1;\r
+  Status = PeiServicesAllocatePages (\r
+             EfiBootServicesCode,\r
+             PageNumber,\r
+             &TempPtr\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+  ZeroMem ((VOID   *)(UINTN)TempPtr, PageNumber*EFI_PAGE_SIZE);\r
+\r
+  Pool = (USBHC_MEM_POOL *) ((UINTN) TempPtr);\r
+  Pool->Check4G = Check4G;\r
+  Pool->Which4G = Which4G;\r
+  Pool->Head    = UsbHcAllocMemBlock (Pool, USBHC_MEM_DEFAULT_PAGES);\r
+\r
+  if (Pool->Head == NULL) {\r
+    Pool = NULL;\r
+  }\r
+\r
+  return Pool;\r
+}\r
+\r
+\r
+/**\r
+  Release the memory management pool.\r
+\r
+  @param  Pool              The USB memory pool to free.\r
+\r
+  @retval EFI_SUCCESS       The memory pool is freed.\r
+  @retval EFI_DEVICE_ERROR  Failed to free the memory pool.\r
+\r
+**/\r
+EFI_STATUS\r
+UsbHcFreeMemPool (\r
+  IN USBHC_MEM_POOL       *Pool\r
+  )\r
+{\r
+  USBHC_MEM_BLOCK *Block;\r
+\r
+  ASSERT (Pool->Head != NULL);\r
+\r
+  //\r
+  // Unlink all the memory blocks from the pool, then free them.\r
+  // UsbHcUnlinkMemBlock can't be used to unlink and free the\r
+  // first block.\r
+  //\r
+  for (Block = Pool->Head->Next; Block != NULL; Block = Pool->Head->Next) {\r
+    UsbHcFreeMemBlock (Pool, Block);\r
+  }\r
+\r
+  UsbHcFreeMemBlock (Pool, Pool->Head);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Allocate some memory from the host controller's memory pool\r
+  which can be used to communicate with host controller.\r
+\r
+  @param  Pool           The host controller's memory pool.\r
+  @param  Size           Size of the memory to allocate.\r
+\r
+  @return The allocated memory or NULL.\r
+\r
+**/\r
+VOID *\r
+UsbHcAllocateMem (\r
+  IN  USBHC_MEM_POOL      *Pool,\r
+  IN  UINTN               Size\r
+  )\r
+{\r
+  USBHC_MEM_BLOCK         *Head;\r
+  USBHC_MEM_BLOCK         *Block;\r
+  USBHC_MEM_BLOCK         *NewBlock;\r
+  VOID                    *Mem;\r
+  UINTN                   AllocSize;\r
+  UINTN                   Pages;\r
+\r
+  Mem       = NULL;\r
+  AllocSize = USBHC_MEM_ROUND (Size);\r
+  Head      = Pool->Head;\r
+  ASSERT (Head != NULL);\r
+\r
+  //\r
+  // First check whether current memory blocks can satisfy the allocation.\r
+  //\r
+  for (Block = Head; Block != NULL; Block = Block->Next) {\r
+    Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT);\r
+\r
+    if (Mem != NULL) {\r
+      ZeroMem (Mem, Size);\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (Mem != NULL) {\r
+    return Mem;\r
+  }\r
+\r
+  //\r
+  // Create a new memory block if there is not enough memory\r
+  // in the pool. If the allocation size is larger than the\r
+  // default page number, just allocate a large enough memory\r
+  // block. Otherwise allocate default pages.\r
+  //\r
+  if (AllocSize > EFI_PAGES_TO_SIZE (USBHC_MEM_DEFAULT_PAGES)) {\r
+    Pages = EFI_SIZE_TO_PAGES (AllocSize) + 1;\r
+  } else {\r
+    Pages = USBHC_MEM_DEFAULT_PAGES;\r
+  }\r
+\r
+  NewBlock = UsbHcAllocMemBlock (Pool, Pages);\r
+\r
+  if (NewBlock == NULL) {\r
+    DEBUG ((EFI_D_INFO, "UsbHcAllocateMem: failed to allocate block\n"));\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Add the new memory block to the pool, then allocate memory from it\r
+  //\r
+  UsbHcInsertMemBlockToPool (Head, NewBlock);\r
+  Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT);\r
+\r
+  if (Mem != NULL) {\r
+    ZeroMem (Mem, Size);\r
+  }\r
+\r
+  return Mem;\r
+}\r
+\r
+\r
+/**\r
+  Free the allocated memory back to the memory pool.\r
+\r
+  @param  Pool           The memory pool of the host controller.\r
+  @param  Mem            The memory to free.\r
+  @param  Size           The size of the memory to free.\r
+\r
+**/\r
+VOID\r
+UsbHcFreeMem (\r
+  IN USBHC_MEM_POOL       *Pool,\r
+  IN VOID                 *Mem,\r
+  IN UINTN                Size\r
+  )\r
+{\r
+  USBHC_MEM_BLOCK         *Head;\r
+  USBHC_MEM_BLOCK         *Block;\r
+  UINT8                   *ToFree;\r
+  UINTN                   AllocSize;\r
+  UINTN                   Byte;\r
+  UINTN                   Bit;\r
+  UINTN                   Count;\r
+\r
+  Head      = Pool->Head;\r
+  AllocSize = USBHC_MEM_ROUND (Size);\r
+  ToFree    = (UINT8 *) Mem;\r
+\r
+  for (Block = Head; Block != NULL; Block = Block->Next) {\r
+    //\r
+    // scan the memory block list for the memory block that\r
+    // completely contains the memory to free.\r
+    //\r
+    if ((Block->BufHost <= ToFree) && ((ToFree + AllocSize) <= (Block->BufHost + Block->BufLen))) {\r
+      //\r
+      // compute the start byte and bit in the bit array\r
+      //\r
+      Byte  = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) / 8;\r
+      Bit   = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) % 8;\r
+\r
+      //\r
+      // reset associated bits in bit arry\r
+      //\r
+      for (Count = 0; Count < (AllocSize / USBHC_MEM_UNIT); Count++) {\r
+        ASSERT (USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));\r
+\r
+        Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] ^ USB_HC_BIT (Bit));\r
+        NEXT_BIT (Byte, Bit);\r
+      }\r
+\r
+      break;\r
+    }\r
+  }\r
+\r
+  //\r
+  // If Block == NULL, it means that the current memory isn't\r
+  // in the host controller's pool. This is critical because\r
+  // the caller has passed in a wrong memory point\r
+  //\r
+  ASSERT (Block != NULL);\r
+\r
+  //\r
+  // Release the current memory block if it is empty and not the head\r
+  //\r
+  if ((Block != Head) && UsbHcIsMemBlockEmpty (Block)) {\r
+    UsbHcFreeMemBlock (Pool, Block);\r
+  }\r
+\r
+  return ;\r
+}\r
diff --git a/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/UsbHcMem.h b/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/UsbHcMem.h
new file mode 100644 (file)
index 0000000..0f4e80a
--- /dev/null
@@ -0,0 +1,140 @@
+/** @file\r
+This file contains the definination for host controller memory\r
+management routines.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _USB_HC_MEM_H_\r
+#define _USB_HC_MEM_H_\r
+\r
+#define USB_HC_BIT(a)                  ((UINTN)(1 << (a)))\r
+\r
+#define USB_HC_BIT_IS_SET(Data, Bit)   \\r
+          ((BOOLEAN)(((Data) & USB_HC_BIT(Bit)) == USB_HC_BIT(Bit)))\r
+\r
+#define USB_HC_HIGH_32BIT(Addr64)    \\r
+          ((UINT32)(RShiftU64((UINTN)(Addr64), 32) & 0XFFFFFFFF))\r
+\r
+typedef struct _USBHC_MEM_BLOCK USBHC_MEM_BLOCK;\r
+struct _USBHC_MEM_BLOCK {\r
+  UINT8                   *Bits;    // Bit array to record which unit is allocated\r
+  UINTN                   BitsLen;\r
+  UINT8                   *Buf;\r
+  UINT8                   *BufHost;\r
+  UINTN                   BufLen;   // Memory size in bytes\r
+  VOID                    *Mapping;\r
+  USBHC_MEM_BLOCK         *Next;\r
+};\r
+\r
+//\r
+// USBHC_MEM_POOL is used to manage the memory used by USB\r
+// host controller. EHCI requires the control memory and transfer\r
+// data to be on the same 4G memory.\r
+//\r
+typedef struct _USBHC_MEM_POOL {\r
+  BOOLEAN                 Check4G;\r
+  UINT32                  Which4G;\r
+  USBHC_MEM_BLOCK         *Head;\r
+} USBHC_MEM_POOL;\r
+\r
+//\r
+// Memory allocation unit, must be 2^n, n>4\r
+//\r
+#define USBHC_MEM_UNIT           64\r
+\r
+#define USBHC_MEM_UNIT_MASK      (USBHC_MEM_UNIT - 1)\r
+#define USBHC_MEM_DEFAULT_PAGES  16\r
+\r
+#define USBHC_MEM_ROUND(Len)  (((Len) + USBHC_MEM_UNIT_MASK) & (~USBHC_MEM_UNIT_MASK))\r
+\r
+//\r
+// Advance the byte and bit to the next bit, adjust byte accordingly.\r
+//\r
+#define NEXT_BIT(Byte, Bit)   \\r
+          do {                \\r
+            (Bit)++;          \\r
+            if ((Bit) > 7) {  \\r
+              (Byte)++;       \\r
+              (Bit) = 0;      \\r
+            }                 \\r
+          } while (0)\r
+\r
+\r
+\r
+/**\r
+  Initialize the memory management pool for the host controller.\r
+\r
+  @param  PciIo               The PciIo that can be used to access the host controller.\r
+  @param  Check4G             Whether the host controller requires allocated memory\r
+                              from one 4G address space.\r
+  @param  Which4G             The 4G memory area each memory allocated should be from.\r
+\r
+  @retval EFI_SUCCESS         The memory pool is initialized.\r
+  @retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.\r
+\r
+**/\r
+USBHC_MEM_POOL *\r
+UsbHcInitMemPool (\r
+  IN BOOLEAN              Check4G,\r
+  IN UINT32               Which4G\r
+  );\r
+\r
+\r
+/**\r
+  Release the memory management pool.\r
+\r
+  @param   Pool               The USB memory pool to free.\r
+\r
+  @retval EFI_SUCCESS       The memory pool is freed.\r
+  @retval EFI_DEVICE_ERROR  Failed to free the memory pool.\r
+\r
+**/\r
+EFI_STATUS\r
+UsbHcFreeMemPool (\r
+  IN USBHC_MEM_POOL       *Pool\r
+  );\r
+\r
+\r
+/**\r
+  Allocate some memory from the host controller's memory pool\r
+  which can be used to communicate with host controller.\r
+\r
+  @param  Pool  The host controller's memory pool.\r
+  @param  Size  Size of the memory to allocate.\r
+\r
+  @return The allocated memory or NULL.\r
+\r
+**/\r
+VOID *\r
+UsbHcAllocateMem (\r
+  IN  USBHC_MEM_POOL      *Pool,\r
+  IN  UINTN               Size\r
+  );\r
+\r
+\r
+/**\r
+  Free the allocated memory back to the memory pool.\r
+\r
+  @param  Pool  The memory pool of the host controller.\r
+  @param  Mem   The memory to free.\r
+  @param  Size  The size of the memory to free.\r
+\r
+**/\r
+VOID\r
+UsbHcFreeMem (\r
+  IN USBHC_MEM_POOL       *Pool,\r
+  IN VOID                 *Mem,\r
+  IN UINTN                Size\r
+  );\r
+\r
+#endif\r