/*
Copyright (C) 2008, 2009  GE Intelligent Platforms, Inc
 
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#ifdef __U_BOOT__
#  include <common.h>
#  include <command.h>
#  include <malloc.h>
#  include <devices.h>
#  include <net.h>
#  include <environment.h>
#  include "octeon_boot.h"
#  include <lib_octeon.h>
#  include <cvmx-bootmem.h>
#  include <octeon_eeprom_types.h>
#  include <lib_octeon_shared.h>
#  include "npaEagle.h"
#  include "eagleReg.h"

#  define NPA_CONFIG_EAGLE				1
#  define DPRINTK(a, b, c, d, ...)
#  define ERROR( x )					-1
#elif defined( LINUX_OS )
#  include <linux/module.h>
#  include <linux/moduleparam.h>
#  include <linux/init.h>
#  include "config.h"
#  include <linux/kernel.h> /* printk() */
#  include <linux/fs.h>     /* everything... */
#  include <linux/errno.h>  /* -1 codes */
#  include <linux/types.h>  /* size_t */
#  include <linux/vmalloc.h>
#  include <linux/hdreg.h>
#  include <linux/spinlock.h>
#  include <linux/netdevice.h>
#  include <linux/ethtool.h>
#  include <linux/delay.h>
#  include "cvmx.h"
#  include "npaDevice.h"
#  include "npaIoctl.h"
#  include "eagle/npaEagle.h"
#  include "eagle/eagleReg.h"
#  define ERROR( x )					x
#endif

#if defined( NPA_CONFIG_EAGLE )

#undef USE_TWSI
#define USE_MDIO
#if (defined(USE_MDIO) && defined(USE_TWSI))
#  error "Both USE_MDIO and USE_TWSI cannot be defined.  USE_MDIO recommended"
#endif

static int npaEgInitAsic ( struct npaEagleObj_t * eagleObj, int modeType );
static int npaEgAsicFindModuleType( struct npaEagleObj_t * eagleObj, int portNum );
static int npaEgConfigPort( struct npaEagleObj_t * eagleObj, int portNum, int sfpType );
static int npaEgAsicConfigFiberPort( struct npaEagleObj_t * eagleObj, int portNum );
static int configMACSpeed( struct npaEagleObj_t * eagleObj, int portNum, int macSpeed );
#ifdef __U_BOOT__
int configMACAfterAutoneg ( struct npaEagleObj_t * eagleObj, int portNum );
int npaEgAsicAutoNegCompleteFiberStatus( struct npaEagleObj_t * eagleObj, int portNum );
#else
static int configMACAfterAutoneg ( struct npaEagleObj_t * eagleObj, int portNum );
static int npaEgAsicAutoNegCompleteFiberStatus( struct npaEagleObj_t * eagleObj, int portNum );
#endif

static int npaEgAsicPhyIntr( struct npaEagleObj_t * eagleObj );

#ifdef __U_BOOT__
int npaEgEnablePort( struct npaEagleObj_t * eagleObj, int portNum );
#else
static int npaEgEnablePort( struct npaEagleObj_t * eagleObj, int portNum );
#endif

static int npaEgDisablePort( struct npaEagleObj_t * eagleObj, int portNum );

#if defined(__U_BOOT__)
struct npaEagleObj_t gEagleObj;
#endif

#if !defined(__U_BOOT__)
static unsigned long getStatVal( struct npaEagleObj_t * eagleObj, int reghi, int reglo )
{
	unsigned long val = 0;
	uint32_t regVal;

	if( reghi != 0 )
	{

	}

	npaEgRegGet( eagleObj, reglo, 0, &regVal );
	val += regVal;

	return val;
}
#endif

#if defined(LINUX_OS) && !defined(__U_BOOT__)
static void npaEagleTimer( unsigned long data )
{
	struct npaFunctionObj_t * pFunction = (struct npaFunctionObj_t *)data;
	struct npaEagleObj_t *	pEagleObj = (struct npaEagleObj_t *)pFunction->function_data;
	int						portNum = 0;
	unsigned long			flags;
	uint32_t				regVal;
	int						i;
	rxSpiStatistics *		pRxSpiStats = &pEagleObj->rxSpiStats;
	txSpiStatistics *		pTxSpiStats = &pEagleObj->txSpiStats;


	spin_lock_irqsave( &pEagleObj->devLock, flags );

#if 1 /* BUGBUG: Polling interrupt for now */
	npaEgAsicPhyIntr( pEagleObj );
#endif

/* update the Rx SPI Statistics */
    for (i=0; i<24; i++) {
        npaEgRegSet( pEagleObj, AD_CfgRxSpiSelMinMdrrCreditCount, MAKE_MASK(4,0), i);
        npaEgRegSet( pEagleObj, AD_CfgRxSpiSelMaxMdrrCreditCount, MAKE_MASK(4,0), i);
		pRxSpiStats->minMdrrCreditCount[i] += getStatVal( pEagleObj, 0, AD_StsRxSpiMinMdrrCreditCount );
		pRxSpiStats->maxMdrrCreditCount[i] += getStatVal( pEagleObj, 0, AD_StsRxSpiMaxMdrrCreditCount );
    }
	pRxSpiStats->miscSPIHM += getStatVal( pEagleObj, 0, AD_StsRxSpiMiscSPIHM );
	pRxSpiStats->ampleUsePipeEmpty += getStatVal( pEagleObj, 0, AD_StsRxSpiAmpleUsePipeEmpty );
	pRxSpiStats->sopCount += getStatVal( pEagleObj, 0, AD_StsRxSpiSopCount );
    pRxSpiStats->eop1Count += getStatVal( pEagleObj, 0, AD_StsRxSpiEop1Count );
    pRxSpiStats->eop2Count += getStatVal( pEagleObj, 0, AD_StsRxSpiEop2Count );
    pRxSpiStats->eopACount += getStatVal( pEagleObj, 0, AD_StsRxSpiEopACount );
    pRxSpiStats->trainingCount += getStatVal( pEagleObj, 0, AD_StsRxSpiTrainingCount );
    pRxSpiStats->burstFifoUFlow += getStatVal( pEagleObj, 0, AD_StsRxSpiBurstFifoUFlow );
	pRxSpiStats->outputFifoUFlow += getStatVal( pEagleObj, 0, AD_StsRxSpiOutputFifoUFlow );
    pRxSpiStats->ampleUseSopCnt += getStatVal( pEagleObj, 0, AD_StsRxSpiAmpleUseSopCnt );
    pRxSpiStats->dip2ErrCount += getStatVal( pEagleObj, 0, AD_StsRxSpiDip2ErrCount );
    pRxSpiStats->losStatus += getStatVal( pEagleObj, 0, AD_StsRxSpiLosStatus );
    pRxSpiStats->shdwCalendarAct += getStatVal( pEagleObj, 0, AD_StsRxSpiShdwCalendarAct );

/* update the Tx SPI Statistics */
    pTxSpiStats->addrMapMemRdData_0 += getStatVal( pEagleObj, 0, AD_StsTxSpiAddrMapMemRdData_0 );
    pTxSpiStats->addrMapMemRdData_1 += getStatVal( pEagleObj, 0, AD_StsTxSpiAddrMapMemRdData_1 );
    pTxSpiStats->addrMapMemRdData_2 += getStatVal( pEagleObj, 0, AD_StsTxSpiAddrMapMemRdData_2 );
    pTxSpiStats->addrMapMemRdData_3 += getStatVal( pEagleObj, 0, AD_StsTxSpiAddrMapMemRdData_3 );
    pTxSpiStats->oneLinePktDrop += getStatVal( pEagleObj, 0, AD_StsTxSpiOneLinePktDrop );
    pTxSpiStats->trainingCount += getStatVal( pEagleObj, 0, AD_StsTxSpiTrainingCount );
    pTxSpiStats->sopCount += getStatVal( pEagleObj, 0, AD_StsTxSpiSopCount );
    pTxSpiStats->eopCount += getStatVal( pEagleObj, 0, AD_StsTxSpiEopCount );
	pTxSpiStats->extAbortEopCount += getStatVal( pEagleObj, 0, AD_StsTxSpiExtAbortEopCount );
    pTxSpiStats->intAbortEopCount += getStatVal( pEagleObj, 0, AD_StsTxSpiIntAbortEopCount );
    pTxSpiStats->dip4ErrCount += getStatVal( pEagleObj, 0, AD_StsTxSpiDip4ErrCount );
    pTxSpiStats->protViolCount += getStatVal( pEagleObj, 0, AD_StsTxSpiProtViolCount );
    pTxSpiStats->fifoOverFlow += getStatVal( pEagleObj, 0, AD_StsTxSpiFifoOverFlow );
    pTxSpiStats->dPGStatus += getStatVal( pEagleObj, 0, AD_StsTxSpiDPGStatus );
    pTxSpiStats->dPVByteErrCnt0 += getStatVal( pEagleObj, 0, AD_StsTxSpiDPVByteErrCnt0 );
    pTxSpiStats->dPVByteErrCnt1 += getStatVal( pEagleObj, 0, AD_StsTxSpiDPVByteErrCnt1 );
    pTxSpiStats->dPVByteErrCnt2 += getStatVal( pEagleObj, 0, AD_StsTxSpiDPVByteErrCnt2 );
    pTxSpiStats->dPVByteErrCnt3 += getStatVal( pEagleObj, 0, AD_StsTxSpiDPVByteErrCnt3 );
    pTxSpiStats->dPVByteErrCnt4 += getStatVal( pEagleObj, 0, AD_StsTxSpiDPVByteErrCnt4 );
    pTxSpiStats->dPVByteErrCnt5 += getStatVal( pEagleObj, 0, AD_StsTxSpiDPVByteErrCnt5 );
    pTxSpiStats->dPVByteErrCnt6 += getStatVal( pEagleObj, 0, AD_StsTxSpiDPVByteErrCnt6 );
    pTxSpiStats->dPVByteErrCnt7 += getStatVal( pEagleObj, 0, AD_StsTxSpiDPVByteErrCnt7 );
    pTxSpiStats->dPVGoodPktCnt += getStatVal( pEagleObj, 0, AD_StsTxSpiDPVGoodPktCnt );
    pTxSpiStats->dPVSyncOnCnt += getStatVal( pEagleObj, 0, AD_StsTxSpiDPVSyncOnCnt );
    pTxSpiStats->dPVEopCnt += getStatVal( pEagleObj, 0, AD_StsTxSpiDPVEopCnt );
    pTxSpiStats->dPGEopCnt += getStatVal( pEagleObj, 0, AD_StsTxSpiDPGEopCnt );
    pTxSpiStats->ampleUseDDS2 += getStatVal( pEagleObj, 0, AD_StsTxSpiAmpleUseDDS2 );

	for( portNum = 0; portNum < EAGLE_DATA_PORTS; portNum++ )
	{
		struct npaEagleNetdev_t * eagleDev = pEagleObj->eagleDev[portNum];
	    txMacStatistics *		pTxMacStats = &eagleDev->txMacStats;
		rxMacStatistics *		pRxMacStats = &eagleDev->rxMacStats;

		/* update the Tx Mac stats */
		pTxMacStats->goodByteCountMSB += getStatVal( pEagleObj, 0, AD_StsTxMacGoodByteCountMSB + ( portNum * 0x200 ) );
		pTxMacStats->goodByteCountLSB += getStatVal( pEagleObj, 0, AD_StsTxMacGoodByteCountLSB + ( portNum * 0x200 ) );
		pTxMacStats->errorByteCountMSB += getStatVal( pEagleObj, 0, AD_StsTxMacErrorByteCountMSB + ( portNum * 0x200 ) );
		pTxMacStats->errorByteCountLSB += getStatVal( pEagleObj, 0, AD_StsTxMacErrorByteCountLSB + ( portNum * 0x200 ) );
		pTxMacStats->goodFrames += getStatVal( pEagleObj, 0, AD_StsTxMacGoodFrames + ( portNum * 0x200 ) );
		pTxMacStats->bCASTFrames += getStatVal( pEagleObj, 0, AD_StsTxMacBCASTFrames + ( portNum * 0x200 ) );
		pTxMacStats->mCASTFrames += getStatVal( pEagleObj, 0, AD_StsTxMacMCASTFrames + ( portNum * 0x200 ) );
		pTxMacStats->controlFrames += getStatVal( pEagleObj, 0, AD_StsTxMacControlFrames + ( portNum * 0x200 ) );
		pTxMacStats->vLANFrames += getStatVal( pEagleObj, 0, AD_StsTxMacVLANFrames + ( portNum * 0x200 ) );
		pTxMacStats->pauseFrames += getStatVal( pEagleObj, 0, AD_StsTxMacPauseFrames + ( portNum * 0x200 ) );
		pTxMacStats->frames64B += getStatVal( pEagleObj, 0, AD_StsTxMac64BFrames + ( portNum * 0x200 ) );
		pTxMacStats->frames65to127B += getStatVal( pEagleObj, 0, AD_StsTxMac65to127BFrames + ( portNum * 0x200 ) );
		pTxMacStats->frames128to255B += getStatVal( pEagleObj, 0, AD_StsTxMac128to255BFrames + ( portNum * 0x200 ) );
		pTxMacStats->frames256to511B += getStatVal( pEagleObj, 0, AD_StsTxMac256to511BFrames + ( portNum * 0x200 ) );
		pTxMacStats->frames512to1023B += getStatVal( pEagleObj, 0, AD_StsTxMac512to1023BFrames + ( portNum * 0x200 ) );
		pTxMacStats->frames1024to1518B += getStatVal( pEagleObj, 0, AD_StsTxMac1024to1518BFrames + ( portNum * 0x200 ) );
		pTxMacStats->over1518BFrames += getStatVal( pEagleObj, 0, AD_StsTxMacOver1518BFrames + ( portNum * 0x200 ) );
		pTxMacStats->erroredFrames += getStatVal( pEagleObj, 0, AD_StsTxMacErroredFrames + ( portNum * 0x200 ) );
		pTxMacStats->filterDropFrames += getStatVal( pEagleObj, 0, AD_StsTxMacFilterDropFrames + ( portNum * 0x200 ) );
		pTxMacStats->tooLongFrames += getStatVal( pEagleObj, 0, AD_StsTxMacTooLongFrames + ( portNum * 0x200 ) );
		pTxMacStats->droppedFrames += getStatVal( pEagleObj, 0, AD_StsTxMacDroppedFrames + ( portNum * 0x200 ) );
		pTxMacStats->fIFOUnderRun += getStatVal( pEagleObj, 0, AD_StsTxMacFIFOUnderRun + ( portNum * 0x200 ) );
		pTxMacStats->cRCErrorCountLT64 += getStatVal( pEagleObj, 0, AD_StsTxMacCRCErrorCountLT64 + ( portNum * 0x200 ) );
		pTxMacStats->cRCErrorCount += getStatVal( pEagleObj, 0, AD_StsTxMacCRCErrorCount + ( portNum * 0x200 ) );
		pTxMacStats->cRCErrorCountGT1518 += getStatVal( pEagleObj, 0, AD_StsTxMacCRCErrorCountGT1518 + ( portNum * 0x200 ) );
		pTxMacStats->cRCErrorCountGTMax += getStatVal( pEagleObj, 0, AD_StsTxMacCRCErrorCountGTMax + ( portNum * 0x200 ) );

		/* update the Rx Mac stats */
		pRxMacStats->vLANTagRcvd += getStatVal( pEagleObj, 0, AD_StsRxMacVLANTagRcvd + ( portNum * 0x200 ) );
		pRxMacStats->pauseTime += getStatVal( pEagleObj, 0, AD_StsRxMacPauseTime + ( portNum * 0x200 ) );
		pRxMacStats->octetsRcvdOKMSB += getStatVal( pEagleObj, 0, AD_StsRxMacOctetsRcvdOKMSB + ( portNum * 0x200 ) );
		pRxMacStats->octetsRcvdOKLSB += getStatVal( pEagleObj, 0, AD_StsRxMacOctetsRcvdOKLSB + ( portNum * 0x200 ) );
		pRxMacStats->numOfBadOctetsMSB += getStatVal( pEagleObj, 0, AD_StsRxMacNumOfBadOctetsMSB + ( portNum * 0x200 ) );
		pRxMacStats->numOfBadOctetsLSB += getStatVal( pEagleObj, 0, AD_StsRxMacNumOfBadOctetsLSB + ( portNum * 0x200 ) );
		pRxMacStats->numOfBadFrms += getStatVal( pEagleObj, 0, AD_StsRxMacNumOfBadFrms + ( portNum * 0x200 ) );
		pRxMacStats->numOfCRCErrors += getStatVal( pEagleObj, 0, AD_StsRxMacNumOfCRCErrors + ( portNum * 0x200 ) );
		pRxMacStats->numOfCRCErrorsGT1518 += getStatVal( pEagleObj, 0, AD_StsRxMacNumOfCRCErrorsGT1518 + ( portNum * 0x200 ) );
		pRxMacStats->numOfCRCErrorsGTMax += getStatVal( pEagleObj, 0, AD_StsRxMacNumOfCRCErrorsGTMax + ( portNum * 0x200 ) );
		pRxMacStats->numOfBcastFrms += getStatVal( pEagleObj, 0, AD_StsRxMacNumOfBcastFrms + ( portNum * 0x200 ) );
		pRxMacStats->numOfMcastFrms += getStatVal( pEagleObj, 0, AD_StsRxMacNumOfMcastFrms + ( portNum * 0x200 ) );
		pRxMacStats->frmsOf64Octets += getStatVal( pEagleObj, 0, AD_StsRxMacFrmsOf64Octets + ( portNum * 0x200 ) );
		pRxMacStats->frmsOf65to127Octets += getStatVal( pEagleObj, 0, AD_StsRxMacFrmsOf65to127Octets + ( portNum * 0x200 ) );
		pRxMacStats->frmsOf128to255Octets += getStatVal( pEagleObj, 0, AD_StsRxMacFrmsOf128to255Octets + ( portNum * 0x200 ) );
		pRxMacStats->frmsOf256to511Octets += getStatVal( pEagleObj, 0, AD_StsRxMacFrmsOf256to511Octets + ( portNum * 0x200 ) );
		pRxMacStats->frmsOf512to1023Octets += getStatVal( pEagleObj, 0, AD_StsRxMacFrmsOf512to1023Octets + ( portNum * 0x200 ) );
		pRxMacStats->frmsOf1024to1518Octets += getStatVal( pEagleObj, 0, AD_StsRxMacFrmsOf1024to1518Octets + ( portNum * 0x200 ) );
		pRxMacStats->oversizeFrms += getStatVal( pEagleObj, 0, AD_StsRxMacOversizeFrms + ( portNum * 0x200 ) );
		pRxMacStats->undersizeFrms += getStatVal( pEagleObj, 0, AD_StsRxMacUndersizeFrms + ( portNum * 0x200 ) );
		pRxMacStats->numOfFragments += getStatVal( pEagleObj, 0, AD_StsRxMacNumOfFragments + ( portNum * 0x200 ) );
		pRxMacStats->numOfLongErrors += getStatVal( pEagleObj, 0, AD_StsRxMacNumOfLongErrors + ( portNum * 0x200 ) );
		pRxMacStats->numOfJabbers += getStatVal( pEagleObj, 0, AD_StsRxMacNumOfJabbers + ( portNum * 0x200 ) );
		pRxMacStats->fRcvdOK += getStatVal( pEagleObj, 0, AD_StsRxMacFRcvdOK + ( portNum * 0x200 ) );
		pRxMacStats->fTooLongErrors += getStatVal( pEagleObj, 0, AD_StsRxMacFTooLongErrors + ( portNum * 0x200 ) );
		pRxMacStats->ctrlFRcvd += getStatVal( pEagleObj, 0, AD_StsRxMacCtrlFRcvd + ( portNum * 0x200 ) );
		pRxMacStats->unsuppOpcodeRcvd += getStatVal( pEagleObj, 0, AD_StsRxMacUnsuppOpcodeRcvd + ( portNum * 0x200 ) );
		pRxMacStats->goodVLANFRcvd += getStatVal( pEagleObj, 0, AD_StsRxMacGoodVLANFRcvd + ( portNum * 0x200 ) );
		pRxMacStats->badSAFRcvd += getStatVal( pEagleObj, 0, AD_StsRxMacBadSAFRcvd + ( portNum * 0x200 ) );
		pRxMacStats->dataError += getStatVal( pEagleObj, 0, AD_StsRxMacDataError + ( portNum * 0x200 ) );
		pRxMacStats->uCASTDrop += getStatVal( pEagleObj, 0, AD_StsRxMacUCASTDrop + ( portNum * 0x200 ) );
		pRxMacStats->filDrop += getStatVal( pEagleObj, 0, AD_StsRxMacFilDrop + ( portNum * 0x200 ) );
	}

	npaEgRegGet( pEagleObj, 0x54, 0, &regVal );
	DPRINTK( TRACE, INFO, "eagle", "clock monitor is %x\n", ( regVal & 0x3F ) );


	spin_unlock_irqrestore( &pEagleObj->devLock, flags );

	/* reschedule timer in 5 second intervals */
	mod_timer(&pEagleObj->npa_eh_timer, jiffies + 5*HZ );
}

