Merge with /home/stefan/git/u-boot/bamboo-nand
[oweals/u-boot.git] / cpu / mpc85xx / pci.c
index 11f0c3e450250091ca20155ea00fa182ce94d3aa..3c1a323aad2f625c6fa8f5b853de808de5e49953 100644 (file)
 #include <asm/cpm_85xx.h>
 #include <pci.h>
 
+#if defined(CONFIG_OF_FLAT_TREE)
+#include <ft_build.h>
+#endif
 
 #if defined(CONFIG_PCI)
 
+static struct pci_controller *pci_hose;
 
-/*
- * 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}},
-       {}
-};
-#endif
+void
+pci_mpc85xx_init(struct pci_controller *board_hose)
+{
+       u16 reg16;
+       u32 dev;
 
-struct pci_controller local_hose = {
-#ifndef CONFIG_PCI_PNP
-       config_table: pci_mpc85xxads_config_table,
+       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;
 
-void pci_init_board (void)
-{
-       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;
+       pci_hose = board_hose;
 
-       u16 reg16;
+       hose = &pci_hose[0];
 
        hose->first_busno = 0;
        hose->last_busno = 0xff;
 
-       pci_set_region (hose->regions + 0,
-                       CFG_PCI1_MEM_BASE,
-                       CFG_PCI1_MEM_PHYS, CFG_PCI1_MEM_SIZE, PCI_REGION_MEM);
+       pci_setup_indirect(hose,
+                          (CFG_IMMR+0x8000),
+                          (CFG_IMMR+0x8004));
 
-       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_setup_indirect (hose, (CFG_IMMR + 0x8000), (CFG_IMMR + 0x8004));
-
-       pci_read_config_word (PCI_BDF (0, 0, 0), PCI_COMMAND, &reg16);
+       /*
+        * 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_write_config_word (PCI_BDF (0, 0, 0), PCI_COMMAND, reg16);
+       pci_hose_write_config_word(hose, dev, 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);
+       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_BASE >> 12) & 0x000fffff;
+       pcix->potar1   = (CFG_PCI1_MEM_BASE >> 12) & 0x000fffff;
+       pcix->potear1  = 0x00000000;
+       pcix->powbar1  = (CFG_PCI1_MEM_PHYS >> 12) & 0x000fffff;
        pcix->powbear1 = 0x00000000;
-       pcix->powar1 = 0x8004401c;      /* 512M MEM space */
+       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_BASE >> 12) & 0x000fffff;
+       pcix->potar2  = (CFG_PCI1_IO_BASE >> 12) & 0x000fffff;
+       pcix->potear2  = 0x00000000;
+       pcix->powbar2  = (CFG_PCI1_IO_PHYS >> 12) & 0x000fffff;
        pcix->powbear2 = 0x00000000;
-       pcix->powar2 = 0x80088017;      /* 16M IO space */
+       pcix->powar2 = (POWAR_EN | POWAR_IO_READ |
+                       POWAR_IO_WRITE | (__ilog2(CFG_PCI1_IO_SIZE) - 1));
 
        pcix->pitar1 = 0x00000000;
        pcix->piwbar1 = 0x00000000;
-       pcix->piwar1 = 0xa0F5501f;
+       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
+
+       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);
+       pci_register_hose(hose);
+
+       hose->last_busno = pci_hose_scan(hose);
+#endif
 }
 
+#ifdef CONFIG_OF_FLAT_TREE
+void
+ft_pci_setup(void *blob, bd_t *bd)
+{
+       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 */