[U-Boot-Users] [PATCH 05/15 v2] ppc4xx: Add basic support for AMCC 460EX/460GT (1/5)

Stefan Roese sr at denx.de
Tue Mar 11 17:15:12 CET 2008


This patch adds basic support for the AMCC 460EX/460GT PPC's.

Signed-off-by: Stefan Roese <sr at denx.de>
---
 cpu/ppc4xx/44x_spd_ddr2.c |   41 +++++-
 cpu/ppc4xx/4xx_enet.c     |  369 ++++++++++++++++++++++++++++++++++++---------
 cpu/ppc4xx/4xx_pci.c      |    9 +-
 cpu/ppc4xx/4xx_pcie.c     |  203 ++++++++++++++++++++++++-
 cpu/ppc4xx/4xx_uart.c     |   24 ++-
 5 files changed, 553 insertions(+), 93 deletions(-)

diff --git a/cpu/ppc4xx/44x_spd_ddr2.c b/cpu/ppc4xx/44x_spd_ddr2.c
index 3bafea3..9e722b9 100644
--- a/cpu/ppc4xx/44x_spd_ddr2.c
+++ b/cpu/ppc4xx/44x_spd_ddr2.c
@@ -42,7 +42,8 @@
 #include <asm/mmu.h>
 
 #if defined(CONFIG_SPD_EEPROM) &&				\
-	(defined(CONFIG_440SP) || defined(CONFIG_440SPE))
+	(defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+	 defined(CONFIG_460EX) || defined(CONFIG_460GT))
 
 /*-----------------------------------------------------------------------------+
  * Defines
@@ -579,6 +580,13 @@ long int initdram(int board_type)
 
 	ppc440sp_sdram_register_dump();
 
+	/*
+	 * Clear potential errors resulting from auto-calibration.
+	 * If not done, then we could get an interrupt later on when
+	 * exceptions are enabled.
+	 */
+	set_mcsr(get_mcsr());
+
 	return dram_size;
 }
 
@@ -2125,6 +2133,7 @@ static void program_memory_queue(unsigned long *dimm_populated,
 	unsigned long baseadd_size;
 	unsigned long i;
 	unsigned long bank_0_populated = 0;
+	unsigned long total_size = 0;
 
 	/*------------------------------------------------------------------
 	 * Reset the rank_base_address.
@@ -2147,28 +2156,38 @@ static void program_memory_queue(unsigned long *dimm_populated,
 			 * Set the sizes
 			 *-----------------------------------------------------------------*/
 			baseadd_size = 0;
-			rank_size_bytes = 4 * 1024 * 1024 * rank_size_id;
 			switch (rank_size_id) {
+			case 0x01:
+				baseadd_size |= SDRAM_RXBAS_SDSZ_1024;
+				total_size = 1024;
+				break;
 			case 0x02:
-				baseadd_size |= SDRAM_RXBAS_SDSZ_8;
+				baseadd_size |= SDRAM_RXBAS_SDSZ_2048;
+				total_size = 2048;
 				break;
 			case 0x04:
-				baseadd_size |= SDRAM_RXBAS_SDSZ_16;
+				baseadd_size |= SDRAM_RXBAS_SDSZ_4096;
+				total_size = 4096;
 				break;
 			case 0x08:
 				baseadd_size |= SDRAM_RXBAS_SDSZ_32;
+				total_size = 32;
 				break;
 			case 0x10:
 				baseadd_size |= SDRAM_RXBAS_SDSZ_64;
+				total_size = 64;
 				break;
 			case 0x20:
 				baseadd_size |= SDRAM_RXBAS_SDSZ_128;
+				total_size = 128;
 				break;
 			case 0x40:
 				baseadd_size |= SDRAM_RXBAS_SDSZ_256;
+				total_size = 256;
 				break;
 			case 0x80:
 				baseadd_size |= SDRAM_RXBAS_SDSZ_512;
+				total_size = 512;
 				break;
 			default:
 				printf("DDR-SDRAM: DIMM %d memory queue configuration.\n",
@@ -2178,6 +2197,7 @@ static void program_memory_queue(unsigned long *dimm_populated,
 				printf("Replace the DIMM module with a supported DIMM.\n\n");
 				spd_ddr_init_hang ();
 			}
+			rank_size_bytes = total_size << 20;
 
 			if ((dimm_populated[dimm_num] != SDRAM_NONE) && (dimm_num == 1))
 				bank_0_populated = 1;
@@ -2190,6 +2210,19 @@ static void program_memory_queue(unsigned long *dimm_populated,
 			}
 		}
 	}
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+	/*
+	 * Enable high bandwidth access on 460EX/GT.
+	 * This should/could probably be done on other
+	 * PPC's too, like 440SPe.
+	 * This is currently not used, but with this setup
+	 * it is possible to use it later on in e.g. the Linux
+	 * EMAC driver for performance gain.
+	 */
+	mtdcr(SDRAM_PLBADDULL, 0x00000000); /* MQ0_BAUL */
+	mtdcr(SDRAM_PLBADDUHB, 0x00000008); /* MQ0_BAUH */
+#endif
 }
 
 /*-----------------------------------------------------------------------------+
diff --git a/cpu/ppc4xx/4xx_enet.c b/cpu/ppc4xx/4xx_enet.c
index 599f5ce..d990250 100644
--- a/cpu/ppc4xx/4xx_enet.c
+++ b/cpu/ppc4xx/4xx_enet.c
@@ -137,17 +137,32 @@
 #define BI_PHYMODE_RTBI  4
 #define BI_PHYMODE_TBI   5
 #if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
 #define BI_PHYMODE_SMII  6
 #define BI_PHYMODE_MII   7
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define BI_PHYMODE_RMII  8
+#endif
 #endif
 
 #if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
 #define SDR0_MFR_ETH_CLK_SEL_V(n)	((0x01<<27) / (n+1))
 #endif
 
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define SDR0_ETH_CFG_CLK_SEL_V(n)	(0x01 << (8 + n))
+#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define MAL_RX_CHAN_MUL	8	/* 460EX/GT uses MAL channel 8 for EMAC1 */
+#else
+#define MAL_RX_CHAN_MUL	1
+#endif
+
 /*-----------------------------------------------------------------------------+
  * Global variables. TX and RX descriptors and buffers.
  *-----------------------------------------------------------------------------*/
