浏览代码

PCIe endpoint support for AMCC Yucca 440SPe board
Patch by Tirumala R Marri, 26 Aug 2006

Stefan Roese 18 年之前
父节点
当前提交
2b393b0f0a
共有 4 个文件被更改,包括 481 次插入29 次删除
  1. 3 0
      CHANGELOG
  2. 75 5
      board/amcc/yucca/yucca.c
  3. 393 23
      cpu/ppc4xx/440spe_pcie.c
  4. 10 1
      cpu/ppc4xx/440spe_pcie.h

+ 3 - 0
CHANGELOG

@@ -2,6 +2,9 @@
 Changes since U-Boot 1.1.4:
 Changes since U-Boot 1.1.4:
 ======================================================================
 ======================================================================
 
 
+* PCIe endpoint support for AMCC Yucca 440SPe board
+  Patch by Tirumala R Marri, 26 Aug 2006
+
 * Improve DIMM detection for AMCC Yucca 440SPe board
 * Improve DIMM detection for AMCC Yucca 440SPe board
   Improved the memory DIMM detection for the Yucca 440SPe board for
   Improved the memory DIMM detection for the Yucca 440SPe board for
   the case where a memory DIMM is falsely detected as present.
   the case where a memory DIMM is falsely detected as present.

+ 75 - 5
board/amcc/yucca/yucca.c

@@ -32,6 +32,10 @@
 #include <asm-ppc/io.h>
 #include <asm-ppc/io.h>
 
 
 #include "yucca.h"
 #include "yucca.h"
+#include "../cpu/ppc4xx/440spe_pcie.h"
+
+#undef PCIE_ENDPOINT
+/* #define PCIE_ENDPOINT 1 */
 
 
 void fpga_init (void);
 void fpga_init (void);
 
 
