/******************************************************************************/
/*                                                                            */
/*         Copyright(c) 2000-2002 by Ikanos Communications Inc.               */
/*                                                                            */
/*  All rights are reserved.  Reproduction in whole or in part is prohibited  */
/*  without the written consent of the copyright owner.                       */
/*                                                                            */
/*  The information and contents of this file are the proprietary information */
/*  of Ikanos Communication and may not be disclosed or used without the      */
/*  formal written approval of Ikanos Communication Inc.                      */
/*                                                                            */
/*  This Copyright notice may not be removed or modified without prior        */
/*  written consent of Ikanos Communications, Inc.                            */
/*                                                                            */
/******************************************************************************/
/*
**  Filename:    HostPtmfUtils.c
**
**  Project:     Ikanos INI ASIC (AMUR) Bring UP
**
**  Target:      MOTOROLA XPC855T based host board
**
**  Platform specific:
**    None.
**
**  Description:
**
**  $Revision: 1.1 $
**  $Date: 2006/10/16 04:34:51 $
**
**
**  **************************************************************************** 
**  Public Functions:
**
**  **************************************************************************** 
**  Private Functions:
**
**  **************************************************************************** 
**  Modification History:
**
**    Date         By     Description
**    -----------  ---    ------------------------------------------------------
**	  Jun-07-2002  SFA    Created
**    Jul-24-2002  SFA    Integration into new host code
**    Nov-06-2002  SFA    Adapted to the EIU of the CPE 2.0
*/
/******************************************************************************/
/*------------------------------------------------------------------------------
  INCLUDE FILES
  ----------------------------------------------------------------------------*/
#include <stdio.h>
#include "apiosmacro.h"
#include "HostPtmfApi.h"
#include "HostPtmfHwRegs.h"

/*------------------------------------------------------------------------------
  PRIVATE PREPROCESSOR CONSTANTS
  ----------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
  PRIVATE PREPROCESSOR MACROS
  ----------------------------------------------------------------------------*/

/*------------------------------------------------------------------------------
  PRIVATE ENUMERATION DEFINITIONS
  ----------------------------------------------------------------------------*/

/*------------------------------------------------------------------------------
  PRIVATE TYPE DEFINITIONS
  ----------------------------------------------------------------------------*/

/*------------------------------------------------------------------------------
  PUBLIC VARIABLES DEFINITIONS
  ----------------------------------------------------------------------------*/

/*------------------------------------------------------------------------------
  PRIVATE VARIABLES DEFINITIONS
  ----------------------------------------------------------------------------*/

/*------------------------------------------------------------------------------
  PRIVATE FUNCTION PROTOTYPE
  ----------------------------------------------------------------------------*/
extern U32 eiuPioRead (int BmeNum, unsigned long addr);
extern U32 eiuPioWrite (int BmeNum, unsigned long addr, unsigned long data);

/*------------------------------------------------------------------------------
  PUBLIC FUNCTION DEFINITIONS
  ----------------------------------------------------------------------------*/
/******************************************************************************/

/******************************************************************************
*                                                                             *
* Function.. : iposPtmfSemCreate              	   	                          *
*                                                   	                        *
* Purpose... : Program the EPLD register to set the INI mode. from amongst    *
*              RMII, SMII, SSSMII                                             *
*									                                                            *
* Parameters : Base address value                                             *
*                                                                             *
* Returns... : None                                                           *
*                                                                             *
******************************************************************************/
void 
  iposPtmfSemCreate (void)
{
  return;
}

/******************************************************************************
*                                                                             *
* Function.. : iposMdioRead                             	   	                *
*                                                   	                        *
* Purpose... : Reads the Ethernet PHY register through the MDIO interface     *
*									                                                            *
* Parameters : Pointer to the structure containing the port, register address *
*              and place to store the read data                               *
*                                                                             *
* Returns... : Success or Failure                                             *
*                                                                             *
******************************************************************************/

