/*****************************************************************************
 *   target.c:  Target C file for Philips LPC29xx Family Microprocessors
 *
 *   Copyright(C) 2007, NXP Semiconductor
 *   All rights reserved.
 *
 *   History
 *   2007.09.01  ver 1.00    Preliminary version, first Release
 *   2009.04.15  ver 2.00    Updated TargetResetInit
 *
 *
 ****************************************************************************
 * Software that is described herein is for illustrative purposes only
 * which provides customers with programming information regarding the
 * products. This software is supplied "AS IS" without any warranties.
 * NXP Semiconductors assumes no responsibility or liability for the
 * use of the software, conveys no license or title under any patent,
 * copyright, or mask work right to the product. NXP Semiconductors
 * reserves the right to make changes in the software without
 * notification. NXP Semiconductors also make no representation or
 * warranty that such application will be suitable for the specified
 * use without further testing or modification.
 *****************************************************************************/

#include "LPC29xx.h"
#include "type.h"
#include "irq.h"
#include "target.h"

DWORD RGU_Status[6];
DWORD RGU_SRC_Status[23];

void Release_Security(void)
{ 
    SEC_DIS = 1;	// Seting this bit will diable security
    // normally enabled by the flash index sector
    return;
}


/******************************************************************************
** Function name:		TargetInit
**
** Descriptions:		Initialize the target board; it is called in a necessary
**									place, change it as needed
**
** parameters:			None
** Returned value:		None
**
******************************************************************************/
void TargetInit(void)
{
    /* Add your codes here */
    return;
}

/******************************************************************************
** Function name:	GPIOResetInit
**
** Descriptions:	Initialize the target board before running the main()
**					function; User may change it as needed, but may not
**					delete it.
**
** parameters:		None
** Returned value:	None
**
******************************************************************************/
void GPIOResetInit( void )
{
    return;
}

