提交 936478e7 编写于 作者: T Tom Rini

SPARC: Remove

The SPARC architecture is currently unmaintained, remove.

Cc: Francois Retief <fgretief@spaceteq.co.za>
Signed-off-by: NTom Rini <trini@konsulko.com>
上级 ea3310e8
......@@ -284,7 +284,7 @@ config SYS_EXTRA_OPTIONS
new boards should not use this option.
config SYS_TEXT_BASE
depends on SPARC || ARC || X86 || ARCH_UNIPHIER || ARCH_ZYNQMP || \
depends on ARC || X86 || ARCH_UNIPHIER || ARCH_ZYNQMP || \
(M68K && !TARGET_ASTRO_MCF5373L) || MICROBLAZE || MIPS || \
ARCH_ZYNQ
depends on !EFI_APP
......
......@@ -414,12 +414,6 @@ S: Maintained
T: git git://git.denx.de/u-boot-sh.git
F: arch/sh/
SPARC
#M: Francois Retief <fgretief@spaceteq.co.za>
S: Orphaned (Since 2016-02)
T: git git://git.denx.de/u-boot-sparc.git
F: arch/sparc/
SPI
M: Jagan Teki <jagan@openedev.com>
S: Maintained
......
......@@ -146,7 +146,6 @@ Directory Hierarchy:
/powerpc Files generic to PowerPC architecture
/sandbox Files generic to HW-independent "sandbox"
/sh Files generic to SH architecture
/sparc Files generic to SPARC architecture
/x86 Files generic to x86 architecture
/api Machine/arch independent API for external apps
/board Board dependent files
......
......@@ -76,10 +76,6 @@ config SH
bool "SuperH architecture"
select HAVE_PRIVATE_LIBGCC
config SPARC
bool "SPARC architecture"
select CREATE_ARCH_SYMLINK
config X86
bool "x86 architecture"
select CREATE_ARCH_SYMLINK
......@@ -167,6 +163,5 @@ source "arch/openrisc/Kconfig"
source "arch/powerpc/Kconfig"
source "arch/sandbox/Kconfig"
source "arch/sh/Kconfig"
source "arch/sparc/Kconfig"
source "arch/x86/Kconfig"
source "arch/xtensa/Kconfig"
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
#
# 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/
#
# (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
#
# (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
/* 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
/* 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;
}
/*
* (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
此差异已折叠。
/* 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, &regs->UART_Scaler);
/* Let bit 11 be unchanged (debug bit for GRMON) */
tmp = readl(&regs->UART_Control) & LEON2_UART_CTRL_DBG;
tmp |= (LEON2_UART1_LOOPBACK_ENABLE << 7);
tmp |= (LEON2_UART1_FLOWCTRL_ENABLE << 6);
tmp |= (LEON2_UART1_PARITY_ENABLE << 5);
tmp |= (LEON2_UART1_ODDPAR_ENABLE << 4);
/* Receiver & transmitter enable */
tmp |= (LEON2_UART_CTRL_RE | LEON2_UART_CTRL_TE);
writel(tmp, &regs->UART_Control);
gd->arch.uart = regs;
return 0;
}
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;
}
/* 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
#
# (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
/* 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;
}
此差异已折叠。
/* 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
/* 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
/* 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;
}
/*
* (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
/* 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
};
/* 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
/* 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
此差异已折叠。
/* 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
此差异已折叠。
此差异已折叠。
此差异已折叠。
/*
* (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) }
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
/* 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_ */
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册