@@ -214,6 +229,44 @@ extern int emac4xx_miiphy_write (char *devname, unsigned char addr,
 
 int board_emac_count(void);
 
+static void emac_loopback_enable(EMAC_4XX_HW_PST hw_p)
+{
+#if defined(CONFIG_440SPE) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_405EX)
+	u32 val;
+
+	mfsdr(sdr_mfr, val);
+	val |= SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum);
+	mtsdr(sdr_mfr, val);
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+	u32 val;
+
+	mfsdr(SDR0_ETH_CFG, val);
+	val |= SDR0_ETH_CFG_CLK_SEL_V(hw_p->devnum);
+	mtsdr(SDR0_ETH_CFG, val);
+#endif
+}
+
+static void emac_loopback_disable(EMAC_4XX_HW_PST hw_p)
+{
+#if defined(CONFIG_440SPE) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_405EX)
+	u32 val;
+
+	mfsdr(sdr_mfr, val);
+	val &= ~SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum);
+	mtsdr(sdr_mfr, val);
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+	u32 val;
+
+	mfsdr(SDR0_ETH_CFG, val);
+	val &= ~SDR0_ETH_CFG_CLK_SEL_V(hw_p->devnum);
+	mtsdr(SDR0_ETH_CFG, val);
+#endif
+}
+
 /*-----------------------------------------------------------------------------+
 | ppc_4xx_eth_halt
 | Disable MAL channel, and EMACn
@@ -222,11 +275,6 @@ static void ppc_4xx_eth_halt (struct eth_device *dev)
 {
 	EMAC_4XX_HW_PST hw_p = dev->priv;
 	uint32_t failsafe = 10000;
-#if defined(CONFIG_440SPE) || \
-    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
-    defined(CONFIG_405EX)
-	unsigned long mfr;
-#endif
 
 	out_be32((void *)EMAC_IER + hw_p->hw_addr, 0x00000000);	/* disable emac interrupts */
 
@@ -247,27 +295,14 @@ static void ppc_4xx_eth_halt (struct eth_device *dev)
 			break;
 	}
 
-	/* EMAC RESET */
-#if defined(CONFIG_440SPE) || \
-    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
-    defined(CONFIG_405EX)
 	/* provide clocks for EMAC internal loopback  */
-	mfsdr (sdr_mfr, mfr);
-	mfr |= SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum);
-	mtsdr(sdr_mfr, mfr);
-#endif
+	emac_loopback_enable(hw_p);
 
+	/* EMAC RESET */
 	out_be32((void *)EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
 
-#if defined(CONFIG_440SPE) || \
-    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
-    defined(CONFIG_405EX)
 	/* remove clocks for EMAC internal loopback  */
-	mfsdr (sdr_mfr, mfr);
-	mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum);
-	mtsdr(sdr_mfr, mfr);
-#endif
-
+	emac_loopback_disable(hw_p);
 
 #ifndef CONFIG_NETCONSOLE
 	hw_p->print_speed = 1;	/* print speed message again next time */