static int npaEagleDestroy( struct npaFunctionObj_t * pFunction )
{
	struct npaObject_t * devObj = pFunction->parent;
	struct npaEagleObj_t * pEagleObj = (struct npaEagleObj_t *)pFunction->function_data;
	int i = 0;

	if( pFunction->function_id != eNpaFunctionEagle )
	{
		DPRINTK( ERROR, ERR, "eagle", "npaEagleDestroy(); invalid function object of type %d\n", pFunction->function_id );
		return -EINVAL;
	}

	if( ( pEagleObj->flags & OBJ_FLAG_INTERRUPT_ALLOC) == OBJ_FLAG_INTERRUPT_ALLOC )
	{
		DPRINTK( TRACE, INFO, "eagle", "npaEagleDestroy(): freeing ISR\n");
		npaFreeIrq( pFunction->parent, AT5800_INT_RTM0, pFunction );
		pEagleObj->flags &= ~OBJ_FLAG_INTERRUPT_ALLOC;
	}

	if( (pEagleObj->flags & OBJ_FLAG_TIMER_ALLOC) == OBJ_FLAG_TIMER_ALLOC )
	{
		DPRINTK( TRACE, INFO, "eagle", "npaEagleDestroy(): shutting down timer\n");

		/* shutdown the timer */
		del_timer_sync(&pEagleObj->npa_eh_timer);
		pEagleObj->flags &= ~OBJ_FLAG_TIMER_ALLOC;
	}

	if( (pEagleObj->flags & OBJ_FLAG_PROC_ALLOC) == OBJ_FLAG_PROC_ALLOC )
	{
		DPRINTK( TRACE, INFO, "eagle", "shutting down proc interfaces\n");
		npaEgRemoveProcEntries( pFunction );
		pEagleObj->flags &= ~OBJ_FLAG_PROC_ALLOC;
	}

	/* unregister netdevs */
	for( i = 0; i < EAGLE_DATA_PORTS; i++ )
	{
		struct net_device * netdev = (pEagleObj->eagleDev[i]) ? pEagleObj->eagleDev[i]->netdev : NULL;
		if( netdev )
		{
			if( (pEagleObj->eagleDev[i]->flags & PORT_FLAG_NETDEV_REGISTERED) == PORT_FLAG_NETDEV_REGISTERED )
			{
				unregister_netdev( netdev );
				pEagleObj->eagleDev[i]->flags &= ~PORT_FLAG_NETDEV_REGISTERED;
			}
			free_netdev( netdev );
		}
	}

	/* shutdown the device */

	/* free the struct */
	kfree( pFunction );

	return 0;
}

static int npaEagleSetLoopback( struct npaFunctionObj_t * pFunction, int port, int type )
{
	struct npaObject_t * devObj = pFunction->parent;
	struct npaEagleObj_t * pEagleObj = (struct npaEagleObj_t *)pFunction->function_data;
	uint32_t regVal = 0;
	int retVal = -EIO;

	switch( type )
	{
	case eNpaLoopbackModeLine:
		/* enable the Rx to Tx loopback on the SERDES level */
		regVal = 1 << port;
#if 0
		npaEgRegSet ( egAsicRegs, CfgCoSGMIIRx2TxLoopbackMode__SelSGMIIRx2TxLb, 0, regVal);
#endif
		retVal = 0;
		break;

	case eNpaLoopbackModePhy:
	case eNpaLoopbackModeMAC:
		/* enable the Tx to Rx loopback on the SERDES level */
		regVal = 1 << port;
#if 0
		npaEgRegSet ( egAsicRegs, CfgCoSGMIITx2RxLoopbackMode__SelSGMIITx2RxLb, 0, regVal);
#endif
		retVal = 0;
		break;

	case eNpaLoopbackModeDisable:
#if 0
		regGet( egAsicRegs, CfgCoSGMIITx2RxLoopbackMode, 0, &regVal );
		regVal &= ~( 1 << port );
		npaEgRegSet( egAsicRegs, CfgCoSGMIITx2RxLoopbackMode, 0, regVal );

		regGet( egAsicRegs, CfgCoSGMIIRx2TxLoopbackMode, 0, &regVal );
		regVal &= ~( 1 << port );
		npaEgRegSet( egAsicRegs, CfgCoSGMIIRx2TxLoopbackMode, 0, regVal );
#endif
		break;
	default:
		DPRINTK(ERROR, ERR, "eagle", "unsupported loopback mode\n");
		return -EINVAL;
	}

	return 0;
}

