//###########################################################################
//
// FILE:   sysctl.c
//
// TITLE:  C28x system control driver.
//
//###########################################################################
// 
// C2000Ware v26.01.00.00
//
// Copyright (C) 2024 Texas Instruments Incorporated - http://www.ti.com
//
// Redistribution and use in source and binary forms, with or without 
// modification, are permitted provided that the following conditions 
// are met:
// 
//   Redistributions of source code must retain the above copyright 
//   notice, this list of conditions and the following disclaimer.
// 
//   Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the 
//   documentation and/or other materials provided with the   
//   distribution.
// 
//   Neither the name of Texas Instruments Incorporated nor the names of
//   its contributors may be used to endorse or promote products derived
//   from this software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// $
//###########################################################################

#include "cputimer.h"
#include "sysctl.h"
#include "dcc.h"

//
// Define to isolate inline assembly
//
#define SYSCTL_DELAY        __asm(" .if __TI_EABI__\n"                         \
                                  " .asg    SysCtl_delay    , _SysCtl_delay\n" \
                                  " .endif\n"                                  \
                                  " .def _SysCtl_delay\n"                      \
                                  " .sect \".TI.ramfunc\"\n"                   \
                                  " .global  _SysCtl_delay\n"                  \
                                  "_SysCtl_delay:\n"                           \
                                  " SUB    ACC,#1\n"                           \
                                  " BF     _SysCtl_delay, GEQ\n"               \
                                  " LRETR\n")

//*****************************************************************************
//
// SysCtl_delay()
//
//*****************************************************************************
SYSCTL_DELAY;


//*****************************************************************************
//
// SysCtl_pollX1Counter()
//
//*****************************************************************************
static bool
SysCtl_pollX1Counter(void)
{
    uint16_t loopCount = 0U;
    uint32_t localCounter = 0U;
    bool status = false;

    //
    // Delay for 1 ms while the XTAL powers up
    //
    // 2000 loops, 5 cycles per loop + 9 cycles overhead = 10009 cycles
    //
    SysCtl_delay(2000);

    //
    // Clear and saturate X1CNT 4 times to guarantee operation
    //
    do
    {
        //
        // Keep clearing the counter until it is no longer saturated
        //
        while(HWREG(CLKCFG_BASE + SYSCTL_O_X1CNT) > 0x1FFU)
        {
            HWREG(CLKCFG_BASE + SYSCTL_O_X1CNT) |= SYSCTL_X1CNT_CLR;
            HWREG(CLKCFG_BASE + SYSCTL_O_X1CNT) &= ~SYSCTL_X1CNT_CLR;
        }

        //
        // Wait for the X1 clock to saturate
        //
        while(HWREGH(CLKCFG_BASE + SYSCTL_O_X1CNT) != SYSCTL_X1CNT_X1CNT_M)
        {
            //
            // If your application is stuck in this loop, please check if the
            // input clock source is valid.
            //
            localCounter++;
            if(localCounter>2500000U)
            {
                if(loopCount == 3U)
                {
                    status = false;
                }
                break;
            }
        }

        if(loopCount == 3U &&
           (HWREGH(CLKCFG_BASE + SYSCTL_O_X1CNT) == SYSCTL_X1CNT_X1CNT_M))
        {
            status = true;
        }
        //
        // Increment the counter
        //
        loopCount++;
        localCounter = 0U;
    }while(loopCount < 4U);

    return status;
}

//*****************************************************************************
//
// SysCtl_getClock()
//
//*****************************************************************************
uint32_t
SysCtl_getClock(uint32_t clockInHz)
{
    uint32_t temp;
    uint32_t oscSource;
    uint32_t clockOut;

    //
    // Don't proceed if an MCD failure is detected.
    //
    if(SysCtl_isMCDClockFailureDetected())
    {
        //
        // OSCCLKSRC2 failure detected. Returning the INTOSC1 rate. You need
        // to handle the MCD and clear the failure.
        //
        clockOut = SYSCTL_DEFAULT_OSC_FREQ;
    }
    else
    {
        //
        // If one of the internal oscillators is being used, start from the
        // known default frequency.  Otherwise, use clockInHz parameter.
        //
        oscSource = HWREG(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL1) &
                    (uint32_t)SYSCTL_CLKSRCCTL1_OSCCLKSRCSEL_M;

        if((oscSource == (SYSCTL_OSCSRC_OSC2 >> SYSCTL_OSCSRC_S)) ||
           (oscSource == (SYSCTL_OSCSRC_OSC1 >> SYSCTL_OSCSRC_S)))
        {
            clockOut = SYSCTL_DEFAULT_OSC_FREQ;
        }
        else
        {
            clockOut = clockInHz;
        }

        //
        // If the PLL is enabled calculate its effect on the clock
        //
        if((HWREG(CLKCFG_BASE + SYSCTL_O_SYSPLLCTL1) &
            (SYSCTL_SYSPLLCTL1_PLLEN | SYSCTL_SYSPLLCTL1_PLLCLKEN)) == 3U)
        {
            //
            // Calculate integer multiplier
            //
            clockOut = clockOut * ((HWREG(CLKCFG_BASE + SYSCTL_O_SYSPLLMULT) &
                                    SYSCTL_SYSPLLMULT_IMULT_M) >>
                                   SYSCTL_SYSPLLMULT_IMULT_S);

            //
            // Calculate PLL divider
            //
            temp = ((((HWREG(CLKCFG_BASE + SYSCTL_O_SYSPLLMULT) &
                       SYSCTL_SYSPLLMULT_REFDIV_M) >>
                      SYSCTL_SYSPLLMULT_REFDIV_S) + 1U) *
                    (((HWREG(CLKCFG_BASE + SYSCTL_O_SYSPLLMULT) &
                       SYSCTL_SYSPLLMULT_ODIV_M) >>
                      SYSCTL_SYSPLLMULT_ODIV_S) + 1U));

            //
            //  Divide dividers
            //
            if(temp != 0U)
            {
                clockOut /= temp;
            }
        }

        if((HWREG(CLKCFG_BASE + SYSCTL_O_SYSCLKDIVSEL) &
            SYSCTL_SYSCLKDIVSEL_PLLSYSCLKDIV_M) != 0U)
        {
            clockOut /= (2U * (HWREG(CLKCFG_BASE + SYSCTL_O_SYSCLKDIVSEL) &
                               SYSCTL_SYSCLKDIVSEL_PLLSYSCLKDIV_M));
        }
    }

    return(clockOut);
}

