audk/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/UartInit.c

193 lines
5.9 KiB
C

/** @file
This PEIM will parse the hoblist from fsp and report them into pei core.
This file contains the main entrypoint of the PEIM.
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <PiPei.h>
#include <Library/IoLib.h>
#include <Library/SerialPortLib.h>
#define PCI_IDX 0xCF8
#define PCI_DAT 0xCFC
#define PCI_LPC_BASE (0x8000F800)
#define PCI_LPC_REG(x) (PCI_LPC_BASE + (x))
#define PMC_BASE_ADDRESS 0xFED03000 // PMC Memory Base Address
#define R_PCH_LPC_PMC_BASE 0x44 // PBASE, 32bit, 512 Bytes
#define B_PCH_LPC_PMC_BASE_EN BIT1 // Enable Bit
#define R_PCH_PMC_GEN_PMCON_1 0x20 // General PM Configuration 1
#define B_PCH_PMC_GEN_PMCON_SUS_PWR_FLR BIT14 // SUS Well Power Failure
#define B_PCH_PMC_GEN_PMCON_PWROK_FLR BIT16 // PWROK Failure
#define R_PCH_LPC_UART_CTRL 0x80 // UART Control
#define B_PCH_LPC_UART_CTRL_COM1_EN BIT0 // COM1 Enable
#define ILB_BASE_ADDRESS 0xFED08000 // ILB Memory Base Address
#define R_PCH_ILB_IRQE 0x88 // IRQ Enable Control
#define IO_BASE_ADDRESS 0xFED0C000 // IO Memory Base Address
#define V_PCH_ILB_IRQE_UARTIRQEN_IRQ3 BIT3 // UART IRQ3 Enable
#define V_PCH_ILB_IRQE_UARTIRQEN_IRQ4 BIT4 // UART IRQ4 Enable
#define PCIEX_BASE_ADDRESS 0xE0000000
#define PCI_EXPRESS_BASE_ADDRESS PCIEX_BASE_ADDRESS
#define PciD31F0RegBase PCIEX_BASE_ADDRESS + (UINT32) (31 << 15)
#define SB_RCBA 0xfed1c000
typedef enum {
PchA0 = 0,
PchA1 = 1,
PchB0 = 2,
PchB1 = 3,
PchB2 = 4,
PchB3 = 5,
PchC0 = 6,
PchSteppingMax
} PCH_STEPPING;
#define MmPciAddress( Segment, Bus, Device, Function, Register ) \
( (UINTN)PCI_EXPRESS_BASE_ADDRESS + \
(UINTN)(Bus << 20) + \
(UINTN)(Device << 15) + \
(UINTN)(Function << 12) + \
(UINTN)(Register) \
)
#define DEFAULT_PCI_BUS_NUMBER_PCH 0
#define PCI_DEVICE_NUMBER_PCH_LPC 31
#define PCI_FUNCTION_NUMBER_PCH_LPC 0
#define R_PCH_LPC_RID_CC 0x08 // Revision ID & Class Code
#define V_PCH_LPC_RID_0 0x01 // A0 Stepping (17 x 17)
#define V_PCH_LPC_RID_1 0x02 // A0 Stepping (25 x 27)
#define V_PCH_LPC_RID_2 0x03 // A1 Stepping (17 x 17)
#define V_PCH_LPC_RID_3 0x04 // A1 Stepping (25 x 27)
#define V_PCH_LPC_RID_4 0x05 // B0 Stepping (17 x 17)
#define V_PCH_LPC_RID_5 0x06 // B0 Stepping (25 x 27)
#define V_PCH_LPC_RID_6 0x07 // B1 Stepping (17 x 17)
#define V_PCH_LPC_RID_7 0x08 // B1 Stepping (25 x 27)
#define V_PCH_LPC_RID_8 0x09 // B2 Stepping (17 x 17)
#define V_PCH_LPC_RID_9 0x0A // B2 Stepping (25 x 27)
#define V_PCH_LPC_RID_A 0x0B // B3 Stepping (17 x 17)
#define V_PCH_LPC_RID_B 0x0C // B3 Stepping (25 x 27)
#define V_PCH_LPC_RID_C 0x0D // C0 Stepping (17 x 17)
#define V_PCH_LPC_RID_D 0x0E // C0 Stepping (25 x 27)
/**
Return Pch stepping type
@param[in] None
@retval PCH_STEPPING Pch stepping type
**/
PCH_STEPPING
EFIAPI
PchStepping (
VOID
)
{
UINT8 RevId;
RevId = MmioRead8 (
MmPciAddress (0,
DEFAULT_PCI_BUS_NUMBER_PCH,
PCI_DEVICE_NUMBER_PCH_LPC,
PCI_FUNCTION_NUMBER_PCH_LPC,
R_PCH_LPC_RID_CC)
);
switch (RevId) {
case V_PCH_LPC_RID_0:
case V_PCH_LPC_RID_1:
return PchA0;
break;
case V_PCH_LPC_RID_2:
case V_PCH_LPC_RID_3:
return PchA1;
break;
case V_PCH_LPC_RID_4:
case V_PCH_LPC_RID_5:
return PchB0;
break;
case V_PCH_LPC_RID_6:
case V_PCH_LPC_RID_7:
return PchB1;
break;
case V_PCH_LPC_RID_8:
case V_PCH_LPC_RID_9:
return PchB2;
break;
case V_PCH_LPC_RID_A:
case V_PCH_LPC_RID_B:
return PchB3;
break;
case V_PCH_LPC_RID_C:
case V_PCH_LPC_RID_D:
return PchC0;
break;
default:
return PchSteppingMax;
break;
}
}
/**
Enable legacy decoding on ICH6
@param[in] none
@retval EFI_SUCCESS Always returns success.
**/
VOID
EnableInternalUart(
VOID
)
{
//
// Program and enable PMC Base.
//
IoWrite32 (PCI_IDX, PCI_LPC_REG(R_PCH_LPC_PMC_BASE));
IoWrite32 (PCI_DAT, (PMC_BASE_ADDRESS | B_PCH_LPC_PMC_BASE_EN));
//
// Enable COM1 for debug message output.
//
MmioAndThenOr32 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1, (UINT32) (~(B_PCH_PMC_GEN_PMCON_SUS_PWR_FLR + B_PCH_PMC_GEN_PMCON_PWROK_FLR)), BIT24);
//
// Silicon Steppings
//
if (PchStepping()>= PchB0)
MmioOr8 (ILB_BASE_ADDRESS + R_PCH_ILB_IRQE, (UINT8) V_PCH_ILB_IRQE_UARTIRQEN_IRQ4);
else
MmioOr8 (ILB_BASE_ADDRESS + R_PCH_ILB_IRQE, (UINT8) V_PCH_ILB_IRQE_UARTIRQEN_IRQ3);
MmioAnd32(IO_BASE_ADDRESS + 0x0520, (UINT32)~(0x00000187));
MmioOr32 (IO_BASE_ADDRESS + 0x0520, (UINT32)0x81); // UART3_RXD-L
MmioAnd32(IO_BASE_ADDRESS + 0x0530, (UINT32)~(0x00000007));
MmioOr32 (IO_BASE_ADDRESS + 0x0530, (UINT32)0x1); // UART3_RXD-L
MmioOr8 (PciD31F0RegBase + R_PCH_LPC_UART_CTRL, (UINT8) B_PCH_LPC_UART_CTRL_COM1_EN);
SerialPortInitialize ();
SerialPortWrite ((UINT8 *)"EnableInternalUart!\r\n", sizeof("EnableInternalUart!\r\n") - 1);
return ;
}