/****************************************************************************/
/* Copyright 2010, © Bendor Research Pty. Ltd. All rights reserved.			*/
/* Permission is granted to use this software for any purpose whatsoever	*/
/* as long as this copyright notice is preserved. The code is provided		*/
/* "as is", with no explicit, implicit or implied warranty or guarantee		*/
/* of any kind and Bendor Research Pty. Ltd. can not be held liable for		*/
/* any loss or damages arising out of the use of this software.				*/
/****************************************************************************/
/*																			*/
/*	Include file describing the Philips LPC23xx system control block		*/
/*	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~		*/
/*																			*/
/*	2010 Mar	ZK		Original											*/
/*	2010 May	ZK		Modified to match NXP's names						*/
/*																			*/
/****************************************************************************/

#ifndef	LPC23xx_SCB
#define	LPC23xx_SCB

/*
*	System control block registers
*/

struct lpc23xx_scb {

	unsigned mamcr;			// 000 Memory acceleration module control
	unsigned mamtim;		// 004 Memory acceleration module timing
	unsigned _1[14];
	unsigned memmap;		// 040 Interrupt vector table mapping
	unsigned _2[15];
	unsigned pllcon;		// 080 PLL control
	unsigned pllcfg;		// 084 PLL configuration
	unsigned pllstat;		// 088 PLL status
	unsigned pllfeed;		// 08c PLL feed
	unsigned _3[12];
	unsigned pcon;			// 0c0 Power mode control
	unsigned pconp;			// 0c4 Peripheral power control
	unsigned _4[15];
	unsigned cclkcfg;		// 104 Clock control for CPU core
	unsigned usbclkcfg;		// 108 Clock control for USB controller
	unsigned clksrcsel;		// 10c Clock source select
	unsigned _5[12];
	unsigned extint;		// 140 External interrupt status flags
	unsigned intwake;		// 144 Wake-up interrupt select
	unsigned extmode;		// 148 External interrupt edge sensitive
	unsigned extpolar;		// 14c External interrupt active high
	unsigned _6[12];
	unsigned rsir;			// 180 Reset source identification
	unsigned _7;
	unsigned ahbcfg1;		// 188 AHB arbiter 1 config
	unsigned ahbcfg2;		// 18c AHB arbiter 2 config
	unsigned _8[4];
	unsigned scs;			// 1a0 Micellaneous system control
	unsigned irctrim;		// 1a4 Internal RC oscillator trim
	unsigned pclksel0;		// 1a8 Peripheral clock control 0
	unsigned pclksel1;		// 1ac Peripheral clock control 1
	unsigned _9[4];
	unsigned usbintst;		// 1c0 USB interrupt status
};

/****************************************************************************/
/*				General system control related definitions					*/
/****************************************************************************/

/*
*	Definitions for the reset source register
*/

#define	SCB_RSIR_POR	0x01		// Power-on reset
#define	SCB_RSIR_EXTR	0x02		// External reset
#define	SCB_RSIR_WDTR	0x04		// Watchdog reset
#define	SCB_RSIR_BODR	0x08		// Brown-out detect reset

/*
*	Definitions for the system control register
*/

#define	SCB_SCS_HSPIO	0x01		// High-speed mode GPIO ports 1 & 2
#define	SCB_SCS_EMCRD	0x02		// EMC resets are disabled
#define	SCB_SCS_MCIPW	0x08		// SD/MMC power enable
#define	SCB_SCS_SXTAL	0x00		// Slow xtal osc (1Mhz - 20MHz)
#define	SCB_SCS_FXTAL	0x10		// Slow xtal osc (15Mhz - 25MHz)
#define	SCB_SCS_OSCEN	0x20		// Crystal oscillator enable
#define	SCB_SCS_OSCST	0x40		// Osc. status (1:OK, 0:not ready)

/*
*	Definitions for the map_vect register
*	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/

#define	SCB_MEMMAP_BOOT		0		// Boot loader mode
#define	SCB_MEMMAP_FLASH	1		// User FLASH mode
#define	SCB_MEMMAP_RAM		2		// Internal RAM mode
#define	SCB_MEMMAP_EXT		3		// External memory mode

/****************************************************************************/
/*				Memory acceleration related definitions						*/
/****************************************************************************/

/*
*	Definitions for the mamcr register
*	Note that mamtim should be set to 1 - 7, the number of CCLK cycles
*	per fetch.
*/

#define	SCB_MAMCR_MODE_NONE	0x00	// Memory acceleration disabled
#define	SCB_MAMCR_MODE_PART	0x01	// Memory acceleration partially enab.
#define	SCB_MAMCR_MODE_FULL	0x02	// Memory acceleration fully enabled

