Fix PCI-Express on PPC440SPe rev. A.
[oweals/u-boot.git] / cpu / ppc4xx / cpu_init.c
index ac34092d8b8d04d62779635756e1c73722ea598d..b27567fa4d14100e2ae07fe83ee3c394da06c29b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2000
+ * (C) Copyright 2000-2006
  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  *
  * See file CREDITS for list of people who contributed to this
 
 #include <common.h>
 #include <watchdog.h>
-#include <405gp_enet.h>
+#include <ppc4xx_enet.h>
 #include <asm/processor.h>
 #include <ppc4xx.h>
 
+#if defined(CONFIG_405GP)  || defined(CONFIG_405EP)
+DECLARE_GLOBAL_DATA_PTR;
+#endif
+
 
 #define mtebc(reg, data)  mtdcr(ebccfga,reg);mtdcr(ebccfgd,data)
 
+#ifdef CFG_INIT_DCACHE_CS
+# if (CFG_INIT_DCACHE_CS == 0)
+#  define PBxAP pb0ap
+#  define PBxCR pb0cr
+#  if (defined(CFG_EBC_PB0AP) && defined(CFG_EBC_PB0CR))
+#   define PBxAP_VAL CFG_EBC_PB0AP
+#   define PBxCR_VAL CFG_EBC_PB0CR
+#  endif
+# endif
+# if (CFG_INIT_DCACHE_CS == 1)
+#  define PBxAP pb1ap
+#  define PBxCR pb1cr
+#  if (defined(CFG_EBC_PB1AP) && defined(CFG_EBC_PB1CR))
+#   define PBxAP_VAL CFG_EBC_PB1AP
+#   define PBxCR_VAL CFG_EBC_PB1CR
+#  endif
+# endif
+# if (CFG_INIT_DCACHE_CS == 2)
+#  define PBxAP pb2ap
+#  define PBxCR pb2cr
+#  if (defined(CFG_EBC_PB2AP) && defined(CFG_EBC_PB2CR))
+#   define PBxAP_VAL CFG_EBC_PB2AP
+#   define PBxCR_VAL CFG_EBC_PB2CR
+#  endif
+# endif
+# if (CFG_INIT_DCACHE_CS == 3)
+#  define PBxAP pb3ap
+#  define PBxCR pb3cr
+#  if (defined(CFG_EBC_PB3AP) && defined(CFG_EBC_PB3CR))
+#   define PBxAP_VAL CFG_EBC_PB3AP
+#   define PBxCR_VAL CFG_EBC_PB3CR
+#  endif
+# endif
+# if (CFG_INIT_DCACHE_CS == 4)
+#  define PBxAP pb4ap
+#  define PBxCR pb4cr
+#  if (defined(CFG_EBC_PB4AP) && defined(CFG_EBC_PB4CR))
+#   define PBxAP_VAL CFG_EBC_PB4AP
+#   define PBxCR_VAL CFG_EBC_PB4CR
+#  endif
+# endif
+# if (CFG_INIT_DCACHE_CS == 5)
+#  define PBxAP pb5ap
+#  define PBxCR pb5cr
+#  if (defined(CFG_EBC_PB5AP) && defined(CFG_EBC_PB5CR))
+#   define PBxAP_VAL CFG_EBC_PB5AP
+#   define PBxCR_VAL CFG_EBC_PB5CR
+#  endif
+# endif
+# if (CFG_INIT_DCACHE_CS == 6)
+#  define PBxAP pb6ap
+#  define PBxCR pb6cr
+#  if (defined(CFG_EBC_PB6AP) && defined(CFG_EBC_PB6CR))
+#   define PBxAP_VAL CFG_EBC_PB6AP
+#   define PBxCR_VAL CFG_EBC_PB6CR
+#  endif
+# endif
+# if (CFG_INIT_DCACHE_CS == 7)
+#  define PBxAP pb7ap
+#  define PBxCR pb7cr
+#  if (defined(CFG_EBC_PB7AP) && defined(CFG_EBC_PB7CR))
+#   define PBxAP_VAL CFG_EBC_PB7AP
+#   define PBxCR_VAL CFG_EBC_PB7CR
+#  endif
+# endif
+#endif /* CFG_INIT_DCACHE_CS */
+
+#if defined(CFG_440_GPIO_TABLE)
+gpio_param_s gpio_tab[GPIO_GROUP_MAX][GPIO_MAX] = CFG_440_GPIO_TABLE;
+
+void set_chip_gpio_configuration(gpio_param_s (*gpio_tab)[GPIO_GROUP_MAX][GPIO_MAX])
+{
+       unsigned char i=0, j=0, reg_offset = 0, gpio_core;
+       unsigned long gpio_reg, gpio_core_add;
+
+       for (gpio_core=0; gpio_core<GPIO_GROUP_MAX; gpio_core++) {
+               j = 0;
+               reg_offset = 0;
+               /* GPIO config of the GPIOs 0 to 31 */
+               for (i=0; i<GPIO_MAX; i++, j++) {
+                       if (i == GPIO_MAX/2) {
+                               reg_offset = 4;
+                               j = i-16;
+                       }
+
+                       gpio_core_add = (*gpio_tab)[gpio_core][i].add;
+
+                       if (((*gpio_tab)[gpio_core][i].in_out == GPIO_IN) ||
+                            ((*gpio_tab)[gpio_core][i].in_out == GPIO_BI)) {
+
+                               switch ((*gpio_tab)[gpio_core][i].alt_nb) {
+                               case GPIO_SEL:
+                                       break;
+
+                               case GPIO_ALT1:
+                                       gpio_reg = in32(GPIO_IS1(gpio_core_add+reg_offset))
+                                               & ~(GPIO_MASK >> (j*2));
+                                       gpio_reg = gpio_reg | (GPIO_IN_SEL >> (j*2));
+                                       out32(GPIO_IS1(gpio_core_add+reg_offset), gpio_reg);
+                                       break;
+
+                               case GPIO_ALT2:
+                                       gpio_reg = in32(GPIO_IS2(gpio_core_add+reg_offset))
+                                               & ~(GPIO_MASK >> (j*2));
+                                       gpio_reg = gpio_reg | (GPIO_IN_SEL >> (j*2));
+                                       out32(GPIO_IS2(gpio_core_add+reg_offset), gpio_reg);
+                                       break;
+
+                               case GPIO_ALT3:
+                                       gpio_reg = in32(GPIO_IS3(gpio_core_add+reg_offset))
+                                               & ~(GPIO_MASK >> (j*2));
+                                       gpio_reg = gpio_reg | (GPIO_IN_SEL >> (j*2));
+                                       out32(GPIO_IS3(gpio_core_add+reg_offset), gpio_reg);
+                                       break;
+                               }
+                       }
+
+                       if (((*gpio_tab)[gpio_core][i].in_out == GPIO_OUT) ||
+                            ((*gpio_tab)[gpio_core][i].in_out == GPIO_BI)) {
+
+                               switch ((*gpio_tab)[gpio_core][i].alt_nb) {
+                               case GPIO_SEL:
+                                       if (gpio_core == GPIO0) {
+                                               gpio_reg = in32(GPIO0_TCR) | (0x80000000 >> (j));
+                                               out32(GPIO0_TCR, gpio_reg);
+                                       }
+
+                                       if (gpio_core == GPIO1) {
+                                               gpio_reg = in32(GPIO1_TCR) | (0x80000000 >> (j));
+                                               out32(GPIO1_TCR, gpio_reg);
+                                       }
+
+                                       gpio_reg = in32(GPIO_OS(gpio_core_add+reg_offset))
+                                               & ~(GPIO_MASK >> (j*2));
+                                       out32(GPIO_OS(gpio_core_add+reg_offset), gpio_reg);
+                                       gpio_reg = in32(GPIO_TS(gpio_core_add+reg_offset))
+                                               & ~(GPIO_MASK >> (j*2));
+                                       out32(GPIO_TS(gpio_core_add+reg_offset), gpio_reg);
+                                       break;
+
+                               case GPIO_ALT1:
+                                       gpio_reg = in32(GPIO_OS(gpio_core_add+reg_offset))
+                                               & ~(GPIO_MASK >> (j*2));
+                                       gpio_reg = gpio_reg | (GPIO_ALT1_SEL >> (j*2));
+                                       out32(GPIO_OS(gpio_core_add+reg_offset), gpio_reg);
+                                       gpio_reg = in32(GPIO_TS(gpio_core_add+reg_offset))
+                                               & ~(GPIO_MASK >> (j*2));
+                                       gpio_reg = gpio_reg | (GPIO_ALT1_SEL >> (j*2));
+                                       out32(GPIO_TS(gpio_core_add+reg_offset), gpio_reg);
+                                       break;
+
+                               case GPIO_ALT2:
+                                       gpio_reg = in32(GPIO_OS(gpio_core_add+reg_offset))
+                                               & ~(GPIO_MASK >> (j*2));
+                                       gpio_reg = gpio_reg | (GPIO_ALT2_SEL >> (j*2));
+                                       out32(GPIO_OS(gpio_core_add+reg_offset), gpio_reg);
+                                       gpio_reg = in32(GPIO_TS(gpio_core_add+reg_offset))
+                                               & ~(GPIO_MASK >> (j*2));
+                                       gpio_reg = gpio_reg | (GPIO_ALT2_SEL >> (j*2));
+                                       out32(GPIO_TS(gpio_core_add+reg_offset), gpio_reg);
+                                       break;
+
+                               case GPIO_ALT3:
+                                       gpio_reg = in32(GPIO_OS(gpio_core_add+reg_offset))
+                                               & ~(GPIO_MASK >> (j*2));
+                                       gpio_reg = gpio_reg | (GPIO_ALT3_SEL >> (j*2));
+                                       out32(GPIO_OS(gpio_core_add+reg_offset), gpio_reg);
+                                       gpio_reg = in32(GPIO_TS(gpio_core_add+reg_offset))
+                                               & ~(GPIO_MASK >> (j*2));
+                                       gpio_reg = gpio_reg | (GPIO_ALT3_SEL >> (j*2));
+                                       out32(GPIO_TS(gpio_core_add+reg_offset), gpio_reg);
+                                       break;
+                               }
+                       }
+               }
+       }
+}
+#endif /* CFG_440_GPIO_TABLE */
 
 /*
  * Breath some life into the CPU...
@@ -58,10 +240,16 @@ cpu_init_f (void)
        mtdcr(cpc0_epctl, CPC0_EPRCSR_E0NFE | CPC0_EPRCSR_E1NFE);
 #endif /* CONFIG_405EP */
 
