From 18ee5b6d78d2275abc05dd58bf5062364a4e640e Mon Sep 17 00:00:00 2001 From: Olivier Martin Date: Tue, 8 Apr 2014 17:59:00 +0000 Subject: ArmPlatformPkg/PL031RealTimeClock: Fixed driver to support UEFI Runtime Services - Removed PCD base address from the macro definition. The base address needs to be fixup when the driver runs in UEFI Runtime mode - Added the PL031 controller memory region to the Runtime UEFI Memory Mapped IO - Caught the gEfiEventVirtualAddressChangeGuid event to fixup the PL031 Base address Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Olivier Martin git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15435 6f19259b-4bc3-4df7-8a09-765794883524 --- .../PL031RealTimeClockLib/PL031RealTimeClockLib.c | 122 ++++++++++++++------- .../PL031RealTimeClockLib.inf | 7 +- 2 files changed, 86 insertions(+), 43 deletions(-) (limited to 'ArmPlatformPkg/Library/PL031RealTimeClockLib') diff --git a/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.c b/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.c index 980f809b2c..b43d8dc4ba 100644 --- a/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.c +++ b/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.c @@ -4,7 +4,7 @@ Currently this driver does not support runtime virtual calling. Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.
- Copyright (c) 2011-2013, ARM Ltd. All rights reserved.
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -26,10 +26,16 @@ #include #include #include +#include #include #include +#include + #include + #include +#include + #include #include @@ -37,6 +43,8 @@ STATIC CONST CHAR16 mTimeZoneVariableName[] = L"PL031RtcTimeZone"; STATIC CONST CHAR16 mDaylightVariableName[] = L"PL031RtcDaylight"; STATIC BOOLEAN mPL031Initialized = FALSE; +STATIC EFI_EVENT mRtcVirtualAddrChangeEvent; +STATIC UINTN mPL031RtcBase; EFI_STATUS IdentifyPL031 ( @@ -46,19 +54,19 @@ IdentifyPL031 ( EFI_STATUS Status; // Check if this is a PrimeCell Peripheral - if ( (MmioRead8 (PL031_RTC_PCELL_ID0) != 0x0D) - || (MmioRead8 (PL031_RTC_PCELL_ID1) != 0xF0) - || (MmioRead8 (PL031_RTC_PCELL_ID2) != 0x05) - || (MmioRead8 (PL031_RTC_PCELL_ID3) != 0xB1)) { + if ( (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID0) != 0x0D) + || (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID1) != 0xF0) + || (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID2) != 0x05) + || (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID3) != 0xB1)) { Status = EFI_NOT_FOUND; goto EXIT; } // Check if this PrimeCell Peripheral is the PL031 Real Time Clock - if ( (MmioRead8 (PL031_RTC_PERIPH_ID0) != 0x31) - || (MmioRead8 (PL031_RTC_PERIPH_ID1) != 0x10) - || ((MmioRead8 (PL031_RTC_PERIPH_ID2) & 0xF) != 0x04) - || (MmioRead8 (PL031_RTC_PERIPH_ID3) != 0x00)) { + if ( (MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID0) != 0x31) + || (MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID1) != 0x10) + || ((MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID2) & 0xF) != 0x04) + || (MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID3) != 0x00)) { Status = EFI_NOT_FOUND; goto EXIT; } @@ -83,18 +91,18 @@ InitializePL031 ( } // Ensure interrupts are masked. We do not want RTC interrupts in UEFI - if ((MmioRead32 (PL031_RTC_IMSC_IRQ_MASK_SET_CLEAR_REGISTER) & PL031_SET_IRQ_MASK) != PL031_SET_IRQ_MASK) { - MmioOr32 (PL031_RTC_IMSC_IRQ_MASK_SET_CLEAR_REGISTER, PL031_SET_IRQ_MASK); + if ((MmioRead32 (mPL031RtcBase + PL031_RTC_IMSC_IRQ_MASK_SET_CLEAR_REGISTER) & PL031_SET_IRQ_MASK) != PL031_SET_IRQ_MASK) { + MmioOr32 (mPL031RtcBase + PL031_RTC_IMSC_IRQ_MASK_SET_CLEAR_REGISTER, PL031_SET_IRQ_MASK); } // Clear any existing interrupts - if ((MmioRead32 (PL031_RTC_RIS_RAW_IRQ_STATUS_REGISTER) & PL031_IRQ_TRIGGERED) == PL031_IRQ_TRIGGERED) { - MmioOr32 (PL031_RTC_ICR_IRQ_CLEAR_REGISTER, PL031_CLEAR_IRQ); + if ((MmioRead32 (mPL031RtcBase + PL031_RTC_RIS_RAW_IRQ_STATUS_REGISTER) & PL031_IRQ_TRIGGERED) == PL031_IRQ_TRIGGERED) { + MmioOr32 (mPL031RtcBase + PL031_RTC_ICR_IRQ_CLEAR_REGISTER, PL031_CLEAR_IRQ); } // Start the clock counter - if ((MmioRead32 (PL031_RTC_CR_CONTROL_REGISTER) & PL031_RTC_ENABLED) != PL031_RTC_ENABLED) { - MmioOr32 (PL031_RTC_CR_CONTROL_REGISTER, PL031_RTC_ENABLED); + if ((MmioRead32 (mPL031RtcBase + PL031_RTC_CR_CONTROL_REGISTER) & PL031_RTC_ENABLED) != PL031_RTC_ENABLED) { + MmioOr32 (mPL031RtcBase + PL031_RTC_CR_CONTROL_REGISTER, PL031_RTC_ENABLED); } mPL031Initialized = TRUE; @@ -267,7 +275,7 @@ LibGetTime ( Status = ArmPlatformSysConfigGet (SYS_CFG_RTC, &EpochSeconds); if (Status == EFI_UNSUPPORTED) { // Battery backed up hardware RTC does not exist, revert to PL031 - EpochSeconds = MmioRead32 (PL031_RTC_DR_DATA_REGISTER); + EpochSeconds = MmioRead32 (mPL031RtcBase + PL031_RTC_DR_DATA_REGISTER); Status = EFI_SUCCESS; } else if (EFI_ERROR (Status)) { // Battery backed up hardware RTC exists but could not be read due to error. Abort. @@ -275,7 +283,7 @@ LibGetTime ( } else { // Battery backed up hardware RTC exists and we read the time correctly from it. // Now sync the PL031 to the new time. - MmioWrite32 (PL031_RTC_LR_LOAD_REGISTER, EpochSeconds); + MmioWrite32 (mPL031RtcBase + PL031_RTC_LR_LOAD_REGISTER, EpochSeconds); } // Ensure Time is a valid pointer @@ -484,7 +492,7 @@ LibSetTime ( // Set the PL031 - MmioWrite32 (PL031_RTC_LR_LOAD_REGISTER, EpochSeconds); + MmioWrite32 (mPL031RtcBase + PL031_RTC_LR_LOAD_REGISTER, EpochSeconds); // The accesses to Variable Services can be very slow, because we may be writing to Flash. // Do this after having set the RTC. @@ -579,7 +587,30 @@ LibSetWakeupTime ( return EFI_UNSUPPORTED; } +/** + Fixup internal data so that EFI can be call 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**)&mPL031RtcBase); + return; +} /** This is the declaration of an EFI image entry point. This can be the entry point to an application @@ -601,6 +632,24 @@ LibRtcInitialize ( EFI_STATUS Status; EFI_HANDLE Handle; + // Initialize RTC Base Address + mPL031RtcBase = PcdGet32 (PcdPL031RtcBase); + + // Declare the controller as EFI_MEMORY_RUNTIME + Status = gDS->AddMemorySpace ( + EfiGcdMemoryTypeMemoryMappedIo, + mPL031RtcBase, SIZE_4KB, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gDS->SetMemorySpaceAttributes (mPL031RtcBase, SIZE_4KB, EFI_MEMORY_UC | EFI_MEMORY_RUNTIME); + if (EFI_ERROR (Status)) { + return Status; + } + // Setup the setters and getters gRT->GetTime = LibGetTime; gRT->SetTime = LibSetTime; @@ -614,31 +663,20 @@ LibRtcInitialize ( &gEfiRealTimeClockArchProtocolGuid, NULL, NULL ); + ASSERT_EFI_ERROR (Status); - return Status; -} - - -/** - Fixup internal data so that EFI can be call 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. + // Register for the virtual address change event // - return; + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + LibRtcVirtualNotifyEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mRtcVirtualAddrChangeEvent + ); + ASSERT_EFI_ERROR (Status); + + return Status; } diff --git a/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf b/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf index add982ce8e..3a98fc757e 100644 --- a/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf +++ b/ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf @@ -1,7 +1,7 @@ #/** @file # # Copyright (c) 2006, Intel Corporation. All rights reserved.
-# Copyright (c) 2011-2013, ARM Ltd. All rights reserved.
+# Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
# # This program and the accompanying materials # are licensed and made available under the terms and conditions of the BSD License @@ -35,6 +35,11 @@ DebugLib PcdLib ArmPlatformSysConfigLib + DxeServicesTableLib + UefiRuntimeLib + +[Guids] + gEfiEventVirtualAddressChangeGuid [Pcd] gArmPlatformTokenSpaceGuid.PcdPL031RtcBase -- cgit v1.2.3