diff options
Diffstat (limited to 'drivers/net/cpsw.c')
| -rw-r--r-- | drivers/net/cpsw.c | 21 | 
1 files changed, 19 insertions, 2 deletions
| diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c index db04795df..7a3685019 100644 --- a/drivers/net/cpsw.c +++ b/drivers/net/cpsw.c @@ -24,6 +24,7 @@  #include <asm/errno.h>  #include <asm/io.h>  #include <phy.h> +#include <asm/arch/cpu.h>  #define BITMASK(bits)		(BIT(bits) - 1)  #define PHY_REG_MASK		0x1f @@ -227,6 +228,9 @@ struct cpsw_priv {  	struct cpsw_slave		*slaves;  	struct phy_device		*phydev;  	struct mii_dev			*bus; + +	u32				mdio_link; +	u32				phy_mask;  };  static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits) @@ -598,10 +602,21 @@ static int cpsw_update_link(struct cpsw_priv *priv)  	for_each_slave(slave, priv)  		cpsw_slave_update_link(slave, priv, &link); - +	priv->mdio_link = readl(&mdio_regs->link);  	return link;  } +static int cpsw_check_link(struct cpsw_priv *priv) +{ +	u32 link = 0; + +	link = __raw_readl(&mdio_regs->link) & priv->phy_mask; +	if ((link) && (link == priv->mdio_link)) +		return 1; + +	return cpsw_update_link(priv); +} +  static inline u32  cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)  {  	if (priv->host_port == 0) @@ -631,6 +646,8 @@ static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv)  	cpsw_ale_port_state(priv, slave_port, ALE_PORT_STATE_FORWARD);  	cpsw_ale_add_mcast(priv, NetBcastAddr, 1 << slave_port); + +	priv->phy_mask |= 1 << slave->data->phy_id;  }  static struct cpdma_desc *cpdma_desc_alloc(struct cpsw_priv *priv) @@ -862,7 +879,7 @@ static int cpsw_send(struct eth_device *dev, void *packet, int length)  	int len;  	int timeout = CPDMA_TIMEOUT; -	if (!cpsw_update_link(priv)) +	if (!cpsw_check_link(priv))  		return -EIO;  	flush_dcache_range((unsigned long)packet, |