static int npaEagleIoctl( struct npaFunctionObj_t * pFunction, unsigned int cmd, void * data )
{
	struct npaObject_t * devObj = pFunction->parent;
	struct npaEagleObj_t * pEagleObj = (struct npaEagleObj_t *)pFunction->function_data;
	int retVal = -EINVAL;
	unsigned long flags;

	if( pFunction->function_id != eNpaFunctionEagle )  {
		DPRINTK(ERROR, ERR, "eagle", "invalid operation\n");
		return -EINVAL;
	}

/* BUGBUG, TODO: NPA FPGA logic expects PHY OP to work */

	/* single access to the device */
	spin_lock_irqsave( &pEagleObj->devLock, flags );
	switch( cmd )
	{
	/*
	 * request from the upper layer for the supported user-mode device type
	 */
	case cmdGeneric_GetDeviceId:
		spin_unlock_irqrestore( &pEagleObj->devLock, flags );
		return eDevEagle;
	/*
	 * When the upper level receives a loopback mode command directed
	 * at the Prestera device, this is where it ends up
	 */
	case cmdGeneric_SetLoopback:
		{
			NPA_LOOPBACK_INFO_t * pLoopData = (NPA_LOOPBACK_INFO_t *)data;
			retVal = npaEagleSetLoopback( pFunction, pLoopData->port, pLoopData->type );
		}
		break;
	/*
	 * When a new SFP is inserted or removed, the eagle port must be reinitialized
	 * to the correct mode.  This IOCTL does that reinitialization
	 */
	case cmdGeneric_ReinitPort:
		/*
		 * Ignore the SFP_TYPE that is passed in and read it ourselves.  This also
		 * handles the case where the port was disabled and ReinitPort is being
		 * called to reactivate the port as well
		 */
		if( 0 != npaEgEnablePort( pEagleObj, ((int *)data)[0] ))
		{
			DPRINTK( ERROR, ERR, "eagle", "failed to configure port: %d\n", ((int *)data)[0] );
			spin_unlock_irqrestore( &pEagleObj->devLock, flags );
			return -EIO;
		}
		retVal = 0;
		break;

	/*
	 * Called when the upper layer wants to disable this port's output
	 */
	case cmdGeneric_DisablePort:
		if( 0 != npaEgDisablePort( pEagleObj, ((int *)data)[0] ))
		{
			DPRINTK( ERROR, ERR, "eagle", "failed to configure port: %d\n", ((int *)data)[0] );
			spin_unlock_irqrestore( &pEagleObj->devLock, flags );
			return -EIO;
		}
		retVal = 0;
		break;

	/*
	 * Called when the upper layer wants to enable the port's output
	 */
	case cmdGeneric_EnablePort:
		if( 0 != npaEgEnablePort( pEagleObj, ((int *)data)[0] ))
		{
			DPRINTK( ERROR, ERR, "eagle", "failed to configure port: %d\n", ((int *)data)[0] );
			spin_unlock_irqrestore( &pEagleObj->devLock, flags );
			return -EIO;
		}
		retVal = 0;
		break;

	default:
		DPRINTK(ERROR, ERR, "eagle", "npaEagleIoctl(): invalid operation\n");
		spin_unlock_irqrestore( &pEagleObj->devLock, flags );
		return -EINVAL;
	}
	spin_unlock_irqrestore( &pEagleObj->devLock, flags );
	return 0;
}

static struct net_device_stats * npaEagleGetStats(struct net_device *netdev)
{
	struct npaEagleNetdev_t *eagleDev = netdev_priv(netdev);
	struct net_device_stats *stats = &eagleDev->stats;
#define MAKE_QWORD( x, y )		( (u64)0 | ((u64)x << 32) | (u64)y )

	/* snapshot the stats out of the timer stats */
	stats->tx_packets = eagleDev->txMacStats.goodFrames;
	stats->tx_bytes = MAKE_QWORD( eagleDev->txMacStats.goodByteCountMSB, eagleDev->txMacStats.goodByteCountLSB );

	stats->rx_packets = eagleDev->rxMacStats.fRcvdOK;
	stats->rx_bytes = MAKE_QWORD( eagleDev->rxMacStats.octetsRcvdOKMSB, eagleDev->rxMacStats.octetsRcvdOKLSB );
	stats->rx_errors = eagleDev->rxMacStats.numOfBadFrms;
	stats->rx_length_errors = eagleDev->rxMacStats.fTooLongErrors;
	stats->rx_crc_errors = eagleDev->rxMacStats.numOfCRCErrors;

	return stats;
}

static int npaEagleEtherIoctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
{
	struct npaEagleNetdev_t *eagleDev = netdev_priv(netdev);
	return 0;
}
#endif /*defined(LINUX_OS) && !defined(__U_BOOT__) */

int npaEgAsicPhyIntr( struct npaEagleObj_t * eagleObj )
{
	int portNum;
	uint32_t regVal, intrRegVal;

	/* process interrupts on all the ports in our data path */
	for( portNum = 0; portNum < EAGLE_DATA_PORTS; portNum++ )
	{
#if defined(LINUX_OS) && !defined(__U_BOOT__)
		struct npaEagleNetdev_t *eagleDev = eagleObj->eagleDev[portNum];
#endif
		npaEgRegGet( eagleObj, AD_StsMdioRxInterrupt + (portNum * 0x200), 0, &intrRegVal );
		if( intrRegVal == 0 )
			continue;
		if( intrRegVal & ( 1 << 8 ))
		{
			DPRINTK( ERROR, ERR, "eagle", "AutoNeg completed for port %d\n", portNum );
			if( eagleObj->sfpType[portNum] == SFP_COPPER )
			{
				configMACAfterAutoneg( eagleObj, portNum);
			}
			else if( eagleObj->sfpType[portNum] == SFP_FIBER )
			{
				npaEgAsicAutoNegCompleteFiberStatus(eagleObj, portNum);
			}

		}

		if( intrRegVal & ( 1 << 7 ))
		{
			npaEgRegGet( eagleObj, AD_StsMdioRxStatus + ( portNum * 0x200), 0, &regVal);
			if( regVal & (1<<7) )
			{
				DPRINTK( ERROR, ERR, "eagle", "LinkStatus changed to UP for port %d\n", portNum );
#if defined(LINUX_OS) && !defined(__U_BOOT__)
				netif_carrier_on( eagleDev->netdev );
#endif
			}
			else
			{
				DPRINTK( ERROR, ERR, "eagle", "LinkStatus changed to DOWN for port %d\n", portNum );
#if defined(LINUX_OS) && !defined(__U_BOOT__)
				netif_carrier_off( eagleDev->netdev );
#endif
			}
		}
	}

	return 0;
}

#if defined(LINUX_OS)
static int npaEagleIntr( struct npaFunctionObj_t * pFunction )
#elif defined(__U_BOOT__)
int npaEagleIntr( void * unused )
#endif
{
#if defined(__U_BOOT__)
	struct npaEagleObj_t * eagleObj = &gEagleObj;
#elif defined(LINUX_OS)
	struct npaObject_t * devObj = pFunction->parent;
	struct npaEagleObj_t * eagleObj = (struct npaEagleObj_t *)pFunction->function_data;
#endif
	unsigned int intSrc = 0;
#if defined(LINUX_OS)
	unsigned int flags;
#endif

#if defined(LINUX_OS)
	spin_lock_irqsave( &eagleObj->devLock, flags );
#endif
    /* Read the Interrupt Source register */
    npaEgRegGet( eagleObj, AD_StsCoInterruptSource, 0, &intSrc);
	if( intSrc != 0 )
	{
		/* Check for the PHY Modules Interrupt */
		if (intSrc & (1 << 15) ) {
			npaEgAsicPhyIntr( eagleObj );
		}
#if 0
    if (intSrc & MDIO_INTR); /* no MDIO interface enabled on the EAGLE */


    /* Check for the Rx MAC Interrupt */
    if (intSrc & MAC_INTR) {
        egAsicRxMacIntr(regdb);
    }

    /* Check for the Rx SPI Interrupt */
    if (intSrc & RXSPI_INTR) {
        egAsicRxSpiIntr(regdb);
    }

    /* Check for the Tx SPI Interrupt */
    if (intSrc & TXSPI_INTR) {
        egAsicTxSpiIntr(regdb);
    }

    /* Check for the Rx Queue Manager Interrupt */
    if (intSrc & RXQUEUE_MGR_INTR) {
        egAsicRxQueueMgrIntr(regdb);
    }

    /* Check for the Rx Dequeuer Interrupt */
    if (intSrc & RXDEQUEUE_INTR) {
        egAsicRxDeqIntr(regdb);
    }

    /* Check for the Rx Enqueuer Interrupt */
    if (intSrc & RXENQ_INTR) {
        egAsicEnqIntr(regdb);
    }

    /* Check for the Rx Internal Memory Interrupt */
    if (intSrc & RXINT_MEM_INTR) {
        egAsicRxIntMemIntr(regdb);
    }

    /* Check for the Tx Memory Manager Interrupt */
    if (intSrc & TXMEM_MGR_INTR) {
        egAsicTxMemIntr(regdb);
    }

    /* Check for the Tx CPU To Line Interrupt */
    if (intSrc & TXCPU2LINE_INTR) {
        egAsicTxCpu2LineIntr(regdb);
    }

    /* Check for the Rx Line To CPU Interrupt */
    if (intSrc & RXLINE2CPU_INTR) {
        egAsicRxLine2CpuIntr(regdb);
    }

    /* Check for the Rx Drop Controller Interrupt */
    if (intSrc & RXDROPCTRL_INTR) {
        egAsicRxDropCtrlIntr(regdb);
    }


    /* Check for the Common Source Interrupt */
    if (intSrc & COMMON_INTR) {
        egAsicCommonIntr(regdb);
    }
#endif
	}

#if defined(LINUX_OS)
	spin_unlock_irqrestore( &eagleObj->devLock, flags );
#endif
	return 0;
}


#if defined(LINUX_OS) && !defined(__U_BOOT__)
/* place holders in case someone ifconfig's our interface */
static int npaFakeDevOpen( struct net_device *dev)
{
    return -EINVAL;
}

static int npaFakeDevStop( struct net_device *dev)
{
    return -EINVAL;
}
#endif

#if defined(LINUX_OS) && !defined(__U_BOOT__)
  int npaEagleInit( struct npaObject_t * devObj, struct npaFunctionObj_t ** ppFunction )
#else
  int npaEagleInit( void * unused1, void * unused2 )
