]> git.sur5r.net Git - u-boot/blobdiff - arch/blackfin/cpu/initcode.c
i2c: common changes for multibus/multiadapter support
[u-boot] / arch / blackfin / cpu / initcode.c
index a717148651f4f671eab30b055ee576118ca96891..ffaf1017d7b7772f2b0aa25133ae572e5646bd23 100644 (file)
 
 #include <config.h>
 #include <asm/blackfin.h>
+#include <asm/mach-common/bits/watchdog.h>
 #include <asm/mach-common/bits/bootrom.h>
 #include <asm/mach-common/bits/core.h>
+#include <asm/serial.h>
 
-#define BUG() while (1) { asm volatile("emuexcpt;"); }
-
-#include "serial.h"
+#define BUG() while (1) asm volatile("emuexcpt;");
 
 #ifndef __ADSPBF60x__
 #include <asm/mach-common/bits/ebiu.h>
@@ -193,17 +193,12 @@ static inline void serial_init(void)
        }
 #endif
 
+#if CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS
        if (BFIN_DEBUG_EARLY_SERIAL) {
-               int enabled = serial_early_enabled(uart_base);
-
                serial_early_init(uart_base);
-
-               /* If the UART is off, that means we need to program
-                * the baud rate ourselves initially.
-                */
-               if (!enabled)
-                       serial_early_set_baud(uart_base, CONFIG_BAUDRATE);
+               serial_early_set_baud(uart_base, CONFIG_BAUDRATE);
        }
+#endif
 }
 
 __attribute__((always_inline))
@@ -262,7 +257,8 @@ program_nmi_handler(void)
                "%1 = RETS;" /* Load addr of NMI handler */
                "RETS = %0;" /* Restore RETS */
                "[%2] = %1;" /* Write NMI handler */
-               : "=r"(tmp1), "=r"(tmp2) : "ab"(EVT2)
+               : "=d"(tmp1), "=d"(tmp2)
+               : "ab"(EVT2)
        );
 }
 
@@ -461,8 +457,31 @@ program_early_devices(ADI_BOOT_DATA *bs, uint *sdivB, uint *divB, uint *vcoB)
         */
        if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS) {
                serial_putc('e');
+#ifdef __ADSPBF60x__
+               /* Reset system event controller */
+               bfin_write_SEC_GCTL(0x2);
+               bfin_write_SEC_CCTL(0x2);
+               SSYNC();
+
+               /* Enable fault event input and system reset action in fault
+                * controller. Route watchdog timeout event to fault interface.
+                */
+               bfin_write_SEC_FCTL(0xc1);
+               /* Enable watchdog interrupt source */
+               bfin_write_SEC_SCTL(2, bfin_read_SEC_SCTL(2) | 0x6);
+               SSYNC();
+
+               /* Enable system event controller */
+               bfin_write_SEC_GCTL(0x1);
+               bfin_write_SEC_CCTL(0x1);
+               SSYNC();
+#endif
+               bfin_write_WDOG_CTL(WDDIS);
+               SSYNC();
                bfin_write_WDOG_CNT(MSEC_TO_SCLK(CONFIG_HW_WATCHDOG_TIMEOUT_INITCODE));
-               bfin_write_WDOG_CTL(0);
+#if CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_UART
+               bfin_write_WDOG_CTL(WDEN);
+#endif
                serial_putc('f');
        }
 #endif
@@ -496,6 +515,11 @@ maybe_self_refresh(ADI_BOOT_DATA *bs)
                return false;
 
 #ifdef __ADSPBF60x__
+       /* resume from hibernate, return false let ddr initialize */
+       if ((bfin_read32(DPM0_STAT) & 0xF0) == 0x50) {
+               serial_putc('b');
+               return false;
+       }
 
 #else /* __ADSPBF60x__ */
 