eIniRetCode
iposMdioRead (ptsHostIniMdioAddrData ptsIniReg)
{
  U32 uiEiuRegAddr, uiEiuRegData;
  U16 uiTimeout = 0;

  if (PTMF_BUS_HIC_PIO == (ptsIniReg->uiIniPhyAddr & PTMF_BUS_MASK))
  {
    // Reads the Ethernet PHY register through the MDIO interface of the COBRA

#ifdef DEBUG_INI
    if (gbDebugLevel <= 0)
      printf("\nCobra Mdio Read ");
#endif //DEBUG_INI

    // Make the COBRA PIO Address from the 10 bit index of the register.
    uiEiuRegAddr = MMDI_OP << 2;
    uiEiuRegAddr |= QUAD0_BASE_ADDR;

    // Wait till the Cobra's EIU is done with previous read/write operation
    do
    {
      uiEiuRegData = eiuPioRead (1, uiEiuRegAddr);

      uiTimeout++;
      if( uiTimeout > 300)
      {
        printf("\n Cobra EIU read timeout");
        return HOST_INI_REG_READ_TIMEOUT;
      }

    }while( (uiEiuRegData & MDIO_OP_READ) || (uiEiuRegData & MDIO_OP_WRITE));

    // Write the PHY reister address to the master MDIO address register of 
    // the COBRA
    uiEiuRegAddr = MMDI_ADD; 
    uiEiuRegAddr = uiEiuRegAddr << 2;
    uiEiuRegAddr |= QUAD0_BASE_ADDR;

    uiEiuRegData  = (ptsIniReg->uiIniPhyAddr & 0x1f) << 5;
    uiEiuRegData |= (ptsIniReg->uiIniRegAddr & 0x1f);

    eiuPioWrite (1, uiEiuRegAddr, uiEiuRegData);

    // START the read operation by reading from the MDIO read operation
    // register of the COBRA
    uiEiuRegAddr = MMDI_RD << 2;
    uiEiuRegAddr |= QUAD0_BASE_ADDR;
    
    uiEiuRegData = eiuPioRead (1, uiEiuRegAddr);

    uiEiuRegAddr = MMDI_OP << 2;
    uiEiuRegAddr |= QUAD0_BASE_ADDR;
    // Wait till the Cobra's EIU is done with previous read operation
    uiTimeout = 0;
    do
    {
      uiEiuRegData = eiuPioRead (1, uiEiuRegAddr);

      uiTimeout++;
      if( uiTimeout > 300)
      {
        printf("\n Cobra EIU read timeout");
        return HOST_INI_REG_READ_TIMEOUT;
      }

    }while(uiEiuRegData & MDIO_OP_READ); 

    uiEiuRegAddr = MMDI_RDAT << 2;
    uiEiuRegAddr |= QUAD0_BASE_ADDR;

    ptsIniReg->uiIniRdWrData = eiuPioRead (1, uiEiuRegAddr);

#ifdef DEBUG_INI
    if (gbDebugLevel <= 1)
      printf("\nREAD  %08x = %04x", (unsigned int)uiEiuRegAddr, ptsIniReg->uiIniRdWrData);
#endif //DEBUG_INI

    return HOST_INI_NO_ERROR;
  }
  else
    return HOST_INI_UNDEFINED_ERROR;
}

/******************************************************************************
*                                                                             *
* Function.. : iposMdioWrite                            	   	                *
*                                                   	                        *
* Purpose... : Writes to the Ethernet PHY register through the MDIO interface *
*									                                                            *
* Parameters : Pointer to the structure containing the port, register address *
*              and data to be written to the PHY                              *
*                                                                             *
* Returns... : Success or Failure                                             *
*                                                                             *
******************************************************************************/