//*****************************************************************************
//
// SysCtl_getAuxClock()
//
//*****************************************************************************
uint32_t SysCtl_getAuxClock(uint32_t clockInHz)
{
    uint32_t temp;
    uint32_t oscSource;
    uint32_t clockOut;
    uint32_t divider;

    oscSource = HWREG(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL2) &
                (uint32_t)SYSCTL_CLKSRCCTL2_AUXOSCCLKSRCSEL_M;

    //
    // If one of the internal oscillators is being used, start from the
    // known default frequency.  Otherwise, use clockInHz parameter.
    //
    if(oscSource == (SYSCTL_AUXPLL_OSCSRC_OSC2 >> SYSCTL_OSCSRC_S))
    {
        //
        // 10MHz Internal Clock
        //
        clockOut = SYSCTL_DEFAULT_OSC_FREQ;
    }
    else
    {
        clockOut = clockInHz;
    }

    //
    // If the PLL is enabled calculate its effect on the clock
    //
    if((HWREG(CLKCFG_BASE + SYSCTL_O_AUXPLLCTL1) &
        (SYSCTL_AUXPLLCTL1_PLLEN | SYSCTL_AUXPLLCTL1_PLLCLKEN)) == 3U)
    {
        //
        // Calculate integer multiplier
        //
        clockOut = clockOut * ((HWREG(CLKCFG_BASE + SYSCTL_O_AUXPLLMULT) &
                                SYSCTL_AUXPLLMULT_IMULT_M) >>
                               SYSCTL_AUXPLLMULT_IMULT_S);

        //
        // Calculate AUXPLL divider
        //
        temp = ((((HWREG(CLKCFG_BASE + SYSCTL_O_AUXPLLMULT) &
                   SYSCTL_AUXPLLMULT_REFDIV_M) >>
                  SYSCTL_AUXPLLMULT_REFDIV_S) + 1U) *
                (((HWREG(CLKCFG_BASE + SYSCTL_O_AUXPLLMULT) &
                   SYSCTL_AUXPLLMULT_ODIV_M) >>
                  SYSCTL_AUXPLLMULT_ODIV_S) + 1U));

        //
        //  Divide by calculated dividers
        //
        if(temp != 0U)
        {
            clockOut /= temp;
        }
    }

    //
    // Calculate divider and divide the clock
    //
    divider = (HWREG(CLKCFG_BASE + SYSCTL_O_AUXCLKDIVSEL) &
               SYSCTL_AUXCLKDIVSEL_AUXPLLDIV_M);

    if(divider < 0x4U)
    {
        clockOut /= (1UL << divider);
    }
    else if(divider > 0x4U)
    {
        clockOut /= divider;
    }
    else
    {
        clockOut /= 0x3U;
    }

    return(clockOut);
}

