/** @file
CPU REGBAR ACCESS library.
All function in this library is available for PEI, DXE, and SMM,
But do not support UEFI RUNTIME environment call.
Copyright (c) 2021, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include
#include
#include
#include
#include
#include
/**
Definition for REGBAR address
The REGBAR address is used for the CPU IP's SB register access
**/
#define CPU_REGBAR_ADDRESS(Pid, Offset) (PcdGet32(PcdRegBarBaseAddress) | ((UINT8)(Pid) << 16) | (UINT16)(Offset))
/**
Read REGBAR register.
It returns REGBAR register and size in 8bytes.
The Offset should not exceed 0xFFFF and must be aligned with size.
@param[in] CpuSbDevicePid CPU SB Device Port ID
@param[in] Offset Register offset of this Port ID
@retval UINT64 REGBAR register value.
**/
UINT64
CpuRegbarRead64 (
IN CPU_SB_DEVICE_PID CpuSbDevicePid,
IN UINT16 Offset
)
{
UINT8 Pid;
Pid = CpuSbDevicePid;
if (Pid != INVALID_PID)
return ((UINT64) MmioRead32 (CPU_REGBAR_ADDRESS (Pid, Offset)) + LShiftU64 ((UINT64) MmioRead32 (CPU_REGBAR_ADDRESS (Pid, Offset+4)), 32));
else
return INVALID_DATA_64;
}
/**
Read REGBAR register.
It returns REGBAR register and size in 4bytes.
The Offset should not exceed 0xFFFF and must be aligned with size.
@param[in] CpuSbDevicePid CPU SB Device Port ID
@param[in] Offset Register offset of this Port ID
@retval UINT32 REGBAR register value.
**/
UINT32
CpuRegbarRead32 (
IN CPU_SB_DEVICE_PID CpuSbDevicePid,
IN UINT16 Offset
)
{
UINT8 Pid;
Pid = CpuSbDevicePid;
if (Pid != INVALID_PID)
return MmioRead32 (CPU_REGBAR_ADDRESS (Pid, Offset));
else
return INVALID_DATA_32;
}
/**
Read REGBAR register.
It returns REGBAR register and size in 2bytes.
The Offset should not exceed 0xFFFF and must be aligned with size.
@param[in] CpuSbDevicePid CPU SB Device Port ID
@param[in] Offset Register offset of this Port ID
@retval UINT16 REGBAR register value.
**/
UINT16
CpuRegbarRead16 (
IN CPU_SB_DEVICE_PID CpuSbDevicePid,
IN UINT16 Offset
)
{
UINT16 DwOffset;
UINT32 Data32;
UINT16 Data16;
Data16 = 0;
Data32 = 0;
DwOffset = 0;
if (CpuSbDevicePid == INVALID_PID) {
return INVALID_DATA_16;
}
switch (Offset & 0x0003) {
case 0:
DwOffset = Offset;
break;
case 2:
DwOffset = Offset - 0x2;
break;
}
Data32 = MmioRead32 (CPU_REGBAR_ADDRESS (CpuSbDevicePid, DwOffset));
switch (Offset & 0x0003) {
case 0:
Data16 = (UINT16) Data32;
break;
case 2:
Data16 = (UINT16) (Data32 >> 16);
break;
}
return Data16;
}
/**
Read REGBAR register.
It returns REGBAR register and size in 1bytes.
The Offset should not exceed 0xFFFF and must be aligned with size.
@param[in] CpuSbDevicePid CPU SB Device Port ID
@param[in] Offset Register offset of this Port ID
@retval UINT8 REGBAR regsiter value
**/
UINT8
CpuRegbarRead8 (
IN CPU_SB_DEVICE_PID CpuSbDevicePid,
IN UINT16 Offset
)
{
UINT16 DwOffset;
UINT32 Data32;
UINT8 Data8;
DwOffset = 0;
Data32 = 0;
Data8 = 0;
if (CpuSbDevicePid == INVALID_PID)
return INVALID_DATA_8;
switch (Offset & 0x0003) {
case 0:
DwOffset = Offset;
break;
case 1:
DwOffset = Offset - 0x1;
break;
case 2:
DwOffset = Offset - 0x2;
break;
case 3:
DwOffset = Offset - 0x3;
break;
}
Data32 = MmioRead32 (CPU_REGBAR_ADDRESS (CpuSbDevicePid, DwOffset));
switch (Offset & 0x0003) {
case 0:
Data8 = (UINT8) Data32;
break;
case 1:
Data8 = (UINT8) (Data32 >> 8);
break;
case 2:
Data8 = (UINT8) (Data32 >> 16);
break;
case 3:
Data8 = (UINT8) (Data32 >> 24);
break;
}
return Data8;
}
/**
Write REGBAR register.
It programs REGBAR register and size in 8bytes.
The Offset should not exceed 0xFFFF and must be aligned with size.
@param[in] CpuSbDevicePid CPU SB Device Port ID
@param[in] Offset Register offset of Port ID.
@param[in] Data Input Data. Must be the same size as Size parameter.
@retval UINT64 Value written to register
**/
UINT64
CpuRegbarWrite64 (
IN CPU_SB_DEVICE_PID CpuSbDevicePid,
IN UINT16 Offset,
IN UINT64 Data
)
{
UINT8 Pid;
Pid = CpuSbDevicePid;
if (Pid != INVALID_PID) {
MmioWrite32 (CPU_REGBAR_ADDRESS (Pid, Offset) + 4, (UINT32) RShiftU64 (Data, 32));
MmioWrite32 (CPU_REGBAR_ADDRESS (Pid, Offset), (UINT32) Data);
return Data;
}
else
return INVALID_DATA_64;
}
/**
Write REGBAR register.
It programs REGBAR register and size in 4bytes.
The Offset should not exceed 0xFFFF and must be aligned with size.
@param[in] CpuSbDevicePid CPU SB Device Port ID
@param[in] Offset Register offset of Port ID.
@param[in] Data Input Data. Must be the same size as Size parameter.
@retval UINT32 Value written to register
**/
UINT32
CpuRegbarWrite32 (
IN CPU_SB_DEVICE_PID CpuSbDevicePid,
IN UINT16 Offset,
IN UINT32 Data
)
{
UINT8 Pid;
Pid = CpuSbDevicePid;
if (Pid != INVALID_PID)
return MmioWrite32 (CPU_REGBAR_ADDRESS (Pid, Offset), Data);
else
return INVALID_DATA_32;
}
/**
Write REGBAR register.
It programs REGBAR register and size in 2bytes.
The Offset should not exceed 0xFFFF and must be aligned with size.
@param[in] CpuSbDevicePid CPU SB Device Port ID
@param[in] Offset Register offset of Port ID.
@param[in] Data Input Data. Must be the same size as Size parameter.
@retval UINT16 Value written to register
**/
UINT16
CpuRegbarWrite16 (
IN CPU_SB_DEVICE_PID CpuSbDevicePid,
IN UINT16 Offset,
IN UINT16 Data
)
{
UINT8 Pid;
Pid = CpuSbDevicePid;
if (Pid != INVALID_PID)
return MmioWrite16 (CPU_REGBAR_ADDRESS (Pid, Offset), Data);
else
return INVALID_DATA_16;
}
/**
Write REGBAR register.
It programs REGBAR register and size in 1bytes.
The Offset should not exceed 0xFFFF and must be aligned with size.
@param[in] CpuSbDevicePid CPU SB Device Port ID
@param[in] Offset Register offset of Port ID.
@param[in] Data Input Data. Must be the same size as Size parameter.
@retval UINT8 Value written to register
**/
UINT8
CpuRegbarWrite8 (
IN CPU_SB_DEVICE_PID CpuSbDevicePid,
IN UINT16 Offset,
IN UINT8 Data
)
{
UINT8 Pid;
Pid = CpuSbDevicePid;
if (Pid != INVALID_PID)
return MmioWrite8 (CPU_REGBAR_ADDRESS (Pid, Offset), Data);
else
return INVALID_DATA_8;
}
/**
Write REGBAR register.
It programs REGBAR register and size in 4bytes.
The Offset should not exceed 0xFFFF and must be aligned with size.
@param[in] CpuSbDevicePid CPU SB Device Port ID
@param[in] Offset Register offset of Port ID.
@param[in] OrData OR Data. Must be the same size as Size parameter.
@retval UINT32 Value written to register
**/
UINT32
CpuRegbarOr32 (
IN CPU_SB_DEVICE_PID CpuSbDevicePid,
IN UINT16 Offset,
IN UINT32 OrData
)
{
return CpuRegbarWrite32 (CpuSbDevicePid, Offset, CpuRegbarRead32(CpuSbDevicePid, Offset) | OrData);
}
/**
Write REGBAR register.
It programs REGBAR register and size in 2bytes.
The Offset should not exceed 0xFFFF and must be aligned with size.
@param[in] CpuSbDevicePid CPU SB Device Port ID
@param[in] Offset Register offset of Port ID.
@param[in] OrData OR Data. Must be the same size as Size parameter.
@retval UINT16 Value written to register
**/
UINT16
CpuRegbarOr16 (
IN CPU_SB_DEVICE_PID CpuSbDevicePid,
IN UINT16 Offset,
IN UINT16 OrData
)
{
return CpuRegbarWrite16 (CpuSbDevicePid, Offset, CpuRegbarRead16(CpuSbDevicePid, Offset) | OrData);
}
/**
Write REGBAR register.
It programs REGBAR register and size in 1bytes.
The Offset should not exceed 0xFFFF and must be aligned with size.
@param[in] CpuSbDevicePid CPU SB Device Port ID
@param[in] Offset Register offset of Port ID.
@param[in] OrData OR Data. Must be the same size as Size parameter.
@retval UINT8 Value written to register
**/
UINT8
CpuRegbarOr8(
IN CPU_SB_DEVICE_PID CpuSbDevicePid,
IN UINT16 Offset,
IN UINT8 OrData
)
{
return CpuRegbarWrite8 (CpuSbDevicePid, Offset, CpuRegbarRead8(CpuSbDevicePid, Offset) | OrData);
}
/**
Performs a bitwise AND of a 32-bit data.
It programs REGBAR register and size in 4bytes.
The Offset should not exceed 0xFFFF and must be aligned with size.
@param[in] CpuSbDevice CPU SB Device
@param[in] Offset Register offset of Port ID.
@param[in] AndData And Data. Must be the same size as Size parameter.
@retval UINT32 Value written to register
**/
UINT32
CpuRegbarAnd32 (
IN CPU_SB_DEVICE_PID CpuSbDevicePid,
IN UINT16 Offset,
IN UINT32 AndData
)
{
return CpuRegbarWrite32 (CpuSbDevicePid, Offset, CpuRegbarRead32 (CpuSbDevicePid, Offset) & AndData);
}
/**
Performs a bitwise AND of a 16-bit data.
It programs REGBAR register and size in 2bytes.
The Offset should not exceed 0xFFFF and must be aligned with size.
@param[in] CpuSbDevice CPU SB Device
@param[in] Offset Register offset of Port ID.
@param[in] AndData And Data. Must be the same size as Size parameter.
@retval UINT16 Value written to register
**/
UINT16
CpuRegbarAnd16 (
IN CPU_SB_DEVICE_PID CpuSbDevicePid,
IN UINT16 Offset,
IN UINT16 AndData
)
{
return CpuRegbarWrite16 (CpuSbDevicePid, Offset, CpuRegbarRead16 (CpuSbDevicePid, Offset) & AndData);
}
/**
Performs a bitwise AND of a 8-bit data.
It programs REGBAR register and size in 1byte.
The Offset should not exceed 0xFFFF and must be aligned with size.
@param[in] CpuSbDevice CPU SB Device
@param[in] Offset Register offset of Port ID.
@param[in] AndData And Data. Must be the same size as Size parameter.
@retval UINT8 Value written to register
**/
UINT8
CpuRegbarAnd8 (
IN CPU_SB_DEVICE_PID CpuSbDevicePid,
IN UINT16 Offset,
IN UINT8 AndData
)
{
return CpuRegbarWrite8 (CpuSbDevicePid, Offset, CpuRegbarRead8 (CpuSbDevicePid, Offset) & AndData);
}
/**
Write REGBAR register.
It programs REGBAR register and size in 4bytes.
The Offset should not exceed 0xFFFF and must be aligned with size.
@param[in] CpuSbDevicePid CPU SB Device Port ID
@param[in] Offset Register offset of Port ID.
@param[in] AndData AND Data. Must be the same size as Size parameter.
@param[in] OrData OR Data. Must be the same size as Size parameter.
@retval UINT32 Value written to register
**/
UINT32
CpuRegbarAndThenOr32 (
IN CPU_SB_DEVICE_PID CpuSbDevicePid,
IN UINT16 Offset,
IN UINT32 AndData,
IN UINT32 OrData
)
{
return CpuRegbarWrite32 (CpuSbDevicePid, Offset, (CpuRegbarRead32 (CpuSbDevicePid, Offset) & AndData) | OrData);
}
/**
Write REGBAR register.
It programs REGBAR register and size in 2bytes.
The Offset should not exceed 0xFFFF and must be aligned with size.
@param[in] CpuSbDevicePid CPU SB Device Port ID
@param[in] Offset Register offset of Port ID.
@param[in] AndData AND Data. Must be the same size as Size parameter.
@param[in] OrData OR Data. Must be the same size as Size parameter.
@retval UINT16 Value written to register
**/
UINT16
CpuRegbarAndThenOr16 (
IN CPU_SB_DEVICE_PID CpuSbDevicePid,
IN UINT16 Offset,
IN UINT16 AndData,
IN UINT16 OrData
)
{
return CpuRegbarWrite16 (CpuSbDevicePid, Offset, (CpuRegbarRead16 (CpuSbDevicePid, Offset) & AndData) | OrData);
}
/**
Write REGBAR register.
It programs REGBAR register and size in 1bytes.
The Offset should not exceed 0xFFFF and must be aligned with size.
@param[in] CpuSbDevicePid CPU SB Device Port ID
@param[in] Offset Register offset of Port ID.
@param[in] AndData AND Data. Must be the same size as Size parameter.
@param[in] OrData OR Data. Must be the same size as Size parameter.
@retval UINT8 Value written to register
**/
UINT8
CpuRegbarAndThenOr8 (
IN CPU_SB_DEVICE_PID CpuSbDevicePid,
IN UINT16 Offset,
IN UINT8 AndData,
IN UINT8 OrData
)
{
return CpuRegbarWrite8 (CpuSbDevicePid, Offset, (CpuRegbarRead8 (CpuSbDevicePid, Offset) & AndData) | OrData);
}