/******************************************************************************
** Function name:	TargetResetInit
**
** Descriptions:	Initialize the target board before running the main()
**								function; User may change it as needed, but may not
**								delete it.
**
** parameters:		None
** Returned value:	None
**
******************************************************************************/
void TargetResetInit(void)
{
	unsigned long i;
	for(i=0;i<0xFFFFF;i++)NOP;
	
	/* (re-) Enable the OSC */
	CGU_OSC_CTRL = (0x1<<2) | (0x1<<0);
	/* Wait for OSC to start up */
	while ( !(CGU_OSC_STAT & (0x1<<0))){NOP;}
	
	/* Initialize and disable all interrupts */
	init_VIC();
	
	/* Enable the Flash and set to Async read mode (Flash/EEPROM chapter in UM) */
	FCTR = FS_DCR | FS_CS;
	/* Setup the wait-states for the Flash reading and writing */
	FBWST = SPECALWAYS | 0x04;
	
	/* Sys clk config, source is Xtal - 16MHz on Hitex LPC2929/39 board */
	SYS_CLK_CONF = CLK_SEL_XTAL | AUTOBLK;
	
	/* PLL, 3-phase output control enable, and power down PLL. */
	CGU_PLL_CTRL = P23EN | PLL_PD;
	/* PLL, MSEL=16, 3-phase output control enable, power down PLL. */
	CGU_PLL_CTRL = PLL_XTAL_SEL | (PLL_M_VALUE<<MSEL_SHIFT) | P23EN | PLL_PD;
	/* PLL, MSEL=16, 3-phase output control enable, PLL normal operation. */
	CGU_PLL_CTRL = PLL_XTAL_SEL | (PLL_M_VALUE<<MSEL_SHIFT) | P23EN;
	                   
	/* Check lock bit, if unlocked, PLL_LOCK is always 0 */
	while ( !(CGU_PLL_STAT & PLL_LOCK)){NOP;}
	/* Check clock detection register to make sure PLL is present now. */
	while ( !(CGU_RDET & PLL_PRESENT)){NOP;}
	
	/******************************************************************************/
	/* BASE CLOCK SETUP 																													*/
	/******************************************************************************
	** 	Based on if USB used or not, the multiplier is set differently.
	**	Hitex LPC2929/39 board:
	**		- XTAL 16 MHz
	**		- CGU0:
	**				- PLL_M_VALUE = 15 (see target.h) --> PLL = 16*15 = 240MHz
	**				-	e.g. 	SYS_CLK_CONF = DIV2 --> CPU_CLK or BASE_SYS_CLK = 120MHz 
	**		- CGU1:		
	**				- USE ICLK1, connect to XTAL divided by 2, so ICLK1 = 16/2 = 8MHz
	**				- PLL1_M_VALUE = 6 (see target.h) -->	PLL1 = 8*6 = 48MHz
	**				- USB_CLK_CONF = DIV1 --> BASE_USB_CLK = PLL/4 = 48MHz
	**				- USB_I2C_CLK_CONF is connected to XTAL --> BASE_USB_I2C_CLK = 16/2
	*******************************************************************************/

	/******************************************************************************/
	/* CGU0 setup 																																*/		
	/******************************************************************************/
	/* PLL is 240MHz, SYS_CLK and TMR_CLK is 120MHz */
	SYS_CLK_CONF 		= CLK_SEL_PLL | AUTOBLK | DIV2; /* BASE_SYS_CLK 	*/
	IVNSS_CLK_CONF 	= CLK_SEL_PLL | AUTOBLK | DIV2;	/* BASE_IVNSS_CLK */
	MSCSS_CLK_CONF 	= CLK_SEL_PLL | AUTOBLK | DIV2;	/* BASE_MSCSS_CLK */
	UART_CLK_CONF 	= CLK_SEL_PLL | AUTOBLK | DIV2;	/* BASE_UART_CLK 	*/
	TMR_CLK_CONF 		= CLK_SEL_PLL | AUTOBLK | DIV2;	/* BASE_TMR_CLK 	*/
	
	/******************************************************************************/
	/* CGU1 setup 																																*/		
	/******************************************************************************/
	/* ICLK1 going to CGU1 is the same as XTAL clock divided by 2 */
	ICLK1_CLK_CONF = CLK_SEL_XTAL | AUTOBLK | DIV2;
	
	/* ICLK1 as CGU1 PLL input. USB clock configuration only, for CGU1 */
	/* CGU1 PLL, 3-phase output control enable, and power down PLL. */
	CGU1_PLL_CTRL = P23EN | PLL_PD;
	
	/* PLL, MSEL=6, 3-phase output control enable, power down PLL. */
	/* Bit 24 is set to one, the name(PLL_XTAL_SEL) doesn't match, it's
	actually the ICLK1 from CGU0. */
	CGU1_PLL_CTRL = PLL_XTAL_SEL | (PLL1_M_VALUE<<MSEL_SHIFT) | P23EN | PLL_PD;
	/* PLL, MSEL=16, 3-phase output control enable, PLL normal operation. */
	CGU1_PLL_CTRL = PLL_XTAL_SEL | (PLL1_M_VALUE<<MSEL_SHIFT) | P23EN;
	
	/* Check lock bit, if unlocked, PLL_LOCK is always 0 */
	while (!(CGU1_PLL_STAT & PLL_LOCK)){NOP;}
	/* Check clock detection register to make sure PLL is present now. */
	while (!(CGU1_RDET & PLL_PRESENT)){NOP;}
	
	/* USB clock is 48Mhz, 48/1=48Mhz */
	USB_CLK_CONF = CLK_SEL_PLL | AUTOBLK | DIV1;
	/* USB I2C clock uses ICLK1(16Mhz) from CGU0, I2C clock is 8Mhz(/2) */
	USB_I2C_CLK_CONF = CLK_SEL_XTAL | AUTOBLK | DIV1;
	/* OUT clock from CGU1 is 96Mhz */
	OUT_CLK_CONF = CLK_SEL_PLL | AUTOBLK | DIV2;

	/* Add your codes here */
	GPIOResetInit();
	return;
}

