mpc83xx: Add support for MPC83xx PCI-E controllers

This patch adds support for MPC83xx PCI-E controllers in Root Complex
mode.

The patch is based on Tony Li and Dave Liu work[1].

Though unlike the original patch, by default we don't register PCI-E
buses for use in U-Boot, we only configure the controllers for future
use in other OSes (Linux). This is done because we don't have enough
of spare BATs to map all the PCI-E regions.

To actually use PCI-E in U-Boot, users should explicitly define
CONFIG_83XX_GENERIC_PCIE_REGISTER_HOSES symbol in the board file. And
only then U-Boot will able to access PCI-E, but at the cost of disabled
address translation.

[1] http://lists.denx.de/pipermail/u-boot/2008-January/027630.html

Signed-off-by: Tony Li <tony.li@freescale.com>
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Acked-by: Dave Liu <daveliu@freescale.com>
Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
diff --git a/include/asm-ppc/global_data.h b/include/asm-ppc/global_data.h
index 2bb50b4..e5a3b2c 100644
--- a/include/asm-ppc/global_data.h
+++ b/include/asm-ppc/global_data.h
@@ -75,7 +75,7 @@
 	u32 lbiu_clk;
 	u32 lclk_clk;
 	u32 pci_clk;
-#if defined(CONFIG_MPC837X)
+#if defined(CONFIG_MPC837X) || defined(CONFIG_MPC831X)
 	u32 pciexp1_clk;
 	u32 pciexp2_clk;
 #endif
diff --git a/include/asm-ppc/immap_83xx.h b/include/asm-ppc/immap_83xx.h
index df24a6e..77c09db 100644
--- a/include/asm-ppc/immap_83xx.h
+++ b/include/asm-ppc/immap_83xx.h
@@ -52,23 +52,28 @@
 	law83xx_t lblaw[4];	/* LBIU local access window */
 	u8 res2[0x20];
 	law83xx_t pcilaw[2];	/* PCI local access window */
-	u8 res3[0x30];
+	u8 res3[0x10];
+	law83xx_t pcielaw[2];	/* PCI Express local access window */
+	u8 res4[0x10];
 	law83xx_t ddrlaw[2];	/* DDR local access window */
-	u8 res4[0x50];
+	u8 res5[0x50];
 	u32 sgprl;		/* System General Purpose Register Low */
 	u32 sgprh;		/* System General Purpose Register High */
 	u32 spridr;		/* System Part and Revision ID Register */
-	u8 res5[0x04];
+	u8 res6[0x04];
 	u32 spcr;		/* System Priority Configuration Register */
 	u32 sicrl;		/* System I/O Configuration Register Low */
 	u32 sicrh;		/* System I/O Configuration Register High */
-	u8 res6[0x04];
+	u8 res7[0x04];
 	u32 sidcr0;		/* System I/O Delay Configuration Register 0 */
 	u32 sidcr1;		/* System I/O Delay Configuration Register 1 */
 	u32 ddrcdr;		/* DDR Control Driver Register */
 	u32 ddrdsr;		/* DDR Debug Status Register */
 	u32 obir;		/* Output Buffer Impedance Register */
-	u8 res7[0xCC];
+	u8 res8[0xC];
+	u32 pecr1;		/* PCI Express control register 1 */
+	u32 pecr2;		/* PCI Express control register 2 */
+	u8 res9[0xB8];
 } sysconf83xx_t;
 
 /*
@@ -503,8 +508,110 @@
 /*
  *  PCI Express
  */
