summaryrefslogtreecommitdiff
path: root/arch/sparc/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/cpu')
-rw-r--r--arch/sparc/cpu/leon2/cpu.c14
-rw-r--r--arch/sparc/cpu/leon2/cpu_init.c94
-rw-r--r--arch/sparc/cpu/leon2/interrupts.c14
-rw-r--r--arch/sparc/cpu/leon2/prom.c2
-rw-r--r--arch/sparc/cpu/leon2/serial.c2
-rw-r--r--arch/sparc/cpu/leon2/start.S213
-rw-r--r--arch/sparc/cpu/leon3/ambapp.c2
-rw-r--r--arch/sparc/cpu/leon3/cpu.c60
-rw-r--r--arch/sparc/cpu/leon3/cpu_init.c175
-rw-r--r--arch/sparc/cpu/leon3/interrupts.c11
-rw-r--r--arch/sparc/cpu/leon3/prom.c2
-rw-r--r--arch/sparc/cpu/leon3/serial.c23
-rw-r--r--arch/sparc/cpu/leon3/start.S303
-rw-r--r--arch/sparc/cpu/leon3/usb_uhci.c7
14 files changed, 497 insertions, 425 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
diff --git a/arch/sparc/cpu/leon3/ambapp.c b/arch/sparc/cpu/leon3/ambapp.c
index b8ac05faf12..47769cffd70 100644
--- a/arch/sparc/cpu/leon3/ambapp.c
+++ b/arch/sparc/cpu/leon3/ambapp.c
@@ -40,7 +40,7 @@ extern int ambapp_find_ahb(struct ambapp_bus *abus, unsigned int dev_vend,
int index, int type, struct ambapp_find_ahb_info *result);
/************ C ROUTINES USED BY U-BOOT AMBA CORE DRIVERS ************/
-struct ambapp_bus ambapp_plb;
+struct ambapp_bus ambapp_plb __section(.data);
void ambapp_bus_init(
unsigned int ioarea,
diff --git a/arch/sparc/cpu/leon3/cpu.c b/arch/sparc/cpu/leon3/cpu.c
index 8ab315016b6..149e5c69e63 100644
--- a/arch/sparc/cpu/leon3/cpu.c
+++ b/arch/sparc/cpu/leon3/cpu.c
@@ -1,7 +1,7 @@
/* CPU specific code for the LEON3 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+
*/
@@ -13,18 +13,72 @@
#include <asm/io.h>
#include <asm/processor.h>
+#include <ambapp.h>
DECLARE_GLOBAL_DATA_PTR;
extern void _reset_reloc(void);
+int leon_cpu_cnt = 1;
+int leon_ver = 3;
+unsigned int leon_cpu_freq = CONFIG_SYS_CLK_FREQ;
+
+int cpu_freq(void)
+{
+ ambapp_ahbdev dev;
+
+ if (leon_ver == 3) {
+ ambapp_ahbmst_find(&ambapp_plb, VENDOR_GAISLER,
+ GAISLER_LEON3, 0, &dev);
+ } else {
+ ambapp_ahbmst_find(&ambapp_plb, VENDOR_GAISLER,
+ GAISLER_LEON4, 0, &dev);
+ }
+
+ leon_cpu_freq = ambapp_bus_freq(&ambapp_plb, dev.ahb_bus_index);
+
+ return 0;
+}
+
int checkcpu(void)
{
+ int cnt;
+ char str[4];
+
/* check LEON version here */
- printf("CPU: LEON3\n");
+ cnt = ambapp_ahbmst_count(&ambapp_plb, VENDOR_GAISLER, GAISLER_LEON3);
+ if (cnt <= 0) {
+ cnt = ambapp_ahbmst_count(&ambapp_plb, VENDOR_GAISLER,
+ GAISLER_LEON4);
+ if (cnt > 0)
+ leon_ver = 4;
+ }
+
+ cpu_freq();
+
+ str[0] = '\0';
+ if (cnt > 1) {
+ leon_cpu_cnt = cnt;
+ str[0] = '0' + cnt;
+ str[1] = 'x';
+ str[2] = '\0';
+ }
+ printf("CPU: %sLEON%d @ %dMHz\n", str, leon_ver,
+ leon_cpu_freq / 1000000);
+
return 0;
}
+#ifdef CONFIG_DISPLAY_CPUINFO
+
+int print_cpuinfo(void)
+{
+ printf("CPU: LEON3\n");
+ return 0;
+}
+
+#endif
+
/* ------------------------------------------------------------------------- */
void cpu_reset(void)
diff --git a/arch/sparc/cpu/leon3/cpu_init.c b/arch/sparc/cpu/leon3/cpu_init.c
index b140da31b13..f25388cf841 100644
--- a/arch/sparc/cpu/leon3/cpu_init.c
+++ b/arch/sparc/cpu/leon3/cpu_init.c
@@ -10,6 +10,7 @@
#include <common.h>
#include <asm/asi.h>
#include <asm/leon.h>
+#include <asm/io.h>
#include <ambapp.h>
#include <grlib/irqmp.h>
#include <grlib/gptimer.h>
@@ -22,23 +23,14 @@
#define CONFIG_AMBAPP_IOAREA AMBA_DEFAULT_IOAREA
#endif
-#define TIMER_BASE_CLK 1000000
-#define US_PER_TICK (1000000 / CONFIG_SYS_HZ)
+/* Select which TIMER that will become the time base */
+#ifndef CONFIG_SYS_GRLIB_GPTIMER_INDEX
+#define CONFIG_SYS_GRLIB_GPTIMER_INDEX 0
+#endif
DECLARE_GLOBAL_DATA_PTR;
-/* reset CPU (jump to 0, without reset) */
-void start(void);
-
ambapp_dev_irqmp *irqmp = NULL;
-ambapp_dev_gptimer *gptimer = NULL;
-unsigned int gptimer_irq = 0;
-int leon3_snooping_avail = 0;
-
-struct {
- gd_t gd_area;
- bd_t bd;
-} global_data;
/*
* Breath some life into the CPU...
@@ -56,19 +48,62 @@ void cpu_init_f(void)
#endif
}
-/* Routine called from start.S,
- *
- * Run from FLASH/PROM:
- * - memory controller has already been setup up, stack can be used
- * - global variables available for read/writing
- * - constants avaiable
- */
-void cpu_init_f2(void)
+/* If cache snooping is available in hardware the result will be set
+ * to 0x800000, otherwise 0.
+ */
+static unsigned int snoop_detect(void)
{
+ unsigned int result;
+ asm("lda [%%g0] 2, %0" : "=r"(result));
+ return result & 0x00800000;
+}
+
+int arch_cpu_init(void)
+{
+ ambapp_apbdev apbdev;
+ int index;
+
+ gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
+ gd->bus_clk = CONFIG_SYS_CLK_FREQ;
+ gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
+
+ gd->arch.snooping_available = snoop_detect();
+
/* Initialize the AMBA Plug & Play bus structure, the bus
* structure represents the AMBA bus that the CPU is located at.
*/
ambapp_bus_init(CONFIG_AMBAPP_IOAREA, CONFIG_SYS_CLK_FREQ, &ambapp_plb);
+
+ /* Initialize/clear all the timers in the system.
+ */
+ for (index = 0; ambapp_apb_find(&ambapp_plb, VENDOR_GAISLER,
+ GAISLER_GPTIMER, index, &apbdev) == 1; index++) {
+ ambapp_dev_gptimer *timer;
+ unsigned int bus_freq;
+ int i, ntimers;
+
+ timer = (ambapp_dev_gptimer *)apbdev.address;
+
+ /* Different buses may have different frequency, the
+ * frequency of the bus tell in which frequency the timer
+ * prescaler operates.
+ */
+ bus_freq = ambapp_bus_freq(&ambapp_plb, apbdev.ahb_bus_index);
+
+ /* Initialize prescaler common to all timers to 1MHz */
+ timer->scalar = timer->scalar_reload =
+ (((bus_freq / 1000) + 500) / 1000) - 1;
+
+ /* Clear all timers */
+ ntimers = timer->config & 0x7;
+ for (i = 0; i < ntimers; i++) {
+ timer->e[i].ctrl = GPTIMER_CTRL_IP;
+ timer->e[i].rld = 0;
+ timer->e[i].ctrl = GPTIMER_CTRL_LD;
+ }
+ }
+
+ return 0;
}
/*
@@ -77,9 +112,7 @@ void cpu_init_f2(void)
int cpu_init_r(void)
{
ambapp_apbdev apbdev;
- int index, cpu;
- ambapp_dev_gptimer *timer = NULL;
- unsigned int bus_freq;
+ int cpu;
/*
* Find AMBA APB IRQMP Controller,
@@ -102,77 +135,41 @@ int cpu_init_r(void)
irqmp->cpu_force[cpu] = 0;
}
- /* timer */
- index = 0;
- while (ambapp_apb_find(&ambapp_plb, VENDOR_GAISLER, GAISLER_GPTIMER,
- index, &apbdev) == 1) {
- timer = (ambapp_dev_gptimer *)apbdev.address;
- if (gptimer == NULL) {
- gptimer = timer;
- gptimer_irq = apbdev.irq;
- }
-
- /* Different buses may have different frequency, the
- * frequency of the bus tell in which frequency the timer
- * prescaler operates.
- */
- bus_freq = ambapp_bus_freq(&ambapp_plb, apbdev.ahb_bus_index);
-
- /* initialize prescaler common to all timers to 1MHz */
- timer->scalar = timer->scalar_reload =
- (((bus_freq / 1000) + 500) / 1000) - 1;
-
- index++;
- }
- if (!gptimer) {
- printf("%s: gptimer not found!\n", __func__);
- return 1;
- }
return 0;
}
-/* Uses Timer 0 to get accurate
- * pauses. Max 2 raised to 32 ticks
- *
- */
-void cpu_wait_ticks(unsigned long ticks)
+ ;
+int timer_init(void)
{
- unsigned long start = get_timer(0);
- while (get_timer(start) < ticks) ;
-}
+ ambapp_dev_gptimer_element *tmr;
+ ambapp_dev_gptimer *gptimer;
+ ambapp_apbdev apbdev;
+ unsigned bus_freq;
-/* 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)
-{
- /* SYS_HZ ticks per second */
- gptimer->e[0].val = 0;
- gptimer->e[0].rld = (TIMER_BASE_CLK / CONFIG_SYS_HZ) - 1;
- gptimer->e[0].ctrl =
- (GPTIMER_CTRL_EN | GPTIMER_CTRL_RS |
- GPTIMER_CTRL_LD | GPTIMER_CTRL_IE);
-
- return gptimer_irq;
-}
+ if (ambapp_apb_find(&ambapp_plb, VENDOR_GAISLER, GAISLER_GPTIMER,
+ CONFIG_SYS_GRLIB_GPTIMER_INDEX, &apbdev) != 1) {
+ panic("%s: gptimer not found!\n", __func__);
+ return -1;
+ }
-ulong get_tbclk(void)
-{
- return TIMER_BASE_CLK;
-}
+ gptimer = (ambapp_dev_gptimer *) apbdev.address;
-/*
- * 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;
-}
+ /* Different buses may have different frequency, the
+ * frequency of the bus tell in which frequency the timer
+ * prescaler operates.
+ */
+ bus_freq = ambapp_bus_freq(&ambapp_plb, apbdev.ahb_bus_index);
-unsigned long cpu_ticks2usec(unsigned long ticks)
-{
- return ticks * US_PER_TICK;
+ /* initialize prescaler common to all timers to 1MHz */
+ gptimer->scalar = gptimer->scalar_reload =
+ (((bus_freq / 1000) + 500) / 1000) - 1;
+
+ tmr = (ambapp_dev_gptimer_element *)&gptimer->e[0];
+
+ tmr->val = 0;
+ tmr->rld = ~0;
+ tmr->ctrl = GPTIMER_CTRL_EN | GPTIMER_CTRL_RS | GPTIMER_CTRL_LD;
+
+ CONFIG_SYS_TIMER_COUNTER = (void *)&tmr->val;
+ return 0;
}
diff --git a/arch/sparc/cpu/leon3/interrupts.c b/arch/sparc/cpu/leon3/interrupts.c
index 2312b58d29b..00c3288774f 100644
--- a/arch/sparc/cpu/leon3/interrupts.c
+++ b/arch/sparc/cpu/leon3/interrupts.c
@@ -124,17 +124,6 @@ int interrupt_init_cpu(void)
/****************************************************************************/
-/* Handle Timer 0 IRQ */
-void timer_interrupt_cpu(void *arg)
-{
- gptimer->e[0].ctrl = (GPTIMER_CTRL_EN | GPTIMER_CTRL_RS |
- GPTIMER_CTRL_LD | GPTIMER_CTRL_IE);
- /* nothing to do here */
- return;
-}
-
-/****************************************************************************/
-
/*
* Install and free a interrupt handler.
*/
diff --git a/arch/sparc/cpu/leon3/prom.c b/arch/sparc/cpu/leon3/prom.c
index c391be7420c..1f185b776b4 100644
--- a/arch/sparc/cpu/leon3/prom.c
+++ b/arch/sparc/cpu/leon3/prom.c
@@ -33,6 +33,8 @@ DECLARE_GLOBAL_DATA_PTR;
ambapp_dev_gptimer *gptimer;
+void *__prom_start_reloc; /* relocated prom_start address */
+
/* for __va */
extern int __prom_start;
#define PAGE_OFFSET 0xf0000000
diff --git a/arch/sparc/cpu/leon3/serial.c b/arch/sparc/cpu/leon3/serial.c
index 66b37730270..bc6e7a172e5 100644
--- a/arch/sparc/cpu/leon3/serial.c
+++ b/arch/sparc/cpu/leon3/serial.c
@@ -17,8 +17,18 @@ DECLARE_GLOBAL_DATA_PTR;
/* Select which UART that will become u-boot console */
#ifndef CONFIG_SYS_GRLIB_APBUART_INDEX
+/* Try to use CONFIG_CONS_INDEX, if available, it is numbered from 1 */
+#ifdef CONFIG_CONS_INDEX
+#define CONFIG_SYS_GRLIB_APBUART_INDEX (CONFIG_CONS_INDEX - 1)
+#else
#define CONFIG_SYS_GRLIB_APBUART_INDEX 0
#endif
+#endif
+
+static unsigned apbuart_calc_scaler(unsigned apbuart_freq, unsigned baud)
+{
+ return (((apbuart_freq * 10) / (baud * 8)) - 5) / 10;
+}
static int leon3_serial_init(void)
{
@@ -29,6 +39,7 @@ static int leon3_serial_init(void)
/* find UART */
if (ambapp_apb_find(&ambapp_plb, VENDOR_GAISLER, GAISLER_APBUART,
CONFIG_SYS_GRLIB_APBUART_INDEX, &apbdev) != 1) {
+ gd->flags &= ~GD_FLG_SERIAL_READY;
panic("%s: apbuart not found!\n", __func__);
return -1; /* didn't find hardware */
}
@@ -36,8 +47,11 @@ static int leon3_serial_init(void)
/* found apbuart, let's init .. */
uart = (ambapp_dev_apbuart *) apbdev.address;
+ /* APBUART Frequency is equal to bus frequency */
+ gd->arch.uart_freq = ambapp_bus_freq(&ambapp_plb, apbdev.ahb_bus_index);
+
/* Set scaler / baud rate */
- tmp = (((CONFIG_SYS_CLK_FREQ*10) / (CONFIG_BAUDRATE*8)) - 5)/10;
+ tmp = apbuart_calc_scaler(gd->arch.uart_freq, CONFIG_BAUDRATE);
writel(tmp, &uart->scaler);
/* Let bit 11 be unchanged (debug bit for GRMON) */
@@ -122,7 +136,10 @@ static void leon3_serial_setbrg(void)
if (!gd->baudrate)
gd->baudrate = CONFIG_BAUDRATE;
- scaler = (((CONFIG_SYS_CLK_FREQ*10) / (gd->baudrate*8)) - 5)/10;
+ if (!gd->arch.uart_freq)
+ gd->arch.uart_freq = CONFIG_SYS_CLK_FREQ;
+
+ scaler = apbuart_calc_scaler(gd->arch.uart_freq, gd->baudrate);
writel(scaler, &uart->scaler);
}
@@ -155,7 +172,7 @@ __weak struct serial_device *default_serial_console(void)
static inline void _debug_uart_init(void)
{
ambapp_dev_apbuart *uart = (ambapp_dev_apbuart *)CONFIG_DEBUG_UART_BASE;
- uart->scaler = (((CONFIG_DEBUG_UART_CLOCK*10) / (CONFIG_BAUDRATE*8)) - 5)/10;
+ uart->scaler = apbuart_calc_scaler(CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
uart->ctrl = APBUART_CTRL_RE | APBUART_CTRL_TE;
}
diff --git a/arch/sparc/cpu/leon3/start.S b/arch/sparc/cpu/leon3/start.S
index 203114970b2..1527d72a6d7 100644
--- a/arch/sparc/cpu/leon3/start.S
+++ b/arch/sparc/cpu/leon3/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>
#include <ambapp.h>
/* Default Plug&Play I/O area */
@@ -20,6 +20,11 @@
#define CONFIG_AMBAPP_IOAREA AMBA_DEFAULT_IOAREA
#endif
+/* Default number of SPARC register windows */
+#ifndef CONFIG_SYS_SPARC_NWINDOWS
+#define CONFIG_SYS_SPARC_NWINDOWS 8
+#endif
+
/* Entry for traps which jump to a programmer-specified trap handler. */
#define TRAPR(H) \
wr %g0, 0xfe0, %psr; \
@@ -203,15 +208,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
- .extern leon3_snooping_avail
- .globl version_string
-version_string:
- .ascii U_BOOT_VERSION_STRING, "\0"
.section ".text"
.extern _nomem_amba_init, _nomem_memory_ctrl_init
@@ -261,11 +257,18 @@ wiminit:
set WIM_INIT, %g3
mov %g3, %wim
-stackp:
+stackinit:
set CONFIG_SYS_INIT_SP_OFFSET, %fp
andn %fp, 0x0f, %fp
sub %fp, 64, %sp
+tbrinit:
+ set CONFIG_SYS_TEXT_BASE, %g2
+ wr %g0, %g2, %tbr
+ nop
+ nop
+ nop
+
/* Obtain the address of _GLOBAL_OFFSET_TABLE_ */
SPARC_PIC_THUNK_CALL(l7)
@@ -302,25 +305,50 @@ cpu_init_unreloc:
call cpu_init_f
nop
-/* un relocated start address of monitor */
-#define TEXT_START _text
+board_init_unreloc:
+ call board_init_f
+ clr %o0 ! boot_flags
-/* un relocated end address of monitor */
-#define DATA_END __init_end
+dead_unreloc:
+ mov 1, %g1 ! For GRMON2 to exit normally.
+ ta 0 ! If board_init_f call returns.. (unlikely)
+ nop
+ nop
+ 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
+ *
+ * %l7 = _GLOBAL_OFFSET_TABLE_ address
+ */
+ .globl relocate_code
+ .type relocate_code, #function
+ .align 4
+relocate_code:
+ !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
+ SPARC_LOAD_ADDRESS(_text, l7, g2) ! start address of monitor
+ SPARC_LOAD_ADDRESS(__init_end, l7, g3) ! end address of monitor
+ 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
@@ -335,106 +363,97 @@ reloc_loop:
*
*/
+ /* clear the relocated .bss area */
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
+#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
+update_trap_table_address:
+ wr %g0, %o2, %tbr
nop
nop
nop
-/* If CACHE snooping is available in hardware the
- * variable leon3_snooping_avail will be set to
- * 0x800000 else 0.
- */
-snoop_detect:
- sethi %hi(0x00800000), %o0
- lda [%g0] 2, %o1
- and %o0, %o1, %o0
- sethi %hi(leon3_snooping_avail+CONFIG_SYS_RELOC_MONITOR_BASE-CONFIG_SYS_TEXT_BASE), %o1
- st %o0, [%lo(leon3_snooping_avail+CONFIG_SYS_RELOC_MONITOR_BASE-CONFIG_SYS_TEXT_BASE)+%o1]
-
-/* call relocate*/
- 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
+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
- SPARC_LOAD_ADDRESS(board_init_f, l7, o1)
- set CONFIG_SYS_RELOC_MONITOR_BASE,%o2
- SPARC_LOAD_ADDRESS(TEXT_START, l7, g1)
- add %o1,%o2,%o1
- sub %o1,%g1,%o1
- call %o1
- clr %o0
+dead:
+ mov 1, %g1 ! For GRMON2 to exit normally.
+ ta 0 ! if call returns.. (unlikely)
+ nop
+ b dead ! infinte loop
+ nop
-dead: ta 0 ! if call returns...
- nop
+!------------------------------------------------------------------------------
/* Interrupt handler caller,
* reg L7: interrupt number
@@ -463,54 +482,56 @@ _irq_entry:
RESTORE_ALL
-!Window overflow trap handler.
+!------------------------------------------------------------------------------
+
+/*
+ * Window overflow trap handler
+ */
.global _window_overflow
_window_overflow:
mov %wim, %l3 ! Calculate next WIM
- mov %g1, %l7
- srl %l3, 1, %g1
- sll %l3, (CONFIG_SYS_SPARC_NWINDOWS-1) , %l4
- or %l4, %g1, %g1
-
+ mov %g1, %l7
+ srl %l3, 1, %g1
+ sll %l3, (CONFIG_SYS_SPARC_NWINDOWS-1), %l4
+ or %g1, %l4, %g1
save ! Get into window to be saved.
- mov %g1, %wim
- nop;
- nop;
- nop
- st %l0, [%sp + 0];
- st %l1, [%sp + 4];
- st %l2, [%sp + 8];
- st %l3, [%sp + 12];
- st %l4, [%sp + 16];
- st %l5, [%sp + 20];
- st %l6, [%sp + 24];
- st %l7, [%sp + 28];
- st %i0, [%sp + 32];
- st %i1, [%sp + 36];
- st %i2, [%sp + 40];
- st %i3, [%sp + 44];
- st %i4, [%sp + 48];
- st %i5, [%sp + 52];
- st %i6, [%sp + 56];
- st %i7, [%sp + 60];
+ mov %g1, %wim
+ nop; nop; nop
+ st %l0, [%sp + 0] ! Save window to the stack
+ st %l1, [%sp + 4]
+ st %l2, [%sp + 8]
+ st %l3, [%sp + 12]
+ st %l4, [%sp + 16]
+ st %l5, [%sp + 20]
+ st %l6, [%sp + 24]
+ st %l7, [%sp + 28]
+ st %i0, [%sp + 32]
+ st %i1, [%sp + 36]
+ st %i2, [%sp + 40]
+ st %i3, [%sp + 44]
+ st %i4, [%sp + 48]
+ st %i5, [%sp + 52]
+ st %i6, [%sp + 56]
+ st %i7, [%sp + 60]
restore ! Go back to trap window.
- mov %l7, %g1
+ mov %l7, %g1
jmp %l1 ! Re-execute save.
- rett %l2
-
-/* Window underflow trap handler. */
+ rett %l2
+/*
+ * Window underflow trap handler
+ */
.global _window_underflow
_window_underflow:
- mov %wim, %l3 ! Calculate next WIM
- sll %l3, 1, %l4
- srl %l3, (CONFIG_SYS_SPARC_NWINDOWS-1), %l5
- or %l5, %l4, %l5
- mov %l5, %wim
+ mov %wim, %l3 ! Calculate next WIM
+ srl %l3, (CONFIG_SYS_SPARC_NWINDOWS-1), %l5
+ sll %l3, 1, %l4
+ or %l5, %l4, %l5
+ mov %l5, %wim
nop; nop; nop
restore ! Two restores to get into the
restore ! window to restore
@@ -533,9 +554,9 @@ _window_underflow:
save ! Get back to the trap window.
save
jmp %l1 ! Re-execute restore.
- rett %l2
+ rett %l2
- retl
+!------------------------------------------------------------------------------
_nmi_trap:
nop
diff --git a/arch/sparc/cpu/leon3/usb_uhci.c b/arch/sparc/cpu/leon3/usb_uhci.c
index 1be84c646b8..242b83fbcfa 100644
--- a/arch/sparc/cpu/leon3/usb_uhci.c
+++ b/arch/sparc/cpu/leon3/usb_uhci.c
@@ -85,10 +85,11 @@
#include <usb.h>
#include "usb_uhci.h"
+DECLARE_GLOBAL_DATA_PTR;
+
#define USB_MAX_TEMP_TD 128 /* number of temporary TDs for bulk and control transfers */
#define USB_MAX_TEMP_INT_TD 32 /* number of temporary TDs for Interrupt transfers */
-extern int leon3_snooping_avail;
/*
#define out16r(address,data) (*(unsigned short *)(address) = \
(unsigned short)( \
@@ -573,7 +574,7 @@ void usb_check_skel(void)
if (qh_cntrl.dev_ptr != 0) { /* it's a device assigned check if this caused IRQ */
dev = (struct usb_device *)qh_cntrl.dev_ptr;
/* Flush cache now that hardware updated DATA and TDs/QHs */
- if (!leon3_snooping_avail)
+ if (!gd->arch.snooping_avail)
sparc_dcache_flush_all();
usb_get_td_status(&tmp_td[0], dev); /* update status */
if (!(dev->status & USB_ST_NOT_PROC)) { /* is not active anymore, disconnect devices */
@@ -584,7 +585,7 @@ void usb_check_skel(void)
if (qh_bulk.dev_ptr != 0) { /* it's a device assigned check if this caused IRQ */
dev = (struct usb_device *)qh_bulk.dev_ptr;
/* Flush cache now that hardware updated DATA and TDs/QHs */
- if (!leon3_snooping_avail)
+ if (!gd->arch.snooping_avail)
sparc_dcache_flush_all();
usb_get_td_status(&tmp_td[0], dev); /* update status */
if (!(dev->status & USB_ST_NOT_PROC)) { /* is not active anymore, disconnect devices */