@@ -695,37 +719,32 @@ program_clocks(ADI_BOOT_DATA *bs, bool put_into_srfs)
 __attribute__((always_inline)) static inline void
 update_serial_clocks(ADI_BOOT_DATA *bs, uint sdivB, uint divB, uint vcoB)
 {
-       serial_putc('a');
-
        /* Since we've changed the SCLK above, we may need to update
         * the UART divisors (UART baud rates are based on SCLK).
         * Do the division by hand as there are no native instructions
         * for dividing which means we'd generate a libgcc reference.
         */
-       if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) {
-               unsigned int sdivR, vcoR;
-               int dividend = sdivB * divB * vcoR;
-               int divisor = vcoB * sdivR;
-               unsigned int quotient;
+       unsigned int sdivR, vcoR;
+       unsigned int dividend;
+       unsigned int divisor;
+       unsigned int quotient;
 
-               serial_putc('b');
+       serial_putc('a');
 
 #ifdef __ADSPBF60x__
-               sdivR = bfin_read_CGU_DIV();
-               sdivR = ((sdivR >> 8) & 0x1f) * ((sdivR >> 5) & 0x7);
-               vcoR = (bfin_read_CGU_CTL() >> 8) & 0x7f;
+       sdivR = bfin_read_CGU_DIV();
+       sdivR = ((sdivR >> 8) & 0x1f) * ((sdivR >> 5) & 0x7);
+       vcoR = (bfin_read_CGU_CTL() >> 8) & 0x7f;
 #else
-               sdivR = bfin_read_PLL_DIV() & 0xf;
-               vcoR = (bfin_read_PLL_CTL() >> 9) & 0x3f;
+       sdivR = bfin_read_PLL_DIV() & 0xf;
+       vcoR = (bfin_read_PLL_CTL() >> 9) & 0x3f;
 #endif
 
-               for (quotient = 0; dividend > 0; ++quotient)
-                       dividend -= divisor;
-               serial_early_put_div(quotient - ANOMALY_05000230);
-               serial_putc('c');
-       }
-
-       serial_putc('d');
+       dividend = sdivB * divB * vcoR;
+       divisor = vcoB * sdivR;
+       quotient = early_division(dividend, divisor);
+       serial_early_put_div(quotient - ANOMALY_05000230);
+       serial_putc('c');
 }
 
 __attribute__((always_inline)) static inline void
@@ -814,6 +833,7 @@ program_memory_controller(ADI_BOOT_DATA *bs, bool put_into_srfs)
        while (!(bfin_read_DMC0_STAT() & DLLCALDONE))
                continue;
        serial_putc('!');
+
 #else /* __ADSPBF60x__ */
 
        /* Program the external memory controller before we come out of
@@ -881,7 +901,46 @@ check_hibernation(ADI_BOOT_DATA *bs, u16 vr_ctl, bool put_into_srfs)
                return;
 
        serial_putc('b');
+#ifdef __ADSPBF60x__
+       if (bfin_read32(DPM0_RESTORE0) != 0) {
+               uint32_t reg = bfin_read_DMC0_CTL();
+               reg &= ~0x8;
+               bfin_write_DMC0_CTL(reg);
+
+               while ((bfin_read_DMC0_STAT() & 0x8))
+                       continue;
+               while (!(bfin_read_DMC0_STAT() & 0x1))
+                       continue;
+
+               serial_putc('z');
+               uint32_t *hibernate_magic = bfin_read32(DPM0_RESTORE4);
+               SSYNC(); /* make sure memory controller is done */
+               if (hibernate_magic[0] == 0xDEADBEEF) {
+                       serial_putc('c');
+                       SSYNC();
+                       bfin_write_EVT15(hibernate_magic[1]);
+                       bfin_write_IMASK(EVT_IVG15);
+                       __asm__ __volatile__ (
+                               /* load reti early to avoid anomaly 281 */
+                               "reti = %2;"
+                               /* clear hibernate magic */
+                               "[%0] = %1;"
+                               /* load stack pointer */
+                               "SP = [%0 + 8];"
+                               /* lower ourselves from reset ivg to ivg15 */
+                               "raise 15;"
+                               "nop;nop;nop;"
+                               "rti;"
+                               :
+                               : "p"(hibernate_magic),
+                               "d"(0x2000 /* jump.s 0 */),
+                               "d"(0xffa00000)
+                       );
+               }
+
 
+       }
+#else
        /* Are we coming out of hibernate (suspend to memory) ?
         * The memory layout is:
         * 0x0: hibernate magic for anomaly 307 (0xDEADBEEF)
@@ -914,6 +973,7 @@ check_hibernation(ADI_BOOT_DATA *bs, u16 vr_ctl, bool put_into_srfs)
                }
                serial_putc('d');
        }
+#endif
 
        serial_putc('e');
 }