/** @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); }