Merge with /home/stefan/git/u-boot/bamboo-nand
[oweals/u-boot.git] / cpu / mpc85xx / pci.c
index 5732c29eb68be91377315d3129e748c3b4bfafbe..3c1a323aad2f625c6fa8f5b853de808de5e49953 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2004 Freescale Semiconductor.
  * Copyright (C) 2003 Motorola Inc.
  * Xianghua Xiao (x.xiao@motorola.com)
  *
 #include <asm/cpm_85xx.h>
 #include <pci.h>
 
+#if defined(CONFIG_OF_FLAT_TREE)
+#include <ft_build.h>
+#endif
+
 #if defined(CONFIG_PCI)
-/*
- * Initialize PCI Devices, report devices found.
- */
-#ifndef CONFIG_PCI_PNP
-static struct pci_config_table pci_mpc85xxads_config_table[] = {
-       { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_IDSEL_NUMBER, PCI_ANY_ID,
-         pci_cfgfunc_config_device, { PCI_ENET0_IOADDR,
-                                      PCI_ENET0_MEMADDR,
-                                      PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }},
-       { }
-};
+
+static struct pci_controller *pci_hose;
+
+void
+pci_mpc85xx_init(struct pci_controller *board_hose)
+{
+       u16 reg16;
+       u32 dev;
+
+       volatile immap_t    *immap = (immap_t *)CFG_CCSRBAR;
+       volatile ccsr_pcix_t *pcix = &immap->im_pcix;
+#ifdef CONFIG_MPC85XX_PCI2
+       volatile ccsr_pcix_t *pcix2 = &immap->im_pcix2;
+#endif
+       volatile ccsr_gur_t *gur = &immap->im_gur;
+       struct pci_controller * hose;
+
+       pci_hose = board_hose;
+
+       hose = &pci_hose[0];
+
+       hose->first_busno = 0;
+       hose->last_busno = 0xff;
+
+       pci_setup_indirect(hose,
+                          (CFG_IMMR+0x8000),
+                          (CFG_IMMR+0x8004));
+
+       /*
+        * Hose scan.
+        */
+       dev = PCI_BDF(hose->first_busno, 0, 0);
+       pci_hose_read_config_word (hose, dev, PCI_COMMAND, &reg16);
+       reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+       pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16);
+
+       /*
+        * Clear non-reserved bits in status register.
+        */
+       pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff);
+
+       if (!(gur->pordevsr & PORDEVSR_PCI)) {
+               /* PCI-X init */
+               if (CONFIG_SYS_CLK_FREQ < 66000000)
+                       printf("PCI-X will only work at 66 MHz\n");
+
+               reg16 = PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ
+                       | PCI_X_CMD_ERO | PCI_X_CMD_DPERR_E;
+               pci_hose_write_config_word(hose, dev, PCIX_COMMAND, reg16);
+       }
+
+       pcix->potar1   = (CFG_PCI1_MEM_BASE >> 12) & 0x000fffff;
+       pcix->potear1  = 0x00000000;
+       pcix->powbar1  = (CFG_PCI1_MEM_PHYS >> 12) & 0x000fffff;
+       pcix->powbear1 = 0x00000000;
+       pcix->powar1 = (POWAR_EN | POWAR_MEM_READ |
+                       POWAR_MEM_WRITE | (__ilog2(CFG_PCI1_MEM_SIZE) - 1));
+
+       pcix->potar2  = (CFG_PCI1_IO_BASE >> 12) & 0x000fffff;
+       pcix->potear2  = 0x00000000;
+       pcix->powbar2  = (CFG_PCI1_IO_PHYS >> 12) & 0x000fffff;
+       pcix->powbear2 = 0x00000000;
+       pcix->powar2 = (POWAR_EN | POWAR_IO_READ |
+                       POWAR_IO_WRITE | (__ilog2(CFG_PCI1_IO_SIZE) - 1));
+
+       pcix->pitar1 = 0x00000000;
+       pcix->piwbar1 = 0x00000000;
+       pcix->piwar1 = (PIWAR_EN | PIWAR_PF | PIWAR_LOCAL |
+                       PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP | PIWAR_MEM_2G);
+
+       pcix->powar3 = 0;
+       pcix->powar4 = 0;
+       pcix->piwar2 = 0;
+       pcix->piwar3 = 0;
+
+       pci_set_region(hose->regions + 0,
+                      CFG_PCI1_MEM_BASE,
+                      CFG_PCI1_MEM_PHYS,
+                      CFG_PCI1_MEM_SIZE,
+                      PCI_REGION_MEM);
+
+       pci_set_region(hose->regions + 1,
+                      CFG_PCI1_IO_BASE,
+                      CFG_PCI1_IO_PHYS,
+                      CFG_PCI1_IO_SIZE,
+                      PCI_REGION_IO);
+
+       hose->region_count = 2;
+
+       pci_register_hose(hose);
+
+#if defined(CONFIG_MPC8555CDS) || defined(CONFIG_MPC8541CDS)
+       /*
+        * This is a SW workaround for an apparent HW problem
+        * in the PCI controller on the MPC85555/41 CDS boards.
+        * The first config cycle must be to a valid, known
+        * device on the PCI bus in order to trick the PCI
+        * controller state machine into a known valid state.
+        * Without this, the first config cycle has the chance
+        * of hanging the controller permanently, just leaving
+        * it in a semi-working state, or leaving it working.
+        *
+        * Pick on the Tundra, Device 17, to get it right.
+        */
+       {
+               u8 header_type;
+
+               pci_hose_read_config_byte(hose,
+                                         PCI_BDF(0,17,0),
+                                         PCI_HEADER_TYPE,
+                                         &header_type);
+       }
 #endif
 