@@ -452,6 +487,187 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
 }
 #endif  /* CONFIG_405EX */
 
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
+{
+	u32 eth_cfg;
+	u32 zmiifer;		/* ZMII0_FER reg. */
+	u32 rmiifer;		/* RGMII0_FER reg. Bridge 0 */
+	u32 rmiifer1;		/* RGMII0_FER reg. Bridge 1 */
+
+	zmiifer  = 0;
+	rmiifer  = 0;
+	rmiifer1 = 0;
+
+	/* TODO:
+	 * NOTE: 460GT has 2 RGMII bridge cores:
+	 *		emac0 ------ RGMII0_BASE
+	 *		           |
+	 *		emac1 -----+
+	 *
+	 *		emac2 ------ RGMII1_BASE
+	 *		           |
+	 *		emac3 -----+
+	 *
+	 *	460EX has 1 RGMII bridge core:
+	 *	and RGMII1_BASE is disabled
+	 *		emac0 ------ RGMII0_BASE
+	 *		           |
+	 *		emac1 -----+
+	 */
+
+	/*
+	 * Right now only 2*RGMII is supported. Please extend when needed.
+	 * sr - 2008-02-19
+	 */
+	switch (9) {
+	case 1:
+		/* 1 MII - 460EX */
+		/* GMC0 EMAC4_0, ZMII Bridge */
+		zmiifer |= ZMII_FER_MII << ZMII_FER_V(0);
+		bis->bi_phymode[0] = BI_PHYMODE_MII;
+		bis->bi_phymode[1] = BI_PHYMODE_NONE;
+		bis->bi_phymode[2] = BI_PHYMODE_NONE;
+		bis->bi_phymode[3] = BI_PHYMODE_NONE;
+		break;
+	case 2:
+		/* 2 MII - 460GT */
+		/* GMC0 EMAC4_0, GMC1 EMAC4_2, ZMII Bridge */
+		zmiifer |= ZMII_FER_MII << ZMII_FER_V(0);
+		zmiifer |= ZMII_FER_MII << ZMII_FER_V(2);
+		bis->bi_phymode[0] = BI_PHYMODE_MII;
+		bis->bi_phymode[1] = BI_PHYMODE_NONE;
+		bis->bi_phymode[2] = BI_PHYMODE_MII;
+		bis->bi_phymode[3] = BI_PHYMODE_NONE;
+		break;
+	case 3:
+		/* 2 RMII - 460EX */
+		/* GMC0 EMAC4_0, GMC0 EMAC4_1, ZMII Bridge */
+		zmiifer |= ZMII_FER_RMII << ZMII_FER_V(0);
+		zmiifer |= ZMII_FER_RMII << ZMII_FER_V(1);
+		bis->bi_phymode[0] = BI_PHYMODE_RMII;
+		bis->bi_phymode[1] = BI_PHYMODE_RMII;
+		bis->bi_phymode[2] = BI_PHYMODE_NONE;
+		bis->bi_phymode[3] = BI_PHYMODE_NONE;
+		break;
+	case 4:
+		/* 4 RMII - 460GT */
+		/* GMC0 EMAC4_0, GMC0 EMAC4_1, GMC1 EMAC4_2, GMC1, EMAC4_3 */
+		/* ZMII Bridge */
+		zmiifer |= ZMII_FER_RMII << ZMII_FER_V(0);
+		zmiifer |= ZMII_FER_RMII << ZMII_FER_V(1);
+		zmiifer |= ZMII_FER_RMII << ZMII_FER_V(2);
+		zmiifer |= ZMII_FER_RMII << ZMII_FER_V(3);
+		bis->bi_phymode[0] = BI_PHYMODE_RMII;
+		bis->bi_phymode[1] = BI_PHYMODE_RMII;
+		bis->bi_phymode[2] = BI_PHYMODE_RMII;
+		bis->bi_phymode[3] = BI_PHYMODE_RMII;
+		break;
+	case 5:
+		/* 2 SMII - 460EX */
+		/* GMC0 EMAC4_0, GMC0 EMAC4_1, ZMII Bridge */
+		zmiifer |= ZMII_FER_SMII << ZMII_FER_V(0);
+		zmiifer |= ZMII_FER_SMII << ZMII_FER_V(1);
+		bis->bi_phymode[0] = BI_PHYMODE_SMII;
+		bis->bi_phymode[1] = BI_PHYMODE_SMII;
+		bis->bi_phymode[2] = BI_PHYMODE_NONE;
+		bis->bi_phymode[3] = BI_PHYMODE_NONE;
+		break;
+	case 6:
+		/* 4 SMII - 460GT */
+		/* GMC0 EMAC4_0, GMC0 EMAC4_1, GMC0 EMAC4_3, GMC0 EMAC4_3 */
+		/* ZMII Bridge */
+		zmiifer |= ZMII_FER_SMII << ZMII_FER_V(0);
+		zmiifer |= ZMII_FER_SMII << ZMII_FER_V(1);
+		zmiifer |= ZMII_FER_SMII << ZMII_FER_V(2);
+		zmiifer |= ZMII_FER_SMII << ZMII_FER_V(3);
+		bis->bi_phymode[0] = BI_PHYMODE_SMII;
+		bis->bi_phymode[1] = BI_PHYMODE_SMII;
+		bis->bi_phymode[2] = BI_PHYMODE_SMII;
+		bis->bi_phymode[3] = BI_PHYMODE_SMII;
+		break;
+	case 7:
+		/* This is the default mode that we want for board bringup - Maple */
+		/* 1 GMII - 460EX */
+		/* GMC0 EMAC4_0, RGMII Bridge 0 */
+		rmiifer |= RGMII_FER_MDIO(0);
+
+		if (devnum == 0) {
+			rmiifer |= RGMII_FER_GMII << RGMII_FER_V(2); /* CH0CFG - EMAC0 */
+			bis->bi_phymode[0] = BI_PHYMODE_GMII;
+			bis->bi_phymode[1] = BI_PHYMODE_NONE;
+			bis->bi_phymode[2] = BI_PHYMODE_NONE;
+			bis->bi_phymode[3] = BI_PHYMODE_NONE;
+		} else {
+			rmiifer |= RGMII_FER_GMII << RGMII_FER_V(3); /* CH1CFG - EMAC1 */
+			bis->bi_phymode[0] = BI_PHYMODE_NONE;
+			bis->bi_phymode[1] = BI_PHYMODE_GMII;
+			bis->bi_phymode[2] = BI_PHYMODE_NONE;
+			bis->bi_phymode[3] = BI_PHYMODE_NONE;
+		}
+		break;
+	case 8:
+		/* 2 GMII - 460GT */
+		/* GMC0 EMAC4_0, RGMII Bridge 0 */
+		/* GMC1 EMAC4_2, RGMII Bridge 1 */
+		rmiifer |= RGMII_FER_GMII << RGMII_FER_V(2);	/* CH0CFG - EMAC0 */
+		rmiifer1 |= RGMII_FER_GMII << RGMII_FER_V(2);	/* CH0CFG - EMAC2 */
+		rmiifer |= RGMII_FER_MDIO(0);			/* enable MDIO - EMAC0 */
+		rmiifer1 |= RGMII_FER_MDIO(0);			/* enable MDIO - EMAC2 */
+
+		bis->bi_phymode[0] = BI_PHYMODE_GMII;
+		bis->bi_phymode[1] = BI_PHYMODE_NONE;
+		bis->bi_phymode[2] = BI_PHYMODE_GMII;
+		bis->bi_phymode[3] = BI_PHYMODE_NONE;
+		break;
+	case 9:
+		/* 2 RGMII - 460EX */
+		/* GMC0 EMAC4_0, GMC0 EMAC4_1, RGMII Bridge 0 */
+		rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(2);
+		rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(3);
+		rmiifer |= RGMII_FER_MDIO(0);			/* enable MDIO - EMAC0 */
+
+		bis->bi_phymode[0] = BI_PHYMODE_RGMII;
+		bis->bi_phymode[1] = BI_PHYMODE_RGMII;
+		bis->bi_phymode[2] = BI_PHYMODE_NONE;
+		bis->bi_phymode[3] = BI_PHYMODE_NONE;
+		break;
+	case 10:
+		/* 4 RGMII - 460GT */
+		/* GMC0 EMAC4_0, GMC0 EMAC4_1, RGMII Bridge 0 */
+		/* GMC1 EMAC4_2, GMC1 EMAC4_3, RGMII Bridge 1 */
+		rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(2);
+		rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(3);
+		rmiifer1 |= RGMII_FER_RGMII << RGMII_FER_V(2);
+		rmiifer1 |= RGMII_FER_RGMII << RGMII_FER_V(3);
+		bis->bi_phymode[0] = BI_PHYMODE_RGMII;
+		bis->bi_phymode[1] = BI_PHYMODE_RGMII;
+		bis->bi_phymode[2] = BI_PHYMODE_RGMII;
+		bis->bi_phymode[3] = BI_PHYMODE_RGMII;
+		break;
+	default:
+		break;
+	}
+
+	/* Set EMAC for MDIO */
+	mfsdr(SDR0_ETH_CFG, eth_cfg);
+	eth_cfg |= SDR0_ETH_CFG_MDIO_SEL_EMAC0;
+	mtsdr(SDR0_ETH_CFG, eth_cfg);
+
+	out_be32((void *)RGMII_FER, rmiifer);
+#if defined(CONFIG_460GT)
+	out_be32((void *)RGMII_FER + RGMII1_BASE_OFFSET, rmiifer1);
+#endif
+
+	/* bypass the TAHOE0/TAHOE1 cores for U-Boot */
+	mfsdr(SDR0_ETH_CFG, eth_cfg);
+	eth_cfg |= (SDR0_ETH_CFG_TAHOE0_BYPASS | SDR0_ETH_CFG_TAHOE1_BYPASS);
+	mtsdr(SDR0_ETH_CFG, eth_cfg);
+
+	return 0;
+}
+#endif /* CONFIG_460EX || CONFIG_460GT */
+
 static inline void *malloc_aligned(u32 size, u32 align)
 {
 	return (void *)(((u32)malloc(size + align) + align - 1) &
@@ -472,19 +688,16 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 #if defined(CONFIG_440GX) || \
     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
     defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
 	sys_info_t sysinfo;
 #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
 	int ethgroup = -1;
 #endif
 #endif
-#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
-    defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
-    defined(CONFIG_405EX)
-	unsigned long mfr;
-#endif
 	u32 bd_cached;
 	u32 bd_uncached = 0;
 #ifdef CONFIG_4xx_DCACHE
@@ -503,6 +716,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 #if defined(CONFIG_440GX) || \
     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
     defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
 	/* Need to get the OPB frequency so we can access the PHY */
 	get_sys_info (&sysinfo);
@@ -556,21 +770,12 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 	out_be32((void *)ZMII_FER, 0);
 	udelay (100);
 
-#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+#if defined(CONFIG_440GP) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
 	out_be32((void *)ZMII_FER, (ZMII_FER_RMII | ZMII_FER_MDI) << ZMII_FER_V (devnum));
-#elif defined(CONFIG_440GX) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#elif defined(CONFIG_440GX) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)
 	ethgroup = ppc_4xx_eth_setup_bridge(devnum, bis);
-#elif defined(CONFIG_440GP)
-	/* set RMII mode */
-	out_be32((void *)ZMII_FER, ZMII_RMII | ZMII_MDI0);
-#else
-	if ((devnum == 0) || (devnum == 1)) {
-		out_be32((void *)ZMII_FER, (ZMII_FER_SMII | ZMII_FER_MDI) << ZMII_FER_V (devnum));
-	} else { /* ((devnum == 2) || (devnum == 3)) */
-		out_be32((void *)ZMII_FER, ZMII_FER_MDI << ZMII_FER_V (devnum));
-		out_be32((void *)RGMII_FER, ((RGMII_FER_RGMII << RGMII_FER_V (2)) |
-					     (RGMII_FER_RGMII << RGMII_FER_V (3))));
-	}
 #endif
 
 	out_be32((void *)ZMII_SSR, ZMII_SSR_SP << ZMII_SSR_V(devnum));
@@ -579,20 +784,17 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 	ethgroup = ppc_4xx_eth_setup_bridge(devnum, bis);
 #endif
 
-	__asm__ volatile ("eieio");
+	sync();
 
-	/* reset emac so we have access to the phy */
-#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
-    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
-    defined(CONFIG_405EX)
 	/* provide clocks for EMAC internal loopback  */
-	mfsdr (sdr_mfr, mfr);
-	mfr |= SDR0_MFR_ETH_CLK_SEL_V(devnum);
-	mtsdr(sdr_mfr, mfr);
-#endif
+	emac_loopback_enable(hw_p);
 
+	/* EMAC RESET */
 	out_be32((void *)EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
 
+	/* remove clocks for EMAC internal loopback  */
+	emac_loopback_disable(hw_p);
+
 	failsafe = 1000;
 	while ((in_be32((void *)EMAC_M0 + hw_p->hw_addr) & (EMAC_M0_SRST)) && failsafe) {
 		udelay (1000);
@@ -601,18 +803,10 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 	if (failsafe <= 0)
 		printf("\nProblem resetting EMAC!\n");
 
-#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
-    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
-    defined(CONFIG_405EX)
-	/* remove clocks for EMAC internal loopback  */
-	mfsdr (sdr_mfr, mfr);
-	mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(devnum);
-	mtsdr(sdr_mfr, mfr);
-#endif
-
 #if defined(CONFIG_440GX) || \
     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
     defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
 	/* Whack the M1 register */
 	mode_reg = 0x0;
@@ -674,6 +868,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 #if defined(CONFIG_440GX) || \
     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
     defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
 
 #if defined(CONFIG_CIS8201_PHY)
@@ -772,8 +967,10 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 			hw_p->devnum);
 	}
 
-#if defined(CONFIG_440) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
-    !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX)
+#if defined(CONFIG_440) && \
+    !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
+    !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX) && \
+    !defined(CONFIG_460EX) && !defined(CONFIG_460GT)
 #if defined(CONFIG_440EP) || defined(CONFIG_440GR)
 	mfsdr(sdr_mfr, reg);
 	if (speed == 100) {
@@ -807,6 +1004,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 #endif /* defined(CONFIG_440) && !defined(CONFIG_440SP) */
 
 #if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
 	if (speed == 1000)
 		reg = (RGMII_SSR_SP_1000MBPS << RGMII_SSR_V (devnum));
@@ -819,12 +1017,17 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 		return -1;
 	}
 	out_be32((void *)RGMII_SSR, reg);