@@ -583,12 +587,12 @@ static long int yucca_probe_for_dimms(void)
 
 
 		memset(dimm_spd_data, 0, MAX_SPD_BYTES * sizeof(char));
 		memset(dimm_spd_data, 0, MAX_SPD_BYTES * sizeof(char));
 		if (result == 0) {
 		if (result == 0) {
-			/* read first byte of SPD data, if there is any data */ 
+			/* read first byte of SPD data, if there is any data */
 			result = i2c_read(dimm_addr, 0, 1, dimm_spd_data, 1);
 			result = i2c_read(dimm_addr, 0, 1, dimm_spd_data, 1);
 
 
 			if (result == 0) {
 			if (result == 0) {
 				result = dimm_spd_data[0];
 				result = dimm_spd_data[0];
-				result = result > MAX_SPD_BYTES ? 
+				result = result > MAX_SPD_BYTES ?
 						MAX_SPD_BYTES : result;
 						MAX_SPD_BYTES : result;
 				result = i2c_read(dimm_addr, 0, 1,
 				result = i2c_read(dimm_addr, 0, 1,
 							dimm_spd_data, result);
 							dimm_spd_data, result);
@@ -596,7 +600,7 @@ static long int yucca_probe_for_dimms(void)
 		}
 		}
 
 
 		if ((result == 0) &&
 		if ((result == 0) &&
-		    (dimm_spd_data[64] == MICRON_SPD_JEDEC_ID)) {	
+		    (dimm_spd_data[64] == MICRON_SPD_JEDEC_ID)) {
 			dimm_installed[dimm_num] = TRUE;
 			dimm_installed[dimm_num] = TRUE;
 			dimms_found++;
 			dimms_found++;
 			debug("DIMM slot %d: DDR2 SDRAM detected\n", dimm_num);
 			debug("DIMM slot %d: DDR2 SDRAM detected\n", dimm_num);
@@ -1029,6 +1033,57 @@ void yucca_setup_pcie_fpga_rootpoint(int port)
 
 
 	out_be16((u16 *)FPGA_REG1C, reset_off | in_be16((u16 *)FPGA_REG1C));
 	out_be16((u16 *)FPGA_REG1C, reset_off | in_be16((u16 *)FPGA_REG1C));
 }
 }
+/*
+ * For the given slot, set endpoint mode, send power to the slot,
+ * turn on the green LED and turn off the yellow LED, enable the clock
+ * .In end point mode reset bit is  read only.
+ */
+void yucca_setup_pcie_fpga_endpoint(int port)
+{
+	u16 power, clock, green_led, yellow_led, reset_off, rootpoint, endpoint;
+
+	switch(port) {
+	case 0:
+		rootpoint   = FPGA_REG1C_PE0_ROOTPOINT;
+		endpoint    = 0;
+		power 	    = FPGA_REG1A_PE0_PWRON;
+		green_led   = FPGA_REG1A_PE0_GLED;
+		clock 	    = FPGA_REG1A_PE0_REFCLK_ENABLE;
+		yellow_led  = FPGA_REG1A_PE0_YLED;
+		reset_off   = FPGA_REG1C_PE0_PERST;
+		break;
+	case 1:
+		rootpoint   = 0;
+		endpoint    = FPGA_REG1C_PE1_ENDPOINT;
+		power 	    = FPGA_REG1A_PE1_PWRON;
+		green_led   = FPGA_REG1A_PE1_GLED;
+		clock 	    = FPGA_REG1A_PE1_REFCLK_ENABLE;
+		yellow_led  = FPGA_REG1A_PE1_YLED;
+		reset_off   = FPGA_REG1C_PE1_PERST;
+		break;
+	case 2:
+		rootpoint   = 0;
+		endpoint    = FPGA_REG1C_PE2_ENDPOINT;
+		power 	    = FPGA_REG1A_PE2_PWRON;
+		green_led   = FPGA_REG1A_PE2_GLED;
+		clock 	    = FPGA_REG1A_PE2_REFCLK_ENABLE;
+		yellow_led  = FPGA_REG1A_PE2_YLED;
+		reset_off   = FPGA_REG1C_PE2_PERST;
+		break;
+
+	default:
+		return;
+	}
+
+	out_be16((u16 *)FPGA_REG1A,
+		 ~(power | clock | green_led) &
+		 (yellow_led | in_be16((u16 *)FPGA_REG1A)));
+
+	out_be16((u16 *)FPGA_REG1C,
+		 ~(rootpoint | reset_off) &
+		 (endpoint | in_be16((u16 *)FPGA_REG1C)));
+}
+
 
 
 
 
 static struct pci_controller pcie_hose[3] = {{0},{0},{0}};
 static struct pci_controller pcie_hose[3] = {{0},{0},{0}};
@@ -1048,9 +1103,13 @@ void pcie_setup_hoses(void)
 		if (!yucca_pcie_card_present(i))
 		if (!yucca_pcie_card_present(i))
 			continue;
 			continue;
 
 
+#ifdef PCIE_ENDPOINT
+ 		yucca_setup_pcie_fpga_endpoint(i);
+ 		if (ppc440spe_init_pcie_endport(i)) {
+#else
 		yucca_setup_pcie_fpga_rootpoint(i);
 		yucca_setup_pcie_fpga_rootpoint(i);
-
 		if (ppc440spe_init_pcie_rootport(i)) {
 		if (ppc440spe_init_pcie_rootport(i)) {
+#endif
 			printf("PCIE%d: initialization failed\n", i);
 			printf("PCIE%d: initialization failed\n", i);
 			continue;
 			continue;
 		}
 		}
@@ -1070,8 +1129,19 @@ void pcie_setup_hoses(void)
 		hose->region_count = 1;
 		hose->region_count = 1;
 		pci_register_hose(hose);
 		pci_register_hose(hose);
 
 
-		ppc440spe_setup_pcie(hose, i);
+#ifdef PCIE_ENDPOINT
+		ppc440spe_setup_pcie_endpoint(hose, i);
+		/*
+		 * Reson for no scanning is endpoint can not generate
+		 * upstream configuration accesses.
+		 */
+#else
+		ppc440spe_setup_pcie_rootpoint(hose, i);
+		/*
+		 * Config access can only go down stream
+		 */
 		hose->last_busno = pci_hose_scan(hose);
 		hose->last_busno = pci_hose_scan(hose);
+#endif
 	}
 	}
 }
 }
 #endif	/* defined(CONFIG_PCI) */
 #endif	/* defined(CONFIG_PCI) */

+ 393 - 23
cpu/ppc4xx/440spe_pcie.c

@@ -270,7 +270,7 @@ int ppc440spe_init_pcie(void)
 	SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) & ~(1 << 24));
 	SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) & ~(1 << 24));
 	udelay(3);
 	udelay(3);
 
 
