/**
 * cpsw.c
 * 
 *
 * Copyright (c) 2012 Texas Instruments Incorporated ALL RIGHTS RESERVED
 *
*/

#include "cpsw_plfm.h"
#include "cpsw_impl.h"

/**
 * \brief   Gets MAC Control Register Value
 *
 * \param   baseAddr    Base address of the Sliver
 *
 * \return  None
 **/
unsigned int CPSWSlMACControlGet(unsigned int baseAddr)
{
	return HWREG(baseAddr + CPSW_SL_MACCONTROL);
}

void CPSWSlMACControlSet(unsigned int baseAddr, unsigned int mode)
{
    HWREG(baseAddr + CPSW_SL_MACCONTROL) &= ~(CPSW_SL_MACCONTROL_GIG
                                              | CPSW_SL_MACCONTROL_FULLDUPLEX | CPSW_SL_MACCONTROL_EXT_EN);
	 HWREG(baseAddr + CPSW_SL_MACCONTROL) |= mode;
}

/**
 * \brief   IFCTL_A enabled for the sliver
 *
 * \param   baseAddr    Base address of the Sliver
 *
 * \return  None
 **/
void CPSWSlIFCTLAEnable(unsigned int baseAddr)
{
	HWREG(baseAddr + CPSW_SL_MACCONTROL) |= CPSW_SL_MACCONTROL_IFCTL_A;
}

/**
 * \brief   Full Duplex enabled for the sliver
 *
 * \param   baseAddr    Base address of the Sliver
 *
 * \return  None
 **/
void CPSWSlFullDuplexEnable(unsigned int baseAddr)
{
	HWREG(baseAddr + CPSW_SL_MACCONTROL) |= CPSW_SL_MACCONTROL_FULLDUPLEX;
}

/**
 * \brief   Setting this bit causes the ALE hardware to remove
 * (free up) any ageable table entry that does not have a set touch bit.
 *
 * \param   baseAddr    Base address of the ALE module
 *
 * \return  None
 **/
void CPSWALEAgeOutNow(unsigned int baseAddr)
{
    HWREG(baseAddr + CPSW_ALE_CONTROL) |= CPSW_ALE_CONTROL_AGE_OUT_NOW;
}

/**
 * \brief   Gets the port state in the ALE for a given port
 *
 * \param   baseAddr    Base address of the ALE module
 * \param   portNum     The port number
 * 'portState' can take one of the below values \n
 *
 * \return  port State
 **/
unsigned int CPSWALEPortStateGetAny(unsigned int baseAddr, unsigned int portNum)
{
   return (HWREG(baseAddr + CPSW_ALE_PORTCTL(portNum)) & CPSW_ALE_PORTCTL0_PORT_STATE);
}

/**
 * \brief   Gets Interrupt vector status
 *
 * \param   baseAddr    Base address of the cpdma module
 *
 * \return  None
 **/
unsigned int CPSWCPDMAIntVectorGet(unsigned int baseAddr)
{
    return(HWREG(baseAddr + CPSW_CPDMA_CPDMA_IN_VECTOR));
}


/**
 * \brief   Enables the TXPULSE Interrupt Generation.
 *
 * \param   baseAddr      Base address of the CPDMA Module registers.
 * \param   value         Takes
 * 				CPSW_CPDMA_DMA_INTMASK_SET_HOST_ERR_INT_MASK
 * 				CPSW_CPDMA_DMA_INTMASK_SET_STAT_INT_MASK
 *
 * \return  None
 *
 **/
void CPSWCPDMADMAIntEnable(unsigned int baseAddr, unsigned int value)
{
    HWREG(baseAddr + CPSW_CPDMA_TX_INTMASK_SET ) = value;
}

/**
 * \brief   Enables the TXPULSE Interrupt Generation.
 *
 * \param   baseAddr      Base address of the CPDMA Module registers.
 * \param   channel       Channel number for which interrupt to be enabled
 *
 * \return  None
 *
 **/
void CPSWCPDMADMAIntDisable(unsigned int baseAddr, unsigned int channel)
{
    HWREG(baseAddr + CPSW_CPDMA_DMA_INTMASK_CLEAR) |= (1 << channel);
}
/**
 * \brief   Enables a Misc interrupt for the specified core.
 *
 * \param   baseAddr    Base address of the CPSW Wrapper Module
 * \param   core        Core number
 * \param   value     Type of interrupt
 * 				CPSW3G_ECTL_HOSTERR_INTMASK
 * 				CPSW3G_ECTL_STATPEND_INTMASK
 *
 * \return  None
 **/
void CPSWWrCoreMiscIntEnable(unsigned int baseAddr, unsigned int core,
                         unsigned int value)
{
    HWREG(baseAddr + CPSW_WR_C_MISC_EN(core)) |= value;
}

/**
 * \brief   Disables a Misc interrupt for the specified core.
 *
 * \param   baseAddr    Base address of the CPSW Wrapper Module
 * \param   core        Core number
 * \param   value     Type of interrupt
 * 				CPSW3G_ECTL_HOSTERR_INTMASK
 * 				CPSW3G_ECTL_STATPEND_INTMASK
 *
 * \return  None
 **/
void CPSWWrCoreMiscIntDisable(unsigned int baseAddr, unsigned int core,
                         unsigned int value)
{
    HWREG(baseAddr + CPSW_WR_C_MISC_EN(core)) &= value;
}