-struct pci_controller local_hose = {
-#ifndef CONFIG_PCI_PNP
-       config_table: pci_mpc85xxads_config_table,
+       hose->last_busno = pci_hose_scan(hose);
+
+#ifdef CONFIG_MPC85XX_PCI2
+       hose = &pci_hose[1];
+
+       hose->first_busno = pci_hose[0].last_busno + 1;
+       hose->last_busno = 0xff;
+
+       pci_setup_indirect(hose,
+                          (CFG_IMMR+0x9000),
+                          (CFG_IMMR+0x9004));
+
+       dev = PCI_BDF(hose->first_busno, 0, 0);
+       pci_hose_read_config_word (hose, dev, PCI_COMMAND, &reg16);
+       reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+       pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16);
+
+       /*
+        * Clear non-reserved bits in status register.
+        */
+       pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff);
+
+       pcix2->potar1   = (CFG_PCI2_MEM_BASE >> 12) & 0x000fffff;
+       pcix2->potear1  = 0x00000000;
+       pcix2->powbar1  = (CFG_PCI2_MEM_PHYS >> 12) & 0x000fffff;
+       pcix2->powbear1 = 0x00000000;
+       pcix2->powar1 = (POWAR_EN | POWAR_MEM_READ |
+                       POWAR_MEM_WRITE | (__ilog2(CFG_PCI2_MEM_SIZE) - 1));
+
+       pcix2->potar2  = (CFG_PCI2_IO_BASE >> 12) & 0x000fffff;
+       pcix2->potear2  = 0x00000000;
+       pcix2->powbar2  = (CFG_PCI2_IO_PHYS >> 12) & 0x000fffff;
+       pcix2->powbear2 = 0x00000000;
+       pcix2->powar2 = (POWAR_EN | POWAR_IO_READ |
+                       POWAR_IO_WRITE | (__ilog2(CFG_PCI2_IO_SIZE) - 1));
+
+       pcix2->pitar1 = 0x00000000;
+       pcix2->piwbar1 = 0x00000000;
+       pcix2->piwar1 = (PIWAR_EN | PIWAR_PF | PIWAR_LOCAL |
+                       PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP | PIWAR_MEM_2G);
+
+       pcix2->powar3 = 0;
+       pcix2->powar4 = 0;
+       pcix2->piwar2 = 0;
+       pcix2->piwar3 = 0;
+
+       pci_set_region(hose->regions + 0,
+                      CFG_PCI2_MEM_BASE,
+                      CFG_PCI2_MEM_PHYS,
+                      CFG_PCI2_MEM_SIZE,
+                      PCI_REGION_MEM);
+
+       pci_set_region(hose->regions + 1,
+                      CFG_PCI2_IO_BASE,
+                      CFG_PCI2_IO_PHYS,
+                      CFG_PCI2_IO_SIZE,
+                      PCI_REGION_IO);
+
+       hose->region_count = 2;
+
+       /*
+        * Hose scan.
+        */
+       pci_register_hose(hose);
+
+       hose->last_busno = pci_hose_scan(hose);
 #endif
