Browse Source

SPARC: Remove

The SPARC architecture is currently unmaintained, remove.

Cc: Francois Retief <fgretief@spaceteq.co.za>
Signed-off-by: Tom Rini <trini@konsulko.com>
tags/2020-06-01
Tom Rini 4 years ago
parent
commit
936478e797
94 changed files with 6 additions and 14232 deletions
  1. +1
    -1
      Kconfig
  2. +0
    -6
      MAINTAINERS
  3. +0
    -1
      README
  4. +0
    -5
      arch/Kconfig
  5. +0
    -70
      arch/sparc/Kconfig
  6. +0
    -8
      arch/sparc/Makefile
  7. +0
    -25
      arch/sparc/config.mk
  8. +0
    -9
      arch/sparc/cpu/leon2/Makefile
  9. +0
    -60
      arch/sparc/cpu/leon2/cpu.c
  10. +0
    -95
      arch/sparc/cpu/leon2/cpu_init.c
  11. +0
    -187
      arch/sparc/cpu/leon2/interrupts.c
  12. +0
    -1032
      arch/sparc/cpu/leon2/prom.c
  13. +0
    -147
      arch/sparc/cpu/leon2/serial.c
  14. +0
    -695
      arch/sparc/cpu/leon2/start.S
  15. +0
    -10
      arch/sparc/cpu/leon3/Makefile
  16. +0
    -316
      arch/sparc/cpu/leon3/ambapp.c
  17. +0
    -784
      arch/sparc/cpu/leon3/ambapp_low.S
  18. +0
    -113
      arch/sparc/cpu/leon3/ambapp_low_c.S
  19. +0
    -113
      arch/sparc/cpu/leon3/cpu.c
  20. +0
    -175
      arch/sparc/cpu/leon3/cpu_init.c
  21. +0
    -193
      arch/sparc/cpu/leon3/interrupts.c
  22. +0
    -237
      arch/sparc/cpu/leon3/memcfg.c
  23. +0
    -90
      arch/sparc/cpu/leon3/memcfg.h
  24. +0
    -253
      arch/sparc/cpu/leon3/memcfg_low.S
  25. +0
    -1067
      arch/sparc/cpu/leon3/prom.c
  26. +0
    -189
      arch/sparc/cpu/leon3/serial.c
  27. +0
    -681
      arch/sparc/cpu/leon3/start.S
  28. +0
    -1195
      arch/sparc/cpu/leon3/usb_uhci.c
  29. +0
    -167
      arch/sparc/cpu/leon3/usb_uhci.h
  30. +0
    -142
      arch/sparc/cpu/u-boot.lds
  31. +0
    -19
      arch/sparc/include/asm/arch-leon2/asi.h
  32. +0
    -19
      arch/sparc/include/asm/arch-leon3/asi.h
  33. +0
    -15
      arch/sparc/include/asm/asi.h
  34. +0
    -28
      arch/sparc/include/asm/asmmacro.h
  35. +0
    -12
      arch/sparc/include/asm/atomic.h
  36. +0
    -17
      arch/sparc/include/asm/bitops.h
  37. +0
    -21
      arch/sparc/include/asm/byteorder.h
  38. +0
    -23
      arch/sparc/include/asm/cache.h
  39. +0
    -21
      arch/sparc/include/asm/config.h
  40. +0
    -30
      arch/sparc/include/asm/global_data.h
  41. +0
    -96
      arch/sparc/include/asm/io.h
  42. +0
    -38
      arch/sparc/include/asm/irq.h
  43. +0
    -28
      arch/sparc/include/asm/leon.h
  44. +0
    -222
      arch/sparc/include/asm/leon2.h
  45. +0
    -35
      arch/sparc/include/asm/leon3.h
  46. +0
    -0
     
  47. +0
    -78
      arch/sparc/include/asm/machines.h
  48. +0
    -28
      arch/sparc/include/asm/page.h
  49. +0
    -125
      arch/sparc/include/asm/posix_types.h
  50. +0
    -102
      arch/sparc/include/asm/processor.h
  51. +0
    -283
      arch/sparc/include/asm/prom.h
  52. +0
    -83
      arch/sparc/include/asm/psr.h
  53. +0
    -167
      arch/sparc/include/asm/ptrace.h
  54. +0
    -11
      arch/sparc/include/asm/sections.h
  55. +0
    -287
      arch/sparc/include/asm/srmmu.h
  56. +0
    -148
      arch/sparc/include/asm/stack.h
  57. +0
    -41
      arch/sparc/include/asm/string.h
  58. +0
    -60
      arch/sparc/include/asm/types.h
  59. +0
    -24
      arch/sparc/include/asm/u-boot.h
  60. +0
    -10
      arch/sparc/include/asm/unaligned.h
  61. +0
    -138
      arch/sparc/include/asm/winmacro.h
  62. +0
    -9
      arch/sparc/lib/Makefile
  63. +0
    -166
      arch/sparc/lib/bootm.c
  64. +0
    -17
      arch/sparc/lib/cache.c
  65. +0
    -68
      arch/sparc/lib/interrupts.c
  66. +0
    -14
      cmd/Kconfig
  67. +0
    -1
      cmd/Makefile
  68. +0
    -575
      cmd/ambapp.c
  69. +0
    -32
      cmd/bdinfo.c
  70. +1
    -1
      common/Kconfig
  71. +1
    -19
      common/board_f.c
  72. +1
    -30
      common/board_r.c
  73. +0
    -10
      configs/gr_cpci_ax2000_defconfig
  74. +0
    -10
      configs/gr_ep2s60_defconfig
  75. +0
    -10
      configs/gr_xc3s_1500_defconfig
  76. +0
    -23
      configs/grsim_defconfig
  77. +0
    -18
      configs/grsim_leon2_defconfig
  78. +2
    -3
      disk/Kconfig
  79. +0
    -1
      drivers/net/Makefile
  80. +0
    -677
      drivers/net/greth.c
  81. +0
    -81
      drivers/net/greth.h
  82. +0
    -15
      examples/standalone/stubs.c
  83. +0
    -225
      include/ambapp.h
  84. +0
    -250
      include/ambapp_ids.h
  85. +0
    -339
      include/configs/gr_cpci_ax2000.h
  86. +0
    -304
      include/configs/gr_ep2s60.h
  87. +0
    -271
      include/configs/gr_xc3s_1500.h
  88. +0
    -313
      include/configs/grsim.h
  89. +0
    -283
      include/configs/grsim_leon2.h
  90. +0
    -47
      include/grlib/apbuart.h
  91. +0
    -34
      include/grlib/gptimer.h
  92. +0
    -87
      include/grlib/greth.h
  93. +0
    -23
      include/grlib/irqmp.h
  94. +0
    -1
      include/netdev.h