//*****************************************************************************
//
// SysCtl_setClock()
//
//*****************************************************************************
bool
SysCtl_setClock(uint32_t config)
{
    uint16_t divSel, pllen, oscclksrcsel, pllLockStatus, xtalval;
    uint32_t oscSource, pllMult, mult;
    uint32_t timeout, refdiv;
    bool status = false;

    //
    // Check the arguments.
    //
    ASSERT((config & SYSCTL_OSCSRC_M) <= SYSCTL_OSCSRC_M);
    ASSERT(((config & SYSCTL_PLL_CONFIG_M) == SYSCTL_PLL_ENABLE) ||
           ((config & SYSCTL_PLL_CONFIG_M) == SYSCTL_PLL_BYPASS) ||
           ((config & SYSCTL_PLL_CONFIG_M) == SYSCTL_PLL_DISABLE));

    //
    // Don't proceed to the PLL initialization if an MCD failure is detected.
    //
    if(SysCtl_isMCDClockFailureDetected())
    {
        //
        // OSCCLKSRC2 failure detected. Returning false. You'll need to clear
        // the MCD error.
        //
        status = false;
    }
    else
    {
        //
        // Bypass PLL
        //
        EALLOW;
        HWREGH(CLKCFG_BASE + SYSCTL_O_SYSPLLCTL1) &=
            ~SYSCTL_SYSPLLCTL1_PLLCLKEN;
        EDIS;

        //
        // Delay of at least 120 OSCCLK cycles required post PLL bypass
        //
        SysCtl_delay(23U);

        //
        // Derive the current and previous oscillator clock source values
        //
        oscclksrcsel = HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL1) &
                      (uint16_t)SYSCTL_CLKSRCCTL1_OSCCLKSRCSEL_M;

        xtalval = (HWREGH(CLKCFG_BASE + SYSCTL_O_XTALCR) &
                  (uint16_t)SYSCTL_XTALCR_SE);

        oscSource = (config & SYSCTL_OSCSRC_M) >> SYSCTL_OSCSRC_S;

        //
        // Check if the oscillator clock source has changed
        //
        if((oscclksrcsel | xtalval) != oscSource)
        {
            //
            // Turn off PLL
            //
            EALLOW;
            HWREGH(CLKCFG_BASE + SYSCTL_O_SYSPLLCTL1) &=
                ~SYSCTL_SYSPLLCTL1_PLLEN;
            EDIS;

            //
            // Delay of at least 66 OSCCLK cycles required between
            // powerdown to powerup of PLL
            //
            SysCtl_delay(12U);

            //
            // Configure oscillator source
            //
            SysCtl_selectOscSource(config & SYSCTL_OSCSRC_M);

            //
            // Delay of at least 60 OSCCLK cycles
            //
            SysCtl_delay(11U);
        }

        //
        // Set dividers to /1 to ensure the fastest PLL configuration
        //
        SysCtl_setPLLSysClk(0U);

        //
        // Configure PLL if PLL usage is enabled or bypassed in config
        //
        if(((config & SYSCTL_PLL_CONFIG_M) == SYSCTL_PLL_ENABLE) ||
           ((config & SYSCTL_PLL_CONFIG_M) == SYSCTL_PLL_BYPASS))
        {
            //
            // Get the PLL multiplier settings from config
            //
            pllMult  = ((config & SYSCTL_IMULT_M) <<
                         SYSCTL_SYSPLLMULT_IMULT_S);

            pllMult |= (((config & SYSCTL_REFDIV_M) >>
                        SYSCTL_REFDIV_S) <<
                        SYSCTL_SYSPLLMULT_REFDIV_S);

            pllMult |= (((config & SYSCTL_ODIV_M) >>
                          SYSCTL_ODIV_S) <<
                          SYSCTL_SYSPLLMULT_ODIV_S);

            //
            // Get the PLL multipliers currently programmed
            //
            mult  = ((HWREG(CLKCFG_BASE + SYSCTL_O_SYSPLLMULT) &
                      SYSCTL_SYSPLLMULT_IMULT_M) >>
                      SYSCTL_SYSPLLMULT_IMULT_S);

            mult |= (HWREG(CLKCFG_BASE + SYSCTL_O_SYSPLLMULT) &
                     SYSCTL_SYSPLLMULT_REFDIV_M);

            mult |= (HWREG(CLKCFG_BASE + SYSCTL_O_SYSPLLMULT) &
                     SYSCTL_SYSPLLMULT_ODIV_M);

            pllen = (HWREGH(CLKCFG_BASE + SYSCTL_O_SYSPLLCTL1) &
                     SYSCTL_SYSPLLCTL1_PLLEN);

            //
            // Lock PLL only if the multipliers need an update or PLL needs
            // to be powered on / enabled
            //
            if((mult !=  pllMult) || (pllen != 1U))
            {
                //
                // Turn off PLL
                //
                EALLOW;
                HWREGH(CLKCFG_BASE + SYSCTL_O_SYSPLLCTL1) &=
                    ~SYSCTL_SYSPLLCTL1_PLLEN;
                EDIS;

                //
                // Delay of at least 66 OSCCLK cycles required between
                // powerdown to powerup of PLL
                //
                SysCtl_delay(12U);

                //
                // Write multiplier, which automatically turns on the PLL
                //
                EALLOW;
                HWREG(CLKCFG_BASE + SYSCTL_O_SYSPLLMULT) = pllMult;

                //
                // Enable/ turn on PLL
                //
                HWREGH(CLKCFG_BASE + SYSCTL_O_SYSPLLCTL1) |=
                       SYSCTL_SYSPLLCTL1_PLLEN;

                //
                // Wait for the SYSPLL lock counter or a timeout
                // This timeout needs to be computed based on OSCCLK
                // with a factor of REFDIV.
                // Lock time is 1024 OSCCLK * (REFDIV+1)
                //
                refdiv  = ((config & SYSCTL_REFDIV_M) >> SYSCTL_REFDIV_S);

                timeout = (1024U * (refdiv + 1U));
                pllLockStatus = HWREGH(CLKCFG_BASE + SYSCTL_O_SYSPLLSTS) &
                                SYSCTL_SYSPLLSTS_LOCKS;

                while((pllLockStatus != 1U) && (timeout != 0U))
                {
                    pllLockStatus = HWREGH(CLKCFG_BASE + SYSCTL_O_SYSPLLSTS) &
                                    SYSCTL_SYSPLLSTS_LOCKS;
                    timeout--;
                }
                EDIS;

                //
                // Check PLL Frequency using DCC
                //
                status = SysCtl_isPLLValid(
                        (config & SYSCTL_DCC_BASE_M),
                        (config & SYSCTL_OSCSRC_M),
                        SYSCTL_SOURCE_SYSPLL,
                        (config & (SYSCTL_IMULT_M | SYSCTL_ODIV_M |
                                   SYSCTL_REFDIV_M)));

            }
            else
            {
                //
                // Re-Lock of PLL not needed since the multipliers
                // are not updated
                //
                status = true;
            }
        }
        else if((config & SYSCTL_PLL_CONFIG_M) == SYSCTL_PLL_DISABLE)
        {
            //
            // Turn off PLL when the PLL is disabled in config
            //
            EALLOW;
            HWREGH(CLKCFG_BASE + SYSCTL_O_SYSPLLCTL1) &=
                   ~SYSCTL_SYSPLLCTL1_PLLEN;
            SYSCTL_REGWRITE_DELAY;
            EDIS;

            //
            // PLL is bypassed and not in use
            // Status is updated to true to allow configuring the dividers later
            //
            status = true;
        }
        else
        {
            //
            // Empty
            //
        }

        //
        // If PLL locked successfully, configure the dividers
        // Or if PLL is bypassed, only configure the dividers
        //
        if(status)
        {
            //
            // Set divider to produce slower output frequency to limit current
            // increase.
            //
            divSel = (uint16_t)(config & SYSCTL_SYSDIV_M) >> SYSCTL_SYSDIV_S;

            EALLOW;
            if(divSel != (126U / 2U))
            {
                HWREGH(CLKCFG_BASE + SYSCTL_O_SYSCLKDIVSEL) =
                    (HWREGH(CLKCFG_BASE + SYSCTL_O_SYSCLKDIVSEL) &
                     ~(uint16_t)SYSCTL_SYSCLKDIVSEL_PLLSYSCLKDIV_M) |
                    (divSel + 1U);
                SYSCTL_REGWRITE_DELAY;
            }
            else
            {
                HWREGH(CLKCFG_BASE + SYSCTL_O_SYSCLKDIVSEL) =
                    (HWREGH(CLKCFG_BASE + SYSCTL_O_SYSCLKDIVSEL) &
                     ~(uint16_t)SYSCTL_SYSCLKDIVSEL_PLLSYSCLKDIV_M) | divSel;
                SYSCTL_REGWRITE_DELAY;
            }

            EDIS;

            //
            // Feed system clock from SYSPLL only if PLL usage is enabled
            //
            if((config & SYSCTL_PLL_CONFIG_M) == SYSCTL_PLL_ENABLE)
            {

                //
                // Enable PLLSYSCLK is fed from system PLL clock
                //
                EALLOW;
                HWREGH(CLKCFG_BASE + SYSCTL_O_SYSPLLCTL1) |=
                       SYSCTL_SYSPLLCTL1_PLLCLKEN;
                EDIS;

            }

            //
            // ~200 PLLSYSCLK delay to allow voltage regulator to stabilize
            // prior to increasing entire system clock frequency.
            //
            SysCtl_delay(40U);

            //
            // Set the divider to user value
            //
            EALLOW;
            HWREGH(CLKCFG_BASE + SYSCTL_O_SYSCLKDIVSEL) =
                (HWREGH(CLKCFG_BASE + SYSCTL_O_SYSCLKDIVSEL) &
                 ~SYSCTL_SYSCLKDIVSEL_PLLSYSCLKDIV_M) | divSel;
            SYSCTL_REGWRITE_DELAY;
            EDIS;
        }
        else
        {
            ESTOP0; // If the frequency is out of range, stop here.
        }
    }

    return(status);
}
//*****************************************************************************
//
// SysCtl_setAuxClock()
//
//*****************************************************************************
void SysCtl_setAuxClock(uint32_t config)
{
    uint32_t pllMult = 0U, mult, oscSource;
    uint16_t started = 0U, pllen, oscclksrcsel, xtalval;
    bool status = false;

    //
    // Check the arguments
    //
    ASSERT((config & SYSCTL_OSCSRC_M) <= SYSCTL_OSCSRC_M);
    ASSERT(((config & SYSCTL_PLL_CONFIG_M) == SYSCTL_AUXPLL_ENABLE) ||
           ((config & SYSCTL_PLL_CONFIG_M) == SYSCTL_AUXPLL_BYPASS) ||
           ((config & SYSCTL_PLL_CONFIG_M) == SYSCTL_AUXPLL_DISABLE));

    //
    // Bypass PLL
    //
    EALLOW;
    HWREGH(CLKCFG_BASE + SYSCTL_O_AUXPLLCTL1) &= ~SYSCTL_AUXPLLCTL1_PLLCLKEN;

    //
    // Delay of at least 120 OSCCLK cycles required post PLL bypass
    //
    SysCtl_delay(23U);
    EDIS;

    //
    // Derive the current and previous oscillator clock source values
    //
    oscclksrcsel = HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL2) &
                  SYSCTL_CLKSRCCTL2_AUXOSCCLKSRCSEL_M;

    oscSource = (config & SYSCTL_OSCSRC_M) >> SYSCTL_OSCSRC_S;

    xtalval = (HWREGH(CLKCFG_BASE + SYSCTL_O_XTALCR) &  SYSCTL_XTALCR_SE);

    //
    // Check if the oscillator clock source has changed
    //
    if((oscclksrcsel | xtalval) != oscSource)
    {
        //
        // Turn off PLL
        //
        EALLOW;
        HWREGH(CLKCFG_BASE + SYSCTL_O_AUXPLLCTL1) &= ~SYSCTL_AUXPLLCTL1_PLLEN;
        EDIS;

        //
        // Delay of at least 66 OSCCLK cycles
        //
        SysCtl_delay(12U);

        //
        // Configure oscillator source
        //
        SysCtl_selectOscSourceAuxPLL(config & SYSCTL_OSCSRC_M);

        //
        // Delay of at least 60 OSCCLK cycles
        //
        SysCtl_delay(11U);
    }

    //
    // Configure PLL if PLL usage is enabled or bypassed in config
    //
    if(((config & SYSCTL_PLL_CONFIG_M) == SYSCTL_AUXPLL_ENABLE) ||
       ((config & SYSCTL_PLL_CONFIG_M) == SYSCTL_AUXPLL_BYPASS))
    {
        //
        // Get the PLL multiplier settings from config
        //
        pllMult |= ((config & SYSCTL_IMULT_M) << SYSCTL_AUXPLLMULT_IMULT_S);

        pllMult |= (((config & SYSCTL_REFDIV_M) >> SYSCTL_REFDIV_S) <<
                    SYSCTL_AUXPLLMULT_REFDIV_S);

        pllMult |= (((config & SYSCTL_ODIV_M) >> SYSCTL_ODIV_S) <<
                    SYSCTL_AUXPLLMULT_ODIV_S);

        //
        // Get the PLL multipliers currently programmed
        //
        mult  = ((HWREG(CLKCFG_BASE + SYSCTL_O_AUXPLLMULT) &
                  SYSCTL_AUXPLLMULT_IMULT_M) >>
                  SYSCTL_AUXPLLMULT_IMULT_S);

        mult |= (HWREG(CLKCFG_BASE + SYSCTL_O_AUXPLLMULT) &
                 SYSCTL_AUXPLLMULT_REFDIV_M);

        mult |= (HWREG(CLKCFG_BASE + SYSCTL_O_AUXPLLMULT) &
                 SYSCTL_AUXPLLMULT_ODIV_M);

        pllen = (HWREGH(CLKCFG_BASE + SYSCTL_O_AUXPLLCTL1) &
                 SYSCTL_AUXPLLCTL1_PLLEN);

        //
        // Lock PLL only if the multipliers need an update or PLL needs
        // to be powered on / enabled
        //
        if((mult !=  pllMult) || (pllen != 1U))
        {

            EALLOW;

            //
            // Turn off AUXPLL and delay for it to power down.
            //
            HWREGH(CLKCFG_BASE + SYSCTL_O_AUXPLLCTL1) &=
                ~SYSCTL_AUXPLLCTL1_PLLEN;

            //
            // Delay of at least 66 OSCCLK cycles
            //
            SysCtl_delay(12U);

            //
            // Set integer and fractional multiplier, which automatically
            // turns on the PLL
            //
            HWREG(CLKCFG_BASE + SYSCTL_O_AUXPLLMULT) = pllMult;
            SYSCTL_REGWRITE_DELAY;

            //
            // Enable AUXPLL
            //
            HWREGH(CLKCFG_BASE + SYSCTL_O_AUXPLLCTL1) |=
                SYSCTL_AUXPLLCTL1_PLLEN;
            EDIS;

            //
            // Wait for the AUXPLL lock counter
            //

            while((HWREGH(CLKCFG_BASE + SYSCTL_O_AUXPLLSTS) &
                   SYSCTL_AUXPLLSTS_LOCKS) != 1U)
            {
                //
                // Consider to servicing the watchdog using
                // SysCtl_serviceWatchdog()
                //
            }

            //
            // Check PLL Frequency using DCC
            //
            status = SysCtl_isPLLValid(
                    (config & SYSCTL_DCC_BASE_M), (config & SYSCTL_OSCSRC_M),
                     SYSCTL_SOURCE_AUXPLL ,
                    (config & (SYSCTL_IMULT_M | SYSCTL_ODIV_M |
                               SYSCTL_REFDIV_M )));

            //
            // Check DCC Status, If the frequency is out of range, stop here.
            //
            if(status)
            {
                //
                // Set flag to indicate PLL started
                //
                started = 1U;
            }
            else
            {
                ESTOP0;
            }

            if((config & SYSCTL_PLL_CONFIG_M) == SYSCTL_AUXPLL_ENABLE)
            {
                //
                // Enable AUXPLLCLK to be fed from AUXPLL
                //
                EALLOW;
                HWREGH(CLKCFG_BASE + SYSCTL_O_AUXPLLCTL1) |=
                       SYSCTL_AUXPLLCTL1_PLLCLKEN;
                SysCtl_delay(3U);

                EDIS;
            }

            if(started == 0U)
            {
                //
                // AUX PLL may not have started. Reset multiplier to 0 (bypass
                // PLL).
                //
                EALLOW;
                HWREGH(CLKCFG_BASE + SYSCTL_O_AUXPLLMULT) = 0U;
                EDIS;

                //
                // The user should put some handler code here based on how
                // this condition should be handled in their application.
                //
                ESTOP0;
            }

        }
        else
        {
            if((config & SYSCTL_PLL_CONFIG_M) == SYSCTL_AUXPLL_ENABLE)
            {
                //
                // Enable AUXPLLCLK to be fed from AUXPLL
                //
                EALLOW;
                HWREGH(CLKCFG_BASE + SYSCTL_O_AUXPLLCTL1) |=
                       SYSCTL_AUXPLLCTL1_PLLCLKEN;
                SysCtl_delay(3U);

                EDIS;
            }
        }

    }
    else if((config & SYSCTL_PLL_CONFIG_M) == SYSCTL_AUXPLL_DISABLE)
    {
        //
        // Turn off PLL when the PLL is disabled in config
        //
        EALLOW;
        HWREGH(CLKCFG_BASE + SYSCTL_O_AUXPLLCTL1) &= ~SYSCTL_AUXPLLCTL1_PLLEN;
        EDIS;
    }
    else
    {
        //
        // Empty
        //
    }

    //
    // Set divider to desired value
    //
    EALLOW;
    HWREGH(CLKCFG_BASE + SYSCTL_O_AUXCLKDIVSEL) =
        (uint16_t)(config & SYSCTL_SYSDIV_M) >> SYSCTL_SYSDIV_S;
    SYSCTL_REGWRITE_DELAY;
    EDIS;

}