#endif
{
#if defined(LINUX_OS)
	struct npaFunctionObj_t * pFunction = NULL;
	struct npaEagleObj_t * pEagleObj = NULL;
	void * baseAddr = (void *)(devObj->fpgaBase + AT5800_EAGLE_BASE_ADDR);
	uint8_t mcr1;
	uint8_t intenb1;
	struct npaEagleNetdev_t * eagleDev = NULL;
	struct net_device *netdev;
	int i;
	uint32_t regVal;
#elif defined(__U_BOOT__)
	struct npaEagleObj_t * pEagleObj = &gEagleObj;

	memset( pEagleObj, 0x00, sizeof(struct npaEagleObj_t));
#endif

#if defined(LINUX_OS)
	/* confirm the module has access to the device */
	switch(devObj->ModuleID)
	{
		case OCTEON_AT5800:
			break;
		default:
			DPRINTK(ERROR, ERR, "eagle", "the eagle is not supported on %d\n", devObj->ModuleID);
			return -EINVAL;
	}

	/* check if we have access to the EAGLE device */
	mcr1 = readFpgaReg( devObj, AT5800_MCR1 );
	if( ((AT5800_CAV_ID( devObj->flags ) == AT5800_CAVA_ID) && (AT5800_MCR1_RTM_MSTR(mcr1) != AT5800_MCR_CAVA_MASTER) ) ||
		((AT5800_CAV_ID( devObj->flags ) == AT5800_CAVB_ID) && (AT5800_MCR1_RTM_MSTR(mcr1) != AT5800_MCR_CAVB_MASTER) ) )
	{
		DPRINTK(ERROR, ERR, "eagle", "MCR1 set to 0x%x, we do not have Eagle control\n", mcr1);
		return -EACCES;
	}

	pFunction = (struct npaFunctionObj_t *)kmalloc( (sizeof(struct npaFunctionObj_t) + sizeof(struct npaEagleObj_t) ), GFP_KERNEL );
	if( NULL == pFunction )
	{
		DPRINTK(ERROR, ERR, "eagle", "npaHawkInit(): failed to initialize function object\n");
		return -ENOMEM;
	}
	memset( pFunction, 0x00, (sizeof(struct npaFunctionObj_t) + sizeof(struct npaEagleObj_t) ));

	pFunction->parent = devObj;
	pFunction->function_id = eNpaFunctionEagle;
	pFunction->function_data = (char *)pFunction + sizeof(struct npaFunctionObj_t);
	pFunction->shutdown = npaEagleDestroy;
	pFunction->ioctl = npaEagleIoctl;

	pEagleObj = (struct npaEagleObj_t *)pFunction->function_data;
	spin_lock_init( &pEagleObj->devLock );
	pEagleObj->flags |= OBJ_FLAG_SEM_ALLOC;
	pEagleObj->baseAddress = (unsigned long)baseAddr;
#elif defined(__U_BOOT__)
	pEagleObj->baseAddress = (unsigned long)BOARD_RTM_EAGLE_BASE_REG;
#endif

	/***********************************************
    * mode_type = 0; 24 SGMII ports
    * mode_type = 1; 12 SGMII ports
    * mode_type = 2; 12 SGMII ports + 2 RGMII ports
    * mode_type = 3; 2:1 Funnel
    * mode_type = 4; 3:1 Funnel
    * mode_type = 5; 22 SGMII ports + 2 RGMII ports
    * mode_type = 6; 16 SGMII ports
    */
    if( 0 != npaEgInitAsic( pEagleObj, 1 ))
	{
		DPRINTK(ERROR, ERR, "eagle", "eagleInit(): failed to initialize the EAGLE\n");
		return ERROR(-EIO);
	}

#if defined(LINUX_OS)
	/* Create some linux netdevs that we will use just for ethtool */
	for( i = 0; i < EAGLE_DATA_PORTS; i++ )
	{
        if( NULL == (netdev = alloc_netdev( sizeof(struct npaEagleNetdev_t), "eag%d", ether_setup )))
		{
			DPRINTK(ERROR, ERR, "eagle", "npaEagleInit(): -1 allocating netdevs\n");
			pFunction->shutdown( pFunction );
			return ERROR(-ENOMEM);
		}
		netdev->get_stats = npaEagleGetStats;
		netdev->do_ioctl = npaEagleEtherIoctl;
		netdev->open = npaFakeDevOpen;
		netdev->stop = npaFakeDevStop;

		eagleDev = netdev_priv(netdev);
		eagleDev->netdev = netdev;
		eagleDev->parent = pEagleObj;

		/* setup our ethtool hooks */
		npaEgSetEthtoolOps( netdev );

		if( 0 != register_netdev( netdev ))
		{
			DPRINTK(ERROR, ERR, "eagle", "npaEagleInit(): -1 registering device\n");
			pFunction->shutdown( pFunction );
			return ERROR(-EIO);
		}
		eagleDev->flags |= PORT_FLAG_NETDEV_REGISTERED;

		/* set initial link status */
		npaEgRegGet( pEagleObj, AD_StsMdioRxStatus + ( i * 0x200), 0, &regVal);
		if( regVal & (1<<7) )
			netif_carrier_on( eagleDev->netdev );
		else
			netif_carrier_off( eagleDev->netdev );

		pEagleObj->eagleDev[i] = eagleDev;
	}

	if( (devObj->flags & NPA_FLAG_INTERRUPT) != NPA_FLAG_INTERRUPT )
	{
		DPRINTK(ERROR, ERR, "eagle", "interrupt not hooked, not enabling redhawk interrupts\n");
	}
	else
	{
		npaRequestIrq( devObj, AT5800_INT_RTM0, npaEagleIntr, pFunction );
		pEagleObj->flags |= OBJ_FLAG_INTERRUPT_ALLOC;
	}

	init_timer(&pEagleObj->npa_eh_timer);
	pEagleObj->npa_eh_timer.function = npaEagleTimer;
	pEagleObj->npa_eh_timer.data = (unsigned long)pFunction;
	mod_timer(&pEagleObj->npa_eh_timer, jiffies );
	pEagleObj->flags |= OBJ_FLAG_TIMER_ALLOC;

	if( 0 != npaEgAddProcEntries( pFunction ) )
	{
		DPRINTK(ERROR, ERR, "eagle", "Failed to add proc entries for eagle\n");
		pFunction->shutdown(pFunction);
		return ERROR(-EIO);
	}
	pEagleObj->flags |= OBJ_FLAG_PROC_ALLOC;

	*ppFunction = pFunction;
#endif
	return 0;
}

#endif


int npaEgRegSet( struct npaEagleObj_t * eagleObj, int offset, uint32_t mask, uint32_t val )
{
	if( mask != 0 )
	{
		uint32_t curVal = 0;
		uint32_t shiftFact = 0;
		/* find the lo bit postion */
		while( (mask & ( 0x1 << shiftFact )) == 0 )
			shiftFact++;

		npaEgRegGet( eagleObj, offset, 0, &curVal );
		val = val << shiftFact;
		val |= (curVal & ~mask );
	}
	*((volatile uint32_t *)((volatile char *)eagleObj->baseAddress + offset)) = val;

	//printk(KERN_ERR"npaEgRegSet(): writing %x to %llx using mask: %x\n", val, eagleObj->baseAddress + offset, mask );

	return 0;
}

int npaEgRegGet( struct npaEagleObj_t * eagleObj, int offset, int instance, uint32_t * pVal )
{
	*pVal = *((volatile uint32_t *)((volatile char *)eagleObj->baseAddress + offset));
	//printk(KERN_ERR"npaEgRegSet(): read %x from %llx\n", *pVal, eagleObj->baseAddress + offset );
	return 0;

}

int npaEgAsicFindModuleType( struct npaEagleObj_t * eagleObj, int portNum )
{
    int regVal;
    int mask;

    if (portNum < 0 || portNum > 23)
	{
        DPRINTK( ERROR, ERR, "eagle", "The argument portNum passed is incorrect\n");
        DPRINTK( ERROR, ERR, "eagle", "portNum can take values between 0 and 23\n");
		return -1;
    }

    /* Check for the RGMII port */
    if (portNum > 21) {
        /* BIT_10 - RGMII 22; BIT_11 - RGMII 23 */
        mask = 1 << (portNum - 22);
        npaEgRegGet (eagleObj, AD_CfgCoRGMIIInterfaceSetup, 0, (unsigned int *)&regVal);
        if (regVal & mask) {
            DPRINTK( ERROR, ERR, "eagle", "The port %d is configured as RGMII port\n", portNum);
            DPRINTK( ERROR, ERR, "eagle", "Check CfgCoRGMIIInterfaceSetup register\n");
            return -1;
        }
    }

    /* Reading register 6 of EEPROM */
    /* BIT_3 - Copper */
    /* BIT_1 or BIT_0 - Fiber */
    if ( 0 == npaEgPhyRegRead( eagleObj, portNum, SFP_TRANSCEIVER_6, (unsigned int *)&regVal)) {
        if (regVal & 0x3) {
            return SFP_FIBER;
        } else {
            return SFP_COPPER;
        }
    }
    return SFP_VACANT;
}

int npaEgAsicConfigFiberPort( struct npaEagleObj_t * eagleObj, int portNum )
{
    if (portNum < 0 || portNum > 23) {
        DPRINTK(ERROR, ERR, "eagle", "The argument portNum passed is incorrect\n");
        DPRINTK(ERROR, ERR, "eagle", "portNum can take values between 0 and 23\n");
    }

    /*
     * Find the Fiber port and make the required configuration because the ports come
     * up in Copper mode by default
     */
    if( SFP_FIBER == npaEgAsicFindModuleType(eagleObj, portNum))
	{
        /* Found a Fiber Port */
        /* Enable Fiber mode */
		if( (portNum > 0) && (portNum < EAGLE_DATA_PORTS) )
		{
			npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_0 + (portNum * 4), MAKE_MASK( 0, 0 ), 0);
		}

        /* Enable Auto Negotiation for the respective port */
        npaEgRegSet (eagleObj, AD_VarMdioControl + (portNum * 0x200), MAKE_MASK(12, 12), 1);
        npaEgRegSet (eagleObj, AD_VarMdioAutonegAdvt + (portNum * 0x200), MAKE_MASK(15, 0), 0x20);

		if( (portNum > 0) && (portNum < EAGLE_DATA_PORTS) )
		{
			/* Enable PCS Layer for the respective fiber port */
			npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_0 + (portNum * 4), MAKE_MASK( 3, 3 ), 1);
		}

        /* Restart Autonegotation on the respective port */
        npaEgRegSet (eagleObj, AD_VarMdioControl + (portNum * 0x200), MAKE_MASK( 9, 9 ), 1);

		DPRINTK( TRACE, INFO, "eagle", "configuring port %d to fiber mode\n", portNum );
		return 0;
    }
	return -1;
}

/******************************************************************
* egAsicWriteSpiDeskewReg - Write to Spi 4.2 Deskew core register.
*
* This routine write's to a Deskew Core register. This routine configures the
* AmpleUseOnly register as Deskew Core write data and Rsvdbit31to24 of
* TxFunctionActivateTxMemPerPort register field will act as a Deskew write
* command. After Deskew Core access is done, the CPU Access Enable has to Reset.
*
* RETURNS: None
*/
static int npaEgAsicWriteSpiDeskewReg(
	struct npaEagleObj_t * eagleObj,
    unsigned int addr,          /* register address */
    unsigned int data           /* data to be written */
    )
{
    unsigned int regVal;

    npaEgRegSet (eagleObj, AD_CfgCoAmpleUseOnly, 0, data);
    regVal = addr | 6 << 5; /* 6 is for Write En and Deskew CPU Access Enable */
    npaEgRegSet (eagleObj, AD_VarCoTxFunctionActivateTxMemPerPort, MAKE_MASK(31,24), regVal);
    udelay(100);
    /* Write Completion */
    npaEgRegSet (eagleObj, AD_VarCoTxFunctionActivateTxMemPerPort, MAKE_MASK(31,24), 0);
	return 0;
}

