diff options
author | Wolfgang Denk <wd@denx.de> | 2009-02-07 21:53:45 (GMT) |
---|---|---|
committer | Wolfgang Denk <wd@denx.de> | 2009-02-07 21:53:45 (GMT) |
commit | 045639397df535b7eac820b9dc3e4814ae16f19d (patch) | |
tree | d2959b011dca9b66ce497cc5d8dc7062d2576a8c /cpu | |
parent | 0ab5410a40930ed235a83161cd7e5a98c963ca91 (diff) | |
parent | 4b7e3d045cc82f7f7b6f3a19b54a814da36ac52c (diff) | |
download | u-boot-045639397df535b7eac820b9dc3e4814ae16f19d.tar.xz |
Merge branch 'master' of git://git.denx.de/u-boot-blackfin
Diffstat (limited to 'cpu')
-rw-r--r-- | cpu/blackfin/initcode.c | 157 | ||||
-rw-r--r-- | cpu/blackfin/serial.h | 72 |
2 files changed, 108 insertions, 121 deletions
diff --git a/cpu/blackfin/initcode.c b/cpu/blackfin/initcode.c index 6091f8c..ae0016d 100644 --- a/cpu/blackfin/initcode.c +++ b/cpu/blackfin/initcode.c @@ -20,7 +20,7 @@ #include "serial.h" __attribute__((always_inline)) -static inline uint32_t serial_init(void) +static inline void serial_init(void) { #ifdef __ADSPBF54x__ # ifdef BFIN_BOOT_UART_USE_RTS @@ -61,25 +61,16 @@ static inline uint32_t serial_init(void) } #endif - uint32_t old_baud; - if (BFIN_DEBUG_EARLY_SERIAL || CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) - old_baud = serial_early_get_baud(); - else - old_baud = CONFIG_BAUDRATE; - if (BFIN_DEBUG_EARLY_SERIAL) { + int ucen = *pUART_GCTL & UCEN; serial_early_init(); /* If the UART is off, that means we need to program * the baud rate ourselves initially. */ - if (!old_baud) { - old_baud = CONFIG_BAUDRATE; + if (ucen != UCEN) serial_early_set_baud(CONFIG_BAUDRATE); - } } - - return old_baud; } __attribute__((always_inline)) @@ -93,30 +84,6 @@ static inline void serial_deinit(void) #endif } -/* We need to reset the baud rate when we have early debug turned on - * or when we are booting over the UART. - * XXX: we should fix this to calc the old baud and restore it rather - * than hardcoding it via CONFIG_LDR_LOAD_BAUD ... but we have - * to figure out how to avoid the division in the baud calc ... - */ -__attribute__((always_inline)) -static inline void serial_reset_baud(uint32_t baud) -{ - if (!BFIN_DEBUG_EARLY_SERIAL && CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_UART) - return; - -#ifndef CONFIG_LDR_LOAD_BAUD -# define CONFIG_LDR_LOAD_BAUD 115200 -#endif - - if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS) - serial_early_set_baud(baud); - else if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) - serial_early_set_baud(CONFIG_LDR_LOAD_BAUD); - else - serial_early_set_baud(CONFIG_BAUDRATE); -} - __attribute__((always_inline)) static inline void serial_putc(char c) { @@ -133,12 +100,22 @@ static inline void serial_putc(char c) } -/* Max SCLK can be 133MHz ... dividing that by 4 gives - * us a freq of 33MHz for SPI which should generally be +/* Max SCLK can be 133MHz ... dividing that by (2*4) gives + * us a freq of 16MHz for SPI which should generally be * slow enough for the slow reads the bootrom uses. */ +#if !defined(CONFIG_SPI_FLASH_SLOW_READ) && \ + ((defined(__ADSPBF52x__) && __SILICON_REVISION__ >= 2) || \ + (defined(__ADSPBF54x__) && __SILICON_REVISION__ >= 1)) +# define BOOTROM_SUPPORTS_SPI_FAST_READ 1 +#else +# define BOOTROM_SUPPORTS_SPI_FAST_READ 0 +#endif #ifndef CONFIG_SPI_BAUD_INITBLOCK -# define CONFIG_SPI_BAUD_INITBLOCK 4 +# define CONFIG_SPI_BAUD_INITBLOCK (BOOTROM_SUPPORTS_SPI_FAST_READ ? 2 : 4) +#endif +#ifdef SPI0_BAUD +# define bfin_write_SPI_BAUD bfin_write_SPI0_BAUD #endif /* PLL_DIV defines */ @@ -168,11 +145,18 @@ static inline void serial_putc(char c) #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) @@ -199,6 +183,9 @@ static inline void serial_putc(char c) # elif defined(__ADSPBF54x__) /* TBD; use default */ # undef CONFIG_VR_CTL_VLEV # define CONFIG_VR_CTL_VLEV VLEV_120 +# elif defined(__ADSPBF538__) || defined(__ADSPBF539__) /* TBD; use default */ +# undef CONFIG_VR_CTL_VLEV +# define CONFIG_VR_CTL_VLEV VLEV_125 # endif # ifdef CONFIG_BFIN_MAC @@ -216,10 +203,17 @@ static inline void serial_putc(char c) # define CONFIG_VR_CTL_VAL (CONFIG_VR_CTL_CLKBUF | CONFIG_VR_CTL_VLEV | CONFIG_VR_CTL_FREQ) #endif -__attribute__((saveall)) +BOOTROM_CALLED_FUNC_ATTR void initcode(ADI_BOOT_DATA *bootstruct) { - uint32_t old_baud = serial_init(); + /* 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(); + } #ifdef CONFIG_HW_WATCHDOG # ifndef CONFIG_HW_WATCHDOG_TIMEOUT_INITCODE @@ -244,12 +238,11 @@ void initcode(ADI_BOOT_DATA *bootstruct) * 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) -#ifdef SPI0_BAUD - bfin_write_SPI0_BAUD(CONFIG_SPI_BAUD_INITBLOCK); -#else + 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); -#endif + } serial_putc('B'); @@ -267,40 +260,68 @@ void initcode(ADI_BOOT_DATA *bootstruct) bfin_write_SIC_IWR(1); #endif - serial_putc('L'); + /* With newer bootroms, we use the helper function to set up + * the memory controller. Older bootroms lacks such helpers + * so we do it ourselves. + */ + if (BOOTROM_CAPS_SYSCONTROL) { + serial_putc('S'); + + ADI_SYSCTRL_VALUES memory_settings; + memory_settings.uwVrCtl = CONFIG_VR_CTL_VAL; + memory_settings.uwPllCtl = CONFIG_PLL_CTL_VAL; + memory_settings.uwPllDiv = CONFIG_PLL_DIV_VAL; + memory_settings.uwPllLockCnt = CONFIG_PLL_LOCKCNT_VAL; + syscontrol(SYSCTRL_WRITE | SYSCTRL_VRCTL | SYSCTRL_PLLCTL | SYSCTRL_PLLDIV | SYSCTRL_LOCKCNT | + (CONFIG_VR_CTL_VAL & FREQ_MASK ? SYSCTRL_INTVOLTAGE : SYSCTRL_EXTVOLTAGE), &memory_settings, NULL); + } else { + serial_putc('L'); - bfin_write_PLL_LOCKCNT(CONFIG_PLL_LOCKCNT_VAL); + bfin_write_PLL_LOCKCNT(CONFIG_PLL_LOCKCNT_VAL); - serial_putc('A'); + serial_putc('A'); - /* Only reprogram when needed to avoid triggering unnecessary - * PLL relock sequences. - */ - if (bfin_read_VR_CTL() != CONFIG_VR_CTL_VAL) { - serial_putc('!'); - bfin_write_VR_CTL(CONFIG_VR_CTL_VAL); - asm("idle;"); - } + /* Only reprogram when needed to avoid triggering unnecessary + * PLL relock sequences. + */ + if (bfin_read_VR_CTL() != CONFIG_VR_CTL_VAL) { + serial_putc('!'); + bfin_write_VR_CTL(CONFIG_VR_CTL_VAL); + asm("idle;"); + } - serial_putc('C'); + serial_putc('C'); - bfin_write_PLL_DIV(CONFIG_PLL_DIV_VAL); + bfin_write_PLL_DIV(CONFIG_PLL_DIV_VAL); - serial_putc('K'); + serial_putc('K'); - /* Only reprogram when needed to avoid triggering unnecessary - * PLL relock sequences. - */ - if (bfin_read_PLL_CTL() != CONFIG_PLL_CTL_VAL) { - serial_putc('!'); - bfin_write_PLL_CTL(CONFIG_PLL_CTL_VAL); - asm("idle;"); + /* Only reprogram when needed to avoid triggering unnecessary + * PLL relock sequences. + */ + if (bfin_read_PLL_CTL() != CONFIG_PLL_CTL_VAL) { + serial_putc('!'); + bfin_write_PLL_CTL(CONFIG_PLL_CTL_VAL); + asm("idle;"); + } } /* 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. */ - serial_reset_baud(old_baud); + if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) { + unsigned int sdivR, vcoR; + sdivR = bfin_read_PLL_DIV() & 0xf; + vcoR = (bfin_read_PLL_CTL() >> 9) & 0x3f; + int dividend = sdivB * divB * vcoR; + int divisor = vcoB * sdivR; + unsigned int quotient; + for (quotient = 0; dividend > 0; ++quotient) + dividend -= divisor; + serial_early_put_div(quotient - ANOMALY_05000230); + } serial_putc('F'); diff --git a/cpu/blackfin/serial.h b/cpu/blackfin/serial.h index f671096..ce39148 100644 --- a/cpu/blackfin/serial.h +++ b/cpu/blackfin/serial.h @@ -156,16 +156,25 @@ static inline void serial_early_init(void) } __attribute__((always_inline)) -static inline uint32_t serial_early_get_baud(void) +static inline void serial_early_put_div(uint16_t divisor) { - /* If the UART isnt enabled, then we are booting an LDR - * from a non-UART source (so like flash) which means - * the baud rate here is meaningless. - */ - if ((*pUART_GCTL & UCEN) != UCEN) - return 0; + /* Set DLAB in LCR to Access DLL and DLH */ + ACCESS_LATCH(); + SSYNC(); -#if (0) /* See comment for serial_reset_baud() in initcode.c */ + /* Program the divisor to get the baud rate we want */ + *pUART_DLL = LOB(divisor); + *pUART_DLH = HIB(divisor); + SSYNC(); + + /* Clear DLAB in LCR to Access THR RBR IER */ + ACCESS_PORT_IER(); + SSYNC(); +} + +__attribute__((always_inline)) +static inline uint16_t serial_early_get_div(void) +{ /* Set DLAB in LCR to Access DLL and DLH */ ACCESS_LATCH(); SSYNC(); @@ -173,16 +182,12 @@ static inline uint32_t serial_early_get_baud(void) uint8_t dll = *pUART_DLL; uint8_t dlh = *pUART_DLH; uint16_t divisor = (dlh << 8) | dll; - uint32_t baud = get_sclk() / (divisor * 16); /* Clear DLAB in LCR to Access THR RBR IER */ ACCESS_PORT_IER(); SSYNC(); - return baud; -#else - return CONFIG_BAUDRATE; -#endif + return divisor; } __attribute__((always_inline)) @@ -192,20 +197,7 @@ static inline void serial_early_set_baud(uint32_t baud) * weird multiplication is to make sure we over sample just * a little rather than under sample the incoming signals. */ - uint16_t divisor = (get_sclk() + (baud * 8)) / (baud * 16) - ANOMALY_05000230; - - /* Set DLAB in LCR to Access DLL and DLH */ - ACCESS_LATCH(); - SSYNC(); - - /* Program the divisor to get the baud rate we want */ - *pUART_DLL = LOB(divisor); - *pUART_DLH = HIB(divisor); - SSYNC(); - - /* Clear DLAB in LCR to Access THR RBR IER */ - ACCESS_PORT_IER(); - SSYNC(); + serial_early_put_div((get_sclk() + (baud * 8)) / (baud * 16) - ANOMALY_05000230); } #ifndef BFIN_IN_INITCODE @@ -235,32 +227,6 @@ static inline void serial_early_puts(const char *s) #endif .endm -/* Recursively expand calls to _serial_putc for every byte - * passed to us. Append a newline when we're all done. - */ -.macro _serial_early_putc byte:req morebytes:vararg -#ifdef CONFIG_DEBUG_EARLY_SERIAL - R0 = \byte; - call _serial_putc; -.ifnb \morebytes - _serial_early_putc \morebytes -.else -.if (\byte != '\n') - _serial_early_putc '\n' -.endif -.endif -#endif -.endm - -/* Wrapper around recurisve _serial_early_putc macro which - * simply prepends the string "Early: " - */ -.macro serial_early_putc byte:req morebytes:vararg -#ifdef CONFIG_DEBUG_EARLY_SERIAL - _serial_early_putc 'E', 'a', 'r', 'l', 'y', ':', ' ', \byte, \morebytes -#endif -.endm - /* Since we embed the string right into our .text section, we need * to find its address. We do this by getting our PC and adding 2 * bytes (which is the length of the jump instruction). Then we |