//*****************************************************************************
//
// SysCtl_selectXTAL()
//
//*****************************************************************************
void
SysCtl_selectXTAL(void)
{
    bool status = false;
    uint16_t loopCount = 0U;

    EALLOW;

    //
    // Turn on XTAL and select crystal mode
    //
    HWREGH(CLKCFG_BASE + SYSCTL_O_XTALCR) &= ~SYSCTL_XTALCR_OSCOFF;
    SYSCTL_REGWRITE_DELAY;
    HWREGH(CLKCFG_BASE + SYSCTL_O_XTALCR) &= ~SYSCTL_XTALCR_SE;
    SYSCTL_REGWRITE_DELAY;
    EDIS;

    //
    // Wait for the X1 clock to saturate
    //
    status = SysCtl_pollX1Counter();

    //
    // Select XTAL as the oscillator source
    //
    EALLOW;
    HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL1) =
    ((HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL1) &
      (~SYSCTL_CLKSRCCTL1_OSCCLKSRCSEL_M)) |
     (SYSCTL_OSCSRC_XTAL >> SYSCTL_OSCSRC_S));
    SYSCTL_CLKSRCCTL_DELAY;
    EDIS;

    //
    // If a missing clock failure was detected, try waiting for the X1 counter
    // to saturate again. Consider modifying this code to add a 10ms timeout.
    //
    while(SysCtl_isMCDClockFailureDetected() && (status == (bool)FALSE) &&
          (loopCount < 4U))
    {
        //
        // Clear the MCD failure
        //
        SysCtl_resetMCD();

        //
        // Wait for the X1 clock to saturate
        //
        status = SysCtl_pollX1Counter();

        //
        // Select XTAL as the oscillator source
        //
        EALLOW;
        HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL1) =
        ((HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL1) &
          (~SYSCTL_CLKSRCCTL1_OSCCLKSRCSEL_M)) |
         (SYSCTL_OSCSRC_XTAL >> SYSCTL_OSCSRC_S));
        EDIS;
        loopCount ++;
    }
    while(status == (bool)FALSE)
    {         
        // If code is stuck here, it means crystal has not started.  
        //Replace crystal or update code below to take necessary actions if 
        //crystal is bad         
        ESTOP0;     
    }
}