+#if defined(CONFIG_460GT)
+	if ((devnum == 2) || (devnum == 3))
+		out_be32((void *)RGMII_SSR + RGMII1_BASE_OFFSET, reg);
+#endif
 #endif
 
 	/* set the Mal configuration reg */
 #if defined(CONFIG_440GX) || \
     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
     defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
 	mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA |
 	       MAL_CR_PLBLT_DEFAULT | MAL_CR_EOPIE | 0x00330000);
@@ -926,9 +1129,16 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 		mtdcr (maltxbattr, 0x0);
 		mtdcr (malrxbattr, 0x0);
 #endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+		mtdcr (malrxctp8r, hw_p->rx);
+		/* set RX buffer size */
+		mtdcr (malrcbs8, ENET_MAX_MTU_ALIGNED / 16);
+#else
 		mtdcr (malrxctp1r, hw_p->rx_phys);
 		/* set RX buffer size */
 		mtdcr (malrcbs1, ENET_MAX_MTU_ALIGNED / 16);
+#endif
 		break;
 #if defined (CONFIG_440GX)
 	case 2:
@@ -1087,7 +1297,7 @@ static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr,
 	hw_p->tx[hw_p->tx_slot].data_len = (short) len;
 	hw_p->tx[hw_p->tx_slot].ctrl |= MAL_TX_CTRL_READY;
 
