/*************************************************************************************************/
/*                                                                                               */
/*            FSL Sample Software for Rainier                                                    */
/*                                                                                               */
/* FILE NAME     :  mcu_init.c                                                                   */
/* DESCRIPTION   :  Freescale sample source for Rainier Mode and Clock tree configuration        */
/* DATE          :  April 18, 2013                                                               */
/* AUTHOR        :                                                                               */
/*                                                                                               */
/*************************************************************************************************/

/*************************************************************************************************/
/****   0.0.0   2013.04.18        Kuniaki Hirabayashi  	       Initial Version                ****/
/****   0.0.1   2013.05.06        Kuniaki Hirabayashi  	       connected CLKOUT to PL14       ****/
/****   0.0.2   2013.05.06        Kuniaki Hirabayashi  	        Re-arranged orders of DE/DIV  ****/
/****                                             to enable divider before changing DIV value ****/
/******************************* CHANGES *********************************************************/


/*************************************************************************************************/
/*****                                   INCLUDE FILES                                       *****/
/*************************************************************************************************/

#include "../headers/project.h"

/*************************************************************************************************/
/*****                                  GLOBAL DATA                                          *****/
/*************************************************************************************************/

/*************************************************************************************************/
/*****                                  STATIC DATA                                          *****/
/*************************************************************************************************/

/*************************************************************************************************/
/*****                                  PROTOTYPES                                           *****/
/*************************************************************************************************/

/*************************************************************************************************/
/*************************************************************************************************/
/****         Function: Clock_and_Mode_Init                                                   ****/
/****         Content:  Configure the Mode and Clock Tree                                     ****/
/****                                                                                         ****/
/****         Argument: void                                                                  ****/
/****         Return value: void                                                              ****/
/*************************************************************************************************/
/*************************************************************************************************/