/****************************************************************************/
/*						Clock related definitions							*/
/****************************************************************************/

/*
*	Definitions for the clock source register
*	This register selects the clock source for the PLL, or for the system
*	if the PLL is bypassed (i.e. PLL is not connected).
*/

#define	SCB_CLKSRCSEL_RCO	0x00	// PLL source is the 14MHz RC osc.
#define	SCB_CLKSRCSEL_OSC	0x01	// PLL source is the main crystal osc.
#define	SCB_CLKSRCSEL_RTC	0x02	// PLL soutce is the 32kHz RTC osc.

/*
*	Definitons for the CPU clock divider
*	This register holds the clock divisor for the CPU. It must be an
*	even number and the register should be written with that value - 1.
*	The permitted values range from 2 to 256.
*	If you pass 1 to this macro, then CCLK is the same as HCLK and you
*	must bypass the PLL.
*/

#define	SCB_CCLKCFG(n)			((n)-1)

/*
*	Definitons for the USB clock divider
*	This register holds the clock divisor for the USB. The division
*	factor must be even and the register should be written one less than
*	that. Writing 0 to the register turns division off, in which case the
*	HCLK frequency must be 48MHz +/- 500ppm. Allowed values are 2 - 16.
*/

#define	SCB_USBCLKCFG(n)		((n)-1)

/*
*	Definitions for pclksel0 and pclksel1 registers
*	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*	Each peripkeral has a 2-bit field in one of the registers, the content
*	of that field determines that the peripheral gets CCLK divided by 1, 2,
*	4 or 8. There are some exceptions, however:
*
*	- The RTC *must* not be clocked by CCLK, at least a div 2 must be used
*
*	- When selecting div 8, the CAN controllers will actually get CCLK / 6
*/

#define	SCB_PCLKSELX_DIV4		0		// Value for dividing by 4
#define	SCB_PCLKSELX_DIV1		1		// Value for dividing by 1
#define	SCB_PCLKSELX_DIV2		2		// Value for dividing by 2
#define	SCB_PCLKSELX_DIV8		3		// Value for dividing by 8 (or 6)
#define	SCB_PCLKSELX_MASK		3		// Value for masking

#define	SCB_PCLKSEL0_SFT_WDT	0		// Clock select for watchdog
#define	SCB_PCLKSEL0_SFT_TIM0	2		// Clock select for timer 0
#define	SCB_PCLKSEL0_SFT_TIM1	4		// Clock select for timer 1
#define	SCB_PCLKSEL0_SFT_SIO0	6		// Clock select for UART 0
#define	SCB_PCLKSEL0_SFT_SIO1	8		// Clock select for UART 1
#define	SCB_PCLKSEL0_SFT_PWM	12		// Clock select for PWM
#define	SCB_PCLKSEL0_SFT_I2C0	14		// Clock select for I2C 0
#define	SCB_PCLKSEL0_SFT_SPI	16		// Clock select for SPI
#define	SCB_PCLKSEL0_SFT_RTC	18		// Clock select for RTC
#define	SCB_PCLKSEL0_SFT_SSP1	20		// Clock select for SSP 1
#define	SCB_PCLKSEL0_SFT_DAC	22		// Clock select for D/A
#define	SCB_PCLKSEL0_SFT_ADC	24		// Clock select for A/D
#define	SCB_PCLKSEL0_SFT_CAN1	26		// Clock select for CAN 1
#define	SCB_PCLKSEL0_SFT_CAN2	28		// Clock select for CAN 2
#define	SCB_PCLKSEL0_SFT_ACF	30		// Clock select for CAN filter

#define	SCB_PCLKSEL1_SFT_BBR	0		// Clock select for RTC RAM
#define	SCB_PCLKSEL1_SFT_PIO	2		// Clock select for GPIO
#define	SCB_PCLKSEL1_SFT_PCB	4		// Clock select for PCB
#define	SCB_PCLKSEL1_SFT_I2C1	6		// Clock select for I2C 1
#define	SCB_PCLKSEL1_SFT_SSP0	10		// Clock select for SSP 0
#define	SCB_PCLKSEL1_SFT_TIM2	12		// Clock select for timer 2
#define	SCB_PCLKSEL1_SFT_TIM3	14		// Clock select for timer 3
#define	SCB_PCLKSEL1_SFT_SIO2	16		// Clock select for UART 2
#define	SCB_PCLKSEL1_SFT_SIO3	18		// Clock select for UART 3
#define	SCB_PCLKSEL1_SFT_I2C2	20		// Clock select for I2C 2
#define	SCB_PCLKSEL1_SFT_I2S	22		// Clock select for I2S
#define	SCB_PCLKSEL1_SFT_MCI	24		// Clock select for SD/MMC
#define	SCB_PCLKSEL1_SFT_SCB	28		// Clock select for SCB

