Add common PchSbiAccessLib
This patch adds a common PchSbiAccessLib that all platforms can use. Changes for platforms will be done in a separate patch. This common lib is not currently linked to any project. Signed-off-by: Talamudupula <stalamudupula@gmail.com>
This commit is contained in:
parent
19123314d5
commit
0faae704d1
|
@ -0,0 +1,152 @@
|
|||
/** @file
|
||||
Header file for PchSbiAccessLib.
|
||||
|
||||
Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
#ifndef _PCH_SBI_ACCESS_LIB_H_
|
||||
#define _PCH_SBI_ACCESS_LIB_H_
|
||||
|
||||
#include <Uefi/UefiBaseType.h>
|
||||
|
||||
typedef UINT8 PCH_SBI_PID;
|
||||
|
||||
//
|
||||
// PCI to P2SB Bridge Registers (D31:F1)
|
||||
//
|
||||
#define PCI_DEVICE_NUMBER_PCH_P2SB 31
|
||||
#define PCI_FUNCTION_NUMBER_PCH_P2SB 1
|
||||
|
||||
//
|
||||
// Definition for SBI
|
||||
//
|
||||
#define R_P2SB_CFG_SBIADDR 0xD0
|
||||
#define R_P2SB_CFG_SBIDATA 0xD4
|
||||
#define R_P2SB_CFG_SBISTAT 0xD8
|
||||
#define B_P2SB_CFG_SBISTAT_OPCODE 0xFF00
|
||||
#define B_P2SB_CFG_SBISTAT_POSTED BIT7
|
||||
#define B_P2SB_CFG_SBISTAT_RESPONSE 0x0006
|
||||
#define N_P2SB_CFG_SBISTAT_RESPONSE 1
|
||||
#define B_P2SB_CFG_SBISTAT_INITRDY BIT0
|
||||
#define R_P2SB_CFG_SBIRID 0xDA
|
||||
#define R_P2SB_CFG_SBIEXTADDR 0xDC
|
||||
|
||||
//
|
||||
// Others
|
||||
//
|
||||
#define R_P2SB_CFG_E0 0xE0
|
||||
|
||||
/**
|
||||
PCH SBI Register structure
|
||||
**/
|
||||
typedef struct {
|
||||
UINT32 SbiAddr;
|
||||
UINT32 SbiExtAddr;
|
||||
UINT32 SbiData;
|
||||
UINT16 SbiStat;
|
||||
UINT16 SbiRid;
|
||||
} PCH_SBI_REGISTER_STRUCT;
|
||||
|
||||
/**
|
||||
PCH SBI opcode definitions
|
||||
**/
|
||||
typedef enum {
|
||||
MemoryRead = 0x0,
|
||||
MemoryWrite = 0x1,
|
||||
PciConfigRead = 0x4,
|
||||
PciConfigWrite = 0x5,
|
||||
PrivateControlRead = 0x6,
|
||||
PrivateControlWrite = 0x7,
|
||||
GpioLockUnlock = 0x13
|
||||
} PCH_SBI_OPCODE;
|
||||
|
||||
/**
|
||||
PCH SBI response status definitions
|
||||
**/
|
||||
typedef enum {
|
||||
SBI_SUCCESSFUL = 0,
|
||||
SBI_UNSUCCESSFUL = 1,
|
||||
SBI_POWERDOWN = 2,
|
||||
SBI_MIXED = 3,
|
||||
SBI_INVALID_RESPONSE
|
||||
} PCH_SBI_RESPONSE;
|
||||
|
||||
/**
|
||||
Execute PCH SBI message
|
||||
Take care of that there is no lock protection when using SBI programming in both POST time and SMI.
|
||||
It will clash with POST time SBI programming when SMI happen.
|
||||
Programmer MUST do the save and restore opration while using the PchSbiExecution inside SMI
|
||||
to prevent from racing condition.
|
||||
This function will reveal P2SB and hide P2SB if it's originally hidden. If more than one SBI access
|
||||
needed, it's better to unhide the P2SB before calling and hide it back after done.
|
||||
|
||||
When the return value is "EFI_SUCCESS", the "Response" do not need to be checked as it would have been
|
||||
SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would provide additional information
|
||||
when needed.
|
||||
|
||||
@param[in] Pid Port ID of the SBI message
|
||||
@param[in] Offset Offset of the SBI message
|
||||
@param[in] Opcode Opcode
|
||||
@param[in] Posted Posted message
|
||||
@param[in, out] Data32 Read/Write data
|
||||
@param[out] Response Response
|
||||
|
||||
@retval EFI_SUCCESS Successfully completed.
|
||||
@retval EFI_DEVICE_ERROR Transaction fail
|
||||
@retval EFI_INVALID_PARAMETER Invalid parameter
|
||||
@retval EFI_TIMEOUT Timeout while waiting for response
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PchSbiExecution (
|
||||
IN PCH_SBI_PID Pid,
|
||||
IN UINT64 Offset,
|
||||
IN PCH_SBI_OPCODE Opcode,
|
||||
IN BOOLEAN Posted,
|
||||
IN OUT UINT32 *Data32,
|
||||
OUT UINT8 *Response
|
||||
);
|
||||
|
||||
/**
|
||||
Full function for executing PCH SBI message
|
||||
Take care of that there is no lock protection when using SBI programming in both POST time and SMI.
|
||||
It will clash with POST time SBI programming when SMI happen.
|
||||
Programmer MUST do the save and restore opration while using the PchSbiExecution inside SMI
|
||||
to prevent from racing condition.
|
||||
This function will reveal P2SB and hide P2SB if it's originally hidden. If more than one SBI access
|
||||
needed, it's better to unhide the P2SB before calling and hide it back after done.
|
||||
|
||||
When the return value is "EFI_SUCCESS", the "Response" do not need to be checked as it would have been
|
||||
SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would provide additional information
|
||||
when needed.
|
||||
|
||||
@param[in] Pid Port ID of the SBI message
|
||||
@param[in] Offset Offset of the SBI message
|
||||
@param[in] Opcode Opcode
|
||||
@param[in] Posted Posted message
|
||||
@param[in] Fbe First byte enable
|
||||
@param[in] Bar Bar
|
||||
@param[in] Fid Function ID
|
||||
@param[in, out] Data32 Read/Write data
|
||||
@param[out] Response Response
|
||||
|
||||
@retval EFI_SUCCESS Successfully completed.
|
||||
@retval EFI_DEVICE_ERROR Transaction fail
|
||||
@retval EFI_INVALID_PARAMETER Invalid parameter
|
||||
@retval EFI_TIMEOUT Timeout while waiting for response
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PchSbiExecutionEx (
|
||||
IN PCH_SBI_PID Pid,
|
||||
IN UINT64 Offset,
|
||||
IN PCH_SBI_OPCODE Opcode,
|
||||
IN BOOLEAN Posted,
|
||||
IN UINT16 Fbe,
|
||||
IN UINT16 Bar,
|
||||
IN UINT16 Fid,
|
||||
IN OUT UINT32 *Data32,
|
||||
OUT UINT8 *Response
|
||||
);
|
||||
|
||||
#endif // _PCH_SBI_ACCESS_LIB_H_
|
|
@ -0,0 +1,319 @@
|
|||
/** @file
|
||||
PCH SBI access library.
|
||||
|
||||
Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include <Base.h>
|
||||
#include <Uefi/UefiBaseType.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/PchSbiAccessLib.h>
|
||||
#include <Library/BootloaderCommonLib.h>
|
||||
#include <IndustryStandard/Pci30.h>
|
||||
|
||||
/**
|
||||
Hide P2SB device.
|
||||
|
||||
@param[in] P2sbBase Pci base address of P2SB controller.
|
||||
|
||||
@retval EFI_SUCCESS Always return success.
|
||||
**/
|
||||
EFI_STATUS
|
||||
HideP2sb (
|
||||
IN UINTN P2sbBase
|
||||
)
|
||||
{
|
||||
MmioWrite8 (P2sbBase + R_P2SB_CFG_E0 + 1, BIT0);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Reveal P2SB device.
|
||||
Also return the original P2SB status which is for Hidding P2SB or not after.
|
||||
If OrgStatus is not NULL, then TRUE means P2SB is unhidden,
|
||||
and FALSE means P2SB is hidden originally.
|
||||
|
||||
@param[in] P2sbBase Pci base address of P2SB controller.
|
||||
@param[out] OrgStatus Original P2SB hidding/unhidden status
|
||||
|
||||
@retval EFI_SUCCESS Always return success.
|
||||
**/
|
||||
EFI_STATUS
|
||||
RevealP2sb (
|
||||
IN UINTN P2sbBase,
|
||||
OUT BOOLEAN *OrgStatus
|
||||
)
|
||||
{
|
||||
BOOLEAN DevicePresent;
|
||||
|
||||
DevicePresent = (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF);
|
||||
if (OrgStatus != NULL) {
|
||||
*OrgStatus = DevicePresent;
|
||||
}
|
||||
if (!DevicePresent) {
|
||||
MmioWrite8 (P2sbBase + R_P2SB_CFG_E0 + 1, 0);
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Execute PCH SBI message
|
||||
Take care of that there is no lock protection when using SBI programming in both POST time and SMI.
|
||||
It will clash with POST time SBI programming when SMI happen.
|
||||
Programmer MUST do the save and restore opration while using the PchSbiExecution inside SMI
|
||||
to prevent from racing condition.
|
||||
This function will reveal P2SB and hide P2SB if it's originally hidden. If more than one SBI access
|
||||
needed, it's better to unhide the P2SB before calling and hide it back after done.
|
||||
|
||||
When the return value is "EFI_SUCCESS", the "Response" do not need to be checked as it would have been
|
||||
SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would provide additional information
|
||||
when needed.
|
||||
|
||||
@param[in] Pid Port ID of the SBI message
|
||||
@param[in] Offset Offset of the SBI message
|
||||
@param[in] Opcode Opcode
|
||||
@param[in] Posted Posted message
|
||||
@param[in, out] Data32 Read/Write data
|
||||
@param[out] Response Response
|
||||
|
||||
@retval EFI_SUCCESS Successfully completed.
|
||||
@retval EFI_DEVICE_ERROR Transaction fail
|
||||
@retval EFI_INVALID_PARAMETER Invalid parameter
|
||||
@retval EFI_TIMEOUT Timeout while waiting for response
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PchSbiExecution (
|
||||
IN PCH_SBI_PID Pid,
|
||||
IN UINT64 Offset,
|
||||
IN PCH_SBI_OPCODE Opcode,
|
||||
IN BOOLEAN Posted,
|
||||
IN OUT UINT32 *Data32,
|
||||
OUT UINT8 *Response
|
||||
)
|
||||
{
|
||||
//
|
||||
// Check address valid
|
||||
//
|
||||
if (((UINT32) Offset & 0x3) != 0) {
|
||||
//
|
||||
// Warning message for the address not DWORD alignment.
|
||||
//
|
||||
DEBUG ((DEBUG_INFO, "PchSbiExecution: Be careful that the address is not DWORD alignment.\n"));
|
||||
}
|
||||
|
||||
return PchSbiExecutionEx ( Pid,
|
||||
Offset,
|
||||
Opcode,
|
||||
Posted,
|
||||
0x000F,
|
||||
0x0000,
|
||||
0x0000,
|
||||
Data32,
|
||||
Response
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Full function for executing PCH SBI message
|
||||
Take care of that there is no lock protection when using SBI programming in both POST time and SMI.
|
||||
It will clash with POST time SBI programming when SMI happen.
|
||||
Programmer MUST do the save and restore opration while using the PchSbiExecution inside SMI
|
||||
to prevent from racing condition.
|
||||
This function will reveal P2SB and hide P2SB if it's originally hidden. If more than one SBI access
|
||||
needed, it's better to unhide the P2SB before calling and hide it back after done.
|
||||
|
||||
When the return value is "EFI_SUCCESS", the "Response" do not need to be checked as it would have been
|
||||
SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would provide additional information
|
||||
when needed.
|
||||
|
||||
@param[in] Pid Port ID of the SBI message
|
||||
@param[in] Offset Offset of the SBI message
|
||||
@param[in] Opcode Opcode
|
||||
@param[in] Posted Posted message
|
||||
@param[in] Fbe First byte enable
|
||||
@param[in] Bar Bar
|
||||
@param[in] Fid Function ID
|
||||
@param[in, out] Data32 Read/Write data
|
||||
@param[out] Response Response
|
||||
|
||||
@retval EFI_SUCCESS Successfully completed.
|
||||
@retval EFI_DEVICE_ERROR Transaction fail
|
||||
@retval EFI_INVALID_PARAMETER Invalid parameter
|
||||
@retval EFI_TIMEOUT Timeout while waiting for response
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PchSbiExecutionEx (
|
||||
IN PCH_SBI_PID Pid,
|
||||
IN UINT64 Offset,
|
||||
IN PCH_SBI_OPCODE Opcode,
|
||||
IN BOOLEAN Posted,
|
||||
IN UINT16 Fbe,
|
||||
IN UINT16 Bar,
|
||||
IN UINT16 Fid,
|
||||
IN OUT UINT32 *Data32,
|
||||
OUT UINT8 *Response
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN P2sbBase;
|
||||
BOOLEAN P2sbOrgStatus;
|
||||
UINTN Timeout;
|
||||
UINT16 SbiStat;
|
||||
|
||||
//
|
||||
// Check opcode valid
|
||||
//
|
||||
switch (Opcode) {
|
||||
case MemoryRead:
|
||||
case MemoryWrite:
|
||||
case PciConfigRead:
|
||||
case PciConfigWrite:
|
||||
case PrivateControlRead:
|
||||
case PrivateControlWrite:
|
||||
case GpioLockUnlock:
|
||||
break;
|
||||
default:
|
||||
return EFI_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
P2sbOrgStatus = FALSE;
|
||||
P2sbBase = MM_PCI_ADDRESS (0, PCI_DEVICE_NUMBER_PCH_P2SB, PCI_FUNCTION_NUMBER_PCH_P2SB, 0);
|
||||
RevealP2sb (P2sbBase, &P2sbOrgStatus);
|
||||
if (MmioRead16 ((UINTN)P2sbBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
|
||||
ASSERT (FALSE);
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
///
|
||||
/// BWG Section 2.2.1
|
||||
/// 1. Poll P2SB PCI offset D8h[0] = 0b
|
||||
/// Make sure the previous opeartion is completed.
|
||||
///
|
||||
Timeout = 0xFFFFFFF;
|
||||
while (Timeout > 0) {
|
||||
SbiStat = MmioRead16 (P2sbBase + R_P2SB_CFG_SBISTAT);
|
||||
if ((SbiStat & B_P2SB_CFG_SBISTAT_INITRDY) == 0) {
|
||||
break;
|
||||
}
|
||||
Timeout--;
|
||||
}
|
||||
if (Timeout == 0) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ExitPchSbiExecutionEx;
|
||||
}
|
||||
//
|
||||
// Initial Response status
|
||||
//
|
||||
*Response = SBI_INVALID_RESPONSE;
|
||||
Status = EFI_SUCCESS;
|
||||
SbiStat = 0;
|
||||
///
|
||||
/// 2. Write P2SB PCI offset D0h[31:0] with Address and Destination Port ID
|
||||
///
|
||||
MmioWrite32 (P2sbBase + R_P2SB_CFG_SBIADDR, (UINT32) ((Pid << 24) | (UINT16) Offset));
|
||||
///
|
||||
/// 3. Write P2SB PCI offset DCh[31:0] with extended address, which is expected to be 0 in SKL PCH.
|
||||
///
|
||||
MmioWrite32 (P2sbBase + R_P2SB_CFG_SBIEXTADDR, (UINT32) RShiftU64 (Offset, 16));
|
||||
///
|
||||
/// 5. Set P2SB PCI offset D8h[15:8] = 00000110b for read
|
||||
/// Set P2SB PCI offset D8h[15:8] = 00000111b for write
|
||||
//
|
||||
// Set SBISTAT[15:8] to the opcode passed in
|
||||
// Set SBISTAT[7] to the posted passed in
|
||||
//
|
||||
MmioAndThenOr16 (
|
||||
(P2sbBase + R_P2SB_CFG_SBISTAT),
|
||||
(UINT16) ~(B_P2SB_CFG_SBISTAT_OPCODE | B_P2SB_CFG_SBISTAT_POSTED),
|
||||
(UINT16) ((Opcode << 8) | (Posted << 7))
|
||||
);
|
||||
///
|
||||
/// 6. Write P2SB PCI offset DAh[15:0] = F000h
|
||||
///
|
||||
//
|
||||
// Set RID[15:0] = Fbe << 12 | Bar << 8 | Fid
|
||||
//
|
||||
MmioWrite16 (
|
||||
(P2sbBase + R_P2SB_CFG_SBIRID),
|
||||
(((Fbe & 0x000F) << 12) | ((Bar & 0x0007) << 8) | (Fid & 0x00FF))
|
||||
);
|
||||
|
||||
switch (Opcode) {
|
||||
case MemoryWrite:
|
||||
case PciConfigWrite:
|
||||
case PrivateControlWrite:
|
||||
case GpioLockUnlock:
|
||||
///
|
||||
/// 4. Write P2SB PCI offset D4h[31:0] with the intended data accordingly
|
||||
///
|
||||
MmioWrite32 ((P2sbBase + R_P2SB_CFG_SBIDATA), *Data32);
|
||||
break;
|
||||
default:
|
||||
///
|
||||
/// 4. Write P2SB PCI offset D4h[31:0] with dummy data such as 0,
|
||||
/// because all D0-DFh register range must be touched in SKL PCH
|
||||
/// for a successful SBI transaction.
|
||||
///
|
||||
MmioWrite32 ((P2sbBase + R_P2SB_CFG_SBIDATA), 0);
|
||||
break;
|
||||
}
|
||||
///
|
||||
/// 7. Set P2SB PCI offset D8h[0] = 1b, Poll P2SB PCI offset D8h[0] = 0b
|
||||
///
|
||||
//
|
||||
// Set SBISTAT[0] = 1b, trigger the SBI operation
|
||||
//
|
||||
MmioOr16 (P2sbBase + R_P2SB_CFG_SBISTAT, (UINT16) B_P2SB_CFG_SBISTAT_INITRDY);
|
||||
//
|
||||
// Poll SBISTAT[0] = 0b, Polling for Busy bit
|
||||
//
|
||||
Timeout = 0xFFFFFFF;
|
||||
while (Timeout > 0) {
|
||||
SbiStat = MmioRead16 (P2sbBase + R_P2SB_CFG_SBISTAT);
|
||||
if ((SbiStat & B_P2SB_CFG_SBISTAT_INITRDY) == 0) {
|
||||
break;
|
||||
}
|
||||
Timeout--;
|
||||
}
|
||||
if (Timeout == 0) {
|
||||
//
|
||||
// If timeout, it's fatal error.
|
||||
//
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
} else {
|
||||
///
|
||||
/// 8. Check if P2SB PCI offset D8h[2:1] = 00b for successful transaction
|
||||
///
|
||||
*Response = (UINT8) ((SbiStat & B_P2SB_CFG_SBISTAT_RESPONSE) >> N_P2SB_CFG_SBISTAT_RESPONSE);
|
||||
if (*Response == SBI_SUCCESSFUL) {
|
||||
switch (Opcode) {
|
||||
case MemoryRead:
|
||||
case PciConfigRead:
|
||||
case PrivateControlRead:
|
||||
///
|
||||
/// 9. Read P2SB PCI offset D4h[31:0] for SBI data
|
||||
///
|
||||
*Data32 = MmioRead32 (P2sbBase + R_P2SB_CFG_SBIDATA);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Status = EFI_SUCCESS;
|
||||
} else {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ExitPchSbiExecutionEx:
|
||||
if (!P2sbOrgStatus) {
|
||||
HideP2sb (P2sbBase);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
## @file
|
||||
#
|
||||
# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = PchSbiAccessLib
|
||||
FILE_GUID = A12BF2B2-1485-4C0B-B2FB-255F645E8AF1
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = PchSbiAccessLib
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
|
||||
[Sources]
|
||||
PchSbiAccessLib.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
BootloaderCorePkg/BootloaderCorePkg.dec
|
||||
BootloaderCommonPkg/BootloaderCommonPkg.dec
|
||||
Silicon/CommonSocPkg/CommonSocPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
IoLib
|
||||
PcdLib
|
||||
|
||||
[Pcd]
|
||||
gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
|
Loading…
Reference in New Issue