mirror of
				https://gitlab.com/qemu-project/edk2.git
				synced 2025-10-30 07:56:39 +08:00 
			
		
		
		
	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:
		 Sami Mujawar
					Sami Mujawar
				
			
				
					committed by
					
						![mergify[bot]](/assets/img/avatar_default.png) mergify[bot]
						mergify[bot]
					
				
			
			
				
	
			
			
			![mergify[bot]](/assets/img/avatar_default.png) mergify[bot]
						mergify[bot]
					
				
			
						parent
						
							a7d977040b
						
					
				
				
					commit
					015be4075f
				
			| @ -6,6 +6,7 @@ | ||||
| # | ||||
| # Copyright (c) 2009 - 2019, 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 | ||||
| # | ||||
| @ -41,6 +42,13 @@ | ||||
|   # @Prompt Configure HPET to use MSI. | ||||
|   gPcAtChipsetPkgTokenSpaceGuid.PcdHpetMsiEnable|TRUE|BOOLEAN|0x00001000 | ||||
|  | ||||
|   ## Indicates the RTC port registers are in MMIO space, or in I/O space. | ||||
|   #  Default is I/O space.<BR><BR> | ||||
|   #   TRUE  - RTC port registers are in MMIO space.<BR> | ||||
|   #   FALSE - RTC port registers are in I/O space.<BR> | ||||
|   # @Prompt RTC port registers use MMIO. | ||||
|   gPcAtChipsetPkgTokenSpaceGuid.PcdRtcUseMmio|FALSE|BOOLEAN|0x00000021 | ||||
|  | ||||
| [PcdsFixedAtBuild, PcdsDynamic, PcdsDynamicEx, PcdsPatchableInModule] | ||||
|   ## This PCD specifies the base address of the HPET timer. | ||||
|   # @Prompt HPET base address. | ||||
| @ -68,6 +76,14 @@ | ||||
|   # @Expression 0x80000001 | gPcAtChipsetPkgTokenSpaceGuid.PcdMaximalValidYear < gPcAtChipsetPkgTokenSpaceGuid.PcdMinimalValidYear + 100 | ||||
|   gPcAtChipsetPkgTokenSpaceGuid.PcdMaximalValidYear|2097|UINT16|0x0000000E | ||||
|  | ||||
|   ## Specifies RTC Index Register address in MMIO space. | ||||
|   # @Prompt RTC Index Register address | ||||
|   gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister64|0x0|UINT64|0x00000022 | ||||
|  | ||||
|   ## Specifies RTC Target Register address in MMIO space. | ||||
|   # @Prompt RTC Target Register address | ||||
|   gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister64|0x0|UINT64|0x00000023 | ||||
|  | ||||
| [PcdsFixedAtBuild, PcdsPatchableInModule] | ||||
|   ## Defines the ACPI register set base address. | ||||
|   #  The invalid 0xFFFF is as its default value. It must be configured to the real value. | ||||
|  | ||||
| @ -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); | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  | ||||
| @ -2,16 +2,23 @@ | ||||
|   Provides Set/Get time operations. | ||||
|  | ||||
| Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> | ||||
| Copyright (c) 2018 - 2020, ARM Limited. All rights reserved.<BR> | ||||
| SPDX-License-Identifier: BSD-2-Clause-Patent | ||||
|  | ||||
| **/ | ||||
|  | ||||
| #include <Library/DxeServicesTableLib.h> | ||||
| #include "PcRtc.h" | ||||
|  | ||||
| PC_RTC_MODULE_GLOBALS  mModuleGlobal; | ||||
|  | ||||
| EFI_HANDLE             mHandle = NULL; | ||||
|  | ||||
| STATIC EFI_EVENT       mVirtualAddrChangeEvent; | ||||
|  | ||||
| UINTN                  mRtcIndexRegister; | ||||
| UINTN                  mRtcTargetRegister; | ||||
|  | ||||
| /** | ||||
|   Returns the current time and date information, and the time-keeping capabilities | ||||
|   of the hardware platform. | ||||
| @ -105,6 +112,30 @@ PcRtcEfiSetWakeupTime ( | ||||
|   return PcRtcSetWakeupTime (Enabled, Time, &mModuleGlobal); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   Fixup internal data so that EFI can be called in virtual mode. | ||||
|   Call the passed in Child Notify event and convert any pointers in | ||||
|   lib to virtual mode. | ||||
|  | ||||
|   @param[in]    Event   The Event that is being processed | ||||
|   @param[in]    Context Event Context | ||||
| **/ | ||||
| VOID | ||||
| EFIAPI | ||||
| LibRtcVirtualNotifyEvent ( | ||||
|   IN EFI_EVENT        Event, | ||||
|   IN VOID             *Context | ||||
|   ) | ||||
| { | ||||
|   // Only needed if you are going to support the OS calling RTC functions in | ||||
|   // virtual mode. You will need to call EfiConvertPointer (). To convert any | ||||
|   // stored physical addresses to virtual address. After the OS transitions to | ||||
|   // calling in virtual mode, all future runtime calls will be made in virtual | ||||
|   // mode. | ||||
|   EfiConvertPointer (0x0, (VOID**)&mRtcIndexRegister); | ||||
|   EfiConvertPointer (0x0, (VOID**)&mRtcTargetRegister); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   The user Entry Point for PcRTC module. | ||||
|  | ||||
| @ -131,6 +162,11 @@ InitializePcRtc ( | ||||
|   EfiInitializeLock (&mModuleGlobal.RtcLock, TPL_CALLBACK); | ||||
|   mModuleGlobal.CenturyRtcAddress = GetCenturyRtcAddress (); | ||||
|  | ||||
|   if (FeaturePcdGet (PcdRtcUseMmio)) { | ||||
|     mRtcIndexRegister = (UINTN)PcdGet64 (PcdRtcIndexRegister64); | ||||
|     mRtcTargetRegister = (UINTN)PcdGet64 (PcdRtcTargetRegister64); | ||||
|   } | ||||
|  | ||||
|   Status = PcRtcInit (&mModuleGlobal); | ||||
|   ASSERT_EFI_ERROR (Status); | ||||
|  | ||||
| @ -165,7 +201,23 @@ InitializePcRtc ( | ||||
|                   NULL, | ||||
|                   NULL | ||||
|                   ); | ||||
|   ASSERT_EFI_ERROR (Status); | ||||
|   if (EFI_ERROR (Status)) { | ||||
|     ASSERT_EFI_ERROR (Status); | ||||
|     return Status; | ||||
|   } | ||||
|  | ||||
|   if (FeaturePcdGet (PcdRtcUseMmio)) { | ||||
|     // Register for the virtual address change event | ||||
|     Status = gBS->CreateEventEx ( | ||||
|                     EVT_NOTIFY_SIGNAL, | ||||
|                     TPL_NOTIFY, | ||||
|                     LibRtcVirtualNotifyEvent, | ||||
|                     NULL, | ||||
|                     &gEfiEventVirtualAddressChangeGuid, | ||||
|                     &mVirtualAddrChangeEvent | ||||
|                     ); | ||||
|     ASSERT_EFI_ERROR (Status); | ||||
|   } | ||||
|  | ||||
|   return Status; | ||||
| } | ||||
|  | ||||
| @ -6,6 +6,7 @@ | ||||
| # | ||||
| # Copyright (c) 2006 - 2019, 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 | ||||
| # | ||||
| @ -61,6 +62,11 @@ | ||||
|   ## SOMETIMES_CONSUMES ## SystemTable | ||||
|   gEfiAcpiTableGuid | ||||
|  | ||||
|   gEfiEventVirtualAddressChangeGuid | ||||
|  | ||||
| [FeaturePcd] | ||||
|   gPcAtChipsetPkgTokenSpaceGuid.PcdRtcUseMmio                   ## CONSUMES | ||||
|  | ||||
| [FixedPcd] | ||||
|   gPcAtChipsetPkgTokenSpaceGuid.PcdInitialValueRtcRegisterA     ## CONSUMES | ||||
|   gPcAtChipsetPkgTokenSpaceGuid.PcdInitialValueRtcRegisterB     ## CONSUMES | ||||
| @ -72,6 +78,8 @@ | ||||
|   gPcAtChipsetPkgTokenSpaceGuid.PcdMaximalValidYear             ## CONSUMES | ||||
|   gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister             ## CONSUMES | ||||
|   gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister            ## CONSUMES | ||||
|   gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister64           ## CONSUMES | ||||
|   gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister64          ## CONSUMES | ||||
|  | ||||
| [Depex] | ||||
|   gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid | ||||
|  | ||||
		Reference in New Issue
	
	Block a user