avionic design with actual uboot and tooling
submodule of avionic design uboot bootloader and with included tools to get you started , read readme.md and readme-tk1-loader.md
This commit is contained in:
70
u-boot/arch/sparc/Kconfig
Normal file
70
u-boot/arch/sparc/Kconfig
Normal file
@@ -0,0 +1,70 @@
|
||||
menu "SPARC architecture"
|
||||
depends on SPARC
|
||||
|
||||
config LEON
|
||||
bool
|
||||
|
||||
config LEON2
|
||||
bool
|
||||
select LEON
|
||||
|
||||
config LEON3
|
||||
bool
|
||||
select LEON
|
||||
|
||||
config SYS_SPARC_NWINDOWS
|
||||
int "Number of SPARC register windows"
|
||||
range 2 32
|
||||
default "8"
|
||||
help
|
||||
Specify the number of SPARC register windows implemented by this
|
||||
processor. A SPARC implementation can have from 2 to 32 windows.
|
||||
If unsure, choose 8.
|
||||
|
||||
choice
|
||||
prompt "Board select"
|
||||
optional
|
||||
|
||||
config TARGET_GRSIM_LEON2
|
||||
bool "GRSIM simulating a LEON2 board"
|
||||
select LEON2
|
||||
|
||||
config TARGET_GR_CPCI_AX2000
|
||||
bool "Gaisler GR-CPCI-AX2000 board"
|
||||
select LEON3
|
||||
|
||||
config TARGET_GR_EP2S60
|
||||
bool "Gaisler Template design for Altera NIOS board with Stratix EP2S60"
|
||||
select LEON3
|
||||
help
|
||||
Gaisler Research AB's Template design (GPL Open Source SPARC/LEON3
|
||||
96MHz) for Altera NIOS Development board Stratix II edition,
|
||||
with the FPGA device EP2S60.
|
||||
|
||||
config TARGET_GR_XC3S_1500
|
||||
bool "Gaisler GR-XC3S-1500 spartan board"
|
||||
select LEON3
|
||||
|
||||
config TARGET_GRSIM
|
||||
bool "GRSIM simulating a LEON3 GR-XC3S-1500 board"
|
||||
select LEON3
|
||||
|
||||
endchoice
|
||||
|
||||
config SYS_ARCH
|
||||
default "sparc"
|
||||
|
||||
config SYS_CPU
|
||||
default "leon2" if LEON2
|
||||
default "leon3" if LEON3
|
||||
|
||||
config SYS_VENDOR
|
||||
default "gaisler"
|
||||
|
||||
source "board/gaisler/gr_cpci_ax2000/Kconfig"
|
||||
source "board/gaisler/gr_ep2s60/Kconfig"
|
||||
source "board/gaisler/gr_xc3s_1500/Kconfig"
|
||||
source "board/gaisler/grsim/Kconfig"
|
||||
source "board/gaisler/grsim_leon2/Kconfig"
|
||||
|
||||
endmenu
|
||||
8
u-boot/arch/sparc/Makefile
Normal file
8
u-boot/arch/sparc/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
head-y := arch/sparc/cpu/$(CPU)/start.o
|
||||
|
||||
libs-y += arch/sparc/cpu/$(CPU)/
|
||||
libs-y += arch/sparc/lib/
|
||||
25
u-boot/arch/sparc/config.mk
Normal file
25
u-boot/arch/sparc/config.mk
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# (C) Copyright 2015
|
||||
# Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
ifeq ($(CROSS_COMPILE),)
|
||||
CROSS_COMPILE := sparc-linux-
|
||||
endif
|
||||
|
||||
# This GCC compiler is known to work:
|
||||
# https://www.kernel.org/pub/tools/crosstool/files/bin/x86_64/4.9.0/
|
||||
|
||||
gcclibdir := $(shell dirname `$(CC) -print-libgcc-file-name`)
|
||||
|
||||
CONFIG_STANDALONE_LOAD_ADDR ?= 0x00000000 -L $(gcclibdir) \
|
||||
-T $(srctree)/examples/standalone/sparc.lds
|
||||
|
||||
cpuflags-$(CONFIG_LEON2) := -mcpu=leon
|
||||
cpuflags-$(CONFIG_LEON3) := -mcpu=leon3
|
||||
|
||||
PLATFORM_CPPFLAGS += $(cpuflags-y)
|
||||
|
||||
PLATFORM_RELFLAGS += -fPIC
|
||||
9
u-boot/arch/sparc/cpu/leon2/Makefile
Normal file
9
u-boot/arch/sparc/cpu/leon2/Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
# (C) Copyright 2003-2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
extra-y = start.o
|
||||
obj-y = cpu_init.o serial.o cpu.o interrupts.o prom.o
|
||||
60
u-boot/arch/sparc/cpu/leon2/cpu.c
Normal file
60
u-boot/arch/sparc/cpu/leon2/cpu.c
Normal file
@@ -0,0 +1,60 @@
|
||||
/* CPU specific code for the LEON2 CPU
|
||||
*
|
||||
* (C) Copyright 2007, 2015
|
||||
* Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <watchdog.h>
|
||||
#include <command.h>
|
||||
#include <netdev.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
extern void _reset_reloc(void);
|
||||
|
||||
int checkcpu(void)
|
||||
{
|
||||
/* check LEON version here */
|
||||
printf("CPU: LEON2\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DISPLAY_CPUINFO
|
||||
|
||||
int print_cpuinfo(void)
|
||||
{
|
||||
printf("CPU: LEON2\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
void cpu_reset(void)
|
||||
{
|
||||
/* Interrupts off */
|
||||
disable_interrupts();
|
||||
|
||||
/* jump to restart in flash */
|
||||
_reset_reloc();
|
||||
}
|
||||
|
||||
int do_reset(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
cpu_reset();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef CONFIG_GRETH
|
||||
int cpu_eth_init(bd_t *bis)
|
||||
{
|
||||
return greth_initialize(bis);
|
||||
}
|
||||
#endif
|
||||
95
u-boot/arch/sparc/cpu/leon2/cpu_init.c
Normal file
95
u-boot/arch/sparc/cpu/leon2/cpu_init.c
Normal file
@@ -0,0 +1,95 @@
|
||||
/* Initializes CPU and basic hardware such as memory
|
||||
* controllers, IRQ controller and system timer 0.
|
||||
*
|
||||
* (C) Copyright 2007, 2015
|
||||
* Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/asi.h>
|
||||
#include <asm/leon.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <config.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/*
|
||||
* Breath some life into the CPU...
|
||||
*
|
||||
* Set up the memory map,
|
||||
* initialize a bunch of registers.
|
||||
*
|
||||
* Run from FLASH/PROM:
|
||||
* - until memory controller is set up, only registers available
|
||||
* - no global variables available for writing
|
||||
* - constants available
|
||||
*/
|
||||
|
||||
void cpu_init_f(void)
|
||||
{
|
||||
LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;
|
||||
|
||||
/* initialize the IRQMP */
|
||||
leon2->Interrupt_Force = 0;
|
||||
leon2->Interrupt_Pending = 0;
|
||||
leon2->Interrupt_Clear = 0xfffe; /* clear all old pending interrupts */
|
||||
leon2->Interrupt_Mask = 0xfffe0000; /* mask all IRQs */
|
||||
|
||||
/* cache */
|
||||
|
||||
/* I/O port setup */
|
||||
#ifdef LEON2_IO_PORT_DIR
|
||||
leon2->PIO_Direction = LEON2_IO_PORT_DIR;
|
||||
#endif
|
||||
#ifdef LEON2_IO_PORT_DATA
|
||||
leon2->PIO_Data = LEON2_IO_PORT_DATA;
|
||||
#endif
|
||||
#ifdef LEON2_IO_PORT_INT
|
||||
leon2->PIO_Interrupt = LEON2_IO_PORT_INT;
|
||||
#else
|
||||
leon2->PIO_Interrupt = 0;
|
||||
#endif
|
||||
|
||||
/* disable timers */
|
||||
leon2->Timer_Control_1 = leon2->Timer_Control_2 = 0;
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
int cpu_init_r(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* initiate and setup timer0 to configured HZ. Base clock is 1MHz.
|
||||
*/
|
||||
int timer_init(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 = (CONFIG_SYS_TIMER_RATE / CONFIG_SYS_HZ) - 1;
|
||||
leon2->Timer_Control_1 = LEON2_TIMER_CTRL_EN | LEON2_TIMER_CTRL_RS |
|
||||
LEON2_TIMER_CTRL_LD;
|
||||
|
||||
CONFIG_SYS_TIMER_COUNTER = (void *)&leon2->Timer_Counter_1;
|
||||
return 0;
|
||||
}
|
||||
187
u-boot/arch/sparc/cpu/leon2/interrupts.c
Normal file
187
u-boot/arch/sparc/cpu/leon2/interrupts.c
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* (C) Copyright 2007
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com
|
||||
*
|
||||
* (C) Copyright 2006
|
||||
* Detlev Zundel, DENX Software Engineering, dzu@denx.de
|
||||
*
|
||||
* (C) Copyright -2003
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2001
|
||||
* Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <asm/stack.h>
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/processor.h>
|
||||
#include <command.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <asm/leon.h>
|
||||
|
||||
/* 15 normal irqs and a non maskable interrupt */
|
||||
#define NR_IRQS 15
|
||||
|
||||
struct irq_action {
|
||||
interrupt_handler_t *handler;
|
||||
void *arg;
|
||||
unsigned int count;
|
||||
};
|
||||
|
||||
static struct irq_action irq_handlers[NR_IRQS] = { {0}, };
|
||||
static int spurious_irq_cnt = 0;
|
||||
static int spurious_irq = 0;
|
||||
|
||||
static inline unsigned int leon2_get_irqmask(unsigned int irq)
|
||||
{
|
||||
if ((irq < 0) || (irq >= NR_IRQS)) {
|
||||
return 0;
|
||||
} else {
|
||||
return (1 << irq);
|
||||
}
|
||||
}
|
||||
|
||||
static void leon2_ic_disable(unsigned int irq)
|
||||
{
|
||||
unsigned int mask, pil;
|
||||
LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;
|
||||
|
||||
pil = intLock();
|
||||
|
||||
/* get mask of interrupt */
|
||||
mask = leon2_get_irqmask(irq);
|
||||
|
||||
/* set int level */
|
||||
leon2->Interrupt_Mask =
|
||||
SPARC_NOCACHE_READ(&leon2->Interrupt_Mask) & (~mask);
|
||||
|
||||
intUnlock(pil);
|
||||
}
|
||||
|
||||
static void leon2_ic_enable(unsigned int irq)
|
||||
{
|
||||
unsigned int mask, pil;
|
||||
LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;
|
||||
|
||||
pil = intLock();
|
||||
|
||||
/* get mask of interrupt */
|
||||
mask = leon2_get_irqmask(irq);
|
||||
|
||||
/* set int level */
|
||||
leon2->Interrupt_Mask =
|
||||
SPARC_NOCACHE_READ(&leon2->Interrupt_Mask) | mask;
|
||||
|
||||
intUnlock(pil);
|
||||
}
|
||||
|
||||
void handler_irq(int irq, struct pt_regs *regs)
|
||||
{
|
||||
if (irq_handlers[irq].handler) {
|
||||
if (((unsigned int)irq_handlers[irq].handler > CONFIG_SYS_RAM_END) ||
|
||||
((unsigned int)irq_handlers[irq].handler < CONFIG_SYS_RAM_BASE)
|
||||
) {
|
||||
printf("handler_irq: bad handler: %x, irq number %d\n",
|
||||
(unsigned int)irq_handlers[irq].handler, irq);
|
||||
return;
|
||||
}
|
||||
irq_handlers[irq].handler(irq_handlers[irq].arg);
|
||||
irq_handlers[irq].count++;
|
||||
} else {
|
||||
spurious_irq_cnt++;
|
||||
spurious_irq = irq;
|
||||
}
|
||||
}
|
||||
|
||||
void leon2_force_int(int irq)
|
||||
{
|
||||
LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;
|
||||
|
||||
if ((irq >= NR_IRQS) || (irq < 0))
|
||||
return;
|
||||
printf("Forcing interrupt %d\n", irq);
|
||||
|
||||
leon2->Interrupt_Force =
|
||||
SPARC_NOCACHE_READ(&leon2->Interrupt_Force) | (1 << irq);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
int interrupt_init_cpu(void)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* Install and free a interrupt handler.
|
||||
*/
|
||||
|
||||
void irq_install_handler(int irq, interrupt_handler_t * handler, void *arg)
|
||||
{
|
||||
if (irq < 0 || irq >= NR_IRQS) {
|
||||
printf("irq_install_handler: bad irq number %d\n", irq);
|
||||
return;
|
||||
}
|
||||
|
||||
if (irq_handlers[irq].handler != NULL)
|
||||
printf("irq_install_handler: 0x%08lx replacing 0x%08lx\n",
|
||||
(ulong) handler, (ulong) irq_handlers[irq].handler);
|
||||
|
||||
if (((unsigned int)handler > CONFIG_SYS_RAM_END) ||
|
||||
((unsigned int)handler < CONFIG_SYS_RAM_BASE)
|
||||
) {
|
||||
printf("irq_install_handler: bad handler: %x, irq number %d\n",
|
||||
(unsigned int)handler, irq);
|
||||
return;
|
||||
}
|
||||
irq_handlers[irq].handler = handler;
|
||||
irq_handlers[irq].arg = arg;
|
||||
|
||||
/* enable irq on LEON2 hardware */
|
||||
leon2_ic_enable(irq);
|
||||
|
||||
}
|
||||
|
||||
void irq_free_handler(int irq)
|
||||
{
|
||||
if (irq < 0 || irq >= NR_IRQS) {
|
||||
printf("irq_free_handler: bad irq number %d\n", irq);
|
||||
return;
|
||||
}
|
||||
|
||||
/* disable irq on LEON2 hardware */
|
||||
leon2_ic_disable(irq);
|
||||
|
||||
irq_handlers[irq].handler = NULL;
|
||||
irq_handlers[irq].arg = NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_CMD_IRQ)
|
||||
void do_irqinfo(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char * const argv[])
|
||||
{
|
||||
int irq;
|
||||
unsigned int pil = get_pil();
|
||||
printf("PIL level: %u\n\r", pil);
|
||||
printf("Spurious IRQ: %u, last unknown IRQ: %d\n",
|
||||
spurious_irq_cnt, spurious_irq);
|
||||
|
||||
puts("\nInterrupt-Information:\n" "Nr Routine Arg Count\n");
|
||||
|
||||
for (irq = 0; irq < NR_IRQS; irq++) {
|
||||
if (irq_handlers[irq].handler != NULL) {
|
||||
printf("%02d %p %p %d\n", irq,
|
||||
irq_handlers[irq].handler,
|
||||
irq_handlers[irq].arg,
|
||||
irq_handlers[irq].count);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
1032
u-boot/arch/sparc/cpu/leon2/prom.c
Normal file
1032
u-boot/arch/sparc/cpu/leon2/prom.c
Normal file
File diff suppressed because it is too large
Load Diff
147
u-boot/arch/sparc/cpu/leon2/serial.c
Normal file
147
u-boot/arch/sparc/cpu/leon2/serial.c
Normal file
@@ -0,0 +1,147 @@
|
||||
/* GRLIB APBUART Serial controller driver
|
||||
*
|
||||
* (C) Copyright 2008, 2015
|
||||
* Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <serial.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_Uart_regs *regs;
|
||||
unsigned int tmp;
|
||||
|
||||
#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
|
||||
|
||||
/* 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 = 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;
|
||||
}
|
||||
|
||||
static inline LEON2_Uart_regs *leon2_get_uart_regs(void)
|
||||
{
|
||||
LEON2_Uart_regs *uart = gd->arch.uart;
|
||||
|
||||
return uart;
|
||||
}
|
||||
|
||||
static void leon2_serial_putc_raw(const char c)
|
||||
{
|
||||
LEON2_Uart_regs *uart = leon2_get_uart_regs();
|
||||
|
||||
if (!uart)
|
||||
return;
|
||||
|
||||
/* Wait for last character to go. */
|
||||
while (!(readl(&uart->UART_Status) & LEON2_UART_STAT_THE))
|
||||
WATCHDOG_RESET();
|
||||
|
||||
/* Send data */
|
||||
writel(c, &uart->UART_Channel);
|
||||
|
||||
#ifdef LEON_DEBUG
|
||||
/* Wait for data to be sent */
|
||||
while (!(readl(&uart->UART_Status) & LEON2_UART_STAT_TSE))
|
||||
WATCHDOG_RESET();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void leon2_serial_putc(const char c)
|
||||
{
|
||||
if (c == '\n')
|
||||
leon2_serial_putc_raw('\r');
|
||||
|
||||
leon2_serial_putc_raw(c);
|
||||
}
|
||||
|
||||
static int leon2_serial_getc(void)
|
||||
{
|
||||
LEON2_Uart_regs *uart = leon2_get_uart_regs();
|
||||
|
||||
if (!uart)
|
||||
return 0;
|
||||
|
||||
/* Wait for a character to arrive. */
|
||||
while (!(readl(&uart->UART_Status) & LEON2_UART_STAT_DR))
|
||||
WATCHDOG_RESET();
|
||||
|
||||
/* Read character data */
|
||||
return readl(&uart->UART_Channel);
|
||||
}
|
||||
|
||||
static int leon2_serial_tstc(void)
|
||||
{
|
||||
LEON2_Uart_regs *uart = leon2_get_uart_regs();
|
||||
|
||||
if (!uart)
|
||||
return 0;
|
||||
|
||||
return readl(&uart->UART_Status) & LEON2_UART_STAT_DR;
|
||||
}
|
||||
|
||||
static void leon2_serial_setbrg(void)
|
||||
{
|
||||
LEON2_Uart_regs *uart = leon2_get_uart_regs();
|
||||
unsigned int scaler;
|
||||
|
||||
if (!uart)
|
||||
return;
|
||||
|
||||
if (!gd->baudrate)
|
||||
gd->baudrate = CONFIG_BAUDRATE;
|
||||
|
||||
scaler = leon2_serial_calc_scaler(CONFIG_SYS_CLK_FREQ, gd->baudrate);
|
||||
|
||||
writel(scaler, &uart->UART_Scaler);
|
||||
}
|
||||
|
||||
static struct serial_device leon2_serial_drv = {
|
||||
.name = "leon2_serial",
|
||||
.start = leon2_serial_init,
|
||||
.stop = NULL,
|
||||
.setbrg = leon2_serial_setbrg,
|
||||
.putc = leon2_serial_putc,
|
||||
.puts = default_serial_puts,
|
||||
.getc = leon2_serial_getc,
|
||||
.tstc = leon2_serial_tstc,
|
||||
};
|
||||
|
||||
void leon2_serial_initialize(void)
|
||||
{
|
||||
serial_register(&leon2_serial_drv);
|
||||
}
|
||||
|
||||
__weak struct serial_device *default_serial_console(void)
|
||||
{
|
||||
return &leon2_serial_drv;
|
||||
}
|
||||
695
u-boot/arch/sparc/cpu/leon2/start.S
Normal file
695
u-boot/arch/sparc/cpu/leon2/start.S
Normal file
@@ -0,0 +1,695 @@
|
||||
/* This is where the SPARC/LEON3 starts
|
||||
*
|
||||
* Copyright (C) 2007, 2015
|
||||
* Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <asm-offsets.h>
|
||||
#include <config.h>
|
||||
#include <asm/asmmacro.h>
|
||||
#include <asm/winmacro.h>
|
||||
#include <asm/psr.h>
|
||||
#include <asm/stack.h>
|
||||
#include <asm/leon.h>
|
||||
|
||||
/* Entry for traps which jump to a programmer-specified trap handler. */
|
||||
#define TRAPR(H) \
|
||||
wr %g0, 0xfe0, %psr; \
|
||||
mov %g0, %tbr; \
|
||||
ba (H); \
|
||||
mov %g0, %wim;
|
||||
|
||||
#define TRAP(H) \
|
||||
mov %psr, %l0; \
|
||||
ba (H); \
|
||||
nop; nop;
|
||||
|
||||
#define TRAPI(ilevel) \
|
||||
mov ilevel, %l7; \
|
||||
mov %psr, %l0; \
|
||||
b _irq_entry; \
|
||||
mov %wim, %l3
|
||||
|
||||
/* Unexcpected trap will halt the processor by forcing it to error state */
|
||||
#undef BAD_TRAP
|
||||
#define BAD_TRAP ta 0; nop; nop; nop;
|
||||
|
||||
/* Software trap. Treat as BAD_TRAP for the time being... */
|
||||
#define SOFT_TRAP TRAP(_hwerr)
|
||||
|
||||
#define PSR_INIT 0x1FC0 /* Disable traps, set s and ps */
|
||||
#define WIM_INIT 2
|
||||
|
||||
/* All traps low-level code here must end with this macro. */
|
||||
#define RESTORE_ALL b ret_trap_entry; clr %l6;
|
||||
|
||||
#define WRITE_PAUSE nop;nop;nop
|
||||
|
||||
WINDOWSIZE = (16 * 4)
|
||||
ARGPUSHSIZE = (6 * 4)
|
||||
ARGPUSH = (WINDOWSIZE + 4)
|
||||
MINFRAME = (WINDOWSIZE + ARGPUSHSIZE + 4)
|
||||
|
||||
/* Number of register windows */
|
||||
#ifndef CONFIG_SYS_SPARC_NWINDOWS
|
||||
#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))
|
||||
|
||||
.section ".start", "ax"
|
||||
.globl _start, start, _trap_table
|
||||
.globl _irq_entry, nmi_trap
|
||||
.globl _reset_reloc
|
||||
|
||||
/* at address 0
|
||||
* Hardware traps
|
||||
*/
|
||||
start:
|
||||
_start:
|
||||
_trap_table:
|
||||
TRAPR(_hardreset); ! 00 reset trap
|
||||
BAD_TRAP; ! 01 instruction_access_exception
|
||||
BAD_TRAP; ! 02 illegal_instruction
|
||||
BAD_TRAP; ! 03 priveleged_instruction
|
||||
BAD_TRAP; ! 04 fp_disabled
|
||||
TRAP(_window_overflow); ! 05 window_overflow
|
||||
TRAP(_window_underflow); ! 06 window_underflow
|
||||
BAD_TRAP; ! 07 Memory Address Not Aligned
|
||||
BAD_TRAP; ! 08 Floating Point Exception
|
||||
BAD_TRAP; ! 09 Data Miss Exception
|
||||
BAD_TRAP; ! 0a Tagged Instruction Ovrflw
|
||||
BAD_TRAP; ! 0b Watchpoint Detected
|
||||
BAD_TRAP; ! 0c
|
||||
BAD_TRAP; ! 0d
|
||||
BAD_TRAP; ! 0e
|
||||
BAD_TRAP; ! 0f
|
||||
BAD_TRAP; ! 10
|
||||
TRAPI(1); ! 11 IRQ level 1
|
||||
TRAPI(2); ! 12 IRQ level 2
|
||||
TRAPI(3); ! 13 IRQ level 3
|
||||
TRAPI(4); ! 14 IRQ level 4
|
||||
TRAPI(5); ! 15 IRQ level 5
|
||||
TRAPI(6); ! 16 IRQ level 6
|
||||
TRAPI(7); ! 17 IRQ level 7
|
||||
TRAPI(8); ! 18 IRQ level 8
|
||||
TRAPI(9); ! 19 IRQ level 9
|
||||
TRAPI(10); ! 1a IRQ level 10
|
||||
TRAPI(11); ! 1b IRQ level 11
|
||||
TRAPI(12); ! 1c IRQ level 12
|
||||
TRAPI(13); ! 1d IRQ level 13
|
||||
TRAPI(14); ! 1e IRQ level 14
|
||||
TRAP(_nmi_trap); ! 1f IRQ level 15 /
|
||||
! NMI (non maskable interrupt)
|
||||
BAD_TRAP; ! 20 r_register_access_error
|
||||
BAD_TRAP; ! 21 instruction access error
|
||||
BAD_TRAP; ! 22
|
||||
BAD_TRAP; ! 23
|
||||
BAD_TRAP; ! 24 co-processor disabled
|
||||
BAD_TRAP; ! 25 uniplemented FLUSH
|
||||
BAD_TRAP; ! 26
|
||||
BAD_TRAP; ! 27
|
||||
BAD_TRAP; ! 28 co-processor exception
|
||||
BAD_TRAP; ! 29 data access error
|
||||
BAD_TRAP; ! 2a division by zero
|
||||
BAD_TRAP; ! 2b data store error
|
||||
BAD_TRAP; ! 2c data access MMU miss
|
||||
BAD_TRAP; ! 2d
|
||||
BAD_TRAP; ! 2e
|
||||
BAD_TRAP; ! 2f
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 30-33
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 34-37
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 38-3b
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 3c-3f
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 40-43
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 44-47
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 48-4b
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 4c-4f
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 50-53
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 54-57
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 58-5b
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 5c-5f
|
||||
|
||||
/* implementaion dependent */
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 60-63
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 64-67
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 68-6b
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 6c-6f
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 70-73
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 74-77
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 78-7b
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 7c-7f
|
||||
|
||||
/* Software traps, not handled */
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 80-83
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 84-87
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 88-8b
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 8c-8f
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 90-93
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 94-97
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 98-9b
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 9c-9f
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! a0-a3
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! a4-a7
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! a8-ab
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! ac-af
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! b0-b3
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! b4-b7
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! b8-bb
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! bc-bf
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! c0-c3
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! c4-c7
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! c8-cb
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! cc-cf
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! d0-d3
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! d4-d7
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! d8-db
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! dc-df
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! e0-e3
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! e4-e7
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! e8-eb
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! ec-ef
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! f0-f3
|
||||
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
|
||||
|
||||
.section ".text"
|
||||
.align 4
|
||||
|
||||
_hardreset:
|
||||
1000:
|
||||
flush
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* Init Cache */
|
||||
set (LEON2_PREGS+LEON_REG_CACHECTRL_OFFSET), %g1
|
||||
set 0x0081000f, %g2
|
||||
st %g2, [%g1]
|
||||
|
||||
mov %g0, %y
|
||||
clr %g1
|
||||
clr %g2
|
||||
clr %g3
|
||||
clr %g4
|
||||
clr %g5
|
||||
clr %g6
|
||||
clr %g7
|
||||
|
||||
mov %asr17, %g3
|
||||
and %g3, 0x1f, %g3
|
||||
clear_window:
|
||||
mov %g0, %l0
|
||||
mov %g0, %l1
|
||||
mov %g0, %l2
|
||||
mov %g0, %l3
|
||||
mov %g0, %l4
|
||||
mov %g0, %l5
|
||||
mov %g0, %l6
|
||||
mov %g0, %l7
|
||||
mov %g0, %o0
|
||||
mov %g0, %o1
|
||||
mov %g0, %o2
|
||||
mov %g0, %o3
|
||||
mov %g0, %o4
|
||||
mov %g0, %o5
|
||||
mov %g0, %o6
|
||||
mov %g0, %o7
|
||||
subcc %g3, 1, %g3
|
||||
bge clear_window
|
||||
save
|
||||
|
||||
leon2_init:
|
||||
/* LEON2 Register Base in g1 */
|
||||
set LEON2_PREGS, %g1
|
||||
|
||||
leon2_init_cache:
|
||||
/* Set Cache control register */
|
||||
set 0x1000f, %g2
|
||||
st %g2, [%g1 + 0x14]
|
||||
|
||||
leon2_init_clear:
|
||||
|
||||
/* Clear LEON2 registers */
|
||||
st %g0, [%g1 + LEON2_ECTRL]
|
||||
st %g0, [%g1 + LEON2_IMASK]
|
||||
st %g0, [%g1 + LEON2_IPEND]
|
||||
st %g0, [%g1 + LEON2_IFORCE]
|
||||
st %g0, [%g1 + LEON2_ICLEAR]
|
||||
st %g0, [%g1 + LEON2_IOREG]
|
||||
st %g0, [%g1 + LEON2_IODIR]
|
||||
st %g0, [%g1 + LEON2_IOICONF]
|
||||
st %g0, [%g1 + LEON2_UCTRL0]
|
||||
st %g0, [%g1 + LEON2_UCTRL1]
|
||||
|
||||
leon2_init_ioport:
|
||||
/* I/O port initialization */
|
||||
set 0xaa00, %g2
|
||||
st %g2, [%g1 + LEON2_IOREG]
|
||||
|
||||
leon2_init_mctrl:
|
||||
|
||||
/* memory config register 1 */
|
||||
set CONFIG_SYS_GRLIB_MEMCFG1, %g2
|
||||
ld [%g1], %g3 !
|
||||
and %g3, 0x300, %g3
|
||||
or %g2, %g3, %g2
|
||||
st %g2, [%g1 + LEON2_MCFG1]
|
||||
set CONFIG_SYS_GRLIB_MEMCFG2, %g2 ! Load memory config register 2
|
||||
#if !( defined(TSIM) || !defined(BZIMAGE))
|
||||
st %g2, [%g1 + LEON2_MCFG2] ! only for prom version, else done by "dumon -i"
|
||||
#endif
|
||||
set CONFIG_SYS_GRLIB_MEMCFG3, %g2 ! Init FT register
|
||||
st %g2, [%g1 + LEON2_ECTRL]
|
||||
ld [%g1 + LEON2_ECTRL], %g2
|
||||
srl %g2, 30, %g2
|
||||
andcc %g2, 3, %g6
|
||||
bne,a leon2_init_wim
|
||||
mov %g0, %asr16 ! clear err_reg
|
||||
|
||||
leon2_init_wim:
|
||||
set WIM_INIT, %g3
|
||||
mov %g3, %wim
|
||||
|
||||
leon2_init_psr:
|
||||
set 0x1000, %g3
|
||||
mov %psr, %g2
|
||||
wr %g2, %g3, %psr
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
leon2_init_stackp:
|
||||
set CONFIG_SYS_INIT_SP_OFFSET, %fp
|
||||
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
|
||||
|
||||
reloc:
|
||||
SPARC_LOAD_ADDRESS(TEXT_START, l7, g2)
|
||||
SPARC_LOAD_ADDRESS(DATA_END, l7, g3)
|
||||
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
|
||||
clr %l2
|
||||
clr %l3
|
||||
clr %g2
|
||||
|
||||
/* register g4 contain address to start
|
||||
* This means that BSS must be directly after data and code segments
|
||||
*
|
||||
* g3 is length of bss = (__bss_end-__bss_start)
|
||||
*
|
||||
*/
|
||||
|
||||
/* clear bss area (the relocated) */
|
||||
clr_bss:
|
||||
SPARC_LOAD_ADDRESS(__bss_start, l7, g2)
|
||||
SPARC_LOAD_ADDRESS(__bss_end, l7, 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 */
|
||||
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 */
|
||||
fixup_got:
|
||||
SPARC_LOAD_ADDRESS(__got_start, l7, g4)
|
||||
add %g4, %g6, %g4
|
||||
SPARC_LOAD_ADDRESS(__got_end, l7, g3)
|
||||
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)
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
update_trap_table_address:
|
||||
wr %g0, %o2, %tbr
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
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
|
||||
|
||||
!------------------------------------------------------------------------------
|
||||
|
||||
/* Interrupt handler caller,
|
||||
* reg L7: interrupt number
|
||||
* reg L0: psr after interrupt
|
||||
* reg L1: PC
|
||||
* reg L2: next PC
|
||||
* reg L3: wim
|
||||
*/
|
||||
_irq_entry:
|
||||
SAVE_ALL
|
||||
|
||||
or %l0, PSR_PIL, %g2
|
||||
wr %g2, 0x0, %psr
|
||||
WRITE_PAUSE
|
||||
wr %g2, PSR_ET, %psr
|
||||
WRITE_PAUSE
|
||||
mov %l7, %o0 ! irq level
|
||||
set handler_irq, %o1
|
||||
set (CONFIG_SYS_RELOC_MONITOR_BASE-CONFIG_SYS_TEXT_BASE), %o2
|
||||
add %o1, %o2, %o1
|
||||
call %o1
|
||||
add %sp, SF_REGS_SZ, %o1 ! pt_regs ptr
|
||||
or %l0, PSR_PIL, %g2 ! restore PIL after handler_irq
|
||||
wr %g2, PSR_ET, %psr ! keep ET up
|
||||
WRITE_PAUSE
|
||||
|
||||
RESTORE_ALL
|
||||
|
||||
!------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
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];
|
||||
restore ! Go back to trap window.
|
||||
mov %l7, %g1
|
||||
jmp %l1 ! Re-execute save.
|
||||
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
|
||||
nop; nop; nop
|
||||
restore ! Two restores to get into the
|
||||
restore ! window to restore
|
||||
ld [%sp + 0], %l0; ! Restore window from the stack
|
||||
ld [%sp + 4], %l1;
|
||||
ld [%sp + 8], %l2;
|
||||
ld [%sp + 12], %l3;
|
||||
ld [%sp + 16], %l4;
|
||||
ld [%sp + 20], %l5;
|
||||
ld [%sp + 24], %l6;
|
||||
ld [%sp + 28], %l7;
|
||||
ld [%sp + 32], %i0;
|
||||
ld [%sp + 36], %i1;
|
||||
ld [%sp + 40], %i2;
|
||||
ld [%sp + 44], %i3;
|
||||
ld [%sp + 48], %i4;
|
||||
ld [%sp + 52], %i5;
|
||||
ld [%sp + 56], %i6;
|
||||
ld [%sp + 60], %i7;
|
||||
save ! Get back to the trap window.
|
||||
save
|
||||
jmp %l1 ! Re-execute restore.
|
||||
rett %l2
|
||||
|
||||
!------------------------------------------------------------------------------
|
||||
|
||||
_nmi_trap:
|
||||
nop
|
||||
jmp %l1
|
||||
rett %l2
|
||||
|
||||
_hwerr:
|
||||
ta 0
|
||||
nop
|
||||
nop
|
||||
b _hwerr ! loop infinite
|
||||
nop
|
||||
|
||||
/* Registers to not touch at all. */
|
||||
#define t_psr l0 /* Set by caller */
|
||||
#define t_pc l1 /* Set by caller */
|
||||
#define t_npc l2 /* Set by caller */
|
||||
#define t_wim l3 /* Set by caller */
|
||||
#define t_twinmask l4 /* Set at beginning of this entry routine. */
|
||||
#define t_kstack l5 /* Set right before pt_regs frame is built */
|
||||
#define t_retpc l6 /* If you change this, change winmacro.h header file */
|
||||
#define t_systable l7 /* Never touch this, could be the syscall table ptr. */
|
||||
#define curptr g6 /* Set after pt_regs frame is built */
|
||||
|
||||
trap_setup:
|
||||
/* build a pt_regs trap frame. */
|
||||
sub %fp, (SF_REGS_SZ + PT_REGS_SZ), %t_kstack
|
||||
PT_STORE_ALL(t_kstack, t_psr, t_pc, t_npc, g2)
|
||||
|
||||
/* See if we are in the trap window. */
|
||||
mov 1, %t_twinmask
|
||||
sll %t_twinmask, %t_psr, %t_twinmask ! t_twinmask = (1 << psr)
|
||||
andcc %t_twinmask, %t_wim, %g0
|
||||
beq 1f ! in trap window, clean up
|
||||
nop
|
||||
|
||||
/*-------------------------------------------------
|
||||
* Spill , adjust %wim and go.
|
||||
*/
|
||||
srl %t_wim, 0x1, %g2 ! begin computation of new %wim
|
||||
|
||||
set (CONFIG_SYS_SPARC_NWINDOWS-1), %g3 !NWINDOWS-1
|
||||
|
||||
sll %t_wim, %g3, %t_wim ! NWINDOWS-1
|
||||
or %t_wim, %g2, %g2
|
||||
and %g2, 0xff, %g2
|
||||
|
||||
save %g0, %g0, %g0 ! get in window to be saved
|
||||
|
||||
/* Set new %wim value */
|
||||
wr %g2, 0x0, %wim
|
||||
|
||||
/* Save the kernel window onto the corresponding stack. */
|
||||
RW_STORE(sp)
|
||||
|
||||
restore %g0, %g0, %g0
|
||||
/*-------------------------------------------------*/
|
||||
|
||||
1:
|
||||
/* Trap from kernel with a window available.
|
||||
* Just do it...
|
||||
*/
|
||||
jmpl %t_retpc + 0x8, %g0 ! return to caller
|
||||
mov %t_kstack, %sp ! jump onto new stack
|
||||
|
||||
#define twin_tmp1 l4
|
||||
#define glob_tmp g4
|
||||
#define curptr g6
|
||||
ret_trap_entry:
|
||||
wr %t_psr, 0x0, %psr ! enable nesting again, clear ET
|
||||
|
||||
/* Will the rett land us in the invalid window? */
|
||||
mov 2, %g1
|
||||
sll %g1, %t_psr, %g1
|
||||
|
||||
set CONFIG_SYS_SPARC_NWINDOWS, %g2 !NWINDOWS
|
||||
|
||||
srl %g1, %g2, %g2
|
||||
or %g1, %g2, %g1
|
||||
rd %wim, %g2
|
||||
andcc %g2, %g1, %g0
|
||||
be 1f ! Nope, just return from the trap
|
||||
sll %g2, 0x1, %g1
|
||||
|
||||
/* We have to grab a window before returning. */
|
||||
set (CONFIG_SYS_SPARC_NWINDOWS-1), %g3 !NWINDOWS-1
|
||||
|
||||
srl %g2, %g3, %g2
|
||||
or %g1, %g2, %g1
|
||||
and %g1, 0xff, %g1
|
||||
|
||||
wr %g1, 0x0, %wim
|
||||
|
||||
/* Grrr, make sure we load from the right %sp... */
|
||||
PT_LOAD_ALL(sp, t_psr, t_pc, t_npc, g1)
|
||||
|
||||
restore %g0, %g0, %g0
|
||||
RW_LOAD(sp)
|
||||
b 2f
|
||||
save %g0, %g0, %g0
|
||||
|
||||
/* Reload the entire frame in case this is from a
|
||||
* kernel system call or whatever...
|
||||
*/
|
||||
1:
|
||||
PT_LOAD_ALL(sp, t_psr, t_pc, t_npc, g1)
|
||||
2:
|
||||
wr %t_psr, 0x0, %psr
|
||||
nop;
|
||||
nop;
|
||||
nop
|
||||
|
||||
jmp %t_pc
|
||||
rett %t_npc
|
||||
|
||||
/* This is called from relocated C-code.
|
||||
* It resets the system by jumping to _start
|
||||
*/
|
||||
_reset_reloc:
|
||||
set start, %l0
|
||||
call %l0
|
||||
nop
|
||||
10
u-boot/arch/sparc/cpu/leon3/Makefile
Normal file
10
u-boot/arch/sparc/cpu/leon3/Makefile
Normal file
@@ -0,0 +1,10 @@
|
||||
#
|
||||
# (C) Copyright 2003-2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
extra-y = start.o
|
||||
obj-y = cpu_init.o serial.o cpu.o ambapp.o ambapp_low.o ambapp_low_c.o \
|
||||
interrupts.o prom.o usb_uhci.o memcfg.o memcfg_low.o
|
||||
316
u-boot/arch/sparc/cpu/leon3/ambapp.c
Normal file
316
u-boot/arch/sparc/cpu/leon3/ambapp.c
Normal file
@@ -0,0 +1,316 @@
|
||||
/* GRLIB AMBA Plug&Play information scanning, relies on assembler
|
||||
* routines.
|
||||
*
|
||||
* (C) Copyright 2010, 2015
|
||||
* Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
#include <common.h>
|
||||
#include <malloc.h>
|
||||
#include <ambapp.h>
|
||||
#include <config.h>
|
||||
|
||||
/************ C INTERFACE OF ASSEMBLER SCAN ROUTINES ************/
|
||||
struct ambapp_find_apb_info {
|
||||
/* Address of APB device Plug&Play information */
|
||||
struct ambapp_pnp_apb *pnp;
|
||||
/* AHB Bus index of where the APB-Master Bridge device was found */
|
||||
int ahb_bus_index;
|
||||
int dec_index;
|
||||
};
|
||||
|
||||
struct ambapp_find_ahb_info {
|
||||
/* Address of AHB device Plug&Play information */
|
||||
struct ambapp_pnp_ahb *pnp;
|
||||
/* AHB Bus index of where the AHB device was found */
|
||||
int ahb_bus_index;
|
||||
int dec_index;
|
||||
};
|
||||
|
||||
extern void ambapp_find_buses(unsigned int ioarea, struct ambapp_bus *abus);
|
||||
|
||||
extern int ambapp_find_apb(struct ambapp_bus *abus, unsigned int dev_vend,
|
||||
int index, struct ambapp_find_apb_info *result);
|
||||
|
||||
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 __section(.data);
|
||||
|
||||
void ambapp_bus_init(
|
||||
unsigned int ioarea,
|
||||
unsigned int freq,
|
||||
struct ambapp_bus *abus)
|
||||
{
|
||||
int i;
|
||||
|
||||
ambapp_find_buses(ioarea, abus);
|
||||
for (i = 0; i < 6; i++)
|
||||
if (abus->ioareas[i] == 0)
|
||||
break;
|
||||
abus->buses = i;
|
||||
abus->freq = freq;
|
||||
}
|
||||
|
||||
/* Parse APB PnP Information */
|
||||
void ambapp_apb_parse(struct ambapp_find_apb_info *info, ambapp_apbdev *dev)
|
||||
{
|
||||
struct ambapp_pnp_apb *apb = info->pnp;
|
||||
unsigned int apbbase = (unsigned int)apb & 0xfff00000;
|
||||
|
||||
dev->vendor = amba_vendor(apb->id);
|
||||
dev->device = amba_device(apb->id);
|
||||
dev->irq = amba_irq(apb->id);
|
||||
dev->ver = amba_ver(apb->id);
|
||||
dev->address = (apbbase | (((apb->iobar & 0xfff00000) >> 12))) &
|
||||
(((apb->iobar & 0x0000fff0) << 4) | 0xfff00000);
|
||||
dev->mask = amba_apb_mask(apb->iobar);
|
||||
dev->ahb_bus_index = info->ahb_bus_index - 1;
|
||||
}
|
||||
|
||||
/* Parse AHB PnP information */
|
||||
void ambapp_ahb_parse(struct ambapp_find_ahb_info *info, ambapp_ahbdev *dev)
|
||||
{
|
||||
struct ambapp_pnp_ahb *ahb = info->pnp;
|
||||
unsigned int ahbbase = (unsigned int)ahb & 0xfff00000;
|
||||
int i, type;
|
||||
unsigned int addr, mask, mbar;
|
||||
|
||||
dev->vendor = amba_vendor(ahb->id);
|
||||
dev->device = amba_device(ahb->id);
|
||||
dev->irq = amba_irq(ahb->id);
|
||||
dev->ver = amba_ver(ahb->id);
|
||||
dev->userdef[0] = ahb->custom[0];
|
||||
dev->userdef[1] = ahb->custom[1];
|
||||
dev->userdef[2] = ahb->custom[2];
|
||||
dev->ahb_bus_index = info->ahb_bus_index - 1;
|
||||
for (i = 0; i < 4; i++) {
|
||||
mbar = ahb->mbar[i];
|
||||
addr = amba_membar_start(mbar);
|
||||
type = amba_membar_type(mbar);
|
||||
if (type == AMBA_TYPE_AHBIO) {
|
||||
addr = amba_ahbio_adr(addr, ahbbase);
|
||||
mask = (((unsigned int)
|
||||
(amba_membar_mask((~mbar))<<8)|0xff))+1;
|
||||
} else {
|
||||
/* AHB memory area, absolute address */
|
||||
mask = (~((unsigned int)
|
||||
(amba_membar_mask(mbar)<<20)))+1;
|
||||
}
|
||||
dev->address[i] = addr;
|
||||
dev->mask[i] = mask;
|
||||
dev->type[i] = type;
|
||||
}
|
||||
}
|
||||
|
||||
int ambapp_apb_find(struct ambapp_bus *abus, int vendor, int device,
|
||||
int index, ambapp_apbdev *dev)
|
||||
{
|
||||
unsigned int devid = AMBA_PNP_ID(vendor, device);
|
||||
int found;
|
||||
struct ambapp_find_apb_info apbdev;
|
||||
|
||||
found = ambapp_find_apb(abus, devid, index, &apbdev);
|
||||
if (found == 1)
|
||||
ambapp_apb_parse(&apbdev, dev);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
int ambapp_apb_count(struct ambapp_bus *abus, int vendor, int device)
|
||||
{
|
||||
unsigned int devid = AMBA_PNP_ID(vendor, device);
|
||||
int found;
|
||||
struct ambapp_find_apb_info apbdev;
|
||||
|
||||
found = ambapp_find_apb(abus, devid, 63, &apbdev);
|
||||
if (found == 1)
|
||||
return 64;
|
||||
else
|
||||
return 63 - apbdev.dec_index;
|
||||
}
|
||||
|
||||
int ambapp_ahb_find(struct ambapp_bus *abus, int vendor, int device,
|
||||
int index, ambapp_ahbdev *dev, int type)
|
||||
{
|
||||
int found;
|
||||
struct ambapp_find_ahb_info ahbdev;
|
||||
unsigned int devid = AMBA_PNP_ID(vendor, device);
|
||||
|
||||
found = ambapp_find_ahb(abus, devid, index, type, &ahbdev);
|
||||
if (found == 1)
|
||||
ambapp_ahb_parse(&ahbdev, dev);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
int ambapp_ahbmst_find(struct ambapp_bus *abus, int vendor, int device,
|
||||
int index, ambapp_ahbdev *dev)
|
||||
{
|
||||
return ambapp_ahb_find(abus, vendor, device, index, dev, DEV_AHB_MST);
|
||||
}
|
||||
|
||||
int ambapp_ahbslv_find(struct ambapp_bus *abus, int vendor, int device,
|
||||
int index, ambapp_ahbdev *dev)
|
||||
{
|
||||
return ambapp_ahb_find(abus, vendor, device, index, dev, DEV_AHB_SLV);
|
||||
}
|
||||
|
||||
int ambapp_ahb_count(struct ambapp_bus *abus, int vendor, int device, int type)
|
||||
{
|
||||
int found;
|
||||
struct ambapp_find_ahb_info ahbdev;
|
||||
unsigned int devid = AMBA_PNP_ID(vendor, device);
|
||||
|
||||
found = ambapp_find_ahb(abus, devid, 63, type, &ahbdev);
|
||||
if (found == 1)
|
||||
return 64;
|
||||
else
|
||||
return 63 - ahbdev.dec_index;
|
||||
}
|
||||
|
||||
int ambapp_ahbmst_count(struct ambapp_bus *abus, int vendor, int device)
|
||||
{
|
||||
return ambapp_ahb_count(abus, vendor, device, DEV_AHB_MST);
|
||||
}
|
||||
|
||||
int ambapp_ahbslv_count(struct ambapp_bus *abus, int vendor, int device)
|
||||
{
|
||||
return ambapp_ahb_count(abus, vendor, device, DEV_AHB_SLV);
|
||||
}
|
||||
|
||||
/* The define CONFIG_SYS_GRLIB_SINGLE_BUS may be defined on GRLIB systems
|
||||
* where only one AHB Bus is available - no bridges are present. This option
|
||||
* is available only to reduce the footprint.
|
||||
*
|
||||
* Defining this on a multi-bus GRLIB system may also work depending on the
|
||||
* design.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_SYS_GRLIB_SINGLE_BUS
|
||||
|
||||
/* GAISLER AHB2AHB Version 1 Bridge Definitions */
|
||||
#define AHB2AHB_V1_FLAG_FFACT 0x0f0 /* Frequency factor against top bus */
|
||||
#define AHB2AHB_V1_FLAG_FFACT_DIR 0x100 /* Factor direction, 0=down, 1=up */
|
||||
#define AHB2AHB_V1_FLAG_MBUS 0x00c /* Master bus number mask */
|
||||
#define AHB2AHB_V1_FLAG_SBUS 0x003 /* Slave bus number mask */
|
||||
|
||||
/* Get Parent bus frequency. Note that since we go from a "child" bus
|
||||
* to a parent bus, the frequency factor direction is inverted.
|
||||
*/
|
||||
unsigned int gaisler_ahb2ahb_v1_freq(ambapp_ahbdev *ahb, unsigned int freq)
|
||||
{
|
||||
int dir;
|
||||
unsigned char ffact;
|
||||
|
||||
/* Get division/multiple factor */
|
||||
ffact = (ahb->userdef[0] & AHB2AHB_V1_FLAG_FFACT) >> 4;
|
||||
if (ffact != 0) {
|
||||
dir = ahb->userdef[0] & AHB2AHB_V1_FLAG_FFACT_DIR;
|
||||
|
||||
/* Calculate frequency by dividing or
|
||||
* multiplying system frequency
|
||||
*/
|
||||
if (dir)
|
||||
freq = freq * ffact;
|
||||
else
|
||||
freq = freq / ffact;
|
||||
}
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
/* AHB2AHB and L2CACHE ver 2 is not supported yet. */
|
||||
unsigned int gaisler_ahb2ahb_v2_freq(ambapp_ahbdev *ahb, unsigned int freq)
|
||||
{
|
||||
panic("gaisler_ahb2ahb_v2_freq: AHB2AHB ver 2 not supported\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return the frequency of a AHB bus identified by index found
|
||||
* note that this is not the AHB Bus number.
|
||||
*/
|
||||
unsigned int ambapp_bus_freq(struct ambapp_bus *abus, int ahb_bus_index)
|
||||
{
|
||||
unsigned int freq = abus->freq;
|
||||
#ifndef CONFIG_SYS_GRLIB_SINGLE_BUS
|
||||
unsigned int ioarea, ioarea_parent, bridge_pnp_ofs;
|
||||
struct ambapp_find_ahb_info ahbinfo;
|
||||
ambapp_ahbdev ahb;
|
||||
int parent;
|
||||
|
||||
debug("ambapp_bus_freq: get freq on bus %d\n", ahb_bus_index);
|
||||
|
||||
while (ahb_bus_index != 0) {
|
||||
debug(" BUS[0]: 0x%08x\n", abus->ioareas[0]);
|
||||
debug(" BUS[1]: 0x%08x\n", abus->ioareas[1]);
|
||||
debug(" BUS[2]: 0x%08x\n", abus->ioareas[2]);
|
||||
debug(" BUS[3]: 0x%08x\n", abus->ioareas[3]);
|
||||
debug(" BUS[4]: 0x%08x\n", abus->ioareas[4]);
|
||||
debug(" BUS[5]: 0x%08x\n", abus->ioareas[5]);
|
||||
|
||||
/* Get I/O area of AHB bus */
|
||||
ioarea = abus->ioareas[ahb_bus_index];
|
||||
|
||||
debug(" IOAREA: 0x%08x\n", ioarea);
|
||||
|
||||
/* Get parent bus */
|
||||
parent = (ioarea & 0x7);
|
||||
if (parent == 0) {
|
||||
panic("%s: parent=0 indicates no parent! Stopping.\n",
|
||||
__func__);
|
||||
return -1;
|
||||
}
|
||||
parent = parent - 1;
|
||||
bridge_pnp_ofs = ioarea & 0x7e0;
|
||||
|
||||
debug(" PARENT: %d\n", parent);
|
||||
debug(" BRIDGE_OFS: 0x%08x\n", bridge_pnp_ofs);
|
||||
|
||||
/* Get AHB/AHB bridge PnP address */
|
||||
ioarea_parent = (abus->ioareas[parent] & 0xfff00000) |
|
||||
AMBA_CONF_AREA | AMBA_AHB_SLAVE_CONF_AREA;
|
||||
ahbinfo.pnp = (struct ambapp_pnp_ahb *)
|
||||
(ioarea_parent | bridge_pnp_ofs);
|
||||
|
||||
debug(" IOAREA PARENT: 0x%08x\n", ioarea_parent);
|
||||
debug(" BRIDGE PNP: 0x%p\n", ahbinfo.pnp);
|
||||
|
||||
/* Parse the AHB information */
|
||||
ahbinfo.ahb_bus_index = parent;
|
||||
ambapp_ahb_parse(&ahbinfo, &ahb);
|
||||
|
||||
debug(" BRIDGE ID: VENDOR=%d(0x%x), DEVICE=%d(0x%x)\n",
|
||||
ahb.vendor, ahb.vendor, ahb.device, ahb.device);
|
||||
|
||||
/* Different bridges may convert frequency differently */
|
||||
if ((ahb.vendor == VENDOR_GAISLER) &&
|
||||
((ahb.device == GAISLER_AHB2AHB) ||
|
||||
(ahb.device == GAISLER_L2CACHE))) {
|
||||
/* Get new frequency */
|
||||
if (ahb.ver > 1)
|
||||
freq = gaisler_ahb2ahb_v2_freq(&ahb, freq);
|
||||
else
|
||||
freq = gaisler_ahb2ahb_v1_freq(&ahb, freq);
|
||||
|
||||
debug(" NEW FREQ: %dHz\n", freq);
|
||||
} else {
|
||||
panic("%s: unsupported AMBA bridge\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Step upwards towards system top bus */
|
||||
ahb_bus_index = parent;
|
||||
}
|
||||
#endif
|
||||
|
||||
debug("ambapp_bus_freq: %dHz\n", freq);
|
||||
|
||||
return freq;
|
||||
}
|
||||
784
u-boot/arch/sparc/cpu/leon3/ambapp_low.S
Normal file
784
u-boot/arch/sparc/cpu/leon3/ambapp_low.S
Normal file
@@ -0,0 +1,784 @@
|
||||
/* GRLIB AMBA Plug&Play information scanning implemented without
|
||||
* using memory (stack) and one register window. The code scan
|
||||
* the PnP info and inserts the AHB bridges/buses into register
|
||||
* i0-i5.
|
||||
* The code support
|
||||
* - up to 6 AHB buses
|
||||
* - multiple APB buses
|
||||
* - support for AHB2AHB & L2CACHE bridges
|
||||
*
|
||||
* (C) Copyright 2010, 2015
|
||||
* Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <ambapp.h>
|
||||
|
||||
.seg "text"
|
||||
.globl _nomem_amba_init
|
||||
.globl _nomem_ambapp_find_buses
|
||||
.globl _nomem_find_apb
|
||||
.globl _nomem_find_ahb
|
||||
|
||||
/* Overview
|
||||
* ========
|
||||
*
|
||||
* _nomem_amba_init - Init AMBA bus and calls _nomem_ambapp_find_buses
|
||||
* _nomem_ambapp_find_buses - Scan AMBA PnP info for AHB buses/bridges and
|
||||
* place them in i0-i5, see below
|
||||
* _nomem_find_apb - Find one APB device identified by VENDOR:DEVICE
|
||||
* ID and an index.
|
||||
* _nomem_find_ahb - Find one AHB Master or Slave device identified
|
||||
* by VENDOR:DEVICE ID and an index.
|
||||
* init_ahb_bridges - Local function. Clears i0-i5
|
||||
* insert_ahb_bridge - Local function. Insert a new AHB bus into first
|
||||
* free register in i0-i5. It also checks that the
|
||||
* bus has not already been added.
|
||||
* get_ahb_bridge - Local function. Get AHB bus from registers,
|
||||
* return register iN, where N is defined by o0.
|
||||
*
|
||||
* The _nomem_find_apb and _nomem_find_ahb function requires that i0-i5
|
||||
* are populated with the AHB buses of the system. The registers are
|
||||
* initialized by _nomem_ambapp_find_buses.
|
||||
*
|
||||
* AHB Bus result and requirements of i0-i5
|
||||
* ========================================
|
||||
*
|
||||
* i0: AHB BUS0 IOAREA, no parent bus
|
||||
* i1: AHB BUS1 IOAREA, parent bus is always i0 (AHB BUS0) and bridge address
|
||||
* i2: AHB BUS2 IOAREA, 3-bit parent bus number and bridge address
|
||||
* i3: AHB BUS3 IOAREA, 3-bit parent bus number and bridge address
|
||||
* i4: AHB BUS4 IOAREA, 3-bit parent bus number and bridge address
|
||||
* i5: AHB BUS5 IOAREA, 3-bit parent bus number and bridge address
|
||||
*
|
||||
* AHB BUS
|
||||
* -------
|
||||
* Bits 31-20 (0xfff00000) contain the found bus I/O Area (AHB PnP area).
|
||||
*
|
||||
* 3-bit Parent bus
|
||||
* ----------------
|
||||
* Bits 2-0 (0x00000007) contain parent bus number. Zero if no parent
|
||||
* bus, 1 = parent is AHB BUS 0 (i0), 2 = parent is AHB BUS 1 (i1)..
|
||||
*
|
||||
* Bridge Address
|
||||
* --------------
|
||||
* Bits 10-5 (0x000007e0) contain the index of the Bridge's PnP
|
||||
* information on the parent. Since all bridges are found in the
|
||||
* PnP information they all have a PnP entry. Together with the
|
||||
* parent bus number the PnP entry can be found:
|
||||
* PnPEntry = (BRIDGE_ADDRESS + (iN & 0xfff00000)) | 0x000ff800
|
||||
* where N is the parent bus minus one.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Function initializes the AHB Bridge I/O AREA storage. (Clears i0-i5)
|
||||
*
|
||||
* Arguments
|
||||
* none
|
||||
*
|
||||
* Results
|
||||
* none
|
||||
*
|
||||
* Clobbered
|
||||
* none
|
||||
*/
|
||||
|
||||
init_ahb_bridges:
|
||||
mov %g0, %i0
|
||||
mov %g0, %i1
|
||||
mov %g0, %i2
|
||||
mov %g0, %i3
|
||||
mov %g0, %i4
|
||||
retl
|
||||
mov %g0, %i5
|
||||
|
||||
/* Function returns AHB Bridge I/O AREA for specified bus.
|
||||
*
|
||||
* Arguments
|
||||
* - o0 = bus number
|
||||
*
|
||||
* Results
|
||||
* - o0 = I/O AREA
|
||||
*
|
||||
* Clobbered
|
||||
* none
|
||||
*/
|
||||
get_ahb_bridge:
|
||||
cmp %o0, 1
|
||||
be,a L1
|
||||
mov %i0, %o0
|
||||
|
||||
cmp %o0, 2
|
||||
be,a L1
|
||||
mov %i1, %o0
|
||||
|
||||
cmp %o0, 3
|
||||
be,a L1
|
||||
mov %i2, %o0
|
||||
|
||||
cmp %o0, 4
|
||||
be,a L1
|
||||
mov %i3, %o0
|
||||
|
||||
cmp %o0, 5
|
||||
be,a L1
|
||||
mov %i4, %o0
|
||||
|
||||
cmp %o0, 6
|
||||
be,a L1
|
||||
mov %i5, %o0
|
||||
|
||||
/* o0 > 6: only 6 buses supported */
|
||||
mov %g0, %o0
|
||||
L1:
|
||||
retl
|
||||
nop
|
||||
|
||||
/* Function adds a AHB Bridge I/O AREA to the i0-i5 registers if
|
||||
* not already added. It stores the bus PnP start information.
|
||||
*
|
||||
* Arguments
|
||||
* - o0 = AHB Bridge I/O area
|
||||
*
|
||||
* Results
|
||||
* none
|
||||
*
|
||||
* Clobbered
|
||||
* o2, o3
|
||||
*/
|
||||
insert_ahb_bridge:
|
||||
/* Check that bridge hasn't already been added */
|
||||
andn %o0, 0x7ff, %o2
|
||||
andn %i0, 0x7ff, %o3
|
||||
cmp %o3, %o2
|
||||
be L2
|
||||
andn %i1, 0x7ff, %o3
|
||||
cmp %o3, %o2
|
||||
be L2
|
||||
andn %i2, 0x7ff, %o3
|
||||
cmp %o3, %o2
|
||||
be L2
|
||||
andn %i3, 0x7ff, %o3
|
||||
cmp %o3, %o2
|
||||
be L2
|
||||
andn %i4, 0x7ff, %o3
|
||||
cmp %o3, %o2
|
||||
be L2
|
||||
andn %i5, 0x7ff, %o3
|
||||
cmp %o3, %o2
|
||||
be L2
|
||||
|
||||
/* Insert into first free posistion */
|
||||
cmp %i0, %g0
|
||||
be,a L2
|
||||
mov %o0, %i0
|
||||
|
||||
cmp %i1, %g0
|
||||
be,a L2
|
||||
mov %o0, %i1
|
||||
|
||||
cmp %i2, %g0
|
||||
be,a L2
|
||||
mov %o0, %i2
|
||||
|
||||
cmp %i3, %g0
|
||||
be,a L2
|
||||
mov %o0, %i3
|
||||
|
||||
cmp %i4, %g0
|
||||
be,a L2
|
||||
mov %o0, %i4
|
||||
|
||||
cmp %i5, %g0
|
||||
be,a L2
|
||||
mov %o0, %i5
|
||||
L2:
|
||||
retl
|
||||
nop
|
||||
|
||||
/* FUNCTION int _nomem_find_ahb_bus(
|
||||
* unsigned int bridge,
|
||||
* int vendor_device,
|
||||
* int index,
|
||||
* void **pconf,
|
||||
* int not_used,
|
||||
* int option
|
||||
* )
|
||||
*
|
||||
* Scans the AHB Master or Slave area for a matching VENDOR:DEVICE, the
|
||||
* index is decremented when a matching device is found but index is
|
||||
* greater than zero. When index is zero and a matching DEVICE:VENDOR
|
||||
* is found the AHB configuration address and AHB I/O area is returned.
|
||||
*
|
||||
* i0-i7,l0,l1,l2,l3,l4,g2,o6 is not available for use.
|
||||
* o1,o5 Must be left untouched
|
||||
*
|
||||
* Results
|
||||
* - o0 Number of found devices (1 or 0)
|
||||
* - o2 is decremented for each matching VENDOR:DEVICE found, zero if found
|
||||
* - o3 Address of the AHB PnP configuration entry (Only valid if o0=1)
|
||||
*
|
||||
* Clobbered
|
||||
* - o3 (Clobbered when no device was found)
|
||||
* - o4 (Number of Devices left to search)
|
||||
* - o0 (Bus ID, PnP ID, Device)
|
||||
*/
|
||||
_nomem_find_ahb_bus:
|
||||
|
||||
/* Get the number of Slaves/Masters.
|
||||
* Only AHB Bus 0 has 64 AHB Masters/Slaves the
|
||||
* other AHB buses has 16 slaves and 16 masters.
|
||||
*/
|
||||
add %g0, 16, %o4 /* Defaulting to 16 */
|
||||
andcc %o0, 0x7, %g0 /* 3-bit bus id */
|
||||
be,a .L_maxloops_detected
|
||||
add %g0, 64, %o4 /* AHB Bus 0 has 64 AHB Masters/Slaves */
|
||||
.L_maxloops_detected:
|
||||
|
||||
/* Get start address of AHB Slave or AHB Master area depending on what
|
||||
* we are searching for.
|
||||
*/
|
||||
andn %o0, 0x7ff, %o0 /* Remove Bus ID and 5-bit AHB/AHB
|
||||
* Bridge PnP Address to get I/O Area */
|
||||
set AMBA_CONF_AREA, %o3
|
||||
or %o3, %o0, %o3 /* Master area address */
|
||||
|
||||
cmp %o5, DEV_AHB_SLV
|
||||
be,a .L_conf_area_calculated
|
||||
or %o3, AMBA_AHB_SLAVE_CONF_AREA, %o3 /* Add 0x800 to get to slave area */
|
||||
.L_conf_area_calculated:
|
||||
|
||||
/* Iterate over all AHB device and try to find matching DEVICE:VENDOR
|
||||
* o1 - VENDOR|DEVICE
|
||||
* o2 - Index
|
||||
* o3 - Current AHB Device Configuration address
|
||||
* o5 - Type (leave untouched)
|
||||
*
|
||||
* o4 - Number of AHB device left to process
|
||||
* o0 - tmp
|
||||
*/
|
||||
.L_process_one_conf:
|
||||
ld [%o3], %o0
|
||||
andn %o0, 0xfff, %o0
|
||||
cmp %o0, 0 /* No device if zero */
|
||||
beq .L_next_conf
|
||||
cmp %o1, 0 /* If VENDOR:DEVICE==0, consider all matching */
|
||||
beq .L_process_ahb_dev_found
|
||||
cmp %o0, %o1 /* Does VENDOR and DEVICE Match? */
|
||||
bne .L_next_conf
|
||||
nop
|
||||
.L_process_ahb_dev_found:
|
||||
/* Found a Matching VENDOR:DEVICE, index must also match */
|
||||
cmp %o2, %g0
|
||||
bne .L_next_conf
|
||||
dec %o2
|
||||
/* Index matches also, return happy with o3 set to AHB Conf Address */
|
||||
mov %g0, %o2
|
||||
retl
|
||||
add %g0, 1, %o0
|
||||
|
||||
.L_next_conf:
|
||||
subcc %o4, 1, %o4 /* One device has been processed,
|
||||
* Are there more devices to process? */
|
||||
bne .L_process_one_conf
|
||||
add %o3, AMBA_AHB_CONF_LENGH, %o3 /* Next Configuration entry */
|
||||
/* No Matching device found */
|
||||
retl
|
||||
mov %g0, %o0
|
||||
|
||||
/* FUNCTION int _nomem_find_ahb(
|
||||
* int unused,
|
||||
* int vendor_device,
|
||||
* int index,
|
||||
* void **pconf,
|
||||
* int *ahb_bus_index,
|
||||
* int option,
|
||||
* )
|
||||
*
|
||||
* Find a AHB Master or AHB Slave device, it puts the address of the AHB PnP
|
||||
* configuration in o3 (pconf), the I/O Area base address in o4 (pioarea).
|
||||
*
|
||||
* Calls _nomem_find_ahb_bus for every AHB bus.
|
||||
*
|
||||
* i0-i7, l0, l1, o6, g1, g4-g7 is not available for use.
|
||||
*
|
||||
* Arguments
|
||||
* - o0 Unused
|
||||
*
|
||||
* Results
|
||||
* - o0 Number of found devices (1 or 0)
|
||||
* - o2 Decremented Index (Zero if found)
|
||||
* - o3 Address of the AHB PnP configuration entry
|
||||
* - o4 AHB Bus index the device was found on (if o0=1)
|
||||
* - o5 Left untouched
|
||||
*
|
||||
* Clobbered
|
||||
* - o0 (AHB Bridge and used by _nomem_find_ahb_bus)
|
||||
* - o2 (index is decremented)
|
||||
* - l2 (Current AHB Bus index)
|
||||
* - g2 (return address)
|
||||
*/
|
||||
_nomem_find_ahb:
|
||||
mov %o7, %g2 /* Save return address */
|
||||
/* Scan all AHB Buses found for the AHB Master/Slave matching VENDOR:DEVICE */
|
||||
clr %l2
|
||||
.L_search_next_ahb_bus:
|
||||
add %l2, 1, %l2
|
||||
call get_ahb_bridge /* Get bus %l0 I/O Area */
|
||||
mov %l2, %o0
|
||||
cmp %o0, %g0
|
||||
be .L_no_device_found /* If no more AHB bus is left to be scanned, proceed */
|
||||
nop
|
||||
call _nomem_find_ahb_bus /* Scan AHB bus %o0 for VENDOR:DEVICE. Index in o3 is decremented */
|
||||
nop
|
||||
cmp %o0, %g0 /* If VENDOR:DEVICE was not found scan next AHB Bus */
|
||||
be .L_search_next_ahb_bus /* Do next bus is o0=0 (not found) */
|
||||
nop
|
||||
/* The device was found, o0 is 1 */
|
||||
mov %g2, %o7 /* Restore return address */
|
||||
retl
|
||||
mov %l2, %o4 /* The AHB bus index the device was found on */
|
||||
|
||||
/* No device found matching */
|
||||
.L_no_device_found:
|
||||
mov %g2, %o7 /* Restore return address */
|
||||
retl
|
||||
mov %g0, %o0
|
||||
|
||||
|
||||
/* FUNCTION int _nomem_find_apb_bus(
|
||||
* int apbmst,
|
||||
* int vendor_device,
|
||||
* int index,
|
||||
* void **pconf
|
||||
* )
|
||||
*
|
||||
* Find a APB Slave device, it puts the address of the APB PnP configuration
|
||||
* in o3 (pconf).
|
||||
*
|
||||
* Calls _nomem_find_ahb_bus for every AHB bus searching for AHB/APB Bridges.
|
||||
* The AHB/APB bridges are AHB Slaves with ID GAISLER_APBMST.
|
||||
*
|
||||
* Results
|
||||
* - o0 Number of found devices (1 or 0)
|
||||
* - o2 Decremented Index
|
||||
* - o3 Address of the found APB device PnP configuration entry
|
||||
*
|
||||
* Clobbered
|
||||
* - o5 PnP VENDOR:DEVICE ID
|
||||
*/
|
||||
|
||||
_nomem_find_apb_bus:
|
||||
set AMBA_CONF_AREA, %o3
|
||||
or %o0, %o3, %o3 /* Calc start of APB device PnP info */
|
||||
add %g0, 16, %o0 /* o0, number of APB Slaves left to scan */
|
||||
.L_process_one_apb_conf:
|
||||
ld [%o3], %o5
|
||||
andn %o5, 0xfff, %o5
|
||||
cmp %o5, 0 /* No device if zero */
|
||||
beq .L_process_apb_dev_not_found
|
||||
cmp %o1, 0 /* If VENDOR:DEVICE == -1, consider all matching */
|
||||
beq .L_process_apb_dev_found
|
||||
cmp %o1, %o5 /* Found VENDOR:DEVICE */
|
||||
bne .L_process_apb_dev_not_found
|
||||
nop
|
||||
|
||||
.L_process_apb_dev_found:
|
||||
/* Found matching device, compare index */
|
||||
cmp %o2, %g0
|
||||
bne .L_process_apb_dev_not_found
|
||||
dec %o2
|
||||
/* Matching index and VENDOR:DEVICE */
|
||||
retl
|
||||
add %g0, 1, %o0
|
||||
|
||||
.L_process_apb_dev_not_found:
|
||||
subcc %o0, 1, %o0
|
||||
bne .L_process_one_apb_conf
|
||||
add %o3, 8, %o3
|
||||
retl
|
||||
mov %g0, %o0
|
||||
|
||||
/* FUNCTION int _nomem_find_apb(
|
||||
* int unused,
|
||||
* int vendor_device,
|
||||
* int index,
|
||||
* void **pconf,
|
||||
* int *ahb_bus_index
|
||||
* )
|
||||
*
|
||||
* Find a APB Slave device, it puts the address of the APB PnP configuration
|
||||
* in o3 (pconf), the APB Master I/O Area base address in o4 (papbarea).
|
||||
*
|
||||
* Calls _nomem_find_ahb_bus for every AHB bus searching for AHB/APB Bridges.
|
||||
* The AHB/APB bridges are AHB Slaves with ID GAISLER_APBMST.
|
||||
*
|
||||
* i0-i7, l0, l1, o6 is not available for use.
|
||||
*
|
||||
* Arguments
|
||||
* - o0 Unused
|
||||
*
|
||||
* Results
|
||||
* - o0 Number of found devices (1 or 0)
|
||||
* - o2 Decremented Index if not found
|
||||
* - o3 Address of the APB PnP configuration entry
|
||||
* - o4 AHB Bus index of APB Bridge/APB Device
|
||||
*
|
||||
* Clobbered
|
||||
* - o0 (AHB Bridge)
|
||||
* - o2 (index is decremented)
|
||||
* - l2 (APB DEV Index [7..4] : APBMST AHB Index [3..0])
|
||||
* - l3 (Current AHB Bus index)
|
||||
* - l4 (temporary storage for APB VENDOR:DEVICE)
|
||||
* - o5 (AHB Slave ID)
|
||||
* - o0 (clobbered by _nomem_find_ahb_bus)
|
||||
* - g2 (Return address)
|
||||
*/
|
||||
_nomem_find_apb:
|
||||
/* Scan all AHB Buses found for AHB/APB Bridges */
|
||||
mov %o7, %g2 /* Save return address */
|
||||
mov %o1, %l4 /* Save APB VENDOR:DEVICE */
|
||||
sll %o2, 4, %l2 /* APB MST index = 0 */
|
||||
add %g0, 1, %l3 /* AHB Bus index = 0 */
|
||||
.L2_search_next_ahb_bus:
|
||||
call get_ahb_bridge /* Get bus %l3 I/O Area */
|
||||
mov %l3, %o0
|
||||
cmp %o0, %g0
|
||||
be .L2_no_device_found /* If no more AHB bus is left to be scanned, proceed */
|
||||
add %g0, DEV_AHB_SLV, %o5 /* Search for AHB Slave */
|
||||
sethi %hi(AMBA_PNP_ID(VENDOR_GAISLER, GAISLER_APBMST)), %o1
|
||||
call _nomem_find_ahb_bus /* Scan AHB bus %o0 for VENDOR:DEVICE. Index in o3 is decremented */
|
||||
and %l2, 0xf, %o2 /* Set APBMST index */
|
||||
cmp %o0, %g0 /* If no AHB/APB Bridge was not found, scan next AHB Bus */
|
||||
be .L_no_apb_bridge_found /* Do next bus */
|
||||
nop
|
||||
|
||||
/* The AHB/APB Bridge was found.
|
||||
* Search for the requested APB Device on the APB bus using
|
||||
* find_apb_bus, it will decrement the index.
|
||||
*/
|
||||
ld [%o3 + AMBA_AHB_MBAR0_OFS], %o3
|
||||
sll %o3, 16, %o0
|
||||
and %o0, %o3, %o0 /* Address AND Address Mask */
|
||||
sethi %hi(0xfff00000), %o3
|
||||
and %o0, %o3, %o0 /* AHB/APB Bridge address */
|
||||
|
||||
srl %l2, 4, %o2 /* APB DEV Index */
|
||||
call _nomem_find_apb_bus
|
||||
mov %l4, %o1 /* APB VENDOR:DEVICE */
|
||||
cmp %o0, %g0
|
||||
be .L_apb_dev_not_found
|
||||
mov %g2, %o7 /* Restore return address */
|
||||
/* APB Device found
|
||||
* o0 1
|
||||
* o2 Index is decremented to zero
|
||||
* o3 APB configuration address,
|
||||
* o4 APB Bridge Configuration address.
|
||||
*/
|
||||
mov %g0, %o2
|
||||
retl
|
||||
mov %l3, %o4
|
||||
|
||||
.L_apb_dev_not_found:
|
||||
/* Update APB DEV Index by saving output from find_apb_bus
|
||||
* (index parameter) into bits [31..4] in L2.
|
||||
*/
|
||||
sll %o2, 4, %o2
|
||||
and %l2, 0xf, %l2
|
||||
or %o2, %l2, %l2
|
||||
/* Try finding the next AHB/APB Bridge on the same AHB bus
|
||||
* to find more APB devices
|
||||
*/
|
||||
ba .L2_search_next_ahb_bus /* Find next AHB/APB bridge */
|
||||
inc %l2
|
||||
|
||||
.L_no_apb_bridge_found:
|
||||
inc %l3 /* Next AHB Bus */
|
||||
ba .L2_search_next_ahb_bus /* Process next AHB bus */
|
||||
andn %l2, 0xf, %l2 /* Start at APB Bridge index 0 at every AHB Bus */
|
||||
/* No device found matching */
|
||||
.L2_no_device_found:
|
||||
mov %g2, %o7 /* Restore return address */
|
||||
srl %l2, 4, %o2 /* APB DEV Index */
|
||||
retl
|
||||
mov %g0, %o0
|
||||
|
||||
|
||||
|
||||
/* FUNCTION _nomem_amba_scan_gaisler_ahb2ahb_bridge(unsigned int bridge, int bus)
|
||||
*
|
||||
* Constraints:
|
||||
* - o1 may not be used
|
||||
* - o0, o2, o3 may be used.
|
||||
*
|
||||
* Arguments
|
||||
* - o0 PnP Address of Bridge AHB device
|
||||
* - o2 PnP ID of AHB device
|
||||
*
|
||||
* Results
|
||||
* - o0 Address of new bus PnP area or a 1 if AHB device is no bridge
|
||||
*
|
||||
* Clobbered
|
||||
* - o0, o2
|
||||
*
|
||||
*/
|
||||
_nomem_amba_scan_gaisler_ahb2ahb_bridge:
|
||||
andn %o2, 0xfff, %o2
|
||||
sethi %hi(AMBA_PNP_ID(VENDOR_GAISLER,GAISLER_AHB2AHB)), %o3
|
||||
cmp %o2, %o3
|
||||
beq .L_is_ahb2ahb_bridge
|
||||
nop
|
||||
|
||||
retl
|
||||
add %g0, 1, %o0
|
||||
|
||||
.L_is_ahb2ahb_bridge:
|
||||
/* Found a GAISLER AHB2AHB bridge */
|
||||
retl
|
||||
ld [%o0 + AMBA_AHB_CUSTOM1_OFS], %o0 /* Get address of bridge PnP area */
|
||||
|
||||
|
||||
/* FUNCTION _nomem_amba_scan_gaisler_l2cache_bridge(unsigned int bridge, int bus)
|
||||
*
|
||||
* Constraints:
|
||||
* - o1 may not be used
|
||||
* - o0, o2, o3 may be used.
|
||||
*
|
||||
* Arguments
|
||||
* - o0 PnP Address of Bridge AHB device
|
||||
* - o2 PnP ID of AHB device
|
||||
*
|
||||
* Results
|
||||
* - o0 Address of new bus PnP area or a 1 if AHB device is no bridge
|
||||
*
|
||||
* Clobbered
|
||||
* - o0, o2
|
||||
*
|
||||
*/
|
||||
_nomem_amba_scan_gaisler_l2cache_bridge:
|
||||
andn %o2, 0xfff, %o2
|
||||
sethi %hi(AMBA_PNP_ID(VENDOR_GAISLER,GAISLER_L2CACHE)), %o3
|
||||
cmp %o2, %o3
|
||||
beq .L_is_l2cache_bridge
|
||||
nop
|
||||
|
||||
retl
|
||||
add %g0, 1, %o0
|
||||
|
||||
.L_is_l2cache_bridge:
|
||||
/* Found a GAISLER l2cache bridge */
|
||||
retl
|
||||
ld [%o0 + AMBA_AHB_CUSTOM1_OFS], %o0 /* Get address of bridge PnP area */
|
||||
|
||||
|
||||
/* FUNCTION _nomem_amba_scan(unsigned int bridge, int bus)
|
||||
*
|
||||
* Constraints:
|
||||
* i0-i7, l0 is used by caller
|
||||
* o5-o7 may not be used.
|
||||
*
|
||||
* Arguments
|
||||
* - o0 Bridge Information: I/O AREA and parent bus
|
||||
* - o1 Bus
|
||||
*
|
||||
* Results
|
||||
* - o0 Number of AHB bridges found
|
||||
*
|
||||
* Clobbered
|
||||
* - o0 (Current AHB slave conf address)
|
||||
* - o2 (Used by insert_bridge)
|
||||
* - o3 (Used by insert_bridge)
|
||||
* - l1 (Number of AHB Slaves left to process)
|
||||
* - l2 (Current AHB slave conf address)
|
||||
* - g2 (Return address)
|
||||
*/
|
||||
_nomem_amba_scan:
|
||||
mov %o7, %g2 /* Save return address */
|
||||
set 16, %l1
|
||||
cmp %o1, 1
|
||||
be,a .L2_maxloops_detected
|
||||
add %g0, 64, %l1
|
||||
.L2_maxloops_detected:
|
||||
|
||||
/* Clear 3-bit parent bus from bridge to get I/O AREA, then or
|
||||
* (AMBA_CONF_AREA | AMBA_AHB_SLAVE_CONF_AREA) to get first AHB slave
|
||||
* conf address.
|
||||
*/
|
||||
andn %o0, 0x7ff, %o0
|
||||
set (AMBA_CONF_AREA | AMBA_AHB_SLAVE_CONF_AREA), %l2
|
||||
or %o0, %l2, %l2
|
||||
|
||||
/* Scan AHB Slave area for AHB<->AHB bridges. For each AHB device
|
||||
* all "bridge drivers" are called, the driver function interface:
|
||||
*
|
||||
* Input:
|
||||
* - o0 PnP Address of Bridge AHB device
|
||||
* - o2 PnP ID of AHB device
|
||||
* Return values:
|
||||
* - o0 Address of new bus PnP area, returning a 1 in o2 means not found
|
||||
*
|
||||
* Constraints:
|
||||
* - o1 may not be used
|
||||
* - o0, o2, o3 may be used.
|
||||
*
|
||||
*/
|
||||
.L_scan_one_ahb_slave:
|
||||
ld [%l2], %o2
|
||||
|
||||
cmp %o2, %g0
|
||||
beq .L_scan_next_ahb_slave
|
||||
nop
|
||||
|
||||
/* Call the GAISLER AHB2AHB bridge driver */
|
||||
call _nomem_amba_scan_gaisler_ahb2ahb_bridge
|
||||
mov %l2, %o0
|
||||
cmp %o0, 1
|
||||
bne .L_found_bridge
|
||||
ld [%l2], %o2
|
||||
|
||||
/* Call the GAISLER L2CACHE bridge driver */
|
||||
call _nomem_amba_scan_gaisler_l2cache_bridge
|
||||
mov %l2, %o0
|
||||
cmp %o0, 1
|
||||
bne .L_found_bridge
|
||||
ld [%l2], %o2
|
||||
|
||||
/* Insert next bridge "driver" function here */
|
||||
|
||||
|
||||
/* The PnP ID did not match a bridge - a new bus was not found ==>
|
||||
* step to next AHB device */
|
||||
ba .L_scan_next_ahb_slave
|
||||
nop
|
||||
|
||||
/* Add Found bus */
|
||||
.L_found_bridge:
|
||||
and %l2, 0x7e0, %o2
|
||||
or %o2, %o0, %o0 /* Add AHB/AHB Bridge PnP address */
|
||||
call insert_ahb_bridge /* Insert Bridge into found buses storage */
|
||||
or %o1, %o0, %o0 /* Add parent bus LSB 3-bits */
|
||||
|
||||
.L_scan_next_ahb_slave:
|
||||
/* More Slaves to process? */
|
||||
subcc %l1, 1, %l1
|
||||
bne .L_scan_one_ahb_slave
|
||||
add %l2, AMBA_AHB_CONF_LENGH, %l2
|
||||
|
||||
/* No more AHB devices to process */
|
||||
mov %g2, %o7 /* Restore return address */
|
||||
retl
|
||||
nop
|
||||
|
||||
/* FUNCTION _nomem_ambapp_find_buses(unsigned int ioarea)
|
||||
*
|
||||
* Find AMBA AHB buses.
|
||||
*
|
||||
* Constraints:
|
||||
* i6-i7, l7 is used by caller
|
||||
*
|
||||
* Arguments
|
||||
* - o0 Bridge Information: I/O AREA and parent bus
|
||||
*
|
||||
* Results
|
||||
* - o0 Number of AHB bridges found
|
||||
* - i0-i5 initialized
|
||||
*
|
||||
* Clobbered
|
||||
* - o0 (Current AHB slave conf address)
|
||||
* - o2 (Used by insert_bridge)
|
||||
* - o3 (Used by insert_bridge)
|
||||
* - l0 (Current AHB Bus)
|
||||
* - l1 (Used by nomem_amba_scan)
|
||||
* - l2 (Used by nomem_amba_scan)
|
||||
* - l3 (Used by nomem_amba_scan)
|
||||
* - l4 (Used by nomem_amba_scan)
|
||||
*
|
||||
* - g1 (level 1 return address)
|
||||
* - g2 (Used by nomem_amba_scan)
|
||||
*/
|
||||
_nomem_ambapp_find_buses:
|
||||
mov %o7, %g1 /* Save return address */
|
||||
|
||||
/* Initialize AHB Bus storage */
|
||||
call init_ahb_bridges
|
||||
nop
|
||||
|
||||
/* Insert AHB Bus 0 */
|
||||
call insert_ahb_bridge
|
||||
nop /* Argument already prepared by caller */
|
||||
|
||||
/* Scan AHB Bus 0 for AHB Bridges */
|
||||
call _nomem_amba_scan
|
||||
add %g0, 1, %o1
|
||||
|
||||
/* Scan all AHB Buses found for more AHB Bridges */
|
||||
add %g0, 2, %l0
|
||||
.L100_search_next_ahb_bus:
|
||||
call get_ahb_bridge /* Get bus %l0 I/O Area */
|
||||
mov %l0, %o0
|
||||
cmp %o0, %g0
|
||||
be .L100_return /* If no more AHB bus is left to be scanned, proceed */
|
||||
nop
|
||||
call _nomem_amba_scan /* Scan bus %l0 for AHB Bridges. i0-i7,l0 is used */
|
||||
mov %l0, %o1 /* I/O AREA untouched in o0 */
|
||||
ba .L100_search_next_ahb_bus /* Do next bus */
|
||||
add %l0, 1, %l0
|
||||
|
||||
.L100_return:
|
||||
mov %g1, %o7
|
||||
retl
|
||||
nop
|
||||
|
||||
|
||||
/* FUNCTION _nomem_amba_init(unsigned int ioarea)
|
||||
*
|
||||
* Find all AHB buses
|
||||
*
|
||||
* Constraints:
|
||||
* i6, i7, o6, o7, l7, l6, g3, g4, g5, g6, g7 is used by caller
|
||||
*
|
||||
* Arguments
|
||||
* - o0 Bridge Information: I/O AREA and parent bus
|
||||
*
|
||||
* Results
|
||||
* - o0 Number of AHB bridges found
|
||||
*
|
||||
* Clobbered
|
||||
* - l0, l1, l2, l3, l4, g1, g2 (used by _nomem_ambapp_find_buses)
|
||||
* - o0, o1, o2, o3 (Used as arguments)
|
||||
* - o5 (return address)
|
||||
* - g1 (level 1 return address)
|
||||
* - g2 (level 2 return address)
|
||||
*/
|
||||
_nomem_amba_init:
|
||||
mov %o7, %o5 /* Save return address, o5 not used */
|
||||
|
||||
/* Scan for buses, it will init i0-i5 */
|
||||
call _nomem_ambapp_find_buses
|
||||
nop
|
||||
|
||||
mov %o5, %o7
|
||||
retl
|
||||
nop
|
||||
|
||||
/* Call tree and their return address register
|
||||
*
|
||||
*_nomem_amba_scan (g1)
|
||||
* -> init_ahb_bridges (o7)
|
||||
* -> insert_ahb_bridge (o7)
|
||||
* -> _nomem_amba_scan (g2)
|
||||
* -> insert_ahb_bridge (o7)
|
||||
* -> get_ahb_bridge (o7)
|
||||
*
|
||||
*
|
||||
* -> _nomem_find_apb (g2)
|
||||
* -> get_ahb_bridge (o7)
|
||||
* -> _nomem_find_ahb_bus (o7)
|
||||
* -> _nomem_find_apb_bus (o7)
|
||||
* -> _nomem_find_ahb (g2)
|
||||
* -> get_ahb_bridge (o7)
|
||||
* -> _nomem_find_ahb_bus (o7)
|
||||
* -> mem_handler.func() (o7)
|
||||
*
|
||||
*/
|
||||
113
u-boot/arch/sparc/cpu/leon3/ambapp_low_c.S
Normal file
113
u-boot/arch/sparc/cpu/leon3/ambapp_low_c.S
Normal file
@@ -0,0 +1,113 @@
|
||||
/* C-interface for AMBA PnP scanning functions implemented in
|
||||
* ambapp_low.S. At the point the memory and stack can be
|
||||
* used.
|
||||
*
|
||||
* (C) Copyright 2010, 2015
|
||||
* Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
|
||||
.seg "text"
|
||||
.extern _nomem_ambapp_find_buses
|
||||
.extern _nomem_find_apb
|
||||
.extern _nomem_find_ahb
|
||||
|
||||
.globl ambapp_find_buses
|
||||
.globl ambapp_find_apb
|
||||
.globl ambapp_find_ahb
|
||||
|
||||
|
||||
/* C-interface for _nomem_ambapp_find_buses used when memory is available.
|
||||
*/
|
||||
ambapp_find_buses:
|
||||
save %sp, -104, %sp
|
||||
mov %i1, %l7 /* Save second argument */
|
||||
call _nomem_ambapp_find_buses
|
||||
mov %i0, %o0
|
||||
|
||||
/* Store result */
|
||||
st %g0, [%l7+0x00]
|
||||
st %i0, [%l7+0x04]
|
||||
st %i1, [%l7+0x08]
|
||||
st %i2, [%l7+0x0c]
|
||||
st %i3, [%l7+0x10]
|
||||
st %i4, [%l7+0x14]
|
||||
st %i5, [%l7+0x18]
|
||||
|
||||
ret
|
||||
restore
|
||||
|
||||
/* C-interface for _nomem_find_apb used when memory is available.
|
||||
*
|
||||
* void ambapp_find_apb(
|
||||
* struct ambapp_bus *abus,
|
||||
* unsigned int dev_vend,
|
||||
* int index,
|
||||
* struct ambapp_find_apb_info *result
|
||||
* );
|
||||
*
|
||||
*/
|
||||
ambapp_find_apb:
|
||||
save %sp, -104, %sp
|
||||
|
||||
mov %i3, %l7 /* Save second argument */
|
||||
mov %i1, %o1
|
||||
mov %i2, %o2
|
||||
|
||||
/* Initialize buses available in system */
|
||||
ld [%i0+0x08], %i1
|
||||
ld [%i0+0x0c], %i2
|
||||
ld [%i0+0x10], %i3
|
||||
ld [%i0+0x14], %i4
|
||||
ld [%i0+0x18], %i5
|
||||
|
||||
call _nomem_find_apb
|
||||
ld [%i0+0x04], %i0
|
||||
|
||||
st %o2, [%l7+0x08] /* Decremented Index */
|
||||
st %o3, [%l7] /* PnP configuration address of APB Device */
|
||||
st %o4, [%l7+0x04] /* AHB Bus Index of AHB/APB bridge and APB Device */
|
||||
mov %o0, %i0
|
||||
ret
|
||||
restore
|
||||
|
||||
/* C-interface for _nomem_find_ahb used when memory is available.
|
||||
*
|
||||
* void ambapp_find_ahb(
|
||||
* struct ambapp_bus *abus,
|
||||
* unsigned int dev_vend,
|
||||
* int index,
|
||||
* int type,
|
||||
* struct ambapp_find_ahb_info *result
|
||||
* );
|
||||
*
|
||||
*/
|
||||
ambapp_find_ahb:
|
||||
save %sp, -104, %sp
|
||||
|
||||
mov %i4, %l7 /* Save second argument */
|
||||
clr %o0
|
||||
mov %i1, %o1
|
||||
mov %i2, %o2
|
||||
clr %o3
|
||||
clr %o4
|
||||
mov %i3, %o5
|
||||
|
||||
/* Initialize buses available in system */
|
||||
ld [%i0+0x08], %i1
|
||||
ld [%i0+0x0c], %i2
|
||||
ld [%i0+0x10], %i3
|
||||
ld [%i0+0x14], %i4
|
||||
ld [%i0+0x18], %i5
|
||||
|
||||
call _nomem_find_ahb
|
||||
ld [%i0+0x04], %i0
|
||||
|
||||
st %o2, [%l7+0x08] /* Decremented Index */
|
||||
st %o3, [%l7] /* PnP configuration address of AHB Device */
|
||||
st %o4, [%l7+0x04] /* AHB Bus Index of AHB Device */
|
||||
mov %o0, %i0
|
||||
ret
|
||||
restore
|
||||
113
u-boot/arch/sparc/cpu/leon3/cpu.c
Normal file
113
u-boot/arch/sparc/cpu/leon3/cpu.c
Normal file
@@ -0,0 +1,113 @@
|
||||
/* CPU specific code for the LEON3 CPU
|
||||
*
|
||||
* (C) Copyright 2007, 2015
|
||||
* Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <watchdog.h>
|
||||
#include <command.h>
|
||||
#include <netdev.h>
|
||||
|
||||
#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 */
|
||||
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)
|
||||
{
|
||||
/* Interrupts off */
|
||||
disable_interrupts();
|
||||
|
||||
/* jump to restart in flash */
|
||||
_reset_reloc();
|
||||
}
|
||||
|
||||
int do_reset(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
cpu_reset();
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
u64 flash_read64(void *addr)
|
||||
{
|
||||
return __raw_readq(addr);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef CONFIG_GRETH
|
||||
int cpu_eth_init(bd_t *bis)
|
||||
{
|
||||
return greth_initialize(bis);
|
||||
}
|
||||
#endif
|
||||
175
u-boot/arch/sparc/cpu/leon3/cpu_init.c
Normal file
175
u-boot/arch/sparc/cpu/leon3/cpu_init.c
Normal file
@@ -0,0 +1,175 @@
|
||||
/* Initializes CPU and basic hardware such as memory
|
||||
* controllers, IRQ controller and system timer 0.
|
||||
*
|
||||
* (C) Copyright 2007, 2015
|
||||
* Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#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>
|
||||
#include <debug_uart.h>
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Default Plug&Play I/O area */
|
||||
#ifndef CONFIG_AMBAPP_IOAREA
|
||||
#define CONFIG_AMBAPP_IOAREA AMBA_DEFAULT_IOAREA
|
||||
#endif
|
||||
|
||||
/* 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;
|
||||
|
||||
ambapp_dev_irqmp *irqmp = NULL;
|
||||
|
||||
/*
|
||||
* Breath some life into the CPU...
|
||||
*
|
||||
* Run from FLASH/PROM:
|
||||
* - until memory controller is set up, only registers available
|
||||
* - memory controller has already been setup up, stack can be used
|
||||
* - no global variables available for writing
|
||||
* - constants available
|
||||
*/
|
||||
void cpu_init_f(void)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_UART
|
||||
debug_uart_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* initialize higher level parts of CPU like time base and timers
|
||||
*/
|
||||
int cpu_init_r(void)
|
||||
{
|
||||
ambapp_apbdev apbdev;
|
||||
int cpu;
|
||||
|
||||
/*
|
||||
* Find AMBA APB IRQMP Controller,
|
||||
*/
|
||||
if (ambapp_apb_find(&ambapp_plb, VENDOR_GAISLER,
|
||||
GAISLER_IRQMP, 0, &apbdev) != 1) {
|
||||
panic("%s: IRQ controller not found\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
irqmp = (ambapp_dev_irqmp *)apbdev.address;
|
||||
|
||||
/* initialize the IRQMP */
|
||||
irqmp->ilevel = 0xf; /* all IRQ off */
|
||||
irqmp->iforce = 0;
|
||||
irqmp->ipend = 0;
|
||||
irqmp->iclear = 0xfffe; /* clear all old pending interrupts */
|
||||
for (cpu = 0; cpu < 16; cpu++) {
|
||||
/* mask and clear force for all IRQs on CPU[N] */
|
||||
irqmp->cpu_mask[cpu] = 0;
|
||||
irqmp->cpu_force[cpu] = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
;
|
||||
int timer_init(void)
|
||||
{
|
||||
ambapp_dev_gptimer_element *tmr;
|
||||
ambapp_dev_gptimer *gptimer;
|
||||
ambapp_apbdev apbdev;
|
||||
unsigned bus_freq;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
gptimer = (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 */
|
||||
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;
|
||||
}
|
||||
193
u-boot/arch/sparc/cpu/leon3/interrupts.c
Normal file
193
u-boot/arch/sparc/cpu/leon3/interrupts.c
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* (C) Copyright 2007
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com
|
||||
*
|
||||
* (C) Copyright 2006
|
||||
* Detlev Zundel, DENX Software Engineering, dzu@denx.de
|
||||
*
|
||||
* (C) Copyright -2003
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2001
|
||||
* Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <asm/stack.h>
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/processor.h>
|
||||
#include <command.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <asm/leon.h>
|
||||
#include <ambapp.h>
|
||||
#include <grlib/irqmp.h>
|
||||
#include <grlib/gptimer.h>
|
||||
|
||||
/* 15 normal irqs and a non maskable interrupt */
|
||||
#define NR_IRQS 15
|
||||
|
||||
struct irq_action {
|
||||
interrupt_handler_t *handler;
|
||||
void *arg;
|
||||
unsigned int count;
|
||||
};
|
||||
|
||||
extern ambapp_dev_irqmp *irqmp;
|
||||
extern ambapp_dev_gptimer *gptimer;
|
||||
|
||||
static struct irq_action irq_handlers[NR_IRQS] = { {0}, };
|
||||
static int spurious_irq_cnt = 0;
|
||||
static int spurious_irq = 0;
|
||||
|
||||
static inline unsigned int irqmp_get_irqmask(unsigned int irq)
|
||||
{
|
||||
if ((irq < 0) || (irq >= NR_IRQS)) {
|
||||
return 0;
|
||||
} else {
|
||||
return (1 << irq);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void leon3_ic_disable(unsigned int irq)
|
||||
{
|
||||
unsigned int mask, pil;
|
||||
if (!irqmp)
|
||||
return;
|
||||
|
||||
pil = intLock();
|
||||
|
||||
/* get mask of interrupt */
|
||||
mask = irqmp_get_irqmask(irq);
|
||||
|
||||
/* set int level */
|
||||
irqmp->cpu_mask[0] = SPARC_NOCACHE_READ(&irqmp->cpu_mask[0]) & (~mask);
|
||||
|
||||
intUnlock(pil);
|
||||
}
|
||||
|
||||
static void leon3_ic_enable(unsigned int irq)
|
||||
{
|
||||
unsigned int mask, pil;
|
||||
if (!irqmp)
|
||||
return;
|
||||
|
||||
pil = intLock();
|
||||
|
||||
/* get mask of interrupt */
|
||||
mask = irqmp_get_irqmask(irq);
|
||||
|
||||
/* set int level */
|
||||
irqmp->cpu_mask[0] = SPARC_NOCACHE_READ(&irqmp->cpu_mask[0]) | mask;
|
||||
|
||||
intUnlock(pil);
|
||||
|
||||
}
|
||||
|
||||
void handler_irq(int irq, struct pt_regs *regs)
|
||||
{
|
||||
if (irq_handlers[irq].handler) {
|
||||
if (((unsigned int)irq_handlers[irq].handler > CONFIG_SYS_RAM_END) ||
|
||||
((unsigned int)irq_handlers[irq].handler < CONFIG_SYS_RAM_BASE)
|
||||
) {
|
||||
printf("handler_irq: bad handler: %x, irq number %d\n",
|
||||
(unsigned int)irq_handlers[irq].handler, irq);
|
||||
return;
|
||||
}
|
||||
irq_handlers[irq].handler(irq_handlers[irq].arg);
|
||||
irq_handlers[irq].count++;
|
||||
} else {
|
||||
spurious_irq_cnt++;
|
||||
spurious_irq = irq;
|
||||
}
|
||||
}
|
||||
|
||||
void leon3_force_int(int irq)
|
||||
{
|
||||
if (!irqmp || (irq >= NR_IRQS) || (irq < 0))
|
||||
return;
|
||||
printf("Forcing interrupt %d\n", irq);
|
||||
|
||||
irqmp->iforce = SPARC_NOCACHE_READ(&irqmp->iforce) | (1 << irq);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
int interrupt_init_cpu(void)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* Install and free a interrupt handler.
|
||||
*/
|
||||
|
||||
void irq_install_handler(int irq, interrupt_handler_t * handler, void *arg)
|
||||
{
|
||||
if (irq < 0 || irq >= NR_IRQS) {
|
||||
printf("irq_install_handler: bad irq number %d\n", irq);
|
||||
return;
|
||||
}
|
||||
|
||||
if (irq_handlers[irq].handler != NULL)
|
||||
printf("irq_install_handler: 0x%08lx replacing 0x%08lx\n",
|
||||
(ulong) handler, (ulong) irq_handlers[irq].handler);
|
||||
|
||||
if (((unsigned int)handler > CONFIG_SYS_RAM_END) ||
|
||||
((unsigned int)handler < CONFIG_SYS_RAM_BASE)
|
||||
) {
|
||||
printf("irq_install_handler: bad handler: %x, irq number %d\n",
|
||||
(unsigned int)handler, irq);
|
||||
return;
|
||||
}
|
||||
irq_handlers[irq].handler = handler;
|
||||
irq_handlers[irq].arg = arg;
|
||||
|
||||
/* enable irq on IRQMP hardware */
|
||||
leon3_ic_enable(irq);
|
||||
|
||||
}
|
||||
|
||||
void irq_free_handler(int irq)
|
||||
{
|
||||
if (irq < 0 || irq >= NR_IRQS) {
|
||||
printf("irq_free_handler: bad irq number %d\n", irq);
|
||||
return;
|
||||
}
|
||||
|
||||
/* disable irq on IRQMP hardware */
|
||||
leon3_ic_disable(irq);
|
||||
|
||||
irq_handlers[irq].handler = NULL;
|
||||
irq_handlers[irq].arg = NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_CMD_IRQ)
|
||||
void do_irqinfo(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char * const argv[])
|
||||
{
|
||||
int irq;
|
||||
unsigned int pil = get_pil();
|
||||
printf("PIL level: %u\n\r", pil);
|
||||
printf("Spurious IRQ: %u, last unknown IRQ: %d\n",
|
||||
spurious_irq_cnt, spurious_irq);
|
||||
|
||||
puts("\nInterrupt-Information:\n" "Nr Routine Arg Count\n");
|
||||
|
||||
for (irq = 0; irq < NR_IRQS; irq++) {
|
||||
if (irq_handlers[irq].handler != NULL) {
|
||||
printf("%02d %p %p %d\n", irq,
|
||||
irq_handlers[irq].handler,
|
||||
irq_handlers[irq].arg,
|
||||
irq_handlers[irq].count);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
237
u-boot/arch/sparc/cpu/leon3/memcfg.c
Normal file
237
u-boot/arch/sparc/cpu/leon3/memcfg.c
Normal file
@@ -0,0 +1,237 @@
|
||||
/* GRLIB Memory controller setup. The register values are used
|
||||
* from the associated low level assembler routine implemented
|
||||
* in memcfg_low.S.
|
||||
*
|
||||
* (C) Copyright 2010, 2015
|
||||
* Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <ambapp.h>
|
||||
#include "memcfg.h"
|
||||
#include <config.h>
|
||||
|
||||
#ifdef CONFIG_SYS_GRLIB_ESA_MCTRL1
|
||||
struct mctrl_setup esa_mctrl1_cfg = {
|
||||
.reg_mask = 0x7,
|
||||
.regs = {
|
||||
{
|
||||
.mask = 0x00000300,
|
||||
.value = CONFIG_SYS_GRLIB_ESA_MCTRL1_CFG1,
|
||||
},
|
||||
{
|
||||
.mask = 0x00000000,
|
||||
.value = CONFIG_SYS_GRLIB_ESA_MCTRL1_CFG2,
|
||||
},
|
||||
{
|
||||
.mask = 0x00000000,
|
||||
.value = CONFIG_SYS_GRLIB_ESA_MCTRL1_CFG3,
|
||||
},
|
||||
}
|
||||
};
|
||||
#ifdef CONFIG_SYS_GRLIB_ESA_MCTRL2
|
||||
struct mctrl_setup esa_mctrl2_cfg = {
|
||||
.reg_mask = 0x7,
|
||||
.regs = {
|
||||
{
|
||||
.mask = 0x00000300,
|
||||
.value = CONFIG_SYS_GRLIB_ESA_MCTRL2_CFG1,
|
||||
},
|
||||
{
|
||||
.mask = 0x00000000,
|
||||
.value = CONFIG_SYS_GRLIB_ESA_MCTRL2_CFG2,
|
||||
},
|
||||
{
|
||||
.mask = 0x00000000,
|
||||
.value = CONFIG_SYS_GRLIB_ESA_MCTRL2_CFG3,
|
||||
},
|
||||
}
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1
|
||||
struct mctrl_setup gaisler_ftmctrl1_cfg = {
|
||||
.reg_mask = 0x7,
|
||||
.regs = {
|
||||
{
|
||||
.mask = 0x00000300,
|
||||
.value = CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1_CFG1,
|
||||
},
|
||||
{
|
||||
.mask = 0x00000000,
|
||||
.value = CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1_CFG2,
|
||||
},
|
||||
{
|
||||
.mask = 0x00000000,
|
||||
.value = CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1_CFG3,
|
||||
},
|
||||
}
|
||||
};
|
||||
#ifdef CONFIG_SYS_GRLIB_GAISLER_FTMCTRL2
|
||||
struct mctrl_setup gaisler_ftmctrl2_cfg = {
|
||||
.reg_mask = 0x7,
|
||||
.regs = {
|
||||
{
|
||||
.mask = 0x00000300,
|
||||
.value = CONFIG_SYS_GRLIB_GAISLER_FTMCTRL2_CFG1,
|
||||
},
|
||||
{
|
||||
.mask = 0x00000000,
|
||||
.value = CONFIG_SYS_GRLIB_GAISLER_FTMCTRL2_CFG2,
|
||||
},
|
||||
{
|
||||
.mask = 0x00000000,
|
||||
.value = CONFIG_SYS_GRLIB_GAISLER_FTMCTRL2_CFG3,
|
||||
},
|
||||
}
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_GRLIB_GAISLER_SDCTRL1
|
||||
struct mctrl_setup gaisler_sdctrl1_cfg = {
|
||||
.reg_mask = 0x1,
|
||||
.regs = {
|
||||
{
|
||||
.mask = 0x00000000,
|
||||
.value = CONFIG_SYS_GRLIB_GAISLER_SDCTRL1_CTRL,
|
||||
},
|
||||
}
|
||||
};
|
||||
#ifdef CONFIG_SYS_GRLIB_GAISLER_SDCTRL2
|
||||
struct mctrl_setup gaisler_sdctrl2_cfg = {
|
||||
.reg_mask = 0x1,
|
||||
.regs = {
|
||||
{
|
||||
.mask = 0x00000000,
|
||||
.value = CONFIG_SYS_GRLIB_GAISLER_SDCTRL2_CTRL,
|
||||
},
|
||||
}
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_GRLIB_GAISLER_DDR2SPA1
|
||||
struct ahbmctrl_setup gaisler_ddr2spa1_cfg = {
|
||||
.ahb_mbar_no = 1,
|
||||
.reg_mask = 0xd,
|
||||
.regs = {
|
||||
{
|
||||
.mask = 0x00000000,
|
||||
.value = CONFIG_SYS_GRLIB_GAISLER_DDR2SPA1_CFG1,
|
||||
},
|
||||
{ 0x00000000, 0},
|
||||
{
|
||||
.mask = 0x00000000,
|
||||
.value = CONFIG_SYS_GRLIB_GAISLER_DDR2SPA1_CFG3,
|
||||
},
|
||||
{
|
||||
.mask = 0x00000000,
|
||||
.value = CONFIG_SYS_GRLIB_GAISLER_DDR2SPA1_CFG4,
|
||||
},
|
||||
}
|
||||
};
|
||||
#ifdef CONFIG_SYS_GRLIB_GAISLER_DDR2SPA2
|
||||
struct ahbmctrl_setup gaisler_ddr2spa2_cfg = {
|
||||
.ahb_mbar_no = 1,
|
||||
.reg_mask = 0xd,
|
||||
.regs = {
|
||||
{
|
||||
.mask = 0x00000000,
|
||||
.value = CONFIG_SYS_GRLIB_GAISLER_DDR2SPA2_CFG1,
|
||||
},
|
||||
{ 0x00000000, 0},
|
||||
{
|
||||
.mask = 0x00000000,
|
||||
.value = CONFIG_SYS_GRLIB_GAISLER_DDR2SPA2_CFG3,
|
||||
},
|
||||
{
|
||||
.mask = 0x00000000,
|
||||
.value = CONFIG_SYS_GRLIB_GAISLER_DDR2SPA2_CFG4,
|
||||
},
|
||||
}
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_GRLIB_GAISLER_DDRSPA1
|
||||
struct ahbmctrl_setup gaisler_ddrspa1_cfg = {
|
||||
.ahb_mbar_no = 1,
|
||||
.reg_mask = 0x1,
|
||||
.regs = {
|
||||
{
|
||||
.mask = 0x00000000,
|
||||
.value = CONFIG_SYS_GRLIB_GAISLER_DDRSPA1_CTRL,
|
||||
},
|
||||
}
|
||||
};
|
||||
#ifdef CONFIG_SYS_GRLIB_GAISLER_DDRSPA2
|
||||
struct ahbmctrl_setup gaisler_ddrspa2_cfg = {
|
||||
.ahb_mbar_no = 1,
|
||||
.reg_mask = 0x1,
|
||||
.regs = {
|
||||
{
|
||||
.mask = 0x00000000,
|
||||
.value = CONFIG_SYS_GRLIB_GAISLER_DDRSPA2_CTRL,
|
||||
},
|
||||
}
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct grlib_mctrl_handler grlib_mctrl_handlers[] = {
|
||||
/* ESA MCTRL (PROM/FLASH/IO/SRAM/SDRAM) */
|
||||
#ifdef CONFIG_SYS_GRLIB_ESA_MCTRL1
|
||||
{DEV_APB_SLV, 0, MH_UNUSED, AMBA_PNP_ID(VENDOR_ESA, ESA_MCTRL),
|
||||
_nomem_mctrl_init, (void *)&esa_mctrl1_cfg},
|
||||
#ifdef CONFIG_SYS_GRLIB_ESA_MCTRL2
|
||||
{DEV_APB_SLV, 1, MH_UNUSED, AMBA_PNP_ID(VENDOR_ESA, ESA_MCTRL),
|
||||
_nomem_mctrl_init, (void *)&esa_mctrl2_cfg},
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* GAISLER Fault Tolerant Memory controller (PROM/FLASH/IO/SRAM/SDRAM) */
|
||||
#ifdef CONFIG_SYS_GRLIB_GAISLER_FTMCTRL1
|
||||
{DEV_APB_SLV, 0, MH_UNUSED, AMBA_PNP_ID(VENDOR_GAISLER, GAISLER_FTMCTRL),
|
||||
_nomem_mctrl_init, (void *)&gaisler_ftmctrl1_cfg},
|
||||
#ifdef CONFIG_SYS_GRLIB_GAISLER_FTMCTRL2
|
||||
{DEV_APB_SLV, 1, MH_UNUSED, AMBA_PNP_ID(VENDOR_GAISLER, GAISLER_FTMCTRL),
|
||||
_nomem_mctrl_init, (void *)&gaisler_ftmctrl2_cfg},
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* GAISLER SDRAM-only Memory controller (SDRAM) */
|
||||
#ifdef CONFIG_SYS_GRLIB_GAISLER_SDCTRL1
|
||||
{DEV_APB_SLV, 0, MH_UNUSED, AMBA_PNP_ID(VENDOR_GAISLER, GAISLER_SDCTRL),
|
||||
_nomem_mctrl_init, (void *)&gaisler_sdctrl1_cfg},
|
||||
#ifdef CONFIG_SYS_GRLIB_GAISLER_SDCTRL2
|
||||
{DEV_APB_SLV, 1, MH_UNUSED, AMBA_PNP_ID(VENDOR_GAISLER, GAISLER_SDCTRL),
|
||||
_nomem_mctrl_init, (void *)&gaisler_sdctrl2_cfg},
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* GAISLER DDR Memory controller (DDR) */
|
||||
#ifdef CONFIG_SYS_GRLIB_GAISLER_DDRSPA1
|
||||
{DEV_AHB_SLV, 0, MH_UNUSED, AMBA_PNP_ID(VENDOR_GAISLER, GAISLER_DDRSP),
|
||||
_nomem_ahbmctrl_init, (void *)&gaisler_ddrspa1_cfg},
|
||||
#ifdef CONFIG_SYS_GRLIB_GAISLER_DDRSPA2
|
||||
{DEV_AHB_SLV, 1, MH_UNUSED, AMBA_PNP_ID(VENDOR_GAISLER, GAISLER_DDRSP),
|
||||
_nomem_ahbmctrl_init, (void *)&gaisler_ddrspa2_cfg},
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* GAISLER DDR2 Memory controller (DDR2) */
|
||||
#ifdef CONFIG_SYS_GRLIB_GAISLER_DDR2SPA1
|
||||
{DEV_AHB_SLV, 0, MH_UNUSED, AMBA_PNP_ID(VENDOR_GAISLER, GAISLER_DDR2SP),
|
||||
_nomem_ahbmctrl_init, (void *)&gaisler_ddr2spa1_cfg},
|
||||
#ifdef CONFIG_SYS_GRLIB_GAISLER_DDR2SPA2
|
||||
{DEV_AHB_SLV, 1, MH_UNUSED, AMBA_PNP_ID(VENDOR_GAISLER, GAISLER_DDR2SP),
|
||||
_nomem_ahbmctrl_init, (void *)&gaisler_ddr2spa2_cfg},
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Mark end */
|
||||
MH_END
|
||||
};
|
||||
90
u-boot/arch/sparc/cpu/leon3/memcfg.h
Normal file
90
u-boot/arch/sparc/cpu/leon3/memcfg.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/* GRLIB Memory controller setup structures
|
||||
*
|
||||
* (C) Copyright 2010, 2015
|
||||
* Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __MEMCFG_H__
|
||||
#define __MEMCFG_H__
|
||||
|
||||
/*********** Low Level Memory Controller Initalization ***********/
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
struct grlib_mctrl_handler;
|
||||
|
||||
typedef void (*mctrl_handler_t)(
|
||||
struct grlib_mctrl_handler *dev,
|
||||
void *conf,
|
||||
unsigned int ioarea
|
||||
);
|
||||
|
||||
/* Memory Controller Handler Structure */
|
||||
struct grlib_mctrl_handler {
|
||||
unsigned char type; /* 0x00. MASK: AHB MST&SLV, APB SLV */
|
||||
char index; /* 0x01. Unit number, 0, 1, 2... */
|
||||
char unused[2]; /* 0x02 */
|
||||
unsigned int ven_dev; /* 0x04. Device and Vendor */
|
||||
mctrl_handler_t func; /* 0x08. Memory Controller Handler */
|
||||
void *priv; /* 0x0c. Optional private data, ptr to
|
||||
* info how to set up controller */
|
||||
};
|
||||
|
||||
extern struct grlib_mctrl_handler grlib_mctrl_handlers[];
|
||||
|
||||
#endif
|
||||
|
||||
#define MH_STRUCT_SIZE (4*4)
|
||||
#define MH_TYPE 0x00
|
||||
#define MH_INDEX 0x01
|
||||
#define MH_VENDOR_DEVICE 0x04
|
||||
#define MH_FUNC 0x08
|
||||
#define MH_PRIV 0x0c
|
||||
|
||||
#define MH_TYPE_NONE DEV_NONE
|
||||
#define MH_TYPE_AHB_MST DEV_AHB_MST
|
||||
#define MH_TYPE_AHB_SLV DEV_AHB_SLV
|
||||
#define MH_TYPE_APB_SLV DEV_APB_SLV
|
||||
|
||||
#define MH_UNUSED {0, 0}
|
||||
#define MH_END {DEV_NONE, 0, MH_UNUSED, AMBA_PNP_ID(0, 0), 0, 0}
|
||||
|
||||
/*********** Low Level Memory Controller Initalization Handlers ***********/
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
extern void _nomem_mctrl_init(
|
||||
struct grlib_mctrl_handler *dev,
|
||||
void *conf,
|
||||
unsigned int ioarea_apbmst);
|
||||
|
||||
struct mctrl_setup {
|
||||
unsigned int reg_mask; /* Which registers to write */
|
||||
struct {
|
||||
unsigned int mask; /* Mask used keep reg bits unchanged */
|
||||
unsigned int value; /* Value written to register */
|
||||
} regs[8];
|
||||
};
|
||||
|
||||
extern void _nomem_ahbmctrl_init(
|
||||
struct grlib_mctrl_handler *dev,
|
||||
void *conf,
|
||||
unsigned int ioarea_apbmst);
|
||||
|
||||
struct ahbmctrl_setup {
|
||||
int ahb_mbar_no; /* MBAR to get register address from */
|
||||
unsigned int reg_mask; /* Which registers to write */
|
||||
struct {
|
||||
unsigned int mask; /* Mask used keep reg bits unchanged */
|
||||
unsigned int value; /* Value written to register */
|
||||
} regs[8];
|
||||
};
|
||||
#endif
|
||||
|
||||
/* mctrl_setup data structure defines */
|
||||
#define NREGS_OFS 0
|
||||
#define REGS_OFS 0x4
|
||||
#define REGS_SIZE 8
|
||||
|
||||
#endif
|
||||
253
u-boot/arch/sparc/cpu/leon3/memcfg_low.S
Normal file
253
u-boot/arch/sparc/cpu/leon3/memcfg_low.S
Normal file
@@ -0,0 +1,253 @@
|
||||
/* This is the memory initialization functions, the function
|
||||
* implemented below initializes each memory controller
|
||||
* found and specified by the input grlib_mctrl_handler structure.
|
||||
*
|
||||
* After the memory controllers have been initialized the stack
|
||||
* can be used.
|
||||
*
|
||||
* (C) Copyright 2010, 2015
|
||||
* Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <ambapp.h>
|
||||
#include "memcfg.h"
|
||||
#include <config.h>
|
||||
|
||||
.seg "text"
|
||||
.globl _nomem_memory_ctrl_init
|
||||
.globl _nomem_mctrl_init, _nomem_ahbmctrl_init
|
||||
.extern _nomem_find_apb
|
||||
.extern _nomem_find_ahb
|
||||
|
||||
|
||||
/* FUNCTION
|
||||
* _nomem_memory_controller_init(struct grlib_mctrl_handler *mem_handlers)
|
||||
*
|
||||
* Initialize AMBA devices, _nomem_amba_init() has prepared i0-i5
|
||||
* with the AHB buses on the system.
|
||||
*
|
||||
* For each entry in mem_handlers find the VENDOR:DEVICE and handle it
|
||||
* by calling the handler function pointer.
|
||||
*
|
||||
* Constraints:
|
||||
* i6, i7, o6, l7, l6, g3, g4, g5, g6, g7 is used by caller
|
||||
* o7 is return address
|
||||
* l5 reserved for this function for future use.
|
||||
*
|
||||
* Arguments
|
||||
* - o0 Pointer to memory handler array
|
||||
*
|
||||
* Results
|
||||
* - o0 Number of memory controllers found
|
||||
*
|
||||
* Clobbered
|
||||
* - o0 (Current AHB slave conf address)
|
||||
* - l0 (mem handler entry address)
|
||||
* - l1 (Return value, number of memory controllers found)
|
||||
* - o7 (function pointer)
|
||||
* - l0, l1, l2, l3, l4, g1, g2 (used by _nomem_ambapp_find_buses)
|
||||
* - o0, o1, o2, o3, o4, o5 (Used as arguments)
|
||||
*
|
||||
* - g1 ( level 1 return address)
|
||||
* - g2 ( level 2 return address)
|
||||
*/
|
||||
|
||||
_nomem_memory_ctrl_init:
|
||||
/* At this point all AHB buses has been found and the I/O Areas of
|
||||
* all AHB buses is stored in the i0-i5 registers. Max 6 buses. Next,
|
||||
* memory controllers are found by searching all buses for matching
|
||||
* VENDOR:DEVICE. The VENDOR:DEVICE to search for are taken from the
|
||||
* mem_handlers array. For each match the function pointer stored in
|
||||
* the mem_handler entry is called to handle the hardware setup.
|
||||
*/
|
||||
mov %o7, %g1 /* Save return address */
|
||||
mov %o0, %l0
|
||||
mov %g0, %l1 /* The return value */
|
||||
|
||||
.L_do_one_mem_handler:
|
||||
ld [%l0 + MH_FUNC], %o7
|
||||
cmp %o7, %g0
|
||||
be .L_all_mctrl_handled
|
||||
nop
|
||||
|
||||
/*** Scan for memory controller ***/
|
||||
|
||||
/* Set up argments, o5 not used by _nomem_find_apb */
|
||||
ldub [%l0 + MH_TYPE], %o5
|
||||
clr %o4
|
||||
clr %o3
|
||||
ldub [%l0 + MH_INDEX], %o2
|
||||
ld [%l0 + MH_VENDOR_DEVICE], %o1
|
||||
|
||||
/* An empty config? */
|
||||
cmp %o5, DEV_NONE
|
||||
beq .L_all_mctrl_next
|
||||
|
||||
/* Select function (APB or AHB) */
|
||||
cmp %o5, DEV_APB_SLV
|
||||
bne .L_find_ahb_memctrl
|
||||
clr %o0
|
||||
.L_find_apb_memctrl:
|
||||
call _nomem_find_apb /* Scan for APB slave device */
|
||||
nop
|
||||
|
||||
/* o3 = iobar address
|
||||
* o4 = AHB Bus index
|
||||
*
|
||||
* REG ADR = ((iobar >> 12) & (iobar << 4) & 0xfff00) | "APB Base"
|
||||
*/
|
||||
ld [%o3 + AMBA_APB_IOBAR_OFS], %o5
|
||||
srl %o5, 12, %o2
|
||||
sll %o5, 4, %o5
|
||||
and %o2, %o5, %o5
|
||||
set 0xfff00, %o2
|
||||
and %o2, %o5, %o5
|
||||
sethi %hi(0xfff00000), %o2
|
||||
and %o3, %o2, %o2
|
||||
or %o5, %o2, %o5 /* Register base address */
|
||||
|
||||
ba .L_call_one_mem_handler
|
||||
nop
|
||||
|
||||
.L_find_ahb_memctrl:
|
||||
call _nomem_find_ahb /* Scan for AHB Slave or Master.
|
||||
* o5 determine type. */
|
||||
nop
|
||||
clr %o5
|
||||
|
||||
/* Call the handler function if the hardware was found
|
||||
*
|
||||
* o0 = mem_handler
|
||||
* o1 = Configuration address
|
||||
* o2 = AHB Bus index
|
||||
* o3 = APB Base register (if APB Slave)
|
||||
*
|
||||
* Constraints:
|
||||
* i0-i7, l0, l1, l5, g1, g3-g7 may no be used.
|
||||
*/
|
||||
.L_call_one_mem_handler:
|
||||
cmp %o0, %g0
|
||||
be .L_all_mctrl_next
|
||||
mov %l0, %o0 /* Mem handler pointer */
|
||||
mov %o3, %o1 /* AMBA PnP Configuration address */
|
||||
mov %o4, %o2 /* AHB Bus index */
|
||||
ld [%l0 + MH_FUNC], %o7 /* Get Function pointer */
|
||||
call %o7
|
||||
mov %o5, %o3 /* APB Register Base Address */
|
||||
|
||||
inc %l1 /* Number of Memory controllers
|
||||
* handled. */
|
||||
|
||||
/* Do next entry in mem_handlers */
|
||||
.L_all_mctrl_next:
|
||||
ba .L_do_one_mem_handler
|
||||
add %l0, MH_STRUCT_SIZE, %l0
|
||||
|
||||
.L_all_mctrl_handled:
|
||||
mov %g1, %o7 /* Restore return address */
|
||||
retl
|
||||
mov %l1, %o0
|
||||
|
||||
|
||||
|
||||
/* Generic Memory controller initialization routine (APB Registers)
|
||||
*
|
||||
* o0 = mem_handler structure pointer
|
||||
* o1 = Configuration address
|
||||
* o2 = AHB Bus index
|
||||
* o3 = APB Base register
|
||||
*
|
||||
* Clobbered
|
||||
* o0-o4
|
||||
*/
|
||||
_nomem_mctrl_init:
|
||||
ld [%o0 + MH_PRIV], %o0 /* Get Private structure */
|
||||
ld [%o0], %o1 /* Get Reg Mask */
|
||||
and %o1, 0xff, %o1
|
||||
add %o0, REGS_OFS, %o0 /* Point to first reg */
|
||||
.L_do_one_reg:
|
||||
andcc %o1, 0x1, %g0
|
||||
beq .L_do_next_reg
|
||||
ld [%o0], %o2
|
||||
ld [%o3], %o4
|
||||
and %o4, %o2, %o4
|
||||
ld [%o0 + 4], %o2
|
||||
or %o4, %o2, %o4
|
||||
st %o4, [%o3]
|
||||
|
||||
.L_do_next_reg:
|
||||
add %o0, REGS_SIZE, %o0
|
||||
add %o3, 4, %o3
|
||||
srl %o1, 1, %o1
|
||||
cmp %o1, 0
|
||||
bne .L_do_one_reg
|
||||
nop
|
||||
|
||||
/* No more registers to write */
|
||||
retl
|
||||
nop
|
||||
|
||||
|
||||
|
||||
/* Generic Memory controller initialization routine (AHB Registers)
|
||||
*
|
||||
* o0 = mem_handler structure pointer
|
||||
* o1 = Configuration address of memory controller
|
||||
* o2 = AHB Bus index
|
||||
*
|
||||
* Clobbered
|
||||
* o0-o5
|
||||
*/
|
||||
_nomem_ahbmctrl_init:
|
||||
ld [%o0 + MH_PRIV], %o0 /* Get Private structure */
|
||||
|
||||
/* Get index of AHB MBAR to get registers from */
|
||||
ld [%o0], %o5
|
||||
add %o0, 4, %o0
|
||||
|
||||
/* Get Address of MBAR in PnP info */
|
||||
add %o5, 4, %o5
|
||||
sll %o5, 2, %o5
|
||||
add %o5, %o1, %o5 /* Address of MBAR */
|
||||
|
||||
/* Get Address of registers from PnP information
|
||||
* Address is in AHB I/O format, i.e. relative to bus
|
||||
*
|
||||
* ADR = (iobar & (iobar << 16) & 0xfff00000)
|
||||
* IOADR = (ADR >> 12) | "APB Base"
|
||||
*/
|
||||
ld [%o5], %o5
|
||||
sll %o5, 16, %o4
|
||||
and %o5, %o4, %o5
|
||||
sethi %hi(0xfff00000), %o4
|
||||
and %o5, %o4, %o5 /* ADR */
|
||||
and %o4, %o1, %o4
|
||||
srl %o5, 12, %o5
|
||||
or %o5, %o4, %o3 /* IOADR in o3 */
|
||||
|
||||
ld [%o0], %o1 /* Get Reg Mask */
|
||||
and %o1, 0xff, %o1
|
||||
add %o0, REGS_OFS, %o0 /* Point to first reg */
|
||||
.L_do_one_ahbreg:
|
||||
andcc %o1, 0x1, %g0
|
||||
beq .L_do_next_reg
|
||||
ld [%o0], %o2
|
||||
ld [%o3], %o4
|
||||
and %o4, %o2, %o4
|
||||
ld [%o0 + 4], %o2
|
||||
or %o4, %o2, %o4
|
||||
st %o4, [%o3]
|
||||
|
||||
.L_do_next_ahbreg:
|
||||
add %o0, REGS_SIZE, %o0
|
||||
add %o3, 4, %o3
|
||||
srl %o1, 1, %o1
|
||||
cmp %o1, 0
|
||||
bne .L_do_one_reg
|
||||
nop
|
||||
|
||||
/* No more registers to write */
|
||||
retl
|
||||
nop
|
||||
1067
u-boot/arch/sparc/cpu/leon3/prom.c
Normal file
1067
u-boot/arch/sparc/cpu/leon3/prom.c
Normal file
File diff suppressed because it is too large
Load Diff
189
u-boot/arch/sparc/cpu/leon3/serial.c
Normal file
189
u-boot/arch/sparc/cpu/leon3/serial.c
Normal file
@@ -0,0 +1,189 @@
|
||||
/* GRLIB APBUART Serial controller driver
|
||||
*
|
||||
* (C) Copyright 2007, 2015
|
||||
* Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <ambapp.h>
|
||||
#include <grlib/apbuart.h>
|
||||
#include <serial.h>
|
||||
#include <watchdog.h>
|
||||
|
||||
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)
|
||||
{
|
||||
ambapp_dev_apbuart *uart;
|
||||
ambapp_apbdev apbdev;
|
||||
unsigned int tmp;
|
||||
|
||||
/* 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 */
|
||||
}
|
||||
|
||||
/* 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 = apbuart_calc_scaler(gd->arch.uart_freq, CONFIG_BAUDRATE);
|
||||
writel(tmp, &uart->scaler);
|
||||
|
||||
/* Let bit 11 be unchanged (debug bit for GRMON) */
|
||||
tmp = readl(&uart->ctrl) & APBUART_CTRL_DBG;
|
||||
/* Receiver & transmitter enable */
|
||||
tmp |= APBUART_CTRL_RE | APBUART_CTRL_TE;
|
||||
writel(tmp, &uart->ctrl);
|
||||
|
||||
gd->arch.uart = uart;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline ambapp_dev_apbuart *leon3_get_uart_regs(void)
|
||||
{
|
||||
ambapp_dev_apbuart *uart = gd->arch.uart;
|
||||
return uart;
|
||||
}
|
||||
|
||||
static void leon3_serial_putc_raw(const char c)
|
||||
{
|
||||
ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
|
||||
|
||||
if (!uart)
|
||||
return;
|
||||
|
||||
/* Wait for last character to go. */
|
||||
while (!(readl(&uart->status) & APBUART_STATUS_THE))
|
||||
WATCHDOG_RESET();
|
||||
|
||||
/* Send data */
|
||||
writel(c, &uart->data);
|
||||
|
||||
#ifdef LEON_DEBUG
|
||||
/* Wait for data to be sent */
|
||||
while (!(readl(&uart->status) & APBUART_STATUS_TSE))
|
||||
WATCHDOG_RESET();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void leon3_serial_putc(const char c)
|
||||
{
|
||||
if (c == '\n')
|
||||
leon3_serial_putc_raw('\r');
|
||||
|
||||
leon3_serial_putc_raw(c);
|
||||
}
|
||||
|
||||
static int leon3_serial_getc(void)
|
||||
{
|
||||
ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
|
||||
|
||||
if (!uart)
|
||||
return 0;
|
||||
|
||||
/* Wait for a character to arrive. */
|
||||
while (!(readl(&uart->status) & APBUART_STATUS_DR))
|
||||
WATCHDOG_RESET();
|
||||
|
||||
/* Read character data */
|
||||
return readl(&uart->data);
|
||||
}
|
||||
|
||||
static int leon3_serial_tstc(void)
|
||||
{
|
||||
ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
|
||||
|
||||
if (!uart)
|
||||
return 0;
|
||||
|
||||
return readl(&uart->status) & APBUART_STATUS_DR;
|
||||
}
|
||||
|
||||
/* set baud rate for uart */
|
||||
static void leon3_serial_setbrg(void)
|
||||
{
|
||||
ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
|
||||
unsigned int scaler;
|
||||
|
||||
if (!uart)
|
||||
return;
|
||||
|
||||
if (!gd->baudrate)
|
||||
gd->baudrate = CONFIG_BAUDRATE;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static struct serial_device leon3_serial_drv = {
|
||||
.name = "leon3_serial",
|
||||
.start = leon3_serial_init,
|
||||
.stop = NULL,
|
||||
.setbrg = leon3_serial_setbrg,
|
||||
.putc = leon3_serial_putc,
|
||||
.puts = default_serial_puts,
|
||||
.getc = leon3_serial_getc,
|
||||
.tstc = leon3_serial_tstc,
|
||||
};
|
||||
|
||||
void leon3_serial_initialize(void)
|
||||
{
|
||||
serial_register(&leon3_serial_drv);
|
||||
}
|
||||
|
||||
__weak struct serial_device *default_serial_console(void)
|
||||
{
|
||||
return &leon3_serial_drv;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_UART_APBUART
|
||||
|
||||
#include <debug_uart.h>
|
||||
|
||||
static inline void _debug_uart_init(void)
|
||||
{
|
||||
ambapp_dev_apbuart *uart = (ambapp_dev_apbuart *)CONFIG_DEBUG_UART_BASE;
|
||||
uart->scaler = apbuart_calc_scaler(CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
|
||||
uart->ctrl = APBUART_CTRL_RE | APBUART_CTRL_TE;
|
||||
}
|
||||
|
||||
static inline void _debug_uart_putc(int ch)
|
||||
{
|
||||
ambapp_dev_apbuart *uart = (ambapp_dev_apbuart *)CONFIG_DEBUG_UART_BASE;
|
||||
while (!(readl(&uart->status) & APBUART_STATUS_THE))
|
||||
WATCHDOG_RESET();
|
||||
writel(ch, &uart->data);
|
||||
}
|
||||
|
||||
DEBUG_UART_FUNCS
|
||||
|
||||
#endif
|
||||
681
u-boot/arch/sparc/cpu/leon3/start.S
Normal file
681
u-boot/arch/sparc/cpu/leon3/start.S
Normal file
@@ -0,0 +1,681 @@
|
||||
/* This is where the SPARC/LEON3 starts
|
||||
*
|
||||
* Copyright (C) 2007, 2015
|
||||
* Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <asm-offsets.h>
|
||||
#include <config.h>
|
||||
#include <asm/asmmacro.h>
|
||||
#include <asm/winmacro.h>
|
||||
#include <asm/psr.h>
|
||||
#include <asm/stack.h>
|
||||
#include <asm/leon.h>
|
||||
#include <ambapp.h>
|
||||
|
||||
/* Default Plug&Play I/O area */
|
||||
#ifndef CONFIG_AMBAPP_IOAREA
|
||||
#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; \
|
||||
mov %g0, %tbr; \
|
||||
ba (H); \
|
||||
mov %g0, %wim;
|
||||
|
||||
#define TRAP(H) \
|
||||
mov %psr, %l0; \
|
||||
ba (H); \
|
||||
nop; nop;
|
||||
|
||||
#define TRAPI(ilevel) \
|
||||
mov ilevel, %l7; \
|
||||
mov %psr, %l0; \
|
||||
b _irq_entry; \
|
||||
mov %wim, %l3
|
||||
|
||||
/* Unexcpected trap will halt the processor by forcing it to error state */
|
||||
#undef BAD_TRAP
|
||||
#define BAD_TRAP ta 0; nop; nop; nop;
|
||||
|
||||
/* Software trap. Treat as BAD_TRAP for the time being... */
|
||||
#define SOFT_TRAP TRAP(_hwerr)
|
||||
|
||||
#define PSR_INIT 0x1FC0 /* Disable traps, set s and ps */
|
||||
#define WIM_INIT 2
|
||||
|
||||
/* All traps low-level code here must end with this macro. */
|
||||
#define RESTORE_ALL b ret_trap_entry; clr %l6;
|
||||
|
||||
#define WRITE_PAUSE nop;nop;nop
|
||||
|
||||
WINDOWSIZE = (16 * 4)
|
||||
ARGPUSHSIZE = (6 * 4)
|
||||
ARGPUSH = (WINDOWSIZE + 4)
|
||||
MINFRAME = (WINDOWSIZE + ARGPUSHSIZE + 4)
|
||||
|
||||
/* Number of register windows */
|
||||
#ifndef CONFIG_SYS_SPARC_NWINDOWS
|
||||
#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))
|
||||
|
||||
.section ".start", "ax"
|
||||
.globl _start, start, _trap_table
|
||||
.globl _irq_entry, nmi_trap
|
||||
.globl _reset_reloc
|
||||
|
||||
/* at address 0
|
||||
* Hardware traps
|
||||
*/
|
||||
start:
|
||||
_start:
|
||||
_trap_table:
|
||||
TRAPR(_hardreset); ! 00 reset trap
|
||||
BAD_TRAP; ! 01 instruction_access_exception
|
||||
BAD_TRAP; ! 02 illegal_instruction
|
||||
BAD_TRAP; ! 03 priveleged_instruction
|
||||
BAD_TRAP; ! 04 fp_disabled
|
||||
TRAP(_window_overflow); ! 05 window_overflow
|
||||
TRAP(_window_underflow); ! 06 window_underflow
|
||||
BAD_TRAP; ! 07 Memory Address Not Aligned
|
||||
BAD_TRAP; ! 08 Floating Point Exception
|
||||
BAD_TRAP; ! 09 Data Miss Exception
|
||||
BAD_TRAP; ! 0a Tagged Instruction Ovrflw
|
||||
BAD_TRAP; ! 0b Watchpoint Detected
|
||||
BAD_TRAP; ! 0c
|
||||
BAD_TRAP; ! 0d
|
||||
BAD_TRAP; ! 0e
|
||||
BAD_TRAP; ! 0f
|
||||
BAD_TRAP; ! 10
|
||||
TRAPI(1); ! 11 IRQ level 1
|
||||
TRAPI(2); ! 12 IRQ level 2
|
||||
TRAPI(3); ! 13 IRQ level 3
|
||||
TRAPI(4); ! 14 IRQ level 4
|
||||
TRAPI(5); ! 15 IRQ level 5
|
||||
TRAPI(6); ! 16 IRQ level 6
|
||||
TRAPI(7); ! 17 IRQ level 7
|
||||
TRAPI(8); ! 18 IRQ level 8
|
||||
TRAPI(9); ! 19 IRQ level 9
|
||||
TRAPI(10); ! 1a IRQ level 10
|
||||
TRAPI(11); ! 1b IRQ level 11
|
||||
TRAPI(12); ! 1c IRQ level 12
|
||||
TRAPI(13); ! 1d IRQ level 13
|
||||
TRAPI(14); ! 1e IRQ level 14
|
||||
TRAP(_nmi_trap); ! 1f IRQ level 15 /
|
||||
! NMI (non maskable interrupt)
|
||||
BAD_TRAP; ! 20 r_register_access_error
|
||||
BAD_TRAP; ! 21 instruction access error
|
||||
BAD_TRAP; ! 22
|
||||
BAD_TRAP; ! 23
|
||||
BAD_TRAP; ! 24 co-processor disabled
|
||||
BAD_TRAP; ! 25 uniplemented FLUSH
|
||||
BAD_TRAP; ! 26
|
||||
BAD_TRAP; ! 27
|
||||
BAD_TRAP; ! 28 co-processor exception
|
||||
BAD_TRAP; ! 29 data access error
|
||||
BAD_TRAP; ! 2a division by zero
|
||||
BAD_TRAP; ! 2b data store error
|
||||
BAD_TRAP; ! 2c data access MMU miss
|
||||
BAD_TRAP; ! 2d
|
||||
BAD_TRAP; ! 2e
|
||||
BAD_TRAP; ! 2f
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 30-33
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 34-37
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 38-3b
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 3c-3f
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 40-43
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 44-47
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 48-4b
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 4c-4f
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 50-53
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 54-57
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 58-5b
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 5c-5f
|
||||
|
||||
/* implementaion dependent */
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 60-63
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 64-67
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 68-6b
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 6c-6f
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 70-73
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 74-77
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 78-7b
|
||||
BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 7c-7f
|
||||
|
||||
/* Software traps, not handled */
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 80-83
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 84-87
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 88-8b
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 8c-8f
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 90-93
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 94-97
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 98-9b
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 9c-9f
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! a0-a3
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! a4-a7
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! a8-ab
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! ac-af
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! b0-b3
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! b4-b7
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! b8-bb
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! bc-bf
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! c0-c3
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! c4-c7
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! c8-cb
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! cc-cf
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! d0-d3
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! d4-d7
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! d8-db
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! dc-df
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! e0-e3
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! e4-e7
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! e8-eb
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! ec-ef
|
||||
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! f0-f3
|
||||
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
|
||||
|
||||
.section ".text"
|
||||
.extern _nomem_amba_init, _nomem_memory_ctrl_init
|
||||
.align 4
|
||||
|
||||
_hardreset:
|
||||
1000:
|
||||
flush
|
||||
|
||||
/* Enable I/D-Cache and Snooping */
|
||||
set 0x0081000f, %g2
|
||||
sta %g2, [%g0] 2
|
||||
|
||||
mov %g0, %y
|
||||
clr %g1
|
||||
clr %g2
|
||||
clr %g3
|
||||
clr %g4
|
||||
clr %g5
|
||||
clr %g6
|
||||
clr %g7
|
||||
|
||||
mov %asr17, %g3
|
||||
and %g3, 0x1f, %g3
|
||||
clear_window:
|
||||
mov %g0, %l0
|
||||
mov %g0, %l1
|
||||
mov %g0, %l2
|
||||
mov %g0, %l3
|
||||
mov %g0, %l4
|
||||
mov %g0, %l5
|
||||
mov %g0, %l6
|
||||
mov %g0, %l7
|
||||
mov %g0, %o0
|
||||
mov %g0, %o1
|
||||
mov %g0, %o2
|
||||
mov %g0, %o3
|
||||
mov %g0, %o4
|
||||
mov %g0, %o5
|
||||
mov %g0, %o6
|
||||
mov %g0, %o7
|
||||
subcc %g3, 1, %g3
|
||||
bge clear_window
|
||||
save
|
||||
|
||||
wiminit:
|
||||
set WIM_INIT, %g3
|
||||
mov %g3, %wim
|
||||
|
||||
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)
|
||||
|
||||
/* Scan AMBA Bus for AMBA buses using PnP information. All found
|
||||
* AMBA buses I/O area will be located in i0-i5 upon return.
|
||||
* The i0-i5 registers are later used by _nomem_amba_init2
|
||||
*/
|
||||
ambainit:
|
||||
call _nomem_amba_init
|
||||
sethi %hi(CONFIG_AMBAPP_IOAREA), %o0
|
||||
|
||||
/* Scan AMBA Buses for memory controllers, then initialize the
|
||||
* memory controllers. Note that before setting up the memory controller
|
||||
* the stack can not be used.
|
||||
*/
|
||||
memory_ctrl_init:
|
||||
SPARC_LOAD_ADDRESS(grlib_mctrl_handlers, l7, o0)
|
||||
|
||||
call _nomem_memory_ctrl_init
|
||||
nop
|
||||
|
||||
/* The return valu indicate how many memory controllers where found and
|
||||
* initialized, if no memory controller was initialized, we can not continue
|
||||
* because from here on we expect memory to be working.
|
||||
*/
|
||||
cmp %o0, 0
|
||||
memory_ctrl_init_failed:
|
||||
beq memory_ctrl_init_failed
|
||||
nop
|
||||
|
||||
/*** From now on the stack can be used. ***/
|
||||
|
||||
cpu_init_unreloc:
|
||||
call cpu_init_f
|
||||
nop
|
||||
|
||||
board_init_unreloc:
|
||||
call board_init_f
|
||||
clr %o0 ! boot_flags
|
||||
|
||||
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, 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
|
||||
clr %l2
|
||||
clr %l3
|
||||
clr %g2
|
||||
|
||||
/* register g4 contain address to start
|
||||
* This means that BSS must be directly after data and code segments
|
||||
*
|
||||
* g3 is length of bss = (__bss_end-__bss_start)
|
||||
*
|
||||
*/
|
||||
|
||||
/* clear the relocated .bss area */
|
||||
clr_bss:
|
||||
SPARC_LOAD_ADDRESS(__bss_start, l7, g2)
|
||||
SPARC_LOAD_ADDRESS(__bss_end, l7, 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 */
|
||||
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 */
|
||||
fixup_got:
|
||||
SPARC_LOAD_ADDRESS(__got_start, l7, g4)
|
||||
add %g4, %g6, %g4
|
||||
SPARC_LOAD_ADDRESS(__got_end, l7, g3)
|
||||
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)
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
update_trap_table_address:
|
||||
wr %g0, %o2, %tbr
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
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:
|
||||
mov 1, %g1 ! For GRMON2 to exit normally.
|
||||
ta 0 ! if call returns.. (unlikely)
|
||||
nop
|
||||
b dead ! infinte loop
|
||||
nop
|
||||
|
||||
!------------------------------------------------------------------------------
|
||||
|
||||
/* Interrupt handler caller,
|
||||
* reg L7: interrupt number
|
||||
* reg L0: psr after interrupt
|
||||
* reg L1: PC
|
||||
* reg L2: next PC
|
||||
* reg L3: wim
|
||||
*/
|
||||
_irq_entry:
|
||||
SAVE_ALL
|
||||
|
||||
or %l0, PSR_PIL, %g2
|
||||
wr %g2, 0x0, %psr
|
||||
WRITE_PAUSE
|
||||
wr %g2, PSR_ET, %psr
|
||||
WRITE_PAUSE
|
||||
mov %l7, %o0 ! irq level
|
||||
set handler_irq, %o1
|
||||
set (CONFIG_SYS_RELOC_MONITOR_BASE-CONFIG_SYS_TEXT_BASE), %o2
|
||||
add %o1, %o2, %o1
|
||||
call %o1
|
||||
add %sp, SF_REGS_SZ, %o1 ! pt_regs ptr
|
||||
or %l0, PSR_PIL, %g2 ! restore PIL after handler_irq
|
||||
wr %g2, PSR_ET, %psr ! keep ET up
|
||||
WRITE_PAUSE
|
||||
|
||||
RESTORE_ALL
|
||||
|
||||
!------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* 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 %g1, %l4, %g1
|
||||
save ! Get into window to be saved.
|
||||
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
|
||||
jmp %l1 ! Re-execute save.
|
||||
rett %l2
|
||||
|
||||
/*
|
||||
* Window underflow trap handler
|
||||
*/
|
||||
.global _window_underflow
|
||||
|
||||
_window_underflow:
|
||||
|
||||
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
|
||||
ld [%sp + 0], %l0; ! Restore window from the stack
|
||||
ld [%sp + 4], %l1;
|
||||
ld [%sp + 8], %l2;
|
||||
ld [%sp + 12], %l3;
|
||||
ld [%sp + 16], %l4;
|
||||
ld [%sp + 20], %l5;
|
||||
ld [%sp + 24], %l6;
|
||||
ld [%sp + 28], %l7;
|
||||
ld [%sp + 32], %i0;
|
||||
ld [%sp + 36], %i1;
|
||||
ld [%sp + 40], %i2;
|
||||
ld [%sp + 44], %i3;
|
||||
ld [%sp + 48], %i4;
|
||||
ld [%sp + 52], %i5;
|
||||
ld [%sp + 56], %i6;
|
||||
ld [%sp + 60], %i7;
|
||||
save ! Get back to the trap window.
|
||||
save
|
||||
jmp %l1 ! Re-execute restore.
|
||||
rett %l2
|
||||
|
||||
!------------------------------------------------------------------------------
|
||||
|
||||
_nmi_trap:
|
||||
nop
|
||||
jmp %l1
|
||||
rett %l2
|
||||
|
||||
_hwerr:
|
||||
ta 0
|
||||
nop
|
||||
nop
|
||||
b _hwerr ! loop infinite
|
||||
nop
|
||||
|
||||
/* Registers to not touch at all. */
|
||||
#define t_psr l0 /* Set by caller */
|
||||
#define t_pc l1 /* Set by caller */
|
||||
#define t_npc l2 /* Set by caller */
|
||||
#define t_wim l3 /* Set by caller */
|
||||
#define t_twinmask l4 /* Set at beginning of this entry routine. */
|
||||
#define t_kstack l5 /* Set right before pt_regs frame is built */
|
||||
#define t_retpc l6 /* If you change this, change winmacro.h header file */
|
||||
#define t_systable l7 /* Never touch this, could be the syscall table ptr. */
|
||||
#define curptr g6 /* Set after pt_regs frame is built */
|
||||
|
||||
trap_setup:
|
||||
/* build a pt_regs trap frame. */
|
||||
sub %fp, (SF_REGS_SZ + PT_REGS_SZ), %t_kstack
|
||||
PT_STORE_ALL(t_kstack, t_psr, t_pc, t_npc, g2)
|
||||
|
||||
/* See if we are in the trap window. */
|
||||
mov 1, %t_twinmask
|
||||
sll %t_twinmask, %t_psr, %t_twinmask ! t_twinmask = (1 << psr)
|
||||
andcc %t_twinmask, %t_wim, %g0
|
||||
beq 1f ! in trap window, clean up
|
||||
nop
|
||||
|
||||
/*-------------------------------------------------
|
||||
* Spill , adjust %wim and go.
|
||||
*/
|
||||
srl %t_wim, 0x1, %g2 ! begin computation of new %wim
|
||||
|
||||
set (CONFIG_SYS_SPARC_NWINDOWS-1), %g3 !NWINDOWS-1
|
||||
|
||||
sll %t_wim, %g3, %t_wim ! NWINDOWS-1
|
||||
or %t_wim, %g2, %g2
|
||||
and %g2, 0xff, %g2
|
||||
|
||||
save %g0, %g0, %g0 ! get in window to be saved
|
||||
|
||||
/* Set new %wim value */
|
||||
wr %g2, 0x0, %wim
|
||||
|
||||
/* Save the kernel window onto the corresponding stack. */
|
||||
RW_STORE(sp)
|
||||
|
||||
restore %g0, %g0, %g0
|
||||
/*-------------------------------------------------*/
|
||||
|
||||
1:
|
||||
/* Trap from kernel with a window available.
|
||||
* Just do it...
|
||||
*/
|
||||
jmpl %t_retpc + 0x8, %g0 ! return to caller
|
||||
mov %t_kstack, %sp ! jump onto new stack
|
||||
|
||||
#define twin_tmp1 l4
|
||||
#define glob_tmp g4
|
||||
#define curptr g6
|
||||
ret_trap_entry:
|
||||
wr %t_psr, 0x0, %psr ! enable nesting again, clear ET
|
||||
|
||||
/* Will the rett land us in the invalid window? */
|
||||
mov 2, %g1
|
||||
sll %g1, %t_psr, %g1
|
||||
|
||||
set CONFIG_SYS_SPARC_NWINDOWS, %g2 !NWINDOWS
|
||||
|
||||
srl %g1, %g2, %g2
|
||||
or %g1, %g2, %g1
|
||||
rd %wim, %g2
|
||||
andcc %g2, %g1, %g0
|
||||
be 1f ! Nope, just return from the trap
|
||||
sll %g2, 0x1, %g1
|
||||
|
||||
/* We have to grab a window before returning. */
|
||||
set (CONFIG_SYS_SPARC_NWINDOWS-1), %g3 !NWINDOWS-1
|
||||
|
||||
srl %g2, %g3, %g2
|
||||
or %g1, %g2, %g1
|
||||
and %g1, 0xff, %g1
|
||||
|
||||
wr %g1, 0x0, %wim
|
||||
|
||||
/* Grrr, make sure we load from the right %sp... */
|
||||
PT_LOAD_ALL(sp, t_psr, t_pc, t_npc, g1)
|
||||
|
||||
restore %g0, %g0, %g0
|
||||
RW_LOAD(sp)
|
||||
b 2f
|
||||
save %g0, %g0, %g0
|
||||
|
||||
/* Reload the entire frame in case this is from a
|
||||
* kernel system call or whatever...
|
||||
*/
|
||||
1:
|
||||
PT_LOAD_ALL(sp, t_psr, t_pc, t_npc, g1)
|
||||
2:
|
||||
wr %t_psr, 0x0, %psr
|
||||
nop;
|
||||
nop;
|
||||
nop
|
||||
|
||||
jmp %t_pc
|
||||
rett %t_npc
|
||||
|
||||
/* This is called from relocated C-code.
|
||||
* It resets the system by jumping to _start
|
||||
*/
|
||||
_reset_reloc:
|
||||
set start, %l0
|
||||
call %l0
|
||||
nop
|
||||
1195
u-boot/arch/sparc/cpu/leon3/usb_uhci.c
Normal file
1195
u-boot/arch/sparc/cpu/leon3/usb_uhci.c
Normal file
File diff suppressed because it is too large
Load Diff
167
u-boot/arch/sparc/cpu/leon3/usb_uhci.h
Normal file
167
u-boot/arch/sparc/cpu/leon3/usb_uhci.h
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* (C) Copyright 2001
|
||||
* Denis Peter, MPL AG Switzerland
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*
|
||||
* Note: Part of this code has been derived from linux
|
||||
*/
|
||||
#ifndef _USB_UHCI_H_
|
||||
#define _USB_UHCI_H_
|
||||
|
||||
/* Command register */
|
||||
#define USBCMD 0
|
||||
#define USBCMD_RS 0x0001 /* Run/Stop */
|
||||
#define USBCMD_HCRESET 0x0002 /* Host reset */
|
||||
#define USBCMD_GRESET 0x0004 /* Global reset */
|
||||
#define USBCMD_EGSM 0x0008 /* Global Suspend Mode */
|
||||
#define USBCMD_FGR 0x0010 /* Force Global Resume */
|
||||
#define USBCMD_SWDBG 0x0020 /* SW Debug mode */
|
||||
#define USBCMD_CF 0x0040 /* Config Flag (sw only) */
|
||||
#define USBCMD_MAXP 0x0080 /* Max Packet (0 = 32, 1 = 64) */
|
||||
|
||||
/* Status register */
|
||||
#define USBSTS 2
|
||||
#define USBSTS_USBINT 0x0001 /* Interrupt due to IOC */
|
||||
#define USBSTS_ERROR 0x0002 /* Interrupt due to error */
|
||||
#define USBSTS_RD 0x0004 /* Resume Detect */
|
||||
#define USBSTS_HSE 0x0008 /* Host System Error - basically PCI problems */
|
||||
#define USBSTS_HCPE 0x0010 /* Host Controller Process Error - the scripts were buggy */
|
||||
#define USBSTS_HCH 0x0020 /* HC Halted */
|
||||
|
||||
/* Interrupt enable register */
|
||||
#define USBINTR 4
|
||||
#define USBINTR_TIMEOUT 0x0001 /* Timeout/CRC error enable */
|
||||
#define USBINTR_RESUME 0x0002 /* Resume interrupt enable */
|
||||
#define USBINTR_IOC 0x0004 /* Interrupt On Complete enable */
|
||||
#define USBINTR_SP 0x0008 /* Short packet interrupt enable */
|
||||
|
||||
#define USBFRNUM 6
|
||||
#define USBFLBASEADD 8
|
||||
#define USBSOF 12
|
||||
|
||||
/* USB port status and control registers */
|
||||
#define USBPORTSC1 16
|
||||
#define USBPORTSC2 18
|
||||
#define USBPORTSC_CCS 0x0001 /* Current Connect Status ("device present") */
|
||||
#define USBPORTSC_CSC 0x0002 /* Connect Status Change */
|
||||
#define USBPORTSC_PE 0x0004 /* Port Enable */
|
||||
#define USBPORTSC_PEC 0x0008 /* Port Enable Change */
|
||||
#define USBPORTSC_LS 0x0030 /* Line Status */
|
||||
#define USBPORTSC_RD 0x0040 /* Resume Detect */
|
||||
#define USBPORTSC_LSDA 0x0100 /* Low Speed Device Attached */
|
||||
#define USBPORTSC_PR 0x0200 /* Port Reset */
|
||||
#define USBPORTSC_SUSP 0x1000 /* Suspend */
|
||||
|
||||
/* Legacy support register */
|
||||
#define USBLEGSUP 0xc0
|
||||
#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */
|
||||
|
||||
#define UHCI_NULL_DATA_SIZE 0x7ff /* for UHCI controller TD */
|
||||
#define UHCI_PID 0xff /* PID MASK */
|
||||
|
||||
#define UHCI_PTR_BITS 0x000F
|
||||
#define UHCI_PTR_TERM 0x0001
|
||||
#define UHCI_PTR_QH 0x0002
|
||||
#define UHCI_PTR_DEPTH 0x0004
|
||||
|
||||
/* for TD <status>: */
|
||||
#define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */
|
||||
#define TD_CTRL_C_ERR_MASK (3 << 27) /* Error Counter bits */
|
||||
#define TD_CTRL_LS (1 << 26) /* Low Speed Device */
|
||||
#define TD_CTRL_IOS (1 << 25) /* Isochronous Select */
|
||||
#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */
|
||||
#define TD_CTRL_ACTIVE (1 << 23) /* TD Active */
|
||||
#define TD_CTRL_STALLED (1 << 22) /* TD Stalled */
|
||||
#define TD_CTRL_DBUFERR (1 << 21) /* Data Buffer Error */
|
||||
#define TD_CTRL_BABBLE (1 << 20) /* Babble Detected */
|
||||
#define TD_CTRL_NAK (1 << 19) /* NAK Received */
|
||||
#define TD_CTRL_CRCTIMEO (1 << 18) /* CRC/Time Out Error */
|
||||
#define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */
|
||||
#define TD_CTRL_ACTLEN_MASK 0x7ff /* actual length, encoded as n - 1 */
|
||||
|
||||
#define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \
|
||||
TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF)
|
||||
|
||||
#define TD_TOKEN_TOGGLE 19
|
||||
|
||||
/* ------------------------------------------------------------------------------------
|
||||
Virtual Root HUB
|
||||
------------------------------------------------------------------------------------ */
|
||||
/* destination of request */
|
||||
#define RH_INTERFACE 0x01
|
||||
#define RH_ENDPOINT 0x02
|
||||
#define RH_OTHER 0x03
|
||||
|
||||
#define RH_CLASS 0x20
|
||||
#define RH_VENDOR 0x40
|
||||
|
||||
/* Requests: bRequest << 8 | bmRequestType */
|
||||
#define RH_GET_STATUS 0x0080
|
||||
#define RH_CLEAR_FEATURE 0x0100
|
||||
#define RH_SET_FEATURE 0x0300
|
||||
#define RH_SET_ADDRESS 0x0500
|
||||
#define RH_GET_DESCRIPTOR 0x0680
|
||||
#define RH_SET_DESCRIPTOR 0x0700
|
||||
#define RH_GET_CONFIGURATION 0x0880
|
||||
#define RH_SET_CONFIGURATION 0x0900
|
||||
#define RH_GET_STATE 0x0280
|
||||
#define RH_GET_INTERFACE 0x0A80
|
||||
#define RH_SET_INTERFACE 0x0B00
|
||||
#define RH_SYNC_FRAME 0x0C80
|
||||
/* Our Vendor Specific Request */
|
||||
#define RH_SET_EP 0x2000
|
||||
|
||||
/* Hub port features */
|
||||
#define RH_PORT_CONNECTION 0x00
|
||||
#define RH_PORT_ENABLE 0x01
|
||||
#define RH_PORT_SUSPEND 0x02
|
||||
#define RH_PORT_OVER_CURRENT 0x03
|
||||
#define RH_PORT_RESET 0x04
|
||||
#define RH_PORT_POWER 0x08
|
||||
#define RH_PORT_LOW_SPEED 0x09
|
||||
#define RH_C_PORT_CONNECTION 0x10
|
||||
#define RH_C_PORT_ENABLE 0x11
|
||||
#define RH_C_PORT_SUSPEND 0x12
|
||||
#define RH_C_PORT_OVER_CURRENT 0x13
|
||||
#define RH_C_PORT_RESET 0x14
|
||||
|
||||
/* Hub features */
|
||||
#define RH_C_HUB_LOCAL_POWER 0x00
|
||||
#define RH_C_HUB_OVER_CURRENT 0x01
|
||||
|
||||
#define RH_DEVICE_REMOTE_WAKEUP 0x00
|
||||
#define RH_ENDPOINT_STALL 0x01
|
||||
|
||||
/* Our Vendor Specific feature */
|
||||
#define RH_REMOVE_EP 0x00
|
||||
|
||||
#define RH_ACK 0x01
|
||||
#define RH_REQ_ERR -1
|
||||
#define RH_NACK 0x00
|
||||
|
||||
/* Transfer descriptor structure */
|
||||
typedef struct {
|
||||
unsigned long link; /* next td/qh (LE) */
|
||||
unsigned long status; /* status of the td */
|
||||
unsigned long info; /* Max Lenght / Endpoint / device address and PID */
|
||||
unsigned long buffer; /* pointer to data buffer (LE) */
|
||||
unsigned long dev_ptr; /* pointer to the assigned device (BE) */
|
||||
unsigned long res[3]; /* reserved (TDs must be 8Byte aligned) */
|
||||
} uhci_td_t, *puhci_td_t;
|
||||
|
||||
/* Queue Header structure */
|
||||
typedef struct {
|
||||
unsigned long head; /* Next QH (LE) */
|
||||
unsigned long element; /* Queue element pointer (LE) */
|
||||
unsigned long res[5]; /* reserved */
|
||||
unsigned long dev_ptr; /* if 0 no tds have been assigned to this qh */
|
||||
} uhci_qh_t, *puhci_qh_t;
|
||||
|
||||
struct virt_root_hub {
|
||||
int devnum; /* Address of Root Hub endpoint */
|
||||
int numports; /* number of ports */
|
||||
int c_p_r[8]; /* C_PORT_RESET */
|
||||
};
|
||||
|
||||
#endif /* _USB_UHCI_H_ */
|
||||
142
u-boot/arch/sparc/cpu/u-boot.lds
Normal file
142
u-boot/arch/sparc/cpu/u-boot.lds
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* (C) Copyright 2007-2008
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT("elf32-sparc", "elf32-sparc", "elf32-sparc")
|
||||
OUTPUT_ARCH(sparc)
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
/* Read-only sections, merged into text segment: */
|
||||
. = + SIZEOF_HEADERS;
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.rel.text : { *(.rel.text) }
|
||||
.rela.text : { *(.rela.text) }
|
||||
.rel.data : { *(.rel.data) }
|
||||
.rela.data : { *(.rela.data) }
|
||||
.rel.rodata : { *(.rel.rodata) }
|
||||
.rela.rodata : { *(.rela.rodata) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.bss : { *(.rel.bss) }
|
||||
.rela.bss : { *(.rela.bss) }
|
||||
.rel.plt : { *(.rel.plt) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
.init : { *(.init) }
|
||||
.plt : { *(.plt) }
|
||||
|
||||
.text : {
|
||||
_load_addr = .;
|
||||
_text = .;
|
||||
|
||||
*(.start)
|
||||
*/start.o (.text)
|
||||
/* 8k is the same as the PROM offset from end of main memory, (CONFIG_SYS_PROM_SIZE) */
|
||||
. = ALIGN(8192);
|
||||
/* PROM CODE, Will be relocated to the end of memory,
|
||||
* no global data accesses please.
|
||||
*/
|
||||
__prom_start = .;
|
||||
*(.prom.pgt)
|
||||
*(.prom.data)
|
||||
*(.prom.text)
|
||||
. = ALIGN(16);
|
||||
__prom_end = .;
|
||||
*(.text)
|
||||
*(.fixup)
|
||||
*(.gnu.warning)
|
||||
/* *(.got1)*/
|
||||
. = ALIGN(16);
|
||||
*(.eh_frame)
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
|
||||
}
|
||||
. = ALIGN(4);
|
||||
_etext = .;
|
||||
|
||||
/* CMD Table */
|
||||
|
||||
|
||||
. = ALIGN(4);
|
||||
.u_boot_list : {
|
||||
KEEP(*(SORT(.u_boot_list*)));
|
||||
}
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
*(.data1)
|
||||
*(.data.rel)
|
||||
*(.data.rel.*)
|
||||
*(.sdata)
|
||||
*(.sdata2)
|
||||
*(.dynamic)
|
||||
CONSTRUCTORS
|
||||
}
|
||||
_edata = .;
|
||||
PROVIDE (edata = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
__got_start = .;
|
||||
.got : {
|
||||
*(.got)
|
||||
/* *(.data.rel)
|
||||
*(.data.rel.local)*/
|
||||
. = ALIGN(16);
|
||||
}
|
||||
__got_end = .;
|
||||
|
||||
/* .data.rel : { } */
|
||||
|
||||
|
||||
. = ALIGN(4096);
|
||||
__init_begin = .;
|
||||
.text.init : { *(.text.init) }
|
||||
.data.init : { *(.data.init) }
|
||||
. = ALIGN(4096);
|
||||
__init_end = .;
|
||||
|
||||
__bss_start = .;
|
||||
.bss :
|
||||
{
|
||||
*(.sbss) *(.scommon)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
. = ALIGN(16); /* to speed clearing of bss up */
|
||||
}
|
||||
__bss_end = . ;
|
||||
__bss_end = . ;
|
||||
PROVIDE (end = .);
|
||||
|
||||
/* Relocated into main memory */
|
||||
|
||||
/* Start of main memory */
|
||||
/*. = 0x40000000;*/
|
||||
|
||||
.stack (NOLOAD) : { *(.stack) }
|
||||
|
||||
/* PROM CODE */
|
||||
|
||||
/* global data in RAM passed to kernel after booting */
|
||||
|
||||
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
|
||||
}
|
||||
19
u-boot/arch/sparc/include/asm/arch-leon2/asi.h
Normal file
19
u-boot/arch/sparc/include/asm/arch-leon2/asi.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/* asi.h: Address Space Identifier values for the LEON2 sparc.
|
||||
*
|
||||
* Copyright (C) 2008 Daniel Hellstrom (daniel@gaisler.com)
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _LEON2_ASI_H
|
||||
#define _LEON2_ASI_H
|
||||
|
||||
#define ASI_CACHEMISS 0x01 /* Force D-Cache miss on load (lda) */
|
||||
#define ASI_M_FLUSH_PROBE 0x03 /* MMU Flush/Probe */
|
||||
#define ASI_IFLUSH 0x05 /* Flush I-Cache */
|
||||
#define ASI_DFLUSH 0x06 /* Flush D-Cache */
|
||||
#define ASI_BYPASS 0x1c /* Bypass MMU (Physical address) */
|
||||
#define ASI_MMUFLUSH 0x18 /* FLUSH TLB */
|
||||
#define ASI_M_MMUREGS 0x19 /* READ/Write MMU Registers */
|
||||
|
||||
#endif /* _LEON2_ASI_H */
|
||||
19
u-boot/arch/sparc/include/asm/arch-leon3/asi.h
Normal file
19
u-boot/arch/sparc/include/asm/arch-leon3/asi.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/* asi.h: Address Space Identifier values for the LEON3 sparc.
|
||||
*
|
||||
* Copyright (C) 2008 Daniel Hellstrom (daniel@gaisler.com)
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _LEON3_ASI_H
|
||||
#define _LEON3_ASI_H
|
||||
|
||||
#define ASI_CACHEMISS 0x01 /* Force D-Cache miss on load (lda) */
|
||||
#define ASI_M_FLUSH_PROBE 0x03 /* MMU Flush/Probe */
|
||||
#define ASI_IFLUSH 0x10 /* Flush I-Cache */
|
||||
#define ASI_DFLUSH 0x11 /* Flush D-Cache */
|
||||
#define ASI_BYPASS 0x1c /* Bypass MMU (Physical address) */
|
||||
#define ASI_MMUFLUSH 0x18 /* FLUSH TLB */
|
||||
#define ASI_M_MMUREGS 0x19 /* READ/Write MMU Registers */
|
||||
|
||||
#endif /* _LEON3_ASI_H */
|
||||
15
u-boot/arch/sparc/include/asm/asi.h
Normal file
15
u-boot/arch/sparc/include/asm/asi.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/* Address Space Identifier (ASI) values for sparc processors.
|
||||
*
|
||||
* (C) Copyright 2008
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _SPARC_ASI_H
|
||||
#define _SPARC_ASI_H
|
||||
|
||||
/* ASI numbers are processor implementation specific */
|
||||
#include <asm/arch/asi.h>
|
||||
|
||||
#endif /* _SPARC_ASI_H */
|
||||
28
u-boot/arch/sparc/include/asm/asmmacro.h
Normal file
28
u-boot/arch/sparc/include/asm/asmmacro.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/* Assembler macros for SPARC
|
||||
*
|
||||
* (C) Copyright 2007, taken from linux asm-sparc/asmmacro.h
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __SPARC_ASMMACRO_H__
|
||||
#define __SPARC_ASMMACRO_H__
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* All trap entry points _must_ begin with this macro or else you
|
||||
* lose. It makes sure the kernel has a proper window so that
|
||||
* c-code can be called.
|
||||
*/
|
||||
#define SAVE_ALL_HEAD \
|
||||
sethi %hi(trap_setup+(CONFIG_SYS_RELOC_MONITOR_BASE-CONFIG_SYS_TEXT_BASE)), %l4; \
|
||||
jmpl %l4 + %lo(trap_setup+(CONFIG_SYS_RELOC_MONITOR_BASE-CONFIG_SYS_TEXT_BASE)), %l6;
|
||||
#define SAVE_ALL \
|
||||
SAVE_ALL_HEAD \
|
||||
nop;
|
||||
|
||||
/* All traps low-level code here must end with this macro. */
|
||||
#define RESTORE_ALL b ret_trap_entry; clr %l6;
|
||||
|
||||
#endif
|
||||
12
u-boot/arch/sparc/include/asm/atomic.h
Normal file
12
u-boot/arch/sparc/include/asm/atomic.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/* SPARC atomic operations
|
||||
*
|
||||
* (C) Copyright 2008
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _ASM_SPARC_ATOMIC_H_
|
||||
#define _ASM_SPARC_ATOMIC_H_
|
||||
|
||||
#endif /* _ASM_SPARC_ATOMIC_H_ */
|
||||
17
u-boot/arch/sparc/include/asm/bitops.h
Normal file
17
u-boot/arch/sparc/include/asm/bitops.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/* Bit string operations on the SPARC
|
||||
*
|
||||
* (C) Copyright 2007, taken from asm-ppc/bitops.h
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _SPARC_BITOPS_H
|
||||
#define _SPARC_BITOPS_H
|
||||
|
||||
#include <asm-generic/bitops/fls.h>
|
||||
#include <asm-generic/bitops/__fls.h>
|
||||
#include <asm-generic/bitops/fls64.h>
|
||||
#include <asm-generic/bitops/__ffs.h>
|
||||
|
||||
#endif /* _SPARC_BITOPS_H */
|
||||
21
u-boot/arch/sparc/include/asm/byteorder.h
Normal file
21
u-boot/arch/sparc/include/asm/byteorder.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2008
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _SPARC_BYTEORDER_H
|
||||
#define _SPARC_BYTEORDER_H
|
||||
|
||||
#include <asm/types.h>
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
#define __BYTEORDER_HAS_U64__
|
||||
#define __SWAB_64_THRU_32__
|
||||
#endif
|
||||
#include <linux/byteorder/big_endian.h>
|
||||
#endif /* _SPARC_BYTEORDER_H */
|
||||
23
u-boot/arch/sparc/include/asm/cache.h
Normal file
23
u-boot/arch/sparc/include/asm/cache.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* (C) Copyright 2008,
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __SPARC_CACHE_H__
|
||||
#define __SPARC_CACHE_H__
|
||||
|
||||
#include <asm/processor.h>
|
||||
|
||||
/*
|
||||
* If CONFIG_SYS_CACHELINE_SIZE is defined use it for DMA alignment. Otherwise
|
||||
* use 32-bytes, the cacheline size for Sparc.
|
||||
*/
|
||||
#ifdef CONFIG_SYS_CACHELINE_SIZE
|
||||
#define ARCH_DMA_MINALIGN CONFIG_SYS_CACHELINE_SIZE
|
||||
#else
|
||||
#define ARCH_DMA_MINALIGN 32
|
||||
#endif
|
||||
|
||||
#endif
|
||||
21
u-boot/arch/sparc/include/asm/config.h
Normal file
21
u-boot/arch/sparc/include/asm/config.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2015,
|
||||
* Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _ASM_CONFIG_H_
|
||||
#define _ASM_CONFIG_H_
|
||||
|
||||
#define CONFIG_SYS_GENERIC_GLOBAL_DATA
|
||||
#define CONFIG_NEEDS_MANUAL_RELOC
|
||||
|
||||
#define CONFIG_LMB
|
||||
#define CONFIG_SYS_BOOT_RAMDISK_HIGH
|
||||
|
||||
#define CONFIG_SYS_TIMER_RATE 1000000 /* 1MHz */
|
||||
#define CONFIG_SYS_TIMER_COUNTER gd->arch.timer
|
||||
#define CONFIG_SYS_TIMER_COUNTS_DOWN
|
||||
|
||||
#endif
|
||||
1
u-boot/arch/sparc/include/asm/errno.h
Normal file
1
u-boot/arch/sparc/include/asm/errno.h
Normal file
@@ -0,0 +1 @@
|
||||
#include <asm-generic/errno.h>
|
||||
30
u-boot/arch/sparc/include/asm/global_data.h
Normal file
30
u-boot/arch/sparc/include/asm/global_data.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* (C) Copyright 2002-2010
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2007, 2015
|
||||
* Daniel Hellstrom, Cobham, Gaisler, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __ASM_GBL_DATA_H
|
||||
#define __ASM_GBL_DATA_H
|
||||
|
||||
#include "asm/types.h"
|
||||
|
||||
/* Architecture-specific global data */
|
||||
struct arch_global_data {
|
||||
void *timer;
|
||||
void *uart;
|
||||
unsigned int uart_freq;
|
||||
#ifdef CONFIG_LEON3
|
||||
unsigned int snooping_available;
|
||||
#endif
|
||||
};
|
||||
|
||||
#include <asm-generic/global_data.h>
|
||||
|
||||
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("%g7")
|
||||
|
||||
#endif /* __ASM_GBL_DATA_H */
|
||||
96
u-boot/arch/sparc/include/asm/io.h
Normal file
96
u-boot/arch/sparc/include/asm/io.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/* SPARC I/O definitions
|
||||
*
|
||||
* (C) Copyright 2007, 2015
|
||||
* Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _SPARC_IO_H
|
||||
#define _SPARC_IO_H
|
||||
|
||||
/* Nothing to sync, total store ordering (TSO)... */
|
||||
#define sync()
|
||||
|
||||
/*
|
||||
* Generic virtual read/write.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_SYS_HAS_NO_CACHE
|
||||
|
||||
/* Forces a cache miss on read/load.
|
||||
* On some architectures we need to bypass the cache when reading
|
||||
* I/O registers so that we are not reading the same status word
|
||||
* over and over again resulting in a hang (until an IRQ if lucky)
|
||||
*/
|
||||
|
||||
#define __arch_getb(a) SPARC_NOCACHE_READ_BYTE((unsigned int)(a))
|
||||
#define __arch_getw(a) SPARC_NOCACHE_READ_HWORD((unsigned int)(a))
|
||||
#define __arch_getl(a) SPARC_NOCACHE_READ((unsigned int)(a))
|
||||
#define __arch_getq(a) SPARC_NOCACHE_READ_DWORD((unsigned int)(a))
|
||||
|
||||
#else
|
||||
|
||||
#define __arch_getb(a) (*(volatile unsigned char *)(a))
|
||||
#define __arch_getw(a) (*(volatile unsigned short *)(a))
|
||||
#define __arch_getl(a) (*(volatile unsigned int *)(a))
|
||||
#define __arch_getq(a) (*(volatile unsigned long long *)(a))
|
||||
|
||||
#endif /* CONFIG_SYS_HAS_NO_CACHE */
|
||||
|
||||
#define __arch_putb(v, a) (*(volatile unsigned char *)(a) = (v))
|
||||
#define __arch_putw(v, a) (*(volatile unsigned short *)(a) = (v))
|
||||
#define __arch_putl(v, a) (*(volatile unsigned int *)(a) = (v))
|
||||
#define __arch_putq(v, a) (*(volatile unsigned long long *)(a) = (v))
|
||||
|
||||
#define __raw_writeb(v, a) __arch_putb(v, a)
|
||||
#define __raw_writew(v, a) __arch_putw(v, a)
|
||||
#define __raw_writel(v, a) __arch_putl(v, a)
|
||||
#define __raw_writeq(v, a) __arch_putq(v, a)
|
||||
|
||||
#define __raw_readb(a) __arch_getb(a)
|
||||
#define __raw_readw(a) __arch_getw(a)
|
||||
#define __raw_readl(a) __arch_getl(a)
|
||||
#define __raw_readq(a) __arch_getq(a)
|
||||
|
||||
#define writeb __raw_writeb
|
||||
#define writew __raw_writew
|
||||
#define writel __raw_writel
|
||||
#define writeq __raw_writeq
|
||||
|
||||
#define readb __raw_readb
|
||||
#define readw __raw_readw
|
||||
#define readl __raw_readl
|
||||
#define readq __raw_readq
|
||||
|
||||
/*
|
||||
* Given a physical address and a length, return a virtual address
|
||||
* that can be used to access the memory range with the caching
|
||||
* properties specified by "flags".
|
||||
*/
|
||||
|
||||
#define MAP_NOCACHE (0)
|
||||
#define MAP_WRCOMBINE (0)
|
||||
#define MAP_WRBACK (0)
|
||||
#define MAP_WRTHROUGH (0)
|
||||
|
||||
static inline void *map_physmem(phys_addr_t paddr, unsigned long len,
|
||||
unsigned long flags)
|
||||
{
|
||||
return (void *)paddr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take down a mapping set up by map_physmem().
|
||||
*/
|
||||
static inline void unmap_physmem(void *vaddr, unsigned long flags)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static inline phys_addr_t virt_to_phys(void * vaddr)
|
||||
{
|
||||
return (phys_addr_t)(vaddr);
|
||||
}
|
||||
|
||||
#endif
|
||||
38
u-boot/arch/sparc/include/asm/irq.h
Normal file
38
u-boot/arch/sparc/include/asm/irq.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* IRQ functions
|
||||
*
|
||||
* (C) Copyright 2007
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __SPARC_IRQ_H__
|
||||
#define __SPARC_IRQ_H__
|
||||
|
||||
#include <asm/psr.h>
|
||||
|
||||
/* Set SPARC Processor Interrupt Level */
|
||||
static inline void set_pil(unsigned int level)
|
||||
{
|
||||
unsigned int psr = get_psr();
|
||||
|
||||
put_psr((psr & ~PSR_PIL) | ((level & 0xf) << PSR_PIL_OFS));
|
||||
}
|
||||
|
||||
/* Get SPARC Processor Interrupt Level */
|
||||
static inline unsigned int get_pil(void)
|
||||
{
|
||||
unsigned int psr = get_psr();
|
||||
return (psr & PSR_PIL) >> PSR_PIL_OFS;
|
||||
}
|
||||
|
||||
/* Disables interrupts and return current PIL value */
|
||||
extern int intLock(void);
|
||||
|
||||
/* Sets the PIL to oldLevel */
|
||||
extern void intUnlock(int oldLevel);
|
||||
|
||||
/* Return non-zero if interrupts are currently enabled */
|
||||
extern int interrupt_is_enabled(void);
|
||||
|
||||
#endif
|
||||
28
u-boot/arch/sparc/include/asm/leon.h
Normal file
28
u-boot/arch/sparc/include/asm/leon.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/* LEON Header File select
|
||||
*
|
||||
* (C) Copyright 2007
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __ASM_LEON_H__
|
||||
#define __ASM_LEON_H__
|
||||
|
||||
#if defined(CONFIG_LEON3)
|
||||
|
||||
#include <asm/leon3.h>
|
||||
|
||||
#elif defined(CONFIG_LEON2)
|
||||
|
||||
#include <asm/leon2.h>
|
||||
|
||||
#else
|
||||
|
||||
#error Unknown LEON processor
|
||||
|
||||
#endif
|
||||
|
||||
/* Common stuff */
|
||||
|
||||
#endif
|
||||
222
u-boot/arch/sparc/include/asm/leon2.h
Normal file
222
u-boot/arch/sparc/include/asm/leon2.h
Normal file
@@ -0,0 +1,222 @@
|
||||
/* LEON2 header file. LEON2 is a SOC processor.
|
||||
*
|
||||
* (C) Copyright 2008
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __LEON2_H__
|
||||
#define __LEON2_H__
|
||||
|
||||
#ifdef CONFIG_LEON2
|
||||
|
||||
/* LEON 2 I/O register definitions */
|
||||
#define LEON2_PREGS 0x80000000
|
||||
#define LEON2_MCFG1 0x00
|
||||
#define LEON2_MCFG2 0x04
|
||||
#define LEON2_ECTRL 0x08
|
||||
#define LEON2_FADDR 0x0C
|
||||
#define LEON2_MSTAT 0x10
|
||||
#define LEON2_CCTRL 0x14
|
||||
#define LEON2_PWDOWN 0x18
|
||||
#define LEON2_WPROT1 0x1C
|
||||
#define LEON2_WPROT2 0x20
|
||||
#define LEON2_LCONF 0x24
|
||||
#define LEON2_TCNT0 0x40
|
||||
#define LEON2_TRLD0 0x44
|
||||
#define LEON2_TCTRL0 0x48
|
||||
#define LEON2_TCNT1 0x50
|
||||
#define LEON2_TRLD1 0x54
|
||||
#define LEON2_TCTRL1 0x58
|
||||
#define LEON2_SCNT 0x60
|
||||
#define LEON2_SRLD 0x64
|
||||
#define LEON2_UART0 0x70
|
||||
#define LEON2_UDATA0 0x70
|
||||
#define LEON2_USTAT0 0x74
|
||||
#define LEON2_UCTRL0 0x78
|
||||
#define LEON2_USCAL0 0x7C
|
||||
#define LEON2_UART1 0x80
|
||||
#define LEON2_UDATA1 0x80
|
||||
#define LEON2_USTAT1 0x84
|
||||
#define LEON2_UCTRL1 0x88
|
||||
#define LEON2_USCAL1 0x8C
|
||||
#define LEON2_IMASK 0x90
|
||||
#define LEON2_IPEND 0x94
|
||||
#define LEON2_IFORCE 0x98
|
||||
#define LEON2_ICLEAR 0x9C
|
||||
#define LEON2_IOREG 0xA0
|
||||
#define LEON2_IODIR 0xA4
|
||||
#define LEON2_IOICONF 0xA8
|
||||
#define LEON2_IPEND2 0xB0
|
||||
#define LEON2_IMASK2 0xB4
|
||||
#define LEON2_ISTAT2 0xB8
|
||||
#define LEON2_ICLEAR2 0xBC
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
/*
|
||||
* Structure for LEON memory mapped registers.
|
||||
*
|
||||
* Source: Section 6.1 - On-chip registers
|
||||
*
|
||||
* NOTE: There is only one of these structures per CPU, its base address
|
||||
* is 0x80000000, and the variable LEON_REG is placed there by the
|
||||
* linkcmds file.
|
||||
*/
|
||||
typedef struct {
|
||||
volatile unsigned int Memory_Config_1;
|
||||
volatile unsigned int Memory_Config_2;
|
||||
volatile unsigned int Edac_Control;
|
||||
volatile unsigned int Failed_Address;
|
||||
volatile unsigned int Memory_Status;
|
||||
volatile unsigned int Cache_Control;
|
||||
volatile unsigned int Power_Down;
|
||||
volatile unsigned int Write_Protection_1;
|
||||
volatile unsigned int Write_Protection_2;
|
||||
volatile unsigned int Leon_Configuration;
|
||||
volatile unsigned int dummy2;
|
||||
volatile unsigned int dummy3;
|
||||
volatile unsigned int dummy4;
|
||||
volatile unsigned int dummy5;
|
||||
volatile unsigned int dummy6;
|
||||
volatile unsigned int dummy7;
|
||||
volatile unsigned int Timer_Counter_1;
|
||||
volatile unsigned int Timer_Reload_1;
|
||||
volatile unsigned int Timer_Control_1;
|
||||
volatile unsigned int Watchdog;
|
||||
volatile unsigned int Timer_Counter_2;
|
||||
volatile unsigned int Timer_Reload_2;
|
||||
volatile unsigned int Timer_Control_2;
|
||||
volatile unsigned int dummy8;
|
||||
volatile unsigned int Scaler_Counter;
|
||||
volatile unsigned int Scaler_Reload;
|
||||
volatile unsigned int dummy9;
|
||||
volatile unsigned int dummy10;
|
||||
volatile unsigned int UART_Channel_1;
|
||||
volatile unsigned int UART_Status_1;
|
||||
volatile unsigned int UART_Control_1;
|
||||
volatile unsigned int UART_Scaler_1;
|
||||
volatile unsigned int UART_Channel_2;
|
||||
volatile unsigned int UART_Status_2;
|
||||
volatile unsigned int UART_Control_2;
|
||||
volatile unsigned int UART_Scaler_2;
|
||||
volatile unsigned int Interrupt_Mask;
|
||||
volatile unsigned int Interrupt_Pending;
|
||||
volatile unsigned int Interrupt_Force;
|
||||
volatile unsigned int Interrupt_Clear;
|
||||
volatile unsigned int PIO_Data;
|
||||
volatile unsigned int PIO_Direction;
|
||||
volatile unsigned int PIO_Interrupt;
|
||||
} LEON2_regs;
|
||||
|
||||
typedef struct {
|
||||
volatile unsigned int UART_Channel;
|
||||
volatile unsigned int UART_Status;
|
||||
volatile unsigned int UART_Control;
|
||||
volatile unsigned int UART_Scaler;
|
||||
} LEON2_Uart_regs;
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following constants are intended to be used ONLY in assembly
|
||||
* language files.
|
||||
*
|
||||
* NOTE: The intended style of usage is to load the address of LEON REGS
|
||||
* into a register and then use these as displacements from
|
||||
* that register.
|
||||
*/
|
||||
#define LEON_REG_MEMCFG1_OFFSET 0x00
|
||||
#define LEON_REG_MEMCFG2_OFFSET 0x04
|
||||
#define LEON_REG_EDACCTRL_OFFSET 0x08
|
||||
#define LEON_REG_FAILADDR_OFFSET 0x0C
|
||||
#define LEON_REG_MEMSTATUS_OFFSET 0x10
|
||||
#define LEON_REG_CACHECTRL_OFFSET 0x14
|
||||
#define LEON_REG_POWERDOWN_OFFSET 0x18
|
||||
#define LEON_REG_WRITEPROT1_OFFSET 0x1C
|
||||
#define LEON_REG_WRITEPROT2_OFFSET 0x20
|
||||
#define LEON_REG_LEONCONF_OFFSET 0x24
|
||||
#define LEON_REG_UNIMPLEMENTED_2_OFFSET 0x28
|
||||
#define LEON_REG_UNIMPLEMENTED_3_OFFSET 0x2C
|
||||
#define LEON_REG_UNIMPLEMENTED_4_OFFSET 0x30
|
||||
#define LEON_REG_UNIMPLEMENTED_5_OFFSET 0x34
|
||||
#define LEON_REG_UNIMPLEMENTED_6_OFFSET 0x38
|
||||
#define LEON_REG_UNIMPLEMENTED_7_OFFSET 0x3C
|
||||
#define LEON_REG_TIMERCNT1_OFFSET 0x40
|
||||
#define LEON_REG_TIMERLOAD1_OFFSET 0x44
|
||||
#define LEON_REG_TIMERCTRL1_OFFSET 0x48
|
||||
#define LEON_REG_WDOG_OFFSET 0x4C
|
||||
#define LEON_REG_TIMERCNT2_OFFSET 0x50
|
||||
#define LEON_REG_TIMERLOAD2_OFFSET 0x54
|
||||
#define LEON_REG_TIMERCTRL2_OFFSET 0x58
|
||||
#define LEON_REG_UNIMPLEMENTED_8_OFFSET 0x5C
|
||||
#define LEON_REG_SCALERCNT_OFFSET 0x60
|
||||
#define LEON_REG_SCALER_LOAD_OFFSET 0x64
|
||||
#define LEON_REG_UNIMPLEMENTED_9_OFFSET 0x68
|
||||
#define LEON_REG_UNIMPLEMENTED_10_OFFSET 0x6C
|
||||
#define LEON_REG_UARTDATA1_OFFSET 0x70
|
||||
#define LEON_REG_UARTSTATUS1_OFFSET 0x74
|
||||
#define LEON_REG_UARTCTRL1_OFFSET 0x78
|
||||
#define LEON_REG_UARTSCALER1_OFFSET 0x7C
|
||||
#define LEON_REG_UARTDATA2_OFFSET 0x80
|
||||
#define LEON_REG_UARTSTATUS2_OFFSET 0x84
|
||||
#define LEON_REG_UARTCTRL2_OFFSET 0x88
|
||||
#define LEON_REG_UARTSCALER2_OFFSET 0x8C
|
||||
#define LEON_REG_IRQMASK_OFFSET 0x90
|
||||
#define LEON_REG_IRQPEND_OFFSET 0x94
|
||||
#define LEON_REG_IRQFORCE_OFFSET 0x98
|
||||
#define LEON_REG_IRQCLEAR_OFFSET 0x9C
|
||||
#define LEON_REG_PIODATA_OFFSET 0xA0
|
||||
#define LEON_REG_PIODIR_OFFSET 0xA4
|
||||
#define LEON_REG_PIOIRQ_OFFSET 0xA8
|
||||
#define LEON_REG_SIM_RAM_SIZE_OFFSET 0xF4
|
||||
#define LEON_REG_SIM_ROM_SIZE_OFFSET 0xF8
|
||||
|
||||
/*
|
||||
* Interrupt Sources
|
||||
*
|
||||
* The interrupt source numbers directly map to the trap type and to
|
||||
* the bits used in the Interrupt Clear, Interrupt Force, Interrupt Mask,
|
||||
* and the Interrupt Pending Registers.
|
||||
*/
|
||||
#define LEON_INTERRUPT_CORRECTABLE_MEMORY_ERROR 1
|
||||
#define LEON_INTERRUPT_UART_1_RX_TX 2
|
||||
#define LEON_INTERRUPT_UART_0_RX_TX 3
|
||||
#define LEON_INTERRUPT_EXTERNAL_0 4
|
||||
#define LEON_INTERRUPT_EXTERNAL_1 5
|
||||
#define LEON_INTERRUPT_EXTERNAL_2 6
|
||||
#define LEON_INTERRUPT_EXTERNAL_3 7
|
||||
#define LEON_INTERRUPT_TIMER1 8
|
||||
#define LEON_INTERRUPT_TIMER2 9
|
||||
#define LEON_INTERRUPT_EMPTY1 10
|
||||
#define LEON_INTERRUPT_EMPTY2 11
|
||||
#define LEON_INTERRUPT_OPEN_ETH 12
|
||||
#define LEON_INTERRUPT_EMPTY4 13
|
||||
#define LEON_INTERRUPT_EMPTY5 14
|
||||
#define LEON_INTERRUPT_EMPTY6 15
|
||||
|
||||
/* Timer Bits */
|
||||
#define LEON2_TIMER_CTRL_EN 0x1 /* Timer enable */
|
||||
#define LEON2_TIMER_CTRL_RS 0x2 /* Timer reStart */
|
||||
#define LEON2_TIMER_CTRL_LD 0x4 /* Timer reLoad */
|
||||
#define LEON2_TIMER1_IRQNO 8 /* Timer 1 IRQ number */
|
||||
#define LEON2_TIMER2_IRQNO 9 /* Timer 2 IRQ number */
|
||||
#define LEON2_TIMER1_IE (1<<LEON2_TIMER1_IRQNO) /* Timer 1 interrupt enable */
|
||||
#define LEON2_TIMER2_IE (1<<LEON2_TIMER2_IRQNO) /* Timer 2 interrupt enable */
|
||||
|
||||
/* UART bits */
|
||||
#define LEON2_UART_CTRL_RE 1 /* UART Receiver enable */
|
||||
#define LEON2_UART_CTRL_TE 2 /* UART Transmitter enable */
|
||||
#define LEON2_UART_CTRL_RI 4 /* UART Receiver Interrupt enable */
|
||||
#define LEON2_UART_CTRL_TI 8 /* UART Transmitter Interrupt enable */
|
||||
#define LEON2_UART_CTRL_DBG (1<<11) /* Debug Bit used by GRMON */
|
||||
|
||||
#define LEON2_UART_STAT_DR 1 /* UART Data Ready */
|
||||
#define LEON2_UART_STAT_TSE 2 /* UART Transmit Shift Reg empty */
|
||||
#define LEON2_UART_STAT_THE 4 /* UART Transmit Hold Reg empty */
|
||||
|
||||
#else
|
||||
#error Include LEON2 header file only if LEON2 processor
|
||||
#endif
|
||||
|
||||
#endif
|
||||
35
u-boot/arch/sparc/include/asm/leon3.h
Normal file
35
u-boot/arch/sparc/include/asm/leon3.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/* LEON3 header file. LEON3 is a free GPL SOC processor available
|
||||
* at www.gaisler.com.
|
||||
*
|
||||
* (C) Copyright 2007
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __LEON3_H__
|
||||
#define __LEON3_H__
|
||||
|
||||
#ifndef CONFIG_LEON3
|
||||
#error Include LEON3 header file only if LEON3 processor
|
||||
#endif
|
||||
|
||||
/* Not much to define, most is Plug and Play and GRLIB dependent
|
||||
* not LEON3 dependent. See <ambapp.h> for GRLIB timers, interrupt
|
||||
* ctrl, memory controllers etc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
/* The frequency of the CPU */
|
||||
extern unsigned int leon_cpu_freq;
|
||||
|
||||
/* Number of LEON processors in system */
|
||||
extern int leon_cpu_cnt;
|
||||
|
||||
/* Ver/subversion of CPU */
|
||||
extern int leon_ver;
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#endif
|
||||
78
u-boot/arch/sparc/include/asm/machines.h
Normal file
78
u-boot/arch/sparc/include/asm/machines.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* machines.h: Defines for taking apart the machine type value in the
|
||||
* idprom and determining the kind of machine we are on.
|
||||
*
|
||||
* Taken from the SPARC port of Linux.
|
||||
*
|
||||
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
|
||||
* Copyright (C) 2007 Daniel Hellstrom (daniel@gaisler.com)
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __SPARC_MACHINES_H__
|
||||
#define __SPARC_MACHINES_H__
|
||||
|
||||
struct Sun_Machine_Models {
|
||||
char *name;
|
||||
unsigned char id_machtype;
|
||||
};
|
||||
|
||||
/* Current number of machines we know about that has an IDPROM
|
||||
* machtype entry including one entry for the 0x80 OBP machines.
|
||||
*/
|
||||
#define NUM_SUN_MACHINES 16
|
||||
|
||||
extern struct Sun_Machine_Models Sun_Machines[NUM_SUN_MACHINES];
|
||||
|
||||
/* The machine type in the idprom area looks like this:
|
||||
*
|
||||
* ---------------
|
||||
* | ARCH | MACH |
|
||||
* ---------------
|
||||
* 7 4 3 0
|
||||
*
|
||||
* The ARCH field determines the architecture line (sun4, sun4c, etc).
|
||||
* The MACH field determines the machine make within that architecture.
|
||||
*/
|
||||
|
||||
#define SM_ARCH_MASK 0xf0
|
||||
#define SM_SUN4 0x20
|
||||
#define M_LEON2 0x30
|
||||
#define SM_SUN4C 0x50
|
||||
#define SM_SUN4M 0x70
|
||||
#define SM_SUN4M_OBP 0x80
|
||||
|
||||
#define SM_TYP_MASK 0x0f
|
||||
/* Sun4 machines */
|
||||
#define SM_4_260 0x01 /* Sun 4/200 series */
|
||||
#define SM_4_110 0x02 /* Sun 4/100 series */
|
||||
#define SM_4_330 0x03 /* Sun 4/300 series */
|
||||
#define SM_4_470 0x04 /* Sun 4/400 series */
|
||||
|
||||
/* Leon machines */
|
||||
#define M_LEON2_SOC 0x01 /* Leon2 SoC */
|
||||
|
||||
/* Sun4c machines Full Name - PROM NAME */
|
||||
#define SM_4C_SS1 0x01 /* Sun4c SparcStation 1 - Sun 4/60 */
|
||||
#define SM_4C_IPC 0x02 /* Sun4c SparcStation IPC - Sun 4/40 */
|
||||
#define SM_4C_SS1PLUS 0x03 /* Sun4c SparcStation 1+ - Sun 4/65 */
|
||||
#define SM_4C_SLC 0x04 /* Sun4c SparcStation SLC - Sun 4/20 */
|
||||
#define SM_4C_SS2 0x05 /* Sun4c SparcStation 2 - Sun 4/75 */
|
||||
#define SM_4C_ELC 0x06 /* Sun4c SparcStation ELC - Sun 4/25 */
|
||||
#define SM_4C_IPX 0x07 /* Sun4c SparcStation IPX - Sun 4/50 */
|
||||
|
||||
/* Sun4m machines, these predate the OpenBoot. These values only mean
|
||||
* something if the value in the ARCH field is SM_SUN4M, if it is
|
||||
* SM_SUN4M_OBP then you have the following situation:
|
||||
* 1) You either have a sun4d, a sun4e, or a recently made sun4m.
|
||||
* 2) You have to consult OpenBoot to determine which machine this is.
|
||||
*/
|
||||
#define SM_4M_SS60 0x01 /* Sun4m SparcSystem 600 */
|
||||
#define SM_4M_SS50 0x02 /* Sun4m SparcStation 10 */
|
||||
#define SM_4M_SS40 0x03 /* Sun4m SparcStation 5 */
|
||||
|
||||
/* Sun4d machines -- N/A */
|
||||
/* Sun4e machines -- N/A */
|
||||
/* Sun4u machines -- N/A */
|
||||
|
||||
#endif /* !(_SPARC_MACHINES_H) */
|
||||
28
u-boot/arch/sparc/include/asm/page.h
Normal file
28
u-boot/arch/sparc/include/asm/page.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/* page.h: Various defines and such for MMU operations on the Sparc for
|
||||
* the Linux kernel.
|
||||
*
|
||||
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
|
||||
* Copyright (C) 2007 Daniel Hellstrom (daniel@gaisler.com)
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _SPARC_PAGE_H
|
||||
#define _SPARC_PAGE_H
|
||||
|
||||
#ifdef CONFIG_SUN4
|
||||
#define PAGE_SHIFT 13
|
||||
#else
|
||||
#define PAGE_SHIFT 12
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
/* I have my suspicions... -DaveM */
|
||||
#define PAGE_SIZE (1UL << PAGE_SHIFT)
|
||||
#else
|
||||
#define PAGE_SIZE (1 << PAGE_SHIFT)
|
||||
#endif
|
||||
|
||||
#define PAGE_MASK (~(PAGE_SIZE-1))
|
||||
|
||||
#endif /* _SPARC_PAGE_H */
|
||||
125
u-boot/arch/sparc/include/asm/posix_types.h
Normal file
125
u-boot/arch/sparc/include/asm/posix_types.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* (C) Copyright 2000 - 2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2007, taken from asm-ppc/posix_types.h
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __SPARC_POSIX_TYPES_H__
|
||||
#define __SPARC_POSIX_TYPES_H__
|
||||
|
||||
/*
|
||||
* This file is generally used by user-level software, so you need to
|
||||
* be a little careful about namespace pollution etc. Also, we cannot
|
||||
* assume GCC is being used.
|
||||
*/
|
||||
|
||||
typedef unsigned int __kernel_dev_t;
|
||||
typedef unsigned int __kernel_ino_t;
|
||||
typedef unsigned int __kernel_mode_t;
|
||||
typedef unsigned short __kernel_nlink_t;
|
||||
typedef long __kernel_off_t;
|
||||
typedef int __kernel_pid_t;
|
||||
typedef unsigned int __kernel_uid_t;
|
||||
typedef unsigned int __kernel_gid_t;
|
||||
typedef unsigned int __kernel_size_t;
|
||||
typedef int __kernel_ssize_t;
|
||||
typedef long __kernel_ptrdiff_t;
|
||||
typedef long __kernel_time_t;
|
||||
typedef long __kernel_suseconds_t;
|
||||
typedef long __kernel_clock_t;
|
||||
typedef int __kernel_daddr_t;
|
||||
typedef char *__kernel_caddr_t;
|
||||
typedef short __kernel_ipc_pid_t;
|
||||
typedef unsigned short __kernel_uid16_t;
|
||||
typedef unsigned short __kernel_gid16_t;
|
||||
typedef unsigned int __kernel_uid32_t;
|
||||
typedef unsigned int __kernel_gid32_t;
|
||||
|
||||
typedef unsigned int __kernel_old_uid_t;
|
||||
typedef unsigned int __kernel_old_gid_t;
|
||||
|
||||
#ifdef __GNUC__
|
||||
typedef long long __kernel_loff_t;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int val[2];
|
||||
} __kernel_fsid_t;
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
|
||||
#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
|
||||
#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
|
||||
#define __FD_ZERO(set) \
|
||||
((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set)))
|
||||
|
||||
#else /* __GNUC__ */
|
||||
|
||||
#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) \
|
||||
|| (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
|
||||
/* With GNU C, use inline functions instead so args are evaluated only once: */
|
||||
|
||||
#undef __FD_SET
|
||||
static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set * fdsetp)
|
||||
{
|
||||
unsigned long _tmp = fd / __NFDBITS;
|
||||
unsigned long _rem = fd % __NFDBITS;
|
||||
fdsetp->fds_bits[_tmp] |= (1UL << _rem);
|
||||
}
|
||||
|
||||
#undef __FD_CLR
|
||||
static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set * fdsetp)
|
||||
{
|
||||
unsigned long _tmp = fd / __NFDBITS;
|
||||
unsigned long _rem = fd % __NFDBITS;
|
||||
fdsetp->fds_bits[_tmp] &= ~(1UL << _rem);
|
||||
}
|
||||
|
||||
#undef __FD_ISSET
|
||||
static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set * p)
|
||||
{
|
||||
unsigned long _tmp = fd / __NFDBITS;
|
||||
unsigned long _rem = fd % __NFDBITS;
|
||||
return (p->fds_bits[_tmp] & (1UL << _rem)) != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This will unroll the loop for the normal constant case (8 ints,
|
||||
* for a 256-bit fd_set)
|
||||
*/
|
||||
#undef __FD_ZERO
|
||||
static __inline__ void __FD_ZERO(__kernel_fd_set * p)
|
||||
{
|
||||
unsigned int *tmp = (unsigned int *)p->fds_bits;
|
||||
int i;
|
||||
|
||||
if (__builtin_constant_p(__FDSET_LONGS)) {
|
||||
switch (__FDSET_LONGS) {
|
||||
case 8:
|
||||
tmp[0] = 0;
|
||||
tmp[1] = 0;
|
||||
tmp[2] = 0;
|
||||
tmp[3] = 0;
|
||||
tmp[4] = 0;
|
||||
tmp[5] = 0;
|
||||
tmp[6] = 0;
|
||||
tmp[7] = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
i = __FDSET_LONGS;
|
||||
while (i) {
|
||||
i--;
|
||||
*tmp = 0;
|
||||
tmp++;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
|
||||
#endif /* __GNUC__ */
|
||||
#endif /* _SPARC_POSIX_TYPES_H */
|
||||
102
u-boot/arch/sparc/include/asm/processor.h
Normal file
102
u-boot/arch/sparc/include/asm/processor.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/* SPARC Processor specifics
|
||||
* taken from the SPARC port of Linux (ptrace.h).
|
||||
*
|
||||
* (C) Copyright 2007
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __ASM_SPARC_PROCESSOR_H
|
||||
#define __ASM_SPARC_PROCESSOR_H
|
||||
|
||||
#include <asm/arch/asi.h>
|
||||
|
||||
#ifdef CONFIG_LEON
|
||||
|
||||
/* All LEON processors supported */
|
||||
#include <asm/leon.h>
|
||||
|
||||
#else
|
||||
/* other processors */
|
||||
#error Unknown SPARC Processor
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/* flush data cache */
|
||||
static __inline__ void sparc_dcache_flush_all(void)
|
||||
{
|
||||
__asm__ __volatile__("sta %%g0, [%%g0] %0\n\t"::"i"(ASI_DFLUSH):"memory");
|
||||
}
|
||||
|
||||
/* flush instruction cache */
|
||||
static __inline__ void sparc_icache_flush_all(void)
|
||||
{
|
||||
__asm__ __volatile__("sta %%g0, [%%g0] %0\n\t"::"i"(ASI_IFLUSH):"memory");
|
||||
}
|
||||
|
||||
/* do a cache miss load */
|
||||
static __inline__ unsigned long long sparc_load_reg_cachemiss_qword(unsigned
|
||||
long paddr)
|
||||
{
|
||||
unsigned long long retval;
|
||||
__asm__ __volatile__("ldda [%1] %2, %0\n\t":
|
||||
"=r"(retval):"r"(paddr), "i"(ASI_CACHEMISS));
|
||||
return retval;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long sparc_load_reg_cachemiss(unsigned long paddr)
|
||||
{
|
||||
unsigned long retval;
|
||||
__asm__ __volatile__("lda [%1] %2, %0\n\t":
|
||||
"=r"(retval):"r"(paddr), "i"(ASI_CACHEMISS));
|
||||
return retval;
|
||||
}
|
||||
|
||||
static __inline__ unsigned short sparc_load_reg_cachemiss_word(unsigned long
|
||||
paddr)
|
||||
{
|
||||
unsigned short retval;
|
||||
__asm__ __volatile__("lduha [%1] %2, %0\n\t":
|
||||
"=r"(retval):"r"(paddr), "i"(ASI_CACHEMISS));
|
||||
return retval;
|
||||
}
|
||||
|
||||
static __inline__ unsigned char sparc_load_reg_cachemiss_byte(unsigned long
|
||||
paddr)
|
||||
{
|
||||
unsigned char retval;
|
||||
__asm__ __volatile__("lduba [%1] %2, %0\n\t":
|
||||
"=r"(retval):"r"(paddr), "i"(ASI_CACHEMISS));
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* do a physical address bypass write, i.e. for 0x80000000 */
|
||||
static __inline__ void sparc_store_reg_bypass(unsigned long paddr,
|
||||
unsigned long value)
|
||||
{
|
||||
__asm__ __volatile__("sta %0, [%1] %2\n\t"::"r"(value), "r"(paddr),
|
||||
"i"(ASI_BYPASS):"memory");
|
||||
}
|
||||
|
||||
static __inline__ unsigned long sparc_load_reg_bypass(unsigned long paddr)
|
||||
{
|
||||
unsigned long retval;
|
||||
__asm__ __volatile__("lda [%1] %2, %0\n\t":
|
||||
"=r"(retval):"r"(paddr), "i"(ASI_BYPASS));
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Macros for bypassing cache when reading */
|
||||
#define SPARC_NOCACHE_READ_DWORD(address) sparc_load_reg_cachemiss_qword((unsigned int)(address))
|
||||
#define SPARC_NOCACHE_READ(address) sparc_load_reg_cachemiss((unsigned int)(address))
|
||||
#define SPARC_NOCACHE_READ_HWORD(address) sparc_load_reg_cachemiss_word((unsigned int)(address))
|
||||
#define SPARC_NOCACHE_READ_BYTE(address) sparc_load_reg_cachemiss_byte((unsigned int)(address))
|
||||
|
||||
#define SPARC_BYPASS_READ(address) sparc_load_reg_bypass((unsigned int)(address))
|
||||
#define SPARC_BYPASS_WRITE(address,value) sparc_store_reg_bypass((unsigned int)(address),(unsigned int)(value))
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_SPARC_PROCESSOR_H */
|
||||
283
u-boot/arch/sparc/include/asm/prom.h
Normal file
283
u-boot/arch/sparc/include/asm/prom.h
Normal file
@@ -0,0 +1,283 @@
|
||||
/* OpenProm defines mainly taken from linux kernel header files
|
||||
*
|
||||
* openprom.h: Prom structures and defines for access to the OPENBOOT
|
||||
* prom routines and data areas.
|
||||
*
|
||||
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
|
||||
* Copyright (C) 2007 Daniel Hellstrom (daniel@gaisler.com)
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __SPARC_OPENPROM_H__
|
||||
#define __SPARC_OPENPROM_H__
|
||||
|
||||
/* Empirical constants... */
|
||||
#define LINUX_OPPROM_MAGIC 0x10010407
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
/* V0 prom device operations. */
|
||||
struct linux_dev_v0_funcs {
|
||||
int (*v0_devopen) (char *device_str);
|
||||
int (*v0_devclose) (int dev_desc);
|
||||
int (*v0_rdblkdev) (int dev_desc, int num_blks, int blk_st, char *buf);
|
||||
int (*v0_wrblkdev) (int dev_desc, int num_blks, int blk_st, char *buf);
|
||||
int (*v0_wrnetdev) (int dev_desc, int num_bytes, char *buf);
|
||||
int (*v0_rdnetdev) (int dev_desc, int num_bytes, char *buf);
|
||||
int (*v0_rdchardev) (int dev_desc, int num_bytes, int dummy, char *buf);
|
||||
int (*v0_wrchardev) (int dev_desc, int num_bytes, int dummy, char *buf);
|
||||
int (*v0_seekdev) (int dev_desc, long logical_offst, int from);
|
||||
};
|
||||
|
||||
/* V2 and later prom device operations. */
|
||||
struct linux_dev_v2_funcs {
|
||||
int (*v2_inst2pkg) (int d); /* Convert ihandle to phandle */
|
||||
char *(*v2_dumb_mem_alloc) (char *va, unsigned sz);
|
||||
void (*v2_dumb_mem_free) (char *va, unsigned sz);
|
||||
|
||||
/* To map devices into virtual I/O space. */
|
||||
char *(*v2_dumb_mmap) (char *virta, int which_io, unsigned paddr,
|
||||
unsigned sz);
|
||||
void (*v2_dumb_munmap) (char *virta, unsigned size);
|
||||
|
||||
int (*v2_dev_open) (char *devpath);
|
||||
void (*v2_dev_close) (int d);
|
||||
int (*v2_dev_read) (int d, char *buf, int nbytes);
|
||||
int (*v2_dev_write) (int d, char *buf, int nbytes);
|
||||
int (*v2_dev_seek) (int d, int hi, int lo);
|
||||
|
||||
/* Never issued (multistage load support) */
|
||||
void (*v2_wheee2) (void);
|
||||
void (*v2_wheee3) (void);
|
||||
};
|
||||
|
||||
struct linux_mlist_v0 {
|
||||
struct linux_mlist_v0 *theres_more;
|
||||
char *start_adr;
|
||||
unsigned num_bytes;
|
||||
};
|
||||
|
||||
struct linux_mem_v0 {
|
||||
struct linux_mlist_v0 **v0_totphys;
|
||||
struct linux_mlist_v0 **v0_prommap;
|
||||
struct linux_mlist_v0 **v0_available; /* What we can use */
|
||||
};
|
||||
|
||||
/* Arguments sent to the kernel from the boot prompt. */
|
||||
struct linux_arguments_v0 {
|
||||
char * const argv[8];
|
||||
char args[100];
|
||||
char boot_dev[2];
|
||||
int boot_dev_ctrl;
|
||||
int boot_dev_unit;
|
||||
int dev_partition;
|
||||
char *kernel_file_name;
|
||||
void *aieee1; /* XXX */
|
||||
};
|
||||
|
||||
/* V2 and up boot things. */
|
||||
struct linux_bootargs_v2 {
|
||||
char **bootpath;
|
||||
char **bootargs;
|
||||
int *fd_stdin;
|
||||
int *fd_stdout;
|
||||
};
|
||||
|
||||
/* The top level PROM vector. */
|
||||
struct linux_romvec {
|
||||
/* Version numbers. */
|
||||
unsigned int pv_magic_cookie;
|
||||
unsigned int pv_romvers;
|
||||
unsigned int pv_plugin_revision;
|
||||
unsigned int pv_printrev;
|
||||
|
||||
/* Version 0 memory descriptors. */
|
||||
struct linux_mem_v0 pv_v0mem;
|
||||
|
||||
/* Node operations. */
|
||||
struct linux_nodeops *pv_nodeops;
|
||||
|
||||
char **pv_bootstr;
|
||||
struct linux_dev_v0_funcs pv_v0devops;
|
||||
|
||||
char *pv_stdin;
|
||||
char *pv_stdout;
|
||||
#define PROMDEV_KBD 0 /* input from keyboard */
|
||||
#define PROMDEV_SCREEN 0 /* output to screen */
|
||||
#define PROMDEV_TTYA 1 /* in/out to ttya */
|
||||
#define PROMDEV_TTYB 2 /* in/out to ttyb */
|
||||
|
||||
/* Blocking getchar/putchar. NOT REENTRANT! (grr) */
|
||||
int (*pv_getchar) (void);
|
||||
void (*pv_putchar) (int ch);
|
||||
|
||||
/* Non-blocking variants. */
|
||||
int (*pv_nbgetchar) (void);
|
||||
int (*pv_nbputchar) (int ch);
|
||||
|
||||
void (*pv_putstr) (char *str, int len);
|
||||
|
||||
/* Miscellany. */
|
||||
void (*pv_reboot) (char *bootstr);
|
||||
void (*pv_printf) (__const__ char *fmt, ...);
|
||||
void (*pv_abort) (void);
|
||||
__volatile__ int *pv_ticks;
|
||||
void (*pv_halt) (void);
|
||||
void (**pv_synchook) (void);
|
||||
|
||||
/* Evaluate a forth string, not different proto for V0 and V2->up. */
|
||||
union {
|
||||
void (*v0_eval) (int len, char *str);
|
||||
void (*v2_eval) (char *str);
|
||||
} pv_fortheval;
|
||||
|
||||
struct linux_arguments_v0 **pv_v0bootargs;
|
||||
|
||||
/* Get ether address. */
|
||||
unsigned int (*pv_enaddr) (int d, char *enaddr);
|
||||
|
||||
struct linux_bootargs_v2 pv_v2bootargs;
|
||||
struct linux_dev_v2_funcs pv_v2devops;
|
||||
|
||||
int filler[15];
|
||||
|
||||
/* This one is sun4c/sun4 only. */
|
||||
void (*pv_setctxt) (int ctxt, char *va, int pmeg);
|
||||
|
||||
/* Prom version 3 Multiprocessor routines. This stuff is crazy.
|
||||
* No joke. Calling these when there is only one cpu probably
|
||||
* crashes the machine, have to test this. :-)
|
||||
*/
|
||||
|
||||
/* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
|
||||
* 'thiscontext' executing at address 'prog_counter'
|
||||
*/
|
||||
int (*v3_cpustart) (unsigned int whichcpu, int ctxtbl_ptr,
|
||||
int thiscontext, char *prog_counter);
|
||||
|
||||
/* v3_cpustop() will cause cpu 'whichcpu' to stop executing
|
||||
* until a resume cpu call is made.
|
||||
*/
|
||||
int (*v3_cpustop) (unsigned int whichcpu);
|
||||
|
||||
/* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
|
||||
* resume cpu call is made.
|
||||
*/
|
||||
int (*v3_cpuidle) (unsigned int whichcpu);
|
||||
|
||||
/* v3_cpuresume() will resume processor 'whichcpu' executing
|
||||
* starting with whatever 'pc' and 'npc' were left at the
|
||||
* last 'idle' or 'stop' call.
|
||||
*/
|
||||
int (*v3_cpuresume) (unsigned int whichcpu);
|
||||
};
|
||||
|
||||
/* Routines for traversing the prom device tree. */
|
||||
struct linux_nodeops {
|
||||
int (*no_nextnode) (int node);
|
||||
int (*no_child) (int node);
|
||||
int (*no_proplen) (int node, char *name);
|
||||
int (*no_getprop) (int node, char *name, char *val);
|
||||
int (*no_setprop) (int node, char *name, char *val, int len);
|
||||
char *(*no_nextprop) (int node, char *name);
|
||||
};
|
||||
|
||||
/* More fun PROM structures for device probing. */
|
||||
#define PROMREG_MAX 16
|
||||
#define PROMVADDR_MAX 16
|
||||
#define PROMINTR_MAX 15
|
||||
|
||||
struct linux_prom_registers {
|
||||
unsigned int which_io; /* is this in OBIO space? */
|
||||
unsigned int phys_addr; /* The physical address of this register */
|
||||
unsigned int reg_size; /* How many bytes does this register take up? */
|
||||
};
|
||||
|
||||
struct linux_prom_irqs {
|
||||
int pri; /* IRQ priority */
|
||||
int vector; /* This is foobar, what does it do? */
|
||||
};
|
||||
|
||||
/* Element of the "ranges" vector */
|
||||
struct linux_prom_ranges {
|
||||
unsigned int ot_child_space;
|
||||
unsigned int ot_child_base; /* Bus feels this */
|
||||
unsigned int ot_parent_space;
|
||||
unsigned int ot_parent_base; /* CPU looks from here */
|
||||
unsigned int or_size;
|
||||
};
|
||||
|
||||
/* Ranges and reg properties are a bit different for PCI. */
|
||||
struct linux_prom_pci_registers {
|
||||
/*
|
||||
* We don't know what information this field contain.
|
||||
* We guess, PCI device function is in bits 15:8
|
||||
* So, ...
|
||||
*/
|
||||
unsigned int which_io; /* Let it be which_io */
|
||||
|
||||
unsigned int phys_hi;
|
||||
unsigned int phys_lo;
|
||||
|
||||
unsigned int size_hi;
|
||||
unsigned int size_lo;
|
||||
};
|
||||
|
||||
struct linux_prom_pci_ranges {
|
||||
unsigned int child_phys_hi; /* Only certain bits are encoded here. */
|
||||
unsigned int child_phys_mid;
|
||||
unsigned int child_phys_lo;
|
||||
|
||||
unsigned int parent_phys_hi;
|
||||
unsigned int parent_phys_lo;
|
||||
|
||||
unsigned int size_hi;
|
||||
unsigned int size_lo;
|
||||
};
|
||||
|
||||
struct linux_prom_pci_assigned_addresses {
|
||||
unsigned int which_io;
|
||||
|
||||
unsigned int phys_hi;
|
||||
unsigned int phys_lo;
|
||||
|
||||
unsigned int size_hi;
|
||||
unsigned int size_lo;
|
||||
};
|
||||
|
||||
struct linux_prom_ebus_ranges {
|
||||
unsigned int child_phys_hi;
|
||||
unsigned int child_phys_lo;
|
||||
|
||||
unsigned int parent_phys_hi;
|
||||
unsigned int parent_phys_mid;
|
||||
unsigned int parent_phys_lo;
|
||||
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
/* Offset into the EEPROM where the id PROM is located on the 4c */
|
||||
#define IDPROM_OFFSET 0x7d8
|
||||
|
||||
/* On sun4m; physical. */
|
||||
/* MicroSPARC(-II) does not decode 31rd bit, but it works. */
|
||||
#define IDPROM_OFFSET_M 0xfd8
|
||||
|
||||
struct idprom {
|
||||
unsigned char id_format; /* Format identifier (always 0x01) */
|
||||
unsigned char id_machtype; /* Machine type */
|
||||
unsigned char id_ethaddr[6]; /* Hardware ethernet address */
|
||||
long id_date; /* Date of manufacture */
|
||||
unsigned int id_sernum:24; /* Unique serial number */
|
||||
unsigned char id_cksum; /* Checksum - xor of the data bytes */
|
||||
unsigned char reserved[16];
|
||||
};
|
||||
|
||||
extern struct idprom *idprom;
|
||||
extern void idprom_init(void);
|
||||
|
||||
#define IDPROM_SIZE (sizeof(struct idprom))
|
||||
|
||||
#endif /* !(__ASSEMBLY__) */
|
||||
|
||||
#endif
|
||||
83
u-boot/arch/sparc/include/asm/psr.h
Normal file
83
u-boot/arch/sparc/include/asm/psr.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/* psr.h: This file holds the macros for masking off various parts of
|
||||
* the processor status register on the Sparc. This is valid
|
||||
* for Version 8. On the V9 this is renamed to the PSTATE
|
||||
* register and its members are accessed as fields like
|
||||
* PSTATE.PRIV for the current CPU privilege level.
|
||||
*
|
||||
* taken from the SPARC port of Linux,
|
||||
*
|
||||
* Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
|
||||
* Copyright (C) 2007 Daniel Hellstrom (daniel@gaisler.com)
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __SPARC_PSR_H__
|
||||
#define __SPARC_PSR_H__
|
||||
|
||||
/* The Sparc PSR fields are laid out as the following:
|
||||
*
|
||||
* ------------------------------------------------------------------------
|
||||
* | impl | vers | icc | resv | EC | EF | PIL | S | PS | ET | CWP |
|
||||
* | 31-28 | 27-24 | 23-20 | 19-14 | 13 | 12 | 11-8 | 7 | 6 | 5 | 4-0 |
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
#define PSR_CWP 0x0000001f /* current window pointer */
|
||||
#define PSR_ET 0x00000020 /* enable traps field */
|
||||
#define PSR_PS 0x00000040 /* previous privilege level */
|
||||
#define PSR_S 0x00000080 /* current privilege level */
|
||||
#define PSR_PIL 0x00000f00 /* processor interrupt level */
|
||||
#define PSR_EF 0x00001000 /* enable floating point */
|
||||
#define PSR_EC 0x00002000 /* enable co-processor */
|
||||
#define PSR_LE 0x00008000 /* SuperSparcII little-endian */
|
||||
#define PSR_ICC 0x00f00000 /* integer condition codes */
|
||||
#define PSR_C 0x00100000 /* carry bit */
|
||||
#define PSR_V 0x00200000 /* overflow bit */
|
||||
#define PSR_Z 0x00400000 /* zero bit */
|
||||
#define PSR_N 0x00800000 /* negative bit */
|
||||
#define PSR_VERS 0x0f000000 /* cpu-version field */
|
||||
#define PSR_IMPL 0xf0000000 /* cpu-implementation field */
|
||||
|
||||
#define PSR_PIL_OFS 8
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
/* Get the %psr register. */
|
||||
static __inline__ unsigned int get_psr(void)
|
||||
{
|
||||
unsigned int psr;
|
||||
__asm__ __volatile__("rd %%psr, %0\n\t"
|
||||
"nop\n\t" "nop\n\t" "nop\n\t":"=r"(psr)
|
||||
: /* no inputs */
|
||||
:"memory");
|
||||
|
||||
return psr;
|
||||
}
|
||||
|
||||
static __inline__ void put_psr(unsigned int new_psr)
|
||||
{
|
||||
__asm__ __volatile__("wr %0, 0x0, %%psr\n\t" "nop\n\t" "nop\n\t" "nop\n\t": /* no outputs */
|
||||
:"r"(new_psr)
|
||||
:"memory", "cc");
|
||||
}
|
||||
|
||||
/* Get the %fsr register. Be careful, make sure the floating point
|
||||
* enable bit is set in the %psr when you execute this or you will
|
||||
* incur a trap.
|
||||
*/
|
||||
|
||||
extern unsigned int fsr_storage;
|
||||
|
||||
static __inline__ unsigned int get_fsr(void)
|
||||
{
|
||||
unsigned int fsr = 0;
|
||||
|
||||
__asm__ __volatile__("st %%fsr, %1\n\t"
|
||||
"ld %1, %0\n\t":"=r"(fsr)
|
||||
:"m"(fsr_storage));
|
||||
|
||||
return fsr;
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLY__) */
|
||||
|
||||
#endif /* !(__SPARC_PSR_H__) */
|
||||
167
u-boot/arch/sparc/include/asm/ptrace.h
Normal file
167
u-boot/arch/sparc/include/asm/ptrace.h
Normal file
@@ -0,0 +1,167 @@
|
||||
/* Contain the Stack frame layout on interrupt. pt_regs.
|
||||
* taken from the SPARC port of Linux (ptrace.h).
|
||||
*
|
||||
* (C) Copyright 2007
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __SPARC_PTRACE_H__
|
||||
#define __SPARC_PTRACE_H__
|
||||
|
||||
#include <asm/psr.h>
|
||||
|
||||
/* This struct defines the way the registers are stored on the
|
||||
* stack during a system call and basically all traps.
|
||||
*/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
struct pt_regs {
|
||||
unsigned long psr;
|
||||
unsigned long pc;
|
||||
unsigned long npc;
|
||||
unsigned long y;
|
||||
unsigned long u_regs[16]; /* globals and ins */
|
||||
};
|
||||
|
||||
#define UREG_G0 0
|
||||
#define UREG_G1 1
|
||||
#define UREG_G2 2
|
||||
#define UREG_G3 3
|
||||
#define UREG_G4 4
|
||||
#define UREG_G5 5
|
||||
#define UREG_G6 6
|
||||
#define UREG_G7 7
|
||||
#define UREG_I0 8
|
||||
#define UREG_I1 9
|
||||
#define UREG_I2 10
|
||||
#define UREG_I3 11
|
||||
#define UREG_I4 12
|
||||
#define UREG_I5 13
|
||||
#define UREG_I6 14
|
||||
#define UREG_I7 15
|
||||
#define UREG_WIM UREG_G0
|
||||
#define UREG_FADDR UREG_G0
|
||||
#define UREG_FP UREG_I6
|
||||
#define UREG_RETPC UREG_I7
|
||||
|
||||
/* A register window */
|
||||
struct reg_window {
|
||||
unsigned long locals[8];
|
||||
unsigned long ins[8];
|
||||
};
|
||||
|
||||
/* A Sparc stack frame */
|
||||
struct sparc_stackf {
|
||||
unsigned long locals[8];
|
||||
unsigned long ins[6];
|
||||
struct sparc_stackf *fp;
|
||||
unsigned long callers_pc;
|
||||
char *structptr;
|
||||
unsigned long xargs[6];
|
||||
unsigned long xxargs[1];
|
||||
};
|
||||
|
||||
#define TRACEREG_SZ sizeof(struct pt_regs)
|
||||
#define STACKFRAME_SZ sizeof(struct sparc_stackf)
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
/* For assembly code. */
|
||||
#define TRACEREG_SZ 0x50
|
||||
#define STACKFRAME_SZ 0x60
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The asm_offsets.h is a generated file, so we cannot include it.
|
||||
* It may be OK for glibc headers, but it's utterly pointless for C code.
|
||||
* The assembly code using those offsets has to include it explicitly.
|
||||
*/
|
||||
/* #include <asm/asm_offsets.h> */
|
||||
|
||||
/* These are for pt_regs. */
|
||||
#define PT_PSR 0x0
|
||||
#define PT_PC 0x4
|
||||
#define PT_NPC 0x8
|
||||
#define PT_Y 0xc
|
||||
#define PT_G0 0x10
|
||||
#define PT_WIM PT_G0
|
||||
#define PT_G1 0x14
|
||||
#define PT_G2 0x18
|
||||
#define PT_G3 0x1c
|
||||
#define PT_G4 0x20
|
||||
#define PT_G5 0x24
|
||||
#define PT_G6 0x28
|
||||
#define PT_G7 0x2c
|
||||
#define PT_I0 0x30
|
||||
#define PT_I1 0x34
|
||||
#define PT_I2 0x38
|
||||
#define PT_I3 0x3c
|
||||
#define PT_I4 0x40
|
||||
#define PT_I5 0x44
|
||||
#define PT_I6 0x48
|
||||
#define PT_FP PT_I6
|
||||
#define PT_I7 0x4c
|
||||
|
||||
/* Reg_window offsets */
|
||||
#define RW_L0 0x00
|
||||
#define RW_L1 0x04
|
||||
#define RW_L2 0x08
|
||||
#define RW_L3 0x0c
|
||||
#define RW_L4 0x10
|
||||
#define RW_L5 0x14
|
||||
#define RW_L6 0x18
|
||||
#define RW_L7 0x1c
|
||||
#define RW_I0 0x20
|
||||
#define RW_I1 0x24
|
||||
#define RW_I2 0x28
|
||||
#define RW_I3 0x2c
|
||||
#define RW_I4 0x30
|
||||
#define RW_I5 0x34
|
||||
#define RW_I6 0x38
|
||||
#define RW_I7 0x3c
|
||||
|
||||
/* Stack_frame offsets */
|
||||
#define SF_L0 0x00
|
||||
#define SF_L1 0x04
|
||||
#define SF_L2 0x08
|
||||
#define SF_L3 0x0c
|
||||
#define SF_L4 0x10
|
||||
#define SF_L5 0x14
|
||||
#define SF_L6 0x18
|
||||
#define SF_L7 0x1c
|
||||
#define SF_I0 0x20
|
||||
#define SF_I1 0x24
|
||||
#define SF_I2 0x28
|
||||
#define SF_I3 0x2c
|
||||
#define SF_I4 0x30
|
||||
#define SF_I5 0x34
|
||||
#define SF_FP 0x38
|
||||
#define SF_PC 0x3c
|
||||
#define SF_RETP 0x40
|
||||
#define SF_XARG0 0x44
|
||||
#define SF_XARG1 0x48
|
||||
#define SF_XARG2 0x4c
|
||||
#define SF_XARG3 0x50
|
||||
#define SF_XARG4 0x54
|
||||
#define SF_XARG5 0x58
|
||||
#define SF_XXARG 0x5c
|
||||
|
||||
/* Stuff for the ptrace system call */
|
||||
#define PTRACE_SUNATTACH 10
|
||||
#define PTRACE_SUNDETACH 11
|
||||
#define PTRACE_GETREGS 12
|
||||
#define PTRACE_SETREGS 13
|
||||
#define PTRACE_GETFPREGS 14
|
||||
#define PTRACE_SETFPREGS 15
|
||||
#define PTRACE_READDATA 16
|
||||
#define PTRACE_WRITEDATA 17
|
||||
#define PTRACE_READTEXT 18
|
||||
#define PTRACE_WRITETEXT 19
|
||||
#define PTRACE_GETFPAREGS 20
|
||||
#define PTRACE_SETFPAREGS 21
|
||||
|
||||
#define PTRACE_GETUCODE 29 /* stupid bsd-ism */
|
||||
|
||||
#endif /* !(_SPARC_PTRACE_H) */
|
||||
11
u-boot/arch/sparc/include/asm/sections.h
Normal file
11
u-boot/arch/sparc/include/asm/sections.h
Normal file
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The Chromium OS Authors.
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __ASM_SPARC_SECTIONS_H
|
||||
#define __ASM_SPARC_SECTIONS_H
|
||||
|
||||
#include <asm-generic/sections.h>
|
||||
|
||||
#endif
|
||||
287
u-boot/arch/sparc/include/asm/srmmu.h
Normal file
287
u-boot/arch/sparc/include/asm/srmmu.h
Normal file
@@ -0,0 +1,287 @@
|
||||
/* SRMMU page table defines and code,
|
||||
* taken from the SPARC port of Linux
|
||||
*
|
||||
* Copyright (C) 2007 Daniel Hellstrom (daniel@gaisler.com)
|
||||
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __SPARC_SRMMU_H__
|
||||
#define __SPARC_SRMMU_H__
|
||||
|
||||
#include <asm/asi.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
/* Number of contexts is implementation-dependent; 64k is the most we support */
|
||||
#define SRMMU_MAX_CONTEXTS 65536
|
||||
|
||||
/* PMD_SHIFT determines the size of the area a second-level page table entry can map */
|
||||
#define SRMMU_REAL_PMD_SHIFT 18
|
||||
#define SRMMU_REAL_PMD_SIZE (1UL << SRMMU_REAL_PMD_SHIFT)
|
||||
#define SRMMU_REAL_PMD_MASK (~(SRMMU_REAL_PMD_SIZE-1))
|
||||
#define SRMMU_REAL_PMD_ALIGN(__addr) (((__addr)+SRMMU_REAL_PMD_SIZE-1)&SRMMU_REAL_PMD_MASK)
|
||||
|
||||
/* PGDIR_SHIFT determines what a third-level page table entry can map */
|
||||
#define SRMMU_PGDIR_SHIFT 24
|
||||
#define SRMMU_PGDIR_SIZE (1UL << SRMMU_PGDIR_SHIFT)
|
||||
#define SRMMU_PGDIR_MASK (~(SRMMU_PGDIR_SIZE-1))
|
||||
#define SRMMU_PGDIR_ALIGN(addr) (((addr)+SRMMU_PGDIR_SIZE-1)&SRMMU_PGDIR_MASK)
|
||||
|
||||
#define SRMMU_REAL_PTRS_PER_PTE 64
|
||||
#define SRMMU_REAL_PTRS_PER_PMD 64
|
||||
#define SRMMU_PTRS_PER_PGD 256
|
||||
|
||||
#define SRMMU_REAL_PTE_TABLE_SIZE (SRMMU_REAL_PTRS_PER_PTE*4)
|
||||
#define SRMMU_PMD_TABLE_SIZE (SRMMU_REAL_PTRS_PER_PMD*4)
|
||||
#define SRMMU_PGD_TABLE_SIZE (SRMMU_PTRS_PER_PGD*4)
|
||||
|
||||
/*
|
||||
* To support pagetables in highmem, Linux introduces APIs which
|
||||
* return struct page* and generally manipulate page tables when
|
||||
* they are not mapped into kernel space. Our hardware page tables
|
||||
* are smaller than pages. We lump hardware tabes into big, page sized
|
||||
* software tables.
|
||||
*
|
||||
* PMD_SHIFT determines the size of the area a second-level page table entry
|
||||
* can map, and our pmd_t is 16 times larger than normal. The values which
|
||||
* were once defined here are now generic for 4c and srmmu, so they're
|
||||
* found in pgtable.h.
|
||||
*/
|
||||
#define SRMMU_PTRS_PER_PMD 4
|
||||
|
||||
/* Definition of the values in the ET field of PTD's and PTE's */
|
||||
#define SRMMU_ET_MASK 0x3
|
||||
#define SRMMU_ET_INVALID 0x0
|
||||
#define SRMMU_ET_PTD 0x1
|
||||
#define SRMMU_ET_PTE 0x2
|
||||
#define SRMMU_ET_REPTE 0x3 /* AIEEE, SuperSparc II reverse endian page! */
|
||||
|
||||
/* Physical page extraction from PTP's and PTE's. */
|
||||
#define SRMMU_CTX_PMASK 0xfffffff0
|
||||
#define SRMMU_PTD_PMASK 0xfffffff0
|
||||
#define SRMMU_PTE_PMASK 0xffffff00
|
||||
|
||||
/* The pte non-page bits. Some notes:
|
||||
* 1) cache, dirty, valid, and ref are frobbable
|
||||
* for both supervisor and user pages.
|
||||
* 2) exec and write will only give the desired effect
|
||||
* on user pages
|
||||
* 3) use priv and priv_readonly for changing the
|
||||
* characteristics of supervisor ptes
|
||||
*/
|
||||
#define SRMMU_CACHE 0x80
|
||||
#define SRMMU_DIRTY 0x40
|
||||
#define SRMMU_REF 0x20
|
||||
#define SRMMU_NOREAD 0x10
|
||||
#define SRMMU_EXEC 0x08
|
||||
#define SRMMU_WRITE 0x04
|
||||
#define SRMMU_VALID 0x02 /* SRMMU_ET_PTE */
|
||||
#define SRMMU_PRIV 0x1c
|
||||
#define SRMMU_PRIV_RDONLY 0x18
|
||||
|
||||
#define SRMMU_FILE 0x40 /* Implemented in software */
|
||||
|
||||
#define SRMMU_PTE_FILE_SHIFT 8 /* == 32-PTE_FILE_MAX_BITS */
|
||||
|
||||
#define SRMMU_CHG_MASK (0xffffff00 | SRMMU_REF | SRMMU_DIRTY)
|
||||
|
||||
/* SRMMU swap entry encoding
|
||||
*
|
||||
* We use 5 bits for the type and 19 for the offset. This gives us
|
||||
* 32 swapfiles of 4GB each. Encoding looks like:
|
||||
*
|
||||
* oooooooooooooooooootttttRRRRRRRR
|
||||
* fedcba9876543210fedcba9876543210
|
||||
*
|
||||
* The bottom 8 bits are reserved for protection and status bits, especially
|
||||
* FILE and PRESENT.
|
||||
*/
|
||||
#define SRMMU_SWP_TYPE_MASK 0x1f
|
||||
#define SRMMU_SWP_TYPE_SHIFT SRMMU_PTE_FILE_SHIFT
|
||||
#define SRMMU_SWP_OFF_MASK 0x7ffff
|
||||
#define SRMMU_SWP_OFF_SHIFT (SRMMU_PTE_FILE_SHIFT + 5)
|
||||
|
||||
/* Some day I will implement true fine grained access bits for
|
||||
* user pages because the SRMMU gives us the capabilities to
|
||||
* enforce all the protection levels that vma's can have.
|
||||
* XXX But for now...
|
||||
*/
|
||||
#define SRMMU_PAGE_NONE __pgprot(SRMMU_CACHE | \
|
||||
SRMMU_PRIV | SRMMU_REF)
|
||||
#define SRMMU_PAGE_SHARED __pgprot(SRMMU_VALID | SRMMU_CACHE | \
|
||||
SRMMU_EXEC | SRMMU_WRITE | SRMMU_REF)
|
||||
#define SRMMU_PAGE_COPY __pgprot(SRMMU_VALID | SRMMU_CACHE | \
|
||||
SRMMU_EXEC | SRMMU_REF)
|
||||
#define SRMMU_PAGE_RDONLY __pgprot(SRMMU_VALID | SRMMU_CACHE | \
|
||||
SRMMU_EXEC | SRMMU_REF)
|
||||
#define SRMMU_PAGE_KERNEL __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_PRIV | \
|
||||
SRMMU_DIRTY | SRMMU_REF)
|
||||
|
||||
/* SRMMU Register addresses in ASI 0x4. These are valid for all
|
||||
* current SRMMU implementations that exist.
|
||||
*/
|
||||
#define SRMMU_CTRL_REG 0x00000000
|
||||
#define SRMMU_CTXTBL_PTR 0x00000100
|
||||
#define SRMMU_CTX_REG 0x00000200
|
||||
#define SRMMU_FAULT_STATUS 0x00000300
|
||||
#define SRMMU_FAULT_ADDR 0x00000400
|
||||
|
||||
#define WINDOW_FLUSH(tmp1, tmp2) \
|
||||
mov 0, tmp1; \
|
||||
98: ld [%g6 + TI_UWINMASK], tmp2; \
|
||||
orcc %g0, tmp2, %g0; \
|
||||
add tmp1, 1, tmp1; \
|
||||
bne 98b; \
|
||||
save %sp, -64, %sp; \
|
||||
99: subcc tmp1, 1, tmp1; \
|
||||
bne 99b; \
|
||||
restore %g0, %g0, %g0;
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/* This makes sense. Honest it does - Anton */
|
||||
/* XXX Yes but it's ugly as sin. FIXME. -KMW */
|
||||
extern void *srmmu_nocache_pool;
|
||||
#define __nocache_pa(VADDR) (((unsigned long)VADDR) - SRMMU_NOCACHE_VADDR + __pa((unsigned long)srmmu_nocache_pool))
|
||||
#define __nocache_va(PADDR) (__va((unsigned long)PADDR) - (unsigned long)srmmu_nocache_pool + SRMMU_NOCACHE_VADDR)
|
||||
#define __nocache_fix(VADDR) __va(__nocache_pa(VADDR))
|
||||
|
||||
/* Accessing the MMU control register. */
|
||||
static __inline__ unsigned int srmmu_get_mmureg(void)
|
||||
{
|
||||
unsigned int retval;
|
||||
__asm__ __volatile__("lda [%%g0] %1, %0\n\t":
|
||||
"=r"(retval):"i"(ASI_M_MMUREGS));
|
||||
return retval;
|
||||
}
|
||||
|
||||
static __inline__ void srmmu_set_mmureg(unsigned long regval)
|
||||
{
|
||||
__asm__ __volatile__("sta %0, [%%g0] %1\n\t"::"r"(regval),
|
||||
"i"(ASI_M_MMUREGS):"memory");
|
||||
|
||||
}
|
||||
|
||||
static __inline__ void srmmu_set_ctable_ptr(unsigned long paddr)
|
||||
{
|
||||
paddr = ((paddr >> 4) & SRMMU_CTX_PMASK);
|
||||
__asm__ __volatile__("sta %0, [%1] %2\n\t"::"r"(paddr),
|
||||
"r"(SRMMU_CTXTBL_PTR),
|
||||
"i"(ASI_M_MMUREGS):"memory");
|
||||
}
|
||||
|
||||
static __inline__ unsigned long srmmu_get_ctable_ptr(void)
|
||||
{
|
||||
unsigned int retval;
|
||||
|
||||
__asm__ __volatile__("lda [%1] %2, %0\n\t":
|
||||
"=r"(retval):
|
||||
"r"(SRMMU_CTXTBL_PTR), "i"(ASI_M_MMUREGS));
|
||||
return (retval & SRMMU_CTX_PMASK) << 4;
|
||||
}
|
||||
|
||||
static __inline__ void srmmu_set_context(int context)
|
||||
{
|
||||
__asm__ __volatile__("sta %0, [%1] %2\n\t"::"r"(context),
|
||||
"r"(SRMMU_CTX_REG), "i"(ASI_M_MMUREGS):"memory");
|
||||
}
|
||||
|
||||
static __inline__ int srmmu_get_context(void)
|
||||
{
|
||||
register int retval;
|
||||
__asm__ __volatile__("lda [%1] %2, %0\n\t":
|
||||
"=r"(retval):
|
||||
"r"(SRMMU_CTX_REG), "i"(ASI_M_MMUREGS));
|
||||
return retval;
|
||||
}
|
||||
|
||||
static __inline__ unsigned int srmmu_get_fstatus(void)
|
||||
{
|
||||
unsigned int retval;
|
||||
|
||||
__asm__ __volatile__("lda [%1] %2, %0\n\t":
|
||||
"=r"(retval):
|
||||
"r"(SRMMU_FAULT_STATUS), "i"(ASI_M_MMUREGS));
|
||||
return retval;
|
||||
}
|
||||
|
||||
static __inline__ unsigned int srmmu_get_faddr(void)
|
||||
{
|
||||
unsigned int retval;
|
||||
|
||||
__asm__ __volatile__("lda [%1] %2, %0\n\t":
|
||||
"=r"(retval):
|
||||
"r"(SRMMU_FAULT_ADDR), "i"(ASI_M_MMUREGS));
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* This is guaranteed on all SRMMU's. */
|
||||
static __inline__ void srmmu_flush_whole_tlb(void)
|
||||
{
|
||||
__asm__ __volatile__("sta %%g0, [%0] %1\n\t"::"r"(0x400), /* Flush entire TLB!! */
|
||||
"i"(ASI_M_FLUSH_PROBE):"memory");
|
||||
|
||||
}
|
||||
|
||||
/* These flush types are not available on all chips... */
|
||||
static __inline__ void srmmu_flush_tlb_ctx(void)
|
||||
{
|
||||
__asm__ __volatile__("sta %%g0, [%0] %1\n\t"::"r"(0x300), /* Flush TLB ctx.. */
|
||||
"i"(ASI_M_FLUSH_PROBE):"memory");
|
||||
|
||||
}
|
||||
|
||||
static __inline__ void srmmu_flush_tlb_region(unsigned long addr)
|
||||
{
|
||||
addr &= SRMMU_PGDIR_MASK;
|
||||
__asm__ __volatile__("sta %%g0, [%0] %1\n\t"::"r"(addr | 0x200), /* Flush TLB region.. */
|
||||
"i"(ASI_M_FLUSH_PROBE):"memory");
|
||||
|
||||
}
|
||||
|
||||
static __inline__ void srmmu_flush_tlb_segment(unsigned long addr)
|
||||
{
|
||||
addr &= SRMMU_REAL_PMD_MASK;
|
||||
__asm__ __volatile__("sta %%g0, [%0] %1\n\t"::"r"(addr | 0x100), /* Flush TLB segment.. */
|
||||
"i"(ASI_M_FLUSH_PROBE):"memory");
|
||||
|
||||
}
|
||||
|
||||
static __inline__ void srmmu_flush_tlb_page(unsigned long page)
|
||||
{
|
||||
page &= PAGE_MASK;
|
||||
__asm__ __volatile__("sta %%g0, [%0] %1\n\t"::"r"(page), /* Flush TLB page.. */
|
||||
"i"(ASI_M_FLUSH_PROBE):"memory");
|
||||
|
||||
}
|
||||
|
||||
static __inline__ unsigned long srmmu_hwprobe(unsigned long vaddr)
|
||||
{
|
||||
unsigned long retval;
|
||||
|
||||
vaddr &= PAGE_MASK;
|
||||
__asm__ __volatile__("lda [%1] %2, %0\n\t":
|
||||
"=r"(retval):
|
||||
"r"(vaddr | 0x400), "i"(ASI_M_FLUSH_PROBE));
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static __inline__ int srmmu_get_pte(unsigned long addr)
|
||||
{
|
||||
register unsigned long entry;
|
||||
|
||||
__asm__ __volatile__("\n\tlda [%1] %2,%0\n\t":
|
||||
"=r"(entry):
|
||||
"r"((addr & 0xfffff000) | 0x400),
|
||||
"i"(ASI_M_FLUSH_PROBE));
|
||||
return entry;
|
||||
}
|
||||
|
||||
extern unsigned long (*srmmu_read_physical) (unsigned long paddr);
|
||||
extern void (*srmmu_write_physical) (unsigned long paddr, unsigned long word);
|
||||
|
||||
#endif /* !(__ASSEMBLY__) */
|
||||
|
||||
#endif /* !(__SPARC_SRMMU_H__) */
|
||||
148
u-boot/arch/sparc/include/asm/stack.h
Normal file
148
u-boot/arch/sparc/include/asm/stack.h
Normal file
@@ -0,0 +1,148 @@
|
||||
/* SPARC stack layout Macros and structures,
|
||||
* mainly taken from BCC (the Bare C compiler for
|
||||
* SPARC LEON2/3) sources.
|
||||
*
|
||||
* (C) Copyright 2007
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __SPARC_STACK_H__
|
||||
#define __SPARC_STACK_H__
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PT_REGS_SZ sizeof(struct pt_regs)
|
||||
|
||||
/* A Sparc stack frame */
|
||||
struct sparc_stackframe_regs {
|
||||
unsigned long sf_locals[8];
|
||||
unsigned long sf_ins[6];
|
||||
struct sparc_stackframe_regs *sf_fp;
|
||||
unsigned long sf_callers_pc;
|
||||
char *sf_structptr;
|
||||
unsigned long sf_xargs[6];
|
||||
unsigned long sf_xxargs[1];
|
||||
};
|
||||
#define SF_REGS_SZ sizeof(struct sparc_stackframe_regs)
|
||||
|
||||
/* A register window */
|
||||
struct sparc_regwindow_regs {
|
||||
unsigned long locals[8];
|
||||
unsigned long ins[8];
|
||||
};
|
||||
#define RW_REGS_SZ sizeof(struct sparc_regwindow_regs)
|
||||
|
||||
/* A fpu window */
|
||||
struct sparc_fpuwindow_regs {
|
||||
unsigned long locals[32];
|
||||
unsigned long fsr;
|
||||
unsigned long lastctx;
|
||||
};
|
||||
#define FW_REGS_SZ sizeof(struct sparc_fpuwindow_regs)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
#define PT_REGS_SZ 0x50 /* 20*4 */
|
||||
#define SF_REGS_SZ 0x60 /* 24*4 */
|
||||
#define RW_REGS_SZ 0x20 /* 16*4 */
|
||||
#define FW_REGS_SZ 0x88 /* 34*4 */
|
||||
#endif /* !ASM */
|
||||
|
||||
/* These are for pt_regs. */
|
||||
#define PT_PSR 0x0
|
||||
#define PT_PC 0x4
|
||||
#define PT_NPC 0x8
|
||||
#define PT_Y 0xc
|
||||
#define PT_G0 0x10
|
||||
#define PT_WIM PT_G0
|
||||
#define PT_G1 0x14
|
||||
#define PT_G2 0x18
|
||||
#define PT_G3 0x1c
|
||||
#define PT_G4 0x20
|
||||
#define PT_G5 0x24
|
||||
#define PT_G6 0x28
|
||||
#define PT_G7 0x2c
|
||||
#define PT_I0 0x30
|
||||
#define PT_I1 0x34
|
||||
#define PT_I2 0x38
|
||||
#define PT_I3 0x3c
|
||||
#define PT_I4 0x40
|
||||
#define PT_I5 0x44
|
||||
#define PT_I6 0x48
|
||||
#define PT_FP PT_I6
|
||||
#define PT_I7 0x4c
|
||||
|
||||
/* Stack_frame offsets */
|
||||
#define SF_L0 0x00
|
||||
#define SF_L1 0x04
|
||||
#define SF_L2 0x08
|
||||
#define SF_L3 0x0c
|
||||
#define SF_L4 0x10
|
||||
#define SF_L5 0x14
|
||||
#define SF_L6 0x18
|
||||
#define SF_L7 0x1c
|
||||
#define SF_I0 0x20
|
||||
#define SF_I1 0x24
|
||||
#define SF_I2 0x28
|
||||
#define SF_I3 0x2c
|
||||
#define SF_I4 0x30
|
||||
#define SF_I5 0x34
|
||||
#define SF_FP 0x38
|
||||
#define SF_PC 0x3c
|
||||
#define SF_RETP 0x40
|
||||
#define SF_XARG0 0x44
|
||||
#define SF_XARG1 0x48
|
||||
#define SF_XARG2 0x4c
|
||||
#define SF_XARG3 0x50
|
||||
#define SF_XARG4 0x54
|
||||
#define SF_XARG5 0x58
|
||||
#define SF_XXARG 0x5c
|
||||
|
||||
/* Reg_window offsets */
|
||||
#define RW_L0 0x00
|
||||
#define RW_L1 0x04
|
||||
#define RW_L2 0x08
|
||||
#define RW_L3 0x0c
|
||||
#define RW_L4 0x10
|
||||
#define RW_L5 0x14
|
||||
#define RW_L6 0x18
|
||||
#define RW_L7 0x1c
|
||||
#define RW_I0 0x20
|
||||
#define RW_I1 0x24
|
||||
#define RW_I2 0x28
|
||||
#define RW_I3 0x2c
|
||||
#define RW_I4 0x30
|
||||
#define RW_I5 0x34
|
||||
#define RW_I6 0x38
|
||||
#define RW_I7 0x3c
|
||||
|
||||
/* Fpu_window offsets */
|
||||
#define FW_F0 0x00
|
||||
#define FW_F2 0x08
|
||||
#define FW_F4 0x10
|
||||
#define FW_F6 0x18
|
||||
#define FW_F8 0x20
|
||||
#define FW_F10 0x28
|
||||
#define FW_F12 0x30
|
||||
#define FW_F14 0x38
|
||||
#define FW_F16 0x40
|
||||
#define FW_F18 0x48
|
||||
#define FW_F20 0x50
|
||||
#define FW_F22 0x58
|
||||
#define FW_F24 0x60
|
||||
#define FW_F26 0x68
|
||||
#define FW_F28 0x70
|
||||
#define FW_F30 0x78
|
||||
#define FW_FSR 0x80
|
||||
|
||||
#endif
|
||||
41
u-boot/arch/sparc/include/asm/string.h
Normal file
41
u-boot/arch/sparc/include/asm/string.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* (C) Copyright 2000 - 2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2007
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _SPARC_STRING_H_
|
||||
#define _SPARC_STRING_H_
|
||||
|
||||
/*
|
||||
#define __HAVE_ARCH_STRCPY
|
||||
#define __HAVE_ARCH_STRNCPY
|
||||
#define __HAVE_ARCH_STRLEN
|
||||
#define __HAVE_ARCH_STRCMP
|
||||
#define __HAVE_ARCH_STRCAT
|
||||
#define __HAVE_ARCH_MEMSET
|
||||
#define __HAVE_ARCH_BCOPY
|
||||
#define __HAVE_ARCH_MEMCPY
|
||||
#define __HAVE_ARCH_MEMMOVE
|
||||
#define __HAVE_ARCH_MEMCMP
|
||||
#define __HAVE_ARCH_MEMCHR
|
||||
*/
|
||||
|
||||
extern int strcasecmp(const char *, const char *);
|
||||
extern int strncasecmp(const char *, const char *, __kernel_size_t);
|
||||
extern char *strcpy(char *, const char *);
|
||||
extern char *strncpy(char *, const char *, __kernel_size_t);
|
||||
extern __kernel_size_t strlen(const char *);
|
||||
extern int strcmp(const char *, const char *);
|
||||
extern char *strcat(char *, const char *);
|
||||
extern void *memset(void *, int, __kernel_size_t);
|
||||
extern void *memcpy(void *, const void *, __kernel_size_t);
|
||||
extern void *memmove(void *, const void *, __kernel_size_t);
|
||||
extern int memcmp(const void *, const void *, __kernel_size_t);
|
||||
extern void *memchr(const void *, int, __kernel_size_t);
|
||||
|
||||
#endif
|
||||
60
u-boot/arch/sparc/include/asm/types.h
Normal file
60
u-boot/arch/sparc/include/asm/types.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* (C) Copyright 2000 - 2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _SPARC_TYPES_H
|
||||
#define _SPARC_TYPES_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef unsigned short umode_t;
|
||||
|
||||
typedef __signed__ char __s8;
|
||||
typedef unsigned char __u8;
|
||||
|
||||
typedef __signed__ short __s16;
|
||||
typedef unsigned short __u16;
|
||||
|
||||
typedef __signed__ int __s32;
|
||||
typedef unsigned int __u32;
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
typedef __signed__ long long __s64;
|
||||
typedef unsigned long long __u64;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
__u32 u[4];
|
||||
} __attribute__((aligned(16))) vector128;
|
||||
|
||||
#ifdef __KERNEL__
|
||||
/*
|
||||
* These aren't exported outside the kernel to avoid name space clashes
|
||||
*/
|
||||
typedef signed char s8;
|
||||
typedef unsigned char u8;
|
||||
|
||||
typedef signed short s16;
|
||||
typedef unsigned short u16;
|
||||
|
||||
typedef signed int s32;
|
||||
typedef unsigned int u32;
|
||||
|
||||
typedef signed long long s64;
|
||||
typedef unsigned long long u64;
|
||||
|
||||
#define BITS_PER_LONG 32
|
||||
|
||||
/* DMA addresses are 32-bits wide */
|
||||
typedef u32 dma_addr_t;
|
||||
|
||||
typedef unsigned long phys_addr_t;
|
||||
typedef unsigned long phys_size_t;
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif
|
||||
24
u-boot/arch/sparc/include/asm/u-boot.h
Normal file
24
u-boot/arch/sparc/include/asm/u-boot.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* (C) Copyright 2000 - 2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2007, 2015
|
||||
* Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __U_BOOT_H__
|
||||
#define __U_BOOT_H__
|
||||
|
||||
/* Currently, this board information is not passed to
|
||||
* Linux kernel from U-Boot, but may be passed to other
|
||||
* Operating systems. This is because U-Boot emulates
|
||||
* a SUN PROM loader (from Linux point of view).
|
||||
*/
|
||||
#include <asm-generic/u-boot.h>
|
||||
|
||||
/* For image.h:image_check_target_arch() */
|
||||
#define IH_ARCH_DEFAULT IH_ARCH_SPARC
|
||||
|
||||
#endif
|
||||
10
u-boot/arch/sparc/include/asm/unaligned.h
Normal file
10
u-boot/arch/sparc/include/asm/unaligned.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef _ASM_SPARC_UNALIGNED_H
|
||||
#define _ASM_SPARC_UNALIGNED_H
|
||||
|
||||
/*
|
||||
* The SPARC can not do unaligned accesses, it must be split into multiple
|
||||
* byte accesses. The SPARC is in big endian mode.
|
||||
*/
|
||||
#include <asm-generic/unaligned.h>
|
||||
|
||||
#endif /* _ASM_SPARC_UNALIGNED_H */
|
||||
138
u-boot/arch/sparc/include/asm/winmacro.h
Normal file
138
u-boot/arch/sparc/include/asm/winmacro.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Added to U-Boot,
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com
|
||||
* Copyright (C) 2007
|
||||
*
|
||||
* LEON2/3 LIBIO low-level routines
|
||||
* Written by Jiri Gaisler.
|
||||
* Copyright (C) 2004 Gaisler Research AB
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __SPARC_WINMACRO_H__
|
||||
#define __SPARC_WINMACRO_H__
|
||||
|
||||
#include <asm/asmmacro.h>
|
||||
#include <asm/stack.h>
|
||||
|
||||
/* Store the register window onto the 8-byte aligned area starting
|
||||
* at %reg. It might be %sp, it might not, we don't care.
|
||||
*/
|
||||
#define RW_STORE(reg) \
|
||||
std %l0, [%reg + RW_L0]; \
|
||||
std %l2, [%reg + RW_L2]; \
|
||||
std %l4, [%reg + RW_L4]; \
|
||||
std %l6, [%reg + RW_L6]; \
|
||||
std %i0, [%reg + RW_I0]; \
|
||||
std %i2, [%reg + RW_I2]; \
|
||||
std %i4, [%reg + RW_I4]; \
|
||||
std %i6, [%reg + RW_I6];
|
||||
|
||||
/* Load a register window from the area beginning at %reg. */
|
||||
#define RW_LOAD(reg) \
|
||||
ldd [%reg + RW_L0], %l0; \
|
||||
ldd [%reg + RW_L2], %l2; \
|
||||
ldd [%reg + RW_L4], %l4; \
|
||||
ldd [%reg + RW_L6], %l6; \
|
||||
ldd [%reg + RW_I0], %i0; \
|
||||
ldd [%reg + RW_I2], %i2; \
|
||||
ldd [%reg + RW_I4], %i4; \
|
||||
ldd [%reg + RW_I6], %i6;
|
||||
|
||||
/* Loading and storing struct pt_reg trap frames. */
|
||||
#define PT_LOAD_INS(base_reg) \
|
||||
ldd [%base_reg + SF_REGS_SZ + PT_I0], %i0; \
|
||||
ldd [%base_reg + SF_REGS_SZ + PT_I2], %i2; \
|
||||
ldd [%base_reg + SF_REGS_SZ + PT_I4], %i4; \
|
||||
ldd [%base_reg + SF_REGS_SZ + PT_I6], %i6;
|
||||
|
||||
#define PT_LOAD_GLOBALS(base_reg) \
|
||||
ld [%base_reg + SF_REGS_SZ + PT_G1], %g1; \
|
||||
ldd [%base_reg + SF_REGS_SZ + PT_G2], %g2; \
|
||||
ldd [%base_reg + SF_REGS_SZ + PT_G4], %g4; \
|
||||
ldd [%base_reg + SF_REGS_SZ + PT_G6], %g6;
|
||||
|
||||
#define PT_LOAD_YREG(base_reg, scratch) \
|
||||
ld [%base_reg + SF_REGS_SZ + PT_Y], %scratch; \
|
||||
wr %scratch, 0x0, %y;
|
||||
|
||||
#define PT_LOAD_PRIV(base_reg, pt_psr, pt_pc, pt_npc) \
|
||||
ld [%base_reg + SF_REGS_SZ + PT_PSR], %pt_psr; \
|
||||
ld [%base_reg + SF_REGS_SZ + PT_PC], %pt_pc; \
|
||||
ld [%base_reg + SF_REGS_SZ + PT_NPC], %pt_npc;
|
||||
|
||||
#define PT_LOAD_ALL(base_reg, pt_psr, pt_pc, pt_npc, scratch) \
|
||||
PT_LOAD_YREG(base_reg, scratch) \
|
||||
PT_LOAD_INS(base_reg) \
|
||||
PT_LOAD_GLOBALS(base_reg) \
|
||||
PT_LOAD_PRIV(base_reg, pt_psr, pt_pc, pt_npc)
|
||||
|
||||
#define PT_STORE_INS(base_reg) \
|
||||
std %i0, [%base_reg + SF_REGS_SZ + PT_I0]; \
|
||||
std %i2, [%base_reg + SF_REGS_SZ + PT_I2]; \
|
||||
std %i4, [%base_reg + SF_REGS_SZ + PT_I4]; \
|
||||
std %i6, [%base_reg + SF_REGS_SZ + PT_I6];
|
||||
|
||||
#define PT_STORE_GLOBALS(base_reg) \
|
||||
st %g1, [%base_reg + SF_REGS_SZ + PT_G1]; \
|
||||
std %g2, [%base_reg + SF_REGS_SZ + PT_G2]; \
|
||||
std %g4, [%base_reg + SF_REGS_SZ + PT_G4]; \
|
||||
std %g6, [%base_reg + SF_REGS_SZ + PT_G6];
|
||||
|
||||
#define PT_STORE_YREG(base_reg, scratch) \
|
||||
rd %y, %scratch; \
|
||||
st %scratch, [%base_reg + SF_REGS_SZ + PT_Y];
|
||||
|
||||
#define PT_STORE_PRIV(base_reg, pt_psr, pt_pc, pt_npc) \
|
||||
st %pt_psr, [%base_reg + SF_REGS_SZ + PT_PSR]; \
|
||||
st %pt_pc, [%base_reg + SF_REGS_SZ + PT_PC]; \
|
||||
st %pt_npc, [%base_reg + SF_REGS_SZ + PT_NPC];
|
||||
|
||||
#define PT_STORE_ALL(base_reg, reg_psr, reg_pc, reg_npc, g_scratch) \
|
||||
PT_STORE_PRIV(base_reg, reg_psr, reg_pc, reg_npc) \
|
||||
PT_STORE_GLOBALS(base_reg) \
|
||||
PT_STORE_YREG(base_reg, g_scratch) \
|
||||
PT_STORE_INS(base_reg)
|
||||
|
||||
/* Store the fpu register window*/
|
||||
#define FW_STORE(reg) \
|
||||
std %f0, [reg + FW_F0]; \
|
||||
std %f2, [reg + FW_F2]; \
|
||||
std %f4, [reg + FW_F4]; \
|
||||
std %f6, [reg + FW_F6]; \
|
||||
std %f8, [reg + FW_F8]; \
|
||||
std %f10, [reg + FW_F10]; \
|
||||
std %f12, [reg + FW_F12]; \
|
||||
std %f14, [reg + FW_F14]; \
|
||||
std %f16, [reg + FW_F16]; \
|
||||
std %f18, [reg + FW_F18]; \
|
||||
std %f20, [reg + FW_F20]; \
|
||||
std %f22, [reg + FW_F22]; \
|
||||
std %f24, [reg + FW_F24]; \
|
||||
std %f26, [reg + FW_F26]; \
|
||||
std %f28, [reg + FW_F28]; \
|
||||
std %f30, [reg + FW_F30]; \
|
||||
st %fsr, [reg + FW_FSR];
|
||||
|
||||
/* Load a fpu register window from the area beginning at reg. */
|
||||
#define FW_LOAD(reg) \
|
||||
ldd [reg + FW_F0], %f0; \
|
||||
ldd [reg + FW_F2], %f2; \
|
||||
ldd [reg + FW_F4], %f4; \
|
||||
ldd [reg + FW_F6], %f6; \
|
||||
ldd [reg + FW_F8], %f8; \
|
||||
ldd [reg + FW_F10], %f10; \
|
||||
ldd [reg + FW_F12], %f12; \
|
||||
ldd [reg + FW_F14], %f14; \
|
||||
ldd [reg + FW_F16], %f16; \
|
||||
ldd [reg + FW_F18], %f18; \
|
||||
ldd [reg + FW_F20], %f20; \
|
||||
ldd [reg + FW_F22], %f22; \
|
||||
ldd [reg + FW_F24], %f24; \
|
||||
ldd [reg + FW_F26], %f26; \
|
||||
ldd [reg + FW_F28], %f28; \
|
||||
ldd [reg + FW_F30], %f30; \
|
||||
ld [reg + FW_FSR], %fsr;
|
||||
|
||||
#endif
|
||||
9
u-boot/arch/sparc/lib/Makefile
Normal file
9
u-boot/arch/sparc/lib/Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
# (C) Copyright 2000-2015
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-y = cache.o interrupts.o
|
||||
obj-$(CONFIG_CMD_BOOTM) += bootm.o
|
||||
166
u-boot/arch/sparc/lib/bootm.c
Normal file
166
u-boot/arch/sparc/lib/bootm.c
Normal file
@@ -0,0 +1,166 @@
|
||||
/* SPARC code for booting linux 2.6
|
||||
*
|
||||
* (C) Copyright 2007
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/cache.h>
|
||||
#include <image.h>
|
||||
|
||||
#define PRINT_KERNEL_HEADER
|
||||
|
||||
extern image_header_t header;
|
||||
extern void srmmu_init_cpu(unsigned int entry);
|
||||
extern void prepare_bootargs(char *bootargs);
|
||||
|
||||
/* sparc kernel argument (the ROM vector) */
|
||||
struct linux_romvec *kernel_arg_promvec;
|
||||
|
||||
/* page szie is 4k */
|
||||
#define PAGE_SIZE 0x1000
|
||||
#define RAMDISK_IMAGE_START_MASK 0x07FF
|
||||
#define RAMDISK_PROMPT_FLAG 0x8000
|
||||
#define RAMDISK_LOAD_FLAG 0x4000
|
||||
struct __attribute__ ((packed)) {
|
||||
char traptable[PAGE_SIZE];
|
||||
char swapper_pg_dir[PAGE_SIZE];
|
||||
char pg0[PAGE_SIZE];
|
||||
char pg1[PAGE_SIZE];
|
||||
char pg2[PAGE_SIZE];
|
||||
char pg3[PAGE_SIZE];
|
||||
char empty_bad_page[PAGE_SIZE];
|
||||
char empty_bad_page_table[PAGE_SIZE];
|
||||
char empty_zero_page[PAGE_SIZE];
|
||||
unsigned char hdr[4]; /* ascii "HdrS" */
|
||||
/* 00.02.06.0b is for Linux kernel 2.6.11 */
|
||||
unsigned char linuxver_mega_major;
|
||||
unsigned char linuxver_major;
|
||||
unsigned char linuxver_minor;
|
||||
unsigned char linuxver_revision;
|
||||
/* header version 0x0203 */
|
||||
unsigned short hdr_ver;
|
||||
union __attribute__ ((packed)) {
|
||||
struct __attribute__ ((packed)) {
|
||||
unsigned short root_flags;
|
||||
unsigned short root_dev;
|
||||
unsigned short ram_flags;
|
||||
unsigned int sparc_ramdisk_image;
|
||||
unsigned int sparc_ramdisk_size;
|
||||
unsigned int reboot_command;
|
||||
unsigned int resv[3];
|
||||
unsigned int end;
|
||||
} ver_0203;
|
||||
} hdr_input;
|
||||
} *linux_hdr;
|
||||
|
||||
/* temporary initrd image holder */
|
||||
image_header_t ihdr;
|
||||
|
||||
void arch_lmb_reserve(struct lmb *lmb)
|
||||
{
|
||||
/* Reserve the space used by PROM and stack. This is done
|
||||
* to avoid that the RAM image is copied over stack or
|
||||
* PROM.
|
||||
*/
|
||||
lmb_reserve(lmb, CONFIG_SYS_RELOC_MONITOR_BASE, CONFIG_SYS_RAM_END);
|
||||
}
|
||||
|
||||
/* boot the linux kernel */
|
||||
int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t * images)
|
||||
{
|
||||
char *bootargs;
|
||||
ulong rd_len;
|
||||
void (*kernel) (struct linux_romvec *, void *);
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* allow the PREP bootm subcommand, it is required for bootm to work
|
||||
*/
|
||||
if (flag & BOOTM_STATE_OS_PREP)
|
||||
return 0;
|
||||
|
||||
if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
|
||||
return 1;
|
||||
|
||||
/* Get virtual address of kernel start */
|
||||
linux_hdr = (void *)images->os.load;
|
||||
|
||||
/* */
|
||||
kernel = (void (*)(struct linux_romvec *, void *))images->ep;
|
||||
|
||||
/* check for a SPARC kernel */
|
||||
if ((linux_hdr->hdr[0] != 'H') ||
|
||||
(linux_hdr->hdr[1] != 'd') ||
|
||||
(linux_hdr->hdr[2] != 'r') || (linux_hdr->hdr[3] != 'S')) {
|
||||
puts("Error reading header of SPARC Linux kernel, aborting\n");
|
||||
goto error;
|
||||
}
|
||||
#ifdef PRINT_KERNEL_HEADER
|
||||
printf("## Found SPARC Linux kernel %d.%d.%d ...\n",
|
||||
linux_hdr->linuxver_major,
|
||||
linux_hdr->linuxver_minor, linux_hdr->linuxver_revision);
|
||||
#endif
|
||||
|
||||
/* set basic boot params in kernel header now that it has been
|
||||
* extracted and is writeable.
|
||||
*/
|
||||
|
||||
ret = image_setup_linux(images);
|
||||
if (ret) {
|
||||
puts("### Failed to relocate RAM disk\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Calc length of RAM disk, if zero no ramdisk available */
|
||||
rd_len = images->rd_end - images->rd_start;
|
||||
|
||||
if (rd_len) {
|
||||
/* Update SPARC kernel header so that Linux knows
|
||||
* what is going on and where to find RAM disk.
|
||||
*
|
||||
* Set INITRD Image address relative to RAM Start
|
||||
*/
|
||||
linux_hdr->hdr_input.ver_0203.sparc_ramdisk_image =
|
||||
images->initrd_start - CONFIG_SYS_RAM_BASE;
|
||||
linux_hdr->hdr_input.ver_0203.sparc_ramdisk_size = rd_len;
|
||||
/* Clear READ ONLY flag if set to non-zero */
|
||||
linux_hdr->hdr_input.ver_0203.root_flags = 1;
|
||||
/* Set root device to: Root_RAM0 */
|
||||
linux_hdr->hdr_input.ver_0203.root_dev = 0x100;
|
||||
linux_hdr->hdr_input.ver_0203.ram_flags = 0;
|
||||
} else {
|
||||
/* NOT using RAMDISK image, overwriting kernel defaults */
|
||||
linux_hdr->hdr_input.ver_0203.sparc_ramdisk_image = 0;
|
||||
linux_hdr->hdr_input.ver_0203.sparc_ramdisk_size = 0;
|
||||
/* Leave to kernel defaults
|
||||
linux_hdr->hdr_input.ver_0203.root_flags = 1;
|
||||
linux_hdr->hdr_input.ver_0203.root_dev = 0;
|
||||
linux_hdr->hdr_input.ver_0203.ram_flags = 0;
|
||||
*/
|
||||
}
|
||||
|
||||
/* Copy bootargs from bootargs variable to kernel readable area */
|
||||
bootargs = getenv("bootargs");
|
||||
prepare_bootargs(bootargs);
|
||||
|
||||
/* turn on mmu & setup context table & page table for process 0 (kernel) */
|
||||
srmmu_init_cpu((unsigned int)kernel);
|
||||
|
||||
/* Enter SPARC Linux kernel
|
||||
* From now on the only code in u-boot that will be
|
||||
* executed is the PROM code.
|
||||
*/
|
||||
kernel(kernel_arg_promvec, (void *)images->ep);
|
||||
|
||||
/* It will never come to this... */
|
||||
while (1) ;
|
||||
|
||||
error:
|
||||
return 1;
|
||||
}
|
||||
17
u-boot/arch/sparc/lib/cache.c
Normal file
17
u-boot/arch/sparc/lib/cache.c
Normal file
@@ -0,0 +1,17 @@
|
||||
/* Sparc cache library
|
||||
*
|
||||
* (C) Copyright 2007
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
void flush_cache(ulong start_addr, ulong size)
|
||||
{
|
||||
/* Flush All Cache */
|
||||
sparc_dcache_flush_all();
|
||||
sparc_icache_flush_all();
|
||||
}
|
||||
68
u-boot/arch/sparc/lib/interrupts.c
Normal file
68
u-boot/arch/sparc/lib/interrupts.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* (C) Copyright 2000-2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2003
|
||||
* Gleb Natapov <gnatapov@mrv.com>
|
||||
*
|
||||
* (C) Copyright 2007
|
||||
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
/* Implemented by SPARC CPUs */
|
||||
extern int interrupt_init_cpu(void);
|
||||
extern void timer_interrupt_cpu(void *arg);
|
||||
extern int timer_interrupt_init_cpu(void);
|
||||
|
||||
int intLock(void)
|
||||
{
|
||||
unsigned int pil;
|
||||
|
||||
pil = get_pil();
|
||||
|
||||
/* set PIL to 15 ==> no pending interrupts will interrupt CPU */
|
||||
set_pil(15);
|
||||
|
||||
return pil;
|
||||
}
|
||||
|
||||
void intUnlock(int oldLevel)
|
||||
{
|
||||
set_pil(oldLevel);
|
||||
}
|
||||
|
||||
void enable_interrupts(void)
|
||||
{
|
||||
set_pil(0); /* enable all interrupts */
|
||||
}
|
||||
|
||||
int disable_interrupts(void)
|
||||
{
|
||||
return intLock();
|
||||
}
|
||||
|
||||
int interrupt_is_enabled(void)
|
||||
{
|
||||
if (get_pil() == 15)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int interrupt_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* call cpu specific function from $(CPU)/interrupts.c */
|
||||
ret = interrupt_init_cpu();
|
||||
|
||||
/* enable global interrupts */
|
||||
enable_interrupts();
|
||||
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user