/** @file HL_epc.c
*   @brief EPC Driver Implementation File
*   @date 20.May.2014
*   @version 04.00.00
*	This file contains APIs for the Error Profiling Controller Module.
*/

/* (c) Texas Instruments 2009-2013, All rights reserved. */

/* USER CODE BEGIN (0) */
/* USER CODE END */

#include "HL_epc.h"
#include "HL_sys_vim.h"
#include "HL_system.h"
#include "HL_reg_esm.h"

/* USER CODE BEGIN (1) */
/* USER CODE END */

/** @fn void epcEnableIP1ErrorGen(void)
*   @brief Enable ECC error generation for ECC errors on DMA Port A
*
*   Enable ECC error generation for ECC errors detected on DMA Port A master by the
*	CPU Interconnect Subsystem
*/
void epcEnableIP1ErrorGen(void)
{
/* USER CODE BEGIN (2) */
/* USER CODE END */

	systemREG2->IP1ECCERREN = (systemREG2->IP1ECCERREN & 0xFFFFFFF0U) | 0xAU;
	
/* USER CODE BEGIN (3) */
/* USER CODE END */
}

/** @fn void epcDisableIP1ErrorGen(void)
*   @brief Disable ECC error generation for ECC errors on DMA Port A
*
*   Disable ECC error generation for ECC errors detected on DMA Port A master by the
*	CPU Interconnect Subsystem
*/
void epcDisableIP1ErrorGen(void)
{
/* USER CODE BEGIN (4) */
/* USER CODE END */

	systemREG2->IP1ECCERREN = (systemREG2->IP1ECCERREN & 0xFFFFFFF0U) | 0x5U;
	
/* USER CODE BEGIN (5) */
/* USER CODE END */
}

/** @fn void epcEnableIP2ErrorGen(void)
*   @brief Enable ECC error generation for ECC errors on PS_SCR_M
*
*   Enable ECC error generation for ECC errors detected on PS_SCR_M master by the
*	CPU Interconnect Subsystem
*/
void epcEnableIP2ErrorGen(void)
{
/* USER CODE BEGIN (6) */
/* USER CODE END */

	systemREG2->IP1ECCERREN = (systemREG2->IP1ECCERREN & 0xFFFFF0FFU) | 0xA00U;
	
/* USER CODE BEGIN (7) */
/* USER CODE END */
}

/** @fn void epcDisableIP2ErrorGen(void)
*   @brief Disable ECC error generation for ECC errors on PS_SCR_M
*
*   Disable ECC error generation for ECC errors detected on PS_SCR_M master by the
*	CPU Interconnect Subsystem
*/
void epcDisableIP2ErrorGen(void)
{
/* USER CODE BEGIN (8) */
/* USER CODE END */

	systemREG2->IP1ECCERREN = (systemREG2->IP1ECCERREN & 0xFFFFF0FFU) | 0x500U;
	
/* USER CODE BEGIN (9) */
/* USER CODE END */
}

/** @fn void epcEnableSERREvent(void)
*   @brief Single (correctable) bit error event enable.
*
*   These bits (when enabled) cause EPC to
*	generate the serr_event if there is a correctable ECC fault address arrives from one of
*	the EPC-IP interface and the CAM has an empty entry.
*/
void epcEnableSERREvent(void)
{
/* USER CODE BEGIN (10) */
/* USER CODE END */

	epcREG1->EPCCNTRL = (epcREG1->EPCCNTRL & 0xFFFFFFF0U) | 0xAU;
	
/* USER CODE BEGIN (11) */
/* USER CODE END */
}

/** @fn void epcDisableSERREvent(void)
*   @brief Single (correctable) bit error event disable.
*
*   These bits (when enabled) cause EPC to
*	disable the serr_event generation.
*/
void epcDisableSERREvent(void)
{
/* USER CODE BEGIN (12) */
/* USER CODE END */

	epcREG1->EPCCNTRL = (epcREG1->EPCCNTRL & 0xFFFFFFF0U) | 0x5U;
	
/* USER CODE BEGIN (13) */
/* USER CODE END */
}

/** @fn void epcEnableInterrupt(void)
*   @brief CAM or FIFO full interrupt enable.
*
*   If this bit is set and CAM is full, CAM Full Interrupt
*	is generated.
*/
void epcEnableInterrupt(void)
{
/* USER CODE BEGIN (14) */
/* USER CODE END */

	epcREG1->EPCCNTRL |= (uint32)((uint32)1U<<24U);

/* USER CODE BEGIN (15) */
/* USER CODE END */
}