/******************************************************************
* egAsicSpiProgramCalendar - Program the Eagle SPI Calendar Sequence
*
* Calendar sequence programming at the ingress SPI (RSPI) and egress SPI (TSPI)
* are done based on the mode type.
*
* modeType = 0; mac24; CalLength = 24; CalM = 1; CalMap = 0, 1, .., 23
* modeType = 1; mac12; CalLength = 12; CalM = 1; CalMap = 0, 1, .., 11
* modeType = 2; mac12 + RGMII; CalLength = 14; CalM = 1; CalMap = 0, 1, .., 11, 22, 23
* modeType = 3; 2:1 Funnel; CalLength = 12; CalM = 1; CalMap = 0, 1, .., 11
* modeType = 4; 3:1 Funnel; CalLength = 8; CalM = 1; CalMap = 0, 1, .., 7
*
* RETURNS: None
*/
static int npaEgAsicSpiProgramCalendar(
	struct npaEagleObj_t * eagleObj,
    int modeType                /* SPI calendar sequence programming type */
    )
{
    int cal_l=1, i;

    if (modeType < 0 || modeType > 6) {
		DPRINTK( ERROR, ERR, "eagle", "The argument 'modeType' passed is incorrect\n" );
		DPRINTK( ERROR, ERR, "eagle", "modeType can take values between 0 and 6\n" );
		return -1;
    }

    /* Configure the cal_l value */
    if (modeType == 0) {
        cal_l = 24;
    } else if (modeType == 1) {
        cal_l = 12;
    } else if (modeType == 2) {
        cal_l = 14;
    } else if (modeType == 3) {
        cal_l = 12;
    } else if (modeType == 4) {
        cal_l = 8;
    } else if (modeType == 5) {
        cal_l = 24;
    } else if (modeType == 6) {
        cal_l = 16;
    }

	/* GEFES Mode = 10 gig-e's mapped to a SPI Port on channels 0-9 */
#if 1
	cal_l = 10;
#endif

    /* Rx SPI Calendar Programming */
    npaEgRegSet (eagleObj, AD_CfgRxSpiSetup, MAKE_MASK( 12, 0 ), 0x00000008);
    npaEgRegSet (eagleObj, AD_CfgRxSpiCalSetup, MAKE_MASK( 10, 2 ), cal_l);
    npaEgRegSet (eagleObj, AD_CfgRxSpiCalSetup, MAKE_MASK( 1, 0 ), 1);
	for( i = 0; i < 24; i++ )
	{
	    if (modeType == 2 && ( i == 12 || i == 13 )) {  /* BUGBUG: modeType==2 is buggy */
	        npaEgRegSet (eagleObj, AD_CfgRxSpiCalPriMem0_0 + ( i * 4 ), MAKE_MASK(5, 0), 0 );
		} else {
            npaEgRegSet (eagleObj, AD_CfgRxSpiCalPriMem0_0 + ( i * 4 ), MAKE_MASK(5, 0), i%cal_l );
		}
	}
    i = 0;
    /*
     * Optionally, the shadow calendars can be be programmed too.
     * This is not necessary for users not planning to use the SPI-4.2
     * calendar switching mechanism.
     *
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_0, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_1, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_2, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_3, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_4, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_5, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_6, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_7, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_8, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_9, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_10, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_11, 0, (i++)%cal_l);
    if (modeType == 2) {
        npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_12, 0, 22);
        npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_13, 0, 23);
    } else {
        npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_12, 0, (i++)%cal_l);
        npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_13, 0, (i++)%cal_l);
    }
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_14, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_15, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_16, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_17, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_18, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_19, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_20, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_21, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_22, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgRxSpiCalShadowMem0_23, 0, (i++)%cal_l);
    */

    /* Tx SPI Calendar Programming */
    npaEgRegSet (eagleObj, AD_CfgTxSpiCalSetup, MAKE_MASK(9,2), cal_l);
    npaEgRegSet (eagleObj, AD_CfgTxSpiCalSetup, MAKE_MASK(1,0), 1);
	for( i = 0; i < 24; i++ )
	{
		npaEgRegSet (eagleObj, AD_CfgTxSpiCalMem0_0 + ( i * 4 ), MAKE_MASK(5, 0), i%cal_l );
	}
    i = 0;
    /*
     * Optionally, the shadow calendars can be be programmed too.
     * This is not necessary for users not planning to use the SPI-4.2
     * calendar switching mechanism.
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_0, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_1, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_2, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_3, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_4, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_5, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_6, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_7, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_8, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_9, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_10, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_11, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_12, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_13, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_14, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_15, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_16, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_17, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_18, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_19, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_20, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_21, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_22, 0, (i++)%cal_l);
    npaEgRegSet (eagleObj, CfgTxSpiCalShadowMem0_23, 0, (i++)%cal_l);
    */
    /* Programming Address Map for TxSPI */
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x00000400);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x00000421);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x00000442);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x00000463);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x00000484);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x000004a5);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x000004c6);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x000004e7);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x00000508);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x00000529);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x0000054a);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x0000056b);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x0000058c);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x000005ad);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x000005ce);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x000005ef);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x00000610);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x00000631);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x00000652);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x00000673);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x00000694);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x000006b5);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x000006d6);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x000006f7);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x00000718);
    npaEgRegSet (eagleObj, AD_CfgTxSpiAddressMap, 0, 0x00000000);
    /*
     * Note that the RxSPIAddressMap does not need to be programmed
     * as the hardware automatically initializes the entries with 1:1 values
     * entry 0 with value 0, entry 1 with value 1 and so on.
     */
	return 0;
}

/******************************************************************
* egAsicInitFreePageTable - Initializes the Rx Queue Manager Free Page Table
*
* The routine initializes the Free page internal memory pool in the
* RxMemMgr (at Queue Manager). This has to be executed whenever hardreset
* was applied to the chip, or softreset was applied to the Queue Manager
* module. This function configures "CfgRxQmgrFreePageTableInit" to a 1, and
* then waits for "StsRxQmgrFreePageTableInitDone" status to become 1.
* "CfgRxQmgrFreePageTableInit" is a self clear config bit. The RxMemMgr
* datapath will be functional only after "StsRxQmgrFreePageTableInitDone"
* was received.
*
* RETURNS: None
*/
static int npaEgAsicInitFreePageTable(
	struct npaEagleObj_t * eagleObj
	)
{
	unsigned int regVal;
	int timeout = 1000;

    npaEgRegSet(eagleObj, AD_CfgRxQmgrFreePageTableInit, 0, 0x00000001);

    /*
     * Check for the FreePageTableInit done interrupt for both the instances
     */
    regVal = 0;
	while( timeout -- )
	{
        npaEgRegGet(eagleObj, AD_StsRxQmgrFreePageTableInitDone, 0, &regVal);
		if( (regVal & 0x1) == 0x1 )
			break;
		udelay(100);
    }
	if( timeout == 0 )
		return -1;
	return 0;
}

static int npaEgAsicConfigTxMem16K(
	struct npaEagleObj_t * eagleObj
	)
{
	int i;

     /*
      * Making all 16KB per port accessible, instead of the default 10KB
      */
     npaEgRegSet (eagleObj, AD_CfgCoMisc, MAKE_MASK(25,2), 0xffffff);

	 for( i = 0; i < 24; i++ )
	 {
		/* adjust the fifo pointers(all ucast mem - 512 lines) */
		npaEgRegSet (eagleObj, AD_CfgTxMemUMcastAllocFifoLinesReg_0 + (i * 4), MAKE_MASK(17,9), 511);
		npaEgRegSet (eagleObj, AD_CfgTxMemUMcastAllocFifoLinesReg_0 + (i * 4), MAKE_MASK(8,0), 511);
		npaEgRegSet (eagleObj, AD_CfgTxMemUcastHungryStarvingThresHoldsReg_0 + (i * 4), MAKE_MASK(18, 9),  485);
	 }
	 return 0;
}

/******************************************************************
* egAsicLEDStatusConfig - Configure the Status LED's on 24 ports
*
* This routine configures the Status LED's for all the 24 ports to indicate
* the possible events, based on the type(input parameter) passed to the
* routine. The type argument can take the following values
*    1 - If MAC speed changed to 10Mbps or changed to other speed from 10Mbps.
*    2 - If MAC speed changed to 100Mbps or changed to other speed from 100Mbps.
*    4 - If MAC speed changed to 1Gbps or changed to other speed from 1Gbps.
*    8 - If there is any change in the Link status.
*   16 - If there is any change in TXFAULT signal from SFP.
*   32 - If there is any change in LOS signal from SFP.
*
* RETURNS: None
*/
static int npaEgAsicLEDStatusConfig(
	struct npaEagleObj_t * eagleObj,
    int type )
{
	int i;

    /* Enable the LED module */
    npaEgRegSet( eagleObj, AD_VarCoTxFunctionActivate, MAKE_MASK(28,28), 1);

    /* Operate the LED clock at its slowest frequency. */
    npaEgRegSet( eagleObj, AD_CfgCoClkDivider, MAKE_MASK(15,8), 0xff);

    /* Change the polarity of the N-LED to make the LED as a Bi-color one. */
    npaEgRegSet( eagleObj, AD_CfgLedOutPolarityVecNReg, MAKE_MASK(23,0), 0x0);

    /*
     * Set the Glitch catch period to 50 LED clocks.
     * The status change in the signal will be reflected on the LED only
     * if the change is stable for atleast the number of clocks configured
     * in this register.
     */
    npaEgRegSet( eagleObj, AD_CfgLedGlitchCatchPeriodReg, 0, 50);

    /* Enable Status LED to indicate the change in status of the enabled signals. */
	for( i = 0; i < EAGLE_CONTROL_PORTS; i++ )
	{
		npaEgRegSet( eagleObj, AD_CfgLedStsEnVecPReg_0 + (i * 4), MAKE_MASK(9,0), type);
		npaEgRegSet( eagleObj, AD_CfgLedStsEnVecNReg_0 + (i * 4), MAKE_MASK(9,0), type);
	}
	return 0;
}

/******************************************************************
* egAsicLEDActivityConfig - Configure the Activity LED's on 24 ports
*
* This routine configures the Activity LED's for all the 24 ports to indicate
* the possible events, based on the type(input parameter) passed to the
* routine. The type argument can take the following values
*      1 - Good Frame Transmitted by TxMAC.
*      2 - Good Frame Recieved by RxMAC.
*      4 - Frame dropped in Drop controller Filters.
*      8 - Broad cast frame drop in dropcontroller.
*     16 - Packet drop in WRED.
*     32 - Packet drop in Enqueuer.
*     64 - SPI Aborted MCast frame drop in Txmemmanager.
*    128 - SPI Aborted UCast frame drop in Txmemmanager.
*
* RETURNS: None
*/
static int npaEgAsicLEDActivityConfig( struct npaEagleObj_t * eagleObj, int type )
{
	int i;

    /* Enable the LED module */
    npaEgRegSet( eagleObj, AD_VarCoTxFunctionActivate, MAKE_MASK(28,28), 1);

    /* Operate the LED clock at its slowest frequency. */
	npaEgRegSet( eagleObj, AD_CfgCoClkDivider, MAKE_MASK(15,8), 0xff);
    /* Program the LED in Bi-colour mode. */
    npaEgRegSet( eagleObj, AD_CfgLedEventWinkCoordEn, MAKE_MASK(0,0), 1);

    /* Program the LED Wink Control ON/OFF timer to some big val so that it helps in LED glowing for atleast a sec. */
	npaEgRegSet( eagleObj, AD_CfgLedWinkCtrlOnOffTimerReg, 0, 0x200);
	/* To clear-off LED counters if no activity occurs for ~1 second */
	npaEgRegSet( eagleObj, AD_CfgLedEventExcessChkTimerMsbReg, MAKE_MASK(16,16), 1);
	npaEgRegSet( eagleObj, AD_CfgLedEventExcessChkTimerMsbReg, MAKE_MASK(15,0), 0);
	npaEgRegSet( eagleObj, AD_CfgLedEventExcessChkTimerLsbReg, MAKE_MASK(31,0), 0x7530);
    /* Enable event LED to indicate the enabled events. */
	for( i = 0; i < EAGLE_CONTROL_PORTS; i++ )
	{
		npaEgRegSet( eagleObj, AD_CfgLedEventEnVecPReg_0 + (i * 4), MAKE_MASK(9,0), type);
		npaEgRegSet( eagleObj, AD_CfgLedEventEnVecNReg_0 + (i * 4), MAKE_MASK(9,0), type);
	}
	return 0;
}

static int npaEgSetLED( struct npaEagleObj_t * eagleObj, int portNum, int enable, int color )
{
	unsigned int enVal, pVal, nVal;
	int type;
	npaEgRegGet( eagleObj, AD_CfgLedStsEnVecPReg_0 + (portNum * 4), 0, (unsigned int *)&type );
	if (type == 8)
	{

		npaEgRegGet( eagleObj, AD_CfgLedStsSwOverRideEnVecReg, 0, &enVal);
		if (enable)
		{
            npaEgRegGet( eagleObj, AD_CfgLedStsSwOverRideValueVecPReg, 0, &pVal);
			npaEgRegGet( eagleObj, AD_CfgLedStsSwOverRideValueVecNReg, 0, &nVal);

			enVal |= (1 << portNum);
			if (color == 0) 
			{
				pVal &= ~(1 << portNum);
				nVal |= (1 << portNum);
			} else if (color == 1) 
			{
				pVal |= (1 << portNum);
				nVal &= ~(1 << portNum);
			}
			npaEgRegSet( eagleObj, AD_CfgLedStsSwOverRideEnVecReg, 0, enVal);
			npaEgRegSet( eagleObj, AD_CfgLedStsSwOverRideValueVecPReg, 0, pVal);
			npaEgRegSet( eagleObj, AD_CfgLedStsSwOverRideValueVecNReg, 0, nVal);
		}
		else
		{
            enVal &= ~(1 << portNum);
			npaEgRegSet( eagleObj, AD_CfgLedStsSwOverRideEnVecReg, 0, enVal);
		}
	}
	return 0;
}

int npaEgDisablePort( struct npaEagleObj_t * eagleObj, int portNum )
{
	DPRINTK( TRACE, INFO, "eagle", "disabling port: %d\n", portNum );

	if( (portNum > 0) && (portNum < EAGLE_DATA_PORTS) )
	{
		/* disable the PCS layer */
		npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_0 + (portNum * 4), MAKE_MASK( 3, 3 ), 0);
	}

	if( (portNum > 0) && (portNum < EAGLE_CONTROL_PORTS) )
	{
		/* power down the SFP PHY by asserting TX_DISABLE */
		npaEgRegSet( eagleObj, AD_CfgCoSFPModDisable, MAKE_MASK(portNum, portNum), 1 );
	}

	return 0;
}

