]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
Blackfin: re-architect initcode
authorMike Frysinger <vapier@gentoo.org>
Tue, 10 Nov 2009 00:44:04 +0000 (19:44 -0500)
committerMike Frysinger <vapier@gentoo.org>
Sun, 17 Jan 2010 14:17:26 +0000 (09:17 -0500)
The single initcode function was growing unwieldy, so split it up the
distinct steps into their own function.  This should making digesting the
result much easier on people.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
cpu/blackfin/initcode.c

index a039cbbbce12d4969b5d9a3f9b2b2452da37f721..bb588988bc4cf0025dd2f10016b5cf8dcf302702 100644 (file)
@@ -9,6 +9,8 @@
  * Licensed under the GPL-2 or later.
  */
 
+#define BFIN_IN_INITCODE
+
 #include <config.h>
 #include <asm/blackfin.h>
 #include <asm/mach-common/bits/bootrom.h>
@@ -17,7 +19,6 @@
 #include <asm/mach-common/bits/pll.h>
 #include <asm/mach-common/bits/uart.h>
 
-#define BFIN_IN_INITCODE
 #include "serial.h"
 
 __attribute__((always_inline))
@@ -213,6 +214,7 @@ static inline void serial_putc(char c)
 # define CONFIG_HAS_VR 1
 #endif
 
+#if CONFIG_MEM_SIZE
 #ifndef EBIU_RSTCTL
 /* Blackfin with SDRAM */
 #ifndef CONFIG_EBIU_SDBCTL_VAL
@@ -245,6 +247,7 @@ static inline void serial_putc(char c)
 # define CONFIG_EBIU_SDBCTL_VAL (CONFIG_EBCAW_VAL | CONFIG_EBSZ_VAL | EBE)
 #endif
 #endif
+#endif
 
 /* Conflicting Column Address Widths Causes SDRAM Errors:
  * EB2CAW and EB3CAW must be the same
@@ -255,28 +258,21 @@ static inline void serial_putc(char c)
 # endif
 #endif
 
-BOOTROM_CALLED_FUNC_ATTR
-void initcode(ADI_BOOT_DATA *bootstruct)
+__attribute__((always_inline)) static inline void
+program_early_devices(ADI_BOOT_DATA *bs, uint *sdivB, uint *divB, uint *vcoB)
 {
-       ADI_BOOT_DATA bootstruct_scratch;
+       serial_putc('a');
 
        /* Save the clock pieces that are used in baud rate calculation */
-       unsigned int sdivB, divB, vcoB;
-       serial_init();
        if (BFIN_DEBUG_EARLY_SERIAL || CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) {
-               sdivB = bfin_read_PLL_DIV() & 0xf;
-               vcoB = (bfin_read_PLL_CTL() >> 9) & 0x3f;
-               divB = serial_early_get_div();
+               serial_putc('b');
+               *sdivB = bfin_read_PLL_DIV() & 0xf;
+               *vcoB = (bfin_read_PLL_CTL() >> 9) & 0x3f;
+               *divB = serial_early_get_div();
+               serial_putc('c');
        }
 
-       serial_putc('A');
-
-       /* If the bootstruct is NULL, then it's because we're loading
-        * dynamically and not via LDR (bootrom).  So set the struct to
-        * some scratch space.
-        */
-       if (!bootstruct)
-               bootstruct = &bootstruct_scratch;
+       serial_putc('d');
 
 #ifdef CONFIG_HW_WATCHDOG
 # ifndef CONFIG_HW_WATCHDOG_TIMEOUT_INITCODE
@@ -289,41 +285,69 @@ void initcode(ADI_BOOT_DATA *bootstruct)
         * timeout, so don't clobber that.
         */
        if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS) {
+               serial_putc('e');
                bfin_write_WDOG_CNT(MSEC_TO_SCLK(CONFIG_HW_WATCHDOG_TIMEOUT_INITCODE));
                bfin_write_WDOG_CTL(0);
+               serial_putc('f');
        }
 #endif
 
