powerpc/fsl-pci: Add generic code to setup PCIe controllers
authorKumar Gala <galak@kernel.crashing.org>
Wed, 15 Dec 2010 20:21:41 +0000 (14:21 -0600)
committerKumar Gala <galak@kernel.crashing.org>
Fri, 14 Jan 2011 07:32:19 +0000 (01:32 -0600)
Since all the PCIe controllers are connected over SERDES on the SoCs we
can utilize is_serdes_configured() to determine if a controller is
enabled.  After which we can setup the ATMUs and LAWs for the controller
in a common fashion and allow board code to specify what the controller
is connected to for reporting reasons.

We also provide a per controller (rather than all) for some systems that
may have special requirements.

Finally, we refactor the code used by the P1022DS to utilize the new
generic code.

Based on patch by: Li Yang <leoli@freescale.com>

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
arch/powerpc/include/asm/fsl_pci.h
board/freescale/p1022ds/p1022ds.c
drivers/pci/fsl_pci_init.c

index 5cbe139d55f8e56cb456efd668b4326f1b4ca706..15ab50d95793076df1473cec5b959d7dcc1ad4c1 100644 (file)
@@ -22,6 +22,8 @@
 #define __FSL_PCI_H_
 
 #include <asm/fsl_law.h>
+#include <asm/fsl_serdes.h>
+#include <pci.h>
 
 int fsl_setup_hose(struct pci_controller *hose, unsigned long addr);
 int fsl_is_pci_agent(struct pci_controller *hose);
@@ -172,6 +174,9 @@ struct fsl_pci_info {
 
 int fsl_pci_init_port(struct fsl_pci_info *pci_info,
                                struct pci_controller *hose, int busno);
+int fsl_pcie_init_ctrl(int busno, u32 devdisr, enum srds_prtcl dev,
+                       struct fsl_pci_info *pci_info);
+int fsl_pcie_init_board(int busno);
 
 #define SET_STD_PCI_INFO(x, num) \
 {                      \
@@ -220,6 +225,7 @@ int fsl_pci_init_port(struct fsl_pci_info *pci_info,
        FT_FSL_PCIE2_SETUP; \
        FT_FSL_PCIE3_SETUP; \
        FT_FSL_PCIE4_SETUP;
+#define FT_FSL_PCIE_SETUP FT_FSL_PCI_SETUP
 #elif defined(CONFIG_MPC85xx)
 #define FSL_PCI_COMPAT "fsl,mpc8540-pci"
 #define FSL_PCIE_COMPAT        "fsl,mpc8548-pcie"
@@ -229,6 +235,10 @@ int fsl_pci_init_port(struct fsl_pci_info *pci_info,
        FT_FSL_PCIE1_SETUP; \
        FT_FSL_PCIE2_SETUP; \
        FT_FSL_PCIE3_SETUP;
+#define FT_FSL_PCIE_SETUP \
+       FT_FSL_PCIE1_SETUP; \
+       FT_FSL_PCIE2_SETUP; \
+       FT_FSL_PCIE3_SETUP;
 #elif defined(CONFIG_MPC86xx)
 #define FSL_PCI_COMPAT "fsl,mpc8610-pci"
 #define FSL_PCIE_COMPAT        "fsl,mpc8641-pcie"
index e3e830066be646829f21a1d169dfab49dec2149b..0ea0bdf28e9e5977c95a4e36867678e61b6e2ea7 100644 (file)
@@ -187,7 +187,7 @@ static u8 serdes_dev_slot[][SATA2 + 1] = {
  * Returns the name of the slot to which the PCIe or SATA controller is
  * connected
  */
-const char *serdes_slot_name(enum srds_prtcl device)
+const char *board_serdes_name(enum srds_prtcl device)
 {
        ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
        u32 pordevsr = in_be32(&gur->pordevsr);
@@ -202,73 +202,10 @@ const char *serdes_slot_name(enum srds_prtcl device)
                return "Nothing";
 }
 
-static void configure_pcie(struct fsl_pci_info *info,
-                          struct pci_controller *hose,
-                          const char *connected)
-{
-       static int bus_number = 0;
-       int is_endpoint;
-
-       set_next_law(info->mem_phys, law_size_bits(info->mem_size), info->law);
-       set_next_law(info->io_phys, law_size_bits(info->io_size), info->law);
-       is_endpoint = fsl_setup_hose(hose, info->regs);
-       printf("PCIE%u: connected to %s as %s (base addr %lx)\n",
-              info->pci_num, connected,
-              is_endpoint ? "Endpoint" : "Root Complex", info->regs);
-       bus_number = fsl_pci_init_port(info, hose, bus_number);
-}
-
-#ifdef CONFIG_PCIE1
-static struct pci_controller pcie1_hose;
-#endif
-
-#ifdef CONFIG_PCIE2
-static struct pci_controller pcie2_hose;
-#endif
-
-#ifdef CONFIG_PCIE3
-static struct pci_controller pcie3_hose;
-#endif
-
 #ifdef CONFIG_PCI
 void pci_init_board(void)
 {
-       ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
-       struct fsl_pci_info pci_info;
-       u32 devdisr = in_be32(&gur->devdisr);
-
-#ifdef CONFIG_PCIE1
-       if (is_serdes_configured(PCIE1) && !(devdisr & MPC85xx_DEVDISR_PCIE)) {
-               SET_STD_PCIE_INFO(pci_info, 1);
-               configure_pcie(&pci_info, &pcie1_hose, serdes_slot_name(PCIE1));
-       } else {
-               printf("PCIE1: disabled\n");
-       }
-#else
-       setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_PCIE); /* disable */
-#endif
-
-#ifdef CONFIG_PCIE2
-       if (is_serdes_configured(PCIE2) && !(devdisr & MPC85xx_DEVDISR_PCIE2)) {
-               SET_STD_PCIE_INFO(pci_info, 2);
-               configure_pcie(&pci_info, &pcie2_hose, serdes_slot_name(PCIE2));
-       } else {
-               printf("PCIE2: disabled\n");
-       }
-#else
-       setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_PCIE2); /* disable */
-#endif
-
-#ifdef CONFIG_PCIE3
-       if (is_serdes_configured(PCIE3) && !(devdisr & MPC85xx_DEVDISR_PCIE3)) {
-               SET_STD_PCIE_INFO(pci_info, 3);
-               configure_pcie(&pci_info, &pcie3_hose, serdes_slot_name(PCIE3));
-       } else {
-               printf("PCIE3: disabled\n");
-       }
-#else
-       setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_PCIE3); /* disable */
-#endif
+       fsl_pcie_init_board(0);
 }
 #endif
 
index 71ab02b88d80c68fdfd8e8b96f0c2c9e493d1ce7..d7623369fea1e0032ba7063e3040fba1cd2df000 100644 (file)
@@ -18,6 +18,8 @@
  */
 
 #include <common.h>
+#include <malloc.h>
+#include <asm/fsl_serdes.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -513,6 +515,152 @@ void fsl_pci_config_unlock(struct pci_controller *hose)
        }
 }
 
