summaryrefslogtreecommitdiff
path: root/cpu/blackfin
diff options
context:
space:
mode:
authorWolfgang Denk <wd@denx.de>2009-02-07 22:53:45 +0100
committerWolfgang Denk <wd@denx.de>2009-02-07 22:53:45 +0100
commit045639397df535b7eac820b9dc3e4814ae16f19d (patch)
treed2959b011dca9b66ce497cc5d8dc7062d2576a8c /cpu/blackfin
parent0ab5410a40930ed235a83161cd7e5a98c963ca91 (diff)
parent4b7e3d045cc82f7f7b6f3a19b54a814da36ac52c (diff)
downloadu-boot-imx-045639397df535b7eac820b9dc3e4814ae16f19d.zip
u-boot-imx-045639397df535b7eac820b9dc3e4814ae16f19d.tar.gz
u-boot-imx-045639397df535b7eac820b9dc3e4814ae16f19d.tar.bz2
Merge branch 'master' of git://git.denx.de/u-boot-blackfin
Diffstat (limited to 'cpu/blackfin')
-rw-r--r--cpu/blackfin/initcode.c157
-rw-r--r--cpu/blackfin/serial.h72
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