//------------------------------------------------------------------------------
//
// Copyright (C) 2006-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
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
//
//  File:  bspgpt.c
//
//  Provides BSP-specific configuration routines for the GPT peripheral.
//
//------------------------------------------------------------------------------

#pragma warning(push)
#pragma warning(disable: 4115 4201 4204 4214)
#include <windows.h>
#pragma warning(pop)

#include "gpt_priv.h"
#include "bsp.h"

//------------------------------------------------------------------------------
// External Functions


//------------------------------------------------------------------------------
// External Variables


//------------------------------------------------------------------------------
// Defines
#define GPT_CLKSRC_FREQ_H     BSP_CLK_CKIH_FREQ
#define GPT_CLKSRC_FREQ_L     BSP_CLK_CKIL_FREQ
#define TICKS_PER_S_H         GPT_CLKSRC_FREQ_H            // ticks per microsecond
#define TICKS_PER_S_L         GPT_CLKSRC_FREQ_L            // ticks per second

#define GPT_CLKSRC_VAL_NO       GPT_CR_CLKSRC_NOCLK
#define GPT_CLKSRC_VAL_IPG      GPT_CR_CLKSRC_IPGCLK
#define GPT_CLKSRC_VAL_HIGH     GPT_CR_CLKSRC_HIGHFREQ  // use high freq
#define GPT_CLKSRC_VAL_EXT      GPT_CR_CLKSRC_EXTCLK
#define GPT_CLKSRC_VAL_32K      GPT_CR_CLKSRC_CLK32K

#define ADJUST_VAL_H 390500
#define ADJUST_VAL_L 1000000


//------------------------------------------------------------------------------
// Types


//------------------------------------------------------------------------------
// Global Variables


//------------------------------------------------------------------------------
// Local Variables
static timerSrc_c g_clkSrc = GPT_HIGHCLK;

//------------------------------------------------------------------------------
// Local Functions

//------------------------------------------------------------------------------
//
// Function: BSPGptGetClockSource
//
// This function returns the BSP-specific clock
// source selection value for the GPT.
//
// Parameters:
//      None
//
// Returns:
//      The clock source for the GPT.
//
//------------------------------------------------------------------------------
UINT32 BSPGptGetClockSource()
{
    switch (g_clkSrc)
    {
        case GPT_NOCLK:
            return GPT_CLKSRC_VAL_NO;
        case GPT_IPGCLK:
            return GPT_CLKSRC_VAL_IPG;
        case GPT_HIGHCLK:
            return GPT_CLKSRC_VAL_HIGH;
        case GPT_EXTCLK:
            return GPT_CLKSRC_VAL_EXT;
        case GPT_32KCLK:
            return GPT_CLKSRC_VAL_32K;
        default:
            return GPT_CLKSRC_VAL_HIGH;
    }
}

//------------------------------------------------------------------------------
//
// Function: BSPCalculateCompareVal
//
// This function computes the tick value that should go
// into the GPT output compare register to achieve
// a requested timer delay period.
//
// Parameters:
//      period
//          [in] The desired timer delay period, in microseconds.
//
// Returns:
//      The value to go into the GPT output compare register.
//
//------------------------------------------------------------------------------
UINT32 BSPGptCalculateCompareVal(UINT32 period)
{
    switch (g_clkSrc)
    {
        case GPT_NOCLK:
        case GPT_IPGCLK:
        case GPT_HIGHCLK:
        case GPT_EXTCLK:
            return (UINT32)(((double)period * TICKS_PER_S_H ) / ADJUST_VAL_H);
        case GPT_32KCLK:
            return (UINT32)(((double)period * TICKS_PER_S_L) / ADJUST_VAL_L);
        default:
            return (UINT32)(((double)period * TICKS_PER_S_H ) / ADJUST_VAL_H);
    }
}

//------------------------------------------------------------------------------
//
// Function: BSPGptChangeClockSource
//
// This function changes the GPT clock source
//
// Parameters:
//     pSetSrcPkt 
//          [in] The desired timer source
//
// Returns:
//     NA
//
//------------------------------------------------------------------------------
void BSPGptChangeClockSource(PGPT_TIMER_SRC_PKT pSetSrcPkt)
{
    g_clkSrc = pSetSrcPkt->timerSrc;
    return;
}

//------------------------------------------------------------------------------
//
// Function: BSPGptShowClockSource
//
// This function shows the current clock source
//
// Parameters:
//     NA
//
// Returns:
//     NA
//
//------------------------------------------------------------------------------
extern void BSPGptShowClockSource(void)
{
    switch (g_clkSrc)
    {
        case GPT_NOCLK:
            RETAILMSG(1, (L"Clk Source is NO\r\n"));
            break;
        case GPT_IPGCLK:
            RETAILMSG(1, (L"Clk Source is IPG\r\n"));
            break;
        case GPT_HIGHCLK:
            RETAILMSG(1, (L"Clk Source is HI_FRQ\r\n"));
            break;
        case GPT_EXTCLK:
            RETAILMSG(1, (L"Clk Source is EXT\r\n"));
            break;
        case GPT_32KCLK:
            RETAILMSG(1, (L"Clk Source is 32K\r\n"));
            break;
    }
    return;
}

//------------------------------------------------------------------------------
//
// Function: BSPGptCrmSetClockGatingMode
//
// This function calls to the CRM module to
// set the clock gating mode, turning on or off
// clocks to the GPT.
//
// Parameters:
//      startClocks
//          [in] If TRUE, turn clocks to GPT on.
//                If FALSE, turn clocks to GPT off
//
// Returns:
//      TRUE if success.
//      FALSE if failure.
//
//------------------------------------------------------------------------------
BOOL BSPGptSetClockGatingMode(BOOL startClocks)
{
    if (startClocks)
    {
        // Turn GPT clocks on
        if (!DDKClockSetGatingMode(DDK_CLOCK_GATE_INDEX_GPT, 
            DDK_CLOCK_GATE_MODE_ENABLED_ALL))
        {
            DEBUGMSG(ZONE_ERROR, (TEXT("%s: Failed to set CRM clock gating mode!\r\n"), __WFUNCTION__));
            return FALSE;
        }
    }
    else
    {
        // Turn GPT clocks off
        if (!DDKClockSetGatingMode(DDK_CLOCK_GATE_INDEX_GPT, 
            DDK_CLOCK_GATE_MODE_DISABLED))
        {
            DEBUGMSG(ZONE_ERROR, (TEXT("%s: Failed to set CRM clock gating mode!\r\n"), __WFUNCTION__));
            return FALSE;
        }
    }

    return TRUE;
}
