@ -191,11 +191,16 @@ DECLARE_GLOBAL_DATA_PTR;
# define MVNETA_GMAC_AUTONEG_CONFIG 0x2c0c
# define MVNETA_GMAC_FORCE_LINK_DOWN BIT(0)
# define MVNETA_GMAC_FORCE_LINK_PASS BIT(1)
# define MVNETA_GMAC_FORCE_LINK_UP (BIT(0) | BIT(1))
# define MVNETA_GMAC_IB_BYPASS_AN_EN BIT(3)
# define MVNETA_GMAC_CONFIG_MII_SPEED BIT(5)
# define MVNETA_GMAC_CONFIG_GMII_SPEED BIT(6)
# define MVNETA_GMAC_AN_SPEED_EN BIT(7)
# define MVNETA_GMAC_SET_FC_EN BIT(8)
# define MVNETA_GMAC_ADVERT_FC_EN BIT(9)
# define MVNETA_GMAC_CONFIG_FULL_DUPLEX BIT(12)
# define MVNETA_GMAC_AN_DUPLEX_EN BIT(13)
# define MVNETA_GMAC_SAMPLE_TX_CFG_EN BIT(15)
# define MVNETA_MIB_COUNTERS_BASE 0x3080
# define MVNETA_MIB_LATE_COLLISION 0x7c
# define MVNETA_DA_FILT_SPEC_MCAST 0x3400
@ -566,6 +571,13 @@ static void mvneta_rxq_buf_size_set(struct mvneta_port *pp,
mvreg_write ( pp , MVNETA_RXQ_SIZE_REG ( rxq - > id ) , val ) ;
}
static int mvneta_port_is_fixed_link ( struct mvneta_port * pp )
{
/* phy_addr is set to invalid value for fixed link */
return pp - > phyaddr > PHY_MAX_ADDR ;
}
/* Start the Ethernet port RX and TX activity */
static void mvneta_port_up ( struct mvneta_port * pp )
{
@ -816,10 +828,12 @@ static void mvneta_defaults_set(struct mvneta_port *pp)
/* Assign port SDMA configuration */
mvreg_write ( pp , MVNETA_SDMA_CONFIG , val ) ;
/* Enable PHY polling in hardware for U-Boot */
val = mvreg_read ( pp , MVNETA_UNIT_CONTROL ) ;
val | = MVNETA_PHY_POLLING_ENABLE ;
mvreg_write ( pp , MVNETA_UNIT_CONTROL , val ) ;
/* Enable PHY polling in hardware if not in fixed-link mode */
if ( ! mvneta_port_is_fixed_link ( pp ) ) {
val = mvreg_read ( pp , MVNETA_UNIT_CONTROL ) ;
val | = MVNETA_PHY_POLLING_ENABLE ;
mvreg_write ( pp , MVNETA_UNIT_CONTROL , val ) ;
}
mvneta_set_ucast_table ( pp , - 1 ) ;
mvneta_set_special_mcast_table ( pp , - 1 ) ;
@ -1137,6 +1151,11 @@ static void mvneta_adjust_link(struct udevice *dev)
struct phy_device * phydev = pp - > phydev ;
int status_change = 0 ;
if ( mvneta_port_is_fixed_link ( pp ) ) {
debug ( " Using fixed link, skip link adjust \n " ) ;
return ;
}
if ( phydev - > link ) {
if ( ( pp - > speed ! = phydev - > speed ) | |
( pp - > duplex ! = phydev - > duplex ) ) {
@ -1507,28 +1526,54 @@ static int mvneta_start(struct udevice *dev)
mvneta_port_power_up ( pp , pp - > phy_interface ) ;
if ( ! pp - > init | | pp - > link = = 0 ) {
/* Set phy address of the port */
mvreg_write ( pp , MVNETA_PHY_ADDR , pp - > phyaddr ) ;
phydev = phy_connect ( pp - > bus , pp - > phyaddr , dev ,
pp - > phy_interface ) ;
pp - > phydev = phydev ;
phy_config ( phydev ) ;
phy_startup ( phydev ) ;
if ( ! phydev - > link ) {
printf ( " %s: No link. \n " , phydev - > dev - > name ) ;
return - 1 ;
}
if ( mvneta_port_is_fixed_link ( pp ) ) {
u32 val ;
/* Full init on first call */
mvneta_init ( dev ) ;
pp - > init = 1 ;
} else {
/* Upon all following calls, this is enough */
mvneta_port_up ( pp ) ;
mvneta_port_enable ( pp ) ;
pp - > init = 1 ;
pp - > link = 1 ;
mvneta_init ( dev ) ;
val = MVNETA_GMAC_FORCE_LINK_UP |
MVNETA_GMAC_IB_BYPASS_AN_EN |
MVNETA_GMAC_SET_FC_EN |
MVNETA_GMAC_ADVERT_FC_EN |
MVNETA_GMAC_SAMPLE_TX_CFG_EN ;
if ( pp - > duplex )
val | = MVNETA_GMAC_CONFIG_FULL_DUPLEX ;
if ( pp - > speed = = SPEED_1000 )
val | = MVNETA_GMAC_CONFIG_GMII_SPEED ;
else if ( pp - > speed = = SPEED_100 )
val | = MVNETA_GMAC_CONFIG_MII_SPEED ;
mvreg_write ( pp , MVNETA_GMAC_AUTONEG_CONFIG , val ) ;
} else {
/* Set phy address of the port */
mvreg_write ( pp , MVNETA_PHY_ADDR , pp - > phyaddr ) ;
phydev = phy_connect ( pp - > bus , pp - > phyaddr , dev ,
pp - > phy_interface ) ;
pp - > phydev = phydev ;
phy_config ( phydev ) ;
phy_startup ( phydev ) ;
if ( ! phydev - > link ) {
printf ( " %s: No link. \n " , phydev - > dev - > name ) ;
return - 1 ;
}
/* Full init on first call */
mvneta_init ( dev ) ;
pp - > init = 1 ;
return 0 ;
}
}
/* Upon all following calls, this is enough */
mvneta_port_up ( pp ) ;
mvneta_port_enable ( pp ) ;
return 0 ;
}
@ -1625,6 +1670,7 @@ static int mvneta_probe(struct udevice *dev)
unsigned long addr ;
void * bd_space ;
int ret ;
int fl_node ;
/*
* Allocate buffer area for descs and rx_buffers . This is only
@ -1657,10 +1703,19 @@ static int mvneta_probe(struct udevice *dev)
/* PHY interface is already decoded in mvneta_ofdata_to_platdata() */
pp - > phy_interface = pdata - > phy_interface ;
/* Now read phyaddr from DT */
addr = fdtdec_get_int ( blob , node , " phy " , 0 ) ;
addr = fdt_node_offset_by_phandle ( blob , addr ) ;
pp - > phyaddr = fdtdec_get_int ( blob , addr , " reg " , 0 ) ;
/* fetch 'fixed-link' property from 'neta' node */
fl_node = fdt_subnode_offset ( blob , node , " fixed-link " ) ;
if ( fl_node ! = - FDT_ERR_NOTFOUND ) {
/* set phy_addr to invalid value for fixed link */
pp - > phyaddr = PHY_MAX_ADDR + 1 ;
pp - > duplex = fdtdec_get_bool ( blob , fl_node , " full-duplex " ) ;
pp - > speed = fdtdec_get_int ( blob , fl_node , " speed " , 0 ) ;
} else {
/* Now read phyaddr from DT */
addr = fdtdec_get_int ( blob , node , " phy " , 0 ) ;
addr = fdt_node_offset_by_phandle ( blob , addr ) ;
pp - > phyaddr = fdtdec_get_int ( blob , addr , " reg " , 0 ) ;
}
bus = mdio_alloc ( ) ;
if ( ! bus ) {