X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=arch%2Fblackfin%2Fcpu%2Finitcode.c;h=fb3a101c7909c8876b05bbd28bc37979cc623c5d;hb=c68436fa427a69ea308d74c410067507d6c7103b;hp=5f80ad615e7e66d368d2c00c7303e1e16edcd71e;hpb=c6fb83d21729321426308c3acff2a3dfb20d250b;p=u-boot diff --git a/arch/blackfin/cpu/initcode.c b/arch/blackfin/cpu/initcode.c index 5f80ad615e..fb3a101c79 100644 --- a/arch/blackfin/cpu/initcode.c +++ b/arch/blackfin/cpu/initcode.c @@ -4,7 +4,7 @@ * cannot make any function calls as it may be executed all by itself by * the Blackfin's bootrom in LDR format. * - * Copyright (c) 2004-2008 Analog Devices Inc. + * Copyright (c) 2004-2011 Analog Devices Inc. * * Licensed under the GPL-2 or later. */ @@ -19,11 +19,15 @@ #include #include +#define BUG() while (1) { asm volatile("emuexcpt;"); } + #include "serial.h" __attribute__((always_inline)) static inline void serial_init(void) { + uint32_t uart_base = UART_DLL; + #ifdef __ADSPBF54x__ # ifdef BFIN_BOOT_UART_USE_RTS # define BFIN_UART_USE_RTS 1 @@ -65,13 +69,13 @@ static inline void serial_init(void) if (BFIN_DEBUG_EARLY_SERIAL) { int ucen = bfin_read16(&pUART->gctl) & UCEN; - serial_early_init(); + serial_early_init(uart_base); /* If the UART is off, that means we need to program * the baud rate ourselves initially. */ if (ucen != UCEN) - serial_early_set_baud(CONFIG_BAUDRATE); + serial_early_set_baud(uart_base, CONFIG_BAUDRATE); } } @@ -79,6 +83,8 @@ __attribute__((always_inline)) static inline void serial_deinit(void) { #ifdef __ADSPBF54x__ + uint32_t uart_base = UART_DLL; + if (BFIN_UART_USE_RTS && CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) { /* clear forced RTS rather than relying on auto RTS */ bfin_write16(&pUART->mcr, bfin_read16(&pUART->mcr) & ~FCPOL); @@ -89,6 +95,8 @@ static inline void serial_deinit(void) __attribute__((always_inline)) static inline void serial_putc(char c) { + uint32_t uart_base = UART_DLL; + if (!BFIN_DEBUG_EARLY_SERIAL) return; @@ -101,6 +109,30 @@ static inline void serial_putc(char c) continue; } +#include "initcode.h" + +__attribute__((always_inline)) static inline void +program_nmi_handler(void) +{ + u32 tmp1, tmp2; + + /* Older bootroms don't create a dummy NMI handler, + * so make one ourselves ASAP in case it fires. + */ + if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS && !ANOMALY_05000219) + return; + + asm volatile ( + "%0 = RETS;" /* Save current RETS */ + "CALL 1f;" /* Figure out current PC */ + "RTN;" /* The simple NMI handler */ + "1:" + "%1 = RETS;" /* Load addr of NMI handler */ + "RETS = %0;" /* Restore RETS */ + "[%2] = %1;" /* Write NMI handler */ + : "=r"(tmp1), "=r"(tmp2) : "ab"(EVT2) + ); +} /* Max SCLK can be 133MHz ... dividing that by (2*4) gives * us a freq of 16MHz for SPI which should generally be @@ -144,21 +176,6 @@ static inline void serial_putc(char c) # define CONFIG_PLL_CTL_VAL (SPORT_HYST | (CONFIG_VCO_MULT << 9) | CONFIG_CLKIN_HALF) #endif -#ifndef CONFIG_EBIU_RSTCTL_VAL -# define CONFIG_EBIU_RSTCTL_VAL 0 /* only MDDRENABLE is useful */ -#endif -#if ((CONFIG_EBIU_RSTCTL_VAL & 0xFFFFFFC4) != 0) -# error invalid EBIU_RSTCTL value: must not set reserved bits -#endif - -#ifndef CONFIG_EBIU_MBSCTL_VAL -# define CONFIG_EBIU_MBSCTL_VAL 0 -#endif - -#if defined(CONFIG_EBIU_DDRQUE_VAL) && ((CONFIG_EBIU_DDRQUE_VAL & 0xFFFF8000) != 0) -# error invalid EBIU_DDRQUE value: must not set reserved bits -#endif - /* Make sure our voltage value is sane so we don't blow up! */ #ifndef CONFIG_VR_CTL_VAL # define BFIN_CCLK ((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT) / CONFIG_CCLK_DIV) @@ -319,13 +336,13 @@ maybe_self_refresh(ADI_BOOT_DATA *bs) return false; /* If external memory is enabled, put it into self refresh first. */ -#ifdef EBIU_RSTCTL +#if defined(EBIU_RSTCTL) if (bfin_read_EBIU_RSTCTL() & DDR_SRESET) { serial_putc('b'); bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() | SRREQ); return true; } -#else +#elif defined(EBIU_SDGCTL) if (bfin_read_EBIU_SDBCTL() & EBE) { serial_putc('b'); bfin_write_EBIU_SDGCTL(bfin_read_EBIU_SDGCTL() | SRFS); @@ -351,12 +368,15 @@ program_clocks(ADI_BOOT_DATA *bs, bool put_into_srfs) /* If we're entering self refresh, make sure it has happened. */ if (put_into_srfs) -#ifdef EBIU_RSTCTL +#if defined(EBIU_RSTCTL) while (!(bfin_read_EBIU_RSTCTL() & SRACK)) -#else + continue; +#elif defined(EBIU_SDGCTL) while (!(bfin_read_EBIU_SDSTAT() & SDSRA)) -#endif continue; +#else + ; +#endif serial_putc('c'); @@ -369,7 +389,9 @@ program_clocks(ADI_BOOT_DATA *bs, bool put_into_srfs) /* Always programming PLL_LOCKCNT avoids Anomaly 05000430 */ ADI_SYSCTRL_VALUES memory_settings; - uint32_t actions = SYSCTRL_WRITE | SYSCTRL_PLLCTL | SYSCTRL_PLLDIV | SYSCTRL_LOCKCNT; + uint32_t actions = SYSCTRL_WRITE | SYSCTRL_PLLCTL | SYSCTRL_LOCKCNT; + if (!ANOMALY_05000440) + actions |= SYSCTRL_PLLDIV; if (CONFIG_HAS_VR) { actions |= SYSCTRL_VRCTL; if (CONFIG_VR_CTL_VAL & FREQ_MASK) @@ -388,6 +410,8 @@ program_clocks(ADI_BOOT_DATA *bs, bool put_into_srfs) serial_putc('e'); bfrom_SysControl(actions, &memory_settings, NULL); serial_putc('f'); + if (ANOMALY_05000440) + bfin_write_PLL_DIV(CONFIG_PLL_DIV_VAL); #if ANOMALY_05000432 bfin_write_SIC_IWR1(-1); #endif @@ -490,7 +514,7 @@ update_serial_clocks(ADI_BOOT_DATA *bs, uint sdivB, uint divB, uint vcoB) unsigned int quotient; for (quotient = 0; dividend > 0; ++quotient) dividend -= divisor; - serial_early_put_div(quotient - ANOMALY_05000230); + serial_early_put_div(UART_DLL, quotient - ANOMALY_05000230); serial_putc('c'); } @@ -510,7 +534,7 @@ program_memory_controller(ADI_BOOT_DATA *bs, bool put_into_srfs) /* Program the external memory controller before we come out of * self-refresh. This only works with our SDRAM controller. */ -#ifndef EBIU_RSTCTL +#ifdef EBIU_SDGCTL # ifdef CONFIG_EBIU_SDRRC_VAL bfin_write_EBIU_SDRRC(CONFIG_EBIU_SDRRC_VAL); # endif @@ -526,9 +550,9 @@ program_memory_controller(ADI_BOOT_DATA *bs, bool put_into_srfs) /* Now that we've reprogrammed, take things out of self refresh. */ if (put_into_srfs) -#ifdef EBIU_RSTCTL +#if defined(EBIU_RSTCTL) bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() & ~(SRREQ)); -#else +#elif defined(EBIU_SDGCTL) bfin_write_EBIU_SDGCTL(bfin_read_EBIU_SDGCTL() & ~(SRFS)); #endif @@ -607,39 +631,14 @@ check_hibernation(ADI_BOOT_DATA *bs, u16 vr_ctl, bool put_into_srfs) 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'); - - /* Not all parts have these additional MMRs. */ -#ifdef EBIU_MODE -# ifdef CONFIG_EBIU_MBSCTL_VAL - bfin_write_EBIU_MBSCTL(CONFIG_EBIU_MBSCTL_VAL); -# endif -# ifdef CONFIG_EBIU_MODE_VAL - bfin_write_EBIU_MODE(CONFIG_EBIU_MODE_VAL); -# endif -# ifdef CONFIG_EBIU_FCTL_VAL - bfin_write_EBIU_FCTL(CONFIG_EBIU_FCTL_VAL); -# endif -#endif - - serial_putc('c'); -} - BOOTROM_CALLED_FUNC_ATTR void initcode(ADI_BOOT_DATA *bs) { ADI_BOOT_DATA bootstruct_scratch; + /* Setup NMI handler before anything else */ + program_nmi_handler(); + serial_init(); serial_putc('A'); @@ -675,7 +674,12 @@ void initcode(ADI_BOOT_DATA *bs) #ifdef CONFIG_BFIN_BOOTROM_USES_EVT1 serial_putc('I'); - /* tell the bootrom where our entry point is */ + /* Tell the bootrom where our entry point is so that it knows + * where to jump to when finishing processing the LDR. This + * allows us to avoid small jump blocks in the LDR, and also + * works around anomaly 05000389 (init address in external + * memory causes bootrom to trigger external addressing IVHW). + */ if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS) bfin_write_EVT1(CONFIG_SYS_MONITOR_BASE); #endif