PcAtChipsetPkg: Add MMIO Support to RTC driver
Some virtual machine managers like Kvmtool emulate the MC146818 RTC controller in the MMIO space so that architectures that do not support I/O Mapped I/O can use the RTC. This patch adds MMIO support to the RTC controller driver. The PCD PcdRtcUseMmio has been added to select I/O or MMIO support. If PcdRtcUseMmio is: TRUE - Indicates the RTC port registers are in MMIO space. FALSE - Indicates the RTC port registers are in I/O space. Default is I/O space. Additionally two new PCDs PcdRtcIndexRegister64 and PcdRtcTargetRegister64 have been introduced to provide the base address for the RTC registers in the MMIO space. When MMIO support is selected (PcdRtcUseMmio == TRUE) the driver converts the pointers to the RTC MMIO registers so that the RTC registers are accessible post ExitBootServices. Signed-off-by: Sami Mujawar <sami.mujawar@arm.com> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@arm.com> Acked-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
committed by
mergify[bot]
parent
a7d977040b
commit
015be4075f
@@ -3,6 +3,7 @@
|
||||
|
||||
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2017, AMD Inc. All rights reserved.<BR>
|
||||
Copyright (c) 2018 - 2020, ARM Limited. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
@@ -10,6 +11,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
#include "PcRtc.h"
|
||||
|
||||
extern UINTN mRtcIndexRegister;
|
||||
extern UINTN mRtcTargetRegister;
|
||||
|
||||
//
|
||||
// Days of month.
|
||||
//
|
||||
@@ -54,38 +58,132 @@ IsWithinOneDay (
|
||||
);
|
||||
|
||||
/**
|
||||
Read RTC content through its registers.
|
||||
Read RTC content through its registers using IO access.
|
||||
|
||||
@param Address Address offset of RTC. It is recommended to use macros such as
|
||||
RTC_ADDRESS_SECONDS.
|
||||
@param Address Address offset of RTC. It is recommended to use
|
||||
macros such as RTC_ADDRESS_SECONDS.
|
||||
|
||||
@return The data of UINT8 type read from RTC.
|
||||
**/
|
||||
STATIC
|
||||
UINT8
|
||||
RtcRead (
|
||||
IN UINT8 Address
|
||||
IoRtcRead (
|
||||
IN UINTN Address
|
||||
)
|
||||
{
|
||||
IoWrite8 (PcdGet8 (PcdRtcIndexRegister), (UINT8) (Address | (UINT8) (IoRead8 (PcdGet8 (PcdRtcIndexRegister)) & 0x80)));
|
||||
IoWrite8 (
|
||||
PcdGet8 (PcdRtcIndexRegister),
|
||||
(UINT8)(Address | (UINT8)(IoRead8 (PcdGet8 (PcdRtcIndexRegister)) & 0x80))
|
||||
);
|
||||
return IoRead8 (PcdGet8 (PcdRtcTargetRegister));
|
||||
}
|
||||
|
||||
/**
|
||||
Write RTC through its registers using IO access.
|
||||
|
||||
@param Address Address offset of RTC. It is recommended to use
|
||||
macros such as RTC_ADDRESS_SECONDS.
|
||||
@param Data The content you want to write into RTC.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
IoRtcWrite (
|
||||
IN UINTN Address,
|
||||
IN UINT8 Data
|
||||
)
|
||||
{
|
||||
IoWrite8 (
|
||||
PcdGet8 (PcdRtcIndexRegister),
|
||||
(UINT8)(Address | (UINT8)(IoRead8 (PcdGet8 (PcdRtcIndexRegister)) & 0x80))
|
||||
);
|
||||
IoWrite8 (PcdGet8 (PcdRtcTargetRegister), Data);
|
||||
}
|
||||
|
||||
/**
|
||||
Read RTC content through its registers using MMIO access.
|
||||
|
||||
@param Address Address offset of RTC. It is recommended to use
|
||||
macros such as RTC_ADDRESS_SECONDS.
|
||||
|
||||
@return The data of UINT8 type read from RTC.
|
||||
**/
|
||||
STATIC
|
||||
UINT8
|
||||
MmioRtcRead (
|
||||
IN UINTN Address
|
||||
)
|
||||
{
|
||||
MmioWrite8 (
|
||||
mRtcIndexRegister,
|
||||
(UINT8)(Address | (UINT8)(MmioRead8 (mRtcIndexRegister) & 0x80))
|
||||
);
|
||||
return MmioRead8 (mRtcTargetRegister);
|
||||
}
|
||||
|
||||
/**
|
||||
Write RTC through its registers using MMIO access.
|
||||
|
||||
@param Address Address offset of RTC. It is recommended to use
|
||||
macros such as RTC_ADDRESS_SECONDS.
|
||||
@param Data The content you want to write into RTC.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
MmioRtcWrite (
|
||||
IN UINTN Address,
|
||||
IN UINT8 Data
|
||||
)
|
||||
{
|
||||
MmioWrite8 (
|
||||
mRtcIndexRegister,
|
||||
(UINT8)(Address | (UINT8)(MmioRead8 (mRtcIndexRegister) & 0x80))
|
||||
);
|
||||
MmioWrite8 (mRtcTargetRegister, Data);
|
||||
}
|
||||
|
||||
/**
|
||||
Read RTC content through its registers.
|
||||
|
||||
@param Address Address offset of RTC. It is recommended to use
|
||||
macros such as RTC_ADDRESS_SECONDS.
|
||||
|
||||
@return The data of UINT8 type read from RTC.
|
||||
**/
|
||||
STATIC
|
||||
UINT8
|
||||
RtcRead (
|
||||
IN UINTN Address
|
||||
)
|
||||
{
|
||||
if (FeaturePcdGet (PcdRtcUseMmio)) {
|
||||
return MmioRtcRead (Address);
|
||||
}
|
||||
|
||||
return IoRtcRead (Address);
|
||||
}
|
||||
|
||||
/**
|
||||
Write RTC through its registers.
|
||||
|
||||
@param Address Address offset of RTC. It is recommended to use macros such as
|
||||
RTC_ADDRESS_SECONDS.
|
||||
@param Data The content you want to write into RTC.
|
||||
@param Address Address offset of RTC. It is recommended to use
|
||||
macros such as RTC_ADDRESS_SECONDS.
|
||||
@param Data The content you want to write into RTC.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
RtcWrite (
|
||||
IN UINT8 Address,
|
||||
IN UINTN Address,
|
||||
IN UINT8 Data
|
||||
)
|
||||
{
|
||||
IoWrite8 (PcdGet8 (PcdRtcIndexRegister), (UINT8) (Address | (UINT8) (IoRead8 (PcdGet8 (PcdRtcIndexRegister)) & 0x80)));
|
||||
IoWrite8 (PcdGet8 (PcdRtcTargetRegister), Data);
|
||||
if (FeaturePcdGet (PcdRtcUseMmio)) {
|
||||
MmioRtcWrite (Address, Data);
|
||||
} else {
|
||||
IoRtcWrite (Address, Data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user