X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=ArmPlatformPkg%2FDrivers%2FSP804TimerDxe%2FSP804Timer.c;h=71b7a32d6d8e3384e0bb44173f2cfcb0a62dc223;hp=a28a045352cf5c6a864e23a424e78654b8236820;hb=0db25ccc6cf1d05dc6b8fd9b07d033b40c387c88;hpb=e100fa8c1e5218865ff6f2c5dd646c2e6ceca49d diff --git a/ArmPlatformPkg/Drivers/SP804TimerDxe/SP804Timer.c b/ArmPlatformPkg/Drivers/SP804TimerDxe/SP804Timer.c index a28a045352..71b7a32d6d 100644 --- a/ArmPlatformPkg/Drivers/SP804TimerDxe/SP804Timer.c +++ b/ArmPlatformPkg/Drivers/SP804TimerDxe/SP804Timer.c @@ -2,6 +2,7 @@ Template for Timer Architecture Protocol driver of the ARM flavor Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ Copyright (c) 2011 - 2012, 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 @@ -28,14 +29,17 @@ #include #include -#include + +#define SP804_TIMER_PERIODIC_BASE ((UINTN)PcdGet32 (PcdSP804TimerPeriodicBase)) +#define SP804_TIMER_METRONOME_BASE ((UINTN)PcdGet32 (PcdSP804TimerMetronomeBase)) +#define SP804_TIMER_PERFORMANCE_BASE ((UINTN)PcdGet32 (PcdSP804TimerPerformanceBase)) // The notification function to call on every timer interrupt. -volatile EFI_TIMER_NOTIFY mTimerNotifyFunction = (EFI_TIMER_NOTIFY)NULL; -EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL; +EFI_TIMER_NOTIFY mTimerNotifyFunction = (EFI_TIMER_NOTIFY)NULL; +EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL; // The current period of the timer interrupt -volatile UINT64 mTimerPeriod = 0; +UINT64 mTimerPeriod = 0; // Cached copy of the Hardware Interrupt protocol instance EFI_HARDWARE_INTERRUPT_PROTOCOL *gInterrupt = NULL; @@ -43,7 +47,6 @@ EFI_HARDWARE_INTERRUPT_PROTOCOL *gInterrupt = NULL; // Cached interrupt vector UINTN gVector; -UINT32 mLastTickCount; /** @@ -75,11 +78,11 @@ TimerInterruptHandler ( OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL); // If the interrupt is shared then we must check if this interrupt source is the one associated to this Timer - if (MmioRead32 (SP804_TIMER0_BASE + SP804_TIMER_MSK_INT_STS_REG) != 0) { - // clear the periodic interrupt - MmioWrite32 (SP804_TIMER0_BASE + SP804_TIMER_INT_CLR_REG, 0); + if (MmioRead32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_MSK_INT_STS_REG) != 0) { + // Clear the periodic interrupt + MmioWrite32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_INT_CLR_REG, 0); - // signal end of interrupt early to help avoid losing subsequent ticks from long duration handlers + // Signal end of interrupt early to help avoid losing subsequent ticks from long duration handlers gInterrupt->EndOfInterrupt (gInterrupt, Source); if (mTimerNotifyFunction) { @@ -139,7 +142,7 @@ TimerDriverRegisterHandler ( } /** - Make sure all ArrmVe Timers are disabled + Make sure all Dual Timers are disabled **/ VOID EFIAPI @@ -148,25 +151,20 @@ ExitBootServicesEvent ( IN VOID *Context ) { - // Disable timer 0 if enabled - if (MmioRead32(SP804_TIMER0_BASE + SP804_TIMER_CONTROL_REG) & SP804_TIMER_CTRL_ENABLE) { - MmioAnd32 (SP804_TIMER0_BASE + SP804_TIMER_CONTROL_REG, 0); - } - - // Disable timer 1 if enabled - if (MmioRead32(SP804_TIMER1_BASE + SP804_TIMER_CONTROL_REG) & SP804_TIMER_CTRL_ENABLE) { - MmioAnd32 (SP804_TIMER1_BASE + SP804_TIMER_CONTROL_REG, 0); - } + // Disable 'Periodic Operation' timer if enabled + if (MmioRead32(SP804_TIMER_PERIODIC_BASE + SP804_TIMER_CONTROL_REG) & SP804_TIMER_CTRL_ENABLE) { + MmioAnd32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_CONTROL_REG, 0); + } - // Disable timer 2 if enabled - if (MmioRead32(SP804_TIMER2_BASE + SP804_TIMER_CONTROL_REG) & SP804_TIMER_CTRL_ENABLE) { - MmioAnd32 (SP804_TIMER2_BASE + SP804_TIMER_CONTROL_REG, 0); - } + // Disable 'Metronome/Delay' timer if enabled + if (MmioRead32(SP804_TIMER_METRONOME_BASE + SP804_TIMER_CONTROL_REG) & SP804_TIMER_CTRL_ENABLE) { + MmioAnd32 (SP804_TIMER_METRONOME_BASE + SP804_TIMER_CONTROL_REG, 0); + } - // Disable timer 3 if enabled - if (MmioRead32(SP804_TIMER3_BASE + SP804_TIMER_CONTROL_REG) & SP804_TIMER_CTRL_ENABLE) { - MmioAnd32 (SP804_TIMER3_BASE + SP804_TIMER_CONTROL_REG, 0); - } + // Disable 'Performance' timer if enabled + if (MmioRead32(SP804_TIMER_PERFORMANCE_BASE + SP804_TIMER_CONTROL_REG) & SP804_TIMER_CTRL_ENABLE) { + MmioAnd32 (SP804_TIMER_PERFORMANCE_BASE + SP804_TIMER_CONTROL_REG, 0); + } } /** @@ -208,29 +206,28 @@ TimerDriverSetTimerPeriod ( UINT64 TimerTicks; // always disable the timer - MmioAnd32 (SP804_TIMER0_BASE + SP804_TIMER_CONTROL_REG, ~SP804_TIMER_CTRL_ENABLE); + MmioAnd32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_CONTROL_REG, ~SP804_TIMER_CTRL_ENABLE); if (TimerPeriod == 0) { - // leave timer disabled from above, and... + // Leave timer disabled from above, and... - // disable timer 0/1 interrupt for a TimerPeriod of 0 + // Disable timer 0/1 interrupt for a TimerPeriod of 0 Status = gInterrupt->DisableInterruptSource (gInterrupt, gVector); } else { - // Convert TimerPeriod into 1MHz clock counts (us units = 100ns units / 10) + // Convert TimerPeriod into 1MHz clock counts (us units = 100ns units * 10) TimerTicks = DivU64x32 (TimerPeriod, 10); + TimerTicks = MultU64x32 (TimerTicks, PcdGet32(PcdSP804TimerFrequencyInMHz)); // if it's larger than 32-bits, pin to highest value if (TimerTicks > 0xffffffff) { - TimerTicks = 0xffffffff; - } // Program the SP804 timer with the new count value - MmioWrite32 (SP804_TIMER0_BASE + SP804_TIMER_LOAD_REG, TimerTicks); + MmioWrite32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_LOAD_REG, TimerTicks); // enable the timer - MmioOr32 (SP804_TIMER0_BASE + SP804_TIMER_CONTROL_REG, SP804_TIMER_CTRL_ENABLE); + MmioOr32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_CONTROL_REG, SP804_TIMER_CTRL_ENABLE); // enable timer 0/1 interrupts Status = gInterrupt->EnableInterruptSource (gInterrupt, gVector); @@ -360,36 +357,23 @@ TimerInitialize ( EFI_HANDLE Handle = NULL; EFI_STATUS Status; + // Set the interrupt timer number + gVector = PcdGet32(PcdSP804TimerPeriodicInterruptNum); + // Find the interrupt controller protocol. ASSERT if not found. Status = gBS->LocateProtocol (&gHardwareInterruptProtocolGuid, NULL, (VOID **)&gInterrupt); ASSERT_EFI_ERROR (Status); - // Configure 1MHz clock - MmioOr32 (SP810_CTRL_BASE + SP810_SYS_CTRL_REG, SP810_SYS_CTRL_TIMER1_TIMCLK); - - // configure timer 1 for free running operation, 32 bits, no prescaler, interrupt disabled - MmioWrite32 (SP804_TIMER1_BASE + SP804_TIMER_CONTROL_REG, SP804_TIMER_CTRL_32BIT | SP804_PRESCALE_DIV_1); - - // enable the free running timer - MmioOr32 (SP804_TIMER1_BASE + SP804_TIMER_CONTROL_REG, SP804_TIMER_CTRL_ENABLE); - - // record free running tick value (should be close to 0xffffffff) - mLastTickCount = MmioRead32 (SP804_TIMER1_BASE + SP804_TIMER_CURRENT_REG); - // Disable the timer Status = TimerDriverSetTimerPeriod (&gTimer, 0); ASSERT_EFI_ERROR (Status); // Install interrupt handler - gVector = TIMER01_INTERRUPT_NUM; Status = gInterrupt->RegisterInterruptSource (gInterrupt, gVector, TimerInterruptHandler); ASSERT_EFI_ERROR (Status); - // configure periodic timer (TIMER0) for 1MHz operation - MmioOr32 (SP810_CTRL_BASE + SP810_SYS_CTRL_REG, SP810_SYS_CTRL_TIMER0_TIMCLK); - // configure timer 0 for periodic operation, 32 bits, no prescaler, and interrupt enabled - MmioWrite32 (SP804_TIMER0_BASE + SP804_TIMER_CONTROL_REG, SP804_TIMER_CTRL_PERIODIC | SP804_TIMER_CTRL_32BIT | SP804_PRESCALE_DIV_1 | SP804_TIMER_CTRL_INT_ENABLE); + MmioWrite32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_CONTROL_REG, SP804_TIMER_CTRL_PERIODIC | SP804_TIMER_CTRL_32BIT | SP804_PRESCALE_DIV_1 | SP804_TIMER_CTRL_INT_ENABLE); // Set up default timer Status = TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32(PcdTimerPeriod)); // TIMER_DEFAULT_PERIOD