mpc83xx: Add PCI-E support for MPC837XEMDS boards
authorAnton Vorontsov <avorontsov@ru.mvista.com>
Thu, 8 Jan 2009 01:26:19 +0000 (04:26 +0300)
committerKim Phillips <kim.phillips@freescale.com>
Thu, 22 Jan 2009 00:43:50 +0000 (18:43 -0600)
MPC837XEMDS boards can support PCI-E via "PCI-E riser card". The card
provides two PCI-E (x2) ports. Though, only one port can be used in x2
mode. Two ports can function simultaneously in x1 mode.

PCI-E x1/x2 modes can be switched via "pex_x2" environment variable.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
board/freescale/mpc837xemds/mpc837xemds.c
board/freescale/mpc837xemds/pci.c
board/freescale/mpc837xemds/pci.h [new file with mode: 0644]
include/configs/MPC837XEMDS.h

index acf8ada7b2e6c5b3b79704df7a361620a404e638..156d8089a11bf9da9651504747f8a46bf4297ef0 100644 (file)
@@ -18,6 +18,7 @@
 #include <tsec.h>
 #include <libfdt.h>
 #include <fdt_support.h>
+#include "pci.h"
 #include "../common/pq-mds-pib.h"
 
 int board_early_init_f(void)
@@ -38,14 +39,10 @@ int board_early_init_f(void)
        case SPR_8377:
                fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_SATA,
                                 FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V);
-               fsl_setup_serdes(CONFIG_FSL_SERDES2, FSL_SERDES_PROTO_PEX,
-                                FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V);
                break;
        case SPR_8378:
                fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_SGMII,
                                 FSL_SERDES_CLK_125, FSL_SERDES_VDD_1V);
-               fsl_setup_serdes(CONFIG_FSL_SERDES2, FSL_SERDES_PROTO_PEX,
-                                FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V);
                break;
        case SPR_8379:
                fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_SATA,
@@ -316,6 +313,7 @@ void ft_board_setup(void *blob, bd_t *bd)
        ft_pci_setup(blob, bd);
        if (board_pci_host_broken())
                ft_pci_fixup(blob, bd);
+       ft_pcie_fixup(blob, bd);
 #endif
 }
 #endif /* CONFIG_OF_BOARD_SETUP */
index df4e748e971070a3e5fc600e2c9efa84251a1c2f..31116b31ce5d09313d3a7640f9d27c2fd923d3d8 100644 (file)
@@ -16,7 +16,9 @@
 #include <mpc83xx.h>
 #include <pci.h>
 #include <i2c.h>
+#include <fdt_support.h>
 #include <asm/fsl_i2c.h>
+#include <asm/fsl_serdes.h>
 
 #if defined(CONFIG_PCI)
 static struct pci_region pci_regions[] = {
@@ -40,15 +42,59 @@ static struct pci_region pci_regions[] = {
        }
 };
 
