[U-Boot] [PATCH] net: Multiple updates/enhancements to designware.c

Amit Virdi amit.virdi at st.com
Wed May 9 11:29:04 CEST 2012


Stefan,

On 5/8/2012 12:59 PM, Stefan Roese wrote:
> This patch adds the following changes to designware ethernet driver
> found on the ST SPEAr SoC:
>
> - Don't init MAC&  PHY upon startup. This causes a delay, waiting for
>    the auto negotiation to complete. And we don't want this delay to
>    always happen. Especially not on platforms where ethernet is not
>    used at all (e.g. booting via flash).
>    Instead postpone the MAC / PHY configuration to the stage, where
>    ethernet is first used.
> - Add possibility for board specific PHY init code. This is needed
>    for example on the X600 board, where the Vitesse PHY needs to be
>    configured for GMII mode.
>    This board specific PHY init is done via the function
>    designware_board_phy_init(). And this driver now adds a weak default
>    which can be overridden by board code.
> - Use common functions miiphy_speed()&  miiphy_duplex() to read
>    link status from PHY.
> - Print status and progress of auto negotiation.
> - Print link status (speed, dupex) upon first usage.
>
> Signed-off-by: Stefan Roese<sr at denx.de>
> Cc: Amit Virdi<amit.virdi at st.com>
> Cc: Vipin Kumar<vipin.kumar at st.com>
> Cc: Joe Hershberger<joe.hershberger at gmail.com>
> ---
>   drivers/net/designware.c       |  114 +++++++++++++++++-----------------------
>   drivers/net/designware.h       |    1 +
>   include/configs/spear-common.h |    1 +
>   3 files changed, 49 insertions(+), 67 deletions(-)
>
> diff --git a/drivers/net/designware.c b/drivers/net/designware.c
> index e263022..945e57b 100644
> --- a/drivers/net/designware.c
> +++ b/drivers/net/designware.c
> @@ -28,6 +28,7 @@
>   #include<common.h>
>   #include<miiphy.h>
>   #include<malloc.h>
> +#include<linux/compiler.h>
>   #include<linux/err.h>
>   #include<asm/io.h>
>   #include "designware.h"
> @@ -153,6 +154,13 @@ static int dw_eth_init(struct eth_device *dev, bd_t *bis)
>   	if (priv->phy_configured != 1)
>   		configure_phy(dev);
>
> +	/* Print link status only once */
> +	if (!priv->link_printed) {
> +		printf("ENET Speed is %d Mbps - %s duplex connection\n",
> +		       priv->speed, (priv->duplex == HALF) ? "HALF" : "FULL");
> +		priv->link_printed = 1;
> +	}
> +
>   	/* Reset ethernet hardware */
>   	if (mac_reset(dev)<  0)
>   		return -1;
> @@ -168,17 +176,17 @@ static int dw_eth_init(struct eth_device *dev, bd_t *bis)
>
>   	conf = FRAMEBURSTENABLE | DISABLERXOWN;
>
> -	if (priv->speed != SPEED_1000M)
> +	if (priv->speed != 1000)
>   		conf |= MII_PORTSELECT;
>
>   	if ((priv->interface != PHY_INTERFACE_MODE_MII)&&
>   		(priv->interface != PHY_INTERFACE_MODE_GMII)) {
>
> -		if (priv->speed == SPEED_100M)
> +		if (priv->speed == 100)
>   			conf |= FES_100;
>   	}
>
> -	if (priv->duplex == FULL_DUPLEX)
> +	if (priv->duplex == FULL)
>   		conf |= FULLDPLXMODE;
>
>   	writel(conf,&mac_p->conf);
> @@ -397,6 +405,16 @@ static int dw_reset_phy(struct eth_device *dev)
>   	return 0;
>   }
>
> +/*
> + * Add weak default function for board specific PHY configuration
> + */
> +int __weak designware_board_phy_init(struct eth_device *dev, int phy_addr,
> +		int (*mii_write)(struct eth_device *, u8, u8, u16),
> +		int dw_reset_phy(struct eth_device *))
> +{
> +	return 0;
> +}
> +
>   static int configure_phy(struct eth_device *dev)
>   {
>   	struct dw_eth_dev *priv = dev->priv;
> @@ -406,9 +424,6 @@ static int configure_phy(struct eth_device *dev)
>   	u16 bmsr;
>   	u32 timeout;
>   	ulong start;
> -	u16 anlpar, btsr;
> -#else
> -	u16 ctrl;
>   #endif
>
>   #if defined(CONFIG_DW_SEARCH_PHY)
> @@ -420,6 +435,16 @@ static int configure_phy(struct eth_device *dev)
>   #else
>   	phy_addr = priv->address;
>   #endif
> +
> +	/*
> +	 * Some boards need board specific PHY initialization. This is
> +	 * after the main driver init code but before the auto negotiation
> +	 * is run.
> +	 */
> +	if (designware_board_phy_init(dev, phy_addr,
> +				      eth_mdio_write, dw_reset_phy)<  0)
> +		return -1;
> +
>   	if (dw_reset_phy(dev)<  0)
>   		return -1;
>
> @@ -445,72 +470,32 @@ static int configure_phy(struct eth_device *dev)
>   #if defined(CONFIG_DW_AUTONEG)
>   	timeout = CONFIG_AUTONEG_TIMEOUT;
>   	start = get_timer(0);
> -
> +	puts("Waiting for PHY auto negotiation to complete");
>   	while (get_timer(start)<  timeout) {
>   		eth_mdio_read(dev, phy_addr, MII_BMSR,&bmsr);
> -		if (bmsr&  BMSR_ANEGCOMPLETE)
> +		if (bmsr&  BMSR_ANEGCOMPLETE) {
> +			priv->phy_configured = 1;
>   			break;
> +		}
> +
> +		/* Print dot all 1s to show progress */
> +		if ((get_timer(start) % 100000) == 0)
> +			putc('.');
>
>   		/* Try again after 10usec */
>   		udelay(10);
>   	};
>
> -	eth_mdio_read(dev, phy_addr, MII_LPA,&anlpar);
> -	eth_mdio_read(dev, phy_addr, MII_STAT1000,&btsr);
> -
> -	if (bmsr&  BMSR_ANEGCOMPLETE) {
> -		if (btsr&  PHY_1000BTSR_1000FD) {
> -			priv->speed = SPEED_1000M;
> -			bmcr |= BMCR_SPEED1000;
> -			priv->duplex = FULL_DUPLEX;
> -			bmcr |= BMCR_FULLDPLX;
> -		} else if (btsr&  PHY_1000BTSR_1000HD) {
> -			priv->speed = SPEED_1000M;
> -			bmcr |= BMCR_SPEED1000;
> -			priv->duplex = HALF_DUPLEX;
> -			bmcr&= ~BMCR_FULLDPLX;
> -		} else if (anlpar&  LPA_100FULL) {
> -			priv->speed = SPEED_100M;
> -			bmcr |= BMCR_SPEED100;
> -			priv->duplex = FULL_DUPLEX;
> -			bmcr |= BMCR_FULLDPLX;
> -		} else if (anlpar&  LPA_100HALF) {
> -			priv->speed = SPEED_100M;
> -			bmcr |= BMCR_SPEED100;
> -			priv->duplex = HALF_DUPLEX;
> -			bmcr&= ~BMCR_FULLDPLX;
> -		} else if (anlpar&  LPA_10FULL) {
> -			priv->speed = SPEED_10M;
> -			bmcr&= ~BMCR_SPEED100;
> -			priv->duplex = FULL_DUPLEX;
> -			bmcr |= BMCR_FULLDPLX;
> -		} else {
> -				priv->speed = SPEED_10M;
> -				bmcr&= ~BMCR_SPEED100;
> -				priv->duplex = HALF_DUPLEX;
> -				bmcr&= ~BMCR_FULLDPLX;
> -		}
> -		if (eth_mdio_write(dev, phy_addr, MII_BMCR, bmcr)<  0)
> -			return -1;
> -	} else
> -		return -1;
> -#else
> -	if (eth_mdio_read(dev, phy_addr, MII_BMCR,&ctrl)<  0)
> -		return -1;
> -
> -	if (ctrl&  BMCR_FULLDPLX)
> -		priv->duplex = FULL_DUPLEX;
> -	else
> -		priv->duplex = HALF_DUPLEX;
> -
> -	if (ctrl&  BMCR_SPEED1000)
> -		priv->speed = SPEED_1000M;
> -	else if (ctrl&  BMCR_SPEED100)
> -		priv->speed = SPEED_100M;
> +	if (!(bmsr&  BMSR_ANEGCOMPLETE))
> +		puts(" TIMEOUT!\n");
>   	else
> -		priv->speed = SPEED_10M;
> -#endif
> +		puts(" done\n");
> +#else
>   	priv->phy_configured = 1;
> +#endif
> +
> +	priv->speed = miiphy_speed(dev->name, phy_addr);
> +	priv->duplex = miiphy_duplex(dev->name, phy_addr);
>
>   	return 0;
>   }
> @@ -575,11 +560,6 @@ int designware_initialize(u32 id, ulong base_addr, u32 phy_addr, u32 interface)
>   	priv->phy_configured = 0;
>   	priv->interface = interface;
>
> -	if (mac_reset(dev)<  0)
> -		return -1;
> -
> -	configure_phy(dev);
> -
>   	dev->init = dw_eth_init;
>   	dev->send = dw_eth_send;
>   	dev->recv = dw_eth_recv;
> diff --git a/drivers/net/designware.h b/drivers/net/designware.h
> index 40020bf..d668f8f 100644
> --- a/drivers/net/designware.h
> +++ b/drivers/net/designware.h
> @@ -240,6 +240,7 @@ struct dw_eth_dev {
>   	u32 tx_currdescnum;
>   	u32 rx_currdescnum;
>   	u32 phy_configured;
> +	int link_printed;
>   	u32 padding;
>
>   	struct dmamacdescr tx_mac_descrtable[CONFIG_TX_DESCR_NUM];
> diff --git a/include/configs/spear-common.h b/include/configs/spear-common.h
> index 3366895..78cc33f 100644
> --- a/include/configs/spear-common.h
> +++ b/include/configs/spear-common.h
> @@ -38,6 +38,7 @@
>   #define CONFIG_NET_MULTI
>   #define CONFIG_PHY_RESET_DELAY			10000		/* in usec */
>   #define CONFIG_DW_AUTONEG
> +#define CONFIG_PHY_GIGE			/* Include GbE speed/duplex detection */
>

Shouldn't this come in a separate patch?

Otherwise, Acked-by: Amit Virdi <amit.virdi at st.com>

Regards
Amit Virdi

>   /* USBD driver configuration */
>   #if defined(CONFIG_SPEAR_USBTTY)


More information about the U-Boot mailing list