//*****************************************************************************
//
// SysCtl_selectXTALSingleEnded()
//
//*****************************************************************************
void
SysCtl_selectXTALSingleEnded(void)
{
    bool status = false;
    
    //
    // Turn on XTAL and select single-ended mode.
    //
    EALLOW;
    HWREGH(CLKCFG_BASE + SYSCTL_O_XTALCR) &= ~SYSCTL_XTALCR_OSCOFF;
    SYSCTL_REGWRITE_DELAY;
    HWREGH(CLKCFG_BASE + SYSCTL_O_XTALCR) |= SYSCTL_XTALCR_SE;
    SYSCTL_REGWRITE_DELAY;
    EDIS;

    //
    // Wait for the X1 clock to saturate
    //
    status = SysCtl_pollX1Counter();

    //
    // Select XTAL as the oscillator source
    //
    EALLOW;
    HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL1) =
    ((HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL1) &
      (~SYSCTL_CLKSRCCTL1_OSCCLKSRCSEL_M)) |
     (SYSCTL_OSCSRC_XTAL >> SYSCTL_OSCSRC_S));
    EDIS;

    //
    // Something is wrong with the oscillator module. Replace the ESTOP0 with
    // an appropriate error-handling routine.
    //
    while(SysCtl_isMCDClockFailureDetected() && (status == (bool)FALSE))
    {
        // If code is stuck here, it means crystal has not started.  
        //Replace crystal or update code below to take necessary actions if 
        //crystal is bad 
        ESTOP0;
    }
}

//*****************************************************************************
//
// SysCtl_selectOscSource()
//
//*****************************************************************************
void
SysCtl_selectOscSource(uint32_t oscSource)
{
    ASSERT((oscSource == SYSCTL_OSCSRC_OSC1) ||
           (oscSource == SYSCTL_OSCSRC_OSC2) ||
           (oscSource == SYSCTL_OSCSRC_XTAL) ||
           (oscSource == SYSCTL_OSCSRC_XTAL_SE));

    //
    // Select the specified source.
    //
    EALLOW;
    switch(oscSource)
    {
        case SYSCTL_OSCSRC_OSC2:
            //
            // Clk Src = INTOSC2
            //
            HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL1) &=
                ~SYSCTL_CLKSRCCTL1_OSCCLKSRCSEL_M;

            break;

        case SYSCTL_OSCSRC_XTAL:
            //
            // Select XTAL in crystal mode and wait for it to power up
            //
            SysCtl_selectXTAL();
            break;

        case SYSCTL_OSCSRC_XTAL_SE:
            //
            // Select XTAL in single-ended mode and wait for it to power up
            //
            SysCtl_selectXTALSingleEnded();
            break;

        case SYSCTL_OSCSRC_OSC1:
            //
            // Clk Src = INTOSC1
            //
            HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL1) =
                   (HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL1) &
                    ~SYSCTL_CLKSRCCTL1_OSCCLKSRCSEL_M) |
                   (SYSCTL_OSCSRC_OSC1 >> SYSCTL_OSCSRC_S);

            SYSCTL_CLKSRCCTL_DELAY;
            break;

        default:
            //
            // Do nothing. Not a valid oscSource value.
            //
            break;
    }
    EDIS;
}

