summaryrefslogtreecommitdiffstats
path: root/arch/sparc/cpu/leon2
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/cpu/leon2')
-rw-r--r--arch/sparc/cpu/leon2/serial.c125
-rw-r--r--arch/sparc/cpu/leon2/start.S60
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, &regs->UART_Scaler);
/* Let bit 11 be unchanged (debug bit for GRMON) */
- tmp = READ_WORD(regs->UART_Control);
+ tmp = readl(&regs->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, &regs->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
OpenPOWER on IntegriCloud