void Clock_and_Mode_Init(void){

    /* Turn On XOSC - PLL's remain off */
    /* This code is not needed if XOSC started oscillate by DCF Record */
    MC_ME.DRUN_MC.R = 0x001F0020; 			  /* Enable the XOSC */

    /* Mode change Re-enter the drun mode, to start XOSC */
    /* These codes are not needed if XOSC started oscillate by DCF Record */
    MC_ME.MCTL.R = 0x30005AF0;                            /* Mode & Key */
    MC_ME.MCTL.R = 0x3000A50F;                            /* Mode & Key inverted */
    while(MC_ME.GS.B.S_MTRANS == 1);                      /* Wait for mode entry complete */
    while(MC_ME.GS.B.S_CURRENT_MODE != 0x3);              /* Check DRUN mode entered */

    /* Route XOSC to the PLL's - IRC is default */
    MC_CGM.AC3_SC.B.SELCTL=1;                             /* Connect XOSC to PLL0 */
    MC_CGM.AC4_SC.B.SELCTL=3;                             /* Connect PLL0 PHI1 to PLL1 */

    /* Configure PLL0 Dividers - 160MHz from 20Mhz xtal oscillator */
    PLLDIG.PLL0DV.B.RFDPHI = 2;
    PLLDIG.PLL0DV.B.PREDIV = 1;
    PLLDIG.PLL0DV.B.MFD = 16;

    /* Configure PLL0 PHI1 Divider - 40MHz from 20Mhz xtal oscillator */
    PLLDIG.PLL0DV.B.RFDPHI1 = 8;

    /* Configure PLL1 Dividers - 200MHz from 40Mhz PLL0 PHI1 */
    PLLDIG.PLL1DV.B.RFDPHI = 2;
    PLLDIG.PLL1DV.B.MFD = 20; 

    /* Configure System clock dividers */
    /* PBRIDGE Clock Divide by 4(50MHz), and enable */
    MC_CGM.SC_DC[2].R = 0x80030000;

    /* Slow crossbar Clock Divide by 2(100MHz), and enable */
    MC_CGM.SC_DC[1].R = 0x80010000;

    /* Fast crossbar Clock Divide by 1(200MHz), and enable */
    MC_CGM.SC_DC[0].R = 0x80000000;

/* Enable/Disable and configure Aux clocks - These are example configurations and
   may not be suitable for a particular application. User should verify
   the system requirements and modify as necessary. */

    MC_CGM.AC0_DC2.B.DE = 0;                              /* Disable Auxilliary Clock 0 divider 2 (SARADC clock) */
    MC_CGM.AC0_DC3.B.DE = 0;                              /* Disable Auxilliary Clock 0 divider 3 (DSPI_CLK0) */
    MC_CGM.AC0_DC4.B.DE = 0;                              /* Disable Auxilliary Clock 0 divider 4 (DSPI_CLK1/LIN_CLK) */
    MC_CGM.AC2_DC0.B.DE = 0;                              /* Disable Auxilliary Clock 2 divider 0 (SENT) */
    MC_CGM.AC5_DC0.B.DE = 1;                              /* Enable Auxilliary Clock 5 divider 0 (eTPU) */
    MC_CGM.AC5_DC1.B.DE = 1;                              /* Disable Auxilliary Clock 5 divider 1 (eMIOS) */
    MC_CGM.AC8_DC0.B.DE = 0;                              /* Disable Auxilliary Clock 8 divider 0 (CAN Clock) */
    MC_CGM.AC9_DC0.B.DE = 0;                              /* Disable Auxilliary Clock 9 divider 0 (RTI) */
    MC_CGM.AC10_DC0.B.DE = 0;                             /* Disable Auxilliary Clock 10 divider 0 (ENET) */

    /* Example of supplying 40MHz to PER_CLK from PLL0 */
    MC_CGM.AC0_SC.B.SELCTL=2;                             /* Select PLL0 for PER_CLK, SD_CLK, SAR_CLK, DSPI_CLK0/1, and LIN_CLK domain */
    MC_CGM.AC0_DC0.B.DE=1;                                /* Enable Auxilliary Clock 0 divider 0 (general peripheral clock) */
    MC_CGM.AC0_DC0.B.DIV=3;                               /* Divide by = 3 + 1. 160MHz/4 = 40MHz */

    /* Example of supplying 16MHz to SDADC clock */
    MC_CGM.AC0_DC1.B.DE = 1;                              /* Enable Auxilliary Clock 0 divider 1 (SDADC clock) */
    MC_CGM.AC0_DC1.B.DIV=9;                               /* Divide PLL0 by 9 + 1 = 10 to get 160MHz / 10 = 16MHz*/

    /* Allow clock out to be viewed for debug purpose */
    MC_CGM.AC6_SC.B.SELCTL=2;                             /* Select PLL0 for CLKOUT domain */
    MC_CGM.AC5_SC.B.SELCTL=2;                             /* Select PLL0 for eTPU domain */
    //MC_CGM.AC6_SC.B.SELCTL=4;                             /* Select PLL1 for CLKOUT domain */
    MC_CGM.AC6_DC0.B.DE=1;                                /* Enable AC6 divider 0 (CLKOUT)*/
    MC_CGM.AC6_DC0.B.DIV=9;                               /* Divide by 10 to get 160MHz / 10 = 16MHz */

    /* Setting RUN Configuration Register ME_RUN_PC to supply clocks to all peripherals */
    /* Clock will not be supplied if corresponding MC_CGM.ACn_DCn.B.DE is cleared.
       Difference between MC_CGM.ACn_DCn.B.DE and ME_RUN_PC is that
       ME_RUN_PC needs mode transition to take effect */
    
    MC_ME.RUN_PC[0].R=0x000000FE;                         /* Peripheral ON in every mode */
    MC_ME.RUN_PC[1].R=0x000000FE;                         /* Peripheral ON in every mode */
    MC_ME.RUN_PC[2].R=0x000000FE;                         /* Peripheral ON in every mode */
    MC_ME.RUN_PC[3].R=0x000000FE;                         /* Peripheral ON in every mode */
    MC_ME.RUN_PC[4].R=0x000000FE;                         /* Peripheral ON in every mode */
    MC_ME.RUN_PC[5].R=0x000000FE;                         /* Peripheral ON in every mode */
    MC_ME.RUN_PC[6].R=0x000000FE;                         /* Peripheral ON in every mode */
    MC_ME.RUN_PC[7].R=0x000000FE;                         /* Peripheral ON in every mode */
    
    MC_ME.DRUN_MC.R = 0x001F00E4;                         /* Enable XOSC and PLLs - PLL1 is sysclk */
                                                          /* PLL1ON field is 24th bit instead of 23rd bit */
    
    /* Setup core0/core0s Vector address */
    MC_ME.CADDR[1].R = 0x01040001;
    MC_ME.CADDR[2].R = 0x01040001;
    
    /* Enable Cores - Will start on next mode transistion: */
    /* core 1 This is the boot core, we don't want to reset it on mode transition. */
//    MC_ME.CCTL[0].R = 0x00FE;                           /* core 1 = index 0 */

    /* core 0/core0s(Lockstep) - Prepare for this core to start on mode transition */
    MC_ME.CCTL[1].R = 0x00FE;                             /* core 0 = index 1 */
    MC_ME.CCTL[2].R = 0x00FE;                             /* core 0s = index 2 */
   
    /* PLL0 needs to be stabilized before turning on PLL1 if PLL0PHI1 is used as PLL1 clock source.
       Mode entry will handle PLL0 stabilization before enabling PLL1 */

    /* Mode change Re-enter the drun mode, to start core & PLL1 */
    MC_ME.MCTL.R = 0x30005AF0;                            /* Mode & Key */
    MC_ME.MCTL.R = 0x3000A50F;                            /* Mode & Key inverted */

    while(MC_ME.GS.B.S_MTRANS == 1);                      /* Wait for mode entry complete */
    while(MC_ME.GS.B.S_CURRENT_MODE != 0x3);              /* Check DRUN mode entered */

    /* Configure Pin for Clock out */
    /* This configuration should be done after PLL is stable */
    SIUL2.MSCR0_255[62].R = 0x12800007;                   /* PD14 as system clock out */
    
}


/*-----------------------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------------------*/
/*---                                   END OF FILES                                          ---*/
/*-----------------------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------------------*/