+#if defined(CFG_440_GPIO_TABLE)
+       set_chip_gpio_configuration(&gpio_tab);
+#endif /* CFG_440_GPIO_TABLE */
+
        /*
         * External Bus Controller (EBC) Setup
         */
 #if (defined(CFG_EBC_PB0AP) && defined(CFG_EBC_PB0CR))
+#if (defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
+     defined(CONFIG_405EP) || defined(CONFIG_405))
        /*
         * Move the next instructions into icache, since these modify the flash
         * we are running from!
@@ -77,42 +265,43 @@ cpu_init_f (void)
        asm volatile("  ori     3, 3, 0xA000"   ::: "r3");
        asm volatile("  mtctr   3"              ::: "ctr");
        asm volatile("2:        bdnz    2b"             ::: "ctr", "cr0");
+#endif
 
        mtebc(pb0ap, CFG_EBC_PB0AP);
        mtebc(pb0cr, CFG_EBC_PB0CR);
 #endif
 
-#if (defined(CFG_EBC_PB1AP) && defined(CFG_EBC_PB1CR))
+#if (defined(CFG_EBC_PB1AP) && defined(CFG_EBC_PB1CR) && !(CFG_INIT_DCACHE_CS == 1))
        mtebc(pb1ap, CFG_EBC_PB1AP);
        mtebc(pb1cr, CFG_EBC_PB1CR);
 #endif
 
-#if (defined(CFG_EBC_PB2AP) && defined(CFG_EBC_PB2CR))
+#if (defined(CFG_EBC_PB2AP) && defined(CFG_EBC_PB2CR) && !(CFG_INIT_DCACHE_CS == 2))
        mtebc(pb2ap, CFG_EBC_PB2AP);
        mtebc(pb2cr, CFG_EBC_PB2CR);
 #endif
 
-#if (defined(CFG_EBC_PB3AP) && defined(CFG_EBC_PB3CR))
+#if (defined(CFG_EBC_PB3AP) && defined(CFG_EBC_PB3CR) && !(CFG_INIT_DCACHE_CS == 3))
        mtebc(pb3ap, CFG_EBC_PB3AP);
        mtebc(pb3cr, CFG_EBC_PB3CR);
 #endif
 
-#if (defined(CFG_EBC_PB4AP) && defined(CFG_EBC_PB4CR))
+#if (defined(CFG_EBC_PB4AP) && defined(CFG_EBC_PB4CR) && !(CFG_INIT_DCACHE_CS == 4))
        mtebc(pb4ap, CFG_EBC_PB4AP);
        mtebc(pb4cr, CFG_EBC_PB4CR);
 #endif
 
-#if (defined(CFG_EBC_PB5AP) && defined(CFG_EBC_PB5CR))
+#if (defined(CFG_EBC_PB5AP) && defined(CFG_EBC_PB5CR) && !(CFG_INIT_DCACHE_CS == 5))
        mtebc(pb5ap, CFG_EBC_PB5AP);
        mtebc(pb5cr, CFG_EBC_PB5CR);
 #endif
 
-#if (defined(CFG_EBC_PB6AP) && defined(CFG_EBC_PB6CR))
+#if (defined(CFG_EBC_PB6AP) && defined(CFG_EBC_PB6CR) && !(CFG_INIT_DCACHE_CS == 6))
        mtebc(pb6ap, CFG_EBC_PB6AP);
        mtebc(pb6cr, CFG_EBC_PB6CR);
 #endif
 
-#if (defined(CFG_EBC_PB7AP) && defined(CFG_EBC_PB7CR))
+#if (defined(CFG_EBC_PB7AP) && defined(CFG_EBC_PB7CR) && !(CFG_INIT_DCACHE_CS == 7))
        mtebc(pb7ap, CFG_EBC_PB7AP);
        mtebc(pb7cr, CFG_EBC_PB7CR);
 #endif
@@ -121,7 +310,11 @@ cpu_init_f (void)
        unsigned long val;
 
        val = mfspr(tcr);
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+       val |= 0xb8000000;      /* generate system reset after 1.34 seconds */
+#else
        val |= 0xf0000000;      /* generate system reset after 2.684 seconds */
+#endif
        mtspr(tcr, val);
 
        val = mfspr(tsr);
@@ -138,14 +331,30 @@ cpu_init_f (void)
 int cpu_init_r (void)
 {
 #if defined(CONFIG_405GP)  || defined(CONFIG_405EP)
-       DECLARE_GLOBAL_DATA_PTR;
-
        bd_t *bd = gd->bd;
        unsigned long reg;
 #if defined(CONFIG_405GP)
        uint pvr = get_pvr();
 #endif
 
+#ifdef CFG_INIT_DCACHE_CS
+       /*
+        * Flush and invalidate dcache, then disable CS for temporary stack.
+        * Afterwards, this CS can be used for other purposes
+        */
+       dcache_disable();   /* flush and invalidate dcache */
+       mtebc(PBxAP, 0);
+       mtebc(PBxCR, 0);    /* disable CS for temporary stack */
+
+#if (defined(PBxAP_VAL) && defined(PBxCR_VAL))
+       /*
+        * Write new value into CS register
+        */
+       mtebc(PBxAP, PBxAP_VAL);
+       mtebc(PBxCR, PBxCR_VAL);
+#endif
+#endif /* CFG_INIT_DCACHE_CS */
+
        /*
         * Write Ethernetaddress into on-chip register
         */