diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /ReferenceCode/Chipset/LynxPoint/PchInit | |
download | zprj-master.tar.xz |
Diffstat (limited to 'ReferenceCode/Chipset/LynxPoint/PchInit')
55 files changed, 25444 insertions, 0 deletions
diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHSIO.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHSIO.c new file mode 100644 index 0000000..4c23c06 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHSIO.c @@ -0,0 +1,48 @@ +/** @file + Intializes all common Hsio structures + +@copyright + Copyright (c) 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ + +#include "PchHsio.h" + +#ifdef ULT_FLAG + +IOBP_MMIO_TABLE_STRUCT PchSerialIoSnoopLptLp[] = { + { 0xCB000240, (UINT32)~(0x000C0000), 0x00040000 }, + { 0xCB000248, (UINT32)~(0x000C0000), 0x00040000 }, + { 0xCB000250, (UINT32)~(0x000C0000), 0x00040000 }, + { 0xCB000258, (UINT32)~(0x000C0000), 0x00040000 }, + { 0xCB000260, (UINT32)~(0x000C0000), 0x00040000 }, + { 0xCB000268, (UINT32)~(0x000C0000), 0x00040000 }, + { 0xCB000270, (UINT32)~(0x000C0000), 0x00040000 }, + { 0xCB000014, (UINT32)~(0x00006000), 0x00002000 } +}; + +IOBP_MMIO_TABLE_STRUCT PchSerialIoIntsLptLp[] = { // Device INTx PCI IRQ ACPI IRQ + { 0xCB000240, (UINT32)~(0x0000003C), 0x00000008 }, // D21:F0 = INTB IRQ20 IRQ6 + { 0xCB000248, (UINT32)~(0x0000003C), 0x0000000C }, // D21:F1 = INTC IRQ21 IRQ7 + { 0xCB000250, (UINT32)~(0x0000003C), 0x0000000C }, // D21:F2 = INTC IRQ21 IRQ7 + { 0xCB000258, (UINT32)~(0x0000003C), 0x0000000C }, // D21:F3 = INTC IRQ21 IRQ7 + { 0xCB000260, (UINT32)~(0x0000003C), 0x0000000C }, // D21:F4 = INTC IRQ21 IRQ7 + { 0xCB000268, (UINT32)~(0x0000003C), 0x00000010 }, // D21:F5 = INTD IRQ21 IRQ13 + { 0xCB000270, (UINT32)~(0x0000003C), 0x00000010 } // D21:F6 = INTD IRQ21 IRQ13 +}; // D23:F0 = INTA IRQ22 IRQ5 + +#endif // ULT_FLAG
\ No newline at end of file diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHSIO.h b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHSIO.h new file mode 100644 index 0000000..4dc83d9 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHSIO.h @@ -0,0 +1,47 @@ +/** @file + + Header file with all common Hsio information + +@copyright + Copyright (c) 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ + +#ifndef _PCH_HSIO_H_ +#define _PCH_HSIO_H_ + +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "EdkIIGlueBase.h" +#include "PchAccess.h" +#include "PchPlatformLib.h" +#include "IobpDefinitions.h" +#ifdef TRAD_FLAG +#include "PchHsioLptHB0.h" +#include "PchHsioLptHCx.h" +#endif //TRAD_FLAG +#ifdef ULT_FLAG +#include "PchHsioLptLpBx.h" +#endif //ULT_FLAG +#endif + + +#ifdef ULT_FLAG +extern IOBP_MMIO_TABLE_STRUCT PchSerialIoSnoopLptLp[8]; +extern IOBP_MMIO_TABLE_STRUCT PchSerialIoIntsLptLp[7]; +#endif // ULT_FLAG + +#endif //_PCH_HSIO_H_
\ No newline at end of file diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHSIOLptHB0.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHSIOLptHB0.c new file mode 100644 index 0000000..190f824 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHSIOLptHB0.c @@ -0,0 +1,295 @@ +/** @file + Intializes all include B0 Hsio structures + +@copyright + Copyright (c) 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ + +#include "PchHsio.h" + +#ifdef TRAD_FLAG + +UINT8 PchChipsetInitTableLptH_B0[] = { + 0x79, 0x56, //U16 CRC-16 + 0x23, 0x02, //U16 Version + 0x1A, //U8 NumEntries + // Hsio Entries + // Offset Value EP + 0x40,0xC1, 0xA6,0x05,0x08,0x00, 0xEB, + 0x44,0xC1, 0x94,0x03,0x04,0x00, 0xEB, + 0x40,0x83, 0x96,0x05,0x08,0x00, 0xE9, + 0x40,0x83, 0x96,0x05,0x08,0x00, 0xEA, + 0x44,0x83, 0x94,0x03,0x04,0x00, 0xE9, + 0x44,0x83, 0x94,0x03,0x04,0x00, 0xEA, + 0x0C,0x80, 0x50,0xAB,0x02,0x0E, 0xEB, + 0x0C,0x80, 0x50,0xAB,0x02,0x0E, 0xE9, + 0x00,0xC1, 0x89,0x5F,0x0B,0x0F, 0xEB, + 0x00,0xC1, 0x89,0x5F,0x0B,0x0F, 0xE9, + 0x7C,0xC1, 0x00,0x3F,0x40,0x3D, 0xEB, + 0x7C,0xC1, 0x00,0x3F,0x00,0x4F, 0xE9, + 0x78,0xC1, 0x84,0x1B,0x00,0x00, 0xE9, + 0xCC,0xC1, 0x04,0x43,0x35,0x00, 0xEB, + 0x90,0xC0, 0x55,0x51,0x3E,0x2B, 0xE9, + 0x90,0x82, 0x55,0x51,0x3E,0x2B, 0xEA, + 0x8C,0xC0, 0x46,0x20,0x78,0x0C, 0xE9, + 0x8C,0x82, 0x46,0x20,0x78,0x0C, 0xEA, + 0x30,0xC0, 0x00,0x0F,0x00,0x00, 0xEB, + 0x30,0xC0, 0x00,0x0F,0x00,0x00, 0xE9, + 0x30,0xC0, 0x00,0x0F,0x00,0x00, 0xEA, + 0xCC,0xC1, 0x04,0x43,0x35,0x00, 0xE9, + 0xCC,0xC1, 0x04,0x43,0x35,0x00, 0xEA, + 0x2C,0xC0, 0x00,0x0A,0x00,0x0F, 0xEB, + 0x2C,0x82, 0x00,0x0A,0x00,0x0F, 0xE9, + 0x2C,0x82, 0x00,0x0A,0x00,0x0F, 0xEA +}; + +IOBP_MMIO_TABLE_STRUCT PchSataHsioLptH_B0[] = { + { 0xEA008008, (UINT32)~(0xFF000000), 0x1C000000 }, + { 0xEA00800C, (UINT32)~(0x00007FFF), 0x00002B50 }, + { 0xEA0024A4, (UINT32)~(0x0030FF00), 0x00308300 }, + { 0xEA0026A4, (UINT32)~(0x0030FF00), 0x00308300 }, + { 0xEA0008A4, (UINT32)~(0x0030FF00), 0x00308300 }, + { 0xEA000AA4, (UINT32)~(0x0030FF00), 0x00308300 }, + { 0xEA0024AC, (UINT32)~(0x00000030), 0x00000020 }, + { 0xEA0026AC, (UINT32)~(0x00000030), 0x00000020 }, + { 0xEA0008AC, (UINT32)~(0x00000030), 0x00000020 }, + { 0xEA000AAC, (UINT32)~(0x00000030), 0x00000020 }, + { 0xEA002488, (UINT32)~(0x0000FF00), 0x00008000 }, + { 0xEA002688, (UINT32)~(0x0000FF00), 0x00008000 }, + { 0xEA000888, (UINT32)~(0x0000FF00), 0x00008000 }, + { 0xEA000A88, (UINT32)~(0x0000FF00), 0x00008000 }, + { 0xEA002494, (UINT32)~(0x80000000), 0x80000000 }, + { 0xEA002694, (UINT32)~(0x80000000), 0x80000000 }, + { 0xEA000894, (UINT32)~(0x80000000), 0x80000000 }, + { 0xEA000A94, (UINT32)~(0x80000000), 0x80000000 }, + { 0xEA002540, (UINT32)~(0x00FFFFFF), 0x00180918 }, + { 0xEA002740, (UINT32)~(0x00FFFFFF), 0x00180918 }, + { 0xEA000940, (UINT32)~(0x00FFFFFF), 0x00180918 }, + { 0xEA000B40, (UINT32)~(0x00FFFFFF), 0x00180918 }, + { 0xEA002544, (UINT32)~(0x00FFFFFF), 0x00140918 }, + { 0xEA002744, (UINT32)~(0x00FFFFFF), 0x00140918 }, + { 0xEA000944, (UINT32)~(0x00FFFFFF), 0x00140918 }, + { 0xEA000B44, (UINT32)~(0x00FFFFFF), 0x00140918 }, + { 0xEA002548, (UINT32)~(0x00FFFFFF), 0x00140918 }, + { 0xEA002748, (UINT32)~(0x00FFFFFF), 0x00140918 }, + { 0xEA000948, (UINT32)~(0x00FFFFFF), 0x00140918 }, + { 0xEA000B48, (UINT32)~(0x00FFFFFF), 0x00140918 }, + { 0xEA002550, (UINT32)~(0x3F000000), 0x02000000 }, + { 0xEA002750, (UINT32)~(0x3F000000), 0x02000000 }, + { 0xEA000950, (UINT32)~(0x3F000000), 0x02000000 }, + { 0xEA000B50, (UINT32)~(0x3F000000), 0x02000000 }, + { 0xEA002554, (UINT32)~(0x003F0000), 0x00020000 }, + { 0xEA002754, (UINT32)~(0x003F0000), 0x00020000 }, + { 0xEA000954, (UINT32)~(0x003F0000), 0x00020000 }, + { 0xEA000B54, (UINT32)~(0x003F0000), 0x00020000 }, + { 0xEA002410, (UINT32)~(0xFFFF0000), 0x0D510000 }, + { 0xEA002610, (UINT32)~(0xFFFF0000), 0x0D510000 }, + { 0xEA000810, (UINT32)~(0xFFFF0000), 0x0D510000 }, + { 0xEA000A10, (UINT32)~(0xFFFF0000), 0x0D510000 }, + { 0xEA002400, (UINT32)~(0xCF030000), 0xCF030000 }, + { 0xEA002600, (UINT32)~(0xCF030000), 0xCF030000 }, + { 0xEA000800, (UINT32)~(0xCF030000), 0xCF030000 }, + { 0xEA000A00, (UINT32)~(0xCF030000), 0xCF030000 }, + { 0xEA002408, (UINT32)~(0xFFFC6108), 0xEA6C6108 }, + { 0xEA002608, (UINT32)~(0xFFFC6108), 0xEA6C6108 }, + { 0xEA000808, (UINT32)~(0xFFFC6108), 0xEA6C6108 }, + { 0xEA000A08, (UINT32)~(0xFFFC6108), 0xEA6C6108 }, + { 0xEA002418, (UINT32)~(0xFFFF0300), 0x38250100 }, + { 0xEA002618, (UINT32)~(0xFFFF0300), 0x38250100 }, + { 0xEA000818, (UINT32)~(0xFFFF0300), 0x38250100 }, + { 0xEA000A18, (UINT32)~(0xFFFF0300), 0x38250100 }, + { 0xEA002428, (UINT32)~(0xFF1F0000), 0x580E0000 }, + { 0xEA002628, (UINT32)~(0xFF1F0000), 0x580E0000 }, + { 0xEA000828, (UINT32)~(0xFF1F0000), 0x580E0000 }, + { 0xEA000A28, (UINT32)~(0xFF1F0000), 0x580E0000 }, + { 0xEA002438, (UINT32)~(0x0000000F), 0x0000000D }, + { 0xEA002638, (UINT32)~(0x0000000F), 0x0000000D }, + { 0xEA000838, (UINT32)~(0x0000000F), 0x0000000D }, + { 0xEA000A38, (UINT32)~(0x0000000F), 0x0000000D }, + { 0xEA002440, (UINT32)~(0x1F000000), 0x01000000 }, + { 0xEA002640, (UINT32)~(0x1F000000), 0x01000000 }, + { 0xEA000840, (UINT32)~(0x1F000000), 0x01000000 }, + { 0xEA000A40, (UINT32)~(0x1F000000), 0x01000000 }, + { 0xEA00242C, (UINT32)~(0x00020000), 0x00020000 }, + { 0xEA00262C, (UINT32)~(0x00020000), 0x00020000 }, + { 0xEA00082C, (UINT32)~(0x00020000), 0x00020000 }, + { 0xEA000A2C, (UINT32)~(0x00020000), 0x00020000 }, + { 0xEA00241C, (UINT32)~(0x00007C00), 0x00002400 }, + { 0xEA00261C, (UINT32)~(0x00007C00), 0x00002400 }, + { 0xEA00081C, (UINT32)~(0x00007C00), 0x00002400 }, + { 0xEA000A1C, (UINT32)~(0x00007C00), 0x00002400 }, + { 0xEA002500, (UINT32)~(0x0000E03E), 0x00004008 }, + { 0xEA002700, (UINT32)~(0x0000E03E), 0x00004008 }, + { 0xEA000900, (UINT32)~(0x0000E03E), 0x00004008 }, + { 0xEA000B00, (UINT32)~(0x0000E03E), 0x00004008 }, + { 0xEA00257C, (UINT32)~(0x000F3F00), 0x00003F00 }, + { 0xEA00277C, (UINT32)~(0x000F3F00), 0x00003F00 }, + { 0xEA00097C, (UINT32)~(0x000F3F00), 0x00003F00 }, + { 0xEA000B7C, (UINT32)~(0x000F3F00), 0x00003F00 } +}; + +IOBP_MMIO_TABLE_STRUCT PchSataSharedHsioLptH_B0[] = { + { 0xEA0020A4, (UINT32)~(0x0030FF00), 0x00308300 }, + { 0xEA0022A4, (UINT32)~(0x0030FF00), 0x00308300 }, + { 0xEA0020AC, (UINT32)~(0x00000030), 0x00000020 }, + { 0xEA0022AC, (UINT32)~(0x00000030), 0x00000020 }, + { 0xEA002088, (UINT32)~(0x0000FF00), 0x00008000 }, + { 0xEA002288, (UINT32)~(0x0000FF00), 0x00008000 }, + { 0xEA002094, (UINT32)~(0x80000000), 0x80000000 }, + { 0xEA002294, (UINT32)~(0x80000000), 0x80000000 }, + { 0xEA002140, (UINT32)~(0x00FFFFFF), 0x00180918 }, + { 0xEA002340, (UINT32)~(0x00FFFFFF), 0x00180918 }, + { 0xEA002144, (UINT32)~(0x00FFFFFF), 0x00140918 }, + { 0xEA002344, (UINT32)~(0x00FFFFFF), 0x00140918 }, + { 0xEA002148, (UINT32)~(0x00FFFFFF), 0x00140918 }, + { 0xEA002348, (UINT32)~(0x00FFFFFF), 0x00140918 }, + { 0xEA002150, (UINT32)~(0x3F000000), 0x02000000 }, + { 0xEA002350, (UINT32)~(0x3F000000), 0x02000000 }, + { 0xEA002154, (UINT32)~(0x003F0000), 0x00020000 }, + { 0xEA002354, (UINT32)~(0x003F0000), 0x00020000 }, + { 0xEA002010, (UINT32)~(0xFFFF0000), 0x0D510000 }, + { 0xEA002210, (UINT32)~(0xFFFF0000), 0x0D510000 }, + { 0xEA002000, (UINT32)~(0xCF030000), 0xCF030000 }, + { 0xEA002200, (UINT32)~(0xCF030000), 0xCF030000 }, + { 0xEA002008, (UINT32)~(0xFFFC6108), 0xEA6C6108 }, + { 0xEA002208, (UINT32)~(0xFFFC6108), 0xEA6C6108 }, + { 0xEA002018, (UINT32)~(0xFFFF0300), 0x38250100 }, + { 0xEA002218, (UINT32)~(0xFFFF0300), 0x38250100 }, + { 0xEA002028, (UINT32)~(0xFF1F0000), 0x580E0000 }, + { 0xEA002228, (UINT32)~(0xFF1F0000), 0x580E0000 }, + { 0xEA002038, (UINT32)~(0x0000000F), 0x0000000D }, + { 0xEA002238, (UINT32)~(0x0000000F), 0x0000000D }, + { 0xEA002040, (UINT32)~(0x1F000000), 0x01000000 }, + { 0xEA002240, (UINT32)~(0x1F000000), 0x01000000 }, + { 0xEA00202C, (UINT32)~(0x00020700), 0x00020100 }, + { 0xEA00222C, (UINT32)~(0x00020700), 0x00020100 }, + { 0xEA00201C, (UINT32)~(0x00007C00), 0x00002400 }, + { 0xEA00221C, (UINT32)~(0x00007C00), 0x00002400 }, + { 0xEA002100, (UINT32)~(0x0000E03E), 0x00004008 }, + { 0xEA002300, (UINT32)~(0x0000E03E), 0x00004008 }, + { 0xEA00217C, (UINT32)~(0x000F3F00), 0x00003F00 }, + { 0xEA00237C, (UINT32)~(0x000F3F00), 0x00003F00 } +}; + +IOBP_MMIO_TABLE_STRUCT PchUsb3HsioLptH_B0[] = { + { 0xE9003140, (UINT32)~(0x00FFFFFF), 0x00040998 }, + { 0xE9003340, (UINT32)~(0x00FFFFFF), 0x00040998 }, + { 0xE9001540, (UINT32)~(0x00FFFFFF), 0x00040998 }, + { 0xE9001740, (UINT32)~(0x00FFFFFF), 0x00040998 }, + { 0xE900316C, (UINT32)~(0x000000FF), 0x0000003F }, + { 0xE900336C, (UINT32)~(0x000000FF), 0x0000003F }, + { 0xE900156C, (UINT32)~(0x000000FF), 0x0000003F }, + { 0xE900176C, (UINT32)~(0x000000FF), 0x0000003F }, + { 0xE9003168, (UINT32)~(0x01000F3C), 0x00000A28 }, + { 0xE9003368, (UINT32)~(0x01000F3C), 0x00000A28 }, + { 0xE9001568, (UINT32)~(0x01000F3C), 0x00000A28 }, + { 0xE9001768, (UINT32)~(0x01000F3C), 0x00000A28 }, + { 0xE900314C, (UINT32)~(0x00FF0000), 0x00140000 }, + { 0xE900334C, (UINT32)~(0x00FF0000), 0x00140000 }, + { 0xE900154C, (UINT32)~(0x00FF0000), 0x00140000 }, + { 0xE900174C, (UINT32)~(0x00FF0000), 0x00140000 }, + { 0xE9003164, (UINT32)~(0x0000F000), 0x00005000 }, + { 0xE9003364, (UINT32)~(0x0000F000), 0x00005000 }, + { 0xE9001564, (UINT32)~(0x0000F000), 0x00005000 }, + { 0xE9001764, (UINT32)~(0x0000F000), 0x00005000 }, + { 0xE9003170, (UINT32)~(0x00000018), 0x00000000 }, + { 0xE9003370, (UINT32)~(0x00000018), 0x00000000 }, + { 0xE9001570, (UINT32)~(0x00000018), 0x00000000 }, + { 0xE9001770, (UINT32)~(0x00000018), 0x00000000 }, + { 0xE90031CC, (UINT32)~(0x00001407), 0x00001401 }, + { 0xE90033CC, (UINT32)~(0x00001407), 0x00001401 }, + { 0xE90015CC, (UINT32)~(0x00001407), 0x00001401 }, + { 0xE90017CC, (UINT32)~(0x00001407), 0x00001401 } +}; + +IOBP_MMIO_TABLE_STRUCT PchUsb3SharedHsioLptH_B0[] = { + { 0xE9002D40, (UINT32)~(0x00FFFFFF), 0x00040998 }, + { 0xE9002F40, (UINT32)~(0x00FFFFFF), 0x00040998 }, + { 0xE9002D6C, (UINT32)~(0x000000FF), 0x0000003F }, + { 0xE9002F6C, (UINT32)~(0x000000FF), 0x0000003F }, + { 0xE9002D44, (UINT32)~(0x000000FF), 0x00000014 }, + { 0xE9002F44, (UINT32)~(0x000000FF), 0x00000014 }, + { 0xE9002D68, (UINT32)~(0x01000F3C), 0x00000A28 }, + { 0xE9002F68, (UINT32)~(0x01000F3C), 0x00000A28 }, + { 0xE9002D4C, (UINT32)~(0x00FF0000), 0x00140000 }, + { 0xE9002F4C, (UINT32)~(0x00FF0000), 0x00140000 }, + { 0xE9002D64, (UINT32)~(0x0000F000), 0x00005000 }, + { 0xE9002F64, (UINT32)~(0x0000F000), 0x00005000 }, + { 0xE9002D70, (UINT32)~(0x00000018), 0x00000000 }, + { 0xE9002F70, (UINT32)~(0x00000018), 0x00000000 }, + { 0xE9002DCC, (UINT32)~(0x00001407), 0x00001401 }, + { 0xE9002FCC, (UINT32)~(0x00001407), 0x00001401 }, + { 0xE9002C2C, (UINT32)~(0x00000700), 0x00000100 }, + { 0xE9002E2C, (UINT32)~(0x00000700), 0x00000100 } +}; + +IOBP_MMIO_TABLE_STRUCT PchGbeSharedHsioLptH_B0[] = { + { 0xE9002E08, (UINT32)~(0xF0000100), 0xE0000100 }, + { 0xE9002C08, (UINT32)~(0xF0000100), 0xE0000100 }, + { 0xE9002A08, (UINT32)~(0xF0000100), 0xE0000100 }, + { 0xE9002808, (UINT32)~(0xF0000100), 0xE0000100 }, + { 0xE9002608, (UINT32)~(0xF0000100), 0xE0000100 }, + { 0xE9002408, (UINT32)~(0xF0000100), 0xE0000100 }, + { 0xE9002208, (UINT32)~(0xF0000100), 0xE0000100 }, + { 0xE9002008, (UINT32)~(0xF0000100), 0xE0000100 } +}; + +IOBP_MMIO_TABLE_STRUCT PchDmiHsioLptH_B0[] = { + { 0xEB002090, (UINT32)~(0x0000FF00), 0x00005100 }, + { 0xEB002290, (UINT32)~(0x0000FF00), 0x00005100 }, + { 0xEB000490, (UINT32)~(0x0000FF00), 0x00005100 }, + { 0xEB000690, (UINT32)~(0x0000FF00), 0x00005100 } +}; + +IOBP_MMIO_TABLE_STRUCT PchSataHsioLptH_DT_B0[] = { + { 0xEA002490, (UINT32)~(0x0000FFFF), 0x00003E67 }, + { 0xEA002690, (UINT32)~(0x0000FFFF), 0x00003E67 }, + { 0xEA000890, (UINT32)~(0x0000FFFF), 0x00003E67 }, + { 0xEA000A90, (UINT32)~(0x0000FFFF), 0x00003E67 }, + { 0xEA00248C, (UINT32)~(0x00FF0000), 0x00800000 }, + { 0xEA00268C, (UINT32)~(0x00FF0000), 0x00800000 }, + { 0xEA00088C, (UINT32)~(0x00FF0000), 0x00800000 }, + { 0xEA000A8C, (UINT32)~(0x00FF0000), 0x00800000 } +}; + +IOBP_MMIO_TABLE_STRUCT PchSataSharedHsioLptH_DT_B0[] = { + { 0xEA002090, (UINT32)~(0x0000FFFF), 0x00003E67 }, + { 0xEA002290, (UINT32)~(0x0000FFFF), 0x00003E67 }, + { 0xEA00208C, (UINT32)~(0x00FF0000), 0x00800000 }, + { 0xEA00228C, (UINT32)~(0x00FF0000), 0x00800000 } +}; + +IOBP_MMIO_TABLE_STRUCT PchSataHsioLptH_MB_B0[] = { + { 0xEA002490, (UINT32)~(0x0000FFFF), 0x00004C5A }, + { 0xEA002690, (UINT32)~(0x0000FFFF), 0x00004C5A }, + { 0xEA000890, (UINT32)~(0x0000FFFF), 0x00004C5A }, + { 0xEA000A90, (UINT32)~(0x0000FFFF), 0x00004C5A }, + { 0xEA00248C, (UINT32)~(0x00FF0000), 0x00800000 }, + { 0xEA00268C, (UINT32)~(0x00FF0000), 0x00800000 }, + { 0xEA00088C, (UINT32)~(0x00FF0000), 0x00800000 }, + { 0xEA000A8C, (UINT32)~(0x00FF0000), 0x00800000 } +}; + +IOBP_MMIO_TABLE_STRUCT PchSataSharedHsioLptH_MB_B0[] = { + { 0xEA002090, (UINT32)~(0x0000FFFF), 0x00004C5A }, + { 0xEA002290, (UINT32)~(0x0000FFFF), 0x00004C5A }, + { 0xEA00208C, (UINT32)~(0x00FF0000), 0x00800000 }, + { 0xEA00228C, (UINT32)~(0x00FF0000), 0x00800000 } +}; + +#endif // TRAD_FLAG diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHSIOLptHB0.h b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHSIOLptHB0.h new file mode 100644 index 0000000..efdd645 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHSIOLptHB0.h @@ -0,0 +1,44 @@ +/** @file + + Header file with all LptHB0 Hsio information + +@copyright + Copyright (c) 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ + + +#ifdef TRAD_FLAG +#ifndef _PCH_HSIO_LPTHB0_H_ +#define _PCH_HSIO_LPTHB0_H_ + +#define PCH_LPTH_HSIO_VER_B0 0x23 + +extern UINT8 PchChipsetInitTableLptH_B0[187]; +extern IOBP_MMIO_TABLE_STRUCT PchSataHsioLptH_B0[82]; +extern IOBP_MMIO_TABLE_STRUCT PchSataSharedHsioLptH_B0[40]; +extern IOBP_MMIO_TABLE_STRUCT PchUsb3HsioLptH_B0[28]; +extern IOBP_MMIO_TABLE_STRUCT PchUsb3SharedHsioLptH_B0[18]; +extern IOBP_MMIO_TABLE_STRUCT PchGbeSharedHsioLptH_B0[8]; +extern IOBP_MMIO_TABLE_STRUCT PchDmiHsioLptH_B0[4]; +extern IOBP_MMIO_TABLE_STRUCT PchSataHsioLptH_DT_B0[8]; +extern IOBP_MMIO_TABLE_STRUCT PchSataSharedHsioLptH_DT_B0[4]; +extern IOBP_MMIO_TABLE_STRUCT PchSataHsioLptH_MB_B0[8]; +extern IOBP_MMIO_TABLE_STRUCT PchSataSharedHsioLptH_MB_B0[4]; + +#endif //_PCH_HSIO_LPTHB0_H_ +#endif //TRAD_FLAG
\ No newline at end of file diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHsioLptHCx.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHsioLptHCx.c new file mode 100644 index 0000000..68e74df --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHsioLptHCx.c @@ -0,0 +1,326 @@ +/** @file + Initializes all LPTHCx Hsio structures + +@copyright + Copyright (c) 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement. + +**/ + +#include "PchHsio.h" + +#ifdef TRAD_FLAG + +UINT8 PchChipsetInitTableLptH_Cx[] = { + 0x9D, 0x59, //U16 CRC-16 + 0x2C, 0x03, //U16 Version + 0x29, //U8 NumEntries; + // HSIO Entries + // Offset Value EP + 0x2C,0xC0, 0x00,0x0A,0x00,0x0F, 0xEB, + 0x2C,0x82, 0x00,0x0A,0x00,0x0F, 0xE9, + 0x40,0xC1, 0x9C,0x05,0x88,0x00, 0xE9, + 0x98,0xC0, 0x41,0x3B,0x20,0x1F, 0xEB, + 0x98,0xC0, 0x41,0x3B,0x20,0x1F, 0xE9, + 0x98,0xC0, 0x41,0x3B,0x20,0x1F, 0xEA, + 0x2C,0x82, 0x00,0x0A,0x00,0x0F, 0xEA, + 0x30,0xC0, 0x00,0x0F,0x00,0x00, 0xEB, + 0x30,0xC0, 0x00,0x0F,0x00,0x00, 0xE9, + 0x94,0xC0, 0x55,0x60,0x40,0x47, 0xEB, + 0x30,0xC0, 0x00,0x0F,0x00,0x00, 0xEA, + 0x40,0x83, 0x9C,0x05,0x88,0x00, 0xEA, + 0x78,0xC1, 0x80,0x19,0x00,0x00, 0xEB, + 0x94,0xC0, 0x55,0x60,0x40,0x47, 0xE9, + 0x94,0xC0, 0x55,0x60,0x40,0x47, 0xEA, + 0x88,0xC0, 0x3A,0x98,0x80,0x55, 0xEB, + 0x78,0xC1, 0x80,0x19,0x00,0x00, 0xE9, + 0x88,0xC0, 0x3A,0x98,0x80,0x55, 0xE9, + 0x88,0x82, 0x3A,0x98,0x80,0x55, 0xEA, + 0x8C,0xC0, 0x46,0x20,0x78,0x0C, 0xEB, + 0x8C,0xC0, 0x46,0x20,0x78,0x0C, 0xE9, + 0x8C,0x82, 0x46,0x20,0x78,0x0C, 0xEA, + 0x78,0xC1, 0x80,0x19,0x00,0x00, 0xEA, + 0xCC,0xC1, 0x04,0x43,0x25,0x38, 0xE9, + 0xCC,0xC1, 0x04,0x43,0x25,0x38, 0xEB, + 0xCC,0xC1, 0x04,0x43,0x25,0x38, 0xEA, + 0x7C,0xC1, 0x00,0x24,0xA0,0x4E, 0xE9, + 0x7C,0xC1, 0x00,0x24,0xC0,0x3E, 0xEB, + 0x7C,0xC1, 0x00,0x24,0xC0,0x3E, 0xEA, + 0x40,0xC1, 0xAC,0x05,0x88,0x00, 0xEB, + 0x90,0xC0, 0x55,0x51,0x3E,0x2B, 0xEB, + 0x90,0xC0, 0x55,0x51,0x3E,0x2B, 0xE9, + 0x90,0x82, 0x55,0x51,0x3E,0x2B, 0xEA, + 0x08,0xC0, 0x00,0xA0,0x00,0xB0, 0xE9, + 0x08,0xC0, 0x00,0xA0,0x00,0xB0, 0xEA, + 0x44,0xC1, 0x94,0x03,0x84,0x00, 0xEB, + 0x44,0xC1, 0x94,0x03,0x84,0x00, 0xE9, + 0x44,0x83, 0x94,0x03,0x84,0x00, 0xEA, + 0x38,0xC0, 0x32,0x00,0xCE,0x38, 0xEB, + 0x38,0xC0, 0x32,0x00,0xCE,0x38, 0xE9, + 0x38,0xC0, 0x32,0x00,0xCE,0x38, 0xEA +}; + +IOBP_MMIO_TABLE_STRUCT PchSataSharedHsioLptH_Cx[] = { + { 0xEA002008, (UINT32)~(0xFFFC6108), 0xEA6C6108 }, + { 0xEA002208, (UINT32)~(0xFFFC6108), 0xEA6C6108 }, + { 0xEA002038, (UINT32)~(0x3F00000F), 0x0700000D }, + { 0xEA002238, (UINT32)~(0x3F00000F), 0x0700000D }, + { 0xEA00202C, (UINT32)~(0x00020F00), 0x00020100 }, + { 0xEA00222C, (UINT32)~(0x00020F00), 0x00020100 }, + { 0xEA002040, (UINT32)~(0x1F000000), 0x01000000 }, + { 0xEA002240, (UINT32)~(0x1F000000), 0x01000000 }, + { 0xEA002010, (UINT32)~(0xFFFF0000), 0x0D510000 }, + { 0xEA002210, (UINT32)~(0xFFFF0000), 0x0D510000 }, + { 0xEA002018, (UINT32)~(0xFFFF0300), 0x38250100 }, + { 0xEA002218, (UINT32)~(0xFFFF0300), 0x38250100 }, + { 0xEA002000, (UINT32)~(0xCF030000), 0xCF030000 }, + { 0xEA002200, (UINT32)~(0xCF030000), 0xCF030000 }, + { 0xEA002028, (UINT32)~(0xFF1F0000), 0x580E0000 }, + { 0xEA002228, (UINT32)~(0xFF1F0000), 0x580E0000 }, + { 0xEA00201C, (UINT32)~(0x00007C00), 0x00002400 }, + { 0xEA00221C, (UINT32)~(0x00007C00), 0x00002400 }, + { 0xEA00208C, (UINT32)~(0x00FF0000), 0x00800000 }, + { 0xEA00228C, (UINT32)~(0x00FF0000), 0x00800000 }, + { 0xEA0020A4, (UINT32)~(0x0030FF00), 0x00308300 }, + { 0xEA0022A4, (UINT32)~(0x0030FF00), 0x00308300 }, + { 0xEA0020AC, (UINT32)~(0x00000030), 0x00000020 }, + { 0xEA0022AC, (UINT32)~(0x00000030), 0x00000020 }, + { 0xEA002140, (UINT32)~(0x00FFFFFF), 0x00140718 }, + { 0xEA002340, (UINT32)~(0x00FFFFFF), 0x00140718 }, + { 0xEA002144, (UINT32)~(0x00FFFFFF), 0x00140998 }, + { 0xEA002344, (UINT32)~(0x00FFFFFF), 0x00140998 }, + { 0xEA002148, (UINT32)~(0x00FFFFFF), 0x00140998 }, + { 0xEA002348, (UINT32)~(0x00FFFFFF), 0x00140998 }, + { 0xEA00217C, (UINT32)~(0x03000000), 0x03000000 }, + { 0xEA00237C, (UINT32)~(0x03000000), 0x03000000 }, + { 0xEA002178, (UINT32)~(0x00001F00), 0x00001800 }, + { 0xEA002378, (UINT32)~(0x00001F00), 0x00001800 }, + { 0xEA00210C, (UINT32)~(0x0038000F), 0x00000005 }, + { 0xEA00230C, (UINT32)~(0x0038000F), 0x00000005 } +}; + +IOBP_MMIO_TABLE_STRUCT PchSataHsioLptH_Cx[] = { + { 0xEA008008, (UINT32)~(0xFF000000), 0x1C000000 }, + { 0xEA002408, (UINT32)~(0xFFFC6108), 0xEA6C6108 }, + { 0xEA002608, (UINT32)~(0xFFFC6108), 0xEA6C6108 }, + { 0xEA000808, (UINT32)~(0xFFFC6108), 0xEA6C6108 }, + { 0xEA000A08, (UINT32)~(0xFFFC6108), 0xEA6C6108 }, + { 0xEA002438, (UINT32)~(0x3F00000F), 0x0700000D }, + { 0xEA002638, (UINT32)~(0x3F00000F), 0x0700000D }, + { 0xEA000838, (UINT32)~(0x3F00000F), 0x0700000D }, + { 0xEA000A38, (UINT32)~(0x3F00000F), 0x0700000D }, + { 0xEA002440, (UINT32)~(0x1F000000), 0x01000000 }, + { 0xEA002640, (UINT32)~(0x1F000000), 0x01000000 }, + { 0xEA000840, (UINT32)~(0x1F000000), 0x01000000 }, + { 0xEA000A40, (UINT32)~(0x1F000000), 0x01000000 }, + { 0xEA002410, (UINT32)~(0xFFFF0000), 0x0D510000 }, + { 0xEA002610, (UINT32)~(0xFFFF0000), 0x0D510000 }, + { 0xEA000810, (UINT32)~(0xFFFF0000), 0x0D510000 }, + { 0xEA000A10, (UINT32)~(0xFFFF0000), 0x0D510000 }, + { 0xEA00242C, (UINT32)~(0x00020800), 0x00020000 }, + { 0xEA00262C, (UINT32)~(0x00020800), 0x00020000 }, + { 0xEA00082C, (UINT32)~(0x00020800), 0x00020000 }, + { 0xEA000A2C, (UINT32)~(0x00020800), 0x00020000 }, + { 0xEA002418, (UINT32)~(0xFFFF0300), 0x38250100 }, + { 0xEA002618, (UINT32)~(0xFFFF0300), 0x38250100 }, + { 0xEA000818, (UINT32)~(0xFFFF0300), 0x38250100 }, + { 0xEA000A18, (UINT32)~(0xFFFF0300), 0x38250100 }, + { 0xEA002400, (UINT32)~(0xCF030000), 0xCF030000 }, + { 0xEA002600, (UINT32)~(0xCF030000), 0xCF030000 }, + { 0xEA000800, (UINT32)~(0xCF030000), 0xCF030000 }, + { 0xEA000A00, (UINT32)~(0xCF030000), 0xCF030000 }, + { 0xEA002428, (UINT32)~(0xFF1F0000), 0x580E0000 }, + { 0xEA002628, (UINT32)~(0xFF1F0000), 0x580E0000 }, + { 0xEA000828, (UINT32)~(0xFF1F0000), 0x580E0000 }, + { 0xEA000A28, (UINT32)~(0xFF1F0000), 0x580E0000 }, + { 0xEA00241C, (UINT32)~(0x00007C00), 0x00002400 }, + { 0xEA00261C, (UINT32)~(0x00007C00), 0x00002400 }, + { 0xEA00081C, (UINT32)~(0x00007C00), 0x00002400 }, + { 0xEA000A1C, (UINT32)~(0x00007C00), 0x00002400 }, + { 0xEA00248C, (UINT32)~(0x00FF0000), 0x00800000 }, + { 0xEA00268C, (UINT32)~(0x00FF0000), 0x00800000 }, + { 0xEA00088C, (UINT32)~(0x00FF0000), 0x00800000 }, + { 0xEA000A8C, (UINT32)~(0x00FF0000), 0x00800000 }, + { 0xEA0024A4, (UINT32)~(0x0030FF00), 0x00308300 }, + { 0xEA0026A4, (UINT32)~(0x0030FF00), 0x00308300 }, + { 0xEA0008A4, (UINT32)~(0x0030FF00), 0x00308300 }, + { 0xEA000AA4, (UINT32)~(0x0030FF00), 0x00308300 }, + { 0xEA0024AC, (UINT32)~(0x00000030), 0x00000020 }, + { 0xEA0026AC, (UINT32)~(0x00000030), 0x00000020 }, + { 0xEA0008AC, (UINT32)~(0x00000030), 0x00000020 }, + { 0xEA000AAC, (UINT32)~(0x00000030), 0x00000020 }, + { 0xEA002540, (UINT32)~(0x00FFFFFF), 0x00140718 }, + { 0xEA002740, (UINT32)~(0x00FFFFFF), 0x00140718 }, + { 0xEA000940, (UINT32)~(0x00FFFFFF), 0x00140718 }, + { 0xEA000B40, (UINT32)~(0x00FFFFFF), 0x00140718 }, + { 0xEA002544, (UINT32)~(0x00FFFFFF), 0x00140998 }, + { 0xEA002744, (UINT32)~(0x00FFFFFF), 0x00140998 }, + { 0xEA000944, (UINT32)~(0x00FFFFFF), 0x00140998 }, + { 0xEA000B44, (UINT32)~(0x00FFFFFF), 0x00140998 }, + { 0xEA002548, (UINT32)~(0x00FFFFFF), 0x00140998 }, + { 0xEA002748, (UINT32)~(0x00FFFFFF), 0x00140998 }, + { 0xEA000948, (UINT32)~(0x00FFFFFF), 0x00140998 }, + { 0xEA000B48, (UINT32)~(0x00FFFFFF), 0x00140998 }, + { 0xEA00257C, (UINT32)~(0x03000000), 0x03000000 }, + { 0xEA00277C, (UINT32)~(0x03000000), 0x03000000 }, + { 0xEA00097C, (UINT32)~(0x03000000), 0x03000000 }, + { 0xEA000B7C, (UINT32)~(0x03000000), 0x03000000 }, + { 0xEA002578, (UINT32)~(0x00001F00), 0x00001800 }, + { 0xEA002778, (UINT32)~(0x00001F00), 0x00001800 }, + { 0xEA000978, (UINT32)~(0x00001F00), 0x00001800 }, + { 0xEA000B78, (UINT32)~(0x00001F00), 0x00001800 }, + { 0xEA00250C, (UINT32)~(0x0038000F), 0x00000005 }, + { 0xEA00270C, (UINT32)~(0x0038000F), 0x00000005 }, + { 0xEA00090C, (UINT32)~(0x0038000F), 0x00000005 }, + { 0xEA000B0C, (UINT32)~(0x0038000F), 0x00000005 } +}; + +IOBP_MMIO_TABLE_STRUCT PchUsb3SharedHsioLptH_Cx[] = { + { 0xE9002C2C, (UINT32)~(0x00000700), 0x00000100 }, + { 0xE9002E2C, (UINT32)~(0x00000700), 0x00000100 }, + { 0xE9002DCC, (UINT32)~(0x00001407), 0x00001407 }, + { 0xE9002FCC, (UINT32)~(0x00001407), 0x00001407 }, + { 0xE9002D68, (UINT32)~(0x01000F3C), 0x00000A28 }, + { 0xE9002F68, (UINT32)~(0x01000F3C), 0x00000A28 }, + { 0xE9002D6C, (UINT32)~(0x000000FF), 0x0000003F }, + { 0xE9002F6C, (UINT32)~(0x000000FF), 0x0000003F }, + { 0xE9002D4C, (UINT32)~(0x00FFFF00), 0x00120500 }, + { 0xE9002F4C, (UINT32)~(0x00FFFF00), 0x00120500 }, + { 0xE9002D14, (UINT32)~(0x38000700), 0x00000100 }, + { 0xE9002F14, (UINT32)~(0x38000700), 0x00000100 }, + { 0xE9002D64, (UINT32)~(0x0000F000), 0x00005000 }, + { 0xE9002F64, (UINT32)~(0x0000F000), 0x00005000 }, + { 0xE9002D70, (UINT32)~(0x00000018), 0x00000000 }, + { 0xE9002F70, (UINT32)~(0x00000018), 0x00000000 }, + { 0xE9002C38, (UINT32)~(0x3F00000F), 0x0700000B }, + { 0xE9002E38, (UINT32)~(0x3F00000F), 0x0700000B }, + { 0xE9002D40, (UINT32)~(0x00800000), 0x00000000 }, + { 0xE9002F40, (UINT32)~(0x00800000), 0x00000000 } +}; + +IOBP_MMIO_TABLE_STRUCT PchUsb3HsioLptH_Cx[] = { + { 0xE90031CC, (UINT32)~(0x00001407), 0x00001407 }, + { 0xE90033CC, (UINT32)~(0x00001407), 0x00001407 }, + { 0xE90015CC, (UINT32)~(0x00001407), 0x00001407 }, + { 0xE90017CC, (UINT32)~(0x00001407), 0x00001407 }, + { 0xE9003168, (UINT32)~(0x01000F3C), 0x00000A28 }, + { 0xE9003368, (UINT32)~(0x01000F3C), 0x00000A28 }, + { 0xE9001568, (UINT32)~(0x01000F3C), 0x00000A28 }, + { 0xE9001768, (UINT32)~(0x01000F3C), 0x00000A28 }, + { 0xE900316C, (UINT32)~(0x000000FF), 0x0000003F }, + { 0xE900336C, (UINT32)~(0x000000FF), 0x0000003F }, + { 0xE900156C, (UINT32)~(0x000000FF), 0x0000003F }, + { 0xE900176C, (UINT32)~(0x000000FF), 0x0000003F }, + { 0xE900314C, (UINT32)~(0x00FFFF00), 0x00120500 }, + { 0xE900334C, (UINT32)~(0x00FFFF00), 0x00120500 }, + { 0xE900154C, (UINT32)~(0x00FFFF00), 0x00120500 }, + { 0xE900174C, (UINT32)~(0x00FFFF00), 0x00120500 }, + { 0xE9003114, (UINT32)~(0x38000700), 0x00000100 }, + { 0xE9003314, (UINT32)~(0x38000700), 0x00000100 }, + { 0xE9001514, (UINT32)~(0x38000700), 0x00000100 }, + { 0xE9001714, (UINT32)~(0x38000700), 0x00000100 }, + { 0xE9003164, (UINT32)~(0x0000F000), 0x00005000 }, + { 0xE9003364, (UINT32)~(0x0000F000), 0x00005000 }, + { 0xE9001564, (UINT32)~(0x0000F000), 0x00005000 }, + { 0xE9001764, (UINT32)~(0x0000F000), 0x00005000 }, + { 0xE9003170, (UINT32)~(0x00000018), 0x00000000 }, + { 0xE9003370, (UINT32)~(0x00000018), 0x00000000 }, + { 0xE9001570, (UINT32)~(0x00000018), 0x00000000 }, + { 0xE9001770, (UINT32)~(0x00000018), 0x00000000 }, + { 0xE9003038, (UINT32)~(0x3F00000F), 0x0700000B }, + { 0xE9003238, (UINT32)~(0x3F00000F), 0x0700000B }, + { 0xE9001438, (UINT32)~(0x3F00000F), 0x0700000B }, + { 0xE9001638, (UINT32)~(0x3F00000F), 0x0700000B }, + { 0xE9003140, (UINT32)~(0x00800000), 0x00000000 }, + { 0xE9003340, (UINT32)~(0x00800000), 0x00000000 }, + { 0xE9001540, (UINT32)~(0x00800000), 0x00000000 }, + { 0xE9001740, (UINT32)~(0x00800000), 0x00000000 } +}; + +IOBP_MMIO_TABLE_STRUCT PchGbeSharedHsioLptH_Cx[] = { + { 0xE9002E08, (UINT32)~(0xF0000100), 0xE0000100 }, + { 0xE9002C08, (UINT32)~(0xF0000100), 0xE0000100 }, + { 0xE9002A08, (UINT32)~(0xF0000100), 0xE0000100 }, + { 0xE9002808, (UINT32)~(0xF0000100), 0xE0000100 }, + { 0xE9002608, (UINT32)~(0xF0000100), 0xE0000100 }, + { 0xE9002408, (UINT32)~(0xF0000100), 0xE0000100 }, + { 0xE9002208, (UINT32)~(0xF0000100), 0xE0000100 }, + { 0xE9002008, (UINT32)~(0xF0000100), 0xE0000100 } +}; + +IOBP_MMIO_TABLE_STRUCT PchSataSharedHsioLptH_MB_Cx[] = { + { 0xEA002090, (UINT32)~(0x0000FFFF), 0x00004C5A }, + { 0xEA002290, (UINT32)~(0x0000FFFF), 0x00004C5A } +}; + +IOBP_MMIO_TABLE_STRUCT PchSataHsioLptH_MB_Cx[] = { + { 0xEA002490, (UINT32)~(0x0000FFFF), 0x00004C5A }, + { 0xEA002690, (UINT32)~(0x0000FFFF), 0x00004C5A }, + { 0xEA000890, (UINT32)~(0x0000FFFF), 0x00004C5A }, + { 0xEA000A90, (UINT32)~(0x0000FFFF), 0x00004C5A } +}; + +IOBP_MMIO_TABLE_STRUCT PchSataSharedHsioLptH_DT_Cx[] = { + { 0xEA002090, (UINT32)~(0x0000FFFF), 0x00003E67 }, + { 0xEA002290, (UINT32)~(0x0000FFFF), 0x00003E67 } +}; + +IOBP_MMIO_TABLE_STRUCT PchSataHsioLptH_DT_Cx[] = { + { 0xEA002490, (UINT32)~(0x0000FFFF), 0x00003E67 }, + { 0xEA002690, (UINT32)~(0x0000FFFF), 0x00003E67 }, + { 0xEA000890, (UINT32)~(0x0000FFFF), 0x00003E67 }, + { 0xEA000A90, (UINT32)~(0x0000FFFF), 0x00003E67 } +}; + +IOBP_SATA_RXEQ_TABLE PchSataRxEqSharedHsioLptH_Cx[] = { + { 0x0400, 0xEA002154, (UINT32)~(0x00003F00) }, + { 0x0400, 0xEA002158, (UINT32)~(0x0000003F) }, + { 0x0500, 0xEA002354, (UINT32)~(0x00003F00) }, + { 0x0500, 0xEA002358, (UINT32)~(0x0000003F) }, + { 0x0401, 0xEA002154, (UINT32)~(0x3F00003F) }, + { 0x0501, 0xEA002354, (UINT32)~(0x3F00003F) }, + { 0x0402, 0xEA002150, (UINT32)~(0x3F000000) }, + { 0x0402, 0xEA002154, (UINT32)~(0x003F0000) }, + { 0x0502, 0xEA002350, (UINT32)~(0x3F000000) }, + { 0x0502, 0xEA002354, (UINT32)~(0x003F0000) } +}; + +IOBP_SATA_RXEQ_TABLE PchSataRxEqHsioLptH_Cx[] = { + { 0x0000, 0xEA002554, (UINT32)~(0x00003F00) }, + { 0x0000, 0xEA002558, (UINT32)~(0x0000003F) }, + { 0x0100, 0xEA002754, (UINT32)~(0x00003F00) }, + { 0x0100, 0xEA002758, (UINT32)~(0x0000003F) }, + { 0x0200, 0xEA000954, (UINT32)~(0x00003F00) }, + { 0x0200, 0xEA000958, (UINT32)~(0x0000003F) }, + { 0x0300, 0xEA000B54, (UINT32)~(0x00003F00) }, + { 0x0300, 0xEA000B58, (UINT32)~(0x0000003F) }, + { 0x0001, 0xEA002554, (UINT32)~(0x3F00003F) }, + { 0x0101, 0xEA002754, (UINT32)~(0x3F00003F) }, + { 0x0201, 0xEA000954, (UINT32)~(0x3F00003F) }, + { 0x0301, 0xEA000B54, (UINT32)~(0x3F00003F) }, + { 0x0002, 0xEA002550, (UINT32)~(0x3F000000) }, + { 0x0002, 0xEA002554, (UINT32)~(0x003F0000) }, + { 0x0102, 0xEA002750, (UINT32)~(0x3F000000) }, + { 0x0102, 0xEA002754, (UINT32)~(0x003F0000) }, + { 0x0202, 0xEA000950, (UINT32)~(0x3F000000) }, + { 0x0202, 0xEA000954, (UINT32)~(0x003F0000) }, + { 0x0302, 0xEA000B50, (UINT32)~(0x3F000000) }, + { 0x0302, 0xEA000B54, (UINT32)~(0x003F0000) } +}; + +#endif // TRAD_FLAG + + diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHsioLptHCx.h b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHsioLptHCx.h new file mode 100644 index 0000000..95ebdf7 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHsioLptHCx.h @@ -0,0 +1,47 @@ +/** @file + + Header file with all LPTHCx Hsio information + +@copyright + Copyright (c) 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement. + +**/ + + +#ifdef TRAD_FLAG +#ifndef _PCH_HSIO_LPTHCX_H_ +#define _PCH_HSIO_LPTHCX_H_ + +#define PCH_LPTH_HSIO_VER_CX 0x2C + +extern UINT8 PchChipsetInitTableLptH_Cx[292]; +extern IOBP_MMIO_TABLE_STRUCT PchSataSharedHsioLptH_Cx[36]; +extern IOBP_MMIO_TABLE_STRUCT PchSataHsioLptH_Cx[73]; +extern IOBP_MMIO_TABLE_STRUCT PchUsb3SharedHsioLptH_Cx[20]; +extern IOBP_MMIO_TABLE_STRUCT PchUsb3HsioLptH_Cx[36]; +extern IOBP_MMIO_TABLE_STRUCT PchGbeSharedHsioLptH_Cx[8]; +extern IOBP_MMIO_TABLE_STRUCT PchSataSharedHsioLptH_MB_Cx[2]; +extern IOBP_MMIO_TABLE_STRUCT PchSataHsioLptH_MB_Cx[4]; +extern IOBP_MMIO_TABLE_STRUCT PchSataSharedHsioLptH_DT_Cx[2]; +extern IOBP_MMIO_TABLE_STRUCT PchSataHsioLptH_DT_Cx[4]; +extern IOBP_SATA_RXEQ_TABLE PchSataRxEqSharedHsioLptH_Cx[10]; +extern IOBP_SATA_RXEQ_TABLE PchSataRxEqHsioLptH_Cx[20]; + + +#endif //_PCH_HSIO_LPTHCX_H_ +#endif //TRAD_FLAG + diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHsioLptLpBx.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHsioLptLpBx.c new file mode 100644 index 0000000..85d763b --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHsioLptLpBx.c @@ -0,0 +1,239 @@ +/** @file + Initializes all LPTLPBx Hsio structures + +@copyright + Copyright (c) 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement. + +**/ + +#include "PchHsio.h" + +#ifdef ULT_FLAG + +UINT8 PchChipsetInitTableLptLp_Bx[] = { + 0xC2, 0xFB, //U16 CRC-16 + 0x19, 0x11, //U16 Version + 0x20, //U8 NumEntries; + // HSIO Entries + // Offset Value EP + 0x0C,0xC0, 0x09,0x37,0x22,0x07, 0xE9, + 0x0C,0xC0, 0x09,0x37,0x22,0x07, 0xEA, + 0x2C,0x82, 0x00,0x0A,0x00,0x0F, 0xE9, + 0x40,0xC1, 0x9C,0x05,0x88,0x00, 0xEA, + 0x2C,0xC0, 0x00,0x0A,0x00,0x0F, 0xEA, + 0x98,0xC0, 0x41,0x3B,0x20,0x1F, 0xE9, + 0x30,0xC0, 0x00,0x0F,0x00,0x00, 0xE9, + 0x98,0xC0, 0x41,0x3B,0x20,0x1F, 0xEA, + 0x40,0xC1, 0x9C,0x05,0x88,0x00, 0xE9, + 0x94,0xC0, 0x55,0x60,0x40,0x47, 0xE9, + 0x30,0xC0, 0x00,0x0F,0x00,0x00, 0xEA, + 0x78,0xC1, 0x80,0x19,0x00,0x00, 0xE9, + 0x94,0xC0, 0x55,0x60,0x40,0x47, 0xEA, + 0x78,0xC1, 0x80,0x19,0x00,0x00, 0xEA, + 0x88,0xC0, 0x3A,0x98,0x80,0x55, 0xE9, + 0x88,0xC0, 0x3A,0x98,0x80,0x55, 0xEA, + 0x8C,0xC0, 0x46,0x20,0x78,0x0C, 0xE9, + 0x8C,0xC0, 0x46,0x20,0x78,0x0C, 0xEA, + 0x90,0xC0, 0x55,0x51,0x3E,0x2B, 0xE9, + 0x90,0xC0, 0x55,0x51,0x3E,0x2B, 0xEA, + 0xCC,0xC1, 0x04,0x43,0x00,0x38, 0xE9, + 0x7C,0xC1, 0x00,0x24,0xA0,0x4E, 0xE9, + 0xCC,0xC1, 0x04,0x43,0x00,0x38, 0xEA, + 0x7C,0xC1, 0x00,0x24,0xC0,0x3E, 0xEA, + 0xC4,0xC1, 0x00,0x02,0x00,0x00, 0xEA, + 0xC4,0xC1, 0x00,0x02,0x00,0x00, 0xE9, + 0x08,0xC0, 0x00,0xA0,0x00,0xB0, 0xE9, + 0x08,0xC0, 0x00,0xA0,0x00,0xB0, 0xEA, + 0x44,0xC1, 0x94,0x03,0x84,0x00, 0xE9, + 0x44,0xC1, 0x94,0x03,0x84,0x00, 0xEA, + 0x0C,0xC0, 0x09,0x17,0x22,0x07, 0xE9, + 0x0C,0xC0, 0x09,0x17,0x22,0x07, 0xEA +}; + +IOBP_MMIO_TABLE_STRUCT PchUsb3HsioLptLp_Bx[] = { + { 0xE90021CC, (UINT32)~(0x00001407), 0x00001407 }, + { 0xE90023CC, (UINT32)~(0x00001407), 0x00001407 }, + { 0xE9002168, (UINT32)~(0x01000F3C), 0x00000A28 }, + { 0xE9002368, (UINT32)~(0x01000F3C), 0x00000A28 }, + { 0xE900216C, (UINT32)~(0x000000FF), 0x0000003F }, + { 0xE900236C, (UINT32)~(0x000000FF), 0x0000003F }, + { 0xE900214C, (UINT32)~(0x00FFFF00), 0x00120500 }, + { 0xE900234C, (UINT32)~(0x00FFFF00), 0x00120500 }, + { 0xE9002164, (UINT32)~(0x0000F000), 0x00005000 }, + { 0xE9002364, (UINT32)~(0x0000F000), 0x00005000 }, + { 0xE9002170, (UINT32)~(0x00000018), 0x00000000 }, + { 0xE9002370, (UINT32)~(0x00000018), 0x00000000 }, + { 0xE9002114, (UINT32)~(0x38000700), 0x00000100 }, + { 0xE9002314, (UINT32)~(0x38000700), 0x00000100 }, + { 0xE9002038, (UINT32)~(0x0000000F), 0x0000000B }, + { 0xE9002238, (UINT32)~(0x0000000F), 0x0000000B }, + { 0xE9002014, (UINT32)~(0x0000FE00), 0x00006600 }, + { 0xE9002214, (UINT32)~(0x0000FE00), 0x00006600 }, + { 0xE9002140, (UINT32)~(0x00800000), 0x00000000 }, + { 0xE9002340, (UINT32)~(0x00800000), 0x00000000 } +}; + +IOBP_MMIO_TABLE_STRUCT PchUsb3SharedHsioLptLp_Bx[] = { + { 0xE90025CC, (UINT32)~(0x00001407), 0x00001407 }, + { 0xE90027CC, (UINT32)~(0x00001407), 0x00001407 }, + { 0xE9002568, (UINT32)~(0x01000F3C), 0x00000A28 }, + { 0xE9002768, (UINT32)~(0x01000F3C), 0x00000A28 }, + { 0xE900242C, (UINT32)~(0x00000700), 0x00000100 }, + { 0xE900262C, (UINT32)~(0x00000700), 0x00000100 }, + { 0xE900256C, (UINT32)~(0x000000FF), 0x0000003F }, + { 0xE900276C, (UINT32)~(0x000000FF), 0x0000003F }, + { 0xE900254C, (UINT32)~(0x00FFFF00), 0x00120500 }, + { 0xE900274C, (UINT32)~(0x00FFFF00), 0x00120500 }, + { 0xE9002564, (UINT32)~(0x0000F000), 0x00005000 }, + { 0xE9002764, (UINT32)~(0x0000F000), 0x00005000 }, + { 0xE9002570, (UINT32)~(0x00000018), 0x00000000 }, + { 0xE9002770, (UINT32)~(0x00000018), 0x00000000 }, + { 0xE9002514, (UINT32)~(0x38000700), 0x00000100 }, + { 0xE9002714, (UINT32)~(0x38000700), 0x00000100 }, + { 0xE9002438, (UINT32)~(0x0000000F), 0x0000000B }, + { 0xE9002638, (UINT32)~(0x0000000F), 0x0000000B }, + { 0xE9002414, (UINT32)~(0x0000FE00), 0x00006600 }, + { 0xE9002614, (UINT32)~(0x0000FE00), 0x00006600 }, + { 0xE9002540, (UINT32)~(0x00800000), 0x00000000 }, + { 0xE9002740, (UINT32)~(0x00800000), 0x00000000 } +}; + +IOBP_MMIO_TABLE_STRUCT PchSataSharedHsioLptLp_Bx[] = { + { 0xEA008008, (UINT32)~(0xFF000000), 0x1C000000 }, + { 0xEA002008, (UINT32)~(0xFFFC6108), 0xEA6C6108 }, + { 0xEA002208, (UINT32)~(0xFFFC6108), 0xEA6C6108 }, + { 0xEA002408, (UINT32)~(0xFFFC6108), 0xEA6C6108 }, + { 0xEA002608, (UINT32)~(0xFFFC6108), 0xEA6C6108 }, + { 0xEA002038, (UINT32)~(0x0000000F), 0x0000000D }, + { 0xEA002238, (UINT32)~(0x0000000F), 0x0000000D }, + { 0xEA002438, (UINT32)~(0x0000000F), 0x0000000D }, + { 0xEA002638, (UINT32)~(0x0000000F), 0x0000000D }, + { 0xEA00202C, (UINT32)~(0x00020F00), 0x00020100 }, + { 0xEA00222C, (UINT32)~(0x00020F00), 0x00020100 }, + { 0xEA00242C, (UINT32)~(0x00020F00), 0x00020100 }, + { 0xEA00262C, (UINT32)~(0x00020F00), 0x00020100 }, + { 0xEA002040, (UINT32)~(0x1F000000), 0x01000000 }, + { 0xEA002240, (UINT32)~(0x1F000000), 0x01000000 }, + { 0xEA002440, (UINT32)~(0x1F000000), 0x01000000 }, + { 0xEA002640, (UINT32)~(0x1F000000), 0x01000000 }, + { 0xEA002010, (UINT32)~(0xFFFF0000), 0x55510000 }, + { 0xEA002210, (UINT32)~(0xFFFF0000), 0x55510000 }, + { 0xEA002410, (UINT32)~(0xFFFF0000), 0x55510000 }, + { 0xEA002610, (UINT32)~(0xFFFF0000), 0x55510000 }, + { 0xEA002140, (UINT32)~(0x00FFFFFF), 0x00140718 }, + { 0xEA002340, (UINT32)~(0x00FFFFFF), 0x00140718 }, + { 0xEA002540, (UINT32)~(0x00FFFFFF), 0x00140718 }, + { 0xEA002740, (UINT32)~(0x00FFFFFF), 0x00140718 }, + { 0xEA002144, (UINT32)~(0x00FFFFFF), 0x00140998 }, + { 0xEA002344, (UINT32)~(0x00FFFFFF), 0x00140998 }, + { 0xEA002544, (UINT32)~(0x00FFFFFF), 0x00140998 }, + { 0xEA002744, (UINT32)~(0x00FFFFFF), 0x00140998 }, + { 0xEA002148, (UINT32)~(0x00FFFFFF), 0x00140998 }, + { 0xEA002348, (UINT32)~(0x00FFFFFF), 0x00140998 }, + { 0xEA002548, (UINT32)~(0x00FFFFFF), 0x00140998 }, + { 0xEA002748, (UINT32)~(0x00FFFFFF), 0x00140998 }, + { 0xEA00217C, (UINT32)~(0x03000000), 0x03000000 }, + { 0xEA00237C, (UINT32)~(0x03000000), 0x03000000 }, + { 0xEA00257C, (UINT32)~(0x03000000), 0x03000000 }, + { 0xEA00277C, (UINT32)~(0x03000000), 0x03000000 }, + { 0xEA00208C, (UINT32)~(0x00FF0000), 0x00800000 }, + { 0xEA00228C, (UINT32)~(0x00FF0000), 0x00800000 }, + { 0xEA00248C, (UINT32)~(0x00FF0000), 0x00800000 }, + { 0xEA00268C, (UINT32)~(0x00FF0000), 0x00800000 }, + { 0xEA0020A4, (UINT32)~(0x0030FF00), 0x00308300 }, + { 0xEA0022A4, (UINT32)~(0x0030FF00), 0x00308300 }, + { 0xEA0024A4, (UINT32)~(0x0030FF00), 0x00308300 }, + { 0xEA0026A4, (UINT32)~(0x0030FF00), 0x00308300 }, + { 0xEA0020AC, (UINT32)~(0x00000030), 0x00000020 }, + { 0xEA0022AC, (UINT32)~(0x00000030), 0x00000020 }, + { 0xEA0024AC, (UINT32)~(0x00000030), 0x00000020 }, + { 0xEA0026AC, (UINT32)~(0x00000030), 0x00000020 }, + { 0xEA002018, (UINT32)~(0xFFFF0300), 0x38250100 }, + { 0xEA002218, (UINT32)~(0xFFFF0300), 0x38250100 }, + { 0xEA002418, (UINT32)~(0xFFFF0300), 0x38250100 }, + { 0xEA002618, (UINT32)~(0xFFFF0300), 0x38250100 }, + { 0xEA002000, (UINT32)~(0xCF030000), 0xCF030000 }, + { 0xEA002200, (UINT32)~(0xCF030000), 0xCF030000 }, + { 0xEA002400, (UINT32)~(0xCF030000), 0xCF030000 }, + { 0xEA002600, (UINT32)~(0xCF030000), 0xCF030000 }, + { 0xEA002028, (UINT32)~(0xFF1F0000), 0x580E0000 }, + { 0xEA002228, (UINT32)~(0xFF1F0000), 0x580E0000 }, + { 0xEA002428, (UINT32)~(0xFF1F0000), 0x580E0000 }, + { 0xEA002628, (UINT32)~(0xFF1F0000), 0x580E0000 }, + { 0xEA00201C, (UINT32)~(0x00007C00), 0x00002400 }, + { 0xEA00221C, (UINT32)~(0x00007C00), 0x00002400 }, + { 0xEA00241C, (UINT32)~(0x00007C00), 0x00002400 }, + { 0xEA00261C, (UINT32)~(0x00007C00), 0x00002400 }, + { 0xEA002178, (UINT32)~(0x00001F00), 0x00001800 }, + { 0xEA002378, (UINT32)~(0x00001F00), 0x00001800 }, + { 0xEA002578, (UINT32)~(0x00001F00), 0x00001800 }, + { 0xEA002778, (UINT32)~(0x00001F00), 0x00001800 }, + { 0xEA00210C, (UINT32)~(0x0038000F), 0x00000005 }, + { 0xEA00230C, (UINT32)~(0x0038000F), 0x00000005 }, + { 0xEA00250C, (UINT32)~(0x0038000F), 0x00000005 }, + { 0xEA00270C, (UINT32)~(0x0038000F), 0x00000005 } +}; + +IOBP_MMIO_TABLE_STRUCT PchGbeSharedHsioLptLp_Bx[] = { + { 0xE9000808, (UINT32)~(0xF0000100), 0xE0000100 }, + { 0xE9000A08, (UINT32)~(0xF0000100), 0xE0000100 }, + { 0xE9000C08, (UINT32)~(0xF0000100), 0xE0000100 }, + { 0xE9000E08, (UINT32)~(0xF0000100), 0xE0000100 }, + { 0xE9001008, (UINT32)~(0xF0000100), 0xE0000100 }, + { 0xE9001208, (UINT32)~(0xF0000100), 0xE0000100 } +}; + +IOBP_MMIO_TABLE_STRUCT PchSataSharedHsioLptLp_MB_Bx[] = { + { 0xEA002090, (UINT32)~(0x0000FFFF), 0x00004C5A }, + { 0xEA002290, (UINT32)~(0x0000FFFF), 0x00004C5A }, + { 0xEA002490, (UINT32)~(0x0000FFFF), 0x00004C5A }, + { 0xEA002690, (UINT32)~(0x0000FFFF), 0x00004C5A } +}; + +IOBP_MMIO_TABLE_STRUCT PchSataSharedHsioLptLp_DT_Bx[] = { + { 0xEA002090, (UINT32)~(0x0000FFFF), 0x00003E67 }, + { 0xEA002290, (UINT32)~(0x0000FFFF), 0x00003E67 }, + { 0xEA002490, (UINT32)~(0x0000FFFF), 0x00003E67 }, + { 0xEA002690, (UINT32)~(0x0000FFFF), 0x00003E67 } +}; + +IOBP_SATA_RXEQ_TABLE PchSataRxEqSharedHsioLptLp_Bx[] = { + { 0x0300, 0xEA002154, (UINT32)~(0x00003F00) }, + { 0x0300, 0xEA002158, (UINT32)~(0x0000003F) }, + { 0x0200, 0xEA002354, (UINT32)~(0x00003F00) }, + { 0x0200, 0xEA002358, (UINT32)~(0x0000003F) }, + { 0x0100, 0xEA002554, (UINT32)~(0x00003F00) }, + { 0x0100, 0xEA002558, (UINT32)~(0x0000003F) }, + { 0x0000, 0xEA002754, (UINT32)~(0x00003F00) }, + { 0x0000, 0xEA002758, (UINT32)~(0x0000003F) }, + { 0x0301, 0xEA002154, (UINT32)~(0x3F00003F) }, + { 0x0201, 0xEA002354, (UINT32)~(0x3F00003F) }, + { 0x0101, 0xEA002554, (UINT32)~(0x3F00003F) }, + { 0x0001, 0xEA002754, (UINT32)~(0x3F00003F) }, + { 0x0302, 0xEA002150, (UINT32)~(0x3F000000) }, + { 0x0302, 0xEA002154, (UINT32)~(0x003F0000) }, + { 0x0202, 0xEA002350, (UINT32)~(0x3F000000) }, + { 0x0202, 0xEA002354, (UINT32)~(0x003F0000) }, + { 0x0102, 0xEA002550, (UINT32)~(0x3F000000) }, + { 0x0102, 0xEA002554, (UINT32)~(0x003F0000) }, + { 0x0002, 0xEA002750, (UINT32)~(0x3F000000) }, + { 0x0002, 0xEA002754, (UINT32)~(0x003F0000) } +}; + +#endif // ULT_FLAG + + diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHsioLptLpBx.h b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHsioLptLpBx.h new file mode 100644 index 0000000..d46962a --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchHsioLptLpBx.h @@ -0,0 +1,42 @@ +/** @file + + Header file with all LPTLPBx Hsio information + +@copyright + Copyright (c) 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement. + +**/ + + +#ifdef ULT_FLAG +#ifndef _PCH_HSIO_LPTLPBX_H_ +#define _PCH_HSIO_LPTLPBX_H_ + +#define PCH_LPTLP_HSIO_VER_BX 0x19 + +extern UINT8 PchChipsetInitTableLptLp_Bx[229]; +extern IOBP_MMIO_TABLE_STRUCT PchUsb3HsioLptLp_Bx[20]; +extern IOBP_MMIO_TABLE_STRUCT PchUsb3SharedHsioLptLp_Bx[22]; +extern IOBP_MMIO_TABLE_STRUCT PchSataSharedHsioLptLp_Bx[73]; +extern IOBP_MMIO_TABLE_STRUCT PchGbeSharedHsioLptLp_Bx[6]; +extern IOBP_MMIO_TABLE_STRUCT PchSataSharedHsioLptLp_MB_Bx[4]; +extern IOBP_MMIO_TABLE_STRUCT PchSataSharedHsioLptLp_DT_Bx[4]; +extern IOBP_SATA_RXEQ_TABLE PchSataRxEqSharedHsioLptLp_Bx[20]; + +#endif //_PCH_HSIO_LPTLPBX_H_ +#endif //ULT_FLAG + diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchInitVar.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchInitVar.c new file mode 100644 index 0000000..5bd895a --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchInitVar.c @@ -0,0 +1,31 @@ +/** @file + This file defines variable shared between PCH Init DXE driver and PCH + Init S3 Resume PEIM. + +@copyright + Copyright (c) 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ + +/// +/// Include the protocol header file +/// +#include "PchInitVar.h" + +/// +/// Protocol GUID definition +/// +EFI_GUID gPchInitPeiVariableGuid = PCH_INIT_PEI_VARIABLE_GUID; diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchInitVar.h b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchInitVar.h new file mode 100644 index 0000000..7bd461b --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchInitVar.h @@ -0,0 +1,65 @@ +/** @file + This file defines variable shared between PCH Init DXE driver and PCH + Init S3 Resume PEIM. + +@copyright + Copyright (c) 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ + +#ifndef _PCH_INIT_VAR_H_ +#define _PCH_INIT_VAR_H_ + +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "EdkIIGlueBase.h" +#endif +/// +/// Define the PCH Init Var GUID +/// +/// +/// EDK and EDKII have different GUID formats +/// +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#define PCH_INIT_PEI_VARIABLE_GUID \ + { \ + 0xa31b27a4, 0xcae6, 0x48ff, 0x8c, 0x5a, 0x29, 0x42, 0x21, 0xe6, 0xf3, 0x89 \ + } +#else +#define PCH_INIT_PEI_VARIABLE_GUID \ + { \ + 0xa31b27a4, 0xcae6, 0x48ff, \ + { \ + 0x8c, 0x5a, 0x29, 0x42, 0x21, 0xe6, 0xf3, 0x89 \ + } \ + } +#endif +/// +/// Extern the GUID for PPI users. +/// +extern EFI_GUID gPchInitPeiVariableGuid; + +#define PCH_INIT_PEI_VARIABLE_NAME L"PchInitPei" + +/// +/// Define the Pch Init Variable structure +/// + +typedef struct _PCH_LATE_INIT_SMM_VARIABLE { + UINT16 IoTrapAddress; + UINT32 PciMemBase; +} PCH_LATE_INIT_SMM_VARIABLE; + +#endif diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchUsbCommon.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchUsbCommon.c new file mode 100644 index 0000000..e53d783 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchUsbCommon.c @@ -0,0 +1,3032 @@ +/** @file + Initializes PCH USB Controllers. + +@copyright + Copyright (c) 2009 - 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#include "PchUsbCommon.h" +#include "Token.h" + +const USB_CONTROLLER EhciControllersMap[PchEhciControllerMax] = { + { + PCI_DEVICE_NUMBER_PCH_USB, + PCI_FUNCTION_NUMBER_PCH_EHCI + }, + { + PCI_DEVICE_NUMBER_PCH_USB_EXT, + PCI_FUNCTION_NUMBER_PCH_EHCI2 + } +}; + +UINTN PCH_H_PORTSCxUSB2[] = { + R_PCH_XHCI_PORTSC01USB2, + R_PCH_XHCI_PORTSC02USB2, + R_PCH_XHCI_PORTSC03USB2, + R_PCH_XHCI_PORTSC04USB2, + R_PCH_XHCI_PORTSC05USB2, + R_PCH_XHCI_PORTSC06USB2, + R_PCH_XHCI_PORTSC07USB2, + R_PCH_XHCI_PORTSC08USB2, + R_PCH_XHCI_PORTSC09USB2, + R_PCH_H_XHCI_PORTSC10USB2, + R_PCH_H_XHCI_PORTSC11USB2, + R_PCH_H_XHCI_PORTSC12USB2, + R_PCH_H_XHCI_PORTSC13USB2, + R_PCH_H_XHCI_PORTSC14USB2, + R_PCH_H_XHCI_PORTSC15USB2 +}; + +UINTN PCH_LP_PORTSCxUSB2[] = { + R_PCH_XHCI_PORTSC01USB2, + R_PCH_XHCI_PORTSC02USB2, + R_PCH_XHCI_PORTSC03USB2, + R_PCH_XHCI_PORTSC04USB2, + R_PCH_XHCI_PORTSC05USB2, + R_PCH_XHCI_PORTSC06USB2, + R_PCH_XHCI_PORTSC07USB2, + R_PCH_XHCI_PORTSC08USB2, + R_PCH_XHCI_PORTSC09USB2 +}; + +UINTN PCH_H_PORTSCxUSB3[] = { + R_PCH_H_XHCI_PORTSC1USB3, + R_PCH_H_XHCI_PORTSC2USB3, + R_PCH_H_XHCI_PORTSC3USB3, + R_PCH_H_XHCI_PORTSC4USB3, + R_PCH_H_XHCI_PORTSC5USB3, + R_PCH_H_XHCI_PORTSC6USB3 +}; + +UINTN PCH_LP_PORTSCxUSB3[] = { + R_PCH_LP_XHCI_PORTSC1USB3, + R_PCH_LP_XHCI_PORTSC2USB3, + R_PCH_LP_XHCI_PORTSC3USB3, + R_PCH_LP_XHCI_PORTSC4USB3 +}; + +/// +/// Table: USB2 Pins Mapping between XHCI/EHCI Port +/// ------------------------------------------- +/// | USB2 Pin | EHCI Port | XHCI Port | +/// |--------------+----------------+-----------| +/// | USB[P,N][0] | EHCI 1 Port 0 | Port 0 | +/// | USB[P,N][1] | EHCI 1 Port 1 | Port 1 | +/// | USB[P,N][2] | EHCI 1 Port 2 | Port 2 | +/// | USB[P,N][3] | EHCI 1 Port 3 | Port 3 | +/// | USB[P,N][4] | EHCI 1 Port 4 | Port 8 | +/// | USB[P,N][5] | EHCI 1 Port 5 | Port 9 | +/// | USB[P,N][6] | EHCI 1 Port 6 | Port 12 | +/// | USB[P,N][7] | EHCI 1 Port 7 | Port 13 | +/// | USB[P,N][8] | EHCI 2 Port 8 | Port 4 | +/// | USB[P,N][9] | EHCI 2 Port 9 | Port 5 | +/// | USB[P,N][10] | EHCI 2 Port 10 | Port 6 | +/// | USB[P,N][11] | EHCI 2 Port 11 | Port 7 | +/// | USB[P,N][12] | EHCI 2 Port 12 | Port 10 | +/// | USB[P,N][13] | EHCI 2 Port 13 | Port 11 | +/// ------------------------------------------- +/// +const UINT32 XhciUsb2InternalPortNumberLookUpTable[] = { + 0,1,2,3,8,9,12,13,4,5,6,7,10,11,12,13 +}; + +/** + Configures PCH USB controller + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] EhciMmioBase Memory base address of EHCI Controller + @param[in] XhciMmioBase Memory base address of XHCI Controller + @param[in] BusNumber PCI Bus Number of the PCH device + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[out] FuncDisableReg Function Disable Register + @param[in] Revision The policy revision used for backward compatible check + + @retval EFI_INVALID_PARAMETER The parameter of PchPlatformPolicy is invalid + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +EFIAPI +CommonUsbInit ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINT32 EhciMmioBase, + IN UINT32 XhciMmioBase, + IN UINT8 BusNumber, + IN UINT32 RootComplexBar, + OUT UINT32 *FuncDisableReg, + IN UINT8 Revision + ) +{ + UINTN PciD31F0RegBase; + UINTN XhciPciMmBase; + UINTN Ehci1PciMmBase; + UINTN Ehci2PciMmBase; + UINT16 LpcDeviceId; + UINT16 PmBase; + UINT16 RegData16 =0; + PCH_SERIES PchSeries; + + DEBUG ((EFI_D_INFO, "CommonUsbInit() - Start\n")); + + PchSeries = GetPchSeries(); + PciD31F0RegBase = MmPciAddress ( + 0, + BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); + XhciPciMmBase = MmPciAddress ( + 0, + BusNumber, + PCI_DEVICE_NUMBER_PCH_XHCI, + PCI_FUNCTION_NUMBER_PCH_XHCI, + 0 + ); + Ehci1PciMmBase = MmPciAddress ( + 0, + BusNumber, + EhciControllersMap[PchEhci1].Device, + EhciControllersMap[PchEhci1].Function, + 0 + ); + Ehci2PciMmBase = 0; + if (PchSeries == PchH) { + Ehci2PciMmBase = MmPciAddress ( + 0, + BusNumber, + EhciControllersMap[PchEhci2].Device, + EhciControllersMap[PchEhci2].Function, + 0 + ); + } + + PmBase = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_ACPI_BASE) & B_PCH_LPC_ACPI_BASE_BAR; + LpcDeviceId = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_DEVICE_ID); + /// + /// Check to disable USB Controllers + /// + if (UsbConfig->Usb20Settings[PchEhci1].Enable == PCH_DEVICE_DISABLE) { + *FuncDisableReg |= B_PCH_RCRB_FUNC_DIS_EHCI1; + } + + if (PchSeries == PchH) { + if (UsbConfig->Usb20Settings[PchEhci2].Enable == PCH_DEVICE_DISABLE) { + *FuncDisableReg |= B_PCH_RCRB_FUNC_DIS_EHCI2; + } + } + + if (UsbConfig->Usb30Settings.Mode == PCH_XHCI_MODE_OFF) { + /// + /// PCH BIOS Spec Rev 0.5.0, section 13.2.3 Hiding/Disabling xHCI Controller + /// In some instances, the System BIOS may choose to "hide" the xHCI controller. When + /// the xHCI device is hidden, all high speed shareable ports should be routed to the EHCI + /// controller to avoid the situation where USB ports are not functioning. To hide a host + /// controller, the BIOS must program the Function Disable register (RCBA + 3418h). See + /// the PCH EDS for a description of the register. + /// + *FuncDisableReg |= B_PCH_RCRB_FUNC_DIS_XHCI; + } + + /// + /// Init USB Host Controllers + /// + CommonEhciHcsInit ( + UsbConfig, + EhciMmioBase, + BusNumber, + Revision, + LpcDeviceId, + RootComplexBar + ); + + /// + /// Assign memory resources + /// + XhciMemorySpaceOpen ( + UsbConfig, + XhciMmioBase, + XhciPciMmBase + ); + + CommonXhciHcInit ( + UsbConfig, + XhciMmioBase, + Revision, + LpcDeviceId, + XhciPciMmBase + ); + + /// + /// Init Port Switching Flow + /// + PerformXhciEhciPortSwitchingFlow ( + UsbConfig, + XhciMmioBase, + Revision, + LpcDeviceId, + XhciPciMmBase, + PciD31F0RegBase + ); + /// + /// Setup USB Over-Current Mapping. + /// + EhciOverCurrentMapping ( + UsbConfig, + Ehci1PciMmBase, + Ehci2PciMmBase + ); + + XhciOverCurrentMapping ( + UsbConfig, + XhciPciMmBase + ); + + // + // Tune the USB 2.0 high-speed signals quality. + // + Usb2PortLengthProgramming ( + UsbConfig, + LpcDeviceId, + RootComplexBar + ); + + /// + /// Support USB Per-Port Disable Control Override feature + /// +#if defined OEM_USB_PER_PORT_DISABLE_SUPPORT && OEM_USB_PER_PORT_DISABLE_SUPPORT == 0 + if (UsbConfig->UsbPerPortCtl == PCH_DEVICE_ENABLE) { + /// + /// PCH BIOS Spec Rev 0.5.0 Section 12.2 Disabling USB Ports + /// The PCH USB Port Disable Override Register (D26/29:F0 + 64h) can be locked by setting + /// the Write Enable bit of the PCH USB Per-Port Register Write Control Register, + /// PMBASE + 3Ch[1]. + /// + /// Open the Per-Port Disable Control Override + /// + RegData16 = IoRead16 ((UINTN) ((UINT64) (PmBase + R_PCH_UPRWC))); + RegData16 |= B_PCH_UPRWC_WR_EN; + IoWrite16 ((UINTN) ((UINT64) (PmBase + R_PCH_UPRWC)), RegData16); +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, all resume well registers need to be saved + /// into S3 Script table. + /// + PCH_INIT_COMMON_SCRIPT_IO_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PmBase + R_PCH_UPRWC), + 1, + &RegData16 + ); +#endif + + EhciPortDisableOverride ( + UsbConfig, + Ehci1PciMmBase, + Ehci2PciMmBase + ); + + XhciPortDisableOverride ( + UsbConfig, + XhciPciMmBase, + Revision + ); + + /// + /// Close the Per-Port Disable Control Override + /// + RegData16 &= (~B_PCH_UPRWC_WR_EN); + IoWrite16 ((UINTN) ((UINT64) (PmBase + R_PCH_UPRWC)), RegData16); +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, all resume well registers need to be saved + /// into S3 Script table. + /// + PCH_INIT_COMMON_SCRIPT_IO_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PmBase + R_PCH_UPRWC), + 1, + &RegData16 + ); +#endif + } +#endif + /// + /// Support USBR feature + /// + if (UsbConfig->Ehci1Usbr == PCH_DEVICE_ENABLE && + UsbConfig->Usb20Settings[PchEhci1].Enable == PCH_DEVICE_ENABLE) { + EhciUsbrEnable (Ehci1PciMmBase); + } + if (PchSeries == PchH) { + if (UsbConfig->Ehci2Usbr == PCH_DEVICE_ENABLE && UsbConfig->Usb20Settings[PchEhci2].Enable == PCH_DEVICE_ENABLE) { + EhciUsbrEnable (Ehci2PciMmBase); + } + } + /// + /// Clear memory resources + /// + XhciMemorySpaceClose ( + UsbConfig, + XhciMmioBase, + XhciPciMmBase + ); + + DEBUG ((EFI_D_INFO, "CommonUsbInit() - End\n")); + + return EFI_SUCCESS; +} + +/** + Performs basic configuration of PCH EHCI controller. + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] EhciMmioBase Memory base address of EHCI Controller + @param[in] BusNumber PCI Bus Number of the PCH device + @param[in] Revision The policy revision used for backward compatible check + @param[in] LpcDeviceId The device ID of LPC + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +EFIAPI +CommonEhciHcsInit ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINT32 EhciMmioBase, + IN UINT8 BusNumber, + IN UINT8 Revision, + IN UINT16 LpcDeviceId, + IN UINT32 RootComplexBar + ) +{ + UINTN EhciPciMmBase; + UINT8 Index; + UINT16 PciCmd; + BOOLEAN SkipRst; + UINT32 DwordReg; + UINT8 NumberOfPorts; + EFI_STATUS Status; + UINT32 Data32And; + UINT32 Data32Or; + PCH_SERIES PchSeries; +#ifndef AMI_OVERRIDE_EHCI_MMIOBASE + UINT32 TempMmioBase = EhciMmioBase; +#endif + + PchSeries = GetPchSeries(); + + for (Index = 0; Index < GetPchEhciMaxControllerNum (); Index++) { + EhciPciMmBase = MmPciAddress ( + 0, + BusNumber, + EhciControllersMap[Index].Device, + EhciControllersMap[Index].Function, + 0 + ); + +#ifndef AMI_OVERRIDE_EHCI_MMIOBASE + if (EhciMmioBase != TempMmioBase) + EhciMmioBase = TempMmioBase; +#endif + /// + /// Set EHCI structural parameter + /// + if (UsbConfig->Usb20Settings[Index].Enable == PCH_DEVICE_DISABLE) { + MmioWrite32 (EhciPciMmBase + R_PCH_EHCI_MEM_BASE, 0); + MmioWrite16 (EhciPciMmBase + R_PCH_EHCI_COMMAND_REGISTER, 0); + } else { + PciCmd = 0; + /// + /// Shared EHCI/XHCI ports w/a. + /// This step is required when some of the ports are routed to EHCI + /// and other ports are routed XHCI at the same time. + /// + /// Clear D26/D29:F0 + 78h [1:0] + /// + if (UsbConfig->Usb30Settings.ManualMode == PCH_DEVICE_ENABLE) { + MmioAnd16 ( + (EhciPciMmBase + 0x78), + (UINT16) ~(BIT1 | BIT0)); +#ifdef SUS_WELL_RESTORE + /// + /// To support DeepSx and RapidStart resume from G3 state, all resume well registers + /// need to be saved into S3 Script table. + /// + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (EhciPciMmBase + 0x78), + 1, + (VOID *) (UINTN) (EhciPciMmBase + 0x78) + ); +#endif + } + /// + /// For some cases, like usb debug mode, the Ehci memory resource will have been assigned and + /// enabled here. If so, then set SkipRst flag to skip the steps that are for Ehci memory + /// resource clear and host controller reset + /// + if ((MmioRead32 (EhciPciMmBase + R_PCH_EHCI_MEM_BASE) == 0) && + !(MmioRead16 (EhciPciMmBase + R_PCH_EHCI_COMMAND_REGISTER) & B_PCH_EHCI_COMMAND_MSE)) { + MmioWrite32 ((EhciPciMmBase + R_PCH_EHCI_MEM_BASE), EhciMmioBase); +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, all resume well registers need to be saved + /// into S3 Script table. + /// + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (EhciPciMmBase + R_PCH_EHCI_MEM_BASE), + 1, + (VOID *) (UINTN) (EhciPciMmBase + R_PCH_EHCI_MEM_BASE) + ); +#endif + /// + /// Clear SkipRst flag + /// + SkipRst = FALSE; + } else { + /// + /// Use the memory address of Ehci controller that has been assigned before initialization + /// to do the programming. + /// + EhciMmioBase = MmioRead32 (EhciPciMmBase + R_PCH_EHCI_MEM_BASE); + /// + /// Save Pci command register + /// + PciCmd = MmioRead16 (EhciPciMmBase + R_PCH_EHCI_COMMAND_REGISTER); + /// + /// Set SkipRst flag + /// + SkipRst = TRUE; + } + + MmioOr16 ( + (EhciPciMmBase + R_PCH_EHCI_COMMAND_REGISTER), + (UINT16) (B_PCH_EHCI_COMMAND_MSE | B_PCH_EHCI_COMMAND_BME) + ); +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, all resume well registers need to be saved + /// into S3 Script table. + /// + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (EhciPciMmBase + R_PCH_EHCI_COMMAND_REGISTER), + 1, + (VOID *) (UINTN) (EhciPciMmBase + R_PCH_EHCI_COMMAND_REGISTER) + ); +#endif + /// + /// PCH BIOS Spec Rev 0.5.0 Section 12.10 + /// Additional Programming Requirements during USB Initialization + /// + /// Step 1 + /// Program D29/D26:MEM_BASE + 20h [1] = 1b, + /// This should be done before FS/LS initialitiation and also after S4/S5 + /// + /// For some cases, like usb debug mode, we will skip this step, in case something will be destroyed + /// after doing host controller reset + /// + if (!SkipRst) { +#ifdef USB_PRECONDITION_ENABLE_FLAG + /// + /// Reset the EHCI when running in PEI phase where USB precondition feature is enabled + /// or in DXE phase where USB precondition feature is disabled + /// If the precondition is enabled and running in DXE phase, EHCI has reset done already + /// + if (USB_RUN_IN_PEI || (!USB_PRECONDITION_POLICY_SUPPORT (UsbConfig))) { +#endif // USB_PRECONDITION_ENABLE_FLAG + MmioOr16 ((EhciMmioBase + R_PCH_EHCI_USB2CMD), B_PCH_EHCI_USB2CMD_HCRESET); +#ifdef USB_PRECONDITION_ENABLE_FLAG + } +#endif // USB_PRECONDITION_ENABLE_FLAG + } + /// + /// Step 2 + /// Configure number of controller and port: + /// + /// Step 2.a + /// Set D26/D29:F0:80h [0] = 1b + /// + MmioOr16 ((EhciPciMmBase + R_PCH_EHCI_ACCESS_CNTL), (UINT16) V_PCH_EHCI_ACCESS_CNTL_ENABLE); +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, all resume well registers need to be saved + /// into S3 Script table. + /// + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (EhciPciMmBase + R_PCH_EHCI_ACCESS_CNTL), + 1, + (VOID *) (UINTN) (EhciPciMmBase + R_PCH_EHCI_ACCESS_CNTL) + ); +#endif + /// + /// Step 2.b + /// Set both EHCI's N_CC bit, D26 & D29 MEM_BASE + offset 04h [15:12], to 0000b + /// + MmioBitFieldWrite32 ( + (EhciMmioBase + R_PCH_EHCI_HCSPARAMS), + N_PCH_EHCI_HCSPARAMS_N_CC, + (N_PCH_EHCI_HCSPARAMS_N_CC + 3), + 0 + ); +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, all resume well registers need to be saved + /// into S3 Script table. + /// + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (EhciMmioBase + R_PCH_EHCI_HCSPARAMS), + 1, + (VOID *) (UINTN) (EhciMmioBase + R_PCH_EHCI_HCSPARAMS) + ); +#endif + /// + /// Step 2.c + /// Set both EHCI's N_PORTS bit, D26 & D29 MEM_BASE + offset 04h [3:0], to 2h + /// + NumberOfPorts = 2; + if (Index == PchEhci1) { + if (UsbConfig->Ehci1Usbr == PCH_DEVICE_ENABLE) { + NumberOfPorts = NumberOfPorts + 1; + } + } else { + if (PchSeries == PchH) { + if (Index == PchEhci2) { + if (UsbConfig->Ehci2Usbr == PCH_DEVICE_ENABLE) { + NumberOfPorts = NumberOfPorts + 1; + } + } + } + } + MmioBitFieldWrite32 ( + (EhciMmioBase + R_PCH_EHCI_HCSPARAMS), + N_PCH_EHCI_HCSPARAMS_N_PORTS, + (N_PCH_EHCI_HCSPARAMS_N_PORTS + 3), + NumberOfPorts + ); +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, all resume well registers need to be saved + /// into S3 Script table. + /// + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (EhciMmioBase + R_PCH_EHCI_HCSPARAMS), + 1, + (VOID *) (UINTN) (EhciMmioBase + R_PCH_EHCI_HCSPARAMS) + ); +#endif + /// + /// Step 2.d + /// Clear D26/D29:F0:80h [0] to 0b + /// + MmioAnd16 ((EhciPciMmBase + R_PCH_EHCI_ACCESS_CNTL), (UINT16) (~V_PCH_EHCI_ACCESS_CNTL_ENABLE)); +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, all resume well registers need to be saved + /// into S3 Script table. + /// + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (EhciPciMmBase + R_PCH_EHCI_ACCESS_CNTL), + 1, + (VOID *) (UINTN) (EhciPciMmBase + R_PCH_EHCI_ACCESS_CNTL) + ); +#endif + /// + /// Step 3 + /// Program D29/D26:F0 + 78h[2] = 1b. + /// + DwordReg = MmioRead32 (EhciPciMmBase + 0x78); + DwordReg |= (UINT32) (BIT2); + MmioWrite32 ( + (UINTN) (EhciPciMmBase + 0x78), + DwordReg + ); +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, all resume well registers need to be saved + /// into S3 Script table. + /// + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (EhciPciMmBase + 0x78), + 1, + (VOID *) (UINTN) (EhciPciMmBase + 0x78) + ); +#endif + /// + /// Step 4 + /// Program D29/D26:F0 + 7Ch[14,7] = 1b + /// + MmioOr32 (EhciPciMmBase + 0x7C, (UINT32) BIT14 | BIT7); +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, all resume well registers need to be saved + /// into S3 Script table. + /// + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (EhciPciMmBase + 0x7C), + 1, + (VOID *) (UINTN) (EhciPciMmBase + 0x7C) + ); +#endif + /// + /// Step 5 + /// Program D29/D26:F0 + 8Ch[11:8] = 0100b + /// Step 6 + /// Program D29/D26:F0 + 8Ch[26,17] = 0b, 1b + /// + DwordReg = MmioRead32 (EhciPciMmBase + 0x8C); + DwordReg |= (UINT32) (BIT17 | BIT10); + DwordReg &= (UINT32)~(BIT26 | BIT11 | BIT9 | BIT8); + MmioWrite32 ( + (UINTN) (EhciPciMmBase + 0x8C), + DwordReg + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (EhciPciMmBase + 0x8C), + 1, + (VOID *) (UINTN) (EhciPciMmBase + 0x8C) + ); + + if (SkipRst) { + /// + /// Restore Pci command register + /// + MmioWrite16 ((EhciPciMmBase + R_PCH_EHCI_COMMAND_REGISTER), PciCmd); +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, all resume well registers need to be saved + /// into S3 Script table. + /// + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (EhciPciMmBase + R_PCH_EHCI_COMMAND_REGISTER), + 1, + (VOID *) (UINTN) (EhciPciMmBase + R_PCH_EHCI_COMMAND_REGISTER) + ); +#endif + } else { +#ifdef USB_PRECONDITION_ENABLE_FLAG + /// + /// If precondition is enabled, execute USB precondition function by each phase call + /// + if (USB_PRECONDITION_POLICY_SUPPORT (UsbConfig)) { + EHCI_PRECONDITION (EhciControllersMap[Index].Device, EhciMmioBase); + } +#endif // USB_PRECONDITION_ENABLE_FLAG + /// + /// Clear memory resource and command register after initialization + /// + MmioAnd16 ( + (EhciPciMmBase + R_PCH_EHCI_COMMAND_REGISTER), + (UINT16)~(B_PCH_EHCI_COMMAND_MSE | B_PCH_EHCI_COMMAND_BME) + ); + MmioWrite32 ((EhciPciMmBase + R_PCH_EHCI_MEM_BASE), 0); +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, all resume well registers need to be saved + /// into S3 Script table. + /// + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (EhciPciMmBase + R_PCH_EHCI_COMMAND_REGISTER), + 1, + (VOID *) (UINTN) (EhciPciMmBase + R_PCH_EHCI_COMMAND_REGISTER) + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (EhciPciMmBase + R_PCH_EHCI_MEM_BASE), + 1, + (VOID *) (UINTN) (EhciPciMmBase + R_PCH_EHCI_MEM_BASE) + ); +#endif + } + } + } +#ifdef USB_PRECONDITION_ENABLE_FLAG + /// + /// Execute the code if running in PEI phase when USB precondition feature is enabled + /// or in DXE phase when USB precondition feature disabled + /// If the precondition is enabled and running in DXE phase, + /// the code has already run once in PEI but the save S3 script need to run again in DXE phase + /// but only run if and only if both EHCI is not disabled + /// + if ((USB_RUN_IN_PEI || (!USB_PRECONDITION_POLICY_SUPPORT (UsbConfig))) || + ((USB_RUN_IN_DXE) && ((UsbConfig->Usb20Settings[PchEhci1].Enable == PCH_DEVICE_ENABLE) || + ((UsbConfig->Usb20Settings[PchEhci2].Enable == PCH_DEVICE_ENABLE) && (PchSeries == PchH))))) + { +#endif // USB_PRECONDITION_ENABLE_FLAG + /// + /// PCH BIOS Spec Rev 0.5.5 Section 12.10 + /// Additional Programming Requirements during USB Initialization + /// Step 7 + /// IOBP Programming: + /// a) Set IOBP register 0xE5007F04 to 00004481h. + /// b) Set IOBP register 0xE500400F[0] + (PortNumber * 0x100) = 0b. + /// c) Set IOBP register 0xE5007F14[20:19] to 11b. + /// d) Set IOBP register 0xE5007F02[23:22] to 00b for LPT-LP + /// + /// Set IOBP register 0xE5007F04[14:13] to 10b. + /// + Data32And = 0; + Data32Or = 0x00004481; + Status = ProgramIobp ( + RootComplexBar, + 0xE5007F04, + Data32And, + Data32Or + ); + ASSERT_EFI_ERROR (Status); + Status = PCH_INIT_COMMON_SCRIPT_SAVE_IOBP_S3_ITEM ( + RootComplexBar, + 0xE5007F04, + Data32And, + Data32Or + ); + ASSERT_EFI_ERROR (Status); + for (Index = 0; Index < GetPchUsbMaxPhysicalPortNum (); Index++) { + /// + /// Set IOBP register 0xE500400F[0] + (PortNumber * 0x100) = 0b. + /// + Data32And = (UINT32)~(BIT0); + Data32Or = (UINT32) (0); + Status = ProgramIobp ( + RootComplexBar, + 0xE500400F + ((Index + 1) * 0x100), + Data32And, + Data32Or + ); + ASSERT_EFI_ERROR (Status); + Status = PCH_INIT_COMMON_SCRIPT_SAVE_IOBP_S3_ITEM ( + RootComplexBar, + 0xE500400F + ((Index + 1) * 0x100), + Data32And, + Data32Or + ); + ASSERT_EFI_ERROR (Status); + } + /// + /// Set IOBP register 0xE5007F14[20:19] to 11b. + /// + Data32And = (UINT32)~(0); + Data32Or = (UINT32) (BIT20 | BIT19); + Status = ProgramIobp ( + RootComplexBar, + 0xE5007F14, + Data32And, + Data32Or + ); + ASSERT_EFI_ERROR (Status); + Status = PCH_INIT_COMMON_SCRIPT_SAVE_IOBP_S3_ITEM ( + RootComplexBar, + 0xE5007F14, + Data32And, + Data32Or + ); + ASSERT_EFI_ERROR (Status); + /// + /// Set IOBP register 0xE5007F02[23:22] to 00b for LPT-LP + /// + if (PchSeries == PchLp) { + Data32And = (UINT32)~(BIT23 | BIT22); + Data32Or = (UINT32) (0); + Status = ProgramIobp ( + RootComplexBar, + 0xE5007F02, + Data32And, + Data32Or + ); + ASSERT_EFI_ERROR (Status); + Status = PCH_INIT_COMMON_SCRIPT_SAVE_IOBP_S3_ITEM ( + RootComplexBar, + 0xE5007F02, + Data32And, + Data32Or + ); + ASSERT_EFI_ERROR (Status); + } + +#ifdef USB_PRECONDITION_ENABLE_FLAG + } +#endif // USB_PRECONDITION_ENABLE_FLAG + return EFI_SUCCESS; +} + +/** + Performs basic configuration of PCH USB3 (xHCI) controller. + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] XhciMmioBase Memory base address of xHCI Controller + @param[in] Revision The policy revision used for backward compatible check + @param[in] LpcDeviceId The device ID of LPC + @param[in] XhciPciMmBase XHCI PCI Base Address + + @retval None +**/ +VOID +CommonXhciHcInit ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINT32 XhciMmioBase, + IN UINT8 Revision, + IN UINT16 LpcDeviceId, + IN UINTN XhciPciMmBase + ) +{ + UINT32 Data32Or; + UINT32 Data32And; + UINT8 PchSteppingValue; + PCH_SERIES PchSeries; + + Data32Or = 0; + Data32And = 0; + PchSeries = GetPchSeries(); + PchSteppingValue = PchStepping(); + /// + /// Check if XHCI disabled, Exit function. + /// + if (UsbConfig->Usb30Settings.Mode == PCH_XHCI_MODE_OFF) { + return; + } + /// + /// PCH BIOS Spec Rev 0.5.5, Section 13.2.1 xHCI controller setup + /// + if (PchSeries == PchH) { + /// + /// For LPT-H Only: + /// USB3 ports always start at offset 16 (accounting for 15 USB2 ports) regardless of the number of USB2 ports + /// the XHCI spec allows there to be a gap between the highest numbered USB2 port and the lowest numbered USB3 port). + /// So the Maxports value is dependent entirely on the number of USB3 ports, and not upon the number of USB2 ports. + /// So the appropriate BIOS workaround is to look at the number of USB3 ports in the FUS register - config offset E0h. + /// (since there are SKUs with fewer than 6 port). + /// * If number of SS ports = 6, maxports = 21 (15h) + /// * If number of SS ports = 4, maxports = 19 (13h) + /// * If number of SS ports = 2, maxports = 17 (11h) + /// * If number of SS ports = 0, maxports = 15 (0Fh) + /// + switch (MmioRead32 (XhciPciMmBase + R_PCH_XHCI_FUS) & B_PCH_XHCI_FUS_SSPRTCNT) { + case V_PCH_XHCI_FUS_SSPRTCNT_11B: + // Number of SS ports is 0, Set xHCIBAR + 04h[31:24] = 0Fh + Data32Or = 0x0F000000; + break; + + case V_PCH_XHCI_FUS_SSPRTCNT_10B: + // Number of SS ports is 2, Set xHCIBAR + 04h[31:24] = 11h + Data32Or = 0x11000000; + break; + + case V_PCH_XHCI_FUS_SSPRTCNT_01B: + // Number of SS ports is 4, Set xHCIBAR + 04h[31:24] = 13h + Data32Or = 0x13000000; + break; + + case V_PCH_XHCI_FUS_SSPRTCNT_00B: + default: + // Number of SS ports is 6, Set xHCIBAR + 04h[31:24] = 15h + Data32Or = 0x15000000; + break; + } + MmioAndThenOr32 ( + (XhciMmioBase + R_PCH_XHCI_HCSPARAMS1), + (UINT32) 0x00FFFFFF, + (UINT32) Data32Or + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + R_PCH_XHCI_HCSPARAMS1), + 1, + (VOID *) (UINTN) (XhciMmioBase + R_PCH_XHCI_HCSPARAMS1) + ); + } + /// + /// Set xHCIBAR + 0Ch[7:0] = 0Ah and [31:16] = 200h + /// + MmioAndThenOr32 ( + (XhciMmioBase + R_PCH_XHCI_HCSPARAMS3), + (UINT32) 0x0000FF00, + (UINT32) 0x0200000A + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + R_PCH_XHCI_HCSPARAMS3), + 1, + (VOID *) (UINTN) (XhciMmioBase + R_PCH_XHCI_HCSPARAMS3) + ); + /// + /// Set xHCIBAR + 10h[10,9,5] to 1b, 1b, 0b + /// + MmioAndThenOr32 ( + (XhciMmioBase + R_PCH_XHCI_HCCPARAMS), + (UINT32)~(BIT5), + (UINT32) (BIT10 | BIT9) + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + R_PCH_XHCI_HCCPARAMS), + 1, + (VOID *) (UINTN) (XhciMmioBase + R_PCH_XHCI_HCCPARAMS) + ); + if (PchSeries == PchH) { + /// + /// For LPT-H, Set xHCIBAR + 8008h[19] to 0b + /// + MmioAnd32 ( + (XhciMmioBase + 0x8008), + (UINT32)~(BIT19) + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x8008), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x8008) + ); + } + + if (PchSeries == PchLp) { + /// + /// Set xHCIBAR + 8058h[16,8] to 1b, 0b + /// + MmioAndThenOr32 ( + (XhciMmioBase + 0x8058), + (UINT32)~(BIT8), + (UINT32) (BIT16) + ); + } else if (PchSeries == PchH) { + /// + /// Set xHCIBAR + 8058h[20,16,8] to 1b, 1b, 0b + /// + MmioAndThenOr32 ( + (XhciMmioBase + 0x8058), + (UINT32)~(BIT8), + (UINT32) (BIT20 | BIT16) + ); + } + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x8058), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x8058) + ); + /// + /// Set xHCIBAR + 8060h[25, 18] to 1b, 1b + /// + MmioOr32 ( + (XhciMmioBase + 0x8060), + (UINT32) (BIT25 | BIT18) + ); + + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x8060), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x8060) + ); + /// + /// Set xHCIBAR + 8090h[14,8] to 1b, 1b + /// + MmioOr32 (XhciMmioBase + 0x8090, (UINT32) (BIT14 | BIT8)); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x8090), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x8090) + ); + /// + /// Set xHCIBAR + 8094h[23, 21, 14] to 1b, 1b, 1b + /// + MmioOr32 (XhciMmioBase + 0x8094, (UINT32) (BIT23 | BIT21 | BIT14)); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x8094), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x8094) + ); + /// + /// Set xHCIBAR + 80E0h[16, 6] to 0b, 1b + /// + MmioAndThenOr32 ( + (XhciMmioBase + 0x80E0), + (UINT32)~(BIT16), + (UINT32) (BIT6) + ); +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, all resume well registers need to be saved + /// into S3 Script table. + /// + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x80E0), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x80E0) + ); +#endif // SUS_WELL_RESTORE + /// + /// Set xHCIBAR + 80ECh[14:12] to 00h + /// Set xHCIBAR + 80ECh[11:9] to 06h + /// + MmioAndThenOr32 ( + (XhciMmioBase + 0x80EC), + (UINT32)~(BIT14 | BIT13 | BIT12 | BIT9), + (UINT32) (BIT11 | BIT10) + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x80EC), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x80EC) + ); + /// + /// Set xHCIBAR + 80F0h[20] to 0b + /// + MmioAnd32 ( + (XhciMmioBase + 0x80F0), + (UINT32)~(BIT20) + ); +#ifdef SUS_WELL_RESTORE + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x80F0), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x80F0) + ); +#endif // SUS_WELL_RESTORE + /// + /// For LPT-LP, Set xHCIBAR + 80FCh[25] to 1b (Note: In document it is written as bit 121 of 80F0h.) + /// + if (PchSeries == PchLp) { + MmioOr32 (XhciMmioBase + 0x80FC, (UINT32) (BIT25)); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x80FC), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x80FC) + ); + } + if (PchSeries == PchLp) { + /// + /// Set xHCIBAR + 8110h[20,11, 8, 2] to 1b, 1b, 0b, 0b + /// + MmioAndThenOr32 ( + (XhciMmioBase + 0x8110), + (UINT32)~(BIT2 | BIT8), + (UINT32) (BIT20 | BIT11) + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x8110), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x8110) + ); + } else if (PchSeries == PchH) { + /// + /// Set xHCIBAR + 8110h[20,11,2] to 1b, 1b, 0b + /// + MmioAndThenOr32 ( + (XhciMmioBase + 0x8110), + (UINT32)~(BIT2), + (UINT32) (BIT20 | BIT11) + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x8110), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x8110) + ); + } + /// + /// For LPT-H , Set xHCIBAR + 8140h[31:0] to FF03C132h + /// For LPT-LP, Set xHCIBAR + 8140h[31:0] to FF00F03Ch + /// + if (PchSeries == PchH) { + Data32And = (UINT32)~(0xFFFFFFFF); + Data32Or = (UINT32) (0xFF03C132); + MmioAndThenOr32 ( + (XhciMmioBase + 0x8140), + Data32And, + Data32Or + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x8140), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x8140) + ); + } + if (PchSeries == PchLp) { + Data32And = (UINT32)~(0xFFFFFFFF); + Data32Or = (UINT32) (0xFF00F03C); + MmioAndThenOr32 ( + (XhciMmioBase + 0x8140), + Data32And, + Data32Or + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x8140), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x8140) + ); + } + + /// + /// For LPT-LP Set xHCIBAR + 8154h[21, 13] to 0b, 1b + /// For LPT-H Set xHCIBAR + 8154h[21, 13] to 0b, 0b + /// + if (PchSeries == PchH) { + Data32And = BIT21 | BIT13; + Data32Or = 0; + } else if (PchSeries == PchLp) { + Data32And = BIT21; + Data32Or = BIT13; + } + MmioAndThenOr32 ( + (XhciMmioBase + 0x8154), + (UINT32)~(Data32And), + (UINT32) (Data32Or) + ); + /// + /// Clear xHCIBAR + 8154h[3] to 0b + /// + MmioAnd32 ( + (XhciMmioBase + 0x8154), + (UINT32)~(BIT3) + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x8154), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x8154) + ); + + /// + /// For LPT-LP, Set xHCIBAR + 8164h[0,1] to 1b + /// + if (PchSeries == PchLp) { + MmioOr32 (XhciMmioBase + 0x8164, (UINT32) (BIT1 | BIT0)); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x8164), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x8164) + ); + } + + /// + /// For LPT-LP, Set xHCIBAR + 8174h = 0x01400C0A + /// + if (PchSeries == PchLp) { + MmioWrite32 (XhciMmioBase + 0x8174, 0x01400c0a); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x8174), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x8174) + ); + } + /// + /// For LPT-LP, Set xHCIBAR + 817Ch[31:0] to 033200A3h + /// + if (PchSeries == PchLp) { + Data32And = (UINT32)~(0xFFFFFFFF); + Data32Or = (UINT32) (0x033200A3); + MmioAndThenOr32 ( + (XhciMmioBase + 0x817C), + Data32And, + Data32Or + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x817C), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x817C) + ); + } + /// + /// For LPT-LP, Set xHCIBAR + 8180h[31:0] to 00CB0028h + /// + if (PchSeries == PchLp) { + Data32And = (UINT32)~(0xFFFFFFFF); + Data32Or = (UINT32) (0x00CB0028); + MmioAndThenOr32 ( + (XhciMmioBase + 0x8180), + Data32And, + Data32Or + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x8180), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x8180) + ); + } + /// + /// For LPT-LP, Set xHCIBAR + 8184h[31:0] to 0064001Eh + /// + if (PchSeries == PchLp) { + Data32And = (UINT32)~(0xFFFFFFFF); + Data32Or = (UINT32) (0x0064001E); + MmioAndThenOr32 ( + (XhciMmioBase + 0x8184), + Data32And, + Data32Or + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x8184), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x8184) + ); + } + + /// + /// Set D20:F0:44h[15,14,10,0] to 1b + /// Note: Only update D20:F0:44h by word since D20:F0:44h[31] is write-once bit + /// + MmioOr16 (XhciPciMmBase + 0x44, (UINT16) (BIT15 | BIT14 | BIT10 | BIT0)); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (XhciPciMmBase + 0x44), + 1, + (VOID *) (UINTN) (XhciPciMmBase + 0x44) + ); + + /// + /// Set D20:F0:44h[19:16] to 1111b + /// Note: Update D20:F0:44h by byte to 46h since D20:F0:44h[31] is write-once bit + /// + MmioOr8 (XhciPciMmBase + 0x46, (UINT8) (BIT3 | BIT2 | BIT1 | BIT0)); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (XhciPciMmBase + 0x46), + 1, + (VOID *) (UINTN) (XhciPciMmBase + 0x46) + ); + + /// + /// LPT-LP >= B0: BIOS must set XhciMmioBase + 0x8188[26, 24] to 1b, 1b + /// LPT-H >= C0: BIOS must set XhciMmioBase + 0x8188[ 24] to 1b + /// + if(((PchSeries == PchLp) && (PchSteppingValue >= LptLpB0))) { + MmioOr32 (XhciMmioBase + 0x8188, (UINT32) (BIT26 | BIT24)); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x8188), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x8188) + ); + } else if(((PchSeries == PchH) && (PchSteppingValue >= LptHC0))){ + MmioOr32 (XhciMmioBase + 0x8188, (UINT32) (BIT24)); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x8188), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x8188) + ); + } +} + +/** + Initialization XHCI Clock Gating registers + + @param[in] PchPlatformPolicy The PCH Platform Policy + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval None +**/ +VOID +ConfigureXhciClockGating ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ) +{ + UINT32 XhccCfg; + UINTN XhciPciMmBase; + UINT8 Data8; + UINT16 Data16; + UINT32 Data32And; + UINT32 Data32Or; + EFI_STATUS Status; + PCH_SERIES PchSeries; + PchSeries = GetPchSeries(); + XhciPciMmBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_XHCI, + PCI_FUNCTION_NUMBER_PCH_XHCI, + 0 + ); + /// + /// Set IOBP register 0xE5004001[7:6] to 11b + /// + Data32And = (UINT32)~(0); + Data32Or = (UINT32) (BIT7 | BIT6); + Status = ProgramIobp ( + RootComplexBar, + 0xE5004001, + Data32And, + Data32Or + ); + ASSERT_EFI_ERROR (Status); + Status = PCH_INIT_COMMON_SCRIPT_SAVE_IOBP_S3_ITEM ( + RootComplexBar, + 0xE5004001, + Data32And, + Data32Or + ); + ASSERT_EFI_ERROR (Status); + /// + /// For LPT-H : Set D20:F0:40h[21,20,18,17,8] to 1b + /// For LPT-LP: + /// Set D20:F0:40h[18,17,8] to 1b. + /// Set D20:F0:40h[21,20,19] to 000b to disable XHCI Idle L1. + /// Set D20:F0:40h[21,20,19] to 110b to enable XHCI Idle L1. + /// Note for LPT-LP Ax stepping, + /// USB3 hot plug will fail after 1 hot plug removal. + /// BIOS implement a Setup Option to disable XHCI Idle L1 as workaround. + /// Option should default to enable XHCI Idle L1 to allow PCH PM testing. + /// User need to put the system to G3 when changing from Enable to Disable state. + /// + XhccCfg = MmioRead32 (XhciPciMmBase + R_PCH_XHCI_XHCC1); + XhccCfg &= (UINT32) ~(B_PCH_XHCI_XHCC1_URD); + if (PchSeries == PchH) { + XhccCfg |= (UINT32) (BIT21 | BIT20 | BIT18 | BIT17 | BIT8); + } else if (PchSeries == PchLp) { + XhccCfg |= (UINT32) (BIT18 | BIT17 | BIT8); + if (PchPlatformPolicy->UsbConfig->Usb30Settings.XhciIdleL1 == PCH_DEVICE_DISABLE) { + XhccCfg &= (UINT32)~(BIT21 | BIT20 | BIT19); + } else { + XhccCfg |= (UINT32) (BIT21 | BIT20); + XhccCfg &= (UINT32)~(BIT19); + } + } + Data16 = (UINT16)XhccCfg; + Data8 = (UINT8)(XhccCfg >> 16); + MmioWrite16 (XhciPciMmBase + R_PCH_XHCI_XHCC1, Data16); + MmioWrite8 (XhciPciMmBase + R_PCH_XHCI_XHCC1 + 2, Data8); + /// + /// Set D20:F0:44h[9, 7, 3] to 1b + /// + MmioOr16 (XhciPciMmBase + 0x44, (UINT16) (BIT9 | BIT7 | BIT3)); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (XhciPciMmBase + 0x44), + 1, + (VOID *) (UINTN) (XhciPciMmBase + 0x44) + ); + + /// + /// For LPT-LP, Set D20:F0:A0h[18] to 1b + /// For LPT-H, Set D20:F0:A0h[6] to 1b + /// + if (PchSeries == PchH) { + Data32Or = BIT6; + } else if (PchSeries == PchLp) { + Data32Or = BIT18; + } + MmioOr32 (XhciPciMmBase + 0xA0, (UINT32) Data32Or); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciPciMmBase + 0xA0), + 1, + (VOID *) (UINTN) (XhciPciMmBase + 0xA0) + ); + /// + /// Set D20:F0:A4h[13] to 0b + /// + MmioAnd32 (XhciPciMmBase + 0xA4, (UINT32)~(BIT13)); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciPciMmBase + 0xA4), + 1, + (VOID *) (UINTN) (XhciPciMmBase + 0xA4) + ); +} + +/** + Performs basic configuration of PCH USB3 (xHCI) controller. + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] XhciMmioBase Memory base address of XHCI Controller + @param[in] Revision The policy revision used for backward compatible check + @param[in] LpcDeviceId The device ID of LPC + @param[in] XhciPciMmBase XHCI PCI Base Address + @param[in] PciD31F0RegBase LPC PCI Base Address + + @retval None +**/ +VOID +PerformXhciEhciPortSwitchingFlow ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINT32 XhciMmioBase, + IN UINT8 Revision, + IN UINT16 LpcDeviceId, + IN UINTN XhciPciMmBase, + IN UINTN PciD31F0RegBase + ) +{ + UINT32 UsbPort; + UINTN PortResetTimeout; + UINTN HsPortCount; + UINTN HsUsbrPortCount; + UINTN SsPortCount; + UINT32 PortMask; + UINT8 UsbPortRouting; + PCH_SERIES PchSeries; + UINTN *PORTSCxUSB2Ptr; + UINTN *PORTSCxUSB3Ptr; + UINT32 Data32; + + PchSeries = GetPchSeries(); + PORTSCxUSB2Ptr = NULL; + PORTSCxUSB3Ptr = NULL; + switch (PchSeries) { + case PchLp: + PORTSCxUSB2Ptr = &PCH_LP_PORTSCxUSB2[0]; + PORTSCxUSB3Ptr = &PCH_LP_PORTSCxUSB3[0]; + break; + + case PchH: + PORTSCxUSB2Ptr = &PCH_H_PORTSCxUSB2[0]; + PORTSCxUSB3Ptr = &PCH_H_PORTSCxUSB3[0]; + break; + + default: + break; + } + /// + /// Check if XHCI disabled, Exit function. + /// + if (UsbConfig->Usb30Settings.Mode == PCH_XHCI_MODE_OFF) { + return; + } + /// + /// Retrieves information about number of implemented xHCI ports and sets + /// appropriate port mask registers + /// Get the xHCI port number and program xHCI Port Routing Mask register + /// + GetXhciPortCountAndSetPortRoutingMask ( + XhciPciMmBase, + &HsPortCount, + &HsUsbrPortCount, + &SsPortCount + ); + /// + /// Workaround for USB2PR / USB3PR value not surviving warm reset. + /// + /// Check if Warm Reset + /// +#ifdef USB_PRECONDITION_ENABLE_FLAG + if (USB_RUN_IN_PEI || (!USB_PRECONDITION_POLICY_SUPPORT (UsbConfig))) { +#endif // USB_PRECONDITION_ENABLE_FLAG + if (MmioRead16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_2) & B_PCH_LPC_GEN_PMCON_MEM_SR) { + /// + /// Restore USB Port Routing registers if OS HC Switch driver has been executed + /// + if (MmioRead32 (PciD31F0RegBase + 0xAC) & BIT16) { + /// + /// Program D20:F0:D8h[5:0] to the value of xHCI D20:F0:DCh[5:0] + /// + PortMask = MmioRead32 (XhciPciMmBase + R_PCH_XHCI_USB3PRM) & (UINT32) B_PCH_XHCI_USB3PR_USB3SSENM; + + MmioAndThenOr32 ( + XhciPciMmBase + R_PCH_XHCI_USB3PR, + (UINT32)~B_PCH_XHCI_USB3PR_USB3SSEN, + PortMask + ); + /// + /// Step 3 + /// Program D20:F0:D0h[14:0] to the value of xHCI D20:F0:D4h[14:0] + /// + PortMask = MmioRead32 (XhciPciMmBase + R_PCH_XHCI_USB2PRM) & (UINT32) B_PCH_XHCI_USB2PR_USB2HCSELM; + + MmioAndThenOr32 ( + XhciPciMmBase + R_PCH_XHCI_USB2PR, + (UINT32)~B_PCH_XHCI_USB2PR_USB2HCSEL, + PortMask + ); + } + } +#ifdef USB_PRECONDITION_ENABLE_FLAG + } +#endif // USB_PRECONDITION_ENABLE_FLAG +#ifdef USB_PRECONDITION_ENABLE_FLAG + /// + /// Only clear this bit after DXE phase has finished using it. + /// because if we clear it too early in PEI phase + /// then we cannot determine if OS HC Switch driver has been executed in DXE phase. + /// + if (USB_RUN_IN_DXE || (!USB_PRECONDITION_POLICY_SUPPORT (UsbConfig))) { +#endif // USB_PRECONDITION_ENABLE_FLAG + /// + /// Clear B0:D31:F0 ACh[16] to indicate finish using this bit and begin of BIOS phase of USB port routing + /// + MmioAnd32 (PciD31F0RegBase + 0xAC, (UINT32) ~BIT16); +#ifdef USB_PRECONDITION_ENABLE_FLAG + } +#endif // USB_PRECONDITION_ENABLE_FLAG + /// + /// Do nothing for this case + /// + UsbPortRouting = USB_PR_CASE_0; + + if ((UsbConfig->Usb30Settings.PreBootSupport == PCH_DEVICE_DISABLE) || + ((UsbConfig->Usb30Settings.PreBootSupport == PCH_DEVICE_ENABLE) && + (UsbConfig->Usb30Settings.Mode == PCH_XHCI_MODE_AUTO))) { + /// + /// PCH BIOS Spec Rev 0.5.0 + /// When the BIOS does not have xHCI pre-boot software available: + /// Section 13.1.1.2 xHCI Enabled mode + /// BIOS should route the Ports to the EHCI controller and prior to OS boot + /// it should route the ports to the xHCI controller. + /// Section 13.1.1.3 xHCI Auto mode + /// BIOS should route the Ports to the EHCI controller + /// + /// When the BIOS has xHCI pre-boot software available: + /// Section 13.1.2.3 xHCI Auto mode + /// BIOS should route the Ports to the EHCI controller + /// + /// For above cases, BIOS should follow Section 13.2.5 to route the + /// USB Ports to EHCI Controller. + /// + UsbPortRouting = USB_PR_CASE_1; + } + + if ((UsbConfig->Usb30Settings.PreBootSupport == PCH_DEVICE_ENABLE) && + (UsbConfig->Usb30Settings.Mode == PCH_XHCI_MODE_ON)) { + /// + /// PCH BIOS Spec Rev 0.5.0 + /// When the BIOS has xHCI pre-boot software available: + /// Section 13.1.2.2 xHCI Enabled mode + /// BIOS should route the Ports to the xHCI controller + /// + /// For the above case, BIOS should follow Section 13.2.6 to route the + /// USB Ports to xHCI Controller. + /// + UsbPortRouting = USB_PR_CASE_2; +#ifdef USB_PRECONDITION_ENABLE_FLAG + /// + /// Execute if runnin in PEI phase or USB precondition feature is not enabled + /// If the precondition is enabled and running in DXE phase, the workaround is done already + /// + if (USB_RUN_IN_PEI || (!USB_PRECONDITION_POLICY_SUPPORT (UsbConfig))) { +#endif // USB_PRECONDITION_ENABLE_FLAG + if (MmioRead16(PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_2) & B_PCH_LPC_GEN_PMCON_MEM_SR) { + /// + /// Step 3 + /// Initiate warm reset to all USB3 ports + /// + for (UsbPort = 0; UsbPort < SsPortCount; UsbPort++) { + MmioAndThenOr32 ( + XhciMmioBase + PORTSCxUSB3Ptr[UsbPort], + (UINT32)~ (B_PCH_XHCI_PORTSCXUSB3_PED), + B_PCH_XHCI_PORTSCXUSB3_WPR + ); + } + /// + /// 3.c. Poll for warm reset bit at steps #a to be cleared or timeout at 100ms + /// + PortResetTimeout = 0; + do { + Data32 = 0; + for (UsbPort = 0; UsbPort < SsPortCount; UsbPort++) { + Data32 |= MmioRead32 (XhciMmioBase + PORTSCxUSB3Ptr[UsbPort]); + } + PchPmTimerStall (TEN_MS_TIMEOUT); + PortResetTimeout++; + } while ((Data32 & B_PCH_XHCI_PORTSCXUSB3_PR) && + (PortResetTimeout < PORT_RESET_TIMEOUT)); + } +#ifdef USB_PRECONDITION_ENABLE_FLAG + } +#endif // USB_PRECONDITION_ENABLE_FLAG + } +#ifdef USB_PRECONDITION_ENABLE_FLAG + /// + /// Execute if runnin in PEI phase or USB precondition feature is not enabled + /// If the precondition is enabled and running in DXE phase, the workaround is done already + /// + if (USB_RUN_IN_PEI || (!USB_PRECONDITION_POLICY_SUPPORT (UsbConfig))) { +#endif // USB_PRECONDITION_ENABLE_FLAG + if ((SsPortCount != 0) && + (UsbPortRouting == USB_PR_CASE_1) && + ((MmioRead32 (XhciPciMmBase + R_PCH_XHCI_USB2PR) != 0) || + (MmioRead32 (XhciPciMmBase + R_PCH_XHCI_USB3PR) != 0))) { + /// + /// PCH BIOS Spec Rev 0.5.0 Section 13.2.5 Routing of switchable USB Ports to + /// EHCI Controller + /// Step 1 + /// Retrieve information about the number of implemented xHCI ports and set appropriate + /// port mask registers + /// Done in GetXhciPortCountAndSetPortRoutingMask() + /// Step 2 + /// Based on available number of ports (from step 1) initiate port reset to enabled ports + /// where USB 2.0 device is connected + /// + /// 2.a. For Port #1, if xHCIBAR + 480h [0] is sets then + /// 2.b. Issue port reset by sets xHCIBAR + 480h [4] to 1b + /// 2.f. Repeat steps #a to #e for all the USB2.0 ports. + /// + for (UsbPort = 0; UsbPort < HsPortCount; UsbPort++) { + if (MmioRead32 (XhciMmioBase + PORTSCxUSB2Ptr[UsbPort]) & B_PCH_XHCI_PORTSCXUSB2_CCS) { + MmioAndThenOr32 ( + XhciMmioBase + PORTSCxUSB2Ptr[UsbPort], + (UINT32)~(B_PCH_XHCI_PORTSCXUSB2_PED), + B_PCH_XHCI_PORTSCXUSB2_PR + ); + } + } + /// + /// 2.c. Poll for port reset bit at steps #b to be cleared or timeout at 100ms + /// + PortResetTimeout = 0; + do { + Data32 = 0; + for (UsbPort = 0; UsbPort < HsPortCount; UsbPort++) { + Data32 |= MmioRead32 (XhciMmioBase + PORTSCxUSB2Ptr[UsbPort]); + } + PchPmTimerStall (TEN_MS_TIMEOUT); + PortResetTimeout++; + } while ((Data32 & B_PCH_XHCI_PORTSCXUSB2_PR) && + (PortResetTimeout < PORT_RESET_TIMEOUT)); + /// + /// 2.d. Program D20:F0:D0h[14:0] to 0 + /// + MmioAnd32 ( + XhciPciMmBase + R_PCH_XHCI_USB2PR, + (UINT32)~B_PCH_XHCI_USB2PR_USB2HCSEL + ); + /// + /// 2.e. Clear all the port's status by program xHCIBAR + 480h [23:17] to 1111111b + /// + for (UsbPort = 0; UsbPort < HsPortCount; UsbPort++) { + MmioAndThenOr32 ( + XhciMmioBase + PORTSCxUSB2Ptr[UsbPort], + (UINT32)~ (B_PCH_XHCI_PORTSCXUSB2_PED), + B_PCH_XHCI_PORTSCXUSB2_CEC | + B_PCH_XHCI_PORTSCXUSB2_PLC | + B_PCH_XHCI_PORTSCXUSB2_PRC | + B_PCH_XHCI_PORTSCXUSB2_OCC | + B_PCH_XHCI_PORTSCXUSB2_WRC | + B_PCH_XHCI_PORTSCXUSB2_PEC | + B_PCH_XHCI_PORTSCXUSB2_CSC + ); + } + if (HsUsbrPortCount > 0) { + MmioAndThenOr32 ( + XhciMmioBase + PORTSCxUSB2Ptr[HsPortCount], + (UINT32)~ (B_PCH_XHCI_PORTSCXUSB2_PED), + B_PCH_XHCI_PORTSCXUSB2_CEC | + B_PCH_XHCI_PORTSCXUSB2_PLC | + B_PCH_XHCI_PORTSCXUSB2_PRC | + B_PCH_XHCI_PORTSCXUSB2_OCC | + B_PCH_XHCI_PORTSCXUSB2_WRC | + B_PCH_XHCI_PORTSCXUSB2_PEC | + B_PCH_XHCI_PORTSCXUSB2_CSC + ); + } + /// + /// Step 3 + /// Initiate warm reset to all USB 3.0 ports + /// + /// 3.a. For Port #1, sets xHCIBAR + 570h [31] + /// 3.e. Repeat steps #a to #e for all the USB3.0 ports. + /// + for (UsbPort = 0; UsbPort < SsPortCount; UsbPort++) { + MmioAndThenOr32 ( + XhciMmioBase + PORTSCxUSB3Ptr[UsbPort], + (UINT32)~ (B_PCH_XHCI_PORTSCXUSB3_PED), + B_PCH_XHCI_PORTSCXUSB3_WPR + ); + } + /// + /// 3.b. Program D20:F0:D8h[5:0] to 0h. + /// + MmioAnd32 ( + XhciPciMmBase + R_PCH_XHCI_USB3PR, + (UINT32)~B_PCH_XHCI_USB3PR_USB3SSEN + ); + /// + /// 3.c. Poll for warm reset bit at steps #a to be cleared or timeout at 100ms + /// + PortResetTimeout = 0; + do { + Data32 = 0; + for (UsbPort = 0; UsbPort < SsPortCount; UsbPort++) { + Data32 |= MmioRead32 (XhciMmioBase + PORTSCxUSB3Ptr[UsbPort]); + } + PchPmTimerStall (TEN_MS_TIMEOUT); + PortResetTimeout++; + } while ((Data32 & B_PCH_XHCI_PORTSCXUSB3_PR) && + (PortResetTimeout < PORT_RESET_TIMEOUT)); + /// + /// 3.d. Clear all the port's status by program xHCIBAR + 570h [23:17] to 1111111b. + /// + for (UsbPort = 0; UsbPort < SsPortCount; UsbPort++) { + MmioAndThenOr32 ( + XhciMmioBase + PORTSCxUSB3Ptr[UsbPort], + (UINT32)~ (B_PCH_XHCI_PORTSCXUSB3_PED), + B_PCH_XHCI_PORTSCXUSB3_CEC | + B_PCH_XHCI_PORTSCXUSB3_PLC | + B_PCH_XHCI_PORTSCXUSB3_PRC | + B_PCH_XHCI_PORTSCXUSB3_OCC | + B_PCH_XHCI_PORTSCXUSB3_WRC | + B_PCH_XHCI_PORTSCXUSB3_PEC | + B_PCH_XHCI_PORTSCXUSB3_CSC + ); + } + /// + /// Step 4 + /// Set the Run bit of xHCI controller, xHCIBAR +80h[0] to 1b + /// + MmioOr32 ( + XhciMmioBase + R_PCH_XHCI_USBCMD, + B_PCH_XHCI_USBCMD_RS + ); + /// + /// Step 5 + /// Then clear the Run bit of xHCI controller, xHCIBAR +80h[0] to 0b + /// + MmioAnd32 ( + XhciMmioBase + R_PCH_XHCI_USBCMD, + (UINT32)~B_PCH_XHCI_USBCMD_RS + ); + } else if ((SsPortCount != 0) && (UsbPortRouting == USB_PR_CASE_2)) { + /// + /// PCH BIOS Spec Rev 0.5.0 Section 13.2.6 Routing of switchable USB Ports to + /// xHCI Controller + /// Step 1 + /// Retrieve information about the number of implemented xHCI ports and set appropriate + /// port mask registers + /// Done in GetXhciPortCountAndSetPortRoutingMask() + /// Step 2 + /// Program D20:F0:D8h[5:0] to the value of xHCI D20:F0:DCh[5:0] + /// + PortMask = MmioRead32 (XhciPciMmBase + R_PCH_XHCI_USB3PRM) & (UINT32) B_PCH_XHCI_USB3PR_USB3SSENM; + + MmioAndThenOr32 ( + XhciPciMmBase + R_PCH_XHCI_USB3PR, + (UINT32)~B_PCH_XHCI_USB3PR_USB3SSEN, + PortMask + ); + /// + /// Step 3 + /// Program D20:F0:D0h[14:0] to the value of xHCI D20:F0:D4h[14:0] + /// + PortMask = MmioRead32 (XhciPciMmBase + R_PCH_XHCI_USB2PRM) & (UINT32) B_PCH_XHCI_USB2PR_USB2HCSELM; + + MmioAndThenOr32 ( + XhciPciMmBase + R_PCH_XHCI_USB2PR, + (UINT32)~B_PCH_XHCI_USB2PR_USB2HCSEL, + PortMask + ); + } else if (SsPortCount != 0) { + // + // Check if Warm Reset + // + if (MmioRead16(PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_2) & B_PCH_LPC_GEN_PMCON_MEM_SR) { + /// + /// Step 3 + /// Initiate warm reset to all USB3 ports + /// + for (UsbPort = 0; UsbPort < SsPortCount; UsbPort++) { + MmioAndThenOr32 ( + XhciMmioBase + PORTSCxUSB3Ptr[UsbPort], + (UINT32)~ (B_PCH_XHCI_PORTSCXUSB3_PED), + B_PCH_XHCI_PORTSCXUSB3_WPR + ); + } + /// + /// 3.c. Poll for warm reset bit at steps #a to be cleared or timeout at 100ms + /// + PortResetTimeout = 0; + do { + Data32 = 0; + for (UsbPort = 0; UsbPort < SsPortCount; UsbPort++) { + Data32 |= MmioRead32 (XhciMmioBase + PORTSCxUSB3Ptr[UsbPort]); + } + PchPmTimerStall (TEN_MS_TIMEOUT); + PortResetTimeout++; + } while ((Data32 & B_PCH_XHCI_PORTSCXUSB3_PR) && + (PortResetTimeout < PORT_RESET_TIMEOUT)); + } + } + if (UsbConfig->Usb30Settings.ManualMode == PCH_DEVICE_ENABLE) { + /// + /// Using the similar method as + /// PCH BIOS Spec Rev 0.5.0 Section 13.2.5 Routing of switchable USB Ports to + /// EHCI Controller + /// Step 1 + /// Retrieve information about the number of implemented xHCI ports and set appropriate + /// port mask registers + /// Done in GetXhciPortCountAndSetPortRoutingMask() + /// Step 2 + /// Based on available number of ports (from step 1) initiate port reset to enabled ports + /// where USB 2.0 device is connected + /// + /// 2.a. For Port #1, if xHCIBAR + 480h [0] is sets then + /// 2.b. Issue port reset by sets xHCIBAR + 480h [4] to 1b + /// 2.f. Repeat steps #a to #e for all the USB2.0 ports. + /// + for (UsbPort = 0; UsbPort < HsPortCount; UsbPort++) { + if (MmioRead32 (XhciMmioBase + PORTSCxUSB2Ptr[UsbPort]) & B_PCH_XHCI_PORTSCXUSB2_CCS) { + MmioAndThenOr32 ( + XhciMmioBase + PORTSCxUSB2Ptr[UsbPort], + (UINT32)~(B_PCH_XHCI_PORTSCXUSB2_PED), + B_PCH_XHCI_PORTSCXUSB2_PR + ); + } + } + /// + /// 2.c. Poll for port reset bit at steps #b to be cleared or timeout at 100ms + /// + PortResetTimeout = 0; + do { + Data32 = 0; + for (UsbPort = 0; UsbPort < HsPortCount; UsbPort++) { + Data32 |= MmioRead32 (XhciMmioBase + PORTSCxUSB2Ptr[UsbPort]); + } + PchPmTimerStall (TEN_MS_TIMEOUT); + PortResetTimeout++; + } while ((Data32 & B_PCH_XHCI_PORTSCXUSB2_PR) && + (PortResetTimeout < PORT_RESET_TIMEOUT)); + /// + /// 2.d. Program D20:F0:D0h[14:0] manually + /// + PortMask = 0; + for (UsbPort = 0; UsbPort < HsPortCount; UsbPort++) { + if (UsbConfig->Usb30Settings.ManualModeUsb20PerPinRoute[UsbPort]==1) { // 0: EHCI; 1 :XHCI; + PortMask |= 1 << UsbPort; + } + } + MmioAndThenOr32 ( + XhciPciMmBase + R_PCH_XHCI_USB2PR, + (UINT32)~B_PCH_XHCI_USB2PR_USB2HCSEL, + PortMask + ); + /// + /// 2.e. Clear all the port's status by program xHCIBAR + 480h [23:17] to 1111111b + /// + for (UsbPort = 0; UsbPort < HsPortCount; UsbPort++) { + MmioAndThenOr32 ( + XhciMmioBase + PORTSCxUSB2Ptr[UsbPort], + (UINT32)~ (B_PCH_XHCI_PORTSCXUSB2_PED), + B_PCH_XHCI_PORTSCXUSB2_CEC | + B_PCH_XHCI_PORTSCXUSB2_PLC | + B_PCH_XHCI_PORTSCXUSB2_PRC | + B_PCH_XHCI_PORTSCXUSB2_OCC | + B_PCH_XHCI_PORTSCXUSB2_WRC | + B_PCH_XHCI_PORTSCXUSB2_PEC | + B_PCH_XHCI_PORTSCXUSB2_CSC + ); + } + if (HsUsbrPortCount > 0) { + MmioAndThenOr32 ( + XhciMmioBase + PORTSCxUSB2Ptr[HsPortCount], + (UINT32)~ (B_PCH_XHCI_PORTSCXUSB2_PED), + B_PCH_XHCI_PORTSCXUSB2_CEC | + B_PCH_XHCI_PORTSCXUSB2_PLC | + B_PCH_XHCI_PORTSCXUSB2_PRC | + B_PCH_XHCI_PORTSCXUSB2_OCC | + B_PCH_XHCI_PORTSCXUSB2_WRC | + B_PCH_XHCI_PORTSCXUSB2_PEC | + B_PCH_XHCI_PORTSCXUSB2_CSC + ); + } + /// + /// Step 3 + /// Initiate warm reset to all USB 3.0 ports + /// + /// 3.a. For Port #1, sets xHCIBAR + 570h [31] + /// 3.e. Repeat steps #a to #e for all the USB3.0 ports. + /// + for (UsbPort = 0; UsbPort < SsPortCount; UsbPort++) { + MmioAndThenOr32 ( + XhciMmioBase + PORTSCxUSB3Ptr[UsbPort], + (UINT32)~ (B_PCH_XHCI_PORTSCXUSB3_PED), + B_PCH_XHCI_PORTSCXUSB3_WPR + ); + } + /// + /// 3.b. Program D20:F0:D8h[5:0] manually. + /// + PortMask = 0; + for (UsbPort = 0; UsbPort < SsPortCount; UsbPort++) { + if (UsbConfig->Usb30Settings.ManualModeUsb30PerPinEnable[UsbPort]==1) { // 0: Disable; 1:Enable; + PortMask |= 1 << UsbPort; + } + } + MmioAndThenOr32 ( + XhciPciMmBase + R_PCH_XHCI_USB3PR, + (UINT32)~B_PCH_XHCI_USB3PR_USB3SSEN, + PortMask + ); + /// + /// 3.c. Poll for warm reset bit at steps #a to be cleared or timeout at 100ms + /// + PortResetTimeout = 0; + do { + Data32 = 0; + for (UsbPort = 0; UsbPort < SsPortCount; UsbPort++) { + Data32 |= MmioRead32 (XhciMmioBase + PORTSCxUSB3Ptr[UsbPort]); + } + PchPmTimerStall (TEN_MS_TIMEOUT); + PortResetTimeout++; + } while ((Data32 & B_PCH_XHCI_PORTSCXUSB3_PR) && + (PortResetTimeout < PORT_RESET_TIMEOUT)); + /// + /// 3.d. Clear all the port's status by program xHCIBAR + 570h [23:17] to 1111111b. + /// + for (UsbPort = 0; UsbPort < SsPortCount; UsbPort++) { + MmioAndThenOr32 ( + XhciMmioBase + PORTSCxUSB3Ptr[UsbPort], + (UINT32)~ (B_PCH_XHCI_PORTSCXUSB3_PED), + B_PCH_XHCI_PORTSCXUSB3_CEC | + B_PCH_XHCI_PORTSCXUSB3_PLC | + B_PCH_XHCI_PORTSCXUSB3_PRC | + B_PCH_XHCI_PORTSCXUSB3_OCC | + B_PCH_XHCI_PORTSCXUSB3_WRC | + B_PCH_XHCI_PORTSCXUSB3_PEC | + B_PCH_XHCI_PORTSCXUSB3_CSC + ); + } + /// + /// Step 4 + /// Set the Run bit of xHCI controller, xHCIBAR + 80h[0] to 1b + /// + MmioOr32 ( + XhciMmioBase + R_PCH_XHCI_USBCMD, + (UINT32) B_PCH_XHCI_USBCMD_RS + ); + /// + /// Step 5 + /// Then clear the Run bit of xHCI controller, xHCIBAR + 80h[0] to 0b + /// + MmioAnd32 ( + XhciMmioBase + R_PCH_XHCI_USBCMD, + (UINT32) ~B_PCH_XHCI_USBCMD_RS + ); + } +#ifdef USB_PRECONDITION_ENABLE_FLAG + } +#endif // USB_PRECONDITION_ENABLE_FLAG + +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, XHCI USB3 PR resume well registers + /// get save into S3 Script table only when not running in Auto/Smart Auto mode. + /// + if (((UsbConfig->Usb30Settings.ManualMode == PCH_DEVICE_ENABLE)) || + ((UsbConfig->Usb30Settings.PreBootSupport == PCH_DEVICE_ENABLE) && + (UsbConfig->Usb30Settings.Mode == PCH_XHCI_MODE_ON))) { + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciPciMmBase + R_PCH_XHCI_USB3PR), + 1, + (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_USB3PR) + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciPciMmBase + R_PCH_XHCI_USB2PR), + 1, + (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_USB2PR) + ); + } +#endif + +#ifdef USB_PRECONDITION_ENABLE_FLAG + /// + /// Check if XHCI disabled or auto even no preboot support, exit function directly + /// + if ((UsbConfig->Usb30Settings.Mode == PCH_XHCI_MODE_OFF) || + (UsbConfig->Usb30Settings.Mode == PCH_XHCI_MODE_AUTO) || + (UsbConfig->Usb30Settings.PreBootSupport == PCH_DEVICE_DISABLE) + ) { + return; + } + /// + /// If precondition is enabled, execute USB precondition function by each phase call + /// + if (USB_PRECONDITION_POLICY_SUPPORT (UsbConfig)) { + XHCI_PRECONDITION ( + (UINT8) ((XhciPciMmBase >> 20) &0xFF), + PCI_DEVICE_NUMBER_PCH_XHCI, + PCI_FUNCTION_NUMBER_PCH_XHCI, + XhciMmioBase, + PORTSCxUSB2Ptr, + HsPortCount, + PORTSCxUSB3Ptr, + SsPortCount + ); + } +#endif // USB_PRECONDITION_ENABLE_FLAG +} + +/** + Retrieves information about number of implemented xHCI ports + and sets appropriate port mask registers. + + @param[in] XhciPciMmBase XHCI PCI Base Address + @param[out] HsPortCount Count of High Speed Ports + @param[out] HsUsbrPortCount Count of USBr Port + @param[out] SsPortCount Count of Super Speed Ports + + @retval None +**/ +VOID +GetXhciPortCountAndSetPortRoutingMask ( + IN UINTN XhciPciMmBase, + OUT UINTN *HsPortCount, + OUT UINTN *HsUsbrPortCount, + OUT UINTN *SsPortCount + ) +{ + UINT32 HsPortEnableMask; + UINT32 SsPortEnableMask; + PCH_SERIES PchSeries; + + HsPortEnableMask = 0; + SsPortEnableMask = 0; + PchSeries = GetPchSeries(); + /// + /// PCH BIOS Spec Rev 0.5.0 + /// Section 13.2.5 Routing of switchable USB Ports to EHCI Controller + /// Section 13.2.6 Routing of switchable USB Ports to xHCI Controller + /// + if (PchSeries == PchH) { + /// + /// Step 1.a Check xHCI D20:F0:E0h[2:1] to get HS Port Count. + /// + switch (MmioRead32 (XhciPciMmBase + R_PCH_XHCI_FUS) & B_PCH_XHCI_FUS_HSPRTCNT) { + case V_PCH_XHCI_FUS_HSPRTCNT_11B: + /// + /// If the value is 11b: Set xHCI D20:F0:D4h[13:0] to 00FFh. Number of HS ports is 8. + /// + *HsPortCount = V_PCH_H_XHCI_FUS_HSPRTCNT_11B_CNT; + HsPortEnableMask = V_PCH_H_XHCI_FUS_HSPRTCNT_11B_MASK; + break; + + case V_PCH_XHCI_FUS_HSPRTCNT_10B: + /// + /// If the value is 10b: Set xHCI D20:F0:D4h[13:0] to 0FFFh. Number of HS ports is 10. + /// It is work around. Bit 6 and 7 have to be set to 1 to enable USB2 ports. + /// + *HsPortCount = V_PCH_H_XHCI_FUS_HSPRTCNT_10B_CNT; + HsPortEnableMask = V_PCH_H_XHCI_FUS_HSPRTCNT_10B_MASK; + break; + + case V_PCH_XHCI_FUS_HSPRTCNT_01B: + /// + /// If the value is 01b: Set xHCI D20:F0:D4h[13:0] to 3FFFh. Number of HS ports is 12. + /// It is work around. Bit 6 and 7 have to be set to 1 to enable USB2 ports. + /// + *HsPortCount = V_PCH_H_XHCI_FUS_HSPRTCNT_01B_CNT; + HsPortEnableMask = V_PCH_H_XHCI_FUS_HSPRTCNT_01B_MASK; + break; + + case V_PCH_XHCI_FUS_HSPRTCNT_00B: + /// + /// If the value is 00b: Set xHCI D20:F0:D4h[13:0] to 3FFFh. Number of HS ports is 14 + /// + default: + *HsPortCount = V_PCH_H_XHCI_FUS_HSPRTCNT_00B_CNT; + HsPortEnableMask = V_PCH_H_XHCI_FUS_HSPRTCNT_00B_MASK; + break; + } + /// + /// Step 1.b Check xHCI D20:F0:E0h[4:3] to get SS Port Count. + /// + switch (MmioRead32 (XhciPciMmBase + R_PCH_XHCI_FUS) & B_PCH_XHCI_FUS_SSPRTCNT) { + case V_PCH_XHCI_FUS_SSPRTCNT_11B: + /// + /// If the value is 11b: Set xHCI D20:F0:DCh[5:0] to 000000b. Number of SS ports is 0. + /// + *SsPortCount = V_PCH_H_XHCI_FUS_SSPRTCNT_11B_CNT; + SsPortEnableMask = V_PCH_H_XHCI_FUS_SSPRTCNT_11B_MASK; + break; + + case V_PCH_XHCI_FUS_SSPRTCNT_10B: + /// + /// If the value is 10b: Set xHCI D20:F0:DCh[5:0] to 000011b. Number of SS ports is 2. + /// + *SsPortCount = V_PCH_H_XHCI_FUS_SSPRTCNT_10B_CNT; + SsPortEnableMask = V_PCH_H_XHCI_FUS_SSPRTCNT_10B_MASK; + break; + + case V_PCH_XHCI_FUS_SSPRTCNT_01B: + /// + /// If the value is 01b: Set xHCI D20:F0:DCh[5:0] to 001111b. Number of SS ports is 4. + /// + *SsPortCount = V_PCH_H_XHCI_FUS_SSPRTCNT_01B_CNT; + SsPortEnableMask = V_PCH_H_XHCI_FUS_SSPRTCNT_01B_MASK; + break; + + case V_PCH_XHCI_FUS_SSPRTCNT_00B: + /// + /// If the value is 00b: Set xHCI D20:F0:DCh[5:0] to 111111b. Number of SS ports is 6. + /// + default: + *SsPortCount = V_PCH_H_XHCI_FUS_SSPRTCNT_00B_CNT; + SsPortEnableMask = V_PCH_H_XHCI_FUS_SSPRTCNT_00B_MASK; + break; + } + /// + /// Step 1.c Check xHCI D20:F0:E0h[5] to know if USBr is enabled. + /// @todo Need more comments to understand this + /// + switch (MmioRead32 (XhciPciMmBase + R_PCH_XHCI_FUS) & B_PCH_XHCI_FUS_USBR) { + case V_PCH_XHCI_FUS_USBR_EN: + /// + /// If 0b: Set xHCI D20:F0:D4[14] to 1b. USBr port is enabled. + /// + *HsUsbrPortCount = 1; + HsPortEnableMask |= BIT14; + break; + + case V_PCH_XHCI_FUS_USBR_DIS: + /// + /// If 1b: Set xHCI D20:F0:D4[14] to 0b. USBr port is disabled. + /// + *HsUsbrPortCount = 0; + HsPortEnableMask &= (~BIT14); + break; + } + } else if (PchSeries == PchLp) { + /// + /// Step 1.a LPT-LP has a fixed number of 8 HS ports. Set xHCI D20:F0:D4h[13:0] to 00FFh. + /// + *HsPortCount = V_PCH_LP_XHCI_FIXED_HSPRTCNT; + HsPortEnableMask = V_PCH_LP_XHCI_FIXED_HSPRTCNT_MASK; + /// + /// Step 1.b LPT-LP has a fixed number of 4 SS ports. Set xHCI D20:F0:DCh[3:0] to 0Fh. + /// + *SsPortCount = V_PCH_LP_XHCI_FIXED_SSPRTCNT; + SsPortEnableMask = V_PCH_LP_XHCI_FIXED_SSPRTCNT_MASK; + /// + /// Step 1.c Check xHCI D20:F0:E0h[5] to know if USBr is enabled. + /// @todo Need more comments to understand this + /// + switch (MmioRead32 (XhciPciMmBase + R_PCH_XHCI_FUS) & B_PCH_XHCI_FUS_USBR) { + case V_PCH_XHCI_FUS_USBR_EN: + /// + /// If 0b: Set xHCI D20:F0:D4[8] to 1b. USBr port is enabled. + /// + *HsUsbrPortCount = 1; + HsPortEnableMask |= BIT8; + break; + + case V_PCH_XHCI_FUS_USBR_DIS: + /// + /// If 1b: Set xHCI D20:F0:D4[8] to 0b. USBr port is disabled. + /// + *HsUsbrPortCount = 0; + HsPortEnableMask &= (~BIT8); + break; + } + } + + //Routing the USB ports 12, 8, and 5 to EHCI to avoid OC detection when wakening up from S3 + + #ifdef UPSERVER_SUPPORT + HsPortEnableMask &=~(BIT12|BIT8|BIT5); + #endif + + /// + /// Set xHCI USB2 Port Routing Mask register (D20:F0:D4h[14:0]) + /// per HS Port Enable Mask value + /// + MmioAndThenOr32 ( + XhciPciMmBase + R_PCH_XHCI_USB2PRM, + ~ (UINT32) B_PCH_XHCI_USB2PR_USB2HCSELM, + HsPortEnableMask + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciPciMmBase + R_PCH_XHCI_USB2PRM), + 1, + (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_USB2PRM) + ); + /// + /// Set xHCI USB3 Port Routing Mask register (D20:F0:DCh[5:0]) + /// per SS Port Enable Mask value + /// + MmioAndThenOr32 ( + XhciPciMmBase + R_PCH_XHCI_USB3PRM, + ~ (UINT32) B_PCH_XHCI_USB3PR_USB3SSENM, + SsPortEnableMask + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciPciMmBase + R_PCH_XHCI_USB3PRM), + 1, + (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_USB3PRM) + ); +} + +/** + Setup XHCI Over-Current Mapping + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] XhciPciMmBase XHCI PCI Base Address + + @retval None +**/ +VOID +XhciOverCurrentMapping ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINTN XhciPciMmBase + ) +{ + /// + /// BIOS responsibility on Overcurrent protection. + /// ---------------------------------------------- + /// There are 8 total overcurrent pins + /// which can be map to 14 USB2 ports and 6 USB3 ports. + /// On a given physical connector, + /// one OC pin is shared between the USB2 (HS) pins and USB3 (SS) pins. + /// USB2 (HS) pins are programmable to be owned by either XHCI or EHCI. + /// OC pins are associated to the current owner. + /// USB2 (HS) ports 1-8 use OC pins 1-4, ports 9-14 use OC pins 4-8 + /// USB3 (SS) ports has the flexibility in pairing with any of the OC pins. + /// It is ok to map multiple ports to a single pin. + /// It is not ok to map a single ports to a multiple pins. + /// All USB ports routed out of the package must have Overcurrent protection. + /// USB Ports not routed out from the package should not be assigned OC pins. + /// + UINT32 Index; + UINT32 CurrentIndex; + UINT32 XhciHsOcm1; + UINT32 XhciHsOcm2; + UINT32 XhciSsOcm1; + UINT32 XhciSsOcm2; + PCH_SERIES PchSeries; + + PchSeries = GetPchSeries(); + /// + /// Check if XHCI disabled, Exit function. + /// + if (UsbConfig->Usb30Settings.Mode == PCH_XHCI_MODE_OFF) { + return; + } + /// + /// Find the corresponding register and set the bits + /// + XhciHsOcm1 = 0; + XhciHsOcm2 = 0; + XhciSsOcm1 = 0; + XhciSsOcm2 = 0; + + for (Index = 0; Index < GetPchUsbMaxPhysicalPortNum (); Index++) { + if (UsbConfig->Usb20OverCurrentPins[Index] == PchUsbOverCurrentPinSkip) { + /// + /// No OC pin assigned, skip this port + /// + } else { + if (Index < 8) { + /// + /// Port 0-7: OC0 - OC3 + /// + if (UsbConfig->Usb20OverCurrentPins[Index] > PchUsbOverCurrentPin3) { + ASSERT (FALSE); + continue; + } + + CurrentIndex = UsbConfig->Usb20OverCurrentPins[Index] * 8 + Index; + XhciHsOcm1 |= (UINT32) (BIT0 << CurrentIndex); + } else { + /// + /// Port 8-13: OC4 - OC7 + /// + if ((UsbConfig->Usb20OverCurrentPins[Index] < PchUsbOverCurrentPin4) || + (UsbConfig->Usb20OverCurrentPins[Index] > PchUsbOverCurrentPin7)) { + ASSERT (FALSE); + continue; + } + + CurrentIndex = (UsbConfig->Usb20OverCurrentPins[Index] - 4) * 8 + (Index - 8); + XhciHsOcm2 |= (UINT32) (BIT0 << CurrentIndex); + } + } + } + + for (Index = 0; Index < GetPchXhciMaxUsb3PortNum (); Index++) { + if (UsbConfig->Usb30OverCurrentPins[Index] == PchUsbOverCurrentPinSkip) { + /// + /// No OC pin assigned, skip this port + /// + } else { + /// + /// Port 0-5: OC0 - OC7 + /// + if (UsbConfig->Usb30OverCurrentPins[Index] < PchUsbOverCurrentPin4) { + CurrentIndex = UsbConfig->Usb30OverCurrentPins[Index] * 8 + Index; + XhciSsOcm1 |= (UINT32) (BIT0 << CurrentIndex); + } else { + CurrentIndex = (UsbConfig->Usb30OverCurrentPins[Index] - 4) * 8 + Index; + XhciSsOcm2 |= (UINT32) (BIT0 << CurrentIndex); + } + } + } + /// + /// OCM registers are in the suspend well. + /// + MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_U2OCM1, XhciHsOcm1); + MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_U3OCM1, XhciSsOcm1); + if (PchSeries == PchH) { + MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_U2OCM2, XhciHsOcm2); + MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_U3OCM2, XhciSsOcm2); + } + +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, all resume well registers need to be saved + /// into S3 Script table. + /// + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciPciMmBase + R_PCH_XHCI_U2OCM1), + 1, + (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_U2OCM1) + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciPciMmBase + R_PCH_XHCI_U3OCM1), + 1, + (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_U3OCM1) + ); + if (PchSeries == PchH) { + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciPciMmBase + R_PCH_XHCI_U2OCM2), + 1, + (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_U2OCM2) + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciPciMmBase + R_PCH_XHCI_U3OCM2), + 1, + (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_U3OCM2) + ); + } +#endif // SUS_WELL_RESTORE +} + +/** + Setup EHCI Over-Current Mapping + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] Ehci1PciMmBase EHCI 1 PCI Base Address + @param[in] Ehci2PciMmBase EHCI 2 PCI Base Address + + @retval None +**/ +VOID +EhciOverCurrentMapping ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINTN Ehci1PciMmBase, + IN UINTN Ehci2PciMmBase + ) +{ + UINT32 Index; + UINT32 CurrentIndex; + UINT32 Ehci1Ocm; + UINT32 Ehci2Ocm; + PCH_SERIES PchSeries; + + Ehci1Ocm = 0; + Ehci2Ocm = 0; + PchSeries = GetPchSeries(); + + for (Index = 0; Index < GetPchUsbMaxPhysicalPortNum (); Index++) { + if (UsbConfig->Usb20OverCurrentPins[Index] == PchUsbOverCurrentPinSkip) { + /// + /// No OC pin assigned, skip this port + /// + } else { + if (Index < 8) { + /// + /// Port 0~7 -> OC0~3 + /// + if (UsbConfig->Usb20OverCurrentPins[Index] > PchUsbOverCurrentPin3) { + ASSERT (FALSE); + continue; + } + + CurrentIndex = UsbConfig->Usb20OverCurrentPins[Index] * 8 + Index; + Ehci1Ocm |= (UINT32) (BIT0 << CurrentIndex); + } else { + if (PchSeries == PchH) { + /// + /// Port 8~13 -> OC4~7 + /// + if ((UsbConfig->Usb20OverCurrentPins[Index] < PchUsbOverCurrentPin4) || + (UsbConfig->Usb20OverCurrentPins[Index] > PchUsbOverCurrentPin7)) { + ASSERT (FALSE); + continue; + } + CurrentIndex = (UsbConfig->Usb20OverCurrentPins[Index] - 4) * 8 + (Index - 8); + Ehci2Ocm |= (UINT32) (BIT0 << CurrentIndex); + } + } + } + } + /// + /// EHCI1OCM and EHCI2OCM are in the suspend well. + /// + if (UsbConfig->Usb20Settings[PchEhci1].Enable == PCH_DEVICE_ENABLE) { + MmioWrite32 (Ehci1PciMmBase + R_PCH_EHCI_OCMAP, Ehci1Ocm); + } + + if (PchSeries == PchH) { + if (UsbConfig->Usb20Settings[PchEhci2].Enable == PCH_DEVICE_ENABLE) { + MmioWrite32 (Ehci2PciMmBase + R_PCH_EHCI_OCMAP, Ehci2Ocm); + } + } + +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, all resume well registers need to be saved + /// into S3 Script table. + /// + if (UsbConfig->Usb20Settings[PchEhci1].Enable == PCH_DEVICE_ENABLE) { + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (Ehci1PciMmBase + R_PCH_EHCI_OCMAP), + 1, + (VOID *) (UINTN) (Ehci1PciMmBase + R_PCH_EHCI_OCMAP) + ); + } + + if (PchSeries == PchH) { + if (UsbConfig->Usb20Settings[PchEhci2].Enable == PCH_DEVICE_ENABLE) { + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (Ehci2PciMmBase + R_PCH_EHCI_OCMAP), + 1, + (VOID *) (UINTN) (Ehci2PciMmBase + R_PCH_EHCI_OCMAP) + ); + } + } +#endif +} + +/** + Program Ehci Port Disable Override + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] Ehci1PciMmBase EHCI 1 PCI Base Address + @param[in] Ehci2PciMmBase EHCI 2 PCI Base Address + + @retval None +**/ +VOID +EhciPortDisableOverride ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINTN Ehci1PciMmBase, + IN UINTN Ehci2PciMmBase + ) +{ + UINT32 Index; + PCH_SERIES PchSeries; + + PchSeries = GetPchSeries(); + /// + /// PCH BIOS Spec Rev 0.5.0 Section 12.2 Disabling USB Ports + /// System BIOS may choose to disable individual USB ports to save power or for security + /// purposes. Each of the USB ports has a corresponding bit within the PCH USB Port + /// Disable Override Register (D26/29:F0 + 64h). The PCH USB Port Disable Override + /// Register can be locked by setting the Write Enable bit of the PCH USB Per-Port Register + /// Write Control Register, PMBASE + 3Ch[1]. Refer to the PCH EDS for more details on + /// these registers. + /// + for (Index = 0; Index < GetPchUsbMaxPhysicalPortNum (); Index++) { + if ((Index < 8) && (UsbConfig->Usb20Settings[PchEhci1].Enable == PCH_DEVICE_ENABLE)) { + /// + /// EHCI1 PDO for Port 0 to 7 + /// + if (UsbConfig->PortSettings[Index].Enable == PCH_DEVICE_DISABLE) { + MmioOr8 (Ehci1PciMmBase + R_PCH_EHCI_PDO, (UINT8) (B_PCH_EHCI_PDO_DIS_PORT0 << Index)); + } else { + MmioAnd8 (Ehci1PciMmBase + R_PCH_EHCI_PDO, (UINT8) ~(B_PCH_EHCI_PDO_DIS_PORT0 << Index)); + } + } + if (PchSeries == PchH) { + if ((Index < 14) && (UsbConfig->Usb20Settings[PchEhci2].Enable == PCH_DEVICE_ENABLE)) { + /// + /// EHCI2 PDO for Port 8 to 13 + /// + if (UsbConfig->PortSettings[Index].Enable == PCH_DEVICE_DISABLE) { + MmioOr8 (Ehci2PciMmBase + R_PCH_EHCI_PDO, (UINT8) (B_PCH_EHCI_PDO_DIS_PORT0 << (Index - 8))); + } else { + MmioAnd8 (Ehci2PciMmBase + R_PCH_EHCI_PDO, (UINT8) ~(B_PCH_EHCI_PDO_DIS_PORT0 << (Index - 8))); + } + } + } + } + +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, all resume well registers need to be saved + /// into S3 Script table. + /// + if (UsbConfig->Usb20Settings[PchEhci1].Enable == PCH_DEVICE_ENABLE) { + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (Ehci1PciMmBase + R_PCH_EHCI_PDO), + 1, + (VOID *) (UINTN) (Ehci1PciMmBase + R_PCH_EHCI_PDO) + ); + } + + if (PchSeries == PchH) { + if (UsbConfig->Usb20Settings[PchEhci2].Enable == PCH_DEVICE_ENABLE) { + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (Ehci2PciMmBase + R_PCH_EHCI_PDO), + 1, + (VOID *) (UINTN) (Ehci2PciMmBase + R_PCH_EHCI_PDO) + ); + } + } +#endif // SUS_WELL_RESTORE +} + +/** + Program Xhci Port Disable Override + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] XhciPciMmBase XHCI PCI Base Address + @param[in] Revision Platform policy revision + + @retval None +**/ +VOID +XhciPortDisableOverride ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINTN XhciPciMmBase, + IN UINT8 Revision + ) +{ + UINT32 Index; + UINT32 XhciUsb2Pdo; + UINT32 XhciUsb3Pdo; + UINT32 XhciIndex; + PCH_SERIES PchSeries; + + PchSeries = GetPchSeries(); + /// + /// Check if XHCI disabled, Exit function. + /// + if (UsbConfig->Usb30Settings.Mode == PCH_XHCI_MODE_OFF) { + return; + } + /// + /// PCH BIOS Spec Rev 0.5.0 Section 13.2.2 Port Disable Override + /// In LynxPoint PCH, Port disable override on xHCI ports is implemented by mapping the + /// appropriate ports to the EHCI controller and then setting the port disable override in + /// the EHCI function. Please refer to section 12.2. + /// Please note that there is a corresponding disable bit on D20:F0:E4h[14:0] for USB 2.0 + /// ports and D20:F0:E8h[5:0] for USB 3.0 ports. BIOS needs to program them accordingly. + /// + /// XHCI PDO for HS + /// + XhciUsb2Pdo = MmioRead32 (XhciPciMmBase + R_PCH_XHCI_USB2PDO) & B_PCH_XHCI_USB2PDO_MASK; + for (Index = 0; Index < GetPchUsbMaxPhysicalPortNum (); Index++) { + XhciIndex = Index; + if (PchSeries == PchH) { + /// + /// Translate physical pins to internal ports numbering + /// + XhciIndex = XhciUsb2InternalPortNumberLookUpTable[Index]; + } + if (UsbConfig->PortSettings[Index].Enable == PCH_DEVICE_DISABLE) { + XhciUsb2Pdo |= (UINT32) (B_PCH_XHCI_USB2PDO_DIS_PORT0 << XhciIndex); + } else { + XhciUsb2Pdo &= (UINT32)~(B_PCH_XHCI_USB2PDO_DIS_PORT0 << XhciIndex); + } + } + /// + /// XHCI PDO for SS + /// + XhciUsb3Pdo = MmioRead32 (XhciPciMmBase + R_PCH_XHCI_USB3PDO) & B_PCH_XHCI_USB3PDO_MASK; + for (Index = 0; Index < GetPchXhciMaxUsb3PortNum (); Index++) { + + if (USB3PORT_SETTING_POLICY_SUPPORT(Revision)){ + if (UsbConfig->Port30Settings[Index].Enable == PCH_DEVICE_DISABLE) { + XhciUsb3Pdo |= (UINT32) (B_PCH_XHCI_USB3PDO_DIS_PORT0 << Index); + } else { + XhciUsb3Pdo &= (UINT32)~(B_PCH_XHCI_USB3PDO_DIS_PORT0 << Index); + } + } else { + if (UsbConfig->PortSettings[Index].Enable == PCH_DEVICE_DISABLE) { + XhciUsb3Pdo |= (UINT32) (B_PCH_XHCI_USB3PDO_DIS_PORT0 << Index); + } else { + XhciUsb3Pdo &= (UINT32)~(B_PCH_XHCI_USB3PDO_DIS_PORT0 << Index); + } + } + } + /// + /// USB2PDO and USB3PDO are Write-Once registers and bits in them are in the SUS Well. + /// + MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_USB2PDO, XhciUsb2Pdo); + MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_USB3PDO, XhciUsb3Pdo); +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, all resume well registers need to be saved + /// into S3 Script table. + /// + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciPciMmBase + R_PCH_XHCI_USB2PDO), + 1, + (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_USB2PDO) + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciPciMmBase + R_PCH_XHCI_USB3PDO), + 1, + (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_USB3PDO) + ); +#endif +} + +/** + Enable EHCI USBR device + + @param[in] EhciPciMmBase Ehci PCI Base Address + + @retval None +**/ +VOID +EhciUsbrEnable ( + IN UINTN EhciPciMmBase + ) +{ + /// + /// NOTE: EHCI USBR Enable + /// EHCI1_USBr_en and EHCI2_USBr_en are mutually exclusive. Both cannot be set to 1 at any one time. + /// SW must ensure at any one time, only 1 EHCI should have the bit set. + /// + MmioOr16 (EhciPciMmBase + 0x7A, (UINT16) BIT8); +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, all resume well registers need to be saved + /// into S3 Script table. + /// + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (EhciPciMmBase + 0x7A), + 1, + (VOID *) (UINTN) (EhciPciMmBase + 0x7A) + ); +#endif +} + +/** + Program and enable XHCI Memory Space + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] XhciMmioBase Memory base address of XHCI Controller + @param[in] XhciPciMmBase XHCI PCI Base Address + + @retval None +**/ +VOID +XhciMemorySpaceOpen ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINT32 XhciMmioBase, + IN UINTN XhciPciMmBase + ) +{ + /// + /// Check if XHCI disabled, Exit function. + /// + if (UsbConfig->Usb30Settings.Mode == PCH_XHCI_MODE_OFF) { + return; + } + /// + /// Assign memory resources + /// + MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE, XhciMmioBase); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciPciMmBase + R_PCH_XHCI_MEM_BASE), + 1, + (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_MEM_BASE) + ); + + MmioOr16 ( + XhciPciMmBase + R_PCH_XHCI_COMMAND_REGISTER, + (UINT16) (B_PCH_XHCI_COMMAND_MSE | B_PCH_XHCI_COMMAND_BME) + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (XhciPciMmBase + R_PCH_XHCI_COMMAND_REGISTER), + 1, + (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_COMMAND_REGISTER) + ); +} + +/** + Clear and disable XHCI Memory Space + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] XhciMmioBase Memory base address of XHCI Controller + @param[in] XhciPciMmBase XHCI PCI Base Address + + @retval None +**/ +VOID +XhciMemorySpaceClose ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINT32 XhciMmioBase, + IN UINTN XhciPciMmBase + ) +{ + /// + /// Check if XHCI disabled, Exit function. + /// + if (UsbConfig->Usb30Settings.Mode == PCH_XHCI_MODE_OFF) { + return; + } + /// + /// Clear memory resources + /// + MmioAnd16 ( + XhciPciMmBase + R_PCH_XHCI_COMMAND_REGISTER, + (UINT16)~(B_PCH_XHCI_COMMAND_MSE | B_PCH_XHCI_COMMAND_BME) + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (XhciPciMmBase + R_PCH_XHCI_COMMAND_REGISTER), + 1, + (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_COMMAND_REGISTER) + ); + + MmioWrite32 ((XhciPciMmBase + R_PCH_XHCI_MEM_BASE), 0); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciPciMmBase + R_PCH_XHCI_MEM_BASE), + 1, + (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_MEM_BASE) + ); +} + +/** + Tune the USB 2.0 high-speed signals quality. + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] LpcDeviceId The device ID of LPC + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval EFI_SUCCESS Successfully completed + @retval EFI_DEVICE_ERROR Programming is failed +**/ +VOID +Usb2PortLengthProgramming ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINT16 LpcDeviceId, + IN UINT32 RootComplexBar + ) +{ + EFI_STATUS Status; + UINT32 Index; + UINT32 Data32And; + UINT32 Data32Or; +#ifdef USB_PRECONDITION_ENABLE_FLAG + PCH_SERIES PchSeries; + PchSeries = GetPchSeries(); + /// + /// Execute the code if running in PEI phase when USB precondition feature is enabled + /// or in DXE phase when USB precondition feature disabled + /// If the precondition is enabled and running in DXE phase, + /// the code has already run once in PEI but the save S3 script need to run again in DXE phase + /// but only run if and only if both EHCI is not disabled + /// + if ((USB_RUN_IN_PEI || (!USB_PRECONDITION_POLICY_SUPPORT (UsbConfig))) || + ((USB_RUN_IN_DXE) && ((UsbConfig->Usb20Settings[PchEhci1].Enable == PCH_DEVICE_ENABLE) || + ((UsbConfig->Usb20Settings[PchEhci2].Enable == PCH_DEVICE_ENABLE) && (PchSeries == PchH))))) + { +#endif // USB_PRECONDITION_ENABLE_FLAG + + // + // Set EHCI AFE USB2 PER PORT register + // IOBP registers 0xE5004000 + ((PortNumber+1) * 0x100) + // + for (Index = 0; Index < GetPchUsbMaxPhysicalPortNum (); Index++) { + Data32And = (UINT32)~(0x00007F00); + Data32Or = (UINT32) (0x00000000); // BIT[14] (PERPORTTXPEHALF) = 0 + ASSERT (UsbConfig->PortSettings[Index].Usb20EyeDiagramTuningParam2 < 8); + Data32Or |= (UsbConfig->PortSettings[Index].Usb20EyeDiagramTuningParam2 & 0x07) << 11; // BIT[13:11] (PERPORTPETXISET) = Usb20EyeDiagramTuningParam2 + ASSERT (UsbConfig->PortSettings[Index].Usb20EyeDiagramTuningParam1 < 8); + Data32Or |= (UsbConfig->PortSettings[Index].Usb20EyeDiagramTuningParam1 & 0x07) << 8; // BIT[10:08] (PERPORTTXISET) = Usb20EyeDiagramTuningParam1 + Status = ProgramIobp ( + RootComplexBar, + 0xE5004000 + ((Index + 1) * 0x100), + Data32And, + Data32Or + ); + ASSERT_EFI_ERROR (Status); + Status = PCH_INIT_COMMON_SCRIPT_SAVE_IOBP_S3_ITEM ( + RootComplexBar, + 0xE5004000 + ((Index + 1) * 0x100), + Data32And, + Data32Or + ); + ASSERT_EFI_ERROR (Status); + } +#ifdef USB_PRECONDITION_ENABLE_FLAG + } +#endif // USB_PRECONDITION_ENABLE_FLAG +} + +VOID +ConfigureUsbClockGating ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar +) +{ + ConfigureEhciClockGating(PchPlatformPolicy,RootComplexBar); + ConfigureXhciClockGating(PchPlatformPolicy,RootComplexBar); +} + +VOID +ConfigureEhciClockGating ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar +) +{ + UINTN EhciPciMmBase; + UINT8 Index; + UINT32 Data32And; + UINT32 Data32Or; + EFI_STATUS Status; + PCH_SERIES PchSeries; + PchSeries = GetPchSeries(); + // + // Enable EHCI Clock Gating + // + + /// + /// If LPT-LP when EHCI disabled, Set RCBA + Offset 3A84[2,0] = 1b, 1b + /// + if (PchSeries == PchLp) { + if (PchPlatformPolicy->UsbConfig->Usb20Settings[PchEhci1].Enable == PCH_DEVICE_DISABLE) { + MmioOr32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A84), + (UINT32) (BIT2 | BIT0) + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A84), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A84) + ); + } + } + + /// + /// Set IOBP register 0xE5004001[7:6] to 11b. + /// + Data32And = (UINT32)~(0); + Data32Or = (UINT32) (BIT7 | BIT6); + Status = ProgramIobp ( + RootComplexBar, + 0xE5004001, + Data32And, + Data32Or + ); + ASSERT_EFI_ERROR (Status); + Status = PCH_INIT_COMMON_SCRIPT_SAVE_IOBP_S3_ITEM ( + RootComplexBar, + 0xE5004001, + Data32And, + Data32Or + ); + /// + /// For each EHCI's PCI Config space registers + /// + for (Index = 0; Index < GetPchEhciMaxControllerNum (); Index++) { + EhciPciMmBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + EhciControllersMap[Index].Device, + EhciControllersMap[Index].Function, + 0 + ); + /// + /// Set D29/D26:F0 + DCh[5,2,1] to 1b + /// Set D29/D26:F0 + DCh[0] to 1b when EHCI controller is disable + /// + Data32Or = (UINT32) (BIT5 | BIT2 | BIT1); + if (PchPlatformPolicy->UsbConfig->Usb20Settings[Index].Enable == PCH_DEVICE_DISABLE) { + Data32Or |= (UINT32) (BIT0); + } + MmioOr32 (EhciPciMmBase + 0xDC, Data32Or); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (EhciPciMmBase + 0xDC), + 1, + (VOID *) (UINTN) (EhciPciMmBase + 0xDC) + ); + /// + /// Set D29/D26:F0 + 78h[1:0] to 11b + /// + Data32Or = (UINT32) (BIT1 | BIT0); + MmioOr32 (EhciPciMmBase + 0x78, Data32Or); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (EhciPciMmBase + 0x78), + 1, + (VOID *) (UINTN) (EhciPciMmBase + 0x78) + ); + ASSERT_EFI_ERROR (Status); + } +} + diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchUsbCommon.h b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchUsbCommon.h new file mode 100644 index 0000000..a4b3a32 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchUsbCommon.h @@ -0,0 +1,360 @@ +/** @file + + Header file for the PCH USB Common Driver. + +@copyright + Copyright (c) 2009 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#ifndef _USB_COMMON_H_ +#define _USB_COMMON_H_ + +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "EdkIIGlueBase.h" +#include "PchAccess.h" +#include "PchPlatformLib.h" +#include "PchInitCommon.h" +#endif + +#define USB_PR_CASE_0 0 +#define USB_PR_CASE_1 1 +#define USB_PR_CASE_2 2 +#define TEN_MS_TIMEOUT 10000 +#define PORT_RESET_TIMEOUT 10 ///< 100 ms timeout for xHCI port reset + +typedef struct { + UINT8 Device; + UINT8 Function; +} USB_CONTROLLER; + +/** + Configures PCH USB controller + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] EhciMmioBase Memory base address of EHCI Controller + @param[in] XhciMmioBase Memory base address of XHCI Controller + @param[in] BusNumber PCI Bus Number of the PCH device + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[out] FuncDisableReg Function Disable Register + @param[in] Revision The policy revision used for backward compatible check + + @retval EFI_INVALID_PARAMETER The parameter of PchPlatformPolicy is invalid + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +EFIAPI +CommonUsbInit ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINT32 EhciMmioBase, + IN UINT32 XhciMmioBase, + IN UINT8 BusNumber, + IN UINT32 RootComplexBar, + OUT UINT32 *FuncDisableReg, + IN UINT8 Revision + ); + +/** + Performs basic configuration of PCH EHCI controller. + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] EhciMmioBase Memory base address of EHCI Controller + @param[in] BusNumber PCI Bus Number of the PCH device + @param[in] Revision The policy revision used for backward compatible check + @param[in] LpcDeviceId The device ID of LPC + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +EFIAPI +CommonEhciHcsInit ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINT32 EhciMmioBase, + IN UINT8 BusNumber, + IN UINT8 Revision, + IN UINT16 LpcDeviceId, + IN UINT32 RootComplexBar + ); + +/** + Performs basic configuration of PCH USB3 (xHCI) controller. + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] XhciMmioBase Memory base address of xHCI Controller + @param[in] Revision The policy revision used for backward compatible check + @param[in] LpcDeviceId The device ID of LPC + @param[in] XhciPciMmBase XHCI PCI Base Address + + @retval None +**/ +VOID +CommonXhciHcInit ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINT32 XhciMmioBase, + IN UINT8 Revision, + IN UINT16 LpcDeviceId, + IN UINTN XhciPciMmBase + ); + +/** + Performs basic configuration of PCH USB3 (xHCI) controller. + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] XhciMmioBase Memory base address of XHCI Controller + @param[in] Revision The policy revision used for backward compatible check + @param[in] LpcDeviceId The device ID of LPC + @param[in] XhciPciMmBase XHCI PCI Base Address + @param[in] PciD31F0RegBase LPC PCI Base Address + + @retval None +**/ +VOID +PerformXhciEhciPortSwitchingFlow ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINT32 XhciMmioBase, + IN UINT8 Revision, + IN UINT16 LpcDeviceId, + IN UINTN XhciPciMmBase, + IN UINTN PciD31F0RegBase + ); + +/** + Retrieves information about number of implemented xHCI ports + and sets appropriate port mask registers. + + @param[in] XhciPciMmBase XHCI PCI Base Address + @param[out] HsPortCount Count of High Speed Ports + @param[out] HsUsbrPortCount Count of USBr Port + @param[out] SsPortCount Count of Super Speed Ports + + @retval None +**/ +VOID +GetXhciPortCountAndSetPortRoutingMask ( + IN UINTN XhciPciMmBase, + OUT UINTN *HsPortCount, + OUT UINTN *HsUsbrPortCount, + OUT UINTN *SsPortCount + ); + +/** + Setup XHCI Over-Current Mapping + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] XhciPciMmBase XHCI PCI Base Address + + @retval None +**/ +VOID +XhciOverCurrentMapping ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINTN XhciPciMmBase + ); + +/** + Setup EHCI Over-Current Mapping + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] Ehci1PciMmBase EHCI 1 PCI Base Address + @param[in] Ehci2PciMmBase EHCI 2 PCI Base Address + + @retval None +**/ +VOID +EhciOverCurrentMapping ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINTN Ehci1PciMmBase, + IN UINTN Ehci2PciMmBase + ); + +/** + Program Ehci Port Disable Override + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] Ehci1PciMmBase EHCI 1 PCI Base Address + @param[in] Ehci2PciMmBase EHCI 2 PCI Base Address + + @retval None +**/ +VOID +EhciPortDisableOverride ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINTN Ehci1PciMmBase, + IN UINTN Ehci2PciMmBase + ); + +/** + Program Xhci Port Disable Override + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] XhciPciMmBase XHCI PCI Base Address + @param[in] Revision Platform policy revision + + @retval None +**/ +VOID +XhciPortDisableOverride ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINTN XhciPciMmBase, + IN UINT8 Revision + ); + +/** + Enable EHCI USBR device + + @param[in] EhciPciMmBase Ehci PCI Base Address + + @retval None +**/ +VOID +EhciUsbrEnable ( + IN UINTN EhciPciMmBase + ); + +/** + Program and enable XHCI Memory Space + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] XhciMmioBase Memory base address of XHCI Controller + @param[in] XhciPciMmBase XHCI PCI Base Address + + @retval None +**/ +VOID +XhciMemorySpaceOpen ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINT32 XhciMmioBase, + IN UINTN XhciPciMmBase + ); + +/** + Clear and disable XHCI Memory Space + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] XhciMmioBase Memory base address of XHCI Controller + @param[in] XhciPciMmBase XHCI PCI Base Address + + @retval None +**/ +VOID +XhciMemorySpaceClose ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINT32 XhciMmioBase, + IN UINTN XhciPciMmBase + ); + +/** + Tune the USB 2.0 high-speed signals quality. + + @param[in] UsbConfig The PCH Platform Policy for USB configuration + @param[in] LpcDeviceId The device ID of LPC + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval None +**/ +VOID +Usb2PortLengthProgramming ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINT16 LpcDeviceId, + IN UINT32 RootComplexBar + ); + +/** + Initialization USB Clock Gating registers + + @param[in] PchPlatformPolicy The PCH Platform Policy + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval None +**/ +VOID +ConfigureUsbClockGating ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ); + +/** + Initialization EHCI Clock Gating registers + + @param[in] PchPlatformPolicy The PCH Platform Policy + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval None +**/ +VOID +ConfigureEhciClockGating ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ); + +/** + Initialization XHCI Clock Gating registers + + @param[in] PchPlatformPolicy The PCH Platform Policy + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval None +**/ +VOID +ConfigureXhciClockGating ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ); + +#ifdef USB_PRECONDITION_ENABLE_FLAG +/** + Perform USB precondition on EHCI, it is the HC on USB HC in PEI phase; + it is the root port reset on installed USB device in DXE phase + + @param[in] Device The device number of the EHCI + @param[in] EhciMmioBase Memory base address of EHCI Controller + + @retval None +**/ +VOID +EhciPrecondition ( + IN UINT8 Device, + IN UINT32 EhciMmioBase + ); + +/** + Perform USB precondition on XHCI, it is the HC on USB HC in PEI phase; + it is the root port reset on installed USB device in DXE phase + + @param[in] BusNumber The Bus number of the XHCI + @param[in] Device The device number of the XHCI + @param[in] Function The function number of the XHCI + @param[in] XhciMmioBase Memory base address of XHCI Controller + @param[in] XhciUSB2Ptr Pointer to USB2 protocol port register + @param[in] HsPortCount The number of USB2 protocol port supported by this XHCI + + @retval None +**/ +VOID +XhciPrecondition ( + IN UINT8 BusNumber, + IN UINT8 Device, + IN UINT8 Function, + IN UINT32 XhciMmioBase, + IN UINTN *XhciUSB2Ptr, + IN UINTN HsPortCount, + IN UINTN *XhciUSB3Ptr, + IN UINTN SsPortCount + ); +#endif // USB_PRECONDITION_ENABLE_FLAG + +#endif diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchUsbCommonLib.cif b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchUsbCommonLib.cif new file mode 100644 index 0000000..8b9628f --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchUsbCommonLib.cif @@ -0,0 +1,21 @@ +<component> + name = "PchUsbCommonLib" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\LynxPoint\PchInit\Common" + RefName = "PchUsbCommonLib" +[files] +"PchUsbCommonLib.sdl" +"PchUsbCommonLib.mak" +"PchUsbCommon.h" +"PchUsbCommon.c" +"PchHSIO.c" +"PchHSIO.h" +"PchHSIOLptHB0.c" +"PchHSIOLptHB0.h" +"PchInitVar.c" +"PchInitVar.h" +"PchHsioLptLpBx.h" +"PchHsioLptHCx.c" +"PchHsioLptHCx.h" +"PchHsioLptLpBx.c" +<endComponent> diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchUsbCommonLib.mak b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchUsbCommonLib.mak new file mode 100644 index 0000000..6abbf99 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchUsbCommonLib.mak @@ -0,0 +1,127 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchUsbCommonLib/PchUsbCommonLib.mak 2 8/13/12 9:08a Victortu $ +# +# $Revision: 2 $ +# +# $Date: 8/13/12 9:08a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchUsbCommonLib/PchUsbCommonLib.mak $ +# +# 2 8/13/12 9:08a Victortu +# +# 1 2/08/12 9:29a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* +all : PchUsbCommonLib + +!IF "$(PchInitPeim_SUPPORT)" == "1" +PchUsbCommonLib : PchUsbCommonPeiLib +!ENDIF + +!IF "$(PchInitDxe_SUPPORT)" == "1" +PchUsbCommonLib : PchUsbCommonDxeLib +!ENDIF + +!IF "$(PchInitPeim_SUPPORT)" == "1" +!IF "$(PchInitDxe_SUPPORT)" == "1" +PchUsbCommonLib : PchUsbCommonDxeLib PchUsbCommonPeiLib +!ENDIF +!ENDIF + +!IF "$(PchInitDxe_SUPPORT)" == "1" +$(PchUsbCommonDxeLib_LIB) : PchUsbCommonDxeLib +!ENDIF + +!IF "$(PchInitPeim_SUPPORT)" == "1" +$(PchUsbCommonPeiLib_LIB) : PchUsbCommonPeiLib +!ENDIF + +PchUsbCommonDxeLib : $(BUILD_DIR)\PchUsbCommonLib.mak PchUsbCommonLibDxeBin + +PchUsbCommonPeiLib : $(BUILD_DIR)\PchUsbCommonLib.mak PchUsbCommonLibPeiBin + +$(BUILD_DIR)\PchUsbCommonLib.mak : $(PchUsbCommonLib_DIR)\$(@B).cif $(PchUsbCommonLib_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(PchUsbCommonLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +PchUsbCommonLib_INCLUDES=\ + $(EDK_INCLUDES)\ + $(EdkIIGlueLib_INCLUDES)\ + $(INTEL_PCH_INCLUDES)\ + /I$(INTEL_PCH_DIR)\Protocol\PchInfo\ + +PchUsbCommonLibDxe_INCLUDES=\ + $(PchUsbCommonLib_INCLUDES) $(PCH_INITDXE_INCLUDES) + +PchUsbCommonLibPeim_INCLUDES=\ + $(PchUsbCommonLib_INCLUDES) $(PCH_INITPEI_INCLUDES) + +PchUsbCommonLib_DEFINES = \ + $(CFLAGS) + +DxeCpuBuildDefine = \ +!IF "$(x64_BUILD)"=="1" + /DMDE_CPU_X64\ +!ELSE + /DMDE_CPU_IA32\ +!ENDIF + +PeimCpuBuildDefine = \ + /DMDE_CPU_IA32\ + +PchUsbCommonLibPeim_DEFINES = \ + $(PchUsbCommonLib_DEFINES)\ + $(PeimCpuBuildDefine)\ + +PchUsbCommonLibDxe_DEFINES = \ + $(PchUsbCommonLib_DEFINES)\ + $(DxeCpuBuildDefine)\ + +PchUsbCommonLibDxeBin : + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS) \ + /f $(BUILD_DIR)\PchUsbCommonLib.mak all\ + "MY_INCLUDES=$(PchUsbCommonLibDxe_INCLUDES)" \ + "CFLAGS=$(PchUsbCommonLibDxe_DEFINES)"\ + TYPE=LIBRARY \ + LIBRARY_NAME=$(PchUsbCommonDxeLib_LIB) + +PchUsbCommonLibPeiBin : $(EFISCRIPTLIB) $(EDKFRAMEWORKPROTOCOLLIB) +!IF "$(x64_BUILD)"=="1" + $(MAKE) /$(MAKEFLAGS) $(EDK_DEFAULTS) BUILD_DIR=$(BUILD_DIR)\IA32 \ +!ELSE + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS) \ +!ENDIF + /f $(BUILD_DIR)\PchUsbCommonLib.mak all\ + "MY_INCLUDES=$(PchUsbCommonLibPeim_INCLUDES)" \ + "CFLAGS=$(PchUsbCommonLibPeim_DEFINES)"\ + TYPE=PEI_LIBRARY \ + LIBRARY_NAME=$(PchUsbCommonPeiLib_LIB) +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchUsbCommonLib.sdl b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchUsbCommonLib.sdl new file mode 100644 index 0000000..6d78a0b --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Common/PchUsbCommonLib.sdl @@ -0,0 +1,81 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchUsbCommonLib/PchUsbCommonLib.sdl 1 2/08/12 9:29a Yurenlai $ +# +# $Revision: 1 $ +# +# $Date: 2/08/12 9:29a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchUsbCommonLib/PchUsbCommonLib.sdl $ +# +# 1 2/08/12 9:29a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* +TOKEN + Name = "PchUsbCommonLib_SUPPORT" + Value = "1" + Help = "Main switch to enable PchUsbCommonLib support in Project" + TokenType = Boolean + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "PchUsbCommonLib_DIR" +End + +MODULE + Help = "Includes PchUsbCommonLib.mak to Project" + File = "PchUsbCommonLib.mak" +End + +ELINK + Name = "PchUsbCommonDxeLib_LIB" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "$$(LIB_BUILD_DIR)\PchUsbCommonDxeLib.lib" + Parent = "PchUsbCommonDxeLib_LIB" + InvokeOrder = AfterParent +End + +ELINK + Name = "PchUsbCommonPeiLib_LIB" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "$$(LIB_BUILD_DIR)\PchUsbCommonPeiLib.lib" + Parent = "PchUsbCommonPeiLib_LIB" + InvokeOrder = AfterParent +End +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchAudioDsp.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchAudioDsp.c new file mode 100644 index 0000000..0045460 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchAudioDsp.c @@ -0,0 +1,602 @@ +/** @file + Configures Audio DSP device + +@copyright + Copyright (c) 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#include "PchInit.h" + +#ifdef ADSP_FLAG +#include "PchAslUpdateLib.h" + +// +// AUDIO DSP Memory space definitions +// +#define V_PCH_ADSP_MEM_BASE_ADDRESS 0xFE000000 +#define S_PCH_ADSP_ADBAR_LENGTH 0x100000 +#define S_PCH_ADSP_SPCBAR_LENGTH 0x1000 +#define N_PCH_ADSP_ADBAR_ALIGN 16 +#define N_PCH_ADSP_SPCBAR_ALIGN 12 + +/** + Configure AudioDSP SSP lines ownership + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + + @retval EFI_SUCCESS ADSP owns all I/O Buffers +**/ +EFI_STATUS +ConfigureAudioDspSsp( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy + ) +{ + UINTN PciAzaliaRegBase; + + /// + /// Retrieve Azalia PCI Config base + /// + PciAzaliaRegBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_AZALIA, + PCI_FUNCTION_NUMBER_PCH_AZALIA, + 0 + ); + + DEBUG ((EFI_D_INFO, "Audio DSP: Switch HDA pins to ADSP\n")); + + /// + /// BIOS is required to set Ownership select of I/O Buffer to Audio DSP. + /// Set D27:F0:42h[7:6] = 11b - Audio DSP subsystem owns all the I/O buffers. + /// + MmioOr8 ((UINTN)(PciAzaliaRegBase + R_PCH_HDA_AZIOBC), (UINT8)B_PCH_HDA_AZIOBC_OSEL); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciAzaliaRegBase + R_PCH_HDA_AZIOBC), + 1, + (VOID *) (UINTN) (PciAzaliaRegBase + R_PCH_HDA_AZIOBC) + ); + + PchPlatformPolicy->DeviceEnabling->Azalia = PCH_DEVICE_DISABLE; + + return EFI_SUCCESS; +} + +/** + Allocates static memory pool for Audio DSP BAR and Shadowed PCI Configuration Space. + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_ERROR Error occured on initialization +**/ +EFI_STATUS +AllocateAudioDspBar ( +) +{ + EFI_PHYSICAL_ADDRESS AdspMemBaseAddress; + EFI_PHYSICAL_ADDRESS AdspBar; + EFI_PHYSICAL_ADDRESS AdspShadowedPciBar; + UINT32 PciAdspRegBase; + EFI_STATUS Status; + + DEBUG ((EFI_D_INFO, "Audio DSP: Allocate fixed memory space\n")); + + AdspMemBaseAddress = V_PCH_ADSP_MEM_BASE_ADDRESS; + + Status = gDS->AddMemorySpace ( + EfiGcdMemoryTypeReserved, + AdspMemBaseAddress, + S_PCH_ADSP_ADBAR_LENGTH + S_PCH_ADSP_SPCBAR_LENGTH, + 0 + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR(Status)) { + return Status; + } + + AdspBar = AdspMemBaseAddress; + + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateAddress, + EfiGcdMemoryTypeReserved, + N_PCH_ADSP_ADBAR_ALIGN, + S_PCH_ADSP_ADBAR_LENGTH, + &AdspBar, + mImageHandle, + NULL + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR(Status)) { + return Status; + } + ASSERT(AdspBar == V_PCH_ADSP_MEM_BASE_ADDRESS); + + AdspShadowedPciBar = AdspMemBaseAddress + S_PCH_ADSP_ADBAR_LENGTH; + + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateAddress, + EfiGcdMemoryTypeReserved, + N_PCH_ADSP_SPCBAR_ALIGN, + S_PCH_ADSP_SPCBAR_LENGTH, + &AdspShadowedPciBar, + mImageHandle, + NULL + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR(Status)) { + return Status; + } + ASSERT(AdspShadowedPciBar == V_PCH_ADSP_MEM_BASE_ADDRESS + S_PCH_ADSP_ADBAR_LENGTH); + + PciAdspRegBase = MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PCH_ADSP, PCI_FUNCTION_NUMBER_PCH_ADSP, 0); + + DEBUG ((EFI_D_INFO, "Audio DSP: Base Address (ADBA) = 0x%04x; Length = 0x%x\n", AdspBar, S_PCH_ADSP_ADBAR_LENGTH)); + + MmioWrite32 ((UINTN)(PciAdspRegBase + R_PCH_ADSP_ADBA), (UINT32)AdspBar); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciAdspRegBase + R_PCH_ADSP_ADBA), + 1, + (VOID *)(UINTN) (PciAdspRegBase + R_PCH_ADSP_ADBA) + ); + + DEBUG ((EFI_D_INFO, "Audio DSP: Shadowed PCI Configuration Base Address (SPCBA) = 0x%04x; Length = 0x%x\n", AdspShadowedPciBar, S_PCH_ADSP_SPCBAR_LENGTH)); + + MmioWrite32 ((UINTN)(PciAdspRegBase + R_PCH_ADSP_SPCBA), (UINT32)AdspShadowedPciBar); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciAdspRegBase + R_PCH_ADSP_SPCBA), + 1, + (VOID *)(UINTN) (PciAdspRegBase + R_PCH_ADSP_SPCBA) + ); + + /// + /// Enable memory space access + /// Program D19:F0:04h[2:1] = 11b + /// + MmioOr32 ((UINTN)(PciAdspRegBase + R_PCH_ADSP_COMMAND), (B_PCH_ADSP_COMMAND_BME | B_PCH_ADSP_COMMAND_MSE)); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciAdspRegBase + R_PCH_ADSP_COMMAND), + 1, + (VOID *) (UINTN) (PciAdspRegBase + R_PCH_ADSP_COMMAND) + ); + + return Status; +} + +/** + Disables/hides or enables/unhides Audio DSP PCI Configuration Space + + @param[in] PciConfigurationDisable If TRUE, PCI Config Space will be disabled. + If FALSE, PCI Config Space will be enabled. + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_DEVICE_ERROR Transaction fail +**/ +EFI_STATUS +DisableAudioDspPciConfigSpace( + IN BOOLEAN PciConfigurationDisable, + IN UINT32 RootComplexBar + ) +{ + UINT32 Data32Or; + EFI_STATUS Status; + + if (PciConfigurationDisable) { + DEBUG ((EFI_D_INFO, "Audio DSP: Hiding PCI Config Space\n")); + Data32Or = B_PCH_ADSP_PCICFGCTL_PCICD; + } else { + DEBUG ((EFI_D_INFO, "Audio DSP: Unhiding PCI Config Space\n")); + Data32Or = 0; + } + + Status = ProgramIobp ( + RootComplexBar, + (UINT32) (R_PCH_RCRB_IOBPIRI_IOBPIS_ADSP + R_PCH_ADSP_PCICFGCTL), + (UINT32)~(B_PCH_ADSP_PCICFGCTL_PCICD), + (UINT32) Data32Or + ); + ASSERT_EFI_ERROR (Status); + Status = PCH_INIT_COMMON_SCRIPT_SAVE_IOBP_S3_ITEM ( + RootComplexBar, + (UINT32) (R_PCH_RCRB_IOBPIRI_IOBPIS_ADSP + R_PCH_ADSP_PCICFGCTL), + (UINT32)~(B_PCH_ADSP_PCICFGCTL_PCICD), + (UINT32) Data32Or + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Finalize Audio DSP initialization after PCI enumeration. + In particular configure ADSP in ACPI or PCI mode: + ACPI - patches ACPI table, sets ACPI IRQ and hides PCI config space. + PCI - sets PCI IRQ, does not hide PCI config space. + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_UNSUPPORTED Audio DSP not found or not enabled +**/ +EFI_STATUS +ConfigureAudioDspBeforeBoot( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ) +{ + UINT8 Data8; + UINT32 Data32; + UINT32 PciAdspRegBase; + UINT16 AdspDeviceId; + EFI_STATUS Status; + EFI_STATUS AcpiTablePresent; + + Status = EFI_SUCCESS; + AcpiTablePresent = EFI_NOT_FOUND; + + DEBUG ((EFI_D_INFO, "ConfigureAudioDspBeforeBoot() Start\n")); + + if (PchPlatformPolicy->DeviceEnabling->AudioDsp == PCH_DEVICE_ENABLE) { + + PciAdspRegBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_ADSP, + PCI_FUNCTION_NUMBER_PCH_ADSP, + 0 + ); + + // Unhide ADSP PCI Config Space to do the final initialization + Status = DisableAudioDspPciConfigSpace (FALSE, RootComplexBar); + + AdspDeviceId = MmioRead16 (PciAdspRegBase + R_PCH_LPTLP_ADSP_DEVICE_ID); + + if (AdspDeviceId == V_PCH_LPTLP_ADSP_DEVICE_ID) { + + if (PchPlatformPolicy->AudioDspConfig->AudioDspAcpiMode) { + // + // Locate ACPI table + // + AcpiTablePresent = InitializePchAslUpdateLib(); + + /// + /// Assign DSP BARs for ACPI use + /// + if(!EFI_ERROR(AcpiTablePresent)) { + DEBUG ((EFI_D_INFO, "Audio DSP: Updating ACPI tables\n")); + Data32 = (MmioRead32(PciAdspRegBase + R_PCH_ADSP_ADBA) & MMIO_ADDR_MASK); + UpdateResourceTemplateAslCode((EFI_SIGNATURE_32 ('A', 'D', 'S', 'P')), + (EFI_SIGNATURE_32 ('R', 'B', 'U', 'F')), + AML_MEMORY32_FIXED_OP, + 1, + 0x04, + &Data32, + sizeof(Data32) + ); + + Data32 = (MmioRead32(PciAdspRegBase + R_PCH_ADSP_SPCBA) & MMIO_ADDR_MASK); + UpdateResourceTemplateAslCode((EFI_SIGNATURE_32 ('A', 'D', 'S', 'P')), + (EFI_SIGNATURE_32 ('R', 'B', 'U', 'F')), + AML_MEMORY32_FIXED_OP, + 2, + 0x04, + &Data32, + sizeof(Data32) + ); + + if (PchPlatformPolicy->AudioDspConfig->AudioDspBluetoothSupport) { + DEBUG ((EFI_D_INFO, "Audio DSP: Bluetooth support enabled\n")); + Data8 = PCH_DEVICE_ENABLE; + UpdateNameAslCode(EFI_SIGNATURE_32('A','B','T','H'), &Data8, sizeof(Data8)); + } + + if (PchPlatformPolicy->AudioDspConfig->AudioDspAcpiInterruptMode == PCH_DEVICE_DISABLE) { + Data8 = 23; // PCI IRQ 23 + UpdateResourceTemplateAslCode((EFI_SIGNATURE_32 ('A', 'D', 'S', 'P')), + (EFI_SIGNATURE_32 ('R', 'B', 'U', 'F')), + AML_INTERRUPT_DESC_OP, + 1, + 0x05, + &Data8, + sizeof(Data8) + ); + } + } + } + + if (PchPlatformPolicy->AudioDspConfig->AudioDspAcpiInterruptMode) { + DEBUG ((EFI_D_INFO, "Audio DSP: ACPI Interrupt mode\n")); + + /// + /// Set Interrupt De-assert/Assert Opcode Override to IRQ3 + /// + Data32 = V_PCH_ADSP_VDLDAT2_IRQ3; + Status = ProgramIobp ( + RootComplexBar, + (UINT32) (R_PCH_RCRB_IOBPIRI_IOBPIS_ADSP + R_PCH_ADSP_VDLDAT2), + (UINT32)~(V_PCH_ADSP_VDLDAT2_MASK), + (UINT32) (Data32) + ); + ASSERT_EFI_ERROR (Status); + Status = PCH_INIT_COMMON_SCRIPT_SAVE_IOBP_S3_ITEM ( + RootComplexBar, + (UINT32) (R_PCH_RCRB_IOBPIRI_IOBPIS_ADSP + R_PCH_ADSP_VDLDAT2), + (UINT32)~(V_PCH_ADSP_VDLDAT2_MASK), + (UINT32) (Data32) + ); + ASSERT_EFI_ERROR (Status); + + // Enable IRQ3 in RCRB + MmioOr32 ((UINTN)(RootComplexBar + R_PCH_RCRB_INT_ACPIIRQEN), B_PCH_RCRB_INT_ACPIIRQEN_A3E); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_INT_ACPIIRQEN), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_INT_ACPIIRQEN) + ); + + // Set ACPI Interrupt Enable bit + Data32 = B_PCH_ADSP_PCICFGCTL_ACPIIE; + + } else { + DEBUG ((EFI_D_INFO, "Audio DSP: PCI Interrupt mode\n")); + + /// Program D19:F0:3Ch = 23 - INTLN (Interrupt Line) to IRQ23 + DEBUG ((EFI_D_INFO, "Audio DSP: Set INTLN to IRQ23\n")); + MmioWrite32 ((UINTN)(PciAdspRegBase + 0x3C), (UINT32)(0x17)); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciAdspRegBase + 0x3C), + 1, + (VOID *)(UINTN) (PciAdspRegBase + 0x3C) + ); + + // Do not set ACPI Interrupt Enable bit + Data32 = 0; + } + + /// + /// Configure ADSP in ACPI or PCI interrupt mode + /// Update ACPI Interrupt Enable (bit 1) in PCICFGCTL (offset 0x500) accordingly + /// + Status = ProgramIobp ( + RootComplexBar, + (UINT32) (R_PCH_RCRB_IOBPIRI_IOBPIS_ADSP + R_PCH_ADSP_PCICFGCTL), + (UINT32)~(B_PCH_ADSP_PCICFGCTL_ACPIIE | B_PCH_ADSP_PCICFGCTL_SPCBAD), + (UINT32) (Data32) + ); + ASSERT_EFI_ERROR (Status); + Status = PCH_INIT_COMMON_SCRIPT_SAVE_IOBP_S3_ITEM ( + RootComplexBar, + (UINT32) (R_PCH_RCRB_IOBPIRI_IOBPIS_ADSP + R_PCH_ADSP_PCICFGCTL), + (UINT32)~(B_PCH_ADSP_PCICFGCTL_ACPIIE | B_PCH_ADSP_PCICFGCTL_SPCBAD), + (UINT32) (Data32) + ); + + if (PchPlatformPolicy->AudioDspConfig->AudioDspAcpiMode) { + /// + /// Configure ADSP in ACPI mode + /// Set PCI Configuration Disable (bit 0) in PCICFGCTL (offset 0x500) + /// + DEBUG ((EFI_D_INFO, "Audio DSP: ACPI mode\n")); + Status = DisableAudioDspPciConfigSpace(TRUE, RootComplexBar); + } + } + } + + DEBUG ((EFI_D_INFO, "ConfigureAudioDspBeforeBoot() End\n")); + + return Status; +} + +/** + Initialize Audio DSP subsystem + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in, out] FuncDisableReg The value of Function disable register + + @retval EFI_SUCCESS Codec is detected and initialized + @retval EFI_UNSUPPORTED Audio DSP disabled + @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to initialize the codec +**/ +EFI_STATUS +ConfigureAudioDsp ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar, + IN OUT UINT32 *FuncDisableReg + ) +{ + UINT32 Data32; + UINT32 PciAdspRegBase; + UINT32 AdspBar; + UINT16 AdspDeviceId; + EFI_STATUS Status; + + DEBUG ((EFI_D_INFO, "ConfigureAudioDsp() Start\n")); + + if (PchPlatformPolicy->DeviceEnabling->AudioDsp == PCH_DEVICE_ENABLE) { + + PciAdspRegBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_ADSP, + PCI_FUNCTION_NUMBER_PCH_ADSP, + 0 + ); + + AdspDeviceId = MmioRead16 (PciAdspRegBase + R_PCH_LPTLP_ADSP_DEVICE_ID); + + if (AdspDeviceId == V_PCH_LPTLP_ADSP_DEVICE_ID) { + DEBUG ((EFI_D_INFO, "Audio DSP: Found and Enabled\n")); + + Status = AllocateAudioDspBar(); + if (EFI_ERROR(Status)) { + return Status; + } + + AdspBar = MmioRead32 (PciAdspRegBase + R_PCH_ADSP_ADBA); + + /// + /// Set LTR value in DSP Shim LTR Control register to 3ms + /// SNOOP_REQ[13] = 1b, SNOOP_SCALE[12:10] = 100b (1ms), SNOOP_VAL[9:0] = 3h + /// + MmioWrite32 ((UINTN)(AdspBar + (R_PCH_ADSP_SHIM_BASE + R_PCH_ADSP_SHIM_LTRC)), (UINT32)V_PCH_ADSP_SHIM_LTRC); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (AdspBar + (R_PCH_ADSP_SHIM_BASE + R_PCH_ADSP_SHIM_LTRC)), + 1, + (VOID *)(UINTN) (AdspBar + (R_PCH_ADSP_SHIM_BASE + R_PCH_ADSP_SHIM_LTRC)) + ); + + /// + /// Program VDRTCTL2 D19:F0:A8h[31:0] = FFFh + /// + MmioWrite32 (PciAdspRegBase + R_PCH_ADSP_VDRTCTL2, (UINT32)V_PCH_ADSP_VDRTCTL2); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciAdspRegBase + R_PCH_ADSP_VDRTCTL2), + 1, + (VOID *)(UINTN) (PciAdspRegBase + R_PCH_ADSP_VDRTCTL2) + ); + + /// + /// Set DSP IOBP register VDLDAT1 (0x624) to 0x040100 + /// + Status = ProgramIobp ( + RootComplexBar, + (UINT32) (R_PCH_RCRB_IOBPIRI_IOBPIS_ADSP + R_PCH_ADSP_VDLDAT1), + (UINT32)~(V_PCH_ADSP_VDLDAT1_CCO), + (UINT32) (V_PCH_ADSP_VDLDAT1_CCO) + ); + ASSERT_EFI_ERROR (Status); + Status = PCH_INIT_COMMON_SCRIPT_SAVE_IOBP_S3_ITEM ( + RootComplexBar, + (UINT32) (R_PCH_RCRB_IOBPIRI_IOBPIS_ADSP + R_PCH_ADSP_VDLDAT1), + (UINT32)~(V_PCH_ADSP_VDLDAT1_CCO), + (UINT32) (V_PCH_ADSP_VDLDAT1_CCO) + ); + ASSERT_EFI_ERROR (Status); + + /// + /// Set D3 Power Gating Enable + /// Program D19:F0:A0h[2:1] = 00b + /// + Data32 = MmioRead32 (PciAdspRegBase + R_PCH_ADSP_VDRTCTL0); + if (PchPlatformPolicy->AudioDspConfig->AudioDspD3PowerGating) { + DEBUG ((EFI_D_INFO, "Audio DSP: D3 Power Gating Enabled\n")); + Data32 &= ~(B_PCH_ADSP_VDRTCTL0_D3PGD | B_PCH_ADSP_VDRTCTL0_D3SRAMPGD); + } else { + DEBUG ((EFI_D_INFO, "Audio DSP: D3 Power Gating Disabled\n")); + Data32 |= B_PCH_ADSP_VDRTCTL0_D3PGD | B_PCH_ADSP_VDRTCTL0_D3SRAMPGD; + } + + MmioWrite32 ((UINTN)(PciAdspRegBase + R_PCH_ADSP_VDRTCTL0), Data32); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciAdspRegBase + R_PCH_ADSP_VDRTCTL0), + 1, + &Data32 + ); + + /// + /// Set PSF Snoop to SA + /// Program RCBA + 0x3350[10] = 1b + /// + MmioOr32 ((UINTN)(RootComplexBar + R_PCH_RCRB_CIR3350), (UINT32) BIT10); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3350), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3350) + ); + + /// + /// Switch I/O Buffers ownership to ADSP + /// + ConfigureAudioDspSsp (PchPlatformPolicy); + + /// + /// Disable ADSP PCI Configuration Space in order + /// to avoid Base Adresses override on PCI enumeration + /// + DisableAudioDspPciConfigSpace (TRUE, RootComplexBar); + + } + + Status = EFI_SUCCESS; + } + else { + DEBUG ((EFI_D_INFO, "Audio DSP: Disabled\n")); + /// + /// Set RCBA + 2B1Ch[29] = 1b + /// + MmioOr32 ((UINTN)(RootComplexBar + 0x2B1C), (UINT32)BIT29); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x2B1C), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x2B1C) + ); + + /// + /// Set Audio DSP function disable by programming RCBA + 3418h[1] = 1b + /// + *FuncDisableReg |= B_PCH_RCRB_FUNC_DIS_ADSP; + Status = EFI_SUCCESS; + } + + /// + /// Set DSP IOBP register PMCTL (0x1E0) to 0x3F + /// This should be set for both: ADSP enabled and disabled + /// + Status = ProgramIobp ( + RootComplexBar, + (UINT32) (R_PCH_RCRB_IOBPIRI_IOBPIS_ADSP + R_PCH_ADSP_PMCTL), + (UINT32)~(V_PCH_ADSP_PMCTL), + (UINT32) (V_PCH_ADSP_PMCTL) + ); + ASSERT_EFI_ERROR (Status); + Status = PCH_INIT_COMMON_SCRIPT_SAVE_IOBP_S3_ITEM ( + RootComplexBar, + (UINT32) (R_PCH_RCRB_IOBPIRI_IOBPIS_ADSP + R_PCH_ADSP_PMCTL), + (UINT32)~(V_PCH_ADSP_PMCTL), + (UINT32) (V_PCH_ADSP_PMCTL) + ); + ASSERT_EFI_ERROR (Status); + + DEBUG ((EFI_D_INFO, "ConfigureAudioDsp() End\n")); + + return Status; +} + +#endif // ADSP_FLAG diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchAzalia.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchAzalia.c new file mode 100644 index 0000000..a0c7535 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchAzalia.c @@ -0,0 +1,915 @@ +/** @file + Initializes the PCH Azalia codec. + +@copyright + Copyright (c) 1999 - 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#include "PchInit.h" + +/** + Polling the Status bit + + @param[in] StatusReg The regsiter address to read the status + @param[in] PollingBitMap The bit mapping for polling + @param[in] PollingData The Data for polling + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_TIMEOUT Polling the bit map time out +**/ +EFI_STATUS +StatusPolling ( + IN UINT32 StatusReg, + IN UINT16 PollingBitMap, + IN UINT16 PollingData + ) +{ + UINT32 LoopTime; + + for (LoopTime = 0; LoopTime < AZALIA_MAX_LOOP_TIME; LoopTime++) { + if ((MmioRead16 (StatusReg) & PollingBitMap) == PollingData) { + break; + } else { + PchPmTimerStall (AZALIA_WAIT_PERIOD); + } + } + + if (LoopTime >= AZALIA_MAX_LOOP_TIME) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + Send the command to the codec via the Immediate Command mechanism is written + to the IC register + + @param[in] HdaBar Base address of Intel HD Audio memory mapped configuration registers + @param[in, out] CodecCommandData The Codec Command to be sent to the codec + @param[in] ReadBack Whether to get the response received from the codec + + @retval EFI_DEVICE_ERROR Device status error, operation failed + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +SendCodecCommand ( + IN UINT32 HdaBar, + IN OUT UINT32 *CodecCommandData, + IN BOOLEAN ReadBack + ) +{ + EFI_STATUS Status; + + Status = StatusPolling (HdaBar + R_HDA_IRS, (UINT16) B_HDA_IRS_ICB, (UINT16) 0); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "ICB bit is not zero before SendCodecCommand! \n")); + return EFI_DEVICE_ERROR; + } + + MmioWrite32 (HdaBar + R_HDA_IC, *CodecCommandData); + MmioOr16 ((UINTN) (HdaBar + R_HDA_IRS), (UINT16) ((B_HDA_IRS_IRV | B_HDA_IRS_ICB))); + + Status = StatusPolling (HdaBar + R_HDA_IRS, (UINT16) B_HDA_IRS_ICB, (UINT16) 0); + if (EFI_ERROR (Status)) { + MmioAnd16 ((UINTN) (HdaBar + R_HDA_IRS), (UINT16)~(B_HDA_IRS_ICB)); + return Status; + } + + if (ReadBack == TRUE) { + if ((MmioRead16 (HdaBar + R_HDA_IRS) & B_HDA_IRS_IRV) != 0) { + *CodecCommandData = MmioRead32 (HdaBar + R_HDA_IR); + } else { + DEBUG ((EFI_D_ERROR, "SendCodecCommand: ReadBack fail! \n")); + return EFI_DEVICE_ERROR; + } + } + + return EFI_SUCCESS; +} + +/** + Set a "Send Codec Command" S3 dispatch item + + @param[in] HdaBar Base address of Intel HD Audio memory mapped configuration registers + @param[in, out] CodecCommandData The Codec Command to be sent to the codec + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +SendCodecCommandS3Item ( + IN UINT32 HdaBar, + IN OUT UINT32 CodecCommandData + ) +{ + EFI_STATUS Status; +#ifdef EFI_S3_RESUME + STATIC EFI_PCH_S3_SUPPORT_PROTOCOL *PchS3Support; + STATIC EFI_PCH_S3_PARAMETER_SEND_CODEC_COMMAND S3ParameterSendCodecCommand; + STATIC EFI_PCH_S3_DISPATCH_ITEM S3DispatchItem = { + PchS3ItemTypeSendCodecCommand, + &S3ParameterSendCodecCommand + }; + EFI_PHYSICAL_ADDRESS S3DispatchEntryPoint; + + if (!PchS3Support) { + /// + /// Get the PCH S3 Support Protocol + /// + Status = gBS->LocateProtocol ( + &gEfiPchS3SupportProtocolGuid, + NULL, + (VOID **) &PchS3Support + ); + ASSERT_EFI_ERROR (Status); + + if (EFI_ERROR (Status)) { + return Status; + } + } + + S3ParameterSendCodecCommand.HdaBar = HdaBar; + S3ParameterSendCodecCommand.CodecCmdData = CodecCommandData; + Status = PchS3Support->SetDispatchItem ( + PchS3Support, + &S3DispatchItem, + &S3DispatchEntryPoint + ); + ASSERT_EFI_ERROR (Status); + + /// + /// Save the script dispatch item in the Boot Script + /// + SCRIPT_DISPATCH (EFI_ACPI_S3_RESUME_SCRIPT_TABLE, S3DispatchEntryPoint); +#else + Status = EFI_SUCCESS; +#endif + return Status; +} + +/** + Initialize the Intel High Definition Audio Codec(s) present in the system. + For each codec, a predefined codec verb table should be programmed. + The list contains 32-bit verbs to be sent to the corresponding codec. + If it is not programmed, the codec uses the default verb table, which may or may not + correspond to the platform jack information. + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar address of this PCH device + @param[in, out] AzaliaStarted Whether Azalia is successfully started + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER Provided VerbTableData is null +**/ +EFI_STATUS +DetectAndInitializeAzalia ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar, + IN OUT BOOLEAN *AzaliaStarted + ) +{ + EFI_STATUS Status; + UINT32 Index; + UINT32 VendorDeviceId; + UINT32 RevisionId; + UINT8 ByteReg; + UINTN AzaliaBase; + UINT8 AzaliaSDINo; + UINT32 HdaBar; + UINT32 *VerbTable; + UINT32 LoopTime; + PCH_AZALIA_VERB_TABLE_HEADER *VerbHeaderTable; + EFI_PHYSICAL_ADDRESS BaseAddressBarMem; + UINT8 VerbTableNum; + PCH_AZALIA_CONFIG *AzaliaConfig; + UINT32 Data32And; + UINT32 Data32Or; + UINT16 Data16And; + UINT16 Data16Or; + UINT8 Data8And; + UINT8 Data8Or; + UINT32 CodecCmdData; + UINTN PciD31F0RegBase; + UINT16 LpcDeviceId; + UINT16 Data16; + UINT16 BitMask; + UINT16 BitValue; + PCH_SERIES PchSeries; + + PchSeries = GetPchSeries(); + AzaliaConfig = PchPlatformPolicy->AzaliaConfig; + AzaliaBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_AZALIA, + PCI_FUNCTION_NUMBER_PCH_AZALIA, + 0 + ); + PciD31F0RegBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); + LpcDeviceId = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_DEVICE_ID); + + Data32And = 0xF8FFFF01; + if ((MmioRead32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CIR2030)) & (UINT32) BIT31) != 0) { + /// + /// PCH BIOS Spec Rev 0.5.0 Section 9.4.2 High Definition Audio VCi Configuration + /// For Sever + /// Step 1 + /// Configure and enable Vcp on DMI, done on PchDmiPeim.c + /// Step 2 + /// Assign a Vcp ID value of 2 to High Definition Audio VCi ID field of VCi Resource Control register + /// D27:F0:Reg 120h[26:24] = 2 + /// Step 3 + /// Map Tcp to VCP. Set bit 2 of TC/VCi Map field of High Definition Audio VCi Resource Control register + /// D27:F0:Reg 120h[7:1] + /// + Data32Or = BIT25; + Data32Or |= MmioRead32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CIR2030)) & V_PCH_RCRB_V1CTL_TVM_MASK; + MmioAndThenOr32 ( + (UINTN) (AzaliaBase + R_PCH_HDA_VCICTL), + Data32And, // Data to be ANDed + Data32Or // Data to be ORed + ); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (AzaliaBase + R_PCH_HDA_VCICTL), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + /// + /// Step 4 + /// Avoid isochronous transfers to use VC1, Clear No Snoop Enable of Device Control Register + /// D27:F0:Reg 78h[11] = 0b + /// + if (PchSeries == PchH) { + MmioAnd16 ( + (UINTN) (AzaliaBase + R_PCH_HDA_DEVC), + (UINT16) (~B_PCH_HDA_DEVC_NSNPEN) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (AzaliaBase + R_PCH_HDA_DEVC), + 1, + (VOID *) (UINTN) (AzaliaBase + R_PCH_HDA_DEVC) + ); + } + } + if ((MmioRead32 ((UINTN) (AzaliaBase + R_PCH_HDA_VCICTL)) & B_PCH_HDA_VCICTL_ID) != 0) { + /// + /// Step 5 + /// Clear the TC/VC0 Map field of VC0 Resource Control register + /// D27:F0:Reg 114h[7:1] = 0 + /// + MmioAnd32 ( + (UINTN) (AzaliaBase + R_PCH_HDA_VC0CTL), + (UINT32) (~B_PCH_HDA_VC0CTL_TCVC0_MAP) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (AzaliaBase + R_PCH_HDA_VC0CTL), + 1, + (VOID *) (UINTN) (AzaliaBase + R_PCH_HDA_VC0CTL) + ); + /// + /// Step 6 + /// For LPT-H, Set VCi Enable bit of VCi Resource Control register + /// D27:F0:Reg 120h[31] = 1 + /// For LPT-LP, Clear VCi Enable bit of VCi Resource Control register + /// D27:F0:Reg 120h[31] = 0 + /// + if (PchSeries == PchH) { + MmioOr32 ((UINTN) (AzaliaBase + R_PCH_HDA_VCICTL), (UINT32) (B_PCH_HDA_VCICTL_EN)); + } + if (PchSeries == PchLp) { + MmioAnd32 ((UINTN) (AzaliaBase + R_PCH_HDA_VCICTL), (UINT32)~(B_PCH_HDA_VCICTL_EN)); + } + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (AzaliaBase + R_PCH_HDA_VCICTL), + 1, + (VOID *) (UINTN) (AzaliaBase + R_PCH_HDA_VCICTL) + ); + } + /// + /// Firstly Initialize Azalia to be not started. + /// + *AzaliaStarted = FALSE; + + /// + /// Allocate resource for HDBAR + /// + BaseAddressBarMem = 0x0FFFFFFFF; + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateMaxAddressSearchBottomUp, + EfiGcdMemoryTypeMemoryMappedIo, + 14, + V_PCH_HDA_HDBAR_SIZE, + &BaseAddressBarMem, + mImageHandle, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + /// + /// System BIOS should ensure that the High Definition Audio HDBAR D27:F0:Reg 10-17h contains a valid address value + /// and is enabled by setting D27:F0:Reg 04h[1]. + /// + HdaBar = (UINT32) BaseAddressBarMem; + MmioWrite32 (AzaliaBase + R_PCH_HDA_HDBARL, HdaBar); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (AzaliaBase + R_PCH_HDA_HDBARL), + 1, + (VOID *) (UINTN) (AzaliaBase + R_PCH_HDA_HDBARL) + ); + + MmioWrite32 (AzaliaBase + R_PCH_HDA_HDBARU, 0); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (AzaliaBase + R_PCH_HDA_HDBARU), + 1, + (VOID *) (UINTN) (AzaliaBase + R_PCH_HDA_HDBARU) + ); + + MmioOr16 ((UINTN) (AzaliaBase + R_PCH_HDA_COMMAND), (UINT16) B_PCH_HDA_COMMAND_MSE); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (AzaliaBase + R_PCH_HDA_COMMAND), + 1, + (VOID *) (UINTN) (AzaliaBase + R_PCH_HDA_COMMAND) + ); + + /// + /// PCH BIOS Spec Rev 0.5.0 Section 9.5 + /// Additional High Definition Audio Programming Steps + /// + if(PchSeries == PchH) { + /// + /// Step 1 + /// Set D27:F0:43h[4] = 1b + /// + Data8And = (UINT8) ~0; + Data8Or = BIT4; + MmioOr8 ((UINTN) (AzaliaBase + 0x43), Data8Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (AzaliaBase + 0x43), + &Data8Or, // Data to be ORed + &Data8And // Data to be ANDed + ); + /// + /// Step 2 + /// Set D27:F0:C0h[17] = 1b + /// + Data32And = (UINT32) ~0; + Data32Or = BIT17; + MmioOr32 ((UINTN) (AzaliaBase + 0xC0), Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (AzaliaBase + 0xC0), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + } + /// + /// For LPT-LP, clear D27:F0:43h[6] = 0b + /// + if(PchSeries == PchLp) { + /// + /// Step 1 + /// Set D27:F0:43h[6] = 0b + /// + MmioAnd8 ((UINTN) (AzaliaBase + 0x43), (UINT8) (~BIT6)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (AzaliaBase + 0x43), + 1, + (VOID *) (UINTN) (AzaliaBase + 0x43) + ); + } + + /// + /// Step 3 + /// For LPT-H, Set D27:F0:C4h[14] = 1b + /// For LPT-LP, Set D27:F0:C4h[24] = 1b + /// + Data32And = (UINT32) ~0; + Data32Or = 0; + if (PchSeries == PchH) { + Data32Or |= BIT14; + } + if (PchSeries == PchLp) { + Data32Or |= BIT24; + } + MmioOr32 ((UINTN) (AzaliaBase + 0xC4), Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (AzaliaBase + 0xC4), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + + if (PchSeries == PchH) { + /// + /// Step 4 + /// Set D27:F0:D0h[31] = 0b + /// + Data32And = ~BIT31; + Data32Or = (UINT32) 0; + MmioAnd32 ((UINTN) (AzaliaBase + 0xD0), Data32And); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (AzaliaBase + 0xD0), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + } + + if (AzaliaConfig->DS == PCH_DEVICE_DISABLE) { + MmioAnd8 ((UINTN) (AzaliaBase + R_PCH_HDA_DCKSTS), (UINT8) (~B_PCH_HDA_DCKSTS_DS)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (AzaliaBase + R_PCH_HDA_DCKSTS), + 1, + (VOID *) (UINTN) (AzaliaBase + R_PCH_HDA_DCKSTS) + ); + } else if (AzaliaConfig->DA != PCH_DEVICE_DISABLE) { + if ((MmioRead8 (AzaliaBase + R_PCH_HDA_DCKSTS) & B_PCH_HDA_DCKSTS_DM) == 0) { + MmioOr8 ((UINTN) (AzaliaBase + R_PCH_HDA_DCKCTL), (UINT8) (B_PCH_HDA_DCKCTL_DA)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (AzaliaBase + R_PCH_HDA_DCKCTL), + 1, + (VOID *) (UINTN) (AzaliaBase + R_PCH_HDA_DCKCTL) + ); + } + } + + if (PchSeries == PchLp) { + /// + /// @todo: Policy check to bypass for PO + /// Set Hdabar + 0x0012h[0] to 1b + /// + Data16And = (UINT16)~BIT0; + Data16Or = (UINT16) (BIT0); + MmioOr16 ((UINTN) (HdaBar + 0x0012), Data16Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (HdaBar + 0x0012), + &Data16Or, // Data to be ORed + &Data16And // Data to be ANDed + ); + + /// + /// W/A: Azalia BCLK is not at full swing when operating in high voltage mode + /// Set D27:F0:42h[2] = 1b - disabling Auto Voltage Detector. + /// + MmioOr8 ((UINTN)(AzaliaBase + R_PCH_HDA_AZIOBC), (UINT8)B_PCH_HDA_AZIOBC_AVDDIS); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (AzaliaBase + R_PCH_HDA_AZIOBC), + 1, + (VOID *) (UINTN) (AzaliaBase + R_PCH_HDA_AZIOBC) + ); + } + /// + /// PCH BIOS Spec Rev 0.5.0 Section 9.1.3 Codec Initialization Programming Sequence + /// System BIOS should also ensure that the Controller Reset# bit of Global Control register + /// in memory-mapped space (HDBAR+08h[0]) is set to 1 and read back as 1. + /// Deassert the HDA controller RESET# to start up the link + /// + Data32And = 0xFFFFFFFF; + Data32Or = (UINT32) (B_HDA_GCTL_CRST); + MmioOr32 ((UINTN) (HdaBar + R_HDA_GCTL), Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (HdaBar + R_HDA_GCTL), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + + BitMask = (UINT16) B_HDA_GCTL_CRST; + BitValue = (UINT16) B_HDA_GCTL_CRST; + Status = StatusPolling (HdaBar + R_HDA_GCTL, BitMask, BitValue); + SCRIPT_MEM_POLL ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + HdaBar + R_HDA_GCTL, + &BitMask, + &BitValue, + AZALIA_WAIT_PERIOD, + AZALIA_MAX_LOOP_TIME + ); + /// + /// PCH BIOS Spec Rev 0.5.0 Section 9.1.3 Codec Initialization Programming Sequence + /// Read GCAP and write the same value back to the register once after Controller Reset# bit is set + /// + Data16 = MmioRead16 (HdaBar + R_HDA_GCAP); + MmioWrite16 (HdaBar + R_HDA_GCAP, Data16); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (HdaBar + R_HDA_GCAP), + 1, + (VOID *) (UINTN) (HdaBar + R_HDA_GCAP) + ); + + /// + /// Clear the "State Change Status Register" STATESTS bits for + /// each of the "SDIN Stat Change Status Flag" + /// + Data16 = AZALIA_MAX_SID_MASK_PCH_H; + if (PchSeries == PchLp) { + Data16 = AZALIA_MAX_SID_MASK_PCH_LP; + } + MmioOr8 ((UINTN) (HdaBar + R_HDA_STATESTS), (UINT8) (Data16)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (HdaBar + R_HDA_STATESTS), + 1, + (VOID *) (UINTN) (HdaBar + R_HDA_STATESTS) + ); + + /// + /// Turn off the link and poll RESET# bit until it reads back as 0 to get hardware reset report + /// + Data32And = (UINT32) (~B_HDA_GCTL_CRST); + Data32Or = (UINT32) 0; + MmioAnd32 ((UINTN) (HdaBar + R_HDA_GCTL), Data32And); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (HdaBar + R_HDA_GCTL), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + + BitMask = (UINT16) B_HDA_GCTL_CRST; + BitValue = 0; + Status = StatusPolling (HdaBar + R_HDA_GCTL, BitMask, BitValue); + SCRIPT_MEM_POLL ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + HdaBar + R_HDA_GCTL, + &BitMask, + &BitValue, + AZALIA_WAIT_PERIOD, + AZALIA_MAX_LOOP_TIME + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Reset High Definition Audio (Azalia) Codec Time Out - 1! \n")); + goto ExitInitAzalia; + } + /// + /// Turn on the link and poll RESET# bit until it reads back as 1 + /// + Data32And = 0xFFFFFFFF; + Data32Or = (UINT32) (B_HDA_GCTL_CRST); + MmioOr32 ((UINTN) (HdaBar + R_HDA_GCTL), Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (HdaBar + R_HDA_GCTL), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + /// + /// For some combo card that will need this delay because each codec has different latency to come out from RESET. + /// This delay can make sure all codecs be recognized by BIOS after RESET sequence. + /// Additional delay might be required to allow codec coming out of reset prior to subsequent operations, + /// please contact your codec vendor for detail. When clearing this bit and setting it afterward, + /// BIOS must ensure that minimum link timing requirements (minimum RESET# assertion time, etc.) are met.. + /// + PchPmTimerStall (AzaliaConfig->ResetWaitTimer); + SCRIPT_STALL (EFI_ACPI_S3_RESUME_SCRIPT_TABLE, AzaliaConfig->ResetWaitTimer); + + BitMask = (UINT16) B_HDA_GCTL_CRST; + BitValue = (UINT16) B_HDA_GCTL_CRST; + Status = StatusPolling (HdaBar + R_HDA_GCTL, BitMask, BitValue); + SCRIPT_MEM_POLL ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + HdaBar + R_HDA_GCTL, + &BitMask, + &BitValue, + AZALIA_WAIT_PERIOD, + AZALIA_MAX_LOOP_TIME + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Reset High Definition Audio (Azalia) Codec Time Out - 2! \n")); + goto ExitInitAzalia; + } + /// + /// Read the "State Change Status Register" STATESTS bits twice to find out if any SDIN is connected + /// to a codec. + /// + Data16 = AZALIA_MAX_SID_MASK_PCH_H; + if (PchSeries == PchLp) { + Data16 = AZALIA_MAX_SID_MASK_PCH_LP; + } + for (LoopTime = 0, ByteReg = 0, AzaliaSDINo = 0; LoopTime < AZALIA_MAX_LOOP_TIME; LoopTime++) { + ByteReg = (UINT8)(MmioRead8 (HdaBar + R_HDA_STATESTS) & Data16); + if (ByteReg != 0 && (ByteReg == AzaliaSDINo)) { + break; + } else { + AzaliaSDINo = ByteReg; + } + + PchPmTimerStall (AZALIA_WAIT_PERIOD); + } + /// + /// BIT3(1000) -- SDI3 + /// BIT2(0100) -- SDI2 + /// BIT1(0010) -- SDI1 + /// BIT0(0001) -- SDI0 + /// + if (ByteReg == 0) { + /// + /// No Azalia Detected + /// + /// + /// Turn off the link + /// + DEBUG ((EFI_D_ERROR, "No Azalia device is detected.\n")); + Data32And = (UINT32) (~B_HDA_GCTL_CRST); + Data32Or = (UINT32) 0; + MmioAnd32 ((UINTN) (HdaBar + R_HDA_GCTL), Data32And); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (HdaBar + R_HDA_GCTL), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + Status = EFI_DEVICE_ERROR; + goto ExitInitAzalia; + } + /// + /// PME Enable for Audio controller, this bit is in the resume well + /// + if (AzaliaConfig->Pme == PCH_DEVICE_ENABLE) { + MmioOr32 ((UINTN) (AzaliaBase + R_PCH_HDA_PCS), (UINT32) (B_PCH_HDA_PCS_PMEE)); +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, all resume well registers need to be saved + /// into S3 Script table. + /// + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (AzaliaBase + R_PCH_HDA_PCS), + 1, + (VOID *) (UINTN) (AzaliaBase + R_PCH_HDA_PCS) + ); +#endif + } + + Data16 = AZALIA_MAX_SID_NUMBER_PCH_H; + if (PchSeries == PchLp) { + Data16 = AZALIA_MAX_SID_NUMBER_PCH_LP; + } + for (AzaliaSDINo = 0; AzaliaSDINo < Data16; AzaliaSDINo++, ByteReg >>= 1) { + if ((ByteReg & 0x1) == 0) { + /// + /// SDIx has no Azalia Device + /// + DEBUG ((EFI_D_ERROR, "SDI%d has no Azalia device.\n", AzaliaSDINo)); + continue; + } + /// + /// PME Enable for each existing codec, these bits are in the resume well + /// + if (AzaliaConfig->Pme != PCH_DEVICE_DISABLE) { + MmioOr16 ( + (UINTN) (HdaBar + R_HDA_WAKEEN), + (UINT16) ((B_HDA_WAKEEN_SDI_0 << AzaliaSDINo)) + ); +#ifdef SUS_WELL_RESTORE + /// + /// To support RapidStart resume from G3 state, all resume well registers need to be saved + /// into S3 Script table. + /// + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (HdaBar + R_HDA_WAKEEN), + 1, + (VOID *) (UINTN) (HdaBar + R_HDA_WAKEEN) + ); +#endif + } + /// + /// Verb: 31~28 27 26~20 19~0 + /// CAd 1 NID Verb Command and data + /// 0/1/2 + /// + /// Read the Vendor ID/Device ID pair from the attached codec + /// + VendorDeviceId = 0x000F0000 | (AzaliaSDINo << 28); + Status = SendCodecCommand (HdaBar, &VendorDeviceId, TRUE); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Read the Codec Vendor ID/Device ID fail! \n")); + goto ExitInitAzalia; + } + /// + /// Read the Revision ID from the attached codec + /// + RevisionId = 0x000F0002 | (AzaliaSDINo << 28); + Status = SendCodecCommand (HdaBar, &RevisionId, TRUE); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Read the Codec Revision ID fail! \n")); + goto ExitInitAzalia; + } + + RevisionId = (RevisionId >> 8) & 0xFF; + + /// + /// Get the match codec verb table, RevID of 0xFF applies to all steppings. + /// + for (VerbTableNum = 0, VerbHeaderTable = NULL, VerbTable = NULL; + VerbTableNum < AzaliaConfig->AzaliaVerbTableNum; + VerbTableNum++) { + if ((VendorDeviceId == AzaliaConfig->AzaliaVerbTable[VerbTableNum].VerbTableHeader.VendorDeviceId) && + ((AzaliaConfig->AzaliaVerbTable[VerbTableNum].VerbTableHeader.RevisionId == 0xFF) || + ( RevisionId == AzaliaConfig->AzaliaVerbTable[VerbTableNum].VerbTableHeader.RevisionId))) { + VerbHeaderTable = &(AzaliaConfig->AzaliaVerbTable[VerbTableNum].VerbTableHeader); + VerbTable = AzaliaConfig->AzaliaVerbTable[VerbTableNum].VerbTableData; + if (VerbTable == 0) { + DEBUG ((EFI_D_ERROR | EFI_D_INFO, "VerbTableData of VendorID:0x%X is null.\n", VendorDeviceId)); + Status = EFI_INVALID_PARAMETER; + goto ExitInitAzalia; + } + DEBUG ((EFI_D_INFO, "Detected Azalia Codec with verb table, VendorID = 0x%X", VendorDeviceId)); + DEBUG ((EFI_D_INFO, " on SDI%d, revision = 0x%0x.\n", AzaliaSDINo, RevisionId)); + /// + /// Send the entire list of verbs in the matching verb table one by one to the codec + /// + for (Index = 0; + Index < (UINT32) ((VerbHeaderTable->NumberOfFrontJacks + VerbHeaderTable->NumberOfRearJacks) * 4); + Index++) { + /// + /// Clear CAd Field + /// + CodecCmdData = VerbTable[Index] & (UINT32) ~(BIT31 | BIT30 | BIT29 | BIT28); + /// + /// Program CAd Field per the SDI number got during codec detection + /// + CodecCmdData |= (UINT32) (AzaliaSDINo << 28); + Status = SendCodecCommand (HdaBar, &CodecCmdData, FALSE); + if (EFI_ERROR (Status)) { + /// + /// Skip the Azalia verb table loading when find the verb table content is not + /// properly matched with the HDA hardware, though IDs match. + /// + DEBUG ( + (EFI_D_ERROR | EFI_D_INFO, + "Detected Azalia Codec of VendorID:0x%X, error occurs during loading verb table.\n", + VendorDeviceId) + ); + goto ExitInitAzalia; + } + SendCodecCommandS3Item (HdaBar, CodecCmdData); + } + break; + } + } + + if (VerbTableNum >= AzaliaConfig->AzaliaVerbTableNum) { + DEBUG ( + (EFI_D_ERROR, + "Detected High Definition Audio (Azalia) Codec, VendorID = 0x%08x on SDI%d,", + VendorDeviceId, + AzaliaSDINo) + ); + DEBUG ((EFI_D_ERROR, " but no matching verb table found.\n")); + } + } + /// + /// end of for + /// + *AzaliaStarted = TRUE; + Status = EFI_SUCCESS; + +ExitInitAzalia: + /// + /// Clear AZBAR and disable memory map access + /// + MmioAnd16 ((UINTN) (AzaliaBase + R_PCH_HDA_COMMAND), (UINT16) (~B_PCH_HDA_COMMAND_MSE)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (AzaliaBase + R_PCH_HDA_COMMAND), + 1, + (VOID *) (UINTN) (AzaliaBase + R_PCH_HDA_COMMAND) + ); + + MmioWrite32 (AzaliaBase + R_PCH_HDA_HDBARL, 0); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (AzaliaBase + R_PCH_HDA_HDBARL), + 1, + (VOID *) (UINTN) (AzaliaBase + R_PCH_HDA_HDBARL) + ); + + MmioWrite32 (AzaliaBase + R_PCH_HDA_HDBARU, 0); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (AzaliaBase + R_PCH_HDA_HDBARU), + 1, + (VOID *) (UINTN) (AzaliaBase + R_PCH_HDA_HDBARU) + ); + + gDS->FreeMemorySpace ( + BaseAddressBarMem, + V_PCH_HDA_HDBAR_SIZE + ); + + return Status; +} + +/** + Detect and initialize the type of codec (AC'97 and HDA) present in the system. + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in, out] AzaliaEnable Returned with TRUE if Azalia High Definition Audio codec + is detected and initialized. + + @retval EFI_SUCCESS Codec is detected and initialized. + @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to initialize the codec. +**/ +EFI_STATUS +ConfigureAzalia ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar, + IN OUT BOOLEAN *AzaliaEnable + ) +{ + EFI_STATUS Status; + + DEBUG ((EFI_D_INFO, "ConfigureAzalia() Start\n")); + + *AzaliaEnable = FALSE; + + /// + /// If all codec devices are to be disabled, skip the detection code + /// + if (PchPlatformPolicy->DeviceEnabling->Azalia == PCH_DEVICE_DISABLE) { + DEBUG ((EFI_D_ERROR | EFI_D_INFO, "Skip Azalia Codec detection.\n")); + return EFI_SUCCESS; + } + + Status = DetectAndInitializeAzalia (PchPlatformPolicy, RootComplexBar, AzaliaEnable); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR | EFI_D_INFO, "Azalia detection / initialization failure!\n")); + + if (PchPlatformPolicy->DeviceEnabling->Azalia == PCH_DEVICE_ENABLE) { + *AzaliaEnable = TRUE; + } + } + + DEBUG ((EFI_D_INFO, "ConfigureAzalia() End\n")); + return EFI_SUCCESS; +} diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchDebugDump.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchDebugDump.c new file mode 100644 index 0000000..f588686 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchDebugDump.c @@ -0,0 +1,330 @@ +/** @file + Dump whole DXE_PCH_PLATFORM_POLICY_PROTOCOL and serial out. + +@copyright + Copyright (c) 1999 - 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#include "PchInit.h" + +/** + Dump whole DXE_PCH_PLATFORM_POLICY_PROTOCOL and serial out. + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + + @retval None +**/ +VOID +PchDumpPlatformProtocol ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy + ) +{ +#ifdef EFI_DEBUG + UINT8 i; + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "------------------------ PCH Dump platform protocol Start -----------------\n")); + DEBUG ((EFI_D_INFO, " PCH PLATFORM POLICY Revision= %x\n", PchPlatformPolicy->Revision)); + DEBUG ((EFI_D_INFO, " PCH PLATFORM POLICY BusNumber= %x\n", PchPlatformPolicy->BusNumber)); + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "------------------------ PCH_DEVICE_ENABLE -----------------\n")); + DEBUG ((EFI_D_INFO, " PCH_DEVICE_ENABLE Lan= %x\n", PchPlatformPolicy->DeviceEnabling->Lan)); + DEBUG ((EFI_D_INFO, " PCH_DEVICE_ENABLE Azalia= %x\n", PchPlatformPolicy->DeviceEnabling->Azalia)); + DEBUG ((EFI_D_INFO, " PCH_DEVICE_ENABLE Sata= %x\n", PchPlatformPolicy->DeviceEnabling->Sata)); + DEBUG ((EFI_D_INFO, " PCH_DEVICE_ENABLE Smbus= %x\n", PchPlatformPolicy->DeviceEnabling->Smbus)); + DEBUG ((EFI_D_INFO, " PCH_DEVICE_ENABLE PciClockRun= %x\n", PchPlatformPolicy->DeviceEnabling->PciClockRun)); + DEBUG ((EFI_D_INFO, " PCH_DEVICE_ENABLE Display= %x\n", PchPlatformPolicy->DeviceEnabling->Display)); + DEBUG ((EFI_D_INFO, " PCH_DEVICE_ENABLE Crid%x\n", PchPlatformPolicy->DeviceEnabling->Crid)); + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "------------------------ PCH_USB_CONFIG -----------------\n")); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG UsbPerPortCtl= %x\n", PchPlatformPolicy->UsbConfig->UsbPerPortCtl)); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Ehci1Usbr= %x\n", PchPlatformPolicy->UsbConfig->Ehci1Usbr)); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Ehci2Usbr= %x\n", PchPlatformPolicy->UsbConfig->Ehci2Usbr)); + for (i = 0; i < GetPchUsbMaxPhysicalPortNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG PortSettings[%d] Enabled= %x\n", i, PchPlatformPolicy->UsbConfig->PortSettings[i].Enable)); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG PortSettings[%d] Location= %x\n", i, PchPlatformPolicy->UsbConfig->PortSettings[i].Location)); + } + + for (i = 0; i < GetPchXhciMaxUsb3PortNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Port30Settings[%d] Enabled= %x\n", i, PchPlatformPolicy->UsbConfig->Port30Settings[i].Enable)); + } + + for (i = 0; i < GetPchEhciMaxControllerNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb20Settings[%d] Enabled= %x\n", i, PchPlatformPolicy->UsbConfig->Usb20Settings[i].Enable)); + } + + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30Settings.Mode= %x\n", PchPlatformPolicy->UsbConfig->Usb30Settings.Mode)); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30Settings.PreBootSupport= %x\n", PchPlatformPolicy->UsbConfig->Usb30Settings.PreBootSupport)); + DEBUG ((EFI_D_INFO, " XhciStreams is obsoleted, it doesn't effect any setting change since Revision 2.\n")); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30Settings.ManualMode= %x\n", PchPlatformPolicy->UsbConfig->Usb30Settings.ManualMode)); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30Settings.XhciIdleL1= %x\n", PchPlatformPolicy->UsbConfig->Usb30Settings.XhciIdleL1)); + + for (i = 0; i < GetPchUsbMaxPhysicalPortNum (); i++) { + if (PchPlatformPolicy->UsbConfig->Usb30Settings.ManualModeUsb20PerPinRoute[i] == 0) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30Settings.ManualModeUsb20PerPinRoute[%d]= EHCI\n", i)); + } else { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30Settings.ManualModeUsb20PerPinRoute[%d]= XHCI\n", i)); + } + } + + for (i = 0; i < GetPchXhciMaxUsb3PortNum (); i++) { + DEBUG ((EFI_D_INFO, + "PCH_USB_CONFIG Usb30Settings.ManualModeUsb30PerPinEnable[%d]= %x\n", + i, + PchPlatformPolicy->UsbConfig->Usb30Settings.ManualModeUsb30PerPinEnable[i])); + } + + for (i = 0; i < GetPchUsbMaxPhysicalPortNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb20OverCurrentPins[%d]= OC%x\n", i, PchPlatformPolicy->UsbConfig->Usb20OverCurrentPins[i])); + } + + for (i = 0; i < GetPchXhciMaxUsb3PortNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30OverCurrentPins[%d]= OC%x\n", i, PchPlatformPolicy->UsbConfig->Usb30OverCurrentPins[i])); + } + + for (i = 0; i < GetPchEhciMaxUsbPortNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb20PortLength[%d]= %x.%0x\n", i, PchPlatformPolicy->UsbConfig->PortSettings[i].Usb20PortLength >> 4, PchPlatformPolicy->UsbConfig->PortSettings[i].Usb20PortLength & 0xF)); + } + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "------------------------ PCH_PCI_EXPRESS_CONFIG -----------------\n")); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG TempRootPortBusNumMin= %x\n", PchPlatformPolicy->PciExpressConfig->TempRootPortBusNumMin)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG TempRootPortBusNumMax= %x\n", PchPlatformPolicy->PciExpressConfig->TempRootPortBusNumMax)); + for (i = 0; i < GetPchMaxPciePortNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] Enabled= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].Enable)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] Hide= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].Hide)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] SlotImplemented= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].SlotImplemented)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] HotPlug= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].HotPlug)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] PmSci= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].PmSci)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] ExtSync= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].ExtSync)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] UnsupportedRequestReport= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].UnsupportedRequestReport)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] FatalErrorReport= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].FatalErrorReport)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] NoFatalErrorReport= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].NoFatalErrorReport)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] CorrectableErrorReport= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].CorrectableErrorReport)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] PmeInterrupt= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].PmeInterrupt)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] SystemErrorOnFatalError= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].SystemErrorOnFatalError)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] SystemErrorOnNonFatalError= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].SystemErrorOnNonFatalError)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] SystemErrorOnCorrectableError= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].SystemErrorOnCorrectableError)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] AdvancedErrorReporting= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].AdvancedErrorReporting)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] TransmitterHalfSwing= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].TransmitterHalfSwing)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] FunctionNumber= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].FunctionNumber)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] PhysicalSlotNumber= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].PhysicalSlotNumber)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] CompletionTimeout= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].CompletionTimeout)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] Aspm= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].Aspm)); + if (PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_2) { + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPort[%d] L1Substates= %x\n", i, PchPlatformPolicy->PciExpressConfig->RootPort[i].L1Substates)); + } + } + + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG NumOfDevAspmOverride= %x\n", PchPlatformPolicy->PciExpressConfig->NumOfDevAspmOverride)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG DevAspmOverride VendorId= %x\n", PchPlatformPolicy->PciExpressConfig->DevAspmOverride->VendorId)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG DevAspmOverride DeviceId= %x\n", PchPlatformPolicy->PciExpressConfig->DevAspmOverride->DeviceId)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG DevAspmOverride RevId= %x\n", PchPlatformPolicy->PciExpressConfig->DevAspmOverride->RevId)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG DevAspmOverride BaseClassCode= %x\n", PchPlatformPolicy->PciExpressConfig->DevAspmOverride->BaseClassCode)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG DevAspmOverride SubClassCode= %x\n", PchPlatformPolicy->PciExpressConfig->DevAspmOverride->SubClassCode)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG DevAspmOverride EndPointAspm= %x\n", PchPlatformPolicy->PciExpressConfig->DevAspmOverride->EndPointAspm)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG PchPcieSbdePort= %x\n", PchPlatformPolicy->PciExpressConfig->PchPcieSbdePort)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG RootPortClockGating= %x\n", PchPlatformPolicy->PciExpressConfig->RootPortClockGating)); + DEBUG ((EFI_D_INFO, " PCH_PCI_EXPRESS_CONFIG EnableSubDecode= %x\n", PchPlatformPolicy->PciExpressConfig->EnableSubDecode)); + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "------------------------ PCH_SATA_CONFIG -----------------\n")); + for (i = 0; i < GetPchMaxSataPortNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG PortSettings[%d] Enabled= %x\n", i, PchPlatformPolicy->SataConfig->PortSettings[i].Enable)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG PortSettings[%d] HotPlug= %x\n", i, PchPlatformPolicy->SataConfig->PortSettings[i].HotPlug)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG PortSettings[%d] InterlockSw= %x\n", i, PchPlatformPolicy->SataConfig->PortSettings[i].InterlockSw)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG PortSettings[%d] External= %x\n", i, PchPlatformPolicy->SataConfig->PortSettings[i].External)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG PortSettings[%d] SpinUp= %x\n", i, PchPlatformPolicy->SataConfig->PortSettings[i].SpinUp)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG PortSettings[%d] SolidStateDrive= %x\n", i, PchPlatformPolicy->SataConfig->PortSettings[i].SolidStateDrive)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG PortSettings[%d] EnableDitoConfig= %x\n", PchPlatformPolicy->SataConfig->PortSettings[i].EnableDitoConfig)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG PortSettings[%d] DmVal= %x\n", PchPlatformPolicy->SataConfig->PortSettings[i].DmVal)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG PortSettings[%d] DitoVal= %x\n", PchPlatformPolicy->SataConfig->PortSettings[i].DitoVal)); + } + + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG RaidAlternateId= %x\n", PchPlatformPolicy->SataConfig->RaidAlternateId)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG Raid0= %x\n", PchPlatformPolicy->SataConfig->Raid0)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG Raid1= %x\n", PchPlatformPolicy->SataConfig->Raid1)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG Raid10= %x\n", PchPlatformPolicy->SataConfig->Raid10)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG Raid5= %x\n", PchPlatformPolicy->SataConfig->Raid5)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG Irrt= %x\n", PchPlatformPolicy->SataConfig->Irrt)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG OromUiBanner= %x\n", PchPlatformPolicy->SataConfig->OromUiBanner)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG HddUnlock= %x\n", PchPlatformPolicy->SataConfig->HddUnlock)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG LedLocate= %x\n", PchPlatformPolicy->SataConfig->LedLocate)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG IrrtOnly= %x\n", PchPlatformPolicy->SataConfig->IrrtOnly)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG TestMode= %x\n", PchPlatformPolicy->SataConfig->TestMode)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG SalpSupport= %x\n", PchPlatformPolicy->SataConfig->SalpSupport)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG LegacyMode= %x\n", PchPlatformPolicy->SataConfig->LegacyMode)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG SmartStorage= %x\n", PchPlatformPolicy->SataConfig->SmartStorage)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG OromUiDelay= %x\n", PchPlatformPolicy->SataConfig->OromUiDelay)); + DEBUG ((EFI_D_INFO, " PCH_SATA_CONFIG SpeedSupport= %x\n", PchPlatformPolicy->SataConfig->SpeedSupport)); + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "------------------------ PCH_AZALIA_CONFIG -----------------\n")); + DEBUG ((EFI_D_INFO, " PCH_AZALIA_CONFIG Pme= %x\n", PchPlatformPolicy->AzaliaConfig->Pme)); + DEBUG ((EFI_D_INFO, " PCH_AZALIA_CONFIG DS= %x\n", PchPlatformPolicy->AzaliaConfig->DS)); + DEBUG ((EFI_D_INFO, " PCH_AZALIA_CONFIG DA= %x\n", PchPlatformPolicy->AzaliaConfig->DA)); + DEBUG ((EFI_D_INFO, " PCH_AZALIA_CONFIG AzaliaVerbTableNum= %x\n", PchPlatformPolicy->AzaliaConfig->AzaliaVerbTableNum)); + DEBUG ((EFI_D_INFO, " PCH_AZALIA_CONFIG AzaliaVerbTable Header VendorDeviceId= %x\n", PchPlatformPolicy->AzaliaConfig->AzaliaVerbTable->VerbTableHeader.VendorDeviceId)); + DEBUG ((EFI_D_INFO, " PCH_AZALIA_CONFIG AzaliaVerbTable Header SubSystemId= %x\n", PchPlatformPolicy->AzaliaConfig->AzaliaVerbTable->VerbTableHeader.SubSystemId)); + DEBUG ((EFI_D_INFO, " PCH_AZALIA_CONFIG AzaliaVerbTable Header RevisionId= %x\n", PchPlatformPolicy->AzaliaConfig->AzaliaVerbTable->VerbTableHeader.RevisionId)); + DEBUG ((EFI_D_INFO, " PCH_AZALIA_CONFIG AzaliaVerbTable Header FrontPanelSupport= %x\n", PchPlatformPolicy->AzaliaConfig->AzaliaVerbTable->VerbTableHeader.FrontPanelSupport)); + DEBUG ((EFI_D_INFO, " PCH_AZALIA_CONFIG AzaliaVerbTable Header NumberOfRearJacks= %x\n", PchPlatformPolicy->AzaliaConfig->AzaliaVerbTable->VerbTableHeader.NumberOfRearJacks)); + DEBUG ((EFI_D_INFO, " PCH_AZALIA_CONFIG AzaliaVerbTable Header NumberOfFrontJacks= %x\n", PchPlatformPolicy->AzaliaConfig->AzaliaVerbTable->VerbTableHeader.NumberOfFrontJacks)); + DEBUG ((EFI_D_INFO, " PCH_AZALIA_CONFIG AzaliaVerbTable VerbTableData= %x\n", PchPlatformPolicy->AzaliaConfig->AzaliaVerbTable->VerbTableData)); + DEBUG ((EFI_D_INFO, " PCH_AZALIA_CONFIG ResetWaitTimer= %x\n", PchPlatformPolicy->AzaliaConfig->ResetWaitTimer)); + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "------------------------ PCH_SMBUS_CONFIG -----------------\n")); + DEBUG ((EFI_D_INFO, " PCH_SMBUS_CONFIG NumRsvdSmbusAddresses= %x\n", PchPlatformPolicy->SmbusConfig->NumRsvdSmbusAddresses)); + DEBUG ((EFI_D_INFO, " PCH_SMBUS_CONFIG RsvdSmbusAddressTable= %x\n", PchPlatformPolicy->SmbusConfig->RsvdSmbusAddressTable)); + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "------------------------ PCH_MISC_PM_CONFIG -----------------\n")); + DEBUG ((EFI_D_INFO, " PCH_MISC_PM_CONFIG PowerResetStatusClear MeWakeSts= %x\n", PchPlatformPolicy->MiscPmConfig->PowerResetStatusClear.MeWakeSts)); + DEBUG ((EFI_D_INFO, " PCH_MISC_PM_CONFIG PowerResetStatusClear MeHrstColdSts= %x\n", PchPlatformPolicy->MiscPmConfig->PowerResetStatusClear.MeHrstColdSts)); + DEBUG ((EFI_D_INFO, " PCH_MISC_PM_CONFIG PowerResetStatusClear MeHrstWarmSts= %x\n", PchPlatformPolicy->MiscPmConfig->PowerResetStatusClear.MeHrstWarmSts)); + DEBUG ((EFI_D_INFO, " PCH_MISC_PM_CONFIG PowerResetStatusClear MeHostPowerDn= %x\n", PchPlatformPolicy->MiscPmConfig->PowerResetStatusClear.MeHostPowerDn)); + DEBUG ((EFI_D_INFO, " PCH_MISC_PM_CONFIG PowerResetStatusClear WolOvrWkSts= %x\n", PchPlatformPolicy->MiscPmConfig->PowerResetStatusClear.WolOvrWkSts)); + DEBUG ((EFI_D_INFO, " PCH_MISC_PM_CONFIG WakeConfig PmeB0S5Dis= %x\n", PchPlatformPolicy->MiscPmConfig->WakeConfig.PmeB0S5Dis)); + DEBUG ((EFI_D_INFO, " PCH_MISC_PM_CONFIG WakeConfig WolEnableOverride= %x\n", PchPlatformPolicy->MiscPmConfig->WakeConfig.WolEnableOverride)); + DEBUG ((EFI_D_INFO, " PCH_MISC_PM_CONFIG WakeConfig Gp27WakeFromDeepSx= %x\n", PchPlatformPolicy->MiscPmConfig->WakeConfig.Gp27WakeFromDeepSx)); + DEBUG ((EFI_D_INFO, " PCH_MISC_PM_CONFIG PchDeepSxPol= %x\n", PchPlatformPolicy->MiscPmConfig->PchDeepSxPol)); + DEBUG ((EFI_D_INFO, " PCH_MISC_PM_CONFIG PchSlpS3MinAssert= %x\n", PchPlatformPolicy->MiscPmConfig->PchSlpS3MinAssert)); + DEBUG ((EFI_D_INFO, " PCH_MISC_PM_CONFIG PchSlpS4MinAssert= %x\n", PchPlatformPolicy->MiscPmConfig->PchSlpS4MinAssert)); + DEBUG ((EFI_D_INFO, " PCH_MISC_PM_CONFIG PchSlpSusMinAssert= %x\n", PchPlatformPolicy->MiscPmConfig->PchSlpSusMinAssert)); + DEBUG ((EFI_D_INFO, " PCH_MISC_PM_CONFIG PchSlpAMinAssert= %x\n", PchPlatformPolicy->MiscPmConfig->PchSlpAMinAssert)); + DEBUG ((EFI_D_INFO, " PCH_MISC_PM_CONFIG SlpStrchSusUp= %x\n", PchPlatformPolicy->MiscPmConfig->SlpStrchSusUp)); + DEBUG ((EFI_D_INFO, " PCH_MISC_PM_CONFIG SlpLanLowDc= %x\n", PchPlatformPolicy->MiscPmConfig->SlpLanLowDc)); + DEBUG ((EFI_D_INFO, " PCH_MISC_PM_CONFIG PchPwrCycDur= %x\n", PchPlatformPolicy->MiscPmConfig->PchPwrCycDur)); + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "------------------------ PCH_IO_APIC_CONFIG -----------------\n")); + DEBUG ((EFI_D_INFO, " PCH_IO_APIC_CONFIG BdfValid= %x\n", PchPlatformPolicy->IoApicConfig->BdfValid)); + DEBUG ((EFI_D_INFO, " PCH_IO_APIC_CONFIG BusNumber= %x\n", PchPlatformPolicy->IoApicConfig->BusNumber)); + DEBUG ((EFI_D_INFO, " PCH_IO_APIC_CONFIG DeviceNumber= %x\n", PchPlatformPolicy->IoApicConfig->DeviceNumber)); + DEBUG ((EFI_D_INFO, " PCH_IO_APIC_CONFIG FunctionNumber= %x\n", PchPlatformPolicy->IoApicConfig->FunctionNumber)); + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "------------------------ PCH_DEFAULT_SVID_SID -----------------\n")); + DEBUG ((EFI_D_INFO, " PCH_DEFAULT_SVID_SID SubSystemVendorId= %x\n", PchPlatformPolicy->DefaultSvidSid->SubSystemVendorId)); + DEBUG ((EFI_D_INFO, " PCH_DEFAULT_SVID_SID SubSystemId= %x\n", PchPlatformPolicy->DefaultSvidSid->SubSystemId)); + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "------------------------ PCH_LOCK_DOWN_CONFIG -----------------\n")); + DEBUG ((EFI_D_INFO, " PCH_LOCK_DOWN_CONFIG GlobalSmi= %x\n", PchPlatformPolicy->LockDownConfig->GlobalSmi)); + DEBUG ((EFI_D_INFO, " PCH_LOCK_DOWN_CONFIG BiosInterface= %x\n", PchPlatformPolicy->LockDownConfig->BiosInterface)); + DEBUG ((EFI_D_INFO, " PCH_LOCK_DOWN_CONFIG GpioLockDown= %x\n", PchPlatformPolicy->LockDownConfig->GpioLockDown)); + DEBUG ((EFI_D_INFO, " PCH_LOCK_DOWN_CONFIG RtcLock= %x\n", PchPlatformPolicy->LockDownConfig->RtcLock)); + DEBUG ((EFI_D_INFO, " PCH_LOCK_DOWN_CONFIG BiosLock= %x\n", PchPlatformPolicy->LockDownConfig->BiosLock)); + DEBUG ((EFI_D_INFO, " PCH_LOCK_DOWN_CONFIG PchBiosLockIoTrapAddress= %x\n", PchPlatformPolicy->LockDownConfig->PchBiosLockIoTrapAddress)); + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "------------------------ PCH_THERMAL_CONFIG -----------------\n")); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG ThermalAlertEnable TselLock %x\n", PchPlatformPolicy->ThermalConfig->ThermalAlertEnable.TselLock)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG ThermalAlertEnable TscLock %x\n", PchPlatformPolicy->ThermalConfig->ThermalAlertEnable.TscLock)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG ThermalAlertEnable TsmicLock= %x\n", PchPlatformPolicy->ThermalConfig->ThermalAlertEnable.TsmicLock)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG ThermalAlertEnable PhlcLock= %x\n", PchPlatformPolicy->ThermalConfig->ThermalAlertEnable.PhlcLock)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG ThermalDeviceEnable (D31:F6) %x\n", PchPlatformPolicy->ThermalConfig->ThermalDeviceEnable)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING THERMAL_THROTTLE_LEVELS T0Level %x centigrade degree\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.T0Level)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING THERMAL_THROTTLE_LEVELS T1Level %x centigrade degree\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.T1Level)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING THERMAL_THROTTLE_LEVELS T2Level %x centigrade degree\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.T2Level)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING THERMAL_THROTTLE_LEVELS TTEnable %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.TTEnable)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING THERMAL_THROTTLE_LEVELS TTState13Enable %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.TTState13Enable)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING THERMAL_THROTTLE_LEVELS TTLock %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.TTLock)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING THERMAL_THROTTLE_LEVELS SuggestedSetting %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.SuggestedSetting)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING DMI_HW_WIDTH_CONTROL DmiTsawEn %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.DmiHaAWC.DmiTsawEn)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING DMI_HW_WIDTH_CONTROL TS0TW %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.DmiHaAWC.TS0TW)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING DMI_HW_WIDTH_CONTROL TS1TW %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.DmiHaAWC.TS1TW)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING DMI_HW_WIDTH_CONTROL TS2TW %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.DmiHaAWC.TS2TW)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING DMI_HW_WIDTH_CONTROL TS3TW %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.DmiHaAWC.TS3TW)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING DMI_HW_WIDTH_CONTROL SuggestedSetting %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.DmiHaAWC.SuggestedSetting)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING SATA_THERMAL_THROTTLE P0T1M %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P0T1M)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING SATA_THERMAL_THROTTLE P0T2M %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P0T2M)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING SATA_THERMAL_THROTTLE P0T3M %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P0T3M)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING SATA_THERMAL_THROTTLE P0TDisp %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P0TDisp)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING SATA_THERMAL_THROTTLE P0Tinact %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P0Tinact)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING SATA_THERMAL_THROTTLE P0TDispFinit %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P0TDispFinit)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING SATA_THERMAL_THROTTLE P1T1M %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P1T1M)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING SATA_THERMAL_THROTTLE P1T2M %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P1T2M)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING SATA_THERMAL_THROTTLE P1T3M %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P1T3M)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING SATA_THERMAL_THROTTLE P1TDisp %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P1TDisp)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING SATA_THERMAL_THROTTLE P1Tinact %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P1Tinact)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING SATA_THERMAL_THROTTLE P1TDispFinit %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P1TDispFinit)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PCH_THERMAL_THROTTLING SATA_THERMAL_THROTTLE SuggestedSetting %x\n", PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.SuggestedSetting)); + DEBUG ((EFI_D_INFO, " PCH_THERMAL_CONFIG PchHotLevel = %x\n", PchPlatformPolicy->ThermalConfig->PchHotLevel)); + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "------------------------ PCH_LPC_HPET_CONFIG -----------------\n")); + DEBUG ((EFI_D_INFO, " PCH_LPC_HPET_CONFIG HpetConfig %x\n", PchPlatformPolicy->HpetConfig->BdfValid)); + for (i = 0; i < PCH_HPET_BDF_MAX; i++) { + DEBUG ((EFI_D_INFO, " PCH_LPC_HPET_CONFIG Hpet[%d] BusNumber %x\n", i, PchPlatformPolicy->HpetConfig->Hpet[i].BusNumber)); + DEBUG ((EFI_D_INFO, " PCH_LPC_HPET_CONFIG Hpet[%d] DeviceNumber %x\n", i, PchPlatformPolicy->HpetConfig->Hpet[i].DeviceNumber)); + DEBUG ((EFI_D_INFO, " PCH_LPC_HPET_CONFIG Hpet[%d] FunctionNumber %x\n", i, PchPlatformPolicy->HpetConfig->Hpet[i].FunctionNumber)); + } + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "------------------------ PCH_LPC_SIRQ_CONFIG -----------------\n")); + DEBUG ((EFI_D_INFO, " PCH_LPC_SIRQ_CONFIG SirqEnable= %x\n", PchPlatformPolicy->SerialIrqConfig->SirqEnable)); + DEBUG ((EFI_D_INFO, " PCH_LPC_SIRQ_CONFIG SirqMode= %x\n", PchPlatformPolicy->SerialIrqConfig->SirqMode)); + DEBUG ((EFI_D_INFO, " PCH_LPC_SIRQ_CONFIG StartFramePulse= %x\n", PchPlatformPolicy->SerialIrqConfig->StartFramePulse)); + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "------------------------ PCH_DMI_CONFIG -----------------\n")); + DEBUG ((EFI_D_INFO, " PCH_DMI_CONFIG DmiAspm= %x\n", PchPlatformPolicy->DmiConfig->DmiAspm)); + DEBUG ((EFI_D_INFO, " PCH_DMI_CONFIG DmiExtSync= %x\n", PchPlatformPolicy->DmiConfig->DmiExtSync)); + DEBUG ((EFI_D_INFO, " PCH_DMI_CONFIG DmiIot= %x\n", PchPlatformPolicy->DmiConfig->DmiIot)); + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "------------------------ PCH_PWR_OPT_CONFIG -----------------\n")); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG PchPwrOptDmi= %x\n", PchPlatformPolicy->PwrOptConfig->PchPwrOptDmi)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG PchPwrOptGbe= %x\n", PchPlatformPolicy->PwrOptConfig->PchPwrOptGbe)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG PchPwrOptXhci= %x\n", PchPlatformPolicy->PwrOptConfig->PchPwrOptXhci)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG PchPwrOptEhci= %x\n", PchPlatformPolicy->PwrOptConfig->PchPwrOptEhci)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG PchPwrOptSata= %x\n", PchPlatformPolicy->PwrOptConfig->PchPwrOptSata)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG MemCloseStateEn= %x\n", PchPlatformPolicy->PwrOptConfig->MemCloseStateEn)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG InternalObffEn= %x\n", PchPlatformPolicy->PwrOptConfig->InternalObffEn)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG ExternalObffEn= %x\n", PchPlatformPolicy->PwrOptConfig->ExternalObffEn)); + for (i = 0; i < GetPchMaxPciePortNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG RootPort[%d] LtrEnable= %x\n", i, PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[i].LtrEnable)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG RootPort[%d] ObffEnable= %x\n", i, PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[i].ObffEnable)); + } + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG NumOfDevLtrOverride= %x\n", PchPlatformPolicy->PwrOptConfig->NumOfDevLtrOverride)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG DevLtrOverride VendorId= %x\n", PchPlatformPolicy->PwrOptConfig->DevLtrOverride->VendorId)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG DevLtrOverride DeviceId= %x\n", PchPlatformPolicy->PwrOptConfig->DevLtrOverride->DeviceId)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG DevLtrOverride RevId= %x\n", PchPlatformPolicy->PwrOptConfig->DevLtrOverride->RevId)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG DevLtrOverride SnoopLatency= %x\n", PchPlatformPolicy->PwrOptConfig->DevLtrOverride->SnoopLatency)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG DevLtrOverride NonSnoopLatency= %x\n", PchPlatformPolicy->PwrOptConfig->DevLtrOverride->NonSnoopLatency)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG LegacyDmaDisable= %x\n", PchPlatformPolicy->PwrOptConfig->LegacyDmaDisable)); + + for (i = 0; i < GetPchMaxPciePortNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG RootPort[%d] LtrConfigLock= %x\n", i, PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[i].LtrConfigLock)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG RootPort[%d] LtrMaxSnoopLatency = %x\n", i, PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[i]. LtrMaxSnoopLatency)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG RootPort[%d] LtrMaxNoSnoopLatency = %x\n", i, PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[i].LtrMaxNoSnoopLatency)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG RootPort[%d] SnoopLatencyOverrideMode= %x\n", i, PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[i].SnoopLatencyOverrideMode)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG RootPort[%d] SnoopLatencyOverrideMultiplier= %x\n", i, PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[i].SnoopLatencyOverrideMultiplier)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG RootPort[%d] SnoopLatencyOverrideValue= %x\n", i, PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[i].SnoopLatencyOverrideValue)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG RootPort[%d] NonSnoopLatencyOverrideMode= %x\n", i, PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[i].NonSnoopLatencyOverrideMode)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG RootPort[%d] NonSnoopLatencyOverrideMultiplier= %x\n", i, PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[i].NonSnoopLatencyOverrideMultiplier)); + DEBUG ((EFI_D_INFO, " PCH_PWR_OPT_CONFIG RootPort[%d] NonSnoopLatencyOverrideValue= %x\n", i, PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[i].NonSnoopLatencyOverrideValue)); + } + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "------------------------ PCH Dump platform protocol End -----------------\n")); + DEBUG ((EFI_D_INFO, "\n")); +#endif +} diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchFvi.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchFvi.c new file mode 100644 index 0000000..a4f89cc --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchFvi.c @@ -0,0 +1,137 @@ +/** @file + PCH Firmware Version Info implementation. + +@copyright + Copyright (c) 2011 - 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ +#include "PchInit.h" + +FVI_ELEMENT_AND_FUNCTION mPchFviElementsData[] = { + { + DEFAULT_FVI_ELEMENT_DATA (PCH), + NULL + }, + { + { + 1, + 2, + PCH_CRID_VERSION, + PCH_CRID_STATUS, + PCH_CRID_DISABLED, + }, + NULL + }, + { + { + 1, + 0, + PCH_CRID_VERSION, + PCH_CRID_ORIGINAL_VALUE, + { + 0 + }, + }, + NULL + }, + { + { + 1, + 0, + PCH_CRID_VERSION, + PCH_CRID_NEW_VALUE, + { + 0 + }, + }, + NULL + }, + { + { + 1, + 0, + RAID_RC_VERSION, + RAID_FVI_STRING, + { + 0 + }, + }, + NULL + }, +#ifdef ULT_FLAG + { + { + 1, + 0, + { + PCH_LPTLP_HSIO_VER_BX, + 0, + 0, + 0, + }, + PCH_LPTLPBX_HSIO_STRING, + { + 0 + }, + }, + NULL + }, +#endif //ULT_FLAG +#ifdef TRAD_FLAG + { + { + 1, + 0, + { + PCH_LPTH_HSIO_VER_B0, + 0, + 0, + 0, + }, + PCH_LPTHB0_HSIO_STRING, + { + 0 + }, + }, + NULL + }, + { + { + 1, + 0, + { + PCH_LPTH_HSIO_VER_CX, + 0, + 0, + 0, + }, + PCH_LPTHCX_HSIO_STRING, + { + 0 + }, + }, + NULL + }, +#endif //TRAD_FLAG +}; + +FVI_DATA_HUB_CALLBACK_CONTEXT mPchFviVersionData = { + MISC_SUBCLASS_FVI_HEADER_ENTRY (PCH), + mPchFviElementsData, +}; + +UINTN mPchFviElements = sizeof (mPchFviElementsData)/ sizeof (FVI_ELEMENT_AND_FUNCTION); + diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInit.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInit.c new file mode 100644 index 0000000..df7f05b --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInit.c @@ -0,0 +1,2469 @@ +/** @file + This is the driver that initializes the Intel PCH. + +@copyright + Copyright (c) 1999 - 2015 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#include "PchInit.h" +#include "HeciMsgLib.h" +#include "ChipsetInitHob.h" + +// [ EIP357393 ]+>>> +#define AMI_PCI_BUS_EXT_PROTOCOL_GUID \ +{ 0xf42a009d, 0x977f, 0x4f08, 0x94, 0x40, 0xbc, 0xa5, 0xa3, 0xbe, 0xd9, 0xaf }; + +static EFI_GUID gAmiExtPciBusProtocolGuid = AMI_PCI_BUS_EXT_PROTOCOL_GUID; +// [ EIP357393 ]+<<< + +// +// Global Variables +// +EFI_HANDLE mImageHandle; +#ifdef USB_PRECONDITION_ENABLE_FLAG +extern EFI_USB_HC_PORT_PRECONDITION *mPrivatePreConditionList; +#endif // USB_PRECONDITION_ENABLE_FLAG + +// +// GUID Definitions +// +EFI_GUID gChipsetInitHobGuid = CHIPSET_INIT_INFO_HOB_GUID; +EFI_GUID gEfiHeciProtocolGuid = HECI_PROTOCOL_GUID; + +// +// EFI_EVENT +// +EFI_EVENT mHeciEvent; + +// +// Local function prototypes +// +EFI_STATUS +InitializePchDevice ( + IN OUT PCH_INSTANCE_PRIVATE_DATA *PchInstance, + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar, + IN UINT16 PmBase, + IN UINT16 GpioBase + ); + +EFI_STATUS +ProgramSvidSid ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ); + +VOID +EFIAPI +PchExitBootServicesEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +VOID +EFIAPI +PchInitBeforeBoot ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +// [ EIP357393 ]+>>> +EFI_STATUS +EFIAPI +PchSpiLockBeforeEndOfDxe ( + IN EFI_EVENT Event, + IN VOID *Context + ); +// [ EIP357393 ]+<<< + +EFI_STATUS +ChipsetInitSettingsCheck ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy + ); + +/** + Configures PCH IOBP and stores this configuration in S3 boot script + + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in] Address Address of the IOBP register block + @param[in] AndMask Mask to AND with the register + @param[in] OrMask Mask to OR with the register +**/ +VOID +ProgramIobpWithScript ( + IN UINT32 RootComplexBar, + IN UINT32 Address, + IN UINT32 AndMask, + IN UINT32 OrMask + ) +{ + EFI_STATUS Status; + + Status = ProgramIobp (RootComplexBar, Address, AndMask, OrMask); + ASSERT_EFI_ERROR (Status); + + Status = PCH_INIT_COMMON_SCRIPT_SAVE_IOBP_S3_ITEM ( + RootComplexBar, + Address, + AndMask, + OrMask + ); + ASSERT_EFI_ERROR (Status); +} + +/** + Configures 32-bit MMIO register and stores this configuration in S3 boot script + + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in] Address Address of the IOBP register block + @param[in] AndMask Mask to AND with the register + @param[in] OrMask Mask to OR with the register +**/ +VOID +MmioAndThenOr32WithScript ( + IN UINTN Address, + IN UINT32 AndMask, + IN UINT32 OrMask + ) +{ + MmioAndThenOr32 (Address, AndMask, OrMask); + + PCH_INIT_COMMON_SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + Address, + &OrMask, + &AndMask + ); +} + +/** + This is the standard EFI driver point that detects + whether there is an PCH southbridge in the system + and if so, initializes the chip. + + @param[in] ImageHandle Handle for the image of this driver + @param[in] SystemTable Pointer to the EFI System Table + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver +**/ +EFI_STATUS +EFIAPI +PchInitEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINT8 BusNumber; + UINT32 RootComplexBar; + DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy; + UINTN NumHandles; + EFI_HANDLE *HandleBuffer; + UINT32 Index; + PCH_INSTANCE_PRIVATE_DATA *PchInstance; + UINT16 PmBase; + UINT16 GpioBase; + UINTN PciD31F0RegBase; + + DEBUG ((EFI_D_INFO, "PchInitEntryPoint() Start\n")); + + PchInstance = NULL; + PchPlatformPolicy = NULL; + + INITIALIZE_SCRIPT (ImageHandle, SystemTable); + mImageHandle = ImageHandle; + + /// + /// Retrieve all instances of PCH Platform Policy protocol + /// + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gDxePchPlatformPolicyProtocolGuid, + NULL, + &NumHandles, + &HandleBuffer + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < NumHandles; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gDxePchPlatformPolicyProtocolGuid, + (VOID **) &PchPlatformPolicy + ); + ASSERT_EFI_ERROR (Status); + + /// + /// Allocate and install the PCH Info protocol + /// + BusNumber = PchPlatformPolicy->BusNumber; + PciD31F0RegBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); + RootComplexBar = MmioRead32 (PciD31F0RegBase + R_PCH_LPC_RCBA) & B_PCH_LPC_RCBA_BAR; + PmBase = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_ACPI_BASE) & B_PCH_LPC_ACPI_BASE_BAR; + GpioBase = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_GPIO_BASE) & B_PCH_LPC_GPIO_BASE_BAR; + + ASSERT (RootComplexBar != 0); + ASSERT (PmBase != 0); + ASSERT (GpioBase != 0); + + DEBUG ((EFI_D_INFO, "PCH Device:\n-------------\n")); + DEBUG ((EFI_D_INFO, " RCBA 0x%X\n", RootComplexBar)); + DEBUG ((EFI_D_INFO, " PmBase 0x%X\n", PmBase)); + DEBUG ((EFI_D_INFO, " GpioBase 0x%X\n", GpioBase)); + DEBUG ((EFI_D_INFO, "-------------\n")); + + /// + /// Dump whole DXE_PCH_PLATFORM_POLICY_PROTOCOL and serial out. + /// + PchDumpPlatformProtocol (PchPlatformPolicy); + /// + /// Initialize the PCH device + /// + InitializePchDevice (PchInstance, PchPlatformPolicy, RootComplexBar, PmBase, GpioBase); + + PchInstance = AllocateZeroPool (sizeof (PCH_INSTANCE_PRIVATE_DATA)); + if (PchInstance == NULL) { + ASSERT (FALSE); + return EFI_OUT_OF_RESOURCES; + } + + PchInstance->PchInfo.Revision = PCH_INFO_PROTOCOL_REVISION_2; + PchInstance->PchInfo.BusNumber = BusNumber; + PchInstance->PchInfo.RCVersion = PCH_RC_VERSION; +#ifdef USB_PRECONDITION_ENABLE_FLAG + PchInstance->PchInfo.Preconditioned = mPrivatePreConditionList; +#endif // USB_PRECONDITION_ENABLE_FLAG + + Status = gBS->InstallMultipleProtocolInterfaces ( + &(HandleBuffer[Index]), + &gEfiPchInfoProtocolGuid, + &(PchInstance->PchInfo), + NULL + ); + } + + (gBS->FreePool) (HandleBuffer); + + DEBUG ((EFI_D_INFO, "PchInitEntryPoint() End\n")); + + return EFI_SUCCESS; +} + +/** + Initialize the PCH device according to the PCH Platform Policy protocol + + @param[in, out] PchInstance PCH instance private data. May get updated by this function + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in] PmBase Power Management IO base address of this PCH device + @param[in] GpioBase GPIO base address of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +InitializePchDevice ( + IN OUT PCH_INSTANCE_PRIVATE_DATA *PchInstance, + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar, + IN UINT16 PmBase, + IN UINT16 GpioBase + ) +{ + EFI_STATUS Status; + BOOLEAN AzaliaEnable; + UINT32 FuncDisableReg; + VOID *Registration; + VOID *Registration1; // [ EIP357393 ] + EFI_EVENT LegacyBootEvent; + EFI_EVENT ExitBootServicesEvent; + UINT16 LpcDeviceId; + + DEBUG ((EFI_D_INFO, "InitializePchDevice() Start\n")); + + FuncDisableReg = MmioRead32 (RootComplexBar + R_PCH_RCRB_FUNC_DIS); + + LpcDeviceId = MmioRead16 ( + MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ) + R_PCH_LPC_DEVICE_ID); + + /// + /// Take care of any ChipsetInit settings before going any further. + /// + Status = ChipsetInitSettingsCheck(PchPlatformPolicy); + ASSERT_EFI_ERROR (Status); + + /// + /// Miscellaneous power management handling + /// + Status = ConfigureMiscPm (PchPlatformPolicy, RootComplexBar, GpioBase); + ASSERT_EFI_ERROR (Status); + /// + /// Additional power management setting + /// + Status = ConfigureAdditionalPm (PchPlatformPolicy, RootComplexBar); + ASSERT_EFI_ERROR (Status); + /// + /// Configures PCH DMI power management configuration + /// + Status = ConfigureDmiPm (PchPlatformPolicy, RootComplexBar); + ASSERT_EFI_ERROR (Status); + /// + /// Deep Sx Enabling + /// + Status = ProgramDeepSx (PchPlatformPolicy, RootComplexBar); + ASSERT_EFI_ERROR (Status); + /// + /// Perform PCH initialization sequence + /// + Status = ConfigureMiscItems (PchPlatformPolicy, RootComplexBar, &FuncDisableReg); + ASSERT_EFI_ERROR (Status); + +#ifdef ADSP_FLAG + /// + /// Configure AudioDSP + /// + if(IS_PCH_LPTLP_LPC_DEVICE_ID(LpcDeviceId)) { + Status = ConfigureAudioDsp (PchPlatformPolicy, RootComplexBar, &FuncDisableReg); + ASSERT_EFI_ERROR (Status); + } +#endif // ADSP_FLAG + + /// + /// Detect and initialize the type of codec present in the system + /// + Status = ConfigureAzalia (PchPlatformPolicy, RootComplexBar, &AzaliaEnable); + ASSERT_EFI_ERROR (Status); + + /// + /// Check to disable Azalia controller + /// + if (!AzaliaEnable) { + FuncDisableReg |= B_PCH_RCRB_FUNC_DIS_AZALIA; + } + /// + /// Initialize LAN + /// + Status = ConfigureLan (PchPlatformPolicy, RootComplexBar); + ASSERT_EFI_ERROR (Status); + + /// + /// Configure USB + /// + Status = ConfigureUsb (PchPlatformPolicy, RootComplexBar, &FuncDisableReg); + ASSERT_EFI_ERROR (Status); + + /// + /// Initialize PCIE root ports + /// + Status = PchInitRootPorts (PchPlatformPolicy, RootComplexBar, PmBase, &FuncDisableReg); + ASSERT_EFI_ERROR (Status); + + /// + /// Thermal controller already enabled in PEI + /// + + /// + /// Sata Controllers + /// + Status = ConfigureSata (PchPlatformPolicy, RootComplexBar, &FuncDisableReg, GpioBase); + ASSERT_EFI_ERROR (Status); + + /// + /// Display link + /// + Status = ConfigureDisplay (PchPlatformPolicy, RootComplexBar); + ASSERT_EFI_ERROR (Status); + + /// + /// Set the PCH Function Disable Register + /// + MmioWrite32 ((UINTN) (RootComplexBar + R_PCH_RCRB_FUNC_DIS), (UINT32) (FuncDisableReg)); + + /// + /// Reads back for posted write to take effect + /// + MmioRead32 (RootComplexBar + R_PCH_RCRB_FUNC_DIS); + + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_FUNC_DIS), + 1, + &FuncDisableReg + ); + + /// + /// Reads back for posted write to take effect + /// + SCRIPT_MEM_POLL ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_FUNC_DIS), + &FuncDisableReg, // BitMask + &FuncDisableReg, // BitValue + 1, // Duration + 1 // LoopTimes + ); + /// + /// Perform clock gating register settings + /// PCH BIOS Spec Rev 0.5.0, section 19.10 Enabling Clock Gating + /// + Status = ConfigureClockGating (PchPlatformPolicy, RootComplexBar, FuncDisableReg); + ASSERT_EFI_ERROR (Status); + + Status = ConfigureIoApic (PchPlatformPolicy, RootComplexBar); + ASSERT_EFI_ERROR (Status); + + Status = ProgramSvidSid (PchPlatformPolicy, RootComplexBar); + ASSERT_EFI_ERROR (Status); + +#ifdef SERIAL_IO_FLAG + /// + /// Configure Serial IO Controllers + /// + if(IS_PCH_LPTLP_LPC_DEVICE_ID(LpcDeviceId)) { + Status = ConfigureSerialIo (PchPlatformPolicy, RootComplexBar); + ASSERT_EFI_ERROR (Status); + } +#endif // SERIAL_IO_FLAG + +// [ EIP357393 ]+>>> + // Create an AMI ExtPciBus protocol call back event. + // + EfiCreateProtocolNotifyEvent ( + &gAmiExtPciBusProtocolGuid, + EFI_TPL_CALLBACK, + PchSpiLockBeforeEndOfDxe, + NULL, + &Registration1 + ); +// [ EIP357393 ]+<<< + + /// + /// Create an ExitPmAuth protocol call back event. + /// + EfiCreateProtocolNotifyEvent ( + &gExitPmAuthProtocolGuid, + EFI_TPL_CALLBACK, + PchInitBeforeBoot, + NULL, + &Registration + ); + + /// + /// Create events for PCH to do the task before ExitBootServices/LegacyBoot. + /// It is guaranteed that only one of two events below will be signalled + /// + Status = gBS->CreateEvent ( + EVENT_SIGNAL_EXIT_BOOT_SERVICES, + EFI_TPL_CALLBACK, + PchExitBootServicesEvent, + NULL, + &ExitBootServicesEvent + ); + ASSERT_EFI_ERROR (Status); + + Status = EfiCreateEventLegacyBootEx ( + EFI_TPL_CALLBACK, + PchExitBootServicesEvent, + NULL, + &LegacyBootEvent + ); + ASSERT_EFI_ERROR (Status); + + DEBUG ((EFI_D_INFO, "InitializePchDevice() End\n")); + + return Status; +} + +/** + Program Pch devices Subsystem Vendor Identifier (SVID) and Subsystem Identifier (SID). + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ProgramSvidSid ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ) +{ + UINT8 Index; + UINT16 EhciAccessCntl; + UINT8 BusNumber; + UINTN PciEAddressBase; + UINT8 DeviceNumber; + UINT8 FunctionNumber; + UINT8 SvidRegOffset; + BOOLEAN IsPchEhci; + STATIC PCH_SVID_SID_INIT_ENTRY SvidSidInitTable[] = { + { + 31, + 0, + R_PCH_LPC_SS + }, + { + 31, + 2, + R_PCH_SATA_AHCI_SVID + }, + { + 31, + 5, + R_PCH_SATA_AHCI_SVID + }, + { + 31, + 3, + R_PCH_SMBUS_SVID + }, + { + 31, + 6, + R_PCH_THERMAL_SVID + }, + { + 29, + 0, + R_PCH_EHCI_SVID + }, + { + 26, + 0, + R_PCH_EHCI_SVID + }, + { + 20, + 0, + R_PCH_XHCI_SVID + }, + { + 27, + 0, + R_PCH_HDA_SVID + }, + { + 28, + 0, + R_PCH_PCIE_SVID + }, + { + 28, + 1, + R_PCH_PCIE_SVID + }, + { + 28, + 2, + R_PCH_PCIE_SVID + }, + { + 28, + 3, + R_PCH_PCIE_SVID + }, + { + 28, + 4, + R_PCH_PCIE_SVID + }, + { + 28, + 5, + R_PCH_PCIE_SVID + }, + { + 28, + 6, + R_PCH_PCIE_SVID + }, + { + 28, + 7, + R_PCH_PCIE_SVID + }, + { + 25, + 0, + R_PCH_LAN_SVID + }, + /* HECI */ + { + 22, + 0, + PCI_SVID_OFFSET + }, + { + 22, + 1, + PCI_SVID_OFFSET + }, + { + 22, + 2, + PCI_SVID_OFFSET + }, + { + 22, + 3, + PCI_SVID_OFFSET + } + }; + PCH_SERIES PchSeries; + + DEBUG ((EFI_D_INFO, "ProgramSvidSid() Start\n")); + + PchSeries = GetPchSeries(); + EhciAccessCntl = 0; + BusNumber = PchPlatformPolicy->BusNumber; + + if ((PchPlatformPolicy->DefaultSvidSid->SubSystemVendorId != 0) || + (PchPlatformPolicy->DefaultSvidSid->SubSystemId != 0)) { + for (Index = 0; Index < (sizeof (SvidSidInitTable) / sizeof (PCH_SVID_SID_INIT_ENTRY)); Index++) { + DeviceNumber = SvidSidInitTable[Index].DeviceNumber; + FunctionNumber = SvidSidInitTable[Index].FunctionNumber; + SvidRegOffset = SvidSidInitTable[Index].SvidRegOffset; + PciEAddressBase = MmPciAddress ( + 0, + BusNumber, + DeviceNumber, + FunctionNumber, + 0 + ); + /// + /// Skip if the device is disabled + /// + if (MmioRead16 (PciEAddressBase) != V_PCH_INTEL_VENDOR_ID) { + continue; + } + + IsPchEhci = FALSE; + if (PchSeries == PchH) { + IsPchEhci = IS_PCH_H_EHCI (DeviceNumber, FunctionNumber); + } else if (PchSeries == PchLp) { + IsPchEhci = IS_PCH_LP_EHCI (DeviceNumber, FunctionNumber); + } + + /// + /// Set EHCI devices WRT_RDONLY bit (D29:F0,D26:F0:80h, bit 0) to 1, to make SVID and SID registers are writable + /// + if (IsPchEhci) { + EhciAccessCntl = MmioRead16 ((UINTN) (PciEAddressBase + R_PCH_EHCI_ACCESS_CNTL)); + MmioOr16 ((UINTN) (PciEAddressBase + R_PCH_EHCI_ACCESS_CNTL), B_PCH_EHCI_ACCESS_CNTL_ENABLE); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciEAddressBase + R_PCH_EHCI_ACCESS_CNTL), + 1, + (VOID *) (UINTN) (PciEAddressBase + R_PCH_EHCI_ACCESS_CNTL) + ); + } + + if ((DeviceNumber == 22 && FunctionNumber == 2) || (DeviceNumber == 22 && FunctionNumber == 3)) { + /// + /// Sub System Identifiers register of D22:F2&F3 is 32bit access and write once + /// + MmioWrite32 ( + (UINTN) (PciEAddressBase + SvidRegOffset), + (UINT32) (PchPlatformPolicy->DefaultSvidSid->SubSystemVendorId | + (PchPlatformPolicy->DefaultSvidSid->SubSystemId << 16)) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciEAddressBase + SvidRegOffset), + 1, + (VOID *) (UINTN) (PciEAddressBase + SvidRegOffset) + ); + } else { + /// + /// Program Pch devices Subsystem Vendor Identifier (SVID) + /// + MmioWrite16 ( + (UINTN) (PciEAddressBase + SvidRegOffset), + PchPlatformPolicy->DefaultSvidSid->SubSystemVendorId + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciEAddressBase + SvidRegOffset), + 1, + (VOID *) (UINTN) (PciEAddressBase + SvidRegOffset) + ); + + /// + /// Program Pch devices Subsystem Identifier (SID) + /// + MmioWrite16 ( + (UINTN) (PciEAddressBase + SvidRegOffset + 2), + PchPlatformPolicy->DefaultSvidSid->SubSystemId + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciEAddressBase + SvidRegOffset + 2), + 1, + (VOID *) (PciEAddressBase + SvidRegOffset + 2) + ); + } + /// + /// Restore the EHCI devices WRT_RDONLY bit (D29:F0,D26:F0:80h, bit 0) value + /// + if (IsPchEhci) { + MmioWrite16 ((UINTN) (PciEAddressBase + R_PCH_EHCI_ACCESS_CNTL), EhciAccessCntl); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciEAddressBase + R_PCH_EHCI_ACCESS_CNTL), + 1, + &EhciAccessCntl + ); + } + } + } + + DEBUG ((EFI_D_INFO, "ProgramSvidSid() End\n")); + + return EFI_SUCCESS; +} + +/** + Initialize R/WO Registers that described in PCH BIOS Spec + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar address of this PCH device + @param[in, out] FuncDisableReg The value of Function disable register + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +PciERWORegInit ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar, + IN OUT UINT32 *FuncDisableReg + ) +{ + UINTN Index; + UINTN PciD31F5RegBase; + UINT8 BusNumber; + UINT8 RootPortFunction; + UINTN RPBase; + UINT32 Data32; + UINT16 Data16; + UINT8 Data8; + PCH_SERIES PchSeries; + + DEBUG ((EFI_D_INFO, "PciERWORegInit() Start\n")); + + PchSeries = GetPchSeries(); + BusNumber = PchPlatformPolicy->BusNumber; + PciD31F5RegBase = 0; + if (PchSeries == PchH) { + PciD31F5RegBase = MmPciAddress (0, BusNumber, 31, 5, 0); + } + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 5.12 R/WO Registers, Table 5-4 + /// System BIOS must read the register and write the same value back to the register + /// before passing control to the operating system. + /// Dev:Func/Type Register Offset Register Name Bits + /// D28:F0-F7 034h Capabilities Pointer 7:0 + /// D28:F0-F7 040h Capabilities List 15:8 + /// D28:F0-F7 042h PCI Express Capabilities 8 + /// D28:F0~F7 044h Device Capabilities 2:0 + /// D28:F0-F7 04Ch Link Capabilities 11:10, 17:15 + /// D28:F0-F7 050h Link Control 3 + /// D28:F0-F7 054h Slot Capabilities 31:19, 16:5 + /// D28:F0-F7 064h Device Capabilities 2 11 + /// D28:F0-F7 080h Message Signaled Interrupt Capability ID 15:8 + /// D28:F0-F7 090h Port Mapping Regster 15:8 + /// D28:F0-F7 094h Subsystem Vendor ID 31:0 + /// D28:F0-F7 0D8h Miscellaneous Port Configuration 23, 2 + /// D28:F0-F7 404h Latency Tolerance Reporting Override 2 2 + /// RCBA 21A4h Link Capabilities 17:15 For PCH H + /// D31:F5 0A8h Next Capabilities Pointer 15:8 + /// D31:F5 0B2h Capabilities List 9:8 + /// + for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) { + if (((*FuncDisableReg) & (B_PCH_RCRB_FUNC_DIS_PCI_EX_PORT1 << Index)) == 0) { + RootPortFunction = GetPchPcieRpfn(RootComplexBar, (UINT8)Index); + RPBase = MmPciAddress (0, BusNumber, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, RootPortFunction, 0); + Data32 = MmioRead32 (RPBase + R_PCH_PCIE_LCAP); + MmioWrite32 (RPBase + R_PCH_PCIE_LCAP, Data32); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_LCAP), + 1, + &Data32 + ); + + Data32 = MmioRead32 (RPBase + R_PCH_PCIE_SVID); + MmioWrite32 (RPBase + R_PCH_PCIE_SVID, Data32); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_SVID), + 1, + &Data32 + ); + + Data32 = MmioRead32 (RPBase + R_PCH_PCIE_SLCAP); + MmioWrite32 (RPBase + R_PCH_PCIE_SLCAP, Data32); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_SLCAP), + 1, + &Data32 + ); + /// + /// Added PCIe register to be lockdown + /// + Data8 = MmioRead8 (RPBase + R_PCH_PCIE_CAPP); + MmioWrite8 (RPBase + R_PCH_PCIE_CAPP, Data8); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (RPBase + R_PCH_PCIE_CAPP), + 1, + &Data8 + ); + + Data16 = MmioRead16 (RPBase + R_PCH_PCIE_CLIST); + MmioWrite16 (RPBase + R_PCH_PCIE_CLIST, Data16); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RPBase + R_PCH_PCIE_CLIST), + 1, + &Data16 + ); + + Data16 = MmioRead16 (RPBase + R_PCH_PCIE_DCAP); + MmioWrite16 (RPBase + R_PCH_PCIE_DCAP, Data16); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RPBase + R_PCH_PCIE_DCAP), + 1, + &Data16 + ); + + Data16 = MmioRead16 (RPBase + R_PCH_PCIE_MID); + MmioWrite16 (RPBase + R_PCH_PCIE_MID, Data16); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RPBase + R_PCH_PCIE_MID), + 1, + &Data16 + ); + + Data16 = MmioRead16 (RPBase + R_PCH_PCIE_SVCAP); + MmioWrite16 (RPBase + R_PCH_PCIE_SVCAP, Data16); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RPBase + R_PCH_PCIE_SVCAP), + 1, + &Data16 + ); + + if (PchSeries == PchLp) { + Data32 = MmioRead32 (RPBase + R_PCH_PCIE_L1SECH); + Data32 |= V_PCH_PCIE_L1SECH_L1SUBST_CAP_ID; + MmioWrite32 (RPBase + R_PCH_PCIE_L1SECH, Data32); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_L1SECH), + 1, + &Data32 + ); + + Data32 = MmioRead32 (RPBase + R_PCH_PCIE_L1SCAP); + MmioWrite32 (RPBase + R_PCH_PCIE_L1SCAP, Data32); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_L1SCAP), + 1, + &Data32 + ); + } + } + } + + if (PchSeries == PchH) { + /// + /// D31:F5:A8h[15:8] + /// + Data16 = MmioRead16 (PciD31F5RegBase + R_PCH_SATA_CR0); + MmioWrite16 (PciD31F5RegBase + R_PCH_SATA_CR0, Data16); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD31F5RegBase + R_PCH_SATA_CR0), + 1, + &Data16 + ); + /// + /// D31:F5:B2h[9:8] + /// + Data16 = MmioRead16 (PciD31F5RegBase + R_PCH_SATA_FLR_CLV); + MmioWrite16 (PciD31F5RegBase + R_PCH_SATA_FLR_CLV, Data16); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD31F5RegBase + R_PCH_SATA_FLR_CLV), + 1, + &Data16 + ); + } + + /// + /// D28:F0-F7:42h[8] (PCI Express Capabilities) has been done in PchInitRootPorts(). + /// D28:F0-F7:4Ch[17:15] (Link Capabilities) has been done in PchInitSingleRootPort(). + /// D28:F0-F7:404h[2] (Latency Tolerance Reporting Override 2) has been done in PchInitSingleRootPort(). + /// RCBA + 21A4h[17:15] (Link Capabilities) has been done in ConfigureDmiPm() for PCH H. + /// + + DEBUG ((EFI_D_INFO, "PciERWORegInit() End\n")); + + return EFI_SUCCESS; +} + +/** + Set a Root Port Downstream devices ASPM and LTR S3 dispatch item, this function may assert if any error happend + + @param[in] RootPortBus Pci Bus Number of the root port + @param[in] RootPortDevice Pci Device Number of the root port + @param[in] RootPortFunc Pci Function Number of the root port + @param[in] RootPortAspm Root port Aspm configuration + @param[in] NumOfDevAspmOverride Number of Device specific ASPM policy override items + @param[in] DevAspmOverride Pointer to array of Device specific ASPM policy override items + @param[in] TempBusNumberMin Minimal temp bus number that can be assigned to the root port (as secondary + bus number) and its down stream switches + @param[in] TempBusNumberMax Maximal temp bus number that can be assigned to the root port (as subordinate + bus number) and its down stream switches + @param[in] NumOfDevLtrOverride Number of Device specific LTR override items + @param[in] DevLtrOverride Pointer to array of Device specific LTR policy override items + @param[in] PchPwrOptPcie Pcie Power Optimizer Configuration + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +SetPciePmS3Item ( + IN UINT8 RootPortBus, + IN UINT8 RootPortDevice, + IN UINT8 RootPortFunc, + IN PCH_PCI_EXPRESS_ASPM_CONTROL RootPortAspm, + IN UINT8 NumOfDevAspmOverride, + IN PCH_PCIE_DEVICE_ASPM_OVERRIDE *DevAspmOverride, + IN UINT8 TempBusNumberMin, + IN UINT8 TempBusNumberMax, + IN UINT8 NumOfDevLtrOverride, + IN PCH_PCIE_DEVICE_LTR_OVERRIDE *DevLtrOverride, + IN PCH_PCIE_PWR_OPT *PchPwrOptPcie, + IN PCH_PCIE_EXPRESS_L1SUBSTATES_CONTROL L1SubstatesConfig, + IN UINT8 PolicyRevision, + IN BOOLEAN FirstRPToSetPm, + IN BOOLEAN L1SupportedInAllEnabledPorts, + IN BOOLEAN ClkreqSupportedInAllEnabledPorts + ) +{ + EFI_STATUS Status; +#ifdef EFI_S3_RESUME + STATIC EFI_PCH_S3_SUPPORT_PROTOCOL *PchS3Support; + STATIC EFI_PCH_S3_PARAMETER_PCIE_SET_PM S3ParameterSetPm; + STATIC EFI_PCH_S3_DISPATCH_ITEM S3DispatchItem = { + PchS3ItemTypePcieSetPm, + &S3ParameterSetPm + }; + EFI_PHYSICAL_ADDRESS S3DispatchEntryPoint; + + if (!PchS3Support) { + DEBUG ((EFI_D_INFO, "Locating the S3 Support Protocol - PCH Init\n")); + + /// + /// Get the PCH S3 Support Protocol + /// + Status = gBS->LocateProtocol ( + &gEfiPchS3SupportProtocolGuid, + NULL, + (VOID **) &PchS3Support + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + DEBUG ((EFI_D_INFO, "Located the S3 Support Protocol - PCH Init: %x\n", (UINTN)PchS3Support)); + } + + DEBUG ((EFI_D_INFO, "Attempting to set Custom PCH Init Dispatch Item\n")); + + S3ParameterSetPm.RootPortBus = RootPortBus; + S3ParameterSetPm.RootPortDevice = RootPortDevice; + S3ParameterSetPm.RootPortFunc = RootPortFunc; + S3ParameterSetPm.RootPortAspm = RootPortAspm; + S3ParameterSetPm.NumOfDevAspmOverride = NumOfDevAspmOverride; + S3ParameterSetPm.DevAspmOverrideAddr = (UINT32) (UINTN) DevAspmOverride; + S3ParameterSetPm.TempBusNumberMin = TempBusNumberMin; + S3ParameterSetPm.TempBusNumberMax = TempBusNumberMax; + S3ParameterSetPm.PchPwrOptPcie = (UINT32) (UINTN) PchPwrOptPcie; + S3ParameterSetPm.NumOfDevLtrOverride = NumOfDevLtrOverride; + S3ParameterSetPm.DevLtrOverrideAddr = (UINT32) (UINTN) DevLtrOverride; + S3ParameterSetPm.L1SubstatesConfig = L1SubstatesConfig; + S3ParameterSetPm.PolicyRevision = PolicyRevision; + S3ParameterSetPm.FirstRPToSetPm = FirstRPToSetPm; + S3ParameterSetPm.L1SupportedInAllEnabledPorts = L1SupportedInAllEnabledPorts; + S3ParameterSetPm.ClkreqSupportedInAllEnabledPorts = ClkreqSupportedInAllEnabledPorts; + Status = PchS3Support->SetDispatchItem ( + PchS3Support, + &S3DispatchItem, + &S3DispatchEntryPoint + ); + ASSERT_EFI_ERROR (Status); + /// + /// Save the script dispatch item in the Boot Script + /// + SCRIPT_DISPATCH (EFI_ACPI_S3_RESUME_SCRIPT_TABLE, S3DispatchEntryPoint); +#else + Status = EFI_SUCCESS; +#endif + return Status; +} + +/** + PCH initialization before ExitBootServices / LegacyBoot events + Useful for operations which must happen later than at EndOfPost event + + @param[in] Event A pointer to the Event that triggered the callback. + @param[in] Context A pointer to private data registered with the callback function. + + @retval None +**/ +VOID +EFIAPI +PchExitBootServicesEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + UINTN NumHandles; + EFI_HANDLE *HandleBuffer; + DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy; + UINTN Index; + UINT32 AhciBar; + UINTN PciD31F2RegBase; + UINT16 SataModeSelect; + UINT16 LpcDeviceId; + UINT32 PxSctlDet; + UINT32 PxCmdSud; + UINT16 OrgCmdWord; + + /// + /// Closed the event to avoid call twice + /// + gBS->CloseEvent (Event); + + LpcDeviceId = MmioRead16 ( + MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ) + R_PCH_LPC_DEVICE_ID); + + /// + /// Retrieve all instances of PCH Platform Policy protocol + /// + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gDxePchPlatformPolicyProtocolGuid, + NULL, + &NumHandles, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR | EFI_D_INFO, "Failed to locate handle buffer for PCH Policy protocol.\n")); + return; + } + + for (Index = 0; Index < NumHandles; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gDxePchPlatformPolicyProtocolGuid, + (VOID **) &PchPlatformPolicy + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR | EFI_D_INFO, "Failed to find PCH Policy protocol.\n")); + return; + } + + ConfigureXhciAtBoot (PchPlatformPolicy); +#ifdef SERIAL_IO_FLAG + ConfigureSerialIoAtBoot(PchPlatformPolicy); +#endif // SERIAL_IO_FLAG + + /// + /// eSATA port support only up to Gen2 + /// + PciD31F2RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, PCI_DEVICE_NUMBER_PCH_SATA, PCI_FUNCTION_NUMBER_PCH_SATA, 0); + // + // Make sure SATA device exists. + // + if (MmioRead16 (PciD31F2RegBase + R_PCH_SATA_VENDOR_ID) != 0xFFFF) { + SataModeSelect = MmioRead16 (PciD31F2RegBase + R_PCH_SATA_MAP) & B_PCH_SATA_MAP_SMS_MASK; + if ((SataModeSelect == V_PCH_SATA_MAP_SMS_AHCI) || + (SataModeSelect == V_PCH_SATA_MAP_SMS_RAID)) { + AhciBar = MmioRead32 (PciD31F2RegBase + R_PCH_SATA_AHCI_BAR) & B_PCH_SATA_AHCI_BAR_BA; + // + // Make sure the AhciBar is valid. + // + if ((AhciBar != 0x00000000) && (AhciBar != 0xFFFFFFFF)) { + /// + /// Keep original CMD word, and enable MSE + /// + OrgCmdWord = MmioRead16 (PciD31F2RegBase + R_PCH_SATA_COMMAND); + if ((OrgCmdWord & B_PCH_SATA_COMMAND_MSE) == 0) { + MmioOr16 ((PciD31F2RegBase + R_PCH_SATA_COMMAND), B_PCH_SATA_COMMAND_MSE); + } + for (Index = 0; Index < GetPchMaxSataPortNum (); Index++) { + if (PchPlatformPolicy->SataConfig->PortSettings[Index].External == PCH_DEVICE_ENABLE) { + PxSctlDet = MmioRead32(AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index))) & B_PCH_SATA_AHCI_PXSCTL_DET; + PxCmdSud = MmioRead32(AhciBar + (R_PCH_SATA_AHCI_P0CMD + (0x80 * Index))) & B_PCH_SATA_AHCI_PxCMD_SUD; + /// + /// Limit speed to Gen2 + /// + MmioAndThenOr32 ( + (UINTN) (AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index))), + (UINT32)~(B_PCH_SATA_AHCI_PXSCTL_SPD), + (UINT32) V_PCH_SATA_AHCI_PXSCTL_SPD_2 + ); + /// + /// If port is not offline, and it's spin up, need to port reset. + /// After port reset, clear the SERR. + /// - Set DET=1, and then set DET=0. + /// + if ((PxSctlDet == V_PCH_SATA_AHCI_PXSCTL_DET_0) && + (PxCmdSud == B_PCH_SATA_AHCI_PxCMD_SUD)) + { + MmioOr32 (AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index)), V_PCH_SATA_AHCI_PXSCTL_DET_1); + PchPmTimerStall (1000); + MmioAnd32(AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index)), (UINT32) ~(B_PCH_SATA_AHCI_PXSCTL_DET)); + MmioWrite32 (AhciBar + (R_PCH_SATA_AHCI_P0SERR + (0x80 * Index)), (UINT32)~0u); + } + /// + /// If port is offline, and it's not spin up, meets the power bug. + /// Need to do the W/A to spin up the port and then spin down. + /// Then entering back to offline and listen. + /// - Set DET=0, SUD=1, and then set SUD=0, DET=4. + /// + if ((PxSctlDet == V_PCH_SATA_AHCI_PXSCTL_DET_4) && + (PxCmdSud == 0)) + { + MmioAnd32(AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index)), (UINT32) ~(B_PCH_SATA_AHCI_PXSCTL_DET)); + MmioOr32 (AhciBar + (R_PCH_SATA_AHCI_P0CMD + (0x80 * Index)), B_PCH_SATA_AHCI_PxCMD_SUD); + PchPmTimerStall (1000); + MmioAnd32(AhciBar + (R_PCH_SATA_AHCI_P0CMD + (0x80 * Index)), (UINT32) ~(B_PCH_SATA_AHCI_PxCMD_SUD)); + MmioOr32 (AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index)), V_PCH_SATA_AHCI_PXSCTL_DET_4); + } + } + } + /// + /// Restore original CMD word. + /// + if ((OrgCmdWord & B_PCH_SATA_COMMAND_MSE) == 0) { + MmioWrite16 ((PciD31F2RegBase + R_PCH_SATA_COMMAND), OrgCmdWord); + } + } // AhciBar is vaild + } // SATA mode is AHCI or RAID + } // if D31F2 is existed + } + + return; +} + +/** + PCH checkes the HECI protocol and sends ChipsetInitSyncMsg + + @param[in] Event Event objext + @param[in] *Context VOID Pointer + + @retval None +**/ +VOID +EFIAPI +ChipsetInitSyncCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + EFI_HECI_PROTOCOL *Heci; + CHIPSET_INIT_INFO_HOB *ChipsetInitHob; + + ChipsetInitHob = NULL; + Status = EFI_SUCCESS; + DEBUG ((EFI_D_INFO, "ChipsetInitSyncCallback() Start\n")); + + // + // Get the HECI protocol to make sure HECI is ready. + // + Status = gBS->LocateProtocol (&gEfiHeciProtocolGuid, NULL, (VOID **) &Heci); + if (EFI_ERROR (Status)) { + return; + } + + if (mHeciEvent) { + gBS->CloseEvent (mHeciEvent); + } + + // + // Search for the ChipsetInit Info PEIM GUID HOB. + // + ChipsetInitHob = GetFirstGuidHob (&gChipsetInitHobGuid); + if (ChipsetInitHob == NULL) { + DEBUG ((EFI_D_INFO, "ChipsetInitHob not found.\n")); + return; + } + + // + // If ChipsetInitTableUpdReq == 0, settings are already in sync and no furhter work needed + // + if (ChipsetInitHob->ChipsetInitTableUpdReq == 1) { + // + // If we do not have the ChipsetInit table that ME FW expects us to have, + // we must send the current ChipsetInit table to ME FW via HECI message. + // + Status = HeciChipsetInitSyncMsg(ChipsetInitHob->ChipsetInitTable, ChipsetInitHob->ChipsetInitTableLen); + } + + DEBUG ((EFI_D_INFO, "ChipsetInitSyncCallback() End\n")); + + return; +} + +/** + Register the HECI protocol callback function for the ChipsetInit sync message. + + @param[in] *PchPlatformPolicy A pointer to the PchPlatformPolicy. + + @retval EFI_STATUS +**/ +EFI_STATUS +ChipsetInitSettingsCheck ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy + ) +{ + EFI_STATUS Status; + VOID *HeciRegistration; + + DEBUG ((EFI_D_INFO, "ChipsetInitSettingsCheck() Start\n")); + + Status = gBS->CreateEvent ( + EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, + ChipsetInitSyncCallback, + NULL, + &mHeciEvent + ); + ASSERT_EFI_ERROR(Status); + + Status = gBS->RegisterProtocolNotify ( + &gEfiHeciProtocolGuid, + mHeciEvent, + &HeciRegistration + ); + ASSERT_EFI_ERROR(Status); + + ChipsetInitSyncCallback (NULL, NULL); + + return Status; +} + +/** + Update ASL object before Boot + + @param[in] *PchPlatformPolicy A pointer to the PchPlatformPolicy. + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval EFI_STATUS + @retval EFI_NOT_READY The Acpi protocols are not ready. +**/ +EFI_STATUS +PchUpdateAslObjects ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN VariableSize; + UINT32 PciMemBase; + PCH_LATE_INIT_SMM_VARIABLE SaveRestoreData; + UINT32 AslSignature; + UINT32 RpFn; + UINT32 Data32; + + Status = InitializePchAslUpdateLib(); + DEBUG ((EFI_D_INFO, "InitializePchAslUpdateLib Status %x\n", Status)); + ASSERT_EFI_ERROR (Status); + + if(EFI_ERROR(Status)) { + return EFI_NOT_READY; + } + + // + // Update SRMB, Save & Restore Memroy Base + // + VariableSize = sizeof (PCH_LATE_INIT_SMM_VARIABLE); + Status = gRT->GetVariable ( + PCH_INIT_PEI_VARIABLE_NAME, + &gPchInitPeiVariableGuid, + NULL, + &VariableSize, + &SaveRestoreData + ); + PciMemBase = SaveRestoreData.PciMemBase; + Status = UpdateNameAslCode(EFI_SIGNATURE_32('S','R','M','B'), &PciMemBase, sizeof(PciMemBase)); + + RpFn = MmioRead32 (RootComplexBar + R_PCH_RCRB_RPFN); + for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) { + // + // Update RPA0, RPA1, RPA2, RPA3, RPA4, RPA5, RPA6, RPA7 for root port function swapping + // + Data32 = '0' + (UINT32)Index; + AslSignature = EFI_SIGNATURE_32('R','P','A',Data32); + Data32 = (UINT32)((RpFn >> (Index * S_PCH_RCRB_PRFN_RP_FIELD)) & B_PCH_RCRB_RPFN_RP1FN); + Data32 |= (UINT32)(PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS << 16); + Status = UpdateNameAslCode(AslSignature, &Data32, sizeof(UINT32)); + DEBUG ((EFI_D_INFO, "Update RPAx %x %x\n", Index, Data32)); + ASSERT_EFI_ERROR (Status); + + // + // Update Maximum Snoop Latency and Maximum No-Snoop Latency values for PCIE + // + if (PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_7) { + AslSignature = EFI_SIGNATURE_32('P','M','L',(UINT32)('1' + Index)); + Data32 = (UINT32) PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[Index].LtrMaxSnoopLatency; + Status = UpdateNameAslCode(AslSignature, &Data32, sizeof(UINT32)); + DEBUG ((EFI_D_INFO, "Update PMLx %x %x\n", Index+1, Data32)); + ASSERT_EFI_ERROR (Status); + AslSignature = EFI_SIGNATURE_32('P','N','L',(UINT32)('1' + Index)); + Data32 = (UINT32) PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[Index].LtrMaxNoSnoopLatency; + Status = UpdateNameAslCode(AslSignature, &Data32, sizeof(UINT32)); + DEBUG ((EFI_D_INFO, "Update PNLx %x %x\n", Index+1, Data32)); + ASSERT_EFI_ERROR (Status); + } + } + + // + // Update PCHS. + // + Data32 = (UINT32) GetPchSeries(); + Status = UpdateNameAslCode(EFI_SIGNATURE_32('P','C','H','S'), &Data32, sizeof(UINT32)); + + return EFI_SUCCESS; +} + +/** + PCH initialization before Boot Sript Table is closed + + @param[in] Event A pointer to the Event that triggered the callback. + @param[in] Context A pointer to private data registered with the callback function. + + @retval None +**/ +VOID +EFIAPI +PchInitBeforeBoot ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + UINTN NumHandles; + EFI_HANDLE *HandleBuffer; + UINTN Index; + DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy; + UINT32 RootComplexBar; + UINT32 FuncDisableReg; + UINTN PciD25F0RegBase; + UINTN PciD31F2RegBase; + UINT32 GbEMemBar; + UINTN PciD31F0RegBase; + UINTN GbeRootPortNumber; + UINT16 PmBase; + UINT16 GpioBase; + UINT32 Data32And; + UINT32 Data32Or; + UINT32 Data32; + UINT16 Data16And; + UINT16 Data16Or; + UINT8 Data8; + VOID *ProtocolPointer; + UINTN AzaliaBase; + const UINT8 StrEnabled[sizeof (PCH_CRID_ENABLED)] = PCH_CRID_ENABLED; + const UINT8 StrDisabled[sizeof (PCH_CRID_DISABLED)] = PCH_CRID_DISABLED; + EFI_HANDLE Handle; + PCH_SERIES PchSeries; + BOOLEAN L1SubstatesSupportedPerPort; + PCI_DATA_STRUCTURE *PcirBlockPtr; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_EXPANSION_ROM_HEADER *RomImage; + BOOLEAN FoundLegacyRaid; + EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2; + CHAR16 RstDriverName1[] = L"Intel RST"; + CHAR16 RstDriverName2[] = L"Intel(R) RST"; + EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL *DriverEfiVersion; + EFI_STRING DriverName; + UINT16 AspmVal; + BOOLEAN ClkreqPerPortSupported; + BOOLEAN ClkreqSupportedInAllEnabledPorts; + BOOLEAN L1SupportedInAllEnabledPorts; + BOOLEAN FirstRPToSetPm; +#ifdef EFI_S3_RESUME + STATIC EFI_PCH_S3_SUPPORT_PROTOCOL *PchS3Support; +#endif + + UINTN RPBase; + UINT8 PortIndex; + PCH_PCIE_DEVICE_ASPM_OVERRIDE *S3DevAspmOverrideTbl; + PCH_PCIE_PWR_OPT *S3PchPwrOptPcie; + UINT32 DevAspmOverrideTblSize; + PCH_PCI_EXPRESS_ASPM_CONTROL RootPortAspmVal; + UINT8 NumOfDevltrOverride; + PCH_PCIE_DEVICE_LTR_OVERRIDE *S3DevLtrOverrideTbl; + PCH_PCIE_DEVICE_LTR_OVERRIDE *DevLtrOverrideTbl; + UINT32 DevLtrOverrideTblSize; + PCH_PCIE_EXPRESS_L1SUBSTATES_CONTROL L1SubVal; + BOOLEAN LtrSupported; + + S3DevLtrOverrideTbl = NULL; + DevLtrOverrideTbl = NULL; + NumOfDevltrOverride = 0; + LtrSupported = TRUE; + L1SubstatesSupportedPerPort = FALSE; + Handle = NULL; + PchSeries = GetPchSeries(); + AspmVal = 0; + ClkreqPerPortSupported = FALSE; + ClkreqSupportedInAllEnabledPorts = TRUE; + L1SupportedInAllEnabledPorts = TRUE; + FirstRPToSetPm = TRUE; + + /// + /// Check whether this is real ExitPmAuth notification, or just a SignalEvent + /// + Status = gBS->LocateProtocol (&gExitPmAuthProtocolGuid, NULL, (VOID **) &ProtocolPointer); + if (EFI_ERROR (Status)) { + return; + } + + DEBUG ((EFI_D_INFO, "PchInitBeforeBoot() Start\n")); + + /// + /// Closed the event to avoid call twice when launch shell + /// + gBS->CloseEvent (Event); + + /// + /// Retrieve all instances of PCH Platform Policy protocol + /// + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gDxePchPlatformPolicyProtocolGuid, + NULL, + &NumHandles, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR | EFI_D_INFO, "Failed to locate handle buffer for PCH Policy protocol.\n")); + return; + } + /// + /// Find the matching PCH Policy protocol + /// + for (Index = 0; Index < NumHandles; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gDxePchPlatformPolicyProtocolGuid, + (VOID **) &PchPlatformPolicy + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR | EFI_D_INFO, "Failed to find PCH Policy protocol.\n")); + return; + } + + InitFviDataHubCbContext ( + PchPlatformPolicy->MiscConfig->FviSmbiosType, + (UINT8) mPchFviElements, + &mPchFviVersionData + ); + + RootComplexBar = PCH_RCRB_BASE; + + FuncDisableReg = MmioRead32 (RootComplexBar + R_PCH_RCRB_FUNC_DIS); + PciD31F0RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 0, 0); + GpioBase = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_GPIO_BASE) & B_PCH_LPC_GPIO_BASE_BAR; + PmBase = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_ACPI_BASE) & B_PCH_LPC_ACPI_BASE_BAR; + + Status = PciERWORegInit (PchPlatformPolicy, RootComplexBar, &FuncDisableReg); + ASSERT_EFI_ERROR (Status); + + /// + /// Locking Thermal Reporting Settings prior to end of POST + /// + Status = ThermalLockDown (PchPlatformPolicy, GpioBase); + ASSERT_EFI_ERROR (Status); + + if ((FuncDisableReg & B_PCH_RCRB_FUNC_DIS_AZALIA) == 0) { + AzaliaBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_AZALIA, + PCI_FUNCTION_NUMBER_PCH_AZALIA, + 0 + ); + /// + /// PCH BIOS Spec Rev 0.5.0 Section 9.5 + /// Additional High Definition Audio Programming Steps + /// Step 5 + /// Set D27:F0:40h[1] = 1b after all settings done including 19.10.5 + /// + MmioOr8 (AzaliaBase + R_PCH_HDA_HDCTL, B_PCH_HDA_HDCTL_BCLD); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (AzaliaBase + R_PCH_HDA_HDCTL), + 1, + (VOID *) (UINTN) (AzaliaBase + R_PCH_HDA_HDCTL) + ); + } + /// + /// PCH BIOS Spec Rev 0.5.0 Section 19.4 + /// Step 29 + /// Set RCBA + Offset 3A6Ch[31:0] = 0x00000001, after step #26 to #28 are done + /// + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A6C), + (UINT32) (0x00000001) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A6C), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A6C) + ); + if (PchSeries == PchH) { + /// + /// PCH BIOS Spec Rev 0.5.5, Section 19.4 Additional Power Management Programming + /// Step 30 + /// Set RCBA + Offset 2344h[31:24] = 0xFF + /// Set RCBA + Offset 2344h[7:0] = 0x0C + /// + Data32And = (UINT32)~(0xFF00000F); + Data32Or = (UINT32) (0xFF00000C); + MmioAndThenOr32 ( + (UINTN) (RootComplexBar + 0x2344), + Data32And, + Data32Or + ); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x2344), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + } else if (PchSeries == PchLp) { + /// + /// PCH BIOS Spec Rev 0.3.0 Section 31.7.2 + /// Step 5 + /// Set RCBA + Offset 2618h [25] = 1b. + /// + MmioOr32 ( + (UINTN) (RootComplexBar + 0x2618), + (UINT32) (BIT25) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x2618), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x2618) + ); + } +/* // [ EIP357393 ]+>>> + /// + /// SPI Flash Programming Guide Section 5.5.1 Flash Configuration Lockdown + /// It is strongly recommended that BIOS sets the Host and GbE Flash Configuration Lock-Down (FLOCKDN) + /// bits (located at SPIBAR + 04h and MBAR + 04h respectively) to 1 on production platforms + /// + if (PchSeries == PchH) { + MmioOr16 ((UINTN) (RootComplexBar + R_PCH_SPI_HSFS), (UINT16) (B_PCH_SPI_HSFS_FLOCKDN + B_PCH_SPI_PRR3PRR4_LOCKDN)); + } else if (PchSeries == PchLp) { + MmioOr16 ((UINTN) (RootComplexBar + R_PCH_SPI_HSFS), (UINT16) (B_PCH_SPI_HSFS_FLOCKDN)); + } + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RootComplexBar + R_PCH_SPI_HSFS), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_SPI_HSFS) + ); +*/ // [ EIP357393 ]+<<< + + /// + /// Set the GbE Flash Configuration Lock-Down (FLOCKDN) bit (MBAR + 04h[15]) to 1 + /// + if (PchPlatformPolicy->DeviceEnabling->Lan == PCH_DEVICE_ENABLE) { + PciD25F0RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 25, 0, 0); + /// + /// Enable memory space decoding in command register + /// + Data16And = 0xFFFF; + Data16Or = (UINT16) B_PCH_LAN_CMD_MSE; + MmioOr16 (PciD25F0RegBase + R_PCH_LAN_CMD, Data16Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD25F0RegBase + R_PCH_LAN_CMD), + &Data16Or, // Data to be ORed + &Data16And // Data to be ANDed + ); + +/* // [ EIP357393 ]+>>> + GbEMemBar = MmioRead32 (PciD25F0RegBase + R_PCH_LAN_MBARB) & B_PCH_LAN_MBARB_BA; + /// + /// Assert if the memory data of GbEMemBar is invalid. + /// + if (MmioRead32 (GbEMemBar) == 0xFFFFFFFF) { + ASSERT (FALSE); + } else { + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD25F0RegBase + R_PCH_LAN_MBARB), + 1, + (VOID *) (UINTN) (PciD25F0RegBase + R_PCH_LAN_MBARB) + ); + MmioOr16 (GbEMemBar + 0x04, BIT15); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (GbEMemBar + 0x04), + 1, + (VOID *) (UINTN) (GbEMemBar + 0x04) + ); + } +*/ // [ EIP357393 ]+<<< + + /// + /// PCH BIOS Spec Rev 0.5.0 Section 10.5 Additional GbE Controller Configurations for WOL Support + /// System BIOS requires to program the registers listed below for internal GbE. + /// Step 1, Set MBARA + Offset 2Ch [31] = 1b + /// Step 2, If WOL is enabled set MBARA + Offset 2Ch [30] = 1b + /// else if disabled set MBARA + Offset 2Ch [30] = 0b + /// + /// Additional Steppings: + /// Set MBARA + Offset 10h [31] = 1b + /// + GbEMemBar = MmioRead32 (PciD25F0RegBase + R_PCH_LAN_MEM_BASE_A) & B_PCH_LAN_MBARA_BA; + /// + /// Assert if the memory data of GbEMemBar is invalid. + /// + if (MmioRead32 (GbEMemBar) == 0xFFFFFFFF) { + ASSERT (FALSE); + } else { + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD25F0RegBase + R_PCH_LAN_MEM_BASE_A), + 1, + (VOID *) (UINTN) (PciD25F0RegBase + R_PCH_LAN_MEM_BASE_A) + ); + MmioOr32 (GbEMemBar + 0x2c, (BIT31)); + if (PchPlatformPolicy->MiscPmConfig->WakeConfig.WolEnableOverride) { + MmioOr32 (GbEMemBar + 0x2c, (BIT30)); + } else { + MmioAnd32 (GbEMemBar + 0x2c, (UINT32) (~BIT30)); + } + + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (GbEMemBar + 0x2c), + 1, + (VOID *) (UINTN) (GbEMemBar + 0x2c) + ); + + /// + /// Set GbEMemBar + 0x10[31] to 1b if Gbe Clkreq is in native mode (0b) + /// + if (PchSeries == PchLp) { + GbeRootPortNumber = PchGetGbePortNumber(); + Data32 = (IoRead32 ((UINTN) (GpioBase + R_PCH_GP_X_CONFIG0(18 + GbeRootPortNumber))) & B_PCH_GPIO_OWN0_GPIO_USE_SEL); + if (Data32 == 0) { + MmioOr32 (GbEMemBar + 0x10, BIT31); + } else { + MmioAnd32 (GbEMemBar + 0x10, (UINT32) (~BIT31)); + } + + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (GbEMemBar + 0x10), + 1, + (VOID *) (UINTN) (GbEMemBar + 0x10) + ); + } + } + } + /// + /// PCH BIOS Spec Rev 0.5.0 section 14.1.7 Additional Programming Requirements during + /// SATA Initialization + /// Step 11 + /// Program D31:F2:98h [29] to 1b + /// + PciD31F2RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 2, 0); + MmioOr32 ((UINTN) (PciD31F2RegBase + 0x98), BIT29); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F2RegBase + 0x98), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + 0x98) + ); + /// + /// Step 14 + /// Program D31:F2:9Ch [31] to 1b + /// + MmioOr32 ((UINTN) (PciD31F2RegBase + 0x9C), BIT31); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F2RegBase + 0x9C), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + 0x9C) + ); + /// + /// Do the Pcie ASPM enable prior to the end of POST + /// + /// PCH BIOS Spec Rev 0.5.0, Section 8.3.1 ASPM on DMI and the PCI Express* Root Ports + /// + /// Allcoate and Copy the entire Aspm override table pointed by DevAspmOverride to < 4G EfiReservedMemory + /// It's for S3 resume used. + /// + DevAspmOverrideTblSize = PchPlatformPolicy->PciExpressConfig->NumOfDevAspmOverride * + sizeof (PCH_PCIE_DEVICE_ASPM_OVERRIDE); + S3DevAspmOverrideTbl = AllocateReservedCopyPool ( + DevAspmOverrideTblSize, + PchPlatformPolicy->PciExpressConfig->DevAspmOverride + ); + ASSERT_EFI_ERROR (S3DevAspmOverrideTbl != NULL); + + /// + /// Allcoate and Copy the entire LTR override table pointed by DevLtrOverride to < 4G EfiReservedMemory + /// It's used for S3 resume used. + /// + DevLtrOverrideTbl = PchPlatformPolicy->PwrOptConfig->DevLtrOverride; + NumOfDevltrOverride = PchPlatformPolicy->PwrOptConfig->NumOfDevLtrOverride; + if ((DevLtrOverrideTbl != NULL) && (NumOfDevltrOverride != 0)) { + DevLtrOverrideTblSize = NumOfDevltrOverride * sizeof (PCH_PCIE_DEVICE_LTR_OVERRIDE); + S3DevLtrOverrideTbl = AllocateReservedCopyPool ( + DevLtrOverrideTblSize, + DevLtrOverrideTbl + ); + ASSERT_EFI_ERROR (S3DevLtrOverrideTbl != NULL); + } + /// + /// Check all the enabled root ports and end point devices if they support Clkreq Per Port, L1 and L1 substates + /// + for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex++) { + RPBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, GetPchPcieRpfn(RootComplexBar, PortIndex), 0); + if (((FuncDisableReg & (B_PCH_RCRB_FUNC_DIS_PCI_EX_PORT1 << PortIndex)) == 0) && ((MmioRead16 (RPBase + R_PCH_PCIE_SLSTS) & B_PCH_PCIE_SLSTS_PDS) != 0)) { + RootPortAspmVal = PchPlatformPolicy->PciExpressConfig->RootPort[PortIndex].Aspm; + L1SubVal = PchPcieL1SubstatesL1_1_2; + if (PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_2) { + L1SubVal = PchPlatformPolicy->PciExpressConfig->RootPort[PortIndex].L1Substates; + } + Status = PcieCheckPmConfig ( + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + GetPchPcieRpfn(RootComplexBar, PortIndex), + RootPortAspmVal, + PchPlatformPolicy->PciExpressConfig->NumOfDevAspmOverride, + PchPlatformPolicy->PciExpressConfig->DevAspmOverride, + PchPlatformPolicy->PciExpressConfig->TempRootPortBusNumMin, + PchPlatformPolicy->PciExpressConfig->TempRootPortBusNumMax, + NumOfDevltrOverride, + DevLtrOverrideTbl, + &(PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[PortIndex]), + &L1SubstatesSupportedPerPort, + L1SubVal, + PchPlatformPolicy->Revision, + &AspmVal, + &ClkreqPerPortSupported, + &LtrSupported + ); + if ((AspmVal & V_PCH_PCIE_LCTL_APMC_L1) != V_PCH_PCIE_LCTL_APMC_L1) { + L1SupportedInAllEnabledPorts = FALSE; + } + ClkreqSupportedInAllEnabledPorts &= ClkreqPerPortSupported; + } + } + for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex++) { + if ((FuncDisableReg & (B_PCH_RCRB_FUNC_DIS_PCI_EX_PORT1 << PortIndex)) == 0) { + S3PchPwrOptPcie = AllocateReservedCopyPool ( + sizeof (PCH_PCIE_PWR_OPT), + &PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[PortIndex] + ); + ASSERT_EFI_ERROR (S3PchPwrOptPcie != NULL); + RootPortAspmVal = PchPlatformPolicy->PciExpressConfig->RootPort[PortIndex].Aspm; + L1SubVal = PchPcieL1SubstatesL1_1_2; + if (PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_2) { + L1SubVal = PchPlatformPolicy->PciExpressConfig->RootPort[PortIndex].L1Substates; + } + Status = PcieSetPm ( + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + GetPchPcieRpfn(RootComplexBar, PortIndex), + RootPortAspmVal, + PchPlatformPolicy->PciExpressConfig->NumOfDevAspmOverride, + PchPlatformPolicy->PciExpressConfig->DevAspmOverride, + PchPlatformPolicy->PciExpressConfig->TempRootPortBusNumMin, + PchPlatformPolicy->PciExpressConfig->TempRootPortBusNumMax, + NumOfDevltrOverride, + DevLtrOverrideTbl, + &(PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[PortIndex]), + &L1SubstatesSupportedPerPort, + L1SubVal, + PchPlatformPolicy->Revision, + FirstRPToSetPm, + L1SupportedInAllEnabledPorts, + ClkreqSupportedInAllEnabledPorts, + &LtrSupported + ); + Status = SetPciePmS3Item ( + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + GetPchPcieRpfn(RootComplexBar, PortIndex), + RootPortAspmVal, + PchPlatformPolicy->PciExpressConfig->NumOfDevAspmOverride, + S3DevAspmOverrideTbl, + PchPlatformPolicy->PciExpressConfig->TempRootPortBusNumMin, + PchPlatformPolicy->PciExpressConfig->TempRootPortBusNumMax, + NumOfDevltrOverride, + S3DevLtrOverrideTbl, + S3PchPwrOptPcie, + L1SubVal, + PchPlatformPolicy->Revision, + FirstRPToSetPm, + L1SupportedInAllEnabledPorts, + ClkreqSupportedInAllEnabledPorts + ); + FirstRPToSetPm = FALSE; + } + } + /// + /// LPT-LP only: If not all devices support LTR, set RCBA + 0x3320 to 0x00010003 + /// + if (!LtrSupported && (PchSeries == PchLp) ) { + MmioAndThenOr32 ( (RootComplexBar + 0x3320), 0, 0x00010003); + } + /// + /// SPI Flash Programming Guide Section 5.5.2 Vendor Component Lock + /// It is strongly recommended that BIOS sets the Vendor Component Lock (VCL) bits. VCL applies + /// the lock to both VSCC0 and VSCC1 even if VSCC0 is not used. Without the VCL bits set, it is + /// possible to make Host/GbE VSCC register(s) changes in that can cause undesired host and + /// integrated GbE Serial Flash functionality. + /// + MmioOr32 ((UINTN) (RootComplexBar + R_PCH_SPI_VSCC0), B_PCH_SPI_VSCC0_VCL); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_SPI_VSCC0), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_SPI_VSCC0) + ); + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 19.4 Additional Power Management Programming + /// Step 3 + /// Set GEN_PMCON_LOCK register, D31:F0:A6h = 06h, after stretch and ACPI base programming completed. + /// + MmioOr8 ( + (UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_LOCK), + (UINT8) (B_PCH_LPC_GEN_PMCON_LOCK_S4_STRET_LD | B_PCH_LPC_GEN_PMCON_LOCK_ABASE_LK) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_LOCK), + 1, + (VOID *) (UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_LOCK) + ); + /// + /// PCH BIOS Spec Rev 0.5.0, Section 3.6 Flash Security Recommendation + /// Step 1 + /// Intel strongly recommends that BIOS enables the BIOS Lock Enable (BLE) feature of the PCH. + /// Left to platform code to register an callback function to handle IchnBiosWp SMI + /// + /// Step 2 + /// Intel strongly recommends that BIOS enables SMI_LOCK (B0:D31:F0:Offset A0h [4]=1) + /// which prevent writes to the Global SMI Enable bit (GLB_SMI_EN PMBASE + 30h Bit + /// [0]). Enabling this bit will mitigate malicious software attempts to gain system management + /// mode privileges. + /// + if (PchPlatformPolicy->LockDownConfig->GlobalSmi == PCH_DEVICE_ENABLE) { + /// + /// Save Global SMI Enable bit setting before BIOS enables SMI_LOCK during S3 resume + /// + Data32Or = IoRead32 ((UINTN) (PmBase + R_PCH_SMI_EN)); + if ((Data32Or & B_PCH_SMI_EN_GBL_SMI) != 0) { + Data32And = 0xFFFFFFFF; + Data32Or &= B_PCH_SMI_EN_GBL_SMI; + SCRIPT_IO_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PmBase + R_PCH_SMI_EN), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + } + + MmioOr8 ((UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1), B_PCH_LPC_GEN_PMCON_SMI_LOCK); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1), + 1, + (VOID *) (UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1) + ); + } + /// + /// Step 3 + /// Intel strongly recommends that BIOS sets the BIOS Interface Lock Down bit + /// (RCBA+3410[0]=1 General Control and Status - BILD). Setting this bit will prevent writes + /// to the Backup Control Register Top Swap bit (BUC.TS RCBA + 3414 [0]) and the General + /// Control and Status Registers Boot BIOS Straps (RCBA + 3410h [11:10]). Enabling this bit + /// will mitigate malicious software attempts to replace the system BIOS option ROM with its own code. + /// + if (PchPlatformPolicy->LockDownConfig->BiosInterface == PCH_DEVICE_ENABLE) { + MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_GCS), (UINT32) B_PCH_RCRB_GCS_BILD); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_GCS), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_GCS) + ); + /// + /// Reads back for posted write to take effect + /// + Data32Or = MmioRead32 ((UINTN) (RootComplexBar + R_PCH_RCRB_GCS)); + SCRIPT_MEM_POLL ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_GCS), + &Data32Or, // BitMask + &Data32Or, // BitValue + 1, // Duration + 1 // LoopTimes + ); + } + /// + /// PCH EDS Rev 1.0, Section 14.1.35.1.2 + /// SATA Indexed Register 1Ch Bit18, 1 = This bit allows entrance to the PCH SATA test modes when set. + /// This bit should only be set when following the PCH MSQT for system board testing. + /// It is recommended to set this bit manually. + /// + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 5.15 IntelR Stable Image Platform Program (SIPP) + /// For platforms supporting Intel(R) SIPP, System BIOS will need to enable the CRID feature by: + /// Write the value 1Dh to to the RevID field in B0:D31:F0 Offset 08h + /// + + /// + /// Update CRID FVI record + /// + mPchFviElementsData[CRID_ORIGINAL].Element.Version.BuildNum = (UINT16) MmioRead8 ((UINTN) (PciD31F0RegBase + R_PCH_LPC_RID)); + if (PchPlatformPolicy->DeviceEnabling->Crid == PCH_DEVICE_ENABLE) { + Data8 = 0x1D; + MmioWrite8 ((UINTN) (PciD31F0RegBase + R_PCH_LPC_RID), Data8); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciD31F0RegBase + R_PCH_LPC_RID), + 1, + &Data8 + ); + CopyMem (mPchFviElementsData[CRID_STATUS].Element.VerString, StrEnabled, sizeof (StrEnabled)); + } else { + CopyMem (mPchFviElementsData[CRID_STATUS].Element.VerString, StrDisabled, sizeof (StrDisabled)); + } + + mPchFviElementsData[CRID_NEW].Element.Version.BuildNum = (UINT16) MmioRead8 ((UINTN) (PciD31F0RegBase + R_PCH_LPC_RID)); + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 16.4 GPIO Registers Lockdown + /// If GPIO configurations are not used after boot, it is recommended that the GLE Lockdown Enable + /// and the GPIO_UNLOCK_SMI_EN bits are set by BIOS prior to end of POST. + /// + if (PchPlatformPolicy->LockDownConfig->GpioLockDown == PCH_DEVICE_ENABLE) { + /// + /// Set GPIO Lockdown Enable bit + /// + MmioOr8 ((UINTN) (PciD31F0RegBase + R_PCH_LPC_GPIO_CNT), (UINT8) B_PCH_LPC_GPIO_LOCKDOWN_EN); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciD31F0RegBase + R_PCH_LPC_GPIO_CNT), + 1, + (VOID *) (UINTN) (PciD31F0RegBase + R_PCH_LPC_GPIO_CNT) + ); + /// + /// Please locate SMM ICHn SMI Dispatch Extended Protocol and register the callback function to + /// IchnExGpioUnlock to set GPIO_UNLOCK_SMI_EN bit in the platform code. + /// + } + /// + /// PCH BIOS Spec Rev 0.5.0, Section 5.13 BIOS guide on using RTC RAM + /// For Data integrity protection, set RTC Memory locks (Upper 128 Byte Lock and + /// Lower 128 Byte Lock) at RCBA + 3400h[4] and RCBA + 3400h[3]. Note once locked + /// bytes 0x38 - 0x3F in each of the Upper and Lower Byte blocks, respectively, + /// cannot be unlocked until next reset. + /// + if (PchPlatformPolicy->LockDownConfig->RtcLock == PCH_DEVICE_ENABLE) { + MmioOr32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_RTC_CONF), + (UINT32) (B_PCH_RCRB_RTC_CONF_UCMOS_LOCK | B_PCH_RCRB_RTC_CONF_LCMOS_LOCK) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_RTC_CONF), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_RTC_CONF) + ); + } + /// + /// + /// PCH BIOS Spec Rev 0.5.0, Section 3.6 Flash Security Recommendation + /// Step 1 + /// BIOS needs to enable the BIOS Lock Enable (BLE) feature of the PCH by setting + /// B0:D31:F0:DCh[1] = 1b. When this bit is set, attempts to write the BIOS Write + /// Enable (BIOSWE) bit in PCH will cause a SMI which will allow the BIOS to verify + /// that the write is from a valid source. Remember that BIOS needs to set B0:D31:F0 + /// Offset DC [0] = 0b to enable BIOS region protection before exiting the SMI handler. + /// Also, TCO_EN bit needs to be set (SMI_EN Register, PMBASE + 30h[13] = 1b) to keep + /// BLE feature enabled after booting to the OS. + /// + /// Generate PCH IO TRAP SMI to register IchnBiosWp callback function in + /// PchBiosLockIoTrapCallback() to handle TCO BIOSWR SMI + /// + if ((PchPlatformPolicy->LockDownConfig->BiosLock == PCH_DEVICE_ENABLE)) { + DEBUG ( + (EFI_D_ERROR, + "PchBiosLockIoTrapAddress = 0x%x\n", + PchPlatformPolicy->LockDownConfig->PchBiosLockIoTrapAddress) + ); + + if (PchPlatformPolicy->LockDownConfig->PchBiosLockIoTrapAddress != 0) { + /// + /// Write PCH_BWP_SIGNATURE to IoTrap Address + /// + IoWrite32 (PchPlatformPolicy->LockDownConfig->PchBiosLockIoTrapAddress, PCH_BWP_SIGNATURE); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciD31F0RegBase + R_PCH_LPC_BIOS_CNTL), + 1, + (VOID *) (UINTN) (PciD31F0RegBase + R_PCH_LPC_BIOS_CNTL) + ); + } + } + /// + /// Lock Down TCO + /// + Data16And = 0xFFFF; + Data16Or = B_PCH_TCO_CNT_LOCK; + IoOr16(PmBase + PCH_TCO_BASE + R_PCH_TCO1_CNT, Data16Or); + SCRIPT_IO_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PmBase + PCH_TCO_BASE + R_PCH_TCO1_CNT), + &Data16Or, // Data to be ORed + &Data16And // Data to be ANDed + ); + /// + /// PCH BIOS Spec Rev 0.5.0, Section 5.15.1 Additional Chipset Initialization + /// Step 1 + /// Set SPIBAR + F0h [0] to 1b + /// + MmioOr8 ((UINTN) (RootComplexBar + R_PCH_SPI_SRDL), B_PCH_SPI_SRDL_SSL); + /// + /// Check to disable Smbus controller + /// + if (PchPlatformPolicy->DeviceEnabling->Smbus == PCH_DEVICE_DISABLE) { + MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_FUNC_DIS), (UINT32) B_PCH_RCRB_FUNC_DIS_SMBUS); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_FUNC_DIS), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_FUNC_DIS) + ); + /// + /// Reads back for posted write to take effect + /// + Data32Or = MmioRead32 ((UINTN) (RootComplexBar + R_PCH_RCRB_FUNC_DIS)); + SCRIPT_MEM_POLL ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_FUNC_DIS), + &Data32Or, // BitMask + &Data32Or, // BitValue + 1, // Duration + 1 // LoopTimes + ); + } + + UsbInitBeforeBoot (PchPlatformPolicy); + FoundLegacyRaid = FALSE; + /// + /// Get all PCI IO protocols + /// + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &NumHandles, + &HandleBuffer + ); + if (!EFI_ERROR (Status)) { + /// + /// Find the RAID BIOS by checking each PCI IO handle for RST OPROM + /// + for (Index = 0; Index < NumHandles; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + if (EFI_ERROR (Status) || (PciIo->RomImage == NULL)) { + /// + /// If this PCI device doesn't have a ROM image, skip to the next device. + /// + continue; + } + + RomImage = PciIo->RomImage; + + /// + /// Get pointer to PCIR structure + /// + PcirBlockPtr = (PCI_DATA_STRUCTURE *) ((UINTN) RomImage + RomImage->PcirOffset); + + /// + /// Check if we have an RAID BIOS OPROM. + /// + if ((RomImage->Signature == 0xAA55) && + (PcirBlockPtr->ClassCode[0] == 0x00) && + (PcirBlockPtr->ClassCode[1] == 0x04) && + (PcirBlockPtr->ClassCode[2] == 0x01) + ) { + mPchFviElementsData[RAID_VER].Element.Version.MajorVersion = (UINT8) ((PcirBlockPtr->CodeRevision & 0xFF00) >> 8); + mPchFviElementsData[RAID_VER].Element.Version.MinorVersion = (UINT8) (PcirBlockPtr->CodeRevision & 0x00FF); + mPchFviElementsData[RAID_VER].Element.Version.Revision = 0; + mPchFviElementsData[RAID_VER].Element.Version.BuildNum = 0; + FoundLegacyRaid = TRUE; + } + } + } + /// + /// Search EFI RST OPROM + /// + if (FoundLegacyRaid == FALSE) { + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDriverSupportedEfiVersionProtocolGuid, + NULL, + &NumHandles, + &HandleBuffer + ); + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < NumHandles; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiComponentName2ProtocolGuid, + (VOID **) &ComponentName2 + ); + if (EFI_ERROR(Status)) { + continue; + } + + Status = ComponentName2->GetDriverName (ComponentName2, LANGUAGE_CODE_ENGLISH, &DriverName); + if (EFI_ERROR(Status)) { + continue; + } + + if ((StrnCmp (DriverName, RstDriverName1, (sizeof (RstDriverName1) / sizeof (CHAR16)) - 1) == 0) || + (StrnCmp (DriverName, RstDriverName2, (sizeof (RstDriverName2) / sizeof (CHAR16)) - 1) == 0)) { + Status = gBS->HandleProtocol( + HandleBuffer[Index], + &gEfiDriverSupportedEfiVersionProtocolGuid, + (VOID**)&DriverEfiVersion); + mPchFviElementsData[RAID_VER].Element.Version.MajorVersion = (UINT8) ((DriverEfiVersion->FirmwareVersion & 0x00FF0000) >> 16); + mPchFviElementsData[RAID_VER].Element.Version.MinorVersion = (UINT8) (DriverEfiVersion->FirmwareVersion & 0x000000FF); + mPchFviElementsData[RAID_VER].Element.Version.Revision = 0; + mPchFviElementsData[RAID_VER].Element.Version.BuildNum = 0; + } + } + } + } + + if (PchSeries == PchLp) { +#ifdef SERIAL_IO_FLAG + ConfigureSerialIoBeforeBoot(PchPlatformPolicy, RootComplexBar); +#endif // SERIAL_IO_FLAG +#ifdef ADSP_FLAG + ConfigureAudioDspBeforeBoot (PchPlatformPolicy, RootComplexBar); +#endif // ADSP_FLAG + } + + // + // Update ASL objects + // + PchUpdateAslObjects (PchPlatformPolicy, RootComplexBar); + + // + // Create RC FVI data hubs + // + CreateRcFviDatahub (&mPchFviVersionData); + } + +#ifdef EFI_S3_RESUME + if (!PchS3Support) { + DEBUG ((EFI_D_INFO, "Locating the S3 Support Protocol - PCH Init before Boot\n")); + + /// + /// Get the PCH S3 Support Protocol + /// + Status = gBS->LocateProtocol ( + &gEfiPchS3SupportProtocolGuid, + NULL, + (VOID **) &PchS3Support + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return; + } + + Status = PchS3Support->ReadyToLock(PchS3Support); + if (EFI_ERROR (Status)) { + return; + } + + } +#endif + + DEBUG ((EFI_D_INFO, "PchInitBeforeBoot() End\n")); + + return; +} + +// [ EIP357393 ]+>>> +EFI_STATUS +EFIAPI +PchSpiLockBeforeEndOfDxe ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + Locking SPI configuration before End of Dxe + +Arguments: + + Event A pointer to the Event that triggered the callback. + Context A pointer to private data registered with the callback function. + +Returns: + + EFI_SUCCESS The function completed successfully + + --*/ +{ + EFI_STATUS Status; + UINTN NumHandles; + EFI_HANDLE *HandleBuffer; + UINTN Index; + DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy; + UINT32 RootComplexBar; + UINTN PciD25F0RegBase; + UINT32 GbEMemBar; + PCH_SERIES PchSeries = GetPchSeries(); +// UINT32 Data32And; +// UINT32 Data32Or; + UINT16 Data16And; + UINT16 Data16Or; +// UINT8 Data8; + VOID *ProtocolPointer; + + // + // Check whether this is real AMI ExtPciBusProtocol notification, or just a SignalEvent + // + Status = gBS->LocateProtocol (&gAmiExtPciBusProtocolGuid, NULL, &ProtocolPointer); + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + // + // Closed the event to avoid call twice when launch shell + // + gBS->CloseEvent (Event); + + + // + // Retrieve all instances of PCH Platform Policy protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gDxePchPlatformPolicyProtocolGuid, + NULL, + &NumHandles, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR | EFI_D_INFO, "Failed to locate handle buffer for PCH Policy protocol.\n")); + return Status; + } + // + // Find the matching PCH Policy protocol + // + for (Index = 0; Index < NumHandles; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gDxePchPlatformPolicyProtocolGuid, + &PchPlatformPolicy + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR | EFI_D_INFO, "Failed to find PCH Policy protocol.\n")); + return Status; + } + + RootComplexBar = PCH_RCRB_BASE; + + /// + /// SPI Flash Programming Guide Section 5.5.1 Flash Configuration Lockdown + /// It is strongly recommended that BIOS sets the Host and GbE Flash Configuration Lock-Down (FLOCKDN) + /// bits (located at SPIBAR + 04h and MBAR + 04h respectively) to 1 on production platforms + /// + if (PchSeries == PchH) { + MmioOr16 ((UINTN) (RootComplexBar + R_PCH_SPI_HSFS), (UINT16) (B_PCH_SPI_HSFS_FLOCKDN + B_PCH_SPI_PRR3PRR4_LOCKDN)); + } else if (PchSeries == PchLp) { + MmioOr16 ((UINTN) (RootComplexBar + R_PCH_SPI_HSFS), (UINT16) (B_PCH_SPI_HSFS_FLOCKDN)); + } + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RootComplexBar + R_PCH_SPI_HSFS), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_SPI_HSFS) + ); + // + // Set the GbE Flash Configuration Lock-Down (FLOCKDN) bit (MBAR + 04h[15]) to 1 + // + if (PchPlatformPolicy->DeviceEnabling->Lan == PCH_DEVICE_ENABLE) { + PciD25F0RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 25, 0, 0); + GbEMemBar = MmioRead32 (PciD25F0RegBase + R_PCH_LAN_MBARB) & B_PCH_LAN_MBARB_BA; + if (GbEMemBar) { + // + // Enable memory space decoding in command register + // + Data16And = 0xFFFF; + Data16Or = (UINT16) B_PCH_LAN_CMD_MSE; + MmioOr16 (PciD25F0RegBase + R_PCH_LAN_CMD, Data16Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD25F0RegBase + R_PCH_LAN_CMD), + &Data16Or, // Data to be ORed + &Data16And // Data to be ANDed + ); + + /// + /// Assert if the memory data of GbEMemBar is invalid. + /// + if (MmioRead32 (GbEMemBar) == 0xFFFFFFFF) { + ASSERT (FALSE); + } else { + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD25F0RegBase + R_PCH_LAN_MBARB), + 1, + (VOID *) (UINTN) (PciD25F0RegBase + R_PCH_LAN_MBARB) + ); + MmioOr16 (GbEMemBar + 0x04, BIT15); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (GbEMemBar + 0x04), + 1, + (VOID *) (UINTN) (GbEMemBar + 0x04) + ); + } + } + } + } + return EFI_SUCCESS; +} +// [ EIP357393 ]+<<< diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInit.dxs b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInit.dxs new file mode 100644 index 0000000..5e1ad9a --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInit.dxs @@ -0,0 +1,48 @@ +/** @file + Dispatch dependency expression file for the PchInit driver. + +@copyright + Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains a 'Sample Driver' and is licensed as such + under the terms of your license agreement with Intel or your + vendor. This file may be modified by the user, subject to + the additional terms of the license agreement + +**/ + +// +// Common for R8 and R9 codebase +// +#include "AutoGen.h" +#include "DxeDepex.h" + +// +// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase; +// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version +// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase. +// +#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB) +#include "EfiDepex.h" + +#include EFI_PROTOCOL_DEFINITION (BootScriptSave) +#include EFI_PROTOCOL_DEFINITION (PchPlatformPolicy) +#include EFI_PROTOCOL_DEFINITION (PchS3Support) +#include EFI_PROTOCOL_DEFINITION (SmmControl) +#endif + +DEPENDENCY_START +#ifdef EFI_S3_RESUME + EFI_BOOT_SCRIPT_SAVE_PROTOCOL_GUID AND + EFI_PCH_S3_SUPPORT_PROTOCOL_GUID AND +#endif + DXE_PCH_PLATFORM_POLICY_PROTOCOL_GUID AND + EFI_SMM_CONTROL_PROTOCOL_GUID +DEPENDENCY_END diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInit.h b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInit.h new file mode 100644 index 0000000..a99c375 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInit.h @@ -0,0 +1,653 @@ +/** @file + Header file for PCH Initialization Driver. + +@copyright + Copyright (c) 1999 - 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#ifndef _PCH_INITIALIZATION_DRIVER_H_ +#define _PCH_INITIALIZATION_DRIVER_H_ + +// +// External include files do NOT need to be explicitly specified in real EDKII +// environment +// +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) + +#include "EdkIIGlueDxe.h" +#include "EfiScriptLib.h" + +// +// Driver Consumed Protocol Prototypes +// +#include EFI_PROTOCOL_CONSUMER (PchPlatformPolicy) +#include EFI_PROTOCOL_CONSUMER (BootScriptSave) +#include EFI_PROTOCOL_CONSUMER (ExitPmAuth) +#include EFI_PROTOCOL_CONSUMER (PchS3Support) +#include EFI_PROTOCOL_PRODUCER (PchInfo) +#include EFI_PROTOCOL_CONSUMER (DriverSupportedEfiVersion) +#include EFI_GUID_DEFINITION (ChipsetInitHob) + +#include "PchAccess.h" +#include "PchPlatformLib.h" +#include "PchPciExpressHelpersLib.h" +#include "PchUsbCommon.h" +#include "PchHsio.h" +#include "Pci22.h" +#include "IobpDefinitions.h" +#include "RcFviDxeLib.h" +#include "PchInitVar.h" +#include "PchAslUpdateLib.h" +#endif + +#define AZALIA_MAX_LOOP_TIME 10 +#define AZALIA_WAIT_PERIOD 100 +#define AZALIA_MAX_SID_NUMBER_PCH_H 4 +#define AZALIA_MAX_SID_NUMBER_PCH_LP 2 +#define AZALIA_MAX_SID_MASK_PCH_H ((1 << AZALIA_MAX_SID_NUMBER_PCH_H) - 1) +#define AZALIA_MAX_SID_MASK_PCH_LP ((1 << AZALIA_MAX_SID_NUMBER_PCH_LP) - 1) +// +// CPUID and MSR definitions +// +#define CPUID_VERSION_INFO 0x1 +#define CPUID_FULL_FAMILY_MODEL 0x0FFF0FF0 +#define CPUID_FULL_STEPPING 0x0000000F +#define CPUID_FULL_FAMILY_MODEL_HASWELL 0x000306C0 +#define CPUID_FULL_FAMILY_MODEL_HASWELL_ULT 0x00040650 +#define CPUID_FULL_FAMILY_MODEL_CRYSTALWELL 0x00040660 +#define MSR_TEMPERATURE_TARGET 0x000001A2 + +typedef enum { + // + // Haswell Family Stepping + // + EnumHswA0 = 1, + EnumHswB0, + EnumHswC0, + EnumHswD0, + // + // Haswell ULT Family Stepping + // + EnumHswUltB0 = 0, + EnumHswUltC0, + // + // Crystalwell Family Stepping + // + EnumCrwB0 = 0, + EnumCrwC0, + EnumCrwD0, + EnumCpuSteppingMax = CPUID_FULL_STEPPING +} CPU_STEPPING; + +#pragma pack(1) +typedef union _MSR_REGISTER { + UINT64 Qword; + + struct _DWORDS { + UINT32 Low; + UINT32 High; + } Dwords; + + struct _BYTES { + UINT8 FirstByte; + UINT8 SecondByte; + UINT8 ThirdByte; + UINT8 FouthByte; + UINT8 FifthByte; + UINT8 SixthByte; + UINT8 SeventhByte; + UINT8 EighthByte; + } Bytes; + +} MSR_REGISTER; + +typedef struct { + UINT32 RegEax; + UINT32 RegEbx; + UINT32 RegEcx; + UINT32 RegEdx; +} EFI_CPUID_REGISTER; +#pragma pack() + +typedef struct { + EFI_PCH_INFO_PROTOCOL PchInfo; +} PCH_INSTANCE_PRIVATE_DATA; + +#define IS_PCH_H_EHCI(DeviceNumber, FunctionNumber) \ + ( \ + (DeviceNumber == PCI_DEVICE_NUMBER_PCH_USB && FunctionNumber == PCI_FUNCTION_NUMBER_PCH_EHCI) || \ + (DeviceNumber == PCI_DEVICE_NUMBER_PCH_USB_EXT && FunctionNumber == PCI_FUNCTION_NUMBER_PCH_EHCI2) \ + ) + +#define IS_PCH_LP_EHCI(DeviceNumber, FunctionNumber) \ + ( \ + (DeviceNumber == PCI_DEVICE_NUMBER_PCH_USB && FunctionNumber == PCI_FUNCTION_NUMBER_PCH_EHCI) \ + ) + +// +// Data definitions +// +extern EFI_HANDLE mImageHandle; + +/// +/// SVID / SID init table entry +/// +typedef struct { + UINT8 DeviceNumber; + UINT8 FunctionNumber; + UINT8 SvidRegOffset; +} PCH_SVID_SID_INIT_ENTRY; + +#define PCH_FVI_STRING "Reference Code - PCH - Lynxpoint" +#define PCH_FVI_SMBIOS_TYPE 0xDD +#define PCH_FVI_SMBIOS_INSTANCE 0x04 +#define PCH_CRID_STATUS "PCH-CRID Status" +#define PCH_CRID_ORIGINAL_VALUE "PCH-CRID Original Value" +#define PCH_CRID_NEW_VALUE "PCH-CRID New Value" +#define PCH_CRID_ENABLED "Enabled " +#define PCH_CRID_DISABLED "Disabled" +#define PCH_LPTLPBX_HSIO_STRING "LPTLp Bx Hsio Version" +#define PCH_LPTHB0_HSIO_STRING "LPTH B0 Hsio Version" +#define PCH_LPTHCX_HSIO_STRING "LPTH Cx Hsio Version" +#define PCH_CRID_VERSION \ + { \ + 0xFF, 0xFF, 0xFF, 0xFFFF \ + } +#define RAID_FVI_STRING "OPROM - RST - RAID" +#define RAID_RC_VERSION \ + { \ + 0xFF, 0xFF, 0xFF, 0xFFFF \ + } + +enum { + RC_VER = 0, + CRID_STATUS, + CRID_ORIGINAL, + CRID_NEW, + RAID_VER, + HSIO_LPTLPAX_VER, + HSIO_LPTLPBX_VER, + HSIO_LPTHB0_VER, + HSIO_LPTHCX_VER +} PCH_FVI_INDEX; + +extern FVI_ELEMENT_AND_FUNCTION mPchFviElementsData[]; +extern FVI_DATA_HUB_CALLBACK_CONTEXT mPchFviVersionData; +extern UINTN mPchFviElements; + +// +// Function Prototype +// + +/** + Configures PCH IOBP and stores this configuration in S3 boot script + + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in] Address Address of the IOBP register block + @param[in] AndMask Mask to AND with the register + @param[in] OrMask Mask to OR with the register +**/ +VOID +ProgramIobpWithScript ( + IN UINT32 RootComplexBar, + IN UINT32 Address, + IN UINT32 AndMask, + IN UINT32 OrMask + ); + +/** + Configures 32-bit MMIO register and stores this configuration in S3 boot script + + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in] Address Address of the IOBP register block + @param[in] AndMask Mask to AND with the register + @param[in] OrMask Mask to OR with the register +**/ +VOID +MmioAndThenOr32WithScript ( + IN UINTN Address, + IN UINT32 AndMask, + IN UINT32 OrMask + ); + +/** + Detect and initialize the type of codec (AC'97 and HDA) present in the system. + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in] AzaliaEnable Returned with TRUE if Azalia High Definition Audio codec + is detected and initialized. + + @retval EFI_SUCCESS Codec is detected and initialized. + @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to initialize the codec. +**/ +EFI_STATUS +ConfigureAzalia ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar, + IN OUT BOOLEAN *AzaliaEnable + ); + +/** + Configure miscellaneous power management settings + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in] GpioBase GPIO base address of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ConfigureMiscPm ( + DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + UINT32 RootComplexBar, + UINT16 GpioBase + ); + +/** + Configure additional power management settings + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ConfigureAdditionalPm ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ); + +/** + Configure deep Sx programming + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ProgramDeepSx ( + DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + UINT32 RootComplexBar + ); + +/** + Perform miscellany PCH initialization + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in, out] FuncDisableReg The value of Function disable register + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ConfigureMiscItems ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar, + IN OUT UINT32 *FuncDisableReg + ); + +/** + Initialize LAN device. Reference: PCH BIOS Spec Rev 0.5.0, + 10.2 Enabling / Disabling the Internal GbE Controller + ** NOTE: + - The platform reset mandated by GbE enabling / disabling is handled + in PchInit PEIM. Platform PEI code is responsible for calling PCH Init PPI + - (BUC register setting is also done in the PCH Init PPI) + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar address of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ConfigureLan ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ); + +/** + Configures PCH USB controller + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in, out] FuncDisableReg Function Disable Register + + @retval EFI_INVALID_PARAMETER The parameter of PchPlatformPolicy is invalid + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ConfigureUsb ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar, + IN OUT UINT32 *FuncDisableReg + ); + +/** + Configures PCH Sata Controller + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in, out] FuncDisableReg Function Disable Register + @param[in] GpioBase GPIO base address of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ConfigureSata ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar, + IN OUT UINT32 *FuncDisableReg, + IN UINT16 GpioBase + ); + +/** + Perform Clock Gating programming + Enables clock gating in various PCH interfaces and the registers must be restored during S3 resume. + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in] FuncDisableReg The Function Disable Register + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ConfigureClockGating ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar, + IN UINT32 FuncDisableReg + ); + +/** + Configure IoApic Controler + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar address of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ConfigureIoApic ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ); + +/** + Configure PCH Display + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar address of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ConfigureDisplay ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ); + +/** + Perform Root Port Initialization. + + @param[in] RootPort The root port to be initialized (zero based) + @param[in] RootPortFunction The PCI function number of the root port + @param[in] PchPlatformPolicy The PCH Platform Policy protocol + @param[in] PmBase The PM I/O Base address of the PCH + @param[in] RootComplexBar RCBA of the PCH + + @retval EFI_SUCCESS Device found. The root port must be enabled. + @retval EFI_NOT_FOUND No device is found on the root port. It may be disabled. + @exception EFI_UNSUPPORTED Unsupported operation. +**/ +EFI_STATUS +PchInitSingleRootPort ( + IN UINT8 RootPort, + IN UINT8 RootPortFunction, + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT16 PmBase, + IN UINT32 RootComplexBar + ); + +/** + Perform Initialization of the Downstream Root Ports. + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol + @param[in] RootComplexBar RCBA of the PCH + @param[in] PmBase The PM I/O Base address of the PCH + @param[in, out] FuncDisableReg The function disable register. IN / OUT parameter. + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER The PCIe Root Port Number of D28:F0 is not found + or invalid +**/ +EFI_STATUS +PchInitRootPorts ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar, + IN UINT16 PmBase, + IN OUT UINT32 *FuncDisableReg + ); + +/** + This is the function to enable the clock gating for PCI Express ports. + + @param[in] BusNumber The Bus Number of the PCH device + @param[in] PchPlatformPolicy PCH Platform Policy protocol + @param[in] RpEnableMask Bit Mask indicating the enabled root ports + @param[in] RpHiddenMask Bit Mask indicating the root ports used for other > x1 root ports + @param[in] RootComplexBar Root complex base address + + @retval EFI_SUCCESS Successfully completed. +**/ +EFI_STATUS +PcieEnableClockGating ( + IN UINT8 BusNumber, + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RpEnableMask, + IN UINT32 RpHiddenMask, + IN UINT32 RootComplexBar, + IN UINT32 NandPort + ); + +/** + Set an Init Root Port Downstream devices S3 dispatch item, this function may assert if any error happend + + @param[in] RootPortBus Pci Bus Number of the root port + @param[in] RootPortDevice Pci Device Number of the root port + @param[in] RootPortFunc Pci Function Number of the root port + @param[in] TempBusNumberMin Minimal temp bus number that can be assigned to the root port (as secondary + bus number) and its down stream switches + @param[in] TempBusNumberMax Maximal temp bus number that can be assigned to the root port (as subordinate + bus number) and its down stream switches + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +SetInitRootPortDownstreamS3Item ( + IN UINT8 RootPortBus, + IN UINT8 RootPortDevice, + IN UINT8 RootPortFunc, + IN UINT8 TempBusNumberMin, + IN UINT8 TempBusNumberMax + ); + +/** + Set an PCH IOBP programming S3 dispatch item, this function may assert if any error happend + + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in] Address Address of the IOBP register block + @param[in] AndMask Mask to AND with the register + @param[in] OrMask Mask to OR with the register + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_OUT_OF_RESOURCES Out of resources + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_NOT_FOUND Protocol interface not found +**/ +EFI_STATUS +SetProgramIobpS3Item ( + IN UINT32 RootComplexBar, + IN UINT32 Address, + IN UINT32 AndMask, + IN UINT32 OrMask + ); + +/** + Locking Thermal Reporting Settings + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] GpioBase GPIO base address of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ThermalLockDown ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + UINT16 GpioBase + ); + +/** + Configures PCH DMI according to policies specified in PCH Platform Policy protocol + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval EFI_SUCCESS Successfully completed. +**/ +EFI_STATUS +EFIAPI +ConfigureDmiPm ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ); + +/** + Dump whole DXE_PCH_PLATFORM_POLICY_PROTOCOL and serial out. + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + + @retval None +**/ +VOID +PchDumpPlatformProtocol ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy + ); + +/** + Lock USB registers before boot + + @param[in] PchPlatformPolicy The PCH Platform Policy + + @retval None +**/ +VOID +UsbInitBeforeBoot ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy + ); + +/** + Configures ports of the PCH USB3 (xHCI) controller + just before OS boot. + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + + @retval EFI_INVALID_PARAMETER The parameter of PchPlatformPolicy is invalid + @retval EFI_SUCCESS The function completed successfully +**/ +VOID +ConfigureXhciAtBoot ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy + ); + +#ifdef SERIAL_IO_FLAG +/** + Puts Serial IO controllers in D3 + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance +**/ +VOID +ConfigureSerialIoAtBoot ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy + ); + +/** + Hide PCI config space of Serial IO Controllerss and do any + final initialization. + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ConfigureSerialIoBeforeBoot ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ); + +/** + Configures Serial IO Controllers + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar address of this PCH device + + @retval None +**/ +EFI_STATUS +ConfigureSerialIo ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ); +#endif // SERIAL_IO_FLAG + +#ifdef ADSP_FLAG +/** + Initialize Audio DSP subsystem + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in, out] FuncDisableReg The value of Function disable register + + @retval EFI_SUCCESS Codec is detected and initialized + @retval EFI_UNSUPPORTED Audio DSP disabled + @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to initialize the codec +**/ +EFI_STATUS +ConfigureAudioDsp ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar, + IN OUT UINT32 *FuncDisableReg + ); + +/** + Finalize Audio DSP initialization after PCI enumeration. + In particular configure ADSP in ACPI or PCI mode. + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_UNSUPPORTED Audio DSP not found or not enabled +**/ +EFI_STATUS +ConfigureAudioDspBeforeBoot ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ); + +#endif // ADSP_FLAG +#endif diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInitCommon.h b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInitCommon.h new file mode 100644 index 0000000..86a6805 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInitCommon.h @@ -0,0 +1,110 @@ +/** @file + + Header file for PCH common Initialization Driver. + +@copyright + Copyright (c) 2011 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ +#ifndef _PCH_INIT_COMMON_DRIVER_H_ +#define _PCH_INIT_COMMON_DRIVER_H_ + +// +// External include files do NOT need to be explicitly specified in real EDKII +// environment +// +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) + +#include "EdkIIGlueDxe.h" +#include "EfiScriptLib.h" +#include EFI_PROTOCOL_CONSUMER (PchPlatformPolicy) +#ifdef USB_PRECONDITION_ENABLE_FLAG +#include "PchUsbPrecondition.h" +#endif // USB_PRECONDITION_ENABLE_FLAG + +#endif + +#define PCH_INIT_COMMON_SCRIPT_IO_WRITE(TableName, Width, Address, Count, Buffer) \ + SCRIPT_IO_WRITE(TableName, Width, Address, Count, Buffer) + +#define PCH_INIT_COMMON_SCRIPT_IO_READ_WRITE(TableName, Width, Address, Data, DataMask) \ + SCRIPT_IO_READ_WRITE(TableName, Width, Address, Data, DataMask) + +#define PCH_INIT_COMMON_SCRIPT_MEM_WRITE(TableName, Width, Address, Count, Buffer) \ + SCRIPT_MEM_WRITE(TableName, Width, Address, Count, Buffer) + +#define PCH_INIT_COMMON_SCRIPT_MEM_READ_WRITE(TableName, Width, Address, Data, DataMask) \ + SCRIPT_MEM_READ_WRITE(TableName, Width, Address, Data, DataMask) + +#define PCH_INIT_COMMON_SCRIPT_PCI_CFG_WRITE(TableName, Width, Address, Count, Buffer) \ + SCRIPT_PCI_CFG_WRITE(TableName, Width, Address, Count, Buffer) + +#define PCH_INIT_COMMON_SCRIPT_PCI_CFG_READ_WRITE(TableName, Width, Address, Data, DataMask) \ + SCRIPT_PCI_CFG_READ_WRITE(TableName, Width, Address, Data, DataMask) + +#define PCH_INIT_COMMON_SCRIPT_STALL(TableName, Duration) SCRIPT_STALL (TableName, Duration) + +#define PCH_INIT_COMMON_SCRIPT_SAVE_IOBP_S3_ITEM(RootComplexBar, Address, AndMask, OrMask) \ + SetProgramIobpS3Item(RootComplexBar, Address, AndMask, OrMask) + +#ifdef USB_PRECONDITION_ENABLE_FLAG +/// +/// Execute function when running in PEI +/// It is always FALSE for DXE phase check +/// +#define USB_RUN_IN_PEI FALSE + +/// +/// Execute function when running in DXE +/// +#define USB_RUN_IN_DXE TRUE + +/// +/// USB precondition policy check +/// +#define USB_PRECONDITION_POLICY_SUPPORT(UsbPolicy) \ + ((UsbPolicy)->UsbPrecondition) + +#endif // USB_PRECONDITION_ENABLE_FLAG + +/// +/// USB3 port setting policy check +/// +#define USB3PORT_SETTING_POLICY_SUPPORT(Revision) \ + ((Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_5)) + +/** + Set an PCH IOBP programming S3 dispatch item, this function may assert if any error happend + + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in] Address Address of the IOBP register block + @param[in] AndMask Mask to AND with the register + @param[in] OrMask Mask to OR with the register + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_OUT_OF_RESOURCES Out of resources + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_NOT_FOUND Protocol interface not found +**/ +EFI_STATUS +SetProgramIobpS3Item ( + IN UINT32 RootComplexBar, + IN UINT32 Address, + IN UINT32 AndMask, + IN UINT32 OrMask + ); + +#endif diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInitDxe.cif b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInitDxe.cif new file mode 100644 index 0000000..a8922a8 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInitDxe.cif @@ -0,0 +1,28 @@ +<component> + name = "PchInitDxe" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\LynxPoint\PchInit\Dxe" + RefName = "PchInitDxe" +[files] +"PchInitDxe.sdl" +"PchInitDxe.mak" +"PchInit.h" +"PchInit.c" +"PchAzalia.c" +"PchIoApic.c" +"PchLan.c" +"PchMisc.c" +"PchPm.c" +"PchSata.c" +"PchUsb.c" +"PchInit.dxs" +"PchRootPorts.c" +"PchInitCommon.h" +"PchDebugDump.c" +"PchFvi.c" +"PchInitDxe.inf" +"PchAudioDsp.c" +"PchUsbPrecondition.c" +"PchUsbPrecondition.h" +"PchSerialIo.c" +<endComponent> diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInitDxe.inf b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInitDxe.inf new file mode 100644 index 0000000..62675c2 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInitDxe.inf @@ -0,0 +1,134 @@ +## @file +# Component description file for Pch Initialization driver +# +#@copyright +# Copyright (c) 1999 - 2013 Intel Corporation. All rights reserved +# This software and associated documentation (if any) is furnished +# under a license and may only be used or copied in accordance +# with the terms of the license. Except as permitted by such +# license, no part of this software or documentation may be +# reproduced, stored in a retrieval system, or transmitted in any +# form or by any means without the express written consent of +# Intel Corporation. +# +# This file contains a 'Sample Driver' and is licensed as such +# under the terms of your license agreement with Intel or your +# vendor. This file may be modified by the user, subject to +# the additional terms of the license agreement +# + +[defines] +BASE_NAME = PchInitDxe +FILE_GUID = DE23ACEE-CF55-4fb6-AA77-984AB53DE823 +COMPONENT_TYPE = BS_DRIVER + +[sources.common] + PchInit.h + PchInit.c + PchAzalia.c + PchIoApic.c + PchLan.c + PchMisc.c + PchPm.c + PchSata.c + PchUsb.c + PchRootPorts.c + PchDebugDump.c + ../Common/PchUsbCommon.c + ../Common/PchHsio.c + ../Common/PchInitVar.c + PchFvi.c + PchSerialIo.c + PchAudioDsp.c + PchUsbPrecondition.c +# +# Edk II Glue Driver Entry Point +# + EdkIIGlueDxeDriverEntryPoint.c + +[includes.common] + . + ../Common + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Efi + $(EDK_SOURCE)/Foundation/Include + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework/Include + $(EDK_SOURCE)/Foundation/Framework/Guid/Hob + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT) + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Guid/ChipsetInitHob + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Protocol + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Protocol/PchInfo + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Samplecode/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Samplecode/Library/AslUpdate/Dxe + $(EFI_SOURCE)/$(PROJECT_ME_ROOT) + $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Guid/MeDataHob + $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Library/MeKernel + $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Library/MeKernel/include + $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Library/MeKernel/Dxe + $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Heci/Include + $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Protocol/MePlatformPolicy +# +# EDK II Glue Library utilizes some standard headers from EDK +# + $(EFI_SOURCE) + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Include/Pei + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include/Library +# +# Typically the sample code referenced will be available in the code base already +# So keep this include at the end to defer to the source base definition +# and only use the sample code definition if source base does not include these files. +# + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/SampleCode + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT) + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include + $(EFI_SOURCE)/$(PROJECT_SA_ROOT) + $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/Include + $(EFI_SOURCE)/Include + +[libraries.common] + EdkIIGlueBaseIoLibIntrinsic + EdkIIGlueDxeReportStatusCodeLib + EdkIIGlueDxeDebugLibReportStatusCode + EdkIIGlueUefiBootServicesTableLib + EdkIIGlueUefiRuntimeServicesTableLib + EdkIIGlueDxeServicesTableLib + EdkIIGlueDxeMemoryAllocationLib + EdkIIGlueDxeFirmwarePerformanceLib + EdkIIGlueBasePciLibPciExpress + EdkFrameworkProtocolLib + EdkProtocolLib + EdkIIGlueDxeHobLib + PchPciExpressHelpersLib + $(PROJECT_PCH_FAMILY)ProtocolLib + PchPlatformLib + EfiGuidLib + EfiScriptLib + RcFviDxeLib + PchAslUpdateLib + MeLib + +[nmake.common] + IMAGE_ENTRY_POINT = _ModuleEntryPoint + DPX_SOURCE = PchInit.dxs +# +# Module Entry Point +# + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=PchInitEntryPoint + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \ + -D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \ + -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \ + -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \ + -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \ + -D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \ + -D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \ + -D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \ + -D __EDKII_GLUE_DXE_HOB_LIB__ diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInitDxe.mak b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInitDxe.mak new file mode 100644 index 0000000..a1c641e --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInitDxe.mak @@ -0,0 +1,150 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchInitDxe/PchInitDxe.mak 6 1/14/13 2:40a Scottyang $ +# +# $Revision: 6 $ +# +# $Date: 1/14/13 2:40a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchInitDxe/PchInitDxe.mak $ +# +# 6 1/14/13 2:40a Scottyang +# [TAG] EIP112059 +# +# [Category] Improvement +# +# [Description] Update PCH RC 0.9.0. +# [Files] ReferenceCode\Chipset\LynxPoint\*.* +# +# 5 11/20/12 8:34a Scottyang +# [TAG] EIP107014 +# [Category] Improvement +# [Description] Update RC 0.8.0 +# [Files] ReferenceCode\Chipset\LynxPoint\*.*, SBDxe.c, SB.sd, +# SbSetupData.c, GetSetupDate.c +# +# 4 8/13/12 9:14a Victortu +# +# 3 7/02/12 9:56a Victortu +# +# 2 2/24/12 2:12a Victortu +# Updated to support 4.6.5.3_IntelEDK_1117_Patch7_00. +# +# 1 2/08/12 8:51a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* + +#--------------------------------------------------------------------------- +# Create PchInitDxe Driver +#--------------------------------------------------------------------------- +EDK : PchInitDxe +PchInitDxe : $(BUILD_DIR)\PchInitDxe.mak PchInitDxeBin + + +$(BUILD_DIR)\PchInitDxe.mak : $(PchInitDxe_DIR)\$(@B).cif $(PchInitDxe_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(PchInitDxe_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +MY_DEFINES=\ +!IF "$(PCH_DEBUG_INFO)"=="1" + /D"PCH_DEBUG_INFO=1"\ +!ELSE + /D"PCH_DEBUG_INFO=0"\ +!ENDIF + +PchInitDxe_INCLUDES=\ + /I$(PchUsbCommonLib_DIR)\ + $(INTEL_PCH_INCLUDES)\ + $(EdkIIGlueLib_INCLUDES)\ + /I$(INTEL_PCH_DIR)\Protocol\PchInfo\ + /I$(INTEL_PCH_DIR)\SampleCode\Include\ + /I$(INTEL_PCH_DIR)\SampleCode\Library\AslUpdate\Dxe\ + /I$(INTEL_PCH_DIR)\Guid\SurvivabilityHob\ + $(ME_INCLUDES) + +PchInitDxe_DEFINES = $(MY_DEFINES)\ + /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=PchInitEntryPoint"\ + /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \ + /D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \ + /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \ + /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \ + /D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \ + /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \ + /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \ + /D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__\ + /D __EDKII_GLUE_DXE_HOB_LIB__ + +PchInitDxe_LIB_LINKS =\ +!IF "$(x64_BUILD)"=="1" + $(EdkIIGlueBaseLibX64_LIB)\ +!ELSE + $(EdkIIGlueBaseLibIA32_LIB)\ +!ENDIF + $(EdkIIGlueBaseIoLibIntrinsic_LIB)\ + $(EdkIIGlueDxeReportStatusCodeLib_LIB)\ + $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\ + $(EdkIIGlueUefiBootServicesTableLib_LIB)\ + $(EdkIIGlueDxeServicesTableLib_LIB)\ + $(EdkIIGlueDxeMemoryAllocationLib_LIB)\ + $(EdkIIGlueBasePciLibPciExpress_LIB)\ + $(EDKFRAMEWORKPROTOCOLLIB)\ + $(EDKPROTOCOLLIB)\ + $(PchPciExpressHelpersDxeLib_LIB)\ + $(INTEL_PCH_PROTOCOL_LIB)\ + $(PchPlatformDxeLib_LIB)\ + $(EFIGUIDLIB)\ + $(EFISCRIPTLIB)\ + $(PchUsbCommonDxeLib_LIB)\ + $(EdkIIGlueUefiRuntimeServicesTableLib_LIB)\ + $(RcFviDxeLib_LIB)\ + $(PchAslUpdateLib_LIB)\ + $(EdkIIGlueDxeHobLib_LIB)\ +!IF "$(iME_SUPPORT)"=="1" + $(PchGuidLib_LIB)\ + $(MeLibDxe_LIB) +!ENDIF + +PchInitDxeBin: $(PchInitDxe_LIB_LINKS) + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ + /f $(BUILD_DIR)\PchInitDxe.mak all \ + "MY_INCLUDES=$(PchInitDxe_INCLUDES)"\ + "MY_DEFINES=$(PchInitDxe_DEFINES)"\ + GUID=DE23ACEE-CF55-4fb6-AA77-984AB53DE823\ + ENTRY_POINT=_ModuleEntryPoint \ + TYPE=BS_DRIVER\ + EDKIIModule=DXEDRIVER\ + DEPEX1=$(PchInitDxe_DIR)\PchInit.dxs\ + DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX\ +!IF "$(SOFTSDV_PARTIAL_COMPRESS)"=="1" + COMPRESS=0 +!ELSE + COMPRESS=1 +!ENDIF +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInitDxe.sdl b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInitDxe.sdl new file mode 100644 index 0000000..e0b5eb2 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchInitDxe.sdl @@ -0,0 +1,66 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchInitDxe/PchInitDxe.sdl 1 2/08/12 8:51a Yurenlai $ +# +# $Revision: 1 $ +# +# $Date: 2/08/12 8:51a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchInitDxe/PchInitDxe.sdl $ +# +# 1 2/08/12 8:51a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* +TOKEN + Name = "PchInitDxe_SUPPORT" + Value = "1" + Help = "Main switch to enable PchInitDxe support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "PchInitDxe_DIR" +End + +MODULE + File = "PchInitDxe.mak" + Help = "Includes PchInitDxe.mak to Project" +End + +ELINK + Name = "$(BUILD_DIR)\PchInitDxe.ffs" + Parent = "FV_MAIN" + InvokeOrder = AfterParent +End +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchIoApic.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchIoApic.c new file mode 100644 index 0000000..ba0b94f --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchIoApic.c @@ -0,0 +1,134 @@ +/** @file + Initializes PCH IO APIC Device. + +@copyright + Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ +#include "PchInit.h" + +/** + Configure IoApic Controler + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar address of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ConfigureIoApic ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ) +{ + UINT8 RegData8; + UINT16 RegData16; + UINT32 RegData32; + UINTN PciD31F0RegBase; + UINT32 IoApicAddress; + PCH_IO_APIC_CONFIG *IoApicConfig; + PCH_LPC_HPET_CONFIG *HpetConfig; + UINT8 Index; + + DEBUG ((EFI_D_INFO, "ConfigureIoApic() Start\n")); + + /// + /// Get LPC base address + /// + PciD31F0RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 0, 0); + IoApicConfig = PchPlatformPolicy->IoApicConfig; + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 6.6.2.1 + /// 1. Enable the IOAPIC by setting the APIC Enable bit, RCBA + offset 31FFh, Bit[0] if the + /// system needs to use the IOxAPIC. The APIC Enable bits needs read back after the bit is written. + /// Done in PchInitPeim.c PchIoApicInit() + /// + /// 2. Build the MP table and/or ACPI APIC table for the OS + /// This will be done in ACPI code. + /// + /// 3. Maximum Redirection Entries (MRE) in APIC Version Register (VER), offset 01h, + /// [23:16] has to be written once for Microsoft Windows OS. + /// The address bits 19:12 of IOAPIC INDEX and DATA are programmable + /// through OIC register at RCBA + 31FEh[7:0]. + /// + IoApicAddress = (UINT32) MmioRead8 (RootComplexBar + R_PCH_RCRB_OIC); + IoApicAddress = IoApicAddress << N_PCH_IO_APIC_ASEL; + RegData8 = 0x01; + MmioWrite8 ((UINTN) (R_PCH_IO_APIC_INDEX | IoApicAddress), RegData8); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (R_PCH_IO_APIC_INDEX | IoApicAddress), + 1, + &RegData8 + ); + RegData32 = 0x170020; + if (GetPchSeries() == PchLp) { + if (IoApicConfig->IoApicEntry24_39 == PCH_DEVICE_ENABLE) { + RegData32 = 0x270020; + } + } + MmioWrite32 ((R_PCH_IO_APIC_DATA | IoApicAddress), RegData32); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (R_PCH_IO_APIC_DATA | IoApicAddress), + 1, + &RegData32 + ); + + /// + /// Program this field to provide a unique bus:device:function number for the internal IOxAPIC + /// + if (IoApicConfig->BdfValid) { + RegData16 = ((UINT16) (IoApicConfig->BusNumber) << 8) & B_PCH_LPC_IOXAPIC_BUS; + RegData16 |= ((UINT16) (IoApicConfig->DeviceNumber) << 3) & B_PCH_LPC_IOXAPIC_DEVICE; + RegData16 |= (UINT16) (IoApicConfig->FunctionNumber) & B_PCH_LPC_IOXAPIC_FUNC; + MmioWrite16 ((UINTN) (PciD31F0RegBase + R_PCH_LPC_IOXAPIC), RegData16); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD31F0RegBase + R_PCH_LPC_IOXAPIC), + 1, + &RegData16 + ); + } + /// + /// Program this field accordingly if unique bus:device:function number is required for the + /// corresponding HPET + /// + HpetConfig = PchPlatformPolicy->HpetConfig; + if (HpetConfig->BdfValid) { + for (Index = 0; Index < PCH_HPET_BDF_MAX; Index++) { + RegData16 = ((UINT16) (HpetConfig->Hpet[Index].BusNumber) << 8) & B_PCH_LPC_HPET0_BUS; + RegData16 |= ((UINT16) (HpetConfig->Hpet[Index].DeviceNumber) << 3) & B_PCH_LPC_HPET0_DEVICE; + RegData16 |= (UINT16) (HpetConfig->Hpet[Index].FunctionNumber) & B_PCH_LPC_HPET0_FUNC; + MmioWrite16 ((UINTN) (PciD31F0RegBase + R_PCH_LPC_HPET0 + Index * 2), RegData16); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD31F0RegBase + R_PCH_LPC_HPET0 + Index * 2), + 1, + &RegData16 + ); + } + } + + DEBUG ((EFI_D_INFO, "ConfigureIoApic() End\n")); + + return EFI_SUCCESS; +} diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchLan.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchLan.c new file mode 100644 index 0000000..ab0c427 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchLan.c @@ -0,0 +1,152 @@ +/** @file + Initializes PCH LAN Device + +@copyright + Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ +#include "PchInit.h" + +/** + Enable GbE Controller + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +EnableGbEController ( + DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + UINT32 RootComplexBar + ) +{ + /// + /// PCH BIOS Spec Rev 0.5.0, section 10.2.1 + /// Done in PchInitPeimm.c PchGbeMandatedReset() + /// + return EFI_SUCCESS; +} + +/** + Disable GbE Controller + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +DisableGbEController ( + DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + UINT32 RootComplexBar + ) +{ + /// + /// PCH BIOS Spec Rev 0.5.0, section 10.2.2 + /// Done in PchInitPeimm.c PchGbeMandatedReset() + /// + return EFI_SUCCESS; +} + +/** + Initialize LAN device. Reference: PCH BIOS Spec Rev 0.5.0, + 10.2 Enabling / Disabling the Internal GbE Controller + ** NOTE: + - The platform reset mandated by GbE enabling / disabling is handled + in PchInit PEIM. Platform PEI code is responsible for calling PCH Init PPI + - BUC register setting is also done in the PCH Init PPI + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar address of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ConfigureLan ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ) +{ + UINT32 RegData32; + UINTN PciD25F0RegBase; + PCH_SERIES PchSeries; + + DEBUG ((EFI_D_INFO, "ConfigureLan() Start\n")); + PchSeries = GetPchSeries(); + /// + /// If SPI is used and in Descriptor mode, the PCIE Port X need to be disabled to use GbE + /// if not, the GbE should be disabled + /// + if (PchIsSpiDescriptorMode (RootComplexBar)) { + DEBUG ((EFI_D_INFO, "LAN can be enabled or disabled as SPI is in Descriptor Mode.\n")); + + if (PchPlatformPolicy->DeviceEnabling->Lan == PCH_DEVICE_DISABLE) { + /// + /// Disable LAN + /// + DisableGbEController (PchPlatformPolicy, RootComplexBar); + } else { + /// + /// Enable LAN + /// + EnableGbEController (PchPlatformPolicy, RootComplexBar); + + /// + /// PCH BIOS Spec Rev 0.5.6 Section 10.7.1 LTR Programming + /// The maximum snoop/non-snoop platform latency values to 00000846h + /// in the GbE controller's PCI LTR capability register at D25:F0:Reg 0A8h + /// + if (PchPlatformPolicy->PwrOptConfig->PchPwrOptGbe == PCH_DEVICE_ENABLE) { + PciD25F0RegBase = MmPciAddress ( + 0, + PCI_BUS_NUMBER_PCH_LAN, + PCI_DEVICE_NUMBER_PCH_LAN, + PCI_FUNCTION_NUMBER_PCH_LAN, + 0 + ); + RegData32 = 0x00000000; + if (PchSeries == PchH) { + RegData32 = 0x00000846; + } + if (PchSeries == PchLp) { + RegData32 = 0x00001003; + } + MmioWrite32 (PciD25F0RegBase + R_PCH_LAN_LTR_CAP, RegData32); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD25F0RegBase + R_PCH_LAN_LTR_CAP), + 1, + (VOID *) (UINTN) (PciD25F0RegBase + R_PCH_LAN_LTR_CAP) + ); + } + } + } else { + /// + /// Non Descriptor mode: Disable LAN + /// + DEBUG ((EFI_D_ERROR, "LAN is disabled as SPI not in Descriptor Mode.\n")); + /// + /// Disable LAN + /// + DisableGbEController (PchPlatformPolicy, RootComplexBar); + } + + DEBUG ((EFI_D_INFO, "ConfigureLan() End\n")); + + return EFI_SUCCESS; +} diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchMisc.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchMisc.c new file mode 100644 index 0000000..ec38433 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchMisc.c @@ -0,0 +1,395 @@ +/** @file + Miscellaneous PCH initialization tasks + +@copyright + Copyright (c) 1999 - 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#include "PchInit.h" + +/** + Perform miscellany PCH initialization + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in, out] FuncDisableReg The value of Function disable register + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ConfigureMiscItems ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar, + IN OUT UINT32 *FuncDisableReg + ) +{ + UINTN PciD31F0RegBase; + UINT8 RegData8; + UINT16 RegData16; + UINT16 LpcDeviceId; + UINTN RPBase; + UINT16 RpcConfig; + + DEBUG ((EFI_D_INFO, "ConfigureMiscItems() Start\n")); + + PciD31F0RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 0, 0); + RegData8 = 0; + LpcDeviceId = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_DEVICE_ID); + + /// + /// Get PCIE Root Port Configuration + /// + RPBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + GetPchPcieRpfn( RootComplexBar, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1), + 0 + ); + RpcConfig = MmioRead16 (RPBase + R_PCH_PCIE_STRPFUSECFG); + /// + /// PCH BIOS Spec Rev 0.5.0, 8.13 IOSF Port Configuration and Grant Count Programming + /// The following table shows the setting of IOSF fabric register (RCBA 0x103C [15:0]) based + /// on PCIe port configuration. BIOS should program the register based on the table below. + /// For Root Port 1 - 4: + /// (Program RCBA + 103Ch[7:3] according to B0:D28:F0 + FCh[15:14]) + /// B0:D28:F0+FCh[15:14] RCBA+103Ch[1:0] RCBA+103Ch[3:2] RCBA+103Ch[5:4] RCBA+103Ch[7:6] + /// 00b 00b 00b 00b 00b + /// 01b 10b 00b 00b 00b + /// 10b 10b 00b 10b 00b + /// 11b 10b 00b 00b 00b + /// + switch (RpcConfig & B_PCH_PCIE_STRPFUSECFG_RPC) { + case V_PCH_PCIE_STRPFUSECFG_RPC_2_1_1: + RegData16 = 0x02; + break; + + case V_PCH_PCIE_STRPFUSECFG_RPC_2_2: + RegData16 = 0x22; + break; + + case V_PCH_PCIE_STRPFUSECFG_RPC_4: + RegData16 = 0x02; + break; + + default: + RegData16 = 0x0; + break; + } + + if (GetPchSeries() == PchH) { + /// + /// Get PCIE Root Port Configuration + /// + RPBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_5, + 0 + ); + RpcConfig = MmioRead16 (RPBase + R_PCH_PCIE_STRPFUSECFG); + /// + /// For Root Port 5 - 8: + /// (Program RCBA + 103Ch[7:3] according to B0:D28:F4 + FCh[15:14]) + /// B0:D28:F4+FCh[15:14] RCBA+103Ch[9:8] RCBA+103Ch[11:10] RCBA+103Ch[13:12] RCBA+103Ch[15:14] + /// 00b 00b 00b 00b 00b + /// 01b 10b 00b 00b 00b + /// 10b 10b 00b 10b 00b + /// 11b 10b 00b 00b 00b + /// + switch (RpcConfig & B_PCH_PCIE_STRPFUSECFG_RPC) { + case V_PCH_PCIE_STRPFUSECFG_RPC_2_1_1: + RegData16 |= 0x02 << 8; + break; + + case V_PCH_PCIE_STRPFUSECFG_RPC_2_2: + RegData16 |= 0x22 << 8; + break; + + case V_PCH_PCIE_STRPFUSECFG_RPC_4: + RegData16 |= 0x02 << 8; + break; + + default: + RegData16 |= 0x0 << 8; + break; + } + } + + MmioWrite16 (RootComplexBar + 0x103C, RegData16); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RootComplexBar + 0x103C), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x103C) + ); + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 6.2 Serial IRQs + /// The only System BIOS requirement to use IRQs as a serial IRQ is to enable the function in D31:F0:Reg 64h[7] and + /// select continuous or quiet mode, D31:F0:Reg 64h[6]. + /// PCH requires that the System BIOS first set the SERIRQ logic to continuous mode operation for at least one frame + /// before switching it into quiet mode operation. This operation should be performed during the normal boot sequence + /// as well as a resume from STR (S3). + /// + RegData8 = MmioRead8 (PciD31F0RegBase + R_PCH_LPC_SERIRQ_CNT) & + (UINT8) ~(B_PCH_LPC_SERIRQ_CNT_SIRQEN | B_PCH_LPC_SERIRQ_CNT_SFPW); + + if (PchPlatformPolicy->SerialIrqConfig->SirqEnable == TRUE) { + switch (PchPlatformPolicy->SerialIrqConfig->StartFramePulse) { + case PchSfpw8Clk: + RegData8 |= V_PCH_LPC_SERIRQ_CNT_SFPW_8CLK; + break; + + case PchSfpw6Clk: + RegData8 |= V_PCH_LPC_SERIRQ_CNT_SFPW_6CLK; + break; + + case PchSfpw4Clk: + default: + RegData8 |= V_PCH_LPC_SERIRQ_CNT_SFPW_4CLK; + break; + } + /// + /// Set the SERIRQ logic to continuous mode + /// + RegData8 |= (UINT8) (B_PCH_LPC_SERIRQ_CNT_SIRQEN | B_PCH_LPC_SERIRQ_CNT_SIRQMD); + } + + MmioWrite8 (PciD31F0RegBase + R_PCH_LPC_SERIRQ_CNT, RegData8); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciD31F0RegBase + R_PCH_LPC_SERIRQ_CNT), + 1, + (VOID *) (UINTN) (PciD31F0RegBase + R_PCH_LPC_SERIRQ_CNT) + ); + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 19.8.1 RTC Resets + /// The PCH will set the RTC_PWR_STS bit (D31:F0:Reg A4h[2]) when the RTCRST# pin goes low. + /// The System BIOS shouldn't rely on the RTC RAM contents when the RTC_PWR_STS bit is set. + /// BIOS should clear this bit by writing a 0 to this bit position. + /// This bit isn't cleared by any reset function. + /// + MmioAnd8 ((UINTN) (PciD31F0RegBase + 0xA4), (UINT8) (~(BIT2))); + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 5.11 Intel PCH Boot Checklist + /// Step 8.1 + /// Always set RCBA + Offset 3418h[0] = 1b + /// + *FuncDisableReg |= B_PCH_RCRB_FUNC_DIS_FUNCTION_0; + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 19.1 Handling Status Registers + /// System BIOS must set 1b to clear the following registers during power-on + /// and resuming from Sx sleep state. + /// - RCBA + Offset 3310h[0] = 1b + /// - RCBA + Offset 3310h[4] = 1b, needs to be done as early as possible during PEI + /// Done in InstallPchInitPpi () + /// - RCBA + Offset 3310h[5] = 1b + /// + MmioOr32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_PRSTS), + (UINT32) (B_PCH_RCRB_PRSTS_ME_WAKE_STS | B_PCH_RCRB_PRSTS_WOL_OVR_WK_STS) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_PRSTS), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_PRSTS) + ); + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 4.7 + /// Enabling SLP_S3# and SLP_S4# Stretch + /// B0:D31:F0 Reg A4h[12:10] = 110b + /// B0:D31:F0 Reg A4h[5:3] = 001b + /// + RegData16 = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_3) & + (UINT16) (~(B_PCH_LPC_GEN_PMCON_SLP_S3_MAW | + B_PCH_LPC_GEN_PMCON_SLP_S4_MAW)); + + switch (PchPlatformPolicy->MiscPmConfig->PchSlpS3MinAssert) { + case PchSlpS360us: + RegData16 |= V_PCH_LPC_GEN_PMCON_SLP_S3_MAW_60US; + break; + + case PchSlpS31ms: + RegData16 |= V_PCH_LPC_GEN_PMCON_SLP_S3_MAW_1MS; + break; + + case PchSlpS350ms: + default: + RegData16 |= V_PCH_LPC_GEN_PMCON_SLP_S3_MAW_50MS; + break; + + case PchSlpS32s: + RegData16 |= V_PCH_LPC_GEN_PMCON_SLP_S3_MAW_2S; + break; + } + + switch (PchPlatformPolicy->MiscPmConfig->PchSlpS4MinAssert) { + case PchSlpS4PchTime: + RegData16 &= (UINT16) (~B_PCH_LPC_GEN_PMCON_SLP_S4_ASE); + break; + + case PchSlpS41s: + RegData16 |= V_PCH_LPC_GEN_PMCON_SLP_S4_MAW_1S | B_PCH_LPC_GEN_PMCON_SLP_S4_ASE; + break; + + case PchSlpS42s: + RegData16 |= V_PCH_LPC_GEN_PMCON_SLP_S4_MAW_2S | B_PCH_LPC_GEN_PMCON_SLP_S4_ASE; + break; + + case PchSlpS43s: + RegData16 |= V_PCH_LPC_GEN_PMCON_SLP_S4_MAW_3S | B_PCH_LPC_GEN_PMCON_SLP_S4_ASE; + break; + + case PchSlpS44s: + default: + RegData16 |= V_PCH_LPC_GEN_PMCON_SLP_S4_MAW_4S | B_PCH_LPC_GEN_PMCON_SLP_S4_ASE; + break; + } + + if (PchPlatformPolicy->MiscPmConfig->SlpStrchSusUp == PCH_DEVICE_DISABLE) { + RegData16 |= B_PCH_LPC_GEN_PMCON_DISABLE_SX_STRETCH; + } else { + RegData16 &= ~B_PCH_LPC_GEN_PMCON_DISABLE_SX_STRETCH; + } + + MmioWrite16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_3, RegData16); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_3), + 1, + (VOID *) (UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_3) + ); + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 6.2 Serial IRQs + /// The only System BIOS requirement to use IRQs as a serial IRQ is to enable the function + /// in D31:F0:Reg 64h[7] and select continuous or quiet mode, D31:F0:Reg 64h[6]. + /// + if ((PchPlatformPolicy->SerialIrqConfig->SirqEnable == TRUE) && + (PchPlatformPolicy->SerialIrqConfig->SirqMode == PchQuietMode)) { + MmioAnd8 (PciD31F0RegBase + R_PCH_LPC_SERIRQ_CNT, (UINT8)~B_PCH_LPC_SERIRQ_CNT_SIRQMD); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciD31F0RegBase + R_PCH_LPC_SERIRQ_CNT), + 1, + (VOID *) (UINTN) (PciD31F0RegBase + R_PCH_LPC_SERIRQ_CNT) + ); + } + + /// + /// For LPT-LP, if Direct Connect Interface (DCI) is enabled, set RCBA + 3F02h[0] = 1, + /// else, set RCBA + 3F02h[0] = 0. + /// When enabling DCI (through the enable bit), it's able to access JTAG and Run Control features + /// in a closed chassis situation, by using the USB3 port on a Shark Bay ULT platform. + /// + if ((PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_6) && + (GetPchSeries() == PchLp)) { + RegData16 = MmioRead16 (RootComplexBar + 0x3F02) & (UINT16)~BIT0; + if (PchPlatformPolicy->MiscConfig->DciEn) { + RegData16 |= BIT0; + } + MmioWrite16 (RootComplexBar + 0x3F02, RegData16); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RootComplexBar + 0x3F02), + 1, + &RegData16 + ); + } + + DEBUG ((EFI_D_INFO, "ConfigureMiscItems() End\n")); + + return EFI_SUCCESS; +} + +/** + Configure PCH Display + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar address of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ConfigureDisplay ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ) +{ + UINT32 Data32And; + UINT32 Data32Or; + + DEBUG ((EFI_D_INFO, "ConfigureDisplay() Start\n")); + + if (PchPlatformPolicy->DeviceEnabling->Display == PCH_DEVICE_DISABLE) { + /// + /// Disable PCH Display Port + /// Step 1 + /// Set RCBA + 3424h = 0h + /// + MmioWrite16 ((UINTN) (RootComplexBar + R_PCH_RCRB_DISPBDF), (UINT16) 0x0); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RootComplexBar + R_PCH_RCRB_DISPBDF), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_DISPBDF) + ); + /// + /// Step 2 + /// Set RCBA + 3428h[0] = 0b + /// + Data32Or = 0; + Data32And = (UINT32) ~(B_PCH_RCRB_FD2_DBDFEN); + MmioAnd32 ((UINTN) (RootComplexBar + R_PCH_RCRB_FD2), Data32And); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_FD2), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + + Data32Or = 0; + Data32And = (UINT32) (~BIT0); + MmioAnd32 ((UINTN) (RootComplexBar + R_PCH_RCRB_FD2), Data32And); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_FD2), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + } + + DEBUG ((EFI_D_INFO, "ConfigureDisplay() End\n")); + + return EFI_SUCCESS; +}
\ No newline at end of file diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchPm.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchPm.c new file mode 100644 index 0000000..b2f53d7 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchPm.c @@ -0,0 +1,3389 @@ +/** @file + Initializes PCH power management features. +@copyright + Copyright (c) 1999 - 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#include "PchInit.h" + +/** + Set an PCH IOBP programming S3 dispatch item, this function may assert if any error happend + + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in] Address Address of the IOBP register block + @param[in] AndMask Mask to AND with the register + @param[in] OrMask Mask to OR with the register + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_OUT_OF_RESOURCES Out of resources + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_NOT_FOUND Protocol interface not found +**/ +EFI_STATUS +SetProgramIobpS3Item ( + IN UINT32 RootComplexBar, + IN UINT32 Address, + IN UINT32 AndMask, + IN UINT32 OrMask + ) +{ + EFI_STATUS Status; +#ifdef EFI_S3_RESUME + STATIC EFI_PCH_S3_SUPPORT_PROTOCOL *PchS3Support; + STATIC EFI_PCH_S3_PARAMETER_PROG_IOBP S3ParameterProgramIobp; + STATIC EFI_PCH_S3_DISPATCH_ITEM S3DispatchItem = { + PchS3ItemTypeProgramIobp, + &S3ParameterProgramIobp + }; + EFI_PHYSICAL_ADDRESS S3DispatchEntryPoint; + + if (!PchS3Support) { + /// + /// Get the PCH S3 Support Protocol + /// + Status = gBS->LocateProtocol ( + &gEfiPchS3SupportProtocolGuid, + NULL, + (VOID **) &PchS3Support + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + } + + S3ParameterProgramIobp.RootComplexBar = RootComplexBar; + S3ParameterProgramIobp.Address = Address; + S3ParameterProgramIobp.AndMask = AndMask; + S3ParameterProgramIobp.OrMask = OrMask; + Status = PchS3Support->SetDispatchItem ( + PchS3Support, + &S3DispatchItem, + &S3DispatchEntryPoint + ); + ASSERT_EFI_ERROR (Status); + /// + /// Save the script dispatch item in the Boot Script + /// + SCRIPT_DISPATCH (EFI_ACPI_S3_RESUME_SCRIPT_TABLE, S3DispatchEntryPoint); +#else + Status = EFI_SUCCESS; +#endif + return Status; +} + +/** + Locking Thermal Reporting Settings + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] GpioBase GPIO base address of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ThermalLockDown ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + UINT16 GpioBase + ) +{ + UINTN PciD31F6RegBase; + UINTN PciD31F2RegBase; + UINT32 ThermalBaseB; + UINT32 ThermalBase; + EFI_PHYSICAL_ADDRESS MemBaseAddress; + EFI_STATUS Status; + UINT8 Index; + UINT8 RegData8; + UINT16 RegData16; + UINT32 RegData32; + UINT32 RootComplexBar; + UINT32 Data32And; + UINT32 Data32Or = 0; + UINT16 Data16And; + UINT16 Data16Or; + UINT32 PchTTLevels = 0; + BOOLEAN PchHotEnable; + PCH_SERIES PchSeries; + EFI_CPUID_REGISTER Cpuid; + MSR_REGISTER TempMsr; + UINT32 temperature; + UINT8 MaxSataPortNum; + + DEBUG ((EFI_D_INFO, "ThermalLockDown() Start\n")); + + PchSeries = GetPchSeries(); + /// + /// Check if TBARB is already initialized by platform code + /// + PciD31F6RegBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_THERMAL, + PCI_FUNCTION_NUMBER_PCH_THERMAL, + 0 + ); + PciD31F2RegBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_SATA, + PCI_FUNCTION_NUMBER_PCH_SATA, + 0 + ); + RootComplexBar = PCH_RCRB_BASE; + ThermalBaseB = MmioRead32 (PciD31F6RegBase + R_PCH_THERMAL_TBARB); + MemBaseAddress = 0x0ffffffff; + + if (ThermalBaseB & B_PCH_THERMAL_SPTYPEN) { + /// + /// Check if TBARB is already initialized and if so use it. + /// + ThermalBaseB &= B_PCH_THERMAL_TBARB_MASK; + } else { +#ifndef AMI_OVERRIDE_FOR_PCH + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateMaxAddressSearchTopDown, + EfiGcdMemoryTypeMemoryMappedIo, + N_PCH_THREMAL_TBARB_ALIGNMENT, + V_PCH_THERMAL_TBARB_SIZE, + &MemBaseAddress, + mImageHandle, + NULL + ); +#else + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateMaxAddressSearchBottomUp, + EfiGcdMemoryTypeMemoryMappedIo, + N_PCH_THREMAL_TBARB_ALIGNMENT, + V_PCH_THERMAL_TBARB_SIZE, + &MemBaseAddress, + mImageHandle, + NULL + ); +#endif + if (EFI_ERROR (Status)) { + return Status; + } + + ThermalBaseB = (UINT32) MemBaseAddress; + MmioWrite32 (PciD31F6RegBase + R_PCH_THERMAL_TBARB, ThermalBaseB); + MmioWrite32 (PciD31F6RegBase + R_PCH_THERMAL_TBARBH, 0); + MmioOr32 (PciD31F6RegBase + R_PCH_THERMAL_TBARB, (UINT32) B_PCH_THERMAL_SPTYPEN); + + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F6RegBase + R_PCH_THERMAL_TBARB), + 1, + (VOID *) (UINTN) (PciD31F6RegBase + R_PCH_THERMAL_TBARB) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F6RegBase + R_PCH_THERMAL_TBARBH), + 1, + (VOID *) (UINTN) (PciD31F6RegBase + R_PCH_THERMAL_TBARBH) + ); + } + /// + /// PCH BIOS Spec Rev 0.5.0, 17.3.1 Initializing Lynx Point Thermal Sensors + /// Step 1 + /// TSC must then be written to 0x81 to enable the power down and lock the register. + /// + RegData8 = MmioRead8 (ThermalBaseB + R_PCH_TBARB_TSC); + /// + /// Enable Catastrophic Power Down + /// + RegData8 |= (UINT8) B_PCH_TBARB_TSC_CPDE; + /// + /// Step 8.1 + /// It is recommended that TSC [7] set to 1 to lock the CAT Trip behavior. + /// + if (PchPlatformPolicy->ThermalConfig->ThermalAlertEnable.TscLock == PCH_DEVICE_ENABLE) { + RegData8 |= (UINT8) B_PCH_TBARB_TSC_PLD; + } + + MmioWrite8 (ThermalBaseB + R_PCH_TBARB_TSC, RegData8); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (ThermalBaseB + R_PCH_TBARB_TSC), + 1, + (VOID *) (UINTN) (ThermalBaseB + R_PCH_TBARB_TSC) + ); + /// + /// Step 8.2 + /// TSMIC [7] locks SMI reporting of thermal events + /// + if (PchPlatformPolicy->ThermalConfig->ThermalAlertEnable.TsmicLock == PCH_DEVICE_ENABLE) { + MmioWrite8 (ThermalBaseB + R_PCH_TBARB_TSMIC, 0x80); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (ThermalBaseB + R_PCH_TBARB_TSMIC), + 1, + (VOID *) (UINTN) (ThermalBaseB + R_PCH_TBARB_TSMIC) + ); + } + + /// + /// Step 5 + /// If the PCH_Hot pin reporting is supported, then write the temperature value and set the enable in PHL. + /// + PchHotEnable = FALSE; +#ifdef TRAD_FLAG + if (PchSeries == PchH) { + /// + /// Note: For PCHHOT# support, we need to make sure if GPIO74 is set to native mode and PCHSTRP9[22] is + /// set to 1. + /// Check if GPIO74 is set to native mode. + /// + RegData8 = (UINT8)((IoRead32 ((UINTN) (GpioBase + R_PCH_GPIO_USE_SEL3)) & BIT10) >> 10); + } +#endif // TRAD_FLAG + +#ifdef ULT_FLAG + if (PchSeries == PchLp) { + /// + /// Note: For PCHHOT# support, we need to make sure if GPIO73 is set to native mode and PCHSTRP9[22] is + /// set to 1. + /// Check if GPIO73 is set to native mode. + /// + RegData8 = (UINT8)(IoRead32 ((UINTN) (GpioBase + R_PCH_GP_73_CONFIG0)) & B_PCH_GPIO_OWN0_GPIO_USE_SEL); + } +#endif // ULT_FLAG + + if(RegData8 == 0x00) { + /// + /// Check if PCHSTRP9[22] is set to 1 (PCHHOT# is the native functionality of GPIO74) + /// + if ((MmioRead16 (RootComplexBar + R_PCH_SPI_HSFS) & B_PCH_SPI_HSFS_FDV) == B_PCH_SPI_HSFS_FDV) { + MmioAnd32 ((RootComplexBar + R_PCH_SPI_FDOC), (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK))); + MmioOr32 ((RootComplexBar + R_PCH_SPI_FDOC), (UINT32) (V_PCH_SPI_FDOC_FDSS_PCHS | R_PCH_SPI_STRP9)); + if (MmioRead32 (RootComplexBar + R_PCH_SPI_FDOD) & B_PCH_SPI_STRP9_HOT_SML1_SEL) { + PchHotEnable = TRUE; + } + } + } + + /// + /// The value in PHL register is valid only if it is between 00h and 1FFh. + /// + if ((PchHotEnable == TRUE) && (PchPlatformPolicy->ThermalConfig->PchHotLevel < 0x0200)) { + /// + /// Program PHL register according to PchHotLevel setting. + /// + RegData16 = (PchPlatformPolicy->ThermalConfig->PchHotLevel | B_PCH_TBARB_PHLE); + MmioWrite16 (ThermalBaseB + R_PCH_TBARB_PHL, RegData16); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (ThermalBaseB + R_PCH_TBARB_PHL), + 1, + &RegData16 + ); + } + /// + /// Step 8.3 + /// PHLC [0] locks the PHL and PHLC registers for PCH_Hot# + /// + if (PchPlatformPolicy->ThermalConfig->ThermalAlertEnable.PhlcLock == PCH_DEVICE_ENABLE) { + MmioWrite8 (ThermalBaseB + R_PCH_TBARB_PHLC, 0x01); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (ThermalBaseB + R_PCH_TBARB_PHLC), + 1, + (VOID *) (UINTN) (ThermalBaseB + R_PCH_TBARB_PHLC) + ); + } + /// + /// PCH BIOS Spec Rev 0.5.0, Section 17.5 Thermal Throttling + /// Step 1 + /// Additional programming to initialize Thermal Throttle device + /// For LPT-H, + /// a. Program ThermalBAR + 0xC0 to 8000390Bh + /// b. Program ThermalBAR + 0xC4 to C11F0201h + /// c. Program ThermalBAR + 0xC8 to 05800000h + /// d. Program ThermalBAR + 0xCC to 0000C000h + /// e. Program ThermalBAR + 0xD0 to 00000320h + /// f. Program ThermalBAR + 0xE0 to 80001E4Fh + /// g. Program ThermalBAR + 0xF0 to 00000003h + /// For LPT-LP, + /// a. Program ThermalBar + 0xC0 to 8000390Bh + /// b. Program ThermalBar + 0xC4 to C11F0401h + /// c. Program ThermalBAR + 0xC8 to 05800000h + /// d. Program ThermalBar + 0xCC to 0000C000h + /// e. Program ThermalBar + 0xD0 to 00000320h + /// f. Program ThermalBar + 0xE0 to 80001EDCh + /// g. Program ThermalBar + 0xF0 to 00000003h + /// + + if (PchSeries == PchH) { + MmioWrite32 (ThermalBaseB + 0xC4, 0xC11F0201); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (ThermalBaseB + 0xC4), + 1, + (VOID *) (UINTN) (ThermalBaseB + 0xC4) + ); + + MmioWrite32 (ThermalBaseB + 0xE0, 0x80001E4F); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (ThermalBaseB + 0xE0), + 1, + (VOID *) (UINTN) (ThermalBaseB + 0xE0) + ); + } + + if (PchSeries == PchLp) { + MmioWrite32 (ThermalBaseB + 0xC4, 0xC11F0401); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (ThermalBaseB + 0xC4), + 1, + (VOID *) (UINTN) (ThermalBaseB + 0xC4) + ); + + MmioWrite32 (ThermalBaseB + 0xE0, 0x80001EDC); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (ThermalBaseB + 0xE0), + 1, + (VOID *) (UINTN) (ThermalBaseB + 0xE0) + ); + } + + MmioWrite32 (ThermalBaseB + 0xC0, 0x8000390B); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (ThermalBaseB + 0xC0), + 1, + (VOID *) (UINTN) (ThermalBaseB + 0xC0) + ); + + MmioWrite32 (ThermalBaseB + 0xC8, 0x05800000); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (ThermalBaseB + 0xC8), + 1, + (VOID *) (UINTN) (ThermalBaseB + 0xC8) + ); + + MmioWrite32 (ThermalBaseB + 0xCC, 0x0000C000); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (ThermalBaseB + 0xCC), + 1, + (VOID *) (UINTN) (ThermalBaseB + 0xCC) + ); + + MmioWrite32 (ThermalBaseB + 0xD0, 0x00000320); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (ThermalBaseB + 0xD0), + 1, + (VOID *) (UINTN) (ThermalBaseB + 0xD0) + ); + + MmioWrite32 (ThermalBaseB + 0xF0, 0x00000003); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (ThermalBaseB + 0xF0), + 1, + (VOID *) (UINTN) (ThermalBaseB + 0xF0) + ); + /// + /// HSW BWG 15.8 : Processor PCH-LP cross throttling + /// + if (PchSeries == PchLp){ + AsmCpuid (CPUID_VERSION_INFO, &Cpuid.RegEax, &Cpuid.RegEbx, &Cpuid.RegEcx, &Cpuid.RegEdx); + if (((Cpuid.RegEax & CPUID_FULL_FAMILY_MODEL) == CPUID_FULL_FAMILY_MODEL_HASWELL_ULT) && + ((PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.PchCrossThrottling == PCH_DEVICE_ENABLE) || + (PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.SuggestedSetting == PCH_DEVICE_ENABLE))) { + // + // Read MSR 0x1A2 TEMPERATURE_TARGET + // + TempMsr.Qword = AsmReadMsr64 (MSR_TEMPERATURE_TARGET); + /// + /// Tcc activation offset in temperature target MSR changes from 4 bits [27:24] to 6 bits [29:24] on ULT C step onwards + /// since Tcc will never be more than 205C, thus the calculation for PHL will never overflow + /// + if ((Cpuid.RegEax & CPUID_FULL_STEPPING) >= EnumHswUltC0) { + temperature = (TempMsr.Bytes.ThirdByte - (TempMsr.Bytes.FouthByte & 0x3F)); + } else { + temperature = (TempMsr.Bytes.ThirdByte - (TempMsr.Bytes.FouthByte & 0xF)); + } + + if (PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.SuggestedSetting == PCH_DEVICE_ENABLE) { + /// + /// PCH T0/T1/T2 Level (MMIO TBARB+40h) : + /// T0L = (((MSR TEMPERATURE_TARGET[23:16] - TEMPERATURE_TARGET) + 50) * 2) + /// T1L = T0L + 5C + /// T2L = T1L + 5C + /// + PchTTLevels = (UINT32)((( temperature + 10 + 50) * 2) << 20) | + (UINT32)(((temperature + 5 + 50) * 2) << 10) | + (UINT32)((temperature + 50) * 2); + Data32Or = BIT31 | BIT29; + } else { + PchTTLevels = (UINT32) (((PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.T2Level + 10 + 50) * 2) << 20) | + (UINT32) (((PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.T1Level + 5 + 50) * 2) << 10) | + (UINT32) ((PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.T0Level + 50) * 2); + Data32Or = (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.TTLock << 31) | + (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.TTState13Enable << 30) | + (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.TTEnable << 29); + } + } + } else if (PchSeries == PchH) { + if (PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.SuggestedSetting == PCH_DEVICE_ENABLE) { + /// + /// Set TBARB + 40h = 0B485093Ch + /// Program TBARB + 40h[31:28] in separate write + /// + PchTTLevels = 0xB485093C; + Data32Or = BIT31 | BIT29; + }else { + /// + /// PCH BIOS Spec Rev 0.5.5, Section 17.3.1 Initializing Lynx Point Thermal Sensors + /// Trip Point Temperature = (Trip Point Register [8:0]) / 2 - 50 centigrade degree + /// If Trip Point Temperature <= T0Level, the system will be in T0 state. + /// If T1Level >= Trip Point Temperature > T0Level, the system will be in T1 state. + /// If T2Level >= Trip Point Temperature > T1Level, the system will be in T2 state. + /// If Trip Point Temperature > T2Level, the system will be in T3 state. + /// + PchTTLevels = (UINT32) (((PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.T2Level + 50) * 2) << 20) | + (UINT32) (((PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.T1Level + 50) * 2) << 10) | + (UINT32) ((PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.T0Level + 50) * 2); + Data32Or = (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.TTLock << 31) | + (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.TTState13Enable << 30) | + (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.TTEnable << 29); + } + } + + /// + /// Program TBARB + 40h[27:0] + /// + MmioWrite32 (ThermalBaseB + R_PCH_TBARB_TL, PchTTLevels); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (ThermalBaseB + R_PCH_TBARB_TL), + 1, + (VOID *) (UINTN) (ThermalBaseB + R_PCH_TBARB_TL) + ); + /// + /// Program TBARB + 40h[31:28] + /// + /// PCH BIOS Spec Rev 0.5.0, 17.3.1 Initializing Lynx Point Thermal Sensors + /// Step 8.4 + /// TL [31] locks the thermal throttling registers + /// + MmioOr32 (ThermalBaseB + R_PCH_TBARB_TL, Data32Or); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (ThermalBaseB + R_PCH_TBARB_TL), + 1, + (VOID *) (UINTN) (ThermalBaseB + R_PCH_TBARB_TL) + ); + + if (PchSeries == PchLp) { + /// + /// Processor PCH-LP cross throttling - Set RCBA MMIO offset 0x33C4[26:24] = 101b + /// + AsmCpuid (CPUID_VERSION_INFO, &Cpuid.RegEax, &Cpuid.RegEbx, &Cpuid.RegEcx, &Cpuid.RegEdx); + if (((Cpuid.RegEax & CPUID_FULL_FAMILY_MODEL) == CPUID_FULL_FAMILY_MODEL_HASWELL_ULT) && + ((PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.PchCrossThrottling == PCH_DEVICE_ENABLE) || + (PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.SuggestedSetting == PCH_DEVICE_ENABLE))) { + Data32And = (UINT32)~(BIT26 | BIT25 | BIT24); + Data32Or = BIT26 | BIT24; + MmioAndThenOr32 ((UINTN) (RootComplexBar + PMSYNC_TPR_CONFIG), Data32And, Data32Or); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + PMSYNC_TPR_CONFIG), + 1, + (VOID *) (UINTN) (RootComplexBar + PMSYNC_TPR_CONFIG) + ); + } + /// + /// Lock PMSYNC_TPR_CFG and PMSYNC_TPR_CFG2 + /// Set RCBA + 0x33C4[31] = 1b. + /// + MmioOr32 (RootComplexBar + PMSYNC_TPR_CONFIG,B_PMSYNC_TPR_CONFIG_LOCK); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + PMSYNC_TPR_CONFIG), + 1, + (VOID *) (UINTN) (RootComplexBar + PMSYNC_TPR_CONFIG) + ); + } + + if (PchSeries == PchH) { + /// + /// PCH BIOS Spec Rev 0.5.0, Section 17.5 Thermal Throttling + /// Step 3 + /// Set Chipset Initialization Register 30 (RCBA + 2238h) = 00000941h + /// + if (PchPlatformPolicy->ThermalConfig->ThermalThrottling.DmiHaAWC.SuggestedSetting == PCH_DEVICE_ENABLE) { + RegData32 = 0x00000941; + } else { + RegData32 = (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.DmiHaAWC.TS3TW << 10) | + (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.DmiHaAWC.TS2TW << 8) | + (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.DmiHaAWC.TS1TW << 6) | + (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.DmiHaAWC.TS0TW << 4) | + (UINT32) PchPlatformPolicy->ThermalConfig->ThermalThrottling.DmiHaAWC.DmiTsawEn; + } + /// + /// If DMI IOT is enabled, set chipset Initialization Register 30 (RCBA + 2238h) = 00000551h + /// + if (PchPlatformPolicy->DmiConfig->DmiIot == PCH_DEVICE_ENABLE) { + RegData32 = 0x00000551; + } + MmioWrite32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CIR2238), RegData32); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2238), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2238) + ); + } + + /// + /// Step 4 + /// Program SATA Indexed Register Index and Data: + /// a. If port 0 is empty, set D31:F2:A0h=A0h and D31:F2:A4h[15:00] = 0000h + /// else if Port 0 has a HDD, set D31:F2:A4h[15:00] = 0039h + /// else if Port 0 has a SSD, set D31:F2:A4h[15:00] = 0F39h + /// b. If port 1 is empty, set D31:F2:A0h=A0h and D31:F2:A4h[31:16] = 0000h + /// else if Port 1 has a HDD, set D31:F2:A4h[31:16] = 0039h + /// else if Port 1 has a SSD, set D31:F2:A4h[31:16] = 0F39h + /// c. If port 2 is empty, set D31:F2:A0h=A4h and D31:F2:A4h[15:00] = 0000h + /// else if Port 2 has a HDD, set D31:F2:A4h[15:00] = 0039h + /// else if Port 2 has a SSD, set D31:F2:A4h[15:00] = 0F39h + /// d. If port 3 is empty, set D31:F2:A0h=A4h and D31:F2:A4h[31:16] = 0000h + /// else if Port 3 has a HDD, set D31:F2:A4h[31:16] = 0039h + /// else if Port 3 has a SSD, set D31:F2:A4h[31:16] = 0F39h + /// e. If port 4 is empty, set D31:F2:A0h=A8h and D31:F2:A4h[15:00] = 0000h + /// else if Port 4 has a HDD, set D31:F2:A4h[15:00] = 0039h + /// else if Port 4 has a SSD, set D31:F2:A4h[15:00] = 0F39h + /// f. If port 5 is empty, set D31:F2:A0h=A8h and D31:F2:A4h[31:16] = 0000h + /// else if Port 5 has a HDD, set D31:F2:A4h[31:16] = 0039h + /// else if Port 5 has a SSD, set D31:F2:A4h[31:16] = 0F39h + /// + MaxSataPortNum = GetPchMaxSataPortNum(); + RegData16 = MmioRead16 (PciD31F2RegBase + R_PCH_SATA_PCS); + for (Index = 0; Index < (MaxSataPortNum / 2); Index++) { + Data32And = 0x70C070C0; + Data32Or = 0x00000000; + if (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.SuggestedSetting == PCH_DEVICE_ENABLE) { + if ((RegData16 & (B_PCH_SATA_PCS_PORT0_DET << (Index * 2))) != 0) { + Data32Or |= 0x00000039; + if (PchPlatformPolicy->SataConfig->PortSettings[0 + (Index * 2)].SolidStateDrive == PCH_DEVICE_ENABLE) { + Data32Or |= 0x00000F00; + } + } + + if ((RegData16 & (B_PCH_SATA_PCS_PORT0_DET << ((Index * 2) + 1))) != 0) { + Data32Or |= 0x00390000; + if (PchPlatformPolicy->SataConfig->PortSettings[1 + (Index * 2)].SolidStateDrive == PCH_DEVICE_ENABLE) { + Data32Or |= 0x0F000000; + } + } + } else { + Data32Or = (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P1TDispFinit << 31) | + (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P1Tinact << 26) | + (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P1TDisp << 24) | + (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P1T3M << 20) | + (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P1T2M << 18) | + (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P1T1M << 16) | + (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P0TDispFinit << 15) | + (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P0Tinact << 10) | + (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P0TDisp << 8) | + (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P0T3M << 4) | + (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P0T2M << 2) | + (UINT32) PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P0T1M; + } + + MmioWrite8 (PciD31F2RegBase + R_PCH_SATA_SIRI, (0xA0 + (Index * 4))); + MmioAndThenOr32 ((UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), Data32And, Data32Or); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD) + ); + } + + /// + /// Program ThermalBar + 0xA4 [1:0] = 11b + /// + MmioOr8 (ThermalBaseB + 0xA4, (UINT8) (BIT1 | BIT0)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (ThermalBaseB + 0xA4), + 1, + (VOID *) (UINTN) (ThermalBaseB + 0xA4) + ); + /// + /// PCH BIOS Spec Rev 0.5.0, 17.3.1 Initializing Lynx Point Thermal Sensors + /// Step 7 + /// Enable thermal sensor by programming TSEL register to 01h + /// This should be done after all thermal initialization steps are finished. + /// + RegData8 = MmioRead8 (ThermalBaseB + R_PCH_TBARB_TSEL); + RegData8 |= (UINT8) B_PCH_TBARB_TSEL_ETS; + /// + /// Step 8.5 + /// TSEL [7] locks the thermal sensor enable, after TAHV and TAHL are programmed by BIOS or driver + /// later in case. + /// + if (PchPlatformPolicy->ThermalConfig->ThermalAlertEnable.TselLock == PCH_DEVICE_ENABLE) { + RegData8 |= (UINT8) B_PCH_TBARB_TSEL_PLD; + } + + MmioWrite8 (ThermalBaseB + R_PCH_TBARB_TSEL, RegData8); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (ThermalBaseB + R_PCH_TBARB_TSEL), + 1, + (VOID *) (UINTN) (ThermalBaseB + R_PCH_TBARB_TSEL) + ); + /// + /// Step 8.6 + /// Program ThermalBAR + 0x0A [7] = 1b + /// For LP, Program ThermalBar + 0x0A [7, 0] = 1b, 1b + /// + RegData8 = BIT7; + if (PchSeries == PchLp) { + RegData8 |= BIT0; + } + MmioOr8 (ThermalBaseB + R_PCH_TBARB_TSREL, RegData8); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (ThermalBaseB + R_PCH_TBARB_TSREL), + 1, + (VOID *) (UINTN) (ThermalBaseB + R_PCH_TBARB_TSREL) + ); + + /// + /// For LP, Program ThermalBar + 0x1C [14:0] = 48C8h + /// For LP, Program ThermalBar + 0x1C [15] = 1h + /// + if (PchSeries == PchLp) { + Data16And = (B_PCH_TBARB_TSPM_LTT | B_PCH_TBARB_TSPM_MAXTSST | B_PCH_TBARB_TSPM_MINTSST | B_PCH_TBARB_TSPM_DTSSIC0 | + B_PCH_TBARB_TSPM_DTSSS0EN); + Data16Or = (V_PCH_TBARB_TSPM_LTT | V_PCH_TBARB_TSPM_MAXTSST | B_PCH_TBARB_TSPM_DTSSS0EN); + MmioAndThenOr16 (ThermalBaseB + R_PCH_TBARB_TSPM, + (UINT16) Data16And, + (UINT16) Data16Or); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (ThermalBaseB + R_PCH_TBARB_TSPM), + 1, + (VOID *) (UINTN) (ThermalBaseB + R_PCH_TBARB_TSPM) + ); + + MmioOr16 (ThermalBaseB + R_PCH_TBARB_TSPM, (UINT16) B_PCH_TBARB_TSPM_TSPMLOCK); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (ThermalBaseB + R_PCH_TBARB_TSPM), + 1, + (VOID *) (UINTN) (ThermalBaseB + R_PCH_TBARB_TSPM) + ); + } + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 17.2, Thermal Subsystem Device Initialization + /// Step 5 + /// BIOS needs to perform the following steps prior to end of POST to free up the PCI resources + /// and hide the thermal subsystem device(OPTIONAL), except on mobile platforms that support + /// Intel DPPM. Also, BIOS may keep the TBARBH programmed if BIOS needs runtime access to PCH + /// thermal subsystem device data. In that case, BIOS must ensure TBARBH memory is reserved and + /// reported to the OS as motherboard resources to avoid memory allocation conflicts. + /// + if (PchPlatformPolicy->ThermalConfig->ThermalDeviceEnable == FALSE) { + /// + /// Step 5.1 + /// Clear the Memory and Bus Master enable bit of D31:F6 + /// + MmioAnd16 ( + PciD31F6RegBase + R_PCH_THERMAL_COMMAND, + (UINT16)~(B_PCH_THERMAL_COMMAND_MSE | B_PCH_THERMAL_COMMAND_BME) + ); + /// + /// Step 5.2 + /// Clear and release memory resource assigned in TBAR (D31:F6:10h-13h) + /// + ThermalBase = MmioRead32 (PciD31F6RegBase + R_PCH_THERMAL_TBAR) & B_PCH_THERMAL_TBAR_MASK; + + if ((ThermalBase != 0) && (ThermalBase != B_PCH_THERMAL_TBAR_MASK)) { + MmioWrite32 (PciD31F6RegBase + R_PCH_THERMAL_TBAR, 0); + MmioWrite32 (PciD31F6RegBase + R_PCH_THERMAL_TBARH, 0); + + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F6RegBase + R_PCH_THERMAL_TBAR), + 1, + (VOID *) (UINTN) (PciD31F6RegBase + R_PCH_THERMAL_TBAR) + ); + + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F6RegBase + R_PCH_THERMAL_TBARH), + 1, + (VOID *) (UINTN) (PciD31F6RegBase + R_PCH_THERMAL_TBARH) + ); + + gDS->FreeMemorySpace ( + (EFI_PHYSICAL_ADDRESS) ThermalBase, + V_PCH_THERMAL_TBAR_SIZE + ); + } + /// + /// Step 5.3 + /// Optionally, release and clear memory resource assigned in TBARB (D31:F6:40h-48h) if BIOS/ASL + /// implementation does not require access to PCH thermal subsystem device data during run time. + /// Left this to platform code + /// + /// Step 5.4 + /// Hide D31:F6 PCI configuration space by setting FD.TTD (RCBA + 3418h[24]) + /// + Data32And = 0xFFFFFFFF; + Data32Or = (UINT32) B_PCH_RCRB_FUNC_DIS_THERMAL; + MmioOr32 (RootComplexBar + R_PCH_RCRB_FUNC_DIS, Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_FUNC_DIS), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + /// + /// Reads back for posted write to take effect + /// + Data32Or = MmioRead32 ((UINTN) (RootComplexBar + R_PCH_RCRB_FUNC_DIS)); + SCRIPT_MEM_POLL ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_FUNC_DIS), + &Data32Or, // BitMask + &Data32Or, // BitValue + 1, // Duration + 1 // LoopTimes + ); + } + + DEBUG ((EFI_D_INFO, "ThermalLockDown() End\n")); + + return EFI_SUCCESS; +} + +/** + Perform Clock Gating programming + Enables clock gating in various PCH interfaces and the registers must be restored during S3 resume. + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in] FuncDisableReg The Function Disable Register + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ConfigureClockGating ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar, + IN UINT32 FuncDisableReg + ) +{ + UINT8 RegData8; + UINT32 RegData32; + UINT32 RegDataOr32; + UINT32 RegDataAnd32; + UINTN PciD31F0RegBase; + UINT16 LpcDeviceId; + UINT16 Data16Or; + PCH_SERIES PchSeries; + UINT32 D2F0Base; + + DEBUG ((EFI_D_INFO, "ConfigureClockGating() Start\n")); + + PchSeries = GetPchSeries(); + PciD31F0RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 0, 0); + LpcDeviceId = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_DEVICE_ID); + + /// + /// PCH BIOS Spec Rev 0.5.5, section 19.10 + /// 1 + /// DMI interface + /// Enable Dynamic Clock Gating in the DMIC register by programming + /// For PCH LP + /// RCBA + 2234h [2] to 1b, RCBA + 2234h [0] to 1b + /// RCBA + 2234h [3:0] to 1111b + /// Set D31:F0:A0h[5] = 1b + /// Set D31:F0:A0h[6] = 1b + /// Set D31:F0:A0h[7] = 1b + /// Set D31:F0:A0h[11] = 0b + /// Set D31:F0:A0h[12] = 1b + /// For PCH H + /// RCBA + 2234h [3:0] to 1111b + /// Enable Dynamic Clock Gating in the DMIC register by programming RCBA + 2234h [3:0] to 1111b + /// before enabling ASPM. + /// Set D31:F0:A0h[11] = 1b + /// Set D31:F0:A0h[12] = 1b + /// Set D31:F0:A0h[14] = 1b. + /// System BIOS is also required to set following bit. + /// Dekstop: "Pseudo CLKRUN_EN (PSEUDO_CLKRUN_EN)" bit (D31:F0:A0h[3]) = 1b + /// Mobile: "PCI CLKRUN# Enable" bit (D31:F0:A0h[2]) = 1b + /// + switch (PchSeries) { + case PchLp: + MmioOr8 ((UINTN) (RootComplexBar + R_PCH_RCRB_DMIC), (UINT8) (B_PCH_LP_RCRB_DMIC_DMICGEN)); + break; + + case PchH: + MmioOr8 ((UINTN) (RootComplexBar + R_PCH_RCRB_DMIC), (UINT8) (B_PCH_H_RCRB_DMIC_DMICGEN)); + break; + + default: + break; + } + + if (PchSeries == PchLp) { + Data16Or = (UINT16)(BIT12 | BIT7 | BIT6 | BIT5); + Data16Or |= BIT11; + MmioOr16 ((UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1), Data16Or); + } else if (PchSeries == PchH) { + MmioOr16 ((UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1), (UINT16) (BIT14 | BIT12 | BIT11)); + } + + if (PchPlatformPolicy->DeviceEnabling->PciClockRun == PCH_DEVICE_DISABLE) { + if (IS_PCH_LPT_LPC_DEVICE_ID_MOBILE (LpcDeviceId)) { + MmioAnd16 ((UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1), (UINT16) (~B_PCH_LPC_GEN_PMCON_CLKRUN_EN)); + } else { + MmioAnd16 ((UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1), (UINT16) (~B_PCH_LPC_GEN_PMCON_PSEUDO_CLKRUN_EN)); + } + } else { + if (IS_PCH_LPT_LPC_DEVICE_ID_MOBILE (LpcDeviceId)) { + MmioOr16 ((UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1), (UINT16) (B_PCH_LPC_GEN_PMCON_CLKRUN_EN)); + } else { + MmioOr16 ((UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1), (UINT16) (B_PCH_LPC_GEN_PMCON_PSEUDO_CLKRUN_EN)); + } + } + + RegData8 = MmioRead8 (RootComplexBar + R_PCH_RCRB_DMIC); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (RootComplexBar + R_PCH_RCRB_DMIC), + 1, + &RegData8 + ); + + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1), + 1, + (VOID *) (UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1) + ); + + if (PchSeries == PchLp) { + /// + /// Set RCBA + 2614h[27:25],[14:13],[10],[8] = 101b, 11b, 1b, 1b respectively + /// Set RCBA + 2614h[23:16] = 0x20 + /// Set RCBA + 2614h[30:28] = 0b + /// Set RCBA + 2614h[26] = 1b if D2F0+8 >= 0x0B + /// + D2F0Base = MmPciAddress (0, 0, 2, 0, 0); + RegDataAnd32 = (UINT32) ~(BIT30 | BIT29 | BIT28 | BIT26 | 0x00FF0000); + RegDataOr32 = (UINT32) (BIT27 | BIT25 | BIT21 | BIT14 | BIT13 | BIT10 | BIT8); + if ((MmioRead16 (D2F0Base) != 0xFFFF) && (MmioRead8 (D2F0Base + 8) >= 0x0B)) { + RegDataOr32 |= (UINT32) BIT26; + } + MmioAndThenOr32 ( + (UINTN) (RootComplexBar + 0x2614), + RegDataAnd32, + RegDataOr32 + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x2614), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x2614) + ); + /// + /// Set Chipset Initialization Register 2 [4:0] (RCBA + 900h) = 11111b + /// Set Chipset Initialization Register 2 [9:8] (RCBA + 900h) = 11b + /// + MmioOr32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR0900), + (UINT32) (BIT9 | BIT8 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR0900), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR0900) + ); + } else if (PchSeries == PchH) { + /// + /// Set Chipset Initialization Register 2 [14] (RCBA + 900h) = 1b + /// + MmioOr32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR0900), + (UINT32) (BIT14) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR0900), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR0900) + ); + } + /// + /// 2 + /// PCI Express* interface + /// 2.1 + /// For each enabled PCI Express* root port, program D28:F0~F7:Reg E1h[1:0] to 3h to enable dynamic clock gating. + /// System BIOS also require to set D28:F0~F7:Reg E8h[0] = 1b + /// 2.2 + /// Additionally, if port 0 is in x2 mode, these bits should not be set for port 1. + /// Likewise, if port 0 is in x4 mode, these bits should not be set for ports 1, 2, or 3 + /// Done in PchRootPorts.c PcieEnableClockGating + /// 2.2.1 + /// If PCIe root ports 0-3 are all disabled, set B0:D28:F0 + E2h[0] = 1b + /// if PCIe root ports 4-7 are all disabled, set B0:D28:F4 + E2h[0] = 1b + /// 2.3 + /// Set B0:D28:F0&F4 + E1h [5:2] = 1111b + /// 2.4 + /// Set B0:D28:F0&F4:E1h[7] = 1b + /// 2.6 + /// Set B0:D28:F0~F7 + 324h[5] = 1b + /// Done in PchRootPorts.c PcieEnableClockGating + /// + /// Reg RCBA+341C is modified at multiple places, save at the end of the function + /// + /// 3 + /// Serial ATA* + /// - Set bits D31:F2:94h[29:24] to 3Fh as part of the chipset initialization before disabling + /// the SATA function when the SATA interface is not supported on the platform. BIOS can also + /// set PCD bits to disable clocks for the un-routed ports on the platform. + /// - After configuring Port and Control Status (PCS) Register Port x Enabled (PxE) bits accordingly, + /// wait 1.4 micro second, then the PCD bits (D31:F2:Reg 94h[29:24]) should be set to be the inverse + /// of the Port and Control Status (PCS) Register Port x Enabled (PxE) bits + /// Please note that PCS should be set and PCD should not be set when ports are enabled for hot + /// plug support or used for SATA testing in test mode. + /// Done in ConfigureSata(); + /// - Program D31:F2:98h[29] to 1b + /// Done in PchInitBeforeBoot() + /// - Set SATA Initialization Register 70h[31:0] = 3F00BF1Fh (Done in ConfigureMiscPm) + /// Set SATA Initialization Register 54h[31:0] = CF000F0Fh (Done in ConfigureMiscPm) + /// Set SATA Initialization Register 58h[31:0] = 190000h (Done in ConfigureMiscPm) + /// + /// 4 + /// USB 1.1 / USB 2.0 / USB 3.0 + /// + /// ConfigureUsbClockGating() has been moved to ConfigureMiscPm() to run before Function Disable + /// + /// 5 + /// Intel High Definition Audio (HDA) controller. + /// + if (FuncDisableReg & B_PCH_RCRB_FUNC_DIS_AZALIA) { + /// + /// 5.1 + /// If the HD Audio Controller is not being used, D27:F0 can be disabled and statically gated. Only statically + /// gate the Intel High Definition Audio controller if it is not being used in the system by setting RCBA + 341Ch[21]. + /// + MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (B_PCH_RCRB_CG_EN_SCG_HDA)); + } else { + /// + /// 5.2 + /// When the Intel High Definition Audio controller is used in the system, + /// dynamic clock gating can be used by setting RCBA + 341Ch[22]. + /// + MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (B_PCH_RCRB_CG_EN_DCG_HDA)); + } + if (PchSeries == PchLp) { + /// + /// For PchLp, set RCBA + 341Ch[22] + /// + MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (B_PCH_RCRB_CG_EN_DCG_HDA)); + /// + /// 5.3 + /// Set D27:F0:43h[6:5][2:0] = 11b, 111b (Done in ConfigureMiscPm) + /// + } + /// + /// Reg RCBA+341C is modified at multiple places, save at the end of the function + /// + /// 7 + /// LPC. + /// Enable dynamic clock gating by setting RCRB+341C[31] to 1b. + /// + MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (B_PCH_RCRB_CG_EN_DCG_LPC)); + if (PchSeries == PchH) { + /// + /// Reg RCBA+341C is modified at multiple places, save at the end of the function + /// + /// 8 + /// PCI Interface. + /// Enable PCI dynamic clock gating by setting RCBA + 341Ch[16]. + /// + MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (B_PCH_RCRB_CG_EN_DCG_PCI)); + } else if (PchSeries == PchLp) { + /// + /// Set RCRB+341Ch[30][28:26] to 1b, 111b + /// + MmioOr32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CG), + (UINT32) (B_PCH_RCRB_CG_EN_DCG_BLA | B_PCH_RCRB_CG_EN_DCG_GPIO | B_PCH_RCRB_CG_EN_DCG_HPET | + B_PCH_RCRB_CG_EN_CG_GPEC)); + /// + /// Set RCRB+3434h[2:0] to 111b + /// + MmioOr8 ( + (UINTN) (RootComplexBar + 0x3434), + (UINT8) (BIT2 | BIT1 | BIT0) + ); + RegData8 = MmioRead8 (RootComplexBar + 0x3434); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (RootComplexBar + 0x3434), + 1, + &RegData8 + ); + /// + /// If RCRB+3454h[4] is 0b, then set RCRB+341C[29] to 1b, else set RCRB+341C[29] to 0b + /// + if ((MmioRead32 (RootComplexBar + R_PCH_RCRB_GSX_CTRL) & B_PCH_RCRB_GSX_BAR_ENABLE) == 0) { + MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (B_PCH_RCRB_CG_EN_SCG_GSX)); + } else { + MmioAnd32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (~B_PCH_RCRB_CG_EN_SCG_GSX)); + } + } + /// + /// PCH BIOS Spec Rev 0.5.0, Section 10.2.1/10.2.2 Enable/Disable the GbE Clock Gating + /// Set RCBA + 341Ch[23] + /// + if (PchPlatformPolicy->DeviceEnabling->Lan == PCH_DEVICE_ENABLE) { + MmioAnd32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (~B_PCH_RCRB_CG_EN_SCG_LAN)); + } else { + MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (B_PCH_RCRB_CG_EN_SCG_LAN)); + } + if (PchSeries == PchLp) { + /// + /// 9 + /// SPI Clock gating. + /// Enable SPI clock gating by programming RCBA + 38C0h [13:10][2:0] to 1111b, 111b + /// + MmioOr32 ( + (UINTN) (RootComplexBar + R_PCH_SPI_AFC), + (UINT32) (BIT13 | BIT12 | BIT11 | BIT10 | B_PCH_SPI_AFC_INF_DCGE | B_PCH_SPI_AFC_CORE_DCGE) + ); + RegData32 = MmioRead32 (RootComplexBar + R_PCH_SPI_AFC); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_SPI_AFC), + 1, + &RegData32 + ); + } else if (PchSeries == PchH) { + /// + /// 9 + /// SPI Clock gating. + /// Enable SPI clock gating by programming RCBA + 38C0h [2:0] to 111b + /// + MmioOr32 ( + (UINTN) (RootComplexBar + R_PCH_SPI_AFC), + (UINT32) (B_PCH_SPI_AFC_INF_DCGE | B_PCH_SPI_AFC_CORE_DCGE) + ); + RegData32 = MmioRead32 (RootComplexBar + R_PCH_SPI_AFC); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_SPI_AFC), + 1, + &RegData32 + ); + } + /// + /// 10 + /// SMBus + /// Enable SMBus dynamic clock gating by setting D31:F3:80h [8, 10, 12 and 14] = 0b respectively (Done in ConfigureMiscPm) + /// + /// + /// PCH BIOS Spec Rev 0.5.5, section 19.10 + /// 11 + /// Misc + /// Set D31:F2:300h [17:16] = 11b (Done in ConfigureMiscPm) + /// + + if (PchSeries == PchLp) { + /// + /// Set D31:F2:98h [31:30], [23] to 00b, 1b (Done in ConfigureMiscPm) + /// + /// Set iobp register CE00C000h[0] to 0b + /// + ProgramIobpWithScript ( + RootComplexBar, + 0xCE00C000, + (UINT32)~(BIT0), + 0 + ); + + /// + /// Disable legacy DMA (8237) if desired + /// Set RCBA + Offset 0x341C[24] = 1 + /// + if ((PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_4) + && PchPlatformPolicy->PwrOptConfig->LegacyDmaDisable) + { + MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (B_PCH_RCRB_CG_EN_SCG_8237)); + } + } + /// + /// Save 341C value to the S3 script table. This register is modified at multiple places in this function. So instead of saving + /// at each location read the value once at the end of the function and save in S3 resume script. + /// + RegData32 = MmioRead32 (RootComplexBar + R_PCH_RCRB_CG); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CG), + 1, + &RegData32 + ); + + DEBUG ((EFI_D_INFO, "ConfigureClockGating() End\n")); + + return EFI_SUCCESS; +} + +/** + Configure miscellaneous power management settings + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in] GpioBase GPIO base address of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ConfigureMiscPm ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar, + IN UINT16 GpioBase + ) +{ + UINT8 Data8Or; + UINT8 Data8And; + UINT32 RegData32; + UINT16 RegData16; + UINT32 RegData32Tmp; + UINTN PciD31F0RegBase; + UINTN PciD31F3RegBase; + UINTN PciD31F2RegBase; + UINT16 LpcDeviceId; + UINTN PciD27F0RegBase; + PCH_SERIES PchSeries; + UINT32 DsxCfg; + + DEBUG ((EFI_D_INFO, "ConfigureMiscPm() Start\n")); + + PchSeries = GetPchSeries(); + PciD31F0RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 0, 0); + PciD31F3RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 3, 0); + PciD31F2RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 2, 0); + LpcDeviceId = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_DEVICE_ID); + PciD27F0RegBase = 0; + if (PchSeries == PchLp) { + PciD27F0RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 27, 0, 0); + } + + /// + /// Clear power / reset status bits on PCH Corporate + /// + RegData32 = 0; + if (PchPlatformPolicy->MiscPmConfig->PowerResetStatusClear.MeWakeSts) { + RegData32 |= B_PCH_RCRB_PRSTS_ME_WAKE_STS; + } + + if (PchPlatformPolicy->MiscPmConfig->PowerResetStatusClear.MeHrstColdSts) { + RegData32 |= B_PCH_RCRB_PRSTS_ME_HRST_COLD_STS; + } + + if (PchPlatformPolicy->MiscPmConfig->PowerResetStatusClear.MeHrstWarmSts) { + RegData32 |= B_PCH_RCRB_PRSTS_ME_HRST_WARM_STS; + } + + if (PchPlatformPolicy->MiscPmConfig->PowerResetStatusClear.MeHostPowerDn) { + RegData32 |= B_PCH_RCRB_PRSTS_ME_HOST_PWRDN; + } + + if (PchPlatformPolicy->MiscPmConfig->PowerResetStatusClear.WolOvrWkSts) { + RegData32 |= B_PCH_RCRB_PRSTS_WOL_OVR_WK_STS; + } + + MmioOr32 (RootComplexBar + R_PCH_RCRB_PRSTS, RegData32); + RegData32Tmp = 0xFFFFFFFF; + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + RootComplexBar + R_PCH_RCRB_PRSTS, + &RegData32, // OR mask + &RegData32Tmp // AND mask + ); + + /// + /// We need to enable GP27_PIN_DSX_EN for Wake from both SX and DSX + /// + DsxCfg = MmioRead32(RootComplexBar + 0x3334); + if (PchPlatformPolicy->MiscPmConfig->WakeConfig.Gp27WakeFromDeepSx == PCH_DEVICE_ENABLE) { + DsxCfg |= BIT0; + } else { + DsxCfg &= ~BIT0; + } + + /// + /// Enable WAKE_PIN__DSX_EN for Wake + /// + if(PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_5) { + if (PchPlatformPolicy->MiscPmConfig->WakeConfig.PcieWakeFromDeepSx == PCH_DEVICE_ENABLE) { + DsxCfg |= BIT2; + } else { + DsxCfg &= ~BIT2; + } + } + MmioWrite32 ((RootComplexBar + 0x3334), DsxCfg); + + /// + /// Handle wake policy + /// Don't need to record in S3 script as R_PCH_LPC_GEN_PMCON_3 is in RTC and SUS power well + /// + RegData16 = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_3) & + (UINT16) (~(B_PCH_LPC_GEN_PMCON_PME_B0_S5_DIS + + B_PCH_LPC_GEN_PMCON_WOL_ENABLE_OVERRIDE)); + + if (PchPlatformPolicy->MiscPmConfig->WakeConfig.PmeB0S5Dis) { + RegData16 |= B_PCH_LPC_GEN_PMCON_PME_B0_S5_DIS; + MmioWrite16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_3, RegData16); + } + + if (PchPlatformPolicy->MiscPmConfig->WakeConfig.WolEnableOverride) { + /// + /// PCH BIOS Spec Rev 0.5.0 Section 10.4 Wake-On-LAN (WOL) Implementation + /// Step 1 + /// Clear D31:F0:A2h[14] = 0b to ensure the LAN PHY will be powered for WOL + /// when the power source is either the AC or the DC battery. + /// + RegData16 = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_2); + RegData16 &= (UINT16) ~B_PCH_LPC_GEN_PMCON_DC_PP_DIS; + + /// + /// Step 2 + /// Clear D31:F0:A2h[13] = 0b to ensure the LAN PHY will be powered for WOL in Deep Sx. + /// + RegData16 &= (UINT16) ~B_PCH_LPC_GEN_PMCON_DSX_PP_DIS; + + /// + /// Step 3 + /// Set D31:F0:A2h[12] = 1b to ensure the LAN PHY will be powered for WOL after a G3 transition. + /// + RegData16 |= (UINT16) B_PCH_LPC_GEN_PMCON_AG3_PP_EN; + + /// + /// Step 4 + /// Set D31:F0:A2h[11] = 1b to ensure the LAN PHY will be powered for WOL from Sx. + /// + RegData16 |= (UINT16) B_PCH_LPC_GEN_PMCON_SX_PP_EN; + MmioWrite16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_2, RegData16); + + /// + /// Step 5 + /// "PME_B0_EN", PMBASE + Offset 28h[13], bit must be programmed to enable wakes + /// from S1-S4 at the Power Management Controller + /// Done in ASL code(_PRW) + /// + /// + /// Step 6 + /// Set "WOL Enable Override", D31:F0:A4h:[13], bit to 1b to guarantee the + /// LAN-Wakes are enabled at the Power Management Controller, even in surprise + /// S5 cases such as power loss/return and Power Button Override + /// + RegData16 = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_3); + RegData16 |= (UINT16) B_PCH_LPC_GEN_PMCON_WOL_ENABLE_OVERRIDE; + MmioWrite16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_3, RegData16); + + /// + /// Step 7 + /// Moreover, system BIOS also require to enables in the LAN device by performing + /// the WOL configuration requirements in the GbE region of the SPI flash. + /// Done in PchSmmSxGoToSleep() SMM handler. + /// + } else { + /// + /// D31:F0:A2h[14:11] and D31:F0:A4h[13] are all in RTC or DSW well, so BIOS also + /// needs to program them while WOL setup option is disabled. + /// + RegData16 = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_2); + RegData16 |= (UINT16) (B_PCH_LPC_GEN_PMCON_DC_PP_DIS | B_PCH_LPC_GEN_PMCON_DSX_PP_DIS); + RegData16 &= (UINT16) ~(B_PCH_LPC_GEN_PMCON_AG3_PP_EN | B_PCH_LPC_GEN_PMCON_SX_PP_EN); + MmioWrite16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_2, RegData16); + + RegData16 = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_3); + RegData16 &= (UINT16) ~(B_PCH_LPC_GEN_PMCON_WOL_ENABLE_OVERRIDE); + MmioWrite16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_3, RegData16); + } + + /// + /// Configure On DC PHY Power Diable according to policy SlpLanLowDc. + /// When this bit is set, SLP_LAN# will be driven low when ACPRESENT is low. + /// This indicates that LAN PHY should be powered off on battery mode. + /// This will override the DC_PP_DIS setting by WolEnableOverride. + /// + if (PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_7) { + RegData16 = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_2); + if (PchPlatformPolicy->MiscPmConfig->SlpLanLowDc) { + if ((RegData16 & B_PCH_LPC_GEN_PMCON_DC_PP_DIS) == 0) { + RegData16 |= (UINT16) (B_PCH_LPC_GEN_PMCON_DC_PP_DIS); + MmioWrite16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_2, RegData16); + } + } else { + if ((RegData16 & B_PCH_LPC_GEN_PMCON_DC_PP_DIS) != 0) { + RegData16 &= (UINT16) ~(B_PCH_LPC_GEN_PMCON_DC_PP_DIS); + MmioWrite16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_2, RegData16); + } + } + } + + /// + /// - Set SATA Initialization Register 70h[31:0] = 3F00BF1Fh + /// + MmioWrite8 (PciD31F2RegBase + R_PCH_SATA_SIRI, 0x70); + MmioWrite32 (PciD31F2RegBase + R_PCH_SATA_STRD, 0x3F00BF1F); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD) + ); + if (PchSeries == PchLp) { + /// + /// Set SATA Initialization Register 54h[31:0] = CF000F0Fh + /// + MmioWrite8 (PciD31F2RegBase + R_PCH_SATA_SIRI, 0x54); + MmioWrite32 (PciD31F2RegBase + R_PCH_SATA_STRD, 0xCF000F0F); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD) + ); + /// + /// Set SATA Initialization Register 58h[31:0] = 190000h + /// + MmioWrite8 (PciD31F2RegBase + R_PCH_SATA_SIRI, 0x58); + MmioWrite32 (PciD31F2RegBase + R_PCH_SATA_STRD, 0x190000); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD) + ); + } + /// + /// 4 + /// USB 1.1 / USB 2.0 / USB 3.0 + /// + ConfigureUsbClockGating (PchPlatformPolicy, RootComplexBar); + + if (PchSeries == PchLp) { + /// + /// 5.3 + /// Set D27:F0:43h[6:5][3:0] = 11b, 111b + /// + Data8And = (UINT8) ~0x0; + Data8Or = (BIT6 | BIT5 | BIT3 | BIT2 | BIT1 | BIT0); + MmioOr8 ((UINTN) (PciD27F0RegBase + 0x43), Data8Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciD27F0RegBase + 0x43), + &Data8Or, // Data to be ORed + &Data8And // Data to be ANDed + ); + } + /// + /// 10 + /// SMBus + /// Enable SMBus dynamic clock gating by setting D31:F3:80h [8, 10, 12 and 14] = 0b respectively + /// + MmioAnd16 ((UINTN) (PciD31F3RegBase + 0x80), (UINT16) ~(BIT14 | BIT12 | BIT10 | BIT8)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD31F3RegBase + 0x80), + 1, + (VOID *) (UINTN) (PciD31F3RegBase + 0x80) + ); + /// + /// PCH BIOS Spec Rev 0.5.5, section 19.10 + /// 11 + /// Misc + /// + /// Set D31:F2:300h [31:29] to 111b and [19] to 1b + /// + MmioOr32 ((UINTN) (PciD31F2RegBase + 0x300), BIT31 | BIT30 | BIT29 | BIT19); + /// + /// Set D31:F2:300h [17:16] = 11b + /// + MmioOr32 ((UINTN) (PciD31F2RegBase + 0x300), BIT17 | BIT16); + + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F2RegBase + 0x300), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + 0x300) + ); + + if (PchSeries == PchLp) { + /// + /// Set D31:F2:98h [31:30], [23] to 00b, 1b + /// + MmioAndThenOr32(PciD31F2RegBase + 0x98, (UINT32)~(BIT31 | BIT30), BIT23); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F2RegBase + 0x98), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + 0x98) + ); + + /// + /// Set RCBA + 0x333C[23:20] to 1100b + /// + MmioAndThenOr32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_PM_CFG2), + (UINT32)~(BIT21 | BIT20), + (UINT32) (BIT22 | BIT23) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_PM_CFG2), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_PM_CFG2) + ); + } + DEBUG ((EFI_D_INFO, "ConfigureMiscPm() End\n")); + + return EFI_SUCCESS; +} + +/** + Configure additional power management settings + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ConfigureAdditionalPm ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ) +{ + UINTN PciD31F0RegBase; + UINTN PciD31F2RegBase; + UINTN PciD28F0RegBase; + UINT32 Data32; + UINT8 Data8; + UINT16 LpcDeviceId; + UINT32 Data32And; + UINT32 Data32Or; + EFI_STATUS Status; + PCH_SERIES PchSeries; + + Data32 = 0x0; + PchSeries = GetPchSeries(); + PciD31F0RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 0, 0); + PciD31F2RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 2, 0); + PciD28F0RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 28, 0, 0); + LpcDeviceId = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_DEVICE_ID); + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 19.4 Additional Power Management Programming + /// Step 1 + /// Set D31:F0:A9h[7:0] = 46h + /// + MmioWrite8 ( + (UINTN) (PciD31F0RegBase + R_PCH_LPC_CIR4), + (UINT8) (0x46) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciD31F0RegBase + R_PCH_LPC_CIR4), + 1, + (VOID *) (UINTN) (PciD31F0RegBase + R_PCH_LPC_CIR4) + ); + /// + /// Step 2 + /// Set Power Management Initialization Register (PMIR) Field 1, D31:F0:ACh[31] = 1b + /// Done in Intel Management Engine Framework Reference Code + /// Step 3 + /// Set GEN_PMCON_LOCK register, D31:F0:A6h = 06h, after stretch and ACPI base programming completed. + /// Done in PchInitBeforeBoot() + if (PchSeries == PchH) { + /// + /// Step 4 + /// Set RCBA + Offset 2238h[0] = 1b + /// + MmioOr32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2238), + (UINT32) (BIT0) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2238), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2238) + ); + } + /// + /// Step 5 + /// Set RCBA + Offset 232Ch[0] = 1b + /// + if (PchSeries == PchH) { + MmioOr32 ( + (UINTN) (RootComplexBar + 0x232C), + (UINT32) (BIT0) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x232C), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x232C) + ); + } + + if (PchSeries == PchLp) { + /// + /// Step 5 + /// Set RCBA + Offset 232Ch[0] = 0b + /// + MmioAnd32 ( + (UINTN) (RootComplexBar + 0x232C), + (UINT32) ~(BIT0) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x232C), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x232C) + ); + /// + /// Step 6 + /// If Trunk Clock Gating is enabled: + /// set RCBA + Offset 1100h[15,14,8,5,4,3,2,1,0] all 1b + /// If Trunk Clock Gating is disabled: + /// set RCBA + Offset 1100h[15] = 0b + /// set RCBA + Offset 1100h[14,8,5,4,3,2,1,0] all 1b + /// + + if((PchPlatformPolicy->UsbConfig->Usb30Settings.Mode != PCH_XHCI_MODE_ON) && + (PchPlatformPolicy->UsbConfig->Usb30Settings.Btcg == PCH_DEVICE_DISABLE)) { + MmioAndThenOr32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR1100), + (UINT32)~(BIT15), + (UINT32) (BIT14 | BIT8 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0) + ); + } else { + MmioOr32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR1100), + (UINT32) (BIT15 | BIT14 | BIT8 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0) + ); + } + + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR1100), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR1100) + ); + } else if (PchSeries == PchH) { + /// + /// Step 6 + /// If Truck Clock Gating is enabled: + /// set RCBA + Offset 1100h[14:13] = 11b + /// If Truck Clock Gating is disabled: + /// set RCBA + Offset 1100h[14:13] = 10b + /// + if((PchPlatformPolicy->UsbConfig->Usb30Settings.Mode != PCH_XHCI_MODE_ON) && + (PchPlatformPolicy->UsbConfig->Usb30Settings.Btcg == PCH_DEVICE_DISABLE)) { + MmioAndThenOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CIR1100), (UINT32) ~(BIT13), (UINT32) (BIT14)); + } else { + MmioOr32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR1100), + (UINT32) (BIT14 | BIT13) + ); + } + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR1100), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR1100) + ); + } + + if (PchSeries == PchLp) { + /// + /// Set IOBP register 0xCF000000[14:12] = 111b + /// Set IOBP register 0XCF000000[0] = 1b + /// + Data32And = (UINT32)~(0); + Data32Or = 0x7001; + Status = ProgramIobp ( + RootComplexBar, + 0xCF000000, + Data32And, + Data32Or + ); + ASSERT_EFI_ERROR (Status); + Status = PCH_INIT_COMMON_SCRIPT_SAVE_IOBP_S3_ITEM ( + RootComplexBar, + 0xCF000000, + Data32And, + Data32Or + ); + ASSERT_EFI_ERROR (Status); + + /// + /// Set IOBP register 0xCA000000[3] = 1b + /// Set IOBP register 0XCA000000[0] = 1b + /// + Data32And = (UINT32)~(0); + Data32Or = (UINT32) (0x09); + Status = ProgramIobp ( + RootComplexBar, + 0xCA000000, + Data32And, + Data32Or + ); + ASSERT_EFI_ERROR (Status); + Status = PCH_INIT_COMMON_SCRIPT_SAVE_IOBP_S3_ITEM ( + RootComplexBar, + 0xCA000000, + Data32And, + Data32Or + ); + ASSERT_EFI_ERROR (Status); + } else if (PchSeries == PchH) { + /// + /// Step 7 + /// Set RCBA + Offset 2304h[31:0] = 0xC07B8400 + /// + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_DMC), + (UINT32) (0xC07B8400) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_DMC), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_DMC) + ); + /// + /// Step 8 + /// Set RCBA + Offset 2314h[23 and 5] = 1b + /// + MmioOr32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2314), + (UINT32) (BIT23 | BIT5) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2314), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2314) + ); + } + + /// + /// PCH BIOS Spec Rev 0.5.5, Section 19.4 Additional Power Management Programming + /// Step 9 + /// Set B0:D28:F0 + F5h[3:0] = 0101b + /// + MmioAndThenOr8 ( + (UINTN) (PciD28F0RegBase + 0xF5), + (UINT8) ~(BIT3 | BIT1), + (UINT8) (BIT2 | BIT0) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciD28F0RegBase + 0xF5), + 1, + (VOID *) (UINTN) (PciD28F0RegBase + 0xF5) + ); + + if (PchSeries == PchH) { + /// + /// Step 10 + /// Set RCBA + Offset 2320h [1] = 1b + /// + MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CIR2320), (UINT32) (BIT1)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2320), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2320) + ); + } + if (PchSeries == PchLp) { + /// + /// Step 10 + /// Set RCBA + Offset 2320h [6:4] = 001b + /// + MmioAndThenOr32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2320), + (UINT8) ~(BIT6 | BIT5), + (UINT8) (BIT4) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2320), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2320) + ); + } + switch (PchSeries) { + case PchLp: + /// + /// Step 11 + /// Set RCBA + Offset 3314h[31:0] = 0x00012FFF + /// + Data32 = 0x00012FFF; + break; + + case PchH: + default: + /// + /// Step 11 + /// Set RCBA + Offset 3314h[31:0] = 0x000007BF + /// + Data32 = 0x000007BF; + break; + } + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3314), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3314), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3314) + ); + + switch (PchSeries) { + case PchLp: + /// + /// Step 12 + /// Set RCBA + Offset 3318h[31:0] = 0x0DCF0400 + /// + Data32 = 0x0DCF0400; + break; + + case PchH: + default: + /// + /// Step 12 + /// Set RCBA + Offset 3318h[31:0] = 0x0DCF0020 (Note: Keep BIT5 unchanged) + /// + Data32 = 0x0DCF0020; + break; + } + /// + /// Note: RCBA + 3318h[19:16] are platform dependent settings (0Fh provides longest assertion), + /// please consult with your board design engineers for correct values to be programmed to. + /// + /// For RCBA + 3318h[9:8] Reset Power Cycle Duration could be customized, please refer to EDS + /// and make sure the setting correct, which never less than the following register. + /// - GEN_PMCON_3.SLP_S3_MIN_ASST_WDTH + /// - GEN_PMCON_3.SLP_S4_MIN_ASST_WDTH + /// - PM_CFG.SLP_A_MIN_ASST_WDTH + /// - PM_CFG.SLP_LAN_MIN_ASST_WDTH + /// + Data32 &= (UINT32)~(B_PCH_RCRB_PM_CFG_SSMAW_MASK | B_PCH_RCRB_PM_CFG_SAMAW_MASK); + if (PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_4) { + Data32 &= (UINT32)~(B_PCH_RCRB_PM_CFG_RPCD_MASK); + } + + switch (PchPlatformPolicy->MiscPmConfig->PchSlpSusMinAssert) { + case PchSlpSus0ms: + Data32 |= V_PCH_RCRB_PM_CFG_SSMAW_0S; + break; + + case PchSlpSus500ms: + Data32 |= V_PCH_RCRB_PM_CFG_SSMAW_0_5S; + break; + + case PchSlpSus1s: + Data32 |= V_PCH_RCRB_PM_CFG_SSMAW_1S; + break; + + case PchSlpSus4s: + default: + Data32 |= V_PCH_RCRB_PM_CFG_SSMAW_4S; + break; + } + switch (PchPlatformPolicy->MiscPmConfig->PchSlpAMinAssert) { + case PchSlpA0ms: + Data32 |= V_PCH_RCRB_PM_CFG_SAMAW_0S; + break; + + case PchSlpA4s: + Data32 |= V_PCH_RCRB_PM_CFG_SAMAW_4S; + break; + + case PchSlpA98ms: + Data32 |= V_PCH_RCRB_PM_CFG_SAMAW_98ms; + break; + + case PchSlpA2s: + default: + Data32 |= V_PCH_RCRB_PM_CFG_SAMAW_2S; + break; + } + if (PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_4) { + switch (PchPlatformPolicy->MiscPmConfig->PchPwrCycDur) { + case 0: // treat as PCH default + Data32 |= V_PCH_RCRB_PM_CFG_RPCD_4S; + break; + + case 1: + Data32 |= V_PCH_RCRB_PM_CFG_RPCD_1S; + break; + + case 2: + Data32 |= V_PCH_RCRB_PM_CFG_RPCD_2S; + break; + + case 3: + Data32 |= V_PCH_RCRB_PM_CFG_RPCD_3S; + break; + + case 4: + Data32 |= V_PCH_RCRB_PM_CFG_RPCD_4S; + break; + + default: + Data32 |= V_PCH_RCRB_PM_CFG_RPCD_4S; + DEBUG ((EFI_D_ERROR, "Error. Not a valid PCH reset power cycle duration setting.\n")); + break; + } + } + /// + /// For LP, force bit 5 = 0 + /// For LPT-H, preserve bit 5 + /// + if (PchSeries == PchLp) { + Data32 &= (UINT32) ~(BIT5); + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_PM_CFG), + Data32 + ); + } else { + MmioOr32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_PM_CFG), + Data32 + ); + } + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_PM_CFG), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_PM_CFG) + ); + /// + /// PCH BIOS Spec Rev 0.5.0, Section 19.4 Additional Power Management Programming + /// Step 13 + /// Set RCBA + Offset 3324h[31:0] = 0x04000000 + /// + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3324), + (UINT32) (0x04000000) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3324), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3324) + ); + + if (PchSeries == PchH) { + /// + /// Step 14 + /// Set RCBA + Offset 3340h[31:0] = 0x020DDBFF + /// + MmioOr32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3340), + (UINT32) (0x020DDBFF) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3340), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3340) + ); + /// + /// Step 15 + /// Set RCBA + Offset 3344h[0] = 1b + /// + MmioOr32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3344), + (UINT32) (BIT0) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3344), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3344) + ); + } + switch (PchSeries) { + case PchLp: + /// + /// Step 16 + /// Set RCBA + Offset 3368h[31:0] = 0x00041400 + /// + Data32 = 0x00041400; + break; + + case PchH: + default: + /// + /// Step 16 + /// Set RCBA + Offset 3368h[31:0] = 0x00041000 + /// + Data32 = 0x00041000; + break; + } + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3368), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3368), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3368) + ); + + if (PchSeries == PchH) { + /// + /// Step 17 + /// Set RCBA + Offset 3378h[31:0] = 3F8DDBFFh + /// + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3378), + (UINT32) (0x3F8DDBFF) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3378), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3378) + ); + /// + /// Step 18 + /// Set RCBA + Offset 337Ch[31:0] = 000001E1h + /// + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR337C), + (UINT32) (0x000001E1) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR337C), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR337C) + ); + } + switch (PchSeries) { + case PchLp: + /// + /// Step 19 + /// Set RCBA + Offset 3388h[31:0] = 0x3F8DDBFF + /// + Data32 = 0x3F8DDBFF; + break; + + case PchH: + default: + /// + /// Step 19 + /// Set RCBA + Offset 3388h[31:0] = 0x00001000 + /// + Data32 = 0x00001000; + break; + } + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3388), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3388), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3388) + ); + if (PchSeries == PchH) { + /// + /// Step 20 + /// Set RCBA + Offset 33A0h[31:0] = 00000800h + /// + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33A0), + (UINT32) (0x00000800) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33A0), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33A0) + ); + } + switch (PchSeries) { + case PchLp: + /// + /// Step 21 + /// Set RCBA + Offset 33ACh[31:0] = 0x00007001 + /// + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x33AC), + (UINT32) (0x00007001) + ); + break; + + case PchH: + default: + /// + /// Step 21 + /// Set RCBA + Offset 33ACh[31:0] = 00001000h + /// + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x33AC), + (UINT32) (0x00001000) + ); + break; + } + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x33AC), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x33AC) + ); + switch (PchSeries) { + case PchLp: + /// + /// Step 22 + /// Set RCBA + Offset 33B0h[31:0] = 0x00181900 + /// + Data32 = 0x00181900; + break; + + case PchH: + default: + /// + /// Step 22 + /// Set RCBA + Offset 33B0h[31:0] = 0x00001000 + /// + Data32 = 0x00001000; + break; + } + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33B0), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33B0), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33B0) + ); + switch (PchSeries) { + case PchLp: + /// + /// Step 23 + /// Set RCBA + Offset 33C0h[31:0] = 0x00060A00 + /// + Data32 = 0x00060A00; + break; + + case PchH: + default: + /// + /// Step 23 + /// Set RCBA + Offset 33C0h[31:0] = 0x00011900 + /// + Data32 = 0x00011900; + break; + } + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33C0), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33C0), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33C0) + ); + /// + /// Step 24 + /// LP Set RCBA + Offset 33D0h[31:0] = 0x06200840 + /// LP Set RCBA + Offset 33D0h[31:0] = 06004622h for LPT LP A0/A1 only + /// LPT-H Set RCBA + Offset 33D0h[31:0] = 06000802h + switch (PchSeries) { + case PchLp: + if (PchSeries == PchLp && PchStepping() < LptLpB0) { + Data32 = 0x06004622; + } else { + Data32 = 0x06200840; + } + break; + + case PchH: + default: + Data32 = 0x06000802; + break; + } + + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33D0), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33D0), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33D0) + ); + /// + /// Step 25 -- Note, this step has been moved to meet programming sequence requirements + /// Register 3A80 - 3A88 must be program after 3A00-3A3F and before 3A6C + /// Set RCBA + 3A88h[31:0] = 0x00000001 + /// + switch (PchSeries) { + case PchLp: + /// + /// Step 26 + /// Set RCBA + Offset 3A28h[31:0] = 01010101h + /// + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A28), + (UINT32) (0x01010101) + ); + break; + + case PchH: + default: + /// + /// Step 26 + /// Set RCBA + Offset 3A28h[31:0] = 01010000h + /// + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A28), + (UINT32) (0x01010000) + ); + break; + } + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A28), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A28) + ); + switch (PchSeries) { + case PchLp: + /// + /// Step 27 + /// Set RCBA + Offset 3A2Ch[31:0] = 04040404h + /// + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A2C), + (UINT32) (0x04040404) + ); + break; + + case PchH: + default: + /// + /// Step 27 + /// Set RCBA + Offset 3A2Ch[31:0] = 01010404h + /// + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A2C), + (UINT32) (0x01010404) + ); + break; + } + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A2C), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A2C) + ); + /// + /// Step 29 + /// Set RCBA + Offset 3A6Ch[31:0] = 00000001h, after all steps in this routine are done + /// Done in PchInitBeforeBoot() + /// + /// Step 30 + /// For PCH H + /// Set RCBA + Offset 2344h[31:24] = 0FFh + /// Set RCBA + Offset 2344h[7:0] = 0Ch + /// Done in PchInitBeforeBoot() + /// + /// Step 31 + /// For LPT-H set RCBA + Offset 33A4h[0] = 1b + /// + if (PchSeries == PchH) { + MmioOr32 ( + (UINTN) (RootComplexBar + 0x33A4), + (UINT32) (BIT0) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x33A4), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x33A4) + ); + } + + if (PchSeries == PchLp) { + /// + /// Step 32 + /// + /// Set RCBA + Offset 2B1Ch + /// [31:30] =2'b00 + /// [29] =0 if Audio DSP is enabled. 1 if disabled (RCBA offset x3418[1]=1). ConfigureAudioDsp will take care of this bit, which is executed later + /// Note1: Must assume enable in this flow because ConfigureAudioDsp only program this in the "audio disable flow" only + /// [28:22] = 7'b0001110 + /// [21:16]=corresponding bit has to be set for each SRC[5:0]CLKRQ# pin that is enabled (ie attached to a PCIe device) + /// [15:0]=0x8033h + /// + Data32 = 0x03808033; + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x2B1C), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x2B1C), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x2B1C) + ); + /// + /// Step 33 + /// Set RCBA + Offset 2B34[31:0] = 80000009h + /// Set bit 3 and 0, PMC shutdown time = 16us + /// + Data32 = 0x80000009; + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x2B34), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x2B34), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x2B34) + ); + + /// + /// Step 34 + /// Set RCBA + Offset 3348[31:0] = 022DDFFFh + /// + Data32 = 0x022DDFFF; + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x3348), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x3348), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x3348) + ); + /// + /// Step 35 + /// Set RCBA + Offset 334C[31:0] = 00000001h + /// + Data32 = 0x00000001; + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x334C), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x334C), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x334C) + ); + /// + /// Step 36 + /// Set RCBA + Offset 3358[31:0] = 0001C000h + /// + Data32 = 0x0001C000; + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x3358), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x3358), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x3358) + ); + /// + /// Step 37 + /// Set RCBA + Offset 3380[31:0] = 3F8DDBFFh + /// + Data32 = 0x3F8DDBFF; + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x3380), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x3380), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x3380) + ); + /// + /// Step 38 + /// Set RCBA + Offset 3384[31:0] = 0001C7E1h + /// + Data32 = 0x0001C7E1; + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x3384), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x3384), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x3384) + ); + /// + /// Step 39 + /// Set RCBA + Offset 338C[31:0] = 0x0001C7E1 + /// + Data32 = 0x0001C7E1; + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x338C), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x338C), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x338C) + ); + /// + /// Step 40 + /// Set RCBA + Offset 3398[31:0] = 0001C000h + /// + Data32 = 0x0001C000; + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x3398), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x3398), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x3398) + ); + /// + /// Step 41 + /// Set RCBA + Offset 33A8[31:0] = 0x00181900 + /// + Data32 = 0x00181900; + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x33A8), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x33A8), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x33A8) + ); + /// + /// Step 42 + /// Set RCBA + Offset 33DC[31:0] = 00080000h + /// + Data32 = 0x00080000; + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x33DC), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x33DC), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x33DC) + ); + /// + /// Step 43 + /// Set RCBA + Offset 33E0[31:0] = 00000001h + /// + Data32 = 0x00000001; + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x33E0), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x33E0), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x33E0) + ); + /// + /// Step 44 + /// Set RCBA + Offset 3A20[31:0] = 00000404h + /// + Data32 = 0x00000404; + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x3A20), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x3A20), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x3A20) + ); + /// + /// Step 45 + /// Set RCBA + Offset 3A24[31:0] = 01010101h + /// + Data32 = 0x01010101; + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x3A24), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x3A24), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x3A24) + ); + /// + /// Step 46 + /// Set RCBA + Offset 3A30[31:0] = 01010101h + /// + Data32 = 0x01010101; + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x3A30), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x3A30), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x3A30) + ); + /// + /// Step 47 + /// Set D31:F0:ACh[21] = 0b + /// + MmioAnd32 ( + (UINTN) (PciD31F0RegBase + R_PCH_LPC_PMIR), + (UINT32) ~(BIT21) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F0RegBase + R_PCH_LPC_PMIR), + 1, + (VOID *) (UINTN) (PciD31F0RegBase + R_PCH_LPC_PMIR) + ); + /// + /// Step 48 + /// set RCBA + Offset 410h[1:0] = 11b + /// + MmioOr32 ( + (UINTN) (RootComplexBar + 0x410), + (UINT32) (BIT1 | BIT0) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x410), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x410) + ); + /// + /// Step 49 + /// Set RCBA + 2618h[27] = 1b + /// + MmioOr32 ( + (UINTN) (RootComplexBar + 0x2618), + (UINT32) BIT27 + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x2618), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x2618) + ); + /// + /// Step 50 + /// Set RCBA + 2300h[1] = 1b + /// + Data32And = 0xFFFFFFFF; + Data32Or = (UINT32) BIT1; + MmioOr32 (RootComplexBar + 0x2300 , Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x2300), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + /// + /// Step 51 + /// Set RCBA + 2600h[3] = 1b + /// + MmioOr32 ( + (UINTN) (RootComplexBar + 0x2600), + (UINT32) BIT3 + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x2600), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x2600) + ); + /// + /// Step 52 + /// Set RCBA + 33B4h[0] = 0x00007001 + /// + Data32 = 0x00007001; + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x33B4), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x33B4), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x33B4) + ); + /// Step 53 + /// Set RCBA + Offset 3350[31:0] = 0x022DDFFF + /// + Data32 = 0x022DDFFF; + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x3350), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x3350), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x3350) + ); + /// + /// Step 54 + /// Set RCBA + Offset 3354[31:0] = 0x00000001 + /// + Data32 = 0x00000001; + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x3354), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x3354), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x3354) + ); + } + + if ((PchPlatformPolicy->PwrOptConfig->PchPwrOptDmi == PCH_DEVICE_ENABLE)) { + /// + /// PCH BIOS Spec Rev 0.5.0, Section 19.13 Power Optimizer Considerations (MB Only) + /// Notes: Settings is not recommended for Lynx Point Power on ES0 samples + /// Step 1 + /// Enable PM SYNC State 12 + /// Program RCBA + 33D4h[27] = 1b + /// For PCH LP + /// Program RCBA + 2B14[31:0] = 1E0A4616h + /// Program RCBA + 2B24[31:0] = 40000005h + /// For PCH H + /// Program RCBA + 2B14[31:0] = 1E0A0317h + /// Program RCBA + 2B24[31:0] = 4000000Bh + /// Program RCBA + 2B28[31:0] = 00000002h + /// Program RCBA + 2B2C[31:0] = 00008813h + /// + MmioOr32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33D4), + (UINT32) BIT27 + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33D4), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33D4) + ); + /// + /// Program RCBA + 33C8h[27] = 1b + /// + Data32Or = BIT27; + if (PchSeries == PchLp) { + /// + /// Program RCBA + 33C8h[7] = 1b + /// + Data32Or = BIT7; + } + MmioOr32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_PMSYNC), + (UINT32) Data32Or + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_PMSYNC), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_PMSYNC) + ); + /// + /// For LPT-LP, Program RCBA + 2B10[31:0] = 0000883Ch + /// + if (PchSeries == PchLp) { + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x2B10), + (UINT32) (0x0000883C) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x2B10), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x2B10) + ); + } + /// + /// Program RCBA + 2B14[31:0] = 1E0A0317h + /// For LP Program RCBA + 2B14[31:0] = 1E0A4616h + /// + Data32 = 0x1E0A0317; + if (PchSeries == PchLp) { + Data32 = 0x1E0A4616; + } + if (PchPlatformPolicy->PwrOptConfig->MemCloseStateEn == PCH_DEVICE_DISABLE) { + Data32 &= (UINT32) ~(BIT2); + } + if (PchPlatformPolicy->PwrOptConfig->InternalObffEn == PCH_DEVICE_DISABLE) { + Data32 &= (UINT32) ~(BIT1); + } + if (PchPlatformPolicy->PwrOptConfig->ExternalObffEn == PCH_DEVICE_DISABLE) { + Data32 &= (UINT32) ~(BIT0); + } + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x2B14), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x2B14), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x2B14) + ); + if (PchSeries == PchLp) { + /// + /// Set RCBA + Offset 2B24[31:0] = 0x40000005 + /// + Data32 = 0x40000005; + } else { + /// + /// Set RCBA + Offset 2B24[31:0] = 0x4000000B + /// + Data32 = 0x4000000B; + } + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x2B24), + Data32 + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x2B24), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x2B24) + ); + if (PchSeries == PchH) { + /// + /// Set RCBA + Offset 2B28[31:0] = 0x00000002 + /// + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x2B28), + (UINT32) (0x00000002) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x2B28), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x2B28) + ); + } + if (PchSeries == PchH) { + /// + /// Set RCBA + Offset 2B2C[31:0] = 0x00008813 + /// + Data32 = 0x00008813; + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x2B2C), + Data32 + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x2B2C), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x2B2C) + ); + } + /// Step 7 + /// Enable PM Demand in Cx States + /// For LPT-H, use default + /// For LPT-LP Program RCBA + 02B20h[1:0] = 0x0005DB01 + /// + if (PchSeries == PchLp) { + Data32 = 0x0005DB01; + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x2B20), + Data32 + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x2B20), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x2B20) + ); + } + } + switch (PchSeries) { + case PchLp: + /// + /// Step 55 + /// Set RCBA + 3A80h[31:0] = 05145005h + /// + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A80), + (UINT32) (0x05145005) + ); + break; + case PchH: + default: + /// + /// Step 55 + /// Set RCBA + 3A80h[31:0] = 01040000h + /// + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A80), + (UINT32) (0x01040000) + ); + break; + } + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A80), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A80) + ); + /// + /// Step 56 + /// Ensure this is done after 3A00-3A3C and before 3A6C + /// if PchLp, Set RCBA + Offset 3A84h[31:0] = 0x00001005 + /// if PchH, Set RCBA + Offset 3A84h[31:0] = 0x01041001 + /// if PCS.P0E and PCS.P1E = 0b, Set RCBA + Offset 3A84h[20,18] = 1b, 1b + /// if PCS.P2E and PCS.P3E = 0b, Set RCBA + Offset 3A84h[24,26] = 1b, 1b + /// + if (PchSeries == PchLp) { + Data32 = 0x00001005; + } else { + Data32 = 0x01041001; + } + Data8 = MmioRead8 (PciD31F2RegBase + R_PCH_SATA_PCS); + if((Data8 & (UINT8) (B_PCH_SATA_PCS_PORT0_EN | B_PCH_SATA_PCS_PORT1_EN)) == 0) { + Data32 |= (BIT20 | BIT18); + } + if((Data8 & (UINT8) (B_PCH_SATA_PCS_PORT2_EN | B_PCH_SATA_PCS_PORT3_EN)) == 0) { + Data32 |= (BIT24 | BIT26); + } + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A84), + (UINT32) (Data32) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A84), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A84) + ); + /// + /// Step 57 + /// Set RCBA + 3A88h[31:0] = 0x00000001 + /// + if (PchSeries == PchH) { + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A88), + (UINT32) (0x00000001) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A88), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A88) + ); + } + /// + /// Step 58 + /// For LPT-LP Set RCBA + Offset 33D4h = 0x2FFF2FB1, after step #14 to #24 and D31:F0:A9h are done + /// Note for LP only: Preserve bits 31,30,28,15,14,12, which are platform specific + /// For LPT-H Set RCBA + Offset 33D4h = 0xC00BC000, after step #14 to #24 and D31:F0:A9h are done + /// + switch (PchSeries) { + case PchLp: + MmioOr32 ( + (UINTN) (RootComplexBar + 0x33D4), + (UINT32) (0x2FFF2FB1) + ); + break; + + case PchH: + default: + MmioWrite32 ( + (UINTN) (RootComplexBar + 0x33D4), + (UINT32) (0xC00BC000) + ); + break; + } + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x33D4), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x33D4) + ); + + if (PchSeries == PchLp) { + /// + /// This is the last step which only apply for LPT-LP + /// Set RCBA + Offset 33C8h[15] = 1b + /// + MmioOr32 ( + (UINTN) (RootComplexBar + 0x33C8), + (UINT32) (BIT15) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x33C8), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x33C8) + ); + } + return EFI_SUCCESS; +} + +/** + Configures PCH DMI according to policies specified in PCH Platform Policy protocol + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval EFI_SUCCESS Successfully completed. +**/ +EFI_STATUS +EFIAPI +ConfigureDmiPm ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ) +{ + UINT32 Data32And; + UINT32 Data32Or; + UINT16 Data16And; + UINT16 Data16Or; + UINTN PciD28F0RegBase; + PCH_PCI_EXPRESS_ASPM_CONTROL DmiAspmCtrl; + PCH_SERIES PchSeries; + + DEBUG ((EFI_D_INFO, "ConfigureDmi() Start\n")); + + PchSeries = GetPchSeries(); + PciD28F0RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 28, 0, 0); + + /// + /// PCH BIOS Spec Rev 0.5.0 Section 7.1.5 Additional PCH DMI Programming Steps + /// + if (PchSeries == PchH) { + /// Step 4.1 + /// If RCBA + Offset 2320h[1] = 0 and B0:D28:F0 + F5h[0] = 0, set RCBA + Offset 21A4h[17:15] = 010b + /// Else set RCBA + Offset 21A4h[17:15] = 100b + /// + if (((MmioRead32 ((UINTN) RootComplexBar + R_PCH_RCRB_CIR2320) & (UINT32) (BIT1)) == 0) && + ((MmioRead8 (PciD28F0RegBase + 0xF5) & BIT0) == 0)) { + Data32Or = BIT16; + } else { + Data32Or = BIT17; + } + /// + /// Step 4.2 + /// Set RCBA + Offset 21A4h[14:12] = 011b + /// + Data32Or |= BIT13 | BIT12; + Data32And = (UINT32)~(B_PCH_RCRB_LCAP_EL1 | B_PCH_RCRB_LCAP_EL0); + MmioAndThenOr32 (RootComplexBar + R_PCH_RCRB_LCAP, Data32And, Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_LCAP), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + } + /// + /// Step 4.3 + /// Set RCBA + 2348[3:0] = 0h + /// + Data32Or = 0; + Data32And = (UINT32) ~(BIT0 | BIT1 | BIT2 | BIT3); + MmioAnd32 (RootComplexBar + 0x2348, Data32And); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + 0x2348), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + + /// + /// Enable DMI ASPM + /// + /// PCH BIOS Spec Rev 0.5.0, Section 8.3.1 ASPM on DMI and the PCI Express* Root Ports + /// + if (PchPlatformPolicy->DmiConfig->DmiAspm == PCH_DEVICE_ENABLE) { + /// + /// While DmiAspm is enabled, DMI ASPM will be set to Intel recommended value. + /// PCH BIOS Spec Rev 0.5.0, Section 8.3.1 ASPM on DMI and the PCI Express* Root Ports + /// Note: We recommend PCH platforms to enable L0s and L1, but unless both sides of the link have L0s and/or + /// L1 enabled they will be disabled by the link. + /// + DmiAspmCtrl = PchPcieAspmL0sL1; + } else { + DmiAspmCtrl = PchPcieAspmDisabled; + } + + if (DmiAspmCtrl != PchPcieAspmDisabled) { + if (PchSeries == PchH) { + /// + /// PCH BIOS Spec Rev 0.5.0, Section 8.3.1 + /// BIOS should set RCBA + 2304h[10] to 0b prior to enabling DMI ASPM. + /// + Data32And = (UINT32)~(BIT10); + Data32Or = 0; + MmioAnd32 (RootComplexBar + R_PCH_RCRB_DMC, Data32And); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_DMC), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 8.3.1 + /// + /// Step 1 + /// RCBA + 21A4h[11:10] = 11b + /// + Data32And = 0xFFFFFFFF; + Data32Or = B_PCH_RCRB_LCAP_APMS; + MmioOr32 (RootComplexBar + R_PCH_RCRB_LCAP, Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_LCAP), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + } + + if (DmiAspmCtrl == PchPcieAspmL0sL1) { + /// + /// Step 2 + /// Enable L0s/L1 on DMI by setting RCBA + offset 21A8h[1:0] to 11b + /// + Data16And = (UINT16) (~(BIT1 + BIT0)); + Data16Or = (UINT16) (BIT1 + BIT0); + + } else { + // + // Do nothing + // + Data16And = 0xFFFF; + Data16Or = 0; + } + if (PchSeries == PchH) { + /// + /// Program RCBA + offset 21A8h[1:0] + /// + MmioAndThenOr16 (RootComplexBar + R_PCH_RCRB_LCTL, Data16And, Data16Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RootComplexBar + R_PCH_RCRB_LCTL), + &Data16Or, // Data to be ORed + &Data16And // Data to be ANDed + ); + /// + /// BIOS should set RCBA + 2304h[10] back to 1b after enabling DMI ASPM. + /// + Data32And = 0xFFFFFFFF; + Data32Or = (UINT32) (BIT10); + MmioOr32 (RootComplexBar + R_PCH_RCRB_DMC, Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_DMC), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + } + } + + if (PchSeries == PchH) { + if (PchPlatformPolicy->DmiConfig->DmiExtSync == PCH_DEVICE_ENABLE) { + Data16And = (UINT16) (~(B_PCH_RCRB_LCTL_ES)); + Data16Or = (UINT16) B_PCH_RCRB_LCTL_ES; + MmioAndThenOr16 (RootComplexBar + R_PCH_RCRB_LCTL, Data16And, Data16Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RootComplexBar + R_PCH_RCRB_LCTL), + &Data16Or, // Data to be ORed + &Data16And // Data to be ANDed + ); + } + } + + DEBUG ((EFI_D_INFO, "ConfigureDmi() End\n")); + + return EFI_SUCCESS; +} + +/** + Configure deep Sx programming + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ProgramDeepSx ( + DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + UINT32 RootComplexBar + ) +{ + UINT32 S3Data32; + UINT32 S4Data32; + UINT32 S5Data32; + UINTN PciD31F0RegBase; + UINT16 LpcDeviceId; + + PciD31F0RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 0, 0); + LpcDeviceId = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_DEVICE_ID); + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 19.11 Deep Sx Power Policies + /// The System BIOS can perform the following register programming guidelines to enable system + /// enter Deep S4 or Deep S5. + /// + /// DPS3_EN_DC DPS3_EN_AC DPS4_EN_DC DPS4_EN_AC DPS5_EN_DC DPS5_EN_AC + /// RCBA+3328h[1] RCBA + 3328h[0] RCBA + 332Ch[1] RCBA + 332Ch[0] RCBA + 3330h[15] RCBA + 3330h[14] + /// Deep Sx disabled 0 0 0 0 0 0 + /// + /// Enabled in S5 0 0 0 0 1 1 + /// + /// Enabled in S4 and S5 0 0 1 1 1 1 + /// + /// Enabled in S3, S4 and S5 1 1 1 1 1 1 + /// + /// Configuration supported by MOBILE: + /// Enabled in S5 0 0 0 0 1 0 + /// (Battery mode) + /// Enabled in S4 and S5 0 0 1 0 1 0 + /// (Battery Mode) + /// Enabled in S3, S4 and S5 1 0 1 0 1 0 + /// (Battery Mode) + /// + /// NOTE: Mobile platforms support Deep S4/S5 in DC ONLY, + /// Desktop and Intel C206 Chipset (LPC Dev ID 0x1C56) platforms support Deep S4/S5 in AC ONLY, + /// Intel C204 Chipset (LPC Dev ID 0x1C54) and Intel C202 Chipset (LPC Dev ID 0x1C52) platforms DO NOT support Deep S4/S5. + /// + /// Deep Sx disabled 0 0 0 0 0 0 + /// + if (IS_PCH_LPT_LPC_DEVICE_ID_DESKTOP (LpcDeviceId) || + IS_PCH_LPT_LPC_DEVICE_ID_SERVER (LpcDeviceId) || + IS_PCH_LPT_LPC_DEVICE_ID_WS (LpcDeviceId)) { + if ((PchPlatformPolicy->MiscPmConfig->PchDeepSxPol == PchMobileDpS5En) || + (PchPlatformPolicy->MiscPmConfig->PchDeepSxPol == PchMobileDpS4S5En) || + (PchPlatformPolicy->MiscPmConfig->PchDeepSxPol == PchMobileDpS3S4S5En)) { + /// + /// Set PchDeepSxPol to PchDeepSxPolDisable for unsupported deep Sx policy + /// + PchPlatformPolicy->MiscPmConfig->PchDeepSxPol = PchDeepSxPolDisable; + DEBUG ((EFI_D_ERROR, "Unsupported Deep Sx policy for desktop system\n")); + } + + } else { + if ((PchPlatformPolicy->MiscPmConfig->PchDeepSxPol == PchDesktopDpS5En) || + (PchPlatformPolicy->MiscPmConfig->PchDeepSxPol == PchDesktopDpS4S5En) || + (PchPlatformPolicy->MiscPmConfig->PchDeepSxPol == PchDesktopDpS3S4S5En)) { + /// + /// Set PchDeepSxPol to PchDeepSxPolDisable for unsupported deep Sx policy + /// + PchPlatformPolicy->MiscPmConfig->PchDeepSxPol = PchDeepSxPolDisable; + DEBUG ((EFI_D_ERROR, "Unsupported Deep Sx policy for mobile system\n")); + } + } + + switch (PchPlatformPolicy->MiscPmConfig->PchDeepSxPol) { + case PchDesktopDpS5En: + /// + /// Configuration 2: Enabled in S5/AC-DC + /// DEEP_S3_POL.DPS3_EN_DC = 0; DEEP_S3_POL.DPS3_EN_AC = 0; + /// DEEP_S4_POL.DPS4_EN_DC = 0; DEEP_S4_POL.DPS4_EN_AC = 0; + /// DEEP_S5_POL.DPS5_EN_DC = 1; DEEP_S5_POL.DPS5_EN_AC = 1; + /// + S3Data32 = 0; + S4Data32 = 0; + S5Data32 = (UINT32) (B_PCH_RCRB_DEEP_S5_POL_DPS5_EN_AC | B_PCH_RCRB_DEEP_S5_POL_DPS5_EN_DC); + break; + + case PchDesktopDpS4S5En: + /// + /// Configuration 4: Enabled only in S4-S5 + /// DEEP_S3_POL.DPS3_EN_DC = 0; DEEP_S3_POL.DPS3_EN_AC = 0; + /// DEEP_S4_POL.DPS4_EN_DC = 1; DEEP_S4_POL.DPS4_EN_AC = 1; + /// DEEP_S5_POL.DPS5_EN_DC = 1; DEEP_S5_POL.DPS5_EN_AC = 1; + /// + S3Data32 = 0; + S4Data32 = (UINT32) (B_PCH_RCRB_DEEP_S4_POL_DPS4_EN_AC | B_PCH_RCRB_DEEP_S4_POL_DPS4_EN_DC); + S5Data32 = (UINT32) (B_PCH_RCRB_DEEP_S5_POL_DPS5_EN_AC | B_PCH_RCRB_DEEP_S5_POL_DPS5_EN_DC); + break; + + case PchDesktopDpS3S4S5En: + /// + /// Configuration 6: Enabled only in S3-S4-S5 + /// DEEP_S3_POL.DPS3_EN_DC = 1; DEEP_S3_POL.DPS3_EN_AC = 1; + /// DEEP_S4_POL.DPS4_EN_DC = 1; DEEP_S4_POL.DPS4_EN_AC = 1; + /// DEEP_S5_POL.DPS5_EN_DC = 1; DEEP_S5_POL.DPS5_EN_AC = 1; + /// + S3Data32 = (UINT32) (B_PCH_RCRB_DEEP_S3_POL_DPS3_EN_AC | B_PCH_RCRB_DEEP_S3_POL_DPS3_EN_DC); + S4Data32 = (UINT32) (B_PCH_RCRB_DEEP_S4_POL_DPS4_EN_AC | B_PCH_RCRB_DEEP_S4_POL_DPS4_EN_DC); + S5Data32 = (UINT32) (B_PCH_RCRB_DEEP_S5_POL_DPS5_EN_AC | B_PCH_RCRB_DEEP_S5_POL_DPS5_EN_DC); + break; + + case PchMobileDpS5En: + /// + /// Configuration 1: Enabled in S5/Battery only + /// DEEP_S3_POL.DPS3_EN_DC = 0; DEEP_S3_POL.DPS3_EN_AC = 0; + /// DEEP_S4_POL.DPS4_EN_DC = 0; DEEP_S4_POL.DPS4_EN_AC = 0; + /// DEEP_S5_POL.DPS5_EN_DC = 1; DEEP_S5_POL.DPS5_EN_AC = 0; + /// + S3Data32 = 0; + S4Data32 = 0; + S5Data32 = (UINT32) (B_PCH_RCRB_DEEP_S5_POL_DPS5_EN_DC); + break; + + case PchMobileDpS4S5En: + /// + /// Configuration 3: Enabled only in S4-S5/Battery Mode + /// DEEP_S3_POL.DPS3_EN_DC = 0; DEEP_S3_POL.DPS3_EN_AC = 0; + /// DEEP_S4_POL.DPS4_EN_DC = 1; DEEP_S4_POL.DPS4_EN_AC = 0; + /// DEEP_S5_POL.DPS5_EN_DC = 1; DEEP_S5_POL.DPS5_EN_AC = 0; + /// + S3Data32 = 0; + S4Data32 = (UINT32) (B_PCH_RCRB_DEEP_S4_POL_DPS4_EN_DC); + S5Data32 = (UINT32) (B_PCH_RCRB_DEEP_S5_POL_DPS5_EN_DC); + break; + + case PchMobileDpS3S4S5En: + /// + /// Configuration 5: Enabled only in S4-S5/Battery Mode + /// DEEP_S3_POL.DPS3_EN_DC = 1; DEEP_S3_POL.DPS3_EN_AC = 0; + /// DEEP_S4_POL.DPS4_EN_DC = 1; DEEP_S4_POL.DPS4_EN_AC = 0; + /// DEEP_S5_POL.DPS5_EN_DC = 1; DEEP_S5_POL.DPS5_EN_AC = 0; + /// + S3Data32 = (UINT32) (B_PCH_RCRB_DEEP_S3_POL_DPS3_EN_DC); + S4Data32 = (UINT32) (B_PCH_RCRB_DEEP_S4_POL_DPS4_EN_DC); + S5Data32 = (UINT32) (B_PCH_RCRB_DEEP_S5_POL_DPS5_EN_DC); + break; + + case PchDeepSxPolDisable: + default: + /// + /// Configuration 5: DeepSx Disabled + /// DEEP_S3_POL.DPS3_EN_DC = 0; DEEP_S3_POL.DPS3_EN_AC = 0; + /// DEEP_S4_POL.DPS4_EN_DC = 0; DEEP_S4_POL.DPS4_EN_AC = 0; + /// DEEP_S5_POL.DPS5_EN_DC = 0; DEEP_S5_POL.DPS5_EN_AC = 0; + /// + S3Data32 = 0; + S4Data32 = 0; + S5Data32 = 0; + break; + } + + MmioWrite32 ((RootComplexBar + R_PCH_RCRB_DEEP_S3_POL), S3Data32); + MmioWrite32 ((RootComplexBar + R_PCH_RCRB_DEEP_S4_POL), S4Data32); + MmioWrite32 ((RootComplexBar + R_PCH_RCRB_DEEP_S5_POL), S5Data32); + + return EFI_SUCCESS; +} diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchRootPorts.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchRootPorts.c new file mode 100644 index 0000000..e9ae324 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchRootPorts.c @@ -0,0 +1,2154 @@ +/** @file + This file contains functions that initializes PCI Express Root Ports of PCH. + +@copyright + Copyright (c) 1999 - 2014 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#include "PchInit.h" +// AMI_OVERRIDE, [EIP84720]> +#include "Token.h" +// AMI_OVERRIDE, [EIP84720]< + +#ifdef TRAD_FLAG +UINT32 PchHPcieHsioAddr[] = { + 0xE9002E40, + 0xE9002C40, + 0xE9002A40, + 0xE9002840, + 0xE9002640, + 0xE9002440, + 0xE9002240, + 0xE9002040, + 0xEA002040, + 0xEA002240 +}; +#endif // TRAD_FLAG + +#ifdef ULT_FLAG +UINT32 PchLpPcieHsioAddr[] = { + 0xE9002440, + 0xE9002640, + 0xE9000840, + 0xE9000A40, + 0xE9000C40, + 0xE9000E40, + 0xE9001040, + 0xE9001240, + 0xEA002040, + 0xEA002240, + 0xEA002440, + 0xEA002640 +}; +#endif // ULT_FLAG + +/** + Set an Init Root Port Downstream devices S3 dispatch item, this function may assert if any error happend + + @param[in] RootPortBus Pci Bus Number of the root port + @param[in] RootPortDevice Pci Device Number of the root port + @param[in] RootPortFunc Pci Function Number of the root port + @param[in] TempBusNumberMin Minimal temp bus number that can be assigned to the root port (as secondary + bus number) and its down stream switches + @param[in] TempBusNumberMax Maximal temp bus number that can be assigned to the root port (as subordinate + bus number) and its down stream switches + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +SetInitRootPortDownstreamS3Item ( + IN UINT8 RootPortBus, + IN UINT8 RootPortDevice, + IN UINT8 RootPortFunc, + IN UINT8 TempBusNumberMin, + IN UINT8 TempBusNumberMax + ) +{ + EFI_STATUS Status; +#ifdef EFI_S3_RESUME + STATIC EFI_PCH_S3_SUPPORT_PROTOCOL *PchS3Support; + STATIC EFI_PCH_S3_PARAMETER_INIT_PCIE_ROOT_PORT_DOWNSTREAM S3ParameterRootPortDownstream; + STATIC EFI_PCH_S3_DISPATCH_ITEM S3DispatchItem = { + PchS3ItemTypeInitPcieRootPortDownstream, + &S3ParameterRootPortDownstream + }; + EFI_PHYSICAL_ADDRESS S3DispatchEntryPoint; + + if (!PchS3Support) { + /// + /// Get the PCH S3 Support Protocol + /// + Status = gBS->LocateProtocol ( + &gEfiPchS3SupportProtocolGuid, + NULL, + (VOID **) &PchS3Support + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + } + + S3ParameterRootPortDownstream.RootPortBus = RootPortBus; + S3ParameterRootPortDownstream.RootPortDevice = RootPortDevice; + S3ParameterRootPortDownstream.RootPortFunc = RootPortFunc; + S3ParameterRootPortDownstream.TempBusNumberMin = TempBusNumberMin; + S3ParameterRootPortDownstream.TempBusNumberMax = TempBusNumberMax; + Status = PchS3Support->SetDispatchItem ( + PchS3Support, + &S3DispatchItem, + &S3DispatchEntryPoint + ); + ASSERT_EFI_ERROR (Status); + /// + /// Save the script dispatch item in the Boot Script + /// + SCRIPT_DISPATCH (EFI_ACPI_S3_RESUME_SCRIPT_TABLE, S3DispatchEntryPoint); +#else + Status = EFI_SUCCESS; +#endif + return Status; +} + +/** + Perform Initialization of the Downstream Root Ports. + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol + @param[in] RootComplexBar RCBA of the PCH + @param[in] PmBase The PM I/O Base address of the PCH + @param[in, out] FuncDisableReg The function disable register. IN / OUT parameter. + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_INVALID_PARAMETER The PCIe Root Port Number of D28:F0 is not found + or invalid +**/ +EFI_STATUS +PchInitRootPorts ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar, + IN UINT16 PmBase, + IN OUT UINT32 *FuncDisableReg + ) +{ + EFI_STATUS Status; + UINT32 Data32And; + UINT32 Data32Or; + PCH_PCI_EXPRESS_CONFIG *PciExpressConfig; + UINT32 RpEnableMask; + UINT8 PortIndex; + UINTN RPBase; + UINT32 LoopTime; + UINTN PciD31F0RegBase; + UINTN PciD31F2RegBase; + UINTN PciD28F0RegBase; + UINTN PciD28F4RegBase; + UINT32 RpFnAnd; + UINT32 RpFnOr; + UINT32 StrpFuseCfg1; + UINT32 StrpFuseCfg2; + UINT8 RpLaneOwner; + UINT8 GbePort; + UINT8 NandPort; + UINT16 LpcDeviceId; + UINT32 BitMask; + UINT32 BitValue; + UINT8 FuncNum; + UINT8 RpPortFuncIndex; + UINT8 Func0PortNum; + /// + /// Whether a root port is hidden by another one with width > x1 + /// + UINT32 RpHiddenMask; + /// + /// Subtractive Decode ports if enabled + /// + UINT32 SubDecodePort; + PCH_SERIES PchSeries; + UINT8 Mask; + BOOLEAN LanEnabled; + + DEBUG ((EFI_D_INFO, "PchInitRootPorts() Start\n")); + + PchSeries = GetPchSeries(); + Status = EFI_SUCCESS; + RpEnableMask = 0; + RpHiddenMask = 0; + PciExpressConfig = PchPlatformPolicy->PciExpressConfig; + Data32And = 0xFFFFFFFF; + Data32Or = 0; + PciD31F0RegBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); + PciD31F2RegBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_SATA, + PCI_FUNCTION_NUMBER_PCH_SATA, + 0 + ); + PciD28F0RegBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + GetPchPcieRpfn( RootComplexBar, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1), + 0 + ); + PciD28F4RegBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + GetPchPcieRpfn( RootComplexBar, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_5), + 0 + ); + LpcDeviceId = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_DEVICE_ID); + FuncNum = 0; + RpPortFuncIndex = 0; + Func0PortNum = 0xFF; + RpLaneOwner = 0; + + /// + /// Configure root port function number mapping and configuration space hiding + /// Program at end of function + /// + RpFnAnd = 0xFFFFFFFF; + RpFnOr = 0; + for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex++) { + // + // if RootPortFunctionSwapping is enabled, Function number is equal to port index. + // else, use the function number mapping from platform policy. + // + if ((PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_3) && + (PciExpressConfig->RootPortFunctionSwapping == 1)) { + FuncNum = PortIndex; + } else { + FuncNum = PciExpressConfig->RootPort[PortIndex].FunctionNumber; + } + RpFnAnd &= (UINT32) (~((B_PCH_RCRB_RPFN_RP1CH | B_PCH_RCRB_RPFN_RP1FN) << (PortIndex * S_PCH_RCRB_PRFN_RP_FIELD))); + RpFnOr |= (FuncNum) << (PortIndex * S_PCH_RCRB_PRFN_RP_FIELD); + + if (FuncNum < GetPchMaxPciePortNum ()) { + /// + /// If FunctionNumber of the PCIE Root Port is duplicated, then disable the corresponding "Enable" field. + /// + if (RpPortFuncIndex & (UINT8) (1 << FuncNum)) { + DEBUG ((EFI_D_ERROR, " Hide Root Port %x since its FunctionNumber is duplicated.\n", PortIndex + 1)); + ASSERT (FALSE); + PciExpressConfig->RootPort[PortIndex].Hide = PCH_DEVICE_ENABLE; + PciExpressConfig->RootPort[PortIndex].Enable = PCH_DEVICE_DISABLE; + RpHiddenMask |= (1 << PortIndex); + } + /// + /// Set RpPortFuncIndex while the FunctionNumber is used. + /// + RpPortFuncIndex |= (UINT8) (1 << FuncNum); + } else { + /// + /// If FunctionNumber of the PCIE Root Port is outside 7, the Root Port Config Hide bit will be set. + /// If so, then disable the corresponding "Enable" field. + /// + DEBUG ((EFI_D_ERROR, " Root Port %x will be hidden since its FunctionNumber is out of 7.\n", PortIndex + 1)); + ASSERT (FALSE); + PciExpressConfig->RootPort[PortIndex].Enable = PCH_DEVICE_DISABLE; + RpHiddenMask |= (1 << PortIndex); + } + + RpFnOr |= ((PciExpressConfig->RootPort[PortIndex].Hide) ? B_PCH_RCRB_RPFN_RP1CH : 0) << (PortIndex * S_PCH_RCRB_PRFN_RP_FIELD); + /// + /// Func0PortNum indicates which PCIe Root Port is D28:F0 + /// + if (FuncNum == 0) { + Func0PortNum = PortIndex; + } + } + + if (Func0PortNum >= GetPchMaxPciePortNum ()) { + DEBUG ((EFI_D_ERROR, "The PCIe Root Port Number of D28:F0 is not found or invalid!\n")); + return EFI_INVALID_PARAMETER; + } + /// + /// Hide PCIE root port 1-4 according to the PCIE port configuration 1 + /// + StrpFuseCfg1 = MmioRead32 (PciD28F0RegBase + R_PCH_PCIE_STRPFUSECFG); + switch (StrpFuseCfg1 & (UINT32) B_PCH_PCIE_STRPFUSECFG_RPC) { + case V_PCH_PCIE_STRPFUSECFG_RPC_2_1_1: + /// + /// Port Configuration = 01b: 1x2, 2x1 Port 1 (x2), Port 2 (disabled), Ports 3, 4 (x1) + /// + RpHiddenMask |= BIT1; + break; + + case V_PCH_PCIE_STRPFUSECFG_RPC_2_2: + /// + /// Port Configuration = 10b: 2x2 Port 1 (x2), Port 3 (x2), Ports 2, 4 (disabled) + /// + RpHiddenMask |= (BIT1 | BIT3); + break; + + case V_PCH_PCIE_STRPFUSECFG_RPC_4: + /// + /// Port Configuration = 11b: 1x4 Port 1 (x4), Ports 2-4 (disabled) + /// + RpHiddenMask |= (BIT1 | BIT2 | BIT3); + break; + + default: + break; + } + + if (PchSeries == PchH) { + /// + /// Hide PCIE root port 5-8 according to the PCIE port configuration + /// + StrpFuseCfg2 = MmioRead32 (PciD28F4RegBase + R_PCH_PCIE_STRPFUSECFG); + switch (StrpFuseCfg2 & (UINT32) B_PCH_PCIE_STRPFUSECFG_RPC) { + case V_PCH_PCIE_STRPFUSECFG_RPC_2_1_1: + /// + /// Port Configuration = 01b: 1x2, 2x1 Port 5 (x2), Port 6 (disabled), Ports 7, 8 (x1) + /// + RpHiddenMask |= BIT5; + break; + + case V_PCH_PCIE_STRPFUSECFG_RPC_2_2: + /// + /// Port Configuration = 10b: 2x2 Port 5 (x2), Port 7 (x2), Ports 6, 8 (disabled) + /// + RpHiddenMask |= (BIT5 | BIT7); + break; + + case V_PCH_PCIE_STRPFUSECFG_RPC_4: + /// + /// Port Configuration = 11b: 1x4 Port 5 (x4), Ports 6-8 (disabled) + /// + RpHiddenMask |= (BIT5 | BIT6 | BIT7); + break; + + default: + break; + } + } + /// + /// If GBE Over PCIe Enabled, then System BIOS must disable the PCI Express* Root Port + /// + LanEnabled = !(MmioRead32 (RootComplexBar + R_PCH_RCRB_BUC) & B_PCH_RCRB_BUC_LAN_DIS); + + if ((StrpFuseCfg1 & B_PCH_PCIE_STRPFUSECFG_GBE_PCIE_PEN) && LanEnabled) { + GbePort = (UINT8) ((StrpFuseCfg1 & B_PCH_PCIE_STRPFUSECFG_GBE_PCIEPORTSEL) >> N_PCH_PCIE_STRPFUSECFG_GBE_PCIEPORTSEL); + } else { + GbePort = 0xFF; + } + /// + /// If NAND Over PCIe Enabled, then System BIOS must disable the PCI Express* Root Port + /// + if ((MmioRead32 (PciD31F2RegBase + 0x300) & BIT0) != 0) { + NandPort = (UINT8) (((MmioRead32 (PciD31F2RegBase + 0x300)) & 0x1FE) >> 1); + } else { + NandPort = 0x00; + } + if (PchSeries == PchH) { + /// + /// PCH BIOS Spec Rev 0.5.0, Section 8.14 Additional PCI Express* Programming Steps + /// Step 3 + /// Function disable unused PCIE port + /// Disable PCIe Port 1 if either of the conditions are met + /// i. B0:D28:F0 + 410h[4] = 0b and B0:D28:F0 + 410h[0] = 0b + /// ii. GbeOverPCIe is configured to use Pcie Port 1 and SATA port 4 is mapped to this lane instead of PCIe Port 1 + /// iii. NandOverPCIe is configured to use PCIe Port 1 + /// NOTE: + /// For condition ii, if Gbe is configured to Pcie Port 1, and Pcie Port 1 ownes the shared lane instead of SATA port 4, + /// then it supports Gbe + 8 PCIES configuration, and BIOS won't hide the Root Port 1. + /// + RpLaneOwner = MmioRead8 (PciD28F0RegBase + 0x410); + if ((((RpLaneOwner & (BIT4)) == 0x0) && ((RpLaneOwner & BIT0) == 0x0)) || + ((GbePort == 0x0) && ((RpLaneOwner & (BIT4)) == 0)) || + (NandPort == BIT0)) { + RpHiddenMask |= BIT0; + } + } + if (PchSeries == PchLp) { + /// + /// Function disabled unused PCIE port + /// Disable PCIe Port 1 if either of the conditions are met + /// i. B0:D28:F0 + 410h [1:0] = 00b or 10b + /// ii. NandOverPCIe is configured to use PCIe Port 1 + /// + if (((MmioRead32 (PciD28F0RegBase + 0x410) & (BIT1 | BIT0)) == 0) || + ((MmioRead32 (PciD28F0RegBase + 0x410) & (BIT1 | BIT0)) == BIT1) || + (NandPort == BIT0)) { + RpHiddenMask |= BIT0; + } + } + if (PchSeries == PchH) { + /// + /// Disable PCIe Port 2 if either of the conditions are met + /// i. B0:D28:F0 + 410h [5] = 0b and B0:D28:F0 + 410h [2] = 0b + /// ii. GbeOverPCIe is configured to use Pcie Port 2 and SATA port 5 is mapped to this lane instead of PCIe Port 2 + /// iii. NandOverPCIe is configured to use PCIe Port 2 + /// NOTE: + /// For condition ii, if Gbe is configured to Pcie Port 2, and Pcie Port 2 ownes the shared lane instead of SATA port 5, + /// then it supports Gbe + 8 PCIES configuration, and BIOS won't hide the Root Port 2. + /// + if ((((RpLaneOwner & (BIT5)) == 0x0) && ((RpLaneOwner & BIT2) == 0x0)) || + ((GbePort == 0x1) && ((RpLaneOwner & (BIT5)) == 0)) || + (NandPort == BIT1)) { + RpHiddenMask |= BIT1; + } + } + if (PchSeries == PchLp) { + /// + /// Disable PCIe Port 2 if either of the conditions are met + /// i. B0:D28:F0 + 410h [3:2] = 00b or 10b + /// ii. NandOverPCIe is configured to use PCIe Port 2 + /// + if (((MmioRead32 (PciD28F0RegBase + 0x410) & (BIT3 | BIT2)) == 0) || + ((MmioRead32 (PciD28F0RegBase + 0x410) & (BIT3 | BIT2)) == BIT3) || + (NandPort == BIT1)) { + RpHiddenMask |= BIT1; + } + } + /// + /// Disable PCIe Port 3 if GbeOverPCIe is configured to use Port 3 + /// + if ((PchSeries == PchH) && (GbePort == 0x2)) { + RpHiddenMask |= BIT2; + } + if ((PchSeries == PchLp) && (GbePort == 0x0)) { + RpHiddenMask |= BIT2; + } + /// + /// Disable PCIe Port 4 if GbeOverPCIe is configured to use Port 4 + /// + if ((PchSeries == PchH) && (GbePort == 0x3)) { + RpHiddenMask |= BIT3; + } + if ((PchSeries == PchLp) && (GbePort == 0x1)) { + RpHiddenMask |= BIT3; + } + /// + /// Disable PCIe Port 5 if GbeOverPCIe is configured to use Port 5 + /// or NandOverPCIe is configure to use Port 5 + /// + if ((PchSeries == PchH) && (GbePort == 0x4 || NandPort == BIT4)) { + RpHiddenMask |= BIT4; + } + /// + /// Disable PCIe Port 5 if GbeOverPCIe is configured to use Port 5 + /// NandOverPCIe is configure to use Port 5 + /// + if ((PchSeries == PchLp) && (GbePort == 0x2 || GbePort == 0x3 || GbePort == 0x4 || GbePort == 0x5 || NandPort == BIT4)) { + RpHiddenMask |= BIT4; + } + /// + /// Disable PCIe Port 6 if GbeOverPCIe is configured to use Port 6 + /// or NandOverPCIe is configure to use Port 6 + /// + if ((PchSeries == PchH) && (GbePort == 0x5 || NandPort == BIT5)) { + RpHiddenMask |= BIT5; + } + /// + /// Disable PCIe Port 6 if SATA P1-P4 is configured + /// to use Port 6 Lane 0 - Lane 3 + /// or NandOverPCIe is configure to use Port 6 + /// + if ((PchSeries == PchLp) && ((MmioRead32 (PciD28F0RegBase + 0x410) & (BIT7 | BIT6 | BIT5 | BIT4)) == 0x0) || NandPort == BIT5) { + RpHiddenMask |= BIT5; + } + if (PchSeries == PchH) { + /// + /// Disable PCIe Port 7 if GbeOverPCIe is configured to use Port 7 + /// + if (GbePort == 0x6) { + RpHiddenMask |= BIT6; + } + /// + /// Disable PCIe Port 8 if GbeOverPCIe is configured to use Port 8 + /// + if (GbePort == 0x7) { + RpHiddenMask |= BIT7; + } + } + if (((MmioRead32 ((UINTN) (RootComplexBar + 0x1030))) & ((UINT32) (BIT22))) && + (PciExpressConfig->EnableSubDecode)) { + /// + /// Assert if Subtractive Decode Port is disabled by configuration + /// + ASSERT_EFI_ERROR ((RpHiddenMask & (B_PCH_RCRB_FUNC_DIS_PCI_EX_PORT1 << + (PciExpressConfig->PchPcieSbdePort))) == 0x1); + SubDecodePort = PciExpressConfig->PchPcieSbdePort; + } else { + SubDecodePort = 0xFF; + } + /// + /// The port of function number 0 might be disabled. + /// Will swap the function number 0 to enabled port on the end of this function. + /// Gather the enabled root ports here. + /// + for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex++) { + if ((PciExpressConfig->RootPort[PortIndex].Enable) && + (((*FuncDisableReg) & (B_PCH_RCRB_FUNC_DIS_PCI_EX_PORT1 << PortIndex)) == 0)) { + RpEnableMask |= 1 << PortIndex; + } + } + /// + /// Disable the port which is going to be hidden. + /// + if (RpEnableMask != 0) { + RpEnableMask &= ~(RpHiddenMask); + } + // + // If RootPortFunctionSwapping is disabled, force to enable the root port of function 0 + // + if (!((PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_3) && + (PciExpressConfig->RootPortFunctionSwapping == 1))) { + RpEnableMask |= 1 << Func0PortNum; + } + for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex++) { + FuncNum = GetPchPcieRpfn (RootComplexBar, PortIndex); + RPBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + FuncNum, + 0 + ); + + /// + /// PCH BIOS Spec Rev 0.5.0 Section 8.2 + /// Else if the port is hot-plug enable, do not disable the port. If BIOS wants to disable the port, + /// BIOS should not enable the hot plug capability or must disable the hot plug capability of the port. + /// Set B0:D28:Fn + 338h [26] = 0b at early POST. Done in PchInitPeim.c PchMiscInit(). + /// + /// Enabled Slot implemented for the enabled PCIE Root Ports. This is due to new PCIe disabling methodtology + /// to check if any is populated on the slots. + /// + if ((RpHiddenMask & (1 << PortIndex)) == 0) { + MmioOr16 (RPBase + R_PCH_PCIE_XCAP, B_PCH_PCIE_XCAP_SI); + } + + if ((RpHiddenMask & (1 << PortIndex)) != 0) { + *FuncDisableReg |= B_PCH_RCRB_FUNC_DIS_PCI_EX_PORT1 << PortIndex; + } else if (((RpEnableMask & (1 << PortIndex)) != 0) && + ((MmioRead16 (RPBase + R_PCH_PCIE_SLSTS) & BIT6) == 0) && + (PciExpressConfig->RootPort[PortIndex].HotPlug == 0) && + (PortIndex != SubDecodePort)) { + /// + /// PCH BIOS Spec Rev 0.5.0 Section 8.2 + /// Else if the port is not hot plug enable and no PCIe card is detected, + /// Set B0:D28:Fn + 338h [26] = 1b + /// Poll B0:D28:Fn + 328h [31:24] until 01h or else 50ms timeout + /// Set B0:D28:Fn + 408h [27] = 1b + /// Function disable the port at RCBA+ 3418 + /// + Data32And = 0xFFFFFFFF; + Data32Or = (UINT32) BIT26; + MmioOr32 ((RPBase + 0x338), Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + 0x338), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + + BitMask = (UINT32) (BIT31 | BIT30 | BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24); + BitValue = 1 << 24; + for (LoopTime = 0; LoopTime < 500; LoopTime++) { + if ((MmioRead32 (RPBase + 0x328) & BitMask) == BitValue) { + break; + } else { + PchPmTimerStall (100); + } + } + SCRIPT_MEM_POLL ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + RPBase + 0x328, + &BitMask, + &BitValue, + 50, + 1000 + ); + + Data32And = 0xFFFFFFFF; + Data32Or = (UINT32) BIT27; + MmioOr32 ((RPBase + 0x408), Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + 0x408), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + *FuncDisableReg |= B_PCH_RCRB_FUNC_DIS_PCI_EX_PORT1 << PortIndex; + } else if ((RpEnableMask & (1 << PortIndex)) == 0) { + /// + /// Else if the port is not hot plug enable, and BIOS wants to disable the port + /// If a PCIe card is detected, set B0:D28:Fn + 50h[4] = 1b + /// followed by function disable the port at RCBA + 3418h + /// + if ((MmioRead16 (RPBase + R_PCH_PCIE_SLSTS) & BIT6) != 0) { + MmioOr16 ((RPBase + R_PCH_PCIE_LCTL), (UINT16) BIT4); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RPBase + R_PCH_PCIE_LCTL), + 1, + (VOID *) (UINTN) (RPBase + R_PCH_PCIE_LCTL) + ); + } + *FuncDisableReg |= B_PCH_RCRB_FUNC_DIS_PCI_EX_PORT1 << PortIndex; + } else { + /// + /// Configure the rootports + /// + Status = PchInitSingleRootPort ( + (UINT8) PortIndex, + FuncNum, + PchPlatformPolicy, + PmBase, + RootComplexBar + ); + if (!EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, " Root Port %x device enabled. RpEnableMask: 0x%x\n", PortIndex + 1, RpEnableMask)); + } + + if ((PciExpressConfig->RootPort[PortIndex].TransmitterHalfSwing) && + (((MmioRead32 (RPBase + 0x328) & (0x00780000)) >> 19) == 0x7)) { + MmioOr8 (RPBase + R_PCH_PCIE_LCTL, B_PCH_PCIE_LCTL_LD); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (RPBase + R_PCH_PCIE_LCTL), + 1, + (VOID *) (UINTN) (RPBase + R_PCH_PCIE_LCTL) + ); + MmioOr16 (RPBase + R_PCH_PCIE_PECR1, BIT13); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RPBase + R_PCH_PCIE_PECR1), + 1, + (VOID *) (UINTN) (RPBase + R_PCH_PCIE_PECR1) + ); + MmioAnd8 (RPBase + R_PCH_PCIE_LCTL, (UINT8) ~(B_PCH_PCIE_LCTL_LD)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (RPBase + R_PCH_PCIE_LCTL), + 1, + (VOID *) (UINTN) (RPBase + R_PCH_PCIE_LCTL) + ); + } + } + + if (MmioRead32 (RPBase) == 0xFFFFFFFF) { + continue; + } + + if ((PchSeries == PchH) && (PortIndex == 0 || PortIndex == 4)) { + /// + /// PCH BIOS Spec Rev 0.5.0, Section 8.14 Additional PCI Express* Programming Steps + /// Step 19 + /// Set B0:F28:F0&F4 + F7h[3:2] = 00b + /// + MmioAnd8 (RPBase + 0xF7, (UINT8) ~(BIT3 | BIT2)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (RPBase + 0xF7), + 1, + (VOID *) (UINTN) (RPBase + 0xF7) + ); + } + if ((PchSeries == PchLp) && (PortIndex == 0 || PortIndex == 4 || PortIndex == 5)) { + /// + /// Set B0:F28:F0,F4&F5 + F7h[3:2] = 00b + /// + MmioAnd8 (RPBase + 0xF7, (UINT8) ~(BIT3 | BIT2)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (RPBase + 0xF7), + 1, + (VOID *) (UINTN) (RPBase + 0xF7) + ); + } + + if ((RpHiddenMask & (1 << PortIndex)) == 0) { + /// + /// Disable the forwarding of EOI messages. + /// Set B0:D28:F0/F1/F2/F3/F4/F5/F6/F7 + D4h [1] = 1b + /// + #ifdef HOTPLUG_EOI_FLAG // AMI_OVERRIDE, [EIP84720]> + MmioOr8 (RPBase + 0xD4, (UINT8) (BIT1)); + #else + //Supporting _RMV method in asl code, and reading hotplug capability register of root port + //if hotplug disable, then set EOI Forwarding Disable bit + #ifdef TBT_UP_PORT_FUNC_FLAG + if((TBT_UP_PORT_FUNC == PortIndex) || (!(MmioRead8 (RPBase + 0x54) & 0x40))) + #else + if(!(MmioRead8 (RPBase + 0x54) & 0x40)) + #endif + MmioOr8 (RPBase + 0xD4, (UINT8) (BIT1)); + #endif // AMI_OVERRIDE, [EIP84720]< + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (RPBase + 0xD4), + 1, + (VOID *) (UINTN) (RPBase + 0xD4) + ); + } + } + // + // If RootPortFunctionSwapping is disabled, force to enable the root port of function 0 + // + if (!((PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_3) && + (PciExpressConfig->RootPortFunctionSwapping == 1))) { + Mask = (0xFF >>(8-GetPchMaxPciePortNum ())); + if (((*FuncDisableReg >> N_PCH_RCRB_FUNC_DIS_PCI_EX_PORT1) & Mask) != Mask) { + *FuncDisableReg &= ~(B_PCH_RCRB_FUNC_DIS_PCI_EX_PORT1 << Func0PortNum); + } + } + + /// + /// Configure root port clock gating + /// + RpEnableMask = (UINT8)~(*FuncDisableReg >> 16); + if (PciExpressConfig->RootPortClockGating) { + PcieEnableClockGating ( + PchPlatformPolicy->BusNumber, + PchPlatformPolicy, + RpEnableMask, + RpHiddenMask, + RootComplexBar, + NandPort + ); + } + + /// + /// Enable PCIE Relaxed Order. It always allows downstream completions to pass posted write. + /// Set B0:D28:Fx offset 320h [24,23] to 1, 1b. + /// Set RCBA 2314h[31,7] to 1, 1b. + /// Set RCBA 1114h[15,14] to 1, 1b. + /// + for (FuncNum = 0; FuncNum < GetPchMaxPciePortNum (); FuncNum++) { + RPBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + FuncNum, + 0 + ); + if (MmioRead16 (RPBase + R_PCH_PCIE_VENDOR_ID) == 0xFFFF) { + continue; + } + MmioOr32 (RPBase + R_PCH_PCIE_PECR2, (BIT24 | BIT23)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_PECR2), + 1, + (VOID *) (UINTN) (RPBase + R_PCH_PCIE_PECR2) + ); + } + MmioOr32 (RootComplexBar + R_PCH_RCRB_CIR2314, (BIT31 | BIT7)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2314), + 1, + (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2314) + ); + MmioOr16 (RootComplexBar + 0x1114, (BIT15 | BIT14)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RootComplexBar + 0x1114), + 1, + (VOID *) (UINTN) (RootComplexBar + 0x1114) + ); + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 8.14 Additional PCI Express* Programming Steps + /// Step 4 + /// Reconfigured the Function number using RPFN register at RCBA + 404h if function 0 (F0) is disabled + /// (If Port of function 0 is disable, swap the function number with other enabled port) + /// + if ((PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_3) && + (PciExpressConfig->RootPortFunctionSwapping == 1)) { + Func0PortNum = 0xFF; + for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex++) { + FuncNum = (UINT8)((RpFnOr >> (PortIndex * S_PCH_RCRB_PRFN_RP_FIELD)) & B_PCH_RCRB_RPFN_RP1FN); + if (FuncNum == 0) { + Func0PortNum = PortIndex; + break; + } + } + if ((Func0PortNum < GetPchMaxPciePortNum ()) && ((RpEnableMask & (BIT0 << Func0PortNum)) == 0)) { + for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex++) { + if ((RpEnableMask & (BIT0 << PortIndex)) != 0) { + FuncNum = (UINT8)((RpFnOr >> (PortIndex * S_PCH_RCRB_PRFN_RP_FIELD)) & B_PCH_RCRB_RPFN_RP1FN); + RpFnOr &= ((UINT32)~(B_PCH_RCRB_RPFN_RP1FN << (Func0PortNum * S_PCH_RCRB_PRFN_RP_FIELD))) & + ((UINT32)~(B_PCH_RCRB_RPFN_RP1FN << (PortIndex * S_PCH_RCRB_PRFN_RP_FIELD))); + RpFnOr |= ((UINT32)(((UINT32)FuncNum) << (Func0PortNum * S_PCH_RCRB_PRFN_RP_FIELD))); + break; + } + } + } + } + + MmioAndThenOr32 (RootComplexBar + R_PCH_RCRB_RPFN, RpFnAnd, RpFnOr); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RootComplexBar + R_PCH_RCRB_RPFN), + &RpFnOr, // Data to be ORed + &RpFnAnd // Data to be ANDed + ); + + DEBUG ((EFI_D_INFO, "PchInitRootPorts() End\n")); + + return EFI_SUCCESS; +} + +/** + Perform Root Port Initialization. + + @param[in] RootPort The root port to be initialized (zero based) + @param[in] RootPortFunction The PCI function number of the root port + @param[in] PchPlatformPolicy The PCH Platform Policy protocol + @param[in] PmBase The PM I/O Base address of the PCH + @param[in] RootComplexBar RCBA of the PCH + + @retval EFI_SUCCESS Device found. The root port must be enabled. + @retval EFI_NOT_FOUND No device is found on the root port. It may be disabled. + @exception EFI_UNSUPPORTED Unsupported operation. +**/ +EFI_STATUS +PchInitSingleRootPort ( + IN UINT8 RootPort, + IN UINT8 RootPortFunction, + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT16 PmBase, + IN UINT32 RootComplexBar + ) +{ + EFI_STATUS Status; + UINTN RPBase; + UINTN LpcBase; + UINTN PciD28F0RegBase; + UINTN PciD28F4RegBase; + UINTN PciD28F5RegBase; + UINT32 CapOffset; + UINT8 BusNumber; + UINT32 Data32; + UINT16 Data16; + UINT32 Data32Or; + UINT32 Data32And; + UINT16 Data16Or; + UINT16 Data16And; + UINT32 PcieNccSSc; + UINT8 DeviceLaneOwner; + UINT32 PchPcieHsioAddrPerPort[4]; + UINT8 NumOfLanePerPort; + UINT8 LaneIndex; + PCH_PCI_EXPRESS_ROOT_PORT_CONFIG *RootPortConfig; + BOOLEAN DeviceFound; + PCH_SERIES PchSeries; + UINT32 DeviceClassDword; + + PchSeries = GetPchSeries(); + DeviceFound = FALSE; + RootPortConfig = &PchPlatformPolicy->PciExpressConfig->RootPort[RootPort]; + BusNumber = PchPlatformPolicy->BusNumber; + RPBase = MmPciAddress (0, BusNumber, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, RootPortFunction, 0); + LpcBase = MmPciAddress (0, BusNumber, PCI_DEVICE_NUMBER_PCH_LPC, PCI_FUNCTION_NUMBER_PCH_LPC, 0); + PciD28F0RegBase = MmPciAddress (0, BusNumber, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, GetPchPcieRpfn( RootComplexBar, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1), 0); + PciD28F4RegBase = MmPciAddress (0, BusNumber, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, GetPchPcieRpfn( RootComplexBar, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_5), 0); + PciD28F5RegBase = 0; + DeviceClassDword = 0; + if (PchSeries == PchLp) { + PciD28F5RegBase = MmPciAddress (0, BusNumber, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, GetPchPcieRpfn( RootComplexBar, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_6), 0); + } + CapOffset = PcieFindCapId ( + BusNumber, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + RootPortFunction, + 0x10 + ); + + if (CapOffset == 0) { + return EFI_UNSUPPORTED; + } + + PcieNccSSc = 0; + NumOfLanePerPort = 0; + switch (RootPort) { + case PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1: + PcieNccSSc = MmioRead32 (PciD28F0RegBase + 0x32C) & BIT28; + break; + + case PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_2: + PcieNccSSc = MmioRead32 (PciD28F0RegBase + 0x32C) & BIT29; + break; + + case PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_3: + PcieNccSSc = MmioRead32 (PciD28F0RegBase + 0x32C) & BIT30; + break; + + case PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_4: + PcieNccSSc = MmioRead32 (PciD28F0RegBase + 0x32C) & BIT31; + break; + + case PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_5: + PcieNccSSc = MmioRead32 (PciD28F4RegBase + 0x32C) & BIT28; + break; + + case PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_6: + if (PchSeries == PchH) { + PcieNccSSc = MmioRead32 (PciD28F4RegBase + 0x32C) & BIT29; + } else if (PchSeries == PchLp) { + PcieNccSSc = MmioRead32 (PciD28F5RegBase + 0x32C) & BIT29; + } + break; + + case PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_7: + if (PchSeries == PchH) { + PcieNccSSc = MmioRead32 (PciD28F4RegBase + 0x32C) & BIT30; + } + break; + + case PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_8: + if (PchSeries == PchH) { + PcieNccSSc = MmioRead32 (PciD28F4RegBase + 0x32C) & BIT31; + } + break; + + default: + PcieNccSSc = 0; + } + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 8.14 Additional PCI Express* Programming Steps + /// Step 5 + /// If corresponding Root Port 4 to 1 in B0:D28:F0 + 32Ch [31:28], Root Port 8 to 5 + /// in B0:D28:F4 + 32Ch [31:28], is set, for EACH PORT (x): + /// + if (PcieNccSSc) { + /// + /// Step 5.1, 5.2 + /// Set B0:D28:Fx + D4h[4] = 1b + /// Set B0:D28:Fx + D4h[3:2] = 10b + /// + MmioAndThenOr8 ((RPBase + 0xD4), (UINT8)~BIT2, BIT4 | BIT3); + /// + /// Step 5.3 + /// Set B0:D28:Fx + D8h[20:18] = 111b + /// + MmioOr32 ((RPBase + 0xD8), BIT20 | BIT19 | BIT18); + /// + /// Step 5.4 + /// Set B0:D28:Fx + 4Ch[17:15] = 100b, see also step 9. + /// + MmioAndThenOr32 ((RPBase + 0x4C), (UINT32)~(BIT16 | BIT15), BIT17); +#ifdef ULT_FLAG + if (PchSeries == PchLp) { + /// + /// Step 5.5 + /// Read the IOBP register below, increase the values by 2 and write back. + /// E9002440 [20:16], [12:8] + /// E9002640 [20:16], [12:8] + /// E9000840 [20:16], [12:8] + /// E9000A40 [20:16], [12:8] + /// E9000C40 [20:16], [12:8] + /// E9000E40 [20:16], [12:8] + /// E9001040 [20:16], [12:8] + /// E9001240 [20:16], [12:8] + /// EA002040 [20:16], [12:8] + /// EA002240 [20:16], [12:8] + /// EA002440 [20:16], [12:8] + /// EA002640 [20:16], [12:8] + /// + DeviceLaneOwner = MmioRead8 (PciD28F0RegBase + 0x410); + if (RootPort == PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_5) { + NumOfLanePerPort = 4; + PchPcieHsioAddrPerPort[0] = PchLpPcieHsioAddr[4]; + PchPcieHsioAddrPerPort[1] = PchLpPcieHsioAddr[5]; + PchPcieHsioAddrPerPort[2] = PchLpPcieHsioAddr[6]; + PchPcieHsioAddrPerPort[3] = PchLpPcieHsioAddr[7]; + } else if (RootPort == PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_6) { + NumOfLanePerPort = 0; + if ((DeviceLaneOwner & BIT4) == BIT4) { + PchPcieHsioAddrPerPort[NumOfLanePerPort++] = PchLpPcieHsioAddr[8]; + } + if ((DeviceLaneOwner & BIT5) == BIT5) { + PchPcieHsioAddrPerPort[NumOfLanePerPort++] = PchLpPcieHsioAddr[9]; + } + if ((DeviceLaneOwner & BIT6) == BIT6) { + PchPcieHsioAddrPerPort[NumOfLanePerPort++] = PchLpPcieHsioAddr[10]; + } + if ((DeviceLaneOwner & BIT7) == BIT7) { + PchPcieHsioAddrPerPort[NumOfLanePerPort++] = PchLpPcieHsioAddr[11]; + } + } else { + NumOfLanePerPort = 1; + PchPcieHsioAddrPerPort[0] = PchLpPcieHsioAddr[RootPort]; + } + } +#endif // ULT_FLAG +#ifdef TRAD_FLAG + if (PchSeries == PchH) { + /// + /// Step 5.5 + /// Read the IOBP register below, increase the values by 2 and write back. + /// Dedicated lane Setting + /// E9002040 [20:16], [12:8] + /// E9002240 [20:16], [12:8] + /// E9002440 [20:16], [12:8] + /// E9002640 [20:16], [12:8] + /// E9002840 [20:16], [12:8] + /// E9002A40 [20:16], [12:8] + /// Shared lane Setting + /// E9002C40 [20:16], [12:8] + /// E9002E40 [20:16], [12:8] + /// EA002040 [20:16], [12:8] + /// EA002240 [20:16], [12:8] + /// + DeviceLaneOwner = MmioRead8 (PciD28F0RegBase + 0x410); + NumOfLanePerPort = 1; + if (RootPort == PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1) { + if ((DeviceLaneOwner & (BIT1 | BIT0)) == BIT0) { + PchPcieHsioAddrPerPort[0] = PchHPcieHsioAddr[0]; + } else { + PchPcieHsioAddrPerPort[0] = PchHPcieHsioAddr[8]; + } + } else if (RootPort == PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_2) { + if ((DeviceLaneOwner & (BIT3 | BIT2)) == BIT2) { + PchPcieHsioAddrPerPort[0] = PchHPcieHsioAddr[1]; + } else { + PchPcieHsioAddrPerPort[0] = PchHPcieHsioAddr[9]; + } + } else { + PchPcieHsioAddrPerPort[0] = PchHPcieHsioAddr[RootPort]; + } + } +#endif // TRAD_FLAG + for (LaneIndex = 0; LaneIndex < NumOfLanePerPort; LaneIndex++) { + Status = ReadIobp ( + RootComplexBar, + PchPcieHsioAddrPerPort[LaneIndex], + &Data32 + ); + ASSERT_EFI_ERROR (Status); + Data32 += 0x00020200; + Status = ProgramIobp ( + RootComplexBar, + PchPcieHsioAddrPerPort[LaneIndex], + 0x0, + Data32 + ); + ASSERT_EFI_ERROR (Status); + Status = SetProgramIobpS3Item ( + RootComplexBar, + PchPcieHsioAddrPerPort[LaneIndex], + 0x0, + Data32 + ); + ASSERT_EFI_ERROR (Status); + } + /// + /// Step 5.6 + /// Set B0:D28:Fx + 338h[26] = 0b + /// + MmioAnd32 ((RPBase + 0x338), (UINT32)~BIT26); + } + + Data32 = MmioRead32 (RPBase + R_PCH_PCIE_DCAP2); + /// + /// PCH BIOS Spec Rev 0.5.5, Section 8.14.1 Power Optimizer Configuration + /// Step 1 + /// Enable support Latency Tolerance Reporting (LTR) + /// Step 1.1 + /// Program B0:D28:F0~F7 + 400h to 883C883Ch for ports which has a PCIe + /// device attached to it. + /// Done in PcieSetPm() + /// Step 1.2 + /// Program B0:D28:F0~F7 + 404h [1:0] = 11b for ports which has a PCIe device + /// device attached to it. + /// Done in PcieSetPm() + /// Step 1.3 + /// Program B0:D28:F0-F7 + 64h [11] = 1b + /// + if (PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[RootPort].LtrEnable == PCH_DEVICE_ENABLE) { + Data32 |= BIT11; + } else { + Data32 &= (UINT32) ~(BIT11); + } + /// + /// Step 2 + /// Support Optimized Buffer Flush/Fill (OBFF) + /// Step 2.1 + /// Program B0:D28:F0-F7 + 64h [19:18] = 2h + /// + if (PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[RootPort].ObffEnable == PCH_DEVICE_ENABLE) { + Data32 |= BIT19; + } else { + Data32 &= (UINT32) ~(BIT19 | BIT18); + } + MmioWrite32 (RPBase + R_PCH_PCIE_DCAP2, Data32); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_DCAP2), + 1, + &Data32 + ); + + Data16 = MmioRead16 (RPBase + R_PCH_PCIE_DCTL2); + /// + /// Step 1.4 + /// Program B0:D28:F0-F7 + 68h [10] = 1b + /// + if (PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[RootPort].LtrEnable == PCH_DEVICE_ENABLE) { + Data16 |= BIT10; + } else { + Data16 &= (UINT16) ~(BIT10); + } + /// + /// Step 2.2 + /// Program B0:D28:F0-F7 + 68h [14:13] = 3h + /// + if (PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[RootPort].ObffEnable == PCH_DEVICE_ENABLE) { + Data16 |= BIT14 | BIT13; + } else { + Data16 &= (UINT16) ~(BIT14 | BIT13); + } + + MmioWrite16 (RPBase + R_PCH_PCIE_DCTL2, Data16); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RPBase + R_PCH_PCIE_DCTL2), + 1, + &Data16 + ); + /// + /// PCH BIOS Spec Rev 0.5.0, Section 8.14 Additional PCI Express* Programming Steps + /// Step 6 + /// Set B0:D28:F0~F7 + 318h [31:16] = 1414h + /// + Data32Or = 0x14140000; + Data32And = (UINT32) (~(0xFFFF0000)); + MmioAndThenOr32 (RPBase + 0x318, Data32And, Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + 0x318), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + + /// + /// Step 7 + /// If B0:D28:F0 + F5h[0] = 1b or step 5 is TRUE, set B0:D28:F0~F7 + 4Ch[17:15] = 100b + /// Else set B0:D28:F0~F7 + 4Ch[17:15] = 010b + /// + if ((MmioRead8 (PciD28F0RegBase + 0xF5) & BIT0) || PcieNccSSc) { + Data32Or = BIT17; + } else { + Data32Or = BIT16; + } + + Data32And = (UINT32) (~B_PCH_PCIE_LCAP_EL1); + MmioAndThenOr32 (RPBase + R_PCH_PCIE_LCAP, Data32And, Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_LCAP), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + /// + /// Step 8 + /// Set B0:D28:F0~F7 + 314h[31:24] = 74h + /// Step 9 + /// Set B0:D28:F0~F7 + 314h[23:16] = 3Ah + /// Step 10 + /// Set B0:D28:F0~F7 + 314h[15:08] = 36h + /// Step 11 + /// Set B0:D28:F0~F7 + 314h[07:00] = 1Bh + /// + Data32Or = 0x743A361B; + Data32And = (UINT32) (0x0); + MmioAndThenOr32 (RPBase + 0x314, Data32And, Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + 0x314), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + /// + /// Step 12 + /// Set B0:D28:F0~F7 + D8h[17:15] = 3h + /// + Data32And = (UINT32) (~B_PCH_PCIE_MPC_CCEL); + Data32Or = BIT16 | BIT15; + MmioAndThenOr32 (RPBase + R_PCH_PCIE_MPC, Data32And, Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_MPC), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + /// + /// Step 13 + /// Set B0:D28:F0~F7 + 33Ch[24:0] = 854C74h + /// + Data32And = 0xFF000000; + Data32Or = 0x854C74; + MmioAndThenOr32 (RPBase + 0x33C, Data32And, Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + 0x33C), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + + /// + /// Step 16 + /// Set B0:D28:F0~F7 + D8h[25] = 1b + /// + Data32And = (UINT32) ~(B_PCH_PCIE_MPC_IRRCE); + Data32Or = B_PCH_PCIE_MPC_IRRCE; + MmioAndThenOr32 (RPBase + R_PCH_PCIE_MPC, Data32And, Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_MPC), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + /// + /// Step 17 + /// For system that support MCTP over PCIE set + /// Set B0:D28:F0~F7 + D8h[27] = 1b + /// Set B0:D28:F0~F7 + D8h[3] = 1b + /// + Data32And = (UINT32) ~(B_PCH_PCIE_MPC_MCTPSE | B_PCH_PCIE_MPC_MMBNCE); + Data32Or = B_PCH_PCIE_MPC_MCTPSE | B_PCH_PCIE_MPC_MMBNCE; + MmioAndThenOr32 (RPBase + R_PCH_PCIE_MPC, Data32And, Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_MPC), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + /// + /// Step 18 + /// Set B0:D28:F0~F7 + F5h[7:4] = 0000b + /// + MmioAnd8 (RPBase + 0xF5, (UINT8) ~(BIT4 | BIT5 | BIT6 | BIT7)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (RPBase + 0xF5), + 1, + (VOID *) (UINTN) (RPBase + 0xF5) + ); + /// + /// Step 20 + /// If there is no IOAPIC behind the root port, set EOI Forwarding Disable bit (B0:D28:F0-F7:D4h[1]) to 1b. + /// Done in PchPciExpressHelpersLibrary.c PcieSetEoiFwdDisable() + /// + /// Step 21 + /// For systems that support Advanced Error Reporting set + /// B0:D28:F0~F7:100h[19:0] = 10001h + /// Else + /// B0:D28:F0~F7:100h[19:0] = 0h + /// + if (RootPortConfig->AdvancedErrorReporting) { + Data32 = (UINT32)(BIT16 | BIT0); + } else { + Data32 = 0; + } + /// + /// For LPT-LP, setup the next capability offset to 0x200 + /// B0:D28:F0~F7:100h[29] = 1b + /// + if (PchSeries == PchLp) { + Data32 |= BIT29; + } + MmioWrite32 (RPBase + R_PCH_PCIE_AECH, Data32); + + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_AECH), + 1, + (VOID *) (UINTN) (RPBase + R_PCH_PCIE_AECH) + ); + /// + /// Step 22 + /// System bios should initiate link retrain for all slots that has card populated after register restoration. + /// Done in PchPciExpressHelpersLibrary.c PchPcieInitRootPortDownstreamDevices () + /// Step 23 + /// System BIOS should read and write back to capability register B0:D28:F0 offsets 34h, 40h, + /// 80h and 90h after it has been configure or prior to boot + /// Done in PchInit.c PciERWORegInit () + /// + /// Configure Extended Synch + /// + if (RootPortConfig->ExtSync) { + Data16And = (UINT16) (-1); + Data16Or = B_PCH_PCIE_LCTL_ES; + } else { + Data16And = (UINT16) (~B_PCH_PCIE_LCTL_ES); + Data16Or = 0; + } + + MmioAndThenOr16 (RPBase + R_PCH_PCIE_LCTL, Data16And, Data16Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RPBase + R_PCH_PCIE_LCTL), + &Data16Or, // Data to be ORed + &Data16And // Data to be ANDed + ); + + if (PchSeries == PchLp) { + /// + /// Step 23 + /// Program B0:D28:F0~F5:320h[21:20] to 01b and [8:6] to 011b + /// + Data32And = (UINT32) (~(BIT21 | BIT20 | BIT8 | BIT7 | BIT6)); + Data32Or = BIT20 | BIT7 | BIT6; + MmioAndThenOr32 (RPBase + R_PCH_PCIE_PECR2, Data32And, Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_PECR2), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + } + + /// + /// Configure Completion Timeout + /// + Data16And = (UINT16)~(B_PCH_PCIE_DCTL2_CTD | B_PCH_PCIE_DCTL2_CTV); + Data16Or = 0; + if (RootPortConfig->CompletionTimeout == PchPcieCompletionTO_Disabled) { + Data16Or = B_PCH_PCIE_DCTL2_CTD; + } else { + switch (RootPortConfig->CompletionTimeout) { + case PchPcieCompletionTO_Default: + Data16Or = V_PCH_PCIE_DCTL2_CTV_DEFAULT; + break; + + case PchPcieCompletionTO_16_55ms: + Data16Or = V_PCH_PCIE_DCTL2_CTV_40MS_50MS; + break; + + case PchPcieCompletionTO_65_210ms: + Data16Or = V_PCH_PCIE_DCTL2_CTV_160MS_170MS; + break; + + case PchPcieCompletionTO_260_900ms: + Data16Or = V_PCH_PCIE_DCTL2_CTV_400MS_500MS; + break; + + case PchPcieCompletionTO_1_3P5s: + Data16Or = V_PCH_PCIE_DCTL2_CTV_1P6S_1P7S; + break; + + default: + Data16Or = 0; + break; + } + } + + MmioAndThenOr16 (RPBase + R_PCH_PCIE_DCTL2, Data16And, Data16Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RPBase + R_PCH_PCIE_DCTL2), + &Data16Or, // Data to be ORed + &Data16And // Data to be ANDed + ); + + /// + /// Set the Slot Implmemented Bit. Note that this must be set before + /// presence is valid. + /// PCH BIOS Spec Rev 0.5.0 section 8.2.2, The System BIOS must + /// initialize the "Slot Implemented" bit of the PCI Express* Capabilities Register, + /// XCAP D28:F0~7:Reg 42h[8] of each available and enabled downstream root port. + /// Setting this bit will indicate that the PCI Express* link associated with this + /// port is connected to a slot (as compared to being connected to an integrated + /// device component). + /// + if (RootPortConfig->SlotImplemented) { + /// + /// Slot Implemented enabled earlier. Here will only save this register for enabled ports + /// + Data16Or = BIT8; + Data16And = 0xFFFF; + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RPBase + CapOffset + 2), + &Data16Or, // Data to be ORed + &Data16And // Data to be ANDed + ); + /// + /// For Root Port Slots Numbering on the CRBs. + /// + Data32Or = 0; + Data32And = (UINT32) (~(B_PCH_PCIE_SLCAP_SLV | B_PCH_PCIE_SLCAP_SLS | B_PCH_PCIE_SLCAP_PSN)); + /// + /// PCH BIOS Spec Rev 0.5.0 section 8.8.2.1 + /// Note: If Hot Plug is supported, then write a 1 to the Hot Plug Capable (bit6) and Hot Plug + /// Surprise (bit5) in the Slot Capabilities register, D28:F0~7:Reg 54h. Otherwise, + /// write 0 to the bits PCIe Hot Plug SCI Enable + /// + Data32And &= (UINT32) (~(B_PCH_PCIE_SLCAP_HPC | B_PCH_PCIE_SLCAP_HPS)); + if (RootPortConfig->HotPlug) { + Data32Or |= B_PCH_PCIE_SLCAP_HPC | B_PCH_PCIE_SLCAP_HPS; + } + /// + /// Get the width from LCAP + /// Slot Type X1 X4/X8 X16 + /// Default 10W 25W 75W + /// The slot power consumption and allocation is platform specific. Please refer to the + /// "PCI Express* Card Electromechanical (CEM) Spec" for details. + /// bugbug what's the default setting for X2 + /// + if ((((MmioRead32 (RPBase + R_PCH_PCIE_LCAP)) & B_PCH_PCIE_LCAP_MLW) >> 4) == 0x01) { + Data32Or |= (UINT32) (100 << 7); + Data32Or |= (UINT32) (1 << 15); + } else if ((((MmioRead32 (RPBase + R_PCH_PCIE_LCAP)) & B_PCH_PCIE_LCAP_MLW) >> 4) >= 0x04) { + Data32Or |= (UINT32) (250 << 7); + Data32Or |= (UINT32) (1 << 15); + } + + Data32Or |= (UINT32) (RootPortConfig->PhysicalSlotNumber << 19); + MmioAndThenOr32 (RPBase + R_PCH_PCIE_SLCAP, Data32And, Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_SLCAP), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + } + /// + /// Initialize downstream devices + /// + Status = PchPcieInitRootPortDownstreamDevices ( + BusNumber, + (UINT8) PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + RootPortFunction, + PchPlatformPolicy->PciExpressConfig->TempRootPortBusNumMin, + PchPlatformPolicy->PciExpressConfig->TempRootPortBusNumMax, + &DeviceClassDword + ); + if (Status == EFI_SUCCESS) { + DeviceFound = TRUE; + } else { + /// + /// Disable the forwarding of EOI messages. + /// Set B0:D28:F0/F1/F2/F3/F4/F5/F6/F7 + D4h [1] = 1b + /// + #ifdef HOTPLUG_EOI_FLAG // AMI_OVERRIDE, [EIP84720]> + MmioOr8 (RPBase + 0xD4, (UINT8) (BIT1)); + #else + //Supporting _RMV method in asl code, and reading hotplug capability register of root port + //if hotplug disable, then set EOI Forwarding Disable bit + #ifdef TBT_UP_PORT_FUNC_FLAG + if((TBT_UP_PORT_FUNC == RootPortFunction) || (!(MmioRead8 (RPBase + 0x54) & 0x40))) + #else + if(!(MmioRead8 (RPBase + 0x54) & 0x40)) + #endif + MmioOr8 (RPBase + 0xD4, (UINT8) (BIT1)); + #endif // AMI_OVERRIDE, [EIP84720]< + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (RPBase + 0xD4), + 1, + (VOID *) (UINTN) (RPBase + 0xD4) + ); + } + /// + /// Not checking the error status here - downstream device not present does not + /// mean an error of this root port. Our return status of EFI_SUCCESS means this + /// port is enabled and outer function depends on this return status to do + /// subsequent initializations. + /// + Status = SetInitRootPortDownstreamS3Item ( + BusNumber, + (UINT8) PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + RootPortFunction, + PchPlatformPolicy->PciExpressConfig->TempRootPortBusNumMin, + PchPlatformPolicy->PciExpressConfig->TempRootPortBusNumMax + ); + ASSERT_EFI_ERROR (Status); + + /// + /// Additional configurations + /// + + /// + /// Enable Subtractive Decode of RootPort + /// Step 1 + /// Ensure flash descriptor PCH Strap 9 Bit 14, which read RCBA + 1030h[22] = 1b + /// Step 2 + /// Set B0:D28:Fn + ECh[1:0] = 11b, + /// If downstream is PCI-to-PCI bridge, then also set B0:D28:Fn + ECh[2] = 1b + /// + if ((RootPort == PchPlatformPolicy->PciExpressConfig->PchPcieSbdePort) && + (MmioRead32 ((UINTN) (RootComplexBar + 0x1030)) & BIT22) && + (PchPlatformPolicy->PciExpressConfig->EnableSubDecode)) + { + Data32Or = (B_PCH_PCIE_PECR3_SDCDID | B_PCH_PCIE_PECR3_SDE); + if ((((DeviceClassDword >> 24) & 0xFF) == PCI_CLASS_BRIDGE) && // BCC + (((DeviceClassDword >> 16) & 0xFF) == PCI_CLASS_BRIDGE_CARDBUS)) // SCC + { + Data32Or |= BIT2; + } + + MmioOr32 (RPBase + R_PCH_PCIE_PECR3, Data32Or); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_PECR3), + 1, + (VOID *) (UINTN) (RPBase + R_PCH_PCIE_PECR3) + ); + } + + /// + /// Configure Error Reporting policy in the Device Control Register + /// + Data16And = (UINT16) (~(B_PCH_PCIE_DCTL_URE | B_PCH_PCIE_DCTL_FEE | B_PCH_PCIE_DCTL_NFE | B_PCH_PCIE_DCTL_CEE)); + Data16Or = 0; + + if (RootPortConfig->UnsupportedRequestReport) { + Data16Or |= B_PCH_PCIE_DCTL_URE; + } + + if (RootPortConfig->FatalErrorReport) { + Data16Or |= B_PCH_PCIE_DCTL_FEE; + } + + if (RootPortConfig->NoFatalErrorReport) { + Data16Or |= B_PCH_PCIE_DCTL_NFE; + } + + if (RootPortConfig->CorrectableErrorReport) { + Data16Or |= B_PCH_PCIE_DCTL_CEE; + } + + MmioAndThenOr16 (RPBase + R_PCH_PCIE_DCTL, Data16And, Data16Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RPBase + R_PCH_PCIE_DCTL), + &Data16Or, // Data to be ORed + &Data16And // Data to be ANDed + ); + + /// + /// Configure Interrupt / Error reporting in R_PCH_PCIE_RCTL + /// + Data16And = (UINT16) (~(B_PCH_PCIE_RCTL_PIE | B_PCH_PCIE_RCTL_SFE | B_PCH_PCIE_RCTL_SNE | B_PCH_PCIE_RCTL_SCE)); + Data16Or = 0; + + if (RootPortConfig->PmeInterrupt) { + Data16Or |= B_PCH_PCIE_RCTL_PIE; + } + + if (RootPortConfig->SystemErrorOnFatalError) { + Data16Or |= B_PCH_PCIE_RCTL_SFE; + } + + if (RootPortConfig->SystemErrorOnNonFatalError) { + Data16Or |= B_PCH_PCIE_RCTL_SNE; + } + + if (RootPortConfig->SystemErrorOnCorrectableError) { + Data16Or |= B_PCH_PCIE_RCTL_SCE; + } + + MmioAndThenOr16 (RPBase + R_PCH_PCIE_RCTL, Data16And, Data16Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RPBase + R_PCH_PCIE_RCTL), + &Data16Or, // Data to be ORed + &Data16And // Data to be ANDed + ); + + /// + /// Root PCI-E Powermanagement SCI Enable + /// + if (RootPortConfig->PmSci) { + /// + /// PCH BIOS Spec Rev 0.5.0 section 8.7.3 BIOS Enabling of Intel PCH PCI Express* PME SCI Generation + /// Step 1 + /// Make sure that PME Interrupt Enable bit, D28:F0-7:Reg 5Ch[3] is cleared + /// + Data16And = (UINT16) (~B_PCH_PCIE_RCTL_PIE); + Data16Or = 0; + MmioAnd16 (RPBase + R_PCH_PCIE_RCTL, Data16And); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RPBase + R_PCH_PCIE_RCTL), + &Data16Or, // Data to be ORed + &Data16And // Data to be ANDed + ); + + /// + /// Step 2 + /// Program Misc Port Config (MPC) register at PCI config space offset + /// D8h as follows: + /// Set Power Management SCI Enable bit, D28:F0~7:Reg D8h[31] + /// Clear Power Management SMI Enable bit, D28:F0~7:Reg D8h[0] + /// + Data32And = (UINT32) (~B_PCH_PCIE_MPC_PMME); + Data32Or = B_PCH_PCIE_MPC_PMCE; + MmioAndThenOr32 (RPBase + R_PCH_PCIE_MPC, Data32And, Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_MPC), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + + /// + /// Step 3 + /// Make sure GPE0 Register (PMBase+20h[9]), PCI_EXP_STS is 0, clear it if not zero + /// + if (PchSeries == PchLp) { + Data32Or = IoRead32 (PmBase + R_PCH_ACPI_GPE0_STS_127_96); + if ((Data32Or & B_PCH_ACPI_GPE0_STS_127_96_PCI_EXP) != 0) { + Data32Or = B_PCH_ACPI_GPE0_STS_127_96_PCI_EXP; + IoWrite32 (PmBase + R_PCH_ACPI_GPE0_STS_127_96, Data32Or); + SCRIPT_IO_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PmBase + R_PCH_ACPI_GPE0_STS_127_96), + 1, + &Data32Or + ); + } + } else if (PchSeries == PchH) { + Data32Or = IoRead32 (PmBase + R_PCH_ACPI_GPE0a_STS); + if ((Data32Or & B_PCH_ACPI_GPE0a_STS_PCI_EXP) != 0) { + Data32Or = B_PCH_ACPI_GPE0a_STS_PCI_EXP; + IoWrite32 (PmBase + R_PCH_ACPI_GPE0a_STS, Data32Or); + SCRIPT_IO_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PmBase + R_PCH_ACPI_GPE0a_STS), + 1, + &Data32Or + ); + } + } + /// + /// Step 4 + /// Set BIOS_PCI_EXP_EN bit, D31:F0:Reg A0[10], + /// to globally enable the setting of the PCI_EXP_STS bit by a PCI Express* PME event. + /// + Data16Or = MmioRead16 (LpcBase + R_PCH_LPC_GEN_PMCON_1); + if ((Data16Or & B_PCH_LPC_GEN_PMCON_BIOS_PCI_EXP_EN) == 0) { + Data16And = 0xFFFF; + Data16Or = B_PCH_LPC_GEN_PMCON_BIOS_PCI_EXP_EN; + MmioOr16 (LpcBase + R_PCH_LPC_GEN_PMCON_1, Data16Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (LpcBase + R_PCH_LPC_GEN_PMCON_1), + &Data16Or, // Data to be ORed + &Data16And // Data to be ANDed + ); + } + } + + if (RootPortConfig->HotPlug) { + /// + /// PCH BIOS Spec Rev 0.5.0 section 8.8.2.1 + /// Step 1 + /// Clear following status bits, by writing 1b to them, in the Slot + /// Status register at offset 1Ah of PCI Express Capability structure: + /// Attention Button Pressed (bit0) + /// Presence Detect Changed (bit3) + /// + Data16And = 0xFFFF; + Data16Or = (BIT3 | BIT0); + MmioOr16 (RPBase + CapOffset + 0x1A, Data16Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RPBase + CapOffset + 0x1A), + &Data16Or, // Data to be ORed + &Data16And // Data to be ANDed + ); + /// + /// Step 2 + /// Program the following bits in Slot Control register at offset 18h + /// of PCI Express* Capability structure: + /// Attention Button Pressed Enable (bit0) = 1b + /// Presence Detect Changed Enable (bit3) = 1b + /// Hot Plug Interrupt Enable (bit5) = 0b + /// + Data16And = (UINT16) (~BIT5); + Data16Or = (BIT3 | BIT0); + MmioAndThenOr16 (RPBase + CapOffset + 0x18, Data16And, Data16Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (RPBase + CapOffset + 0x18), + &Data16Or, // Data to be ORed + &Data16And // Data to be ANDed + ); + /// + /// Step 3 + /// Program Misc Port Config (MPC) register at PCI config space offset + /// D8h as follows: + /// Hot Plug SCI Enable (HPCE, bit30) = 1b + /// Hot Plug SMI Enable (HPME, bit1) = 0b + /// + Data32And = (UINT32) (~B_PCH_PCIE_MPC_HPME); + Data32Or = B_PCH_PCIE_MPC_HPCE; + MmioAndThenOr32 (RPBase + R_PCH_PCIE_MPC, Data32And, Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_MPC), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + /// + /// Step 4 + /// Clear GPE0 Register (PMBase+20h), bit1, HOT_PLUG_STS by writing 1 + /// + if (PchSeries == PchLp) { + IoWrite32 (PmBase + R_PCH_ACPI_GPE0_STS_127_96, (UINT32) B_PCH_ACPI_GPE0_STS_127_96_HOT_PLUG); + } else if (PchSeries == PchH) { + IoWrite32 (PmBase + R_PCH_ACPI_GPE0a_STS, (UINT32) B_PCH_ACPI_GPE0a_STS_HOT_PLUG); + } + + /// + /// PCH BIOS Spec Rev 0.5.0 section 8.9 + /// BIOS should mask the reporting of Completion timeout (CT) errors byerrors by setting + /// the uncorrectable Error Mask register D28:F0~7:Reg 108h[14]. + /// + Data32And = 0xFFFFFFFF; + Data32Or = B_PCH_PCIE_UEM_CT; + MmioOr32 (RPBase + R_PCH_PCIE_UEM, Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_UEM), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + } + + if (DeviceFound == TRUE || (RootPortConfig->HotPlug == PCH_DEVICE_ENABLE)) { + return EFI_SUCCESS; + } else { + return EFI_NOT_FOUND; + } +} + +/** + This is the function to enable the clock gating for PCI Express ports. + + @param[in] BusNumber The Bus Number of the PCH device + @param[in] PchPlatformPolicy PCH Platform Policy protocol + @param[in] RpEnableMask Bit Mask indicating the enabled root ports + @param[in] RpHiddenMask Bit Mask indicating the root ports used for other > x1 root ports + @param[in] RootComplexBar Root complex base address + + @retval EFI_SUCCESS Successfully completed. +**/ +EFI_STATUS +PcieEnableClockGating ( + IN UINT8 BusNumber, + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RpEnableMask, + IN UINT32 RpHiddenMask, + IN UINT32 RootComplexBar, + IN UINT32 NandPort + ) +{ + UINTN RPBase; + UINT32 PortIndex; + UINT8 Data8Or; + UINT8 Data8And; + UINT32 Data32Or; + UINT32 Data32And; + UINT16 GpioBase; + BOOLEAN ClkreqPerPortSupported; + PCH_SERIES PchSeries; + + PchSeries = GetPchSeries(); + GpioBase = 0; + + /// + /// PCH BIOS Spec Rev 0.5.0, section 19.10 Enabling Clock Gating + /// 2.1 + /// For each enabled PCI Express* root port, program D28:F0~F7:Reg E1h[1:0] to 3h to enable dynamic clock gating. + /// System BIOS also require to set D28:F0~F7:Reg E8h[0] = 1b + /// 2.2 + /// Additionally, if port 0 is in x2 mode, these bits should not be set for port 1. + /// Likewise, if port 0 is in x4 mode, these bits should not be set for ports 1, 2, or 3 + /// + for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex++) { + ClkreqPerPortSupported = FALSE; + if (PchSeries == PchLp) { + GpioBase = MmioRead16 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_GPIO_BASE) + ) & B_PCH_LPC_GPIO_BASE_BAR; + Data32Or = (IoRead32 ((UINTN) (GpioBase + R_PCH_GP_X_CONFIG0(18 + PortIndex))) & B_PCH_GPIO_OWN0_GPIO_USE_SEL); + if (Data32Or == 0) { + ClkreqPerPortSupported = TRUE; + } + } + if (((RpEnableMask & (1 << PortIndex)) != 0) && ((RpHiddenMask & (1 << PortIndex)) == 0)) { + RPBase = MmPciAddress ( + 0, + BusNumber, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + GetPchPcieRpfn (RootComplexBar, (UINT8) PortIndex), + 0 + ); + + Data8Or = B_PCH_PCIE_RPDCGEN_RPDLCGEN | B_PCH_PCIE_RPDCGEN_RPDBCGEN; + Data8And = 0xFF; + MmioOr8 ( + RPBase + R_PCH_PCIE_RPDCGEN, + Data8Or + ); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN), + &Data8Or, // Data to be ORed + &Data8And // Data to be ANDed + ); + + if (PchSeries == PchLp) { + /// + /// 2.3 + /// Program D28:F0~F5:E2h[6] to 1b + /// + Data8Or = B_PCH_PCIE_RPPGEN_PTOTOP; + Data8And = (UINT8)~B_PCH_PCIE_RPPGEN_PTOTOP; + MmioOr8 ( + RPBase + R_PCH_PCIE_RPPGEN, + Data8Or + ); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (RPBase + R_PCH_PCIE_RPPGEN), + &Data8Or, // Data to be ORed + &Data8And // Data to be ANDed + ); + + /// + /// 2.4 + /// Program D28:F0~F5:E8h[3:2] to 10b before setting D28:F0~F5:E8h[1:0] + /// + Data8Or = BIT3; + Data8And = (UINT8)~(V_PCH_PCIE_PECR1_FIELD_3); + MmioAndThenOr8 ( + RPBase + R_PCH_PCIE_PECR1, + Data8And, + Data8Or + ); + } + + Data32And = 0xFFFFFFFF; + Data32Or = (UINT32) BIT0; + MmioOr32 (RPBase + R_PCH_PCIE_PECR1, Data32Or); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_PECR1), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + /// + /// Step 2.6 + /// Set B0:D28:F0~F7 + 324h[5] = 1b + /// + MmioOr32 (RPBase + R_PCH_PCIE_PEETM, (UINT32) (BIT5)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_PEETM), + 1, + (VOID *) (UINTN) (RPBase + R_PCH_PCIE_PEETM) + ); +//for Denlow SVR, refer Inel doc 493798, c state communication +#ifdef PCH_DENLOW_SERVER_SUPPORT + /// Set B0:D28:F0~F7 + 324h[3] = 1b + /// + MmioOr32 (RPBase + R_PCH_PCIE_PEETM, (UINT32) (BIT3)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_PEETM), + 1, + (VOID *) (UINTN) (RPBase + R_PCH_PCIE_PEETM) + ); +#endif + } + + if (PchSeries == PchLp) { + /// + /// Program D28:F0~F5:E2h[5:4] to 11b prior to function disable the port + /// Program D28:F0~F5:420h[31] to 1b prior to function disable the port + /// + if ((RpEnableMask & (1 << PortIndex)) == 0) { + RPBase = MmPciAddress ( + 0, + BusNumber, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + GetPchPcieRpfn (RootComplexBar, (UINT8) PortIndex), + 0 + ); + Data8Or = (B_PCH_PCIE_RPPGEN_LMSDOCGE | B_PCH_PCIE_RPPGEN_SEOCGE); + Data8And = (UINT8)~(B_PCH_PCIE_RPPGEN_LMSDOCGE | B_PCH_PCIE_RPPGEN_SEOCGE); + MmioOr8 ( + RPBase + R_PCH_PCIE_RPPGEN, + Data8Or + ); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (RPBase + R_PCH_PCIE_RPPGEN), + &Data8Or, // Data to be ORed + &Data8And // Data to be ANDed + ); + Data32Or = (B_PCH_PCIE_PCIEPMECTL_FDPGE); + Data32And = (UINT32)~(B_PCH_PCIE_PCIEPMECTL_FDPGE); + MmioOr32 ( + RPBase + R_PCH_PCIE_PCIEPMECTL, + Data32Or + ); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_PCIEPMECTL), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + } + /// + /// Program D28:F0~F5:420h[30:29] to 111b + /// + if (ClkreqPerPortSupported) { + RPBase = MmPciAddress ( + 0, + BusNumber, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + GetPchPcieRpfn (RootComplexBar, (UINT8) PortIndex), + 0 + ); + Data32Or = (B_PCH_PCIE_PCIEPMECTL_DLSULPGE | B_PCH_PCIE_PCIEPMECTL_DLSULDLSD); + Data32And = (UINT32)~(B_PCH_PCIE_PCIEPMECTL_DLSULPGE | B_PCH_PCIE_PCIEPMECTL_DLSULDLSD); + MmioOr32 ( + RPBase + R_PCH_PCIE_PCIEPMECTL, + Data32Or + ); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (RPBase + R_PCH_PCIE_PCIEPMECTL), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + } + } + } + + if (PchSeries == PchLp) { + /// + /// PCH BIOS Spec Rev 0.5.0, section 19.10 + /// Step 2.4 + /// Program D28:F0,F4&F5:Reg E1h[5:2] to 1111b + /// Program D28:F0,F4&F5:Reg E1h[7] to 1b + /// + for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex ++) { + if ((PortIndex == 0 || PortIndex == 4 || PortIndex == 5) && !(NandPort & (0x1 << PortIndex))) { + RPBase = MmPciAddress ( + 0, + BusNumber, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + GetPchPcieRpfn (RootComplexBar, (UINT8) PortIndex), + 0 + ); + Data8Or = + ( + B_PCH_PCIE_RPDCGEN_LCLKREQEN | + B_PCH_PCIE_RPDCGEN_BBCLKREQEN | + B_PCH_PCIE_RPDCGEN_SRDLCGEN | + B_PCH_PCIE_RPDCGEN_SRDBCGEN + ); + + MmioOr8 (RPBase + R_PCH_PCIE_RPDCGEN, Data8Or); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN), + 1, + (VOID *) (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN) + ); + + /// + /// PCH BIOS Spec Rev 0.5.0, section 19.10 + /// Step 2.5 + /// If PCIe root ports 0-3 are all disabled, set B0:D28:F0 + E2h [0] = 1b and E1h [7] = 1b. + /// If PCIe root port 4 is disabled, set B0:D28:F4 + E2h [0] = 1b and E1h [7] = 1b. + /// If PCIe root port 5 is disabled, set B0:D28:F5 + E2h [0] = 1b and E1h [7] = 1b. + /// + if (((!(RpEnableMask & 0xF)) && (PortIndex == 0)) || ((!(RpEnableMask & (0x1 << PortIndex))) && (PortIndex >= 4))) { + MmioOr8 ((RPBase + 0xE2), BIT0); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (RPBase + 0xE2), + 1, + (VOID *) (UINTN) (RPBase + 0xE2) + ); + + MmioOr8 (RPBase + R_PCH_PCIE_RPDCGEN, B_PCH_PCIE_RPDCGEN_RPSCGEN); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN), + 1, + (VOID *) (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN) + ); + } + } + } + /// + /// Additional steps + /// If all PCIe root ports are disabled, set B0:D28:F0 + E1h[6] to 1b + /// + if ((RpEnableMask & 0x3F) == 0) { + RPBase = MmPciAddress ( + 0, + BusNumber, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + GetPchPcieRpfn(RootComplexBar, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1), + 0 + ); + MmioOr8 ( + RPBase + R_PCH_PCIE_RPDCGEN, + B_PCH_PCIE_RPDCGEN_POCGE + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN), + 1, + (VOID *) (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN) + ); + } + } + if (PchSeries == PchH) { + /// + /// PCH BIOS Spec Rev 0.5.5, section 19.10 + /// Step 2.3 + /// Program D28:F0&F4:Reg E1h[5:2] to 1111b + /// + for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex += 4) { + if (((RpHiddenMask & (1 << PortIndex)) == 0) && !(NandPort & (0x1 << PortIndex))) { + RPBase = MmPciAddress ( + 0, + BusNumber, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + GetPchPcieRpfn (RootComplexBar, (UINT8) PortIndex), + 0 + ); + Data8Or = + ( + B_PCH_PCIE_RPDCGEN_LCLKREQEN | + B_PCH_PCIE_RPDCGEN_BBCLKREQEN | + B_PCH_PCIE_RPDCGEN_SRDLCGEN | + B_PCH_PCIE_RPDCGEN_SRDBCGEN + ); + MmioOr8 (RPBase + R_PCH_PCIE_RPDCGEN, Data8Or); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN), + 1, + (VOID *) (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN) + ); + /// + /// PCH BIOS Spec Rev 0.5.5, section 19.10 + /// Step 2.4 + /// If PCIe root ports 0-3 are all disabled, set B0:D28:F0 + E2h [0] = 1b and E1h [7] = 1b. + /// If PCIe root ports 4-7 are all disabled, set B0:D28:F4 + E2h [0] = 1b and E1h [7] = 1b. + /// + if (!(RpEnableMask & (0xF << PortIndex))) { + MmioOr8 ((RPBase + 0xE2), BIT0); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (RPBase + 0xE2), + 1, + (VOID *) (UINTN) (RPBase + 0xE2) + ); + + MmioOr8 (RPBase + R_PCH_PCIE_RPDCGEN, B_PCH_PCIE_RPDCGEN_RPSCGEN); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN), + 1, + (VOID *) (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN) + ); + } + } + } + } + + return EFI_SUCCESS; +} diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchSata.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchSata.c new file mode 100644 index 0000000..56021ca --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchSata.c @@ -0,0 +1,1547 @@ +/** @file + Configures PCH Sata Controller + +@copyright + Copyright (c) 2008 - 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#include "PchInit.h" + + +EFI_STATUS +ConfigureSataAhci ( + DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + UINT32 RootComplexBar, + UINT16 GpioBase + ); + +EFI_STATUS +ConfigureSataSpeedIde ( + DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + UINTN PciDevFuncRegBase, + UINTN MaxPorts + ); + +EFI_STATUS +DisableSataController ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN OUT UINT32 *FuncDisableReg + ); + +/** + Configures PCH Sata Controller + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in, out] FuncDisableReg Function Disable Register + @param[in] GpioBase GPIO base address of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ConfigureSata ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar, + IN OUT UINT32 *FuncDisableReg, + IN UINT16 GpioBase + ) +{ + EFI_STATUS Status; + UINT32 Index; + UINT16 WordReg; + UINT16 SataGcReg; + UINTN PciD31F2RegBase; + PCH_SATA_CONFIG *SataConfig; + UINT16 SataPortsEnabled; + UINT16 SataModeSelect; + UINTN PciD31F5RegBase; + UINTN PciDevFuncRegBase; + UINTN MaxPorts; + UINT32 Data32And; + UINT32 Data32Or; + PCH_SERIES PchSeries; + + DEBUG ((EFI_D_INFO, "ConfigureSata() Start\n")); + + PchSeries = GetPchSeries(); + SataConfig = PchPlatformPolicy->SataConfig; + PciD31F2RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 2, 0); + PciD31F5RegBase = 0; + if (PchSeries == PchH) { + PciD31F5RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 5, 0); + } + SataModeSelect = MmioRead16 (PciD31F2RegBase + R_PCH_SATA_MAP) & B_PCH_SATA_MAP_SMS_MASK; + Status = EFI_SUCCESS; + + /// + /// Check to disable SATA controller + /// + if (PchPlatformPolicy->DeviceEnabling->Sata == PCH_DEVICE_DISABLE) { + Status = DisableSataController (PchPlatformPolicy, FuncDisableReg); + return Status; + } + + /// + /// PCH BIOS Spec Rev 0.5.0 section 14.1.7 Additional Programming Requirements during + /// SATA Initialization + /// Step 12 + /// Program D31:F2:9Ch[5] to 1b (Note: this must be programmed together with D31:F2:9Ch[7:6] + /// in word write) + /// + SataGcReg = MmioRead16 (PciD31F2RegBase + R_PCH_SATA_SCLKGC); + SataGcReg |= BIT5; + + switch (SataModeSelect) { +#ifdef TRAD_FLAG + case V_PCH_SATA_MAP_SMS_IDE: + if (PchSeries == PchH) { + /// + /// Set Native IDE decoding + /// + /// PCH BIOS Spec Rev 0.5.0 Section 14.1.3 Set the Programming Interface + /// Using native IDE is only possible when the SATA controller is operating in IDE mode. + /// The programming interface is selected by setting the programming interface register + /// (PI = Reg: 09h) appropriately. There are two native mode enabling bits in the + /// PI register to control the primary and secondary channels of SATA1. + /// + /// Only D31:F2 needs to be set. D31:F5 is readonly + /// + if (SataConfig->LegacyMode == PCH_DEVICE_ENABLE) { + MmioAnd8 ( + PciD31F2RegBase + R_PCH_SATA_PI_REGISTER, + (UINT8)~(B_PCH_SATA_PI_REGISTER_PNE | B_PCH_SATA_PI_REGISTER_SNE) + ); + } else { + MmioOr8 ( + PciD31F2RegBase + R_PCH_SATA_PI_REGISTER, + (UINT8) B_PCH_SATA_PI_REGISTER_PNE | B_PCH_SATA_PI_REGISTER_SNE + ); + } + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_PI_REGISTER), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_PI_REGISTER) + ); + MmioOr16 ((UINTN) (PciD31F5RegBase + R_PCH_SATA_TIMP), (UINT16) (B_PCH_SATA_TIM_IDE)); + WordReg = MmioRead16 (PciD31F5RegBase + R_PCH_SATA_TIMP); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD31F5RegBase + R_PCH_SATA_TIMP), + 1, + &WordReg + ); + MmioOr16 ((UINTN) (PciD31F5RegBase + R_PCH_SATA_TIMS), (UINT16) (B_PCH_SATA_TIM_IDE)); + WordReg = MmioRead16 (PciD31F5RegBase + R_PCH_SATA_TIMS); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD31F5RegBase + R_PCH_SATA_TIMS), + 1, + &WordReg + ); + } + break; +#endif // TRAD_FLAG + + case V_PCH_SATA_MAP_SMS_RAID: + /// + /// When RAID alternate ID is enabled, the Device ID will change to 30XX from 282X in RAID mode + /// + if (SataConfig->RaidAlternateId == PCH_DEVICE_ENABLE) { + SataGcReg &= ~B_PCH_SATA_SCLKGC_AIES; + SataGcReg |= B_PCH_SATA_SCLKGC_AIE; + } +#ifdef PCH_SVR_WS_SKU + SataGcReg &= ~B_PCH_SATA_SCLKGC_AIE; + SataGcReg |= B_PCH_SATA_SCLKGC_AIES; +#endif + break; + } + /// + /// Unconditional write is necessary to lock the register + /// + MmioWrite16 (PciD31F2RegBase + R_PCH_SATA_SCLKGC, SataGcReg); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_SCLKGC), + 1, + &SataGcReg + ); + + /// + /// Set legacy IDE decoding + /// These bits also effect with AHCI mode when PCH is using legacy mechanisms. + /// + MmioOr16 ((UINTN) (PciD31F2RegBase + R_PCH_SATA_TIMP), (UINT16) (B_PCH_SATA_TIM_IDE)); + WordReg = MmioRead16 (PciD31F2RegBase + R_PCH_SATA_TIMP); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_TIMP), + 1, + &WordReg + ); + + MmioOr16 ((UINTN) (PciD31F2RegBase + R_PCH_SATA_TIMS), (UINT16) (B_PCH_SATA_TIM_IDE)); + WordReg = MmioRead16 (PciD31F2RegBase + R_PCH_SATA_TIMS); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_TIMS), + 1, + &WordReg + ); + /// + /// PCH BIOS Spec Rev 0.5.0, section 19.10 + /// Step 4.2 + /// D31:F2 PCS: Enable the port in any of below condition: + /// Hot plug is enabled + /// A device is attached + /// Test mode is enabled + /// Configured as eSATA port + /// + SataPortsEnabled = 0; + WordReg = MmioRead16 (PciD31F2RegBase + R_PCH_SATA_PCS); + for (Index = 0; Index < GetPchMaxSataPortNum (); Index++) { + if ((SataConfig->PortSettings[Index].HotPlug == PCH_DEVICE_ENABLE) || + (WordReg & (BIT0 << (8 + Index))) || + (SataConfig->TestMode == PCH_DEVICE_ENABLE) || + (SataConfig->PortSettings[Index].External == PCH_DEVICE_ENABLE)) { + SataPortsEnabled |= (SataConfig->PortSettings[Index].Enable << Index); + } + } + if (PchSeries == PchH) { + /// + /// D31:F5 PCS: Enable the port in any of below condition: + /// Hot plug is enabled + /// A device is attached + /// Test mode is enabled + /// + /// Note: In IDE mode, SATA Port 4/5 enable status needs to be checked before setting D31:F2 MAP[13:8]. + /// It's because: + /// (1) SataPortsEnabled [5:4] will be set while it is configured as eSATA port that is not + /// supported in IDE mode. + /// (2) D31:F2 MAP[12] setting needs to sync up with D31:F5 MAP[8] setting. + /// D31:F2 MAP[13] setting needs to sync up with D31:F5 MAP[9] setting. + /// + if (SataModeSelect == V_PCH_SATA_MAP_SMS_IDE) { + /// + /// Clear SataPortsEnabled [5:4] before checking SATA Port 4/5 enable status + /// + SataPortsEnabled &= ~(BIT5 | BIT4); + WordReg = MmioRead16 (PciD31F5RegBase + R_PCH_SATA_PCS); + for (Index = 4; Index < GetPchMaxSataPortNum (); Index++) { + /// + /// D31:F5 PCS[9:8] = Port 4/5 Present bit + /// + if ((SataConfig->PortSettings[Index].HotPlug == PCH_DEVICE_ENABLE) || + (WordReg & (BIT0 << (4 + Index))) || + (SataConfig->TestMode == PCH_DEVICE_ENABLE)) { + /// + /// SataPortsEnabled [5:4] = Sata Port 4/5 enable status + /// + SataPortsEnabled |= (SataConfig->PortSettings[Index].Enable << Index); + } + } + } + } + + /// + /// Set MAP register for PCH H + /// Set D31:F2 MAP[13:8] to 1b if SATA Port 0/1/2/3/4/5 is disabled + /// SataPortsEnabled [5:0] = Sata Port 0/1/2/3/4/5 enable status + /// MAP.SPD (D31:F2:Reg90h[13:8]) is Write Once + /// + /// Set MAP register for PCH LP + /// Set D31:F2 MAP[11:8] to 1b if SATA Port 0/1/2/3 is disabled + /// SataPortsEnabled [3:0] = Sata Port 0/1/2/3 enable status + /// MAP.SPD (D31:F2:Reg90h[11:8]) is Write Once + /// + switch (PchSeries) { + case PchLp: + MmioOr16 ((UINTN) (PciD31F2RegBase + R_PCH_SATA_MAP), ((~SataPortsEnabled << 8) & (UINT16) B_PCH_LP_SATA_MAP_SPD)); + break; + + case PchH: + MmioOr16 ((UINTN) (PciD31F2RegBase + R_PCH_SATA_MAP), ((~SataPortsEnabled << 8) & (UINT16) B_PCH_H_SATA_MAP_SPD)); + break; + + default: + break; + } + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_MAP), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_MAP) + ); + + // + // D31:F2 PCS[5:0] = Port 0~5 Enabled bit + // as per SataPortsEnabled value. + // + MmioOr16 ((UINTN) (PciD31F2RegBase + R_PCH_SATA_PCS), (UINT16) (SataPortsEnabled)); + + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_PCS), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_PCS) + ); + +#ifdef TRAD_FLAG + if (PchSeries == PchH) { + /// + /// Set D31:F5 MAP[9:8] and D31:F5 PCS[1:0] + /// + if (SataModeSelect == V_PCH_SATA_MAP_SMS_IDE) { + /// + /// Set D31:F5 MAP[9:8] to 1b if SATA Port 4/5 is disabled + /// SataPortsEnabled [5:4] = Sata Port 4/5 enable status + /// MAP.SPD (D31:F5:Reg90h[9:8]) is Write Once + /// + MmioOr16 ((UINTN) (PciD31F5RegBase + R_PCH_SATA_MAP), ((~SataPortsEnabled << 4) & (UINT16) B_PCH_SATA2_MAP_SPD)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD31F5RegBase + R_PCH_SATA_MAP), + 1, + (VOID *) (UINTN) (PciD31F5RegBase + R_PCH_SATA_MAP) + ); + /// + /// D31:F5 PCS[1:0] = Port 4/5 Enabled bit + /// + MmioAndThenOr16 ( + (UINTN) (PciD31F5RegBase + R_PCH_SATA_PCS), + (UINT16) (~(B_PCH_SATA2_PCS_PORT5_EN | B_PCH_SATA2_PCS_PORT4_EN)), + (UINT16) (SataPortsEnabled >> 4) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD31F5RegBase + R_PCH_SATA_PCS), + 1, + (VOID *) (UINTN) (PciD31F5RegBase + R_PCH_SATA_PCS) + ); + } + } +#endif // TRAD_FLAG + /// + /// PCH BIOS Spec Rev 0.5.0, section 19.10 + /// Step 4.2 + /// After configuring Port and Control Status (PCS) Register Port x Enabled (PxE) bits accordingly, + /// wait 1.4 micro second + /// + PchPmTimerStall (0x02); + SCRIPT_STALL (EFI_ACPI_S3_RESUME_SCRIPT_TABLE, 0x02); + + /// + /// After programming the PCS.PxE, check if it is zero. + /// If no port enabled, terminate the SATA configuration and disable the SATA controller. + /// + WordReg = MmioRead16 ((UINTN) (PciD31F2RegBase + R_PCH_SATA_PCS)); + WordReg &= (UINT16) ((1 << GetPchMaxSataPortNum ()) - 1); +#ifdef TRAD_FLAG + if (WordReg == 0) { + if ((PchSeries == PchH) && (SataModeSelect == V_PCH_SATA_MAP_SMS_IDE)) { + WordReg = MmioRead16 ((UINTN) (PciD31F5RegBase + R_PCH_SATA_PCS)); + WordReg &= (UINT16) (B_PCH_SATA2_PCS_PORT5_EN | + B_PCH_SATA2_PCS_PORT4_EN); + } + } +#endif // TRAD_FLAG + if (WordReg == 0) { + Status = DisableSataController (PchPlatformPolicy, FuncDisableReg); + return Status; + } + + if (PchSeries == PchLp) { + /// + /// If Listen Mode support is not required, program D31:F2:98h[24] to 1b. + /// + if ((SataConfig->PortSettings[0].HotPlug == PCH_DEVICE_DISABLE) && + (SataConfig->PortSettings[1].HotPlug == PCH_DEVICE_DISABLE) && + (SataConfig->PortSettings[2].HotPlug == PCH_DEVICE_DISABLE) && + (SataConfig->PortSettings[3].HotPlug == PCH_DEVICE_DISABLE)) { + MmioOr32 ((UINTN) (PciD31F2RegBase + 0x98), (UINT32) (BIT24)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F2RegBase + 0x98), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + 0x98) + ); + } + } + + /// + /// Configure AHCI + /// + if (PchSeries == PchLp) { + if (SataModeSelect != V_PCH_SATA_MAP_SMS_LOOBACK_TESTMODE) { + Status = ConfigureSataAhci (PchPlatformPolicy, RootComplexBar, GpioBase); + } + } else if (PchSeries == PchH) { + if (SataModeSelect != V_PCH_SATA_MAP_SMS_IDE) { + Status = ConfigureSataAhci (PchPlatformPolicy, RootComplexBar, GpioBase); + } else { + /// + /// If it is IDE mode + /// + if(PchPlatformPolicy->SataConfig->SpeedSupport != PchSataSpeedSupportDefault){ + PciDevFuncRegBase = 0; + MaxPorts = 0; + for (Index = 0; Index < GetPchMaxSataControllerNum (); Index++) { + switch (Index) { + case 0: + PciDevFuncRegBase = PciD31F2RegBase; + MaxPorts = PCH_IDE_1_MAX_PORTS; + break; + + case 1: + PciDevFuncRegBase = PciD31F5RegBase; + MaxPorts = PCH_IDE_2_MAX_PORTS; + break; + } + Status = ConfigureSataSpeedIde (PchPlatformPolicy, PciDevFuncRegBase, MaxPorts); + } + } + } + } + /// + /// PCH BIOS Spec Rev 0.5.0, section 19.10 + /// Step 4.1 + /// Set bits D31:F2:Reg 94h[29:24] to 3Fh as part of the chipset initialization and before disabling the + /// SATA function if the SATA interface is not supported. BIOS can also set PCD bits for the un-routed ports + /// on the platform to disable clocks for the unused ports + /// Set the PCD [port x] = 1 if the corresponding PCS.PxE = 0 (either have a device attached or have + /// hot plug enabled) + /// + for (Index = 0; Index < GetPchMaxSataPortNum (); Index++) { + if ((SataPortsEnabled & (B_PCH_SATA_PCS_PORT0_EN << Index)) == 0) { + MmioOr32 ((UINTN) (PciD31F2RegBase + R_PCH_SATA_SCLKCG), (UINT32) (B_PCH_SATA_SCLKCG_PORT0_PCD << Index)); + } + } + + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_SCLKCG), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_SCLKCG) + ); + /// + /// PCH BIOS Spec Rev 0.5.6, 14.1.6 Power Optimizer Configuration + /// System BIOS must execute the following steps as part of System BIOS initialization + /// of the PCH SATA controller on both cold boot (G3/S5) and S3/S4 resume path. Please + /// refer to the PCH EDS, section 14.1.35.1 for the SATA initialization settings and + /// the actual register indexes/values to be programmed. + /// + if (PchPlatformPolicy->PwrOptConfig->PchPwrOptSata == PCH_DEVICE_ENABLE) { + /// + /// Step 1 + /// Set D31:F2 + SIR Index 64h[31:0] = 883C9001h + /// + MmioWrite8 (PciD31F2RegBase + R_PCH_SATA_SIRI, 0x64); + if (PchSeries == PchH) { + MmioWrite32 (PciD31F2RegBase + R_PCH_SATA_STRD, 0x883C9001); + } + if (PchSeries == PchLp) { + MmioWrite32 (PciD31F2RegBase + R_PCH_SATA_STRD, 0x883C9003); + } + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD) + ); + /// + /// Step 2 + /// Set D31:F2 + SIR Index 68h[15:0] = 880Ah + /// + MmioWrite8 (PciD31F2RegBase + R_PCH_SATA_SIRI, 0x68); + Data32And = 0xFFFF0000; + Data32Or = 0x0000880A; + MmioAndThenOr32 ( + (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), + Data32And, + Data32Or + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD) + ); + /// + /// Step 3 + /// Set D31:F2 + SIR Index 60h[3] = 1b + /// + MmioWrite8 (PciD31F2RegBase + R_PCH_SATA_SIRI, 0x60); + Data32And = 0xFFFFFFF7; + Data32Or = 0x00000008; + MmioAndThenOr32 ( + (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), + Data32And, + Data32Or + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD) + ); + /// + /// Step 4 + /// Set D31:F2 + SIR Index 60h[0] = 1b + /// + MmioWrite8 (PciD31F2RegBase + R_PCH_SATA_SIRI, 0x60); + Data32And = 0xFFFFFFFE; +//for Denlow SVR, refer Inel doc 493798, c state communication +#ifdef PCH_DENLOW_SERVER_SUPPORT + /// Set D31:F2 + SIR Index 60h[0] = 0b + Data32Or = 0x00000000; +#else + Data32Or = 0x00000001; +#endif + MmioAndThenOr32 ( + (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), + Data32And, + Data32Or + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD) + ); + /// + /// Step 5 + /// Set D31:F2 + SIR Index 60h[1] = 1b + /// + MmioWrite8 (PciD31F2RegBase + R_PCH_SATA_SIRI, 0x60); + Data32And = 0xFFFFFFFD; + Data32Or = 0x00000002; + MmioAndThenOr32 ( + (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), + Data32And, + Data32Or + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI) + ); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD) + ); + } + +#ifdef TRAD_FLAG + /// + /// For dual controller IDE mode, disable the individual controller if no port enabled. + /// For SATA2, the SATA configuration should be done through SATA1. + /// Therefore, disabling the SATA1/SATA2 after finishing SATA configuration. + /// + if (PchSeries == PchH) { + if (SataModeSelect == V_PCH_SATA_MAP_SMS_IDE) { + WordReg = MmioRead16 (PciD31F5RegBase + R_PCH_SATA_PCS); + WordReg &= (UINT16) (B_PCH_SATA2_PCS_PORT5_EN | + B_PCH_SATA2_PCS_PORT4_EN); + if (WordReg == 0) { + *FuncDisableReg |= B_PCH_RCRB_FUNC_DIS_SATA2; + } + WordReg = MmioRead16 (PciD31F2RegBase + R_PCH_SATA_PCS); + WordReg &= (UINT16) (B_PCH_SATA_PCS_PORT3_EN | + B_PCH_SATA_PCS_PORT2_EN | + B_PCH_SATA_PCS_PORT1_EN | + B_PCH_SATA_PCS_PORT0_EN); + if (WordReg == 0) { + *FuncDisableReg |= B_PCH_RCRB_FUNC_DIS_SATA1; + } + } + } +#endif // TRAD_FLAG + + DEBUG ((EFI_D_INFO, "ConfigureSata() End\n")); + + return Status; +} + +/** + Program the Max speed suported in each ports while in IDE mode. + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance. + @param[in] PciDevFuncRegBase Pci B/D/F/Reg Base for the Sata controler. + @param[in] MaxPorts Max Sata ports supported in the Controller. + + @retval EFI_SUCESS The function exited sucessfully + @retval EFI_OUT_OF_RESOURCES Insufficient resources are available +**/ +EFI_STATUS +ConfigureSataSpeedIde ( + DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + UINTN PciDevFuncRegBase, + UINTN MaxPorts + ) +{ + EFI_STATUS Status; +#ifdef TRAD_FLAG + PCH_SATA_CONFIG *SataConfig; + EFI_PHYSICAL_ADDRESS IoBaseAddress; + UINT16 SidpBa; + UINT16 SidpBaSaveRestore; + UINT16 DevCmdSaveRestore; + UINT8 Data8; + UINT16 Data16; + UINTN PortIndex; + + Data16 = 0; + Data8 = 0; + + SataConfig = PchPlatformPolicy->SataConfig; + + Status = gDS->AllocateIoSpace ( + EfiGcdAllocateAnySearchBottomUp, + EfiGcdIoTypeIo, + N_PCH_SATA_SIDP_BAR_ALIGNMENT, + V_PCH_SATA_SIDP_BAR_LENGTH, + &IoBaseAddress, + mImageHandle, + NULL + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + /// + /// Set the SIDP BAR + /// + SidpBa = (UINT16) IoBaseAddress; + SidpBaSaveRestore = MmioRead16 (PciDevFuncRegBase + R_PCH_SATA_SIDP_BAR); + MmioWrite16 (PciDevFuncRegBase + R_PCH_SATA_SIDP_BAR, SidpBa); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciDevFuncRegBase + R_PCH_SATA_SIDP_BAR), + 1, + &SidpBa + ); + /// + /// Enable command register I/O space decoding + /// + DevCmdSaveRestore = MmioRead16 (PciDevFuncRegBase + R_PCH_SATA_COMMAND); + MmioOr16 ((UINTN) (PciDevFuncRegBase + R_PCH_SATA_COMMAND), (UINT16) B_PCH_SATA_COMMAND_IOSE); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciDevFuncRegBase + R_PCH_SATA_COMMAND), + 1, + (VOID *) (UINTN) (PciDevFuncRegBase + R_PCH_SATA_COMMAND) + ); + /// + /// Configure for the max speed support 1.5Gb/s, 3.0Gb/s and 6.0Gb/s. + /// + for (PortIndex = 0; PortIndex < MaxPorts; PortIndex++) { + switch (PortIndex) { + case 0: + Data16 = V_PCH_SATA_AHCI_SINDX_RIDX_SCTL | V_PCH_SATA_AHCI_SINDX_PIDX_PORT0; + break; + + case 1: + Data16 = V_PCH_SATA_AHCI_SINDX_RIDX_SCTL | V_PCH_SATA_AHCI_SINDX_PIDX_PORT1; + break; + + case 2: + Data16 = V_PCH_SATA_AHCI_SINDX_RIDX_SCTL | V_PCH_SATA_AHCI_SINDX_PIDX_PORT2; + break; + + case 3: + Data16 = V_PCH_SATA_AHCI_SINDX_RIDX_SCTL | V_PCH_SATA_AHCI_SINDX_PIDX_PORT3; + break; + } + + IoWrite16 ((UINTN) (SidpBa + R_PCH_SATA_SIDPBA_SINDX), Data16); + SCRIPT_IO_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (SidpBa + R_PCH_SATA_SIDPBA_SINDX), + 1, + &Data16 + ); + + switch (SataConfig->SpeedSupport) { + case PchSataSpeedSupportGen1: + Data8 = V_PCH_SATA_SIDPBA_SDATA_GEN1; + break; + + case PchSataSpeedSupportGen2: + Data8 = V_PCH_SATA_SIDPBA_SDATA_GEN2; + break; + + case PchSataSpeedSupportGen3: + Data8 = V_PCH_SATA_SIDPBA_SDATA_GEN3; + break; + } + + IoWrite8 ((UINTN) (SidpBa + R_PCH_SATA_SIDPBA_SDATA), Data8); + SCRIPT_IO_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (SidpBa + R_PCH_SATA_SIDPBA_SDATA), + 1, + &Data8 + ); + Data16 = MmioRead16 ((UINTN) (PciDevFuncRegBase + R_PCH_SATA_PCS)) >> 8; + if(((Data16 >> PortIndex) & BIT0)){ + Data8 = (IoRead8 (SidpBa + R_PCH_SATA_SIDPBA_SDATA) & ~B_PCH_SATA_SIDPBA_SCTL_DET) + V_PCH_SATA_SIDPBA_SCTL_DET_COMRST; + IoWrite8 ((UINTN) (SidpBa + R_PCH_SATA_SIDPBA_SDATA), Data8); + SCRIPT_IO_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (SidpBa + R_PCH_SATA_SIDPBA_SDATA), + 1, + &Data8 + ); + PchPmTimerStall (1000); + SCRIPT_STALL (EFI_ACPI_S3_RESUME_SCRIPT_TABLE, 1000); + Data8 = (IoRead8 (SidpBa + R_PCH_SATA_SIDPBA_SDATA) & ~B_PCH_SATA_SIDPBA_SCTL_DET) + V_PCH_SATA_SIDPBA_SCTL_DET_NOINT; + IoWrite8 ((UINTN) (SidpBa + R_PCH_SATA_SIDPBA_SDATA), Data8); + SCRIPT_IO_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (SidpBa + R_PCH_SATA_SIDPBA_SDATA), + 1, + &Data8 + ); + } + } + /// + /// Restore command register I/O space decoding + /// + MmioWrite16 (PciDevFuncRegBase + R_PCH_SATA_COMMAND, DevCmdSaveRestore); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciDevFuncRegBase + R_PCH_SATA_COMMAND), + 1, + &DevCmdSaveRestore + ); + /// + /// Restore the SIDP BAR + /// + MmioWrite16 (PciDevFuncRegBase + R_PCH_SATA_SIDP_BAR, SidpBaSaveRestore); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciDevFuncRegBase + R_PCH_SATA_SIDP_BAR), + 1, + &SidpBaSaveRestore + ); + /// + /// Free allocated resources + /// + gDS->FreeIoSpace (IoBaseAddress, (UINT64) V_PCH_SATA_SIDP_BAR_LENGTH); +#else + Status = EFI_SUCCESS; +#endif // TRAD_FLAG + + return Status; +} + +/** + Program AHCI PI register for Enabled ports + Handle hotplug, and interlock switch setting, + and config related GPIOs. + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar value of this PCH device + @param[in] GpioBase GPIO base address of this PCH device + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ConfigureSataAhci ( + DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + UINT32 RootComplexBar, + UINT16 GpioBase + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS MemBaseAddress; + UINT32 AhciBar; + UINT32 CapRegister; + UINT32 Data32And; + UINT32 Data32Or; + UINT32 DwordReg; + UINT32 PxCMDRegister; + UINT16 SataPortsEnabled; + UINT8 Index; + UINTN PciD31F2RegBase; + UINT16 WordReg; + UINT8 ByteReg; + PCH_SATA_CONFIG *SataConfig; + UINT16 SataModeSelect; + PCH_SERIES PchSeries; + UINT8 SataResetGpio[LPTH_AHCI_MAX_PORTS] = { + PCH_GPIO_SATA_PORT0_RESET, + PCH_GPIO_SATA_PORT1_RESET, + PCH_GPIO_SATA_PORT2_RESET, + PCH_GPIO_SATA_PORT3_RESET, + PCH_GPIO_SATA_PORT4_RESET, + PCH_GPIO_SATA_PORT5_RESET, + }; + + UINT16 SataResetLpGpio[LPTLP_AHCI_MAX_PORTS] = { + PCH_LP_GPIO_SATA_PORT0_RESET, + PCH_LP_GPIO_SATA_PORT1_RESET, + PCH_LP_GPIO_SATA_PORT2_RESET, + PCH_LP_GPIO_SATA_PORT3_RESET, + }; + + DEBUG ((EFI_D_INFO, "ConfigureSataAhci() Start\n")); + PchSeries = GetPchSeries(); + SataConfig = PchPlatformPolicy->SataConfig; + PciD31F2RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 2, 0); + SataModeSelect = MmioRead16 (PciD31F2RegBase + R_PCH_SATA_MAP) & B_PCH_SATA_MAP_SMS_MASK; + DwordReg = 0; + + /// + /// Allocate the AHCI BAR + /// + MemBaseAddress = 0x0ffffffff; + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateMaxAddressSearchBottomUp, + EfiGcdMemoryTypeMemoryMappedIo, + N_PCH_SATA_AHCI_BAR_ALIGNMENT, // 2^11: 2K Alignment + V_PCH_SATA_AHCI_BAR_LENGTH, // 2K Length + &MemBaseAddress, + mImageHandle, + NULL + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + /// + /// Set the AHCI BAR + /// + AhciBar = (UINT32) MemBaseAddress; + MmioWrite32 (PciD31F2RegBase + R_PCH_SATA_AHCI_BAR, AhciBar); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_AHCI_BAR), + 1, + &AhciBar + ); + + /// + /// Enable command register memory space decoding + /// + MmioOr16 ((UINTN) (PciD31F2RegBase + R_PCH_SATA_COMMAND), (UINT16) B_PCH_SATA_COMMAND_MSE); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_COMMAND), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_COMMAND) + ); + + /// + /// Assert if the memory data of AhciBar is invalid. + /// + ASSERT (MmioRead32 (AhciBar) != 0xFFFFFFFF); + + /// + /// Get Port Settings + /// + SataPortsEnabled = MmioRead16 ((UINTN) (PciD31F2RegBase + R_PCH_SATA_PCS)); + if (PchSeries == PchH) { + SataPortsEnabled &= (UINT16) (B_PCH_SATA_PCS_PORT5_EN | + B_PCH_SATA_PCS_PORT4_EN | + B_PCH_SATA_PCS_PORT3_EN | + B_PCH_SATA_PCS_PORT2_EN | + B_PCH_SATA_PCS_PORT1_EN | + B_PCH_SATA_PCS_PORT0_EN ); + } else if (PchSeries == PchLp) { + SataPortsEnabled &= (UINT16) (B_PCH_SATA_PCS_PORT3_EN | + B_PCH_SATA_PCS_PORT2_EN | + B_PCH_SATA_PCS_PORT1_EN | + B_PCH_SATA_PCS_PORT0_EN ); + } + + /// + /// Read the default value of the Host Capabilites Register + /// NOTE: many of the bits in this register are R/WO (Read/Write Once) + /// + CapRegister = MmioRead32 (AhciBar + R_PCH_SATA_AHCI_CAP); + CapRegister &= (UINT32)~(B_PCH_SATA_AHCI_CAP_SIS | B_PCH_SATA_AHCI_CAP_SSS | B_PCH_SATA_AHCI_CAP_SALP | + B_PCH_SATA_AHCI_CAP_PMS | B_PCH_SATA_AHCI_CAP_SSC | B_PCH_SATA_AHCI_CAP_PSC | + B_PCH_SATA_AHCI_CAP_SXS); + if (PchSeries == PchLp) { + CapRegister &= (UINT32)~(B_PCH_SATA_AHCI_CAP_SAM); + } + + for (Index = 0; Index < GetPchMaxSataPortNum (); Index++) { + /// + /// Check PCS.PxE to know if the SATA Port x is disabled. + /// + if ((SataPortsEnabled & (B_PCH_SATA_PCS_PORT0_EN << Index)) == 0) { + continue; + } + if (PchSeries == PchLp) { + /// + /// Program AhciBar + 0h[18] = 1b + /// + CapRegister |= B_PCH_SATA_AHCI_CAP_SAM; + } + + if (SataConfig->PortSettings[Index].InterlockSw == PCH_DEVICE_ENABLE) { + /// + /// Mechanical Presence Switch is Enabled for at least one of the ports + /// + CapRegister |= B_PCH_SATA_AHCI_CAP_SIS; + } + + if ((SataConfig->PortSettings[Index].SpinUp == PCH_DEVICE_ENABLE) || + (SataConfig->PortSettings[Index].External == PCH_DEVICE_ENABLE)) { + /// + /// PCH BIOS Spec Rev 0.5.0, Section 14.1.4 Initialize Registers in AHCI Memory-Mapped Space + /// Step 1.4 + /// Set SSS (ABAR + 00h[27]) to enable SATA controller supports staggered + /// spin-up on its ports, for use in balancing power spikes + /// SATA Port Spin up is supported at least one of the ports + /// If this is an extra eSATA port. It needs to be hotpluggable but it's usually empty anyway + /// so LPM is not available but Listen Mode is available, so it will have good power management. + /// If Sata Test Mode enabled, then uncoditonally clear SSS (ABAR + 00h[27]) + /// to resolve Spin-donw issue with the test equiepment + /// + if (SataConfig->TestMode == PCH_DEVICE_ENABLE ) { + CapRegister &= ~B_PCH_SATA_AHCI_CAP_SSS; + } else { + CapRegister |= B_PCH_SATA_AHCI_CAP_SSS; + } + } + + if (SataConfig->PortSettings[Index].External == PCH_DEVICE_ENABLE) { + /// + /// External SATA is supported at least one of the ports + /// + CapRegister |= B_PCH_SATA_AHCI_CAP_SXS; + } + } + /// + /// Enable Enabled SATA ports, + /// If BIOS accesses any of the port specific AHCI address range before setting PI bit, + /// BIOS is required to read the PI register before the initial write to the PI register. + /// NOTE: many of the bits in this register are R/WO (Read/Write Once) + /// + Data32And = (UINT32) (~B_PCH_H_SATA_PORT_MASK); + if (PchSeries == PchLp) { + Data32And = (UINT32) (~B_PCH_LP_SATA_PORT_MASK); + } + Data32Or = (UINT32) (SataPortsEnabled); + MmioAndThenOr32 ( + (UINTN) (AhciBar + R_PCH_SATA_AHCI_PI), + Data32And, + Data32Or + ); + SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (AhciBar + R_PCH_SATA_AHCI_PI), + &Data32Or, // Data to be ORed + &Data32And // Data to be ANDed + ); + /// + /// After BIOS issues initial write to this register, BIOS is requested to issue two + /// reads to this register. + /// + Data32Or = MmioRead32 (AhciBar + R_PCH_SATA_AHCI_PI); + SCRIPT_MEM_POLL ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (AhciBar + R_PCH_SATA_AHCI_PI), + &Data32Or, // BitMask + &Data32Or, // BitValue + 1, // Duration + 1 // LoopTimes + ); + SCRIPT_MEM_POLL ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (AhciBar + R_PCH_SATA_AHCI_PI), + &Data32Or, // BitMask + &Data32Or, // BitValue + 1, // Duration + 1 // LoopTimes + ); + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 14.1.4 Initialize Registers in AHCI Memory-Mapped Space + /// Step 1 + /// For Lynx Point + /// Set PSC (ABAR + 00h[13]). This bit informs the Windows software driver that the AHCI + /// Controller supports the partial low-power state. + /// Set SSC (ABAR + 00h[14]). This bit informs the Windows software driver that the AHCI + /// Controller supports the slumber low-power state. + /// Set SALP (ABAR + 00h[26]) to enable Aggressive Link Power Management (LPM) support. + /// + CapRegister |= (B_PCH_SATA_AHCI_CAP_SSC | B_PCH_SATA_AHCI_CAP_PSC); + + if (SataConfig->SalpSupport == PCH_DEVICE_ENABLE) { + CapRegister |= B_PCH_SATA_AHCI_CAP_SALP; + } + /// + /// Support Command List Override & PIO Multiple DRQ Block + /// + CapRegister |= (B_PCH_SATA_AHCI_CAP_SCLO | B_PCH_SATA_AHCI_CAP_PMD); + + /// + /// Configure for the max speed support 1.5Gb/s, 3.0Gb/s and 6.0Gb/s. + /// + CapRegister &= ~B_PCH_SATA_AHCI_CAP_ISS_MASK; + + switch (SataConfig->SpeedSupport) { + case PchSataSpeedSupportGen1: + CapRegister |= (V_PCH_SATA_AHCI_CAP_ISS_1_5_G << N_PCH_SATA_AHCI_CAP_ISS); + break; + + case PchSataSpeedSupportGen2: + CapRegister |= (V_PCH_SATA_AHCI_CAP_ISS_3_0_G << N_PCH_SATA_AHCI_CAP_ISS); + break; + + case PchSataSpeedSupportGen3: + case PchSataSpeedSupportDefault: + CapRegister |= (V_PCH_SATA_AHCI_CAP_ISS_6_0_G << N_PCH_SATA_AHCI_CAP_ISS); + break; + } + /// + /// Update the Host Capabilites Register and save for S3 resume + /// NOTE: Many of the bits in this register are R/WO (Read/Write Once) + /// + MmioWrite32 (AhciBar + R_PCH_SATA_AHCI_CAP, CapRegister); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (AhciBar + R_PCH_SATA_AHCI_CAP), + 1, + &CapRegister + ); + + if (PchSeries == PchLp) { + /// + /// Set ABAR + 24h[5] to 1b + /// Set ABAR + 24h[4:2] to 111b + /// + Data32Or = B_PCH_SATA_AHCI_CAP2_DESO; + Data32Or |= B_PCH_SATA_AHCI_CAP2_SDS | B_PCH_SATA_AHCI_CAP2_SADM | B_PCH_SATA_AHCI_CAP2_APST; + MmioOr32 (AhciBar + R_PCH_SATA_AHCI_CAP2, Data32Or); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (AhciBar + R_PCH_SATA_AHCI_CAP2), + 1, + (VOID *) (UINTN) (AhciBar + R_PCH_SATA_AHCI_CAP2) + ); + } + + /// + /// Port[Max:0] Command Register update + /// NOTE: this register must be updated after Port Implemented and Capabilities register, + /// Many of the bits in this register are R/WO (Read/Write Once) + /// + for (Index = 0; Index < GetPchMaxSataPortNum (); Index++) { + /// + /// Check PCS.PxE to know if the SATA Port x is disabled. + /// + if ((SataPortsEnabled & (B_PCH_SATA_PCS_PORT0_EN << Index)) == 0) { + continue; + } + /// + /// Initial to zero first + /// + PxCMDRegister = 0; + + if (SataConfig->PortSettings[Index].HotPlug == PCH_DEVICE_ENABLE) { + if (SataConfig->PortSettings[Index].External == PCH_DEVICE_DISABLE) { + /// + /// Hot Plug of this port is enabled + /// + PxCMDRegister |= B_PCH_SATA_AHCI_PxCMD_HPCP; + if (SataConfig->PortSettings[Index].InterlockSw == PCH_DEVICE_ENABLE) { + /// + /// Mechanical Switch of this port is Attached + /// + PxCMDRegister |= B_PCH_SATA_AHCI_PxCMD_MPSP; + /// + /// Check the GPIO Pin is set as used for native function not a normal GPIO + /// + if (PchSeries == PchH) { + DwordReg = IoRead32 ( + (UINTN) + (GpioBase + R_PCH_GPIO_USE_SEL + + (SataResetGpio[Index] / 32 * (R_PCH_GPIO_USE_SEL2 - R_PCH_GPIO_USE_SEL)))); + DwordReg = (DwordReg & (1 << SataResetGpio[Index] % 32)); + } + + if (PchSeries == PchLp) { + DwordReg = IoRead32 ( + (UINTN) + (GpioBase + SataResetLpGpio[Index])); + DwordReg = (DwordReg & B_PCH_GPIO_OWN0_GPIO_USE_SEL); + } + + if(DwordReg != 0) { + if (PchSeries == PchH) { + DEBUG ((EFI_D_ERROR, + "BIOS must set the SATA%0xGP / GPIO%0d to native function if Inter Lock Switch is enabled!\n", + Index, + SataResetGpio[Index])); + ASSERT_EFI_ERROR (EFI_DEVICE_ERROR); + } + + if (PchSeries == PchLp) { + DEBUG ((EFI_D_ERROR, + "BIOS must set the SATA%0xGP / GPIO%0d to native function if Inter Lock Switch is enabled!\n", + Index, + SataResetLpGpio[Index])); + ASSERT_EFI_ERROR (EFI_DEVICE_ERROR); + } + } + } + } + } else { + /// + /// When "Mechanical Switch Attached to Port" (PxCMD[19]) is set, it is expected that HPCP (PxCMD[18]) is also set. + /// + if (SataConfig->PortSettings[Index].InterlockSw == PCH_DEVICE_ENABLE) { + DEBUG ((EFI_D_ERROR, "Hot-Plug function of Port%d should be enabled while the Inter Lock Switch of it is enabled!\n", + Index)); + } + } + + if (SataConfig->PortSettings[Index].External == PCH_DEVICE_ENABLE) { + PxCMDRegister |= B_PCH_SATA_AHCI_PxCMD_ESP; + } + + if (SataConfig->PortSettings[Index].SpinUp == PCH_DEVICE_ENABLE) { + PxCMDRegister |= B_PCH_SATA_AHCI_PxCMD_SUD; + } + + /// + /// eSATA port support only up to Gen2 + /// + if (SataConfig->PortSettings[Index].External == PCH_DEVICE_ENABLE) { + Data32And = (UINT32)~(B_PCH_SATA_AHCI_PXSCTL_SPD); + Data32Or = (V_PCH_SATA_AHCI_PXSCTL_SPD_2); + if (PchSeries == PchLp) { + Data32And = (UINT32)~(B_PCH_SATA_AHCI_PXSCTL_SPD | B_PCH_SATA_AHCI_PXSCTL_IPM); + Data32Or = (V_PCH_SATA_AHCI_PXSCTL_SPD_2); + } + MmioAndThenOr32 ( + (UINTN) (AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index))), + Data32And, + Data32Or + ); + + DwordReg = MmioRead32 (AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index))); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index))), + 1, + &DwordReg + ); + } + + MmioAndThenOr32 ( + (UINTN) (AhciBar + (R_PCH_SATA_AHCI_P0CMD + (0x80 * Index))), + (UINT32)~(B_PCH_SATA_AHCI_PxCMD_MASK), + (UINT32) PxCMDRegister + ); + DwordReg = MmioRead32 (AhciBar + (R_PCH_SATA_AHCI_P0CMD + (0x80 * Index))); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (AhciBar + (R_PCH_SATA_AHCI_P0CMD + (0x80 * Index))), + 1, + &DwordReg + ); + if ((PchSeries == PchLp)) { + /// + /// Set ABAR + 144h[1], ABAR + 1C4h[1], ABAR + 244h[1], ABAR + 2C4[1] to 0b as default + /// Board rework is required to enable DevSlp. + /// POR settings are ABAR + 144h[1], ABAR + 1C4h[1], ABAR + 244h[1] = 1b, ABAR + 2C4[1] to 0b + /// + if (SataConfig->PortSettings[Index].DevSlp == PCH_DEVICE_ENABLE) { + Data32And = (UINT32)~(B_PCH_SATA_AHCI_PxDEVSLP_DITO_MASK | B_PCH_SATA_AHCI_PxDEVSLP_DM_MASK); + Data32Or = (B_PCH_SATA_AHCI_PxDEVSLP_DSP | V_PCH_SATA_AHCI_PxDEVSLP_DM_16 | V_PCH_SATA_AHCI_PxDEVSLP_DITO_625); + if (SataConfig->PortSettings[Index].EnableDitoConfig == PCH_DEVICE_ENABLE) { + Data32Or &= Data32And; + Data32Or |= ((SataConfig->PortSettings[Index].DitoVal << 15) | (SataConfig->PortSettings[Index].DmVal << 25)); + } + MmioAndThenOr32 ( + (UINTN) (AhciBar + (R_PCH_SATA_AHCI_P0DEVSLP + (0x80 * Index))), + Data32And, + Data32Or + ); + } else { + MmioAnd32 ( + (UINTN) (AhciBar + (R_PCH_SATA_AHCI_P0DEVSLP + (0x80 * Index))), + (UINT32) ~(B_PCH_SATA_AHCI_PxDEVSLP_DSP) + ); + } + DwordReg = MmioRead32 (AhciBar + (R_PCH_SATA_AHCI_P0DEVSLP + (0x80 * Index))); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (AhciBar + (R_PCH_SATA_AHCI_P0DEVSLP + (0x80 * Index))), + 1, + &DwordReg + ); + } + + /// + /// eSATA port support only up to Gen2. + /// Save and restore Port Speed limitation + /// + if (SataConfig->PortSettings[Index].External == PCH_DEVICE_ENABLE) { + ByteReg = MmioRead8 (AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index))); + ByteReg &= (UINT8) ~(B_PCH_SATA_AHCI_PXSCTL_SPD); + ByteReg |= (UINT8) V_PCH_SATA_AHCI_PXSCTL_SPD_2; + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINTN) (AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index))), + 1, + &ByteReg + ); + } + } + if ((PchSeries == PchLp)) { + /// + /// DevSlp on Port 0 and Port 3 are mutual exclusive. Assert if otherwise. + /// + ASSERT (!((SataConfig->PortSettings[0].DevSlp) && (SataConfig->PortSettings[3].DevSlp))); + if ((SataConfig->PortSettings[0].DevSlp == PCH_DEVICE_DISABLE) && + (SataConfig->PortSettings[3].DevSlp == PCH_DEVICE_ENABLE)) { + MmioOr32 ( + (UINTN) (PciD31F2RegBase + R_PCH_SATA_SCLKCG), + (UINT32) B_PCH_SATA_SCLKCG_POP3_DEVSLP + ); + DwordReg = MmioRead32 (PciD31F2RegBase + R_PCH_SATA_SCLKCG); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_SCLKCG), + 1, + &DwordReg + ); + } + } + /// + /// PCH BIOS Spec Rev 0.5.0, Section 14.1.5.2 Enable Flexible RAID OROM Features + /// Lynx Point with RAID capable sku is able to customize the RAID features through setting the + /// Intel RST Feature Capabilities (RSTF) register before loading the RAID Option ROM. The RAID + /// OROM will enable the desired features based on the setting in that register, please refer to + /// PCH EDS for more details. + /// For example, if the platform desired features are RAID0, RAID1, RAID5, RAID10 and + /// RST Smart Storage caching. System BIOS should set RSTF (ABAR + C8h [15:0]) to 022Fh before + /// loading RAID OROM. + /// + WordReg = 0; + + if (SataConfig->HddUnlock == PCH_DEVICE_ENABLE) { + /// + /// If set to "1", indicates that the HDD password unlock in the OS is enabled + /// while SATA is configured as RAID mode. + /// + WordReg |= B_PCH_SATA_AHCI_RSTF_HDDLK; + } + + if (SataConfig->LedLocate == PCH_DEVICE_ENABLE) { + /// + /// If set to "1", indicates that the LED/SGPIO hardware is attached and ping to + /// locate feature is enabled on the OS while SATA is configured as RAID mode. + /// + WordReg |= B_PCH_SATA_AHCI_RSTF_LEDL; + } + + if (SataModeSelect == V_PCH_SATA_MAP_SMS_RAID) { + if (SataConfig->Raid0 == PCH_DEVICE_ENABLE) { + /// + /// If set to "1", then RAID0 is enabled in Flexible RAID Option ROM. + /// + WordReg |= B_PCH_SATA_AHCI_RSTF_R0E; + } + + if (SataConfig->Raid1 == PCH_DEVICE_ENABLE) { + /// + /// If set to "1", then RAID1 is enabled in FD-OROM. + /// + WordReg |= B_PCH_SATA_AHCI_RSTF_R1E; + } + + if (SataConfig->Raid10 == PCH_DEVICE_ENABLE) { + /// + /// If set to "1", then RAID10 is enabled in FD-OROM. + /// + WordReg |= B_PCH_SATA_AHCI_RSTF_R10E; + } + + if (SataConfig->Raid5 == PCH_DEVICE_ENABLE) { + /// + /// If set to "1", then RAID5 is enabled in FD-OROM. + /// + WordReg |= B_PCH_SATA_AHCI_RSTF_R5E; + } + + if (SataConfig->Irrt == PCH_DEVICE_ENABLE) { + /// + /// If set to "1", then Intel Rapid Recovery Technology is enabled. + /// + WordReg |= B_PCH_SATA_AHCI_RSTF_RSTE; + } + + if (SataConfig->OromUiBanner == PCH_DEVICE_ENABLE) { + /// + /// If set to "1" then the OROM UI is shown. Otherwise, no OROM banner or information + /// will be displayed if all disks and RAID volumes are Normal. + /// + WordReg |= B_PCH_SATA_AHCI_RSTF_IRSTOROM; + } + + if (SataConfig->IrrtOnly == PCH_DEVICE_ENABLE) { + /// + /// If set to "1", then only IRRT volumes can span internal and eSATA drives. If cleared + /// to "0", then any RAID volume can span internal and eSATA drives. + /// + WordReg |= B_PCH_SATA_AHCI_RSTF_IROES; + } + /// + /// Enable the RST Smart Storage caching bit to support Smart Storage caching. + /// + if (SataConfig->SmartStorage == PCH_DEVICE_ENABLE) { + WordReg |= B_PCH_SATA_AHCI_RSTF_SEREQ; + } + /// + /// Program the delay of the OROM UI Splash Screen in a normal status. + /// + WordReg |= (UINT16) (SataConfig->OromUiDelay << N_PCH_SATA_AHCI_RSTF_OUD); + } + /// + /// RSTF(RST Feature Capabilities) is a Write-Once register. + /// + MmioWrite16 ((UINTN) (AhciBar + R_PCH_SATA_AHCI_RSTF), WordReg); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (AhciBar + R_PCH_SATA_AHCI_RSTF), + 1, + &WordReg + ); + + /// + /// Set Ahci Bar to zero + /// + AhciBar = 0; + MmioWrite32 (PciD31F2RegBase + R_PCH_SATA_AHCI_BAR, AhciBar); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_AHCI_BAR), + 1, + &AhciBar + ); + + /// + /// Free the GCD pool + /// + gDS->FreeMemorySpace ( + MemBaseAddress, + V_PCH_SATA_AHCI_BAR_LENGTH + ); + DEBUG ((EFI_D_INFO, "ConfigureSataAhci() End\n")); + return EFI_SUCCESS; +} + +/** + Disable Sata Controller + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in, out] FuncDisableReg Function Disable Register + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +DisableSataController ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN OUT UINT32 *FuncDisableReg + ) +{ + UINTN PciD31F2RegBase; + UINTN PciD31F5RegBase; + UINT16 SataModeSelect; + PCH_SERIES PchSeries; + + PciD31F2RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 2, 0); + PciD31F5RegBase = 0; + SataModeSelect = MmioRead16 (PciD31F2RegBase + R_PCH_SATA_MAP) & B_PCH_SATA_MAP_SMS_MASK; + PchSeries = GetPchSeries(); + +#ifdef ULT_FLAG + if (PchSeries == PchLp) { + /// + /// PCH BIOS Spec Rev 0.5.0, Section 14.2 SATA Controller Disabling + /// Step 1 + /// Set D31:F2:92h [3:0] to 0000b + /// + MmioAnd16 (PciD31F2RegBase + R_PCH_SATA_PCS, + (UINT16) ~(B_PCH_SATA_PCS_PORT0_EN | B_PCH_SATA_PCS_PORT1_EN | B_PCH_SATA_PCS_PORT2_EN | + B_PCH_SATA_PCS_PORT3_EN)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_PCS), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_PCS) + ); + /// + /// Step 3 + /// Set Sata Port Clock Disable bits D31:F2:94h[27:24] to Fh + /// + MmioOr32 ((UINTN) (PciD31F2RegBase + R_PCH_SATA_SCLKCG), + (UINT32) (B_PCH_SATA_SCLKCG_PORT0_PCD | B_PCH_SATA_SCLKCG_PORT1_PCD | B_PCH_SATA_SCLKCG_PORT2_PCD | + B_PCH_SATA_SCLKCG_PORT3_PCD)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_SCLKCG), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_SCLKCG) + ); + /// + /// Step 4 + /// Disabling SATA Device by programming RCBA + 3418h [2][25] + /// + *FuncDisableReg |= B_PCH_RCRB_FUNC_DIS_SATA1; + } +#endif // ULT_FLAG +#ifdef TRAD_FLAG + if (PchSeries == PchH) { + PciD31F5RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 5, 0); + /// + /// PCH BIOS Spec Rev 0.5.0, Section 14.2 SATA Controller Disabling + /// Step 1 + /// Set D31:F2:92h [5:0] to 000000b + /// + MmioAnd16 (PciD31F2RegBase + R_PCH_SATA_PCS, + (UINT16) ~(B_PCH_SATA_PCS_PORT0_EN | B_PCH_SATA_PCS_PORT1_EN | B_PCH_SATA_PCS_PORT2_EN | + B_PCH_SATA_PCS_PORT3_EN | B_PCH_SATA_PCS_PORT4_EN | B_PCH_SATA_PCS_PORT5_EN)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_PCS), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_PCS) + ); + if (SataModeSelect == V_PCH_SATA_MAP_SMS_IDE) { + /// + /// Step 2 + /// Set D31:F5:92h [1:0] to 00b if SATA is in IDE mode + /// + MmioAnd16 (PciD31F5RegBase + R_PCH_SATA_PCS, + (UINT16) ~(B_PCH_SATA_PCS_PORT0_EN | B_PCH_SATA_PCS_PORT1_EN)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (PciD31F5RegBase + R_PCH_SATA_PCS), + 1, + (VOID *) (UINTN) (PciD31F5RegBase + R_PCH_SATA_PCS) + ); + } + /// + /// Step 3 + /// Set Sata Port Clock Disable bits D31:F2:94h[29:24] to 3Fh + /// + MmioOr32 ((UINTN) (PciD31F2RegBase + R_PCH_SATA_SCLKCG), + (UINT32) (B_PCH_SATA_SCLKCG_PORT0_PCD | B_PCH_SATA_SCLKCG_PORT1_PCD | B_PCH_SATA_SCLKCG_PORT2_PCD | + B_PCH_SATA_SCLKCG_PORT3_PCD | B_PCH_SATA_SCLKCG_PORT4_PCD | B_PCH_SATA_SCLKCG_PORT5_PCD)); + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (PciD31F2RegBase + R_PCH_SATA_SCLKCG), + 1, + (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_SCLKCG) + ); + /// + /// Step 4 + /// Disabling SATA Device by programming RCBA + 3418h [2][25] + /// + *FuncDisableReg |= B_PCH_RCRB_FUNC_DIS_SATA1; + *FuncDisableReg |= B_PCH_RCRB_FUNC_DIS_SATA2; + } +#endif // TRAD_FLAG + + return EFI_SUCCESS; +} diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchSerialIo.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchSerialIo.c new file mode 100644 index 0000000..16e23a6 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchSerialIo.c @@ -0,0 +1,997 @@ +/** @file + Initializes the PCH Serial IO Controllers. + +@copyright + Copyright (c) 2012 - 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#include "PchInit.h" + +#ifdef SERIAL_IO_FLAG +#include "PchAslUpdateLib.h" + +#include EFI_PROTOCOL_DEPENDENCY (AcpiTable) + + + +#define SERIAL_IO_ADDRESS_AREA 0xFE101000; + +// +// Resource Group Header +// +typedef struct { + UINT32 ResourceGroupLength; + UINT32 VendorId; + UINT32 SubVendorId; + UINT16 DeviceId; + UINT16 SubDeviceId; + UINT16 Revision; + UINT16 Reserved; + UINT32 SharedInfoLength; +} EFI_ACPI_5_0_CSRT_RESOURCE_GROUP_HEADER; + +// +// Resource Group1 Share Info +// +typedef struct { + UINT16 MajorVersion1; + UINT16 MinorVersion0; + UINT32 MmioBaseL; + UINT32 MmioBaseH; + UINT32 InterruptGSI; + UINT8 InterruptPolarity; + UINT8 InterruptMode; + UINT8 NumberofChannels; + UINT8 DMAAddressWidth; + UINT16 BaseRequestLine; + UINT16 NumberofHandshakeSignals; + UINT32 MaximumBlockTransferSize; +} EFI_ACPI_5_0_RESOURCE_GROUP1_SHARED_INFO; + +// +// Resource Descriptor Header +// +typedef struct { + UINT32 ResourceDescriptorLength; + UINT16 ResourceType; + UINT16 ResourceSubType; + UINT32 UID; +} EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER; + +// +// Core System Resources Table Structure (CSRT) +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + EFI_ACPI_5_0_CSRT_RESOURCE_GROUP_HEADER ResourceGroup1; + EFI_ACPI_5_0_RESOURCE_GROUP1_SHARED_INFO ResourceGroup1SharedInfo; + EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER ControllerResourceDescriptor1; + EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER ChannelResourceDescriptor1[8]; +} EFI_ACPI_5_0_CORE_SYSTEM_RESOURCES_TABLE; + +typedef enum { + INDEX_DMA, + INDEX_I2C0, + INDEX_I2C1, + INDEX_SPI0, + INDEX_SPI1, + INDEX_UART0, + INDEX_UART1, + INDEX_SDIO, + MAX_SIO_INDEX +} SIO_DEVICE; + +typedef struct { + UINT8 DevNum; + UINT8 FuncNum; + UINT32 DisableAddr; + UINT32 AcpiSwitchAddr; + UINT32 DeviceModeSwitchBit; // turns device into ACPI mode by hiding its PCI config space + UINT32 IrqModeSwitchBit; // turns device's interrupts into ACPI mode + UINT32 Signature; + UINT8 IrqPin; + UINT32 Bar0; + UINT32 Bar1; +} SERIAL_IO_DEVICE_DESCRIPTOR; + +#define SERIAL_IO_DEVICE_QUANTITY 8 + +SERIAL_IO_DEVICE_DESCRIPTOR SerialIoDevice [SERIAL_IO_DEVICE_QUANTITY] = +{ {21, 0, 0xCE00AA07, 0xCB000240, BIT20, BIT21, EFI_SIGNATURE_32('S','D','M','A'), 2, 0xFE101000, 0xFE102000}, + {21, 1, 0xCE00AA47, 0xCB000248, BIT20, BIT21, EFI_SIGNATURE_32('I','2','C','0'), 3, 0xFE103000, 0xFE104000}, + {21, 2, 0xCE00AA87, 0xCB000250, BIT20, BIT21, EFI_SIGNATURE_32('I','2','C','1'), 3, 0xFE105000, 0xFE106000}, + {21, 3, 0xCE00AAC7, 0xCB000258, BIT20, BIT21, EFI_SIGNATURE_32('S','P','I','0'), 3, 0xFE107000, 0xFE108000}, + {21, 4, 0xCE00AB07, 0xCB000260, BIT20, BIT21, EFI_SIGNATURE_32('S','P','I','1'), 3, 0xFE109000, 0xFE10A000}, + {21, 5, 0xCE00AB47, 0xCB000268, BIT20, BIT21, EFI_SIGNATURE_32('U','A','0','0'), 4, 0xFE10B000, 0xFE10C000}, + {21, 6, 0xCE00AB87, 0xCB000270, BIT20, BIT21, EFI_SIGNATURE_32('U','A','0','1'), 4, 0xFE10D000, 0xFE10E000}, + {23, 0, 0xCE00AE07, 0xCB000000, BIT4, BIT5, EFI_SIGNATURE_32('S','D','H','C'), 1, 0xFE110000, 0xFE112000} +}; + +EFI_STATUS +InstallDmaAcpiTable ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy +); + +BOOLEAN IsSerialIoDeviceEnabled ( + SIO_DEVICE Device + ) +{ + UINTN RegBase; + UINT32 VendorDeviceId; + + RegBase = MmPciAddress (0, 0, SerialIoDevice[Device].DevNum, SerialIoDevice[Device].FuncNum, 0); + VendorDeviceId = MmioRead32 (RegBase + R_PCH_LP_SERIAL_IO_VENDOR_ID); + if (VendorDeviceId == 0xFFFFFFFF) { + return FALSE; + } else { + return TRUE; + } +} + +/** + Disable Serial IO Controllers based on PchPlatformPolicy. + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar address of this PCH device + + @retval None +**/ +VOID +DisableSerialIoControllers ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ) +{ + UINT8 FunctionEnable[SERIAL_IO_DEVICE_QUANTITY]; + UINTN Address; + UINT8 i; + BOOLEAN Func0Missing; + + // + // Higher functions of a PCI device can't exist if there's no Function0 + // This issue only applies in PCI mode, not in ACPI. + // + Func0Missing = PchPlatformPolicy->DeviceEnabling->SerialIoDma == PCH_DEVICE_DISABLE && + PchPlatformPolicy->SerialIoConfig->SerialIoMode == PchSerialIoIsPci; + + // + // DMA is useless without at least one SerialIo device + // + FunctionEnable[INDEX_DMA] = PchPlatformPolicy->DeviceEnabling->SerialIoDma && + ( PchPlatformPolicy->DeviceEnabling->SerialIoI2c0 || + PchPlatformPolicy->DeviceEnabling->SerialIoI2c1 || + PchPlatformPolicy->DeviceEnabling->SerialIoSpi0 || + PchPlatformPolicy->DeviceEnabling->SerialIoSpi1 || + PchPlatformPolicy->DeviceEnabling->SerialIoUart0 || + PchPlatformPolicy->DeviceEnabling->SerialIoUart1 || + PchPlatformPolicy->DeviceEnabling->SerialIoSdio ); + + FunctionEnable[INDEX_I2C0] = PchPlatformPolicy->DeviceEnabling->SerialIoI2c0 && !Func0Missing; + FunctionEnable[INDEX_I2C1] = PchPlatformPolicy->DeviceEnabling->SerialIoI2c1 && !Func0Missing; + FunctionEnable[INDEX_SPI0] = PchPlatformPolicy->DeviceEnabling->SerialIoSpi0 && !Func0Missing; + FunctionEnable[INDEX_SPI1] = PchPlatformPolicy->DeviceEnabling->SerialIoSpi1 && !Func0Missing; + FunctionEnable[INDEX_UART0] = PchPlatformPolicy->DeviceEnabling->SerialIoUart0 && !Func0Missing; + FunctionEnable[INDEX_UART1] = PchPlatformPolicy->DeviceEnabling->SerialIoUart1 && !Func0Missing; + // + // SDIO doesn't care about DMA missing - it has its own device number + // + FunctionEnable[INDEX_SDIO] = PchPlatformPolicy->DeviceEnabling->SerialIoSdio; + + DEBUG ((EFI_D_INFO, "DisableSerialIoControllers() Start\n")); + + /// + /// PCH BIOS Spec Rev 0.7.0 Section 23.2 Disabling Serial IO Controllers + /// By default all controllers are enabled in hardware. + /// + + for (i = 0; i < SERIAL_IO_DEVICE_QUANTITY; i++) { + if (FunctionEnable[i] == PCH_DEVICE_DISABLE) { + /// + /// Step 1 + /// Set the Dx:Fx:84h[1:0] = 11b + /// + Address = MmPciAddress (0, 0, SerialIoDevice[i].DevNum, SerialIoDevice[i].FuncNum, R_PCH_LP_SERIAL_IO_PME_CTRL_STS); + MmioAndThenOr32WithScript(Address, (UINT32)~(B_PCH_LP_SERIAL_IO_PME_CTRL_STS_PWR_ST), BIT1 | BIT0 ); + /// + /// Step 2 + /// Program IOBP register CE00Axx7h[8] = 1b + /// + ProgramIobpWithScript (RootComplexBar, SerialIoDevice[i].DisableAddr, (UINT32)~(BIT8), BIT8); + } + } + + DEBUG ((EFI_D_INFO, "DisableSerialIoControllers() End\n")); +} + +UINT8 +GetSerialIoIrqNumber( + UINT8 DeviceNumber, + UINT8 InterruptPin, + UINT8 InterruptMode +) +{ + UINT32 IrqRoute; + UINT8 InterruptRoute; + UINT32 RootComplexBar; + UINT32 IrqRoutingRegister; + + if (InterruptMode == PchSerialIoIsAcpi) { + // + // ACPI IRQs are wired to irq pins 5,6,7,13 + // + switch(InterruptPin) { + case 0x1: + return 5; + break; + case 0x2: + return 6; + break; + case 0x3: + return 7; + break; + case 0x4: + return 13; + break; + case 0x0: + default: + return 0; + } + } else { + if(InterruptPin > 0) { + // + // PCI INTs are first routed to PIRQs according to R_PCH_RCRB_D21IR / R_PCH_RCRB_D23IR register + // + RootComplexBar = MmioRead32 ( + MmPciAddress (0, + 0, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_RCBA) + ) & B_PCH_LPC_RCBA_BAR; + + if (DeviceNumber == 21) { + IrqRoutingRegister = R_PCH_RCRB_D21IR; + } else if (DeviceNumber == 23) { + IrqRoutingRegister = R_PCH_RCRB_D23IR; + } else { + ASSERT(FALSE); + return 0; + } + IrqRoute = MmioRead32 (RootComplexBar + IrqRoutingRegister); + + InterruptRoute = ( IrqRoute >> (4* (InterruptPin-1) ) ) & 0x7; + + // + // ...and PIRQs are wired to irq pins 16..23 + // A 16, B 17, C 18, D 19, E 20, F 21, G 22, H 23 + // + return (InterruptRoute + 16); + } else { + return 0; + } + } +} + + +/** + Update ASL definitions for SerialIo devices. + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +UpdateSerialIoAcpiData ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ) +{ + + EFI_STATUS Status; + UINTN RegBase; + UINT32 Data32; + UINT16 GpioBase; + UINT8 i; + + Status = InitializePchAslUpdateLib(); + + if(EFI_ERROR(Status)) { + return Status; + } + + // + // ACPI code update for all devices + // + for (i=0; i<SERIAL_IO_DEVICE_QUANTITY; i++) { + + if (!IsSerialIoDeviceEnabled(i)) { + continue; + } + + RegBase = MmPciAddress (0, 0, SerialIoDevice[i].DevNum, SerialIoDevice[i].FuncNum, 0); + + Data32 = (MmioRead32(RegBase + R_PCH_LP_SERIAL_IO_BAR0) & B_PCH_LP_SERIAL_IO_BAR0_BAR); + UpdateResourceTemplateAslCode(SerialIoDevice[i].Signature, + EFI_SIGNATURE_32 ('R', 'B', 'U', 'F'), + AML_MEMORY32_FIXED_OP, + 1, + 0x04, + &Data32, + sizeof(Data32) + ); + } + + // + // Update GPIO device ACPI variables + // + RegBase = MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PCH_LPC, PCI_FUNCTION_NUMBER_PCH_LPC, 0); + + GpioBase = (MmioRead16(RegBase + R_PCH_LPC_GPIO_BASE) & B_PCH_LPC_GPIO_BASE_BAR); + + // + // Update _MIN[32:0] of the DWord Address Space Descriptor with GPIO BAR0 + // + Data32 = (UINT32)GpioBase; + UpdateResourceTemplateAslCode((EFI_SIGNATURE_32 ('G', 'P', 'I', '0')), + (EFI_SIGNATURE_32 ('R', 'B', 'U', 'F')), + AML_DWORD_OP, + 1, + 0x0A, + &Data32, + sizeof(Data32) + ); + + // + // Update _MAX[32:0] of the DWord Address Space Descriptor with GPIO BAR0 + 3FFh + // + Data32 = (UINT32)GpioBase + 0x3FF; + UpdateResourceTemplateAslCode((EFI_SIGNATURE_32 ('G', 'P', 'I', '0')), + (EFI_SIGNATURE_32 ('R', 'B', 'U', 'F')), + AML_DWORD_OP, + 1, + 0x0E, + &Data32, + sizeof(Data32) + ); + + + return Status; +} + +/** + Hide PCI config space of Serial IO Controllers and do any final initialization. + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +PutSerialIoInAcpiMode ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ) +{ + EFI_STATUS Status; + UINTN Bar1; + UINTN RegBase; + UINT32 Data32; + UINT32 Data32And; + UINT32 Data32Or; + UINT8 i; + + Status = EFI_SUCCESS; + + Status = InitializePchAslUpdateLib(); + + if(EFI_ERROR(Status)) { + return Status; + } + + // + // ACPI code update for all devices + // + for (i=0; i<SERIAL_IO_DEVICE_QUANTITY; i++) { + + if (!IsSerialIoDeviceEnabled(i)) { + continue; + } + + RegBase = MmPciAddress (0, 0, SerialIoDevice[i].DevNum, SerialIoDevice[i].FuncNum, 0); + + Data32 = (MmioRead32(RegBase + R_PCH_LP_SERIAL_IO_BAR1) & B_PCH_LP_SERIAL_IO_BAR1_BAR); + UpdateResourceTemplateAslCode(EFI_SIGNATURE_32 ('S', 'I', 'R', 'C'), + EFI_SIGNATURE_32 ('B', 'U', 'F', ('1'+i)), + AML_MEMORY32_FIXED_OP, + 1, + 0x04, + &Data32, + sizeof(Data32) + ); + + Data32 = GetSerialIoIrqNumber(SerialIoDevice[i].DevNum, SerialIoDevice[i].IrqPin, PchPlatformPolicy->SerialIoConfig->SerialIoInterruptMode); + UpdateResourceTemplateAslCode(SerialIoDevice[i].Signature, + EFI_SIGNATURE_32 ('R', 'B', 'U', 'F'), + AML_INTERRUPT_DESC_OP, + 1, + 0x05, + &Data32, + sizeof(UINT8) + ); + + } + + // + // Install DMA CSRT ACPI table as per ACPI5.0 spec + // + if(PchPlatformPolicy->DeviceEnabling->SerialIoDma == PCH_DEVICE_ENABLE) { + InstallDmaAcpiTable(PchPlatformPolicy); + } + + /// + /// PCH BIOS Spec Rev 0.7.0 Section 23.6 Enable Serial IO PCI Controllers ACPI Mode + /// + + for (i = 0; i < SERIAL_IO_DEVICE_QUANTITY; i++) { + /// + /// Check if SerialIo device is present + /// + if (!IsSerialIoDeviceEnabled(i)) { + continue; + } + + /// + /// Get BAR1 Address + /// + Bar1 = MmioRead32( + MmPciAddress (0, + PchPlatformPolicy->BusNumber, + SerialIoDevice[i].DevNum, + SerialIoDevice[i].FuncNum, + R_PCH_LP_SERIAL_IO_BAR1) + ) & B_PCH_LP_SERIAL_IO_BAR1_BAR; + + /// + /// Step 1 + /// Program Dx:Fx:04h[2:1] = 11b + /// (skipped - this was performed while assigning BARs) + /// + + /// + /// Step 2 + /// Program Dx:Fx to ACPI Mode + /// + Data32And = 0xFFFFFFFF; + Data32Or = SerialIoDevice[i].DeviceModeSwitchBit; + ProgramIobpWithScript (RootComplexBar, SerialIoDevice[i].AcpiSwitchAddr, Data32And, Data32Or); + + /// + /// Set D3Hot Power State via BAR1 Address, for all devices except DMA + /// + if(i != INDEX_DMA) { + Data32And = (UINT32) ~B_PCH_LP_SERIAL_IO_PME_CTRL_STS_PWR_ST; + Data32Or = B_PCH_LP_SERIAL_IO_PME_CTRL_STS_PWR_ST; + + PCH_INIT_COMMON_SCRIPT_MEM_READ_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + Bar1 + R_PCH_LP_SERIAL_IO_PME_CTRL_STS, + &Data32Or, + &Data32And + ); + } + + } + + return Status; +} + +/** + Assigns MMIO addresses for SerialIO controllers from a predefined pool + + @retval None +**/ +EFI_STATUS +AssignBARs ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy +) +{ + EFI_PHYSICAL_ADDRESS Bar; + EFI_PHYSICAL_ADDRESS RegBase; + EFI_STATUS Status; + UINTN i; + UINT64 TotalSize; + UINT32 IrqNumber; + + Bar = SERIAL_IO_ADDRESS_AREA; + TotalSize = 2 * ((SERIAL_IO_DEVICE_QUANTITY - 1) * V_PCH_LP_SERIAL_IO_BAR_SIZE + V_PCH_LP_SERIAL_SDIO_BAR_SIZE); + + Status = gDS->AddMemorySpace ( + EfiGcdMemoryTypeReserved, + Bar, + TotalSize, + 0 + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR(Status)) { + return Status; + } + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateAddress, + EfiGcdMemoryTypeReserved, + N_PCH_LP_SERIAL_IO_BAR_ALIGNMENT, + TotalSize, + &Bar, + mImageHandle, + NULL + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR(Status)) { + return Status; + } + + for (i = 0; i < SERIAL_IO_DEVICE_QUANTITY; i++) { + if (!IsSerialIoDeviceEnabled(i)) { + continue; + } + RegBase = MmPciAddress (0, 0, SerialIoDevice[i].DevNum, SerialIoDevice[i].FuncNum, 0); + + MmioAndThenOr32WithScript(RegBase + R_PCH_LP_SERIAL_IO_BAR0, 0x0, SerialIoDevice[i].Bar0); + MmioAndThenOr32WithScript(RegBase + R_PCH_LP_SERIAL_IO_BAR1, 0x0, SerialIoDevice[i].Bar1); + + MmioAndThenOr32WithScript(RegBase + R_PCH_LP_SERIAL_IO_COMMAND, + 0xFFFFFFFF, + B_PCH_LP_SERIAL_IO_COMMAND_BME | B_PCH_LP_SERIAL_IO_COMMAND_MSE + ); + IrqNumber = GetSerialIoIrqNumber(SerialIoDevice[i].DevNum, SerialIoDevice[i].IrqPin, PchPlatformPolicy->SerialIoConfig->SerialIoInterruptMode); + MmioAndThenOr32WithScript(RegBase + R_PCH_PCIE_INTR, (UINT32)~B_PCH_PCIE_INTR_ILINE, IrqNumber); + } + return Status; + +} + + +/** + Hides SerialIo controllers from Pci config space + This prevents BIOS Pci enumerator from assigning mmio resources + SerialIo controllers will receive addresses from a separate pool + + @param[in] RootComplexBar RootComplexBar address of this PCH device + + @retval None +**/ +VOID +HideSerialIoDevices ( + IN UINT32 RootComplexBar + ) +{ + UINTN i; + UINT32 Data32And; + UINT32 Data32Or; + + for (i = 0; i < SERIAL_IO_DEVICE_QUANTITY; i++) { + Data32And = (UINT32) 0xFFFFFFFF; + Data32Or = (UINT32) SerialIoDevice[i].DeviceModeSwitchBit; + + ProgramIobpWithScript (RootComplexBar, SerialIoDevice[i].AcpiSwitchAddr, Data32And, Data32Or); + } +} + +/** + Reveals SerialIo controllers' Pci config space + This allows BIOS to complete initialization for those devices + + @param[in] RootComplexBar RootComplexBar address of this PCH device + + @retval None +**/ +VOID +RevealConfigSpace ( + IN UINT32 RootComplexBar + ) +{ + UINTN i; + UINT32 Data32And; + UINT32 Data32Or; + + for (i = 0; i < SERIAL_IO_DEVICE_QUANTITY; i++) { + Data32And = (UINT32)~(SerialIoDevice[i].DeviceModeSwitchBit); + Data32Or = (UINT32) 0x0; + ProgramIobpWithScript (RootComplexBar, SerialIoDevice[i].AcpiSwitchAddr, Data32And, Data32Or); + } +} + + +/** + Configures Serial IO Controllers + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar address of this PCH device + + @retval None +**/ +EFI_STATUS +ConfigureSerialIoDevices ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ) +{ + UINT8 Index; + UINTN RegBase; + UINTN Bar0; + UINT32 Data32And; + UINT32 Data32Or; + UINT8 i; + + for (i = 0; i < INDEX_SDIO; i++) { + /// + /// Check if device is present + /// + if (!IsSerialIoDeviceEnabled(i)) { + continue; + } + RegBase = MmPciAddress (0, 0, SerialIoDevice[i].DevNum, SerialIoDevice[i].FuncNum, 0); + + Bar0 = MmioRead32 (RegBase + R_PCH_LP_SERIAL_IO_BAR0); + + if(i != PCI_FUNCTION_NUMBER_PCH_LP_SERIAL_IO_DMA) { + /// + /// PCH BIOS Spec Rev 0.7.0 Section 23.3 Serial IO LTR Programming + /// Step 1: Program BAR0 + 808h[2] = 0b + /// Step 2: Program BAR0 + 804h[1:0] = 00b + /// Step 3: Program BAR0 + 804h[1:0] = 11b + /// + MmioAndThenOr32WithScript (Bar0 + R_PCH_LP_SERIAL_IO_PPR_GEN, (UINT32)(~B_PCH_LP_SERIAL_IO_PPR_GEN_LTR_MODE), 0x0); + MmioAndThenOr32WithScript (Bar0 + R_PCH_LP_SERIAL_IO_PPR_RST, (UINT32)(~(B_PCH_LP_SERIAL_IO_PPR_RST_FUNC | B_PCH_LP_SERIAL_IO_PPR_RST_APB)), 0); + MmioAndThenOr32WithScript (Bar0 + R_PCH_LP_SERIAL_IO_PPR_RST, 0xFFFFFFFF, (UINT32)(B_PCH_LP_SERIAL_IO_PPR_RST_FUNC | B_PCH_LP_SERIAL_IO_PPR_RST_APB)); + + /// + /// Step 4 + /// Program BAR0 + 814h with LTR value for each SerialIo controller + /// + MmioAndThenOr32WithScript(Bar0 + R_PCH_LP_SERIAL_IO_PPR_AUTO_LTR, 0, 0); + } + + /// + /// PCH BIOS Spec Rev 0.7.0 Section 23.7 Serial IO Power Management Programming + /// Step 4 + /// Program IO Voltage Select for I2C0 & I2C1 as per platform policy + /// + if(i == PCI_FUNCTION_NUMBER_PCH_LP_SERIAL_IO_I2C0) { + if (PchPlatformPolicy->SerialIoConfig->I2c0VoltageSelect == PchSerialIoIs33V) { + MmioAndThenOr32WithScript(Bar0 + R_PCH_LP_SERIAL_IO_PPR_GEN, (UINT32)~(B_PCH_LP_SERIAL_IO_PPR_GEN_IO_VOLTAGE_SEL), 0); + } else { + MmioAndThenOr32WithScript(Bar0 + R_PCH_LP_SERIAL_IO_PPR_GEN, 0xFFFFFFFF, B_PCH_LP_SERIAL_IO_PPR_GEN_IO_VOLTAGE_SEL); + } + } + + if(i== PCI_FUNCTION_NUMBER_PCH_LP_SERIAL_IO_I2C1) { + if (PchPlatformPolicy->SerialIoConfig->I2c1VoltageSelect == PchSerialIoIs33V) { + MmioAndThenOr32WithScript(Bar0 + R_PCH_LP_SERIAL_IO_PPR_GEN, (UINT32)~(B_PCH_LP_SERIAL_IO_PPR_GEN_IO_VOLTAGE_SEL), 0); + } else { + MmioAndThenOr32WithScript(Bar0 + R_PCH_LP_SERIAL_IO_PPR_GEN, 0xFFFFFFFF, B_PCH_LP_SERIAL_IO_PPR_GEN_IO_VOLTAGE_SEL); + } + } + + /// + /// PCH BIOS Spec Rev 0.7.0 Section 23.4 Serial IO Interrupt Programming + /// Step 4 + /// Program D21:Fx to PCI Interrupt Mode + /// + Data32And = (UINT32)~(SerialIoDevice[i].IrqModeSwitchBit); + if(PchPlatformPolicy->SerialIoConfig->SerialIoInterruptMode == PchSerialIoIsAcpi) { + Data32Or = SerialIoDevice[i].IrqModeSwitchBit; + } else { + Data32Or = 0x00; + } + + /// + /// PCH BIOS Spec Rev 0.7.0 Section 23.7 Serial IO Power Management Programming + /// Step 5 + /// Program D21:Fx FAB_PM_CAP_PRSNT_PORT0 + /// + Data32Or |= BIT1; + ProgramIobpWithScript (RootComplexBar, SerialIoDevice[i].AcpiSwitchAddr, Data32And, Data32Or); + } + + /// + /// Check if SDIO device is present + /// + if (IsSerialIoDeviceEnabled(INDEX_SDIO)) { + + RegBase = MmPciAddress (0, 0, SerialIoDevice[INDEX_SDIO].DevNum, SerialIoDevice[INDEX_SDIO].FuncNum, 0); + + Bar0 = MmioRead32 (RegBase + R_PCH_LP_SERIAL_IO_BAR0); + + MmioAndThenOr32WithScript (Bar0 + R_PCH_LP_SERIAL_IO_SDIO_SLAVE_DELAY_DDR50_MODE, 0, 0x00000306); + + + /// + /// PCH BIOS Spec Rev 0.3.0 Section 23.3 Serial IO LTR Programming + /// Step 5 + /// Program BAR0 + 1008h[2] = 1b + /// + MmioAndThenOr32WithScript (Bar0 + R_PCH_LP_SERIAL_IO_SDIO_PPR_GEN, 0xFFFFFFFF, B_PCH_LP_SERIAL_IO_SDIO_PPR_GEN_LTR_MODE); + + /// + /// Step 6 + /// Program BAR0 + 1010h = 0x00000000 for SDIO controller + /// + Data32And = 0x00000000; + MmioAndThenOr32WithScript (Bar0 + R_PCH_LP_SERIAL_IO_SDIO_PPR_SW_LTR, 0, 0); + + /// + /// Program D23:F0 to PCI Interrupt Mode + /// + Data32And = (UINT32)~(SerialIoDevice[INDEX_SDIO].IrqModeSwitchBit); + if(PchPlatformPolicy->SerialIoConfig->SerialIoInterruptMode == PchSerialIoIsAcpi) { + Data32Or = SerialIoDevice[INDEX_SDIO].IrqModeSwitchBit; + } else { + Data32Or = 0x00; + } + ProgramIobpWithScript (RootComplexBar, SerialIoDevice[INDEX_SDIO].AcpiSwitchAddr, Data32And, Data32Or); + } + + /// + /// PCH BIOS Spec Rev 0.7.0 Section 23.4 Serial IO Interrupt Programing + /// + if(PchPlatformPolicy->SerialIoConfig->SerialIoInterruptMode == PchSerialIoIsAcpi) { + /// + /// Enable ACPI IRQ for IRQ13, IRQ7, IRQ6, IRQ5 in RCRB + /// + Data32Or = (B_PCH_RCRB_INT_ACPIIRQEN_A13E | B_PCH_RCRB_INT_ACPIIRQEN_A7E | B_PCH_RCRB_INT_ACPIIRQEN_A6E | B_PCH_RCRB_INT_ACPIIRQEN_A5E); + MmioAndThenOr32WithScript((UINTN)(RootComplexBar + R_PCH_RCRB_INT_ACPIIRQEN), 0xFFFFFFFF, Data32Or); + } + +#ifdef ULT_FLAG + if (GetPchSeries() == PchLp) { + for (Index = 0; Index < (sizeof (PchSerialIoIntsLptLp) / sizeof (IOBP_MMIO_TABLE_STRUCT)); Index++) { + /// + /// Program IOBP register + /// + Data32And = PchSerialIoIntsLptLp[Index].AndMask; + Data32Or = PchSerialIoIntsLptLp[Index].OrMask; + ProgramIobpWithScript (RootComplexBar, PchSerialIoIntsLptLp[Index].Address, Data32And, Data32Or); + } + } +#endif //ULT_FLAG + + /// + /// PCH BIOS Spec Rev 0.3.0 Section 31.22.6 Serial IO Power Management Programming + /// Step 1 + /// Program CB000154h[12,9:8,4:0] = 1001100011111b + /// + Data32And = (UINT32)~(BIT12 | BIT9 | BIT8 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0); + Data32Or = (UINT32) (BIT12 | BIT9 | BIT8 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0); + + if (PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_6) { + if (PchPlatformPolicy->SerialIoConfig->Ddr50Support) { + Data32Or |= BIT6; + } + } + + ProgramIobpWithScript (RootComplexBar, 0xCB000154, Data32And, Data32Or); + + /// + /// Step 2 + /// Programming done above + /// + /// Step 3 + /// Program CB000180h[5:0] = 111111b + /// + Data32And = (UINT32)~(BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0); + Data32Or = (UINT32) (BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0); + ProgramIobpWithScript (RootComplexBar, 0xCB000180, Data32And, Data32Or); + +#ifdef ULT_FLAG + if (GetPchSeries() == PchLp) { + /// + /// PCH BIOS Spec Rev 0.3.0 Section 23.8 Serial IO Snoop Programing + /// + for (Index = 0; Index < (sizeof (PchSerialIoSnoopLptLp) / sizeof (IOBP_MMIO_TABLE_STRUCT)); Index++) { + /// + /// Program IOBP register + /// + ProgramIobpWithScript ( + RootComplexBar, + PchSerialIoSnoopLptLp[Index].Address, + PchSerialIoSnoopLptLp[Index].AndMask, + PchSerialIoSnoopLptLp[Index].OrMask + ); + } + } +#endif // ULT_FLAG + + return EFI_SUCCESS; +} + +VOID +ConfigureSerialIoAtBoot ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy + ) +{ + UINTN i; + UINT8 FunctionEnable[SERIAL_IO_DEVICE_QUANTITY]; + + if (PchPlatformPolicy->SerialIoConfig->SerialIoMode != PchSerialIoIsAcpi) { + return; + } + + FunctionEnable[INDEX_I2C0] = PchPlatformPolicy->DeviceEnabling->SerialIoI2c0; + FunctionEnable[INDEX_I2C1] = PchPlatformPolicy->DeviceEnabling->SerialIoI2c1; + FunctionEnable[INDEX_SPI0] = PchPlatformPolicy->DeviceEnabling->SerialIoSpi0; + FunctionEnable[INDEX_SPI1] = PchPlatformPolicy->DeviceEnabling->SerialIoSpi1; + FunctionEnable[INDEX_UART0] = PchPlatformPolicy->DeviceEnabling->SerialIoUart0; + FunctionEnable[INDEX_UART1] = PchPlatformPolicy->DeviceEnabling->SerialIoUart1; + FunctionEnable[INDEX_SDIO] = PchPlatformPolicy->DeviceEnabling->SerialIoSdio; + + for (i=INDEX_I2C0; i<MAX_SIO_INDEX; i++) { + if (!FunctionEnable[i]) { + continue; + } + + /// + /// Set D3Hot Power State via BAR1 Address, for all devices except DMA + /// + if(i != INDEX_DMA) { + MmioAndThenOr32 (SerialIoDevice[i].Bar1 + R_PCH_LP_SERIAL_IO_PME_CTRL_STS, + (UINT32) ~B_PCH_LP_SERIAL_IO_PME_CTRL_STS_PWR_ST, + B_PCH_LP_SERIAL_IO_PME_CTRL_STS_PWR_ST + ); + MmioRead32(SerialIoDevice[i].Bar1 + R_PCH_LP_SERIAL_IO_PME_CTRL_STS); + } + } +} + + +/** + Configures Serial IO Controllers after Pci Enum + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar address of this PCH device + + @retval None +**/ +EFI_STATUS +ConfigureSerialIoBeforeBoot ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ) +{ + + RevealConfigSpace(RootComplexBar); + DisableSerialIoControllers(PchPlatformPolicy, RootComplexBar); + AssignBARs(PchPlatformPolicy); + ConfigureSerialIoDevices(PchPlatformPolicy, RootComplexBar); + UpdateSerialIoAcpiData(PchPlatformPolicy, RootComplexBar); + + if (PchPlatformPolicy->SerialIoConfig->SerialIoMode == PchSerialIoIsAcpi) { + PutSerialIoInAcpiMode(PchPlatformPolicy, RootComplexBar); + } + return EFI_SUCCESS; +} + + +EFI_STATUS +ConfigureSerialIo ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar + ) +{ + HideSerialIoDevices(RootComplexBar); + return EFI_SUCCESS; +} + +EFI_STATUS +InstallDmaAcpiTable ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy +) +{ + UINTN AcpiTableKey; + EFI_ACPI_TABLE_PROTOCOL *AcpiTable; + EFI_ACPI_5_0_CORE_SYSTEM_RESOURCES_TABLE *CoreSystemResourcesTable; + UINT64 Data64; + UINT32 Data32; + UINTN RegBase; + UINT8 Index; + EFI_STATUS Status; + UINT32 IrqNumber; + + AcpiTable = NULL; + CoreSystemResourcesTable = NULL; + AcpiTableKey = 0; + + // + // Locate ACPI support protocol + // + Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, &AcpiTable); + if( EFI_ERROR(Status) || AcpiTable == NULL) { + return EFI_UNSUPPORTED; + } + // + // Allocate Memory for Core System Resources Table + // + CoreSystemResourcesTable = AllocateZeroPool(sizeof(EFI_ACPI_5_0_CORE_SYSTEM_RESOURCES_TABLE)); + + if(CoreSystemResourcesTable == NULL) { + return EFI_UNSUPPORTED; + } + + CoreSystemResourcesTable->Header.Signature = EFI_SIGNATURE_32('C','S','R','T'); + CoreSystemResourcesTable->Header.Length = sizeof(EFI_ACPI_5_0_CORE_SYSTEM_RESOURCES_TABLE); + CoreSystemResourcesTable->Header.Revision = 0x01; + CoreSystemResourcesTable->Header.Checksum = 0x00; + Data64 = EFI_SIGNATURE_64 ('I', 'N', 'T', 'L', 0, 0, 0, 0); + CopyMem (&CoreSystemResourcesTable->Header.OemId, &Data64, sizeof(CoreSystemResourcesTable->Header.OemId)); + Data64 = EFI_SIGNATURE_64 ('H', 'S', 'W', 'U', 'L', 'T', '-', 'R'); + CopyMem (&CoreSystemResourcesTable->Header.OemTableId, &Data64, sizeof(CoreSystemResourcesTable->Header.OemTableId)); + CoreSystemResourcesTable->Header.OemRevision = 0x00000001; + CoreSystemResourcesTable->Header.CreatorId = EFI_SIGNATURE_32('I','N','T','L'); + CoreSystemResourcesTable->Header.CreatorRevision = 0x20100528; + + CoreSystemResourcesTable->ResourceGroup1.ResourceGroupLength = sizeof(EFI_ACPI_5_0_CORE_SYSTEM_RESOURCES_TABLE) - sizeof(EFI_ACPI_DESCRIPTION_HEADER); + CoreSystemResourcesTable->ResourceGroup1.VendorId = EFI_SIGNATURE_32('I','N','T','L'); + CoreSystemResourcesTable->ResourceGroup1.SubVendorId = 0x00000000; + CoreSystemResourcesTable->ResourceGroup1.DeviceId = 0x9C60; + CoreSystemResourcesTable->ResourceGroup1.SubDeviceId = 0x0000; + CoreSystemResourcesTable->ResourceGroup1.Revision = 0x0001; + CoreSystemResourcesTable->ResourceGroup1.Reserved = 0x0000; + CoreSystemResourcesTable->ResourceGroup1.SharedInfoLength = 0x00000001C; + CoreSystemResourcesTable->ResourceGroup1SharedInfo.MajorVersion1 = 0x001; + CoreSystemResourcesTable->ResourceGroup1SharedInfo.MinorVersion0 = 0x000; + + RegBase = MmPciAddress (0, 0, SerialIoDevice[INDEX_DMA].DevNum, SerialIoDevice[INDEX_DMA].FuncNum, 0); + Data32 = (MmioRead32(RegBase + R_PCH_LP_SERIAL_IO_BAR0) & B_PCH_LP_SERIAL_IO_BAR0_BAR); + CoreSystemResourcesTable->ResourceGroup1SharedInfo.MmioBaseL = Data32; + CoreSystemResourcesTable->ResourceGroup1SharedInfo.MmioBaseH = 0x00000000; + // + // Match DMA interrupt value + // + IrqNumber = GetSerialIoIrqNumber(SerialIoDevice[INDEX_DMA].DevNum, SerialIoDevice[INDEX_DMA].IrqPin, PchPlatformPolicy->SerialIoConfig->SerialIoInterruptMode); + CoreSystemResourcesTable->ResourceGroup1SharedInfo.InterruptGSI = IrqNumber; + + CoreSystemResourcesTable->ResourceGroup1SharedInfo.InterruptPolarity = 0x02; + CoreSystemResourcesTable->ResourceGroup1SharedInfo.InterruptMode = 0x00; + CoreSystemResourcesTable->ResourceGroup1SharedInfo.NumberofChannels = 0x08; + CoreSystemResourcesTable->ResourceGroup1SharedInfo.DMAAddressWidth = 0x20; + + CoreSystemResourcesTable->ResourceGroup1SharedInfo.BaseRequestLine = 0x0010; + CoreSystemResourcesTable->ResourceGroup1SharedInfo.NumberofHandshakeSignals = 0x0010; + CoreSystemResourcesTable->ResourceGroup1SharedInfo.MaximumBlockTransferSize = 0x00000FFF; + + CoreSystemResourcesTable->ControllerResourceDescriptor1.ResourceDescriptorLength = 0x0000000C; + CoreSystemResourcesTable->ControllerResourceDescriptor1.ResourceType = 0x0003; + CoreSystemResourcesTable->ControllerResourceDescriptor1.ResourceSubType = 0x0001; + CoreSystemResourcesTable->ControllerResourceDescriptor1.UID = 0x20495053; + + Data32 = 0x30414843; + for(Index = 0; Index < 8; Index++) { + CoreSystemResourcesTable->ChannelResourceDescriptor1[Index].ResourceDescriptorLength = 0x0000000C; + CoreSystemResourcesTable->ChannelResourceDescriptor1[Index].ResourceType = 0x0003; + CoreSystemResourcesTable->ChannelResourceDescriptor1[Index].ResourceSubType = 0x0000; + CoreSystemResourcesTable->ChannelResourceDescriptor1[Index].UID = Data32; + Data32 += 0x1000000; + } + Status = AcpiTable->InstallAcpiTable (AcpiTable, CoreSystemResourcesTable, CoreSystemResourcesTable->Header.Length, &AcpiTableKey); + return Status; +} + + + +#endif // SERIAL_IO_FLAG + + + diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchUsb.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchUsb.c new file mode 100644 index 0000000..ddf41a8 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchUsb.c @@ -0,0 +1,439 @@ +/** @file + Initializes PCH USB Controllers. + +@copyright + Copyright (c) 1999 - 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ +#include "PchInit.h" + +/** + Lock USB registers before boot + + @param[in] PchPlatformPolicy The PCH Platform Policy + + @retval None +**/ +VOID +UsbInitBeforeBoot( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy +) +{ + EFI_STATUS Status; + UINT32 XhccCfg; + UINTN XhciPciMmBase; + UINT32 XhciMmioBase; + UINT32 Data32And; + UINT32 Data32Or; + UINT32 PchSeries; + UINT16 OrgCommandWord; + BOOLEAN NeedGcdMemSpace; + + Data32And = 0xFFFFFFFF; + Data32Or = 0x0; + NeedGcdMemSpace = FALSE; + + if (PchPlatformPolicy->UsbConfig->Usb30Settings.Mode == PCH_XHCI_MODE_OFF) { + return; + } + + XhciPciMmBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_XHCI, + PCI_FUNCTION_NUMBER_PCH_XHCI, + 0 + ); + XhciMmioBase = MmioRead32(XhciPciMmBase + R_PCH_XHCI_MEM_BASE) & ~(0x0F); + if(XhciMmioBase == 0){ + /// + /// Allocate GCD mem space + /// + XhciMmioBase = 0xFFFFFFFF; + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateMaxAddressSearchBottomUp, + EfiGcdMemoryTypeMemoryMappedIo, + N_PCH_XHCI_MEM_ALIGN, + V_PCH_XHCI_MEM_LENGTH, + (EFI_PHYSICAL_ADDRESS *)&XhciMmioBase, + mImageHandle, + NULL + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return; + } + NeedGcdMemSpace = TRUE; + MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE, XhciMmioBase); + } + PchSeries = GetPchSeries(); + + /// + ///Restore xHCI MMIO Enable + /// + OrgCommandWord = MmioRead16 (XhciPciMmBase + R_PCH_XHCI_COMMAND_REGISTER); + MmioOr16 ( + XhciPciMmBase + R_PCH_XHCI_COMMAND_REGISTER, + (UINT16) (B_PCH_XHCI_COMMAND_MSE | B_PCH_XHCI_COMMAND_BME) + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (XhciPciMmBase + R_PCH_XHCI_COMMAND_REGISTER), + 1, + (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_COMMAND_REGISTER) + ); + + /// + ///Restore xHCI BAR + /// + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciPciMmBase + R_PCH_XHCI_MEM_BASE), + 1, + (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_MEM_BASE) + ); + + if (PchSeries == PchH) { + /// + /// For LPT-H, Set xHCIBAR + 8144h[8, 7, 6] to 1b, 0b, 0b + /// + MmioAndThenOr32 (XhciMmioBase + 0x8144, (UINT32) ~(BIT7 | BIT6), (UINT32) (BIT8)); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x8144), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x8144) + ); + } else if (PchSeries == PchLp) { + /// + /// For LPT-LP, Set xHCIBAR + 8144h[8, 7, 6] to 1b, 1b, 1b + /// + MmioOr32 (XhciMmioBase + 0x8144, (UINT32) (BIT8 | BIT7 | BIT6)); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x8144), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x8144) + ); + /// + /// For LPT-LP, Set xHCIBAR + 816Ch[19:0] to 000E0038h + /// + Data32And = (UINT32) ~(0x000FFFFF); + Data32Or = (UINT32) (0x000E0038); + MmioAndThenOr32 ( + (XhciMmioBase + 0x816C), + Data32And, + Data32Or + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciMmioBase + 0x816C), + 1, + (VOID *) (UINTN) (XhciMmioBase + 0x816C) + ); + /// + /// For LPT-LP, Set D20:F0:B0h[17,14,13] to 1b, 0b, 0b + /// + MmioAndThenOr32 (XhciPciMmBase + 0xB0, (UINT32) ~(BIT14 | BIT13), (UINT32) (BIT17)); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciPciMmBase + 0xB0), + 1, + (VOID *) (UINTN) (XhciPciMmBase + 0xB0) + ); + } + + /// + /// Set D20:F0:50h[28:0] to 0FCE2E5F for LPT-LP + /// Set D20:F0:50h[26:0] to 07886E9Fh for LPT-H B0 onward + /// + if (PchSeries == PchH) { + Data32And = (UINT32)~(0x07FFFFFF); + Data32Or = (UINT32) (0x07886E9F); + } else if (PchSeries == PchLp) { + Data32And = (UINT32) ~(0x1FFFFFFF); + Data32Or = (UINT32) (0x0FCE2E5F); + } + MmioAndThenOr32 ( + (XhciPciMmBase + 0x50), + Data32And, + Data32Or + ); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciPciMmBase + 0x50), + 1, + (VOID *) (UINTN) (XhciPciMmBase + 0x50) + ); + + if ((GetBootModeHob () == BOOT_ON_S4_RESUME) && + (PchPlatformPolicy->UsbConfig->UsbPrecondition == PCH_DEVICE_ENABLE)) { + /// + /// For LPT-LP, Set xHCIBAR + 80E0[24] to 1h + /// + MmioOr32 (XhciMmioBase + 0x80E0, (UINT32) (BIT24)); + + /// + /// For LPT-LP, Set xHCIBAR + 80E0[24] to 0h + /// + MmioAnd32 (XhciMmioBase + 0x80E0, (UINT32) ~(BIT24)); + } + + /// + /// PCH BIOS Spec xHCI controller setup + /// Note: + /// D20:F0:40h is write once register. + /// Unsupported Request Detected bit is write clear + /// + XhccCfg = MmioRead32 (XhciPciMmBase + R_PCH_XHCI_XHCC1); + XhccCfg &= (UINT32) ~(B_PCH_XHCI_XHCC1_URD); + /// + /// PCH BIOS Spec Rev 0.5.5, Section 13.2.4 Locking xHCI Register Settings + /// PCH BIOS Spec Locking xHCI Register settings + /// After xHCI is initialized, BIOS should lock the xHCI configuration registers to RO. + /// This prevent any unintended changes. There is also a lockdown feature for OverCurrent + /// registers. BIOS should set these bits to lock down the settings prior to end of POST. + /// 1. Set Access Control bit at D20:F0:40h[31] to 1b to lock xHCI register settings. + /// 2. Set OC Configuration Done bit at D20:F0:44h[31] to lock overcurrent mappings from + /// further changes. + /// + MmioOr32 (XhciPciMmBase + 0x44, (UINT32) (BIT31)); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciPciMmBase + 0x44), + 1, + (VOID *) (UINTN) (XhciPciMmBase + 0x44) + ); + XhccCfg |= (UINT32) (B_PCH_XHCI_XHCC1_ACCTRL); + MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_XHCC1, XhccCfg); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciPciMmBase + R_PCH_XHCI_XHCC1), + 1, + &XhccCfg + ); + + /// + ///restore xHCI original command byte + /// + MmioWrite16 ((XhciPciMmBase + R_PCH_XHCI_COMMAND_REGISTER), OrgCommandWord); + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint16, + (UINTN) (XhciPciMmBase + R_PCH_XHCI_COMMAND_REGISTER), + 1, + (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_COMMAND_REGISTER) + ); + + if (NeedGcdMemSpace) { + MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE, 0); + /// + ///clear xHCI BAR + /// + PCH_INIT_COMMON_SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (XhciPciMmBase + R_PCH_XHCI_MEM_BASE), + 1, + (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_MEM_BASE) + ); + /// + /// release GCD Mem space + /// + gDS->FreeMemorySpace ( + XhciMmioBase, + V_PCH_XHCI_MEM_LENGTH + ); + } + +} + +/** + Configures ports of the PCH USB3 (xHCI) controller + just before OS boot. + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + + @retval EFI_INVALID_PARAMETER The parameter of PchPlatformPolicy is invalid + @retval EFI_SUCCESS The function completed successfully +**/ +VOID +ConfigureXhciAtBoot ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy + ) +{ + UINTN PciD20F0RegBase; + UINT32 PortMask; + + DEBUG ((EFI_D_INFO, "ConfigureXhciAtBoot() Start\n")); + + PciD20F0RegBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_XHCI, + PCI_FUNCTION_NUMBER_PCH_XHCI, + 0 + ); + + /// + /// PCH BIOS Spec Rev 0.5.0 + /// When the BIOS does not have xHCI pre-boot software available: + /// Section 13.1.1.2 xHCI Enabled mode + /// BIOS should route the Ports to the EHCI controller and prior to OS boot + /// it should route the ports to the xHCI controller. + /// + if ((PchPlatformPolicy->UsbConfig->Usb30Settings.Mode == PCH_XHCI_MODE_ON) && + (PchPlatformPolicy->UsbConfig->Usb30Settings.PreBootSupport == PCH_DEVICE_DISABLE)) { + /// + /// PCH BIOS Spec Rev 0.5.0 Section 13.2.6 Routing of switchable USB Ports to + /// xHCI Controller + /// Step 1 + /// Done in GetXhciPortsNumber() + /// Step 2 + /// Program D20:F0:D8h[5:0] to the value of xHCI D20:F0:DCh[5:0] + /// + PortMask = MmioRead32 (PciD20F0RegBase + R_PCH_XHCI_USB3PRM); + + MmioAndThenOr32 ( + PciD20F0RegBase + R_PCH_XHCI_USB3PR, + (UINT32)~B_PCH_XHCI_USB3PR_USB3SSEN, + PortMask + ); + /// + /// Step 3 + /// Program D20:F0:D0h[14:0] to the value of xHCI D20:F0:D4h[15:0] + /// + PortMask = MmioRead32 (PciD20F0RegBase + R_PCH_XHCI_USB2PRM); + + MmioAndThenOr32 ( + PciD20F0RegBase + R_PCH_XHCI_USB2PR, + (UINT32)~B_PCH_XHCI_USB2PR_USB2HCSEL, + PortMask + ); + /// + /// Note: Registers USB3PR[5:0] and USB2PR[14:0] are located in SUS well so BIOS doesn't + /// need to restore them during S3 resume, but needs to restore corresponding mask + /// registers. For RapidStart resume from G3 state support, HC Switch driver will call + /// _OSC method to restore USB2PR and USB3PR. + } + + DEBUG ((EFI_D_INFO, "ConfigureXhciAtBoot() End\n")); +} + +/** + Configures PCH USB controller + + @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance + @param[in] RootComplexBar RootComplexBar address of this PCH device + @param[in, out] FuncDisableReg Function Disable Register + + @retval EFI_INVALID_PARAMETER The parameter of PchPlatformPolicy is invalid + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +ConfigureUsb ( + IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, + IN UINT32 RootComplexBar, + IN OUT UINT32 *FuncDisableReg + ) +{ + EFI_STATUS Status; + UINT8 BusNumber; + PCH_USB_CONFIG *UsbConfig; + UINT32 UsbFuncDisable; + EFI_PHYSICAL_ADDRESS EhciMemBaseAddress; + EFI_PHYSICAL_ADDRESS XhciMemBaseAddress; + + DEBUG ((EFI_D_INFO, "ConfigureUsb() Start\n")); + + BusNumber = PchPlatformPolicy->BusNumber; + UsbConfig = PchPlatformPolicy->UsbConfig; + EhciMemBaseAddress = 0x0ffffffff; + + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateMaxAddressSearchBottomUp, + EfiGcdMemoryTypeMemoryMappedIo, + N_PCH_EHCI_MEM_ALIGN, + V_PCH_EHCI_MEM_LENGTH, + &EhciMemBaseAddress, + mImageHandle, + NULL + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + XhciMemBaseAddress = 0x0ffffffff; + + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateMaxAddressSearchBottomUp, + EfiGcdMemoryTypeMemoryMappedIo, + N_PCH_XHCI_MEM_ALIGN, + V_PCH_XHCI_MEM_LENGTH, + &XhciMemBaseAddress, + mImageHandle, + NULL + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + + gDS->FreeMemorySpace ( + EhciMemBaseAddress, + V_PCH_EHCI_MEM_LENGTH + ); + + return Status; + } + + UsbFuncDisable = *FuncDisableReg; + + Status = CommonUsbInit ( + UsbConfig, + (UINT32) EhciMemBaseAddress, + (UINT32) XhciMemBaseAddress, + BusNumber, + RootComplexBar, + &UsbFuncDisable, + PchPlatformPolicy->Revision + ); + *FuncDisableReg = UsbFuncDisable; + + // + // Free allocated resources + // + gDS->FreeMemorySpace ( + EhciMemBaseAddress, + V_PCH_EHCI_MEM_LENGTH + ); + + gDS->FreeMemorySpace ( + XhciMemBaseAddress, + V_PCH_XHCI_MEM_LENGTH + ); + DEBUG ((EFI_D_INFO, "ConfigureUsb() End\n")); + + return EFI_SUCCESS; +} diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchUsbPrecondition.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchUsbPrecondition.c new file mode 100644 index 0000000..ea8f794 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchUsbPrecondition.c @@ -0,0 +1,522 @@ +/** @file + PCH USB precondition feature support in DXE phase + +@copyright + Copyright (c) 2012 - 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#include "PchInit.h" +#include "PchUsbPrecondition.h" +#include "PchUsbCommon.h" + +#ifdef USB_PRECONDITION_ENABLE_FLAG +// +// Data referred by EHCI +// +extern USB_CONTROLLER EhciControllersMap[]; + +// +// Data referred by XHCI +// +UINTN *PORTSCxUSB2Ptr; +UINTN *PORTSCxUSB3Ptr; + +// +// Data referred by USB Precondition feature +// +EFI_USB_HC_PORT_PRECONDITION *mPrivatePreConditionList = NULL; + +// +// This flag set when 50ms root port reset duration is satisified (Tdrstr). It is countered from +// last root port reset. +// +BOOLEAN PchUsbRPortsRstDoneFlag = FALSE; + +// +// All root ports reset continuously, so the reset starting time between first root port and last +// root port should not exceed PCH ACPI timer High-to-Low transition frequency - 2.3435 seconds. +// +UINTN LastRPortResetTicks = 0; + +// +// Tdrstr for all root portis satisfied as the following scenarios: +// +// | +// |-> Reset all root ports of 1st HC, save tick_1 to LastRPortResetTicks +// | +// |-> Reset all root ports of 2nd HC, save tick_2 to LastRPortResetTicks +// | +// |-> IsRootPortReset () for is invoked by first call, wait until if delay for tick_2 is enough +// | Set PchUsbRPortsRstDoneFlag = TRUE, return TRUE if the port is in the list +// | +// |-> IsRootPortReset () is invoked for the other HC, and PchUsbRPortsRstDoneFlag is set +// | Return TRUE if the port is in the list +// + +/** + Return current PCH PM1 timer value + + @param[in] None + + @retval PM1 timer value in 32 bit +**/ +UINTN +PchGetPchTimerTick ( + VOID + ) +{ + UINT16 AcpiBaseAddr; + + AcpiBaseAddr = PciRead16 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + 0, + R_PCH_LPC_ACPI_BASE) + ) & B_PCH_LPC_ACPI_BASE_BAR; + + return IoRead32 ((UINTN) (AcpiBaseAddr + R_PCH_ACPI_PM1_TMR)) & B_PCH_ACPI_PM1_TMR_VAL; + +} + +/** + Check if the required delay condition is satisified + Note: The delay can't be larger than PCH ACPI timer High-to-Low + transition frequency - 2.3435 seconds. + + @param[in] InitialTicks Initial PM1 tick value + @param[in] RequiredStallInUs Required delay in us + + @retval TRUE The required delay is satisified + @retval FALSE The required delay is not satisified +**/ +BOOLEAN +UsbTimeout ( + IN UINTN InitialTicks, + IN UINTN RequiredStallInUs + ) +{ + UINTN CurrentTick; + UINTN ExpiredTick; + + // + // The timer frequency is 3.579545 MHz, so 1 us corresponds 3.58 clocks + // + ExpiredTick = RequiredStallInUs * 358 / 100 + InitialTicks + 1; + CurrentTick = PchGetPchTimerTick (); + + // + // The High-to-Low transition will occur every 2.3435 seconds. + // + if (CurrentTick < InitialTicks) { + CurrentTick += V_PCH_ACPI_PM1_TMR_MAX_VAL; + } + + if (CurrentTick > ExpiredTick){ + return TRUE; + } + return FALSE; +} + +/** + Initialize usb global data and flag for reference + + @param[in] None + + @retval None +**/ +VOID +UsbInitGlobalData ( + VOID + ) +{ + + /// + /// Set the flag to false and start to count time. + /// + PchUsbRPortsRstDoneFlag = FALSE; + + /// + /// This is the latest root port reset, record it to ensure the Tdrstr is satisified. + /// + LastRPortResetTicks = PchGetPchTimerTick(); + return; +} + +/** + Check if the delay is enough since last root port reset + + @param[in] None + + @retval None +**/ +VOID +UsbTdrstrDelayCheck ( + VOID + ) +{ + UINTN i; + + /// + /// If the latest root port reset done, and then for all root ports reset by + /// this protocol is ready. If we are in scenario#3, wait until delay time is enough. The flag + /// is set either by timer event or the waitting loop. + /// + for (i = 0; (PchUsbRPortsRstDoneFlag != TRUE) && (i < USB_ROOT_PORT_RESET_STALL_US/ USB_TDRSTR_CHECK_INTERVAL_US); i++) { + if (UsbTimeout (LastRPortResetTicks, USB_ROOT_PORT_RESET_STALL_US)) { + PchUsbRPortsRstDoneFlag = TRUE; + LastRPortResetTicks = 0; + break; + } + PchPmTimerStall (USB_TDRSTR_CHECK_INTERVAL_US); + } + + return ; +} + +/** + Check if the queried port is reset by USB precondition feature or not + + @param[in] This EFI_USB_HC_PORT_PRECONDITION instance + @param[in] PortNumber The root port number (started by zero) to be queried + + @retval TRUE The root port is reset done + @retval FALSE The root port is not reset +**/ +BOOLEAN +EFIAPI +IsEhcRootPortReset ( + IN EFI_USB_HC_PORT_PRECONDITION *This, + IN UINT8 PortNumber + ) +{ + USB_EHCI_PRECONDITION_DEV *EhcPreCondition; + + EhcPreCondition = EHC_PRECONDITION_FROM_THIS (This); + + /// + /// For the EHCI on PCH, the root port 0 is always RMH and existing. + /// PCH USB precondition feature resets the root port 0 on PCH EHCI only + /// If the signature, PortNumber, or PortResetBitMap is invalid, return + /// FALSE directly. Otherwise, return TRUE when required reset signal delay + /// is satisified. + /// + if ((EhcPreCondition->Signature != EHCI_PRECONDITION_DEV_SIGN) || + (PortNumber != 0) || + (EhcPreCondition->PortResetBitMap == 0)) { + return FALSE; + } + + // + // Drive the reset signal on root port for at least 50ms(Tdrstr). Check USB 2.0 Spec + // section 7.1.7.5 for timing requirements. + // + if (!PchUsbRPortsRstDoneFlag) { + UsbTdrstrDelayCheck (); + } + return TRUE; +} + +/** + Perform USB precondition on EHCI, it is the root port reset on + installed USB device in DXE phase + + @param[in] Device The device number of the EHCI + @param[in] EhciMmioBase Memory base address of EHCI Controller + + @retval None +**/ +VOID +EhciPrecondition ( + IN UINT8 Device, + IN UINT32 EhciMmioBase + ) +{ + UINTN i; + UINT32 Data32; + USB_EHCI_PRECONDITION_DEV *EhcPreCondition; + EFI_USB_HC_LOCATION EhcLocation = {0, 0, 0, 0}; + + // + // Check if all ports routed to this EHCI successfully, if not, exit directly + // + if ((MmioRead32 (EhciMmioBase + R_PCH_EHCI_CONFIGFLAG) & BIT0) == 0) { + return; + } + + EhcPreCondition = AllocateZeroPool (sizeof (USB_EHCI_PRECONDITION_DEV)); + if (EhcPreCondition == NULL) { + return; + } + + /// + /// This is Intel RMH behind EHCI, and it is on root hub port 0. Reset the root hub port0. + /// + for (i = 0; i < (USB_HC_RESET_STALL_US/ 10); i++) { + if ((MmioRead32 (EhciMmioBase + R_PCH_EHCI_PORTSC0) & BIT0) == 0) { + // + // Root port 0 on EHCI is RMH, check the CCS bit before reset port. + // If the CCS bit is not true, wait and poll until timeout + // + PchPmTimerStall (10); + } else { + break; + } + } + + Data32 = MmioRead32 (EhciMmioBase + R_PCH_EHCI_PORTSC0); + + // + // Mask of the port change bits, they are WC (write clean). + // Set one to PortReset bit and must also set zero to PortEnable bit + // + Data32 &= ~B_PCH_EHCI_PORTSC0_CHANGE_ENABLE_MASK; + Data32 |= B_PCH_EHCI_PORTSC0_RESET; + MmioWrite32 ((EhciMmioBase + R_PCH_EHCI_PORTSC0), Data32); + + UsbInitGlobalData (); + EhcPreCondition->Signature = EHCI_PRECONDITION_DEV_SIGN; + + // + // RMH is at root hub port 0 + // + EhcPreCondition->PortResetBitMap = BIT0; + + // + // Suggest required delay time defined by specification per RMH implementation. Reserved so far + // + ZeroMem (&(EhcPreCondition->Protocol.Timing), sizeof (EFI_USB_PORT_ENUM_TIMING_TABLE)); + + EhcLocation.DeviceNumber = (UINTN) Device; + CopyMem (&(EhcPreCondition->Protocol.Location), &EhcLocation, sizeof (EFI_USB_HC_LOCATION)); + + EhcPreCondition->Protocol.IsRootPortReset = IsEhcRootPortReset; + EhcPreCondition->Protocol.Next = mPrivatePreConditionList; + mPrivatePreConditionList = &(EhcPreCondition->Protocol); +} + +/** + Check if the queried port is reset by USB precondition feature or not. This service must be called when + XHC is in Run(R/S = '1') mode per XHCI specification requirement. + + @param[in] This EFI_USB_HC_PORT_PRECONDITION instance + @param[in] PortNumber The root port number (started by zero) to be queried + + @retval TRUE The root port is reset done + @retval FALSE The root port is not reset +**/ +BOOLEAN +EFIAPI +IsXhcRootPortReset ( + IN EFI_USB_HC_PORT_PRECONDITION *This, + IN UINT8 PortNumber + ) +{ + UINT32 UsbPort; + UINT32 Data32; + UINT32 XhciMmioBase; + UINT32 XhciPciMmBase; + USB_XHCI_PRECONDITION_DEV *XhcPreCondition; + BOOLEAN ResumeFlag; + + XhcPreCondition = XHC_PRECONDITION_FROM_THIS (This); + + /// + /// If the signature, PortNumber, or PortResetBitMap is invalid, return + /// FALSE directly. Otherwise, return TRUE when required reset signal delay + /// is satisified. + /// + if ((XhcPreCondition->PortResetBitMap == 0) || (XhcPreCondition->Signature != XHCI_PRECONDITION_DEV_SIGN)) { + return FALSE; + } + + /// + /// Resume all USB2 protocol ports by first call + /// + if (XhcPreCondition->PORTSCxResumeDoneFlag != TRUE) { + // + // Drive the reset signal on root port for at least 50ms(Tdrstr). Check USB 2.0 Spec + // section 7.1.7.5 for timing requirements. + // + if (!PchUsbRPortsRstDoneFlag) { + UsbTdrstrDelayCheck (); + } + + XhciPciMmBase = (UINT32) MmPciAddress ( + 0, + (UINT8) XhcPreCondition->Protocol.Location.BusNumber, + (UINT8) XhcPreCondition->Protocol.Location.DeviceNumber, + (UINT8) XhcPreCondition->Protocol.Location.FunctionNumber, + 0 + ); + + XhciMmioBase = MmioRead32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE) & (~0xF); + ResumeFlag = FALSE; + + /// + /// For USB2 protocol port on XHCI, the reset done port will enter U3 state once the HC is halted + /// To recovery the USB2 protocol port from U3 to U0, SW should: + /// 1. SW shall ensure that the XHC is in Run mode prior to transitioning a root hub port from Resume to + /// the U0 state. + /// 2. Write a "15" (Resume) to the PLS, XHC shall transmit the resume signaling within 1ms (Tursm) + /// 3. SW shall ensure that resume is signaled for at least 20 ms (Tdrsmdn) from the write of Resume + /// 4. After Tdrsmdn is complete, SW shall write a "0"(U0) to the PLS field + /// + for (UsbPort = 0; UsbPort < XhcPreCondition->HsPortCount; UsbPort++) { + if (((UINT32)(1 << UsbPort) & XhcPreCondition->PortResetBitMap) != 0) { + Data32 = MmioRead32 (XhciMmioBase + PORTSCxUSB2Ptr[UsbPort]); + if ((Data32 & B_PCH_XHCI_PORTSCXUSB2_CCS) != 0) { + Data32 &= ~B_PCH_XHCI_PORT_CHANGE_ENABLE_MASK; + Data32 |= (B_PCH_XHCI_USB2_U3_EXIT + B_PCH_XHCI_PORTSCXUSB2_PP + B_PCH_XHCI_PORTSCXUSB2_LWS); + MmioWrite32 ( + XhciMmioBase + PORTSCxUSB2Ptr[UsbPort], + Data32 + ); + ResumeFlag = TRUE; + } else { + // + // The CCS bit of this port disappears, it may be caused by the following reasons: + // 1. Link training is successfully now, the CCS shows on correct USB speed port, i.e. USB3 + // speed if it is USB3 device. + // 2. The device is removed. + // Ignore this port due to there is no device on it now. + // + XhcPreCondition->PortResetBitMap &= ~(UINT32) (1 << UsbPort); + } + } + } + + if (ResumeFlag) { + // + // There is one root port resuming from U3 at least. + // + PchPmTimerStall (20 * 1000); + for (UsbPort = 0; UsbPort < XhcPreCondition->HsPortCount; UsbPort++) { + if (((UINT32)(1 << UsbPort) & XhcPreCondition->PortResetBitMap) != 0 ) { + Data32 = (B_PCH_XHCI_PORTSCXUSB2_PP + B_PCH_XHCI_PORTSCXUSB2_LWS + B_PCH_XHCI_PORTSCXUSB2_CCS); + MmioWrite32 ( + XhciMmioBase + PORTSCxUSB2Ptr[UsbPort], + Data32 + ); + } + } + } + XhcPreCondition->PORTSCxResumeDoneFlag = TRUE; + } + + if (XhcPreCondition->PORTSCxResumeDoneFlag == TRUE) { + // + // If the signature, PortNumber, or PortResetBitMap is invalid, return + // FALSE directly. Otherwise, return TRUE when required reset signal delay + // is satisified. + // + if (((UINT32)(1 << PortNumber) & XhcPreCondition->PortResetBitMap) != 0) { + return TRUE; + } + } + return FALSE; +} + +/** + Perform USB precondition on XHCI, it is the root port reset on + installed USB device in DXE phase + + @param[in] BusNumber The Bus number of the XHCI + @param[in] Device The device number of the XHCI + @param[in] Function The function number of the XHCI + @param[in] XhciMmioBase Memory base address of XHCI Controller + @param[in] XhciUSB2Ptr Pointer to USB2 protocol port register + @param[in] HsPortCount The number of USB2 protocol port supported by this XHCI + + @retval None +**/ +VOID +XhciPrecondition ( + IN UINT8 BusNumber, + IN UINT8 Device, + IN UINT8 Function, + IN UINT32 XhciMmioBase, + IN UINTN *XhciUSB2Ptr, + IN UINTN HsPortCount, + IN UINTN *XhciUSB3Ptr, + IN UINTN SsPortCount + ) +{ + UINT32 UsbPort; + UINT32 Data32; + USB_XHCI_PRECONDITION_DEV *XhcPreCondition; + EFI_USB_HC_LOCATION XhcLocation = {0, 0, 0, 0}; + + XhcPreCondition = AllocateZeroPool (sizeof (USB_XHCI_PRECONDITION_DEV)); + if (XhcPreCondition == NULL) { + return; + } + + PORTSCxUSB2Ptr = XhciUSB2Ptr; + PORTSCxUSB3Ptr = XhciUSB3Ptr; + XhcPreCondition->Signature = XHCI_PRECONDITION_DEV_SIGN; + + XhcPreCondition->HsPortCount = HsPortCount; + + for (UsbPort = 0; UsbPort < HsPortCount; UsbPort++) { + Data32 = MmioRead32 (XhciMmioBase + PORTSCxUSB2Ptr[UsbPort]); + if ((Data32 & B_PCH_XHCI_PORTSCXUSB2_CCS) != 0) { + Data32 &= ~B_PCH_XHCI_PORTSCXUSB2_PED; + Data32 |= B_PCH_XHCI_PORTSCXUSB2_PR | B_PCH_XHCI_PORTSCXUSB2_PP; + MmioWrite32 ( + XhciMmioBase + PORTSCxUSB2Ptr[UsbPort], + Data32 + ); + // + // PortSC registers in PCH XHCI is counted from HS ports + // + XhcPreCondition->PortResetBitMap |= (UINT32) (1 << UsbPort); + } + } +#ifdef EFI_DEBUG + DEBUG ((EFI_D_INFO, "XhciPreconditionDxe - USB3PORTSC Start\n")); + for (UsbPort = 0; UsbPort < SsPortCount; UsbPort++) { + DEBUG ((EFI_D_INFO, "USB3Port %x - %x\n", UsbPort, MmioRead32 (XhciMmioBase + XhciUSB3Ptr[UsbPort]))); + } +#endif + + // + // Clear WRC bit for all USB3 PORTSC + // + for (UsbPort = 0; UsbPort < SsPortCount; UsbPort++) { + MmioAndThenOr32 ( + XhciMmioBase + PORTSCxUSB3Ptr[UsbPort], + (UINT32)~ (B_PCH_XHCI_PORTSCXUSB3_CHANGE_ENABLE_MASK), + B_PCH_XHCI_PORTSCXUSB3_WRC + ); + } +#ifdef EFI_DEBUG + DEBUG ((EFI_D_INFO, "XhciPreconditionDxe - USB3PORTSC Done\n")); + for (UsbPort = 0; UsbPort < SsPortCount; UsbPort++) { + DEBUG ((EFI_D_INFO, "USB3Port %x - %x\n", UsbPort, MmioRead32 (XhciMmioBase + XhciUSB3Ptr[UsbPort]))); + } +#endif + UsbInitGlobalData (); + XhcLocation.DeviceNumber = (UINTN) Device; + XhcLocation.FunctionNumber = (UINTN) Function; + CopyMem (&(XhcPreCondition->Protocol.Location), &XhcLocation, sizeof (EFI_USB_HC_LOCATION)); + XhcPreCondition->Protocol.IsRootPortReset = IsXhcRootPortReset; + XhcPreCondition->PORTSCxResumeDoneFlag = FALSE; + XhcPreCondition->Protocol.Next = mPrivatePreConditionList; + mPrivatePreConditionList = &(XhcPreCondition->Protocol); +} + +#endif // USB_PRECONDITION_ENABLE_FLAG diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchUsbPrecondition.h b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchUsbPrecondition.h new file mode 100644 index 0000000..faaeda9 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchUsbPrecondition.h @@ -0,0 +1,54 @@ +/** @file + Header file for PCH USB precondition feature support in DXE phase + +@copyright + Copyright (c) 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ +#ifndef _PCH_USB_PRECONDITION_H_ +#define _PCH_USB_PRECONDITION_H_ + +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "EdkIIGlueBase.h" +#include "PchAccess.h" +#include "UsbHcPortPrecondition.h" +#endif + +#define USB_HC_RESET_STALL_US 10 * 1000 ///< 10ms +#define USB_ROOT_PORT_RESET_STALL_US 50 * 1000 ///< 50ms +#define USB_TDRSTR_CHECK_INTERVAL_US 100 +#define EHCI_PRECONDITION_DEV_SIGN EFI_SIGNATURE_32 ('e','p','r','e') +#define EHC_PRECONDITION_FROM_THIS(a) CR(a, USB_EHCI_PRECONDITION_DEV, Protocol, EHCI_PRECONDITION_DEV_SIGN) + +typedef struct _USB_EHCI_PRECONDITION_DEV { + UINTN Signature; + EFI_USB_HC_PORT_PRECONDITION Protocol; + UINTN PortResetBitMap; +} USB_EHCI_PRECONDITION_DEV; + +#define XHCI_PRECONDITION_DEV_SIGN EFI_SIGNATURE_32 ('x','p','r','e') +#define XHC_PRECONDITION_FROM_THIS(a) CR(a, USB_XHCI_PRECONDITION_DEV, Protocol, XHCI_PRECONDITION_DEV_SIGN) + +typedef struct _USB_XHCI_PRECONDITION_DEV { + UINTN Signature; + EFI_USB_HC_PORT_PRECONDITION Protocol; + UINTN HsPortCount; + UINTN PortResetBitMap; + UINTN PortResetDoneBitMap; + BOOLEAN PORTSCxResumeDoneFlag; +} USB_XHCI_PRECONDITION_DEV; + +#endif diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchDmiPeim.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchDmiPeim.c new file mode 100644 index 0000000..a53bf8b --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchDmiPeim.c @@ -0,0 +1,831 @@ +/** @file + This file contains functions for PCH DMI TC/VC programing and status polling + +@copyright + Copyright (c) 2009 - 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +// AMI_OVERRIDE >>> +#ifdef AMI_RC_DEBUG +#include "PeiLib.h" +#endif +// AMI_OVERRIDE <<< +#include "PchInitPeim.h" +#include "HeciRegs.h" +#include "MeAccess.h" +#include "ChipsetInitHob.h" + +// +// GUID Definitions +// +EFI_GUID gChipsetInitHobGuid = CHIPSET_INIT_INFO_HOB_GUID; + +/** + Programing transaction classes of the corresponding virtual channel and Enable it + + @param[in] RootComplexBar PCH Root Complex Base Address + @param[in] Vc The virtual channel number for programing + @param[in] VcId The Identifier to be used for this virtual channel + @param[in] VcMap The transaction classes are mapped to this virtual channel. + When a bit is set, this transaction class is mapped to the virtual channel + + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +PchSetDmiTcVcMapping ( + IN UINT32 RootComplexBar, + IN UINT8 Vc, + IN UINT8 VcId, + IN UINT8 VcMap + ) +{ + UINTN Address; + UINT32 VxCtlAnd; + UINT32 VxCtlOr; + + Address = RootComplexBar; + + VxCtlAnd = (UINT32) (~(B_PCH_RCRB_V1CTL_ID | V_PCH_RCRB_V1CTL_TVM_MASK)); + VxCtlOr = (VcId << N_PCH_RCRB_V1CTL_ID) & B_PCH_RCRB_V1CTL_ID; + VxCtlOr |= VcMap; + VxCtlOr |= B_PCH_RCRB_V1CTL_EN; + + switch (Vc) { + case DmiVcTypeVc0: + Address += R_PCH_RCRB_V0CTL; + break; + + case DmiVcTypeVc1: + Address += R_PCH_RCRB_V1CTL; + break; + + case DmiVcTypeVcp: + Address += R_PCH_RCRB_CIR2030; + break; + + case DmiVcTypeVcm: + Address += R_PCH_RCRB_CIR2040; + break; + + default: + return EFI_INVALID_PARAMETER; + } + + MmioAndThenOr32 (Address, VxCtlAnd, VxCtlOr); + if ((Vc == DmiVcTypeVc1) || (Vc == DmiVcTypeVcp)) { + // + // Reads back for posted write to take effect + // + MmioRead32 (Address); + } + + return EFI_SUCCESS; +} + +/** + Polling negotiation status of the corresponding virtual channel + + @param[in] RootComplexBar PCH Root Complex Base Address + @param[in] Vc The virtual channel number for programing + + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +PchPollDmiVcStatus ( + IN UINT32 RootComplexBar, + IN UINT8 Vc + ) +{ + UINTN Address; + + Address = RootComplexBar; + + switch (Vc) { + case DmiVcTypeVc0: + Address += R_PCH_RCRB_V0STS; + break; + + case DmiVcTypeVc1: + Address += R_PCH_RCRB_V1STS; + break; + + case DmiVcTypeVcp: + Address += 0x2036; + break; + + case DmiVcTypeVcm: + Address += 0x2046; + break; + + default: + return EFI_INVALID_PARAMETER; + } + // + // Wait for negotiation to complete + // + while ((MmioRead16 (Address) & B_PCH_RCRB_V1STS_NP) != 0); + + return EFI_SUCCESS; +} + +/** + The function performing TC/VC mapping program, and poll all PCH Virtual Channel + until negotiation completion + + @param[in] PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS The function completed successfully + @retval Others All other error conditions encountered result in an ASSERT. +**/ +EFI_STATUS +EFIAPI +PchDmiTcVcProgPoll ( + IN EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + PCH_DMI_TC_VC_PPI *PchDmiTcVcMapPpi; + UINT32 RootComplexBar; + UINT8 Index; + UINT8 VcMap[DmiVcTypeMax] = { 0 }; + + /// + /// Locate PchDmiTcVcMap Ppi + /// + Status = (*PeiServices)->LocatePpi (PeiServices, &gPchDmiTcVcMapPpiGuid, 0, NULL, (VOID **)&PchDmiTcVcMapPpi); + ASSERT_EFI_ERROR (Status); + RootComplexBar = PCH_RCRB_BASE; + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 7.1.5 + /// Step 3.1 + /// RCBA + Offset 50h[19] = 1b + /// Step 3.2 + /// RCBA + Offset 50h[23:20] = 2h and RCBA + Offset 50h[17] = 1b, + /// ensure that D29/D26:F0:88h [2] = 0b (Done at PchMiscInit() on PchInitPeim.c) + /// + MmioAndThenOr32 (RootComplexBar + R_PCH_RCRB_CIR0050, (UINT32) (~0x00F00000), (UINT32) (0x00200000)); + + if (PchDmiTcVcMapPpi->DmiVc[DmiVcTypeVcp].Enable == PCH_DEVICE_ENABLE) { + MmioOr32 (RootComplexBar + R_PCH_RCRB_CIR0050, BIT17 | BIT19); + } + /// + /// Reads back for posted write to take effect + /// + MmioRead32 (RootComplexBar + R_PCH_RCRB_CIR0050); + + /// + /// Step 3.3, Step 3.4, Step 3.5, Step 3,6, Set the TC/VC mappings + /// + for (Index = 0; Index < DmiTcTypeMax; Index++) { + DEBUG ((EFI_D_INFO, "TC:%0x VC:%0x!\n", Index, PchDmiTcVcMapPpi->DmiTc[Index].Vc)); + VcMap[PchDmiTcVcMapPpi->DmiTc[Index].Vc] |= (BIT0 << Index); + } + + for (Index = 0; Index < DmiVcTypeMax; Index++) { + DEBUG ((EFI_D_INFO, "VC:%0x VCID:%0x Enable:%0x!\n",Index, PchDmiTcVcMapPpi->DmiVc[Index].VcId, PchDmiTcVcMapPpi->DmiVc[Index].Enable)); + if (PchDmiTcVcMapPpi->DmiVc[Index].Enable == PCH_DEVICE_ENABLE) { + PchSetDmiTcVcMapping ( + RootComplexBar, + Index, + PchDmiTcVcMapPpi->DmiVc[Index].VcId, + VcMap[Index] + ); + } + } + /// + /// Step 3.7 + /// Set RCBA + Offset 50h[31] = 1b + /// Lock down the TC mapping if no further changes are required to bits [30:16] + /// + MmioOr32 (RootComplexBar + R_PCH_RCRB_CIR0050, B_PCH_RCRB_CIR0_TCLOCKDN); + /// + /// Reads back for posted write to take effect + /// + MmioRead32 (RootComplexBar + R_PCH_RCRB_CIR0050); + + /// + /// Step 3.8 + /// After both above and System Agent DMI TC/VC mapping are programmed, + /// poll VC negotiation pending status until is zero: + /// 3.8.1 RCBA + Offset 201Ah[1] + /// 3.8.2 RCBA + Offset 2026h[1] + /// 3.8.3 RCBA + Offset 2036h[1] + /// 3.8.4 RCBA + Offset 2046h[1] + /// + for (Index = 0; Index < DmiVcTypeMax; Index++) { + if (PchDmiTcVcMapPpi->DmiVc[Index].Enable == PCH_DEVICE_ENABLE) { + PchPollDmiVcStatus (RootComplexBar, Index); + } + } + + return EFI_SUCCESS; +} + +/** + The function set the Target Link Speed in PCH to DMI GEN 2. + + @param[in] PeiServices General purpose services available to every PEIM. + + @retval None +**/ +VOID +EFIAPI +PchDmiGen2Prog ( + IN EFI_PEI_SERVICES **PeiServices + ) +{ +#ifdef TRAD_FLAG + UINT32 RootComplexBar; + + if (GetPchSeries() == PchH) { + DEBUG ((EFI_D_INFO, "PchDmiGen2Prog() Start\n")); + RootComplexBar = PCH_RCRB_BASE; + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 7.1.5 + /// Step 2 + /// Configure DMI Link Speed as early as possible + /// Step 2.1 + /// Please refer to the System Agent BIOS Writer's Guide on Supported Link Speed + /// field in Link Capabilities register in CPU complex. (Done in SA code) + /// Step 2.2 + /// If the Supported Link Speed in CPU complex is 0010b (Done in SA code) + /// and RCBA + Offset 21A4h[3:0] = 0010b + /// + if ((MmioRead32 (RootComplexBar + R_PCH_RCRB_LCAP) & B_PCH_RCRB_LCAP_MLS) == 0x02) { + /// + /// Step 2.2.1 + /// Set RCBA + Offset 21B0h[3:0] = 0010b + /// + MmioAndThenOr8 (RootComplexBar + 0x21B0, (UINT8)~(BIT3 | BIT2 | BIT1 | BIT0), (UINT8) BIT1); + /// + /// Step 2.2.2 + /// Please refer to the System Agent BIOS Writer's Guide to perform DMI Link Retrain after + /// configures new DMI Link Speed. (Done in SA code) + /// + } + DEBUG ((EFI_D_INFO, "PchDmiGen2Prog() End\n")); + } +#endif // TRAD_FLAG +} + +/** + The function program DMI miscellaneous registers. + + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval EFI_SUCCESS The DMI required settings programmed correctly +**/ +EFI_STATUS +EFIAPI +PchDmiMiscProg ( + IN EFI_PEI_SERVICES **PeiServices, + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ) +{ + UINT32 RootComplexBar; + EFI_STATUS Status; + UINT16 LpcDeviceId; + UINTN PciD31F0RegBase; + UINTN PciD28F0RegBase; + UINTN PciD20F0RegBase; + UINT32 Data32And; + UINT32 Data32Or; + UINT16 i; + UINT16 size; + UINT8 DeviceLaneOwner; + UINT32 StrpFuseCfg1; + UINT8 GbePort; +#ifdef ULT_FLAG + UINTN RPBase; + UINT8 PortIndex; +#endif // ULT_FLAG + PCH_SERIES PchSeries; + UINT8 PchSteppingValue; + UINT32 Msg; + UINT32 MsgTimeout; + UINT32 PchChipsetInitTableId; + UINT32 PchChipsetInitTableLength; + UINT8 *PchChipsetInitTable; + HECI_FWS_REGISTER MeHfs; + CHIPSET_INIT_INFO_HOB *ChipsetInitHob; + EFI_BOOT_MODE BootMode; +#ifdef TRAD_FLAG + IOBP_MMIO_TABLE_STRUCT *PchDmiHsio; +#endif // TRAD_FLAG + IOBP_MMIO_TABLE_STRUCT *PchUsb3Hsio; + IOBP_MMIO_TABLE_STRUCT *PchUsb3SharedHsio; + IOBP_MMIO_TABLE_STRUCT *PchGbeSharedHsio; + + PchSeries = GetPchSeries(); + Status = EFI_SUCCESS; + RootComplexBar = PchPlatformPolicyPpi->Rcba; + PchChipsetInitTable = NULL; + PchChipsetInitTableLength = 0; + Msg = 0; + MsgTimeout = MAX_ME_MSG_ACK_TIMEOUT; + PciD31F0RegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); + PciD28F0RegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1, + 0 + ); + PciD20F0RegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_XHCI, + PCI_FUNCTION_NUMBER_PCH_XHCI, + 0 + ); + LpcDeviceId = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_DEVICE_ID); + PchSteppingValue = PchStepping(); + // + // Get PchSeries and assign the appropriate ChipsetInit table + // + switch (PchSteppingValue) { +#ifdef ULT_FLAG + case LptLpB0: + case LptLpB1: + case LptLpB2: + PchChipsetInitTable = PchChipsetInitTableLptLp_Bx; + PchChipsetInitTableLength = sizeof(PchChipsetInitTableLptLp_Bx); + break; +#endif // ULT_FLAG +#ifdef TRAD_FLAG + case LptHB0: + PchChipsetInitTable = PchChipsetInitTableLptH_B0; + PchChipsetInitTableLength = sizeof(PchChipsetInitTableLptH_B0); + break; + case LptHC0: + case LptHC1: + case LptHC2: + PchChipsetInitTable = PchChipsetInitTableLptH_Cx; + PchChipsetInitTableLength = sizeof(PchChipsetInitTableLptH_Cx); + break; +#endif // TRAD_FLAG + default: + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + + // + // GetBoodMode, do not perform ChipsetInit check on S3 RESUME + // + Status = PeiServicesGetBootMode(&BootMode); + if(BootMode != BOOT_ON_S3_RESUME) { + // + // Create Hob to send ChipsetInit table status to DXE phase. + // + DEBUG((EFI_D_INFO, "(Hsio) Creating HOB to adjust Hsio settings from DXE, if required.\n")); + Status = (**PeiServices).CreateHob ( + PeiServices, + EFI_HOB_TYPE_GUID_EXTENSION, + sizeof (CHIPSET_INIT_INFO_HOB), + &ChipsetInitHob + ); + ASSERT_EFI_ERROR (Status); + + // + // Initialize ChipsetInitHob + // + ChipsetInitHob->Header.Name = gChipsetInitHobGuid; + ChipsetInitHob->ChipsetInitTableLen = PchChipsetInitTableLength; + ChipsetInitHob->ChipsetInitTableUpdReq = 0; + + // + // Set the Host To ME flag requestint the Hsio ChipsetInit Table Version applied by ME FW + // + HeciPciAndThenOr32(R_ME_H_GS, 0, (H2M_HSIO_MESSAGE | H2M_HSIO_CMD_GETHSIOVER)); + + // + // Wait for the acknowledge from the FW, once it completes data should be in the FWSTS register + // Wait max of 100ms for FW to acknowledge. + // + do { + // + // Delay 1us. Need to give some time for ME to respond. + // + PchPmTimerStall(1); + MeHfs.ul = HeciPciRead32(R_ME_HFS); + MsgTimeout--; + if (MsgTimeout == 0) { + DEBUG ((EFI_D_INFO, "(Hsio) ME FW failed to acknowledge the GETHsioVER command.\n")); + Status = EFI_TIMEOUT; + // + // Do not assert until a supporting ME FW is available + // + // ASSERT_EFI_ERROR(Status); + break; + } + } while (MeHfs.r.BiosMessageAck != M2H_HSIO_MSG_ACK); + if (MsgTimeout > 0) { + DEBUG ((EFI_D_INFO, "(Hsio) The GETHsioVER command was acknowledged by ME FW.\n")); + } + + // + // If successfully got the ACK from ME, then the Hsio Version info should be in the FWSTATUS register + // Otherwise, just continue Hsio programming assuming the ChipsetInit settings programmed through other means. + // + if (Status == EFI_SUCCESS) { + // + // Receive the Hsio Version reported by ME FW. + // + Msg = HeciPciRead32(R_ME_HFS_5); + DEBUG((EFI_D_INFO, "(Hsio) ME Reported Hsio Version:%d CRC=0x%04X Response=%d us\n", (Msg>>16), (Msg&0xFFFF), MAX_ME_MSG_ACK_TIMEOUT - MsgTimeout)); + + // + // Send final message back to ME so that it can restore the FWSTS5 value (used for other messaging) + // + HeciPciAndThenOr32 (R_ME_H_GS, 0, H2M_HSIO_MESSAGE | H2M_HSIO_CMD_CLOSE); + + // + // Get ChipsetInit table indentifier from the one found in the code + // + if(PchChipsetInitTable != NULL) { + PchChipsetInitTableId = *((UINT32*)PchChipsetInitTable); + DEBUG((EFI_D_INFO, "(Hsio) BIOS Hsio Version:%d CRC=0x%04X Length=%d bytes.\n", (PchChipsetInitTableId>>16),(PchChipsetInitTableId&0xFFFF), PchChipsetInitTableLength)); + + // + // If expected table id is not found, then skip the rest of the Hsio programming until it can be updated from DXE + // + if (Msg != PchChipsetInitTableId) { + // + // Pass the expected ChipsetInit table to the DXE code that will apply the settings to ME and reset. + // + ChipsetInitHob->ChipsetInitTableUpdReq = 1; + // + // Copy the ChipsetInit settings from local table into the HOB + // + if (sizeof(ChipsetInitHob->ChipsetInitTable) >= PchChipsetInitTableLength) { + CopyMem (ChipsetInitHob->ChipsetInitTable, PchChipsetInitTable, PchChipsetInitTableLength); + } else { + ASSERT(FALSE); // Table should always fit into HOB structure. + } + + // + // Skip the Hsio programming, DMI setting in ChipsetInit table should be good enough to get through DMI init. + // + return Status; + } + } else { + ASSERT(FALSE); + } + } + } + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 7.1.5 + /// Step 1.1 + /// RCBA + Offset 2088h = 00109000h + /// + MmioWrite32 ( + (RootComplexBar + R_PCH_RCRB_CIR2088), + 0x00109000 + ); + /// + /// Step 1.2 + /// RCBA + offset 20ACh[30] = 1b + /// + MmioOr32 (RootComplexBar + R_PCH_RCRB_REC, BIT30); + if (PchSeries == PchH) { + /// + /// Step 1.3 + /// Set RCBA + Offset 2340h[7:0] = 1Bh + /// + MmioWrite8 (RootComplexBar + 0x2340, 0x1B); + /// + /// Step 1.4 + /// Set RCBA + Offset 2340h[23:16] = 3Ah + /// + Data32And = (UINT32) 0xFF00FFFF; + Data32Or = (UINT32) (0x3A << 16); + + MmioAndThenOr32 ( + RootComplexBar + 0x2340, + Data32And, + Data32Or + ); + /// + /// Step 1.5 + /// Program RCBA + Offset 2324[31:0] = 00854C74h + /// + MmioWrite32 (RootComplexBar + 0x2324, 0x00854C74); + } + + /// + /// Program Hsio Setting + /// + DeviceLaneOwner = MmioRead8 (PciD28F0RegBase + 0x410); + StrpFuseCfg1 = MmioRead32 (PciD28F0RegBase + R_PCH_PCIE_STRPFUSECFG); +#ifdef TRAD_FLAG + /// + /// PCH BIOS Spec Rev 0.5.6, Section 7.1.5 + /// Step 6 + /// Bios is required to program IOBP setting according to the following table: + /// Table 7-10 DMI Lane Setting + /// + if (PchSeries == PchH) { + switch (PchSteppingValue) { + case LptHB0: + size = (sizeof (PchDmiHsioLptH_B0) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchDmiHsio = PchDmiHsioLptH_B0; + break; + default: + PchDmiHsio = NULL; + size = 0; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + for (i = 0; i < size; i++) { + Status = ProgramIobp ( + RootComplexBar, + PchDmiHsio[i].Address, + PchDmiHsio[i].AndMask, + PchDmiHsio[i].OrMask + ); + ASSERT_EFI_ERROR (Status); + } + } +#endif // TRAD_FLAG + + /// + /// PCH BIOS Spec Rev 0.5.6, Section 7.1.5 + /// Table 7-3 USB3 dedicated lane Setting + /// + switch (PchSteppingValue) { +#ifdef ULT_FLAG + case LptLpB0: + case LptLpB1: + case LptLpB2: + size = (sizeof (PchUsb3HsioLptLp_Bx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchUsb3Hsio = PchUsb3HsioLptLp_Bx; + break; +#endif // ULT_FLAG +#ifdef TRAD_FLAG + case LptHB0: + size = (sizeof (PchUsb3HsioLptH_B0) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchUsb3Hsio = PchUsb3HsioLptH_B0; + break; + case LptHC0: + case LptHC1: + case LptHC2: + size = (sizeof (PchUsb3HsioLptH_Cx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchUsb3Hsio = PchUsb3HsioLptH_Cx; + break; +#endif // TRAD_FLAG + default: + PchUsb3Hsio = NULL; + size = 0; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + for (i = 0; i < size; i++) { + Status = ProgramIobp ( + RootComplexBar, + PchUsb3Hsio[i].Address, + PchUsb3Hsio[i].AndMask, + PchUsb3Hsio[i].OrMask + ); + ASSERT_EFI_ERROR (Status); + } + + /// + /// PCH BIOS Spec Rev 0.5.6, Section 7.1.5 + /// Table 7-5 USB3 Shared laneSetting + /// + switch (PchSteppingValue) { +#ifdef ULT_FLAG + case LptLpB0: + case LptLpB1: + case LptLpB2: + size = (sizeof (PchUsb3SharedHsioLptLp_Bx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchUsb3SharedHsio = PchUsb3SharedHsioLptLp_Bx; + break; +#endif // ULT_FLAG +#ifdef TRAD_FLAG + case LptHB0: + size = (sizeof (PchUsb3SharedHsioLptH_B0) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchUsb3SharedHsio = PchUsb3SharedHsioLptH_B0; + break; + case LptHC0: + case LptHC1: + case LptHC2: + size = (sizeof (PchUsb3SharedHsioLptH_Cx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchUsb3SharedHsio = PchUsb3SharedHsioLptH_Cx; + break; +#endif // TRAD_FLAG + default: + PchUsb3SharedHsio = NULL; + size = 0; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + for (i = 0; i < size; i++) { + if (PchSeries == PchLp) { + if ((((PchUsb3SharedHsio[i].Address & 0xFE00) == 0x2400) && ((DeviceLaneOwner & (BIT1 | BIT0)) != BIT1)) || + (((PchUsb3SharedHsio[i].Address & 0xFE00) == 0x2600) && ((DeviceLaneOwner & (BIT3 | BIT2)) != BIT3))) { + continue; + } + } else if (PchSeries == PchH) { + if ((((PchUsb3SharedHsio[i].Address & 0xFE00) == 0x2C00) && ((DeviceLaneOwner & (BIT3 | BIT2)) != BIT3)) || + (((PchUsb3SharedHsio[i].Address & 0xFE00) == 0x2E00) && ((DeviceLaneOwner & (BIT1 | BIT0)) != BIT1))) { + continue; + } + } + Status = ProgramIobp ( + RootComplexBar, + PchUsb3SharedHsio[i].Address, + PchUsb3SharedHsio[i].AndMask, + PchUsb3SharedHsio[i].OrMask + ); + ASSERT_EFI_ERROR (Status); + } + + /// + /// Table 7-9 Gbe Lane Setting + /// Bios should check the PCIE port that is assigned to Gbe and program the following address accordingly + /// + switch (PchSteppingValue) { +#ifdef ULT_FLAG + case LptLpB0: + case LptLpB1: + case LptLpB2: + PchGbeSharedHsio = PchGbeSharedHsioLptLp_Bx; + size = (sizeof (PchGbeSharedHsioLptLp_Bx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + break; +#endif // ULT_FLAG +#ifdef TRAD_FLAG + case LptHB0: + PchGbeSharedHsio = PchGbeSharedHsioLptH_B0; + size = (sizeof (PchGbeSharedHsioLptH_B0) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + break; + case LptHC0: + case LptHC1: + case LptHC2: + PchGbeSharedHsio = PchGbeSharedHsioLptH_Cx; + size = (sizeof (PchGbeSharedHsioLptH_Cx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + break; +#endif // TRAD_FLAG + default: + PchGbeSharedHsio = NULL; + size = 0; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + + + if (PchGbeSharedHsio != NULL) { + if ((StrpFuseCfg1 & B_PCH_PCIE_STRPFUSECFG_GBE_PCIE_PEN) != 0) { + GbePort = (UINT8) ((StrpFuseCfg1 & B_PCH_PCIE_STRPFUSECFG_GBE_PCIEPORTSEL) >> N_PCH_PCIE_STRPFUSECFG_GBE_PCIEPORTSEL); + } else { + GbePort = 0xFF; + } + + if (GbePort != 0xFF) { +#ifdef ULT_FLAG + if (PchSeries == PchLp) { + if (GbePort <= 0x5) { + Status = ProgramIobp ( + RootComplexBar, + PchGbeSharedHsio[GbePort].Address, + PchGbeSharedHsio[GbePort].AndMask, + PchGbeSharedHsio[GbePort].OrMask + ); + ASSERT_EFI_ERROR (Status); + } + } +#endif // ULT_FLAG +#ifdef TRAD_FLAG + if (PchSeries == PchH) { + if (GbePort == 0x0) { + if ((DeviceLaneOwner & (BIT1 | BIT0)) == BIT0) { + Status = ProgramIobp ( + RootComplexBar, + PchGbeSharedHsio[GbePort].Address, + PchGbeSharedHsio[GbePort].AndMask, + PchGbeSharedHsio[GbePort].OrMask + ); + ASSERT_EFI_ERROR (Status); + } + } else if (GbePort == 0x1) { + if ((DeviceLaneOwner & (BIT3 | BIT2)) == BIT2) { + Status = ProgramIobp ( + RootComplexBar, + PchGbeSharedHsio[GbePort].Address, + PchGbeSharedHsio[GbePort].AndMask, + PchGbeSharedHsio[GbePort].OrMask + ); + ASSERT_EFI_ERROR (Status); + } + } else { + Status = ProgramIobp ( + RootComplexBar, + PchGbeSharedHsio[GbePort].Address, + PchGbeSharedHsio[GbePort].AndMask, + PchGbeSharedHsio[GbePort].OrMask + ); + ASSERT_EFI_ERROR (Status); + } + } +#endif // TRAD_FLAG + } + } + /// + /// Step 7 + /// For LP, clear B0:D28:F0~F7:110h[13, 12, 8:6, 0] = 1b, 1b, 111b, 1b + /// For LP, clear B0:D28:F0~F7:104h[20, 18:14, 12, 4] = 1b, 11111b, 1b, 1b + /// +#ifdef ULT_FLAG + if (GetPchSeries() == PchLp) { + for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex++) { + RPBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + PortIndex, + 0 + ); + MmioOr32 (RPBase + R_PCH_PCIE_CES, (UINT32)(B_PCH_PCIE_CES_ANFES | B_PCH_PCIE_CES_RTT | + B_PCH_PCIE_CES_RNR | B_PCH_PCIE_CES_BD | + B_PCH_PCIE_CES_BT | B_PCH_PCIE_CES_RE)); + MmioOr32 (RPBase + R_PCH_PCIE_UES, (UINT32)(B_PCH_PCIE_UES_URE | B_PCH_PCIE_UES_MT | + B_PCH_PCIE_UES_RO | B_PCH_PCIE_UES_UC | + B_PCH_PCIE_UES_CA | B_PCH_PCIE_UES_CT | + B_PCH_PCIE_UES_PT | B_PCH_PCIE_UES_DLPE)); + } + } +#endif //ULT_FLAG + + /// + /// Step 8 + /// Bios is required to program IOBP setting according to the table 7-7 to 7-8 + /// using 7.1.4 IOSF SBI with OPCODE "PHY Configuration Register". + /// Done in PchSataInit(). + /// + /// PCH BIOS Spec Rev 0.5.1, Section 7.1.5 + /// Step 9 + /// IOBP Programming: + /// For Mobile: + /// BIOS is required to program IOBP setting according to Table 7-11 and + /// Table 7-12 using settings in Section 7.1.4 with OPCODE "PHY Configuration Register". + /// For Desktop: + /// BIOS is required to program IOBP setting according to Table 7-13 and + /// Table 7-14 using settings in Section 7.1.4 with OPCODE "PHY Configuration Register". + /// Done in PchSataInit(). + /// + /// Step 10, 11 + /// Set D20:F0:B0h[7] to 0b + /// Set D20:F0:B0h[16] to 1b + /// + Data32And = (UINT32) ~(BIT7); + Data32Or = (UINT32) (BIT16); + + MmioAndThenOr32 ( + PciD20F0RegBase + 0xB0, + Data32And, + Data32Or + ); + if (GetPchSeries() == PchLp) { + /// + /// Step 12 + /// Sideband Minimum Duration. T_SB_MIN = 16ns + /// RCBA + Offset 260Ch[15:0]=0010h + /// + MmioWrite16 ( + (RootComplexBar + 0x260C), + 0x0010 + ); + /// + /// Step x + /// Program Iobp 0xEC000106 to 3100h + /// + Status = ProgramIobp ( + RootComplexBar, + 0xEC000106, + (UINT32)~(0x00003100), + 0x00003100 + ); + ASSERT_EFI_ERROR (Status); + } + return Status; +} diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitCommon.h b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitCommon.h new file mode 100644 index 0000000..be59220 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitCommon.h @@ -0,0 +1,73 @@ +/** @file + Header file for the PCH Common Init PEIM. + +@copyright + Copyright (c) 2009 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ +#ifndef _PCH_INIT_COMMON_PEIM_H_ +#define _PCH_INIT_COMMON_PEIM_H_ + +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "EdkIIGluePeim.h" +#include EFI_PPI_CONSUMER (PchPlatformPolicy) +#include EFI_PPI_CONSUMER (PchUsbPolicy) +#endif + +#define PCH_INIT_COMMON_SCRIPT_IO_WRITE(TableName, Width, Address, Count, Buffer) + +#define PCH_INIT_COMMON_SCRIPT_IO_READ_WRITE(TableName, Width, Address, Data, DataMask) + +#define PCH_INIT_COMMON_SCRIPT_MEM_WRITE(TableName, Width, Address, Count, Buffer) + +#define PCH_INIT_COMMON_SCRIPT_MEM_READ_WRITE(TableName, Width, Address, Data, DataMask) + +#define PCH_INIT_COMMON_SCRIPT_PCI_CFG_WRITE(TableName, Width, Address, Count, Buffer) + +#define PCH_INIT_COMMON_SCRIPT_PCI_CFG_READ_WRITE(TableName, Width, Address, Data, DataMask) + +#define PCH_INIT_COMMON_SCRIPT_STALL(TableName, Duration) + +#define PCH_INIT_COMMON_SCRIPT_SAVE_IOBP_S3_ITEM(RootComplexBar, Address, AndMask, OrMask) \ + EFI_SUCCESS + +#ifdef USB_PRECONDITION_ENABLE_FLAG +/// +/// Execute function when running in PEI +/// +#define USB_RUN_IN_PEI TRUE + +/// +/// Execute function when running in DXE +/// It is always FALSE for PEI phase check +/// +#define USB_RUN_IN_DXE FALSE + +/// +/// USB precondition policy check +/// +#define USB_PRECONDITION_POLICY_SUPPORT(UsbPolicy) \ + ((UsbPolicy)->UsbPrecondition) + +#endif // USB_PRECONDITION_ENABLE_FLAG + +/// +/// USB3 port setting policy check +/// +#define USB3PORT_SETTING_POLICY_SUPPORT(Revision) \ + ((Revision >= PCH_PLATFORM_POLICY_PPI_REVISION_3)) + +#endif diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.c new file mode 100644 index 0000000..12133c7 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.c @@ -0,0 +1,2232 @@ +/** @file + The PCH Init PEIM implements the PCH PEI Init PPI. + +@copyright + Copyright (c) 2004 - 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#include "PchInitPeim.h" + +// +// Global variables +// +static PCH_DMI_TC_VC_PPI mPchDmiTcVcMap = { + { + DmiVcTypeVc0, + DmiVcTypeVc1, + DmiVcTypeVcp, + DmiVcTypeVc0, + DmiVcTypeVc0, + DmiVcTypeVc0, + DmiVcTypeVc0, + DmiVcTypeVcm + }, + { + {PCH_DEVICE_ENABLE, (UINT8) 0}, + {PCH_DEVICE_ENABLE, (UINT8) 1}, + {PCH_DEVICE_ENABLE, (UINT8) 2}, + {PCH_DEVICE_ENABLE, (UINT8) 7} + } +}; + +static PCH_INIT_PPI mPchInitPpi = { + PchUsbInit, + PchDmiTcVcProgPoll, + PchDmiGen2Prog, + PchCpuStrapSet +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiListVariable = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPchInitPpiGuid, + &mPchInitPpi +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiPchPeiInitDone = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPchPeiInitDonePpiGuid, + NULL +}; + +static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = { + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gPchPlatformPolicyPpiGuid, + PchInitialize +}; + +EFI_GUID gEfiPeiEndOfPeiPhasePpiGuid = EFI_PEI_END_OF_PEI_PHASE_PPI_GUID; +static EFI_PEI_NOTIFY_DESCRIPTOR mPchS3ResumeNotifyDesc = { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiEndOfPeiPhasePpiGuid, + PchS3ResumeAtEndOfPei +}; +// +// Functions +// + +/** + Internal function performing SATA init needed in PEI phase + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval EFI_SUCCESS No platform reset action is taken. System can continue boot flow. + @retval Others Won't return if platform reset action is taken +**/ +EFI_STATUS +EFIAPI +PchSataInit ( + IN EFI_PEI_SERVICES **PeiServices, + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ) +{ + + UINT32 Data32And; + UINT32 Data32Or; + UINTN PciD31F0RegBase; + UINT16 LpcDeviceId; + UINTN PciD31F2RegBase; + UINTN PciD28F0RegBase; + BOOLEAN SkipSataInit; + UINT16 i; + UINT16 GSpeed; + UINT16 PortId; + UINT8 RxEq; + UINT32 OrMask; + UINT16 size; + UINT32 RootComplexBar; + UINT8 DeviceLaneOwner; + EFI_STATUS Status; + PCH_SERIES PchSeries; + UINT32 PchSataTraceId; +#ifdef TRAD_FLAG + IOBP_MMIO_TABLE_STRUCT *PchSataHsio; + IOBP_MMIO_TABLE_STRUCT *PchSataHsio_MB; + IOBP_MMIO_TABLE_STRUCT *PchSataHsio_DT; + IOBP_SATA_RXEQ_TABLE *PchSataRxEqHsio; +#endif // TRAD_FLAG + IOBP_MMIO_TABLE_STRUCT *PchSataSharedHsio; + IOBP_MMIO_TABLE_STRUCT *PchSataSharedHsio_MB; + IOBP_MMIO_TABLE_STRUCT *PchSataSharedHsio_DT; + IOBP_SATA_RXEQ_TABLE *PchSataRxEqSharedHsio; + + DEBUG ((EFI_D_INFO, "PchSataInit() - Start\n")); + + PchSeries = GetPchSeries(); + RootComplexBar = PCH_RCRB_BASE; + PciD31F0RegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); + LpcDeviceId = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_DEVICE_ID); + PciD31F2RegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_SATA, + PCI_FUNCTION_NUMBER_PCH_SATA, + 0 + ); + PciD28F0RegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1, + 0 + ); + SkipSataInit = FALSE; + + /// + /// Skip SATA init if any of SATA port0 ~ port3 is enabled + /// + if ((MmioRead8 (PciD31F2RegBase + R_PCH_SATA_PCS) & (UINT8) (B_PCH_SATA_PCS_PORT3_EN | + B_PCH_SATA_PCS_PORT2_EN | + B_PCH_SATA_PCS_PORT1_EN | + B_PCH_SATA_PCS_PORT0_EN)) != 0) { + SkipSataInit = TRUE; + } + if (PchSeries == PchH) { + /// + /// Skip SATA init if SATA port4 or port5 is enabled + /// + if ((MmioRead8 (PciD31F2RegBase + R_PCH_SATA_PCS) & (UINT8) (B_PCH_SATA_PCS_PORT5_EN | + B_PCH_SATA_PCS_PORT4_EN)) != 0) { + SkipSataInit = TRUE; + } + } + if (SkipSataInit == TRUE) { + if (PchSeries == PchH) { + /// + /// Any SATA port should not be enabled unless CPU only reset. + /// The value of 0xEA000AAC[5:4] is 10b after issuing CPU only reset. + /// Note: + /// The default value of 0xEA000AAC[5:4] is 00b. + /// The following "if" condition will need to update while the + /// BIOS recommended setting of 0xEA000AAC[5:4] is changed. + /// Asset if any SATA port is enabled before SATA Hsio initialization is done + /// + Status = ReadIobp (RootComplexBar, 0xEA000AAC, &Data32And); + if ((Data32And & (UINT32) (BIT4 | BIT5)) != 0x20) { + DEBUG ((EFI_D_ERROR, "Please do not enable any SATA port before SATA Hsio initialization is done.\n")); + ASSERT (0); + } + } + } else { + /// + /// Assume SATA mode will be AHCI, SATA Port 0 - Port 5 are all for D31:F2 + /// + if (PchSeries == PchH) { + MmioAndThenOr8 ( + PciD31F2RegBase + R_PCH_SATA_MAP, + (UINT8) (~B_PCH_SATA_MAP_SMS_MASK), + (UINT8) (V_PCH_SATA_MAP_SMS_AHCI | B_PCH_SATA_PORT_TO_CONTROLLER_CFG) + ); + } else if (PchSeries == PchLp) { + MmioAndThenOr8 ( + PciD31F2RegBase + R_PCH_SATA_MAP, + (UINT8) (~B_PCH_SATA_MAP_SMS_MASK), + (UINT8) (V_PCH_SATA_MAP_SMS_AHCI) + ); + } + /// + /// PCH BIOS Spec Rev 0.5.0 section 14.1.7 Additional Programming Requirements during + /// SATA Initialization + /// Step 2 + /// System BIOS must set D31:F2:Reg 94h[8:0] = 183h as part of the chipset initialization + /// prior to SATA configuration. These bits should be restored while resuming from a S3 + /// sleep state. + /// + Data32And = (UINT32)~(BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0); + Data32Or = 0x183; + MmioAndThenOr32 ( + (UINTN) (PciD31F2RegBase + R_PCH_SATA_SCLKCG), + Data32And, + Data32Or + ); + /// + /// Step 3 + /// D31:F2:Reg 92h[15] = 1b + /// Set OOB Retry Mode bit of Port Control and Status (PCS) register + /// These bits should be restored while resuming from a S3 sleep state + /// + MmioOr16 ((UINTN) (PciD31F2RegBase + R_PCH_SATA_PCS), (UINT16) (B_PCH_SATA_PCS_OOB_RETRY)); + /// + /// Step 4 + /// System BIOS must program SATA Hsio table as stated in Table 7-7 to 7-8 BEFORE the SATA + /// ports are enabled. + /// + /// PCH BIOS Spec Rev 0.5.6, Section 7.1.5 + /// Step 8 + /// Bios is required to program IOBP setting according to the table 7-7 to 7-8 + /// using 7.1.4 IOSF SBI with OPCODE "PHY Configuration Register". + /// Table 7-7 SATA dedicated lane setting + /// + DeviceLaneOwner = MmioRead8 (PciD28F0RegBase + 0x410); +#ifdef TRAD_FLAG + switch (PchStepping()) { + case LptHB0: + size = (sizeof (PchSataHsioLptH_B0) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataHsio = PchSataHsioLptH_B0; + break; + case LptHC0: + case LptHC1: + case LptHC2: + size = (sizeof (PchSataHsioLptH_Cx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataHsio = PchSataHsioLptH_Cx; + break; + default: + PchSataHsio = NULL; + size = 0; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + + for (i = 0; i < size; i++) { + Status = ProgramIobp ( + RootComplexBar, + PchSataHsio[i].Address, + PchSataHsio[i].AndMask, + PchSataHsio[i].OrMask + ); + ASSERT_EFI_ERROR (Status); + } +#endif // TRAD_FLAG + /// + /// Table 7-8 SATA Shared lane setting + /// + switch (PchStepping()) { +#ifdef ULT_FLAG + case LptLpB0: + case LptLpB1: + case LptLpB2: + size = (sizeof (PchSataSharedHsioLptLp_Bx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataSharedHsio = PchSataSharedHsioLptLp_Bx; + break; +#endif // ULT_FLAG +#ifdef TRAD_FLAG + case LptHB0: + size = (sizeof (PchSataSharedHsioLptH_B0) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataSharedHsio = PchSataSharedHsioLptH_B0; + break; + case LptHC0: + case LptHC1: + case LptHC2: + size = (sizeof (PchSataSharedHsioLptH_Cx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataSharedHsio = PchSataSharedHsioLptH_Cx; + break; +#endif // TRAD_FLAG + default: + size = 0; + PchSataSharedHsio = NULL; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + for (i = 0; i < size; i++) { + if (PchSeries == PchLp) { + if ((((PchSataSharedHsio[i].Address & 0xFE00) == 0x2000) && ((DeviceLaneOwner & BIT4) == BIT4)) || + (((PchSataSharedHsio[i].Address & 0xFE00) == 0x2200) && ((DeviceLaneOwner & BIT5) == BIT5)) || + (((PchSataSharedHsio[i].Address & 0xFE00) == 0x2400) && ((DeviceLaneOwner & BIT6) == BIT6)) || + (((PchSataSharedHsio[i].Address & 0xFE00) == 0x2600) && ((DeviceLaneOwner & BIT7) == BIT7))) { + continue; + } + } else if (PchSeries == PchH) { + if ((((PchSataSharedHsio[i].Address & 0xFE00) == 0x2000) && ((DeviceLaneOwner & BIT4) == BIT4)) || + (((PchSataSharedHsio[i].Address & 0xFE00) == 0x2200) && ((DeviceLaneOwner & BIT5) == BIT5))) { + continue; + } + } + Status = ProgramIobp ( + RootComplexBar, + PchSataSharedHsio[i].Address, + PchSataSharedHsio[i].AndMask, + PchSataSharedHsio[i].OrMask + ); + ASSERT_EFI_ERROR (Status); + } + + /// + /// PCH BIOS Spec Rev 0.5.1, Section 7.1.5 + /// Step 9 + /// IOBP Programming: + /// For Mobile: + /// BIOS is required to program IOBP setting according to Table 7-11 and + /// Table 7-12 using settings in Section 7.1.4 with OPCODE "PHY Configuration Register". + /// + if (IS_PCH_LPT_LPC_DEVICE_ID_MOBILE (LpcDeviceId)) { +#ifdef TRAD_FLAG + /// + /// Table 7-11 SATA Dedicated Lane Setting + /// + switch (PchStepping()) { + case LptHB0: + size = (sizeof (PchSataHsioLptH_MB_B0) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataHsio_MB = PchSataHsioLptH_MB_B0; + break; + case LptHC0: + case LptHC1: + case LptHC2: + size = (sizeof (PchSataHsioLptH_MB_Cx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataHsio_MB = PchSataHsioLptH_MB_Cx; + break; + default: + size = 0; + PchSataHsio_MB = NULL; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + for (i = 0; i < size; i++) { + Status = ProgramIobp ( + RootComplexBar, + PchSataHsio_MB[i].Address, + PchSataHsio_MB[i].AndMask, + PchSataHsio_MB[i].OrMask + ); + ASSERT_EFI_ERROR (Status); + } +#endif // TRAD_FLAG + /// + /// Table 7-12 SATA Shared Lane Setting + /// + switch (PchStepping()) { +#ifdef ULT_FLAG + case LptLpB0: + case LptLpB1: + case LptLpB2: + size = (sizeof (PchSataSharedHsioLptLp_MB_Bx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataSharedHsio_MB = PchSataSharedHsioLptLp_MB_Bx; + break; +#endif // ULT_FLAG +#ifdef TRAD_FLAG + case LptHB0: + size = (sizeof (PchSataSharedHsioLptH_MB_B0) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataSharedHsio_MB = PchSataSharedHsioLptH_MB_B0; + break; + case LptHC0: + case LptHC1: + case LptHC2: + size = (sizeof (PchSataSharedHsioLptH_MB_Cx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataSharedHsio_MB = PchSataSharedHsioLptH_MB_Cx; + break; +#endif // TRAD_FLAG + default: + size = 0; + PchSataSharedHsio_MB = NULL; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + for (i = 0; i < size; i++) { + if (PchSeries == PchLp) { + if ((((PchSataSharedHsio_MB[i].Address & 0xFE00) == 0x2000) && ((DeviceLaneOwner & BIT4) == BIT4)) || + (((PchSataSharedHsio_MB[i].Address & 0xFE00) == 0x2200) && ((DeviceLaneOwner & BIT5) == BIT5)) || + (((PchSataSharedHsio_MB[i].Address & 0xFE00) == 0x2400) && ((DeviceLaneOwner & BIT6) == BIT6)) || + (((PchSataSharedHsio_MB[i].Address & 0xFE00) == 0x2600) && ((DeviceLaneOwner & BIT7) == BIT7))) { + continue; + } + } else if (PchSeries == PchH) { + if ((((PchSataSharedHsio_MB[i].Address & 0xFE00) == 0x2000) && ((DeviceLaneOwner & BIT4) == BIT4)) || + (((PchSataSharedHsio_MB[i].Address & 0xFE00) == 0x2200) && ((DeviceLaneOwner & BIT5) == BIT5))) { + continue; + } + } + Status = ProgramIobp ( + RootComplexBar, + PchSataSharedHsio_MB[i].Address, + PchSataSharedHsio_MB[i].AndMask, + PchSataSharedHsio_MB[i].OrMask + ); + ASSERT_EFI_ERROR (Status); + } + } else { + /// + /// For Desktop: + /// BIOS is required to program IOBP setting according to Table 7-13 and + /// Table 7-14 using settings in Section 7.1.4 with OPCODE "PHY Configuration Register". + /// Table 7-13 SATA Dedicated Lane Setting + /// +#ifdef TRAD_FLAG + switch (PchStepping()) { + case LptHB0: + size = (sizeof (PchSataHsioLptH_DT_B0) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataHsio_DT = PchSataHsioLptH_DT_B0; + break; + case LptHC0: + case LptHC1: + case LptHC2: + size = (sizeof (PchSataHsioLptH_DT_Cx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataHsio_DT = PchSataHsioLptH_DT_Cx; + break; + default: + size = 0; + PchSataHsio_DT = NULL; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + for (i = 0; i < size; i++) { + Status = ProgramIobp ( + RootComplexBar, + PchSataHsio_DT[i].Address, + PchSataHsio_DT[i].AndMask, + PchSataHsio_DT[i].OrMask + ); + ASSERT_EFI_ERROR (Status); + } +#endif // TRAD_FLAG + /// + /// Table 7-14 SATA Shared Lane Setting + /// + switch (PchStepping()) { +#ifdef ULT_FLAG + case LptLpB0: + case LptLpB1: + case LptLpB2: + size = (sizeof (PchSataSharedHsioLptLp_DT_Bx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataSharedHsio_DT = PchSataSharedHsioLptLp_DT_Bx; + break; +#endif // ULT_FLAG +#ifdef TRAD_FLAG + case LptHB0: + size = (sizeof (PchSataSharedHsioLptH_DT_B0) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataSharedHsio_DT = PchSataSharedHsioLptH_DT_B0; + break; + case LptHC0: + case LptHC1: + case LptHC2: + size = (sizeof (PchSataSharedHsioLptH_DT_Cx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataSharedHsio_DT = PchSataSharedHsioLptH_DT_Cx; + break; +#endif // TRAD_FLAG + default: + size = 0; + PchSataSharedHsio_DT = NULL; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + for (i = 0; i < size; i++) { + if (PchSeries == PchLp) { + if ((((PchSataSharedHsio_DT[i].Address & 0xFE00) == 0x2000) && ((DeviceLaneOwner & BIT4) == BIT4)) || + (((PchSataSharedHsio_DT[i].Address & 0xFE00) == 0x2200) && ((DeviceLaneOwner & BIT5) == BIT5)) || + (((PchSataSharedHsio_DT[i].Address & 0xFE00) == 0x2400) && ((DeviceLaneOwner & BIT6) == BIT6)) || + (((PchSataSharedHsio_DT[i].Address & 0xFE00) == 0x2600) && ((DeviceLaneOwner & BIT7) == BIT7))) { + continue; + } + } else if (PchSeries == PchH) { + if ((((PchSataSharedHsio_DT[i].Address & 0xFE00) == 0x2000) && ((DeviceLaneOwner & BIT4) == BIT4)) || + (((PchSataSharedHsio_DT[i].Address & 0xFE00) == 0x2200) && ((DeviceLaneOwner & BIT5) == BIT5))) { + continue; + } + } + Status = ProgramIobp ( + RootComplexBar, + PchSataSharedHsio_DT[i].Address, + PchSataSharedHsio_DT[i].AndMask, + PchSataSharedHsio_DT[i].OrMask + ); + ASSERT_EFI_ERROR (Status); + } + } + + /// + /// Table 7-15 SATA RxEq Dedicated Lane Setting + /// + PchSataTraceId = 0; +#ifdef TRAD_FLAG + switch (PchStepping()) { + case LptHC0: + case LptHC1: + case LptHC2: + size = (sizeof (PchSataRxEqHsioLptH_Cx) / sizeof (IOBP_SATA_RXEQ_TABLE)); + PchSataRxEqHsio = PchSataRxEqHsioLptH_Cx; + break; + default: + PchSataRxEqHsio = NULL; + size = 0; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + + for(PortId = 0; PortId < GetPchMaxSataPortNum (); PortId++){ + for(GSpeed = 0; GSpeed < 3; GSpeed++){ + if(PchPlatformPolicyPpi->SataConfig->SataTraceConfig->PortRxEq[PortId].GenSpeed[GSpeed].Enable == PCH_DEVICE_ENABLE) { + PchSataTraceId = PCH_SATA_RXEQ_ID(PortId, GSpeed); + for (i = 0; i < size; i++) { + if(PchSataRxEqHsio[i].TraceId == PchSataTraceId) { + RxEq = PchPlatformPolicyPpi->SataConfig->SataTraceConfig->PortRxEq[PortId].GenSpeed[GSpeed].RxEq; + OrMask = (((UINT32) (((RxEq) << 24 ) + ((RxEq) << 16 ) + ((RxEq) << 8 ) + RxEq)) & ((UINT32)~(PchSataRxEqHsio[i].AndMask))); + Status = ProgramIobp ( + RootComplexBar, + PchSataRxEqHsio[i].Address, + PchSataRxEqHsio[i].AndMask, + OrMask + ); + ASSERT_EFI_ERROR (Status); + } + } + } + } + } +#endif // TRAD_FLAG + + /// + /// Table 7-16 SATA RxEq Shared Lane Setting + /// + switch (PchStepping()) { +#ifdef ULT_FLAG + case LptLpB0: + case LptLpB1: + case LptLpB2: + size = (sizeof (PchSataRxEqSharedHsioLptLp_Bx) / sizeof (IOBP_SATA_RXEQ_TABLE)); + PchSataRxEqSharedHsio = PchSataRxEqSharedHsioLptLp_Bx; + break; +#endif // ULT_FLAG +#ifdef TRAD_FLAG + case LptHC0: + case LptHC1: + case LptHC2: + size = (sizeof (PchSataRxEqSharedHsioLptH_Cx) / sizeof (IOBP_SATA_RXEQ_TABLE)); + PchSataRxEqSharedHsio = PchSataRxEqSharedHsioLptH_Cx; + break; +#endif // TRAD_FLAG + default: + size = 0; + PchSataRxEqSharedHsio = NULL; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + + for(PortId = 0; PortId < GetPchMaxSataPortNum (); PortId++){ + for(GSpeed = 0; GSpeed < 3; GSpeed++){ + if(PchPlatformPolicyPpi->SataConfig->SataTraceConfig->PortRxEq[PortId].GenSpeed[GSpeed].Enable == PCH_DEVICE_ENABLE) { + PchSataTraceId = PCH_SATA_RXEQ_ID(PortId, GSpeed); + for (i = 0; i < size; i++) { + if(PchSataRxEqSharedHsio[i].TraceId == PchSataTraceId) { + if (PchSeries == PchLp) { + if ((((PchSataRxEqSharedHsio[i].Address & 0xFE00) == 0x2000) && ((DeviceLaneOwner & BIT4) == BIT4)) || + (((PchSataRxEqSharedHsio[i].Address & 0xFE00) == 0x2200) && ((DeviceLaneOwner & BIT5) == BIT5)) || + (((PchSataRxEqSharedHsio[i].Address & 0xFE00) == 0x2400) && ((DeviceLaneOwner & BIT6) == BIT6)) || + (((PchSataRxEqSharedHsio[i].Address & 0xFE00) == 0x2600) && ((DeviceLaneOwner & BIT7) == BIT7))) + { + continue; + } + } else if (PchSeries == PchH) { + if ((((PchSataRxEqSharedHsio[i].Address & 0xFE00) == 0x2000) && ((DeviceLaneOwner & BIT4) == BIT4)) || + (((PchSataRxEqSharedHsio[i].Address & 0xFE00) == 0x2200) && ((DeviceLaneOwner & BIT5) == BIT5))) + { + continue; + } + } + RxEq = PchPlatformPolicyPpi->SataConfig->SataTraceConfig->PortRxEq[PortId].GenSpeed[GSpeed].RxEq; + OrMask = (((UINT32) (((RxEq) << 24 ) + ((RxEq) << 16 ) + ((RxEq) << 8 ) + RxEq)) & ((UINT32)~(PchSataRxEqSharedHsio[i].AndMask))); + Status = ProgramIobp ( + RootComplexBar, + PchSataRxEqSharedHsio[i].Address, + PchSataRxEqSharedHsio[i].AndMask, + OrMask + ); + ASSERT_EFI_ERROR (Status); + } + } + } + } + } + /// + /// PCH BIOS Spec Rev 0.5.0 section 14.1.7 Additional Programming Requirements during + /// SATA Initialization + /// Step 5 + /// Program D31:F2:98h[22] to 1b for desktop and mobile platform only. + /// + if (IS_PCH_LPT_LPC_DEVICE_ID_DESKTOP (LpcDeviceId) || + IS_PCH_LPT_LPC_DEVICE_ID_MOBILE (LpcDeviceId)) { + MmioOr32 ( + (UINTN) (PciD31F2RegBase + 0x98), + (UINT32) (BIT22) + ); + } + /// + /// Step 6 + /// Program D31:F2:98h[19] = 1b + /// + MmioOr32 ( + (UINTN) (PciD31F2RegBase + 0x98), + (UINT32) (BIT19) + ); + /// + /// Step 7 + /// Program D31:F2:98h[12:7] = 04h + /// + Data32And = (UINT32) (~(BIT7 | BIT8 | BIT10 | BIT11 | BIT12)); + Data32Or = (UINT32) (BIT9); + MmioAndThenOr32 ( + (UINTN) (PciD31F2RegBase + 0x98), + Data32And, + Data32Or + ); + /// + /// Step 8 + /// Program D31:F2:98h[20] to 1b + /// + MmioOr32 ((UINTN) (PciD31F2RegBase + 0x98), (UINT32) (BIT20)); + /// + /// Step 9 + /// Program D31:F2:98h[6:5] to 01b + /// + MmioAndThenOr32 ( + (UINTN) (PciD31F2RegBase + 0x98), + (UINT32) (~(BIT6 | BIT5)), + BIT5 + ); + /// + /// Step 10 + /// Program D31:F2:98h [18] to 1b + /// + Data32Or = (UINT32) (BIT18); + MmioOr32 ( + (UINTN) (PciD31F2RegBase + 0x98), + Data32Or + ); + /// + /// Step 11 + /// Program D31:F2:98h[29] to 1b + /// Done in PchInitBeforeBoot() + /// + /// Step 12 + /// Program D31:F2:9Ch[5] to 1b (Note: this must be programmed together with D31:F2:9Ch[7:6] + /// in word write) + /// Done in ConfigureSata () + /// + /// Step 13 + /// When SATA in IDE mode + /// a. Program D31:F2:34h [7:0] to 70h + /// b. Program D31:F2:70h [15:8] to 0h + /// Done in PchMiscInit () + /// + /// Step 14 + /// Program D31:F2:9Ch[31] to 1b at the End of Post + /// Done in PchInitBeforeBoot() + /// + /// Enable the SATA port0 ~ port3. + /// + if (PchSeries == PchH) { + MmioOr8 ( + PciD31F2RegBase + R_PCH_SATA_PCS, + (UINT8) (B_PCH_SATA_PCS_PORT3_EN | B_PCH_SATA_PCS_PORT2_EN | B_PCH_SATA_PCS_PORT1_EN | B_PCH_SATA_PCS_PORT0_EN) + ); + } + if (PchSeries == PchLp) { + /// + /// If D28:F0:410h[7] = 1b, System BIOS should not enable the SATA port0 + /// If D28:F0:410h[6] = 1b, System BIOS should not enable the SATA port1 + /// If D28:F0:410h[5] = 1b, System BIOS should not enable the SATA port2 + /// If D28:F0:410h[4] = 1b, System BIOS should not enable the SATA port3 + /// + if ((MmioRead8 (PciD28F0RegBase + 0x410) & BIT7) == 0) { + MmioOr8 ( + PciD31F2RegBase + R_PCH_SATA_PCS, + (UINT8) B_PCH_SATA_PCS_PORT0_EN + ); + } + if ((MmioRead8 (PciD28F0RegBase + 0x410) & BIT6) == 0) { + MmioOr8 ( + PciD31F2RegBase + R_PCH_SATA_PCS, + (UINT8) B_PCH_SATA_PCS_PORT1_EN + ); + } + if ((MmioRead8 (PciD28F0RegBase + 0x410) & BIT5) == 0) { + MmioOr8 ( + PciD31F2RegBase + R_PCH_SATA_PCS, + (UINT8) B_PCH_SATA_PCS_PORT2_EN + ); + } + if ((MmioRead8 (PciD28F0RegBase + 0x410) & BIT4) == 0) { + MmioOr8 ( + PciD31F2RegBase + R_PCH_SATA_PCS, + (UINT8) B_PCH_SATA_PCS_PORT3_EN + ); + } + } + if (PchSeries == PchH) { + /// + /// Enable the SATA port4 and port5. + /// Step 1.a + /// If D28:F0:410h[4] = 1b, System BIOS should not enable the SATA port4 + /// Step 1.b + /// If D28:F0:410h[5] = 1b, System BIOS should not enable the SATA port5 + /// + if ((MmioRead8 (PciD28F0RegBase + 0x410) & BIT4) == 0) { + MmioOr8 ( + PciD31F2RegBase + R_PCH_SATA_PCS, + (UINT8) B_PCH_SATA_PCS_PORT4_EN + ); + } + if ((MmioRead8 (PciD28F0RegBase + 0x410) & BIT5) == 0) { + MmioOr8 ( + PciD31F2RegBase + R_PCH_SATA_PCS, + (UINT8) B_PCH_SATA_PCS_PORT5_EN + ); + } + } + } + + DEBUG ((EFI_D_INFO, "PchSataInit() - End\n")); + + return EFI_SUCCESS; +} + +/** + The function is used while doing CPU Only Reset, where PCH may be required + to initialize strap data before soft reset. + + @param[in] PeiServices General purpose services available to every PEIM + @param[in] Operation Get/Set Cpu Strap Set Data + @param[in, out] CpuStrapSet Cpu Strap Set Data + + @retval EFI_SUCCESS The function completed successfully. + @exception EFI_UNSUPPORTED The function is not supported. +**/ +EFI_STATUS +EFIAPI +PchCpuStrapSet ( + IN EFI_PEI_SERVICES **PeiServices, + IN CPU_STRAP_OPERATION Operation, + IN OUT UINT16 *CpuStrapSet + ) +{ + UINT32 RootComplexBar; + + DEBUG ((EFI_D_INFO, "PchCpuStrapSet() - Start\n")); + + RootComplexBar = PCH_RCRB_BASE; + + switch (Operation) { + case GetCpuStrapSetData: + /// + /// Get CPU Strap Settings select. 0 = from descriptor, 1 = from PCH + /// + if ((MmioRead8 ((UINTN) (RootComplexBar + R_PCH_SPI_SRDC)) & B_PCH_SPI_SRDC_SRDS) == 0) { + /// + /// Read Strap from Flash Descriptor + /// + *CpuStrapSet = 0; + return EFI_SUCCESS; + } else { + /// + /// Read Strap from PCH Soft Strap. + /// + *CpuStrapSet = MmioRead16 ((UINTN) (RootComplexBar + R_PCH_SPI_SRD)); + } + break; + + case SetCpuStrapSetData: + /// + /// PCH BIOS Spec Rev 0.5.0, Section 4.3 Soft Reset Control + /// 2. If there are CPU configuration changes, program the strap setting into the + /// Soft Reset Data register located at SPIBAR Offset F8h [15:0] (RCBA + Offset 38F8h [15:0]) + /// and follow the steps outlined in the "CPU Only Reset BIOS Flow" section of the Processor + /// BIOS Writer's Guide and skip steps 3 and 4. + /// a. Program Soft Reset Data Register SPIBAR + F8h [13:0] (RCBA + 38F8h [13:0]) + /// (details in Processor BIOS Writer's Guide) + /// b. Set RCBA + Offset 38F4h[0] = 1b + /// c. Set RCBA + Offset 38F0h[0] = 1b + /// d. Skip steps 3 and 4. + /// + MmioWrite16 ((UINTN) (RootComplexBar + R_PCH_SPI_SRD), *CpuStrapSet); + MmioOr8 ((UINTN) (RootComplexBar + R_PCH_SPI_SRDC), B_PCH_SPI_SRDC_SRDS); + MmioOr8 ((UINTN) (RootComplexBar + R_PCH_SPI_SRDL), B_PCH_SPI_SRDL_SSL); + break; + + case LockCpuStrapSetData: + MmioOr8 ((UINTN) (RootComplexBar + R_PCH_SPI_SRDL), B_PCH_SPI_SRDL_SSL); + break; + + default: + break; + } + + DEBUG ((EFI_D_INFO, "PchCpuStrapSet() - End\n")); + + return EFI_SUCCESS; +} + +/** + This function may trigger platform reset depending on the current GbE status, + the intended GbE enabling, and current ME status. (When ME is enabled, this function + may trigger a Global reset.) + This function may not return if it triggers an platform reset and the BIOS boot flow + restarts. + If this function returns EFI_SUCCESS it indicates there is no need for platform + reset in this boot, and boot flow continues. + If this function returns EFI_DEVICE_ERROR, something error happens. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval EFI_SUCCESS No platform reset action is taken. System can continue boot flow. + @retval Others Won't return if platform reset action is taken +**/ +EFI_STATUS +EFIAPI +PchGbeMandatedReset ( + IN EFI_PEI_SERVICES **PeiServices, + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ) +{ + UINT8 RegData8; + UINTN PciD25F0RegBase; + UINT32 GbEMemBar; + UINT32 TempGbEMemBar; + UINT16 CmdReg; + BOOLEAN ResetRequired; + BOOLEAN GbeRegion; + PCH_RESET_PPI *PchResetPpi; + EFI_STATUS Status; + PCH_RESET_TYPE PchResetType; + + PciD25F0RegBase = 0; + GbEMemBar = 0; + ResetRequired = FALSE; + + /// + /// Read the BUC register + /// + RegData8 = MmioRead8 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_BUC); + + GbeRegion = PchIsGbeRegionValid (PchPlatformPolicyPpi->Rcba); + + /// + /// If no change of status, just return success + /// + if (((RegData8 & B_PCH_RCRB_BUC_LAN_DIS) && + !PchPlatformPolicyPpi->GbeConfig->EnableGbe) || + (!(RegData8 & B_PCH_RCRB_BUC_LAN_DIS) && + PchPlatformPolicyPpi->GbeConfig->EnableGbe)) { + return EFI_SUCCESS; + } + + + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gPchResetPpiGuid, + 0, + NULL, + (VOID **)&PchResetPpi + ); + + ASSERT_EFI_ERROR (Status); + + /// + /// Before modifying LAN Disable bit, make sure it's not locked. + /// If it's locked, issus a GlobalReset to unlock it. + /// + RegData8 = MmioRead8 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_FDSW); + if (RegData8 & B_PCH_RCRB_FDSW_FDSWL) { + DEBUG ((EFI_D_ERROR, "PchGbeMandatedReset: resetting the board via CF9 to unlock LAN Disable register...\n")); + PchResetPpi->Reset (PchResetPpi, GlobalReset); + /// + /// Shouldn't reach here + /// + return EFI_SUCCESS; + } + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 10.2.1/10.2.2 Enable/Disable the GbE Clock Gating + /// Step 3 + /// Set RCBA + 341Ch[23] + /// Done in ConfigureClockGating() + /// + /// PCH BIOS Spec Rev 0.5.0, Section 10.2 Enabling / Disabling the Internal GbE Controller + /// In PCH systems, changing the internal GbE controller from disabled to enabled + /// during POST requires a system reset (IO port CF9h = 0Eh) immediately after clearing the LAN disable + /// bit in the BUC register, RCBA + 3414[5]. If ME is enabled and the LAN disable bit + /// has changed, then system BIOS must set D31:F0:Reg 0ACh[20] prior to issuing a platform reset (IO port CF9h = 0x6 or 0xE). + /// + /// Therefore, the flow is as below: + /// When LAN changes from disabled to enabled + /// If ME is not existed, require a power cycle reset. + /// If ME is enabled, require a global reset. + /// When LAN changes from enabled to disabled + /// If ME is not existed, no power cycle reset is required. + /// If ME is enabled, and Me is using Gbe (by checking GBEBAR+0x5B54[15]=1), require a global reset. + /// + + /// + /// Set the BUC register + /// + if (PchPlatformPolicyPpi->GbeConfig->EnableGbe) { + /// + /// Change internal Gbe from disabled to enabled + /// + if (GbeRegion == TRUE) { + ResetRequired = TRUE; + /// + /// PCH BIOS Spec Rev 0.5.0, Section 10.2.1 Enable the Internal GbE Controller + /// Step 1 + /// Set RCBA + 3414h[5] = 0b + /// + MmioAnd8 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_BUC, (UINT8) (~B_PCH_RCRB_BUC_LAN_DIS)); + } + } else { + /// + /// Change internal Gbe from enabled to disabled + /// + if (GbeRegion == TRUE) { + /// + /// PCH BIOS Spec Rev 0.5.0, Section 10.2.2 Disable the Internal GbE Controller + /// Step 1a + /// If Intel ME enable then detect if it supports GBe. Read FWSM_S[15] bit in MBARA + offset 5B54h register. + /// + PciD25F0RegBase = MmPciAddress ( + 0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LAN, + PCI_FUNCTION_NUMBER_PCH_LAN, + 0 + ); + /// + /// Store current value of PCH_LAN_MEM_BASE_A + /// + TempGbEMemBar = MmioRead32 (PciD25F0RegBase + R_PCH_LAN_MEM_BASE_A); + /// + /// As PCI enumeration has not been done, set PCH_LAN_MBARB per the platform policy + /// + MmioWrite32 (PciD25F0RegBase + R_PCH_LAN_MEM_BASE_A, PchPlatformPolicyPpi->PlatformData->TempMemBaseAddr); + /// + /// Store the setting of R_PCH_LAN_CMD + /// + CmdReg = MmioRead16 (PciD25F0RegBase + R_PCH_LAN_CMD); + /// + /// Enable memory space decoding in command register + /// + MmioOr16 (PciD25F0RegBase + R_PCH_LAN_CMD, (UINT16) B_PCH_LAN_CMD_MSE); + /// + /// Check if GbE device exists + /// + GbEMemBar = MmioRead32 (PciD25F0RegBase + R_PCH_LAN_MEM_BASE_A) & B_PCH_LAN_MBARA_BA; + + if (GbEMemBar != 0xFFFFFFFF) { + if ((MmioRead16 (GbEMemBar + 0x5B54)) & BIT15) { + ResetRequired = TRUE; + } + } + /// + /// Restore the setting of R_PCH_LAN_CMD + /// + MmioWrite16 (PciD25F0RegBase + R_PCH_LAN_CMD, CmdReg); + /// + /// Restore the value of PCH_LAN_MEM_BASE_A + /// + MmioWrite32 (PciD25F0RegBase + R_PCH_LAN_MEM_BASE_A, TempGbEMemBar); + } + /// + /// Step 1 + /// Set RCBA + 3414h[5] = 1b + /// + MmioOr8 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_BUC, (UINT8) B_PCH_RCRB_BUC_LAN_DIS); + } + /// + /// PCH BIOS Spec Rev 0.5.0, Section 10.2.1 & 10.2.2 + /// Step 2 + /// Read back for posted write to take effect + /// + MmioRead8 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_BUC); + + if (!ResetRequired) { + return EFI_SUCCESS; + } + + DEBUG ((EFI_D_ERROR, "PchGbeMandatedReset: resetting the board via CF9...\n")); + if ((MmioRead32 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_FD2) & B_PCH_RCRB_FD2_MEI1D) == 0) { + if (PchPlatformPolicyPpi->PlatformData->EcPresent) { + PchResetType = GlobalResetWithEc; + } else { + PchResetType = GlobalReset; + } + } else { + PchResetType = PowerCycleReset; + } + + PchResetPpi->Reset (PchResetPpi, PchResetType); + /// + /// Shouldn't reach here + /// + return EFI_SUCCESS; +} + +/** + Internal function performing miscellaneous init needed in early PEI phase + + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval EFI_SUCCESS Succeeds. + @retval EFI_DEVICE_ERROR Device error, aborts abnormally. +**/ +EFI_STATUS +PchMiscInit ( + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ) +{ + EFI_STATUS Status; + UINT8 Index; + UINTN PciD31F2RegBase; + UINTN PciD31F5RegBase; + UINTN PciD28F0RegBase; + UINTN PciD31F0RegBase; + UINT16 LpcDeviceId; + PCH_HPET_CONFIG *HpetConfig; + UINT16 Data16; + UINT32 Data32; + UINT32 Data32And; + UINT32 Data32Or; + UINTN RPBase; + BOOLEAN RpSpeedChanged; + UINT32 RootComplexBar; + + const USB_CONTROLLER EhciControllersMap[PchEhciControllerMax] = { + { + PCI_DEVICE_NUMBER_PCH_USB, + PCI_FUNCTION_NUMBER_PCH_EHCI + }, + { + PCI_DEVICE_NUMBER_PCH_USB_EXT, + PCI_FUNCTION_NUMBER_PCH_EHCI2 + } + }; + PCH_SERIES PchSeries; + + PchSeries = GetPchSeries(); + PciD31F0RegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); + PciD31F2RegBase = MmPciAddress ( + 0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_SATA, + PCI_FUNCTION_NUMBER_PCH_SATA, + 0 + ); + PciD31F5RegBase = 0; + if (PchSeries == PchH) { + PciD31F5RegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_SATA, + PCI_FUNCTION_NUMBER_PCH_SATA2, + 0 + ); + } + PciD28F0RegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1, + 0 + ); + HpetConfig = PchPlatformPolicyPpi->HpetConfig; + /// + /// Set B0:D31:F0 + ACh[20] = 0 at early boot + /// + MmioAnd32 (PciD31F0RegBase + R_PCH_LPC_PMIR, (UINT32)~(B_PCH_LPC_PMIR_CF9GR)); + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 8.14 Additional PCI Express* Programming Steps + /// NOTE: Detection of Non-Complaint PCI Express Devices in Gen2 Ports + /// Some non-graphics PCI Express devices do not follow PCI Express Specification and currently report + /// the incorrect Gen capability or link width. This may cause the improper detection of the card + /// by the Intel Gen2 PCI Express port. + /// The following settings may improve the ability of an Intel Gen2 PCI Express port to detect + /// these non-compliant PCI Express devices. + /// If BIOS cannot detect or train the device: Set B0:D28:F0~F7 + 70h [3:0]= 1h + /// Wait 100 ms for link to train up + /// Please note the above setting is "as-is" as Intel cannot verify all non-compliant devices. + /// You need to ensure that the workaround works with devices you are planning to use. + /// + RpSpeedChanged = FALSE; + for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) { + RPBase = MmPciAddress ( + 0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + Index, + 0 + ); + if (MmioRead16 (RPBase + R_PCH_PCIE_VENDOR_ID) == 0xFFFF) { + continue; + } + + switch (PchPlatformPolicyPpi->PcieConfig->PcieSpeed[Index]) { + case PchPcieGen1: + Data16 = BIT0; + break; + case PchPcieGen2: + case PchPcieAuto: + default: + Data16 = BIT1; + break; + } + if ((MmioRead16 (RPBase + R_PCH_PCIE_LCTL2) & (UINT16) (B_PCH_PCIE_LCTL2_TLS)) != Data16) { + MmioAndThenOr16 (RPBase + R_PCH_PCIE_LCTL2, (UINT16)~(B_PCH_PCIE_LCTL2_TLS), Data16); + RpSpeedChanged = TRUE; + } + } + // + // Merge all delay for change link speed of RPs together to reduce the delay time. + // + if (RpSpeedChanged) { + PchPmTimerStall (100 * 1000); + } + + for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) { + RPBase = MmPciAddress ( + 0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + Index, + 0 + ); + if (MmioRead16 (RPBase + R_PCH_PCIE_VENDOR_ID) == 0xFFFF) { + continue; + } + /// + /// PCH BIOS Spec Rev 0.5.0 Section 8.2 + /// Else if the port is hot-plug enable, do not disable the port. If BIOS wants to disable the port, + /// BIOS should not enable the hot plug capability or must disable the hot plug capability of the port. + /// Set B0:D28:Fn + 338h [26] = 0b at early POST. + /// + MmioAnd32 ((RPBase + 0x338), (UINT32) ~BIT26); + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 8.14 Additional PCI Express* Programming Steps + /// Step 1 + /// Before MRC execution, system BIOS must program the following register. + /// B0:D28:F0 + F4h[6:5] = 0b + /// B0:D28:F0 + F4h[7] = 1b + /// + if (Index == 0) { + MmioAndThenOr8 ((RPBase + 0xF4), (UINT8) ~(BIT5 | BIT6), BIT7); + } + } + + for (Index = 0; Index < GetPchEhciMaxControllerNum (); Index++) { + /// + /// PCH BIOS Spec Rev 0.5.0 Section 7.1.5 Additional PCH DMI Programming Steps + /// Step 3.2 + /// RCBA + Offset 50h[23:20] = 2h and RCBA + Offset 50h[17] = 1b (Done at + /// PchDmiTcVcProgPoll() on PchDmiPeim.c) + /// and also ensure that D29/D26:F0:88h [2] = 0b + /// + Data32 = MmioRead32 ( + (UINTN) MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + EhciControllersMap[Index].Device, + EhciControllersMap[Index].Function, + 0x88) + ); + Data32 &= (UINT32) (~BIT2); + MmioWrite32 ( + MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + EhciControllersMap[Index].Device, + EhciControllersMap[Index].Function, + 0x88), + Data32 + ); + } + /// + /// Initial and enable HPET High Precision Timer memory address for basic usage + /// + if (HpetConfig->Enable == PCH_DEVICE_ENABLE) { + MmioAndThenOr32 ( + (UINTN) (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_HPTC), + (UINT32)~B_PCH_RCRB_HPTC_AS, + (UINT32) (((HpetConfig->Base >> N_PCH_HPET_ADDR_ASEL) & B_PCH_RCRB_HPTC_AS) | B_PCH_RCRB_HPTC_AE) + ); + /// + /// Read back for posted write to take effect + /// + MmioRead32 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_HPTC); + /// + /// Set HPET Timer enable to start counter spinning + /// + MmioOr32 (HpetConfig->Base + 0x10, 0x1); + } + + if (PchPlatformPolicyPpi->Port80Route == PchReservedPageToLpc) { + MmioAnd32 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_GCS, (UINT32) (~B_PCH_RCRB_GCS_RPR)); + } else { + MmioOr32 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_GCS, (UINT32) B_PCH_RCRB_GCS_RPR); + } + /// + /// Read back for posted write to take effect + /// + MmioRead32 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_GCS); + +#ifdef TRAD_FLAG + if (PchSeries == PchH) { + if (PchPlatformPolicyPpi->SataConfig->SataMode == PchSataModeIde) { + /// + /// PCH BIOS Spec Rev 0.5.0 section 14.1.7 Additional Programming Requirements during + /// Step 13 + /// When SATA in IDE mode + /// a. Program D31:F2:34h [7:0] to 70h + /// + Data32And = (UINT32) ~(0xFF); + Data32Or = (UINT32) (0x70); + MmioAndThenOr32 ( + (UINTN) (PciD31F2RegBase + 0x34), + Data32And, + Data32Or + ); + /// + /// b. Program D31:F2:70h [15:8] to 0h + /// + Data32And = (UINT32) ~(0xFF00); + MmioAnd32 ( + (UINTN) (PciD31F2RegBase + 0x70), + Data32And + ); + /// + /// IDE mode, SATA Port 0 - Port 3 are for D31:F2, Port4 and Port 5 are for D31:F5 + /// + MmioAnd8 ( + PciD31F2RegBase + R_PCH_SATA_MAP, + (UINT8)~(B_PCH_SATA_MAP_SMS_MASK | B_PCH_SATA_PORT_TO_CONTROLLER_CFG) + ); + /// + /// PCH BIOS Spec Rev 0.5.0 section 14.1.7 Additional Programming Requirements during + /// SATA Initialization + /// Step 1 + /// If D28:F0:410h[5:4] = 11b, System BIOS must disable D31:F5 by setting SAD2 bit, + /// RCBA + 3418[25] + /// + if ((MmioRead8 (PciD28F0RegBase + 0x410) & (UINT8) (BIT5 | BIT4)) == (UINT8) (BIT5 | BIT4)) { + MmioOr32 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_FUNC_DIS, (UINT32) B_PCH_RCRB_FUNC_DIS_SATA2); + /// + /// Reads back for posted write to take effect + /// + MmioRead32 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_FUNC_DIS); + } else { + /// + /// Enable the SATA port4 and port5. + /// Step 1.a + /// If D28:F0:410h[4] = 1b, System BIOS should not enable the SATA port4 + /// Step 1.b + /// If D28:F0:410h[5] = 1b, System BIOS should not enable the SATA port5 + /// + if ((MmioRead8 (PciD28F0RegBase + 0x410) & BIT4) == 0) { + MmioOr8 ( + PciD31F5RegBase + R_PCH_SATA_PCS, + (UINT8) B_PCH_SATA2_PCS_PORT4_EN + ); + } + if ((MmioRead8 (PciD28F0RegBase + 0x410) & BIT5) == 0) { + MmioOr8 ( + PciD31F5RegBase + R_PCH_SATA_PCS, + (UINT8) B_PCH_SATA2_PCS_PORT5_EN + ); + } + } + } else { + MmioOr32 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_FUNC_DIS, (UINT32) B_PCH_RCRB_FUNC_DIS_SATA2); + /// + /// Reads back for posted write to take effect + /// + MmioRead32 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_FUNC_DIS); + } + } +#endif //TRAD_FLAG +#ifdef ULT_FLAG + if (PchSeries == PchLp) { + if (PchPlatformPolicyPpi->SataConfig->SataMode == PchSataModeLoopbackTest) { + /// + /// Set D31:F2:90h[7:6] to 00b + /// + MmioAnd8 ( + PciD31F2RegBase + R_PCH_SATA_MAP, + (UINT8)~(B_PCH_SATA_MAP_SMS_MASK) + ); + /// + /// Set D31:F2 + SIR Index 00h[15] = 1b + /// + MmioWrite8 (PciD31F2RegBase + R_PCH_SATA_SIRI, 0x00); + Data32And = 0xFFFF7FFF; + Data32Or = 0x00008000; + MmioAndThenOr32 ( + (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), + Data32And, + Data32Or + ); + } + } +#endif // ULT_FLAG + if (PchPlatformPolicyPpi->SataConfig->SataMode == PchSataModeRaid) { + LpcDeviceId = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_DEVICE_ID); + if (IS_PCH_LPT_RAID_AVAILABLE (LpcDeviceId)) { + MmioAndThenOr8 ( + PciD31F2RegBase + R_PCH_SATA_MAP, + (UINT8) (~B_PCH_SATA_MAP_SMS_MASK), + (UINT8) (V_PCH_SATA_MAP_SMS_RAID) + ); + } else { + DEBUG ((EFI_D_INFO, "PCH Device ID : 0x%x\n", LpcDeviceId)); + DEBUG ((EFI_D_ERROR, "This SKU doesn't support RAID feature. Set to AHCI mode.\n")); + } + } + + // + // The following three ICC isCLK settings must be done for S3/S4/S5 before ICC HW is locked. + // For S3 path, the ICC HW is locked just after DID message. So program those in PEI. + // + if (PchSeries == PchLp) { + RootComplexBar = PchPlatformPolicyPpi->Rcba; + /// + /// Set the isCLK PLL lock speed in the ICC HW. + /// Set bits 13:12 and bits 10:8, clear bit 11, fast lock time = 11us + /// NOTE: Lock occurs after EOP message sent, and this write will fail until core well reset. On write failure + /// expectation is that the register was previously programmed and values are maintained in HW registers. + /// + Status = ProgramIobp(RootComplexBar, 0xED00015C, (UINT32)~(BIT11), (BIT13|BIT12|BIT10|BIT9|BIT8)); + + /// + /// Set the isCLK freeze timer in the ICC HW. + /// Set bits 23:22, Clk timer = 1 clk + /// NOTE: Lock occurs after EOP message sent, and this write will fail until core well reset. On write failure + /// expectation is that the register was previously programmed and values are maintained in HW registers. + /// + Status = ProgramIobp(RootComplexBar, 0xED000118, (UINT32)0xFFFFFFFF, (UINT32) (BIT23|BIT22)); + + /// + /// Set bit 21 and 18, expand Vcont Window + /// + Status = ProgramIobp(RootComplexBar, 0xED000120, (UINT32)0xFFFFFFFF, (UINT32) (BIT21|BIT18)); + } + + return EFI_SUCCESS; +} + +/** + Perform Thermal Management Support initialization + + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval EFI_SUCCESS Succeeds. + @retval EFI_DEVICE_ERROR Device error, aborts abnormally. +**/ +EFI_STATUS +PchThermalInit ( + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ) +{ + UINTN PciD31F6RegBase; + UINTN PciD0F0RegBase; + UINT32 ThermalBaseB; + PCH_MEMORY_THROTTLING *MemoryThrottling; + UINT32 Data32And; + UINT32 Data32Or; + UINT32 Softstrap15; + + PciD31F6RegBase = MmPciAddress ( + 0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_THERMAL, + PCI_FUNCTION_NUMBER_PCH_THERMAL, + 0 + ); + PciD0F0RegBase = MmPciAddress (0, 0, 0, 0, 0); + + MemoryThrottling = PchPlatformPolicyPpi->ThermalMgmt->MemoryThrottling; + ThermalBaseB = PchPlatformPolicyPpi->PlatformData->TempMemBaseAddr; + + /// + /// D31:F6:Reg 44h[31:0], with a 64-bit BAR for BIOS. + /// Enable the BAR by setting the SPTYPEN bit, D31:F6:Reg 40h[0]. + /// + MmioWrite32 (PciD31F6RegBase + R_PCH_THERMAL_TBARB, ThermalBaseB); + MmioWrite32 (PciD31F6RegBase + R_PCH_THERMAL_TBARBH, 0); + MmioOr32 (PciD31F6RegBase + R_PCH_THERMAL_TBARB, (UINT32) B_PCH_THERMAL_SPTYPEN); + + /// + /// PCH BIOS Spec Rev 0.5.0, 17.2 Thermal Subsystem Device Initialization + /// The System BIOS must perform the following steps to initialize the PCH thermal subsystem device, D31:F6. + /// Step 1 + /// Enable Thermal Subsystem device by making sure FD.TTD is cleared. + /// The default value of FD.TTD is cleared. + /// + /// Step 2 + /// Optionally program Device 31 Interrupt Pin/Route registers + /// Left this to platform code + /// + /// Step 3 + /// Go through general PCI enumeration and assign standard PCI resource, including TBARB, TBARBH, etc. + /// Left this to platform code + /// + /// Step 4 + /// Initialize relevant Thermal subsystems for the desired features. + /// + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 17.3.1 Initializing Lynx Point Thermal Sensors + /// Step 1 + /// Set various trip points based on the particular usage model. Note that Cat Trip must always be programmed. + /// - CTT must be programmed for Cat Trip, CTT must never be changed while the TS enable is set. + /// This rule prevents a spurious trip from occurring and causing a system shutdown. + /// TSC must then be written to 0x81 to enable the power down and lock the register. + /// TSC programming is done in PchPm.c ThermalLockDown() + /// - TAHV and TAHL may be programmed if the BIOS or driver wish to force a SW notification for PCH temperature + /// - If TAHL/TAHV programmed much later in the flow when a driver is loaded, this means that the TS had been + /// enabled long before this, the thermal sensor must be disabled when TAHL/TAHV are programmed, and then + /// re-enabled. + /// - TSPIEN or TSGPEN may be programmed to cause either an interrupt or SMI/SCI. + /// - It is recommended that TAHV, TALV, TSPIEN and TSGPEN be left at their default value, unless there is a + /// specific usage that requires these to be programmed. + /// + if (GetPchSeries() == PchLp) { + MmioWrite16 (ThermalBaseB + R_PCH_TBARB_CTT, V_PCH_TBARB_CTT_LPTLP); + } else { + MmioWrite16 (ThermalBaseB + R_PCH_TBARB_CTT, V_PCH_TBARB_CTT_LPTH); + } + + /// + /// Step 2 + /// Clear trip status from TSS/TAS. BIOS should write 0xFF to clear any bit that was inadvertently set while programming + /// the TS. This write of 0xFF should be done before continuing to the next steps. + /// + MmioWrite8 (ThermalBaseB + R_PCH_TBARB_TSS, 0xFF); + MmioWrite8 (ThermalBaseB + R_PCH_TBARB_TAS, 0xFF); + + /// + /// Step 3 + /// Enable the desired thermal trip alert methods, i.e. GPE (TSGPEN), SMI (TSMIC) or Interrupt (TSPIEN). + /// Only one of the methods should be enabled and the method will be depending on the platform implementation. + /// - TSGPEN: BIOS should leave this as default 00h, unless it is required to enable GPE. + /// - TSMIC: BIOS should leave TSMIC[7:0] as default 00h, unless the SMI handler is loaded + /// and it's safe to enable SMI for these events. + /// - TSPIEN: BIOS should leave this as default 0x00, so that a driver can enable later + /// + MmioWrite8 (ThermalBaseB + R_PCH_TBARB_TSGPEN, 0x00); + MmioWrite8 (ThermalBaseB + R_PCH_TBARB_TSPIEN, 0x00); + + /// + /// If PCHSTRP15[14] is 1, PMC will set up SML1 for temp reporting to an EC + /// + MmioAndThenOr32 ( + PCH_RCRB_BASE + R_PCH_SPI_FDOC, + (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)), + (UINT32) (V_PCH_SPI_FDOC_FDSS_PCHS | R_PCH_SPI_STRP15) + ); + + Softstrap15 = MmioRead32 (PCH_RCRB_BASE + R_PCH_SPI_FDOD); + + if ((Softstrap15 & R_PCH_SPI_STRP15_SML1_THRMSEL) != 0) { + /// + /// Step 4 + /// If thermal reporting to an EC over SMBus is supported, then write 0x01 to TSREL, else leave at default. + /// + MmioWrite8 (ThermalBaseB + R_PCH_TBARB_TSREL, 0x01); + } + + /// + /// Step 5 + /// If the PCH_Hot pin reporting is supported, then write the temperature value and set the enable in PHL. + /// Done in PchPm.c ThermalLockDown() + /// + /// Step 6 + /// If thermal throttling is supported, then set the desired values in TL. + /// Done in PchPm.c ThermalLockDown() + /// + /// Step 7 + /// Enable thermal sensor by programming TSEL register to 0x01. + /// Done in PchPm.c ThermalLockDown() + /// + /// Step 8 + /// Lock down the thermal reporting to prevent outside agents from changing the values + /// Done in PchPm.c ThermalLockDown() + /// + + /// + /// Clear BAR and disable access + /// + MmioAnd32 ((UINTN) (PciD31F6RegBase + R_PCH_THERMAL_TBARB), (UINT32)~B_PCH_THERMAL_SPTYPEN); + MmioWrite32 ((UINTN) (PciD31F6RegBase + R_PCH_THERMAL_TBARB), 0); + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 17.5.1 Memory Bandwidth Throttling + /// If the platform supports an external memory thermal sensor (TS-on-DIMM or TS-on-Board), + /// system BIOS needs to program the registers bellow. + /// Here are the settings used in the Intel CRB: + /// 1. Program RCBA + 33D4h [31:28] = 1100b, for GPIO_D and GPIO_C to PM_SYNC Enable + /// 2. Program RCBA + 33D4h [15:12] = 1100b, for GPIO_D and GPIO_C C0 Transmit Enable. + /// 3. Program RCBA + 33C8h [11:8] = 0100b to select GPIO 4 to GPIO_C (EXTTS#0) and + /// GPIO 5 to GPIO_D (EXTTS#1) + /// GPIOBASE + 00h [5:4] = 11b (Done in platform code) + /// + if (MemoryThrottling->Enable == PCH_DEVICE_ENABLE) { + Data32And = 0x0FFF0FFF; + Data32Or = 0; + if (MemoryThrottling->TsGpioPinSetting[TsGpioC].PmsyncEnable == PCH_DEVICE_ENABLE) { + Data32Or |= BIT30; + } + + if (MemoryThrottling->TsGpioPinSetting[TsGpioD].PmsyncEnable == PCH_DEVICE_ENABLE) { + Data32Or |= BIT31; + } + + if (MemoryThrottling->TsGpioPinSetting[TsGpioC].C0TransmitEnable == PCH_DEVICE_ENABLE) { + Data32Or |= BIT14; + } + + if (MemoryThrottling->TsGpioPinSetting[TsGpioD].C0TransmitEnable == PCH_DEVICE_ENABLE) { + Data32Or |= BIT15; + } + + MmioAndThenOr32 ( + PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_CIR33D4, + Data32And, + Data32Or + ); + + Data32And = 0xFFFFF0FF; + Data32Or = 0; + if (MemoryThrottling->TsGpioPinSetting[TsGpioC].PinSelection == 1) { + Data32Or |= B_PCH_RCRB_PMSYNC_GPIO_C_SEL; + } + + if (MemoryThrottling->TsGpioPinSetting[TsGpioD].PinSelection == 1) { + Data32Or |= B_PCH_RCRB_PMSYNC_GPIO_D_SEL; + } + + MmioAndThenOr32 ( + PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_PMSYNC, + Data32And, + Data32Or + ); + } + + return EFI_SUCCESS; +} + +/** + Initialize IOAPIC according to IoApicConfig policy of the PCH + Platform Policy PPI + + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval EFI_SUCCESS Succeeds. + @retval EFI_DEVICE_ERROR Device error, aborts abnormally. +**/ +EFI_STATUS +PchIoApicInit ( + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ) +{ + UINT32 RootComplexBar; + PCH_IOAPIC_CONFIG *IoApicConfig; + UINT32 IoApicAddress; + UINT32 IoApicId; + + RootComplexBar = PchPlatformPolicyPpi->Rcba; + IoApicConfig = PchPlatformPolicyPpi->IoApicConfig; + + if (IoApicConfig->ApicRangeSelect != MmioRead8 (RootComplexBar + R_PCH_RCRB_OIC)) { + /// + /// Program APIC Range Select bits that define address bits 19:12 for the IOxAPIC range. + /// This value must not be changed unless the IOxAPIC Enable bit is cleared. + /// + MmioAnd16 ((UINTN) (RootComplexBar + R_PCH_RCRB_OIC), (UINT16)~(B_PCH_RCRB_OIC_AEN)); + /// + /// Program APIC Range Select bits at RCBA + 31FEh[7:0] + /// + MmioAndThenOr16 ( + RootComplexBar + R_PCH_RCRB_OIC, + (UINT16)~(V_PCH_RCRB_OIC_ASEL), + (UINT16) IoApicConfig->ApicRangeSelect + ); + } + /// + /// PCH BIOS Spec Rev 0.5.0, Section 6.6.2.1 + /// 1. Enable the IOAPIC by setting the APIC Enable bit, RCBA + offset 31FFh, Bit[0] if the + /// system needs to use the IOxAPIC. The APIC Enable bits needs read back after the bit is written. + /// + MmioOr16 ((UINTN) (RootComplexBar + R_PCH_RCRB_OIC), (UINT16) B_PCH_RCRB_OIC_AEN); + /// + /// Reads back for posted write to take effect + /// + MmioRead16 (RootComplexBar + R_PCH_RCRB_OIC); + + /// + /// Get current IO APIC ID + /// + IoApicAddress = (UINT32) (MmioRead8 (RootComplexBar + R_PCH_RCRB_OIC) << N_PCH_IO_APIC_ASEL); + MmioWrite8 ((UINTN) (R_PCH_IO_APIC_INDEX | IoApicAddress), 0); + IoApicId = MmioRead32 ((UINTN) (R_PCH_IO_APIC_DATA | IoApicAddress)) >> 24; + /// + /// IO APIC ID is at APIC Identification Register [27:24] + /// + if ((IoApicConfig->IoApicId != IoApicId) && (IoApicConfig->IoApicId < 0x10)) { + /// + /// Program APIC ID + /// + MmioWrite8 ((UINTN) (R_PCH_IO_APIC_INDEX | IoApicAddress), 0); + MmioWrite32 ((UINTN) (R_PCH_IO_APIC_DATA | IoApicAddress), (UINT32) (IoApicConfig->IoApicId << 24)); + } + + if (GetPchSeries() == PchLp) { + if (IoApicConfig->IoApicEntry24_39 == PCH_DEVICE_DISABLE) { + /// + /// Program IOAPIC Entry 24-39 Disable bit at RCBA + 31FEh[11] + /// + MmioOr16 (RootComplexBar + R_PCH_RCRB_OIC, (UINT16) B_PCH_RCRB_OIC_OA24_39_D); + } + } + + return EFI_SUCCESS; +} + +/** + This function performs basic initialization for PCH in PEI phase. + If any of the base address arguments is zero, this function will disable the corresponding + decoding, otherwise this function will enable the decoding. + This function locks down the PMBase. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] NotifyDescriptor The notification structure this PEIM registered on install. + @param[in] Ppi The memory discovered PPI. Not used. + + @retval EFI_SUCCESS Succeeds. + @retval EFI_DEVICE_ERROR Device error, aborts abnormally. +**/ +EFI_STATUS +EFIAPI +PchInitialize ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + EFI_STATUS Status; + UINT8 Data8Or; + UINT8 Data8And; + PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi; +#ifdef EFI_DEBUG + UINT8 Index; +#endif +#ifdef USB_PRECONDITION_ENABLE_FLAG + EFI_BOOT_MODE BootMode; +#endif // USB_PRECONDITION_ENABLE_FLAG + UINTN AcpiBarAddress; + UINTN GpioBarAddress; + + DEBUG ((EFI_D_INFO, "PchInitialize() - Start\n")); + + /// + /// Get platform policy settings through the PchPlatformPolicy PPI + /// + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gPchPlatformPolicyPpiGuid, + 0, + NULL, + (VOID **)&PchPlatformPolicyPpi + ); + ASSERT_EFI_ERROR (Status); +#ifdef EFI_DEBUG + DEBUG ((EFI_D_INFO, "\n------------------------ PchPlatformPolicyPpi Dump Begin -----------------\n")); + DEBUG ((EFI_D_INFO, "Revision : 0x%x\n", PchPlatformPolicyPpi->Revision)); + DEBUG ((EFI_D_INFO, "BusNumber : 0x%x\n", PchPlatformPolicyPpi->BusNumber)); + DEBUG ((EFI_D_INFO, "Rcba : 0x%x\n", PchPlatformPolicyPpi->Rcba)); + DEBUG ((EFI_D_INFO, "PmBase : 0x%x\n", PchPlatformPolicyPpi->PmBase)); + DEBUG ((EFI_D_INFO, "GpioBase : 0x%x\n", PchPlatformPolicyPpi->GpioBase)); + + DEBUG ((EFI_D_INFO, "PCH GBE Configuration --- \n")); + DEBUG ((EFI_D_INFO, " EnableGbe : 0x%x\n", PchPlatformPolicyPpi->GbeConfig->EnableGbe)); + + DEBUG ((EFI_D_INFO, "\n------------------------ PCH THERMAL Configuration -----------------\n")); + DEBUG ((EFI_D_INFO, "PCH MEMORY THERMAL MANAGEMENT --- \n")); + DEBUG ( + (EFI_D_INFO, + "MemoryThrottling->Enable : 0x%x\n", + PchPlatformPolicyPpi->ThermalMgmt->MemoryThrottling->Enable) + ); + DEBUG ( + (EFI_D_INFO, + "MemoryThrottling->TsGpioPinSetting[TsGpioC].PmsyncEnable : 0x%x\n", + PchPlatformPolicyPpi->ThermalMgmt->MemoryThrottling->TsGpioPinSetting[TsGpioC].PmsyncEnable) + ); + DEBUG ( + (EFI_D_INFO, + "MemoryThrottling->TsGpioPinSetting[TsGpioD].PmsyncEnable : 0x%x\n", + PchPlatformPolicyPpi->ThermalMgmt->MemoryThrottling->TsGpioPinSetting[TsGpioD].PmsyncEnable) + ); + DEBUG ( + (EFI_D_INFO, + "MemoryThrottling->TsGpioPinSetting[TsGpioC].C0TransmitEnable : 0x%x\n", + PchPlatformPolicyPpi->ThermalMgmt->MemoryThrottling->TsGpioPinSetting[TsGpioC].C0TransmitEnable) + ); + DEBUG ( + (EFI_D_INFO, + "MemoryThrottling->TsGpioPinSetting[TsGpioD].C0TransmitEnable : 0x%x\n", + PchPlatformPolicyPpi->ThermalMgmt->MemoryThrottling->TsGpioPinSetting[TsGpioD].C0TransmitEnable) + ); + DEBUG ( + (EFI_D_INFO, + "MemoryThrottling->TsGpioPinSetting[TsGpioC].PinSelection : 0x%x\n", + PchPlatformPolicyPpi->ThermalMgmt->MemoryThrottling->TsGpioPinSetting[TsGpioC].PinSelection) + ); + DEBUG ( + (EFI_D_INFO, + "MemoryThrottling->TsGpioPinSetting[TsGpioD].PinSelection : 0x%x\n", + PchPlatformPolicyPpi->ThermalMgmt->MemoryThrottling->TsGpioPinSetting[TsGpioD].PinSelection) + ); + + DEBUG ((EFI_D_INFO, "PCH HPET Configuration --- \n")); + DEBUG ((EFI_D_INFO, " Enable : 0x%x\n", PchPlatformPolicyPpi->HpetConfig->Enable)); + DEBUG ((EFI_D_INFO, " Base : 0x%x\n", PchPlatformPolicyPpi->HpetConfig->Base)); + + DEBUG ((EFI_D_INFO, "PCH RESERVED PAGE ROUTE --- \n")); + if (PchPlatformPolicyPpi->Port80Route == PchReservedPageToLpc) { + DEBUG ((EFI_D_INFO, " Port80Route : PchReservedPageToLpc\n")); + } else if (PchPlatformPolicyPpi->Port80Route == PchReservedPageToPcie) { + DEBUG ((EFI_D_INFO, " Port80Route : PchReservedPageToPciE\n")); + } + + DEBUG ((EFI_D_INFO, "PCH SATA Mode --- \nSataMode : ")); + switch (PchPlatformPolicyPpi->SataConfig->SataMode) { + case PchSataModeIde: + DEBUG ((EFI_D_INFO, "PchSataModeIde")); + break; + case PchSataModeAhci: + DEBUG ((EFI_D_INFO, "PchSataModeAhci")); + break; + case PchSataModeRaid: + DEBUG ((EFI_D_INFO, "PchSataModeRaid")); + break; + case PchSataModeLoopbackTest: + DEBUG ((EFI_D_INFO, "PchSataModeLoopbackTest")); + break; + default: + break; + } + + DEBUG ((EFI_D_INFO, "\nPCH IO APIC Configuration --- \n")); + DEBUG ((EFI_D_INFO, " IoApicId : 0x%x\n", PchPlatformPolicyPpi->IoApicConfig->IoApicId)); + DEBUG ((EFI_D_INFO, " ApicRangeSelect : 0x%x\n", PchPlatformPolicyPpi->IoApicConfig->ApicRangeSelect)); + + DEBUG ((EFI_D_INFO, "PCH PCIE Speed--- \n")); + for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) { + if (PchPlatformPolicyPpi->PcieConfig->PcieSpeed[Index] == PchPcieGen1) { + DEBUG ((EFI_D_INFO, " PCIE Port %x Speed: PchPcieGen1\n", Index)); + } else if (PchPlatformPolicyPpi->PcieConfig->PcieSpeed[Index] == PchPcieGen2) { + DEBUG ((EFI_D_INFO, " PCIE Port %x Speed: PchPcieGen2\n", Index)); + } else if (PchPlatformPolicyPpi->PcieConfig->PcieSpeed[Index] == PchPcieAuto) { + DEBUG ((EFI_D_INFO, " PCIE Port %x Speed: PchPcieAuto\n", Index)); + } + } + + DEBUG ((EFI_D_INFO, "Platform Data Configuration --- \n")); + DEBUG ((EFI_D_INFO, " EcPresent : %x\n", PchPlatformPolicyPpi->PlatformData->EcPresent)); + DEBUG ((EFI_D_INFO, " SmmBwp : %x\n", PchPlatformPolicyPpi->PlatformData->SmmBwp)); + + DEBUG ((EFI_D_INFO, "\n------------------------ PchPlatformPolicyPpi Dump End -----------------\n")); +#endif + /// + /// Set Rcba + /// + ASSERT ((PchPlatformPolicyPpi->Rcba & (UINT32) (~B_PCH_LPC_RCBA_BAR)) == 0); + MmioAndThenOr32 ( + MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_RCBA), + (UINT32) (~B_PCH_LPC_RCBA_BAR), + PchPlatformPolicyPpi->Rcba | B_PCH_LPC_RCBA_EN + ); + + /// + /// Set PM Base + /// + AcpiBarAddress = MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_ACPI_BASE + ); + MmioWrite32 (AcpiBarAddress, PchPlatformPolicyPpi->PmBase); + ASSERT ((MmioRead32 (AcpiBarAddress) & B_PCH_LPC_ACPI_BASE_BAR) == PchPlatformPolicyPpi->PmBase); + if (PchPlatformPolicyPpi->PmBase != 0) { + /// + /// Enable PM Base + /// + MmioOr8 ( + MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_ACPI_CNT), + (UINT8) B_PCH_LPC_ACPI_CNT_ACPI_EN + ); + } else { + /// + /// Disable PM Base + /// + MmioAnd8 ( + MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_ACPI_CNT), + (UINT8) (~B_PCH_LPC_ACPI_CNT_ACPI_EN) + ); + } + /// + /// Lock down the PM Base + /// + MmioOr8 ( + MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_GEN_PMCON_LOCK), + (UINT8) (B_PCH_LPC_GEN_PMCON_LOCK_ABASE_LK) + ); + + /// + /// Set GPIO Base + /// + GpioBarAddress = MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_GPIO_BASE + ); + MmioWrite32 (GpioBarAddress, PchPlatformPolicyPpi->GpioBase); + ASSERT ((MmioRead32 (GpioBarAddress) & B_PCH_LPC_GPIO_BASE_BAR) == PchPlatformPolicyPpi->GpioBase); + if (PchPlatformPolicyPpi->GpioBase != 0) { + /// + /// Enable GPIO Base + /// + MmioOr8 ( + MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_GPIO_CNT), + (UINT8) B_PCH_LPC_GPIO_CNT_GPIO_EN + ); + } else { + /// + /// Disable GPIO Base + /// + MmioAnd8 ( + MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_GPIO_CNT), + (UINT8) (~B_PCH_LPC_GPIO_CNT_GPIO_EN) + ); + } + + if (PchPlatformPolicyPpi->PlatformData->SmmBwp == 0) { + /// + /// Clear SMM_BWP bit (D31:F0:RegDCh[5]) + /// + Data8And = (UINT8) ~B_PCH_LPC_BIOS_CNTL_SMM_BWP; + Data8Or = 0x00; + } else { + /// + /// Set SMM_BWP and BLE bit (D31:F0:RegDCh[5][1]) + /// + Data8And = 0xFF; + Data8Or = (UINT8) (B_PCH_LPC_BIOS_CNTL_SMM_BWP + B_PCH_LPC_BIOS_CNTL_BLE); + } + + MmioAndThenOr8 ( + MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_BIOS_CNTL), + Data8And, + Data8Or + ); + + Status = PchSataInit (PeiServices, PchPlatformPolicyPpi); + ASSERT_EFI_ERROR (Status); + + Status = PchDmiMiscProg (PeiServices, PchPlatformPolicyPpi); + ASSERT_EFI_ERROR (Status); + + Status = PchGbeMandatedReset (PeiServices, PchPlatformPolicyPpi); + ASSERT_EFI_ERROR (Status); + + Status = PchMiscInit (PchPlatformPolicyPpi); + ASSERT_EFI_ERROR (Status); + Status = PchThermalInit (PchPlatformPolicyPpi); + ASSERT_EFI_ERROR (Status); + Status = PchIoApicInit (PchPlatformPolicyPpi); + ASSERT_EFI_ERROR (Status); + +#ifdef USB_PRECONDITION_ENABLE_FLAG + if (PchPlatformPolicyPpi->Revision > PCH_PLATFORM_POLICY_PPI_REVISION_1) { + /// + /// If it is in S3 boot path or recovery mode, do nothing + /// + Status = (*PeiServices)->GetBootMode (PeiServices, &BootMode); + if (!EFI_ERROR (Status)) { + if ((BootMode != BOOT_ON_S3_RESUME) && (BootMode != BOOT_IN_RECOVERY_MODE)) { + if (PchPlatformPolicyPpi->UsbConfig->UsbPrecondition) { + + /// + /// Initialize PCH USB when USB_PRECONDITION feature is enabled by USB_CONFIG policy + /// Initialize PCH EHCI and XHCI by the same MMIO resource one by one + /// + Status = PchStartUsbInit ( + PchPlatformPolicyPpi->UsbConfig, + PchPlatformPolicyPpi->PlatformData->TempMemBaseAddr, + PchPlatformPolicyPpi->PlatformData->TempMemBaseAddr, + PchPlatformPolicyPpi->Revision + ); + ASSERT_EFI_ERROR (Status); + } + } + } + } +#endif // USB_PRECONDITION_ENABLE_FLAG + DEBUG ((EFI_D_INFO, "PchInitialize() - End\n")); + + /// + /// Install the PCH PEI Init Done PPI + /// + Status = (**PeiServices).InstallPpi (PeiServices, &mPpiPchPeiInitDone); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Internal function performing miscellaneous init needed in very early PEI phase + + @param[in] RootComplexBar RootComplexBar address of this PCH device + + @retval None +**/ +VOID +PchMiscEarlyInit ( + IN UINT32 RootComplexBar + ) +{ + UINTN PciD31F0RegBase; + UINT8 Nmi; + UINT8 Data8; + UINT32 Data32Or; + + DEBUG ((EFI_D_INFO, "PchMiscEarlyInit() - Start\n")); + /// + /// PCH BIOS Spec Rev 0.5.0, Section 7.1.3 PCH Display Port Enable + /// Step 1 + /// Set RCBA + 3424h = 0010h + /// + MmioWrite16 ((UINTN) (RootComplexBar + R_PCH_RCRB_DISPBDF), (UINT16) 0x10); + + /// + /// Step 2 + /// Set RCBA + 3428h[0] = 1b + /// + Data32Or = B_PCH_RCRB_FD2_DBDFEN; + MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_FD2), Data32Or); + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 19.3 Power Failure Considerations + /// RTC_PWR_STS bit, GEN_PMCON_3 (D31:F0:A4h[2]) + /// When the RTC_PWR_STS bit is set, it indicates that the RTCRST# signal went low. + /// Software should clear this bit. For example, changing the RTC battery sets this bit. + /// System BIOS should reset CMOS to default values if the RTC_PWR_STS bit is set. + /// The System BIOS should execute the sequence below if the RTC_PWR_STS bit is set + /// before memory initialization. This will ensure that the RTC state machine has been + /// initialized. + /// 1. If the RTC_PWR_STS bit is set which indicates a new coin-cell battery insertion or a + /// battery failure, steps 2 through 5 should be executed. + /// 2. Set RTC Register 0Ah[6:4] to 110b or 111b + /// 3. Set RTC Register 0Bh[7]. + /// 4. Set RTC Register 0Ah[6:4] to 010b + /// 5. Clear RTC Register 0Bh[7]. + /// + PciD31F0RegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); + + if ((MmioRead16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_3) & + (UINT16) B_PCH_LPC_GEN_PMCON_RTC_PWR_STS) != 0) { + /// + /// Enable Alternate Access Mode + /// Note: The RTC Index field (including the NMI mask at bit7) is write-only + /// for normal operation and can only be read in Alt Access Mode. + /// + PchAlternateAccessMode (RootComplexBar, TRUE); + /// + /// Read NMI Enable bit + /// + Nmi = IoRead8 (R_PCH_NMI_EN) & (UINT8) B_PCH_NMI_EN_NMI_EN; + /// + /// Disable Alternate Access Mode + /// + PchAlternateAccessMode (RootComplexBar, FALSE); + /// + /// 2. Set RTC Register 0Ah[6:4] to 110b or 111b + /// + IoWrite8 (R_PCH_RTC_INDEX, (UINT8) (R_PCH_RTC_REGA | Nmi)); + Data8 = IoRead8 (R_PCH_RTC_TARGET) & (UINT8) ~(BIT6 | BIT5 | BIT4); + Data8 |= (UINT8) (BIT6 | BIT5); + IoWrite8 (R_PCH_RTC_TARGET, Data8); + /// + /// 3. Set RTC Register 0Bh[7]. + /// + IoWrite8 (R_PCH_RTC_INDEX, (UINT8) (R_PCH_RTC_REGB | Nmi)); + IoOr8 (R_PCH_RTC_TARGET, (UINT8) B_PCH_RTC_REGB_SET); + /// + /// 4. Set RTC Register 0Ah[6:4] to 010b + /// + IoWrite8 (R_PCH_RTC_INDEX, (UINT8) (R_PCH_RTC_REGA | Nmi)); + Data8 = IoRead8 (R_PCH_RTC_TARGET) & (UINT8) ~(BIT6 | BIT5 | BIT4); + Data8 |= (UINT8) (BIT5); + IoWrite8 (R_PCH_RTC_TARGET, Data8); + /// + /// 5. Clear RTC Register 0Bh[7]. + /// + IoWrite8 (R_PCH_RTC_INDEX, (UINT8) (R_PCH_RTC_REGB | Nmi)); + IoAnd8 (R_PCH_RTC_TARGET, (UINT8) ~B_PCH_RTC_REGB_SET); + } + /// + /// PCH BIOS Spec Rev 0.5.0, Section 19.1 Handling Status Registers + /// System BIOS must set 1b to clear the following registers during power-on + /// and resuming from Sx sleep state. + /// - RCBA + Offset 3310h[0] = 1b + /// Done in ConfigureMiscItems () + /// - RCBA + Offset 3310h[4] = 1b, needs to be done as early as possible during PEI + /// - RCBA + Offset 3310h[5] = 1b + /// Done in ConfigureMiscItems () + /// + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_PRSTS), + (UINT32) (B_PCH_RCRB_PRSTS_FIELD_1) + ); + + DEBUG ((EFI_D_INFO, "PchMiscEarlyInit() - End\n")); + + return; +} + +/// +/// Entry point +/// + +/** + Installs the PCH PEI Init PPI + Performing Pch early init after PchPlatfromPolicy PPI produced + + @param[in] FfsHeader Not used. + @param[in] PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS The function completes successfully + @retval EFI_OUT_OF_RESOURCES Insufficient resources to create database +**/ +EFI_STATUS +EFIAPI +InstallPchInitPpi ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + UINT32 RootComplexBar; + EFI_PEI_PPI_DESCRIPTOR *PchDmiTcVcMapPpiDesc; + PCH_DMI_TC_VC_PPI *PchDmiTcVcMapPpi; + + DEBUG ((EFI_D_INFO, "InstallPchInitPpi() - Start\n")); + + /// + /// Check if Rcba has been set + /// + RootComplexBar = PCH_RCRB_BASE; + DEBUG ((EFI_D_INFO, "Rcba needs to be programmed before here\n")); + ASSERT ((RootComplexBar & (UINT32) (~B_PCH_LPC_RCBA_BAR)) == 0); + /// + /// Perform miscellaneous init needed in very early PEI phase + /// + PchMiscEarlyInit (RootComplexBar); + + /// + /// Install the DMI TC VC PPI + /// Allocate descriptor and PPI structures. Since these are dynamically updated + /// + PchDmiTcVcMapPpiDesc = (EFI_PEI_PPI_DESCRIPTOR *) AllocateZeroPool (sizeof (EFI_PEI_PPI_DESCRIPTOR)); + if (PchDmiTcVcMapPpiDesc == NULL) { + DEBUG ((EFI_D_ERROR, "Failed to allocate memory for PchDmiTcVcMapPpiDesc! \n")); + return EFI_OUT_OF_RESOURCES; + } + + PchDmiTcVcMapPpi = (PCH_DMI_TC_VC_PPI *) AllocateZeroPool (sizeof (PCH_DMI_TC_VC_PPI)); + if (PchDmiTcVcMapPpi == NULL) { + DEBUG ((EFI_D_ERROR, "Failed to allocate memory for PchDmiTcVcMapPpi! \n")); + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (PchDmiTcVcMapPpi, &mPchDmiTcVcMap, sizeof (PCH_DMI_TC_VC_PPI)); + + PchDmiTcVcMapPpiDesc->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + PchDmiTcVcMapPpiDesc->Guid = &gPchDmiTcVcMapPpiGuid; + PchDmiTcVcMapPpiDesc->Ppi = PchDmiTcVcMapPpi; + Status = (**PeiServices).InstallPpi (PeiServices, PchDmiTcVcMapPpiDesc); + ASSERT_EFI_ERROR (Status); + + /// + /// Install the PCH PEI Init PPI + /// + Status = (**PeiServices).InstallPpi (PeiServices, &mPpiListVariable); + ASSERT_EFI_ERROR (Status); + + /// + /// Performing Pch early init after PchPlatfromPolicy PPI produced + /// + Status = (**PeiServices).NotifyPpi (PeiServices, &mNotifyList); + ASSERT_EFI_ERROR (Status); + + Status = (**PeiServices).NotifyPpi (PeiServices, &mPchS3ResumeNotifyDesc); + ASSERT_EFI_ERROR (Status); + + DEBUG ((EFI_D_INFO, "InstallPchInitPpi() - End\n")); + + return Status; +} + +/** + This function trigger SMI through Iotrap to perform PCH register save and restore in SMI + + @param[in] PeiServices - Pointer to PEI Services Table. + @param[in] NotifyDesc - Pointer to the descriptor for the Notification event that + caused this function to execute. + @param[in] Ppi - Pointer to the PPI data associated with this function. + + @retval EFI_STATUS - Always return EFI_SUCCESS +**/ +EFI_STATUS +PchS3ResumeAtEndOfPei ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc, + IN VOID *Ppi + ) +{ + EFI_STATUS Status; + EFI_BOOT_MODE BootMode; + PCH_LATE_INIT_SMM_VARIABLE SaveRestoreData; + UINTN VariableSize; + PEI_READ_ONLY_VARIABLE_PPI *VariableServices; + + Status = PeiServicesGetBootMode (&BootMode); + DEBUG ((EFI_D_INFO, "[PCH] BootMode = %X\n", BootMode)); + + if (BootMode != BOOT_ON_S3_RESUME) { + return EFI_SUCCESS; + } + /// + /// Locate Variable Ppi + /// + Status = (*PeiServices)->LocatePpi (PeiServices, &gPeiReadOnlyVariablePpiGuid, 0, NULL, &VariableServices); + ASSERT_EFI_ERROR (Status); + + VariableSize = sizeof (PCH_LATE_INIT_SMM_VARIABLE); + Status = VariableServices->PeiGetVariable ( + PeiServices, + PCH_INIT_PEI_VARIABLE_NAME, + &gPchInitPeiVariableGuid, + NULL, + &VariableSize, + &SaveRestoreData + ); + + if (EFI_ERROR(Status)) { + return EFI_SUCCESS; + } + + /// + /// Write to IO trap address to trigger SMI for register restoration + /// + DEBUG ((EFI_D_INFO, "S3 SMI register restoration\n")); + IoWrite16 (SaveRestoreData.IoTrapAddress, 0x0); + + return EFI_SUCCESS; +} diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.cif b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.cif new file mode 100644 index 0000000..f8cc797 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.cif @@ -0,0 +1,17 @@ +<component> + name = "PchInitPeim" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\LynxPoint\PchInit\Pei" + RefName = "PchInitPeim" +[files] +"PchInitPeim.sdl" +"PchInitPeim.mak" +"PchInitPeim.h" +"PchInitPeim.c" +"PchInitPeim.dxs" +"PchInitPeim.inf" +"PchUsbInit.c" +"PchInitCommon.h" +"PchDmiPeim.c" +"PchUsbPreconditionPeim.c" +<endComponent> diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.dxs b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.dxs new file mode 100644 index 0000000..a2a2f80 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.dxs @@ -0,0 +1,39 @@ +/** @file + Dependency expression source file. + +@copyright + Copyright (c) 2004 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains a 'Sample Driver' and is licensed as such + under the terms of your license agreement with Intel or your + vendor. This file may be modified by the user, subject to + the additional terms of the license agreement + +**/ + + +// +// Common for R8 and R9 codebase +// +#include "AutoGen.h" +#include "PeimDepex.h" + +// +// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase; +// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version +// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase. +// +#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB) +#include "EfiDepex.h" +#endif + +DEPENDENCY_START + TRUE +DEPENDENCY_END diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.h b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.h new file mode 100644 index 0000000..1e433db --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.h @@ -0,0 +1,253 @@ +/** @file + Header file for the PCH Init PEIM + +@copyright + Copyright (c) 2004 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ +#ifndef _PCH_INIT_PEIM_H_ +#define _PCH_INIT_PEIM_H_ + +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) + +#include "EdkIIGluePeim.h" +#include "PchInitVar.h" +#include "PchAccess.h" +#include "PchPlatformLib.h" +#include "PchUsbCommon.h" +#include "IobpDefinitions.h" +#include "PchHsio.h" +#include EFI_PPI_PRODUCER (PchInit) +#include EFI_PPI_PRODUCER (PchDmiTcVcMap) +#include EFI_PPI_CONSUMER (MemoryDiscovered) +#include EFI_PPI_CONSUMER (PchUsbPolicy) +#include EFI_PPI_CONSUMER (PchPlatformPolicy) +#include EFI_PPI_CONSUMER (PchReset) +#include EFI_PPI_PRODUCER (PchPeiInitDone) +#endif + +// +// ChipsetInit settings defines +// +#define H2M_HSIO_MESSAGE (0x7 << 28)///< Master type for all H2M Hsio messages +#define H2M_HSIO_CMD_GETHSIOVER 1 ///< Triggers Hsio version to be sent through ME/Host FW Status registers +#define H2M_HSIO_CMD_CLOSE 0 ///< Triggers H2M Hsio interface to close and revert FW Status registers +#define M2H_HSIO_MSG_ACK 0x7 ///< Ack sent in response to any H2M Hsio messages +#define MAX_ME_MSG_ACK_TIMEOUT 0x186A0 // Wait max of 100ms for FW to acknowledge. + +/** + Internal function performing SATA init needed in PEI phase + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval None +**/ +EFI_STATUS +EFIAPI +PchSataInit ( + IN EFI_PEI_SERVICES **PeiServices, + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ); + +/** + This function may trigger platform reset depending on the current GbE status, + the intended GbE enabling, and current ME status. (When ME is enabled, this function + may trigger a Global reset.) + This function may not return if it triggers an platform reset and the BIOS boot flow + restarts. + If this function returns EFI_SUCCESS it indicates there is no need for platform + reset in this boot, and boot flow continues. + If this function returns EFI_DEVICE_ERROR, something error happens. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval EFI_SUCCESS No platform reset action is taken. System can continue boot flow. + @retval Others Won't return if platform reset action is taken +**/ +EFI_STATUS +EFIAPI +PchGbeMandatedReset ( + IN EFI_PEI_SERVICES **PeiServices, + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ); + +/** + Perform Thermal Management Support initialization + + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval EFI_SUCCESS Succeeds. + @retval EFI_DEVICE_ERROR Device error, aborts abnormally. +**/ +EFI_STATUS +PchThermalInit ( + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ); + +/** + Initialize IOAPIC according to IoApicConfig policy of the PCH + Platform Policy PPI + + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval EFI_SUCCESS Succeeds. + @retval EFI_DEVICE_ERROR Device error, aborts abnormally. +**/ +EFI_STATUS +PchIoApicInit ( + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ); + +/** + This function performs basic initialization for PCH in PEI phase. + If any of the base address arguments is zero, this function will disable the corresponding + decoding, otherwise this function will enable the decoding. + This function locks down the PMBase. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] NotifyDescriptor The notification structure this PEIM registered on install. + @param[in] Ppi The memory discovered PPI. Not used. + + @retval EFI_SUCCESS Succeeds. + @retval EFI_DEVICE_ERROR Device error, aborts abnormally. +**/ +EFI_STATUS +EFIAPI +PchInitialize ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +/** + The function performing USB init in PEI phase. This could be used by USB recovery + or debug features that need USB initialization during PEI phase. + Note: Before executing this function, please be sure that PCH_INIT_PPI.Initialize + has been done and PchUsbPolicyPpi has been installed. + + @param[in] PeiServices General purpose services available to every PEIM + + @retval EFI_SUCCESS The function completed successfully + @retval Others All other error conditions encountered result in an ASSERT. +**/ +EFI_STATUS +EFIAPI +PchUsbInit ( + IN EFI_PEI_SERVICES **PeiServices + ); + +/** + The function performing TC/VC mapping program, and poll all PCH Virtual Channel + until negotiation completion + + @param[in] PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS The function completed successfully + @retval Others All other error conditions encountered result in an ASSERT. +**/ +EFI_STATUS +EFIAPI +PchDmiTcVcProgPoll ( + IN EFI_PEI_SERVICES **PeiServices + ); + +/** + The function set the Target Link Speed in PCH to DMI GEN 2. + + @param[in] PeiServices General purpose services available to every PEIM. + + @retval None +**/ +VOID +EFIAPI +PchDmiGen2Prog ( + IN EFI_PEI_SERVICES **PeiServices + ); + +/** + The function program DMI miscellaneous registers. + + @param[in] PeiServices General purpose services available to every PEIM + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval EFI_SUCCESS The DMI required settings programmed correctly +**/ +EFI_STATUS +EFIAPI +PchDmiMiscProg ( + IN EFI_PEI_SERVICES **PeiServices, + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ); + +/** + The function is used while doing CPU Only Reset, where PCH may be required + to initialize strap data before soft reset. + + @param[in] PeiServices General purpose services available to every PEIM + @param[in] Operation Get/Set Cpu Strap Set Data + @param[in, out] CpuStrapSet Cpu Strap Set Data + + @retval EFI_SUCCESS The function completed successfully. + @exception EFI_UNSUPPORTED The function is not supported. +**/ +EFI_STATUS +EFIAPI +PchCpuStrapSet ( + IN EFI_PEI_SERVICES **PeiServices, + IN CPU_STRAP_OPERATION Operation, + IN OUT UINT16 *CpuStrapSet + ); + +/** + The function performing USB init in PEI phase. This could be + used by USB recovery ,debug features or usb precondition + enabled case that need USB initialization during PEI phase. + Please be sure the function should not be executed in if the + boot mode is S3 resume. + + @param[in] PeiServices General purpose services available to every PEIM + + @retval EFI_SUCCESS The function completed successfully + @retval Others All other error conditions encountered result in an ASSERT. +**/ +EFI_STATUS +PchStartUsbInit ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINT32 EhciMemBaseAddr, + IN UINT32 XhciMemBaseAddr, + IN UINT8 Revision + ); + +/** + This function handles Pch S3 resume task + + @param[in] PeiServices - Pointer to PEI Services Table. + @param[in] NotifyDesc - Pointer to the descriptor for the Notification event that + caused this function to execute. + @param[in] Ppi - Pointer to the PPI data associated with this function. + + @retval EFI_STATUS - Always return EFI_SUCCESS +**/ +EFI_STATUS +PchS3ResumeAtEndOfPei ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc, + IN VOID *Ppi + ); + +#endif diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.inf b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.inf new file mode 100644 index 0000000..02e4639 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.inf @@ -0,0 +1,108 @@ +## @file +# Component description file for the PCH Init PEIM. +# +#@copyright +# Copyright (c) 2004 - 2013 Intel Corporation. All rights reserved +# This software and associated documentation (if any) is furnished +# under a license and may only be used or copied in accordance +# with the terms of the license. Except as permitted by such +# license, no part of this software or documentation may be +# reproduced, stored in a retrieval system, or transmitted in any +# form or by any means without the express written consent of +# Intel Corporation. +# +# This file contains a 'Sample Driver' and is licensed as such +# under the terms of your license agreement with Intel or your +# vendor. This file may be modified by the user, subject to +# the additional terms of the license agreement +# + +[defines] +BASE_NAME = PchInitPeim +FILE_GUID = FD236AE7-0791-48c4-B29E-29BDEEE1A838 +COMPONENT_TYPE = PE32_PEIM + +[sources.common] + PchInitPeim.h + PchInitPeim.c + PchUsbInit.c + ../Common/PchUsbCommon.c + ../Common/PchInitVar.c + ../Common/PchHsio.c + ../Common/PchHsioLptHB0.c + ../Common/PchHsioLptHCx.c + ../Common/PchHsioLptLpBx.c + PchDmiPeim.c + + PchUsbPreconditionPeim.c +# +# Edk II Glue Driver Entry Point +# + EdkIIGluePeimEntryPoint.c + +[includes.common] + . + ../Common + $(EDK_SOURCE)/Foundation/Efi + $(EDK_SOURCE)/Foundation/Include + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT) + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Protocol/PchPlatformPolicy + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Guid/ChipsetInitHob + $(EFI_SOURCE)/$(PROJECT_ME_ROOT) + $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Heci/Include + $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Library/MeKernel/include +# +# EDK II Glue Library utilizes some standard headers from EDK +# + $(EFI_SOURCE) + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Include/Pei + $(EDK_SOURCE)/Foundation/library/Pei/Include + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include + $(EDK_SOURCE)/Foundation/Efi + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework/Include + $(EDK_SOURCE)/Foundation/Include + +[libraries.common] + $(PROJECT_PCH_FAMILY)PpiLib + EdkFrameworkPpiLib + EdkIIGlueBaseIoLibIntrinsic + EdkIIGlueBaseMemoryLib + EdkIIGluePeiDebugLibReportStatusCode + EdkIIGluePeiReportStatusCodeLib + EdkIIGluePeiServicesLib + EdkIIGluePeiMemoryAllocationLib + EdkIIGluePeiFirmwarePerformanceLib + EdkIIGlueBasePciLibPciExpress + EdkPpiLib + PchPlatformLib + PeiLib + $(PROJECT_PCH_FAMILY)PpiLib + EdkIIGluePeiFirmwarePerformanceLib + PchPlatformLib + MeLibPpi + MeGuidLib + +[nmake.common] + IMAGE_ENTRY_POINT = _ModuleEntryPoint + DPX_SOURCE = PchInitPeim.dxs +# +# Module Entry Point +# + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=InstallPchInitPpi + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \ + -D __EDKII_GLUE_BASE_MEMORY_LIB__ \ + -D __EDKII_GLUE_PEI_DEBUG_LIB_REPORT_STATUS_CODE__ \ + -D __EDKII_GLUE_PEI_REPORT_STATUS_CODE_LIB__ \ + -D __EDKII_GLUE_PEI_SERVICES_LIB__ \ + -D __EDKII_GLUE_PEI_MEMORY_ALLOCATION_LIB__ \ + -D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.mak b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.mak new file mode 100644 index 0000000..0bd26c3 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.mak @@ -0,0 +1,117 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchInitPeim/PchInitPeim.mak 4 12/18/12 4:53a Scottyang $ +# +# $Revision: 4 $ +# +# $Date: 12/18/12 4:53a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchInitPeim/PchInitPeim.mak $ +# +# 4 12/18/12 4:53a Scottyang +# [TAG] EIP109697 +# [Category] Improvement +# [Description] Update PCH RC 0.8.1 +# [Files] ReferenceCode\Chipset\LynxPoint\*.*, SBDxe.c, SBPEI.c, SB.sd, +# SbSetupData.c, GetSetupDate.c +# +# 3 11/20/12 8:36a Scottyang +# [TAG] EIP107014 +# [Category] Improvement +# [Description] Update RC 0.8.0 +# [Files] ReferenceCode\Chipset\LynxPoint\*.*, SBDxe.c, SB.sd, +# SbSetupData.c, GetSetupDate.c +# +# 2 2/24/12 2:13a Victortu +# Updated to support 4.6.5.3_IntelEDK_1117_Patch7_00. +# +# 1 2/08/12 8:53a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* + +#--------------------------------------------------------------------------- +# Create PchInitPeim module +#--------------------------------------------------------------------------- +EDK : PchInitPeim +PchInitPeim : $(BUILD_DIR)\PchInitPeim.mak PchInitPeimBin + + +$(BUILD_DIR)\PchInitPeim.mak : $(PchInitPeim_DIR)\$(@B).cif $(PchInitPeim_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(PchInitPeim_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +PchInitPeim_INCLUDES=\ + /I$(INTEL_PCH_DIR)\PchInit\Common\ + $(INTEL_PCH_INCLUDES)\ + $(EdkIIGlueLib_INCLUDES)\ + /I$(INTEL_PCH_DIR)\Guid\SurvivabilityHob\ + $(ME_INCLUDES)\ + +PchInitPeim_DEFINES = $(MY_DEFINES)\ + /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=InstallPchInitPpi"\ + /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \ + /D __EDKII_GLUE_PEI_DEBUG_LIB_REPORT_STATUS_CODE__ \ + /D __EDKII_GLUE_PEI_REPORT_STATUS_CODE_LIB__ \ + /D __EDKII_GLUE_PEI_SERVICES_LIB__ \ + /D __EDKII_GLUE_PEI_MEMORY_ALLOCATION_LIB__ \ + /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ + +PchInitPeim_LIB_LINKS =\ + $(GuidLib_LIB) \ + $(PchPlatformPeiLib_LIB) \ + $(IntelPchPpiLib_LIB)\ + $(EDKFRAMEWORKPPILIB) \ + $(EdkIIGlueBaseLib_LIB)\ + $(EdkIIGlueBaseLibIA32_LIB)\ + $(EdkIIGlueBaseIoLibIntrinsic_LIB) \ + $(EdkIIGluePeiDebugLibReportStatusCode_LIB) \ + $(EdkIIGluePeiReportStatusCodeLib_LIB) \ + $(EdkIIGluePeiServicesLib_LIB) \ + $(EdkIIGluePeiMemoryAllocationLib_LIB) \ + $(EdkIIGlueBasePciLibCf8_LIB) \ + $(PchUsbCommonPeiLib_LIB)\ + $(EdkIIGlueBasePciLibPciExpress_LIB)\ + $(PEILIB) + +PchInitPeimBin: $(PchInitPeim_LIB_LINKS) + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ + /f $(BUILD_DIR)\PchInitPeim.mak all \ + "MY_INCLUDES=$(PchInitPeim_INCLUDES)"\ + "MY_DEFINES=$(PchInitPeim_DEFINES)"\ + NAME=PchInitPeim\ + MAKEFILE=$(BUILD_DIR)\PchInitPeim.mak \ + GUID=FD236AE7-0791-48c4-B29E-29BDEEE1A838\ + ENTRY_POINT=_ModuleEntryPoint \ + TYPE=PEIM \ + EDKIIModule=PEIM\ + DEPEX1=$(PchInitPeim_DIR)\PchInitPeim.dxs\ + DEPEX1_TYPE=EFI_SECTION_PEI_DEPEX\ + COMPRESS=0 +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.sdl b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.sdl new file mode 100644 index 0000000..cfde1c7 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.sdl @@ -0,0 +1,67 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchInitPeim/PchInitPeim.sdl 1 2/08/12 8:53a Yurenlai $ +# +# $Revision: 1 $ +# +# $Date: 2/08/12 8:53a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchInitPeim/PchInitPeim.sdl $ +# +# 1 2/08/12 8:53a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* +TOKEN + Name = "PchInitPeim_SUPPORT" + Value = "1" + Help = "Main switch to enable PchInitPeim support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "PchInitPeim_DIR" +End + +MODULE + File = "PchInitPeim.mak" + Help = "Includes PchInitPeim.mak to Project" +End + +ELINK + Name = "$(BUILD_DIR)\PchInitPeim.ffs" + Parent = "FV_BB" + InvokeOrder = AfterParent +End + +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchUsbInit.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchUsbInit.c new file mode 100644 index 0000000..44381fc --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchUsbInit.c @@ -0,0 +1,198 @@ +/** @file + Initializes PCH USB Controllers. + +@copyright + Copyright (c) 2009 - 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#include "PchInitPeim.h" + +/** + The function performing USB init in PEI phase. This could be used by USB recovery + or debug features that need USB initialization during PEI phase. + Note: Before executing this function, please be sure that PCH_INIT_PPI.Initialize + has been done and PchUsbPolicyPpi has been installed. + + @param[in] PeiServices General purpose services available to every PEIM + + @retval EFI_SUCCESS The function completed successfully + @retval Others All other error conditions encountered result in an ASSERT. +**/ +EFI_STATUS +EFIAPI +PchUsbInit ( + IN EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + PCH_USB_POLICY_PPI *PchUsbPolicyPpi; + + DEBUG ((EFI_D_INFO, "PchUsbInit() - Start\n")); + + /// + /// Get PchUsbPolicy PPI for PCH_USB_CONFIG + /// + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gPchUsbPolicyPpiGuid, + 0, + NULL, + (VOID **)&PchUsbPolicyPpi + ); + + if (Status == EFI_SUCCESS) { +#ifdef EFI_DEBUG + DEBUG ((EFI_D_INFO, "\n------------------------ PchUsbPolicyPpi Dump Begin -----------------\n")); + DEBUG ((EFI_D_INFO, "Revision : 0x%x\n", PchUsbPolicyPpi->Revision)); + DEBUG ((EFI_D_INFO, "Mode : 0x%x\n", PchUsbPolicyPpi->Mode)); + DEBUG ((EFI_D_INFO, "EhciMemBaseAddr : 0x%x\n", PchUsbPolicyPpi->EhciMemBaseAddr)); + DEBUG ((EFI_D_INFO, "EhciMemLength : 0x%x\n", PchUsbPolicyPpi->EhciMemLength)); + DEBUG ((EFI_D_INFO, "XhciMemBaseAddr : 0x%x\n", PchUsbPolicyPpi->XhciMemBaseAddr)); +#endif + Status = PchStartUsbInit ( + PchUsbPolicyPpi->UsbConfig, + (UINT32) PchUsbPolicyPpi->EhciMemBaseAddr, + (UINT32) PchUsbPolicyPpi->XhciMemBaseAddr, + PchUsbPolicyPpi->Revision + ); +#ifdef EFI_DEBUG + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "\n------------------------ PchUsbPolicyPpi Dump End -----------------\n")); +#endif + } + DEBUG ((EFI_D_INFO, "PchUsbInit() - End\n")); + return Status; +} + +/** + The function performing USB init in PEI phase. This could be + used by USB recovery ,debug features or usb precondition + enabled case that need USB initialization during PEI phase. + Please be sure the function should not be executed in if the + boot mode is S3 resume. + + @param[in] UsbConfig Pointer to a PCH_USB_CONFIG that provides the platform setting + @param[in] EhciMemBaseAddr Predefined Ehci memory base address for Ehci hc configuration + @param[in] XhciMemBaseAddr Predefined Xhci memory base address for Xhci hc configuration + @param[in] Revision Revision of PCH_USB_CONFIG + + @retval EFI_SUCCESS The function completed successfully + @retval Others All other error conditions encountered result in an ASSERT +**/ +EFI_STATUS +PchStartUsbInit ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINT32 EhciMemBaseAddr, + IN UINT32 XhciMemBaseAddr, + IN UINT8 Revision + ) +{ + EFI_STATUS Status; + UINT32 RootComplexBar; + UINT32 FuncDisableReg; +#ifdef EFI_DEBUG + UINT8 i; +#endif + + DEBUG ((EFI_D_INFO, "PchStartUsbInit() - Start\n")); + Status = EFI_INVALID_PARAMETER; + if (UsbConfig != NULL) { +#ifdef EFI_DEBUG + DEBUG ((EFI_D_INFO, "Revision : 0x%x\n", Revision)); + DEBUG ((EFI_D_INFO, "EhciMemBaseAddr : 0x%x\n", EhciMemBaseAddr)); + DEBUG ((EFI_D_INFO, "XhciMemBaseAddr : 0x%x\n", XhciMemBaseAddr)); + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "------------------------ PCH_USB_CONFIG Dump Start -----------------\n")); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG UsbPerPortCtl= %x\n", UsbConfig->UsbPerPortCtl)); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Ehci1Usbr= %x\n", UsbConfig->Ehci1Usbr)); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Ehci2Usbr= %x\n", UsbConfig->Ehci2Usbr)); + for (i = 0; i < GetPchUsbMaxPhysicalPortNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG PortSettings[%d] Enabled= %x\n", i, UsbConfig->PortSettings[i].Enable)); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG PortSettings[%d] Location = %x\n", i, UsbConfig->PortSettings[i].Location)); + } + + for (i = 0; i < GetPchXhciMaxUsb3PortNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Port30Settings[%d] Enabled= %x\n", i, UsbConfig->Port30Settings[i].Enable)); + } + + for (i = 0; i < GetPchEhciMaxControllerNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb20Settings[%d] Enabled= %x\n", i, UsbConfig->Usb20Settings[i].Enable)); + } + + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30Settings.Mode= %x\n", UsbConfig->Usb30Settings.Mode)); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30Settings.PreBootSupport= %x\n", UsbConfig->Usb30Settings.PreBootSupport)); + DEBUG ((EFI_D_INFO, " XhciStreams is obsoleted, it doesn't effect any setting change since Revision 2.\n")); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30Settings.ManualMode= %x\n", UsbConfig->Usb30Settings.ManualMode)); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30Settings.XhciIdleL1= %x\n", UsbConfig->Usb30Settings.XhciIdleL1)); + + for (i = 0; i < GetPchUsbMaxPhysicalPortNum (); i++) { + if (UsbConfig->Usb30Settings.ManualModeUsb20PerPinRoute[i] == 0) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30Settings.ManualModeUsb20PerPinRoute[%d]= EHCI\n", i)); + } else { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30Settings.ManualModeUsb20PerPinRoute[%d]= XHCI\n", i)); + } + } + + for (i = 0; i < GetPchXhciMaxUsb3PortNum (); i++) { + DEBUG ((EFI_D_INFO, + "PCH_USB_CONFIG Usb30Settings.ManualModeUsb30PerPinEnable[%d]= %x\n", + i, + UsbConfig->Usb30Settings.ManualModeUsb30PerPinEnable[i])); + } + + for (i = 0; i < GetPchUsbMaxPhysicalPortNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb20OverCurrentPins[%d]= OC%x\n", i, UsbConfig->Usb20OverCurrentPins[i])); + } + + for (i = 0; i < GetPchXhciMaxUsb3PortNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30OverCurrentPins[%d]= OC%x\n", i, UsbConfig->Usb30OverCurrentPins[i])); + } + + for (i = 0; i < GetPchEhciMaxUsbPortNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb20PortLength[%d]= %x.%0x\n", i, UsbConfig->PortSettings[i].Usb20PortLength >> 4, UsbConfig->PortSettings[i].Usb20PortLength & 0xF)); + } + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "\n------------------------ PCH_USB_CONFIG Dump End -----------------\n")); +#endif + RootComplexBar = PCH_RCRB_BASE; + FuncDisableReg = MmioRead32 (RootComplexBar + R_PCH_RCRB_FUNC_DIS); + + Status = CommonUsbInit ( + UsbConfig, + (UINT32) EhciMemBaseAddr, + (UINT32) XhciMemBaseAddr, + 0, + RootComplexBar, + &FuncDisableReg, + Revision + ); + + ASSERT_EFI_ERROR (Status); + + MmioWrite32 ((UINTN) (RootComplexBar + R_PCH_RCRB_FUNC_DIS), (UINT32) (FuncDisableReg)); + // + // Reads back for posted write to take effect + // + MmioRead32 ((UINTN) (RootComplexBar + R_PCH_RCRB_FUNC_DIS)); + } + + DEBUG ((EFI_D_INFO, "PchStartUsbInit() - End\n")); + + return Status; + +} diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchUsbPreconditionPeim.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchUsbPreconditionPeim.c new file mode 100644 index 0000000..0735fd6 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchUsbPreconditionPeim.c @@ -0,0 +1,105 @@ +/** @file + + PCH USB precondition feature support in PEI phase + +@copyright + Copyright (c) 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ +#include "PchInitPeim.h" + +#ifdef USB_PRECONDITION_ENABLE_FLAG + +extern USB_CONTROLLER EhciControllersMap[]; + +/** + Perform USB precondition on EHCI, it is the HC on USB HC in PEI phase + + @param[in] Device The device number of the EHCI + @param[in] EhciMmioBase Memory base address of EHCI Controller + + @retval None +**/ +VOID +EhciPrecondition ( + IN UINT8 Device, + IN UINT32 EhciMmioBase + ) +{ + UINTN HcResetTimeout; + + HcResetTimeout = 0; + while ((HcResetTimeout < 200) && + (MmioRead32 (EhciMmioBase + R_PCH_EHCI_USB2CMD) & B_PCH_EHCI_USB2CMD_HCRESET)) { + PchPmTimerStall (100); + HcResetTimeout++; + } + + if ((MmioRead32 (EhciMmioBase + R_PCH_EHCI_USB2CMD) & B_PCH_EHCI_USB2CMD_HCRESET) == 0) { + // + // Route all ports to this EHCI + // + MmioWrite32 ((EhciMmioBase + R_PCH_EHCI_CONFIGFLAG), BIT0); + } +} + +/** + Perform USB precondition on XHCI, it is the HC on USB HC in PEI phase + + @param[in] BusNumber The Bus number of the XHCI + @param[in] Device The device number of the XHCI + @param[in] Function The function number of the XHCI + @param[in] XhciMmioBase Memory base address of XHCI Controller + @param[in] XhciUSB2Ptr Pointer to USB2 protocol port register + @param[in] HsPortCount The number of USB2 protocol port supported by this XHCI + + @retval None +**/ +VOID +XhciPrecondition ( + IN UINT8 BusNumber, + IN UINT8 Device, + IN UINT8 Function, + IN UINT32 XhciMmioBase, + IN UINTN *XhciUSB2Ptr, + IN UINTN HsPortCount, + IN UINTN *XhciUSB3Ptr, + IN UINTN SsPortCount + ) +{ + UINT32 Data32; + UINTN HcHaltTimeout; + + // + // Set the XHC to halt state before reset + // + HcHaltTimeout = 0; + if (!(MmioRead32 (XhciMmioBase + R_PCH_XHCI_USBSTS) & BIT0)) { + Data32 = MmioRead32 (XhciMmioBase + R_PCH_XHCI_USBCMD); + MmioWrite32 ((XhciMmioBase + R_PCH_XHCI_USBCMD), (Data32 &~B_PCH_XHCI_USBCMD_RS)); + while ((HcHaltTimeout < 200) && + (!(MmioRead32 (XhciMmioBase + R_PCH_XHCI_USBSTS) & BIT0))) { + PchPmTimerStall (100); + HcHaltTimeout++; + } + } + + if (MmioRead32 (XhciMmioBase + R_PCH_XHCI_USBSTS) & BIT0) { + MmioOr16 ((XhciMmioBase + R_PCH_XHCI_USBCMD), BIT1); + } +} + +#endif // USB_PRECONDITION_ENABLE_FLAG diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.c new file mode 100644 index 0000000..e29c5a1 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.c @@ -0,0 +1,753 @@ +/** @file + PCH S3 Save and Restore SMM Driver Entry + +@copyright + Copyright (c) 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ +#include "PchLateInitSmm.h" + +STATIC PCH_SAVE_RESTORE_REG PchSaveRestoreReg_Common[] = { + {Acpi, R_PCH_ACPI_PM1_EN, 0, BIT14, 2}, + {Rcrb, 0x3300, 0, 0xFFFFFFFF, 4}, + {Rcrb, 0x3304, 0, 0xFFFFFFFF, 4}, + {Rcrb, 0x3308, 0, 0xFFFFFFFF, 4}, + {Rcrb, 0x330C, 0, 0xFFFFFFFF, 4} +}; + +#ifdef TRAD_FLAG +STATIC PCH_SAVE_RESTORE_REG PchSaveRestoreReg_PchH[] = { + {Acpi, R_PCH_ACPI_GPE0a_EN, 0, 0xFFFF0246, 4}, + {Acpi, R_PCH_ACPI_GPE0b_EN, 0, 0xFF000040, 4}, + {Tco , R_PCH_TCO2_CNT , 0, BIT5 | BIT4, 1} +}; +#endif // TRAD_FLAG + +#ifdef ULT_FLAG +STATIC PCH_SAVE_RESTORE_REG PchSaveRestoreReg_PchLp[] = { + {Rcrb, 0x3320, 0, 0xFFFFFFFF, 4} +}; +#endif // ULT_FLAG + +STATIC PCH_SAVE_RESTORE_PCI PchSaveRestorePciReg_Common[] = { + {PciCfg, PCI_DEVICE_NUMBER_PCH_AZALIA, 0, 0, R_PCH_HDA_PCS + 1, 0, BIT0, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_AZALIA, 0, PCI_BASE_ADDRESSREG_OFFSET, R_HDA_WAKEEN, 0, BIT3 | BIT2 | BIT1 | BIT0, 1, NULL}, + {PciCfg, PCI_DEVICE_NUMBER_PCH_USB, 0, 0, R_PCH_EHCI_PWR_CNTL_STS + 1, 0, BIT0, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_CONFIGFLAG, 0, BIT0, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_PORTSC0 + 2, 0, BIT6 | BIT5 | BIT4, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_PORTSC0 + 6, 0, BIT6 | BIT5 | BIT4, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_PORTSC0 + 10, 0, BIT6 | BIT5 | BIT4, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_PORTSC0 + 14, 0, BIT6 | BIT5 | BIT4, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_PORTSC0 + 18, 0, BIT6 | BIT5 | BIT4, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_PORTSC0 + 22, 0, BIT6 | BIT5 | BIT4, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_PORTSC0 + 26, 0, BIT6 | BIT5 | BIT4, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_PORTSC0 + 30, 0, BIT6 | BIT5 | BIT4, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_PORTSC0 + 34, 0, BIT6 | BIT5 | BIT4, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_PORTSC0 + 38, 0, BIT6 | BIT5 | BIT4, 1, NULL}, + {PciCfg, PCI_DEVICE_NUMBER_PCH_XHCI, 0, 0, R_PCH_XHCI_PWR_CNTL_STS + 1, 0, BIT0 | BIT7, 1, NULL}, + {PciCfg, PCI_DEVICE_NUMBER_PCH_XHCI, 0, 0, R_PCH_XHCI_USB2PR, 0, 0x7FFF, 2, NULL}, + {PciCfg, PCI_DEVICE_NUMBER_PCH_XHCI, 0, 0, R_PCH_XHCI_USB3PR, 0, 0x3F, 1, NULL}, + {PciCfg, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, 0, 0, R_PCH_PCIE_PMCS + 1, 0, BIT0, 1, NULL}, + {PciCfg, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, 1, 0, R_PCH_PCIE_PMCS + 1, 0, BIT0, 1, NULL}, + {PciCfg, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, 2, 0, R_PCH_PCIE_PMCS + 1, 0, BIT0, 1, NULL}, + {PciCfg, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, 3, 0, R_PCH_PCIE_PMCS + 1, 0, BIT0, 1, NULL}, + {PciCfg, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, 4, 0, R_PCH_PCIE_PMCS + 1, 0, BIT0, 1, NULL}, + {PciCfg, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, 5, 0, R_PCH_PCIE_PMCS + 1, 0, BIT0, 1, NULL} +}; + +#ifdef TRAD_FLAG +STATIC PCH_SAVE_RESTORE_PCI PchSaveRestorePciReg_PchH[] = { + {PciCfg, PCI_DEVICE_NUMBER_PCH_USB_EXT, 0, 0, R_PCH_EHCI_PWR_CNTL_STS + 1, 0, BIT0, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB_EXT, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_CONFIGFLAG, 0, BIT0, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB_EXT, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_PORTSC0 + 2, 0, BIT6 | BIT5 | BIT4, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB_EXT, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_PORTSC0 + 6, 0, BIT6 | BIT5 | BIT4, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB_EXT, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_PORTSC0 + 10, 0, BIT6 | BIT5 | BIT4, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB_EXT, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_PORTSC0 + 14, 0, BIT6 | BIT5 | BIT4, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB_EXT, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_PORTSC0 + 18, 0, BIT6 | BIT5 | BIT4, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB_EXT, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_PORTSC0 + 22, 0, BIT6 | BIT5 | BIT4, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB_EXT, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_PORTSC0 + 26, 0, BIT6 | BIT5 | BIT4, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB_EXT, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_PORTSC0 + 30, 0, BIT6 | BIT5 | BIT4, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB_EXT, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_PORTSC0 + 34, 0, BIT6 | BIT5 | BIT4, 1, NULL}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_USB_EXT, 0, PCI_BASE_ADDRESSREG_OFFSET, R_PCH_EHCI_PORTSC0 + 38, 0, BIT6 | BIT5 | BIT4, 1, NULL}, + {PciCfg, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, 6, 0, R_PCH_PCIE_PMCS + 1, 0, BIT0, 1, NULL}, + {PciCfg, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, 7, 0, R_PCH_PCIE_PMCS + 1, 0, BIT0, 1, NULL} +}; +#endif // TRAD_FLAG + +#ifdef ULT_FLAG +STATIC PCH_SAVE_RESTORE_PCI PchSaveRestorePciReg_PchLp[] = { + {PciMmr, PCI_DEVICE_NUMBER_PCH_SATA, 2, R_PCH_SATA_AHCI_BAR, R_PCH_SATA_AHCI_P0DEVSLP, 0, 0x1FFFFFFF, 4, RestorePxDevSlp}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_SATA, 2, R_PCH_SATA_AHCI_BAR, R_PCH_SATA_AHCI_P1DEVSLP, 0, 0x1FFFFFFF, 4, RestorePxDevSlp}, + {PciMmr, PCI_DEVICE_NUMBER_PCH_SATA, 2, R_PCH_SATA_AHCI_BAR, R_PCH_SATA_AHCI_P3DEVSLP, 0, 0x1FFFFFFF, 4, RestorePxDevSlp} +}; +#endif // ULT_FLAG +DEVICE_POWER_STATE DevicePowerState[] = { + {PCI_DEVICE_NUMBER_PCH_AZALIA, 0, DeviceD0}, + {PCI_DEVICE_NUMBER_PCH_USB_EXT, 0, DeviceD0}, + {PCI_DEVICE_NUMBER_PCH_USB, 0, DeviceD0}, + {PCI_DEVICE_NUMBER_PCH_XHCI, 0, DeviceD0}, + {PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, 0, DeviceD0}, + {PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, 1, DeviceD0}, + {PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, 2, DeviceD0}, + {PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, 3, DeviceD0}, + {PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, 4, DeviceD0}, + {PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, 5, DeviceD0}, + {PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, 6, DeviceD0}, + {PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, 7, DeviceD0} +}; + +PCH_SAVE_RESTORE_PCI_WRAP PchSaveRestorePciRegWrap[] = { +#ifdef TRAD_FLAG + {PchSaveRestorePciReg_Common, ARRAY_SIZE(PchSaveRestorePciReg_Common), PchH}, + {PchSaveRestorePciReg_PchH, ARRAY_SIZE (PchSaveRestorePciReg_PchH), PchH} +#endif // TRAD_FLAG +#if (defined ULT_FLAG) && (defined TRAD_FLAG) + , +#endif // ULT_FLAG && TRAD_FLAG +#ifdef ULT_FLAG + {PchSaveRestorePciReg_Common, ARRAY_SIZE(PchSaveRestorePciReg_Common), PchLp}, + {PchSaveRestorePciReg_PchLp, ARRAY_SIZE(PchSaveRestorePciReg_PchLp), PchLp} +#endif // ULT_FLAG +}; + +PCH_SAVE_RESTORE_REG_WRAP PchSaveRestoreRegWrap[] = { +#ifdef TRAD_FLAG + {PchSaveRestoreReg_Common, ARRAY_SIZE(PchSaveRestoreReg_Common), PchH}, + {PchSaveRestoreReg_PchH, ARRAY_SIZE(PchSaveRestoreReg_PchH), PchH} +#endif // TRAD_FLAG +#if (defined ULT_FLAG) && (defined TRAD_FLAG) + , +#endif // ULT_FLAG && TRAD_FLAG +#ifdef ULT_FLAG + {PchSaveRestoreReg_Common, ARRAY_SIZE(PchSaveRestoreReg_Common), PchLp}, + {PchSaveRestoreReg_PchLp, ARRAY_SIZE(PchSaveRestoreReg_PchLp), PchLp} +#endif // ULT_FLAG +}; + +UINT32 PciMemBase = 0; + +/** + + Find the Offset to a given Capabilities ID + CAPID list: + 0x01 = PCI Power Management Interface + 0x04 = Slot Identification + 0x05 = MSI Capability + 0x10 = PCI Express Capability + + @param[in] Bus - Pci Bus Number + @param[in] Device - Pci Device Number + @param[in] Func - Pci Function Number + @param[in] CapId - CAPID to search for + + @retval 0 - CAPID not found + @retval Other - CAPID found, Offset of desired CAPID + +**/ +UINT8 +PcieFindCapId ( + IN UINT8 Bus, + IN UINT8 Device, + IN UINT8 Func, + IN UINT8 CapId + ) +{ + UINT8 CapHeader; + + /// + /// Always start at Offset 0x34 + /// + CapHeader = MmioRead8 (MmPciAddress (0, Bus, Device, Func, PCI_CAPBILITY_POINTER_OFFSET)); + if (CapHeader == 0xFF) { + return 0; + } + + while (CapHeader != 0) { + /// + /// Bottom 2 bits of the pointers are reserved per PCI Local Bus Spec 2.2 + /// + CapHeader &= ~(BIT1 | BIT0); + /// + /// Search for desired CapID + /// + if (MmioRead8 (MmPciAddress (0, Bus, Device, Func, CapHeader)) == CapId) { + return CapHeader; + } + + CapHeader = MmioRead8 (MmPciAddress (0, Bus, Device, Func, CapHeader + 1)); + } + + return 0; +} + +/** + + Save Device Power State and restore later + + @param[in] Device - Pci Device Number + @param[in] Function - Pci Function Number + + @retval None + +**/ +VOID +SaveDevPowState ( + IN UINT8 Device, + IN UINT8 Function + ) +{ + UINTN index; + + for (index = 0; index < ARRAY_SIZE(DevicePowerState); index++) { + if ((DevicePowerState[index].Device == Device) && (DevicePowerState[index].Function) == Function) { + DevicePowerState[index].PowerState = DeviceD3; + break; + } + } +} + +/** + + Restore Device Power State back to D3 + + @retval None + +**/ +VOID +RestoreDevPowState ( + VOID + ) +{ + UINTN index; + UINTN PciBaseAddress; + UINT8 CapOffset; + + for (index = 0; index < ARRAY_SIZE(DevicePowerState); index++) { + if (DevicePowerState[index].PowerState == DeviceD3) { + PciBaseAddress = MmPciAddress( + 0, + 0, + DevicePowerState[index].Device, + DevicePowerState[index].Function, + 0 + ); + CapOffset = PcieFindCapId ( + 0, + DevicePowerState[index].Device, + DevicePowerState[index].Function, + EFI_PCI_CAPABILITY_ID_PCIPM + ); + if (CapOffset != 0) { + MmioOr8 (PciBaseAddress + CapOffset + 0x4, DeviceD3); + } + } + } +} + +/** + Restore PxDevSlp + + @param[in] *PchSaveRestorePci - Pointer to Pch Save Restore Pci to be restored. + + @retval None +**/ +VOID +RestorePxDevSlp( + IN PCH_SAVE_RESTORE_PCI *PchSaveRestorePci + ) +{ + UINTN PciBaseAddress; + UINT32 PciBar; + UINTN Address; + UINT8 PciCmd; + UINT32 Data32; + UINT32 PortIndex; + + ASSERT ((PchSaveRestorePci->AccessType == PciMmr) && + (PchSaveRestorePci->Device == PCI_DEVICE_NUMBER_PCH_SATA) && + ((PchSaveRestorePci->Offset == R_PCH_SATA_AHCI_P0DEVSLP) || + (PchSaveRestorePci->Offset == R_PCH_SATA_AHCI_P1DEVSLP) || + (PchSaveRestorePci->Offset == R_PCH_SATA_AHCI_P3DEVSLP)) && + (PchSaveRestorePci->Width == 4)); + + PciBaseAddress = MmPciAddress ( + 0, + 0, + PchSaveRestorePci->Device, + PchSaveRestorePci->Function, + 0 + ); + PortIndex = (PchSaveRestorePci->Offset - R_PCH_SATA_AHCI_P0DEVSLP)/0x80; + PciCmd = MmioRead8 (PciBaseAddress + PCI_COMMAND_OFFSET); + MmioWrite8 (PciBaseAddress + PCI_COMMAND_OFFSET, BIT1); + PciBar = MmioRead32 (PciBaseAddress + PchSaveRestorePci->BarOffset); + MmioWrite32 (PciBaseAddress + PchSaveRestorePci->BarOffset, PciMemBase); + Address = PciMemBase + PchSaveRestorePci->Offset; + /// + /// Restore DM and DITO + /// + MmioAndThenOr32 (Address, (UINT32)~PchSaveRestorePci->Mask, (PchSaveRestorePci->Data & (B_PCH_SATA_AHCI_PxDEVSLP_DM_MASK | B_PCH_SATA_AHCI_PxDEVSLP_DITO_MASK))); + + /// + /// Makesure PxCMD.ST and PxDEVSLP.ADSE are cleared to '0' before updating PxDEVSLP.DETO and PxDEVSLP.MDAT value. + /// + Data32 = MmioRead32 (PciMemBase + (R_PCH_SATA_AHCI_P0CMD + (0x80 * PortIndex))); + MmioAnd32 (PciMemBase + (R_PCH_SATA_AHCI_P0CMD + (0x80 * PortIndex)), (UINT32)~B_PCH_SATA_AHCI_PxCMD_ST); + MmioAnd32 (Address, (UINT32)~B_PCH_SATA_AHCI_PxDEVSLP_ADSE); + MmioOr32 (Address, (PchSaveRestorePci->Data & (UINT32)~B_PCH_SATA_AHCI_PxDEVSLP_ADSE)); + MmioOr32 (PciMemBase + (R_PCH_SATA_AHCI_P0CMD + (0x80 * PortIndex)), (Data32 & B_PCH_SATA_AHCI_PxCMD_ST)); + MmioOr32 (Address, (PchSaveRestorePci->Data & B_PCH_SATA_AHCI_PxDEVSLP_ADSE)); + + /// + /// Restore original PCI command and bar + /// + MmioWrite8 (PciBaseAddress + PCI_COMMAND_OFFSET, PciCmd); + MmioWrite32 (PciBaseAddress + PchSaveRestorePci->BarOffset, PciBar); +} + +/** + A SMI callback to do PCH SMI register restoration + + @param[in] DispatchHandle - The handle of this callback, obtained when registering + @param[in] DispatchContext - Pointer to the EFI_SMM_IO_TRAP_DISPATCH_CALLBACK_CONTEXT + + @retval None +**/ +VOID +PchIoTrapSmiCallback ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_IO_TRAP_DISPATCH_CALLBACK_CONTEXT *CallbackContext + ) +{ + UINT16 AcpiBase; + UINT16 TcoBase; + UINTN index; + UINTN i; + UINTN PciBaseAddress; + UINTN Address; + UINT8 PowerState; + UINT8 PciCmd; + UINT32 PciBar; + UINT32 Mask; + PCH_SERIES PchSeries; + + AcpiBase = PchLpcPciCfg32(R_PCH_LPC_ACPI_BASE) & B_PCH_LPC_ACPI_BASE_BAR; + TcoBase = AcpiBase + PCH_TCO_BASE; + PowerState = 0x0; + PchSeries = GetPchSeries(); + + /// + /// Restoring IO and MMIO registers + /// + for (i = 0; i < ARRAY_SIZE (PchSaveRestoreRegWrap); i++) { + if (PchSeries != PchSaveRestoreRegWrap[i].PchSeries) { + continue; + } + for (index = 0; index < PchSaveRestoreRegWrap[i].size; index++) { + Mask = PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Mask; + switch (PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].AccessType) { + case Tco: + Address = TcoBase + PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Address; + switch (PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Width) { + case 4: + IoAndThenOr32 (Address, (UINT32) ~Mask, PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Data); + break; + case 2: + IoAndThenOr16 (Address, (UINT16) ~Mask, (UINT16) (PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Data)); + break; + case 1: + IoAndThenOr8 (Address, (UINT8) ~Mask, (UINT8) (PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Data)); + break; + } + break; + case Acpi: + Address = AcpiBase + PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Address; + switch (PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Width) { + case 4: + IoAndThenOr32 (Address, (UINT32) ~Mask, PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Data); + break; + case 2: + IoAndThenOr16 (Address, (UINT16) ~Mask, (UINT16) (PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Data)); + break; + case 1: + IoAndThenOr8 (Address, (UINT8) ~Mask, (UINT8) (PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Data)); + break; + } + break; + case Rcrb: + Address = PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Address; + switch (PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Width) { + case 4: + PchMmRcrb32AndThenOr (Address, (UINT32) ~Mask, PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Data); + break; + case 2: + PchMmRcrb16AndThenOr (Address, (UINT16) ~Mask, (UINT16) (PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Data)); + break; + case 1: + PchMmRcrb8AndThenOr (Address, (UINT8) ~Mask, (UINT8) (PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Data)); + break; + } + break; + } + } + } + + /// + /// Restoring PCI config space and PCI bar registers + /// + for (i = 0; i < ARRAY_SIZE (PchSaveRestorePciRegWrap); i++) { + if (PchSeries != PchSaveRestorePciRegWrap[i].PchSeries) { + continue; + } + for (index = 0; index < PchSaveRestorePciRegWrap[i].size; index++) { + PciBaseAddress = MmPciAddress( + 0, + 0, + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Device, + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Function, + 0 + ); + if (MmioRead32(PciBaseAddress) == 0xFFFFFFFF) { + continue; + } + if (PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].RestoreFunction == NULL) { + Mask = PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Mask; + switch (PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].AccessType) { + case PciCfg: + Address = PciBaseAddress + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Offset; + switch (PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Width) { + case 4: + MmioAndThenOr32 (Address, (UINT32) ~Mask, PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Data); + break; + case 2: + MmioAndThenOr16 (Address, (UINT16) ~Mask, (UINT16) (PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Data)); + break; + case 1: + MmioAndThenOr8 (Address, (UINT8) ~Mask, (UINT8) (PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Data)); + break; + } + break; + case PciMmr: + PciCmd = MmioRead8 (PciBaseAddress + PCI_COMMAND_OFFSET); + MmioWrite8 (PciBaseAddress + PCI_COMMAND_OFFSET, BIT1); + PciBar = MmioRead32 (PciBaseAddress + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].BarOffset); + MmioWrite32 (PciBaseAddress + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].BarOffset, PciMemBase); + Address = PciMemBase + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Offset; + switch (PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Width) { + case 4: + MmioAndThenOr32 (Address, (UINT32) ~Mask, PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Data); + break; + case 2: + MmioAndThenOr16 (Address, (UINT16) ~Mask, (UINT16) (PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Data)); + break; + case 1: + MmioAndThenOr8 (Address, (UINT8) ~Mask, (UINT8) (PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Data)); + break; + } + /// + /// Restore original PCI command and bar + /// + MmioWrite8 (PciBaseAddress + PCI_COMMAND_OFFSET, PciCmd); + MmioWrite32 (PciBaseAddress + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].BarOffset, PciBar); + break; + } + } else { + PchSaveRestorePciRegWrap[i].PchSaveRestorePci [index].RestoreFunction (&(PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index])); + } + } + } +} + +/** + This function save PCH register before enter S3 + + @param[in] Handle Handle of the callback + @param[in] Context The dispatch context + + @retval EFI_SUCCESS PCH register saved +**/ +EFI_STATUS +PchS3EntryCallBack ( + IN EFI_HANDLE Handle, + IN EFI_SMM_SX_DISPATCH_CONTEXT *Context + ) +{ + UINT32 AcpiBase; + UINT32 TcoBase; + UINTN PciBaseAddress; + UINTN index; + UINTN i; + UINT8 PowerState; + UINT8 CapOffset; + UINT32 PciBar; + UINT32 Mask; + UINT32 Address; + PCH_SERIES PchSeries; + + AcpiBase = PchLpcPciCfg32(R_PCH_LPC_ACPI_BASE) & B_PCH_LPC_ACPI_BASE_BAR; + TcoBase = AcpiBase + PCH_TCO_BASE; + PowerState = 0x0; + PchSeries = GetPchSeries(); + + /// + /// Saving IO and MMIO registers + /// + for (i = 0; i < ARRAY_SIZE (PchSaveRestoreRegWrap); i++) { + if (PchSeries != PchSaveRestoreRegWrap[i].PchSeries) { + continue; + } + for (index = 0; index < PchSaveRestoreRegWrap[i].size; index++) { + Mask = PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Mask; + switch (PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].AccessType) { + case Tco: + Address = TcoBase + PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Address; + switch (PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Width) { + case 4: + PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Data = (IoRead32 (Address)) & Mask; + break; + case 2: + PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Data = (IoRead16 (Address)) & Mask; + break; + case 1: + PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Data = (IoRead8 (Address)) & Mask; + break; + } + break; + case Acpi: + Address = AcpiBase + PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Address; + switch (PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Width) { + case 4: + PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Data = (IoRead32 (Address)) & Mask; + break; + case 2: + PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Data = (IoRead16 (Address)) & Mask; + break; + case 1: + PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Data = (IoRead8 (Address)) & Mask; + break; + } + break; + case Rcrb: + Address = PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Address; + switch (PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Width) { + case 4: + PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Data = (PchMmRcrb32 (Address)) & Mask; + break; + case 2: + PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Data = (PchMmRcrb16 (Address)) & Mask; + break; + case 1: + PchSaveRestoreRegWrap[i].PchSaveRestoreReg[index].Data = (PchMmRcrb8 (Address)) & Mask; + break; + } + break; + } + } + } + + /// + /// Saving PCI config space and PCI bar registers + /// + for (i = 0; i < ARRAY_SIZE (PchSaveRestorePciRegWrap); i++) { + if (PchSeries != PchSaveRestorePciRegWrap[i].PchSeries) { + continue; + } + for (index = 0; index < PchSaveRestorePciRegWrap[i].size; index++) { + PciBaseAddress = MmPciAddress( + 0, + 0, + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Device, + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Function, + 0 + ); + if (MmioRead32(PciBaseAddress) == 0xFFFFFFFF) { + continue; + } + Mask = PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Mask; + switch (PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].AccessType) { + case PciCfg: + Address = (UINT32) PciBaseAddress + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Offset; + switch (PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Width) { + case 4: + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Data = (MmioRead32 (Address)) & Mask; + break; + case 2: + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Data = (MmioRead16 (Address)) & Mask; + break; + case 1: + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Data = (MmioRead8 (Address)) & Mask; + break; + } + break; + case PciMmr: + PciBar = MmioRead32 (PciBaseAddress + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].BarOffset); + CapOffset = PcieFindCapId ( + 0, + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Device, + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Function, + EFI_PCI_CAPABILITY_ID_PCIPM + ); + if (CapOffset != 0) { + PowerState = MmioRead8(PciBaseAddress + CapOffset + 0x4) & (BIT1 | BIT0); + if (PowerState == DeviceD3) { + /// + /// Bring up device to D0 + /// + MmioAnd8 (PciBaseAddress + CapOffset + 0x4, (UINT8)~(BIT1 | BIT0)); + MmioWrite32 (PciBaseAddress + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].BarOffset, PciBar); + MmioWrite8 (PciBaseAddress + PCI_COMMAND_OFFSET, BIT1); + SaveDevPowState(PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Device, PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Function); + } + } + PciBar = PciBar & (UINT32)~(0xF); + if (PciBar == 0x0) { + continue; + } + Address = PciBar + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Offset; + switch (PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Width) { + case 4: + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Data = (MmioRead32 (Address)) & Mask; + break; + case 2: + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Data = (MmioRead16 (Address)) & Mask; + break; + case 1: + PchSaveRestorePciRegWrap[i].PchSaveRestorePci[index].Data = (MmioRead8 (Address)) & Mask; + break; + } + break; + } + } + } + + /// + /// Restore devices to D3 + /// + RestoreDevPowState(); + + return EFI_SUCCESS; +} + +/** + Initializes the PCH SMM handler for PCH save and restore + + @param[in] ImageHandle - Handle for the image of this driver + @param[in] SystemTable - Pointer to the EFI System Table + + @retval EFI_SUCCESS - PCH SMM handler was installed +**/ +EFI_STATUS +PchLateInitSmmEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS MemBase; + EFI_SMM_IO_TRAP_DISPATCH_PROTOCOL *PchIoTrap; + EFI_SMM_IO_TRAP_DISPATCH_REGISTER_CONTEXT PchIoTrapContext; + EFI_HANDLE PchIoTrapHandle; + EFI_SMM_SX_DISPATCH_CONTEXT SxDispatchContext; + EFI_SMM_SX_DISPATCH_PROTOCOL *SxDispatchProtocol; + EFI_HANDLE SxDispatchHandle; + PCH_LATE_INIT_SMM_VARIABLE SaveRestoreData; + + DEBUG ((EFI_D_INFO, "PchLateInitSmmEntryPoint()\n")); + + /// + /// Locate the PCH Trap dispatch protocol + /// + Status = gBS->LocateProtocol (&gEfiSmmIoTrapDispatchProtocolGuid, NULL, &PchIoTrap); + ASSERT_EFI_ERROR (Status); + + PchIoTrapContext.Type = ReadWriteTrap; + PchIoTrapContext.Length = 4; + PchIoTrapContext.Address = 0; + PchIoTrapContext.Context = NULL; + PchIoTrapContext.MergeDisable = FALSE; + Status = PchIoTrap->Register ( + PchIoTrap, + PchIoTrapSmiCallback, + &PchIoTrapContext, + &PchIoTrapHandle + ); + ASSERT_EFI_ERROR (Status); + + SaveRestoreData.IoTrapAddress = PchIoTrapContext.Address; + + DEBUG ((EFI_D_INFO, "PchIotrapSmiAddress = 0x%x\n", PchIoTrapContext.Address)); + + /// + /// Locate the Sx Dispatch Protocol + /// + Status = gBS->LocateProtocol ( + &gEfiSmmSxDispatchProtocolGuid, + NULL, + &SxDispatchProtocol + ); + ASSERT_EFI_ERROR (Status); + /// + /// Register the callback for S3 entry + /// + SxDispatchContext.Type = SxS3; + SxDispatchContext.Phase = SxEntry; + Status = SxDispatchProtocol->Register ( + SxDispatchProtocol, + PchS3EntryCallBack, + &SxDispatchContext, + &SxDispatchHandle + ); + ASSERT_EFI_ERROR (Status); + + MemBase = 0x0ffffffff; +#ifndef AMI_OVERRIDE_FOR_SMM + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateMaxAddressSearchTopDown, + EfiGcdMemoryTypeMemoryMappedIo, + 16, // 2^16: 64K Alignment + 0x10000, // 64K Length + &MemBase, + ImageHandle, + NULL + ); +#else + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateMaxAddressSearchBottomUp, + EfiGcdMemoryTypeMemoryMappedIo, + 16, // 2^16: 64K Alignment + 0x10000, // 64K Length + &MemBase, + ImageHandle, + NULL + ); +#endif // AMI_OVERRIDE_FOR_SMM + ASSERT_EFI_ERROR (Status); + + PciMemBase = (UINT32) MemBase; + + SaveRestoreData.PciMemBase = PciMemBase; + + Status = gRT->SetVariable ( + PCH_INIT_PEI_VARIABLE_NAME, + &gPchInitPeiVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof (PCH_LATE_INIT_SMM_VARIABLE), + &SaveRestoreData + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.cif b/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.cif new file mode 100644 index 0000000..260cf93 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.cif @@ -0,0 +1,13 @@ +<component> + name = "PchLateInitSmm" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\LynxPoint\PchInit\Smm" + RefName = "PchLateInitSmm" +[files] +"PchLateInitSmm.sdl" +"PchLateInitSmm.mak" +"PchLateInitSmm.c" +"PchLateInitSmm.h" +"PchLateInitSmm.dxs" +"PchLateInitSmm.inf" +<endComponent> diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.dxs b/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.dxs new file mode 100644 index 0000000..32f981f --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.dxs @@ -0,0 +1,46 @@ +/** @file + Dependency expression source file. + +@copyright + Copyright (c) 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains a 'Sample Driver' and is licensed as such + under the terms of your license agreement with Intel or your + vendor. This file may be modified by the user, subject to + the additional terms of the license agreement + +**/ + +// +// Common for R8 and R9 codebase +// +#include "AutoGen.h" +#include "DxeDepex.h" + +// +// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase; +// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version +// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase. +// +#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB) +#include "EfiDepex.h" + +#include EFI_PROTOCOL_DEPENDENCY (SmmBase) +#include EFI_PROTOCOL_DEPENDENCY (SmmIoTrapDispatch) +#include EFI_ARCH_PROTOCOL_DEFINITION (Variable) +#include EFI_ARCH_PROTOCOL_DEFINITION (VariableWrite) +#endif + +DEPENDENCY_START + EFI_SMM_BASE_PROTOCOL_GUID AND + EFI_SMM_IO_TRAP_DISPATCH_PROTOCOL_GUID AND + EFI_VARIABLE_ARCH_PROTOCOL_GUID AND + EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID +DEPENDENCY_END diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.h b/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.h new file mode 100644 index 0000000..0082af0 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.h @@ -0,0 +1,106 @@ +/** @file + Header file for PCH SMM Handler + +@copyright + Copyright (c) 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ + +#ifndef _PCHLATEINITSMM_H_ +#define _PCHLATEINITSMM_H_ + +/// +/// External include files do NOT need to be explicitly specified in real EDKII +/// environment +/// +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "EdkIIGlueDxe.h" +#include "PchAccess.h" +#include "PchPlatformLib.h" +#include "PchInitVar.h" +#include "pci22.h" +#endif +/// +/// Driver Consumed Protocol Prototypes +/// +#include EFI_PROTOCOL_DEPENDENCY (SmmBase) +#include EFI_PROTOCOL_DEPENDENCY (SmmIoTrapDispatch) +#include EFI_PROTOCOL_DEPENDENCY (SmmSxDispatch) + +#define EFI_PCI_CAPABILITY_ID_PCIPM 0x01 + +#define DeviceD0 0x00 +#define DeviceD3 0x03 + +#define ARRAY_SIZE(data) (sizeof (data) / sizeof (data[0])) + +typedef enum { + PciCfg, + PciMmr +} PCH_PCI_ACCESS_TYPE; + +typedef enum { + Acpi, + Rcrb, + Tco +} PCH_ACCESS_TYPE; + +typedef struct { + PCH_ACCESS_TYPE AccessType; + UINT32 Address; + UINT32 Data; + UINT32 Mask; + UINT8 Width; +} PCH_SAVE_RESTORE_REG; + +typedef struct { + PCH_SAVE_RESTORE_REG* PchSaveRestoreReg; + UINT8 size; + PCH_SERIES PchSeries; +} PCH_SAVE_RESTORE_REG_WRAP; + +struct _PCH_SAVE_RESTORE_PCI; + +typedef struct _PCH_SAVE_RESTORE_PCI{ + PCH_PCI_ACCESS_TYPE AccessType; + UINT8 Device; + UINT8 Function; + UINT8 BarOffset; + UINT16 Offset; + UINT32 Data; + UINT32 Mask; + UINT8 Width; + VOID (*RestoreFunction)(struct _PCH_SAVE_RESTORE_PCI *PchSaveRestorePci); +} PCH_SAVE_RESTORE_PCI; + +typedef struct { + PCH_SAVE_RESTORE_PCI* PchSaveRestorePci; + UINT8 size; + PCH_SERIES PchSeries; +} PCH_SAVE_RESTORE_PCI_WRAP; + +typedef struct { + UINT8 Device; + UINT8 Function; + UINT8 PowerState; +} DEVICE_POWER_STATE; + +VOID +RestorePxDevSlp( + IN PCH_SAVE_RESTORE_PCI *PchSaveRestorePci + ); + +#endif diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.inf b/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.inf new file mode 100644 index 0000000..9f04d49 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.inf @@ -0,0 +1,88 @@ +## @file +# Component description file for the PCH late initialization SMM module. +# +#@copyright +# Copyright (c) 2012 Intel Corporation. All rights reserved +# This software and associated documentation (if any) is furnished +# under a license and may only be used or copied in accordance +# with the terms of the license. Except as permitted by such +# license, no part of this software or documentation may be +# reproduced, stored in a retrieval system, or transmitted in any +# form or by any means without the express written consent of +# Intel Corporation. +# +# This file contains a 'Sample Driver' and is licensed as such +# under the terms of your license agreement with Intel or your +# vendor. This file may be modified by the user, subject to +# the additional terms of the license agreement +# + +[defines] +BASE_NAME = PchLateInitSmm +FILE_GUID = D7B10D4E-67E6-4C74-83E9-F9AF0ACC33CC +COMPONENT_TYPE = BS_DRIVER + +[sources.common] + PchLateInitSmm.c + PchLateInitSmm.h + ../Common/PchInitVar.c + +# +# Edk II Glue Driver Entry Point +# + EdkIIGlueSmmDriverEntryPoint.c +[includes.common] + $(EDK_SOURCE)/Foundation/Efi + . + ../Common + $(EDK_SOURCE)/Foundation/Include + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT) + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/SampleCode/Include +# +# EDK II Glue Library utilizes some standard headers from EDK +# + $(EFI_SOURCE) + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Include/Pei + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include +# +# Typically the sample code referenced will be available in the code base already +# So keep this include at the end to defer to the source base definition +# and only use the sample code definition if source base does not include these files. +# + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/SampleCode + +[libraries.common] + EdkFrameworkProtocolLib + $(PROJECT_PCH_FAMILY)ProtocolLib + PchPlatformLib + EdkIIGlueDxeDebugLibReportStatusCode + EdkIIGlueSmmRuntimeDxeReportStatusCodeLib + EdkIIGlueUefiBootServicesTableLib + EdkIIGlueUefiRuntimeServicesTableLib + EdkIIGlueDxeServicesTableLib + EdkIIGlueDxeMemoryAllocationLib + EdkProtocolLib + EfiScriptLib + +[nmake.common] + IMAGE_ENTRY_POINT=_ModuleEntryPoint + DPX_SOURCE=PchLateInitSmm.dxs +# +# Module Entry Point +# + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=PchLateInitSmmEntryPoint + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \ + -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \ + -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \ + -D __EDKII_GLUE_SMM_RUNTIME_DXE_REPORT_STATUS_CODE_LIB__ \ + -D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \ + -D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \ diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.mak b/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.mak new file mode 100644 index 0000000..d9cf9b7 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.mak @@ -0,0 +1,97 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLateInitSmm.mak 1 12/18/12 4:55a Scottyang $ +# +# $Revision: 1 $ +# +# $Date: 12/18/12 4:55a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLateInitSmm.mak $ +# +# 1 12/18/12 4:55a Scottyang +# [TAG] EIP109697 +# [Category] Improvement +# [Description] Update PCH RC 0.8.1 +# [Files] ReferenceCode\Chipset\LynxPoint\*.*, SBDxe.c, SBPEI.c, SB.sd, +# SbSetupData.c, GetSetupDate.c +# +#************************************************************************* +#--------------------------------------------------------------------------- +# Create PchLateInitSmm Driver +#--------------------------------------------------------------------------- +EDK : PchLateInitSmm +PchLateInitSmm : $(BUILD_DIR)\PchLateInitSmm.mak PchLateInitSmmBin + +$(BUILD_DIR)\PchLateInitSmm.mak : $(PchLateInitSmm_DIR)\$(@B).cif $(PchLateInitSmm_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(PchLateInitSmm_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +PchLateInitSmm_INCLUDES=\ + /I$(INTEL_PCH_DIR)\PchInit\Common\ + $(INTEL_PCH_INCLUDES)\ + $(EdkIIGlueLib_INCLUDES)\ + /I$(EDK_SOURCE)\Foundation\Efi\Include\ + +PchLateInitSmm_DEFINES = $(MY_DEFINES)\ + /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=PchLateInitSmmEntryPoint"\ + /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \ + /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \ + /D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \ + /D __EDKII_GLUE_SMM_RUNTIME_DXE_REPORT_STATUS_CODE_LIB__ \ + /D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \ + /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \ + +PchLateInitSmm_LIB_LINKS =\ + $(EDKFRAMEWORKPROTOCOLLIB)\ + $(INTEL_PCH_PROTOCOL_LIB)\ + $(PchPlatformDxeLib_LIB)\ + $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\ + $(EdkIIGlueSmmRuntimeDxeReportStatusCodeLib_LIB)\ + $(EdkIIGlueUefiBootServicesTableLib_LIB)\ + $(EdkIIGlueUefiRuntimeServicesTableLib_LIB)\ + $(EdkIIGlueDxeServicesTableLib_LIB)\ + $(EdkIIGlueDxeMemoryAllocationLib_LIB)\ + $(EDKPROTOCOLLIB)\ + $(EFISCRIPTLIB)\ + $(PchUsbCommonDxeLib_LIB)\ + $(EdkIIGlueBasePciLibPciExpress_LIB)\ + +PchLateInitSmmBin: $(PchLateInitSmm_LIB_LINKS) + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ + /f $(BUILD_DIR)\PchLateInitSmm.mak all \ + "MY_INCLUDES=$(PchLateInitSmm_INCLUDES)" \ + "MY_DEFINES=$(PchLateInitSmm_DEFINES)" \ + GUID=D7B10D4E-67E6-4C74-83E9-F9AF0ACC33CC\ + ENTRY_POINT=_ModuleEntryPoint \ + TYPE=BS_DRIVER\ + EDKIIModule=SMMDRIVER\ + DEPEX1=$(PchLateInitSmm_DIR)\PchLateInitSmm.dxs\ + DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX \ + COMPRESS=1 +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.sdl b/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.sdl new file mode 100644 index 0000000..efb0a48 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Smm/PchLateInitSmm.sdl @@ -0,0 +1,71 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLateInitSmm.sdl 1 12/18/12 4:55a Scottyang $ +# +# $Revision: 1 $ +# +# $Date: 12/18/12 4:55a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchLateInitSmm.sdl $ +# +# 1 12/18/12 4:55a Scottyang +# [TAG] EIP109697 +# [Category] Improvement +# [Description] Update PCH RC 0.8.1 +# [Files] ReferenceCode\Chipset\LynxPoint\*.*, SBDxe.c, SBPEI.c, SB.sd, +# SbSetupData.c, GetSetupDate.c +# +#************************************************************************* +TOKEN + Name = "PchLateInitSmm_SUPPORT" + Value = "1" + Help = "Main switch to enable PchLateInitSmm support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + TargetH = Yes + Master = Yes +End + +PATH + Name = "PchLateInitSmm_DIR" +End + +MODULE + File = "PchLateInitSmm.mak" + Help = "Includes PchLateInitSmm to Project" +End + +ELINK + Name = "$(BUILD_DIR)\PchLateInitSmm.ffs" + Parent = "FV_MAIN" + InvokeOrder = AfterParent +End +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* |