-	while(time_out) {
+	while (time_out) {
 		if (!(SDR_READ(PESDR0_PLLLCT3) & 0x10000000)) {
 		if (!(SDR_READ(PESDR0_PLLLCT3) & 0x10000000)) {
 			time_out--;
 			time_out--;
 			udelay(1);
 			udelay(1);
@@ -284,6 +284,40 @@ int ppc440spe_init_pcie(void)
 	return 0;
 	return 0;
 }
 }
 
 
+/*
+ *  Yucca board as End point and root point setup
+ *                    and
+ *    testing inbound and out bound windows
+ *
+ *  YUCCA board can be plugged into another yucca board or you can get PCI-E
+ *  cable which can be used to setup loop back from one port to another port.
+ *  Please rememeber that unless there is a endpoint plugged in to root port it
+ *  will not initialize. It is the same in case of endpoint , unless there is
+ *  root port attached it will not initialize.
+ *
+ *  In this release of software all the PCI-E ports are configured as either
+ *  endpoint or rootpoint.In future we will have support for selective ports
+ *  setup as endpoint and root point in single board.
+ *
+ *  Once your board came up as root point , you can verify by reading
+ *  /proc/bus/pci/devices. Where you can see the configuration registers
+ *  of end point device attached to the port.
+ *
+ *  Enpoint cofiguration can be verified by connecting Yucca board to any
+ *  host or another yucca board. Then try to scan the device. In case of
+ *  linux use "lspci" or appripriate os command.
+ *
+ *  How do I verify the inbound and out bound windows ?(yucca to yucca)
+ *  in this configuration inbound and outbound windows are setup to access
+ *  sram memroy area. SRAM is at 0x4 0000 0000 , on PLB bus. This address
+ *  is mapped at 0x90000000. From u-boot prompt write data 0xb000 0000,
+ *  This is waere your POM(PLB out bound memory window) mapped. then
+ *  read the data from other yucca board's u-boot prompt at address
+ *  0x9000 0000(SRAM). Data should match.
+ *  In case of inbound , write data to u-boot command prompt at 0xb000 0000
+ *  which is mapped to 0x4 0000 0000. Now on rootpoint yucca u-boot prompt check
+ *  data at 0x9000 0000(SRAM).Data should match.
+ */
 int ppc440spe_init_pcie_rootport(int port)
 int ppc440spe_init_pcie_rootport(int port)
 {
 {
 	static int core_init;
 	static int core_init;
@@ -326,7 +360,7 @@ int ppc440spe_init_pcie_rootport(int port)
 		SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000);
 		SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000);
 		SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000);
 		SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000);
 		SDR_WRITE(PESDR0_RCSSET,
 		SDR_WRITE(PESDR0_RCSSET,
-			(SDR_READ(PESDR0_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
+			  (SDR_READ(PESDR0_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
 		break;
 		break;
 
 
 	case 1:
 	case 1:
@@ -339,7 +373,7 @@ int ppc440spe_init_pcie_rootport(int port)
 		SDR_WRITE(PESDR1_HSSL2SET1, 0x35000000);
 		SDR_WRITE(PESDR1_HSSL2SET1, 0x35000000);
 		SDR_WRITE(PESDR1_HSSL3SET1, 0x35000000);
 		SDR_WRITE(PESDR1_HSSL3SET1, 0x35000000);
 		SDR_WRITE(PESDR1_RCSSET,
 		SDR_WRITE(PESDR1_RCSSET,
-			(SDR_READ(PESDR1_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
+			  (SDR_READ(PESDR1_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
 		break;
 		break;
 
 
 	case 2:
 	case 2:
@@ -351,6 +385,225 @@ int ppc440spe_init_pcie_rootport(int port)
 		SDR_WRITE(PESDR2_HSSL1SET1, 0x35000000);
 		SDR_WRITE(PESDR2_HSSL1SET1, 0x35000000);
 		SDR_WRITE(PESDR2_HSSL2SET1, 0x35000000);
 		SDR_WRITE(PESDR2_HSSL2SET1, 0x35000000);
 		SDR_WRITE(PESDR2_HSSL3SET1, 0x35000000);
 		SDR_WRITE(PESDR2_HSSL3SET1, 0x35000000);
+		SDR_WRITE(PESDR2_RCSSET,
+			  (SDR_READ(PESDR2_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
+		break;
+	}
+	/*
+	 * Notice: the following delay has critical impact on device
+	 * initialization - if too short (<50ms) the link doesn't get up.
+	 */
+	mdelay(100);
+
+	switch (port) {
+	case 0:
+		val = SDR_READ(PESDR0_RCSSTS);
+		break;
+	case 1:
+		val = SDR_READ(PESDR1_RCSSTS);
+		break;
+	case 2:
+		val = SDR_READ(PESDR2_RCSSTS);
+		break;
+	}
+
+	if (val & (1 << 20)) {
+		printf("PCIE%d: PGRST failed %08x\n", port, val);
+		return -1;
+	}
+
+	/*
+	 * Verify link is up
+	 */
+	val = 0;
+	switch (port) {
+	case 0:
+		val = SDR_READ(PESDR0_LOOP);
+		break;
+	case 1:
+		val = SDR_READ(PESDR1_LOOP);
+		break;
+	case 2:
+		val = SDR_READ(PESDR2_LOOP);
+		break;
+	}
+	if (!(val & 0x00001000)) {
+		printf("PCIE%d: link is not up.\n", port);
+		return -1;
+	}
+
+	/*
+	 * Setup UTL registers - but only on revA!
+	 * We use default settings for revB chip.
+	 */
+	if (!ppc440spe_revB())
+		ppc440spe_setup_utl(port);
+
+	/*
+	 * We map PCI Express configuration access into the 512MB regions
+	 *
+	 * NOTICE: revB is very strict about PLB real addressess and ranges to
+	 * be mapped for config space; it seems to only work with d_nnnn_nnnn
+	 * range (hangs the core upon config transaction attempts when set
+	 * otherwise) while revA uses c_nnnn_nnnn.
+	 *
+	 * For revA:
+	 *     PCIE0: 0xc_4000_0000
+	 *     PCIE1: 0xc_8000_0000
+	 *     PCIE2: 0xc_c000_0000
+	 *
+	 * For revB:
+	 *     PCIE0: 0xd_0000_0000
+	 *     PCIE1: 0xd_2000_0000
+	 *     PCIE2: 0xd_4000_0000
+	 */
+
+	switch (port) {
+	case 0:
+		if (ppc440spe_revB()) {
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000d);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x00000000);
+		} else {
+			/* revA */
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000c);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x40000000);
+		}
+		mtdcr(DCRN_PEGPL_CFGMSK(PCIE0), 0xe0000001); /* 512MB region, valid */
+		break;
+
+	case 1:
+		if (ppc440spe_revB()) {
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000d);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x20000000);
+		} else {
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000c);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x80000000);
+		}
+		mtdcr(DCRN_PEGPL_CFGMSK(PCIE1), 0xe0000001); /* 512MB region, valid */
+		break;
+
+	case 2:
+		if (ppc440spe_revB()) {
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000d);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0x40000000);
+		} else {
+			mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000c);
+			mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0xc0000000);
+		}
+		mtdcr(DCRN_PEGPL_CFGMSK(PCIE2), 0xe0000001); /* 512MB region, valid */
+		break;
+	}
+
+	/*
+	 * Check for VC0 active and assert RDY.
+	 */
+	attempts = 10;
+	switch (port) {
+	case 0:
+		while(!(SDR_READ(PESDR0_RCSSTS) & (1 << 16))) {
+			if (!(attempts--)) {
+				printf("PCIE0: VC0 not active\n");
+				return -1;
+			}
+			mdelay(1000);
+		}
+		SDR_WRITE(PESDR0_RCSSET, SDR_READ(PESDR0_RCSSET) | 1 << 20);
+		break;
+	case 1:
+		while(!(SDR_READ(PESDR1_RCSSTS) & (1 << 16))) {
+			if (!(attempts--)) {
+				printf("PCIE1: VC0 not active\n");
+				return -1;
+			}
+			mdelay(1000);
+		}
+
+		SDR_WRITE(PESDR1_RCSSET, SDR_READ(PESDR1_RCSSET) | 1 << 20);
+		break;
+	case 2:
+		while(!(SDR_READ(PESDR2_RCSSTS) & (1 << 16))) {
+			if (!(attempts--)) {
+				printf("PCIE2: VC0 not active\n");
+				return -1;
+			}
+			mdelay(1000);
+		}
+
+		SDR_WRITE(PESDR2_RCSSET, SDR_READ(PESDR2_RCSSET) | 1 << 20);
+		break;
+	}
+	mdelay(100);
+
+	return 0;
+}
+
+int ppc440spe_init_pcie_endport(int port)
+{
+	static int core_init;
+	volatile u32 val = 0;
+	int attempts;
+
+	if (!core_init) {
+		++core_init;
+		if (ppc440spe_init_pcie())
+			return -1;
+	}
+
+	/*
+	 * Initialize various parts of the PCI Express core for our port:
+	 *
+	 * - Set as a end port and enable max width
+	 *   (PXIE0 -> X8, PCIE1 and PCIE2 -> X4).
+	 * - Set up UTL configuration.
+	 * - Increase SERDES drive strength to levels suggested by AMCC.
+	 * - De-assert RSTPYN, RSTDL and RSTGU.
+	 *
+	 * NOTICE for revB chip: PESDRn_UTLSET2 is not set - we leave it with
+	 * default setting 0x11310000. The register has new fields,
+	 * PESDRn_UTLSET2[LKINE] in particular: clearing it leads to PCIE core
+	 * hang.
+	 */
+	switch (port) {
+	case 0:
+		SDR_WRITE(PESDR0_DLPSET,  1 << 24 | PTYPE_LEGACY_ENDPOINT << 20 | LNKW_X8 << 12);
+
+		SDR_WRITE(PESDR0_UTLSET1, 0x20222222);
+		if (!ppc440spe_revB())
+			SDR_WRITE(PESDR0_UTLSET2, 0x11000000);
+		SDR_WRITE(PESDR0_HSSL0SET1, 0x35000000);
+		SDR_WRITE(PESDR0_HSSL1SET1, 0x35000000);
+		SDR_WRITE(PESDR0_HSSL2SET1, 0x35000000);
+		SDR_WRITE(PESDR0_HSSL3SET1, 0x35000000);
+		SDR_WRITE(PESDR0_HSSL4SET1, 0x35000000);
+		SDR_WRITE(PESDR0_HSSL5SET1, 0x35000000);
+		SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000);
+		SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000);
+		SDR_WRITE(PESDR0_RCSSET,
+			(SDR_READ(PESDR0_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
+		break;
+
+	case 1:
+		SDR_WRITE(PESDR1_DLPSET, 1 << 24 | PTYPE_LEGACY_ENDPOINT << 20 | LNKW_X4 << 12);
+		SDR_WRITE(PESDR1_UTLSET1, 0x20222222);
+		if (!ppc440spe_revB())
+			SDR_WRITE(PESDR1_UTLSET2, 0x11000000);
+		SDR_WRITE(PESDR1_HSSL0SET1, 0x35000000);
+		SDR_WRITE(PESDR1_HSSL1SET1, 0x35000000);
+		SDR_WRITE(PESDR1_HSSL2SET1, 0x35000000);
+		SDR_WRITE(PESDR1_HSSL3SET1, 0x35000000);
+		SDR_WRITE(PESDR1_RCSSET,
+			(SDR_READ(PESDR1_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
+		break;
+
+	case 2:
+		SDR_WRITE(PESDR2_DLPSET, 1 << 24 | PTYPE_LEGACY_ENDPOINT << 20 | LNKW_X4 << 12);
+		SDR_WRITE(PESDR2_UTLSET1, 0x20222222);
+		if (!ppc440spe_revB())
+			SDR_WRITE(PESDR2_UTLSET2, 0x11000000);
+		SDR_WRITE(PESDR2_HSSL0SET1, 0x35000000);
+		SDR_WRITE(PESDR2_HSSL1SET1, 0x35000000);
+		SDR_WRITE(PESDR2_HSSL2SET1, 0x35000000);
+		SDR_WRITE(PESDR2_HSSL3SET1, 0x35000000);
 		SDR_WRITE(PESDR2_RCSSET,
 		SDR_WRITE(PESDR2_RCSSET,
 			(SDR_READ(PESDR2_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
 			(SDR_READ(PESDR2_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
 		break;
 		break;
@@ -418,7 +671,6 @@ int ppc440spe_init_pcie_rootport(int port)
 	 *     PCIE1: 0xd_2000_0000
 	 *     PCIE1: 0xd_2000_0000
 	 *     PCIE2: 0xd_4000_0000
 	 *     PCIE2: 0xd_4000_0000
 	 */
 	 */
-
 	switch (port) {
 	switch (port) {
 	case 0:
 	case 0:
 		if (ppc440spe_revB()) {
 		if (ppc440spe_revB()) {
@@ -498,29 +750,33 @@ int ppc440spe_init_pcie_rootport(int port)
 	return 0;
 	return 0;
 }
 }
 
 
-void ppc440spe_setup_pcie(struct pci_controller *hose, int port)
+void ppc440spe_setup_pcie_rootpoint(struct pci_controller *hose, int port)
 {
 {
 	volatile void *mbase = NULL;
 	volatile void *mbase = NULL;
+	volatile void *rmbase = NULL;
 
 
 	pci_set_ops(hose,
 	pci_set_ops(hose,
-			pcie_read_config_byte,
-			pcie_read_config_word,
-			pcie_read_config_dword,
-			pcie_write_config_byte,
-			pcie_write_config_word,
-			pcie_write_config_dword);
-
-	switch(port) {
+		    pcie_read_config_byte,
+		    pcie_read_config_word,
+		    pcie_read_config_dword,
+		    pcie_write_config_byte,
+		    pcie_write_config_word,
+		    pcie_write_config_dword);
+
+	switch (port) {
 	case 0:
 	case 0:
 		mbase = (u32 *)CFG_PCIE0_XCFGBASE;
 		mbase = (u32 *)CFG_PCIE0_XCFGBASE;
+		rmbase = (u32 *)CFG_PCIE0_CFGBASE;
 		hose->cfg_data = (u8 *)CFG_PCIE0_CFGBASE;
 		hose->cfg_data = (u8 *)CFG_PCIE0_CFGBASE;
 		break;
 		break;
 	case 1:
 	case 1:
 		mbase = (u32 *)CFG_PCIE1_XCFGBASE;
 		mbase = (u32 *)CFG_PCIE1_XCFGBASE;
+		rmbase = (u32 *)CFG_PCIE1_CFGBASE;
 		hose->cfg_data = (u8 *)CFG_PCIE1_CFGBASE;
 		hose->cfg_data = (u8 *)CFG_PCIE1_CFGBASE;
 		break;
 		break;
 	case 2:
 	case 2:
 		mbase = (u32 *)CFG_PCIE2_XCFGBASE;
 		mbase = (u32 *)CFG_PCIE2_XCFGBASE;
+		rmbase = (u32 *)CFG_PCIE2_CFGBASE;
 		hose->cfg_data = (u8 *)CFG_PCIE2_CFGBASE;
 		hose->cfg_data = (u8 *)CFG_PCIE2_CFGBASE;
 		break;
 		break;
 	}
 	}
@@ -528,14 +784,9 @@ void ppc440spe_setup_pcie(struct pci_controller *hose, int port)
 	/*
 	/*
 	 * Set bus numbers on our root port
 	 * Set bus numbers on our root port
 	 */
 	 */
-	if (ppc440spe_revB()) {
-		out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0);
-		out_8((u8 *)mbase + PCI_SECONDARY_BUS, 1);
-		out_8((u8 *)mbase + PCI_SUBORDINATE_BUS, 1);
-	} else {
-		out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0);
-		out_8((u8 *)mbase + PCI_SECONDARY_BUS, 0);
-	}
+	out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0);
+	out_8((u8 *)mbase + PCI_SECONDARY_BUS, 1);
+	out_8((u8 *)mbase + PCI_SUBORDINATE_BUS, 1);
 
 
 	/*
 	/*
 	 * Set up outbound translation to hose->mem_space from PLB
 	 * Set up outbound translation to hose->mem_space from PLB
@@ -544,8 +795,7 @@ void ppc440spe_setup_pcie(struct pci_controller *hose, int port)
 	 * subregions and to enable the outbound translation.
 	 * subregions and to enable the outbound translation.
 	 */
 	 */
 	out_le32(mbase + PECFG_POM0LAH, 0x00000000);
 	out_le32(mbase + PECFG_POM0LAH, 0x00000000);
-	out_le32(mbase + PECFG_POM0LAL, (CFG_PCIE_MEMBASE +
-			port * CFG_PCIE_MEMSIZE));
+	out_le32(mbase + PECFG_POM0LAL, 0x00000000);
 
 
 	switch (port) {
 	switch (port) {
 	case 0:
 	case 0:
@@ -579,14 +829,134 @@ void ppc440spe_setup_pcie(struct pci_controller *hose, int port)
 	out_le32(mbase + PCI_BASE_ADDRESS_1, 0);
 	out_le32(mbase + PCI_BASE_ADDRESS_1, 0);
 	out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffc);
 	out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffc);
 	out_le32(mbase + PECFG_BAR0LMPA, 0);
 	out_le32(mbase + PECFG_BAR0LMPA, 0);
+
+	out_le32(mbase + PECFG_PIM01SAH, 0xffff0000);
+	out_le32(mbase + PECFG_PIM01SAL, 0x00000000);
 	out_le32(mbase + PECFG_PIM0LAL, 0);
 	out_le32(mbase + PECFG_PIM0LAL, 0);
 	out_le32(mbase + PECFG_PIM0LAH, 0);
 	out_le32(mbase + PECFG_PIM0LAH, 0);
+	out_le32(mbase + PECFG_PIM1LAL,  0x00000000);
+	out_le32(mbase + PECFG_PIM1LAH,  0x00000004);
+	out_le32(mbase + PECFG_PIMEN, 0x1);
+
+	/* Enable I/O, Mem, and Busmaster cycles */
+	out_le16((u16 *)(mbase + PCI_COMMAND),
+		 in_le16((u16 *)(mbase + PCI_COMMAND)) |
+		 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+	printf("PCIE:%d successfully set as rootpoint\n",port);
+}
+
+int ppc440spe_setup_pcie_endpoint(struct pci_controller *hose, int port)
+{
+	volatile void *mbase = NULL;
+	int attempts = 0;
+
+	pci_set_ops(hose,
+		    pcie_read_config_byte,
+		    pcie_read_config_word,
+		    pcie_read_config_dword,
+		    pcie_write_config_byte,
+		    pcie_write_config_word,
+		    pcie_write_config_dword);
+
+	switch (port) {
+	case 0:
+		mbase = (u32 *)CFG_PCIE0_XCFGBASE;
+		hose->cfg_data = (u8 *)CFG_PCIE0_CFGBASE;
+		break;
+	case 1:
+		mbase = (u32 *)CFG_PCIE1_XCFGBASE;
+		hose->cfg_data = (u8 *)CFG_PCIE1_CFGBASE;
+		break;
+	case 2:
+		mbase = (u32 *)CFG_PCIE2_XCFGBASE;
+		hose->cfg_data = (u8 *)CFG_PCIE2_CFGBASE;
+		break;
+	}
+
+	/*
+	 * Set up outbound translation to hose->mem_space from PLB
+	 * addresses at an offset of 0xd_0000_0000.  We set the low
+	 * bits of the mask to 11 to turn off splitting into 8
+	 * subregions and to enable the outbound translation.
+	 */
+	out_le32(mbase + PECFG_POM0LAH, 0x00001ff8);
+	out_le32(mbase + PECFG_POM0LAL, 0x00001000);
+
+	switch (port) {
+	case 0:
+		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0),  0x0000000d);
+		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0),  CFG_PCIE_MEMBASE +
+			port * CFG_PCIE_MEMSIZE);
+		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE0), 0x7fffffff);
+		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0),
+			~(CFG_PCIE_MEMSIZE - 1) | 3);
+		break;
+	case 1:
+		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1),  0x0000000d);
+		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1),  (CFG_PCIE_MEMBASE +
+			port * CFG_PCIE_MEMSIZE));
+		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff);
+		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1),
+			~(CFG_PCIE_MEMSIZE - 1) | 3);
+		break;
+	case 2:
+		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2),  0x0000000d);
+		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2),  (CFG_PCIE_MEMBASE +
+			port * CFG_PCIE_MEMSIZE));
+		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE2), 0x7fffffff);
+		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE2),
+			~(CFG_PCIE_MEMSIZE - 1) | 3);
+		break;
+	}
+
+	/* Set up 16GB inbound memory window at 0 */
+	out_le32(mbase + PCI_BASE_ADDRESS_0, 0);
+	out_le32(mbase + PCI_BASE_ADDRESS_1, 0);
+	out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffc);
+	out_le32(mbase + PECFG_BAR0LMPA, 0);
+	out_le32(mbase + PECFG_PIM0LAL, 0x00000000);
+	out_le32(mbase + PECFG_PIM0LAH, 0x00000004);	/* pointing to SRAM */
 	out_le32(mbase + PECFG_PIMEN, 0x1);
 	out_le32(mbase + PECFG_PIMEN, 0x1);
 
 
 	/* Enable I/O, Mem, and Busmaster cycles */
 	/* Enable I/O, Mem, and Busmaster cycles */
 	out_le16((u16 *)(mbase + PCI_COMMAND),
 	out_le16((u16 *)(mbase + PCI_COMMAND),
 		 in_le16((u16 *)(mbase + PCI_COMMAND)) |
 		 in_le16((u16 *)(mbase + PCI_COMMAND)) |
 		 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
 		 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+	out_le16(mbase + 0x200,0xcaad);			/* Setting vendor ID */
+	out_le16(mbase + 0x202,0xfeed);			/* Setting device ID */
+	attempts = 10;
+	switch (port) {
+	case 0:
+		while (!(SDR_READ(PESDR0_RCSSTS) & (1 << 8))) {
+			if (!(attempts--)) {
+				printf("PCIE0: BMEN is  not active\n");
+				return -1;
+			}
+			mdelay(1000);
+		}
+		break;
+	case 1:
+		while (!(SDR_READ(PESDR1_RCSSTS) & (1 << 8))) {
+			if (!(attempts--)) {
+				printf("PCIE1: BMEN is not active\n");
+				return -1;
+			}
+			mdelay(1000);
+		}
+		break;
+	case 2:
+		while (!(SDR_READ(PESDR2_RCSSTS) & (1 << 8))) {
+			if (!(attempts--)) {
+				printf("PCIE2: BMEN is  not active\n");
+				return -1;
+			}
+			mdelay(1000);
+		}
+		break;
+	}
+	printf("PCIE:%d successfully set as endpoint\n",port);
+
+	return 0;
 }
 }
 #endif /* CONFIG_PCI */
 #endif /* CONFIG_PCI */
 #endif /* CONFIG_440SPE */
 #endif /* CONFIG_440SPE */

