Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes...
[cascardo/linux.git] / arch / blackfin / kernel / setup.c
index 8efea00..7a82d10 100644 (file)
@@ -52,6 +52,7 @@ EXPORT_SYMBOL(mtd_size);
 #endif
 
 char __initdata command_line[COMMAND_LINE_SIZE];
+unsigned int __initdata *__retx;
 
 /* boot memmap, for parsing "memmap=" */
 #define BFIN_MEMMAP_MAX                128 /* number of entries in bfin_memmap */
@@ -104,6 +105,7 @@ void __init bf53x_relocate_l1_mem(void)
        unsigned long l1_code_length;
        unsigned long l1_data_a_length;
        unsigned long l1_data_b_length;
+       unsigned long l2_length;
 
        l1_code_length = _etext_l1 - _stext_l1;
        if (l1_code_length > L1_CODE_LENGTH)
@@ -129,6 +131,15 @@ void __init bf53x_relocate_l1_mem(void)
        /* Copy _sdata_b_l1 to _ebss_b_l1 to L1 data bank B SRAM */
        dma_memcpy(_sdata_b_l1, _l1_lma_start + l1_code_length +
                        l1_data_a_length, l1_data_b_length);
+
+       if (L2_LENGTH != 0) {
+               l2_length = _ebss_l2 - _stext_l2;
+               if (l2_length > L2_LENGTH)
+                       panic("L2 SRAM Overflow\n");
+
+               /* Copy _stext_l2 to _edata_l2 to L2 SRAM */
+               dma_memcpy(_stext_l2, _l2_lma_start, l2_length);
+       }
 }
 
 /* add_memory_region to memmap */
@@ -664,11 +675,8 @@ static __init void setup_bootmem_allocator(void)
 })
 static inline int __init get_mem_size(void)
 {
-#ifdef CONFIG_MEM_SIZE
-       return CONFIG_MEM_SIZE;
-#else
-# if defined(EBIU_SDBCTL)
-#  if defined(BF561_FAMILY)
+#if defined(EBIU_SDBCTL)
+# if defined(BF561_FAMILY)
        int ret = 0;
        u32 sdbctl = bfin_read_EBIU_SDBCTL();
        ret += EBSZ_TO_MEG(sdbctl >>  0);
@@ -676,10 +684,10 @@ static inline int __init get_mem_size(void)
        ret += EBSZ_TO_MEG(sdbctl >> 16);
        ret += EBSZ_TO_MEG(sdbctl >> 24);
        return ret;
-#  else
+# else
        return EBSZ_TO_MEG(bfin_read_EBIU_SDBCTL());
-#  endif
-# elif defined(EBIU_DDRCTL1)
+# endif
+#elif defined(EBIU_DDRCTL1)
        u32 ddrctl = bfin_read_EBIU_DDRCTL1();
        int ret = 0;
        switch (ddrctl & 0xc0000) {
@@ -693,8 +701,9 @@ static inline int __init get_mem_size(void)
                case DEVWD_8:  ret *= 2;
                case DEVWD_16: break;
        }
+       if ((ddrctl & 0xc000) == 0x4000)
+               ret *= 2;
        return ret;
-# endif
 #endif
        BUG();
 }
@@ -730,6 +739,16 @@ void __init setup_arch(char **cmdline_p)
 
        memory_setup();
 
+       /* Initialize Async memory banks */
+       bfin_write_EBIU_AMBCTL0(AMBCTL0VAL);
+       bfin_write_EBIU_AMBCTL1(AMBCTL1VAL);
+       bfin_write_EBIU_AMGCTL(AMGCTLVAL);
+#ifdef CONFIG_EBIU_MBSCTLVAL
+       bfin_write_EBIU_MBSCTL(CONFIG_EBIU_MBSCTLVAL);
+       bfin_write_EBIU_MODE(CONFIG_EBIU_MODEVAL);
+       bfin_write_EBIU_FCTL(CONFIG_EBIU_FCTLVAL);
+#endif
+
        cclk = get_cclk();
        sclk = get_sclk();
 
@@ -763,8 +782,15 @@ void __init setup_arch(char **cmdline_p)
 
        _bfin_swrst = bfin_read_SWRST();
 
+       /* If we double fault, reset the system - otherwise we hang forever */
+       bfin_write_SWRST(DOUBLE_FAULT);
+
        if (_bfin_swrst & RESET_DOUBLE)
-               printk(KERN_INFO "Recovering from Double Fault event\n");
+               /*
+                * don't decode the address, since you don't know if this
+                * kernel's symbol map is the same as the crashing kernel
+                */
+               printk(KERN_INFO "Recovering from Double Fault event at %pF\n", __retx);
        else if (_bfin_swrst & RESET_WDOG)
                printk(KERN_INFO "Recovering from Watchdog event\n");
        else if (_bfin_swrst & RESET_SOFTWARE)
@@ -842,38 +868,55 @@ static int __init topology_init(void)
 
 subsys_initcall(topology_init);
 
