TQM8548: PCI express support

This patch adds support for PCI express cards. The board support
now uses common FSL PCI init code, for both, PCI and PCIe on all
TQM85xx modules.

Signed-off-by: Thomas Waehner <thomas.waehner@tqs.de>
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
diff --git a/board/tqc/tqm85xx/law.c b/board/tqc/tqm85xx/law.c
index ad35464..bec1ed5 100644
--- a/board/tqc/tqm85xx/law.c
+++ b/board/tqc/tqm85xx/law.c
@@ -32,11 +32,11 @@
  *
  * 0x0000_0000	   0x7fff_ffff	   DDR			   2G
  * 0x8000_0000	   0x9fff_ffff	   PCI1 MEM		   512M
- * 0xc000_0000	   0xdfff_ffff	   RapidIO		   512M
+ * 0xc000_0000	   0xdfff_ffff	   RapidIO or PCI express  512M
  * 0xe000_0000	   0xe000_ffff	   CCSR			   1M
  * 0xe200_0000	   0xe2ff_ffff	   PCI1 IO		   16M
  * 0xe300_0000	   0xe3ff_ffff	   CAN			   16M
- * 0xf800_0000	   0xf80f_ffff	   BCSR			   1M
+ * 0xef00_0000	   0xefff_ffff     PCI express IO          16M
  * 0xfe00_0000	   0xffff_ffff	   FLASH (boot bank)	   32M
  *
  * Notes:
@@ -49,10 +49,17 @@
 	SET_LAW_ENTRY (2, CFG_PCI1_MEM_PHYS, LAW_SIZE_512M, LAW_TRGT_IF_PCI),
 	SET_LAW_ENTRY (3, CFG_LBC_FLASH_BASE, LAW_SIZE_128M, LAW_TRGT_IF_LBC),
 	SET_LAW_ENTRY (4, CFG_PCI1_IO_PHYS, LAW_SIZE_16M, LAW_TRGT_IF_PCI),
-	SET_LAW_ENTRY (5, CFG_RIO_MEM_BASE, LAWAR_SIZE_512M, LAW_TRGT_IF_RIO),
+#ifdef CONFIG_PCIE1
+	SET_LAW_ENTRY (5, CFG_PCIE1_MEM_BASE, LAW_SIZE_512M, LAW_TRGT_IF_PCIE_1),
+#else /* !CONFIG_PCIE1 */
+	SET_LAW_ENTRY (5, CFG_RIO_MEM_BASE, LAW_SIZE_512M, LAW_TRGT_IF_RIO),
+#endif /* CONFIG_PCIE1 */
 #ifdef CONFIG_CAN_DRIVER
-	SET_LAW_ENTRY (6, CFG_CAN_BASE, LAWAR_SIZE_16M, LAW_TRGT_IF_LBC),
+	SET_LAW_ENTRY (6, CFG_CAN_BASE, LAW_SIZE_16M, LAW_TRGT_IF_LBC),
 #endif /* CONFIG_CAN_DRIVER */
+#ifdef CONFIG_PCIE1
+	SET_LAW_ENTRY (7, CFG_PCIE1_IO_BASE, LAW_SIZE_16M, LAW_TRGT_IF_PCIE_1),
+#endif /* CONFIG_PCIE */
 };
 
 int num_law_entries = ARRAY_SIZE (law_table);
diff --git a/board/tqc/tqm85xx/tlb.c b/board/tqc/tqm85xx/tlb.c
index dc36201..7c4b9a1 100644
--- a/board/tqc/tqm85xx/tlb.c
+++ b/board/tqc/tqm85xx/tlb.c
@@ -74,6 +74,24 @@
 		       MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
 		       0, 3, BOOKE_PAGESZ_256M, 1),
 