//*****************************************************************************
//
// SysCtl_selectOscSourceAuxPLL()
//
//*****************************************************************************
void
SysCtl_selectOscSourceAuxPLL(uint32_t oscSource)
{
    bool status = false;

    EALLOW;

    switch(oscSource)
    {
        case SYSCTL_AUXPLL_OSCSRC_OSC2:
            //
            // Clk Src = INTOSC2
            //
            HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL2) &=
                    ~(SYSCTL_CLKSRCCTL2_AUXOSCCLKSRCSEL_M);
            break;

        case SYSCTL_AUXPLL_OSCSRC_XTAL:
            //
            // Turn on XTALOSC
            //
            HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL1) &=
                   ~(SYSCTL_CLKSRCCTL1_XTALOFF);
            SYSCTL_CLKSRCCTL_DELAY;

            //
            // Select crystal mode
            //
            HWREGH(CLKCFG_BASE + SYSCTL_O_XTALCR) &= ~SYSCTL_XTALCR_SE;

            //
            // Wait for the X1 clock to saturate
            //
            status = SysCtl_pollX1Counter();
            while(status == FALSE)
            {
                // If code is stuck here, it means crystal has not started.
                //Replace crystal or update code below to take necessary actions if
                //crystal is bad
                ESTOP0;
            }

            //
            // Clk Src = XTAL
            //
            HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL2) =
                    (HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL2) &
                     ~(SYSCTL_CLKSRCCTL2_AUXOSCCLKSRCSEL_M)) |
                    (1U << SYSCTL_CLKSRCCTL2_AUXOSCCLKSRCSEL_S);
            break;

        case SYSCTL_AUXPLL_OSCSRC_XTAL_SE:
            HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL1) &=
                   ~(SYSCTL_CLKSRCCTL1_XTALOFF);
            //
            // Select crystal mode
            //
            HWREGH(CLKCFG_BASE + SYSCTL_O_XTALCR) |= SYSCTL_XTALCR_SE;

            //
            // Wait for the X1 clock to saturate
            //
            status = SysCtl_pollX1Counter();
            while(status == FALSE)
            {
                // If code is stuck here, it means crystal has not started.
                //Replace crystal or update code below to take necessary actions if
                //crystal is bad
                ESTOP0;
            }

            //
            // Clk Src = XTAL
            //
            HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL2) =
                    (HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL2) &
                     ~(SYSCTL_CLKSRCCTL2_AUXOSCCLKSRCSEL_M)) |
                    (1U << SYSCTL_CLKSRCCTL2_AUXOSCCLKSRCSEL_S);
            break;

        case SYSCTL_AUXPLL_OSCSRC_AUXCLKIN:
            //
            // Clk Src = AUXCLKIN
            //
            HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL2) =
                    (HWREGH(CLKCFG_BASE + SYSCTL_O_CLKSRCCTL2) &
                     ~(SYSCTL_CLKSRCCTL2_AUXOSCCLKSRCSEL_M)) |
                    (2U << SYSCTL_CLKSRCCTL2_AUXOSCCLKSRCSEL_S);
            SYSCTL_CLKSRCCTL_DELAY;
            break;

        default:
            //
            // Do nothing. Not a valid clock source value.
            //
            break;
    }
    EDIS;
}

//*****************************************************************************
//
// SysCtl_getLowSpeedClock()
//
//*****************************************************************************
uint32_t
SysCtl_getLowSpeedClock(uint32_t clockInHz)
{
    uint32_t clockOut;

    //
    // Get the main system clock
    //
    clockOut = SysCtl_getClock(clockInHz);

    //
    // Apply the divider to the main clock
    //
    if((HWREG(CLKCFG_BASE + SYSCTL_O_LOSPCP) &
        SYSCTL_LOSPCP_LSPCLKDIV_M) != 0U)
    {
        clockOut /= (2U * (HWREG(CLKCFG_BASE + SYSCTL_O_LOSPCP) &
                            SYSCTL_LOSPCP_LSPCLKDIV_M));
    }

    return(clockOut);
}