/*****************************************************************************
** Function name:		Get_RGU_Status
**
** Descriptions:		Get reset status from RGU.(for RGU debugging only)
**
** parameters:			None
** Returned value:		None
**
*****************************************************************************/
void Get_RGU_Status( void )
{
    RGU_Status[0] = RGU_RESET_STAT0;
    RGU_Status[1] = RGU_RESET_STAT1;
    RGU_Status[2] = RGU_RESET_STAT2;
    RGU_Status[3] = RGU_RESET_STAT3;

    RGU_Status[4] = RGU_RST_ACTIVE_STAT0;
    RGU_Status[5] = RGU_RST_ACTIVE_STAT1;
    return;
}

/*****************************************************************************
** Function name:		Get_RGU_SRC_Status
**
** Descriptions:		Get reset source status from RGU.
**						(for RGU debugging only)
**
** parameters:			None
** Returned value:		None
**
*****************************************************************************/
void Get_RGU_SRC_Status( void )
{
    RGU_SRC_Status[0] = RGU_RST_SRC;
    RGU_SRC_Status[1] = RGU_PCR_RST_SRC;
    RGU_SRC_Status[2] = RGU_COLD_RST_SRC;
    RGU_SRC_Status[3] = RGU_WARM_RST_SRC;
    RGU_SRC_Status[4] = RGU_SCU_RST_SRC;

    RGU_SRC_Status[5] = RGU_CFID_RST_SRC;
    RGU_SRC_Status[6] = RGU_FMC_RST_SRC;
    RGU_SRC_Status[7] = RGU_EMC_RST_SRC;
    RGU_SRC_Status[8] = RGU_SMC_SRC;
    RGU_SRC_Status[9] = RGU_GESS_A2V_RST_SRC;

    RGU_SRC_Status[10] = RGU_PESS_A2V_RST_SRC;
    RGU_SRC_Status[11] = RGU_GPIO_RST_SRC;
    RGU_SRC_Status[12] = RGU_UART_RST_SRC;
    RGU_SRC_Status[13] = RGU_TMR_RST_SRC;
    RGU_SRC_Status[14] = RGU_SPI_RST_SRC;

    RGU_SRC_Status[15] = RGU_IVNSS_A2V_RST_SRC;
    RGU_SRC_Status[16] = RGU_IVNSS_CAN_RST_SRC;
    RGU_SRC_Status[17] = RGU_MSCSS_A2V_RST_SRC;
    RGU_SRC_Status[18] = RGU_MSCSS_PWM_RST_SRC;
    RGU_SRC_Status[19] = RGU_MSCSS_ADC_RST_SRC;

    RGU_SRC_Status[20] = RGU_MSCSS_TMR_RST_SRC;
    RGU_SRC_Status[21] = RGU_VIC_RST_SRC;
    RGU_SRC_Status[22] = RGU_AHB_RST_SRC;
    return;
}

/******************************************************************************
** Function name:	IRAM1SanityCheck
**
** Descriptions:	Verify IRAM Instance 1 access.
**					If fail, spin forever.
**
** parameters:		None
** Returned value:	None
**
******************************************************************************/
void IRAM1SanityCheck( void )
{
    volatile BYTE *wrb_ptr, *rdb_ptr;
    volatile DWORD *wr_ptr, *rd_ptr;
    DWORD i;

    wrb_ptr = (BYTE *)IRAM1_BASE_ADDR;
    for ( i = 0; i < IRAM1_SIZE; i++ )
        *wrb_ptr++ = 0x55;

    rdb_ptr = (BYTE *)IRAM1_BASE_ADDR;
    for ( i = 0; i < IRAM1_SIZE; i++ )
    {
        if ( *rdb_ptr++ != 0x55 )
            while ( 1 );		/* Fatal error */
    }

    wr_ptr = (DWORD *)IRAM1_BASE_ADDR;
    for ( i = 0; i < IRAM1_SIZE/4; i++ )
        *wr_ptr++ = 0x12345678;

    rd_ptr = (DWORD *)IRAM1_BASE_ADDR;
    for ( i = 0; i < IRAM1_SIZE/4; i++ )
    {
        if ( *rd_ptr++ != 0x12345678 )
            while ( 1 );		/* Fatal error */
    }
    return;
}

/******************************************************************************
**                            End Of File
******************************************************************************/