-};
+}
 
-void pci_init_board(void)
+#ifdef CONFIG_OF_FLAT_TREE
+void
+ft_pci_setup(void *blob, bd_t *bd)
 {
-    struct pci_controller* hose = (struct pci_controller *)&local_hose;
-    volatile immap_t    *immap = (immap_t *)CFG_CCSRBAR;
-    volatile ccsr_pcix_t *pcix = &immap->im_pcix;
-
-    u16 reg16;
-
-    hose->first_busno = 0;
-    hose->last_busno = 0xff;
-
-    pci_set_region(hose->regions + 0,
-       CFG_PCI_MEM_BASE,
-       CFG_PCI_MEM_PHYS,
-       (CFG_PCI_MEM_SIZE/2),
-       PCI_REGION_MEM);
-
-    pci_set_region(hose->regions + 1,
-       (CFG_PCI_MEM_BASE+0x08000000),
-       (CFG_PCI_MEM_PHYS+0x08000000),
-       0x1000000, /* 16M */
-       PCI_REGION_IO);
-
-    hose->region_count = 2;
-
-    pci_setup_indirect(hose,
-       (CFG_IMMR+0x8000),
-       (CFG_IMMR+0x8004));
-
-    pci_register_hose(hose);
-
-    hose->last_busno = pci_hose_scan(hose);
-
-    pci_read_config_word (PCI_BDF(0,0,0), PCI_COMMAND, &reg16);
-    reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
-    pci_write_config_word(PCI_BDF(0,0,0), PCI_COMMAND, reg16);
-
-    /* Clear non-reserved bits in status register */
-    pci_write_config_word(PCI_BDF(0,0,0), PCI_STATUS, 0xffff);
-    pci_write_config_byte(PCI_BDF(0,0,0), PCI_LATENCY_TIMER,0x80);
-
-    pcix->potar1   = (CFG_PCI_MEM_BASE >> 12) & 0x000fffff;
-    pcix->potear1  = 0x00000000;
-    pcix->powbar1  = (CFG_PCI_MEM_BASE >> 12) & 0x000fffff;
-    pcix->powbear1 = 0x00000000;
-    pcix->powar1   = 0x8004401a; /* 128M MEM space */
-    pcix->potar2   = ((CFG_PCI_MEM_BASE + 0x08000000) >> 12)  & 0x000fffff;
-    pcix->potear2  = 0x00000000;
-    pcix->powbar2  = ((CFG_PCI_MEM_BASE + 0x08000000) >> 12) && 0x000fffff;
-    pcix->powbear2 = 0x00000000;
-    pcix->powar2   = 0x80088017; /* 16M IO  space */
-    pcix->pitar1 = 0x00000000;
-    pcix->piwbar1 = 0x00000000;
-    pcix->piwar1 = 0xa0F5501f;
-
+       u32 *p;
+       int len;
+
+       p = (u32 *)ft_get_prop(blob, "/" OF_SOC "/pci@8000/bus-range", &len);
+       if (p != NULL) {
+               p[0] = pci_hose[0].first_busno;
+               p[1] = pci_hose[0].last_busno;
+       }
+
+#ifdef CONFIG_MPC85XX_PCI2
+       p = (u32 *)ft_get_prop(blob, "/" OF_SOC "/pci@9000/bus-range", &len);
+       if (p != NULL) {
+               p[0] = pci_hose[1].first_busno;
+               p[1] = pci_hose[1].last_busno;
+       }
+#endif
 }
+#endif /* CONFIG_OF_FLAT_TREE */
 #endif /* CONFIG_PCI */