ppc4xx: Consolidate 4xx PCIe board specific configuration

This patch consolidates the PPC4xx board specific PCIe configuration
code. This way the duplicated code is removed. Boards can implement a
special, non standard behaviour (e.g. number of PCIe slots, etc) by
overriding the weak default functions.

Signed-off-by: Stefan Roese <sr@denx.de>
diff --git a/cpu/ppc4xx/4xx_pcie.c b/cpu/ppc4xx/4xx_pcie.c
index 19d2c7d..c4d9cfe 100644
--- a/cpu/ppc4xx/4xx_pcie.c
+++ b/cpu/ppc4xx/4xx_pcie.c
@@ -48,6 +48,129 @@
 	LNKW_X8			= 0x8
 };
 
+#if 1 // test-only
+int board_pcie_first(void);
+int board_pcie_last(void);
+static struct pci_controller pcie_hose[CONFIG_SYS_PCIE_NR_PORTS];
+
+/*
+ * Per default, all cards are present, so we need to check if the
+ * link comes up.
+ */
+int __board_pcie_card_present(int port)
+{
+	return 1;
+}
+int board_pcie_card_present(int port)
+	__attribute__((weak, alias("__board_pcie_card_present")));
+
+/*
+ * Some boards have runtime detection of the first and last PCIe
+ * slot used, so let's provide weak default functions for the
+ * common version.
+ */
+int __board_pcie_first(void)
+{
+	return 0;
+}
+int board_pcie_first(void)
+	__attribute__((weak, alias("__board_pcie_first")));
+
+int __board_pcie_last(void)
+{
+	return CONFIG_SYS_PCIE_NR_PORTS - 1;
+}
+int board_pcie_last(void)
+	__attribute__((weak, alias("__board_pcie_last")));
+
+void __board_pcie_setup_port(int port, int rootpoint)
+{
+	/* noting in this weak default implementation */
+}
+void board_pcie_setup_port(int port, int rootpoint)
+	__attribute__((weak, alias("__board_pcie_setup_port")));
+
+void pcie_setup_hoses(int busno)
+{
+	struct pci_controller *hose;
+	int i, bus;
+	int ret = 0;
+	char *env;
+	unsigned int delay;
+	int first = board_pcie_first();
+	int last = board_pcie_last();
+
+	/*
+	 * Assume we're called after the PCI(X) hose(s) are initialized,
+	 * which takes bus ID 0... and therefore start numbering PCIe's
+	 * from the next number.
+	 */
+	bus = busno;
+
+	for (i = first; i <= last; i++) {
+		/*
+		 * Some boards (e.g. Katmai) can detects via hardware
+		 * if a PCIe card is plugged, so let's check this.
+		 */
+		if (!board_pcie_card_present(i))
+			continue;
+
+		if (is_end_point(i)) {
+			board_pcie_setup_port(i, 0);
+			ret = ppc4xx_init_pcie_endport(i);
+		} else {
+			board_pcie_setup_port(i, 1);
+			ret = ppc4xx_init_pcie_rootport(i);
+		}
+		if (ret == -ENODEV)
+			continue;
+		if (ret) {
+			printf("PCIE%d: initialization as %s failed\n", i,
+			       is_end_point(i) ? "endpoint" : "root-complex");
+			continue;
+		}
+
+		hose = &pcie_hose[i];
+		hose->first_busno = bus;
+		hose->last_busno = bus;
+		hose->current_busno = bus;
+
+		/* setup mem resource */
+		pci_set_region(hose->regions + 0,
+			       CONFIG_SYS_PCIE_MEMBASE + i * CONFIG_SYS_PCIE_MEMSIZE,
+			       CONFIG_SYS_PCIE_MEMBASE + i * CONFIG_SYS_PCIE_MEMSIZE,
+			       CONFIG_SYS_PCIE_MEMSIZE,
+			       PCI_REGION_MEM);
+		hose->region_count = 1;
+		pci_register_hose(hose);
+
+		if (is_end_point(i)) {
+			ppc4xx_setup_pcie_endpoint(hose, i);
+			/*
+			 * Reson for no scanning is endpoint can not generate
+			 * upstream configuration accesses.
+			 */
+		} else {
+			ppc4xx_setup_pcie_rootpoint(hose, i);
+			env = getenv ("pciscandelay");
+			if (env != NULL) {
+				delay = simple_strtoul(env, NULL, 10);
+				if (delay > 5)
+					printf("Warning, expect noticable delay before "
+					       "PCIe scan due to 'pciscandelay' value!\n");
+				mdelay(delay * 1000);
+			}
+
+			/*
+			 * Config access can only go down stream
+			 */
+			hose->last_busno = pci_hose_scan(hose);
+			bus = hose->last_busno + 1;
+		}
+	}
+}
+#endif
+
 static int validate_endpoint(struct pci_controller *hose)
 {
 	if (hose->cfg_data == (u8 *)CONFIG_SYS_PCIE0_CFGBASE)