netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] emac: Fix EMAC soft reset on 460EX/GT
@ 2013-05-10  2:25 Petri Gynther
  2013-05-10  2:42 ` Petri Gynther
  0 siblings, 1 reply; 2+ messages in thread
From: Petri Gynther @ 2013-05-10  2:25 UTC (permalink / raw)
  To: netdev

Fix EMAC soft reset on 460EX/GT to select the right PHY clock source
before and after the soft reset.

EMAC with PHY should use the clock from PHY during soft reset.
EMAC without PHY should use the internal clock during soft reset.

PPC460EX/GT Embedded Processor Advanced User’s Manual
section 28.10.1 Mode Register 0 (EMACx_MR0) states:
Note: The PHY must provide a TX Clk in order to perform a soft reset
of the EMAC. If none is present, select the internal clock
(SDR0_ETH_CFG[EMACx_PHY_CLK] = 1).
After a soft reset, select the external clock.

Without the fix, 460EX/GT-based boards with RGMII PHYs attached to
EMACs experience EMAC interrupt storm and system watchdog reset when
issuing "ifconfig eth0 down" + "ifconfig eth0 up" a few times.
The system enters endless loop of serving emac_irq() with EMACx_ISR
register stuck at value 0x10000000 (Rx parity error).

With the fix, the above issue is no longer observed.

Signed-off-by: Petri Gynther <pgynther@google.com>
---
 drivers/net/ethernet/ibm/emac/core.c | 36 ++++++++++++++++++++++++++++--------
 1 file changed, 28 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index 4989481..205d29c 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -359,10 +359,26 @@ static int emac_reset(struct emac_instance *dev)
 	}
 
 #ifdef CONFIG_PPC_DCR_NATIVE
-	/* Enable internal clock source */
-	if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX))
-		dcri_clrset(SDR0, SDR0_ETH_CFG,
-			    0, SDR0_ETH_CFG_ECS << dev->cell_index);
+	/*
+	 * PPC460EX/GT Embedded Processor Advanced User’s Manual
+	 * section 28.10.1 Mode Register 0 (EMACx_MR0) states:
+	 * Note: The PHY must provide a TX Clk in order to perform a soft reset
+	 * of the EMAC. If none is present, select the internal clock
+	 * (SDR0_ETH_CFG[EMACx_PHY_CLK] = 1).
+	 * After a soft reset, select the external clock.
+	 */
+	if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) {
+		if (dev->phy_address == 0xffffffff &&
+		    dev->phy_map == 0xffffffff) {
+			/* No PHY: select internal loop clock before reset */
+			dcri_clrset(SDR0, SDR0_ETH_CFG,
+				    0, SDR0_ETH_CFG_ECS << dev->cell_index);
+		} else {
+			/* PHY present: select external clock before reset */
+			dcri_clrset(SDR0, SDR0_ETH_CFG,
+				    SDR0_ETH_CFG_ECS << dev->cell_index, 0);
+		}
+	}
 #endif
 
 	out_be32(&p->mr0, EMAC_MR0_SRST);
@@ -370,10 +386,14 @@ static int emac_reset(struct emac_instance *dev)
 		--n;
 
 #ifdef CONFIG_PPC_DCR_NATIVE
-	 /* Enable external clock source */
-	if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX))
-		dcri_clrset(SDR0, SDR0_ETH_CFG,
-			    SDR0_ETH_CFG_ECS << dev->cell_index, 0);
+	if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) {
+		if (dev->phy_address == 0xffffffff &&
+		    dev->phy_map == 0xffffffff) {
+			/* No PHY: restore external clock source after reset */
+			dcri_clrset(SDR0, SDR0_ETH_CFG,
+				    SDR0_ETH_CFG_ECS << dev->cell_index, 0);
+		}
+	}
 #endif
 
 	if (n) {
-- 
1.8.2.1

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] emac: Fix EMAC soft reset on 460EX/GT
  2013-05-10  2:25 [PATCH] emac: Fix EMAC soft reset on 460EX/GT Petri Gynther
@ 2013-05-10  2:42 ` Petri Gynther
  0 siblings, 0 replies; 2+ messages in thread
From: Petri Gynther @ 2013-05-10  2:42 UTC (permalink / raw)
  To: netdev

