mirror of https://github.com/acidanthera/audk.git
1234 lines
39 KiB
C
1234 lines
39 KiB
C
/** @file
|
|
This PEIM initialize platform for MRC, following action is performed,
|
|
1. Initizluize GMCH
|
|
2. Detect boot mode
|
|
3. Detect video adapter to determine whether we need pre allocated memory
|
|
4. Calls MRC to initialize memory and install a PPI notify to do post memory initialization.
|
|
This file contains the main entrypoint of the PEIM.
|
|
|
|
Copyright (c) 2013 - 2016 Intel Corporation.
|
|
|
|
This program and the accompanying materials
|
|
are licensed and made available under the terms and conditions of the BSD License
|
|
which 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 "CommonHeader.h"
|
|
#include "PlatformEarlyInit.h"
|
|
#include "PeiFvSecurity.h"
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EndOfPeiSignalPpiNotifyCallback (
|
|
IN EFI_PEI_SERVICES **PeiServices,
|
|
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
|
|
IN VOID *Ppi
|
|
);
|
|
|
|
//
|
|
// Function prototypes to routines implemented in other source modules
|
|
// within this component.
|
|
//
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PlatformErratasPostMrc (
|
|
VOID
|
|
);
|
|
|
|
//
|
|
// The global indicator, the FvFileLoader callback will modify it to TRUE after loading PEIM into memory
|
|
//
|
|
BOOLEAN ImageInMemory = FALSE;
|
|
|
|
BOARD_LEGACY_GPIO_CONFIG mBoardLegacyGpioConfigTable[] = { PLATFORM_LEGACY_GPIO_TABLE_DEFINITION };
|
|
UINTN mBoardLegacyGpioConfigTableLen = (sizeof(mBoardLegacyGpioConfigTable) / sizeof(BOARD_LEGACY_GPIO_CONFIG));
|
|
BOARD_GPIO_CONTROLLER_CONFIG mBoardGpioControllerConfigTable[] = { PLATFORM_GPIO_CONTROLLER_CONFIG_DEFINITION };
|
|
UINTN mBoardGpioControllerConfigTableLen = (sizeof(mBoardGpioControllerConfigTable) / sizeof(BOARD_GPIO_CONTROLLER_CONFIG));
|
|
UINT8 ChipsetDefaultMac [6] = {0xff,0xff,0xff,0xff,0xff,0xff};
|
|
|
|
EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[1] = {
|
|
{
|
|
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
|
|
&gEfiPeiMasterBootModePpiGuid,
|
|
NULL
|
|
}
|
|
};
|
|
|
|
EFI_PEI_NOTIFY_DESCRIPTOR mMemoryDiscoveredNotifyList[1] = {
|
|
{
|
|
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
|
|
&gEfiPeiMemoryDiscoveredPpiGuid,
|
|
MemoryDiscoveredPpiNotifyCallback
|
|
}
|
|
};
|
|
|
|
EFI_PEI_NOTIFY_DESCRIPTOR mEndOfPeiSignalPpiNotifyList[1] = {
|
|
{
|
|
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
|
|
&gEfiEndOfPeiSignalPpiGuid,
|
|
EndOfPeiSignalPpiNotifyCallback
|
|
}
|
|
};
|
|
|
|
EFI_PEI_STALL_PPI mStallPpi = {
|
|
PEI_STALL_RESOLUTION,
|
|
Stall
|
|
};
|
|
|
|
EFI_PEI_PPI_DESCRIPTOR mPpiStall[1] = {
|
|
{
|
|
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
|
|
&gEfiPeiStallPpiGuid,
|
|
&mStallPpi
|
|
}
|
|
};
|
|
|
|
/**
|
|
Set Mac address on chipset ethernet device.
|
|
|
|
@param Bus PCI Bus number of chipset ethernet device.
|
|
@param Device Device number of chipset ethernet device.
|
|
@param Func PCI Function number of chipset ethernet device.
|
|
@param MacAddr MAC Address to set.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
SetLanControllerMacAddr (
|
|
IN CONST UINT8 Bus,
|
|
IN CONST UINT8 Device,
|
|
IN CONST UINT8 Func,
|
|
IN CONST UINT8 *MacAddr,
|
|
IN CONST UINT32 Bar0
|
|
)
|
|
{
|
|
UINT32 Data32;
|
|
UINT16 PciVid;
|
|
UINT16 PciDid;
|
|
UINT32 Addr;
|
|
UINT32 MacVer;
|
|
volatile UINT8 *Wrote;
|
|
UINT32 DevPcieAddr;
|
|
UINT16 SaveCmdReg;
|
|
UINT32 SaveBarReg;
|
|
|
|
DevPcieAddr = PCI_LIB_ADDRESS (
|
|
Bus,
|
|
Device,
|
|
Func,
|
|
0
|
|
);
|
|
|
|
//
|
|
// Do nothing if not a supported device.
|
|
//
|
|
PciVid = PciRead16 (DevPcieAddr + PCI_VENDOR_ID_OFFSET);
|
|
PciDid = PciRead16 (DevPcieAddr + PCI_DEVICE_ID_OFFSET);
|
|
if((PciVid != V_IOH_MAC_VENDOR_ID) || (PciDid != V_IOH_MAC_DEVICE_ID)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Save current settings for PCI CMD/BAR registers
|
|
//
|
|
SaveCmdReg = PciRead16 (DevPcieAddr + PCI_COMMAND_OFFSET);
|
|
SaveBarReg = PciRead32 (DevPcieAddr + R_IOH_MAC_MEMBAR);
|
|
|
|
//
|
|
// Use predefined temporary memory resource
|
|
//
|
|
PciWrite32 ( DevPcieAddr + R_IOH_MAC_MEMBAR, Bar0);
|
|
PciWrite8 ( DevPcieAddr + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
|
|
|
|
Addr = Bar0 + R_IOH_MAC_GMAC_REG_8;
|
|
MacVer = *((volatile UINT32 *) (UINTN)(Addr));
|
|
|
|
DEBUG ((EFI_D_INFO, "Ioh MAC [B:%d, D:%d, F:%d] VER:%04x ADDR:",
|
|
(UINTN) Bus,
|
|
(UINTN) Device,
|
|
(UINTN) Func,
|
|
(UINTN) MacVer
|
|
));
|
|
|
|
//
|
|
// Set MAC Address0 Low Register (GMAC_REG_17) ADDRLO bits.
|
|
//
|
|
Addr = Bar0 + R_IOH_MAC_GMAC_REG_17;
|
|
Data32 = *((UINT32 *) (UINTN)(&MacAddr[0]));
|
|
*((volatile UINT32 *) (UINTN)(Addr)) = Data32;
|
|
Wrote = (volatile UINT8 *) (UINTN)(Addr);
|
|
DEBUG ((EFI_D_INFO, "%02x-%02x-%02x-%02x-",
|
|
(UINTN) Wrote[0],
|
|
(UINTN) Wrote[1],
|
|
(UINTN) Wrote[2],
|
|
(UINTN) Wrote[3]
|
|
));
|
|
|
|
//
|
|
// Set MAC Address0 High Register (GMAC_REG_16) ADDRHI bits
|
|
// and Address Enable (AE) bit.
|
|
//
|
|
Addr = Bar0 + R_IOH_MAC_GMAC_REG_16;
|
|
Data32 =
|
|
((UINT32) MacAddr[4]) |
|
|
(((UINT32)MacAddr[5]) << 8) |
|
|
B_IOH_MAC_AE;
|
|
*((volatile UINT32 *) (UINTN)(Addr)) = Data32;
|
|
Wrote = (volatile UINT8 *) (UINTN)(Addr);
|
|
|
|
DEBUG ((EFI_D_INFO, "%02x-%02x\n", (UINTN) Wrote[0], (UINTN) Wrote[1]));
|
|
|
|
//
|
|
// Restore settings for PCI CMD/BAR registers
|
|
//
|
|
PciWrite32 ((DevPcieAddr + R_IOH_MAC_MEMBAR), SaveBarReg);
|
|
PciWrite16 (DevPcieAddr + PCI_COMMAND_OFFSET, SaveCmdReg);
|
|
}
|
|
|
|
/**
|
|
Initialize state of I2C GPIO expanders.
|
|
|
|
@param PlatformType Platform type for GPIO expander init.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EarlyPlatformConfigGpioExpanders (
|
|
IN CONST EFI_PLATFORM_TYPE PlatformType,
|
|
EFI_BOOT_MODE BootMode
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_I2C_DEVICE_ADDRESS I2CSlaveAddress;
|
|
UINTN Length;
|
|
UINTN ReadLength;
|
|
UINT8 Buffer[2];
|
|
|
|
//
|
|
// Configure GPIO expanders for Galileo Gen 2
|
|
// Route I2C pins to Arduino header
|
|
// Set all GPIO expander pins connected to the Reset Button as inputs
|
|
//
|
|
if (PlatformType == GalileoGen2) {
|
|
//
|
|
// Configure AMUX1_IN (EXP2.P1_4) as an output
|
|
//
|
|
PlatformPcal9555GpioSetDir (
|
|
GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR, // IO Expander 2.
|
|
12, // P1-4.
|
|
FALSE // Configure as output
|
|
);
|
|
|
|
//
|
|
// Set AMUX1_IN(EXP2.P1_4) low to route I2C to Arduino Shield connector
|
|
//
|
|
PlatformPcal9555GpioSetLevel (
|
|
GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR, // IO Expander 2.
|
|
12, // P1-4.
|
|
FALSE // Set pin low
|
|
);
|
|
|
|
//
|
|
// Configure Reset Button(EXP1.P1_7) as an input
|
|
//
|
|
PlatformPcal9555GpioSetDir (
|
|
GALILEO_GEN2_IOEXP1_7BIT_SLAVE_ADDR, // IO Expander 1.
|
|
15, // P1-7.
|
|
TRUE
|
|
);
|
|
|
|
//
|
|
// Disable pullup on Reset Button(EXP1.P1_7)
|
|
//
|
|
PlatformPcal9555GpioDisablePull (
|
|
GALILEO_GEN2_IOEXP1_7BIT_SLAVE_ADDR, // IO Expander 1.
|
|
15 // P1-7.
|
|
);
|
|
|
|
//
|
|
// Configure Reset Button(EXP2.P1_7) as an input
|
|
//
|
|
PlatformPcal9555GpioSetDir (
|
|
GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR, // IO Expander 2.
|
|
15, // P1-7.
|
|
TRUE
|
|
);
|
|
|
|
//
|
|
// Disable pullup on Reset Button(EXP2.P1_7)
|
|
//
|
|
PlatformPcal9555GpioDisablePull (
|
|
GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR, // IO Expander 2.
|
|
15 // P1-7.
|
|
);
|
|
|
|
if (BootMode != BOOT_IN_RECOVERY_MODE) {
|
|
//
|
|
// Read state of Reset Button - EXP2.P1_7
|
|
// This GPIO is pulled high when the button is not pressed
|
|
// This GPIO reads low when button is pressed
|
|
//
|
|
if (!PlatformPcal9555GpioGetState (
|
|
GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR, // IO Expander 2
|
|
15 // P1-7
|
|
)) {
|
|
DEBUG ((EFI_D_INFO, " Force Recovery mode and reset\n"));
|
|
|
|
//
|
|
// Set 'B_CFG_STICKY_RW_FORCE_RECOVERY' sticky bit so we know we need to do a recovery following warm reset
|
|
//
|
|
QNCAltPortWrite (
|
|
QUARK_SCSS_SOC_UNIT_SB_PORT_ID,
|
|
QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW,
|
|
QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW) | B_CFG_STICKY_RW_FORCE_RECOVERY
|
|
);
|
|
ResetWarm();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Configure GPIO expanders for Galileo Gen 2
|
|
// Set all GPIO expander pins connected to the Reset Button as inputs
|
|
// Route I2C pins to Arduino header
|
|
//
|
|
if (PlatformType == Galileo) {
|
|
//
|
|
// Detect the I2C Slave Address of the GPIO Expander
|
|
//
|
|
if (PlatformLegacyGpioGetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, GALILEO_DETERMINE_IOEXP_SLA_RESUMEWELL_GPIO)) {
|
|
I2CSlaveAddress.I2CDeviceAddress = GALILEO_IOEXP_J2HI_7BIT_SLAVE_ADDR;
|
|
} else {
|
|
I2CSlaveAddress.I2CDeviceAddress = GALILEO_IOEXP_J2LO_7BIT_SLAVE_ADDR;
|
|
}
|
|
DEBUG ((EFI_D_INFO, "Galileo GPIO Expender Slave Address = %02x\n", I2CSlaveAddress.I2CDeviceAddress));
|
|
|
|
//
|
|
// Set I2C_MUX (GPORT1_BIT5) low to route I2C to Arduino Shield connector
|
|
//
|
|
|
|
//
|
|
// Select GPIO Expander GPORT1
|
|
//
|
|
Length = 2;
|
|
Buffer[0] = 0x18; //sub-address
|
|
Buffer[1] = 0x01; //data
|
|
Status = I2cWriteMultipleByte (
|
|
I2CSlaveAddress,
|
|
EfiI2CSevenBitAddrMode,
|
|
&Length,
|
|
&Buffer
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// Read "Pin Direction" of GPIO Expander GPORT1
|
|
//
|
|
Length = 1;
|
|
ReadLength = 1;
|
|
Buffer[1] = 0x1C;
|
|
Status = I2cReadMultipleByte (
|
|
I2CSlaveAddress,
|
|
EfiI2CSevenBitAddrMode,
|
|
&Length,
|
|
&ReadLength,
|
|
&Buffer[1]
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// Configure GPIO Expander GPORT1_BIT5 as an output
|
|
//
|
|
Length = 2;
|
|
Buffer[0] = 0x1C; //sub-address
|
|
Buffer[1] = (UINT8)(Buffer[1] & (~BIT5)); //data
|
|
|
|
Status = I2cWriteMultipleByte (
|
|
I2CSlaveAddress,
|
|
EfiI2CSevenBitAddrMode,
|
|
&Length,
|
|
&Buffer
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// Set GPIO Expander GPORT1_BIT5 low
|
|
//
|
|
Length = 2;
|
|
Buffer[0] = 0x09; //sub-address
|
|
Buffer[1] = (UINT8)(~BIT5); //data
|
|
|
|
Status = I2cWriteMultipleByte (
|
|
I2CSlaveAddress,
|
|
EfiI2CSevenBitAddrMode,
|
|
&Length,
|
|
&Buffer
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// Configure RESET_N_SHLD (GPORT5_BIT0) and SW_RESET_N_SHLD (GPORT5_BIT1) as inputs
|
|
//
|
|
|
|
//
|
|
// Select GPIO Expander GPORT5
|
|
//
|
|
Length = 2;
|
|
Buffer[0] = 0x18;
|
|
Buffer[1] = 0x05;
|
|
Status = I2cWriteMultipleByte (
|
|
I2CSlaveAddress,
|
|
EfiI2CSevenBitAddrMode,
|
|
&Length,
|
|
&Buffer
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// Read "Pin Direction" of GPIO Expander GPORT5
|
|
//
|
|
Length = 1;
|
|
ReadLength = 1;
|
|
Buffer[1] = 0x1C;
|
|
Status = I2cReadMultipleByte (
|
|
I2CSlaveAddress,
|
|
EfiI2CSevenBitAddrMode,
|
|
&Length,
|
|
&ReadLength,
|
|
&Buffer[1]
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// Configure GPIO Expander GPORT5_BIT0 and GPORT5_BIT1 as inputs
|
|
//
|
|
Length = 2;
|
|
Buffer[0] = 0x1C;
|
|
Buffer[1] = Buffer[1] | BIT0 | BIT1;
|
|
Status = I2cWriteMultipleByte (
|
|
I2CSlaveAddress,
|
|
EfiI2CSevenBitAddrMode,
|
|
&Length,
|
|
&Buffer
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
if (BootMode != BOOT_IN_RECOVERY_MODE) {
|
|
//
|
|
// Read state of RESET_N_SHLD (GPORT5_BIT0)
|
|
//
|
|
Buffer[1] = 5;
|
|
Length = 1;
|
|
ReadLength = 1;
|
|
Status = I2cReadMultipleByte (
|
|
I2CSlaveAddress,
|
|
EfiI2CSevenBitAddrMode,
|
|
&Length,
|
|
&ReadLength,
|
|
&Buffer[1]
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// Return the state of GPORT5_BIT0
|
|
//
|
|
if ((Buffer[1] & BIT0) == 0) {
|
|
DEBUG ((EFI_D_INFO, " Force Recovery mode and reset\n"));
|
|
|
|
//
|
|
// Set 'B_CFG_STICKY_RW_FORCE_RECOVERY' sticky bit so we know we need to do a recovery following warm reset
|
|
//
|
|
QNCAltPortWrite (
|
|
QUARK_SCSS_SOC_UNIT_SB_PORT_ID,
|
|
QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW,
|
|
QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW) | B_CFG_STICKY_RW_FORCE_RECOVERY
|
|
);
|
|
ResetWarm();
|
|
}
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
This is the entrypoint of PEIM
|
|
|
|
@param FileHandle Handle of the file being invoked.
|
|
@param PeiServices Describes the list of possible PEI Services.
|
|
|
|
@retval EFI_SUCCESS if it completed successfully.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PeiInitPlatform (
|
|
IN EFI_PEI_FILE_HANDLE FileHandle,
|
|
IN CONST EFI_PEI_SERVICES **PeiServices
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_BOOT_MODE BootMode;
|
|
EFI_PEI_STALL_PPI *StallPpi;
|
|
EFI_PEI_PPI_DESCRIPTOR *StallPeiPpiDescriptor;
|
|
EFI_FV_FILE_INFO FileInfo;
|
|
EFI_PLATFORM_TYPE PlatformType;
|
|
|
|
PlatformType = (EFI_PLATFORM_TYPE)PcdGet16 (PcdPlatformType);
|
|
|
|
//
|
|
// Initialize Firmware Volume security.
|
|
// This must be done before any firmware volume accesses (excl. BFV)
|
|
//
|
|
Status = PeiInitializeFvSecurity();
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// Do any early platform specific initialization.
|
|
//
|
|
EarlyPlatformInit ();
|
|
|
|
//
|
|
// This is a second path on entry, in recovery boot path the Stall PPI need to be memory-based
|
|
// to improve recovery performance.
|
|
//
|
|
Status = PeiServicesFfsGetFileInfo (FileHandle, &FileInfo);
|
|
ASSERT_EFI_ERROR (Status);
|
|
//
|
|
// The follow conditional check only works for memory-mapped FFS,
|
|
// so we ASSERT that the file is really a MM FFS.
|
|
//
|
|
ASSERT (FileInfo.Buffer != NULL);
|
|
if (!(((UINTN) FileInfo.Buffer <= (UINTN) PeiInitPlatform) &&
|
|
((UINTN) PeiInitPlatform <= (UINTN) FileInfo.Buffer + FileInfo.BufferSize))) {
|
|
//
|
|
// Now that module in memory, update the
|
|
// PPI that describes the Stall to other modules
|
|
//
|
|
Status = PeiServicesLocatePpi (
|
|
&gEfiPeiStallPpiGuid,
|
|
0,
|
|
&StallPeiPpiDescriptor,
|
|
(VOID **) &StallPpi
|
|
);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
|
|
Status = PeiServicesReInstallPpi (
|
|
StallPeiPpiDescriptor,
|
|
&mPpiStall[0]
|
|
);
|
|
} else {
|
|
|
|
Status = PeiServicesInstallPpi (&mPpiStall[0]);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Initialize System Phys
|
|
//
|
|
|
|
// Program USB Phy
|
|
InitializeUSBPhy();
|
|
|
|
//
|
|
// Do platform specific logic to create a boot mode
|
|
//
|
|
Status = UpdateBootMode ((EFI_PEI_SERVICES**)PeiServices, &BootMode);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// Signal possible dependent modules that there has been a
|
|
// final boot mode determination
|
|
//
|
|
if (!EFI_ERROR(Status)) {
|
|
Status = PeiServicesInstallPpi (&mPpiBootMode[0]);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
if (BootMode != BOOT_ON_S3_RESUME) {
|
|
QNCClearSmiAndWake ();
|
|
}
|
|
|
|
DEBUG ((EFI_D_INFO, "MRC Entry\n"));
|
|
MemoryInit ((EFI_PEI_SERVICES**)PeiServices);
|
|
|
|
//
|
|
// Do Early PCIe init.
|
|
//
|
|
DEBUG ((EFI_D_INFO, "Early PCIe controller initialization\n"));
|
|
PlatformPciExpressEarlyInit (PlatformType);
|
|
|
|
|
|
DEBUG ((EFI_D_INFO, "Platform Erratas After MRC\n"));
|
|
PlatformErratasPostMrc ();
|
|
|
|
//
|
|
//
|
|
//
|
|
DEBUG ((EFI_D_INFO, "EarlyPlatformConfigGpioExpanders ()\n"));
|
|
EarlyPlatformConfigGpioExpanders (PlatformType, BootMode);
|
|
|
|
//
|
|
// Now that all of the pre-permanent memory activities have
|
|
// been taken care of, post a call-back for the permanent-memory
|
|
// resident services, such as HOB construction.
|
|
// PEI Core will switch stack after this PEIM exit. After that the MTRR
|
|
// can be set.
|
|
//
|
|
Status = PeiServicesNotifyPpi (&mMemoryDiscoveredNotifyList[0]);
|
|
ASSERT_EFI_ERROR (Status);
|
|
/*
|
|
|
|
if (BootMode != BOOT_ON_S3_RESUME) {
|
|
Status = PeiServicesNotifyPpi (mEndOfPeiSignalPpiNotifyList);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
*/
|
|
if (BootMode == BOOT_IN_RECOVERY_MODE) {
|
|
PeiServicesRegisterForShadow (FileHandle);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EndOfPeiSignalPpiNotifyCallback (
|
|
IN EFI_PEI_SERVICES **PeiServices,
|
|
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
|
|
IN VOID *Ppi
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
DEBUG ((EFI_D_INFO, "End of PEI Signal Callback\n"));
|
|
|
|
//
|
|
// Restore the flash region to be UC
|
|
// for both normal boot as we build a Resource Hob to
|
|
// describe this region as UC to DXE core.
|
|
//
|
|
WriteBackInvalidateDataCacheRange (
|
|
(VOID *) (UINTN) PcdGet32 (PcdFlashAreaBaseAddress),
|
|
PcdGet32 (PcdFlashAreaSize)
|
|
);
|
|
|
|
Status = MtrrSetMemoryAttribute (PcdGet32 (PcdFlashAreaBaseAddress), PcdGet32 (PcdFlashAreaSize), CacheUncacheable);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
This function will initialize USB Phy registers associated with QuarkSouthCluster.
|
|
|
|
@param VOID No Argument
|
|
|
|
@retval EFI_SUCCESS All registers have been initialized
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
InitializeUSBPhy (
|
|
VOID
|
|
)
|
|
{
|
|
UINT32 RegData32;
|
|
|
|
/** In order to configure the PHY to use clk120 (ickusbcoreclk) as PLL reference clock
|
|
* and Port2 as a USB device port, the following sequence must be followed
|
|
*
|
|
**/
|
|
|
|
// Sideband register write to USB AFE (Phy)
|
|
RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_GLOBAL_PORT);
|
|
RegData32 &= ~(BIT1);
|
|
//
|
|
// Sighting #4930631 PDNRESCFG [8:7] of USB2_GLOBAL_PORT = 11b.
|
|
// For port 0 & 1 as host and port 2 as device.
|
|
//
|
|
RegData32 |= (BIT8 | BIT7);
|
|
QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_GLOBAL_PORT, RegData32);
|
|
|
|
//
|
|
// Sighting #4930653 Required BIOS change on Disconnect vref to change to 600mV.
|
|
//
|
|
RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_COMPBG);
|
|
RegData32 &= ~(BIT10 | BIT9 | BIT8 | BIT7);
|
|
RegData32 |= (BIT10 | BIT7);
|
|
QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_COMPBG, RegData32);
|
|
|
|
// Sideband register write to USB AFE (Phy)
|
|
// (pllbypass) to bypass/Disable PLL before switch
|
|
RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2);
|
|
RegData32 |= BIT29;
|
|
QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2, RegData32);
|
|
|
|
// Sideband register write to USB AFE (Phy)
|
|
// (coreclksel) to select 120MHz (ickusbcoreclk) clk source.
|
|
// (Default 0 to select 96MHz (ickusbclk96_npad/ppad))
|
|
RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL1);
|
|
RegData32 |= BIT1;
|
|
QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL1, RegData32);
|
|
|
|
// Sideband register write to USB AFE (Phy)
|
|
// (divide by 8) to achieve internal 480MHz clock
|
|
// for 120MHz input refclk. (Default: 4'b1000 (divide by 10) for 96MHz)
|
|
RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL1);
|
|
RegData32 &= ~(BIT5 | BIT4 | BIT3);
|
|
RegData32 |= BIT6;
|
|
QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL1, RegData32);
|
|
|
|
// Sideband register write to USB AFE (Phy)
|
|
// Clear (pllbypass)
|
|
RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2);
|
|
RegData32 &= ~BIT29;
|
|
QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2, RegData32);
|
|
|
|
// Sideband register write to USB AFE (Phy)
|
|
// Set (startlock) to force the PLL FSM to restart the lock
|
|
// sequence due to input clock/freq switch.
|
|
RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2);
|
|
RegData32 |= BIT24;
|
|
QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2, RegData32);
|
|
|
|
// At this point the PLL FSM and COMP FSM will complete
|
|
|
|
}
|
|
|
|
/**
|
|
This function provides early platform Thermal sensor initialisation.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
EarlyPlatformThermalSensorInit (
|
|
VOID
|
|
)
|
|
{
|
|
DEBUG ((EFI_D_INFO, "Early Platform Thermal Sensor Init\n"));
|
|
|
|
//
|
|
// Set Thermal sensor mode.
|
|
//
|
|
QNCThermalSensorSetRatiometricMode ();
|
|
|
|
//
|
|
// Enable RMU Thermal sensor with a Catastrophic Trip point.
|
|
//
|
|
QNCThermalSensorEnableWithCatastrophicTrip (PLATFORM_CATASTROPHIC_TRIP_CELSIUS);
|
|
|
|
//
|
|
// Lock all RMU Thermal sensor control & trip point registers.
|
|
//
|
|
QNCThermalSensorLockAllRegisters ();
|
|
}
|
|
|
|
/**
|
|
Print early platform info messages includeing the Stage1 module that's
|
|
running, MFH item list and platform data item list.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
EarlyPlatformInfoMessages (
|
|
VOID
|
|
)
|
|
{
|
|
DEBUG_CODE_BEGIN ();
|
|
QUARK_EDKII_STAGE1_HEADER *Edk2ImageHeader;
|
|
|
|
//
|
|
// Find which 'Stage1' image we are running and print the details
|
|
//
|
|
Edk2ImageHeader = (QUARK_EDKII_STAGE1_HEADER *) PcdGet32 (PcdEsramStage1Base);
|
|
DEBUG ((EFI_D_INFO, "\n************************************************************\n"));
|
|
|
|
switch ((UINT8)Edk2ImageHeader->ImageIndex & QUARK_STAGE1_IMAGE_TYPE_MASK) {
|
|
case QUARK_STAGE1_BOOT_IMAGE_TYPE:
|
|
DEBUG ((EFI_D_INFO, "**** Quark EDKII Stage 1 Boot Image %d ****\n", ((UINT8)Edk2ImageHeader->ImageIndex & ~(QUARK_STAGE1_IMAGE_TYPE_MASK))));
|
|
break;
|
|
|
|
case QUARK_STAGE1_RECOVERY_IMAGE_TYPE:
|
|
DEBUG ((EFI_D_INFO, "**** Quark EDKII Stage 1 Recovery Image %d ****\n", ((UINT8)Edk2ImageHeader->ImageIndex & ~(QUARK_STAGE1_IMAGE_TYPE_MASK))));
|
|
break;
|
|
|
|
default:
|
|
DEBUG ((EFI_D_INFO, "**** Quark EDKII Unknown Stage 1 Image !!!! ****\n"));
|
|
break;
|
|
}
|
|
DEBUG (
|
|
(EFI_D_INFO,
|
|
"**** Quark EDKII Stage 2 Image 0x%08X:0x%08X ****\n" ,
|
|
(UINTN) PcdGet32 (PcdFlashFvMainBase),
|
|
(UINTN) PcdGet32 (PcdFlashFvMainSize)
|
|
));
|
|
|
|
DEBUG (
|
|
(EFI_D_INFO,
|
|
"**** Quark EDKII Payload Image 0x%08X:0x%08X ****\n" ,
|
|
(UINTN) PcdGet32 (PcdFlashFvPayloadBase),
|
|
(UINTN) PcdGet32 (PcdFlashFvPayloadSize)
|
|
));
|
|
|
|
DEBUG ((EFI_D_INFO, "************************************************************\n\n"));
|
|
|
|
DEBUG_CODE_END ();
|
|
}
|
|
|
|
/**
|
|
Check if system reset due to error condition.
|
|
|
|
@param ClearErrorBits If TRUE clear error flags and value bits.
|
|
|
|
@retval TRUE if system reset due to error condition.
|
|
@retval FALSE if NO reset error conditions.
|
|
**/
|
|
BOOLEAN
|
|
CheckForResetDueToErrors (
|
|
IN BOOLEAN ClearErrorBits
|
|
)
|
|
{
|
|
UINT32 RegValue;
|
|
BOOLEAN ResetDueToError;
|
|
|
|
ResetDueToError = FALSE;
|
|
|
|
//
|
|
// Check if RMU reset system due to access violations.
|
|
// RMU updates a SOC Unit register before resetting the system.
|
|
//
|
|
RegValue = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW);
|
|
if ((RegValue & B_CFG_STICKY_RW_VIOLATION) != 0) {
|
|
ResetDueToError = TRUE;
|
|
|
|
DEBUG (
|
|
(EFI_D_ERROR,
|
|
"\nReset due to access violation: %s %s %s %s\n",
|
|
((RegValue & B_CFG_STICKY_RW_IMR_VIOLATION) != 0) ? L"'IMR'" : L".",
|
|
((RegValue & B_CFG_STICKY_RW_DECC_VIOLATION) != 0) ? L"'DECC'" : L".",
|
|
((RegValue & B_CFG_STICKY_RW_SMM_VIOLATION) != 0) ? L"'SMM'" : L".",
|
|
((RegValue & B_CFG_STICKY_RW_HMB_VIOLATION) != 0) ? L"'HMB'" : L"."
|
|
));
|
|
|
|
//
|
|
// Clear error bits.
|
|
//
|
|
if (ClearErrorBits) {
|
|
RegValue &= ~(B_CFG_STICKY_RW_VIOLATION);
|
|
QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW, RegValue);
|
|
}
|
|
}
|
|
|
|
return ResetDueToError;
|
|
}
|
|
|
|
/**
|
|
This function provides early platform initialization.
|
|
|
|
@param PlatformInfo Pointer to platform Info structure.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
EarlyPlatformInit (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_PLATFORM_TYPE PlatformType;
|
|
|
|
PlatformType = (EFI_PLATFORM_TYPE) PcdGet16 (PcdPlatformType);
|
|
|
|
DEBUG ((EFI_D_INFO, "EarlyPlatformInit for PlatType=0x%02x\n", (UINTN) PlatformType));
|
|
|
|
//
|
|
// Check if system reset due to error condition.
|
|
//
|
|
if (CheckForResetDueToErrors (TRUE)) {
|
|
if(FeaturePcdGet (WaitIfResetDueToError)) {
|
|
DEBUG ((EFI_D_ERROR, "Wait 10 seconds.\n"));
|
|
MicroSecondDelay(10000000);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Display platform info messages.
|
|
//
|
|
EarlyPlatformInfoMessages ();
|
|
|
|
//
|
|
// Early Legacy Gpio Init.
|
|
//
|
|
EarlyPlatformLegacyGpioInit (PlatformType);
|
|
|
|
//
|
|
// Early platform Legacy GPIO manipulation depending on GPIOs
|
|
// setup by EarlyPlatformLegacyGpioInit.
|
|
//
|
|
EarlyPlatformLegacyGpioManipulation (PlatformType);
|
|
|
|
//
|
|
// Early platform specific GPIO Controller init & manipulation.
|
|
// Combined for sharing of temp. memory bar.
|
|
//
|
|
EarlyPlatformGpioCtrlerInitAndManipulation (PlatformType);
|
|
|
|
//
|
|
// Early Thermal Sensor Init.
|
|
//
|
|
EarlyPlatformThermalSensorInit ();
|
|
|
|
//
|
|
// Early Lan Ethernet Mac Init.
|
|
//
|
|
EarlyPlatformMacInit (
|
|
PcdGetPtr (PcdIohEthernetMac0),
|
|
PcdGetPtr (PcdIohEthernetMac1)
|
|
);
|
|
}
|
|
|
|
/**
|
|
This function provides early platform Legacy GPIO initialisation.
|
|
|
|
@param PlatformType Platform type for GPIO init.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
EarlyPlatformLegacyGpioInit (
|
|
IN CONST EFI_PLATFORM_TYPE PlatformType
|
|
)
|
|
{
|
|
BOARD_LEGACY_GPIO_CONFIG *LegacyGpioConfig;
|
|
UINT32 NewValue;
|
|
UINT32 GpioBaseAddress;
|
|
|
|
//
|
|
// Assert if platform type outside table range.
|
|
//
|
|
ASSERT ((UINTN) PlatformType < mBoardLegacyGpioConfigTableLen);
|
|
LegacyGpioConfig = &mBoardLegacyGpioConfigTable[(UINTN) PlatformType];
|
|
|
|
GpioBaseAddress = (UINT32)PcdGet16 (PcdGbaIoBaseAddress);
|
|
|
|
NewValue = 0x0;
|
|
//
|
|
// Program QNC GPIO Registers.
|
|
//
|
|
NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGEN_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellEnable;
|
|
IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGEN_CORE_WELL, NewValue );
|
|
NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGIO_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellIoSelect;
|
|
IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGIO_CORE_WELL, NewValue);
|
|
NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGLVL_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellLvlForInputOrOutput;
|
|
IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGLVL_CORE_WELL, NewValue);
|
|
NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGTPE_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellTriggerPositiveEdge;
|
|
IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGTPE_CORE_WELL, NewValue );
|
|
NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGTNE_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellTriggerNegativeEdge;
|
|
IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGTNE_CORE_WELL, NewValue);
|
|
NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGGPE_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellGPEEnable;
|
|
IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGGPE_CORE_WELL, NewValue);
|
|
NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGSMI_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellSMIEnable;
|
|
IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGSMI_CORE_WELL, NewValue );
|
|
NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGTS_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellTriggerStatus;
|
|
IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGTS_CORE_WELL, NewValue);
|
|
NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CNMIEN_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellNMIEnable;
|
|
IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CNMIEN_CORE_WELL, NewValue);
|
|
|
|
NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGEN_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellEnable;
|
|
IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGEN_RESUME_WELL, NewValue );
|
|
NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGIO_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellIoSelect;
|
|
IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGIO_RESUME_WELL, NewValue) ;
|
|
NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGLVL_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellLvlForInputOrOutput;
|
|
IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGLVL_RESUME_WELL, NewValue);
|
|
NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGTPE_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellTriggerPositiveEdge;
|
|
IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGTPE_RESUME_WELL, NewValue );
|
|
NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGTNE_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellTriggerNegativeEdge;
|
|
IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGTNE_RESUME_WELL, NewValue) ;
|
|
NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGGPE_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellGPEEnable;
|
|
IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGGPE_RESUME_WELL, NewValue);
|
|
NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGSMI_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellSMIEnable;
|
|
IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGSMI_RESUME_WELL, NewValue );
|
|
NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGTS_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellTriggerStatus;
|
|
IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGTS_RESUME_WELL, NewValue) ;
|
|
NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RNMIEN_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellNMIEnable;
|
|
IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RNMIEN_RESUME_WELL, NewValue);
|
|
}
|
|
|
|
/**
|
|
Performs any early platform specific Legacy GPIO manipulation.
|
|
|
|
@param PlatformType Platform type GPIO manipulation.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
EarlyPlatformLegacyGpioManipulation (
|
|
IN CONST EFI_PLATFORM_TYPE PlatformType
|
|
)
|
|
{
|
|
if (PlatformType == CrossHill) {
|
|
|
|
//
|
|
// Pull TPM reset low for 80us (equivalent to cold reset, Table 39
|
|
// Infineon SLB9645 Databook), then pull TPM reset high and wait for
|
|
// 150ms to give time for TPM to stabilise (Section 4.7.1 Infineon
|
|
// SLB9645 Databook states TPM is ready to receive command after 30ms
|
|
// but section 4.7 states some TPM commands may take longer to execute
|
|
// upto 150ms after test).
|
|
//
|
|
|
|
PlatformLegacyGpioSetLevel (
|
|
R_QNC_GPIO_RGLVL_RESUME_WELL,
|
|
PLATFORM_RESUMEWELL_TPM_RST_GPIO,
|
|
FALSE
|
|
);
|
|
MicroSecondDelay (80);
|
|
|
|
PlatformLegacyGpioSetLevel (
|
|
R_QNC_GPIO_RGLVL_RESUME_WELL,
|
|
PLATFORM_RESUMEWELL_TPM_RST_GPIO,
|
|
TRUE
|
|
);
|
|
MicroSecondDelay (150000);
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
Performs any early platform specific GPIO Controller init & manipulation.
|
|
|
|
@param PlatformType Platform type for GPIO init & manipulation.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
EarlyPlatformGpioCtrlerInitAndManipulation (
|
|
IN CONST EFI_PLATFORM_TYPE PlatformType
|
|
)
|
|
{
|
|
UINT32 IohGpioBase;
|
|
UINT32 Data32;
|
|
UINT32 Addr;
|
|
BOARD_GPIO_CONTROLLER_CONFIG *GpioConfig;
|
|
UINT32 DevPcieAddr;
|
|
UINT16 SaveCmdReg;
|
|
UINT32 SaveBarReg;
|
|
UINT16 PciVid;
|
|
UINT16 PciDid;
|
|
|
|
ASSERT ((UINTN) PlatformType < mBoardGpioControllerConfigTableLen);
|
|
GpioConfig = &mBoardGpioControllerConfigTable[(UINTN) PlatformType];
|
|
|
|
IohGpioBase = (UINT32) PcdGet64 (PcdIohGpioMmioBase);
|
|
|
|
DevPcieAddr = PCI_LIB_ADDRESS (
|
|
PcdGet8 (PcdIohGpioBusNumber),
|
|
PcdGet8 (PcdIohGpioDevNumber),
|
|
PcdGet8 (PcdIohGpioFunctionNumber),
|
|
0
|
|
);
|
|
|
|
//
|
|
// Do nothing if not a supported device.
|
|
//
|
|
PciVid = PciRead16 (DevPcieAddr + PCI_VENDOR_ID_OFFSET);
|
|
PciDid = PciRead16 (DevPcieAddr + PCI_DEVICE_ID_OFFSET);
|
|
if((PciVid != V_IOH_I2C_GPIO_VENDOR_ID) || (PciDid != V_IOH_I2C_GPIO_DEVICE_ID)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Save current settings for PCI CMD/BAR registers.
|
|
//
|
|
SaveCmdReg = PciRead16 (DevPcieAddr + PCI_COMMAND_OFFSET);
|
|
SaveBarReg = PciRead32 (DevPcieAddr + PcdGet8 (PcdIohGpioBarRegister));
|
|
|
|
//
|
|
// Use predefined temporary memory resource.
|
|
//
|
|
PciWrite32 ( DevPcieAddr + PcdGet8 (PcdIohGpioBarRegister), IohGpioBase);
|
|
PciWrite8 ( DevPcieAddr + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
|
|
|
|
//
|
|
// Gpio Controller Init Tasks.
|
|
//
|
|
|
|
//
|
|
// IEN- Interrupt Enable Register
|
|
//
|
|
Addr = IohGpioBase + GPIO_INTEN;
|
|
Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
|
|
Data32 |= (GpioConfig->IntEn & 0x000FFFFF);
|
|
*((volatile UINT32 *) (UINTN)(Addr)) = Data32;
|
|
|
|
//
|
|
// ISTATUS- Interrupt Status Register
|
|
//
|
|
Addr = IohGpioBase + GPIO_INTSTATUS;
|
|
Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
|
|
*((volatile UINT32 *) (UINTN)(Addr)) = Data32;
|
|
|
|
//
|
|
// GPIO SWPORTA Direction Register - GPIO_SWPORTA_DR
|
|
//
|
|
Addr = IohGpioBase + GPIO_SWPORTA_DR;
|
|
Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
|
|
Data32 |= (GpioConfig->PortADR & 0x000FFFFF);
|
|
*((volatile UINT32 *) (UINTN)(Addr)) = Data32;
|
|
|
|
//
|
|
// GPIO SWPORTA Data Direction Register - GPIO_SWPORTA_DDR - default input
|
|
//
|
|
Addr = IohGpioBase + GPIO_SWPORTA_DDR;
|
|
Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
|
|
Data32 |= (GpioConfig->PortADir & 0x000FFFFF);
|
|
*((volatile UINT32 *) (UINTN)(Addr)) = Data32;
|
|
|
|
//
|
|
// Interrupt Mask Register - GPIO_INTMASK - default interrupts unmasked
|
|
//
|
|
Addr = IohGpioBase + GPIO_INTMASK;
|
|
Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
|
|
Data32 |= (GpioConfig->IntMask & 0x000FFFFF);
|
|
*((volatile UINT32 *) (UINTN)(Addr)) = Data32;
|
|
|
|
//
|
|
// Interrupt Level Type Register - GPIO_INTTYPE_LEVEL - default is level sensitive
|
|
//
|
|
Addr = IohGpioBase + GPIO_INTTYPE_LEVEL;
|
|
Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
|
|
Data32 |= (GpioConfig->IntType & 0x000FFFFF);
|
|
*((volatile UINT32 *) (UINTN)(Addr)) = Data32;
|
|
|
|
//
|
|
// Interrupt Polarity Type Register - GPIO_INT_POLARITY - default is active low
|
|
//
|
|
Addr = IohGpioBase + GPIO_INT_POLARITY;
|
|
Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
|
|
Data32 |= (GpioConfig->IntPolarity & 0x000FFFFF);
|
|
*((volatile UINT32 *) (UINTN)(Addr)) = Data32;
|
|
|
|
//
|
|
// Interrupt Debounce Type Register - GPIO_DEBOUNCE - default no debounce
|
|
//
|
|
Addr = IohGpioBase + GPIO_DEBOUNCE;
|
|
Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
|
|
Data32 |= (GpioConfig->Debounce & 0x000FFFFF);
|
|
*((volatile UINT32 *) (UINTN)(Addr)) = Data32;
|
|
|
|
//
|
|
// Interrupt Clock Synchronisation Register - GPIO_LS_SYNC - default no sync with pclk_intr(APB bus clk)
|
|
//
|
|
Addr = IohGpioBase + GPIO_LS_SYNC;
|
|
Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
|
|
Data32 |= (GpioConfig->LsSync & 0x000FFFFF);
|
|
*((volatile UINT32 *) (UINTN)(Addr)) = Data32;
|
|
|
|
//
|
|
// Gpio Controller Manipulation Tasks.
|
|
//
|
|
|
|
if (PlatformType == (EFI_PLATFORM_TYPE) Galileo) {
|
|
//
|
|
// Reset Cypress Expander on Galileo Platform
|
|
//
|
|
Addr = IohGpioBase + GPIO_SWPORTA_DR;
|
|
Data32 = *((volatile UINT32 *) (UINTN)(Addr));
|
|
Data32 |= BIT4; // Cypress Reset line controlled by GPIO<4>
|
|
*((volatile UINT32 *) (UINTN)(Addr)) = Data32;
|
|
|
|
Data32 = *((volatile UINT32 *) (UINTN)(Addr));
|
|
Data32 &= ~BIT4; // Cypress Reset line controlled by GPIO<4>
|
|
*((volatile UINT32 *) (UINTN)(Addr)) = Data32;
|
|
|
|
}
|
|
|
|
//
|
|
// Restore settings for PCI CMD/BAR registers
|
|
//
|
|
PciWrite32 ((DevPcieAddr + PcdGet8 (PcdIohGpioBarRegister)), SaveBarReg);
|
|
PciWrite16 (DevPcieAddr + PCI_COMMAND_OFFSET, SaveCmdReg);
|
|
}
|
|
|
|
/**
|
|
Performs any early platform init of SoC Ethernet Mac devices.
|
|
|
|
@param IohMac0Address Mac address to program into Mac0 device.
|
|
@param IohMac1Address Mac address to program into Mac1 device.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
EarlyPlatformMacInit (
|
|
IN CONST UINT8 *IohMac0Address,
|
|
IN CONST UINT8 *IohMac1Address
|
|
)
|
|
{
|
|
BOOLEAN SetMacAddr;
|
|
|
|
//
|
|
// Set chipset MAC0 address if configured.
|
|
//
|
|
SetMacAddr =
|
|
(CompareMem (ChipsetDefaultMac, IohMac0Address, sizeof (ChipsetDefaultMac))) != 0;
|
|
if (SetMacAddr) {
|
|
if ((*(IohMac0Address) & BIT0) != 0) {
|
|
DEBUG ((EFI_D_ERROR, "HALT: Multicast Mac Address configured for Ioh MAC [B:%d, D:%d, F:%d]\n",
|
|
(UINTN) IOH_MAC0_BUS_NUMBER,
|
|
(UINTN) IOH_MAC0_DEVICE_NUMBER,
|
|
(UINTN) IOH_MAC0_FUNCTION_NUMBER
|
|
));
|
|
ASSERT (FALSE);
|
|
} else {
|
|
SetLanControllerMacAddr (
|
|
IOH_MAC0_BUS_NUMBER,
|
|
IOH_MAC0_DEVICE_NUMBER,
|
|
IOH_MAC0_FUNCTION_NUMBER,
|
|
IohMac0Address,
|
|
(UINT32) PcdGet64(PcdIohMac0MmioBase)
|
|
);
|
|
}
|
|
} else {
|
|
DEBUG ((EFI_D_WARN, "WARNING: Ioh MAC [B:%d, D:%d, F:%d] NO HW ADDR CONFIGURED!!!\n",
|
|
(UINTN) IOH_MAC0_BUS_NUMBER,
|
|
(UINTN) IOH_MAC0_DEVICE_NUMBER,
|
|
(UINTN) IOH_MAC0_FUNCTION_NUMBER
|
|
));
|
|
}
|
|
|
|
//
|
|
// Set chipset MAC1 address if configured.
|
|
//
|
|
SetMacAddr =
|
|
(CompareMem (ChipsetDefaultMac, IohMac1Address, sizeof (ChipsetDefaultMac))) != 0;
|
|
if (SetMacAddr) {
|
|
if ((*(IohMac1Address) & BIT0) != 0) {
|
|
DEBUG ((EFI_D_ERROR, "HALT: Multicast Mac Address configured for Ioh MAC [B:%d, D:%d, F:%d]\n",
|
|
(UINTN) IOH_MAC1_BUS_NUMBER,
|
|
(UINTN) IOH_MAC1_DEVICE_NUMBER,
|
|
(UINTN) IOH_MAC1_FUNCTION_NUMBER
|
|
));
|
|
ASSERT (FALSE);
|
|
} else {
|
|
SetLanControllerMacAddr (
|
|
IOH_MAC1_BUS_NUMBER,
|
|
IOH_MAC1_DEVICE_NUMBER,
|
|
IOH_MAC1_FUNCTION_NUMBER,
|
|
IohMac1Address,
|
|
(UINT32) PcdGet64(PcdIohMac1MmioBase)
|
|
);
|
|
}
|
|
} else {
|
|
DEBUG ((EFI_D_WARN, "WARNING: Ioh MAC [B:%d, D:%d, F:%d] NO HW ADDR CONFIGURED!!!\n",
|
|
(UINTN) IOH_MAC1_BUS_NUMBER,
|
|
(UINTN) IOH_MAC1_DEVICE_NUMBER,
|
|
(UINTN) IOH_MAC1_FUNCTION_NUMBER
|
|
));
|
|
}
|
|
}
|
|
|