//-----------------------------------------------------------------------------
//
//  Copyright (C) 2004-2007, Freescale Semiconductor, Inc. All Rights Reserved.
//  THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
//  AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//-----------------------------------------------------------------------------
//
//  Module: timer.c
//
//  This module provides the BSP-specific interfaces required to support
//  the PQOAL timer code.
//
//-----------------------------------------------------------------------------

#include <bsp.h>

extern void OALCPUEnterWFI(void);
extern VOID OALClockSetGatingMode(DDK_CLOCK_GATE_INDEX index, 
    DDK_CLOCK_GATE_MODE mode);

extern PCSP_AVIC_REGS g_pAVIC;
//extern PCSP_PBC_REGS  g_pPBC;
extern UINT32         g_SREV;
extern PCSP_CCM_REGS  g_pCCM;
extern PCSP_UART_REG g_pUART;

//-----------------------------------------------------------------------------
//
//  Function: OALTimerGetClkSrc
//
//  This function returns the clock source setting used to program the EPIT_CR
//  CLKSRC bits.
//
//  Parameters:
//      None.
//
//  Returns:
//      EPIT clock source selection.
//
//-----------------------------------------------------------------------------
UINT32 OALTimerGetClkSrc(void)
{
    return BSP_SYSTIMER_CLKSRC;
}


//-----------------------------------------------------------------------------
//
//  Function: OALTimerGetClkPrescalar
//
//  This function returns the clock prescalar used to program the EPIT_CR
//  PRESCALER bits.
//
//  Parameters:
//      None.
//
//  Returns:
//      EPIT prescalar.
//
//-----------------------------------------------------------------------------
UINT32 OALTimerGetClkPrescalar(void)
{
    return BSP_SYSTIMER_PRESCALAR;
}


//-----------------------------------------------------------------------------
//
//  Function: OALTimerGetClkFreq
//
//  This function returns the frequency of the EPIT input clock.
//
//  Parameters:
//      None.
//
//  Returns:
//      EPIT input clock.
//
//-----------------------------------------------------------------------------
UINT32 OALTimerGetClkFreq(void)
{
#if (BSP_SYSTIMER_CLKSRC == EPIT_CR_CLKSRC_CKIL)
    return BSP_CLK_CKIL_FREQ;
#else
    BSP_ARGS *pBspArgs = (BSP_ARGS *)IMAGE_SHARE_ARGS_UA_START;

    return pBspArgs->clockFreq[DDK_CLOCK_SIGNAL_PER];
#endif
}


//-----------------------------------------------------------------------------
//
//  Function: OALCPUIdle
//
//  This function puts the CPU or SOC in idle state. The CPU or SOC 
//  should exit the idle state when an interrupt occurs. This function is 
//  called with interrupts are disabled. When this function returns, interrupts 
//  must be disabled also.
//
//  Parameters:
//      None.
//
//  Returns:
//      None.
//
//-----------------------------------------------------------------------------
VOID OALCPUIdle()
{
#if BSP_DEBUG_SERIAL_PM
#if (DEBUG_PORT == DBG_UART1)
    // Check if we can gate off debug UART1 clocks
    if(INREG32(&g_pUART->USR2) & CSP_BITFMASK(UART_USR2_TXDC))
    {
        CLRREG32(&g_pCCM->CGR[0], CCM_CGR0_UART1_MASK);
    }
#endif

#if (DEBUG_PORT == DBG_UART3)
    // Check if we can gate off debug UART3 clocks
    if(INREG32(&g_pUART->USR2) & CSP_BITFMASK(UART_USR2_TXDC))
    {
        CLRREG32(&g_pCCM->CGR[1], CCM_CGR1_UART3_MASK);
    }
#endif
#endif

#ifndef IMGFLASH
    // Clock gate the WEIM while we are in wait mode
   // CLRREG32(&g_pCCM->CGR[2], CCM_CGR2_WEIM_MASK);
#endif    

   // Turn Off Debug LED
   OEMWriteDebugLED(RUNNING_INDICATOR_DLED_INDEX, 0);
   
#ifdef BSP_FAKE_IDLE

    // Wait until AVIC reports an interrupt is pending
    while((!INREG32(&g_pAVIC->NIPNDH)) && (!INREG32(&g_pAVIC->NIPNDL)));

#else

    // Enter wait-for-interrupt mode
    OALCPUEnterWFI();

#endif
   
   // Turn On Debug LED
   OEMWriteDebugLED(RUNNING_INDICATOR_DLED_INDEX, 1);

    // Restore WEIM clocks
    //SETREG32(&g_pCCM->CGR[2], CCM_CGR2_WEIM_MASK);
}


//-----------------------------------------------------------------------------
//
//  Function: OALWdogGetConfig
//
//  This function provides the watchdog timer configuration.
//
//  Parameters:
//      None.
//
//  Returns:
//      Watchdog configuration.
//
//-----------------------------------------------------------------------------
UINT16 OALWdogGetConfig()
{
    // Enable watchdog clocks
    OALClockSetGatingMode(DDK_CLOCK_GATE_INDEX_WDOG, DDK_CLOCK_GATE_MODE_ENABLED_ALL);
    
    // Upper layers will configure watchdog timeout (WT field) and enable
    // the watchdog (WE) field.  Other bits in WCR are configured as follows:
    //
    //  WDW = continue timer operation in low-power wait mode
    //  WOE = tri-state WDOG output pin
    //  WDA = no software assertion of WDOG output pin
    //  SRS = no software reset of WDOG
    //  WRE = generate reset signal upon watchdog timeout
    //  WDE = disable watchdog (will be enabled after configuration)
    //  WDBG = suspend timer operation in debug mode
    //  WDZST = suspend timer operation in low-power stop mode
    return  CSP_BITFVAL(WDOG_WCR_WOE, WDOG_WCR_WOE_TRISTATE) |
            CSP_BITFVAL(WDOG_WCR_WDA, WDOG_WCR_WDA_NOEFFECT) |
            CSP_BITFVAL(WDOG_WCR_SRS, WDOG_WCR_SRS_NOEFFECT) |
            CSP_BITFVAL(WDOG_WCR_WRE, WDOG_WCR_WRE_SIG_RESET) |
            CSP_BITFVAL(WDOG_WCR_WDE, WDOG_WCR_WDE_DISABLE) |
            CSP_BITFVAL(WDOG_WCR_WDBG, WDOG_WCR_WDBG_SUSPEND) |
            CSP_BITFVAL(WDOG_WCR_WDZST, WDOG_WCR_WDZST_SUSPEND);
}