-	__asm__ volatile ("eieio");
+	sync();
 
 	out_be32((void *)EMAC_TXM0 + hw_p->hw_addr,
 		 in_be32((void *)EMAC_TXM0 + hw_p->hw_addr) | EMAC_TXM0_GNP0);
@@ -1127,15 +1337,31 @@ static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr,
  */
 #define UIC0MSR		uic1msr
 #define UIC0SR		uic1sr
+#define UIC1MSR		uic1msr
+#define UIC1SR		uic1sr
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+/*
+ * Hack: On 460EX/GT all enet irq sources are located on UIC2
+ * Needs some cleanup. --ag
+ */
+#define UIC0MSR		uic2msr
+#define UIC0SR		uic2sr
+#define UIC1MSR		uic2msr
+#define UIC1SR		uic2sr
 #else
 #define UIC0MSR		uic0msr
 #define UIC0SR		uic0sr
+#define UIC1MSR		uic1msr
+#define UIC1SR		uic1sr
 #endif
 
 #if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
     defined(CONFIG_405EX)
 #define UICMSR_ETHX	uic0msr
 #define UICSR_ETHX	uic0sr
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define UICMSR_ETHX	uic2msr
+#define UICSR_ETHX	uic2sr
 #else
 #define UICMSR_ETHX	uic1msr
 #define UICSR_ETHX	uic1sr
@@ -1173,7 +1399,7 @@ int enetInt (struct eth_device *dev)
 		serviced = 0;
 
 		my_uic0msr = mfdcr (UIC0MSR);
-		my_uic1msr = mfdcr (uic1msr);
+		my_uic1msr = mfdcr (UIC1MSR);
 #if defined(CONFIG_440GX)
 		my_uic2msr = mfdcr (uic2msr);
 #endif
@@ -1219,7 +1445,7 @@ int enetInt (struct eth_device *dev)
 			if ((hw_p->emac_ier & emac_isr)
 			    || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
 				mtdcr (UIC0SR, UIC_MRE | UIC_MTE);	/* Clear */
-				mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE);	/* Clear */
+				mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE);	/* Clear */
 				mtdcr (UICSR_ETHX, UIC_ETH0); /* Clear */
 				return (rc);	/* we had errors so get out */
 			}
@@ -1238,7 +1464,7 @@ int enetInt (struct eth_device *dev)
 			if ((hw_p->emac_ier & emac_isr)
 			    || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
 				mtdcr (UIC0SR, UIC_MRE | UIC_MTE);	/* Clear */
-				mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
+				mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
 				mtdcr (UICSR_ETHX, UIC_ETH1); /* Clear */
 				return (rc);	/* we had errors so get out */
 			}
@@ -1256,7 +1482,7 @@ int enetInt (struct eth_device *dev)
 			if ((hw_p->emac_ier & emac_isr)
 			    || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
 				mtdcr (UIC0SR, UIC_MRE | UIC_MTE);	/* Clear */
-				mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE);	/* Clear */
+				mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE);	/* Clear */
 				mtdcr (uic2sr, UIC_ETH2);
 				return (rc);	/* we had errors so get out */
 			}
@@ -1274,7 +1500,7 @@ int enetInt (struct eth_device *dev)
 			if ((hw_p->emac_ier & emac_isr)
 			    || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
 				mtdcr (UIC0SR, UIC_MRE | UIC_MTE);	/* Clear */
-				mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE);	/* Clear */
+				mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE);	/* Clear */
 				mtdcr (uic2sr, UIC_ETH3);
 				return (rc);	/* we had errors so get out */
 			}