eIniRetCode
iposMdioWrite (ptsHostIniMdioAddrData ptsIniReg)
{
  U32 uiEiuRegAddr, uiEiuRegData;
  U16 uiTimeout = 0;

  if (PTMF_BUS_HIC_PIO == (ptsIniReg->uiIniPhyAddr & PTMF_BUS_MASK))
  {
    // Reads the Ethernet PHY register through the MDIO interface of the COBRA

#ifdef DEBUG_INI
    if (gbDebugLevel <= 0)
      printf("\nCobra Mdio Write ");
#endif //DEBUG_INI

    // Make the COBRA PIO Address from the 10 bit index of the register.
    uiEiuRegAddr = MMDI_OP << 2;
    uiEiuRegAddr |= QUAD0_BASE_ADDR;

    // Wait till the Cobra's EIU is done with previous read/write operation
    do
    {
      uiEiuRegData = eiuPioRead (1, uiEiuRegAddr);

      uiTimeout++;
      if( uiTimeout > 300)
      {
        printf("\n Cobra EIU read timeout");
        return HOST_INI_REG_READ_TIMEOUT;
      }

    }while( (uiEiuRegData & MDIO_OP_READ) || (uiEiuRegData & MDIO_OP_WRITE));

    // Write the PHY register address to the master MDIO address register of 
    // the COBRA
    uiEiuRegAddr = MMDI_ADD; 
    uiEiuRegAddr = uiEiuRegAddr << 2;
    uiEiuRegAddr |= QUAD0_BASE_ADDR;

    uiEiuRegData  = (ptsIniReg->uiIniPhyAddr & 0x1f) << 5;
    uiEiuRegData |= (ptsIniReg->uiIniRegAddr & 0x1f);

    eiuPioWrite (1, uiEiuRegAddr, uiEiuRegData);

    // START the write operation by writing to the MDIO Write operation
    // register of the COBRA
    uiEiuRegAddr = MMDI_WDAT << 2;
    uiEiuRegAddr |= QUAD0_BASE_ADDR;

    uiEiuRegData = ptsIniReg->uiIniRdWrData;
    
    eiuPioWrite (1, uiEiuRegAddr, uiEiuRegData);

    uiEiuRegAddr = MMDI_OP << 2;
    uiEiuRegAddr |= QUAD0_BASE_ADDR;

    // Wait till the Cobra's EIU is done with write operation
    uiTimeout = 0;
    do
    {
      uiEiuRegData = eiuPioRead (1, uiEiuRegAddr);

      uiTimeout++;
      if( uiTimeout > 300)
      {
        printf("\n Cobra EIU read timeout");
        return HOST_INI_REG_READ_TIMEOUT;
      }

    }while(uiEiuRegData & MDIO_OP_WRITE); 

    return HOST_INI_NO_ERROR;
  }
  else
  {

#ifdef DEBUG_INI
    if (gbDebugLevel <= 5)
      printf("\n Error: Unknown Bus Type");
#endif //DEBUG_INI

    return HOST_INI_UNDEFINED_ERROR;
  }
}


/******************************************************************************
*                                                                             *
* Function.. : iposPtmfMdioRead                      	   	                    *
*                                                   	                        *
* Purpose... : Reads the INI register through the MDIO interface    	        *
*									                                                            *
* Parameters : Pointer to the structure containing the port, register address *
*              and place to store the read data                               *
*                                                                             *
* Returns... : Success or Failure                                             *
*                                                                             *
******************************************************************************/

