blob: 74500c130db91e8b1e1d2d0a0b0c6527b15792b5 [file] [log] [blame]
#include <Copyright.h>
/********************************************************************************
* gtMiiSmiIf.c
*
* DESCRIPTION:
* Includes functions prototypes for initializing and accessing the
* MII / SMI interface.
* This is the only file to be included from upper layers.
*
* DEPENDENCIES:
* None.
*
* FILE REVISION NUMBER:
* $Revision: 3 $
*
*******************************************************************************/
#include <gtDrvSwRegs.h>
#include <gtHwCntl.h>
#include <gtMiiSmiIf.h>
#include <platformDeps.h>
#include <gtSem.h>
GT_BOOL qdMultiAddrRead (GT_QD_DEV* dev, unsigned int phyAddr , unsigned int MIIReg,
unsigned int* value);
GT_BOOL qdMultiAddrWrite (GT_QD_DEV* dev, unsigned int phyAddr , unsigned int MIIReg,
unsigned int value);
/*******************************************************************************
* miiSmiIfInit
*
* DESCRIPTION:
* This function initializes the MII / SMI interface.
*
* INPUTS:
* None.
*
* OUTPUTS:
* highSmiDevAddr - Indicates whether to use the high device register
* addresses when accessing switch's registers (of all kinds)
* i.e, the devices registers range is 0x10 to 0x1F, or to
* use the low device register addresses (range 0x0 to 0xF).
* GT_TRUE - use high addresses (0x10 to 0x1F).
* GT_FALSE - use low addresses (0x0 to 0xF).
*
* RETURNS:
* DEVICE_ID - on success
* 0 - on error
*
* COMMENTS:
* None.
*
*******************************************************************************/
GT_U16 miiSmiIfInit
(
IN GT_QD_DEV *dev,
OUT GT_BOOL * highSmiDevAddr
)
{
GT_STATUS status;
GT_U16 data, data1;
if((status = miiSmiIfReadRegister(dev,PORT_REGS_START_ADDR,QD_REG_SWITCH_ID,&data)) != GT_OK)
{
return 0;
}
if((status = miiSmiIfReadRegister(dev,PORT_REGS_START_ADDR+1,QD_REG_SWITCH_ID,&data1)) != GT_OK)
{
return 0;
}
switch(data & 0xFF00)
{
case 0x0200:
case 0x0300:
case 0x0500:
case 0x0600:
case 0x1500:
case 0xF500:
case 0xF900:
if (data == data1)
{
*highSmiDevAddr = GT_FALSE;
return data;
}
break;
default:
break;
}
if((status = miiSmiIfReadRegister(dev,PORT_REGS_START_ADDR+0x10,QD_REG_SWITCH_ID,&data)) != GT_OK)
{
return 0;
}
if((status = miiSmiIfReadRegister(dev,PORT_REGS_START_ADDR+0x11,QD_REG_SWITCH_ID,&data1)) != GT_OK)
{
return 0;
}
switch(data & 0xFF00)
{
case 0x0200:
case 0x0300:
case 0x0500:
case 0x0600:
case 0x1500:
case 0xF500:
case 0xF900:
if (data == data1)
{
*highSmiDevAddr = GT_TRUE;
return data;
}
break;
default:
break;
}
if((status = miiSmiIfReadRegister(dev,PORT_REGS_START_ADDR_8PORT,QD_REG_SWITCH_ID,&data)) != GT_OK)
{
return 0;
}
if((status = miiSmiIfReadRegister(dev,PORT_REGS_START_ADDR_8PORT+1,QD_REG_SWITCH_ID,&data1)) != GT_OK)
{
return 0;
}
switch(data & 0xFF00)
{
case 0x0800:
case 0x1A00:
case 0x1000:
case 0x0900:
case 0x0400:
case 0x1200:
case 0x1400:
case 0x1600:
case 0x1700:
case 0x3200:
case 0x3700:
if (data == data1)
{
*highSmiDevAddr = GT_FALSE;
return data;
}
break;
default:
break;
}
return 0;
}
/*******************************************************************************
* miiSmiManualIfInit
*
* DESCRIPTION:
* This function returns Device ID from the given base address
*
* INPUTS:
* baseAddr - either 0x0 or 0x10. Indicates whether to use the low device
* register address or high device register address.
* The device register range is from 0x0 to 0xF or from 0x10
* to 0x1F for 5 port switchs and from 0x0 to 0x1B for 8 port
* switchs.
*
* OUTPUTS:
* None.
*
* RETURNS:
* DEVICE_ID - on success
* 0 - on error
*
* COMMENTS:
* None.
*
*******************************************************************************/
GT_U16 miiSmiManualIfInit
(
IN GT_QD_DEV *dev,
IN GT_U32 baseAddr
)
{
GT_STATUS status;
GT_U16 data;
if((status = miiSmiIfReadRegister(dev,(GT_U8)(PORT_REGS_START_ADDR+baseAddr),QD_REG_SWITCH_ID,&data)) != GT_OK)
{
return 0;
}
switch(data & 0xFF00)
{
case 0x0200:
case 0x0300:
case 0x0500:
case 0x0600:
case 0x1500:
case 0xF500:
case 0xF900:
return data;
default:
break;
}
if(baseAddr != 0)
return 0;
if((status = miiSmiIfReadRegister(dev,(GT_U8)(PORT_REGS_START_ADDR_8PORT+baseAddr),QD_REG_SWITCH_ID,&data)) != GT_OK)
{
return 0;
}
switch(data & 0xFF00)
{
case 0x0800:
case 0x1A00:
case 0x1000:
case 0x0900:
case 0x0400:
case 0x1200:
case 0x1400:
case 0x1600:
case 0x3200:
case 0x1700:
case 0x3700:
return data;
default:
break;
}
return 0;
}
/*******************************************************************************
* miiSmiIfReadRegister
*
* DESCRIPTION:
* This function reads a register throw the SMI / MII interface, to be used
* by upper layers.
*
* INPUTS:
* phyAddr - The PHY address to be read.
* regAddr - The register address to read.
*
* OUTPUTS:
* data - The register's data.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
* COMMENTS:
* None.
*
*******************************************************************************/
GT_STATUS miiSmiIfReadRegister
(
IN GT_QD_DEV *dev,
IN GT_U8 phyAddr,
IN GT_U8 regAddr,
OUT GT_U16 *data
)
{
unsigned int tmpData;
if(dev->accessMode == SMI_MULTI_ADDR_MODE)
{
if(qdMultiAddrRead(dev,(GT_U32)phyAddr,(GT_U32)regAddr,&tmpData) != GT_TRUE)
{
return GT_FAIL;
}
}
else
{
if(dev->fgtReadMii(dev,(GT_U32)phyAddr,(GT_U32)regAddr,&tmpData) != GT_TRUE)
{
return GT_FAIL;
}
}
*data = (GT_U16)tmpData;
return GT_OK;
}
/*******************************************************************************
* miiSmiIfWriteRegister
*
* DESCRIPTION:
* This function writes to a register throw the SMI / MII interface, to be
* used by upper layers.
*
* INPUTS:
* phyAddr - The PHY address to be read.
* regAddr - The register address to read.
* data - The data to be written to the register.
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
* COMMENTS:
* None.
*
*******************************************************************************/
GT_STATUS miiSmiIfWriteRegister
(
IN GT_QD_DEV *dev,
IN GT_U8 phyAddr,
IN GT_U8 regAddr,
IN GT_U16 data
)
{
if(dev->accessMode == SMI_MULTI_ADDR_MODE)
{
if(qdMultiAddrWrite(dev,(GT_U32)phyAddr,(GT_U32)regAddr,(GT_U32)data) != GT_TRUE)
{
return GT_FAIL;
}
}
else
{
if(dev->fgtWriteMii(dev,(GT_U32)phyAddr,(GT_U32)regAddr,(GT_U32)data) != GT_TRUE)
{
return GT_FAIL;
}
}
return GT_OK;
}
/*****************************************************************************
* qdMultiAddrRead
*
* DESCRIPTION:
* This function reads data from a device in the secondary MII bus.
*
* INPUTS:
* phyAddr - The PHY address to be read.
* regAddr - The register address to read.
* value - The storage where register date to be saved.
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_TRUE - on success
* GT_FALSE - on error
*
* COMMENTS:
* None.
*
*******************************************************************************/
GT_BOOL qdMultiAddrRead (GT_QD_DEV* dev, unsigned int phyAddr , unsigned int regAddr,
unsigned int* value)
{
unsigned int smiReg;
volatile unsigned int timeOut; /* in 100MS units */
volatile int i;
/* first check that it is not busy */
if(dev->fgtReadMii(dev,(GT_U32)dev->phyAddr,(GT_U32)QD_REG_SMI_COMMAND, &smiReg) != GT_TRUE)
{
return GT_FALSE;
}
timeOut = QD_SMI_ACCESS_LOOP; /* initialize the loop count */
if(smiReg & QD_SMI_BUSY)
{
for(i = 0 ; i < QD_SMI_TIMEOUT ; i++);
do
{
if(timeOut-- < 1 )
{
return GT_FALSE;
}
if(dev->fgtReadMii(dev,(GT_U32)dev->phyAddr,(GT_U32)QD_REG_SMI_COMMAND, &smiReg) != GT_TRUE)
{
return GT_FALSE;
}
} while (smiReg & QD_SMI_BUSY);
}
smiReg = QD_SMI_BUSY | (phyAddr << QD_SMI_DEV_ADDR_BIT) | (QD_SMI_READ << QD_SMI_OP_BIT) |
(regAddr << QD_SMI_REG_ADDR_BIT) | (QD_SMI_CLAUSE22 << QD_SMI_MODE_BIT);
if(dev->fgtWriteMii(dev,(GT_U32)dev->phyAddr,(GT_U32)QD_REG_SMI_COMMAND, smiReg) != GT_TRUE)
{
return GT_FALSE;
}
timeOut = QD_SMI_ACCESS_LOOP; /* initialize the loop count */
if(dev->fgtReadMii(dev,(GT_U32)dev->phyAddr,(GT_U32)QD_REG_SMI_COMMAND, &smiReg) != GT_TRUE)
{
return GT_FALSE;
}
if(smiReg & QD_SMI_BUSY)
{
for(i = 0 ; i < QD_SMI_TIMEOUT ; i++);
do
{
if(timeOut-- < 1 )
{
return GT_FALSE;
}
if(dev->fgtReadMii(dev,(GT_U32)dev->phyAddr,(GT_U32)QD_REG_SMI_COMMAND, &smiReg) != GT_TRUE)
{
return GT_FALSE;
}
} while (smiReg & QD_SMI_BUSY);
}
if(dev->fgtReadMii(dev,(GT_U32)dev->phyAddr,(GT_U32)QD_REG_SMI_DATA, &smiReg) != GT_TRUE)
{
return GT_FALSE;
}
*value = smiReg;
return GT_TRUE;
}
/*****************************************************************************
* qdMultiAddrWrite
*
* DESCRIPTION:
* This function writes data to the device in the secondary MII bus.
*
* INPUTS:
* phyAddr - The PHY address to be read.
* regAddr - The register address to read.
* value - The data to be written into the register.
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_TRUE - on success
* GT_FALSE - on error
*
* COMMENTS:
* None.
*
*******************************************************************************/
GT_BOOL qdMultiAddrWrite (GT_QD_DEV* dev, unsigned int phyAddr , unsigned int regAddr,
unsigned int value)
{
unsigned int smiReg;
volatile unsigned int timeOut; /* in 100MS units */
volatile int i;
/* first check that it is not busy */
if(dev->fgtReadMii(dev,(GT_U32)dev->phyAddr,(GT_U32)QD_REG_SMI_COMMAND, &smiReg) != GT_TRUE)
{
return GT_FALSE;
}
timeOut = QD_SMI_ACCESS_LOOP; /* initialize the loop count */
if(smiReg & QD_SMI_BUSY)
{
for(i = 0 ; i < QD_SMI_TIMEOUT ; i++);
do
{
if(timeOut-- < 1 )
{
return GT_FALSE;
}
if(dev->fgtReadMii(dev,(GT_U32)dev->phyAddr,(GT_U32)QD_REG_SMI_COMMAND, &smiReg) != GT_TRUE)
{
return GT_FALSE;
}
} while (smiReg & QD_SMI_BUSY);
}
if(dev->fgtWriteMii(dev,(GT_U32)dev->phyAddr,(GT_U32)QD_REG_SMI_DATA, value) != GT_TRUE)
{
return GT_FALSE;
}
smiReg = QD_SMI_BUSY | (phyAddr << QD_SMI_DEV_ADDR_BIT) | (QD_SMI_WRITE << QD_SMI_OP_BIT) |
(regAddr << QD_SMI_REG_ADDR_BIT) | (QD_SMI_CLAUSE22 << QD_SMI_MODE_BIT);
if(dev->fgtWriteMii(dev,(GT_U32)dev->phyAddr,(GT_U32)QD_REG_SMI_COMMAND, smiReg) != GT_TRUE)
{
return GT_FALSE;
}
return GT_TRUE;
}