11e57a46299244793beb27e74be171d1540606999oliviermartin/** @file 21e57a46299244793beb27e74be171d1540606999oliviermartin Template for Timer Architecture Protocol driver of the ARM flavor 31e57a46299244793beb27e74be171d1540606999oliviermartin 41e57a46299244793beb27e74be171d1540606999oliviermartin Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR> 51e57a46299244793beb27e74be171d1540606999oliviermartin 63402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron This program and the accompanying materials 73402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron are licensed and made available under the terms and conditions of the BSD License 83402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron which accompanies this distribution. The full text of the license may be found at 93402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron http://opensource.org/licenses/bsd-license.php 103402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 113402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 123402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 131e57a46299244793beb27e74be171d1540606999oliviermartin 141e57a46299244793beb27e74be171d1540606999oliviermartin**/ 151e57a46299244793beb27e74be171d1540606999oliviermartin 161e57a46299244793beb27e74be171d1540606999oliviermartin 171e57a46299244793beb27e74be171d1540606999oliviermartin#include <PiDxe.h> 181e57a46299244793beb27e74be171d1540606999oliviermartin 191e57a46299244793beb27e74be171d1540606999oliviermartin#include <Library/BaseLib.h> 201e57a46299244793beb27e74be171d1540606999oliviermartin#include <Library/DebugLib.h> 211e57a46299244793beb27e74be171d1540606999oliviermartin#include <Library/BaseMemoryLib.h> 221e57a46299244793beb27e74be171d1540606999oliviermartin#include <Library/UefiBootServicesTableLib.h> 231e57a46299244793beb27e74be171d1540606999oliviermartin#include <Library/UefiLib.h> 241e57a46299244793beb27e74be171d1540606999oliviermartin#include <Library/PcdLib.h> 251e57a46299244793beb27e74be171d1540606999oliviermartin#include <Library/IoLib.h> 261e57a46299244793beb27e74be171d1540606999oliviermartin#include <Library/OmapLib.h> 271e57a46299244793beb27e74be171d1540606999oliviermartin 281e57a46299244793beb27e74be171d1540606999oliviermartin#include <Protocol/Timer.h> 291e57a46299244793beb27e74be171d1540606999oliviermartin#include <Protocol/HardwareInterrupt.h> 301e57a46299244793beb27e74be171d1540606999oliviermartin 311e57a46299244793beb27e74be171d1540606999oliviermartin#include <Omap3530/Omap3530.h> 321e57a46299244793beb27e74be171d1540606999oliviermartin 331e57a46299244793beb27e74be171d1540606999oliviermartin 341e57a46299244793beb27e74be171d1540606999oliviermartin// The notification function to call on every timer interrupt. 351e57a46299244793beb27e74be171d1540606999oliviermartinvolatile EFI_TIMER_NOTIFY mTimerNotifyFunction = (EFI_TIMER_NOTIFY)NULL; 361e57a46299244793beb27e74be171d1540606999oliviermartin 371e57a46299244793beb27e74be171d1540606999oliviermartin 381e57a46299244793beb27e74be171d1540606999oliviermartin// The current period of the timer interrupt 391e57a46299244793beb27e74be171d1540606999oliviermartinvolatile UINT64 mTimerPeriod = 0; 401e57a46299244793beb27e74be171d1540606999oliviermartin 411e57a46299244793beb27e74be171d1540606999oliviermartin// Cached copy of the Hardware Interrupt protocol instance 421e57a46299244793beb27e74be171d1540606999oliviermartinEFI_HARDWARE_INTERRUPT_PROTOCOL *gInterrupt = NULL; 431e57a46299244793beb27e74be171d1540606999oliviermartin 441e57a46299244793beb27e74be171d1540606999oliviermartin// Cached registers 451e57a46299244793beb27e74be171d1540606999oliviermartinvolatile UINT32 TISR; 461e57a46299244793beb27e74be171d1540606999oliviermartinvolatile UINT32 TCLR; 471e57a46299244793beb27e74be171d1540606999oliviermartinvolatile UINT32 TLDR; 481e57a46299244793beb27e74be171d1540606999oliviermartinvolatile UINT32 TCRR; 491e57a46299244793beb27e74be171d1540606999oliviermartinvolatile UINT32 TIER; 501e57a46299244793beb27e74be171d1540606999oliviermartin 511e57a46299244793beb27e74be171d1540606999oliviermartin// Cached interrupt vector 521e57a46299244793beb27e74be171d1540606999oliviermartinvolatile UINTN gVector; 531e57a46299244793beb27e74be171d1540606999oliviermartin 541e57a46299244793beb27e74be171d1540606999oliviermartin 551e57a46299244793beb27e74be171d1540606999oliviermartin/** 561e57a46299244793beb27e74be171d1540606999oliviermartin 571e57a46299244793beb27e74be171d1540606999oliviermartin C Interrupt Handler calledin the interrupt context when Source interrupt is active. 581e57a46299244793beb27e74be171d1540606999oliviermartin 591e57a46299244793beb27e74be171d1540606999oliviermartin 601e57a46299244793beb27e74be171d1540606999oliviermartin @param Source Source of the interrupt. Hardware routing off a specific platform defines 611e57a46299244793beb27e74be171d1540606999oliviermartin what source means. 621e57a46299244793beb27e74be171d1540606999oliviermartin 631e57a46299244793beb27e74be171d1540606999oliviermartin @param SystemContext Pointer to system register context. Mostly used by debuggers and will 643402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron update the system context after the return from the interrupt if 651e57a46299244793beb27e74be171d1540606999oliviermartin modified. Don't change these values unless you know what you are doing 661e57a46299244793beb27e74be171d1540606999oliviermartin 671e57a46299244793beb27e74be171d1540606999oliviermartin**/ 681e57a46299244793beb27e74be171d1540606999oliviermartinVOID 691e57a46299244793beb27e74be171d1540606999oliviermartinEFIAPI 701e57a46299244793beb27e74be171d1540606999oliviermartinTimerInterruptHandler ( 711e57a46299244793beb27e74be171d1540606999oliviermartin IN HARDWARE_INTERRUPT_SOURCE Source, 723402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron IN EFI_SYSTEM_CONTEXT SystemContext 731e57a46299244793beb27e74be171d1540606999oliviermartin ) 741e57a46299244793beb27e74be171d1540606999oliviermartin{ 751e57a46299244793beb27e74be171d1540606999oliviermartin EFI_TPL OriginalTPL; 761e57a46299244793beb27e74be171d1540606999oliviermartin 771e57a46299244793beb27e74be171d1540606999oliviermartin 781e57a46299244793beb27e74be171d1540606999oliviermartin 791e57a46299244793beb27e74be171d1540606999oliviermartin // 803402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron // DXE core uses this callback for the EFI timer tick. The DXE core uses locks 811e57a46299244793beb27e74be171d1540606999oliviermartin // that raise to TPL_HIGH and then restore back to current level. Thus we need 823402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron // to make sure TPL level is set to TPL_HIGH while we are handling the timer tick. 831e57a46299244793beb27e74be171d1540606999oliviermartin // 841e57a46299244793beb27e74be171d1540606999oliviermartin OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL); 851e57a46299244793beb27e74be171d1540606999oliviermartin 861e57a46299244793beb27e74be171d1540606999oliviermartin if (mTimerNotifyFunction) { 871e57a46299244793beb27e74be171d1540606999oliviermartin mTimerNotifyFunction(mTimerPeriod); 881e57a46299244793beb27e74be171d1540606999oliviermartin } 891e57a46299244793beb27e74be171d1540606999oliviermartin 901e57a46299244793beb27e74be171d1540606999oliviermartin // Clear all timer interrupts 913402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron MmioWrite32 (TISR, TISR_CLEAR_ALL); 921e57a46299244793beb27e74be171d1540606999oliviermartin 931e57a46299244793beb27e74be171d1540606999oliviermartin // Poll interrupt status bits to ensure clearing 941e57a46299244793beb27e74be171d1540606999oliviermartin while ((MmioRead32 (TISR) & TISR_ALL_INTERRUPT_MASK) != TISR_NO_INTERRUPTS_PENDING); 951e57a46299244793beb27e74be171d1540606999oliviermartin 961e57a46299244793beb27e74be171d1540606999oliviermartin gBS->RestoreTPL (OriginalTPL); 971e57a46299244793beb27e74be171d1540606999oliviermartin} 981e57a46299244793beb27e74be171d1540606999oliviermartin 991e57a46299244793beb27e74be171d1540606999oliviermartin/** 1003402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron This function registers the handler NotifyFunction so it is called every time 1013402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron the timer interrupt fires. It also passes the amount of time since the last 1023402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron handler call to the NotifyFunction. If NotifyFunction is NULL, then the 1033402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron handler is unregistered. If the handler is registered, then EFI_SUCCESS is 1043402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron returned. If the CPU does not support registering a timer interrupt handler, 1053402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron then EFI_UNSUPPORTED is returned. If an attempt is made to register a handler 1063402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron when a handler is already registered, then EFI_ALREADY_STARTED is returned. 1073402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron If an attempt is made to unregister a handler when a handler is not registered, 1083402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to 1093402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ERROR 1101e57a46299244793beb27e74be171d1540606999oliviermartin is returned. 1111e57a46299244793beb27e74be171d1540606999oliviermartin 1121e57a46299244793beb27e74be171d1540606999oliviermartin @param This The EFI_TIMER_ARCH_PROTOCOL instance. 1131e57a46299244793beb27e74be171d1540606999oliviermartin @param NotifyFunction The function to call when a timer interrupt fires. This 1141e57a46299244793beb27e74be171d1540606999oliviermartin function executes at TPL_HIGH_LEVEL. The DXE Core will 1151e57a46299244793beb27e74be171d1540606999oliviermartin register a handler for the timer interrupt, so it can know 1161e57a46299244793beb27e74be171d1540606999oliviermartin how much time has passed. This information is used to 1171e57a46299244793beb27e74be171d1540606999oliviermartin signal timer based events. NULL will unregister the handler. 1181e57a46299244793beb27e74be171d1540606999oliviermartin @retval EFI_SUCCESS The timer handler was registered. 1191e57a46299244793beb27e74be171d1540606999oliviermartin @retval EFI_UNSUPPORTED The platform does not support timer interrupts. 1201e57a46299244793beb27e74be171d1540606999oliviermartin @retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handler is already 1211e57a46299244793beb27e74be171d1540606999oliviermartin registered. 1221e57a46299244793beb27e74be171d1540606999oliviermartin @retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not 1231e57a46299244793beb27e74be171d1540606999oliviermartin previously registered. 1241e57a46299244793beb27e74be171d1540606999oliviermartin @retval EFI_DEVICE_ERROR The timer handler could not be registered. 1251e57a46299244793beb27e74be171d1540606999oliviermartin 1261e57a46299244793beb27e74be171d1540606999oliviermartin**/ 1271e57a46299244793beb27e74be171d1540606999oliviermartinEFI_STATUS 1281e57a46299244793beb27e74be171d1540606999oliviermartinEFIAPI 1291e57a46299244793beb27e74be171d1540606999oliviermartinTimerDriverRegisterHandler ( 1301e57a46299244793beb27e74be171d1540606999oliviermartin IN EFI_TIMER_ARCH_PROTOCOL *This, 1311e57a46299244793beb27e74be171d1540606999oliviermartin IN EFI_TIMER_NOTIFY NotifyFunction 1321e57a46299244793beb27e74be171d1540606999oliviermartin ) 1331e57a46299244793beb27e74be171d1540606999oliviermartin{ 1341e57a46299244793beb27e74be171d1540606999oliviermartin if ((NotifyFunction == NULL) && (mTimerNotifyFunction == NULL)) { 1351e57a46299244793beb27e74be171d1540606999oliviermartin return EFI_INVALID_PARAMETER; 1361e57a46299244793beb27e74be171d1540606999oliviermartin } 1371e57a46299244793beb27e74be171d1540606999oliviermartin 1381e57a46299244793beb27e74be171d1540606999oliviermartin if ((NotifyFunction != NULL) && (mTimerNotifyFunction != NULL)) { 1391e57a46299244793beb27e74be171d1540606999oliviermartin return EFI_ALREADY_STARTED; 1401e57a46299244793beb27e74be171d1540606999oliviermartin } 1411e57a46299244793beb27e74be171d1540606999oliviermartin 1421e57a46299244793beb27e74be171d1540606999oliviermartin mTimerNotifyFunction = NotifyFunction; 1431e57a46299244793beb27e74be171d1540606999oliviermartin 1441e57a46299244793beb27e74be171d1540606999oliviermartin return EFI_SUCCESS; 1451e57a46299244793beb27e74be171d1540606999oliviermartin} 1461e57a46299244793beb27e74be171d1540606999oliviermartin 1471e57a46299244793beb27e74be171d1540606999oliviermartin/** 1481e57a46299244793beb27e74be171d1540606999oliviermartin 1493402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron This function adjusts the period of timer interrupts to the value specified 1503402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron by TimerPeriod. If the timer period is updated, then the selected timer 1513402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If 1523402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron the timer hardware is not programmable, then EFI_UNSUPPORTED is returned. 1533402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron If an error occurs while attempting to update the timer period, then the 1543402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron timer hardware will be put back in its state prior to this call, and 1553402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt 1563402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron is disabled. This is not the same as disabling the CPU's interrupts. 1573402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron Instead, it must either turn off the timer hardware, or it must adjust the 1583402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron interrupt controller so that a CPU interrupt is not generated when the timer 1593402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron interrupt fires. 1601e57a46299244793beb27e74be171d1540606999oliviermartin 1611e57a46299244793beb27e74be171d1540606999oliviermartin @param This The EFI_TIMER_ARCH_PROTOCOL instance. 1621e57a46299244793beb27e74be171d1540606999oliviermartin @param TimerPeriod The rate to program the timer interrupt in 100 nS units. If 1631e57a46299244793beb27e74be171d1540606999oliviermartin the timer hardware is not programmable, then EFI_UNSUPPORTED is 1641e57a46299244793beb27e74be171d1540606999oliviermartin returned. If the timer is programmable, then the timer period 1651e57a46299244793beb27e74be171d1540606999oliviermartin will be rounded up to the nearest timer period that is supported 1661e57a46299244793beb27e74be171d1540606999oliviermartin by the timer hardware. If TimerPeriod is set to 0, then the 1671e57a46299244793beb27e74be171d1540606999oliviermartin timer interrupts will be disabled. 1681e57a46299244793beb27e74be171d1540606999oliviermartin 1691e57a46299244793beb27e74be171d1540606999oliviermartin 1701e57a46299244793beb27e74be171d1540606999oliviermartin @retval EFI_SUCCESS The timer period was changed. 1711e57a46299244793beb27e74be171d1540606999oliviermartin @retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt. 1721e57a46299244793beb27e74be171d1540606999oliviermartin @retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error. 1731e57a46299244793beb27e74be171d1540606999oliviermartin 1741e57a46299244793beb27e74be171d1540606999oliviermartin**/ 1751e57a46299244793beb27e74be171d1540606999oliviermartinEFI_STATUS 1761e57a46299244793beb27e74be171d1540606999oliviermartinEFIAPI 1771e57a46299244793beb27e74be171d1540606999oliviermartinTimerDriverSetTimerPeriod ( 1781e57a46299244793beb27e74be171d1540606999oliviermartin IN EFI_TIMER_ARCH_PROTOCOL *This, 1791e57a46299244793beb27e74be171d1540606999oliviermartin IN UINT64 TimerPeriod 1801e57a46299244793beb27e74be171d1540606999oliviermartin ) 1811e57a46299244793beb27e74be171d1540606999oliviermartin{ 1821e57a46299244793beb27e74be171d1540606999oliviermartin EFI_STATUS Status; 1831e57a46299244793beb27e74be171d1540606999oliviermartin UINT64 TimerCount; 1841e57a46299244793beb27e74be171d1540606999oliviermartin INT32 LoadValue; 1853402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 1861e57a46299244793beb27e74be171d1540606999oliviermartin if (TimerPeriod == 0) { 1871e57a46299244793beb27e74be171d1540606999oliviermartin // Turn off GPTIMER3 1881e57a46299244793beb27e74be171d1540606999oliviermartin MmioWrite32 (TCLR, TCLR_ST_OFF); 1893402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron 1903402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron Status = gInterrupt->DisableInterruptSource(gInterrupt, gVector); 1913402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron } else { 1921e57a46299244793beb27e74be171d1540606999oliviermartin // Calculate required timer count 1931e57a46299244793beb27e74be171d1540606999oliviermartin TimerCount = DivU64x32(TimerPeriod * 100, PcdGet32(PcdEmbeddedPerformanceCounterPeriodInNanoseconds)); 1941e57a46299244793beb27e74be171d1540606999oliviermartin 1951e57a46299244793beb27e74be171d1540606999oliviermartin // Set GPTIMER3 Load register 1961e57a46299244793beb27e74be171d1540606999oliviermartin LoadValue = (INT32) -TimerCount; 1971e57a46299244793beb27e74be171d1540606999oliviermartin MmioWrite32 (TLDR, LoadValue); 1981e57a46299244793beb27e74be171d1540606999oliviermartin MmioWrite32 (TCRR, LoadValue); 1991e57a46299244793beb27e74be171d1540606999oliviermartin 2001e57a46299244793beb27e74be171d1540606999oliviermartin // Enable Overflow interrupt 2011e57a46299244793beb27e74be171d1540606999oliviermartin MmioWrite32 (TIER, TIER_TCAR_IT_DISABLE | TIER_OVF_IT_ENABLE | TIER_MAT_IT_DISABLE); 2021e57a46299244793beb27e74be171d1540606999oliviermartin 2031e57a46299244793beb27e74be171d1540606999oliviermartin // Turn on GPTIMER3, it will reload at overflow 2041e57a46299244793beb27e74be171d1540606999oliviermartin MmioWrite32 (TCLR, TCLR_AR_AUTORELOAD | TCLR_ST_ON); 2051e57a46299244793beb27e74be171d1540606999oliviermartin 2063402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron Status = gInterrupt->EnableInterruptSource(gInterrupt, gVector); 2071e57a46299244793beb27e74be171d1540606999oliviermartin } 2081e57a46299244793beb27e74be171d1540606999oliviermartin 2091e57a46299244793beb27e74be171d1540606999oliviermartin // 2101e57a46299244793beb27e74be171d1540606999oliviermartin // Save the new timer period 2111e57a46299244793beb27e74be171d1540606999oliviermartin // 2121e57a46299244793beb27e74be171d1540606999oliviermartin mTimerPeriod = TimerPeriod; 2131e57a46299244793beb27e74be171d1540606999oliviermartin return Status; 2141e57a46299244793beb27e74be171d1540606999oliviermartin} 2151e57a46299244793beb27e74be171d1540606999oliviermartin 2161e57a46299244793beb27e74be171d1540606999oliviermartin 2171e57a46299244793beb27e74be171d1540606999oliviermartin/** 2183402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron This function retrieves the period of timer interrupts in 100 ns units, 2193402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod 2203402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is 2211e57a46299244793beb27e74be171d1540606999oliviermartin returned, then the timer is currently disabled. 2221e57a46299244793beb27e74be171d1540606999oliviermartin 2231e57a46299244793beb27e74be171d1540606999oliviermartin @param This The EFI_TIMER_ARCH_PROTOCOL instance. 2241e57a46299244793beb27e74be171d1540606999oliviermartin @param TimerPeriod A pointer to the timer period to retrieve in 100 ns units. If 2251e57a46299244793beb27e74be171d1540606999oliviermartin 0 is returned, then the timer is currently disabled. 2261e57a46299244793beb27e74be171d1540606999oliviermartin 2271e57a46299244793beb27e74be171d1540606999oliviermartin 2281e57a46299244793beb27e74be171d1540606999oliviermartin @retval EFI_SUCCESS The timer period was returned in TimerPeriod. 2291e57a46299244793beb27e74be171d1540606999oliviermartin @retval EFI_INVALID_PARAMETER TimerPeriod is NULL. 2301e57a46299244793beb27e74be171d1540606999oliviermartin 2311e57a46299244793beb27e74be171d1540606999oliviermartin**/ 2321e57a46299244793beb27e74be171d1540606999oliviermartinEFI_STATUS 2331e57a46299244793beb27e74be171d1540606999oliviermartinEFIAPI 2341e57a46299244793beb27e74be171d1540606999oliviermartinTimerDriverGetTimerPeriod ( 2351e57a46299244793beb27e74be171d1540606999oliviermartin IN EFI_TIMER_ARCH_PROTOCOL *This, 2361e57a46299244793beb27e74be171d1540606999oliviermartin OUT UINT64 *TimerPeriod 2371e57a46299244793beb27e74be171d1540606999oliviermartin ) 2381e57a46299244793beb27e74be171d1540606999oliviermartin{ 2391e57a46299244793beb27e74be171d1540606999oliviermartin if (TimerPeriod == NULL) { 2401e57a46299244793beb27e74be171d1540606999oliviermartin return EFI_INVALID_PARAMETER; 2411e57a46299244793beb27e74be171d1540606999oliviermartin } 2421e57a46299244793beb27e74be171d1540606999oliviermartin 2431e57a46299244793beb27e74be171d1540606999oliviermartin *TimerPeriod = mTimerPeriod; 2441e57a46299244793beb27e74be171d1540606999oliviermartin return EFI_SUCCESS; 2451e57a46299244793beb27e74be171d1540606999oliviermartin} 2461e57a46299244793beb27e74be171d1540606999oliviermartin 2471e57a46299244793beb27e74be171d1540606999oliviermartin/** 2483402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron This function generates a soft timer interrupt. If the platform does not support soft 2493402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned. 2503402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler() 2513402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron service, then a soft timer interrupt will be generated. If the timer interrupt is 2523402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron enabled when this service is called, then the registered handler will be invoked. The 2533402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron registered handler should not be able to distinguish a hardware-generated timer 2541e57a46299244793beb27e74be171d1540606999oliviermartin interrupt from a software-generated timer interrupt. 2551e57a46299244793beb27e74be171d1540606999oliviermartin 2561e57a46299244793beb27e74be171d1540606999oliviermartin @param This The EFI_TIMER_ARCH_PROTOCOL instance. 2571e57a46299244793beb27e74be171d1540606999oliviermartin 2581e57a46299244793beb27e74be171d1540606999oliviermartin @retval EFI_SUCCESS The soft timer interrupt was generated. 2591e57a46299244793beb27e74be171d1540606999oliviermartin @retval EFI_UNSUPPORTED The platform does not support the generation of soft timer interrupts. 2601e57a46299244793beb27e74be171d1540606999oliviermartin 2611e57a46299244793beb27e74be171d1540606999oliviermartin**/ 2621e57a46299244793beb27e74be171d1540606999oliviermartinEFI_STATUS 2631e57a46299244793beb27e74be171d1540606999oliviermartinEFIAPI 2641e57a46299244793beb27e74be171d1540606999oliviermartinTimerDriverGenerateSoftInterrupt ( 2651e57a46299244793beb27e74be171d1540606999oliviermartin IN EFI_TIMER_ARCH_PROTOCOL *This 2661e57a46299244793beb27e74be171d1540606999oliviermartin ) 2671e57a46299244793beb27e74be171d1540606999oliviermartin{ 2681e57a46299244793beb27e74be171d1540606999oliviermartin return EFI_UNSUPPORTED; 2691e57a46299244793beb27e74be171d1540606999oliviermartin} 2701e57a46299244793beb27e74be171d1540606999oliviermartin 2711e57a46299244793beb27e74be171d1540606999oliviermartin 2721e57a46299244793beb27e74be171d1540606999oliviermartin/** 2731e57a46299244793beb27e74be171d1540606999oliviermartin Interface stucture for the Timer Architectural Protocol. 2741e57a46299244793beb27e74be171d1540606999oliviermartin 2751e57a46299244793beb27e74be171d1540606999oliviermartin @par Protocol Description: 2763402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron This protocol provides the services to initialize a periodic timer 2771e57a46299244793beb27e74be171d1540606999oliviermartin interrupt, and to register a handler that is called each time the timer 2781e57a46299244793beb27e74be171d1540606999oliviermartin interrupt fires. It may also provide a service to adjust the rate of the 2793402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron periodic timer interrupt. When a timer interrupt occurs, the handler is 2803402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron passed the amount of time that has passed since the previous timer 2811e57a46299244793beb27e74be171d1540606999oliviermartin interrupt. 2821e57a46299244793beb27e74be171d1540606999oliviermartin 2831e57a46299244793beb27e74be171d1540606999oliviermartin @param RegisterHandler 2843402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron Registers a handler that will be called each time the 2853402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron timer interrupt fires. TimerPeriod defines the minimum 2863402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron time between timer interrupts, so TimerPeriod will also 2873402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron be the minimum time between calls to the registered 2881e57a46299244793beb27e74be171d1540606999oliviermartin handler. 2891e57a46299244793beb27e74be171d1540606999oliviermartin 2901e57a46299244793beb27e74be171d1540606999oliviermartin @param SetTimerPeriod 2913402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron Sets the period of the timer interrupt in 100 nS units. 2923402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron This function is optional, and may return EFI_UNSUPPORTED. 2933402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron If this function is supported, then the timer period will 2941e57a46299244793beb27e74be171d1540606999oliviermartin be rounded up to the nearest supported timer period. 2951e57a46299244793beb27e74be171d1540606999oliviermartin 2961e57a46299244793beb27e74be171d1540606999oliviermartin 2971e57a46299244793beb27e74be171d1540606999oliviermartin @param GetTimerPeriod 2981e57a46299244793beb27e74be171d1540606999oliviermartin Retrieves the period of the timer interrupt in 100 nS units. 2991e57a46299244793beb27e74be171d1540606999oliviermartin 3001e57a46299244793beb27e74be171d1540606999oliviermartin @param GenerateSoftInterrupt 3013402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron Generates a soft timer interrupt that simulates the firing of 3023402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron the timer interrupt. This service can be used to invoke the registered handler if the timer interrupt has been masked for 3031e57a46299244793beb27e74be171d1540606999oliviermartin a period of time. 3041e57a46299244793beb27e74be171d1540606999oliviermartin 3051e57a46299244793beb27e74be171d1540606999oliviermartin**/ 3061e57a46299244793beb27e74be171d1540606999oliviermartinEFI_TIMER_ARCH_PROTOCOL gTimer = { 3071e57a46299244793beb27e74be171d1540606999oliviermartin TimerDriverRegisterHandler, 3081e57a46299244793beb27e74be171d1540606999oliviermartin TimerDriverSetTimerPeriod, 3091e57a46299244793beb27e74be171d1540606999oliviermartin TimerDriverGetTimerPeriod, 3101e57a46299244793beb27e74be171d1540606999oliviermartin TimerDriverGenerateSoftInterrupt 3111e57a46299244793beb27e74be171d1540606999oliviermartin}; 3121e57a46299244793beb27e74be171d1540606999oliviermartin 3131e57a46299244793beb27e74be171d1540606999oliviermartin 3141e57a46299244793beb27e74be171d1540606999oliviermartin/** 3151e57a46299244793beb27e74be171d1540606999oliviermartin Initialize the state information for the Timer Architectural Protocol and 3161e57a46299244793beb27e74be171d1540606999oliviermartin the Timer Debug support protocol that allows the debugger to break into a 3171e57a46299244793beb27e74be171d1540606999oliviermartin running program. 3181e57a46299244793beb27e74be171d1540606999oliviermartin 3191e57a46299244793beb27e74be171d1540606999oliviermartin @param ImageHandle of the loaded driver 3201e57a46299244793beb27e74be171d1540606999oliviermartin @param SystemTable Pointer to the System Table 3211e57a46299244793beb27e74be171d1540606999oliviermartin 3221e57a46299244793beb27e74be171d1540606999oliviermartin @retval EFI_SUCCESS Protocol registered 3231e57a46299244793beb27e74be171d1540606999oliviermartin @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure 3241e57a46299244793beb27e74be171d1540606999oliviermartin @retval EFI_DEVICE_ERROR Hardware problems 3251e57a46299244793beb27e74be171d1540606999oliviermartin 3261e57a46299244793beb27e74be171d1540606999oliviermartin**/ 3271e57a46299244793beb27e74be171d1540606999oliviermartinEFI_STATUS 3281e57a46299244793beb27e74be171d1540606999oliviermartinEFIAPI 3291e57a46299244793beb27e74be171d1540606999oliviermartinTimerInitialize ( 3301e57a46299244793beb27e74be171d1540606999oliviermartin IN EFI_HANDLE ImageHandle, 3311e57a46299244793beb27e74be171d1540606999oliviermartin IN EFI_SYSTEM_TABLE *SystemTable 3321e57a46299244793beb27e74be171d1540606999oliviermartin ) 3331e57a46299244793beb27e74be171d1540606999oliviermartin{ 3341e57a46299244793beb27e74be171d1540606999oliviermartin EFI_HANDLE Handle = NULL; 3351e57a46299244793beb27e74be171d1540606999oliviermartin EFI_STATUS Status; 3361e57a46299244793beb27e74be171d1540606999oliviermartin UINT32 TimerBaseAddress; 3371e57a46299244793beb27e74be171d1540606999oliviermartin 3381e57a46299244793beb27e74be171d1540606999oliviermartin // Find the interrupt controller protocol. ASSERT if not found. 3391e57a46299244793beb27e74be171d1540606999oliviermartin Status = gBS->LocateProtocol (&gHardwareInterruptProtocolGuid, NULL, (VOID **)&gInterrupt); 3401e57a46299244793beb27e74be171d1540606999oliviermartin ASSERT_EFI_ERROR (Status); 3411e57a46299244793beb27e74be171d1540606999oliviermartin 3421e57a46299244793beb27e74be171d1540606999oliviermartin // Set up the timer registers 3431e57a46299244793beb27e74be171d1540606999oliviermartin TimerBaseAddress = TimerBase (FixedPcdGet32(PcdOmap35xxArchTimer)); 3441e57a46299244793beb27e74be171d1540606999oliviermartin TISR = TimerBaseAddress + GPTIMER_TISR; 3451e57a46299244793beb27e74be171d1540606999oliviermartin TCLR = TimerBaseAddress + GPTIMER_TCLR; 3461e57a46299244793beb27e74be171d1540606999oliviermartin TLDR = TimerBaseAddress + GPTIMER_TLDR; 3471e57a46299244793beb27e74be171d1540606999oliviermartin TCRR = TimerBaseAddress + GPTIMER_TCRR; 3481e57a46299244793beb27e74be171d1540606999oliviermartin TIER = TimerBaseAddress + GPTIMER_TIER; 3491e57a46299244793beb27e74be171d1540606999oliviermartin 3501e57a46299244793beb27e74be171d1540606999oliviermartin // Disable the timer 3511e57a46299244793beb27e74be171d1540606999oliviermartin Status = TimerDriverSetTimerPeriod (&gTimer, 0); 3521e57a46299244793beb27e74be171d1540606999oliviermartin ASSERT_EFI_ERROR (Status); 3531e57a46299244793beb27e74be171d1540606999oliviermartin 3541e57a46299244793beb27e74be171d1540606999oliviermartin // Install interrupt handler 3551e57a46299244793beb27e74be171d1540606999oliviermartin gVector = InterruptVectorForTimer (FixedPcdGet32(PcdOmap35xxArchTimer)); 3561e57a46299244793beb27e74be171d1540606999oliviermartin Status = gInterrupt->RegisterInterruptSource (gInterrupt, gVector, TimerInterruptHandler); 3571e57a46299244793beb27e74be171d1540606999oliviermartin ASSERT_EFI_ERROR (Status); 3581e57a46299244793beb27e74be171d1540606999oliviermartin 3591e57a46299244793beb27e74be171d1540606999oliviermartin // Turn on the functional clock for Timer 3601e57a46299244793beb27e74be171d1540606999oliviermartin MmioOr32 (CM_FCLKEN_PER, CM_FCLKEN_PER_EN_GPT3_ENABLE); 3611e57a46299244793beb27e74be171d1540606999oliviermartin 3621e57a46299244793beb27e74be171d1540606999oliviermartin // Set up default timer 3631e57a46299244793beb27e74be171d1540606999oliviermartin Status = TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32(PcdTimerPeriod)); 3641e57a46299244793beb27e74be171d1540606999oliviermartin ASSERT_EFI_ERROR (Status); 3651e57a46299244793beb27e74be171d1540606999oliviermartin 3661e57a46299244793beb27e74be171d1540606999oliviermartin // Install the Timer Architectural Protocol onto a new handle 3671e57a46299244793beb27e74be171d1540606999oliviermartin Status = gBS->InstallMultipleProtocolInterfaces ( 3681e57a46299244793beb27e74be171d1540606999oliviermartin &Handle, 3691e57a46299244793beb27e74be171d1540606999oliviermartin &gEfiTimerArchProtocolGuid, &gTimer, 3701e57a46299244793beb27e74be171d1540606999oliviermartin NULL 3711e57a46299244793beb27e74be171d1540606999oliviermartin ); 3721e57a46299244793beb27e74be171d1540606999oliviermartin ASSERT_EFI_ERROR(Status); 3731e57a46299244793beb27e74be171d1540606999oliviermartin 3741e57a46299244793beb27e74be171d1540606999oliviermartin return Status; 3751e57a46299244793beb27e74be171d1540606999oliviermartin} 3761e57a46299244793beb27e74be171d1540606999oliviermartin 377