//*****************************************************************************
//
// SysCtl_getDeviceParametric()
//
//*****************************************************************************
uint16_t
SysCtl_getDeviceParametric(SysCtl_DeviceParametric parametric)
{
    uint32_t value;

    //
    // Get requested parametric value
    //
    switch(parametric)
    {
        case SYSCTL_DEVICE_QUAL:
            //
            // Qualification Status
            //
            value = ((HWREG(DEVCFG_BASE + SYSCTL_O_PARTIDL) &
                      SYSCTL_PARTIDL_QUAL_M) >> SYSCTL_PARTIDL_QUAL_S);
            break;

        case SYSCTL_DEVICE_PINCOUNT:
            //
            // Pin Count
            //
            value = ((HWREG(DEVCFG_BASE + SYSCTL_O_PARTIDL) &
                      SYSCTL_PARTIDL_PIN_COUNT_M) >>
                     SYSCTL_PARTIDL_PIN_COUNT_S);
            break;

        case SYSCTL_DEVICE_INSTASPIN:
            //
            // InstaSPIN Feature Set
            //
            value = ((HWREG(DEVCFG_BASE + SYSCTL_O_PARTIDL) &
                      SYSCTL_PARTIDL_INSTASPIN_M) >>
                     SYSCTL_PARTIDL_INSTASPIN_S);
            break;

        case SYSCTL_DEVICE_FLASH:
            //
            // Flash Size (KB)
            //
            value = ((HWREG(DEVCFG_BASE + SYSCTL_O_PARTIDL) &
                      SYSCTL_PARTIDL_FLASH_SIZE_M) >>
                     SYSCTL_PARTIDL_FLASH_SIZE_S);
            break;

        case SYSCTL_DEVICE_PARTID:
            //
            // PARTID Format Revision
            //
            value = ((HWREG(DEVCFG_BASE + SYSCTL_O_PARTIDL) &
                      SYSCTL_PARTIDL_PARTID_FORMAT_REVISION_M) >>
                     SYSCTL_PARTIDL_PARTID_FORMAT_REVISION_S);
            break;

        case SYSCTL_DEVICE_FAMILY:
            //
            // Device Family
            //
            value = ((HWREG(DEVCFG_BASE + SYSCTL_O_PARTIDH) &
                      SYSCTL_PARTIDH_FAMILY_M) >> SYSCTL_PARTIDH_FAMILY_S);
            break;

        case SYSCTL_DEVICE_PARTNO:
            //
            // Part Number
            //
            value = ((HWREG(DEVCFG_BASE + SYSCTL_O_PARTIDH) &
                      SYSCTL_PARTIDH_PARTNO_M) >> SYSCTL_PARTIDH_PARTNO_S);
            break;

        case SYSCTL_DEVICE_CLASSID:
            //
            // Class ID
            //
            value = ((HWREG(DEVCFG_BASE + SYSCTL_O_PARTIDH) &
                      SYSCTL_PARTIDH_DEVICE_CLASS_ID_M) >>
                     SYSCTL_PARTIDH_DEVICE_CLASS_ID_S);
            break;

        default:
            //
            // Not a valid value for PARTID register
            //
            value = 0U;
            break;
    }

    return((uint16_t)value);
}
//*****************************************************************************
//
// SysCtl_isPLLValid()
//
//*****************************************************************************
bool
SysCtl_isPLLValid(uint32_t base, uint32_t oscSource,
                  SysCtl_PLLClockSource pllclk, uint32_t pllMultDiv)
{
    uint32_t imult, odiv, refdiv;
    float  fclk1_0ratio, fclk0_1ratio;
    float32_t total_error, window;

    DCC_Count0ClockSource dccClkSrc0;
    DCC_Count1ClockSource dccClkSrc1;
    uint32_t dccCounterSeed0, dccCounterSeed1, dccValidSeed0;

    switch(oscSource)
    {
        case SYSCTL_OSCSRC_OSC2:
            //
            // Select DCC Clk Src0 as INTOSC2
            //
            dccClkSrc0 = DCC_COUNT0SRC_INTOSC2;
            break;
        case SYSCTL_OSCSRC_XTAL:
        case SYSCTL_OSCSRC_XTAL_SE:
            //
            // Select DCC Clk Src0 as XTAL
            //
            dccClkSrc0 = DCC_COUNT0SRC_XTAL;
            break;
        case SYSCTL_OSCSRC_OSC1:
            //
            // Select DCC Clk Src0 as INTOSC1
            //
            dccClkSrc0 = DCC_COUNT0SRC_INTOSC1;
            break;
        default:
            //
            // Select DCC Clk Src0 as INTOSC1
            //
            dccClkSrc0 = DCC_COUNT0SRC_INTOSC1;
            break;
    }

    switch(pllclk)
    {
        case SYSCTL_SOURCE_SYSPLL:
            //
            // Select DCC Clk Src1 as SYSPLL
            //
            dccClkSrc1 = DCC_COUNT1SRC_PLL;
            break;
        case SYSCTL_SOURCE_AUXPLL:
            //
            // Select DCC Clk Src1 as AUXPLL
            //
            dccClkSrc1 = DCC_COUNT1SRC_AUXPLL;
            break;
        default:
            //
            // Select DCC Clk Src1 as SYSPLL
            //
            dccClkSrc1 = DCC_COUNT1SRC_PLL;
            break;
    }

    //
    // Assigning DCC for PLL validation
    //
    if(base == SYSCTL_DCC_BASE_0)
    {
        base = DCC0_BASE;
    }
    else if(base == SYSCTL_DCC_BASE_1)
    {
        base = DCC1_BASE;
    }
    else
    {
        base = DCC2_BASE;
    }

    //
    // Retrieving PLL parameters
    //
    imult = pllMultDiv & SYSCTL_IMULT_M;
    odiv = (pllMultDiv & SYSCTL_ODIV_M) >> SYSCTL_ODIV_S;
    refdiv = (pllMultDiv & SYSCTL_REFDIV_M) >> SYSCTL_REFDIV_S;

    fclk1_0ratio = (float)imult / (((float)odiv + 1.0F) *
                                   ((float)refdiv + 1.0F));
    fclk0_1ratio = (((float)refdiv + 1.0F) * ((float)odiv + 1.0F)) /
                                             (float)imult;

    if(fclk1_0ratio >= 1.0F)
    {
        //
        // Setting Counter0 & Valid Seed Value with +/-1% tolerance
        // Total error is 12
        //
        window = (12U * 100U) / ((uint32_t)SYSCTL_DCC_COUNTER0_TOLERANCE);
        dccCounterSeed0 = (uint32_t)window - 12U;
        dccValidSeed0 = 24U;
    }
    else
    {
        total_error = ((2.0F * fclk0_1ratio) + 10.0F);
        window = (total_error * 100.0F) /
                 ((float32_t)SYSCTL_DCC_COUNTER0_TOLERANCE);

        //
        // Setting Counter0 & Valid Seed Value with +/-1% tolerance
        //
        dccCounterSeed0 = window - total_error;
        dccValidSeed0 = 2U * (uint32_t)total_error;
    }

    //
    // Multiplying Counter-0 window with PLL Integer Multiplier
    //
    dccCounterSeed1 = (window * fclk1_0ratio);


    //
    // Enable peripheral clock to DCC
    //
    if(base == DCC0_BASE)
    {
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_DCC0);
    }
    else if(base == DCC1_BASE)
    {
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_DCC1);
    }
    else
    {
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_DCC2);
    }

    //
    // Clear Error & Done Flag
    //
    DCC_clearErrorFlag(base);
    DCC_clearDoneFlag(base);

    //
    // Disable DCC
    //
    DCC_disableModule(base);

    //
    // Disable Error Signal
    //
    DCC_disableErrorSignal(base);

    //
    // Disable Done Signal
    //
    DCC_disableDoneSignal(base);

    //
    // Configure Clock Source0 to whatever set as a clock source for PLL
    //
    DCC_setCounter0ClkSource(base, dccClkSrc0);

    //
    // Configure Clock Source1 to PLL
    //
    DCC_setCounter1ClkSource(base, dccClkSrc1);

    //
    // Configure COUNTER-0, COUNTER-1 & Valid Window
    //
    DCC_setCounterSeeds(base, dccCounterSeed0, dccValidSeed0,
                        dccCounterSeed1);

    //
    // Enable Single Shot mode
    //
    DCC_enableSingleShotMode(base, DCC_MODE_COUNTER_ZERO);


    //
    // Enable DCC to start counting
    //
    DCC_enableModule(base);

    //
    // Timeout for the loop
    //
    uint32_t timeout = dccCounterSeed1;

    //
    // Wait until Error or Done Flag is generated
    //
    while(((HWREGH(base + DCC_O_STATUS) &
            (DCC_STATUS_ERR | DCC_STATUS_DONE)) == 0U) && (timeout != 0U))

    {
        timeout--;
    }


    //
    // Returns true if DCC completes without error
    //

    return((HWREGH(base + DCC_O_STATUS) &
            (DCC_STATUS_ERR | DCC_STATUS_DONE)) == DCC_STATUS_DONE);
}
//*****************************************************************************
//
// SysCtl_controlCPU2Reset()
//
//*****************************************************************************
void
SysCtl_controlCPU2Reset(SysCtl_CoreReset control)
{
    uint32_t clearvalue;

    //
    //Based on whether the Core is to be reset or not,
    //the core would be put into reset or brought out.
    //
    if(control != SYSCTL_CORE_DEACTIVE)
    {
        //
        //On matching key, write to the reset bits would be successful
        //

        EALLOW;
        HWREG(DEVCFG_BASE +
            SYSCTL_O_CPU2RESCTL)  = ((uint32_t)SYSCTL_CPU2RESCTL_RESET |
                                    (SYSCTL_REG_KEY & SYSCTL_CPU2RESCTL_KEY_M));
        EDIS;
    }
    else
    {
        EALLOW;

        //
        //On matching key, write to the reset bits would be successful
        //
        clearvalue = HWREG(DEVCFG_BASE + SYSCTL_O_CPU2RESCTL);
        clearvalue &= ~SYSCTL_CPU2RESCTL_RESET;
        HWREG(DEVCFG_BASE + SYSCTL_O_CPU2RESCTL) = (SYSCTL_REG_KEY &
                                                    SYSCTL_CPU2RESCTL_KEY_M) |
                                                    clearvalue;
        EDIS;
    }
}