/**
 * \brief   Reades the the TX Completion Pointer for a specific channel
 *
 * \param   baseAddr      Base Address of the CPDMA module registers.
 * \param   channel       Channel Number.
 *
 *
 * \return  None
 *
 **/
unsigned int CPSWCPDMATxCPGet(unsigned int baseAddr, unsigned int channel)

{
    return (HWREG(baseAddr + CPSW_CPDMA_TX_CP(channel)));
}

/**
 * \brief   Reades the the RX Completion Pointer for a specific channel
 *
 * \param   baseAddr      Base Address of the CPDMA module registers.
 * \param   channel       Channel Number.
 *
 *
 * \return  None
 *
 **/
unsigned int CPSWCPDMARxCPGet(unsigned int baseAddr, unsigned int channel)

{
    return (HWREG(baseAddr + CPSW_CPDMA_RX_CP(channel)));
}

/**
 * \brief   Sets the Rx per second(Interrupt Pacing)
 *
 * \param   baseAddr    Base address of the CPSW Wrapper Module
 * \param   core        Core number
 * \param   value       Number of interrupts per second
 *
 * \return  None
 **/
void CPSWWrSetRxIntPerSec(unsigned int baseAddr, unsigned int core,
                         unsigned int value)
{
	HWREG(baseAddr + CPSW_WR_C_RX_IMAX(core)) &= ~(CPSW_WR_C0_RX_IMAX_C0_RX_IMAX);
    HWREG(baseAddr + CPSW_WR_C_RX_IMAX(core)) = (value << CPSW_WR_C0_RX_IMAX_C0_RX_IMAX_SHIFT);
}

/**
 * \brief   Enable Interrupt pacing
 *
 * \param   baseAddr    Base address of the CPSW Wrapper Module
 * \param   core        Core number
 * \param   value       The pulse to which Pacing is enabled
 *
 * \return  None
 **/
void CPSWWrSetIntPacingEnable(unsigned int baseAddr,
                         unsigned int value)
{
	HWREG(baseAddr + CPSW_WR_INT_CONTROL) &= ~(CPSW_WR_INT_CONTROL_INT_PACE_EN);
    HWREG(baseAddr + CPSW_WR_INT_CONTROL) = (value << CPSW_WR_INT_CONTROL_INT_PACE_EN_SHIFT);
}

/**
 * \brief   Set Interrupt counter prescaler
 *
 * \param   baseAddr    Base address of the CPSW Wrapper Module
 * \param   core        Core number
 * \param   value
 *
 * \return  None
 **/
void CPSWWrSetIntPrescaler(unsigned int baseAddr,
                         unsigned int value)
{
	HWREG(baseAddr + CPSW_WR_INT_CONTROL) &= ~(CPSW_WR_INT_CONTROL_INT_PRESCALE);
    HWREG(baseAddr + CPSW_WR_INT_CONTROL) = (value << CPSW_WR_INT_CONTROL_INT_PRESCALE_SHIFT);
}

/**
 * \brief   Teardown TX channel
 *
 * \param   baseAddr      Base address of the CPDMA Module registers.
 * \param   channel       Channel number is torn down
 *
 * \return  None
 *
 **/
void CPSWCPDMATxTeardown(unsigned int baseAddr, unsigned int channel)
{
    HWREG(baseAddr + CPSW_CPDMA_TX_TEARDOWN) = channel;

}

/**
 * \brief   Teardown RX channel
 *
 * \param   baseAddr      Base address of the CPDMA Module registers.
 * \param   channel       Channel number is torn down
 *
 * \return  None
 *
 **/
void CPSWCPDMARxTeardown(unsigned int baseAddr, unsigned int channel)
{
    HWREG(baseAddr + CPSW_CPDMA_RX_TEARDOWN) = channel;

}

/**
 * \brief   API to Disable the transmit in the TX Control Register.
 *
 * \param   baseAddr      Base Address of the CPDMA module registers.
 *
 * \return  None
 *
 **/
void CPSWCPDMATxDisable(unsigned int baseAddr)
{
    HWREG(baseAddr + CPSW_CPDMA_TX_CONTROL) = 0;
}
/**
 * \brief   API to disable the transmit in the RX Control Register.
 *
 * \param   baseAddr      Base Address of the CPDMA module registers.
 *
 * \return  None
 *
 **/
void CPSWCPDMARxDisable(unsigned int baseAddr)
{
    HWREG(baseAddr + CPSW_CPDMA_TX_CONTROL) = 0;
}

/**
 * \brief   API to Clear the statistics
 *
 * \param   baseAddr      Base Address of the CPSW_STATS
 * \param   val 		  if atleast one port is enabled,
 * 						  all values are write to clear hence
 * 						  we write all FFs to clear, else write zero to set value
 *
 * \return  None
 *
 **/
void CPSWSTATSClear(unsigned int baseAddr, unsigned int val)
{
	unsigned int cnt;
	for(cnt = 0; cnt < CPSW3G_NUM_STAT_REGS; cnt++)
		HWREG(baseAddr + (cnt*4)) = val;
}

/**
 * \brief   API to Read Statistics Register and clear it
 *
 * \param   baseAddr      Base Address of the CPSW_STATS
 * \param   reg			  The Stats register to be read
  *
 * \return  Count		  The value of the register
 *
 **/
unsigned int CPSWSTATSRead(unsigned int baseAddr, unsigned int reg)
{
	unsigned int value = 0;
	value = HWREG(baseAddr + (reg*4));
	HWREG(baseAddr + (reg*4)) = value;
	return value;
}

