mirror of https://github.com/acidanthera/audk.git
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 <olivier.martin@arm.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15435 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
9d34cac819
commit
18ee5b6d78
|
@ -1,6 +1,6 @@
|
||||||
/** @file
|
/** @file
|
||||||
*
|
*
|
||||||
* Copyright (c) 2011, ARM Limited. All rights reserved.
|
* Copyright (c) 2011 - 2014, ARM Limited. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program and the accompanying materials
|
* This program and the accompanying materials
|
||||||
* are licensed and made available under the terms and conditions of the BSD License
|
* are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
@ -17,22 +17,22 @@
|
||||||
#define __PL031_REAL_TIME_CLOCK_H__
|
#define __PL031_REAL_TIME_CLOCK_H__
|
||||||
|
|
||||||
// PL031 Registers
|
// PL031 Registers
|
||||||
#define PL031_RTC_DR_DATA_REGISTER ((UINT32)PcdGet32(PcdPL031RtcBase) + 0x000)
|
#define PL031_RTC_DR_DATA_REGISTER 0x000
|
||||||
#define PL031_RTC_MR_MATCH_REGISTER ((UINT32)PcdGet32(PcdPL031RtcBase) + 0x004)
|
#define PL031_RTC_MR_MATCH_REGISTER 0x004
|
||||||
#define PL031_RTC_LR_LOAD_REGISTER ((UINT32)PcdGet32(PcdPL031RtcBase) + 0x008)
|
#define PL031_RTC_LR_LOAD_REGISTER 0x008
|
||||||
#define PL031_RTC_CR_CONTROL_REGISTER ((UINT32)PcdGet32(PcdPL031RtcBase) + 0x00C)
|
#define PL031_RTC_CR_CONTROL_REGISTER 0x00C
|
||||||
#define PL031_RTC_IMSC_IRQ_MASK_SET_CLEAR_REGISTER ((UINT32)PcdGet32(PcdPL031RtcBase) + 0x010)
|
#define PL031_RTC_IMSC_IRQ_MASK_SET_CLEAR_REGISTER 0x010
|
||||||
#define PL031_RTC_RIS_RAW_IRQ_STATUS_REGISTER ((UINT32)PcdGet32(PcdPL031RtcBase) + 0x014)
|
#define PL031_RTC_RIS_RAW_IRQ_STATUS_REGISTER 0x014
|
||||||
#define PL031_RTC_MIS_MASKED_IRQ_STATUS_REGISTER ((UINT32)PcdGet32(PcdPL031RtcBase) + 0x018)
|
#define PL031_RTC_MIS_MASKED_IRQ_STATUS_REGISTER 0x018
|
||||||
#define PL031_RTC_ICR_IRQ_CLEAR_REGISTER ((UINT32)PcdGet32(PcdPL031RtcBase) + 0x01C)
|
#define PL031_RTC_ICR_IRQ_CLEAR_REGISTER 0x01C
|
||||||
#define PL031_RTC_PERIPH_ID0 ((UINT32)PcdGet32(PcdPL031RtcBase) + 0xFE0)
|
#define PL031_RTC_PERIPH_ID0 0xFE0
|
||||||
#define PL031_RTC_PERIPH_ID1 ((UINT32)PcdGet32(PcdPL031RtcBase) + 0xFE4)
|
#define PL031_RTC_PERIPH_ID1 0xFE4
|
||||||
#define PL031_RTC_PERIPH_ID2 ((UINT32)PcdGet32(PcdPL031RtcBase) + 0xFE8)
|
#define PL031_RTC_PERIPH_ID2 0xFE8
|
||||||
#define PL031_RTC_PERIPH_ID3 ((UINT32)PcdGet32(PcdPL031RtcBase) + 0xFEC)
|
#define PL031_RTC_PERIPH_ID3 0xFEC
|
||||||
#define PL031_RTC_PCELL_ID0 ((UINT32)PcdGet32(PcdPL031RtcBase) + 0xFF0)
|
#define PL031_RTC_PCELL_ID0 0xFF0
|
||||||
#define PL031_RTC_PCELL_ID1 ((UINT32)PcdGet32(PcdPL031RtcBase) + 0xFF4)
|
#define PL031_RTC_PCELL_ID1 0xFF4
|
||||||
#define PL031_RTC_PCELL_ID2 ((UINT32)PcdGet32(PcdPL031RtcBase) + 0xFF8)
|
#define PL031_RTC_PCELL_ID2 0xFF8
|
||||||
#define PL031_RTC_PCELL_ID3 ((UINT32)PcdGet32(PcdPL031RtcBase) + 0xFFC)
|
#define PL031_RTC_PCELL_ID3 0xFFC
|
||||||
|
|
||||||
// PL031 Values
|
// PL031 Values
|
||||||
#define PL031_RTC_ENABLED 0x00000001
|
#define PL031_RTC_ENABLED 0x00000001
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
Currently this driver does not support runtime virtual calling.
|
Currently this driver does not support runtime virtual calling.
|
||||||
|
|
||||||
Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
|
Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
|
||||||
Copyright (c) 2011-2013, ARM Ltd. All rights reserved.<BR>
|
Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
|
||||||
|
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
@ -26,10 +26,16 @@
|
||||||
#include <Library/MemoryAllocationLib.h>
|
#include <Library/MemoryAllocationLib.h>
|
||||||
#include <Library/PcdLib.h>
|
#include <Library/PcdLib.h>
|
||||||
#include <Library/ArmPlatformSysConfigLib.h>
|
#include <Library/ArmPlatformSysConfigLib.h>
|
||||||
|
#include <Library/DxeServicesTableLib.h>
|
||||||
#include <Library/UefiBootServicesTableLib.h>
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||||
|
#include <Library/UefiRuntimeLib.h>
|
||||||
|
|
||||||
#include <Protocol/RealTimeClock.h>
|
#include <Protocol/RealTimeClock.h>
|
||||||
|
|
||||||
#include <Guid/GlobalVariable.h>
|
#include <Guid/GlobalVariable.h>
|
||||||
|
#include <Guid/EventGroup.h>
|
||||||
|
|
||||||
#include <Drivers/PL031RealTimeClock.h>
|
#include <Drivers/PL031RealTimeClock.h>
|
||||||
|
|
||||||
#include <ArmPlatform.h>
|
#include <ArmPlatform.h>
|
||||||
|
@ -37,6 +43,8 @@
|
||||||
STATIC CONST CHAR16 mTimeZoneVariableName[] = L"PL031RtcTimeZone";
|
STATIC CONST CHAR16 mTimeZoneVariableName[] = L"PL031RtcTimeZone";
|
||||||
STATIC CONST CHAR16 mDaylightVariableName[] = L"PL031RtcDaylight";
|
STATIC CONST CHAR16 mDaylightVariableName[] = L"PL031RtcDaylight";
|
||||||
STATIC BOOLEAN mPL031Initialized = FALSE;
|
STATIC BOOLEAN mPL031Initialized = FALSE;
|
||||||
|
STATIC EFI_EVENT mRtcVirtualAddrChangeEvent;
|
||||||
|
STATIC UINTN mPL031RtcBase;
|
||||||
|
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
IdentifyPL031 (
|
IdentifyPL031 (
|
||||||
|
@ -46,19 +54,19 @@ IdentifyPL031 (
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
|
|
||||||
// Check if this is a PrimeCell Peripheral
|
// Check if this is a PrimeCell Peripheral
|
||||||
if ( (MmioRead8 (PL031_RTC_PCELL_ID0) != 0x0D)
|
if ( (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID0) != 0x0D)
|
||||||
|| (MmioRead8 (PL031_RTC_PCELL_ID1) != 0xF0)
|
|| (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID1) != 0xF0)
|
||||||
|| (MmioRead8 (PL031_RTC_PCELL_ID2) != 0x05)
|
|| (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID2) != 0x05)
|
||||||
|| (MmioRead8 (PL031_RTC_PCELL_ID3) != 0xB1)) {
|
|| (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID3) != 0xB1)) {
|
||||||
Status = EFI_NOT_FOUND;
|
Status = EFI_NOT_FOUND;
|
||||||
goto EXIT;
|
goto EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this PrimeCell Peripheral is the PL031 Real Time Clock
|
// Check if this PrimeCell Peripheral is the PL031 Real Time Clock
|
||||||
if ( (MmioRead8 (PL031_RTC_PERIPH_ID0) != 0x31)
|
if ( (MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID0) != 0x31)
|
||||||
|| (MmioRead8 (PL031_RTC_PERIPH_ID1) != 0x10)
|
|| (MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID1) != 0x10)
|
||||||
|| ((MmioRead8 (PL031_RTC_PERIPH_ID2) & 0xF) != 0x04)
|
|| ((MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID2) & 0xF) != 0x04)
|
||||||
|| (MmioRead8 (PL031_RTC_PERIPH_ID3) != 0x00)) {
|
|| (MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID3) != 0x00)) {
|
||||||
Status = EFI_NOT_FOUND;
|
Status = EFI_NOT_FOUND;
|
||||||
goto EXIT;
|
goto EXIT;
|
||||||
}
|
}
|
||||||
|
@ -83,18 +91,18 @@ InitializePL031 (
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure interrupts are masked. We do not want RTC interrupts in UEFI
|
// 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) {
|
if ((MmioRead32 (mPL031RtcBase + 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);
|
MmioOr32 (mPL031RtcBase + PL031_RTC_IMSC_IRQ_MASK_SET_CLEAR_REGISTER, PL031_SET_IRQ_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear any existing interrupts
|
// Clear any existing interrupts
|
||||||
if ((MmioRead32 (PL031_RTC_RIS_RAW_IRQ_STATUS_REGISTER) & PL031_IRQ_TRIGGERED) == PL031_IRQ_TRIGGERED) {
|
if ((MmioRead32 (mPL031RtcBase + PL031_RTC_RIS_RAW_IRQ_STATUS_REGISTER) & PL031_IRQ_TRIGGERED) == PL031_IRQ_TRIGGERED) {
|
||||||
MmioOr32 (PL031_RTC_ICR_IRQ_CLEAR_REGISTER, PL031_CLEAR_IRQ);
|
MmioOr32 (mPL031RtcBase + PL031_RTC_ICR_IRQ_CLEAR_REGISTER, PL031_CLEAR_IRQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the clock counter
|
// Start the clock counter
|
||||||
if ((MmioRead32 (PL031_RTC_CR_CONTROL_REGISTER) & PL031_RTC_ENABLED) != PL031_RTC_ENABLED) {
|
if ((MmioRead32 (mPL031RtcBase + PL031_RTC_CR_CONTROL_REGISTER) & PL031_RTC_ENABLED) != PL031_RTC_ENABLED) {
|
||||||
MmioOr32 (PL031_RTC_CR_CONTROL_REGISTER, PL031_RTC_ENABLED);
|
MmioOr32 (mPL031RtcBase + PL031_RTC_CR_CONTROL_REGISTER, PL031_RTC_ENABLED);
|
||||||
}
|
}
|
||||||
|
|
||||||
mPL031Initialized = TRUE;
|
mPL031Initialized = TRUE;
|
||||||
|
@ -267,7 +275,7 @@ LibGetTime (
|
||||||
Status = ArmPlatformSysConfigGet (SYS_CFG_RTC, &EpochSeconds);
|
Status = ArmPlatformSysConfigGet (SYS_CFG_RTC, &EpochSeconds);
|
||||||
if (Status == EFI_UNSUPPORTED) {
|
if (Status == EFI_UNSUPPORTED) {
|
||||||
// Battery backed up hardware RTC does not exist, revert to PL031
|
// 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;
|
Status = EFI_SUCCESS;
|
||||||
} else if (EFI_ERROR (Status)) {
|
} else if (EFI_ERROR (Status)) {
|
||||||
// Battery backed up hardware RTC exists but could not be read due to error. Abort.
|
// Battery backed up hardware RTC exists but could not be read due to error. Abort.
|
||||||
|
@ -275,7 +283,7 @@ LibGetTime (
|
||||||
} else {
|
} else {
|
||||||
// Battery backed up hardware RTC exists and we read the time correctly from it.
|
// Battery backed up hardware RTC exists and we read the time correctly from it.
|
||||||
// Now sync the PL031 to the new time.
|
// 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
|
// Ensure Time is a valid pointer
|
||||||
|
@ -484,7 +492,7 @@ LibSetTime (
|
||||||
|
|
||||||
|
|
||||||
// Set the PL031
|
// 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.
|
// The accesses to Variable Services can be very slow, because we may be writing to Flash.
|
||||||
// Do this after having set the RTC.
|
// Do this after having set the RTC.
|
||||||
|
@ -579,46 +587,6 @@ LibSetWakeupTime (
|
||||||
return EFI_UNSUPPORTED;
|
return EFI_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This is the declaration of an EFI image entry point. This can be the entry point to an application
|
|
||||||
written to this specification, an EFI boot service driver, or an EFI runtime driver.
|
|
||||||
|
|
||||||
@param ImageHandle Handle that identifies the loaded image.
|
|
||||||
@param SystemTable System Table for this image.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The operation completed successfully.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
LibRtcInitialize (
|
|
||||||
IN EFI_HANDLE ImageHandle,
|
|
||||||
IN EFI_SYSTEM_TABLE *SystemTable
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_STATUS Status;
|
|
||||||
EFI_HANDLE Handle;
|
|
||||||
|
|
||||||
// Setup the setters and getters
|
|
||||||
gRT->GetTime = LibGetTime;
|
|
||||||
gRT->SetTime = LibSetTime;
|
|
||||||
gRT->GetWakeupTime = LibGetWakeupTime;
|
|
||||||
gRT->SetWakeupTime = LibSetWakeupTime;
|
|
||||||
|
|
||||||
// Install the protocol
|
|
||||||
Handle = NULL;
|
|
||||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
||||||
&Handle,
|
|
||||||
&gEfiRealTimeClockArchProtocolGuid, NULL,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Fixup internal data so that EFI can be call in virtual mode.
|
Fixup internal data so that EFI can be call in virtual mode.
|
||||||
Call the passed in Child Notify event and convert any pointers in
|
Call the passed in Child Notify event and convert any pointers in
|
||||||
|
@ -640,5 +608,75 @@ LibRtcVirtualNotifyEvent (
|
||||||
// to virtual address. After the OS transitions to calling in virtual mode, all future
|
// to virtual address. After the OS transitions to calling in virtual mode, all future
|
||||||
// runtime calls will be made in virtual mode.
|
// runtime calls will be made in virtual mode.
|
||||||
//
|
//
|
||||||
|
EfiConvertPointer (0x0, (VOID**)&mPL031RtcBase);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
This is the declaration of an EFI image entry point. This can be the entry point to an application
|
||||||
|
written to this specification, an EFI boot service driver, or an EFI runtime driver.
|
||||||
|
|
||||||
|
@param ImageHandle Handle that identifies the loaded image.
|
||||||
|
@param SystemTable System Table for this image.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The operation completed successfully.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
LibRtcInitialize (
|
||||||
|
IN EFI_HANDLE ImageHandle,
|
||||||
|
IN EFI_SYSTEM_TABLE *SystemTable
|
||||||
|
)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
gRT->GetWakeupTime = LibGetWakeupTime;
|
||||||
|
gRT->SetWakeupTime = LibSetWakeupTime;
|
||||||
|
|
||||||
|
// Install the protocol
|
||||||
|
Handle = NULL;
|
||||||
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||||
|
&Handle,
|
||||||
|
&gEfiRealTimeClockArchProtocolGuid, NULL,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Register for the virtual address change event
|
||||||
|
//
|
||||||
|
Status = gBS->CreateEventEx (
|
||||||
|
EVT_NOTIFY_SIGNAL,
|
||||||
|
TPL_NOTIFY,
|
||||||
|
LibRtcVirtualNotifyEvent,
|
||||||
|
NULL,
|
||||||
|
&gEfiEventVirtualAddressChangeGuid,
|
||||||
|
&mRtcVirtualAddrChangeEvent
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#/** @file
|
#/** @file
|
||||||
#
|
#
|
||||||
# Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
|
# Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
|
||||||
# Copyright (c) 2011-2013, ARM Ltd. All rights reserved.<BR>
|
# Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
|
||||||
#
|
#
|
||||||
# This program and the accompanying materials
|
# This program and the accompanying materials
|
||||||
# are licensed and made available under the terms and conditions of the BSD License
|
# are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
@ -35,6 +35,11 @@
|
||||||
DebugLib
|
DebugLib
|
||||||
PcdLib
|
PcdLib
|
||||||
ArmPlatformSysConfigLib
|
ArmPlatformSysConfigLib
|
||||||
|
DxeServicesTableLib
|
||||||
|
UefiRuntimeLib
|
||||||
|
|
||||||
|
[Guids]
|
||||||
|
gEfiEventVirtualAddressChangeGuid
|
||||||
|
|
||||||
[Pcd]
|
[Pcd]
|
||||||
gArmPlatformTokenSpaceGuid.PcdPL031RtcBase
|
gArmPlatformTokenSpaceGuid.PcdPL031RtcBase
|
||||||
|
|
Loading…
Reference in New Issue