/*******************************************************************************
* Copyright 2009, Cypress Semiconductor Corporation.  All rights reserved.
* You may use this file only in accordance with the license, terms, conditions, 
* disclaimers, and limitations in the end user license agreement accompanying 
* the software package with which this file was provided.
********************************************************************************/

/* This header exports the configuration method(s) defined by this file. */
#include <cyfitter_cfg.h>

/* This header includes all of the necessary type definitions. */
#include <cytypes.h>

/* Standard system includes */
#if !defined(__ARMCC_VERSION)
#include <string.h>
#endif

/* This header contains all of the macros necessary for accessing registers on the device */
#include <cydevice.h>

/* This header contains all of the macros defined based on the users choices in the System DWR as well as instance
   based macros for register access. */
#include <cyfitter.h>

/* This header contains functions needed to enable the digital array */
#include <CyLib.h>

/* The section below contains all of the data used to initialize the device. */
#include <CyDmac.h>

#if defined(__C51__) || defined(__CX51__)
#define CYCODE code
#define CYDATA data
#define CYXDATA xdata
#define CYFAR far
extern void cymemzero(void CYFAR *addr, uint16 size);
extern void cyconfigcpy(uint16 size, const void CYFAR *src, void CYFAR *dest) small;
extern void cyconfigcpycode(uint16 size, const void CYCODE *src, void CYFAR *dest);
#define CYMEMZERO(a,c) cymemzero((a),(c))
#define CYCONFIGCPY(d,s,c) cyconfigcpy((c),(s),(d))
#define CYCONFIGCPYCODE(d,s,c) cyconfigcpycode((c),(s),(d))
#else
#define CYCODE
#define CYDATA
#define CYXDATA
#define CYFAR
#define CYMEMZERO(a,c) cymemset((a),0,(c))
#define CYCONFIGCPY(d,s,c) cymemcpy((d),(s),(c))
#define CYCONFIGCPYCODE(d,s,c) cymemcpy((d),(s),(c))
#endif

/* Disable warnings about pointer truncation and pointer to integer conversion */
#if defined(__ARMCC_VERSION)

#pragma diag_suppress 767,69
#elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
#endif

#if defined(__GNUC__) || defined(__ARMCC_VERSION)
#define CYPACKED __attribute__ ((packed))
#define DMAINITSEC __attribute__ ((section (".dma_init")))
#if defined(__ARMCC_VERSION)
#define CY_CFG_MEMORY_BARRIER() __memory_changed()
#else
#define CY_CFG_MEMORY_BARRIER() __sync_synchronize()
#endif
#else
#define CYPACKED
#define DMAINITSEC
#define CY_CFG_MEMORY_BARRIER()
#endif

#define CYDATADECL(name) const uint8 CYCODE name

typedef struct {
	void CYFAR *address;
	uint16 size;
} CYPACKED cfg_memset_t;

typedef struct {
	void CYFAR *dest;
	const void CYCODE *src;
	uint16 size;
} CYPACKED cfg_memcpy_t;

#define CFG_MEMSET_COUNT (sizeof(cfg_memset_list)/sizeof(*cfg_memset_list))
static const cfg_memset_t CYCODE cfg_memset_list [] = {
	/* address, size */
	{(void CYFAR *)(CYDEV_IO_PRT_PRT0_DR), 112},
	{(void CYFAR *)(CYDEV_IO_PRT_PRT12_DR), 16},
	{(void CYFAR *)(CYDEV_UCFG_B0_P0_U0_BASE), 4096},
	{(void CYFAR *)(CYDEV_UCFG_B1_P2_U0_BASE), 2048},
	{(void CYFAR *)(CYDEV_UCFG_DSI0_BASE), 2560},
	{(void CYFAR *)(CYDEV_UCFG_DSI12_BASE), 512},
};

#define CY_CFG_BASE_ADDR_COUNT 6
typedef struct
{
	uint8 offset;
	uint8 value;
} CYPACKED cy_cfg_addrvalue_t;

static const uint32 CYCODE cy_cfg_addr_table[] = {
	0x40014003u, /* Base address: 0x40014000 Count: 3 */
	0x40014104u, /* Base address: 0x40014100 Count: 4 */
	0x40014202u, /* Base address: 0x40014200 Count: 2 */
	0x40014304u, /* Base address: 0x40014300 Count: 4 */
	0x4001480Fu, /* Base address: 0x40014800 Count: 15 */
	0x4001490Fu, /* Base address: 0x40014900 Count: 15 */
};

