diff options
author | Wolfgang Denk <wd@denx.de> | 2011-08-02 21:46:53 +0200 |
---|---|---|
committer | Wolfgang Denk <wd@denx.de> | 2011-08-02 21:46:53 +0200 |
commit | 1902692aa0b2dcbb9351172be03c57d1e82447e4 (patch) | |
tree | f6250202aaa6e98a7beaa08841a55b9e2d54d670 /arch/blackfin/cpu | |
parent | cc4e6d25561b1aaa8501fa6017a0d17fd4f92ed6 (diff) | |
parent | d8940a654435dfa48013229edf53bd3e353e97c1 (diff) | |
download | u-boot-imx-1902692aa0b2dcbb9351172be03c57d1e82447e4.zip u-boot-imx-1902692aa0b2dcbb9351172be03c57d1e82447e4.tar.gz u-boot-imx-1902692aa0b2dcbb9351172be03c57d1e82447e4.tar.bz2 |
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/.gitignore | 3 | ||||
-rw-r--r-- | arch/blackfin/cpu/Makefile | 7 | ||||
-rw-r--r-- | arch/blackfin/cpu/cpu.c | 16 | ||||
-rw-r--r-- | arch/blackfin/cpu/gpio.c | 2 | ||||
-rw-r--r-- | arch/blackfin/cpu/init.S | 9 | ||||
-rw-r--r-- | arch/blackfin/cpu/init.lds.S | 25 | ||||
-rw-r--r-- | arch/blackfin/cpu/initcode.c | 61 | ||||
-rw-r--r-- | arch/blackfin/cpu/initcode.h | 71 | ||||
-rw-r--r-- | arch/blackfin/cpu/jtag-console.c | 4 | ||||
-rw-r--r-- | arch/blackfin/cpu/reset.c | 4 | ||||
-rw-r--r-- | arch/blackfin/cpu/serial.c | 234 | ||||
-rw-r--r-- | arch/blackfin/cpu/serial.h | 70 | ||||
-rw-r--r-- | arch/blackfin/cpu/start.S | 1 |
13 files changed, 367 insertions, 140 deletions
diff --git a/arch/blackfin/cpu/.gitignore b/arch/blackfin/cpu/.gitignore index 0ec9d56..ba986d8 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 df10f1b..5deaa9e 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 18dbdf7..6a0bcca 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 cb96721..5674d42 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 0000000..f48c113 --- /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 0000000..602e7c8 --- /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 750add0..fb3a101 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 0000000..e0aad6d --- /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 e0f2975..a77358a 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 e23dcc7..ff39035 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 650202e..030160f 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 7999a19..8a076dd 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 15ecb1e..90b4d1a 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" |