mirror of https://github.com/acidanthera/audk.git
334 lines
8.9 KiB
C
334 lines
8.9 KiB
C
/** @file
|
|
Common Lib function for QNC internal network access.
|
|
|
|
Copyright (c) 2013-2015 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.
|
|
|
|
**/
|
|
|
|
//
|
|
// The package level header files this module uses
|
|
//
|
|
#include <Uefi.h>
|
|
|
|
#include <IntelQNCRegs.h>
|
|
#include <Library/QNCAccessLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <IndustryStandard/Pci22.h>
|
|
|
|
UINT32
|
|
EFIAPI
|
|
QNCPortRead(
|
|
UINT8 Port,
|
|
UINT32 RegAddress
|
|
)
|
|
{
|
|
McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
|
|
McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_READ_DW (Port, RegAddress);
|
|
return McD0PciCfg32 (QNC_ACCESS_PORT_MDR);
|
|
}
|
|
|
|
VOID
|
|
EFIAPI
|
|
QNCPortWrite (
|
|
UINT8 Port,
|
|
UINT32 RegAddress,
|
|
UINT32 WriteValue
|
|
)
|
|
{
|
|
McD0PciCfg32 (QNC_ACCESS_PORT_MDR) = WriteValue;
|
|
McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
|
|
McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_WRITE_DW (Port, RegAddress);
|
|
}
|
|
|
|
UINT32
|
|
EFIAPI
|
|
QNCAltPortRead (
|
|
UINT8 Port,
|
|
UINT32 RegAddress
|
|
)
|
|
{
|
|
McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
|
|
McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = ALT_MESSAGE_READ_DW (Port, RegAddress);
|
|
return McD0PciCfg32 (QNC_ACCESS_PORT_MDR);
|
|
}
|
|
|
|
VOID
|
|
EFIAPI
|
|
QNCAltPortWrite (
|
|
UINT8 Port,
|
|
UINT32 RegAddress,
|
|
UINT32 WriteValue
|
|
)
|
|
{
|
|
McD0PciCfg32 (QNC_ACCESS_PORT_MDR) = WriteValue;
|
|
McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
|
|
McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = ALT_MESSAGE_WRITE_DW (Port, RegAddress);
|
|
}
|
|
|
|
UINT32
|
|
EFIAPI
|
|
QNCPortIORead(
|
|
UINT8 Port,
|
|
UINT32 RegAddress
|
|
)
|
|
{
|
|
McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
|
|
McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_IO_READ_DW (Port, RegAddress);
|
|
return McD0PciCfg32 (QNC_ACCESS_PORT_MDR);
|
|
}
|
|
|
|
VOID
|
|
EFIAPI
|
|
QNCPortIOWrite (
|
|
UINT8 Port,
|
|
UINT32 RegAddress,
|
|
UINT32 WriteValue
|
|
)
|
|
{
|
|
McD0PciCfg32 (QNC_ACCESS_PORT_MDR) = WriteValue;
|
|
McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
|
|
McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_IO_WRITE_DW (Port, RegAddress);
|
|
}
|
|
|
|
RETURN_STATUS
|
|
EFIAPI
|
|
QNCMmIoWrite (
|
|
UINT32 MmIoAddress,
|
|
QNC_MEM_IO_WIDTH Width,
|
|
UINT32 DataNumber,
|
|
VOID *pData
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is for the special consideration for QNC MMIO write, as required by FWG, a reading must be performed after MMIO writing
|
|
to ensure the expected write is processed and data is flushed into chipset
|
|
|
|
Arguments:
|
|
|
|
Row -- row number to be cleared ( start from 1 )
|
|
|
|
Returns:
|
|
|
|
EFI_SUCCESS
|
|
|
|
--*/
|
|
{
|
|
RETURN_STATUS Status;
|
|
UINTN Index;
|
|
|
|
Status = RETURN_SUCCESS;
|
|
|
|
for (Index =0; Index < DataNumber; Index++) {
|
|
switch (Width) {
|
|
case QNCMmioWidthUint8:
|
|
QNCMmio8 (MmIoAddress, 0) = ((UINT8 *)pData)[Index];
|
|
if (QNCMmio8 (MmIoAddress, 0) != ((UINT8*)pData)[Index]) {
|
|
Status = RETURN_DEVICE_ERROR;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case QNCMmioWidthUint16:
|
|
QNCMmio16 (MmIoAddress, 0) = ((UINT16 *)pData)[Index];
|
|
if (QNCMmio16 (MmIoAddress, 0) != ((UINT16 *)pData)[Index]) {
|
|
Status = RETURN_DEVICE_ERROR;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case QNCMmioWidthUint32:
|
|
QNCMmio32 (MmIoAddress, 0) = ((UINT32 *)pData)[Index];
|
|
if (QNCMmio32 (MmIoAddress, 0) != ((UINT32 *)pData)[Index]) {
|
|
Status = RETURN_DEVICE_ERROR;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case QNCMmioWidthUint64:
|
|
QNCMmio64 (MmIoAddress, 0) = ((UINT64 *)pData)[Index];
|
|
if (QNCMmio64 (MmIoAddress, 0) != ((UINT64 *)pData)[Index]) {
|
|
Status = RETURN_DEVICE_ERROR;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
UINT32
|
|
EFIAPI
|
|
QncHsmmcRead (
|
|
VOID
|
|
)
|
|
{
|
|
return QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC);
|
|
}
|
|
|
|
VOID
|
|
EFIAPI
|
|
QncHsmmcWrite (
|
|
UINT32 WriteValue
|
|
)
|
|
{
|
|
UINT16 DeviceId;
|
|
UINT32 Data32;
|
|
|
|
//
|
|
// Check what Soc we are running on (read Host bridge DeviceId)
|
|
//
|
|
DeviceId = QNCMmPci16(0, MC_BUS, MC_DEV, MC_FUN, PCI_DEVICE_ID_OFFSET);
|
|
|
|
if (DeviceId == QUARK2_MC_DEVICE_ID) {
|
|
//
|
|
// Disable HSMMC configuration
|
|
//
|
|
Data32 = QncHsmmcRead ();
|
|
Data32 &= ~SMM_CTL_EN;
|
|
QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC, Data32);
|
|
|
|
//
|
|
// Validate HSMMC configuration is disabled
|
|
//
|
|
Data32 = QncHsmmcRead ();
|
|
ASSERT((Data32 & SMM_CTL_EN) == 0);
|
|
|
|
//
|
|
// Enable HSMMC configuration
|
|
//
|
|
WriteValue |= SMM_CTL_EN;
|
|
}
|
|
|
|
//
|
|
// Write the register value
|
|
//
|
|
QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC, WriteValue);
|
|
|
|
if (DeviceId == QUARK2_MC_DEVICE_ID) {
|
|
//
|
|
// Validate HSMMC configuration is enabled
|
|
//
|
|
Data32 = QncHsmmcRead ();
|
|
ASSERT((Data32 & SMM_CTL_EN) != 0);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
EFIAPI
|
|
QncImrWrite (
|
|
UINT32 ImrBaseOffset,
|
|
UINT32 ImrLow,
|
|
UINT32 ImrHigh,
|
|
UINT32 ImrReadMask,
|
|
UINT32 ImrWriteMask
|
|
)
|
|
{
|
|
UINT16 DeviceId;
|
|
UINT32 Data32;
|
|
|
|
//
|
|
// Check what Soc we are running on (read Host bridge DeviceId)
|
|
//
|
|
DeviceId = QNCMmPci16(0, MC_BUS, MC_DEV, MC_FUN, PCI_DEVICE_ID_OFFSET);
|
|
|
|
//
|
|
// Disable IMR protection
|
|
//
|
|
if (DeviceId == QUARK2_MC_DEVICE_ID) {
|
|
//
|
|
// Disable IMR protection
|
|
//
|
|
Data32 = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL);
|
|
Data32 &= ~IMR_EN;
|
|
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL, Data32);
|
|
|
|
//
|
|
// Validate IMR protection is disabled
|
|
//
|
|
Data32 = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL);
|
|
ASSERT((Data32 & IMR_EN) == 0);
|
|
|
|
//
|
|
// Update the IMR (IMRXL must be last as it may enable IMR violation checking)
|
|
//
|
|
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXRM, ImrReadMask);
|
|
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXWM, ImrWriteMask);
|
|
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXH, ImrHigh);
|
|
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL, ImrLow);
|
|
|
|
//
|
|
// Validate IMR protection is enabled/disabled
|
|
//
|
|
Data32 = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL);
|
|
ASSERT((Data32 & IMR_EN) == (ImrLow & IMR_EN));
|
|
} else {
|
|
//
|
|
// Disable IMR protection (allow all access)
|
|
//
|
|
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXRM, (UINT32)IMRX_ALL_ACCESS);
|
|
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXWM, (UINT32)IMRX_ALL_ACCESS);
|
|
|
|
//
|
|
// Update the IMR (IMRXRM/IMRXWM must be last as they restrict IMR access)
|
|
//
|
|
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL, (ImrLow & ~IMR_EN));
|
|
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXH, ImrHigh);
|
|
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXRM, ImrReadMask);
|
|
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXWM, ImrWriteMask);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
EFIAPI
|
|
QncIClkAndThenOr (
|
|
UINT32 RegAddress,
|
|
UINT32 AndValue,
|
|
UINT32 OrValue
|
|
)
|
|
{
|
|
UINT32 RegValue;
|
|
//
|
|
// Whenever an iCLK SB register (Endpoint 32h) is being programmed the access
|
|
// should always consist of a READ from the address followed by 2 identical
|
|
// WRITEs to that address.
|
|
//
|
|
RegValue = QNCAltPortRead (QUARK_ICLK_SB_PORT_ID, RegAddress);
|
|
RegValue &= AndValue;
|
|
RegValue |= OrValue;
|
|
QNCAltPortWrite (QUARK_ICLK_SB_PORT_ID, RegAddress, RegValue);
|
|
QNCAltPortWrite (QUARK_ICLK_SB_PORT_ID, RegAddress, RegValue);
|
|
}
|
|
|
|
VOID
|
|
EFIAPI
|
|
QncIClkOr (
|
|
UINT32 RegAddress,
|
|
UINT32 OrValue
|
|
)
|
|
{
|
|
UINT32 RegValue;
|
|
//
|
|
// Whenever an iCLK SB register (Endpoint 32h) is being programmed the access
|
|
// should always consist of a READ from the address followed by 2 identical
|
|
// WRITEs to that address.
|
|
//
|
|
RegValue = QNCAltPortRead (QUARK_ICLK_SB_PORT_ID, RegAddress);
|
|
RegValue |= OrValue;
|
|
QNCAltPortWrite (QUARK_ICLK_SB_PORT_ID, RegAddress, RegValue);
|
|
QNCAltPortWrite (QUARK_ICLK_SB_PORT_ID, RegAddress, RegValue);
|
|
}
|