+struct pex_inbound_window {
+	u32 ar;
+	u32 tar;
+	u32 barl;
+	u32 barh;
+};
+
+struct pex_outbound_window {
+	u32 ar;
+	u32 bar;
+	u32 tarl;
+	u32 tarh;
+};
+
+struct pex_csb_bridge {
+	u32 pex_csb_ver;
+	u32 pex_csb_cab;
+	u32 pex_csb_ctrl;
+	u8 res0[8];
+	u32 pex_dms_dstmr;
+	u8 res1[4];
+	u32 pex_cbs_stat;
+	u8 res2[0x20];
+	u32 pex_csb_obctrl;
+	u32 pex_csb_obstat;
+	u8 res3[0x98];
+	u32 pex_csb_ibctrl;
+	u32 pex_csb_ibstat;
+	u8 res4[0xb8];
+	u32 pex_wdma_ctrl;
+	u32 pex_wdma_addr;
+	u32 pex_wdma_stat;
+	u8 res5[0x94];
+	u32 pex_rdma_ctrl;
+	u32 pex_rdma_addr;
+	u32 pex_rdma_stat;
+	u8 res6[0xd4];
+	u32 pex_ombcr;
+	u32 pex_ombdr;
+	u8 res7[0x38];
+	u32 pex_imbcr;
+	u32 pex_imbdr;
+	u8 res8[0x38];
+	u32 pex_int_enb;
+	u32 pex_int_stat;
+	u32 pex_int_apio_vec1;
+	u32 pex_int_apio_vec2;
+	u8 res9[0x10];
+	u32 pex_int_ppio_vec1;
+	u32 pex_int_ppio_vec2;
+	u32 pex_int_wdma_vec1;
+	u32 pex_int_wdma_vec2;
+	u32 pex_int_rdma_vec1;
+	u32 pex_int_rdma_vec2;
+	u32 pex_int_misc_vec;
+	u8 res10[4];
+	u32 pex_int_axi_pio_enb;
+	u32 pex_int_axi_wdma_enb;
+	u32 pex_int_axi_rdma_enb;
+	u32 pex_int_axi_misc_enb;
+	u32 pex_int_axi_pio_stat;
+	u32 pex_int_axi_wdma_stat;
+	u32 pex_int_axi_rdma_stat;
+	u32 pex_int_axi_misc_stat;
+	u8 res11[0xa0];
+	struct pex_outbound_window pex_outbound_win[4];
+	u8 res12[0x100];
+	u32 pex_epiwtar0;
+	u32 pex_epiwtar1;
+	u32 pex_epiwtar2;
+	u32 pex_epiwtar3;
+	u8 res13[0x70];
+	struct pex_inbound_window pex_inbound_win[4];
+};
+
 typedef struct pex83xx {
-	u8 fixme[0x1000];
+	u8 pex_cfg_header[0x404];
+	u32 pex_ltssm_stat;
+	u8 res0[0x30];
+	u32 pex_ack_replay_timeout;
+	u8 res1[4];
+	u32 pex_gclk_ratio;
+	u8 res2[0xc];
+	u32 pex_pm_timer;
+	u32 pex_pme_timeout;
+	u8 res3[4];
+	u32 pex_aspm_req_timer;
+	u8 res4[0x18];
+	u32 pex_ssvid_update;
+	u8 res5[0x34];
+	u32 pex_cfg_ready;
+	u8 res6[0x24];
+	u32 pex_bar_sizel;
+	u8 res7[4];
+	u32 pex_bar_sel;
+	u8 res8[0x20];
+	u32 pex_bar_pf;
+	u8 res9[0x88];
+	u32 pex_pme_to_ack_tor;
+	u8 res10[0xc];
+	u32 pex_ss_intr_mask;
+	u8 res11[0x25c];
+	struct pex_csb_bridge bridge;
+	u8 res12[0x160];
 } pex83xx_t;
 
 /*
diff --git a/include/mpc83xx.h b/include/mpc83xx.h
index e5dfe3f..191488a 100644
--- a/include/mpc83xx.h
+++ b/include/mpc83xx.h
@@ -751,9 +751,6 @@
 #define SCCR_USBDRCM_2			0x00800000
 #define SCCR_USBDRCM_3			0x00c00000
 
-#define SCCR_PCIEXP1CM			0x00300000
-#define SCCR_PCIEXP2CM			0x000c0000
-
 #define SCCR_SATA1CM			0x00003000
 #define SCCR_SATA1CM_SHIFT		12
 #define SCCR_SATACM			0x00003c00
@@ -800,6 +797,17 @@
 #define SCCR_USBDRCM_2			0x00800000
 #define SCCR_USBDRCM_3			0x00c00000
 
+/* All of the four SATA controllers must have the same clock ratio */
+#define SCCR_SATA1CM			0x000000c0
+#define SCCR_SATA1CM_SHIFT		6
+#define SCCR_SATACM			0x000000ff
+#define SCCR_SATACM_SHIFT		0
+#define SCCR_SATACM_0			0x00000000
+#define SCCR_SATACM_1			0x00000055
+#define SCCR_SATACM_2			0x000000aa
+#define SCCR_SATACM_3			0x000000ff
+#endif
+
 #define SCCR_PCIEXP1CM			0x00300000
 #define SCCR_PCIEXP1CM_SHIFT		20
 #define SCCR_PCIEXP1CM_0		0x00000000