int npaEgEnablePort( struct npaEagleObj_t * eagleObj, int portNum )
{
	int sfpType;
	int i;

	DPRINTK( ERROR, ERR, "eagle", "enabling port: %d\n", portNum );

	/* power up the SFP PHY by asserting TX_DISABLE */
	npaEgRegSet( eagleObj, AD_CfgCoSFPModDisable, MAKE_MASK(portNum, portNum), 0 );

	sfpType = SFP_VACANT;
	for( i = 0; ( (i < 10) && (sfpType != eagleObj->sfpType[portNum]) ); i++ )
	{
		/* wait for the SFP to be ready */
		udelay( 100 );

		/* reconfigure the SFP */
		sfpType = npaEgAsicFindModuleType(eagleObj, portNum );
	}

	/* flag something if the SFP type changed */
	if( sfpType != eagleObj->sfpType[portNum] )
	{
		DPRINTK( ERROR, ERR, "eagle", "SFP type changed from %d to %d while port was powered down\n",
			eagleObj->sfpType[portNum], sfpType );
	}

	/* reconfigure the PCS */
	eagleObj->sfpType[portNum] = sfpType;
	npaEgConfigPort( eagleObj, portNum, eagleObj->sfpType[portNum] );

	return 0;
}

int npaEgAsicAutoNegCompleteFiberStatus( struct npaEagleObj_t * eagleObj, int portNum )
{
	uint32_t regVal;

	DPRINTK( TRACE, INFO, "eagle", "AutoNegotiation Completed for Port %d\n", portNum );

    /* Remote Fault from Link Partner */
#ifdef USE_TWSI  /* No MDIO access, only TWSI */
	npaEgSfpVsRegRead( eagleObj, portNum, 0x01, &regVal );
#elif defined(USE_MDIO)
	npaEgRegGet( eagleObj, AD_StsMdioStatus + (portNum * 0x200), 0, &regVal);
#endif
    if (regVal & (1<<4))
	{
		DPRINTK( LINK, INFO, "eagle", "Remote FAULT received from Link Partner\n");

#ifdef USE_MDIO
        /* If Remote Fault is received, read Partner Ability to know the fault type */
        npaEgRegGet( eagleObj, AD_StsMdioAutonegPartnerAbility + (portNum * 0x200), 0, &regVal);
        regVal = (regVal & 0x3000) >> 12;
        if (regVal == 0)
		{
			DPRINTK( LINK, INFO, "eagle", "Remote Device gives no remote fault\n");
        }
		else if (regVal == 1)
		{
			DPRINTK( LINK, INFO, "eagle", "Remote Device gives remote fault indicating 'Link Failure'\n");
        }
		else if (regVal == 2)
		{
			DPRINTK( LINK, INFO, "eagle", "Remote Device gives remote fault indicating 'Off Line'\n");
        }
		else if (regVal == 3)
		{
			DPRINTK( LINK, INFO, "eagle", "Remote Device gives remote fault indicating 'Auto Negotiation Error'\n");
        }
#endif
    }
	else
	{
		DPRINTK( TRACE, INFO, "eagle", "No Remote FAULT received from Link Partner\n");
    }

    /* Check Link Status */
#ifdef USE_TWSI
	npaEgSfpVsRegRead( eagleObj, portNum, 0x01, &regVal );
	if( regVal & (1<<2))
#elif defined(USE_MDIO)
	npaEgRegGet( eagleObj, AD_StsMdioRxStatus + ( portNum * 0x200), 0, &regVal);
    if (regVal & (1<<7))
#endif
	{
		DPRINTK( LINK, INFO, "eagle", "Link is UP for Port %d\n", portNum);
	}
	else
	{
		DPRINTK( LINK, INFO, "eagle", "Link is DOWN for Port %d\n", portNum);
        return -1;
    }

    /* Read Partner Ability for HD/FD */
#ifdef USE_MDIO
    npaEgRegGet( eagleObj, AD_StsMdioAutonegPartnerAbility + (portNum * 0x200), 0, &regVal);
    if (regVal & (1<<5))
	{
		DPRINTK( LINK, INFO, "eagle", "Other END(partner) is FULL Duplex Capable for Port %d\n", portNum);
	}
    else
	{
		DPRINTK( LINK, INFO, "eagle", "Other END(partner) is NOT FULL Duplex capable for Port %d\n", portNum);
        return -1;
    }

    if (regVal & (1<<6))
	{
 		DPRINTK( LINK, INFO, "eagle", "Other END(partner) is HALF Duplex Capable for Port %d\n", portNum);
        return -1;
    }
#endif
	return 0;
}

static int npaEgAsicPerformAutoNegFiber( struct npaEagleObj_t * eagleObj, int portNum )
{
    unsigned int regVal;
	int num_times;
    /* Check for the port number argument */
	if (portNum < -1 || portNum > 24 )
	{
        DPRINTK( ERROR, ERR, "eagle", "The port address argument passed is incorrect\n");
		DPRINTK( ERROR, ERR, "eagle", "The port address can take values between -1 and %d\n", EAGLE_CONTROL_PORTS);
		return -1;
	}
	/* Select Fiber Mode */
	npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_0 + (portNum * 4), MAKE_MASK( 0, 0 ), 0);
	/* Set the Link Timer value to acheive 10ms */
	npaEgRegSet( eagleObj, AD_CfgCoFiberCntlLinkTimer, MAKE_MASK(21,0), 0x1312d0);
	npaEgRegSet( eagleObj, AD_VarMdioControl + (portNum * 0x200), MAKE_MASK(12,12), 0);
	/* Load Autoneg Advertisment register according to clause 37 of 802.3 */
	/* Advertise FD only */
#ifdef USE_MDIO
    npaEgRegSet( eagleObj, AD_VarMdioAutonegAdvt + (portNum * 0x200), MAKE_MASK(15,0), 0x20);
#endif
    /* Read Interrupt/status registers to clear previous interrupts/status */
#ifdef USE_MDIO
	npaEgRegGet( eagleObj, AD_StsMdioRxInterrupt + (portNum * 0x200), 0, &regVal);
    npaEgRegGet( eagleObj, AD_StsMdioStatus + (portNum * 0x200), 0, &regVal);
	/* Unmask ANCompleteChange, LinkStatusChange and MODLos interrupts */
	npaEgRegSet( eagleObj, AD_StsMdioRxInterruptMask + (portNum * 0x200), MAKE_MASK(15,0), 0xDE7F);
#endif

	npaEgRegSet( eagleObj, AD_VarMdioControl + (portNum * 0x200), MAKE_MASK(12,12), 1);
	/* Restart autoneg (Optional) */
	npaEgRegSet( eagleObj, AD_VarMdioControl + (portNum * 0x200), MAKE_MASK(9,9), 1);
    /* Since Eagle can operate only in 1G speed, in Fiber mode, configure MAC speed at 1G */
	configMACSpeed ( eagleObj, portNum, 1000);
    /* AutoNegotiation Complete Check */
	num_times = 0;
	npaEgRegGet( eagleObj, AD_StsMdioStatus + (portNum * 0x200), 0, &regVal);
	while ((regVal & ( 1 << 5 ) ) == 0)
	{
		npaEgRegGet( eagleObj, AD_StsMdioStatus + (portNum * 0x200), 0, &regVal);
		udelay(100);
		num_times++;
        if (num_times == 100)
		{
			DPRINTK(TRACE, INFO, "eagle", "AutoNegotiation not completed for Port %d\n", portNum);
			DPRINTK(TRACE, INFO, "eagle", "AutoNegotiation will complete in ISR for Port %d\n", portNum);
			return 0;
		}
	}

	DPRINTK( TRACE, INFO, "eagle", "AutoNegotiation Completed for Port %d\n", portNum);
	if( 0 != npaEgAsicAutoNegCompleteFiberStatus(eagleObj, portNum))
	{
		DPRINTK(ERROR, ERR, "eagle", "Error while completing Fiber Auto-Neg on Port %d\n", portNum);
		return -1;
	}
		return 0;
}

int configMACSpeed( struct npaEagleObj_t * eagleObj, int portNum, int macSpeed )
{
	int speed;
	unsigned int regVal;
    /* Disable the MAC */
	npaEgRegGet( eagleObj, AD_VarCoRxFunctionActivate, 0, &regVal);
	regVal = regVal & ~(1 << portNum);
	npaEgRegSet( eagleObj, AD_VarCoRxFunctionActivate, 0, regVal);
	npaEgRegGet( eagleObj, AD_VarCoTxFunctionActivate, 0, &regVal);
	regVal = regVal & ~(1 << portNum);
	npaEgRegSet( eagleObj, AD_VarCoTxFunctionActivate, 0, regVal);
	speed = ( macSpeed == 100 ) ? 3 : ( ( macSpeed == 10 ) ? 2 : 0 );

	npaEgRegSet( eagleObj, AD_CfgCoMACSpeed_0 + (portNum * 4), MAKE_MASK(3,2), speed);
	npaEgRegSet( eagleObj, AD_CfgCoMACSpeed_0 + (portNum * 4), MAKE_MASK(1,0), speed);
    if (macSpeed == 1000)
		npaEgRegSet( eagleObj, AD_CfgTxMacParams + (portNum * 0x200), MAKE_MASK(9,0), 2);
	else if (macSpeed == 100 || macSpeed == 10)
		npaEgRegSet( eagleObj, AD_CfgTxMacParams + (portNum * 0x200), MAKE_MASK(9,0), 14);

    npaEgRegGet( eagleObj, AD_VarCoRxFunctionActivate, 0, &regVal);
	regVal = regVal | (1 << portNum);
	npaEgRegSet( eagleObj, AD_VarCoRxFunctionActivate, 0, regVal);
    npaEgRegGet( eagleObj, AD_VarCoTxFunctionActivate, 0, &regVal);
	regVal = regVal | (1 << portNum);
	npaEgRegSet( eagleObj, AD_VarCoTxFunctionActivate, 0, regVal);
    return 0;
}
#define MAC_SPEED_UNDEFINED		0x3
#define MAC_SPEED_1000			0x2
#define MAC_SPEED_100			0x1
#define MAC_SPEED_10			0x0
int configMACAfterAutoneg ( struct npaEagleObj_t * eagleObj, int portNum )
{
	unsigned int regVal, temp;
	int speed;
	uint32_t speedVal;
    /* Check Link Status of link between Eagle and SFP */
	npaEgRegGet( eagleObj, AD_StsMdioRxStatus + (portNum * 0x200), 0, &regVal);
	if (regVal & ( 1 << 7 ) )
	{
		DPRINTK( TRACE, INFO, "eagle", "SGMII Autoneg Link b/w Eagle and SFP is UP for Port %d\n", portNum);
	}
	else
	{
		DPRINTK( ERROR, ERR, "eagle", "ERROR!!!SGMII Autoneg Link b/w Eagle and SFP is DOWN for Port %d\n", portNum);
		return -1;
	}
	/** Read Partner Ability for HD/FD and Link Status of 1000BaseT autoneg.
	 ** Check the Link Status between the SFP and Far End(Other end to which
	 ** cable is connected)
	 **/
#if defined(USE_TWSI)
    npaEgSfpVsRegRead( eagleObj, portNum, 0x11, &regVal );
#elif defined USE_MDIO
    npaEgRegGet( eagleObj, AD_StsMdioAutonegPartnerAbility + (portNum * 0x200), 0, &regVal);
	npaEgRegGet( eagleObj, AD_VarMdioControl + (portNum * 0x200), 0, &temp);
#endif
#ifdef USE_TWSI
	if( regVal & ( 1 << 10 ))
#elif defined(USE_MDIO)
	if (regVal & ( 1 << 15 ) )
#endif
	{
		DPRINTK( TRACE, INFO, "eagle", "Link is UP for Port %d\n", portNum);
		if (temp & (1 << 12) )
			npaEgSetLED( eagleObj, portNum, 1, 1 ); /* LED on */
	}
	else
	{
		DPRINTK( ERROR, ERR, "eagle", "Link is NOT UP for Port %d\n", portNum);
		if (temp & (1 << 12) )
			npaEgSetLED( eagleObj, portNum, 1, 0 ); /* LED off */
		return -1;
	}
#if defined(USE_MDIO)
	if( (temp & (1 << 12)) == 0 )
		npaEgSetLED( eagleObj, portNum, 0, 0 ); /* Disabled S/W Override */
#endif
	/* Check the Speed agreed upon after negotiation */
	/*	 * Force Use of TWSI as only that can be used to read the SFP status.  The
		 * MDIO status is not valid for speed/duplex only for link and auto neg complete
	*/
	npaEgSfpVsRegRead( eagleObj, portNum, 0x11, (unsigned int *)&regVal );
	speedVal = regVal >> 14;
#if 0
	speedVal = regVal >> 10;
#endif
	if( (speedVal & MAC_SPEED_UNDEFINED) ==  MAC_SPEED_UNDEFINED)
	{
		DPRINTK( ERROR, ERR, "eagle", "SGMII Autoneg - Speed = Reserved not expected from SFP Port %d\n", portNum);
		return -1;
	}
	else if( (speedVal & MAC_SPEED_1000) == MAC_SPEED_1000 )
	{
		DPRINTK( TRACE, INFO, "eagle", "SGMII Autoneg - Speed = 1G demanded by SFP Port %d\n", portNum);
		configMACSpeed( eagleObj, portNum, 1000 );
		speed = 1000;
	}
	else if( (speedVal & MAC_SPEED_100) == MAC_SPEED_100 )
	{
		DPRINTK( TRACE, INFO, "eagle", "SGMII Autoneg - Speed = 100M demanded by SFP Port %d\n", portNum);
		configMACSpeed( eagleObj, portNum, 100 );
		speed = 100;
	}
	else if( (speedVal & MAC_SPEED_10) == MAC_SPEED_10 )
	{
		DPRINTK( TRACE, INFO, "eagle", "SGMII Autoneg - Speed = 10M demanded by SFP Port %d\n", portNum);
		configMACSpeed( eagleObj, portNum, 10 );
		speed = 10;
	}
	if (regVal & (1 << 13) )
#if 0
	if( regVal & ( 1 << 12 ))
#endif
	{
		DPRINTK( TRACE, INFO, "eagle", "SGMII Autoneg - Duplex = FULL\n", portNum);
	}
	else
	{
		DPRINTK( ERROR, ERR, "eagle", "SGMII Autoneg - Duplex = HALF\n", portNum);
		return -1;
	}

	return 0;
}