+#if defined(CONFIG_PCIE1) || defined(CONFIG_PCIE2) || \
+    defined(CONFIG_PCIE3) || defined(CONFIG_PCIE4) 
+int fsl_configure_pcie(struct fsl_pci_info *info,
+                       struct pci_controller *hose,
+                       const char *connected, int busno)
+{
+       int is_endpoint;
+
+       set_next_law(info->mem_phys, law_size_bits(info->mem_size), info->law);
+       set_next_law(info->io_phys, law_size_bits(info->io_size), info->law);
+       is_endpoint = fsl_setup_hose(hose, info->regs);
+       printf("PCIE%u: connected to %s as %s (base addr %lx)\n",
+              info->pci_num, connected,
+              is_endpoint ? "Endpoint" : "Root Complex", info->regs);
+       return fsl_pci_init_port(info, hose, busno);
+}
+
+#if defined(CONFIG_FSL_CORENET)
+       #define _DEVDISR_PCIE1 FSL_CORENET_DEVDISR_PCIE1
+       #define _DEVDISR_PCIE2 FSL_CORENET_DEVDISR_PCIE2
+       #define _DEVDISR_PCIE3 FSL_CORENET_DEVDISR_PCIE3
+       #define _DEVDISR_PCIE4 FSL_CORENET_DEVDISR_PCIE4
+       #define CONFIG_SYS_MPC8xxx_GUTS_ADDR CONFIG_SYS_MPC85xx_GUTS_ADDR
+#elif defined(CONFIG_MPC85xx)
+       #define _DEVDISR_PCIE1 MPC85xx_DEVDISR_PCIE
+       #define _DEVDISR_PCIE2 MPC85xx_DEVDISR_PCIE2
+       #define _DEVDISR_PCIE3 MPC85xx_DEVDISR_PCIE3
+       #define _DEVDISR_PCIE4 0
+       #define CONFIG_SYS_MPC8xxx_GUTS_ADDR CONFIG_SYS_MPC85xx_GUTS_ADDR
+#elif defined(CONFIG_MPC86xx)
+       #define _DEVDISR_PCIE1 MPC86xx_DEVDISR_PCIE1
+       #define _DEVDISR_PCIE2 MPC86xx_DEVDISR_PCIE2
+       #define _DEVDISR_PCIE3 0
+       #define _DEVDISR_PCIE4 0
+       #define CONFIG_SYS_MPC8xxx_GUTS_ADDR \
+               (&((immap_t *)CONFIG_SYS_IMMR)->im_gur)
+#else
+#error "No defines for DEVDISR_PCIE"
+#endif
+
+/* Implement a dummy function for those platforms w/o SERDES */
+static const char *__board_serdes_name(enum srds_prtcl device)
+{
+       switch (device) {
+#ifdef CONFIG_SYS_PCIE1_NAME
+       case PCIE1:
+               return CONFIG_SYS_PCIE1_NAME;
+#endif
+#ifdef CONFIG_SYS_PCIE2_NAME
+       case PCIE2:
+               return CONFIG_SYS_PCIE2_NAME;
+#endif
+#ifdef CONFIG_SYS_PCIE3_NAME
+       case PCIE3:
+               return CONFIG_SYS_PCIE3_NAME;
+#endif
+#ifdef CONFIG_SYS_PCIE4_NAME
+       case PCIE4:
+               return CONFIG_SYS_PCIE4_NAME;
+#endif
+       default:
+               return NULL;
+       }
+
+       return NULL;
+}
+
+__attribute__((weak, alias("__board_serdes_name"))) const char *
+board_serdes_name(enum srds_prtcl device);
+
+static u32 devdisr_mask[] = {
+       _DEVDISR_PCIE1,
+       _DEVDISR_PCIE2,
+       _DEVDISR_PCIE3,
+       _DEVDISR_PCIE4,
+};
+
+int fsl_pcie_init_ctrl(int busno, u32 devdisr, enum srds_prtcl dev,
+                       struct fsl_pci_info *pci_info)
+{
+       struct pci_controller *hose;
+       int num = dev - PCIE1;
+
+       hose = calloc(1, sizeof(struct pci_controller));
+       if (!hose)
+               return busno;
+
+       if (is_serdes_configured(dev) && !(devdisr & devdisr_mask[num])) {
+               busno = fsl_configure_pcie(pci_info, hose,
+                               board_serdes_name(dev), busno);
+       } else {
+               printf("PCIE%d: disabled\n", num + 1);
+       }
+
+       return busno;
+}
+
+int fsl_pcie_init_board(int busno)
+{
+       struct fsl_pci_info pci_info;
+       ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC8xxx_GUTS_ADDR;
+       u32 devdisr = in_be32(&gur->devdisr);
+
+#ifdef CONFIG_PCIE1
+       SET_STD_PCIE_INFO(pci_info, 1);
+       busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE1, &pci_info);
+#else
+       setbits_be32(&gur->devdisr, _DEVDISR_PCIE1); /* disable */
+#endif
+
+#ifdef CONFIG_PCIE2
+       SET_STD_PCIE_INFO(pci_info, 2);
+       busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE2, &pci_info);
+#else
+       setbits_be32(&gur->devdisr, _DEVDISR_PCIE2); /* disable */
+#endif
+
+#ifdef CONFIG_PCIE3
+       SET_STD_PCIE_INFO(pci_info, 3);
+       busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE3, &pci_info);
+#else
+       setbits_be32(&gur->devdisr, _DEVDISR_PCIE3); /* disable */
+#endif
+
+#ifdef CONFIG_PCIE4
+       SET_STD_PCIE_INFO(pci_info, 4);
+       busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE4, &pci_info);
+#else
+       setbits_be32(&gur->devdisr, _DEVDISR_PCIE4); /* disable */
+#endif
+
+       return busno;
+}
+#else
+int fsl_pcie_init_ctrl(int busno, u32 devdisr, enum srds_prtcl dev,
+                       struct fsl_pci_info *pci_info)
+{
+       return busno;
+}
+
+int fsl_pcie_init_board(int busno)
+{
+       return busno;
+}
+#endif
+
 #ifdef CONFIG_OF_BOARD_SETUP
 #include <libfdt.h>
 #include <fdt_support.h>