+int fsl_is_pci_agent(struct pci_controller *hose)
+{
+ u8 pcie_cap;
+ pci_dev_t dev = PCI_BDF(hose->first_busno, 0, 0);
+
+ pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap);
+ if (pcie_cap == PCI_CAP_ID_EXP) {
+ u8 header_type;
+
+ pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE,
+ &header_type);
+ return (header_type & 0x7f) == PCI_HEADER_TYPE_NORMAL;
+ } else {
+ u8 prog_if;
+
+ pci_hose_read_config_byte(hose, dev, PCI_CLASS_PROG, &prog_if);
+ return (prog_if == FSL_PROG_IF_AGENT);
+ }
+}
+
+int fsl_pci_init_port(struct fsl_pci_info *pci_info,
+ struct pci_controller *hose, int busno)
+{
+ volatile ccsr_fsl_pci_t *pci;
+ struct pci_region *r;
+ pci_dev_t dev = PCI_BDF(busno,0,0);
+ u8 pcie_cap;
+
+ pci = (ccsr_fsl_pci_t *) pci_info->regs;
+
+ /* on non-PCIe controllers we don't have pme_msg_det so this code
+ * should do nothing since the read will return 0
+ */
+ if (in_be32(&pci->pme_msg_det)) {
+ out_be32(&pci->pme_msg_det, 0xffffffff);
+ debug (" with errors. Clearing. Now 0x%08x",
+ pci->pme_msg_det);
+ }
+
+ r = hose->regions + hose->region_count;
+
+ /* outbound memory */
+ pci_set_region(r++,
+ pci_info->mem_bus,
+ pci_info->mem_phys,
+ pci_info->mem_size,
+ PCI_REGION_MEM);
+
+ /* outbound io */
+ pci_set_region(r++,
+ pci_info->io_bus,
+ pci_info->io_phys,
+ pci_info->io_size,
+ PCI_REGION_IO);
+
+ hose->region_count = r - hose->regions;
+ hose->first_busno = busno;
+
+ fsl_pci_init(hose, pci_info);
+
+ if (fsl_is_pci_agent(hose)) {
+ fsl_pci_config_unlock(hose);
+ hose->last_busno = hose->first_busno;
+#ifdef CONFIG_SRIO_PCIE_BOOT_MASTER
+ } else {
+ /* boot from PCIE --master releases slave's core 0 */
+ char *s = getenv("bootmaster");
+ char pcie[6];
+ sprintf(pcie, "PCIE%d", pci_info->pci_num);
+
+ if (s && (strcmp(s, pcie) == 0))
+ fsl_pcie_boot_master_release_slave(pci_info->pci_num);
+#endif
+ }
+
+ pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap);
+ printf("PCI%s%x: Bus %02x - %02x\n", pcie_cap == PCI_CAP_ID_EXP ?
+ "e" : "", pci_info->pci_num,
+ hose->first_busno, hose->last_busno);
+
+ return(hose->last_busno + 1);
+}
+
+/* Enable inbound PCI config cycles for agent/endpoint interface */
+void fsl_pci_config_unlock(struct pci_controller *hose)
+{
+ pci_dev_t dev = PCI_BDF(hose->first_busno,0,0);
+ u8 pcie_cap;
+ u16 pbfr;
+
+ if (!fsl_is_pci_agent(hose))
+ return;
+
+ pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap);
+ if (pcie_cap != 0x0) {
+ /* PCIe - set CFG_READY bit of Configuration Ready Register */
+ pci_hose_write_config_byte(hose, dev, FSL_PCIE_CFG_RDY, 0x1);
+ } else {
+ /* PCI - clear ACL bit of PBFR */
+ pci_hose_read_config_word(hose, dev, FSL_PCI_PBFR, &pbfr);
+ pbfr &= ~0x20;
+ pci_hose_write_config_word(hose, dev, FSL_PCI_PBFR, pbfr);
+ }
+}
+
+#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: %s", info->pci_num,
+ is_endpoint ? "Endpoint" : "Root Complex");
+ if (connected)
+ printf(" of %s", connected);
+ puts(", ");
+
+ return fsl_pci_init_port(info, hose, busno);
+}
+
+#if defined(CONFIG_FSL_CORENET)
+#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
+ #define _DEVDISR_PCIE1 FSL_CORENET_DEVDISR3_PCIE1
+ #define _DEVDISR_PCIE2 FSL_CORENET_DEVDISR3_PCIE2
+ #define _DEVDISR_PCIE3 FSL_CORENET_DEVDISR3_PCIE3
+ #define _DEVDISR_PCIE4 FSL_CORENET_DEVDISR3_PCIE4
+#else
+ #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
+#endif
+ #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;
+ u32 *addr;
+
+#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
+ addr = &gur->devdisr3;
+#else
+ addr = &gur->devdisr;
+#endif
+ devdisr = in_be32(addr);
+
+#ifdef CONFIG_PCIE1
+ SET_STD_PCIE_INFO(pci_info, 1);
+ busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE1, &pci_info);
+#else
+ setbits_be32(addr, _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(addr, _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(addr, _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(addr, _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>
+
+void ft_fsl_pci_setup(void *blob, const char *pci_compat,
+ unsigned long ctrl_addr)
+{
+ int off;
+ u32 bus_range[2];
+ phys_addr_t p_ctrl_addr = (phys_addr_t)ctrl_addr;
+ struct pci_controller *hose;
+
+ hose = find_hose_by_cfg_addr((void *)(ctrl_addr));
+
+ /* convert ctrl_addr to true physical address */
+ p_ctrl_addr = (phys_addr_t)ctrl_addr - CONFIG_SYS_CCSRBAR;
+ p_ctrl_addr += CONFIG_SYS_CCSRBAR_PHYS;
+
+ off = fdt_node_offset_by_compat_reg(blob, pci_compat, p_ctrl_addr);
+
+ if (off < 0)
+ return;
+
+ /* We assume a cfg_addr not being set means we didn't setup the controller */
+ if ((hose == NULL) || (hose->cfg_addr == NULL)) {
+ fdt_del_node(blob, off);
+ } else {
+ bus_range[0] = 0;
+ bus_range[1] = hose->last_busno - hose->first_busno;
+ fdt_setprop(blob, off, "bus-range", &bus_range[0], 2*4);
+ fdt_pci_dma_ranges(blob, off, hose);
+ }
+}
+#endif