/****************************************************************************/
/*						PLL related definitions								*/
/****************************************************************************/

/*
*	Definitions for the pllcon register
*/

#define	SCB_PLLCON_PLLE		0x01	// Enable PLL
#define	SCB_PLLCON_PLLC		0x02	// Connect PLL to system clock

/*
*	PLL configuration register
*	~~~~~~~~~~~~~~~~~~~~~~~~~~
*	The PLL will generate the frequency of fsys = ( fosc / N ) * 2 * M.
*	The valid range for fsys is 275MHz - 550MHz.
*	The valid range for fosc is 32kHz - 50MHz
*
*	In addition, you have to select an fsys so that:
*
*	-	If you use the USB, fsys must be an even multiple of 48MHz, which
*		limits you to 288MHz, 384MHz or 480MHz.
*
*	-	Also, fsys must be an even multiple of the CCLK frequency.
*
*	So, if you have USB, then you have the following choices (the first few
*	CPU divisor values are shown):
*
*		fsys		CCLK
*		288 MHz		72 MHz or 48 MHz or 36 MHz
*		384 MHz		64 MHz or 48 MHz or 38.4 MHz
*		480 MHz		60 MHz or 48 MHz or 40 MHz
*
*	Ideally, you want to minimise fsys.
*
*	The M-1 value is a 15-bit number and indeed you can set it to large
*	values, so that you can synthetise the clock from the RTC's 32kHz
*	crystal. Not all values are allowed, however, and you have to look
*	them up in the manual. It should be noted that the allowed values
*	do not make it possible to achieve exactly the three USB determined
*	fsys values, although the difference is in the few tens of ppm range.
*	You have took up the values in the manual, they are not listed here.
*
*	The N-1 value is an 8-bit nuber, but you must not use more than 31.
*
*	fosc can be as high as 50MHz, however, the on-board crystal oscillator
*	itself can only work between 4MHz and 24MHz.
*/

#define	SCB_PLLCFG_MSEL(m)	((m)-1)			// Sets the M value, 6 - 512
#define	SCB_PLLCFG_NSEL(n)	(((n)-1)<<16)	// Sets the N value, 1 - 32

/*
*	Definitions for the pll_stat register
*	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/

#define	SCB_PLLSTAT_MSEL	0x00007fff		// Mask for the M - 1 value
#define	SCB_PLLSTAT_NSEL	0x00ff0000		// Mask for the N - 1 value
#define	SCB_PLLSTAT_PLLE	0x01000000		// PLL is enabled
#define	SCB_PLLSTAT_PLLC	0x02000000		// PLL is connected
#define	SCB_PLLSTAT_PLOCK	0x04000000		// PLL is locked

/*
*	Definitions for the pll_feed register
*	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*	To make the PLL work, you have to set it up, wait until it locks,
*	feed it twice (in the proper order) and then you can connect it.
*/

#define	SCB_PLLFEED_FOOD1	0xaa
#define	SCB_PLLFEED_FOOD2	0x55

/****************************************************************************/
/*					Power control related definitions						*/
/****************************************************************************/

/*
*	Definitions for the power control register
*/

#define	SCB_PCON_PM0		0x01		// Power mode control bit 0
#define	SCB_PCON_PM1		0x02		// Power mode control bit 1
#define	SCB_PCON_PM2		0x80		// Power mode control bit 2
#define	SCB_PCON_PM_MSK		0x83		// Power mode control mask
#define	SCB_PCON_PM_NORM	0x00		// Normal operation
#define	SCB_PCON_PM_IDLE	0x01		// Idle mode
#define	SCB_PCON_PM_SLEP	0x81		// Sleep mode
#define	SCB_PCON_PM_DOWN	0x02		// Power-down mode
#define	SCB_PCON_PM_DEEP	0x82		// Power-down mode
#define	SCB_PCON_BODD		0x04		// Disable brown-out during pwrdown
#define	SCB_PCON_BOGD		0x08		// Disable brown-out overall
#define	SCB_PCON_BORD		0x10		// Disable brown-out reset

/*
*	Definitions for the peripheral power control register
*	This register enables the 'power' (well, the clock, actually) to
*	the on-chip peripherals.
*/