@@ -1292,7 +1518,9 @@ int enetInt (struct eth_device *dev)
 		/* check for EOB on valid channels	      */
 		if (my_uic0msr & UIC_MRE) {
 			mal_rx_eob = mfdcr (malrxeobisr);
-			if ((mal_rx_eob & (0x80000000 >> hw_p->devnum)) != 0) { /* call emac routine for channel x */
+			if ((mal_rx_eob &
+			     (0x80000000 >> (hw_p->devnum * MAL_RX_CHAN_MUL)))
+			    != 0) { /* call emac routine for channel x */
 				/* clear EOB
 				   mtdcr(malrxeobisr, mal_rx_eob); */
 				enet_rcv (dev, emac_isr);
@@ -1303,7 +1531,7 @@ int enetInt (struct eth_device *dev)
 		}
 
 		mtdcr (UIC0SR, UIC_MRE);	/* Clear */
-		mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE);	/* Clear */
+		mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE);	/* Clear */
 		switch (hw_p->devnum) {
 		case 0:
 			mtdcr (UICSR_ETHX, UIC_ETH0);
@@ -1468,7 +1696,7 @@ static void enet_rcv (struct eth_device *dev, unsigned long malisr)
 	int loop_count = 0;
 
 	rx_eob_isr = mfdcr (malrxeobisr);
-	if ((0x80000000 >> hw_p->devnum) & rx_eob_isr) {
+	if ((0x80000000 >> (hw_p->devnum * MAL_RX_CHAN_MUL)) & rx_eob_isr) {
 		/* clear EOB */
 		mtdcr (malrxeobisr, rx_eob_isr);
 
@@ -1482,7 +1710,7 @@ static void enet_rcv (struct eth_device *dev, unsigned long malisr)
 
 			loop_count++;
 			handled++;
-			data_len = (unsigned long) hw_p->rx[i].data_len;	/* Get len */
+			data_len = (unsigned long) hw_p->rx[i].data_len & 0x0fff;	/* Get len */
 			if (data_len) {
 				if (data_len > ENET_MAX_MTU)	/* Check len */
 					data_len = 0;
@@ -1568,7 +1796,7 @@ static int ppc_4xx_eth_rx (struct eth_device *dev)
 		msr = mfmsr ();
 		mtmsr (msr & ~(MSR_EE));
 
-		length = hw_p->rx[user_index].data_len;
+		length = hw_p->rx[user_index].data_len & 0x0fff;
 
 		/* Pass the packet up to the protocol layers. */
 		/*	 NetReceive(NetRxPackets[rxIdx], length - 4); */
@@ -1718,6 +1946,7 @@ int ppc_4xx_eth_initialize (bd_t * bis)
 			/* set the MAL IER ??? names may change with new spec ??? */
 #if defined(CONFIG_440SPE) || \
     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
 			mal_ier =
 				MAL_IER_PT | MAL_IER_PRE | MAL_IER_PWE |
diff --git a/cpu/ppc4xx/4xx_pci.c b/cpu/ppc4xx/4xx_pci.c
index a5b9690..941d4dc 100644
--- a/cpu/ppc4xx/4xx_pci.c
+++ b/cpu/ppc4xx/4xx_pci.c
@@ -531,7 +531,8 @@ int pci_440_init (struct pci_controller *hose)
 	out16r( PCIX0_CLS, 0x00060000 ); /* Bridge, host bridge */
 #endif
 
-#if defined(CONFIG_440GX) || defined(CONFIG_440SPE)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)
 	out32r( PCIX0_BRDGOPT1, 0x04000060 );               /* PLB Rq pri highest   */
 	out32r( PCIX0_BRDGOPT2, in32(PCIX0_BRDGOPT2) | 0x83 ); /* Enable host config, clear Timeout, ensure int src1  */
 #elif defined(PCIX0_BRDGOPT1)
@@ -549,7 +550,8 @@ int pci_440_init (struct pci_controller *hose)
 	out32r( PCIX0_POM0SA, 0 ); /* disable */
 	out32r( PCIX0_POM1SA, 0 ); /* disable */
 	out32r( PCIX0_POM2SA, 0 ); /* disable */
-#if defined(CONFIG_440SPE)
+#if defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)
 	out32r( PCIX0_POM0LAL, 0x10000000 );
 	out32r( PCIX0_POM0LAH, 0x0000000c );
 #else
@@ -586,7 +588,8 @@ void pci_init_board(void)
 	int busno;
 
 	busno = pci_440_init (&ppc440_hose);
-#if defined(CONFIG_440SPE)
+#if defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)
 	pcie_setup_hoses(busno + 1);
 #endif
 }
diff --git a/cpu/ppc4xx/4xx_pcie.c b/cpu/ppc4xx/4xx_pcie.c
index 3af9862..f9a1988 100644
--- a/cpu/ppc4xx/4xx_pcie.c
+++ b/cpu/ppc4xx/4xx_pcie.c
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2006 - 2007
+ * (C) Copyright 2006 - 2008
  * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
  *
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
@@ -31,7 +31,8 @@
 #include <common.h>
 #include <pci.h>
 
-#if (defined(CONFIG_440SPE) || defined(CONFIG_405EX)) && \
+#if (defined(CONFIG_440SPE) || defined(CONFIG_405EX) ||	\
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)) && \
     defined(CONFIG_PCI)
 
 #include <asm/4xx_pcie.h>
@@ -306,9 +307,8 @@ static int check_error(void)
 	int err = 0;
 
 	/* SDR0_PEGPLLLCT1 reset */
-	if (!(valPE0 = SDR_READ(PESDR0_PLLLCT1) & 0x01000000)) {
+	if (!(valPE0 = SDR_READ(PESDR0_PLLLCT1) & 0x01000000))
 		printf("PCIE: SDR0_PEGPLLLCT1 reset error 0x%x\n", valPE0);
-	}
 
 	valPE0 = SDR_READ(PESDR0_RCSSET);
 	valPE1 = SDR_READ(PESDR1_RCSSET);
@@ -400,7 +400,108 @@ int ppc4xx_init_pcie(void)
 	}
 	return 0;
 }