+ 10 - 1
cpu/ppc4xx/440spe_pcie.h

@@ -139,9 +139,17 @@
  */
  */
 #define PECFG_BAR0LMPA		0x210
 #define PECFG_BAR0LMPA		0x210
 #define PECFG_BAR0HMPA		0x214
 #define PECFG_BAR0HMPA		0x214
+#define PECFG_BAR1MPA		0x218
+#define PECFG_BAR2MPA		0x220
+
 #define PECFG_PIMEN		0x33c
 #define PECFG_PIMEN		0x33c
 #define PECFG_PIM0LAL		0x340
 #define PECFG_PIM0LAL		0x340
 #define PECFG_PIM0LAH		0x344
 #define PECFG_PIM0LAH		0x344
+#define PECFG_PIM1LAL     	0x348
+#define PECFG_PIM1LAH     	0x34c
+#define PECFG_PIM01SAL		0x350
+#define PECFG_PIM01SAH		0x354
+
 #define PECFG_POM0LAL		0x380
 #define PECFG_POM0LAL		0x380
 #define PECFG_POM0LAH		0x384
 #define PECFG_POM0LAH		0x384
 
 
@@ -156,7 +164,8 @@
 int ppc440spe_init_pcie(void);
 int ppc440spe_init_pcie(void);
 int ppc440spe_init_pcie_rootport(int port);
 int ppc440spe_init_pcie_rootport(int port);
 void yucca_setup_pcie_fpga_rootpoint(int port);
 void yucca_setup_pcie_fpga_rootpoint(int port);
-void ppc440spe_setup_pcie(struct pci_controller *hose, int port);
+void ppc440spe_setup_pcie_rootpoint(struct pci_controller *hose, int port);
+int ppc440spe_setup_pcie_endpoint(struct pci_controller *hose, int port);
 int yucca_pcie_card_present(int port);
 int yucca_pcie_card_present(int port);
 int pcie_hose_scan(struct pci_controller *hose, int bus);
 int pcie_hose_scan(struct pci_controller *hose, int bus);
 #endif /* __440SPE_PCIE_H */
 #endif /* __440SPE_PCIE_H */