|
@@ -12,6 +12,7 @@
|
|
|
#include <config.h>
|
|
|
#include <asm/blackfin.h>
|
|
|
#include <asm/mach-common/bits/bootrom.h>
|
|
|
+#include <asm/mach-common/bits/core.h>
|
|
|
#include <asm/mach-common/bits/ebiu.h>
|
|
|
#include <asm/mach-common/bits/pll.h>
|
|
|
#include <asm/mach-common/bits/uart.h>
|
|
@@ -257,6 +258,8 @@ void initcode(ADI_BOOT_DATA *bootstruct)
|
|
|
divB = serial_early_get_div();
|
|
|
}
|
|
|
|
|
|
+ serial_putc('A');
|
|
|
+
|
|
|
#ifdef CONFIG_HW_WATCHDOG
|
|
|
# ifndef CONFIG_HW_WATCHDOG_TIMEOUT_INITCODE
|
|
|
# define CONFIG_HW_WATCHDOG_TIMEOUT_INITCODE 20000
|
|
@@ -273,7 +276,23 @@ void initcode(ADI_BOOT_DATA *bootstruct)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
- serial_putc('S');
|
|
|
+ serial_putc('B');
|
|
|
+
|
|
|
+ /* If external memory is enabled, put it into self refresh first. */
|
|
|
+ bool put_into_srfs = false;
|
|
|
+#ifdef EBIU_RSTCTL
|
|
|
+ if (bfin_read_EBIU_RSTCTL() & DDR_SRESET) {
|
|
|
+ bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() | SRREQ);
|
|
|
+ put_into_srfs = true;
|
|
|
+ }
|
|
|
+#else
|
|
|
+ if (bfin_read_EBIU_SDBCTL() & EBE) {
|
|
|
+ bfin_write_EBIU_SDGCTL(bfin_read_EBIU_SDGCTL() | SRFS);
|
|
|
+ put_into_srfs = true;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
+ serial_putc('C');
|
|
|
|
|
|
/* Blackfin bootroms use the SPI slow read opcode instead of the SPI
|
|
|
* fast read, so we need to slow down the SPI clock a lot more during
|
|
@@ -286,29 +305,26 @@ void initcode(ADI_BOOT_DATA *bootstruct)
|
|
|
bfin_write_SPI_BAUD(CONFIG_SPI_BAUD_INITBLOCK);
|
|
|
}
|
|
|
|
|
|
- serial_putc('B');
|
|
|
+ serial_putc('D');
|
|
|
|
|
|
- /* Disable all peripheral wakeups except for the PLL event. */
|
|
|
-#ifdef SIC_IWR0
|
|
|
- bfin_write_SIC_IWR0(1);
|
|
|
- bfin_write_SIC_IWR1(0);
|
|
|
-# ifdef SIC_IWR2
|
|
|
- bfin_write_SIC_IWR2(0);
|
|
|
-# endif
|
|
|
-#elif defined(SICA_IWR0)
|
|
|
- bfin_write_SICA_IWR0(1);
|
|
|
- bfin_write_SICA_IWR1(0);
|
|
|
+ /* If we're entering self refresh, make sure it has happened. */
|
|
|
+ if (put_into_srfs)
|
|
|
+#ifdef EBIU_RSTCTL
|
|
|
+ while (!(bfin_read_EBIU_RSTCTL() & SRACK))
|
|
|
#else
|
|
|
- bfin_write_SIC_IWR(1);
|
|
|
+ while (!(bfin_read_EBIU_SDSTAT() & SDSRA))
|
|
|
#endif
|
|
|
+ continue;
|
|
|
+
|
|
|
+ serial_putc('E');
|
|
|
|
|
|
/* With newer bootroms, we use the helper function to set up
|
|
|
* the memory controller. Older bootroms lacks such helpers
|
|
|
* so we do it ourselves.
|
|
|
*/
|
|
|
-#define BOOTROM_CAPS_SYSCONTROL 0
|
|
|
- if (BOOTROM_CAPS_SYSCONTROL) {
|
|
|
- serial_putc('S');
|
|
|
+ uint16_t vr_ctl = bfin_read_VR_CTL();
|
|
|
+ if (!ANOMALY_05000386) {
|
|
|
+ serial_putc('F');
|
|
|
|
|
|
ADI_SYSCTRL_VALUES memory_settings;
|
|
|
uint32_t actions = SYSCTRL_WRITE | SYSCTRL_PLLCTL | SYSCTRL_PLLDIV | SYSCTRL_LOCKCNT;
|
|
@@ -332,22 +348,38 @@ void initcode(ADI_BOOT_DATA *bootstruct)
|
|
|
bfin_write_SIC_IWR1(-1);
|
|
|
#endif
|
|
|
} else {
|
|
|
- serial_putc('L');
|
|
|
+ serial_putc('G');
|
|
|
+
|
|
|
+ /* Disable all peripheral wakeups except for the PLL event. */
|
|
|
+#ifdef SIC_IWR0
|
|
|
+ bfin_write_SIC_IWR0(1);
|
|
|
+ bfin_write_SIC_IWR1(0);
|
|
|
+# ifdef SIC_IWR2
|
|
|
+ bfin_write_SIC_IWR2(0);
|
|
|
+# endif
|
|
|
+#elif defined(SICA_IWR0)
|
|
|
+ bfin_write_SICA_IWR0(1);
|
|
|
+ bfin_write_SICA_IWR1(0);
|
|
|
+#else
|
|
|
+ bfin_write_SIC_IWR(1);
|
|
|
+#endif
|
|
|
+
|
|
|
+ serial_putc('H');
|
|
|
|
|
|
bfin_write_PLL_LOCKCNT(CONFIG_PLL_LOCKCNT_VAL);
|
|
|
|
|
|
- serial_putc('A');
|
|
|
+ serial_putc('I');
|
|
|
|
|
|
/* Only reprogram when needed to avoid triggering unnecessary
|
|
|
* PLL relock sequences.
|
|
|
*/
|
|
|
- if (bfin_read_VR_CTL() != CONFIG_VR_CTL_VAL) {
|
|
|
+ if (vr_ctl != CONFIG_VR_CTL_VAL) {
|
|
|
serial_putc('!');
|
|
|
bfin_write_VR_CTL(CONFIG_VR_CTL_VAL);
|
|
|
asm("idle;");
|
|
|
}
|
|
|
|
|
|
- serial_putc('C');
|
|
|
+ serial_putc('J');
|
|
|
|
|
|
bfin_write_PLL_DIV(CONFIG_PLL_DIV_VAL);
|
|
|
|
|
@@ -361,8 +393,26 @@ void initcode(ADI_BOOT_DATA *bootstruct)
|
|
|
bfin_write_PLL_CTL(CONFIG_PLL_CTL_VAL);
|
|
|
asm("idle;");
|
|
|
}
|
|
|
+
|
|
|
+ serial_putc('L');
|
|
|
+
|
|
|
+ /* Restore all peripheral wakeups. */
|
|
|
+#ifdef SIC_IWR0
|
|
|
+ bfin_write_SIC_IWR0(-1);
|
|
|
+ bfin_write_SIC_IWR1(-1);
|
|
|
+# ifdef SIC_IWR2
|
|
|
+ bfin_write_SIC_IWR2(-1);
|
|
|
+# endif
|
|
|
+#elif defined(SICA_IWR0)
|
|
|
+ bfin_write_SICA_IWR0(-1);
|
|
|
+ bfin_write_SICA_IWR1(-1);
|
|
|
+#else
|
|
|
+ bfin_write_SIC_IWR(-1);
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
+ serial_putc('M');
|
|
|
+
|
|
|
/* 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
|
|
@@ -380,23 +430,32 @@ void initcode(ADI_BOOT_DATA *bootstruct)
|
|
|
serial_early_put_div(quotient - ANOMALY_05000230);
|
|
|
}
|
|
|
|
|
|
- serial_putc('F');
|
|
|
+ serial_putc('N');
|
|
|
|
|
|
- /* Program the async banks controller. */
|
|
|
- bfin_write_EBIU_AMBCTL0(CONFIG_EBIU_AMBCTL0_VAL);
|
|
|
- bfin_write_EBIU_AMBCTL1(CONFIG_EBIU_AMBCTL1_VAL);
|
|
|
- bfin_write_EBIU_AMGCTL(CONFIG_EBIU_AMGCTL_VAL);
|
|
|
+ /* Program the external memory controller before we come out of
|
|
|
+ * self-refresh. This only works with our SDRAM controller.
|
|
|
+ */
|
|
|
+#ifndef EBIU_RSTCTL
|
|
|
+ bfin_write_EBIU_SDRRC(CONFIG_EBIU_SDRRC_VAL);
|
|
|
+ bfin_write_EBIU_SDBCTL(CONFIG_EBIU_SDBCTL_VAL);
|
|
|
+ bfin_write_EBIU_SDGCTL(CONFIG_EBIU_SDGCTL_VAL);
|
|
|
+#endif
|
|
|
|
|
|
-#ifdef EBIU_MODE
|
|
|
- /* Not all parts have these additional MMRs. */
|
|
|
- bfin_write_EBIU_MBSCTL(CONFIG_EBIU_MBSCTL_VAL);
|
|
|
- bfin_write_EBIU_MODE(CONFIG_EBIU_MODE_VAL);
|
|
|
- bfin_write_EBIU_FCTL(CONFIG_EBIU_FCTL_VAL);
|
|
|
+ serial_putc('O');
|
|
|
+
|
|
|
+ /* Now that we've reprogrammed, take things out of self refresh. */
|
|
|
+ if (put_into_srfs)
|
|
|
+#ifdef EBIU_RSTCTL
|
|
|
+ bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() & ~(SRREQ));
|
|
|
+#else
|
|
|
+ bfin_write_EBIU_SDGCTL(bfin_read_EBIU_SDGCTL() & ~(SRFS));
|
|
|
#endif
|
|
|
|
|
|
- serial_putc('I');
|
|
|
+ serial_putc('P');
|
|
|
|
|
|
- /* Program the external memory controller. */
|
|
|
+ /* Our DDR controller sucks and cannot be programmed while in
|
|
|
+ * self-refresh. So we have to pull it out before programming.
|
|
|
+ */
|
|
|
#ifdef EBIU_RSTCTL
|
|
|
bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() | 0x1 /*DDRSRESET*/ | CONFIG_EBIU_RSTCTL_VAL);
|
|
|
bfin_write_EBIU_DDRCTL0(CONFIG_EBIU_DDRCTL0_VAL);
|
|
@@ -406,28 +465,60 @@ void initcode(ADI_BOOT_DATA *bootstruct)
|
|
|
/* default is disable, so don't need to force this */
|
|
|
bfin_write_EBIU_DDRCTL3(CONFIG_EBIU_DDRCTL3_VAL);
|
|
|
# endif
|
|
|
-#else
|
|
|
- bfin_write_EBIU_SDRRC(CONFIG_EBIU_SDRRC_VAL);
|
|
|
- bfin_write_EBIU_SDBCTL(CONFIG_EBIU_SDBCTL_VAL);
|
|
|
- bfin_write_EBIU_SDGCTL(CONFIG_EBIU_SDGCTL_VAL);
|
|
|
+# ifdef CONFIG_EBIU_DDRQUE_VAL
|
|
|
+ bfin_write_EBIU_DDRQUE(bfin_read_EBIU_DDRQUE() | CONFIG_EBIU_DDRQUE_VAL);
|
|
|
+# endif
|
|
|
#endif
|
|
|
|
|
|
- serial_putc('N');
|
|
|
+ serial_putc('Q');
|
|
|
|
|
|
- /* Restore all peripheral wakeups. */
|
|
|
-#ifdef SIC_IWR0
|
|
|
- bfin_write_SIC_IWR0(-1);
|
|
|
- bfin_write_SIC_IWR1(-1);
|
|
|
-# ifdef SIC_IWR2
|
|
|
- bfin_write_SIC_IWR2(-1);
|
|
|
-# endif
|
|
|
-#elif defined(SICA_IWR0)
|
|
|
- bfin_write_SICA_IWR0(-1);
|
|
|
- bfin_write_SICA_IWR1(-1);
|
|
|
-#else
|
|
|
- bfin_write_SIC_IWR(-1);
|
|
|
+ /* Are we coming out of hibernate (suspend to memory) ?
|
|
|
+ * The memory layout is:
|
|
|
+ * 0x0: hibernate magic for anomaly 307 (0xDEADBEEF)
|
|
|
+ * 0x4: return address
|
|
|
+ * 0x8: stack pointer
|
|
|
+ *
|
|
|
+ * SCKELOW is unreliable on older parts (anomaly 307)
|
|
|
+ */
|
|
|
+ if (ANOMALY_05000307 || vr_ctl & 0x8000) {
|
|
|
+ uint32_t *hibernate_magic = 0;
|
|
|
+ __builtin_bfin_ssync(); /* make sure memory controller is done */
|
|
|
+ if (hibernate_magic[0] == 0xDEADBEEF) {
|
|
|
+ serial_putc('R');
|
|
|
+ bfin_write_EVT15(hibernate_magic[1]);
|
|
|
+ bfin_write_IMASK(EVT_IVG15);
|
|
|
+ __asm__ __volatile__ (
|
|
|
+ /* load reti early to avoid anomaly 281 */
|
|
|
+ "reti = %0;"
|
|
|
+ /* clear hibernate magic */
|
|
|
+ "[%0] = %1;"
|
|
|
+ /* load stack pointer */
|
|
|
+ "SP = [%0 + 8];"
|
|
|
+ /* lower ourselves from reset ivg to ivg15 */
|
|
|
+ "raise 15;"
|
|
|
+ "rti;"
|
|
|
+ :
|
|
|
+ : "p"(hibernate_magic), "d"(0x2000 /* jump.s 0 */)
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ serial_putc('S');
|
|
|
+
|
|
|
+ /* Program the async banks controller. */
|
|
|
+ bfin_write_EBIU_AMBCTL0(CONFIG_EBIU_AMBCTL0_VAL);
|
|
|
+ bfin_write_EBIU_AMBCTL1(CONFIG_EBIU_AMBCTL1_VAL);
|
|
|
+ bfin_write_EBIU_AMGCTL(CONFIG_EBIU_AMGCTL_VAL);
|
|
|
+
|
|
|
+#ifdef EBIU_MODE
|
|
|
+ /* Not all parts have these additional MMRs. */
|
|
|
+ bfin_write_EBIU_MBSCTL(CONFIG_EBIU_MBSCTL_VAL);
|
|
|
+ bfin_write_EBIU_MODE(CONFIG_EBIU_MODE_VAL);
|
|
|
+ bfin_write_EBIU_FCTL(CONFIG_EBIU_FCTL_VAL);
|
|
|
#endif
|
|
|
|
|
|
+ serial_putc('T');
|
|
|
+
|
|
|
/* tell the bootrom where our entry point is */
|
|
|
if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS)
|
|
|
bfin_write_EVT1(CONFIG_SYS_MONITOR_BASE);
|