ppc4xx: Fix 460EX errata with CPU lockup upon high AHB traffic
[oweals/u-boot.git] / cpu / ppc4xx / 4xx_enet.c
index 4541a1468c98623b9f51c9e163fc3d5da65aa62e..c40e0ca48098bfbf4d22af3214c67efba47b6fcd 100644 (file)
@@ -274,8 +274,7 @@ static void emac_loopback_disable(EMAC_4XX_HW_PST hw_p)
 static void ppc_4xx_eth_halt (struct eth_device *dev)
 {
        EMAC_4XX_HW_PST hw_p = dev->priv;
-       uint32_t failsafe = 10000;
-       u32 eth_cfg = 0;
+       u32 val = 10000;
 
        out_be32((void *)EMAC_IER + hw_p->hw_addr, 0x00000000); /* disable emac interrupts */
 
@@ -291,8 +290,8 @@ static void ppc_4xx_eth_halt (struct eth_device *dev)
        /* wait for reset */
        while (mfdcr (malrxcasr) & (MAL_CR_MMSR >> hw_p->devnum)) {
                udelay (1000);  /* Delay 1 MS so as not to hammer the register */
-               failsafe--;
-               if (failsafe == 0)
+               val--;
+               if (val == 0)
                        break;
        }
 
@@ -311,9 +310,9 @@ static void ppc_4xx_eth_halt (struct eth_device *dev)
 
 #if defined(CONFIG_460EX) || defined(CONFIG_460GT)
        /* don't bypass the TAHOE0/TAHOE1 cores for Linux */
-       mfsdr(SDR0_ETH_CFG, eth_cfg);
-       eth_cfg &= ~(SDR0_ETH_CFG_TAHOE0_BYPASS | SDR0_ETH_CFG_TAHOE1_BYPASS);
-       mtsdr(SDR0_ETH_CFG, eth_cfg);
+       mfsdr(SDR0_ETH_CFG, val);
+       val &= ~(SDR0_ETH_CFG_TAHOE0_BYPASS | SDR0_ETH_CFG_TAHOE1_BYPASS);
+       mtsdr(SDR0_ETH_CFG, val);
 #endif
 
        return;
@@ -718,6 +717,11 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 #ifdef CONFIG_4xx_DCACHE
        static u32 last_used_ea = 0;
 #endif
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+    defined(CONFIG_405EX)
+       int rgmii_channel;
+#endif
 
        EMAC_4XX_HW_PST hw_p = dev->priv;
 
@@ -1023,12 +1027,17 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 #if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
     defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
+       if (devnum >= 2)
+               rgmii_channel = devnum - 2;
+       else
+               rgmii_channel = devnum;
+
        if (speed == 1000)
-               reg = (RGMII_SSR_SP_1000MBPS << RGMII_SSR_V (devnum));
+               reg = (RGMII_SSR_SP_1000MBPS << RGMII_SSR_V(rgmii_channel));
        else if (speed == 100)
-               reg = (RGMII_SSR_SP_100MBPS << RGMII_SSR_V (devnum));
+               reg = (RGMII_SSR_SP_100MBPS << RGMII_SSR_V(rgmii_channel));
        else if (speed == 10)
-               reg = (RGMII_SSR_SP_10MBPS << RGMII_SSR_V (devnum));
+               reg = (RGMII_SSR_SP_10MBPS << RGMII_SSR_V(rgmii_channel));
        else {
                printf("Error in RGMII Speed\n");
                return -1;
@@ -1074,7 +1083,11 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 #ifdef CONFIG_4xx_DCACHE
                flush_dcache_range(bd_cached, bd_cached + MAL_ALLOC_SIZE);
                if (!last_used_ea)
+#if defined(CFG_MEM_TOP_HIDE)
+                       bd_uncached = bis->bi_memsize + CFG_MEM_TOP_HIDE;
+#else
                        bd_uncached = bis->bi_memsize;
+#endif
                else
                        bd_uncached = last_used_ea + MAL_ALLOC_SIZE;