/*  ============================================================================
 *     Copyright (C) 2011, 2012, 2013 Texas Instruments Incorporated.          *
 *
 *   Use of this software is controlled by the terms and conditions found in the
 *   license agreement under which this software has been supplied.
 *   ===========================================================================
 */
/** ============================================================================
Interrupts configuration and ISR for HyperLink
 * =============================================================================
 *  Revision History
 *  ===============
 *  17-March-2012 Brighton Feng  file created
 * =============================================================================
 */

#include <stdio.h>
#include <csl_cpintc.h>
#include "K2_common.h"
#include "K2_HyperLink_init.h"
#include "HyperLink_debug.h"

volatile Uint32 HyperLinkIntCCNT;

void HyperLink_Int_Handle(Uint32 uiLinkNum)
{
	Uint32 intVector;
	
	/*read the HyperLink interrupt vector*/
	intVector= gpHyperLinkRegs[uiLinkNum]->INT_PRI_VEC;

	while(0==(intVector&CSL_VUSR_INT_PRI_VEC_NOINTPEND_MASK))
	{
		if(0==intVector)//HyperLink error is routed to vector 0 for this test.
		{
			//print status
			print_HyperLink_status(uiLinkNum);

			/*disable all portal or remote register operation
			This bit should be set before iloop or reset bits are changed.*/
			gpHyperLinkRegs[uiLinkNum]->CTL |= CSL_VUSR_CTL_SERIAL_STOP_MASK;

			/*Wait until no Remote Pending Request*/
			while(gpHyperLinkRegs[uiLinkNum]->STS&CSL_VUSR_STS_RPEND_MASK);

			/*Reset*/
			//gpHyperLinkRegs[uiLinkNum]->CTL |= CSL_VUSR_CTL_RESET_MASK;

			//clear error status
			gpHyperLinkRegs[uiLinkNum]->STS |= CSL_VUSR_STS_LERROR_MASK
				|CSL_VUSR_STS_RERROR_MASK;
			
			/*release from Reset*/
			//gpHyperLinkRegs[uiLinkNum]->CTL &= ~(CSL_VUSR_CTL_RESET_MASK);

			/*enable operation*/
			gpHyperLinkRegs[uiLinkNum]->CTL &= ~(CSL_VUSR_CTL_SERIAL_STOP_MASK);

		}

		printf("HyperLink %d interrupt %d happens at CCNT= %u\n",
			uiLinkNum, intVector, HyperLinkIntCCNT);

		/*write back to clear that interrupt*/
		gpHyperLinkRegs[uiLinkNum]->INT_PRI_VEC= intVector;
		gpHyperLinkRegs[uiLinkNum]->INT_CLR= (1<<intVector);

		/*read the HyperLink interrupt vector*/
		intVector= gpHyperLinkRegs[uiLinkNum]->INT_PRI_VEC;
	}
}

void HyperLinkISR(Uint32 uiIAR_value, Uint32 uiIntAddress)
{
	Uint32 uiINT_ID;
	
	HyperLinkIntCCNT= CP15_read_CCNT(); 	//save the CCNT when the interrupt happens

	uiINT_ID= GIC_GET_INT_ID(uiIAR_value)-32;
	if(CSL_CIC0_HYPERLINK_0_INT==uiINT_ID)
		HyperLink_Int_Handle(CSL_HYPERLINK_0);
#ifdef CSL_CIC0_HYPERLINK_1_INT
	if(CSL_CIC0_HYPERLINK_1_INT==uiINT_ID)
		HyperLink_Int_Handle(CSL_HYPERLINK_1);
#endif
}

void HyperLink_Interrupts_Init(void)
{
	GIC_INT_Config int_cfg;

	int_cfg.trigger_type= GIC_TRIGGER_TYPE_EDGE;
	int_cfg.ucGroupNum= 1; //route QMSS interrupt to group 1, IRQ
	int_cfg.ucPriority= GIC400_PRIORITY_LOWER;

	GIC_interrupt_hook(GIC_CONVERT_SPI_ID(CSL_ARM_GIC_HYPERLINK_0_INT), 
		&int_cfg, HyperLinkISR);
#ifdef CSL_CIC0_HYPERLINK_1_INT
	GIC_interrupt_hook(GIC_CONVERT_SPI_ID(CSL_ARM_GIC_HYPERLINK_1_INT), 
		&int_cfg, HyperLinkISR);
#endif
}