eIniRetCode
iposPtmfMdioRead (ptsHostIniMdioAddrData ptsIniReg)
{
  U32 uiEiuRegAddr, regAddr;
  U8 bPortNum;
  
  if (PTMF_BUS_HIC_PIO == (ptsIniReg->bIniBaseAddr & PTMF_BUS_MASK))
  {
    
#ifdef DEBUG_INI
    if (gbDebugLevel <= 0)
      printf("\nCobra PIO Read ");
#endif //DEBUG_INI

    regAddr = ptsIniReg->uiIniRegAddr;
    uiEiuRegAddr = regAddr << 2;
    bPortNum = ptsIniReg->uiIniPhyAddr - 1;

    if (regAddr >= MMDI_WDAT && regAddr <= SMDI_GSTAT)
    {
        if (regAddr == SMDI_CTL || regAddr == SMDI_STAT)
            uiEiuRegAddr += bPortNum;
        uiEiuRegAddr |= QUAD0_BASE_ADDR;
    }
    else if (regAddr >= UPR_0 && regAddr <= HSBR0)
        uiEiuRegAddr |= QUAD0_BASE_ADDR;
    else if (regAddr >= USGCR && regAddr <= USRFST_7)
        uiEiuRegAddr |= 0xE0000000;
    else if ((bPortNum >= 0) && (bPortNum <= 3))
    {
        uiEiuRegAddr |= QUAD0_BASE_ADDR;
        uiEiuRegAddr += bPortNum * 0x100;
    }
    else if ((bPortNum >= 4) && (bPortNum <= 7))
    {
        uiEiuRegAddr |= QUAD1_BASE_ADDR;
        uiEiuRegAddr += (bPortNum-4) * 0x100;
    }
    else
        return HOST_INI_MAX_ENET_PORT_ERROR;



#ifdef DEBUG_INI
    if (gbDebugLevel <= 0)
      printf(" (0x%08x) ",(unsigned int)uiEiuRegAddr);
#endif //DEBUG_INI
   
    ptsIniReg->uiIniRdWrData = eiuPioRead (
                                (ptsIniReg->bIniBaseAddr & (~PTMF_BUS_MASK)), 
                                uiEiuRegAddr );
#ifdef DEBUG_INI
    if (gbDebugLevel <= 1)
      printf("\nREAD  %08x = %04x", (unsigned int)uiEiuRegAddr, ptsIniReg->uiIniRdWrData);
#endif //DEBUG_INI

    return HOST_INI_NO_ERROR;
  }
  else
  {
#ifdef DEBUG_INI
    if (gbDebugLevel <= 5)
      printf("\n Error: Unknown Bus Type");
#endif //DEBUG_INI

    return HOST_INI_UNDEFINED_ERROR;
  }
}

/******************************************************************************
*                                                                             *
* Function.. : iposPtmfMdioWrite                      	   	                  *
*                                                   	                        *
* Purpose... : Write to the INI register through the MDIO interface  	        *
*									                                                            *
* Parameters : Pointer to the structure containing the port, register address *
*              and data to be written                                         *
*                                                                             *
* Returns... : Success or Failure                                             *
*                                                                             *
******************************************************************************/

