/** @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.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
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);
}