+ 1
- 1
Kconfig View File

@@ -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


+ 0
- 6
MAINTAINERS View File

@@ -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


+ 0
- 1
README View File

@@ -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


+ 0
- 5
arch/Kconfig View File

@@ -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"

+ 0
- 70
arch/sparc/Kconfig View File

@@ -1,70 +0,0 @@
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

+ 0
- 8
arch/sparc/Makefile View File

@@ -1,8 +0,0 @@
#
# 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/

+ 0
- 25
arch/sparc/config.mk View File

@@ -1,25 +0,0 @@
#
# (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

+ 0
- 9
arch/sparc/cpu/leon2/Makefile View File

@@ -1,9 +0,0 @@
#
# (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

+ 0
- 60
arch/sparc/cpu/leon2/cpu.c View File

@@ -1,60 +0,0 @@
/* 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

+ 0
- 95
arch/sparc/cpu/leon2/cpu_init.c View File

@@ -1,95 +0,0 @@
/* 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;
}

+ 0
- 187
arch/sparc/cpu/leon2/interrupts.c View File

@@ -1,187 +0,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

+ 0
- 1032
arch/sparc/cpu/leon2/prom.c
File diff suppressed because it is too large
View File


+ 0
- 147
arch/sparc/cpu/leon2/serial.c View File

@@ -1,147 +0,0 @@
/* 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;
}

+ 0
- 695
arch/sparc/cpu/leon2/start.S View File

@@ -1,695 +0,0 @@
/* 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

+ 0
- 10
arch/sparc/cpu/leon3/Makefile View File

@@ -1,10 +0,0 @@
#
# (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

+ 0
- 316
arch/sparc/cpu/leon3/ambapp.c View File

@@ -1,316 +0,0 @@
/* 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;
}

+ 0
- 784
arch/sparc/cpu/leon3/ambapp_low.S View File

@@ -1,784 +0,0 @@
/* 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