+#ifdef CONFIG_PCIE1
+	/*
+	 * TLB 4:	256M	Non-cacheable, guarded
+	 * 0xc0000000	256M	PCI express MEM First half
+	 */
+	SET_TLB_ENTRY (1, CFG_PCIE1_MEM_BASE, CFG_PCIE1_MEM_BASE,
+		       MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
+		       0, 4, BOOKE_PAGESZ_256M, 1),
+
+	/*
+	 * TLB 5:	256M	Non-cacheable, guarded
+	 * 0xd0000000	256M	PCI express MEM Second half
+	 */
+	SET_TLB_ENTRY (1, CFG_PCIE1_MEM_BASE + 0x10000000,
+		       CFG_PCIE1_MEM_BASE + 0x10000000,
+		       MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
+		       0, 5, BOOKE_PAGESZ_256M, 1),
+#else /* !CONFIG_PCIE */
 	/*
 	 * TLB 4:	256M	Non-cacheable, guarded
 	 * 0xc0000000	256M	Rapid IO MEM First half
@@ -90,6 +108,7 @@
 		       CFG_RIO_MEM_BASE + 0x10000000,
 		       MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
 		       0, 5, BOOKE_PAGESZ_256M, 1),
+#endif /* CONFIG_PCIE */
 
 	/*
 	 * TLB 6:	 64M	Non-cacheable, guarded
@@ -116,6 +135,17 @@
 		       CFG_DDR_SDRAM_BASE + 0x10000000,
 		       MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
 		       0, 8, BOOKE_PAGESZ_256M, 1),
+
+#ifdef CONFIG_PCIE1
+	/*
+	 * TLB 9:	 16M	Non-cacheable, guarded
+	 * 0xef000000	 16M	PCI express IO
+	 */
+	SET_TLB_ENTRY (1, CFG_PCIE1_IO_BASE, CFG_PCIE1_IO_BASE,
+		       MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
+		       0, 9, BOOKE_PAGESZ_16M, 1),
+#endif /* CONFIG_PCIE */
+
 };
 
 int num_tlb_entries = ARRAY_SIZE (tlb_table);
diff --git a/board/tqc/tqm85xx/tqm85xx.c b/board/tqc/tqm85xx/tqm85xx.c
index f96cec3..f1c2e58 100644
--- a/board/tqc/tqm85xx/tqm85xx.c
+++ b/board/tqc/tqm85xx/tqm85xx.c
@@ -36,6 +36,7 @@
 #include <pci.h>
 #include <asm/processor.h>
 #include <asm/immap_85xx.h>
+#include <asm/immap_fsl_pci.h>
 #include <asm/io.h>
 #include <ioports.h>
 #include <flash.h>
@@ -257,13 +258,6 @@
 	}
 	putc ('\n');
 
-#ifdef CONFIG_PCI
-	printf ("PCI1:  32 bit, %d MHz (compiled)\n",
-		CONFIG_SYS_CLK_FREQ / 1000000);
-#else
-	printf ("PCI1:  disabled\n");
-#endif
-
 	/*
 	 * Initialize local bus.
 	 */
@@ -537,38 +531,180 @@
 #endif /* CONFIG_CAN_DRIVER */
 }
 
-#if defined(CONFIG_PCI)
 /*
  * Initialize PCI Devices, report devices found.
  */
+static int first_free_busno;
 
