[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