powerpc/fsl-pci: Add generic code to setup PCIe controllers
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>
diff --git a/arch/powerpc/include/asm/fsl_pci.h b/arch/powerpc/include/asm/fsl_pci.h
index 5cbe139..15ab50d 100644
--- a/arch/powerpc/include/asm/fsl_pci.h
+++ b/arch/powerpc/include/asm/fsl_pci.h
@@ -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 @@
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 @@
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 @@
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"
diff --git a/board/freescale/p1022ds/p1022ds.c b/board/freescale/p1022ds/p1022ds.c
index e3e8300..0ea0bdf 100644
--- a/board/freescale/p1022ds/p1022ds.c
+++ b/board/freescale/p1022ds/p1022ds.c
@@ -187,7 +187,7 @@
* 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 @@
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
diff --git a/drivers/pci/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c
index 71ab02b..d762336 100644
--- a/drivers/pci/fsl_pci_init.c
+++ b/drivers/pci/fsl_pci_init.c
@@ -18,6 +18,8 @@
*/
#include <common.h>
+#include <malloc.h>
+#include <asm/fsl_serdes.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -513,6 +515,152 @@
}
}
+#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>