-#ifndef CONFIG_PCI_PNP
-static struct pci_config_table pci_mpc85xxads_config_table[] = {
-	{PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-	 PCI_IDSEL_NUMBER, PCI_ANY_ID,
-	 pci_cfgfunc_config_device, {PCI_ENET0_IOADDR,
-				     PCI_ENET0_MEMADDR,
-				     PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER}},
-	{}
-};
+#if defined(CONFIG_PCI) || defined(CONFIG_PCI1)
+static struct pci_controller pci1_hose;
+#endif /* CONFIG_PCI || CONFIG_PCI1 */
+
+#ifdef CONFIG_PCIE1
+static struct pci_controller pcie1_hose;
+#endif /* CONFIG_PCIE1 */
+
+static inline void init_pci1(void)
+{
+	volatile ccsr_gur_t *gur = (void *)(CFG_MPC85xx_GUTS_ADDR);
+#if defined(CONFIG_PCI) || defined(CONFIG_PCI1)
+	uint host_agent = (gur->porbmsr & MPC85xx_PORBMSR_HA) >> 16;
+	volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *)CFG_PCI1_ADDR;
+	extern void fsl_pci_init(struct pci_controller *hose);
+	struct pci_controller *hose = &pci1_hose;
+
+	/* PORDEVSR[15] */
+	uint pci_32 = gur->pordevsr & MPC85xx_PORDEVSR_PCI1_PCI32;
+	/* PORDEVSR[14] */
+	uint pci_arb = gur->pordevsr & MPC85xx_PORDEVSR_PCI1_ARB;
+	/* PORPLLSR[16] */
+	uint pci_clk_sel = gur->porpllsr & MPC85xx_PORDEVSR_PCI1_SPD;
+
+	uint pci_agent = (host_agent == 3) || (host_agent == 4 ) ||
+		(host_agent == 6);
+
+	uint pci_speed = CONFIG_SYS_CLK_FREQ;	/* PCI PSPEED in [4:5] */
+
+	if (!(gur->devdisr & MPC85xx_DEVDISR_PCI1)) {
+		printf ("PCI1:  %d bit, %s MHz, %s, %s, %s\n",
+			(pci_32) ? 32 : 64,
+			(pci_speed == 33333333) ? "33" :
+			(pci_speed == 66666666) ? "66" : "unknown",
+			pci_clk_sel ? "sync" : "async",
+			pci_agent ? "agent" : "host",
+			pci_arb ? "arbiter" : "external-arbiter");
+
+
+		/* inbound */
+		pci_set_region (hose->regions + 0,
+				CFG_PCI_MEMORY_BUS,
+				CFG_PCI_MEMORY_PHYS,
+				CFG_PCI_MEMORY_SIZE,
+				PCI_REGION_MEM | PCI_REGION_MEMORY);
+
+
+		/* outbound memory */
+		pci_set_region (hose->regions + 1,
+				CFG_PCI1_MEM_BASE,
+				CFG_PCI1_MEM_PHYS,
+				CFG_PCI1_MEM_SIZE,
+				PCI_REGION_MEM);
+
+		/* outbound io */
+		pci_set_region (hose->regions + 2,
+				CFG_PCI1_IO_BASE,
+				CFG_PCI1_IO_PHYS,
+				CFG_PCI1_IO_SIZE,
+				PCI_REGION_IO);
+
+		hose->region_count = 3;
+
+		hose->first_busno = first_free_busno;
+		pci_setup_indirect (hose, (int)&pci->cfg_addr,
+				    (int)&pci->cfg_data);
+
+		fsl_pci_init (hose);
+
+		printf ("       PCI on bus %02x..%02x\n",
+			hose->first_busno, hose->last_busno);
+
+		first_free_busno = hose->last_busno + 1;
+#ifdef CONFIG_PCIX_CHECK
+		if (!(gur->pordevsr & PORDEVSR_PCI)) {
+			ushort reg16 =
+				PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ |
+				PCI_X_CMD_ERO | PCI_X_CMD_DPERR_E;
+			uint dev = PCI_BDF(hose->first_busno, 0, 0);
+
+			/* PCI-X init */
+			if (CONFIG_SYS_CLK_FREQ < 66000000)
+				puts ("PCI-X will only work at 66 MHz\n");
+
+			pci_hose_write_config_word (hose, dev, PCIX_COMMAND,
+						    reg16);
+		}
 #endif
+	} else {
+		puts ("PCI1:  disabled\n");
+	}
+#else /* !(CONFIG_PCI || CONFIG_PCI1) */
+	gur->devdisr |= MPC85xx_DEVDISR_PCI1; /* disable */
+#endif /* CONFIG_PCI || CONFIG_PCI1) */
+}
 
-static struct pci_controller hose = {
-#ifndef CONFIG_PCI_PNP
-      config_table:pci_mpc85xxads_config_table,
-#endif
-};
+static inline void init_pcie1(void)
+{
+	volatile ccsr_gur_t *gur = (void *)(CFG_MPC85xx_GUTS_ADDR);
+#ifdef CONFIG_PCIE1
+	uint io_sel = (gur->pordevsr & MPC85xx_PORDEVSR_IO_SEL) >> 19;
+	uint host_agent = (gur->porbmsr & MPC85xx_PORBMSR_HA) >> 16;
+	volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *)CFG_PCIE1_ADDR;
+	extern void fsl_pci_init(struct pci_controller *hose);
+	struct pci_controller *hose = &pcie1_hose;
+	int pcie_ep =  (host_agent == 0) || (host_agent == 2 ) ||
+		(host_agent == 3);
 