static int npaEgAsicPerformAutoNegSGMII( struct npaEagleObj_t * eagleObj, int portNum )
{
	unsigned int regVal;
	int num_times;
    /* Check for the port number argument */
	if (portNum < -1 || portNum > EAGLE_CONTROL_PORTS)
	{
		DPRINTK( ERROR, ERR, "eagle", "The port address argument passed is incorrect\n");
		DPRINTK( ERROR, ERR, "eagle", "The port address can take values between -1 and %d\n", EAGLE_CONTROL_PORTS);
		return -1;
	}
    /* Select SGMII Mode */
	npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_0 + (portNum * 4), MAKE_MASK( 0, 0 ), 1);
    /* Set the Link Timer value to acheive 1.6ms */
	npaEgRegSet( eagleObj, AD_CfgCoFiberCntlLinkTimer, MAKE_MASK(21,0), 0x30d40);
    /* Disable autoneg to avoid autoneg while cleaning up the status registers */
	npaEgSfpVsRegWrite( eagleObj, portNum, 0x16, 0x00, 0x0000 );
	npaEgSfpVsRegWrite( eagleObj, portNum, 0x00, 0x00, 0x9084 );
    npaEgRegSet( eagleObj, AD_VarMdioControl + (portNum * 0x200), MAKE_MASK(12,12), 0);
	/* Load Autoneg Advertisment register according to SGMII spec */
	npaEgSfpVsRegWrite( eagleObj, portNum, 0x09, 0, 0x0F00 );
	npaEgSfpVsRegWrite( eagleObj, portNum, 0x04, 0, 0x0DE1 );
	npaEgRegSet( eagleObj, AD_VarMdioAutonegAdvt + (portNum * 0x200), MAKE_MASK(15,0), 0x1);
    /* Read Interrupt/status registers to clear previous interrupts/status */
    npaEgRegGet( eagleObj, AD_StsMdioRxInterrupt + (portNum * 0x200), 0, &regVal);
    npaEgRegGet( eagleObj, AD_StsMdioStatus + (portNum * 0x200), 0, &regVal);
	/* Unmask all the interrupts */
	npaEgRegSet( eagleObj, AD_StsMdioRxInterruptMask + (portNum * 0x200), 0, 0xF820);
	/* Enable autoneg */
	npaEgSfpVsRegWrite( eagleObj, portNum, 0x00, 0x00, 0x9140 );
	npaEgRegSet( eagleObj, AD_VarMdioControl + (portNum * 0x200), MAKE_MASK(12,12), 1);
	/* Restart autoneg (Optional) */
	npaEgRegSet( eagleObj, AD_VarMdioControl + (portNum * 0x200), MAKE_MASK(9,9), 1);
    /* AutoNegotiation Complete Check */
	num_times = 0;
	npaEgRegGet( eagleObj, AD_StsMdioStatus + (portNum * 0x200), 0, &regVal);
	while ((regVal & ( 1 << 10 ) ) == 0)
	{
		npaEgRegGet( eagleObj, AD_StsMdioStatus + (portNum * 0x200), 0, &regVal);
		udelay(100);
		num_times++;
		if (num_times == 10)
		{
			DPRINTK(TRACE, INFO, "eagle", "AutoNegotiation not completed for Port %d\n", portNum);
			DPRINTK(TRACE, INFO, "eagle", "AutoNegotiation will complete in ISR for Port %d\n", portNum);
			return 0;
		}
	}

	DPRINTK( TRACE, INFO, "eagle", "AutoNegotiation Completed for Port %d\n", portNum);

	configMACAfterAutoneg( eagleObj, portNum );
	return 0;
}

static int npaEgAsicConfigSfpCuAdvtAll( struct npaEagleObj_t * eagleObj, int portNum )
{
	/* autoneg fiber */
	npaEgSfpVsRegWrite( eagleObj, portNum, 0x16, 0, 0x0001 );
	npaEgSfpVsRegWrite( eagleObj, portNum, 0x00, 0, 0x9140 );
	/* autoneg copper */
	npaEgSfpVsRegWrite( eagleObj, portNum, 0x16, 0, 0x0000 );
	npaEgSfpVsRegWrite( eagleObj, portNum, 0x1B, 0, 0x9084 );
	npaEgSfpVsRegWrite( eagleObj, portNum, 0x09, 0, 0x0F00 );
	npaEgSfpVsRegWrite( eagleObj, portNum, 0x04, 0, 0x0DE1 );
	npaEgSfpVsRegWrite( eagleObj, portNum, 0x00, 0, 0x9140 );
	npaEgSfpVsRegWrite( eagleObj, portNum, 0x04, 0, 0x0DE1 );
	return 0;
}
int npaEgConfigPort( struct npaEagleObj_t * eagleObj, int portNum, int sfpType )
{
	switch( sfpType )
	{
	case SFP_FIBER:
		DPRINTK( TRACE, INFO, "eagle", "SFP %d is FIBER\n", portNum );
		if( 0 != npaEgAsicConfigFiberPort(eagleObj, portNum) )
		{
			DPRINTK( ERROR, ERR, "eagle", "Error initializing eagle port: %d to fiber mode\n", portNum );
			return -1;
		}
		if( (portNum > 0) && (portNum < EAGLE_DATA_PORTS) )
		{
			if( 0 != npaEgAsicPerformAutoNegFiber(eagleObj, portNum))
			{
				DPRINTK( ERROR, ERR, "eagle", "Error initializing eagle port: %d: cannot start autoneg\n", portNum );
				return -1;
			}
		}
		break;

	case SFP_COPPER:
		DPRINTK( TRACE, INFO, "eagle", "SFP %d is COPPER\n", portNum );
		if( 0 != npaEgAsicConfigSfpCuAdvtAll(eagleObj, portNum) )
		{
			DPRINTK( ERROR, ERR, "eagle", "Error initializing eagle port: %d to copper mode\n", portNum );
			return -1;
		}

		if( (portNum > 0) && (portNum < EAGLE_DATA_PORTS) )
		{
			if( 0 != npaEgAsicPerformAutoNegSGMII(eagleObj, portNum))
			{
				DPRINTK( ERROR, ERR, "eagle", "Error initializing eagle port: %d: cannot start autoneg\n", portNum );
				return -1;
			}
		}
		break;

	case SFP_VACANT:
		DPRINTK( TRACE, INFO, "eagle", "SFP %d is VACANT\n", portNum );
		if( (portNum > 0) && (portNum < EAGLE_DATA_PORTS) )
		{
			npaEgDisablePort( eagleObj, portNum );
		}
		break;
	}
	return 0;
}



