/** @file Debug Agent timer lib for OMAP 35xx. Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR> 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 <Base.h> #include <Library/BaseLib.h> #include <Library/IoLib.h> #include <Library/OmapLib.h> #include <Library/ArmLib.h> #include <Library/PcdLib.h> #include <Omap3530/Omap3530.h> volatile UINT32 gVector; // Cached registers volatile UINT32 gTISR; volatile UINT32 gTCLR; volatile UINT32 gTLDR; volatile UINT32 gTCRR; volatile UINT32 gTIER; VOID EnableInterruptSource ( VOID ) { UINTN Bank; UINTN Bit; // Map vector to FIQ, IRQ is default MmioWrite32 (INTCPS_ILR (gVector), 1); Bank = gVector / 32; Bit = 1UL << (gVector % 32); MmioWrite32 (INTCPS_MIR_CLEAR(Bank), Bit); } VOID DisableInterruptSource ( VOID ) { UINTN Bank; UINTN Bit; Bank = gVector / 32; Bit = 1UL << (gVector % 32); MmioWrite32 (INTCPS_MIR_SET(Bank), Bit); } /** Setup all the hardware needed for the debug agents timer. This function is used to set up debug enviroment. It may enable interrupts. **/ VOID EFIAPI DebugAgentTimerIntialize ( VOID ) { UINT32 TimerBaseAddress; UINT32 TimerNumber; TimerNumber = PcdGet32(PcdOmap35xxDebugAgentTimer); gVector = InterruptVectorForTimer (TimerNumber); // Set up the timer registers TimerBaseAddress = TimerBase (TimerNumber); gTISR = TimerBaseAddress + GPTIMER_TISR; gTCLR = TimerBaseAddress + GPTIMER_TCLR; gTLDR = TimerBaseAddress + GPTIMER_TLDR; gTCRR = TimerBaseAddress + GPTIMER_TCRR; gTIER = TimerBaseAddress + GPTIMER_TIER; if ((TimerNumber < 2) || (TimerNumber > 9)) { // This code assumes one the General Purpose timers is used // GPT2 - GPT9 CpuDeadLoop (); } // Set source clock for GPT2 - GPT9 to SYS_CLK MmioOr32 (CM_CLKSEL_PER, 1 << (TimerNumber - 2)); } /** Set the period for the debug agent timer. Zero means disable the timer. @param[in] TimerPeriodMilliseconds Frequency of the debug agent timer. **/ VOID EFIAPI DebugAgentTimerSetPeriod ( IN UINT32 TimerPeriodMilliseconds ) { UINT64 TimerCount; INT32 LoadValue; if (TimerPeriodMilliseconds == 0) { // Turn off GPTIMER3 MmioWrite32 (gTCLR, TCLR_ST_OFF); DisableInterruptSource (); } else { // Calculate required timer count TimerCount = DivU64x32(TimerPeriodMilliseconds * 1000000, PcdGet32(PcdDebugAgentTimerFreqNanoSeconds)); // Set GPTIMER5 Load register LoadValue = (INT32) -TimerCount; MmioWrite32 (gTLDR, LoadValue); MmioWrite32 (gTCRR, LoadValue); // Enable Overflow interrupt MmioWrite32 (gTIER, TIER_TCAR_IT_DISABLE | TIER_OVF_IT_ENABLE | TIER_MAT_IT_DISABLE); // Turn on GPTIMER3, it will reload at overflow MmioWrite32 (gTCLR, TCLR_AR_AUTORELOAD | TCLR_ST_ON); EnableInterruptSource (); } } /** Perform End Of Interrupt for the debug agent timer. This is called in the interrupt handler after the interrupt has been processed. **/ VOID EFIAPI DebugAgentTimerEndOfInterrupt ( VOID ) { // Clear all timer interrupts MmioWrite32 (gTISR, TISR_CLEAR_ALL); // Poll interrupt status bits to ensure clearing while ((MmioRead32 (gTISR) & TISR_ALL_INTERRUPT_MASK) != TISR_NO_INTERRUPTS_PENDING); MmioWrite32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWFIQAGR); ArmDataSynchronizationBarrier (); }