diff options
Diffstat (limited to 'arch/sparc/cpu/leon2')
| -rw-r--r-- | arch/sparc/cpu/leon2/cpu.c | 14 | ||||
| -rw-r--r-- | arch/sparc/cpu/leon2/cpu_init.c | 94 | ||||
| -rw-r--r-- | arch/sparc/cpu/leon2/interrupts.c | 14 | ||||
| -rw-r--r-- | arch/sparc/cpu/leon2/prom.c | 2 | ||||
| -rw-r--r-- | arch/sparc/cpu/leon2/serial.c | 2 | ||||
| -rw-r--r-- | arch/sparc/cpu/leon2/start.S | 213 |
6 files changed, 165 insertions, 174 deletions
diff --git a/arch/sparc/cpu/leon2/cpu.c b/arch/sparc/cpu/leon2/cpu.c index 380c397be04..d044c3abc72 100644 --- a/arch/sparc/cpu/leon2/cpu.c +++ b/arch/sparc/cpu/leon2/cpu.c @@ -1,7 +1,7 @@ /* CPU specific code for the LEON2 CPU * - * (C) Copyright 2007 - * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com + * (C) Copyright 2007, 2015 + * Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com * * SPDX-License-Identifier: GPL-2.0+ */ @@ -22,6 +22,16 @@ int checkcpu(void) return 0; } +#ifdef CONFIG_DISPLAY_CPUINFO + +int print_cpuinfo(void) +{ + printf("CPU: LEON2\n"); + return 0; +} + +#endif + /* ------------------------------------------------------------------------- */ void cpu_reset(void) diff --git a/arch/sparc/cpu/leon2/cpu_init.c b/arch/sparc/cpu/leon2/cpu_init.c index 6e07fe6bb40..9dfb99cb0f7 100644 --- a/arch/sparc/cpu/leon2/cpu_init.c +++ b/arch/sparc/cpu/leon2/cpu_init.c @@ -1,8 +1,8 @@ /* Initializes CPU and basic hardware such as memory * controllers, IRQ controller and system timer 0. * - * (C) Copyright 2007 - * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com + * (C) Copyright 2007, 2015 + * Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com * * SPDX-License-Identifier: GPL-2.0+ */ @@ -10,22 +10,12 @@ #include <common.h> #include <asm/asi.h> #include <asm/leon.h> +#include <asm/io.h> #include <config.h> -#define TIMER_BASE_CLK 1000000 -#define US_PER_TICK (1000000 / CONFIG_SYS_HZ) - DECLARE_GLOBAL_DATA_PTR; -/* reset CPU (jump to 0, without reset) */ -void start(void); - -struct { - gd_t gd_area; - bd_t bd; -} global_data; - /* * Breath some life into the CPU... * @@ -50,82 +40,56 @@ void cpu_init_f(void) /* cache */ - /* I/O port setup */ + /* I/O port setup */ #ifdef LEON2_IO_PORT_DIR - leon2->PIO_Direction = LEON2_IO_PORT_DIR; + leon2->PIO_Direction = LEON2_IO_PORT_DIR; #endif #ifdef LEON2_IO_PORT_DATA - leon2->PIO_Data = LEON2_IO_PORT_DATA; + leon2->PIO_Data = LEON2_IO_PORT_DATA; #endif #ifdef LEON2_IO_PORT_INT - leon2->PIO_Interrupt = LEON2_IO_PORT_INT; + leon2->PIO_Interrupt = LEON2_IO_PORT_INT; #else - leon2->PIO_Interrupt = 0; + leon2->PIO_Interrupt = 0; #endif + + /* disable timers */ + leon2->Timer_Control_1 = leon2->Timer_Control_2 = 0; } -void cpu_init_f2(void) +int arch_cpu_init(void) { + gd->cpu_clk = CONFIG_SYS_CLK_FREQ; + gd->bus_clk = CONFIG_SYS_CLK_FREQ; + gd->ram_size = CONFIG_SYS_SDRAM_SIZE; + return 0; } /* - * initialize higher level parts of CPU like time base and timers + * initialize higher level parts of CPU */ int cpu_init_r(void) { - LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; - - /* initialize prescaler common to all timers to 1MHz */ - leon2->Scaler_Counter = leon2->Scaler_Reload = - (((CONFIG_SYS_CLK_FREQ / 1000) + 500) / 1000) - 1; - - return (0); + return 0; } -/* Uses Timer 0 to get accurate - * pauses. Max 2 raised to 32 ticks - * +/* initiate and setup timer0 to configured HZ. Base clock is 1MHz. */ -void cpu_wait_ticks(unsigned long ticks) +int timer_init(void) { - unsigned long start = get_timer(0); - while (get_timer(start) < ticks) ; -} + LEON2_regs *leon2 = (LEON2_regs *)LEON2_PREGS; -/* initiate and setup timer0 interrupt to configured HZ. Base clock is 1MHz. - * Return irq number for timer int or a negative number for - * dealing with self - */ -int timer_interrupt_init_cpu(void) -{ - LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; + /* initialize prescaler common to all timers to 1MHz */ + leon2->Scaler_Counter = leon2->Scaler_Reload = + (((CONFIG_SYS_CLK_FREQ / 1000) + 500) / 1000) - 1; /* SYS_HZ ticks per second */ leon2->Timer_Counter_1 = 0; - leon2->Timer_Reload_1 = (TIMER_BASE_CLK / CONFIG_SYS_HZ) - 1; - leon2->Timer_Control_1 = - (LEON2_TIMER_CTRL_EN | LEON2_TIMER_CTRL_RS | LEON2_TIMER_CTRL_LD); - - return LEON2_TIMER1_IRQNO; -} - -ulong get_tbclk(void) -{ - return TIMER_BASE_CLK; -} + leon2->Timer_Reload_1 = (CONFIG_SYS_TIMER_RATE / CONFIG_SYS_HZ) - 1; + leon2->Timer_Control_1 = LEON2_TIMER_CTRL_EN | LEON2_TIMER_CTRL_RS | + LEON2_TIMER_CTRL_LD; -/* - * This function is intended for SHORT delays only. - */ -unsigned long cpu_usec2ticks(unsigned long usec) -{ - if (usec < US_PER_TICK) - return 1; - return usec / US_PER_TICK; -} - -unsigned long cpu_ticks2usec(unsigned long ticks) -{ - return ticks * US_PER_TICK; + CONFIG_SYS_TIMER_COUNTER = (void *)&leon2->Timer_Counter_1; + return 0; } diff --git a/arch/sparc/cpu/leon2/interrupts.c b/arch/sparc/cpu/leon2/interrupts.c index f78ec8a4109..602e4a67ba8 100644 --- a/arch/sparc/cpu/leon2/interrupts.c +++ b/arch/sparc/cpu/leon2/interrupts.c @@ -118,20 +118,6 @@ int interrupt_init_cpu(void) /****************************************************************************/ -/* Handle Timer 0 IRQ */ -void timer_interrupt_cpu(void *arg) -{ - LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; - - leon2->Timer_Control_1 = - (LEON2_TIMER_CTRL_EN | LEON2_TIMER_CTRL_RS | LEON2_TIMER_CTRL_LD); - - /* nothing to do here */ - return; -} - -/****************************************************************************/ - /* * Install and free a interrupt handler. */ diff --git a/arch/sparc/cpu/leon2/prom.c b/arch/sparc/cpu/leon2/prom.c index cd2571f0d6e..7829e7abb2e 100644 --- a/arch/sparc/cpu/leon2/prom.c +++ b/arch/sparc/cpu/leon2/prom.c @@ -25,6 +25,8 @@ extern struct linux_romvec *kernel_arg_promvec; #define PROM_TEXT __attribute__ ((__section__ (".prom.text"))) #define PROM_DATA __attribute__ ((__section__ (".prom.data"))) +void *__prom_start_reloc; /* relocated prom_start address */ + /* for __va */ extern int __prom_start; #define PAGE_OFFSET 0xf0000000 diff --git a/arch/sparc/cpu/leon2/serial.c b/arch/sparc/cpu/leon2/serial.c index 603364ee0bd..460abd1d9f5 100644 --- a/arch/sparc/cpu/leon2/serial.c +++ b/arch/sparc/cpu/leon2/serial.c @@ -120,7 +120,7 @@ static void leon2_serial_setbrg(void) if (!gd->baudrate) gd->baudrate = CONFIG_BAUDRATE; - scaler = leon2_serial_calc_scaler(CONFIG_SYS_CLK_FREQ, CONFIG_BAUDRATE); + scaler = leon2_serial_calc_scaler(CONFIG_SYS_CLK_FREQ, gd->baudrate); writel(scaler, &uart->UART_Scaler); } diff --git a/arch/sparc/cpu/leon2/start.S b/arch/sparc/cpu/leon2/start.S index 974de76852e..1b404da3629 100644 --- a/arch/sparc/cpu/leon2/start.S +++ b/arch/sparc/cpu/leon2/start.S @@ -1,6 +1,7 @@ /* This is where the SPARC/LEON3 starts - * Copyright (C) 2007, - * Daniel Hellstrom, daniel@gaisler.com + * + * Copyright (C) 2007, 2015 + * Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com * * SPDX-License-Identifier: GPL-2.0+ */ @@ -12,7 +13,6 @@ #include <asm/psr.h> #include <asm/stack.h> #include <asm/leon.h> -#include <version.h> /* Entry for traps which jump to a programmer-specified trap handler. */ #define TRAPR(H) \ @@ -197,14 +197,6 @@ _trap_table: SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! f4-f7 SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! f8-fb SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! fc-ff -/* - * Version string - */ - - .data - .globl version_string -version_string: - .ascii U_BOOT_VERSION_STRING, "\0" .section ".text" .align 4 @@ -318,30 +310,62 @@ leon2_init_stackp: andn %fp, 0x0f, %fp sub %fp, 64, %sp +leon2_init_tbr: + set CONFIG_SYS_TEXT_BASE, %g2 + wr %g0, %g2, %tbr + nop + nop + nop + cpu_init_unreloc: call cpu_init_f nop +board_init_unreloc: + call board_init_f + clr %o0 ! boot_flags + +dead_unreloc: + ba dead_unreloc ! infinte loop + nop + +!------------------------------------------------------------------------------- + +/* void relocate_code (addr_sp, gd, addr_moni) + * + * This "function" does not return, instead it continues in RAM after + * relocating the monitor code. + * + * %o0 = Relocated stack pointer + * %o1 = Relocated global data pointer + * %o2 = Relocated text pointer + */ + .globl relocate_code + .type relocate_code, #function + .align 4 +relocate_code: + SPARC_PIC_THUNK_CALL(l7) + /* un relocated start address of monitor */ #define TEXT_START _text /* un relocated end address of monitor */ #define DATA_END __init_end - SPARC_PIC_THUNK_CALL(l7) reloc: 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 - ldd [%g2+8],%l2 - std %l0,[%g4] - std %l2,[%g4+8] - inc 16,%g2 - subcc %g3,%g2,%g0 - bne reloc_loop - inc 16,%g4 + mov %o2, %g4 ! relocation address + sub %g4, %g2, %g6 ! relocation offset + /* copy .text & .data to relocated address */ +10: ldd [%g2], %l0 + ldd [%g2+8], %l2 + std %l0, [%g4] + std %l2, [%g4+8] + inc 16, %g2 ! src += 16 + cmp %g2, %g3 + bcs 10b ! while (src < end) + inc 16, %g4 ! dst += 16 clr %l0 clr %l1 @@ -356,91 +380,93 @@ reloc_loop: * */ + /* clear bss area (the relocated) */ clr_bss: -/* clear bss area (the relocated) */ SPARC_LOAD_ADDRESS(__bss_start, l7, g2) SPARC_LOAD_ADDRESS(__bss_end, l7, g3) - sub %g3,%g2,%g3 + sub %g3,%g2,%g3 ! length of .bss area add %g3,%g4,%g3 + /* clearing 16byte a time ==> linker script need to align to 16 byte offset */ clr %g1 /* std %g0 uses g0 and g1 */ -/* clearing 16byte a time ==> linker script need to align to 16 byte offset */ -clr_bss_16: - std %g0,[%g4] - std %g0,[%g4+8] - inc 16,%g4 - cmp %g3,%g4 - bne clr_bss_16 +20: + std %g0, [%g4] + std %g0, [%g4+8] + inc 16, %g4 ! ptr += 16 + cmp %g4, %g3 + bcs 20b ! while (ptr < end) nop -/* add offsets to GOT table */ + /* add offsets to GOT table */ fixup_got: SPARC_LOAD_ADDRESS(__got_start, l7, g4) + add %g4, %g6, %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 - SPARC_LOAD_ADDRESS(TEXT_START, l7, g1) - add %g4,%g2,%g4 - sub %g4,%g1,%g4 - add %g3,%g2,%g3 - sub %g3,%g1,%g3 - sub %g2,%g1,%g2 ! prepare register with (new base address) - - ! (old base address) -got_loop: - ld [%g4],%l0 ! load old GOT-PTR - add %l0,%g2,%l0 ! increase with (new base address) - - ! (old base) - st %l0,[%g4] - inc 4,%g4 - cmp %g3,%g4 - bne got_loop + add %g3, %g6, %g3 +30: ld [%g4], %l0 ! load old GOT-PTR +#ifdef CONFIG_RELOC_GOT_SKIP_NULL + cmp %l0, 0 + be 32f +#endif + add %l0, %g6, %l0 ! relocate GOT pointer + st %l0, [%g4] +32: inc 4, %g4 ! ptr += 4 + cmp %g4, %g3 + bcs 30b ! while (ptr < end) nop prom_relocate: SPARC_LOAD_ADDRESS(__prom_start, l7, g2) SPARC_LOAD_ADDRESS(__prom_end, l7, g3) - set CONFIG_SYS_PROM_OFFSET, %g4 - -prom_relocate_loop: - ldd [%g2],%l0 - ldd [%g2+8],%l2 - std %l0,[%g4] - std %l2,[%g4+8] - inc 16,%g2 - subcc %g3,%g2,%g0 - bne prom_relocate_loop - inc 16,%g4 + /* + * Calculated addres is stored in this variable by + * reserve_prom() function in common/board_f.c + */ + SPARC_LOAD_ADDRESS(__prom_start_reloc, l7, g4) + ld [%g4], %g4 + +40: ldd [%g2], %l0 + ldd [%g2+8], %l2 + std %l0, [%g4] + std %l2, [%g4+8] + inc 16, %g2 + cmp %g2, %g3 + bcs 40b + inc 16, %g4 + +! %o0 = stack pointer (relocated) +! %o1 = global data pointer (relocated) +! %o2 = text pointer (relocated) + +! %g6 = relocation offset +! %l7 = _GLOBAL_OFFSET_TABLE_ /* Trap table has been moved, lets tell CPU about * the new trap table address */ - - set CONFIG_SYS_RELOC_MONITOR_BASE, %g2 - wr %g0, %g2, %tbr - -/* call relocate*/ +update_trap_table_address: + wr %g0, %o2, %tbr + nop + nop nop -/* Call relocated init functions */ -jump: - 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 - 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 +update_stack_pointers: + mov %o0, %fp + andn %fp, 0x0f, %fp ! align to 16 bytes + add %fp, -64, %fp ! make space for a window push + mov %fp, %sp ! setup stack pointer + +jump_board_init_r: + mov %o1, %o0 ! relocated global data pointer + mov %o2, %o1 ! relocated text pointer + SPARC_LOAD_ADDRESS(board_init_r, l7, o3) + add %o3, %g6, %o3 ! add relocation offset + call %o3 + nop dead: ta 0 ! if call returns... - nop + nop + +!------------------------------------------------------------------------------ /* Interrupt handler caller, * reg L7: interrupt number @@ -469,7 +495,11 @@ _irq_entry: RESTORE_ALL -!Window overflow trap handler. +!------------------------------------------------------------------------------ + +/* + * Window overflow trap handler. + */ .global _window_overflow _window_overflow: @@ -477,14 +507,12 @@ _window_overflow: mov %wim, %l3 ! Calculate next WIM mov %g1, %l7 srl %l3, 1, %g1 - sll %l3, (CONFIG_SYS_SPARC_NWINDOWS-1) , %l4 + sll %l3, (CONFIG_SYS_SPARC_NWINDOWS-1), %l4 or %l4, %g1, %g1 save ! Get into window to be saved. mov %g1, %wim - nop; - nop; - nop + nop; nop; nop st %l0, [%sp + 0]; st %l1, [%sp + 4]; st %l2, [%sp + 8]; @@ -506,8 +534,9 @@ _window_overflow: jmp %l1 ! Re-execute save. rett %l2 -/* Window underflow trap handler. */ - +/* + * Window underflow trap handler. + */ .global _window_underflow _window_underflow: @@ -541,7 +570,7 @@ _window_underflow: jmp %l1 ! Re-execute restore. rett %l2 - retl +!------------------------------------------------------------------------------ _nmi_trap: nop |
