/**
 * \file icss_tlk110.c
 * \brief Contains ICSS PHY (TLK 110) Workaround APIs
 * 
 *
 * \copyright Copyright (c) 2012 Texas Instruments Incorporated ALL RIGHTS RESERVED
 *
*/

/* ========================================================================== */
/*                             Include Files                                  */
/* ========================================================================== */
#include "osdrv_tlk110.h"

/**Task Handle for the TLK thread which swaps MDI/MDI-X bits for link*/
Task_Handle tlkTask;

static unsigned int MDIOBaseAddress;
/* ========================================================================== */
/*                          Function Definitions                              */
/* ========================================================================== */


void tlkMDIXSwap(Uint32 phyBaseAddress,Uint32 phyInst)
{

    unsigned short regVal;
    unsigned short linkregVal=0;

    MDIOPhyRegRead(phyBaseAddress, phyInst, PHY_STAT_REG, &linkregVal);
    MDIOPhyRegRead(phyBaseAddress, phyInst, PHY_STAT_REG, &linkregVal);
    if(!(linkregVal & 1))
    {
		   MDIOPhyRegRead(phyBaseAddress, phyInst, PHY_BCR, &regVal);
		   MDIOPhyRegRead(phyBaseAddress, phyInst, PHY_BCR, &regVal);
		   if(!(regVal & MII_AUTO_NEGOTIATE_EN))
		   {
			   MDIOPhyRegRead(phyBaseAddress, phyInst, PHY_CNTRL_REG, &regVal);
			   MDIOPhyRegRead(phyBaseAddress, phyInst, PHY_CNTRL_REG, &regVal);

			   if(regVal & NWAY_FORCEMDIX_ENABLE)
					regVal &= ~(NWAY_FORCEMDIX_ENABLE);
			   else
					regVal |= NWAY_FORCEMDIX_ENABLE;

			  MDIOPhyRegWrite(phyBaseAddress, phyInst, PHY_CNTRL_REG,regVal);
		   }
    }
}

/**
 *  \name TlkMDIXTask
 *  \brief Main Task which implements Auto MDI/MDI-X for the PHY in Software
 *
 *  \param none No arguments
 *
 *  \return none No arguments
 */
void TlkMDIXTask(UArg a0, UArg a1)
{
	   int i=0;
       Task_sleep(2500);
       while(1)
       {
    	   for(i=0;i<mac_configuration.numberPorts;i++)
    	   {
    		   tlkMDIXSwap(MDIOBaseAddress,mac_configuration.phyAddr[i]);
    		   Task_sleep(2000);
    	   }
       }
}






/**
 *  \name tlkMDIXFixinit
 *  \brief Initializes the task which does Auto MDI/MDI-X for the PHY in Software
 *
 *  \param none No arguments
 *
 *  \return none No arguments
 */
void tlkMDIXFixinit(Uint32 phyBaseAddress)
{

	MDIOBaseAddress =phyBaseAddress;

	Task_Params taskParams;
	Task_Params_init(&taskParams);
	taskParams.priority = 3;
	taskParams.instance->name = "tlk110Task";
	tlkTask = Task_create(TlkMDIXTask, &taskParams, NULL);
}
/**
 *  \name tlkMDIXFixinit
 *  \brief Deletes the task which does Auto MDI/MDI-X for the PHY in Software
 *
 *  \param none No arguments
 *
 *  \return none No arguments
 */
void tlkMDIXFixDeinit()
{

	Task_delete(&tlkTask);
}

/**
 *  \name tlkMDIXFixinit
 *  \brief Deletes the task which does Auto MDI/MDI-X for the PHY in Software
 *
 *  \param phyInst PHY Instance for Port0 or Port 1
 *
 *  \return none No arguments
 */
void tlkDisableAutoMDIX(Uint32 phyBaseAddress,Uint32 phyInst)
{
	  volatile unsigned short phyCtrlReg;

	  MDIOPhyRegRead(phyBaseAddress, phyInst, PHY_CNTRL_REG, &phyCtrlReg);
	  MDIOPhyRegRead(phyBaseAddress, phyInst, PHY_CNTRL_REG, &phyCtrlReg);
	  //clear the auto bit
	  phyCtrlReg &= ~(NWAY_AUTOMDIX_ENABLE);
	  MDIOPhyRegWrite(phyBaseAddress,phyInst,PHY_CNTRL_REG,phyCtrlReg);
}

/**
 *  \name tlkNLPFix
 *  \brief Fix for issue where the link partner change from 10 half to 100 was not detected by TLK 110
 *
 *  \param phyInst PHY Instance for Port0 or Port 1
 *
 *  \return none No arguments
 */
void tlkNLPFix(Uint32 phyBaseAddress,Uint32 phyInst)
{
    MDIOPhyRegWrite( phyBaseAddress,phyInst,PHY_REGCR_REG,EXT_REG_ADDRESS_ACCESS);

    MDIOPhyRegWrite( phyBaseAddress,phyInst,PHY_ADDR_REG,NLP_DET_REG);

    MDIOPhyRegWrite( phyBaseAddress,phyInst,PHY_REGCR_REG,EXT_REG_DATA_NORMAL_ACCESS);

    MDIOPhyRegWrite( phyBaseAddress,phyInst,PHY_ADDR_REG,NLP_DET_CONFIG_REGVAL);
}
/**
 *  \name tlkEnableAutoMDIX
 *  \brief Enable AutoMDIX for the particular Port
 *
 *  \param phyInst PHY Instance for Port0 or Port 1
 *
 *  \return none No arguments
 */
void tlkEnableAutoMDIX(Uint32 phyBaseAddress,Uint32 phyInst)
{
	unsigned short phy;

	MDIOPhyRegRead(phyBaseAddress, phyInst, PHY_CNTRL_REG, &phy);
	MDIOPhyRegRead(phyBaseAddress, phyInst, PHY_CNTRL_REG, &phy);

	phy |= NWAY_AUTOMDIX_ENABLE;
	MDIOPhyRegWrite(phyBaseAddress,phyInst,PHY_CNTRL_REG,phy);
}