static const cy_cfg_addrvalue_t CYCODE cy_cfg_data_table[] = {
	{0x33u, 0x20u},
	{0x35u, 0x80u},
	{0xCCu, 0x30u},
	{0x9Du, 0x80u},
	{0xA7u, 0x20u},
	{0xC6u, 0x10u},
	{0xCAu, 0x20u},
	{0x9Du, 0x80u},
	{0xA7u, 0x20u},
	{0x33u, 0x40u},
	{0x9Du, 0x80u},
	{0xA7u, 0x20u},
	{0xCCu, 0x10u},
	{0x23u, 0x20u},
	{0x27u, 0x40u},
	{0x28u, 0x04u},
	{0x2Bu, 0x20u},
	{0x2Du, 0x88u},
	{0x30u, 0x04u},
	{0x33u, 0x10u},
	{0x35u, 0x08u},
	{0x47u, 0x30u},
	{0x9Du, 0x80u},
	{0x9Fu, 0x40u},
	{0xA7u, 0x20u},
	{0xC8u, 0xC0u},
	{0xCAu, 0xF0u},
	{0xCCu, 0xD0u},
	{0x23u, 0x40u},
	{0x24u, 0x40u},
	{0x27u, 0x04u},
	{0x28u, 0x04u},
	{0x2Eu, 0x80u},
	{0x30u, 0x14u},
	{0x37u, 0x04u},
	{0x3Bu, 0x40u},
	{0x3Cu, 0x40u},
	{0x44u, 0x10u},
	{0x46u, 0x80u},
	{0xC8u, 0xE0u},
	{0xCAu, 0x30u},
	{0xCCu, 0xD0u},
	{0xCEu, 0x30u},
};


/* IDMUX_IRQ Address: CYDEV_IDMUX_IRQ_CTL0 Size (bytes): 8 */
static CYDATADECL(BS_IDMUX_IRQ_VAL) [] DMAINITSEC = {
	0x0A, 0x00, 0x00, 0x00, 0x02, 0x88, 0x22, 0xAA};

#define CFG_MEMCPY_COUNT (sizeof(cfg_memcpy_list)/sizeof(*cfg_memcpy_list))
static const cfg_memcpy_t CYCODE cfg_memcpy_list [] = {
	/* dest, src, size */
	{(void CYFAR *)(CYDEV_IDMUX_IRQ_CTL0), BS_IDMUX_IRQ_VAL, 8},
};


#if defined(__C51__) || defined(__CX51__)
extern void cfg_write_bytes_code(void CYCODE *table);
extern void cfg_write_bytes(void CYFAR *table);
#else
/* For 32-bit little-endian architectures */
static void cfg_write_bytes32(void)
{
	unsigned int i, j = 0;
	for (i = 0; i < CY_CFG_BASE_ADDR_COUNT; i++)
	{
		uint32 baseAddr = cy_cfg_addr_table[i];
		uint8 count = baseAddr & 0xFFu;
		baseAddr &= 0xFFFFFF00u;
		while (count--)
		{
			CY_SET_XTND_REG8((void CYFAR *)(baseAddr + cy_cfg_data_table[j].offset), cy_cfg_data_table[j].value);
			j++;
		}
	}
}
#endif

#if defined(__C51__) || defined(__CX51__)
#define CYMEMZERO8(a,c) cymemzero((a),(c))
#define CYCONFIGCPY8(d,s,c) cyconfigcpy((c),(s),(d))
#define CYCONFIGCPYCODE8(d,s,c) cyconfigcpycode((c),(s),(d))
#else
#if defined(__GNUC__) || defined(__ARMCC_VERSION)
__attribute__ ((unused))
#endif
static void cymemzero8(void *addr, unsigned int count)
{
	uint8 *addr8 = (uint8 *)addr;
	while (count--)
	{
		*addr8 = 0;
		addr8++;
	}
}

#if defined(__GNUC__) || defined(__ARMCC_VERSION)
__attribute__ ((unused))
#endif
static void cymemcpy8(void *dest, const void *src, unsigned int count)
{
	uint8 *dest8 = (uint8 *)dest;
	const uint8 *src8 = (const uint8 *)src;

	while (count--)
	{
		*dest8 = *src8;
		dest8++;
		src8++;
	}
}

#define CYMEMZERO8(a,c) cymemzero8((a),(c))
#define CYCONFIGCPY8(d,s,c) cymemcpy8((d),(s),(c))
#define CYCONFIGCPYCODE8(d,s,c) cymemcpy8((d),(s),(c))
#endif

static void ClockSetup(void)
{
	reg32  timeout;
	reg32* timeout_p = &timeout;
	reg8   pllLock;
	CY_SET_XTND_REG8((void CYFAR *)(CYDEV_SLOWCLK_ILO_CR0), 0x04);
	CY_SET_XTND_REG8((void CYFAR *)(CYDEV_CLKDIST_CR), 0x00);
	CY_SET_XTND_REG8((void CYFAR *)(CYDEV_MFGCFG_IMO_TR1), (CY_GET_XTND_REG8(CYDEV_FLSHID_BASE + 0x10F)));
	CY_SET_XTND_REG8((void CYFAR *)(CYDEV_FASTCLK_IMO_CR), 0x52);
	CY_SET_XTND_REG8((void CYFAR *)(CYDEV_CLKDIST_CR), 0x10);
	CY_SET_XTND_REG16((void CYFAR *)(CYDEV_CLKDIST_MSTR0), 0x0000);
	CY_SET_XTND_REG16((void CYFAR *)(CYDEV_FASTCLK_PLL_P), 0x0F10);
	CY_SET_XTND_REG8((void CYFAR *)(CYDEV_CLKDIST_CR), 0x10);
	CY_SET_XTND_REG16((void CYFAR *)(CYDEV_FASTCLK_PLL_CFG0), 0x1051);
	pllLock = 0;
	for (timeout = 304; *timeout_p && (pllLock != 0x03u); timeout--) { pllLock = 0x03u & ((pllLock << 1) | ((CY_GET_XTND_REG8(CYDEV_FASTCLK_PLL_SR) & 0x01u) >> 0)); }
	CY_SET_XTND_REG8((void CYFAR *)(CYDEV_CLKDIST_BCFG0), 0x00);
	CY_SET_XTND_REG16((void CYFAR *)(CYDEV_CLKDIST_BCFG2), 0x0048);
	CY_SET_XTND_REG8((void CYFAR *)(CYDEV_CLKDIST_LD), 0x02);
}