#define	SCB_PCONP_TIM0	0x00000002		// Timer 0 power enable
#define	SCB_PCONP_TIM1	0x00000004		// Timer 1 power enable
#define	SCB_PCONP_SIO0	0x00000008		// UART 0 power enable
#define	SCB_PCONP_SIO1	0x00000010		// UART 1 power enable
#define	SCB_PCONP_PWM	0x00000040		// PWM power enable
#define	SCB_PCONP_I2C0	0x00000080		// I2C bus 0 power enable
#define	SCB_PCONP_SPI	0x00000100		// SPI controller power enable
#define	SCB_PCONP_RTC	0x00000200		// Real-time clock power enable
#define	SCB_PCONP_SSP1	0x00000400		// SSP controller 1 power enable
#define	SCB_PCONP_EMC	0x00000800		// Ext. RAM I/F power enable
#define	SCB_PCONP_ADC	0x00001000		// A/D converter power enable
#define	SCB_PCONP_CAN0	0x00002000		// CAN controller 0 power enable
#define	SCB_PCONP_CAN1	0x00004000		// CAN controller 1 power enable
#define	SCB_PCONP_I2C1	0x00080000		// I2C bus 1 power enable
#define	SCB_PCONP_SSP0	0x00200000		// SSP controller 0 power enable
#define	SCB_PCONP_TIM2	0x00400000		// Timer 2 power enable
#define	SCB_PCONP_TIM3	0x00800000		// Timer 3 power enable
#define	SCB_PCONP_SIO2	0x01000000		// UART 2 power enable
#define	SCB_PCONP_SIO3	0x02000000		// UART 3 power enable
#define	SCB_PCONP_I2C2	0x04000000		// I2C bus 2 power enable
#define	SCB_PCONP_I2S	0x08000000		// I2S interface power enable
#define	SCB_PCONP_MCI	0x10000000		// SD/MMC I/F power enable
#define	SCB_PCONP_DMA	0x20000000		// DMA controller power enable
#define	SCB_PCONP_ETH	0x40000000		// Ethernet controller power enable
#define	SCB_PCONP_USB	0x80000000		// USB controller power enable

/****************************************************************************/
/*					 Interrupt related definitions							*/
/****************************************************************************/

/*
*	Definitiosn for the ext???? registers
*/

#define	SCB_EXT_EINT0			0x0001		// External interrupt 0
#define	SCB_EXT_EINT1			0x0002		// External interrupt 1
#define	SCB_EXT_EINT2			0x0004		// External interrupt 2
#define	SCB_EXT_EINT3			0x0008		// External interrupt 3

/*
*	Definitions for the intwake register
*/

#define	SCB_INTWAKE_EXTWAKE0	0x0001		// External interrupt 0
#define	SCB_INTWAKE_EXTWAKE1	0x0002		// External interrupt 1
#define	SCB_INTWAKE_EXTWAKE2	0x0004		// External interrupt 2
#define	SCB_INTWAKE_EXTWAKE3	0x0008		// External interrupt 3
#define	SCB_INTWAKE_ETHWAKE		0x0010		// Wake up on Ethernet activity
#define	SCB_INTWAKE_USBWAKE		0x0020		// Wake up on USB activity
#define	SCB_INTWAKE_CANWAKE		0x0040		// Wake up on CAN activity
#define	SCB_INTWAKE_GPIOOWAKE	0x0080		// Wake up on port 0 edge detect
#define	SCB_INTWAKE_GPIO2WAKE	0x0080		// Wake up on port 2 edge detect
#define	SCB_INTWAKE_BODWAKE		0x4000		// Wake up on brown-out detect
#define	SCB_INTWAKE_RTCWAKE		0x8000		// Wake up on RTC request

/*
*	Definitions for the usbintst register
*/

#define	SCB_USBINTST_REQ_LP		0x00000001	// Low priority interrupt status
#define	SCB_USBINTST_REQ_HP		0x00000002	// High priority interrupt status
#define	SCB_USBINTST_REQ_DMA	0x00000004	// DMA interrupt status
#define	SCB_USBINTST_HOST_INT	0x00000008	// Host interrupt status
#define	SCB_USBINTST_ATX_INT	0x00000010	// External ATX interrupt status
#define	SCB_USBINTST_OTG_INT	0x00000020	// OTG interrupt status
#define	SCB_USBINTST_I2C_INT	0x00000040	// OTG I2C interrupt status
#define	SCB_USBINTST_NEED_CLK	0x00000100	// USB should be clocked
#define	SCB_USBINTST_EN_USB_INT	0x80000000	// Enable all USB interrupts

/****************************************************************************/
/*				AHB arbiter configuratuion									*/
/****************************************************************************/