static int npaEgInitAsic ( struct npaEagleObj_t * eagleObj, int modeType )
{
    uint32_t regVal;
    int i, numPorts, mask;

    if (modeType < 0 || modeType > 6) {
        DPRINTK(ERROR, ERR, "eagle", "The argument modeType passed is incorrect\n");
        DPRINTK(ERROR, ERR, "eagle", "modeType argument can take values between 0 and 6\n");
        return ERROR(-EINVAL);
    }

    /* Define number of ports */
    if (modeType == 1)
        numPorts = 12;
    else if (modeType == 2)
        numPorts = 14;
    else if (modeType == 6)
        numPorts = 16;
    else
        numPorts = 24;

    /* Soft RESET for Eagle */
    npaEgRegSet(eagleObj, AD_VarCoGlobalSoftReset, 0, 1);
	DPRINTK(ERROR, ERR, "eagle", "npaEgInitAsic(): soft reset complete\n");

    /* Wait for RESET to complete */
	udelay(100);

	/* Toggle reset to all SFPs */
	npaEgRegSet( eagleObj, AD_CfgCoSFPModDisable, MAKE_MASK(23,0), 0xFFFFFF );

    /*
     * Do Power On Reset for the RAM's. This needs to be done before
     * the RAMs can be used
     */
	npaEgRegGet( eagleObj, AD_VarCoMiscFunctionActivate, 0, &regVal );
	regVal |= VarCoMiscFunctionActivate__EnVarPOR;
    npaEgRegSet( eagleObj, AD_VarCoMiscFunctionActivate, 0, regVal);
    udelay(10);
	DPRINTK(ERROR, ERR, "eagle", "npaEgInitAsic(): Power On Reset for the RAM complete\n");

    /* Enable SFP Modules according to the mode selected */
    if (modeType == 2)
        regVal = 0xFFF000;
    else if (modeType == 5)
        regVal = 0xC00000;
    else
        regVal = 0xFFFFFF << numPorts;
    npaEgRegSet( eagleObj, AD_CfgCoSFPModDisable, MAKE_MASK(23,0), regVal);
	udelay(100);
    npaEgRegGet( eagleObj, AD_CfgCoSFPModDisable, 0, &regVal);
	DPRINTK(ERROR, ERR, "eagle", "npaEgInitAsic(): SFPModDisable = %x\n", regVal );


    /*
     * RGMII Interface Setup:
     * Delaying RGMII Rx and Tx clocks inside chip by approximately 800-1600 ps,
     * to avoid any external clock-data delay
     */
    if (modeType == 2 || modeType == 5) {
        npaEgRegSet(eagleObj, AD_CfgCoRGMIIInterfaceSetup, 0, 0x000002ab);
		npaEgRegSet(eagleObj, AD_CfgCoRGMIIInterfaceSetup, MASK_CfgCoRGMIIInterfaceSetup__RGMII1RxClkDlySelP23, 2 );
		npaEgRegSet(eagleObj, AD_CfgCoRGMIIInterfaceSetup, MASK_CfgCoRGMIIInterfaceSetup__RGMII0RxClkDlySelP22, 2 );
		npaEgRegSet(eagleObj, AD_CfgCoRGMIIInterfaceSetup, MASK_CfgCoRGMIIInterfaceSetup__RGMII1TxClkDlySelP23, 2 );
		npaEgRegSet(eagleObj, AD_CfgCoRGMIIInterfaceSetup, MASK_CfgCoRGMIIInterfaceSetup__RGMII0TxClkDlySelP22, 2 );
    }

    /* Powering down unused ports in accordance with the mode */
    if (modeType == 1 || modeType == 2 || modeType == 6) {
		npaEgRegSet(eagleObj, AD_CfgCoFiberCntlA_12, MASK_CfgCoFiberCntlA_PowerDown, 1 );
		npaEgRegSet(eagleObj, AD_CfgCoFiberCntlA_13, MASK_CfgCoFiberCntlA_PowerDown, 1 );
		npaEgRegSet(eagleObj, AD_CfgCoFiberCntlA_14, MASK_CfgCoFiberCntlA_PowerDown, 1 );
		npaEgRegSet(eagleObj, AD_CfgCoFiberCntlA_15, MASK_CfgCoFiberCntlA_PowerDown, 1 );
		npaEgRegSet(eagleObj, AD_CfgCoFiberCntlA_16, MASK_CfgCoFiberCntlA_PowerDown, 1 );
		npaEgRegSet(eagleObj, AD_CfgCoFiberCntlA_17, MASK_CfgCoFiberCntlA_PowerDown, 1 );
		npaEgRegSet(eagleObj, AD_CfgCoFiberCntlA_18, MASK_CfgCoFiberCntlA_PowerDown, 1 );
		npaEgRegSet(eagleObj, AD_CfgCoFiberCntlA_19, MASK_CfgCoFiberCntlA_PowerDown, 1 );
		npaEgRegSet(eagleObj, AD_CfgCoFiberCntlA_20, MASK_CfgCoFiberCntlA_PowerDown, 1 );
		npaEgRegSet(eagleObj, AD_CfgCoFiberCntlA_21, MASK_CfgCoFiberCntlA_PowerDown, 1 );
		npaEgRegSet(eagleObj, AD_CfgCoFiberCntlA_22, MASK_CfgCoFiberCntlA_PowerDown, 1 );
		npaEgRegSet(eagleObj, AD_CfgCoFiberCntlA_23, MASK_CfgCoFiberCntlA_PowerDown, 1 );
        if (modeType == 1)
		{
            npaEgRegSet(eagleObj, AD_CfgCoClkPowerDown, MASK_CfgCoClkPowerDown__ClkPowerDown, 0x00fff000);
        }
		else if (modeType == 2)
		{
            /* 2 RGMII ports are up along with 12 SGMII ports */
            npaEgRegSet(eagleObj, AD_CfgCoClkPowerDown, MASK_CfgCoClkPowerDown__ClkPowerDown, 0x003ff000);
			npaEgRegSet(eagleObj, AD_CfgCoFiberCntlA_22, MASK_CfgCoFiberCntlA_PowerDown, 0);
			npaEgRegSet(eagleObj, AD_CfgCoFiberCntlA_23, MASK_CfgCoFiberCntlA_PowerDown, 0);
        }
		else if (modeType == 6)
		{
            npaEgRegSet(eagleObj, AD_CfgCoClkPowerDown, MASK_CfgCoClkPowerDown__ClkPowerDown, 0x00ff0000);
            /* 16 SGMII ports are UP */
			npaEgRegSet(eagleObj, AD_CfgCoFiberCntlA_12, MASK_CfgCoFiberCntlA_PowerDown, 0 );
			npaEgRegSet(eagleObj, AD_CfgCoFiberCntlA_13, MASK_CfgCoFiberCntlA_PowerDown, 0 );
			npaEgRegSet(eagleObj, AD_CfgCoFiberCntlA_14, MASK_CfgCoFiberCntlA_PowerDown, 0 );
			npaEgRegSet(eagleObj, AD_CfgCoFiberCntlA_15, MASK_CfgCoFiberCntlA_PowerDown, 0 );
        }
    }

    /* Configuring the Fiber control register with respect to the mode type */
    npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_0, 0, 0x00000089);
    npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_1, 0, 0x00000089);
    npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_2, 0, 0x00000089);
    npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_3, 0, 0x00000089);
    npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_4, 0, 0x00000089);
    npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_5, 0, 0x00000089);
    npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_6, 0, 0x00000089);
    npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_7, 0, 0x00000089);
    npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_8, 0, 0x00000089);
    npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_9, 0, 0x00000089);
    npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_10, 0, 0x00000089);
    npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_11, 0, 0x00000089);
    if (modeType == 0 || modeType > 2) {
        npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_12, 0, 0x00000089);
        npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_13, 0, 0x00000089);
        npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_14, 0, 0x00000089);
        npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_15, 0, 0x00000089);
    }
    if (modeType == 0 || (modeType > 2 &&  modeType < 6)) {
        npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_16, 0, 0x00000089);
        npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_17, 0, 0x00000089);
        npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_18, 0, 0x00000089);
        npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_19, 0, 0x00000089);
        npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_20, 0, 0x00000089);
        npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_21, 0, 0x00000089);
    }
    if (modeType != 1 && modeType != 6) {
        npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_22, 0, 0x00000089);
        npaEgRegSet (eagleObj, AD_CfgCoFiberCntlA_23, 0, 0x00000089);
    }
	DPRINTK(TRACE, INFO, "eagle", "npaEgInitAsic(): Configuring the Fiber control register complete\n");

    /* Initialize the SPI PLLs: changes from defaults suggested by foundry */
    npaEgRegSet(eagleObj, AD_CfgCoRxSpiPLLReg, 0x3FFFF, 0x0007eae4);
    npaEgRegSet(eagleObj, AD_CfgCoTxSpiPLLReg, 0x3FFFF, 0x0003da81);
    /* Setting up internal SPI macro datapath width to 64. */
    npaEgRegSet (eagleObj, AD_CfgCoSpiSetup, 0xFFFF, 0x00000e00);
    /* Enable all the high speed cores and PLLs inside the chip: SPI, line interfaces, core. */
    npaEgRegSet (eagleObj, AD_VarCoMiscFunctionActivate, 0, 0x0000007f);
    /* Wait for internal PLLs to lock */
    npaEgRegGet (eagleObj, AD_StsCoPLLLock, 0, &regVal);
    while (regVal != 0x0000007f) {
        npaEgRegGet (eagleObj, AD_StsCoPLLLock, 0, &regVal);
        regVal = regVal & 0x0000007f;
        break;
    }
	DPRINTK( TRACE, INFO, "eagle", "npaEgInitAsic(): Initialize the SPI PLLs complete\n");

    /* Enable SPI deskew/demux logic. */
    npaEgRegSet(eagleObj, AD_VarCoRxFunctionActivate, 0, 0x80000000);
    npaEgRegSet(eagleObj, AD_VarCoTxFunctionActivate, 0, 0x20000000);
    /* Enable register accesses to internal modules */
    npaEgRegSet(eagleObj, AD_VarCoMiscFunctionActivate, 0, 0x0000017f);

	/*
     * Spi Deskew Core register Write
     * Setting up the TxSPI deskew sampling intervals
     * and applying soft reset to recovery unit of Spi Deskew Core
     */
    npaEgAsicWriteSpiDeskewReg (eagleObj, 0, 0xfe1d);
    udelay(1000);
    npaEgAsicWriteSpiDeskewReg (eagleObj, 0xf, 0xffffffff);
	DPRINTK( TRACE, INFO, "eagle", "Spi Deskew Core complete\n" );

    /* Program the SPI Calendar sequence and memory map */
    npaEgAsicSpiProgramCalendar ( eagleObj, modeType);
	DPRINTK( TRACE, INFO, "eagle", "Program the SPI Calendar complete\n" );

    /* Change the Address Mapping of SPI for MAC12 mode */
    if (modeType == 2 || modeType == 1) {
        npaEgRegSet (eagleObj, AD_CfgRxSpiAddressMap12, 0xFF, 22);
        npaEgRegSet (eagleObj, AD_CfgRxSpiAddressMap13, 0xFF, 23);
        npaEgRegSet (eagleObj, AD_CfgRxSpiAddressMap22, 0xFF, 12);
        npaEgRegSet (eagleObj, AD_CfgRxSpiAddressMap23, 0xFF, 13);
    }
	DPRINTK( TRACE, INFO, "eagle", "npaEgInitAsic(): Change the Address Mapping complete\n");

    /* Configuring the Rx and Tx MAC modes registers */
    /* Enabling the Oversize, CRC Pass, CRC Enable option for all the RxMac and TxMac's */
    for (i=0; i<numPorts; i++) {
        if (numPorts == 14 && i > 11) {
            npaEgRegSet (eagleObj, AD_CfgRxMacModes + ( (i+10) * 0x0200 ), 0, 0xa004f9b8);
            npaEgRegSet (eagleObj, AD_CfgTxMacModes + ( (i+10) * 0x0200 ), 0, 0x4200f998);
        } else {
            npaEgRegSet (eagleObj, AD_CfgRxMacModes + ( i * 0x0200 ), 0, 0xa004f9b8);
            npaEgRegSet (eagleObj, AD_CfgTxMacModes + ( i * 0x0200 ), 0, 0x4200f998);
        }
    }
	DPRINTK( TRACE, INFO, "eagle", "npaEgInitAsic(): Configuring the Rx and Tx MAC modes complete\n");

    /* Enabling the speedselect if the RGMII ports are selected */
    if (modeType == 2 || modeType == 5) {
        npaEgRegSet (eagleObj, AD_CfgRxMacModes + ( 22 * 0x0200), 0x4, 1);
        npaEgRegSet (eagleObj, AD_CfgRxMacModes + ( 22 * 0x0200), 0x4, 1);
    }

    /* Enable and initialize the Queue Manager Free Page Table */
    npaEgRegSet (eagleObj, AD_VarCoRxFunctionActivate, MAKE_MASK( 24, 24 ), 1);
    if( 0 != npaEgAsicInitFreePageTable(eagleObj))
	{
		DPRINTK( ERROR, ERR, "eagle", "failed to initialize free page table\n");
		return -1;
	}
	DPRINTK( TRACE, INFO, "eagle", "Enable and initialize the Queue Manager Free Page Table complete\n");

    /* Configuring Tx Memory to 16K */
    npaEgAsicConfigTxMem16K (eagleObj);
	DPRINTK( TRACE, INFO, "eagle", "Configuring Tx Memory to 16K complete\n");

    /* Status LED for all 24 ports is programmed to reflect the Link Status */
	npaEgAsicLEDActivityConfig( eagleObj, 2 );
    npaEgAsicLEDStatusConfig ( eagleObj, 8 );
	DPRINTK( TRACE, INFO, "eagle", "Status LED complete\n");

    /* Check for ports connected to SFP modules and configure them appropriately. */
    npaEgRegGet (eagleObj, AD_CfgCoSFPModDisable, 0, &regVal);
#if defined( __U_BOOT__ )
    printf("DP SFP Type:");
#endif
    for (i=0; i < EAGLE_CONTROL_PORTS; i++)
	{
        mask = (1 << i);
        if ((regVal & mask) == 0)
		{
			eagleObj->sfpType[i] = npaEgAsicFindModuleType(eagleObj, i );
#if defined( __U_BOOT__ )
			if (i < EAGLE_DATA_PORTS)
			{
				printf(" %s",
					((eagleObj->sfpType[i] == SFP_VACANT) ? "V" : ((eagleObj->sfpType[i]==SFP_FIBER)?"F":"C")));
			}
#endif
			npaEgConfigPort( eagleObj, i, eagleObj->sfpType[i] );
		}
    }
#if defined( __U_BOOT__ )
    printf("\n");
#endif
	DPRINTK( TRACE, INFO, "eagle", "SFP config complete\n" );

    /* Activating modules according to the modeType */
    if (modeType == 6) {
        npaEgRegSet (eagleObj, AD_VarCoRxFunctionActivate, MAKE_MASK(23, 0), 0xff00ffff);
        npaEgRegSet (eagleObj, AD_VarCoTxFunctionActivate, MAKE_MASK(31, 0), 0x3f00ffff);
        npaEgRegSet (eagleObj, AD_VarCoTxFunctionActivateTxMemPerPort, MAKE_MASK(31, 0), 0x0000ffff);
    } else if (modeType == 1)  {
        npaEgRegSet (eagleObj, AD_VarCoRxFunctionActivate, MAKE_MASK(23, 0), 0xff000fff);
        npaEgRegSet (eagleObj, AD_VarCoTxFunctionActivate, MAKE_MASK(31, 0), 0x3f000fff);
        npaEgRegSet (eagleObj, AD_VarCoTxFunctionActivateTxMemPerPort, MAKE_MASK(31, 0), 0x00000fff);
    } else if (modeType == 2)  {
        npaEgRegSet (eagleObj, AD_VarCoRxFunctionActivate, MAKE_MASK(23, 0), 0xffc00fff);
        npaEgRegSet (eagleObj, AD_VarCoTxFunctionActivate, MAKE_MASK(31, 0), 0x3fc00fff);
        npaEgRegSet (eagleObj, AD_VarCoTxFunctionActivateTxMemPerPort, MAKE_MASK(31, 0), 0x00c00fff);
    } else {
        npaEgRegSet (eagleObj, AD_VarCoRxFunctionActivate, MAKE_MASK(23, 0), 0xffffffff);
        npaEgRegSet (eagleObj, AD_VarCoTxFunctionActivate, MAKE_MASK(31, 0), 0x3fffffff);
        npaEgRegSet (eagleObj, AD_VarCoTxFunctionActivateTxMemPerPort, MAKE_MASK(31, 0), 0x00ffffff);
    }

    /* Clear any DIP4 -1s reported during the TSPI training process */
    npaEgRegGet (eagleObj, AD_StsTxSpiDip4ErrCount, 0, &regVal);

	return 0;
}