@@ -814,17 +822,6 @@
 #define SCCR_PCIEXP2CM_2		0x00080000
 #define SCCR_PCIEXP2CM_3		0x000c0000
 
-/* All of the four SATA controllers must have the same clock ratio */
-#define SCCR_SATA1CM			0x000000c0
-#define SCCR_SATA1CM_SHIFT		6
-#define SCCR_SATACM			0x000000ff
-#define SCCR_SATACM_SHIFT		0
-#define SCCR_SATACM_0			0x00000000
-#define SCCR_SATACM_1			0x00000055
-#define SCCR_SATACM_2			0x000000aa
-#define SCCR_SATACM_3			0x000000ff
-#endif
-
 /* CSn_BDNS - Chip Select memory Bounds Register
  */
 #define CSBNDS_SA			0x00FF0000
@@ -1170,10 +1167,52 @@
 #define DDRCDR_M_ODR		0x00000002
 #define DDRCDR_Q_DRN		0x00000001
 
+/* PCIE Bridge Register
+*/
+#define PEX_CSB_CTRL_OBPIOE	0x00000001
+#define PEX_CSB_CTRL_IBPIOE	0x00000002
+#define PEX_CSB_CTRL_WDMAE	0x00000004
+#define PEX_CSB_CTRL_RDMAE	0x00000008
+
+#define PEX_CSB_OBCTRL_PIOE	0x00000001
+#define PEX_CSB_OBCTRL_MEMWE	0x00000002
+#define PEX_CSB_OBCTRL_IOWE	0x00000004
+#define PEX_CSB_OBCTRL_CFGWE	0x00000008
+
+#define PEX_CSB_IBCTRL_PIOE	0x00000001
+
+#define PEX_OWAR_EN		0x00000001
+#define PEX_OWAR_TYPE_CFG	0x00000000
+#define PEX_OWAR_TYPE_IO	0x00000002
+#define PEX_OWAR_TYPE_MEM	0x00000004
+#define PEX_OWAR_RLXO		0x00000008
+#define PEX_OWAR_NANP		0x00000010
+#define PEX_OWAR_SIZE		0xFFFFF000
+
+#define PEX_IWAR_EN		0x00000001
+#define PEX_IWAR_TYPE_INT	0x00000000
+#define PEX_IWAR_TYPE_PF	0x00000004
+#define PEX_IWAR_TYPE_NO_PF	0x00000006
+#define PEX_IWAR_NSOV		0x00000008
+#define PEX_IWAR_NSNP		0x00000010
+#define PEX_IWAR_SIZE		0xFFFFF000
+#define PEX_IWAR_SIZE_1M	0x000FF000
+#define PEX_IWAR_SIZE_2M	0x001FF000
+#define PEX_IWAR_SIZE_4M	0x003FF000
+#define PEX_IWAR_SIZE_8M	0x007FF000
+#define PEX_IWAR_SIZE_16M	0x00FFF000
+#define PEX_IWAR_SIZE_32M	0x01FFF000
+#define PEX_IWAR_SIZE_64M	0x03FFF000
+#define PEX_IWAR_SIZE_128M	0x07FFF000
+#define PEX_IWAR_SIZE_256M	0x0FFFF000
+
+#define PEX_GCLK_RATIO		0x440
+
 #ifndef __ASSEMBLY__
 struct pci_region;
 void mpc83xx_pci_init(int num_buses, struct pci_region **reg, int warmboot);
 void mpc83xx_pcislave_unlock(int bus);
+void mpc83xx_pcie_init(int num_buses, struct pci_region **reg, int warmboot);
 #endif
 
 #endif	/* __MPC83XX_H__ */
diff --git a/include/pci.h b/include/pci.h
index eebe8a8..072273b 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -382,6 +382,8 @@
 
 #define MAX_PCI_REGIONS		7
 
+#define INDIRECT_TYPE_NO_PCIE_LINK	1
+
 /*
  * Structure of a PCI controller (host bridge)
  */
@@ -394,6 +396,8 @@
 	volatile unsigned int *cfg_addr;
 	volatile unsigned char *cfg_data;
 
+	int indirect_type;
+
 	struct pci_region regions[MAX_PCI_REGIONS];
 	int region_count;