#define	SCB_AHB_SCHEDULER		0x00000001	// Scheduler mode
#define	SCB_AHB_SCHEDULER_RR	0x00000001	// Scheduler mode round robin
#define	SCB_AHB_SCHEDULER_BP	0x00000000	// Scheduler mode by priority
#define	SCB_AHB_BREAK_BURST(n)	((n)<<1)	// Defined burst break policy
#define	SCB_AHB_QUANT_TYPE		0x00000008	// Quantum type
#define	SCB_AHB_QUANT_TYPE_CLK	0x00000000	// Quantum is AHB clock
#define	SCB_AHB_QUANT_TYPE_CYC	0x00000008	// Quantum is AHB cycle
#define	SCB_AHB_QUANT_SIZE(n)	((n)<<4)	// Rearbitration length (in quanta)
#define	SCB_AHB_DEFLT_MASTER(n)	((n)<<8)	// Default master
#define	SCB_AHB_EP1(n)			((n)<<12)	// External priority for master 1
#define	SCB_AHB_EP2(n)			((n)<<16)	// External priority for master 2
#define	SCB_AHB_EP3(n)			((n)<<20)	// External priority for master 3
#define	SCB_AHB_EP4(n)			((n)<<24)	// External priority for master 4

/*
*	Burst break control values
*/

#define	SCB_AHB_BREAK_BURST_ALL		0	// Break all defined bursts
#define	SCB_AHB_BREAK_BURST_4		1	// Break defined bursts over 4 beats
#define	SCB_AHB_BREAK_BURST_8		2	// Break defined bursts over 8 beats
#define	SCB_AHB_BREAK_BURST_NO		3	// Do not break defined bursts

/*
*	Rearbitration control values
*/

#define	SCB_AHB_QUANT_SIZE_1		0	// Rearbitrate after 1 quantum
#define	SCB_AHB_QUANT_SIZE_2		1	// Rearbitrate after 2 quanta
#define	SCB_AHB_QUANT_SIZE_4		2	// Rearbitrate after 4 quanta
#define	SCB_AHB_QUANT_SIZE_8		3	// Rearbitrate after 8 quanta
#define	SCB_AHB_QUANT_SIZE_16		4	// Rearbitrate after 16 quanta
#define	SCB_AHB_QUANT_SIZE_32		5	// Rearbitrate after 32 quanta
#define	SCB_AHB_QUANT_SIZE_64		6	// Rearbitrate after 64 quanta
#define	SCB_AHB_QUANT_SIZE_128		7	// Rearbitrate after 128 quanta
#define	SCB_AHB_QUANT_SIZE_256		8	// Rearbitrate after 256 quanta
#define	SCB_AHB_QUANT_SIZE_512		9	// Rearbitrate after 512 quanta
#define	SCB_AHB_QUANT_SIZE_1K		10	// Rearbitrate after 1024 quanta
#define	SCB_AHB_QUANT_SIZE_2K		11	// Rearbitrate after 2048 quanta
#define	SCB_AHB_QUANT_SIZE_4K		12	// Rearbitrate after 4096 quanta
#define	SCB_AHB_QUANT_SIZE_8K		13	// Rearbitrate after 8192 quanta
#define	SCB_AHB_QUANT_SIZE_16K		14	// Rearbitrate after 16384 quanta
#define	SCB_AHB_QUANT_SIZE_INF		15	// Infinite transfer, no rearbitration

/*
*	Master definitions, depends on the arbiter
*/

#define	SCB_AHB1_CPU				1		// CPU
#define	SCB_AHB1_DMA				2		// The general purpose DMA engine
#define	SCB_AHB1_BUS				3		// Request from the AHB2 bus
#define	SCB_AHB1_USB				4		// The USB controller's DMA

#define	SCB_AHB1_PRIO_CPU(n)	((n)<<12)	// External priority for CPU
#define	SCB_AHB1_PRIO_DMA(n)	((n)<<16)	// External priority for GPDMA
#define	SCB_AHB1_PRIO_BUS(n)	((n)<<20)	// External priority for AHB2
#define	SCB_AHB1_PRIO_USB(n)	((n)<<24)	// External priority for USB

#define	SCB_AHB2_CPU				1		// CPU
#define	SCB_AHB2_ETH				2		// Ethernet controller
#define	SCB_AHB2_PRIO_CPU(n)	((n)<<12)	// External priority for CPU
#define	SCB_AHB2_PRIO_ETH(n)	((n)<<16)	// External priority for GPDMA

/*
*	SCB instance
*/

static volatile struct lpc23xx_scb * const lpc_scb = (void *) 0xe01fc000;

#endif