-#endif /* CONFIG_PCI */
+	int pcie_configured  = io_sel >= 1;
+
+	if (pcie_configured && !(gur->devdisr & MPC85xx_DEVDISR_PCIE)){
+		printf ("PCIe:  %s, base address %x",
+			pcie_ep ? "End point" : "Root complex", (uint)pci);
+
+		if (pci->pme_msg_det) {
+			pci->pme_msg_det = 0xffffffff;
+			debug (", with errors. Clearing. Now 0x%08x",
+			       pci->pme_msg_det);
+		}
+		puts ("\n");
+
+		/* inbound */
+		pci_set_region (hose->regions + 0,
+				CFG_PCI_MEMORY_BUS,
+				CFG_PCI_MEMORY_PHYS,
+				CFG_PCI_MEMORY_SIZE,
+				PCI_REGION_MEM | PCI_REGION_MEMORY);
+
+		/* outbound memory */
+		pci_set_region (hose->regions + 1,
+				CFG_PCIE1_MEM_BASE,
+				CFG_PCIE1_MEM_PHYS,
+				CFG_PCIE1_MEM_SIZE,
+				PCI_REGION_MEM);
+
+		/* outbound io */
+		pci_set_region (hose->regions + 2,
+				CFG_PCIE1_IO_BASE,
+				CFG_PCIE1_IO_PHYS,
+				CFG_PCIE1_IO_SIZE,
+				PCI_REGION_IO);
+
+		hose->region_count = 3;
+
+		hose->first_busno = first_free_busno;
+		pci_setup_indirect(hose, (int)&pci->cfg_addr,
+				   (int)&pci->cfg_data);
+
+		fsl_pci_init (hose);
+		printf ("       PCIe on bus %02x..%02x\n",
+			hose->first_busno, hose->last_busno);
+
+		first_free_busno = hose->last_busno + 1;
+
+	} else {
+		printf ("PCIe:  disabled\n");
+	}
+#else /* !CONFIG_PCIE1 */
+	gur->devdisr |= MPC85xx_DEVDISR_PCIE; /* disable */
+#endif /* CONFIG_PCIE1 */
+}
 
 void pci_init_board (void)
 {
-#ifdef CONFIG_PCI
-	pci_mpc85xx_init (&hose);
-#endif /* CONFIG_PCI */
+	init_pci1();
+	init_pcie1();
 }
 
-#if defined(CONFIG_OF_BOARD_SETUP)
+#ifdef CONFIG_OF_BOARD_SETUP
 void ft_board_setup (void *blob, bd_t *bd)
 {
 	int node, tmp[2];
@@ -579,16 +715,23 @@
 	node = fdt_path_offset (blob, "/aliases");
 	tmp[0] = 0;
 	if (node >= 0) {
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) || defined(CONFIG_PCI1)
 		path = fdt_getprop (blob, node, "pci0", NULL);
 		if (path) {
-			tmp[1] = hose.last_busno - hose.first_busno;
+			tmp[1] = pci1_hose.last_busno - pci1_hose.first_busno;
 			do_fixup_by_path (blob, path, "bus-range", &tmp, 8, 1);
 		}
-#endif
+#endif /* CONFIG_PCI || CONFIG_PCI1 */
+#ifdef CONFIG_PCIE1
+		path = fdt_getprop (blob, node, "pci1", NULL);
+		if (path) {
+			tmp[1] = pcie1_hose.last_busno - pcie1_hose.first_busno;
+			do_fixup_by_path (blob, path, "bus-range", &tmp, 8, 1);
+		}
+#endif /* CONFIG_PCIE1 */
 	}
 }
-#endif
+#endif /* CONFIG_OF_BOARD_SETUP */
 
 #ifdef CONFIG_BOARD_EARLY_INIT_R
 int board_early_init_r (void)