aboutsummaryrefslogtreecommitdiff
path: root/arch/blackfin/cpu
diff options
context:
space:
mode:
authorWolfgang Denk <wd@denx.de>2011-08-02 21:46:53 +0200
committerWolfgang Denk <wd@denx.de>2011-08-02 21:46:53 +0200
commit1902692aa0b2dcbb9351172be03c57d1e82447e4 (patch)
treef6250202aaa6e98a7beaa08841a55b9e2d54d670 /arch/blackfin/cpu
parentcc4e6d25561b1aaa8501fa6017a0d17fd4f92ed6 (diff)
parentd8940a654435dfa48013229edf53bd3e353e97c1 (diff)
Merge branch 'master' of git://git.denx.de/u-boot-blackfin
* 'master' of git://git.denx.de/u-boot-blackfin: Blackfin: jtag-console: fix timer usage Blackfin: switch to common display_options() Blackfin: serial: move early debug strings into .rodata section Blackfin: adi boards: also set stderr to nc with helper Blackfin: update anomaly lists to latest public info Blackfin: serial: convert to bfin_{read,write} helpers Blackfin: split out async setup Blackfin: adi boards: enable pretty flash progress output Blackfin: drop unused dma.h header from start code Blackfin: portmux: allow header to be included in assembly files Blackfin: cm-bf537e/cm-bf537u/tcm-bf537: enable mmc_spi support Blackfin: cm-bf537e/cm-bf537u/tcm-bf537: update network settings Blackfin: sync MMR read/write helpers with Linux Blackfin: gpio: optimize free path a little Blackfin: post: setup default CONFIG_SYS_POST_WORD_ADDR Blackfin: uart: fix printf warning Blackfin: add init.elf helper code Blackfin: dont reset SWRST on newer bf526 parts Blackfin: adi boards: enable multi serial support by default Blackfin: uart: add multiple serial support Blackfin: uart: move debug buffers into local bss
Diffstat (limited to 'arch/blackfin/cpu')
-rw-r--r--arch/blackfin/cpu/.gitignore3
-rw-r--r--arch/blackfin/cpu/Makefile7
-rw-r--r--arch/blackfin/cpu/cpu.c16
-rw-r--r--arch/blackfin/cpu/gpio.c2
-rw-r--r--arch/blackfin/cpu/init.S9
-rw-r--r--arch/blackfin/cpu/init.lds.S25
-rw-r--r--arch/blackfin/cpu/initcode.c61
-rw-r--r--arch/blackfin/cpu/initcode.h71
-rw-r--r--arch/blackfin/cpu/jtag-console.c4
-rw-r--r--arch/blackfin/cpu/reset.c4
-rw-r--r--arch/blackfin/cpu/serial.c234
-rw-r--r--arch/blackfin/cpu/serial.h70
-rw-r--r--arch/blackfin/cpu/start.S1
13 files changed, 367 insertions, 140 deletions
diff --git a/arch/blackfin/cpu/.gitignore b/arch/blackfin/cpu/.gitignore
index 0ec9d5672..ba986d8ba 100644
--- a/arch/blackfin/cpu/.gitignore
+++ b/arch/blackfin/cpu/.gitignore
@@ -1 +1,4 @@
bootrom-asm-offsets.[chs]
+
+init.lds
+init.elf
diff --git a/arch/blackfin/cpu/Makefile b/arch/blackfin/cpu/Makefile
index df10f1bc6..5deaa9e6a 100644
--- a/arch/blackfin/cpu/Makefile
+++ b/arch/blackfin/cpu/Makefile
@@ -13,7 +13,7 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(CPU).o
-EXTRA :=
+EXTRA := init.elf
CEXTRA := initcode.o
SEXTRA := start.o
SOBJS := interrupt.o cache.o
@@ -61,6 +61,11 @@ ifneq ($(CONFIG_BFIN_BOOT_MODE),BFIN_BOOT_BYPASS)
fi
endif
+$(obj)init.lds: init.lds.S
+ $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -ansi -D__ASSEMBLY__ -P $^ -o $@
+$(obj)init.elf: $(obj)init.lds $(obj)init.o $(obj)initcode.o
+ $(LD) $(LDFLAGS) -T $^ -o $@
+
#########################################################################
# defines $(obj).depend target
diff --git a/arch/blackfin/cpu/cpu.c b/arch/blackfin/cpu/cpu.c
index 18dbdf7ab..6a0bcca9f 100644
--- a/arch/blackfin/cpu/cpu.c
+++ b/arch/blackfin/cpu/cpu.c
@@ -19,6 +19,7 @@
#include "cpu.h"
#include "serial.h"
+#include "initcode.h"
ulong bfin_poweron_retx;
@@ -44,13 +45,16 @@ void cpu_init_f(ulong bootflag, ulong loaded_from_ldr)
extern char _sdata_l1[], _data_l1_lma[], _data_l1_len[];
memcpy(&_sdata_l1, &_data_l1_lma, (unsigned long)_data_l1_len);
}
-#if defined(__ADSPBF537__) || defined(__ADSPBF536__) || defined(__ADSPBF534__)
- /* The BF537 bootrom will reset the EBIU_AMGCTL register on us
- * after it has finished loading the LDR. So configure it again.
+
+ /*
+ * Make sure our async settings are committed. Some bootroms
+ * (like the BF537) will reset some registers on us after it
+ * has finished loading the LDR. Or if we're booting over
+ * JTAG, the initcode never got a chance to run. Or if we
+ * aren't booting from parallel flash, the initcode skipped
+ * this step completely.
*/
- else
- bfin_write_EBIU_AMGCTL(CONFIG_EBIU_AMGCTL_VAL);
-#endif
+ program_async_controller(NULL);
/* Save RETX so we can pass it while booting Linux */
bfin_poweron_retx = bootflag;
diff --git a/arch/blackfin/cpu/gpio.c b/arch/blackfin/cpu/gpio.c
index cb96721cf..5674d42b6 100644
--- a/arch/blackfin/cpu/gpio.c
+++ b/arch/blackfin/cpu/gpio.c
@@ -665,6 +665,7 @@ int bfin_gpio_request(unsigned gpio, const char *label)
return 0;
}
+#ifdef CONFIG_BFIN_GPIO_TRACK
void bfin_gpio_free(unsigned gpio)
{
if (check_gpio(gpio) < 0)
@@ -679,6 +680,7 @@ void bfin_gpio_free(unsigned gpio)
set_label(gpio, "free");
}
+#endif
#ifdef BFIN_SPECIAL_GPIO_BANKS
DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES));
diff --git a/arch/blackfin/cpu/init.S b/arch/blackfin/cpu/init.S
new file mode 100644
index 000000000..f48c11320
--- /dev/null
+++ b/arch/blackfin/cpu/init.S
@@ -0,0 +1,9 @@
+#include <asm/blackfin.h>
+ENTRY(_start)
+ sp.l = LO(L1_SRAM_SCRATCH_END - 20);
+ sp.h = HI(L1_SRAM_SCRATCH_END - 20);
+ call _initcode;
+1:
+ emuexcpt;
+ jump 1b;
+END(_start)
diff --git a/arch/blackfin/cpu/init.lds.S b/arch/blackfin/cpu/init.lds.S
new file mode 100644
index 000000000..602e7c879
--- /dev/null
+++ b/arch/blackfin/cpu/init.lds.S
@@ -0,0 +1,25 @@
+/*
+ * linker script for simple init.elf
+ *
+ * Copyright (c) 2005-2011 Analog Device Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <config.h>
+#include <asm/blackfin.h>
+#undef ALIGN
+#undef ENTRY
+
+OUTPUT_ARCH(bfin)
+
+MEMORY
+{
+ l1_code : ORIGIN = L1_INST_SRAM, LENGTH = L1_INST_SRAM_SIZE
+}
+
+ENTRY(_start)
+SECTIONS
+{
+ .text.l1 : { *(.text .text.*) } >l1_code
+}
diff --git a/arch/blackfin/cpu/initcode.c b/arch/blackfin/cpu/initcode.c
index 750add06b..fb3a101c7 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 <asm/mach-common/bits/pll.h>
#include <asm/mach-common/bits/uart.h>
+#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,8 @@ static inline void serial_putc(char c)
continue;
}
+#include "initcode.h"
+
__attribute__((always_inline)) static inline void
program_nmi_handler(void)
{
@@ -166,21 +176,6 @@ program_nmi_handler(void)
# 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)
@@ -519,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');
}
@@ -636,34 +631,6 @@ 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_MBSCTL
- bfin_write_EBIU_MBSCTL(CONFIG_EBIU_MBSCTL_VAL);
-#endif
-#ifdef EBIU_MODE
-# 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)
{
diff --git a/arch/blackfin/cpu/initcode.h b/arch/blackfin/cpu/initcode.h
new file mode 100644
index 000000000..e0aad6de0
--- /dev/null
+++ b/arch/blackfin/cpu/initcode.h
@@ -0,0 +1,71 @@
+/*
+ * Code for early processor initialization
+ *
+ * Copyright (c) 2004-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __BFIN_INITCODE_H__
+#define __BFIN_INITCODE_H__
+
+#include <asm/mach-common/bits/bootrom.h>
+
+#ifndef BFIN_IN_INITCODE
+# define serial_putc(c)
+#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
+
+__attribute__((always_inline)) static inline void
+program_async_controller(ADI_BOOT_DATA *bs)
+{
+#ifdef BFIN_IN_INITCODE
+ /*
+ * We really only need to setup the async banks early if we're
+ * booting out of it. Otherwise, do it later on in cpu_init.
+ */
+ if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS &&
+ CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_PARA)
+ return;
+#endif
+
+ 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_MBSCTL
+ bfin_write_EBIU_MBSCTL(CONFIG_EBIU_MBSCTL_VAL);
+#endif
+#ifdef EBIU_MODE
+# 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');
+}
+
+#endif
diff --git a/arch/blackfin/cpu/jtag-console.c b/arch/blackfin/cpu/jtag-console.c
index e0f297560..a77358a88 100644
--- a/arch/blackfin/cpu/jtag-console.c
+++ b/arch/blackfin/cpu/jtag-console.c
@@ -48,11 +48,11 @@ static inline uint32_t bfin_read_emudat(void)
static bool jtag_write_emudat(uint32_t emudat)
{
static bool overflowed = false;
- ulong timeout = get_timer(0) + CONFIG_JTAG_CONSOLE_TIMEOUT;
+ ulong timeout = get_timer(0);
while (bfin_read_DBGSTAT() & 0x1) {
if (overflowed)
return overflowed;
- if (timeout < get_timer(0))
+ if (get_timer(timeout) > CONFIG_JTAG_CONSOLE_TIMEOUT)
overflowed = true;
}
overflowed = false;
diff --git a/arch/blackfin/cpu/reset.c b/arch/blackfin/cpu/reset.c
index e23dcc7ba..ff39035de 100644
--- a/arch/blackfin/cpu/reset.c
+++ b/arch/blackfin/cpu/reset.c
@@ -51,7 +51,9 @@ static void bfin_reset(void)
/* The BF526 ROM will crash during reset */
#if defined(__ADSPBF522__) || defined(__ADSPBF524__) || defined(__ADSPBF526__)
- bfin_read_SWRST();
+ /* Seems to be fixed with newer parts though ... */
+ if (__SILICON_REVISION__ < 1 && bfin_revid() < 1)
+ bfin_read_SWRST();
#endif
/* Wait for the SWRST write to complete. Cannot rely on SSYNC
diff --git a/arch/blackfin/cpu/serial.c b/arch/blackfin/cpu/serial.c
index 650202e24..030160f41 100644
--- a/arch/blackfin/cpu/serial.c
+++ b/arch/blackfin/cpu/serial.c
@@ -39,6 +39,8 @@
#include <common.h>
#include <watchdog.h>
+#include <serial.h>
+#include <linux/compiler.h>
#include <asm/blackfin.h>
#include <asm/mach-common/bits/uart.h>
@@ -49,9 +51,9 @@ DECLARE_GLOBAL_DATA_PTR;
#include "serial.h"
#ifdef CONFIG_DEBUG_SERIAL
-uint16_t cached_lsr[256];
-uint16_t cached_rbr[256];
-size_t cache_count;
+static uint16_t cached_lsr[256];
+static uint16_t cached_rbr[256];
+static size_t cache_count;
/* The LSR is read-to-clear on some parts, so we have to make sure status
* bits aren't inadvertently lost when doing various tests. This also
@@ -59,68 +61,34 @@ size_t cache_count;
* tally of all the status bits.
*/
static uint16_t uart_lsr_save;
-static uint16_t uart_lsr_read(void)
+static uint16_t uart_lsr_read(uint32_t uart_base)
{
- uint16_t lsr = bfin_read16(&pUART->lsr);
+ uint16_t lsr = bfin_read(&pUART->lsr);
uart_lsr_save |= (lsr & (OE|PE|FE|BI));
return lsr | uart_lsr_save;
}
/* Just do the clear for everyone since it can't hurt. */
-static void uart_lsr_clear(void)
+static void uart_lsr_clear(uint32_t uart_base)
{
uart_lsr_save = 0;
- bfin_write16(&pUART->lsr, bfin_read16(&pUART->lsr) | -1);
+ bfin_write(&pUART->lsr, bfin_read(&pUART->lsr) | -1);
}
#else
/* When debugging is disabled, we only care about the DR bit, so if other
* bits get set/cleared, we don't really care since we don't read them
* anyways (and thus anomaly 05000099 is irrelevant).
*/
-static uint16_t uart_lsr_read(void)
+static inline uint16_t uart_lsr_read(uint32_t uart_base)
{
- return bfin_read16(&pUART->lsr);
+ return bfin_read(&pUART->lsr);
}
-static void uart_lsr_clear(void)
+static void uart_lsr_clear(uint32_t uart_base)
{
- bfin_write16(&pUART->lsr, bfin_read16(&pUART->lsr) | -1);
+ bfin_write(&pUART->lsr, bfin_read(&pUART->lsr) | -1);
}
#endif
-/* Symbol for our assembly to call. */
-void serial_set_baud(uint32_t baud)
-{
- serial_early_set_baud(baud);
-}
-
-/* Symbol for common u-boot code to call.
- * Setup the baudrate (brg: baudrate generator).
- */
-void serial_setbrg(void)
-{
- serial_set_baud(gd->baudrate);
-}
-
-/* Symbol for our assembly to call. */
-void serial_initialize(void)
-{
- serial_early_init();
-}
-
-/* Symbol for common u-boot code to call. */
-int serial_init(void)
-{
- serial_initialize();
- serial_setbrg();
- uart_lsr_clear();
-#ifdef CONFIG_DEBUG_SERIAL
- cache_count = 0;
- memset(cached_lsr, 0x00, sizeof(cached_lsr));
- memset(cached_rbr, 0x00, sizeof(cached_rbr));
-#endif
- return 0;
-}
-
-void serial_putc(const char c)
+static void uart_putc(uint32_t uart_base, const char c)
{
/* send a \r for compatibility */
if (c == '\n')
@@ -129,36 +97,36 @@ void serial_putc(const char c)
WATCHDOG_RESET();
/* wait for the hardware fifo to clear up */
- while (!(uart_lsr_read() & THRE))
+ while (!(uart_lsr_read(uart_base) & THRE))
continue;
/* queue the character for transmission */
- bfin_write16(&pUART->thr, c);
+ bfin_write(&pUART->thr, c);
SSYNC();
WATCHDOG_RESET();
}
-int serial_tstc(void)
+static int uart_tstc(uint32_t uart_base)
{
WATCHDOG_RESET();
- return (uart_lsr_read() & DR) ? 1 : 0;
+ return (uart_lsr_read(uart_base) & DR) ? 1 : 0;
}
-int serial_getc(void)
+static int uart_getc(uint32_t uart_base)
{
uint16_t uart_rbr_val;
/* wait for data ! */
- while (!serial_tstc())
+ while (!uart_tstc(uart_base))
continue;
/* grab the new byte */
- uart_rbr_val = bfin_read16(&pUART->rbr);
+ uart_rbr_val = bfin_read(&pUART->rbr);
#ifdef CONFIG_DEBUG_SERIAL
/* grab & clear the LSR */
- uint16_t uart_lsr_val = uart_lsr_read();
+ uint16_t uart_lsr_val = uart_lsr_read(uart_base);
cached_lsr[cache_count] = uart_lsr_val;
cached_rbr[cache_count] = uart_rbr_val;
@@ -168,23 +136,171 @@ int serial_getc(void)
uint16_t dll, dlh;
printf("\n[SERIAL ERROR]\n");
ACCESS_LATCH();
- dll = bfin_read16(&pUART->dll);
- dlh = bfin_read16(&pUART->dlh);
+ dll = bfin_read(&pUART->dll);
+ dlh = bfin_read(&pUART->dlh);
ACCESS_PORT_IER();
printf("\tDLL=0x%x DLH=0x%x\n", dll, dlh);
do {
--cache_count;
- printf("\t%3i: RBR=0x%02x LSR=0x%02x\n", cache_count,
+ printf("\t%3zu: RBR=0x%02x LSR=0x%02x\n", cache_count,
cached_rbr[cache_count], cached_lsr[cache_count]);
} while (cache_count > 0);
return -1;
}
#endif
- uart_lsr_clear();
+ uart_lsr_clear(uart_base);
return uart_rbr_val;
}
+#ifdef CONFIG_SYS_BFIN_UART
+
+static void uart_puts(uint32_t uart_base, const char *s)
+{
+ while (*s)
+ uart_putc(uart_base, *s++);
+}
+
+#define DECL_BFIN_UART(n) \
+static int uart##n##_init(void) \
+{ \
+ const unsigned short pins[] = { _P_UART(n, RX), _P_UART(n, TX), 0, }; \
+ peripheral_request_list(pins, "bfin-uart"); \
+ uart_init(MMR_UART(n)); \
+ serial_early_set_baud(MMR_UART(n), gd->baudrate); \
+ uart_lsr_clear(MMR_UART(n)); \
+ return 0; \
+} \
+\
+static int uart##n##_uninit(void) \
+{ \
+ return serial_early_uninit(MMR_UART(n)); \
+} \
+\
+static void uart##n##_setbrg(void) \
+{ \
+ serial_early_set_baud(MMR_UART(n), gd->baudrate); \
+} \
+\
+static int uart##n##_getc(void) \
+{ \
+ return uart_getc(MMR_UART(n)); \
+} \
+\
+static int uart##n##_tstc(void) \
+{ \
+ return uart_tstc(MMR_UART(n)); \
+} \
+\
+static void uart##n##_putc(const char c) \
+{ \
+ uart_putc(MMR_UART(n), c); \
+} \
+\
+static void uart##n##_puts(const char *s) \
+{ \
+ uart_puts(MMR_UART(n), s); \
+} \
+\
+struct serial_device bfin_serial##n##_device = { \
+ .name = "bfin_uart"#n, \
+ .init = uart##n##_init, \
+ .uninit = uart##n##_uninit, \
+ .setbrg = uart##n##_setbrg, \
+ .getc = uart##n##_getc, \
+ .tstc = uart##n##_tstc, \
+ .putc = uart##n##_putc, \
+ .puts = uart##n##_puts, \
+};
+
+#ifdef UART0_DLL
+DECL_BFIN_UART(0)
+#endif
+#ifdef UART1_DLL
+DECL_BFIN_UART(1)
+#endif
+#ifdef UART2_DLL
+DECL_BFIN_UART(2)
+#endif
+#ifdef UART3_DLL
+DECL_BFIN_UART(3)
+#endif
+
+__weak struct serial_device *default_serial_console(void)
+{
+#if CONFIG_UART_CONSOLE == 0
+ return &bfin_serial0_device;
+#elif CONFIG_UART_CONSOLE == 1
+ return &bfin_serial1_device;
+#elif CONFIG_UART_CONSOLE == 2
+ return &bfin_serial2_device;
+#elif CONFIG_UART_CONSOLE == 3
+ return &bfin_serial3_device;
+#endif
+}
+
+void serial_register_bfin_uart(void)
+{
+#ifdef UART0_DLL
+ serial_register(&bfin_serial0_device);
+#endif
+#ifdef UART1_DLL
+ serial_register(&bfin_serial1_device);
+#endif
+#ifdef UART2_DLL
+ serial_register(&bfin_serial2_device);
+#endif
+#ifdef UART3_DLL
+ serial_register(&bfin_serial3_device);
+#endif
+}
+
+#else
+
+/* Symbol for our assembly to call. */
+void serial_set_baud(uint32_t baud)
+{
+ serial_early_set_baud(UART_DLL, baud);
+}
+
+/* Symbol for common u-boot code to call.
+ * Setup the baudrate (brg: baudrate generator).
+ */
+void serial_setbrg(void)
+{
+ serial_set_baud(gd->baudrate);
+}
+
+/* Symbol for our assembly to call. */
+void serial_initialize(void)
+{
+ serial_early_init(UART_DLL);
+}
+
+/* Symbol for common u-boot code to call. */
+int serial_init(void)
+{
+ serial_initialize();
+ serial_setbrg();
+ uart_lsr_clear(UART_DLL);
+ return 0;
+}
+
+int serial_tstc(void)
+{
+ return uart_tstc(UART_DLL);
+}
+
+int serial_getc(void)
+{
+ return uart_getc(UART_DLL);
+}
+
+void serial_putc(const char c)
+{
+ uart_putc(UART_DLL, c);
+}
+
void serial_puts(const char *s)
{
while (*s)
@@ -192,3 +308,5 @@ void serial_puts(const char *s)
}
#endif
+
+#endif
diff --git a/arch/blackfin/cpu/serial.h b/arch/blackfin/cpu/serial.h
index 7999a1933..8a076ddc9 100644
--- a/arch/blackfin/cpu/serial.h
+++ b/arch/blackfin/cpu/serial.h
@@ -82,26 +82,28 @@ struct bfin_mmr_serial {
#define __PASTE_UART(num, pfx, sfx) pfx##num##_##sfx
#define _PASTE_UART(num, pfx, sfx) __PASTE_UART(num, pfx, sfx)
-#define MMR_UART(mmr) _PASTE_UART(CONFIG_UART_CONSOLE, UART, DLL)
-#define P_UART(pin) _PASTE_UART(CONFIG_UART_CONSOLE, P_UART, pin)
+#define MMR_UART(n) _PASTE_UART(n, UART, DLL)
+#define _P_UART(n, pin) _PASTE_UART(n, P_UART, pin)
+#define P_UART(pin) _P_UART(CONFIG_UART_CONSOLE, pin)
#ifndef UART_DLL
-# define UART_DLL MMR_UART(DLL)
+# define UART_DLL MMR_UART(CONFIG_UART_CONSOLE)
#else
+# define UART0_DLL UART_DLL
# if CONFIG_UART_CONSOLE != 0
# error CONFIG_UART_CONSOLE must be 0 on parts with only one UART
# endif
#endif
-#define pUART ((volatile struct bfin_mmr_serial *)UART_DLL)
+#define pUART ((volatile struct bfin_mmr_serial *)uart_base)
#if BFIN_UART_HW_VER == 2
# define ACCESS_LATCH()
# define ACCESS_PORT_IER()
#else
# define ACCESS_LATCH() \
- bfin_write16(&pUART->lcr, bfin_read16(&pUART->lcr) | DLAB)
+ bfin_write(&pUART->lcr, bfin_read(&pUART->lcr) | DLAB)
# define ACCESS_PORT_IER() \
- bfin_write16(&pUART->lcr, bfin_read16(&pUART->lcr) & ~DLAB)
+ bfin_write(&pUART->lcr, bfin_read(&pUART->lcr) & ~DLAB)
#endif
__attribute__((always_inline))
@@ -168,30 +170,47 @@ static inline void serial_do_portmux(void)
}
__attribute__((always_inline))
-static inline void serial_early_init(void)
+static inline int uart_init(uint32_t uart_base)
{
- /* handle portmux crap on different Blackfins */
- serial_do_portmux();
-
/* always enable UART -- avoids anomalies 05000309 and 05000350 */
- bfin_write16(&pUART->gctl, UCEN);
+ bfin_write(&pUART->gctl, UCEN);
/* Set LCR to Word Lengh 8-bit word select */
- bfin_write16(&pUART->lcr, WLS_8);
+ bfin_write(&pUART->lcr, WLS_8);
SSYNC();
+
+ return 0;
}
__attribute__((always_inline))
-static inline void serial_early_put_div(uint16_t divisor)
+static inline int serial_early_init(uint32_t uart_base)
+{
+ /* handle portmux crap on different Blackfins */
+ serial_do_portmux();
+
+ return uart_init(uart_base);
+}
+
+__attribute__((always_inline))
+static inline int serial_early_uninit(uint32_t uart_base)
+{
+ /* disable the UART by clearing UCEN */
+ bfin_write(&pUART->gctl, 0);
+
+ return 0;
+}
+
+__attribute__((always_inline))
+static inline void serial_early_put_div(uint32_t uart_base, uint16_t divisor)
{
/* Set DLAB in LCR to Access DLL and DLH */
ACCESS_LATCH();
SSYNC();
/* Program the divisor to get the baud rate we want */
- bfin_write16(&pUART->dll, LOB(divisor));
- bfin_write16(&pUART->dlh, HIB(divisor));
+ bfin_write(&pUART->dll, LOB(divisor));
+ bfin_write(&pUART->dlh, HIB(divisor));
SSYNC();
/* Clear DLAB in LCR to Access THR RBR IER */
@@ -202,12 +221,14 @@ static inline void serial_early_put_div(uint16_t divisor)
__attribute__((always_inline))
static inline uint16_t serial_early_get_div(void)
{
+ uint32_t uart_base = UART_DLL;
+
/* Set DLAB in LCR to Access DLL and DLH */
ACCESS_LATCH();
SSYNC();
- uint8_t dll = bfin_read16(&pUART->dll);
- uint8_t dlh = bfin_read16(&pUART->dlh);
+ uint8_t dll = bfin_read(&pUART->dll);
+ uint8_t dlh = bfin_read(&pUART->dlh);
uint16_t divisor = (dlh << 8) | dll;
/* Clear DLAB in LCR to Access THR RBR IER */
@@ -223,13 +244,14 @@ static inline uint16_t serial_early_get_div(void)
#endif
__attribute__((always_inline))
-static inline void serial_early_set_baud(uint32_t baud)
+static inline void serial_early_set_baud(uint32_t uart_base, uint32_t baud)
{
/* Translate from baud into divisor in terms of SCLK. The
* weird multiplication is to make sure we over sample just
* a little rather than under sample the incoming signals.
*/
- serial_early_put_div((get_sclk() + (baud * 8)) / (baud * 16) - ANOMALY_05000230);
+ serial_early_put_div(uart_base,
+ (get_sclk() + (baud * 8)) / (baud * 16) - ANOMALY_05000230);
}
#ifndef BFIN_IN_INITCODE
@@ -266,16 +288,16 @@ static inline void serial_early_puts(const char *s)
*/
#ifdef CONFIG_DEBUG_EARLY_SERIAL
# define serial_early_puts(str) \
- call _get_pc; \
- jump 1f; \
+ .section .rodata; \
+ 7: \
.ascii "Early:"; \
.ascii __FILE__; \
.ascii ": "; \
.ascii str; \
.asciz "\n"; \
- .align 4; \
-1: \
- R0 += 2; \
+ .previous; \
+ R0.L = 7b; \
+ R0.H = 7b; \
call _serial_puts;
#else
# define serial_early_puts(str)
diff --git a/arch/blackfin/cpu/start.S b/arch/blackfin/cpu/start.S
index 15ecb1e8e..90b4d1ae9 100644
--- a/arch/blackfin/cpu/start.S
+++ b/arch/blackfin/cpu/start.S
@@ -33,7 +33,6 @@
#include <config.h>
#include <asm/blackfin.h>
#include <asm/mach-common/bits/core.h>
-#include <asm/mach-common/bits/dma.h>
#include <asm/mach-common/bits/pll.h>
#include "serial.h"