-       serial_putc('B');
+       serial_putc('g');
+
+       /* 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
+        * boot.  Once we switch over to u-boot's SPI flash driver, we'll
+        * increase the speed appropriately.
+        */
+       if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_SPI_MASTER) {
+               serial_putc('h');
+               if (BOOTROM_SUPPORTS_SPI_FAST_READ && CONFIG_SPI_BAUD_INITBLOCK < 4)
+                       bs->dFlags |= BFLAG_FASTREAD;
+               bfin_write_SPI_BAUD(CONFIG_SPI_BAUD_INITBLOCK);
+               serial_putc('i');
+       }
+
+       serial_putc('j');
+}
+
+__attribute__((always_inline)) static inline bool
+maybe_self_refresh(ADI_BOOT_DATA *bs)
+{
+       serial_putc('a');
+
+       if (!CONFIG_MEM_SIZE)
+               return false;
 
        /* 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) {
+               serial_putc('b');
                bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() | SRREQ);
-               put_into_srfs = true;
+               return true;
        }
 #else
        if (bfin_read_EBIU_SDBCTL() & EBE) {
+               serial_putc('b');
                bfin_write_EBIU_SDGCTL(bfin_read_EBIU_SDGCTL() | SRFS);
-               put_into_srfs = true;
+               return true;
        }
 #endif
 
-       serial_putc('C');
+       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
-        * boot.  Once we switch over to u-boot's SPI flash driver, we'll
-        * increase the speed appropriately.
-        */
-       if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_SPI_MASTER) {
-               if (BOOTROM_SUPPORTS_SPI_FAST_READ && CONFIG_SPI_BAUD_INITBLOCK < 4)
-                       bootstruct->dFlags |= BFLAG_FASTREAD;
-               bfin_write_SPI_BAUD(CONFIG_SPI_BAUD_INITBLOCK);
-       }
+       return false;
+}
 