//*****************************************************************************
//
// SysCtl_configureType()
//
//*****************************************************************************
void
SysCtl_configureType(SysCtl_SelType type , uint16_t config, uint16_t lock)
{
    ASSERT(lock <= 1U);

    EALLOW;

    //
    // Check which type needs to be configured , the type would be enabled /
    // disabled along with making the configurations unalterable as per input.
    //
    switch(type)
    {
        case SYSCTL_ECAPTYPE:
            HWREGH(DEVCFG_BASE + SYSCTL_O_ECAPTYPE) =
                                config | (lock << SYSCTL_TYPE_LOCK_S);
            break;

        case SYSCTL_SDFMTYPE:
            HWREGH(DEVCFG_BASE + SYSCTL_O_SDFMTYPE) =
                                config | (lock << SYSCTL_TYPE_LOCK_S);
            break;

        case SYSCTL_USBTYPE:
            HWREGH(DEVCFG_BASE + SYSCTL_O_USBTYPE) =
                                config | (lock << SYSCTL_TYPE_LOCK_S);
            break;

        case SYSCTL_MEMMAPTYPE:
            HWREGH(DEVCFG_BASE + SYSCTL_O_MEMMAPTYPE) =
                                config | (lock << SYSCTL_TYPE_LOCK_S);
            break;

        default:
            break;
    }
    EDIS;

}

//*****************************************************************************
//
// SysCtl_isConfigTypeLocked()
//
//*****************************************************************************
bool
SysCtl_isConfigTypeLocked(SysCtl_SelType type)
{
    bool lock = false;

    //
    // Check if the provided type registers can be modified or not.
    //
    switch(type)
    {
        case SYSCTL_ECAPTYPE:
            lock = ((HWREGH(DEVCFG_BASE + SYSCTL_O_ECAPTYPE) &
                     SYSCTL_ECAPTYPE_LOCK) != 0U);
            break;

        case SYSCTL_USBTYPE:
            lock = ((HWREGH(DEVCFG_BASE + SYSCTL_O_USBTYPE) &
                     SYSCTL_USBTYPE_LOCK) != 0U);
            break;

        case SYSCTL_SDFMTYPE:
            lock = ((HWREGH(DEVCFG_BASE + SYSCTL_O_SDFMTYPE) &
                     SYSCTL_SDFMTYPE_LOCK) != 0U);
            break;

        case SYSCTL_MEMMAPTYPE:
            lock = ((HWREGH(DEVCFG_BASE + SYSCTL_O_MEMMAPTYPE) &
                     SYSCTL_MEMMAPTYPE_LOCK) != 0U);
            break;

        default:
            break;
    }

  return(lock);
}

//*****************************************************************************
//
// SysCtl_setSemOwner()
//
//*****************************************************************************
void
SysCtl_setSemOwner (SysCtl_CPUSel cpuInst)
{
    uint32_t semVal = (cpuInst == SYSCTL_CPUSEL_CPU1) ? 0x10UL : 0x01UL;

    EALLOW;

    //
    // Free the semaphore
    //
    HWREG(CLKCFG_BASE + SYSCTL_O_CLKSEM) = SYSCTL_REG_KEY;

    //
    // CPU1 Acquire the semaphore
    //
    HWREG(CLKCFG_BASE + SYSCTL_O_CLKSEM) = semVal | SYSCTL_REG_KEY;

    EDIS;
}

//*****************************************************************************
//
// SysCtl_lockClkConfig()
//
//*****************************************************************************
void
SysCtl_lockClkConfig(SysCtl_ClkRegSel registerName)
{
    uint16_t bitIndex;

    //
    // Decode the register variable.
    //
    bitIndex = ((uint16_t)registerName & SYSCTL_PERIPH_BIT_M) >>
                SYSCTL_PERIPH_BIT_S;

    //
    // Locks the particular clock configuration register
    //
    EALLOW;
    HWREG(CLKCFG_BASE + SYSCTL_O_CLKCFGLOCK1) |= (1UL << bitIndex);
    EDIS;
}

//*****************************************************************************
//
// SysCtl_lockSysConfig()
//
//*****************************************************************************
void
SysCtl_lockSysConfig (SysCtl_CpuRegSel registerName)
{
    uint16_t regIndex;
    uint16_t bitIndex;

    //
    // Decode the register variable.
    //
    regIndex = 2U * ((uint16_t)registerName & SYSCTL_PERIPH_REG_M);
    bitIndex = ((uint16_t)registerName & SYSCTL_PERIPH_BIT_M) >>
                 SYSCTL_PERIPH_BIT_S;

    //
    // Locks the particular System configuration register
    //
    EALLOW;
    HWREG(CPUSYS_BASE + SYSCTL_O_CPUSYSLOCK1 + regIndex) |=
                                            (1UL << bitIndex);
    EDIS;
}

//*****************************************************************************
//
// SysCtl_controlCMReset()
//
//*****************************************************************************
void
SysCtl_controlCMReset(SysCtl_CoreReset control)
{
    if(control == SYSCTL_CORE_ACTIVE)
    {
        //
        // Assert reset to CM
        //
        EALLOW;
        HWREG(CMCONF_BASE + SYSCTL_O_CMRESCTL) = SYSCTL_CMRESCTL_RESET |
                                                 SYSCTL_REG_KEY;

        //
        // Wait until CM is out to reset.
        //
        while(!SysCtl_isCMReset())
        {
        }

        //
        // De-assert reset to CM
        //
        HWREG(CMCONF_BASE + SYSCTL_O_CMRESCTL) = SYSCTL_REG_KEY;
        EDIS;
    }
    else
    {
        //
        // Bring CM out of reset only when CM is in reset state
        //
        if(SysCtl_isCMReset())
        {
            EALLOW;

            //
            // De-assert reset to CM
            //
            HWREG(CMCONF_BASE + SYSCTL_O_CMRESCTL) = SYSCTL_REG_KEY;
            EDIS;
        }
    }
}


