--- /dev/null
+## @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
--- /dev/null
+\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
--- /dev/null
+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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+## @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
+ PreMt