/* Analog API Functions */
void AnalogSetDefault(void)
{
	CY_SET_XTND_REG8(CYDEV_ANAIF_CFG_PUMP_CR0, 0x44);
}

#define CY_AMUX_UNUSED CYDEV_BOOST_SR

/* Digital routing enable Functions */
static void EnableDigitalRouting() {
	CY_SET_XTND_REG8(CYDEV_UCFG_BCTL0_BANK_CTL, CY_GET_XTND_REG8(CYDEV_UCFG_BCTL0_BANK_CTL) | 0x02);
	CY_SET_XTND_REG8(CYDEV_UCFG_BCTL1_BANK_CTL, CY_GET_XTND_REG8(CYDEV_UCFG_BCTL1_BANK_CTL) | 0x02);
}

/* This function is called by the start-up code for the selected device. */
void cyfitter_cfg(void)
{
	uint8 CYDATA i;

#ifdef CYGlobalIntDisable
	CYGlobalIntDisable;
#endif

	CY_SET_XTND_REG8((void CYFAR *)(CYDEV_CACHE_CC_CTL), ((CYDEV_INSTRUCT_CACHE_ENABLED) ? 0x40 : 0x41));
	CY_SET_XTND_REG8((void CYFAR *)(CYDEV_PHUB_CH0_BASIC_CFG), 0x00);
	CY_SET_XTND_REG8((void CYFAR *)(CYDEV_PHUB_CH1_BASIC_CFG), 0x00);

	CY_SET_XTND_REG8(CYDEV_MFGCFG_MLOGIC_DBG_DBE, (CY_GET_XTND_REG8(CYDEV_MFGCFG_MLOGIC_DBG_DBE) | 0x01));
	for (i = 0; i < CFG_MEMSET_COUNT; i++)
	{
		const cfg_memset_t CYCODE * CYDATA ms = &cfg_memset_list[i];
		CYMEMZERO(ms->address, ms->size);
	}

	for (i = 0; i < CFG_MEMCPY_COUNT; i++)
	{
		const cfg_memcpy_t CYCODE * CYDATA mc = &cfg_memcpy_list[i];
		void * CYDATA dest = mc->dest;
		const void CYCODE * CYDATA src = mc->src;
		uint16 CYDATA size = mc->size;
		CYCONFIGCPYCODE(dest, src, size);
	}

	cfg_write_bytes32();

	CYMEMZERO8((void CYFAR *)(CYDEV_PRTDSI_PRT0_BASE), 7);
	CYMEMZERO8((void CYFAR *)(CYDEV_PRTDSI_PRT1_BASE), 7);
	CYMEMZERO8((void CYFAR *)(CYDEV_PRTDSI_PRT2_BASE), 7);
	CYMEMZERO8((void CYFAR *)(CYDEV_PRTDSI_PRT3_BASE), 7);
	CYMEMZERO8((void CYFAR *)(CYDEV_PRTDSI_PRT4_BASE), 7);
	CYMEMZERO8((void CYFAR *)(CYDEV_PRTDSI_PRT5_BASE), 7);
	CYMEMZERO8((void CYFAR *)(CYDEV_PRTDSI_PRT6_BASE), 7);
	CYMEMZERO8((void CYFAR *)(CYDEV_PRTDSI_PRT12_BASE), 6);
	CYMEMZERO8((void CYFAR *)(CYDEV_PRTDSI_PRT15_BASE), 7);
	/* BYTES WRITTEN: 62 */
	EnableDigitalRouting();

	CyEnableDigitalArray();


	CY_SET_XTND_REG8((void CYFAR *)(CYDEV_CACHE_CC_CTL), ((CYDEV_INSTRUCT_CACHE_ENABLED) ? 0x00 : 0x01));
	ClockSetup();
	CY_SET_XTND_REG8((void CYFAR *)(CYDEV_CACHE_CC_CTL), ((CYDEV_INSTRUCT_CACHE_ENABLED) ? 0x80 : 0x81));

	AnalogSetDefault();
}

/* [] END OF FILE */
