summaryrefslogtreecommitdiff
path: root/BeagleBoardPkg/TimerDxe
diff options
context:
space:
mode:
Diffstat (limited to 'BeagleBoardPkg/TimerDxe')
-rw-r--r--BeagleBoardPkg/TimerDxe/Timer.c239
-rw-r--r--BeagleBoardPkg/TimerDxe/TimerDxe.inf60
2 files changed, 299 insertions, 0 deletions
diff --git a/BeagleBoardPkg/TimerDxe/Timer.c b/BeagleBoardPkg/TimerDxe/Timer.c
new file mode 100644
index 0000000000..32ba09c1eb
--- /dev/null
+++ b/BeagleBoardPkg/TimerDxe/Timer.c
@@ -0,0 +1,239 @@
+/** @file
+ Template for Timer Architecture Protocol driver of the ARM flavor
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/OmapLib.h>
+
+#include <Protocol/Timer.h>
+#include <Protocol/HardwareInterrupt.h>
+#include <Protocol/TimerDebugSupport.h>
+
+#include <Omap3530/Omap3530.h>
+
+
+// The notification function to call on every timer interrupt.
+volatile EFI_TIMER_NOTIFY mTimerNotifyFunction = (EFI_TIMER_NOTIFY)NULL;
+volatile EFI_PERIODIC_CALLBACK mTimerPeriodicCallback = (EFI_PERIODIC_CALLBACK)NULL;
+
+
+// The current period of the timer interrupt
+volatile UINT64 mTimerPeriod = 0;
+
+// Cached copy of the Hardware Interrupt protocol instance
+EFI_HARDWARE_INTERRUPT_PROTOCOL *gInterrupt = NULL;
+
+// Cached registers
+volatile UINT32 TISR;
+volatile UINT32 TCLR;
+volatile UINT32 TLDR;
+volatile UINT32 TCRR;
+volatile UINT32 TIER;
+
+// Cached interrupt vector
+volatile UINTN gVector;
+
+VOID
+EFIAPI
+TimerInterruptHandler (
+ IN HARDWARE_INTERRUPT_SOURCE Source,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ if (mTimerPeriodicCallback) {
+ mTimerPeriodicCallback(SystemContext);
+ }
+
+ if (mTimerNotifyFunction) {
+ mTimerNotifyFunction(mTimerPeriod);
+ }
+
+ // Clear all timer interrupts
+ MmioWrite32(TISR, TISR_CLEAR_ALL);
+
+ // Poll interrupt status bits to ensure clearing
+ while ((MmioRead32(TISR) & TISR_ALL_INTERRUPT_MASK) != TISR_NO_INTERRUPTS_PENDING);
+}
+
+EFI_STATUS
+EFIAPI
+TimerDriverRegisterHandler (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ IN EFI_TIMER_NOTIFY NotifyFunction
+ )
+{
+ if ((NotifyFunction == NULL) && (mTimerNotifyFunction == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((NotifyFunction != NULL) && (mTimerNotifyFunction != NULL)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ mTimerNotifyFunction = NotifyFunction;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+TimerDriverSetTimerPeriod (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ IN UINT64 TimerPeriod
+ )
+{
+ EFI_STATUS Status;
+ UINT64 TimerCount;
+ INT32 LoadValue;
+
+ if (TimerPeriod == 0) {
+ // Turn off GPTIMER3
+ MmioWrite32(TCLR, TCLR_ST_OFF);
+
+ Status = gInterrupt->DisableInterruptSource(gInterrupt, gVector);
+ } else {
+ // Calculate required timer count
+ TimerCount = DivU64x32(TimerPeriod * 100, PcdGet32(PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds));
+
+ // Set GPTIMER3 Load register
+ LoadValue = (INT32) -TimerCount;
+ MmioWrite32(TLDR, LoadValue);
+ MmioWrite32(TCRR, LoadValue);
+
+ // Enable Overflow interrupt
+ MmioWrite32(TIER, TIER_TCAR_IT_DISABLE | TIER_OVF_IT_ENABLE | TIER_MAT_IT_DISABLE);
+
+ // Turn on GPTIMER3, it will reload at overflow
+ MmioWrite32(TCLR, TCLR_AR_AUTORELOAD | TCLR_ST_ON);
+
+ Status = gInterrupt->EnableInterruptSource(gInterrupt, gVector);
+ }
+
+ //
+ // Save the new timer period
+ //
+ mTimerPeriod = TimerPeriod;
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+TimerDriverGetTimerPeriod (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ OUT UINT64 *TimerPeriod
+ )
+{
+ if (TimerPeriod == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *TimerPeriod = mTimerPeriod;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+TimerDriverGenerateSoftInterrupt (
+ IN EFI_TIMER_ARCH_PROTOCOL *This
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+TimerDriverRegisterPeriodicCallback (
+ IN TIMER_DEBUG_SUPPORT_PROTOCOL *This,
+ IN EFI_PERIODIC_CALLBACK PeriodicCallback
+ )
+{
+ if ((PeriodicCallback == NULL) && (mTimerPeriodicCallback == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((PeriodicCallback != NULL) && (mTimerPeriodicCallback != NULL)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ mTimerPeriodicCallback = PeriodicCallback;
+
+ return EFI_SUCCESS;
+}
+
+EFI_TIMER_ARCH_PROTOCOL gTimer = {
+ TimerDriverRegisterHandler,
+ TimerDriverSetTimerPeriod,
+ TimerDriverGetTimerPeriod,
+ TimerDriverGenerateSoftInterrupt
+};
+
+TIMER_DEBUG_SUPPORT_PROTOCOL gTimerDebugSupport = {
+ TimerDriverRegisterPeriodicCallback
+};
+
+EFI_STATUS
+EFIAPI
+TimerInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_HANDLE Handle = NULL;
+ EFI_STATUS Status;
+ UINT32 TimerBaseAddress;
+
+ // Find the interrupt controller protocol. ASSERT if not found.
+ Status = gBS->LocateProtocol(&gHardwareInterruptProtocolGuid, NULL, (VOID **)&gInterrupt);
+ ASSERT_EFI_ERROR (Status);
+
+ // Set up the timer registers
+ TimerBaseAddress = TimerBase(FixedPcdGet32(PcdBeagleArchTimer));
+ TISR = TimerBaseAddress + GPTIMER_TISR;
+ TCLR = TimerBaseAddress + GPTIMER_TCLR;
+ TLDR = TimerBaseAddress + GPTIMER_TLDR;
+ TCRR = TimerBaseAddress + GPTIMER_TCRR;
+ TIER = TimerBaseAddress + GPTIMER_TIER;
+
+ // Disable the timer
+ Status = TimerDriverSetTimerPeriod(&gTimer, 0);
+ ASSERT_EFI_ERROR (Status);
+
+ // Install interrupt handler
+ gVector = InterruptVectorForTimer(FixedPcdGet32(PcdBeagleArchTimer));
+ Status = gInterrupt->RegisterInterruptSource(gInterrupt, gVector, TimerInterruptHandler);
+ ASSERT_EFI_ERROR (Status);
+
+ // Set up default timer
+ Status = TimerDriverSetTimerPeriod(&gTimer, FixedPcdGet32(PcdTimerPeriod));
+ ASSERT_EFI_ERROR (Status);
+
+ // Install the Timer Architectural Protocol onto a new handle
+ Status = gBS->InstallMultipleProtocolInterfaces(&Handle,
+ &gEfiTimerArchProtocolGuid, &gTimer,
+ &gTimerDebugSupportProtocolGuid, &gTimerDebugSupport,
+ NULL);
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
diff --git a/BeagleBoardPkg/TimerDxe/TimerDxe.inf b/BeagleBoardPkg/TimerDxe/TimerDxe.inf
new file mode 100644
index 0000000000..b755aa79b4
--- /dev/null
+++ b/BeagleBoardPkg/TimerDxe/TimerDxe.inf
@@ -0,0 +1,60 @@
+#%HEADER%
+#/** @file
+#
+# Component discription file for Timer module
+#
+# Copyright (c) 2009, Apple Inc. <BR>
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BeagleBoardTimerDxe
+ FILE_GUID = 6ddbf08b-cfc9-43cc-9e81-0784ba312ca0
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = TimerInitialize
+
+[Sources.common]
+ Timer.c
+
+[Packages]
+ BeagleBoardPkg/BeagleBoardPkg.dec
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiRuntimeServicesTableLib
+ PerformanceLib
+ UefiLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ UefiDriverEntryPoint
+ IoLib
+ OmapLib
+
+[Guids]
+
+[Protocols]
+ gEfiTimerArchProtocolGuid
+ gHardwareInterruptProtocolGuid
+ gTimerDebugSupportProtocolGuid
+
+[Pcd.common]
+ gEmbeddedTokenSpaceGuid.PcdTimerPeriod
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds
+ gBeagleBoardTokenSpaceGuid.PcdBeagleArchTimer
+
+[Depex]
+ gHardwareInterruptProtocolGuid \ No newline at end of file