Non-ASCII character slipped into "Advanced User's Manual". I'll fix that ASAP.

On Thu, May 9, 2013 at 7:25 PM, Petri Gynther <pgynther@google.com> wrote:
> Fix EMAC soft reset on 460EX/GT to select the right PHY clock source
> before and after the soft reset.
>
> EMAC with PHY should use the clock from PHY during soft reset.
> EMAC without PHY should use the internal clock during soft reset.
>
> PPC460EX/GT Embedded Processor Advanced User’s Manual
> section 28.10.1 Mode Register 0 (EMACx_MR0) states:
> Note: The PHY must provide a TX Clk in order to perform a soft reset
> of the EMAC. If none is present, select the internal clock
> (SDR0_ETH_CFG[EMACx_PHY_CLK] = 1).
> After a soft reset, select the external clock.
>
> Without the fix, 460EX/GT-based boards with RGMII PHYs attached to
> EMACs experience EMAC interrupt storm and system watchdog reset when
> issuing "ifconfig eth0 down" + "ifconfig eth0 up" a few times.
> The system enters endless loop of serving emac_irq() with EMACx_ISR
> register stuck at value 0x10000000 (Rx parity error).
>
> With the fix, the above issue is no longer observed.
>
> Signed-off-by: Petri Gynther <pgynther@google.com>
> ---
>  drivers/net/ethernet/ibm/emac/core.c | 36 ++++++++++++++++++++++++++++--------
>  1 file changed, 28 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
> index 4989481..205d29c 100644
> --- a/drivers/net/ethernet/ibm/emac/core.c
> +++ b/drivers/net/ethernet/ibm/emac/core.c
> @@ -359,10 +359,26 @@ static int emac_reset(struct emac_instance *dev)
>         }
>
>  #ifdef CONFIG_PPC_DCR_NATIVE
> -       /* Enable internal clock source */
> -       if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX))
> -               dcri_clrset(SDR0, SDR0_ETH_CFG,
> -                           0, SDR0_ETH_CFG_ECS << dev->cell_index);
> +       /*
> +        * PPC460EX/GT Embedded Processor Advanced User’s Manual
> +        * section 28.10.1 Mode Register 0 (EMACx_MR0) states:
> +        * Note: The PHY must provide a TX Clk in order to perform a soft reset
> +        * of the EMAC. If none is present, select the internal clock
> +        * (SDR0_ETH_CFG[EMACx_PHY_CLK] = 1).
> +        * After a soft reset, select the external clock.
> +        */
> +       if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) {
> +               if (dev->phy_address == 0xffffffff &&
> +                   dev->phy_map == 0xffffffff) {
> +                       /* No PHY: select internal loop clock before reset */
> +                       dcri_clrset(SDR0, SDR0_ETH_CFG,
> +                                   0, SDR0_ETH_CFG_ECS << dev->cell_index);
> +               } else {
> +                       /* PHY present: select external clock before reset */
> +                       dcri_clrset(SDR0, SDR0_ETH_CFG,
> +                                   SDR0_ETH_CFG_ECS << dev->cell_index, 0);
> +               }
> +       }
>  #endif
>
>         out_be32(&p->mr0, EMAC_MR0_SRST);
> @@ -370,10 +386,14 @@ static int emac_reset(struct emac_instance *dev)
>                 --n;
>
>  #ifdef CONFIG_PPC_DCR_NATIVE
> -        /* Enable external clock source */
> -       if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX))
> -               dcri_clrset(SDR0, SDR0_ETH_CFG,
> -                           SDR0_ETH_CFG_ECS << dev->cell_index, 0);
> +       if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) {
> +               if (dev->phy_address == 0xffffffff &&
> +                   dev->phy_map == 0xffffffff) {
> +                       /* No PHY: restore external clock source after reset */
> +                       dcri_clrset(SDR0, SDR0_ETH_CFG,
> +                                   SDR0_ETH_CFG_ECS << dev->cell_index, 0);
> +               }
> +       }
>  #endif
>
>         if (n) {
> --
> 1.8.2.1
>

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2013-05-10  2:42 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-10  2:25 [PATCH] emac: Fix EMAC soft reset on 460EX/GT Petri Gynther
2013-05-10  2:42 ` Petri Gynther

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).