diff options
Diffstat (limited to 'arch/sparc/cpu/leon2')
-rw-r--r-- | arch/sparc/cpu/leon2/serial.c | 125 | ||||
-rw-r--r-- | arch/sparc/cpu/leon2/start.S | 60 |
2 files changed, 100 insertions, 85 deletions
diff --git a/arch/sparc/cpu/leon2/serial.c b/arch/sparc/cpu/leon2/serial.c index 5cfbb9ed15..603364ee0b 100644 --- a/arch/sparc/cpu/leon2/serial.c +++ b/arch/sparc/cpu/leon2/serial.c @@ -1,72 +1,78 @@ /* GRLIB APBUART Serial controller driver * - * (C) Copyright 2008 - * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * (C) Copyright 2008, 2015 + * Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com. * * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> -#include <asm/processor.h> -#include <asm/leon.h> +#include <asm/io.h> #include <serial.h> -#include <linux/compiler.h> +#include <watchdog.h> DECLARE_GLOBAL_DATA_PTR; +static unsigned leon2_serial_calc_scaler(unsigned freq, unsigned baud) +{ + return (((freq*10) / (baud*8)) - 5) / 10; +} + static int leon2_serial_init(void) { - LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; + LEON2_regs *leon2 = (LEON2_regs *)LEON2_PREGS; LEON2_Uart_regs *regs; unsigned int tmp; - /* Init LEON2 UART - * - * Set scaler / baud rate - * - * Receiver & transmitter enable - */ #if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 - regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; + regs = (LEON2_Uart_regs *)&leon2->UART_Channel_1; #else - regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; + regs = (LEON2_Uart_regs *)&leon2->UART_Channel_2; #endif - regs->UART_Scaler = CONFIG_SYS_LEON2_UART1_SCALER; + /* Set scaler / baud rate */ + tmp = leon2_serial_calc_scaler(CONFIG_SYS_CLK_FREQ, CONFIG_BAUDRATE); + writel(tmp, ®s->UART_Scaler); /* Let bit 11 be unchanged (debug bit for GRMON) */ - tmp = READ_WORD(regs->UART_Control); + tmp = readl(®s->UART_Control) & LEON2_UART_CTRL_DBG; + tmp |= (LEON2_UART1_LOOPBACK_ENABLE << 7); + tmp |= (LEON2_UART1_FLOWCTRL_ENABLE << 6); + tmp |= (LEON2_UART1_PARITY_ENABLE << 5); + tmp |= (LEON2_UART1_ODDPAR_ENABLE << 4); + /* Receiver & transmitter enable */ + tmp |= (LEON2_UART_CTRL_RE | LEON2_UART_CTRL_TE); + writel(tmp, ®s->UART_Control); + + gd->arch.uart = regs; + return 0; +} - regs->UART_Control = ((tmp & LEON2_UART_CTRL_DBG) | - (LEON2_UART1_LOOPBACK_ENABLE << 7) | - (LEON2_UART1_FLOWCTRL_ENABLE << 6) | - (LEON2_UART1_PARITY_ENABLE << 5) | - (LEON2_UART1_ODDPAR_ENABLE << 4) | - LEON2_UART_CTRL_RE | LEON2_UART_CTRL_TE); +static inline LEON2_Uart_regs *leon2_get_uart_regs(void) +{ + LEON2_Uart_regs *uart = gd->arch.uart; - return 0; + return uart; } static void leon2_serial_putc_raw(const char c) { - LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; - LEON2_Uart_regs *regs; + LEON2_Uart_regs *uart = leon2_get_uart_regs(); -#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 - regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; -#else - regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; -#endif + if (!uart) + return; /* Wait for last character to go. */ - while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_THE)) ; + while (!(readl(&uart->UART_Status) & LEON2_UART_STAT_THE)) + WATCHDOG_RESET(); /* Send data */ - regs->UART_Channel = c; + writel(c, &uart->UART_Channel); #ifdef LEON_DEBUG /* Wait for data to be sent */ - while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_TSE)) ; + while (!(readl(&uart->UART_Status) & LEON2_UART_STAT_TSE)) + WATCHDOG_RESET(); #endif } @@ -80,56 +86,43 @@ static void leon2_serial_putc(const char c) static int leon2_serial_getc(void) { - LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; - LEON2_Uart_regs *regs; + LEON2_Uart_regs *uart = leon2_get_uart_regs(); -#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 - regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; -#else - regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; -#endif + if (!uart) + return 0; /* Wait for a character to arrive. */ - while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_DR)) ; + while (!(readl(&uart->UART_Status) & LEON2_UART_STAT_DR)) + WATCHDOG_RESET(); - /* read data */ - return READ_WORD(regs->UART_Channel); + /* Read character data */ + return readl(&uart->UART_Channel); } static int leon2_serial_tstc(void) { - LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; - LEON2_Uart_regs *regs; + LEON2_Uart_regs *uart = leon2_get_uart_regs(); -#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 - regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; -#else - regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; -#endif + if (!uart) + return 0; - return (READ_WORD(regs->UART_Status) & LEON2_UART_STAT_DR); + return readl(&uart->UART_Status) & LEON2_UART_STAT_DR; } -/* set baud rate for uart */ static void leon2_serial_setbrg(void) { - /* update baud rate settings, read it from gd->baudrate */ + LEON2_Uart_regs *uart = leon2_get_uart_regs(); unsigned int scaler; - LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; - LEON2_Uart_regs *regs; -#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 - regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; -#else - regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; -#endif + if (!uart) + return; + + if (!gd->baudrate) + gd->baudrate = CONFIG_BAUDRATE; + + scaler = leon2_serial_calc_scaler(CONFIG_SYS_CLK_FREQ, CONFIG_BAUDRATE); - if (gd->baudrate > 0) { - scaler = - (((CONFIG_SYS_CLK_FREQ * 10) / (gd->baudrate * 8)) - - 5) / 10; - regs->UART_Scaler = scaler; - } + writel(scaler, &uart->UART_Scaler); } static struct serial_device leon2_serial_drv = { diff --git a/arch/sparc/cpu/leon2/start.S b/arch/sparc/cpu/leon2/start.S index e43097cf9b..974de76852 100644 --- a/arch/sparc/cpu/leon2/start.S +++ b/arch/sparc/cpu/leon2/start.S @@ -57,6 +57,27 @@ MINFRAME = (WINDOWSIZE + ARGPUSHSIZE + 4) #error Must define number of SPARC register windows, default is 8 #endif +/* Macros to load address into a register. Uses GOT table for PIC */ +#ifdef __PIC__ + +#define SPARC_PIC_THUNK_CALL(reg) \ + sethi %pc22(_GLOBAL_OFFSET_TABLE_-4), %##reg; \ + call __sparc_get_pc_thunk.reg; \ + add %##reg, %pc10(_GLOBAL_OFFSET_TABLE_+4), %##reg; + +#define SPARC_LOAD_ADDRESS(sym, got, reg) \ + sethi %gdop_hix22(sym), %##reg; \ + xor %##reg, %gdop_lox10(sym), %##reg; \ + ld [%##got + %##reg], %##reg, %gdop(sym); + +#else + +#define SPARC_PIC_THUNK_CALL(reg) +#define SPARC_LOAD_ADDRESS(sym, got, tmp) \ + set sym, %##reg; + +#endif + #define STACK_ALIGN 8 #define SA(X) (((X)+(STACK_ALIGN-1)) & ~(STACK_ALIGN-1)) @@ -278,7 +299,7 @@ leon2_init_mctrl: srl %g2, 30, %g2 andcc %g2, 3, %g6 bne,a leon2_init_wim - mov %g0, %asr16 ! clear err_reg + mov %g0, %asr16 ! clear err_reg leon2_init_wim: set WIM_INIT, %g3 @@ -299,7 +320,7 @@ leon2_init_stackp: cpu_init_unreloc: call cpu_init_f - nop + nop /* un relocated start address of monitor */ #define TEXT_START _text @@ -307,9 +328,10 @@ cpu_init_unreloc: /* un relocated end address of monitor */ #define DATA_END __init_end + SPARC_PIC_THUNK_CALL(l7) reloc: - set TEXT_START,%g2 - set DATA_END,%g3 + SPARC_LOAD_ADDRESS(TEXT_START, l7, g2) + SPARC_LOAD_ADDRESS(DATA_END, l7, g3) set CONFIG_SYS_RELOC_MONITOR_BASE,%g4 reloc_loop: ldd [%g2],%l0 @@ -319,7 +341,7 @@ reloc_loop: inc 16,%g2 subcc %g3,%g2,%g0 bne reloc_loop - inc 16,%g4 + inc 16,%g4 clr %l0 clr %l1 @@ -336,8 +358,8 @@ reloc_loop: clr_bss: /* clear bss area (the relocated) */ - set __bss_start,%g2 - set __bss_end,%g3 + SPARC_LOAD_ADDRESS(__bss_start, l7, g2) + SPARC_LOAD_ADDRESS(__bss_end, l7, g3) sub %g3,%g2,%g3 add %g3,%g4,%g3 clr %g1 /* std %g0 uses g0 and g1 */ @@ -348,19 +370,19 @@ clr_bss_16: inc 16,%g4 cmp %g3,%g4 bne clr_bss_16 - nop + nop /* add offsets to GOT table */ fixup_got: - set __got_start,%g4 - set __got_end,%g3 + SPARC_LOAD_ADDRESS(__got_start, l7, g4) + SPARC_LOAD_ADDRESS(__got_end, l7, g3) /* * new got offset = (old GOT-PTR (read with ld) - * CONFIG_SYS_RELOC_MONITOR_BASE(from define) ) + * Destination Address (from define) */ set CONFIG_SYS_RELOC_MONITOR_BASE,%g2 - set TEXT_START, %g1 + SPARC_LOAD_ADDRESS(TEXT_START, l7, g1) add %g4,%g2,%g4 sub %g4,%g1,%g4 add %g3,%g2,%g3 @@ -375,11 +397,11 @@ got_loop: inc 4,%g4 cmp %g3,%g4 bne got_loop - nop + nop prom_relocate: - set __prom_start, %g2 - set __prom_end, %g3 + SPARC_LOAD_ADDRESS(__prom_start, l7, g2) + SPARC_LOAD_ADDRESS(__prom_end, l7, g3) set CONFIG_SYS_PROM_OFFSET, %g4 prom_relocate_loop: @@ -390,7 +412,7 @@ prom_relocate_loop: inc 16,%g2 subcc %g3,%g2,%g0 bne prom_relocate_loop - inc 16,%g4 + inc 16,%g4 /* Trap table has been moved, lets tell CPU about * the new trap table address @@ -403,19 +425,19 @@ prom_relocate_loop: nop /* Call relocated init functions */ jump: - set cpu_init_f2,%o1 + SPARC_LOAD_ADDRESS(cpu_init_f2, l7, o1) set CONFIG_SYS_RELOC_MONITOR_BASE,%o2 add %o1,%o2,%o1 sub %o1,%g1,%o1 call %o1 - clr %o0 + clr %o0 - set board_init_f,%o1 + SPARC_LOAD_ADDRESS(board_init_f, l7, o1) set CONFIG_SYS_RELOC_MONITOR_BASE,%o2 add %o1,%o2,%o1 sub %o1,%g1,%o1 call %o1 - clr %o0 + clr %o0 dead: ta 0 ! if call returns... nop |