summaryrefslogtreecommitdiff
path: root/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.c
diff options
context:
space:
mode:
Diffstat (limited to 'Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.c')
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.c527
1 files changed, 527 insertions, 0 deletions
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.c
new file mode 100644
index 0000000000..7d24ed1269
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.c
@@ -0,0 +1,527 @@
+/** @file
+ PCH Serial IO Lib implementation.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <PchAccess.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/PchSerialIoLib.h>
+#include <Library/PchPsfLib.h>
+#include <Include/PcieRegs.h>
+
+typedef struct {
+ UINT32 Bar0;
+ UINT32 Bar1;
+} SERIAL_IO_CONTROLLER_DESCRIPTOR;
+
+typedef struct {
+ UINT8 DevNum;
+ UINT8 FuncNum;
+} SERIAL_IO_BDF_NUMBERS;
+
+typedef struct {
+ UINT16 PciDevIdPchLp;
+ UINT16 PciDevIdSklPchH;
+ UINT16 PciDevIdKblPchH;
+ CHAR8 AcpiHid[SERIALIO_HID_LENGTH];
+} SERIAL_IO_ID;
+
+GLOBAL_REMOVE_IF_UNREFERENCED SERIAL_IO_ID mSerialIoId [PCH_SERIALIO_MAX_CONTROLLERS] =
+{
+ {V_PCH_LP_SERIAL_IO_I2C0_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_I2C0_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_I2C0_DEVICE_ID, "INT3442"},
+ {V_PCH_LP_SERIAL_IO_I2C1_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_I2C1_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_I2C1_DEVICE_ID, "INT3443"},
+ {V_PCH_LP_SERIAL_IO_I2C2_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_I2C2_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_I2C2_DEVICE_ID, "INT3444"},
+ {V_PCH_LP_SERIAL_IO_I2C3_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_I2C3_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_I2C3_DEVICE_ID, "INT3445"},
+ {V_PCH_LP_SERIAL_IO_I2C4_DEVICE_ID, 0 , 0 , "INT3446"},
+ {V_PCH_LP_SERIAL_IO_I2C5_DEVICE_ID, 0 , 0 , "INT3447"},
+ {V_PCH_LP_SERIAL_IO_SPI0_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_SPI0_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_SPI0_DEVICE_ID, "INT3440"},
+ {V_PCH_LP_SERIAL_IO_SPI1_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_SPI1_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_SPI1_DEVICE_ID, "INT3441"},
+ {V_PCH_LP_SERIAL_IO_UART0_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_UART0_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_UART0_DEVICE_ID, "INT3448"},
+ {V_PCH_LP_SERIAL_IO_UART1_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_UART1_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_UART1_DEVICE_ID, "INT3449"},
+ {V_PCH_LP_SERIAL_IO_UART2_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_UART2_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_UART2_DEVICE_ID, "INT344A"}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED SERIAL_IO_BDF_NUMBERS mSerialIoBdf [PCH_SERIALIO_MAX_CONTROLLERS] =
+{
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C0, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C0},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C1, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C1},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C2, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C2},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C3, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C3},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C4, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C4},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C5, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C5},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI0, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI0},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI1, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI1},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART0, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART0},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART1, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART1},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART2, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART2}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED SERIAL_IO_CONTROLLER_DESCRIPTOR mSerialIoAcpiAddress [PCH_SERIALIO_MAX_CONTROLLERS] =
+{
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x0000, PCH_SERIAL_IO_BASE_ADDRESS + 0x1000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x2000, PCH_SERIAL_IO_BASE_ADDRESS + 0x3000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x4000, PCH_SERIAL_IO_BASE_ADDRESS + 0x5000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x6000, PCH_SERIAL_IO_BASE_ADDRESS + 0x7000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x8000, PCH_SERIAL_IO_BASE_ADDRESS + 0x9000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0xA000, PCH_SERIAL_IO_BASE_ADDRESS + 0xB000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0xC000, PCH_SERIAL_IO_BASE_ADDRESS + 0xD000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0xE000, PCH_SERIAL_IO_BASE_ADDRESS + 0xF000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x10000, PCH_SERIAL_IO_BASE_ADDRESS + 0x11000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x12000, PCH_SERIAL_IO_BASE_ADDRESS + 0x13000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x14000, PCH_SERIAL_IO_BASE_ADDRESS + 0x15000}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchLpSerialIoPciCfgCtrAddr [PCH_SERIALIO_MAX_CONTROLLERS] =
+{
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL1,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL2,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL3,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL4,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL5,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL6,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL13,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL14,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL9,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL10,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL11
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchHSerialIoPciCfgCtrAddr[PCH_SERIALIO_MAX_CONTROLLERS] =
+{
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL1,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL2,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL3,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL4,
+ 0,
+ 0,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL13,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL14,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL9,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL10,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL11
+};
+
+
+/**
+ Returns index of the last i2c controller
+
+ @param[in] Number Number of SerialIo controller
+
+ @retval Index of I2C controller
+**/
+PCH_SERIAL_IO_CONTROLLER
+GetMaxI2cNumber (
+ VOID
+ )
+{
+ if (GetPchSeries () == PchH) {
+ return PchSerialIoIndexI2C3;
+ } else {
+ return PchSerialIoIndexI2C5;
+ }
+}
+
+/**
+ Returns string with AcpiHid assigned to selected SerialIo controller
+
+ @param[in] Number Number of SerialIo controller
+
+ @retval pointer to 8-byte string
+**/
+CHAR8*
+GetSerialIoAcpiHID (
+ IN PCH_SERIAL_IO_CONTROLLER Number
+ )
+{
+ return mSerialIoId[Number].AcpiHid;
+}
+
+/**
+ Checks if Device with given PciDeviceId is one of SerialIo controllers
+ If yes, its number is returned through Number parameter, otherwise Number is not updated
+
+ @param[in] PciDevId Device ID
+ @param[out] Number Number of SerialIo controller
+
+ @retval TRUE Yes it is a SerialIo controller
+ @retval FALSE No it isn't a SerialIo controller
+**/
+BOOLEAN
+IsSerialIoPciDevId (
+ IN UINT16 PciDevId,
+ OUT PCH_SERIAL_IO_CONTROLLER *Number
+ )
+{
+ PCH_SERIAL_IO_CONTROLLER Controller;
+ PCH_SERIES PchSeries;
+ PCH_GENERATION PchGen;
+
+ PchSeries = GetPchSeries ();
+ PchGen = GetPchGeneration ();
+ for (Controller = 0; Controller < PCH_SERIALIO_MAX_CONTROLLERS; Controller++) {
+ if (((PchSeries == PchLp) && (PciDevId == mSerialIoId[Controller].PciDevIdPchLp)) ||
+ ((PchSeries == PchH) && (PchGen == SklPch) && (PciDevId == mSerialIoId[Controller].PciDevIdSklPchH)) ||
+ ((PchSeries == PchH) && (PchGen == KblPch) && (PciDevId == mSerialIoId[Controller].PciDevIdKblPchH))) {
+ *Number = Controller;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ Checks if Device with given AcpiHid string is one of SerialIo controllers
+ If yes, its number is returned through Number parameter, otherwise Number is not updated
+
+ @param[in] AcpiHid String
+ @param[out] Number Number of SerialIo controller
+
+ @retval TRUE yes it is a SerialIo controller
+ @retval FALSE no it isn't a SerialIo controller
+**/
+BOOLEAN
+IsSerialIoAcpiHid (
+ IN CHAR8 *AcpiHid,
+ OUT PCH_SERIAL_IO_CONTROLLER *Number
+ )
+{
+ PCH_SERIAL_IO_CONTROLLER Controller;
+ for (Controller = 0; Controller < PCH_SERIALIO_MAX_CONTROLLERS; Controller++) {
+ if (!AsciiStrCmp ((const CHAR8 *) AcpiHid, mSerialIoId[Controller].AcpiHid)) {
+ *Number = Controller;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ Finds PCI Device Number of SerialIo devices.
+
+ @param[in] SerialIoNumber 0=I2C0, ..., 11=UART2
+
+ @retval SerialIo device number
+**/
+UINT8
+GetSerialIoDeviceNumber (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoNumber
+ )
+{
+ return mSerialIoBdf[SerialIoNumber].DevNum;
+}
+
+/**
+ Finds PCI Function Number of SerialIo devices.
+
+ @param[in] SerialIoNumber 0=I2C0, ..., 11=UART2
+
+ @retval SerialIo funciton number
+**/
+UINT8
+GetSerialIoFunctionNumber (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoNumber
+ )
+{
+ return mSerialIoBdf[SerialIoNumber].FuncNum;
+}
+
+/**
+ Finds BAR values of SerialIo devices.
+ SerialIo devices can be configured to not appear on PCI so traditional method of reading BAR might not work.
+ If the SerialIo device is in PCI mode, a request for BAR1 will return its PCI CFG space instead
+
+ @param[in] SerialIoDevice 0=I2C0, ..., 11=UART2
+ @param[in] BarNumber 0=BAR0, 1=BAR1
+
+ @retval SerialIo Bar value
+**/
+UINTN
+FindSerialIoBar (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice,
+ IN UINT8 BarNumber
+ )
+{
+ UINT64 Bar;
+ UINTN PcieBase;
+ UINT32 VenId;
+
+ PcieBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, GetSerialIoDeviceNumber (SerialIoDevice), GetSerialIoFunctionNumber (SerialIoDevice));
+ VenId = MmioRead32 (PcieBase + PCI_VENDOR_ID_OFFSET) & 0xFFFF;
+ if (VenId == V_PCH_INTEL_VENDOR_ID) {
+ if (BarNumber == 1) {
+ return PcieBase;
+ }
+ Bar = MmioRead32 (PcieBase + PCI_BASE_ADDRESSREG_OFFSET);
+ //
+ // For 64-Bit Memory Space BARs ((BAR[x] & 0xFFFFFFF0) + ((BAR[x+1] & 0xFFFFFFFF) << 32)
+ //
+ if ((Bar & B_PCI_BAR_MEMORY_TYPE_MASK) == B_PCI_BAR_MEMORY_TYPE_64) {
+ Bar = (Bar & 0xFFFFF000) + LShiftU64 (MmioRead32 (PcieBase + PCI_BASE_ADDRESSREG_OFFSET + 4) & 0xFFFFFFFF, 32);
+ return (UINTN) Bar;
+ }
+ return (UINTN) (Bar & 0xFFFFF000);
+ }
+ //
+ //PCI mode failed? Try hardcoded addresses from ACPI
+ //
+ if (BarNumber == 0) {
+ Bar = mSerialIoAcpiAddress[SerialIoDevice].Bar0;
+ } else {
+ Bar = mSerialIoAcpiAddress[SerialIoDevice].Bar1;
+ }
+ return (UINTN) Bar;
+}
+
+/**
+ Configures Serial IO Controller
+
+ @param[in] Controller Serial Io controller selector
+ @param[in] DeviceMode Device mode selector
+**/
+VOID
+ConfigureSerialIoController (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode
+ )
+{
+ UINTN PciCfgBase;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ UINT16 *SerialIoPciCfgCtrAddr;
+
+ if (Controller >= PchSerialIoIndexMax) {
+ return;
+ }
+
+ if (DeviceMode == PchSerialIoSkipInit) {
+ return;
+ }
+
+ PciCfgBase = MmPciBase (0, GetSerialIoDeviceNumber (Controller), GetSerialIoFunctionNumber (Controller));
+ //
+ // Do not modify a device that has already been disabled/hidden
+ //
+ if (MmioRead16 (PciCfgBase + PCI_VENDOR_ID_OFFSET) != V_PCH_INTEL_VENDOR_ID) {
+ return;
+ }
+
+ ///
+ /// Step 0. set Bit 16,17,18.
+ ///
+ MmioOr32 (PciCfgBase + R_PCH_SERIAL_IO_D0I3MAXDEVPG, BIT18 | BIT17 | BIT16);
+
+ //
+ // special case for I2C4 and I2C5 on SPT-H
+ //
+ if (GetPchSeries () == PchH && (Controller == PchSerialIoIndexI2C4 || Controller == PchSerialIoIndexI2C5)) {
+ return;
+ }
+
+ if (GetPchSeries () == PchLp) {
+ SerialIoPciCfgCtrAddr = mPchLpSerialIoPciCfgCtrAddr;
+ } else {
+ SerialIoPciCfgCtrAddr = mPchHSerialIoPciCfgCtrAddr;
+ }
+
+ switch (DeviceMode) {
+ case PchSerialIoDisabled:
+ ///
+ /// Step 1. Put device in D3
+ /// Step 2. Function Disable in PSF
+ ///
+ MmioOr32 (PciCfgBase + R_PCH_SERIAL_IO_PME_CTRL_STS, BIT1 | BIT0);
+ PsfDisableSerialIoDevice (Controller);
+ break;
+
+ case PchSerialIoAcpi:
+ case PchSerialIoAcpiHidden:
+ case PchSerialIoLegacyUart:
+ ///
+ /// reenable BAR1 in case it was disabled earlier
+ ///
+ PchPcrAndThenOr32 (PID_SERIALIO, SerialIoPciCfgCtrAddr[Controller],(UINT32) ~(B_PCH_PCR_SERIAL_IO_PCICFGCTRL_BAR1_DIS),0x0);
+ PsfEnableSerialIoDeviceBar1 (Controller);
+ ///
+ /// Step 1. Assign BAR0
+ /// Step 2. Assign BAR1
+ ///
+ MmioWrite32 (PciCfgBase + R_PCH_SERIAL_IO_BAR0_LOW, mSerialIoAcpiAddress[Controller].Bar0);
+ MmioWrite32 (PciCfgBase + R_PCH_SERIAL_IO_BAR0_HIGH, 0x0);
+ MmioWrite32 (PciCfgBase + R_PCH_SERIAL_IO_BAR1_LOW, mSerialIoAcpiAddress[Controller].Bar1);
+ MmioWrite32 (PciCfgBase + R_PCH_SERIAL_IO_BAR1_HIGH, 0x0);
+ ///
+ /// Step 3. Set Memory space Enable
+ ///
+ MmioOr32 (PciCfgBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER);
+ ///
+ /// Step 4. Disable device's PciCfg and enable ACPI interrupts
+ ///
+ PchPcrAndThenOr32 (PID_SERIALIO, SerialIoPciCfgCtrAddr[Controller], 0xFFFFFFFF, (B_PCH_PCR_SERIAL_IO_PCICFGCTRL_PCI_CFG_DIS | B_PCH_PCR_SERIAL_IO_PCICFGCTRL_ACPI_INTR_EN));
+ ///
+ /// Step 5. Disable device's PciCfg in PSF
+ ///
+ PsfHideSerialIoDevice (Controller);
+ ///
+ /// get controller out of reset
+ ///
+ MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_PPR_RESETS,
+ B_PCH_SERIAL_IO_PPR_RESETS_FUNC | B_PCH_SERIAL_IO_PPR_RESETS_APB | B_PCH_SERIAL_IO_PPR_RESETS_IDMA);
+ break;
+ case PchSerialIoPci:
+ ///
+ /// reenable PciCfg in case it was disabled earlier
+ ///
+ PchPcrAndThenOr32 (PID_SERIALIO, SerialIoPciCfgCtrAddr[Controller], (UINT32) ~(B_PCH_PCR_SERIAL_IO_PCICFGCTRL_PCI_CFG_DIS | B_PCH_PCR_SERIAL_IO_PCICFGCTRL_ACPI_INTR_EN),0x0);
+ PsfRevealSerialIoDevice (Controller);
+ ///
+ /// Disable Bar1
+ /// Disable Bar1 in PSF
+ ///
+ PchPcrAndThenOr32 (PID_SERIALIO, SerialIoPciCfgCtrAddr[Controller], 0xFFFFFFFF, B_PCH_PCR_SERIAL_IO_PCICFGCTRL_BAR1_DIS);
+ PsfDisableSerialIoDeviceBar1 (Controller);
+ //
+ // Assign BAR0 and Set Memory space Enable
+ //
+ MmioWrite32 (PciCfgBase + R_PCH_SERIAL_IO_BAR0_LOW, mSerialIoAcpiAddress[Controller].Bar0);
+ MmioWrite32 (PciCfgBase + R_PCH_SERIAL_IO_BAR0_HIGH, 0x0);
+ MmioOr32 (PciCfgBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER);
+ ///
+ /// get controller out of reset
+ ///
+ MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_PPR_RESETS,
+ B_PCH_SERIAL_IO_PPR_RESETS_FUNC | B_PCH_SERIAL_IO_PPR_RESETS_APB | B_PCH_SERIAL_IO_PPR_RESETS_IDMA);
+ break;
+ default:
+ return;
+ }
+
+ ///
+ /// Step X. Program clock dividers for UARTs
+ /// Step Y. Enable Byte addressing for UARTs in legacy mode
+ ///
+ if (Controller >= PchSerialIoIndexUart0 && Controller <= PchSerialIoIndexUart2) {
+ MmioWrite32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_PPR_CLK,
+ (B_PCH_SERIAL_IO_PPR_CLK_UPDATE | (V_PCH_SERIAL_IO_PPR_CLK_N_DIV << 16) |
+ (V_PCH_SERIAL_IO_PPR_CLK_M_DIV << 1) | B_PCH_SERIAL_IO_PPR_CLK_EN )
+ );
+
+ Data32And = (UINT32) (~(B_PCH_PCR_SERIAL_IO_GPPRVRW7_UART0_BYTE_ADDR_EN << (Controller - PchSerialIoIndexUart0)));
+ Data32Or = 0x0;
+ if (DeviceMode == PchSerialIoLegacyUart) {
+ Data32Or = (B_PCH_PCR_SERIAL_IO_GPPRVRW7_UART0_BYTE_ADDR_EN << (Controller - PchSerialIoIndexUart0));
+ }
+ PchPcrAndThenOr32 (PID_SERIALIO, R_PCH_PCR_SERIAL_IO_GPPRVRW7,Data32And,Data32Or);
+ //
+ // Dummy read after setting any of GPPRVRW7.
+ // Required for UART 16550 8-bit Legacy mode to become active
+ //
+ MmioRead32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_PPR_CLK);
+ }
+ ///
+ /// Step Z. Program I2C SDA hold registers
+ ///
+ if (Controller >= PchSerialIoIndexI2C0 && Controller <= GetMaxI2cNumber ()) {
+ if (DeviceMode != PchSerialIoDisabled) {
+ MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_I2C_SDA_HOLD, V_PCH_SERIAL_IO_I2C_SDA_HOLD_VALUE);
+ }
+ }
+
+}
+
+/**
+ Initializes GPIO pins used by SerialIo I2C devices
+
+ @param[in] Controller Serial Io controller selector
+ @param[in] DeviceMode Device mode selector
+ @param[in] I2cVoltage Voltage selector
+**/
+VOID
+SerialIoI2cGpioInit (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode,
+ IN UINT32 I2cVoltage
+ )
+{
+ if ((DeviceMode == PchSerialIoDisabled) || (DeviceMode == PchSerialIoSkipInit)) {
+ return;
+ }
+ GpioSetSerialIoI2cPinsIntoNativeMode (Controller);
+ if (I2cVoltage == PchSerialIoIs18V) {
+ GpioSetSerialIoI2CPinsTolerance (Controller, TRUE);
+ }
+}
+
+/**
+ Initializes GPIO pins used by SerialIo SPI devices
+
+ @param[in] Controller Serial Io controller selector
+ @param[in] DeviceMode Device mode selector
+ @param[in] SpiCsPolarity Polarity selector
+**/
+VOID
+SerialIoSpiGpioInit (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode,
+ IN UINT32 SpiCsPolarity
+ )
+{
+ if ((DeviceMode == PchSerialIoDisabled) || (DeviceMode == PchSerialIoSkipInit)) {
+ return;
+ }
+
+ //
+ // set Invert Frame Signal before enabling pins to ensure correct initial ChipSelect polarity
+ //
+ if (SpiCsPolarity == PchSerialIoCsActiveLow) {
+ MmioAnd32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_SSCR1, (UINT32) ~(B_PCH_SERIAL_IO_SSCR1_IFS));
+ MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_SPI_CS_CONTROL, B_PCH_SERIAL_IO_SPI_CS_CONTROL_STATE);
+ } else {
+ MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_SSCR1, B_PCH_SERIAL_IO_SSCR1_IFS);
+ MmioAnd32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_SPI_CS_CONTROL, (UINT32) ~B_PCH_SERIAL_IO_SPI_CS_CONTROL_STATE);
+ }
+
+ MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_SPI_CS_CONTROL, B_PCH_SERIAL_IO_SPI_CS_CONTROL_MODE);
+ GpioSetSerialIoSpiPinsIntoNativeMode (Controller-PchSerialIoIndexSpi0);
+}
+
+/**
+ Initializes GPIO pins used by SerialIo devices
+
+ @param[in] Controller Serial Io controller selector
+ @param[in] DeviceMode Device mode selector
+ @param[in] HardwareFlowControl Hardware flow control selector
+**/
+VOID
+SerialIoUartGpioInit (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode,
+ IN BOOLEAN HardwareFlowControl
+ )
+{
+
+ if ((DeviceMode == PchSerialIoDisabled) || (DeviceMode == PchSerialIoSkipInit)) {
+ return;
+ }
+ GpioSetSerialIoUartPinsIntoNativeMode (Controller-PchSerialIoIndexUart0, HardwareFlowControl);
+}
+
+