/** @fn void epcDisableInterrupt(void)
*   @brief CAM or FIFO full interrupt disable.
*
*   Disables interrupt generation in case CAM is full.
*/
void epcDisableInterrupt(void)
{
/* USER CODE BEGIN (16) */
/* USER CODE END */

	epcREG1->EPCCNTRL &= ~(uint32)((uint32)1U<<24U);

/* USER CODE BEGIN (17) */
/* USER CODE END */
}

/** @fn void epcCAMInit(void)
*   @brief Initializes CAM.
*
*  	CAM entries are cleared and available for future CAM usage.
*/
void epcCAMInit(void)
{
	int i;
/* USER CODE BEGIN (18) */
/* USER CODE END */

	for(i=0; i<8; i++)
	{
		epcREG1->CAM_INDEX[i] = 0x05050505U;
	}
/* USER CODE BEGIN (19) */
/* USER CODE END */
}

/** @fn void epcDiagnosticTest(void)
*   @brief CAM diagnostic enable.
*
*  	These bits (when enabled) allow the CPU to access the
*	CAM content to clear or set any entry (CAM index) or write any pattern to CAM
*	content.
*/
boolean epcDiagnosticTest(void)
{
	uint32 epccntrl_bk, camCont_bk, camIndex_bk;
	uint32 camAvailable;
	boolean status = true;

/* USER CODE BEGIN (20) */
/* USER CODE END */

	/* Back up EPCCNTRL register */
	epccntrl_bk = epcREG1->EPCCNTRL;

	/* Back up CAM_CONTENT[0] and CAM_INDEX[0] registers */
	camCont_bk = epcREG1->CAM_CONTENT[0U];
	camIndex_bk = epcREG1->CAM_INDEX[0U];

	/* Enter CAM diagnostic mode and and enable Single (correctable) bit error event generation */
	epcREG1->EPCCNTRL = (epcREG1->EPCCNTRL & 0xFFFFF0F0U) | 0x0A0AU;

	/* Clear first CAM entry */
	epcREG1->CAM_INDEX[0U] = (epcREG1->CAM_INDEX[0U] & 0xFFFFFFF0U) | 0x5U;

	/* Identify the number of CAM entries available */
	camAvailable = epcREG1->CAMAVAILSTAT;

	/* New CAM Entry */
	epcREG1->CAM_CONTENT[0U] = 0x1000U;

	/* The number of CAM entries must reduce by 1 */
	if(((esmREG->SR1[0U] & 0x10U) != 0x10U) || (epcREG1->CAMAVAILSTAT != (camAvailable - 1U)) || (epcCheckCAMEntry(0U) == true))
	{
		status = false;
	}


	/* Restore CAM_CONTENT and CAM_INDEX[0] registers */
	epcREG1->CAM_CONTENT[0U] = camCont_bk;
	epcREG1->CAM_INDEX[0U] = camIndex_bk;

	/* Disable CAM diagnostic mode and restore EPCCNTRL register */
	epcREG1->EPCCNTRL = epccntrl_bk;

/* USER CODE BEGIN (21) */
/* USER CODE END */

	return status;
}

/** @fn void epcAddCAMEEntry(uint32 address)
*   @brief Add a new CAM Entry
*
*  	Allows you to write a new CAM entry, after checking if there are any available entries.
*/
boolean epcAddCAMEEntry(uint32 address)
{
	int i = 0;
	boolean status = false;

/* USER CODE BEGIN (22) */
/* USER CODE END */

	if(epcREG1->CAMAVAILSTAT !=0U)
	{

		for(i=0; i<32; i++)
		{
			if(epcCheckCAMEntry(i) == true)
			{
				epcREG1->CAM_CONTENT[i] = address;
				status = true;
				break;
			}
		}
	}
	else
	{
		status = false;
	}

/* USER CODE BEGIN (23) */
/* USER CODE END */

	return status;
}

/** @fn void epcCheckCAMEntry(uint32 CAMIndex)
*   @brief Checks if CAM entry is available.
*
*  	Checks if the CAM Entry is available and ready for future usage.
*/
boolean epcCheckCAMEntry(uint32 index)
{
	uint32 i,j;
	boolean status = false;

/* USER CODE BEGIN (24) */
/* USER CODE END */

	i = index / 4U;
	j = (index % 4U) * 8U;

	/* Check for availability of CAM Entry for future CAM usage. */
	if((epcREG1->CAM_INDEX[i] & (uint32)((uint32)0xFU<<j)) == (uint32)((uint32)0x5U<<j))
	{
		status = true;
	}
	else
	{
		status= false;
	}

/* USER CODE BEGIN (25) */
/* USER CODE END */
	return status;
}