-       serial_putc('D');
+__attribute__((always_inline)) static inline u16
+program_clocks(ADI_BOOT_DATA *bs, bool put_into_srfs)
+{
+       u16 vr_ctl;
+
+       serial_putc('a');
+
+       vr_ctl = bfin_read_VR_CTL();
+
+       serial_putc('b');
 
        /* If we're entering self refresh, make sure it has happened. */
        if (put_into_srfs)
@@ -334,15 +358,14 @@ void initcode(ADI_BOOT_DATA *bootstruct)
 #endif
                        continue;
 
-       serial_putc('E');
+       serial_putc('c');
 
        /* With newer bootroms, we use the helper function to set up
         * the memory controller.  Older bootroms lacks such helpers
         * so we do it ourselves.
         */
-       uint16_t vr_ctl = bfin_read_VR_CTL();
        if (!ANOMALY_05000386) {
-               serial_putc('F');
+               serial_putc('d');
 
                /* Always programming PLL_LOCKCNT avoids Anomaly 05000430 */
                ADI_SYSCTRL_VALUES memory_settings;
@@ -362,7 +385,9 @@ void initcode(ADI_BOOT_DATA *bootstruct)
 #if ANOMALY_05000432
                bfin_write_SIC_IWR1(0);
 #endif
+               serial_putc('e');
                bfrom_SysControl(actions, &memory_settings, NULL);
+               serial_putc('f');
 #if ANOMALY_05000432
                bfin_write_SIC_IWR1(-1);
 #endif
@@ -370,8 +395,9 @@ void initcode(ADI_BOOT_DATA *bootstruct)
                bfin_write_SICA_IWR0(-1);
                bfin_write_SICA_IWR1(-1);
 #endif
+               serial_putc('g');
        } else {
-               serial_putc('G');
+               serial_putc('h');
 
                /* Disable all peripheral wakeups except for the PLL event. */
 #ifdef SIC_IWR0
@@ -387,38 +413,40 @@ void initcode(ADI_BOOT_DATA *bootstruct)
                bfin_write_SIC_IWR(1);
 #endif
 
-               serial_putc('H');
+               serial_putc('i');
 
                /* Always programming PLL_LOCKCNT avoids Anomaly 05000430 */
                bfin_write_PLL_LOCKCNT(CONFIG_PLL_LOCKCNT_VAL);
 
-               serial_putc('I');
+               serial_putc('j');
 
                /* Only reprogram when needed to avoid triggering unnecessary
                 * PLL relock sequences.
                 */
                if (vr_ctl != CONFIG_VR_CTL_VAL) {
-                       serial_putc('!');
+                       serial_putc('?');
                        bfin_write_VR_CTL(CONFIG_VR_CTL_VAL);
                        asm("idle;");
+                       serial_putc('!');
                }
 
-               serial_putc('J');
+               serial_putc('k');
 
                bfin_write_PLL_DIV(CONFIG_PLL_DIV_VAL);
 
-               serial_putc('K');
+               serial_putc('l');
 
                /* Only reprogram when needed to avoid triggering unnecessary
                 * PLL relock sequences.
                 */
                if (ANOMALY_05000242 || bfin_read_PLL_CTL() != CONFIG_PLL_CTL_VAL) {
-                       serial_putc('!');
+                       serial_putc('?');
                        bfin_write_PLL_CTL(CONFIG_PLL_CTL_VAL);
                        asm("idle;");
+                       serial_putc('!');
                }
 
-               serial_putc('L');
+               serial_putc('m');
 
                /* Restore all peripheral wakeups. */
 #ifdef SIC_IWR0
@@ -433,9 +461,19 @@ void initcode(ADI_BOOT_DATA *bootstruct)
 #else
                bfin_write_SIC_IWR(-1);
 #endif
+
+               serial_putc('n');
        }
 
-       serial_putc('M');
+       serial_putc('o');
+
+       return vr_ctl;
+}
+
+__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).
@@ -443,6 +481,7 @@ void initcode(ADI_BOOT_DATA *bootstruct)
         * for dividing which means we'd generate a libgcc reference.
         */
        if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) {
+               serial_putc('b');
                unsigned int sdivR, vcoR;
                sdivR = bfin_read_PLL_DIV() & 0xf;
                vcoR = (bfin_read_PLL_CTL() >> 9) & 0x3f;
@@ -452,20 +491,38 @@ void initcode(ADI_BOOT_DATA *bootstruct)
                for (quotient = 0; dividend > 0; ++quotient)
                        dividend -= divisor;
                serial_early_put_div(quotient - ANOMALY_05000230);
+               serial_putc('c');
        }
 