-#else
+#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+static void ppc4xx_setup_utl(u32 port)
+{
+	volatile void *utl_base = NULL;
+
+	/*
+	 * Map UTL registers at 0x0801_n000 (4K 0xfff mask) PEGPLn_REGMSK
+	 */
+	switch (port) {
+	case 0:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE0), U64_TO_U32_HIGH(CFG_PCIE0_UTLBASE));
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE0), U64_TO_U32_LOW(CFG_PCIE0_UTLBASE));
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001);	/* BAM 11100000=4KB */
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0);
+		break;
+
+	case 1:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE1), U64_TO_U32_HIGH(CFG_PCIE0_UTLBASE));
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE1), U64_TO_U32_LOW(CFG_PCIE0_UTLBASE)
+			+ 0x1000);
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001);	/* BAM 11100000=4KB */
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0);
+		break;
+	}
+	utl_base = (unsigned int *)(CFG_PCIE_BASE + 0x1000 * port);
+
+	/*
+	 * Set buffer allocations and then assert VRB and TXE.
+	 */
+	out_be32(utl_base + PEUTL_PBCTL, 0x0800000c);	/* PLBME, CRRE */
+	out_be32(utl_base + PEUTL_OUTTR, 0x08000000);
+	out_be32(utl_base + PEUTL_INTR, 0x02000000);
+	out_be32(utl_base + PEUTL_OPDBSZ, 0x04000000);	/* OPD = 512 Bytes */
+	out_be32(utl_base + PEUTL_PBBSZ, 0x00000000);	/* Max 512 Bytes */
+	out_be32(utl_base + PEUTL_IPHBSZ, 0x02000000);
+	out_be32(utl_base + PEUTL_IPDBSZ, 0x04000000);	/* IPD = 512 Bytes */
+	out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000);
+	out_be32(utl_base + PEUTL_PCTL, 0x80800066);	/* VRB,TXE,timeout=default */
+}
+
+/*
+ * TODO: double check PCI express SDR based on the latest user manual
+ * 		 Some registers specified here no longer exist.. has to be
+ * 		 updated based on the final EAS spec.
+ */
+static int check_error(void)
+{
+	u32 valPE0, valPE1;
+	int err = 0;
+
+	valPE0 = SDR_READ(SDRN_PESDR_RCSSET(0));
+	valPE1 = SDR_READ(SDRN_PESDR_RCSSET(1));
+
+	/* SDR0_PExRCSSET rstgu */
+	if (!(valPE0 & PESDRx_RCSSET_RSTGU) || !(valPE1 & PESDRx_RCSSET_RSTGU)) {
+		printf("PCIE:  SDR0_PExRCSSET rstgu error\n");
+		err = -1;
+	}
+
+	/* SDR0_PExRCSSET rstdl */
+	if (!(valPE0 & PESDRx_RCSSET_RSTDL) || !(valPE1 & PESDRx_RCSSET_RSTDL)) {
+		printf("PCIE:  SDR0_PExRCSSET rstdl error\n");
+		err = -1;
+	}
+
+	/* SDR0_PExRCSSET rstpyn */
+	if ((valPE0 & PESDRx_RCSSET_RSTPYN) || (valPE1 & PESDRx_RCSSET_RSTPYN)) {
+		printf("PCIE:  SDR0_PExRCSSET rstpyn error\n");
+		err = -1;
+	}
+
+	/* SDR0_PExRCSSET hldplb */
+	if ((valPE0 & PESDRx_RCSSET_HLDPLB) || (valPE1 & PESDRx_RCSSET_HLDPLB)) {
+		printf("PCIE:  SDR0_PExRCSSET hldplb error\n");
+		err = -1;
+	}
+
+	/* SDR0_PExRCSSET rdy */
+	if ((valPE0 & PESDRx_RCSSET_RDY) || (valPE1 & PESDRx_RCSSET_RDY)) {
+		printf("PCIE:  SDR0_PExRCSSET rdy error\n");
+		err = -1;
+	}
+
+	return err;
+}
+
+/*
+ * Initialize PCI Express core as described in User Manual
+ * TODO: double check PE SDR PLL Register with the updated user manual.
+ */
+int ppc4xx_init_pcie(void)
+{
+	if (check_error())
+		return -1;
+
+	return 0;
+}
+#endif /* CONFIG_460EX */
+
+#if defined(CONFIG_405EX)
 static void ppc4xx_setup_utl(u32 port)
 {
 	u32 utl_base;
@@ -450,7 +551,7 @@ int ppc4xx_init_pcie(void)
 	 */
 	return 0;
 }