eIniRetCode
iposPtmfMdioWrite (ptsHostIniMdioAddrData ptsIniReg)
{
  U32 uiEiuRegAddr, uiEiuRegData, regAddr;
  U8 bPortNum;

  if (PTMF_BUS_HIC_PIO == (ptsIniReg->bIniBaseAddr & PTMF_BUS_MASK))
  {

#ifdef DEBUG_INI
    if (gbDebugLevel <= 0)
      printf("\nCobra PIO Write ");
#endif //DEBUG_INI

    regAddr = ptsIniReg->uiIniRegAddr;
    uiEiuRegAddr = regAddr << 2;
    bPortNum = ptsIniReg->uiIniPhyAddr - 1;

    if (regAddr >= MMDI_WDAT && regAddr <= SMDI_GSTAT)
    {
        if (regAddr == SMDI_CTL || regAddr == SMDI_STAT)
            uiEiuRegAddr += bPortNum;
        uiEiuRegAddr |= QUAD0_BASE_ADDR;
    }
    else if (regAddr >= UPR_0 && regAddr <= HSBR0)
        uiEiuRegAddr |= QUAD0_BASE_ADDR;
    else if (regAddr >= USGCR && regAddr <= USRFST_7)
        uiEiuRegAddr |= 0xE0000000;

    else if ((bPortNum >= 0) && (bPortNum <= 3))
    {
        uiEiuRegAddr |= QUAD0_BASE_ADDR;
        uiEiuRegAddr += bPortNum * 0x100;
    }
    else if ((bPortNum >= 4) && (bPortNum <= 7))
    {
        uiEiuRegAddr |= QUAD1_BASE_ADDR;
        uiEiuRegAddr += (bPortNum-4) * 0x100;
    }
    else
        return HOST_INI_MAX_ENET_PORT_ERROR;


    uiEiuRegData = ptsIniReg->uiIniRdWrData;
    
    //printf("\nPIO reg address (0x%08x)",uiEiuRegAddr);

    eiuPioWrite ((ptsIniReg->bIniBaseAddr & (~PTMF_BUS_MASK)), 
                 uiEiuRegAddr,
                 uiEiuRegData);
#ifdef DEBUG_INI
    if (gbDebugLevel <= 1)
      printf("\nWRITE  %08x = %04x", (unsigned int)uiEiuRegAddr, (unsigned int)uiEiuRegData);
#endif //DEBUG_INI

    return HOST_INI_NO_ERROR;
  }
  else
  {
#ifdef DEBUG_INI
    if (gbDebugLevel <= 5)
      printf("\n Error: Unknown Bus Type");
#endif //DEBUG_INI

    return HOST_INI_UNDEFINED_ERROR;
  }
}

/******************************************************************************
*                                                                             *
* Function.. : iposPtmfResetPort                         	                    *
*                                                   	                        *
* Purpose... : Soft-reset the EIU port.                                       *
*									                                                            *
* Parameters : PTMF base address and Port address                             *
*                                                                             *
* Returns... : N/A                                                            *
*                                                                             *
******************************************************************************/
void 
  iposPtmfResetPort (U8 bPtmfBaseAddr, U16 bPortAddr)
{
  tsHostIniMdioAddrData   tsIniReg;

#ifdef DEBUG_INI
  if (gbDebugLevel <= 3)
    printf("\nINI ASIC RESET PORT (%02x-%04x)", bPtmfBaseAddr, bPortAddr);
#endif //DEBUG_INI

  // Before soft reset of the EIU, save the ethernet address filtering
  // related configuration

  // Ethernet Port address set for access to the port specific MDIO registers.
  tsIniReg.bIniBaseAddr = bPtmfBaseAddr;
  tsIniReg.uiIniPhyAddr = bPortAddr;

  tsIniReg.uiIniRegAddr = CGRCR;
  iposPtmfMdioRead (&tsIniReg);

  tsIniReg.uiIniRdWrData |= SOFT_RESET;
  tsIniReg.uiIniRdWrData &= ~PSOFT_RESET;
  iposPtmfMdioWrite (&tsIniReg);

  tsIniReg.uiIniRdWrData |= PSOFT_RESET;
  iposPtmfMdioWrite (&tsIniReg);

  tsIniReg.uiIniRdWrData &= ~SOFT_RESET;
  iposPtmfMdioWrite (&tsIniReg);

  tsIniReg.uiIniRdWrData &= ~PSOFT_RESET;
  iposPtmfMdioWrite (&tsIniReg);

  tsIniReg.uiIniRdWrData |= PSOFT_RESET;
  iposPtmfMdioWrite (&tsIniReg);

  tsIniReg.uiIniRdWrData |= SOFT_RESET;
  iposPtmfMdioWrite (&tsIniReg);

  tsIniReg.uiIniRdWrData &= ~PSOFT_RESET;
  iposPtmfMdioWrite (&tsIniReg);

  // Re-configure the ethernet address filtering related configuration after 
  // soft reset of the EIU.
}


/*------------------------------------------------------------------------------
                                 END OF FILE
------------------------------------------------------------------------------*/