+/* Get the voltage input multiplier */
+static u_long cached_vco_pll_ctl, cached_vco;
 static u_long get_vco(void)
 {
        u_long msel;
-       u_long vco;
 
-       msel = (bfin_read_PLL_CTL() >> 9) & 0x3F;
+       u_long pll_ctl = bfin_read_PLL_CTL();
+       if (pll_ctl == cached_vco_pll_ctl)
+               return cached_vco;
+       else
+               cached_vco_pll_ctl = pll_ctl;
+
+       msel = (pll_ctl >> 9) & 0x3F;
        if (0 == msel)
                msel = 64;
 
-       vco = CONFIG_CLKIN_HZ;
-       vco >>= (1 & bfin_read_PLL_CTL());      /* DF bit */
-       vco = msel * vco;
-       return vco;
+       cached_vco = CONFIG_CLKIN_HZ;
+       cached_vco >>= (1 & pll_ctl);   /* DF bit */
+       cached_vco *= msel;
+       return cached_vco;
 }
 
 /* Get the Core clock */
+static u_long cached_cclk_pll_div, cached_cclk;
 u_long get_cclk(void)
 {
        u_long csel, ssel;
+
        if (bfin_read_PLL_STAT() & 0x1)
                return CONFIG_CLKIN_HZ;
 
        ssel = bfin_read_PLL_DIV();
+       if (ssel == cached_cclk_pll_div)
+               return cached_cclk;
+       else
+               cached_cclk_pll_div = ssel;
+
        csel = ((ssel >> 4) & 0x03);
        ssel &= 0xf;
        if (ssel && ssel < (1 << csel)) /* SCLK > CCLK */
-               return get_vco() / ssel;
-       return get_vco() >> csel;
+               cached_cclk = get_vco() / ssel;
+       else
+               cached_cclk = get_vco() >> csel;
+       return cached_cclk;
 }
 EXPORT_SYMBOL(get_cclk);
 
 /* Get the System clock */
+static u_long cached_sclk_pll_div, cached_sclk;
 u_long get_sclk(void)
 {
        u_long ssel;
@@ -881,13 +924,20 @@ u_long get_sclk(void)
        if (bfin_read_PLL_STAT() & 0x1)
                return CONFIG_CLKIN_HZ;
 
-       ssel = (bfin_read_PLL_DIV() & 0xf);
+       ssel = bfin_read_PLL_DIV();
+       if (ssel == cached_sclk_pll_div)
+               return cached_sclk;
+       else
+               cached_sclk_pll_div = ssel;
+
+       ssel &= 0xf;
        if (0 == ssel) {
                printk(KERN_WARNING "Invalid System Clock\n");
                ssel = 1;
        }
 
-       return get_vco() / ssel;
+       cached_sclk = get_vco() / ssel;
+       return cached_sclk;
 }
 EXPORT_SYMBOL(get_sclk);
 
@@ -916,7 +966,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        uint32_t revid;
 
        u_long cclk = 0, sclk = 0;
-       u_int dcache_size = 0, dsup_banks = 0;
+       u_int icache_size = BFIN_ICACHESIZE / 1024, dcache_size = 0, dsup_banks = 0;
 
        cpu = CPU;
        mmu = "none";
@@ -985,12 +1035,15 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        }
 
        /* Is it turned on? */
-       if (!((bfin_read_DMEM_CONTROL()) & (ENDCPLB | DMC_ENABLE)))
+       if ((bfin_read_DMEM_CONTROL() & (ENDCPLB | DMC_ENABLE)) != (ENDCPLB | DMC_ENABLE))
                dcache_size = 0;
 
+       if ((bfin_read_IMEM_CONTROL() & (IMC | ENICPLB)) == (IMC | ENICPLB))
+               icache_size = 0;
+
        seq_printf(m, "cache size\t: %d KB(L1 icache) "
                "%d KB(L1 dcache-%s) %d KB(L2 cache)\n",
-               BFIN_ICACHESIZE / 1024, dcache_size,
+               icache_size, dcache_size,
 #if defined CONFIG_BFIN_WB
                "wb"
 #elif defined CONFIG_BFIN_WT
@@ -1000,14 +1053,18 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 
        seq_printf(m, "%s\n", cache);
 
-       seq_printf(m, "icache setup\t: %d Sub-banks/%d Ways, %d Lines/Way\n",
-                  BFIN_ISUBBANKS, BFIN_IWAYS, BFIN_ILINES);
+       if (icache_size)
+               seq_printf(m, "icache setup\t: %d Sub-banks/%d Ways, %d Lines/Way\n",
+                          BFIN_ISUBBANKS, BFIN_IWAYS, BFIN_ILINES);
+       else
+               seq_printf(m, "icache setup\t: off\n");
+
        seq_printf(m,
                   "dcache setup\t: %d Super-banks/%d Sub-banks/%d Ways, %d Lines/Way\n",
                   dsup_banks, BFIN_DSUBBANKS, BFIN_DWAYS,
                   BFIN_DLINES);
 #ifdef CONFIG_BFIN_ICACHE_LOCK
-       switch (read_iloc()) {
+       switch ((bfin_read_IMEM_CONTROL() >> 3) & WAYALL_L) {
        case WAY0_L:
                seq_printf(m, "Way0 Locked-Down\n");
                break;