-       serial_putc('N');
+       serial_putc('d');
+}
+
+__attribute__((always_inline)) static inline void
+program_memory_controller(ADI_BOOT_DATA *bs, bool put_into_srfs)
+{
+       serial_putc('a');
+
+       if (!CONFIG_MEM_SIZE)
+               return;
+
+       serial_putc('b');
 
        /* Program the external memory controller before we come out of
         * self-refresh.  This only works with our SDRAM controller.
         */
 #ifndef EBIU_RSTCTL
+# ifdef CONFIG_EBIU_SDRRC_VAL
        bfin_write_EBIU_SDRRC(CONFIG_EBIU_SDRRC_VAL);
+# endif
+# ifdef CONFIG_EBIU_SDBCTL_VAL
        bfin_write_EBIU_SDBCTL(CONFIG_EBIU_SDBCTL_VAL);
+# endif
+# ifdef CONFIG_EBIU_SDGCTL_VAL
        bfin_write_EBIU_SDGCTL(CONFIG_EBIU_SDGCTL_VAL);
+# endif
 #endif
 
-       serial_putc('O');
+       serial_putc('c');
 
        /* Now that we've reprogrammed, take things out of self refresh. */
        if (put_into_srfs)
@@ -475,7 +532,7 @@ void initcode(ADI_BOOT_DATA *bootstruct)
                bfin_write_EBIU_SDGCTL(bfin_read_EBIU_SDGCTL() & ~(SRFS));
 #endif
 
-       serial_putc('P');
+       serial_putc('d');
 
        /* Our DDR controller sucks and cannot be programmed while in
         * self-refresh.  So we have to pull it out before programming.
@@ -494,7 +551,18 @@ void initcode(ADI_BOOT_DATA *bootstruct)
 # endif
 #endif
 
-       serial_putc('Q');
+       serial_putc('e');
+}
+
+__attribute__((always_inline)) static inline void
+check_hibernation(ADI_BOOT_DATA *bs, u16 vr_ctl, bool put_into_srfs)
+{
+       serial_putc('a');
+
+       if (!CONFIG_MEM_SIZE)
+               return;
+
+       serial_putc('b');
 
        /* Are we coming out of hibernate (suspend to memory) ?
         * The memory layout is:
@@ -508,7 +576,7 @@ void initcode(ADI_BOOT_DATA *bootstruct)
                uint32_t *hibernate_magic = 0;
                __builtin_bfin_ssync(); /* make sure memory controller is done */
                if (hibernate_magic[0] == 0xDEADBEEF) {
-                       serial_putc('R');
+                       serial_putc('c');
                        bfin_write_EVT15(hibernate_magic[1]);
                        bfin_write_IMASK(EVT_IVG15);
                        __asm__ __volatile__ (
@@ -525,15 +593,24 @@ void initcode(ADI_BOOT_DATA *bootstruct)
                                : "p"(hibernate_magic), "d"(0x2000 /* jump.s 0 */)
                        );
                }
+               serial_putc('d');
        }
 
-       serial_putc('S');
+       serial_putc('e');
+}
+
+__attribute__((always_inline)) static inline void
+program_async_controller(ADI_BOOT_DATA *bs)
+{
+       serial_putc('a');
 
        /* 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);
 
+       serial_putc('b');
+
 #ifdef EBIU_MODE
        /* Not all parts have these additional MMRs. */
        bfin_write_EBIU_MBSCTL(CONFIG_EBIU_MBSCTL_VAL);
@@ -541,9 +618,49 @@ void initcode(ADI_BOOT_DATA *bootstruct)
        bfin_write_EBIU_FCTL(CONFIG_EBIU_FCTL_VAL);
 #endif
 
-       serial_putc('T');
+       serial_putc('c');
+}
+
+BOOTROM_CALLED_FUNC_ATTR
+void initcode(ADI_BOOT_DATA *bs)
+{
+       ADI_BOOT_DATA bootstruct_scratch;
+
+       serial_init();
+
+       serial_putc('A');
+
+       /* If the bootstruct is NULL, then it's because we're loading
+        * dynamically and not via LDR (bootrom).  So set the struct to
+        * some scratch space.
+        */
+       if (!bs)
+               bs = &bootstruct_scratch;
+
+       serial_putc('B');
+       bool put_into_srfs = maybe_self_refresh(bs);
+
+       serial_putc('C');
+       uint sdivB, divB, vcoB;
+       program_early_devices(bs, &sdivB, &divB, &vcoB);
+
+       serial_putc('D');
+       u16 vr_ctl = program_clocks(bs, put_into_srfs);
+
+       serial_putc('E');
+       update_serial_clocks(bs, sdivB, divB, vcoB);
+
+       serial_putc('F');
+       program_memory_controller(bs, put_into_srfs);
+
+       serial_putc('G');
+       check_hibernation(bs, vr_ctl, put_into_srfs);
+
+       serial_putc('H');
+       program_async_controller(bs);
 
 #ifdef CONFIG_BFIN_BOOTROM_USES_EVT1
+       serial_putc('I');
        /* tell the bootrom where our entry point is */
        if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS)
                bfin_write_EVT1(CONFIG_SYS_MONITOR_BASE);