-#endif
+#endif /* CONFIG_405EX */
 
 /*
  * Board-specific pcie initialization
@@ -511,6 +612,82 @@ int __ppc4xx_init_pcie_port_hw(int port, int rootport)
 }
 #endif /* CONFIG_440SPE */
 
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+int __ppc4xx_init_pcie_port_hw(int port, int rootport)
+{
+	u32 val = 1 << 24;
+	u32 utlset1;
+
+	if (rootport) {
+		val = PTYPE_ROOT_PORT << 20;
+		utlset1 = 0x21222222;
+	} else {
+		val = PTYPE_LEGACY_ENDPOINT << 20;
+		utlset1 = 0x20222222;
+	}
+
+	if (port == 0) {
+		val |= LNKW_X1 << 12;
+	} else {
+		val |= LNKW_X4 << 12;
+		utlset1 |= 0x00101101;
+	}
+
+	SDR_WRITE(SDRN_PESDR_DLPSET(port), val);
+	SDR_WRITE(SDRN_PESDR_UTLSET1(port), utlset1);
+	SDR_WRITE(SDRN_PESDR_UTLSET2(port), 0x01210000);
+
+	switch (port) {
+	case 0:
+		SDR_WRITE(PESDR0_L0CDRCTL, 0x00003230);
+		SDR_WRITE(PESDR0_L0DRV, 0x00000136);
+		SDR_WRITE(PESDR0_L0CLK, 0x00000006);
+
+		SDR_WRITE(PESDR0_PHY_CTL_RST,0x10000000);
+		break;
+
+	case 1:
+		SDR_WRITE(PESDR1_L0CDRCTL, 0x00003230);
+		SDR_WRITE(PESDR1_L1CDRCTL, 0x00003230);
+		SDR_WRITE(PESDR1_L2CDRCTL, 0x00003230);
+		SDR_WRITE(PESDR1_L3CDRCTL, 0x00003230);
+		SDR_WRITE(PESDR1_L0DRV, 0x00000136);
+		SDR_WRITE(PESDR1_L1DRV, 0x00000136);
+		SDR_WRITE(PESDR1_L2DRV, 0x00000136);
+		SDR_WRITE(PESDR1_L3DRV, 0x00000136);
+		SDR_WRITE(PESDR1_L0CLK, 0x00000006);
+		SDR_WRITE(PESDR1_L1CLK, 0x00000006);
+		SDR_WRITE(PESDR1_L2CLK, 0x00000006);
+		SDR_WRITE(PESDR1_L3CLK, 0x00000006);
+
+		SDR_WRITE(PESDR1_PHY_CTL_RST,0x10000000);
+		break;
+	}
+
+	SDR_WRITE(SDRN_PESDR_RCSSET(port), SDR_READ(SDRN_PESDR_RCSSET(port)) |
+		  (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTPYN));
+
+	/* Poll for PHY reset */
+	switch (port) {
+	case 0:
+		while (!(SDR_READ(PESDR0_RSTSTA) & 0x1))
+			udelay(10);
+		break;
+	case 1:
+		while (!(SDR_READ(PESDR1_RSTSTA) & 0x1))
+			udelay(10);
+		break;
+	}
+
+	SDR_WRITE(SDRN_PESDR_RCSSET(port),
+		  (SDR_READ(SDRN_PESDR_RCSSET(port)) &
+		   ~(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL)) |
+		  PESDRx_RCSSET_RSTPYN);
+
+	return 0;
+}
+#endif /* CONFIG_440SPE */
+
 #if defined(CONFIG_405EX)
 int __ppc4xx_init_pcie_port_hw(int port, int rootport)
 {
@@ -564,12 +741,12 @@ __attribute__((weak, alias("__ppc4xx_init_pcie_port_hw")));
  * range (hangs the core upon config transaction attempts when set
  * otherwise) while revA uses c_nnnn_nnnn.
  *
- * For revA:
+ * For 440SPe revA:
  *     PCIE0: 0xc_4000_0000
  *     PCIE1: 0xc_8000_0000
  *     PCIE2: 0xc_c000_0000
  *
- * For revB:
+ * For 440SPe revB:
  *     PCIE0: 0xd_0000_0000
  *     PCIE1: 0xd_2000_0000
  *     PCIE2: 0xd_4000_0000
@@ -577,6 +754,10 @@ __attribute__((weak, alias("__ppc4xx_init_pcie_port_hw")));
  * For 405EX:
  *     PCIE0: 0xa000_0000
  *     PCIE1: 0xc000_0000
+ *
+ * For 460EX/GT:
+ *     PCIE0: 0xd_0000_0000
+ *     PCIE1: 0xd_2000_0000
  */
 static inline u64 ppc4xx_get_cfgaddr(int port)
 {
@@ -609,6 +790,12 @@ static inline u64 ppc4xx_get_cfgaddr(int port)
 		}
 	}
 #endif
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+	if (port == 0)
+		return 0x0000000d00000000ULL;
+	else
+		return 0x0000000d20000000ULL;
+#endif
 }
 
 /*
diff --git a/cpu/ppc4xx/4xx_uart.c b/cpu/ppc4xx/4xx_uart.c
index 3d1124e..ffbc222 100644
--- a/cpu/ppc4xx/4xx_uart.c
+++ b/cpu/ppc4xx/4xx_uart.c
@@ -64,16 +64,22 @@ DECLARE_GLOBAL_DATA_PTR;
 
 #if defined(CONFIG_440)
 #if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
-    defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
-#define UART0_BASE  CFG_PERIPHERAL_BASE + 0x00000300
-#define UART1_BASE  CFG_PERIPHERAL_BASE + 0x00000400
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define UART0_BASE	(CFG_PERIPHERAL_BASE + 0x00000300)
+#define UART1_BASE	(CFG_PERIPHERAL_BASE + 0x00000400)
 #else
-#define UART0_BASE  CFG_PERIPHERAL_BASE + 0x00000200
-#define UART1_BASE  CFG_PERIPHERAL_BASE + 0x00000300
+#define UART0_BASE	(CFG_PERIPHERAL_BASE + 0x00000200)
+#define UART1_BASE	(CFG_PERIPHERAL_BASE + 0x00000300)
 #endif
 
 #if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
-#define UART2_BASE  CFG_PERIPHERAL_BASE + 0x00000600
+#define UART2_BASE	(CFG_PERIPHERAL_BASE + 0x00000600)
+#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define UART2_BASE	(CFG_PERIPHERAL_BASE + 0x00000500)
+#define UART3_BASE	(CFG_PERIPHERAL_BASE + 0x00000600)
 #endif
 
 #if defined(CONFIG_440GP)
@@ -94,11 +100,13 @@ DECLARE_GLOBAL_DATA_PTR;
 #define UART1_SDR	sdr_uart1
 #if defined(CONFIG_440EP) || defined(CONFIG_440EPx) || \
     defined(CONFIG_440GR) || defined(CONFIG_440GRx) || \
-    defined(CONFIG_440SP) || defined(CONFIG_440SPe)
+    defined(CONFIG_440SP) || defined(CONFIG_440SPe) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)
 #define UART2_SDR	sdr_uart2
 #endif
 #if defined(CONFIG_440EP) || defined(CONFIG_440EPx) || \
-    defined(CONFIG_440GR) || defined(CONFIG_440GRx)
+    defined(CONFIG_440GR) || defined(CONFIG_440GRx) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)
 #define UART3_SDR	sdr_uart3
 #endif
 #define MFREG(a, d)	mfsdr(a, d)
-- 
1.5.4.4





More information about the U-Boot mailing list