+static struct pci_region pcie_regions_0[] = {
+       {
+               .bus_start = CONFIG_SYS_PCIE1_MEM_BASE,
+               .phys_start = CONFIG_SYS_PCIE1_MEM_PHYS,
+               .size = CONFIG_SYS_PCIE1_MEM_SIZE,
+               .flags = PCI_REGION_MEM,
+       },
+       {
+               .bus_start = CONFIG_SYS_PCIE1_IO_BASE,
+               .phys_start = CONFIG_SYS_PCIE1_IO_PHYS,
+               .size = CONFIG_SYS_PCIE1_IO_SIZE,
+               .flags = PCI_REGION_IO,
+       },
+};
+
+static struct pci_region pcie_regions_1[] = {
+       {
+               .bus_start = CONFIG_SYS_PCIE2_MEM_BASE,
+               .phys_start = CONFIG_SYS_PCIE2_MEM_PHYS,
+               .size = CONFIG_SYS_PCIE2_MEM_SIZE,
+               .flags = PCI_REGION_MEM,
+       },
+       {
+               .bus_start = CONFIG_SYS_PCIE2_IO_BASE,
+               .phys_start = CONFIG_SYS_PCIE2_IO_PHYS,
+               .size = CONFIG_SYS_PCIE2_IO_SIZE,
+               .flags = PCI_REGION_IO,
+       },
+};
+
+static int is_pex_x2(void)
+{
+       const char *pex_x2 = getenv("pex_x2");
+
+       if (pex_x2 && !strcmp(pex_x2, "yes"))
+               return 1;
+       return 0;
+}
+
 void pci_init_board(void)
 {
        volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR;
+       volatile sysconf83xx_t *sysconf = &immr->sysconf;
        volatile clk83xx_t *clk = (volatile clk83xx_t *)&immr->clk;
        volatile law83xx_t *pci_law = immr->sysconf.pcilaw;
+       volatile law83xx_t *pcie_law = sysconf->pcielaw;
        struct pci_region *reg[] = { pci_regions };
+       struct pci_region *pcie_reg[] = { pcie_regions_0, pcie_regions_1, };
+       u32 spridr = in_be32(&immr->sysconf.spridr);
+       int pex2 = is_pex_x2();
 
        if (board_pci_host_broken())
-               return;
+               goto skip_pci;
 
        /* Enable all 5 PCI_CLK_OUTPUTS */
        clk->occr |= 0xf8000000;
@@ -64,5 +110,46 @@ void pci_init_board(void)
        udelay(2000);
 
        mpc83xx_pci_init(1, reg, 0);
+skip_pci:
+       /* There is no PEX in MPC8379 parts. */
+       if (PARTID_NO_E(spridr) == SPR_8379)
+               return;
+
+       /* Configure the clock for PCIE controller */
+       clrsetbits_be32(&clk->sccr, SCCR_PCIEXP1CM | SCCR_PCIEXP2CM,
+                                   SCCR_PCIEXP1CM_1 | SCCR_PCIEXP2CM_1);
+
+       /* Deassert the resets in the control register */
+       out_be32(&sysconf->pecr1, 0xE0008000);
+       if (!pex2)
+               out_be32(&sysconf->pecr2, 0xE0008000);
+       udelay(2000);
+
+       /* Configure PCI Express Local Access Windows */
+       out_be32(&pcie_law[0].bar, CONFIG_SYS_PCIE1_BASE & LAWBAR_BAR);
+       out_be32(&pcie_law[0].ar, LBLAWAR_EN | LBLAWAR_512MB);
+
+       out_be32(&pcie_law[1].bar, CONFIG_SYS_PCIE2_BASE & LAWBAR_BAR);
+       out_be32(&pcie_law[1].ar, LBLAWAR_EN | LBLAWAR_512MB);
+
+       if (pex2)
+               fsl_setup_serdes(CONFIG_FSL_SERDES2, FSL_SERDES_PROTO_PEX_X2,
+                                FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V);
+       else
+               fsl_setup_serdes(CONFIG_FSL_SERDES2, FSL_SERDES_PROTO_PEX,
+                                FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V);
+
+       mpc83xx_pcie_init(pex2 ? 1 : 2, pcie_reg, 0);
+}
+
+void ft_pcie_fixup(void *blob, bd_t *bd)
+{
+       const char *status = "disabled (PCIE1 is x2)";
+
+       if (!is_pex_x2())
+               return;
+
+       do_fixup_by_path(blob, "pci2", "status", status,
+                        strlen(status) + 1, 1);
 }
 #endif /* CONFIG_PCI */
diff --git a/board/freescale/mpc837xemds/pci.h b/board/freescale/mpc837xemds/pci.h
new file mode 100644 (file)
index 0000000..fd7a916
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __BOARD_MPC837XEMDS_PCI_H
+#define __BOARD_MPC837XEMDS_PCI_H
+
+extern void ft_pcie_fixup(void *blob, bd_t *bd);
+
+#endif /* __BOARD_MPC837XEMDS_PCI_H */
index d49155fce09993762c3f6fff3190afb86d4d76d0..28d442bab1ac9c1177f434cfbf2f89fb04b4e9d5 100644 (file)
 #define CONFIG_SYS_PCI_SLV_MEM_BUS     0x00000000
 #define CONFIG_SYS_PCI_SLV_MEM_SIZE    0x80000000
 
+#define CONFIG_SYS_PCIE1_BASE          0xA0000000
+#define CONFIG_SYS_PCIE1_CFG_BASE      0xA0000000
+#define CONFIG_SYS_PCIE1_CFG_SIZE      0x08000000
+#define CONFIG_SYS_PCIE1_MEM_BASE      0xA8000000
+#define CONFIG_SYS_PCIE1_MEM_PHYS      0xA8000000
+#define CONFIG_SYS_PCIE1_MEM_SIZE      0x10000000
+#define CONFIG_SYS_PCIE1_IO_BASE       0x00000000
+#define CONFIG_SYS_PCIE1_IO_PHYS       0xB8000000
+#define CONFIG_SYS_PCIE1_IO_SIZE       0x00800000
+
+#define CONFIG_SYS_PCIE2_BASE          0xC0000000
+#define CONFIG_SYS_PCIE2_CFG_BASE      0xC0000000
+#define CONFIG_SYS_PCIE2_CFG_SIZE      0x08000000
+#define CONFIG_SYS_PCIE2_MEM_BASE      0xC8000000
+#define CONFIG_SYS_PCIE2_MEM_PHYS      0xC8000000
+#define CONFIG_SYS_PCIE2_MEM_SIZE      0x10000000
+#define CONFIG_SYS_PCIE2_IO_BASE       0x00000000
+#define CONFIG_SYS_PCIE2_IO_PHYS       0xD8000000
+#define CONFIG_SYS_PCIE2_IO_SIZE       0x00800000
+
 #ifdef CONFIG_PCI
 #ifndef __ASSEMBLY__
 extern int board_pci_host_broken(void);
 #endif
 #define CONFIG_83XX_GENERIC_PCI        1 /* Use generic PCI setup */
+#define CONFIG_83XX_GENERIC_PCIE       1
 #define CONFIG_PQ_MDS_PIB      1 /* PQ MDS Platform IO Board */
 
 #define CONFIG_HAS_FSL_DR_USB  1 /* fixup device tree for the DR USB */