@ -12,6 +12,8 @@
# include <netdev.h>
# include <command.h>
# include <malloc.h>
# include <miiphy.h>
# include <linux/mii.h>
# include <asm/blackfin.h>
# include <asm/mach-common/bits/dma.h>
@ -43,8 +45,6 @@ ADI_ETHER_BUFFER *rxbuf[PKTBUFSRX];
static u16 txIdx ; /* index of the current RX buffer */
static u16 rxIdx ; /* index of the current TX buffer */
u16 PHYregs [ NO_PHY_REGS ] ; /* u16 PHYADDR; */
/* DMAx_CONFIG values at DMA Restart */
const ADI_DMA_CONFIG_REG rxdmacfg = {
. b_DMA_EN = 1 , /* enabled */
@ -70,10 +70,38 @@ const ADI_DMA_CONFIG_REG txdmacfg = {
. b_FLOW = 7 /* large desc flow */
} ;
static int bfin_miiphy_wait ( void )
{
/* poll the STABUSY bit */
while ( bfin_read_EMAC_STAADD ( ) & STABUSY )
continue ;
return 0 ;
}
static int bfin_miiphy_read ( char * devname , uchar addr , uchar reg , ushort * val )
{
if ( bfin_miiphy_wait ( ) )
return 1 ;
bfin_write_EMAC_STAADD ( SET_PHYAD ( addr ) | SET_REGAD ( reg ) | STABUSY ) ;
if ( bfin_miiphy_wait ( ) )
return 1 ;
* val = bfin_read_EMAC_STADAT ( ) ;
return 0 ;
}
static int bfin_miiphy_write ( char * devname , uchar addr , uchar reg , ushort val )
{
if ( bfin_miiphy_wait ( ) )
return 1 ;
bfin_write_EMAC_STADAT ( val ) ;
bfin_write_EMAC_STAADD ( SET_PHYAD ( addr ) | SET_REGAD ( reg ) | STAOP | STABUSY ) ;
return 0 ;
}
int bfin_EMAC_initialize ( bd_t * bis )
{
struct eth_device * dev ;
dev = ( struct eth_device * ) malloc ( sizeof ( * dev ) ) ;
dev = malloc ( sizeof ( * dev ) ) ;
if ( dev = = NULL )
hang ( ) ;
@ -89,6 +117,10 @@ int bfin_EMAC_initialize(bd_t *bis)
eth_register ( dev ) ;
# if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
miiphy_register ( dev - > name , bfin_miiphy_read , bfin_miiphy_write ) ;
# endif
return 0 ;
}
@ -182,6 +214,100 @@ static int bfin_EMAC_recv(struct eth_device *dev)
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* MDC = SCLK / MDC_freq / 2 - 1 */
# define MDC_FREQ_TO_DIV(mdc_freq) (get_sclk() / (mdc_freq) / 2 - 1)
static int bfin_miiphy_init ( struct eth_device * dev , int * opmode )
{
u16 phydat ;
size_t count ;
/* Enable PHY output */
* pVR_CTL | = CLKBUFOE ;
/* Set all the pins to peripheral mode */
# ifdef CONFIG_BFIN_MAC_RMII
/* grab RMII pins */
# if defined(__ADSPBF51x__)
* pPORTF_MUX = ( * pPORTF_MUX & \
~ ( PORT_x_MUX_3_MASK | PORT_x_MUX_4_MASK | PORT_x_MUX_5_MASK ) ) | \
PORT_x_MUX_3_FUNC_1 | PORT_x_MUX_4_FUNC_1 | PORT_x_MUX_5_FUNC_1 ;
* pPORTF_FER | = PF8 | PF9 | PF10 | PF11 | PF12 | PF13 | PF14 | PF15 ;
* pPORTG_MUX = ( * pPORTG_MUX & ~ PORT_x_MUX_0_MASK ) | PORT_x_MUX_0_FUNC_1 ;
* pPORTG_FER | = PG0 | PG1 | PG2 ;
# elif defined(__ADSPBF52x__)
* pPORTG_MUX = ( * pPORTG_MUX & ~ PORT_x_MUX_6_MASK ) | PORT_x_MUX_6_FUNC_2 ;
* pPORTG_FER | = PG14 | PG15 ;
* pPORTH_MUX = ( * pPORTH_MUX & ~ ( PORT_x_MUX_0_MASK | PORT_x_MUX_1_MASK ) ) | \
PORT_x_MUX_0_FUNC_2 | PORT_x_MUX_1_FUNC_2 ;
* pPORTH_FER | = PH0 | PH1 | PH2 | PH3 | PH4 | PH5 | PH6 | PH7 | PH8 ;
# else
* pPORTH_FER | = PH0 | PH1 | PH4 | PH5 | PH6 | PH8 | PH9 | PH14 | PH15 ;
# endif
# else
/* grab MII & RMII pins */
# if defined(__ADSPBF51x__)
* pPORTF_MUX = ( * pPORTF_MUX & \
~ ( PORT_x_MUX_0_MASK | PORT_x_MUX_1_MASK | PORT_x_MUX_3_MASK | PORT_x_MUX_4_MASK | PORT_x_MUX_5_MASK ) ) | \
PORT_x_MUX_0_FUNC_1 | PORT_x_MUX_1_FUNC_1 | PORT_x_MUX_3_FUNC_1 | PORT_x_MUX_4_FUNC_1 | PORT_x_MUX_5_FUNC_1 ;
* pPORTF_FER | = PF0 | PF1 | PF2 | PF3 | PF4 | PF5 | PF6 | PF8 | PF9 | PF10 | PF11 | PF12 | PF13 | PF14 | PF15 ;
* pPORTG_MUX = ( * pPORTG_MUX & ~ PORT_x_MUX_0_MASK ) | PORT_x_MUX_0_FUNC_1 ;
* pPORTG_FER | = PG0 | PG1 | PG2 ;
# elif defined(__ADSPBF52x__)
* pPORTG_MUX = ( * pPORTG_MUX & ~ PORT_x_MUX_6_MASK ) | PORT_x_MUX_6_FUNC_2 ;
* pPORTG_FER | = PG14 | PG15 ;
* pPORTH_MUX = PORT_x_MUX_0_FUNC_2 | PORT_x_MUX_1_FUNC_2 | PORT_x_MUX_2_FUNC_2 ;
* pPORTH_FER = - 1 ; /* all pins */
# else
* pPORTH_FER = - 1 ; /* all pins */
# endif
# endif
/* Odd word alignment for Receive Frame DMA word */
/* Configure checksum support and rcve frame word alignment */
bfin_write_EMAC_SYSCTL ( RXDWA | RXCKS | SET_MDCDIV ( MDC_FREQ_TO_DIV ( 2500000 ) ) ) ;
/* turn on auto-negotiation and wait for link to come up */
bfin_miiphy_write ( dev - > name , PHYADDR , MII_BMCR , BMCR_ANENABLE ) ;
count = 0 ;
while ( 1 ) {
+ + count ;
if ( bfin_miiphy_read ( dev - > name , PHYADDR , MII_BMSR , & phydat ) )
return - 1 ;
if ( phydat & BMSR_LSTATUS )
break ;
if ( count > 30000 ) {
printf ( " %s: link down, check cable \n " , dev - > name ) ;
return - 1 ;
}
udelay ( 100 ) ;
}
/* see what kind of link we have */
if ( bfin_miiphy_read ( dev - > name , PHYADDR , MII_LPA , & phydat ) )
return - 1 ;
if ( phydat & LPA_DUPLEX )
* opmode = FDMODE ;
else
* opmode = 0 ;
bfin_write_EMAC_MMC_CTL ( RSTC | CROLL ) ;
/* Initialize the TX DMA channel registers */
* pDMA2_X_COUNT = 0 ;
* pDMA2_X_MODIFY = 4 ;
* pDMA2_Y_COUNT = 0 ;
* pDMA2_Y_MODIFY = 0 ;
/* Initialize the RX DMA channel registers */
* pDMA1_X_COUNT = 0 ;
* pDMA1_X_MODIFY = 4 ;
* pDMA1_Y_COUNT = 0 ;
* pDMA1_Y_MODIFY = 0 ;
return 0 ;
}
static int bfin_EMAC_init ( struct eth_device * dev , bd_t * bd )
{
u32 opmode ;
@ -192,14 +318,14 @@ static int bfin_EMAC_init(struct eth_device *dev, bd_t *bd)
txIdx = 0 ;
rxIdx = 0 ;
/* Initialize System Register */
if ( SetupSystemRegs ( & dat ) < 0 )
/* Initialize System Register */
if ( bfin_miiphy_init ( dev , & dat ) < 0 )
return - 1 ;
/* Initialize EMAC address */
/* Initialize EMAC address */
bfin_EMAC_setup_addr ( bd ) ;
/* Initialize TX and RX buffer */
/* Initialize TX and RX buffer */
for ( i = 0 ; i < PKTBUFSRX ; i + + ) {
rxbuf [ i ] = SetupRxBuffer ( i ) ;
if ( i > 0 ) {
@ -226,7 +352,7 @@ static int bfin_EMAC_init(struct eth_device *dev, bd_t *bd)
* pDMA1_CONFIG = * ( ( u16 * ) ( void * ) & rxbuf [ 0 ] - > Dma [ 0 ] . CONFIG ) ;
/* Wait MII done */
PollMdcDone ( ) ;
bfin_miiphy_wait ( ) ;
/* We enable only RX here */
/* ASTP : Enable Automatic Pad Stripping
@ -271,148 +397,6 @@ void bfin_EMAC_setup_addr(bd_t *bd)
bd - > bi_enetaddr [ 5 ] < < 8 ;
}
static void PollMdcDone ( void )
{
/* poll the STABUSY bit */
while ( * pEMAC_STAADD & STABUSY ) ;
}
static void WrPHYReg ( u16 PHYAddr , u16 RegAddr , u16 Data )
{
PollMdcDone ( ) ;
* pEMAC_STADAT = Data ;
* pEMAC_STAADD = SET_PHYAD ( PHYAddr ) | SET_REGAD ( RegAddr ) |
STAOP | STAIE | STABUSY ;
}
/*********************************************************************************
* Read an off - chip register in a PHY through the MDC / MDIO port *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static u16 RdPHYReg ( u16 PHYAddr , u16 RegAddr )
{
u16 Data ;
PollMdcDone ( ) ;
* pEMAC_STAADD = SET_PHYAD ( PHYAddr ) | SET_REGAD ( RegAddr ) |
STAIE | STABUSY ;
PollMdcDone ( ) ;
Data = ( u16 ) * pEMAC_STADAT ;
PHYregs [ RegAddr ] = Data ; /* save shadow copy */
return Data ;
}
#if 0 /* dead code ? */
static void SoftResetPHY ( void )
{
u16 phydat ;
/* set the reset bit */
WrPHYReg ( PHYADDR , PHY_MODECTL , PHY_RESET ) ;
/* and clear it again */
WrPHYReg ( PHYADDR , PHY_MODECTL , 0x0000 ) ;
do {
/* poll until reset is complete */
phydat = RdPHYReg ( PHYADDR , PHY_MODECTL ) ;
} while ( ( phydat & PHY_RESET ) ! = 0 ) ;
}
# endif
/* MDC = SCLK / MDC_freq / 2 - 1 */
# define MDC_FREQ_TO_DIV(mdc_freq) (get_sclk() / (mdc_freq) / 2 - 1)
static int SetupSystemRegs ( int * opmode )
{
u16 phydat ;
int count = 0 ;
/* Enable PHY output */
* pVR_CTL | = CLKBUFOE ;
/* Set all the pins to peripheral mode */
# ifdef CONFIG_BFIN_MAC_RMII
/* grab RMII pins */
# if defined(__ADSPBF51x__)
* pPORTF_MUX = ( * pPORTF_MUX & \
~ ( PORT_x_MUX_3_MASK | PORT_x_MUX_4_MASK | PORT_x_MUX_5_MASK ) ) | \
PORT_x_MUX_3_FUNC_1 | PORT_x_MUX_4_FUNC_1 | PORT_x_MUX_5_FUNC_1 ;
* pPORTF_FER | = PF8 | PF9 | PF10 | PF11 | PF12 | PF13 | PF14 | PF15 ;
* pPORTG_MUX = ( * pPORTG_MUX & ~ PORT_x_MUX_0_MASK ) | PORT_x_MUX_0_FUNC_1 ;
* pPORTG_FER | = PG0 | PG1 | PG2 ;
# elif defined(__ADSPBF52x__)
* pPORTG_MUX = ( * pPORTG_MUX & ~ PORT_x_MUX_6_MASK ) | PORT_x_MUX_6_FUNC_2 ;
* pPORTG_FER | = PG14 | PG15 ;
* pPORTH_MUX = ( * pPORTH_MUX & ~ ( PORT_x_MUX_0_MASK | PORT_x_MUX_1_MASK ) ) | \
PORT_x_MUX_0_FUNC_2 | PORT_x_MUX_1_FUNC_2 ;
* pPORTH_FER | = PH0 | PH1 | PH2 | PH3 | PH4 | PH5 | PH6 | PH7 | PH8 ;
# else
* pPORTH_FER | = PH0 | PH1 | PH4 | PH5 | PH6 | PH8 | PH9 | PH14 | PH15 ;
# endif
# else
/* grab MII & RMII pins */
# if defined(__ADSPBF51x__)
* pPORTF_MUX = ( * pPORTF_MUX & \
~ ( PORT_x_MUX_0_MASK | PORT_x_MUX_1_MASK | PORT_x_MUX_3_MASK | PORT_x_MUX_4_MASK | PORT_x_MUX_5_MASK ) ) | \
PORT_x_MUX_0_FUNC_1 | PORT_x_MUX_1_FUNC_1 | PORT_x_MUX_3_FUNC_1 | PORT_x_MUX_4_FUNC_1 | PORT_x_MUX_5_FUNC_1 ;
* pPORTF_FER | = PF0 | PF1 | PF2 | PF3 | PF4 | PF5 | PF6 | PF8 | PF9 | PF10 | PF11 | PF12 | PF13 | PF14 | PF15 ;
* pPORTG_MUX = ( * pPORTG_MUX & ~ PORT_x_MUX_0_MASK ) | PORT_x_MUX_0_FUNC_1 ;
* pPORTG_FER | = PG0 | PG1 | PG2 ;
# elif defined(__ADSPBF52x__)
* pPORTG_MUX = ( * pPORTG_MUX & ~ PORT_x_MUX_6_MASK ) | PORT_x_MUX_6_FUNC_2 ;
* pPORTG_FER | = PG14 | PG15 ;
* pPORTH_MUX = PORT_x_MUX_0_FUNC_2 | PORT_x_MUX_1_FUNC_2 | PORT_x_MUX_2_FUNC_2 ;
* pPORTH_FER = - 1 ; /* all pins */
# else
* pPORTH_FER = - 1 ; /* all pins */
# endif
# endif
/* Odd word alignment for Receive Frame DMA word */
/* Configure checksum support and rcve frame word alignment */
* pEMAC_SYSCTL = RXDWA | RXCKS | SET_MDCDIV ( MDC_FREQ_TO_DIV ( 2500000 ) ) ;
/* auto negotiation on */
/* full duplex */
/* 100 Mbps */
phydat = PHY_ANEG_EN | PHY_DUPLEX | PHY_SPD_SET ;
WrPHYReg ( PHYADDR , PHY_MODECTL , phydat ) ;
do {
udelay ( 1000 ) ;
phydat = RdPHYReg ( PHYADDR , PHY_MODESTAT ) ;
if ( count > 3000 ) {
printf
( " Link is down, please check your network connection \n " ) ;
return - 1 ;
}
count + + ;
} while ( ! ( phydat & 0x0004 ) ) ;
phydat = RdPHYReg ( PHYADDR , PHY_ANLPAR ) ;
if ( ( phydat & 0x0100 ) | | ( phydat & 0x0040 ) )
* opmode = FDMODE ;
else
* opmode = 0 ;
* pEMAC_MMC_CTL = RSTC | CROLL ;
/* Initialize the TX DMA channel registers */
* pDMA2_X_COUNT = 0 ;
* pDMA2_X_MODIFY = 4 ;
* pDMA2_Y_COUNT = 0 ;
* pDMA2_Y_MODIFY = 0 ;
/* Initialize the RX DMA channel registers */
* pDMA1_X_COUNT = 0 ;
* pDMA1_X_MODIFY = 4 ;
* pDMA1_Y_COUNT = 0 ;
* pDMA1_Y_MODIFY = 0 ;
return 0 ;
}
ADI_ETHER_BUFFER * SetupRxBuffer ( int no )
{
ADI_ETHER_FRAME_BUFFER * frmbuf ;