diff options
author | 2023-10-10 14:33:42 +0000 | |
---|---|---|
committer | 2023-10-10 14:33:42 +0000 | |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot/arch/nios2 | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/arch/nios2')
43 files changed, 3373 insertions, 0 deletions
diff --git a/roms/u-boot/arch/nios2/Kconfig b/roms/u-boot/arch/nios2/Kconfig new file mode 100644 index 000000000..bb4fb2ac3 --- /dev/null +++ b/roms/u-boot/arch/nios2/Kconfig @@ -0,0 +1,14 @@ +menu "Nios II architecture" + depends on NIOS2 + +config SYS_ARCH + default "nios2" + +config SYS_CONFIG_NAME + string "Board header file" + help + This option should contain the base name of board header file. + The header file include/configs/<CONFIG_SYS_CONFIG_NAME>.h + should be included from include/config.h. + +endmenu diff --git a/roms/u-boot/arch/nios2/Makefile b/roms/u-boot/arch/nios2/Makefile new file mode 100644 index 000000000..fee18b1b5 --- /dev/null +++ b/roms/u-boot/arch/nios2/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ + +head-y := arch/nios2/cpu/start.o + +libs-y += arch/nios2/cpu/ +libs-y += arch/nios2/lib/ diff --git a/roms/u-boot/arch/nios2/config.mk b/roms/u-boot/arch/nios2/config.mk new file mode 100644 index 000000000..44260b143 --- /dev/null +++ b/roms/u-boot/arch/nios2/config.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2004 +# Psyent Corporation <www.psyent.com> +# Scott McNutt <smcnutt@psyent.com> + +CONFIG_STANDALONE_LOAD_ADDR ?= 0x02000000 + +PLATFORM_CPPFLAGS += -D__NIOS2__ +PLATFORM_CPPFLAGS += -G0 + +LDFLAGS_FINAL += --gc-sections +PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections diff --git a/roms/u-boot/arch/nios2/cpu/Makefile b/roms/u-boot/arch/nios2/cpu/Makefile new file mode 100644 index 000000000..0b675e7c0 --- /dev/null +++ b/roms/u-boot/arch/nios2/cpu/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +extra-y = start.o +obj-y = exceptions.o +obj-y += cpu.o interrupts.o traps.o diff --git a/roms/u-boot/arch/nios2/cpu/cpu.c b/roms/u-boot/arch/nios2/cpu/cpu.c new file mode 100644 index 000000000..b55c8fbc5 --- /dev/null +++ b/roms/u-boot/arch/nios2/cpu/cpu.c @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + */ + +#include <common.h> +#include <command.h> +#include <cpu.h> +#include <cpu_func.h> +#include <dm.h> +#include <errno.h> +#include <init.h> +#include <irq_func.h> +#include <asm/cache.h> +#include <asm/global_data.h> +#include <asm/system.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_DISPLAY_CPUINFO +int print_cpuinfo(void) +{ + printf("CPU: Nios-II\n"); + return 0; +} +#endif /* CONFIG_DISPLAY_CPUINFO */ + +#ifdef CONFIG_ALTERA_SYSID +int checkboard(void) +{ + display_sysid(); + return 0; +} +#endif + +int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + disable_interrupts(); + /* indirect call to go beyond 256MB limitation of toolchain */ + nios2_callr(gd->arch.reset_addr); + return 0; +} + +/* + * COPY EXCEPTION TRAMPOLINE -- copy the tramp to the + * exception address. Define CONFIG_ROM_STUBS to prevent + * the copy (e.g. exception in flash or in other + * softare/firmware component). + */ +#ifndef CONFIG_ROM_STUBS +static void copy_exception_trampoline(void) +{ + extern int _except_start, _except_end; + void *except_target = (void *)gd->arch.exception_addr; + + if (&_except_start != except_target) { + memcpy(except_target, &_except_start, + &_except_end - &_except_start); + flush_cache(gd->arch.exception_addr, + &_except_end - &_except_start); + } +} +#endif + +int arch_cpu_init_dm(void) +{ + struct udevice *dev; + int ret; + + ret = uclass_first_device_err(UCLASS_CPU, &dev); + if (ret) + return ret; + + gd->ram_size = CONFIG_SYS_SDRAM_SIZE; +#ifndef CONFIG_ROM_STUBS + copy_exception_trampoline(); +#endif + + return 0; +} + +static int altera_nios2_get_desc(const struct udevice *dev, char *buf, + int size) +{ + const char *cpu_name = "Nios-II"; + + if (size < strlen(cpu_name)) + return -ENOSPC; + strcpy(buf, cpu_name); + + return 0; +} + +static int altera_nios2_get_info(const struct udevice *dev, + struct cpu_info *info) +{ + info->cpu_freq = gd->cpu_clk; + info->features = (1 << CPU_FEAT_L1_CACHE) | + (gd->arch.has_mmu ? (1 << CPU_FEAT_MMU) : 0); + + return 0; +} + +static int altera_nios2_get_count(const struct udevice *dev) +{ + return 1; +} + +static int altera_nios2_probe(struct udevice *dev) +{ + const void *blob = gd->fdt_blob; + int node = dev_of_offset(dev); + + gd->cpu_clk = fdtdec_get_int(blob, node, + "clock-frequency", 0); + gd->arch.dcache_line_size = fdtdec_get_int(blob, node, + "dcache-line-size", 0); + gd->arch.icache_line_size = fdtdec_get_int(blob, node, + "icache-line-size", 0); + gd->arch.dcache_size = fdtdec_get_int(blob, node, + "dcache-size", 0); + gd->arch.icache_size = fdtdec_get_int(blob, node, + "icache-size", 0); + gd->arch.reset_addr = fdtdec_get_int(blob, node, + "altr,reset-addr", 0); + gd->arch.exception_addr = fdtdec_get_int(blob, node, + "altr,exception-addr", 0); + gd->arch.has_initda = fdtdec_get_int(blob, node, + "altr,has-initda", 0); + gd->arch.has_mmu = fdtdec_get_int(blob, node, + "altr,has-mmu", 0); + gd->arch.io_region_base = gd->arch.has_mmu ? 0xe0000000 : 0x80000000; + gd->arch.mem_region_base = gd->arch.has_mmu ? 0xc0000000 : 0x00000000; + gd->arch.physaddr_mask = gd->arch.has_mmu ? 0x1fffffff : 0x7fffffff; + + return 0; +} + +static const struct cpu_ops altera_nios2_ops = { + .get_desc = altera_nios2_get_desc, + .get_info = altera_nios2_get_info, + .get_count = altera_nios2_get_count, +}; + +static const struct udevice_id altera_nios2_ids[] = { + { .compatible = "altr,nios2-1.0" }, + { .compatible = "altr,nios2-1.1" }, + { } +}; + +U_BOOT_DRIVER(altera_nios2) = { + .name = "altera_nios2", + .id = UCLASS_CPU, + .of_match = altera_nios2_ids, + .probe = altera_nios2_probe, + .ops = &altera_nios2_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +/* This is a dummy function on nios2 */ +int dram_init(void) +{ + return 0; +} diff --git a/roms/u-boot/arch/nios2/cpu/exceptions.S b/roms/u-boot/arch/nios2/cpu/exceptions.S new file mode 100644 index 000000000..95be04cdb --- /dev/null +++ b/roms/u-boot/arch/nios2/cpu/exceptions.S @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + */ + +#include <config.h> +#include <asm/opcodes.h> + + + .text + .align 4 + + .global _exception + + .set noat + .set nobreak + +_exception: + /* SAVE ALL REGS -- this allows trap and unimplemented + * instruction handlers to be coded conveniently in C + */ + addi sp, sp, -(33*4) + stw r0, 0(sp) + stw r1, 4(sp) + stw r2, 8(sp) + stw r3, 12(sp) + stw r4, 16(sp) + stw r5, 20(sp) + stw r6, 24(sp) + stw r7, 28(sp) + stw r8, 32(sp) + stw r9, 36(sp) + stw r10, 40(sp) + stw r11, 44(sp) + stw r12, 48(sp) + stw r13, 52(sp) + stw r14, 56(sp) + stw r15, 60(sp) + stw r16, 64(sp) + stw r17, 68(sp) + stw r19, 72(sp) + stw r19, 76(sp) + stw r20, 80(sp) + stw r21, 84(sp) + stw r22, 88(sp) + stw r23, 92(sp) + stw r24, 96(sp) + stw r25, 100(sp) + stw r26, 104(sp) + stw r27, 108(sp) + stw r28, 112(sp) + stw r29, 116(sp) + stw r30, 120(sp) + stw r31, 124(sp) + rdctl et, estatus + stw et, 128(sp) + + /* If interrupts are disabled -- software interrupt */ + rdctl et, estatus + andi et, et, 1 + beq et, r0, 0f + + /* If no interrupts are pending -- software interrupt */ + rdctl et, ipending + beq et, r0, 0f + + /* HARDWARE INTERRUPT: Call interrupt handler */ + movhi r3, %hi(external_interrupt) + ori r3, r3, %lo(external_interrupt) + mov r4, sp /* ptr to regs */ + callr r3 + + /* Return address fixup: execution resumes by re-issue of + * interrupted instruction at ea-4 (ea == r29). Here we do + * simple fixup to allow common exception return. + */ + ldw r3, 116(sp) + addi r3, r3, -4 + stw r3, 116(sp) + br _exception_return + +0: + /* TRAP EXCEPTION */ + movhi r3, %hi(OPC_TRAP) + ori r3, r3, %lo(OPC_TRAP) + addi r1, ea, -4 + ldw r1, 0(r1) + bne r1, r3, 1f + movhi r3, %hi(trap_handler) + ori r3, r3, %lo(trap_handler) + mov r4, sp /* ptr to regs */ + callr r3 + br _exception_return + +1: + /* UNIMPLEMENTED INSTRUCTION EXCEPTION */ + movhi r3, %hi(soft_emulation) + ori r3, r3, %lo(soft_emulation) + mov r4, sp /* ptr to regs */ + callr r3 + + /* Restore regsisters and return from exception*/ +_exception_return: + ldw r1, 4(sp) + ldw r2, 8(sp) + ldw r3, 12(sp) + ldw r4, 16(sp) + ldw r5, 20(sp) + ldw r6, 24(sp) + ldw r7, 28(sp) + ldw r8, 32(sp) + ldw r9, 36(sp) + ldw r10, 40(sp) + ldw r11, 44(sp) + ldw r12, 48(sp) + ldw r13, 52(sp) + ldw r14, 56(sp) + ldw r15, 60(sp) + ldw r16, 64(sp) + ldw r17, 68(sp) + ldw r19, 72(sp) + ldw r19, 76(sp) + ldw r20, 80(sp) + ldw r21, 84(sp) + ldw r22, 88(sp) + ldw r23, 92(sp) + ldw r24, 96(sp) + ldw r25, 100(sp) + ldw r26, 104(sp) + ldw r27, 108(sp) + ldw r28, 112(sp) + ldw r29, 116(sp) + ldw r30, 120(sp) + ldw r31, 124(sp) + addi sp, sp, (33*4) + eret +/*-------------------------------------------------------------*/ diff --git a/roms/u-boot/arch/nios2/cpu/interrupts.c b/roms/u-boot/arch/nios2/cpu/interrupts.c new file mode 100644 index 000000000..90cabb675 --- /dev/null +++ b/roms/u-boot/arch/nios2/cpu/interrupts.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2000-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + */ + +#include <common.h> +#include <command.h> +#include <irq_func.h> +#include <asm/nios2.h> +#include <asm/types.h> +#include <asm/io.h> +#include <asm/ptrace.h> + +/*************************************************************************/ +struct irq_action { + interrupt_handler_t *handler; + void *arg; + int count; +}; + +static struct irq_action vecs[32]; + +int disable_interrupts(void) +{ + int val = rdctl (CTL_STATUS); + wrctl (CTL_STATUS, val & ~STATUS_IE); + return (val & STATUS_IE); +} + +void enable_interrupts( void ) +{ + int val = rdctl (CTL_STATUS); + wrctl (CTL_STATUS, val | STATUS_IE); +} + +void external_interrupt(struct pt_regs *regs) +{ + unsigned irqs; + struct irq_action *act; + + /* Evaluate only irqs that are both enabled AND pending */ + irqs = rdctl (CTL_IENABLE) & rdctl (CTL_IPENDING); + act = vecs; + + /* Assume (as does the Nios2 HAL) that bit 0 is highest + * priority. NOTE: There is ALWAYS a handler assigned + * (the default if no other). + */ + while (irqs) { + if (irqs & 1) { + act->handler (act->arg); + act->count++; + } + irqs >>=1; + act++; + } +} + +static void def_hdlr (void *arg) +{ + unsigned irqs = rdctl (CTL_IENABLE); + + /* Disable the individual interrupt -- with gratuitous + * warning. + */ + irqs &= ~(1 << (int)arg); + wrctl (CTL_IENABLE, irqs); + printf ("WARNING: Disabling unhandled interrupt: %d\n", + (int)arg); +} + +/*************************************************************************/ +void irq_install_handler(int irq, interrupt_handler_t *hdlr, void *arg) +{ + + int flag; + struct irq_action *act; + unsigned ena = rdctl (CTL_IENABLE); + + if ((irq < 0) || (irq > 31)) + return; + act = &vecs[irq]; + + flag = disable_interrupts(); + if (hdlr) { + act->handler = hdlr; + act->arg = arg; + ena |= (1 << irq); /* enable */ + } else { + act->handler = def_hdlr; + act->arg = (void *)irq; + ena &= ~(1 << irq); /* disable */ + } + wrctl (CTL_IENABLE, ena); + if (flag) enable_interrupts(); +} + + +int interrupt_init(void) +{ + int i; + + /* Assign the default handler to all */ + for (i = 0; i < 32; i++) { + vecs[i].handler = def_hdlr; + vecs[i].arg = (void *)i; + vecs[i].count = 0; + } + + enable_interrupts(); + return (0); +} + + +/*************************************************************************/ +#if defined(CONFIG_CMD_IRQ) +int do_irqinfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + int i; + struct irq_action *act = vecs; + + printf ("\nInterrupt-Information:\n\n"); + printf ("Nr Routine Arg Count\n"); + printf ("-----------------------------\n"); + + for (i=0; i<32; i++) { + if (act->handler != def_hdlr) { + printf ("%02d %08lx %08lx %d\n", + i, + (ulong)act->handler, + (ulong)act->arg, + act->count); + } + act++; + } + printf ("\n"); + + return (0); +} +#endif diff --git a/roms/u-boot/arch/nios2/cpu/start.S b/roms/u-boot/arch/nios2/cpu/start.S new file mode 100644 index 000000000..f5ad184e8 --- /dev/null +++ b/roms/u-boot/arch/nios2/cpu/start.S @@ -0,0 +1,179 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + */ + +#include <asm-offsets.h> +#include <config.h> +#include <version.h> + +/* + * icache and dcache configuration used only for start.S. + * the values are chosen so that it will work for all configuration. + */ +#define ICACHE_LINE_SIZE 32 /* fixed 32 */ +#define ICACHE_SIZE_MAX 0x10000 /* 64k max */ +#define DCACHE_LINE_SIZE_MIN 4 /* 4, 16, 32 */ +#define DCACHE_SIZE_MAX 0x10000 /* 64k max */ + + /* RESTART */ + .text + .global _start, _except_start, _except_end + +_start: + wrctl status, r0 /* Disable interrupts */ + /* + * ICACHE INIT -- only the icache line at the reset address + * is invalidated at reset. So the init must stay within + * the cache line size (8 words). If GERMS is used, we'll + * just be invalidating the cache a second time. If cache + * is not implemented initi behaves as nop. + */ + ori r4, r0, %lo(ICACHE_LINE_SIZE) + movhi r5, %hi(ICACHE_SIZE_MAX) + ori r5, r5, %lo(ICACHE_SIZE_MAX) +0: initi r5 + sub r5, r5, r4 + bgt r5, r0, 0b + br _except_end /* Skip the tramp */ + + /* + * EXCEPTION TRAMPOLINE -- the following gets copied + * to the exception address (below), but is otherwise at the + * default exception vector offset (0x0020). + */ +_except_start: + movhi et, %hi(_exception) + ori et, et, %lo(_exception) + jmp et +_except_end: + + /* + * INTERRUPTS -- for now, all interrupts masked and globally + * disabled. + */ + wrctl ienable, r0 /* All disabled */ + + /* + * DCACHE INIT -- if dcache not implemented, initd behaves as + * nop. + */ + ori r4, r0, %lo(DCACHE_LINE_SIZE_MIN) + movhi r5, %hi(DCACHE_SIZE_MAX) + ori r5, r5, %lo(DCACHE_SIZE_MAX) + mov r6, r0 +1: initd 0(r6) + add r6, r6, r4 + bltu r6, r5, 1b + + /* + * RELOCATE CODE, DATA & COMMAND TABLE -- the following code + * assumes code, data and the command table are all + * contiguous. This lets us relocate everything as a single + * block. Make sure the linker script matches this ;-) + */ + nextpc r4 +_cur: movhi r5, %hi(_cur - _start) + ori r5, r5, %lo(_cur - _start) + sub r4, r4, r5 /* r4 <- cur _start */ + mov r8, r4 + movhi r5, %hi(_start) + ori r5, r5, %lo(_start) /* r5 <- linked _start */ + mov sp, r5 /* initial stack below u-boot code */ + beq r4, r5, 3f + + movhi r6, %hi(CONFIG_SYS_MONITOR_LEN) + ori r6, r6, %lo(CONFIG_SYS_MONITOR_LEN) + add r6, r6, r5 +2: ldwio r7, 0(r4) + addi r4, r4, 4 + stwio r7, 0(r5) + addi r5, r5, 4 + bne r5, r6, 2b +3: + + /* JUMP TO RELOC ADDR */ + movhi r4, %hi(_reloc) + ori r4, r4, %lo(_reloc) + jmp r4 +_reloc: + + /* STACK INIT -- zero top two words for call back chain. */ + addi sp, sp, -8 + stw r0, 0(sp) + stw r0, 4(sp) + mov fp, sp + +#ifdef CONFIG_DEBUG_UART + /* Set up the debug UART */ + movhi r2, %hi(debug_uart_init@h) + ori r2, r2, %lo(debug_uart_init@h) + callr r2 +#endif + + /* Allocate and initialize reserved area, update SP */ + mov r4, sp + movhi r2, %hi(board_init_f_alloc_reserve@h) + ori r2, r2, %lo(board_init_f_alloc_reserve@h) + callr r2 + mov sp, r2 + mov r4, sp + movhi r2, %hi(board_init_f_init_reserve@h) + ori r2, r2, %lo(board_init_f_init_reserve@h) + callr r2 + + /* Update frame-pointer */ + mov fp, sp + + /* Call board_init_f -- never returns */ + mov r4, r0 + movhi r2, %hi(board_init_f@h) + ori r2, r2, %lo(board_init_f@h) + callr r2 + + /* + * NEVER RETURNS -- but branch to the _start just + * in case ;-) + */ + br _start + + /* + * relocate_code -- Nios2 handles the relocation above. But + * the generic board code monkeys with the heap, stack, etc. + * (it makes some assumptions that may not be appropriate + * for Nios). Nevertheless, we capitulate here. + * + * We'll call the board_init_r from here since this isn't + * supposed to return. + * + * void relocate_code(ulong sp, gd_t *global_data, + * ulong reloc_addr) + * __attribute__ ((noreturn)); + */ + .text + .global relocate_code + +relocate_code: + mov sp, r4 /* Set the new sp */ + mov r4, r5 + + /* + * ZERO BSS/SBSS -- bss and sbss are assumed to be adjacent + * and between __bss_start and __bss_end. + */ + movhi r5, %hi(__bss_start) + ori r5, r5, %lo(__bss_start) + movhi r6, %hi(__bss_end) + ori r6, r6, %lo(__bss_end) + beq r5, r6, 5f + +4: stw r0, 0(r5) + addi r5, r5, 4 + bne r5, r6, 4b +5: + + movhi r8, %hi(board_init_r@h) + ori r8, r8, %lo(board_init_r@h) + callr r8 + ret diff --git a/roms/u-boot/arch/nios2/cpu/traps.c b/roms/u-boot/arch/nios2/cpu/traps.c new file mode 100644 index 000000000..087a05097 --- /dev/null +++ b/roms/u-boot/arch/nios2/cpu/traps.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + */ + +#include <common.h> +#include <hang.h> +#include <asm/ptrace.h> + +void trap_handler (struct pt_regs *regs) +{ + /* Just issue warning */ + printf ("\n\n*** WARNING: unimplemented trap @ %08x\n\n", + regs->reg[29] - 4); +} + +void soft_emulation (struct pt_regs *regs) +{ + /* TODO: Software emulation of mul/div etc. Until this is + * implemented, generate warning and hang. + */ + printf ("\n\n*** ERROR: unimplemented instruction @ %08x\n", + regs->reg[29] - 4); + hang(); +} diff --git a/roms/u-boot/arch/nios2/cpu/u-boot.lds b/roms/u-boot/arch/nios2/cpu/u-boot.lds new file mode 100644 index 000000000..cbf54b461 --- /dev/null +++ b/roms/u-boot/arch/nios2/cpu/u-boot.lds @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + */ + +#include <config.h> + +OUTPUT_FORMAT("elf32-littlenios2") +OUTPUT_ARCH(nios2) +ENTRY(_start) + +SECTIONS +{ + . = CONFIG_SYS_MONITOR_BASE; + .text : + { + arch/nios2/cpu/start.o (.text) + *(.text) + *(.text.*) + *(.gnu.linkonce.t*) + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) + *(.gnu.linkonce.r*) + } + . = ALIGN (4); + _etext = .; + PROVIDE (etext = .); + + /* CMD TABLE - sandwich this in between text and data so + * the initialization code relocates the command table as + * well -- admittedly, this is just pure laziness ;-) + */ + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + /* INIT DATA sections - "Small" data (see the gcc -G option) + * is always gp-relative. Here we make all init data sections + * adjacent to simplify the startup code -- and provide + * the global pointer for gp-relative access. + */ + _data = .; + .data : + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + } + + /* + * gp - Since we don't use gp for small data with option "-G0", + * we will use gp as global data pointer. The _gp location is + * not needed. + */ + + .sdata : + { + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + } + . = ALIGN(4); + + _edata = .; + PROVIDE (edata = .); + + /* + * _end - This is end of u-boot.bin image. + * dtb will be appended here to make u-boot-dtb.bin + */ + _end = .; + + /* UNINIT DATA - Small uninitialized data is first so it's + * adjacent to sdata and can be referenced via gp. The normal + * bss follows. We keep it adjacent to simplify init code. + */ + __bss_start = .; + .sbss (NOLOAD) : + { + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + } + . = ALIGN(4); + .bss (NOLOAD) : + { + *(.bss) + *(.bss.*) + *(.dynbss) + *(COMMON) + *(.scommon) + } + . = ALIGN(4); + __bss_end = .; + PROVIDE (end = .); + + /* DEBUG -- symbol table, string table, etc. etc. + */ + .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) } + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/roms/u-boot/arch/nios2/dts/10m50_devboard.dts b/roms/u-boot/arch/nios2/dts/10m50_devboard.dts new file mode 100644 index 000000000..9cd40165a --- /dev/null +++ b/roms/u-boot/arch/nios2/dts/10m50_devboard.dts @@ -0,0 +1,267 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Altera Corporation + * + * This file is generated by sopc2dts. + */ + +/dts-v1/; + +/ { + model = "Altera NiosII Max10"; + compatible = "altr,niosii-max10"; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu: cpu@0 { + u-boot,dm-pre-reloc; + device_type = "cpu"; + compatible = "altr,nios2-1.1"; + reg = <0x00000000>; + interrupt-controller; + #interrupt-cells = <1>; + altr,exception-addr = <0xc8000120>; + altr,fast-tlb-miss-addr = <0xc0000100>; + altr,has-div = <1>; + altr,has-initda = <1>; + altr,has-mmu = <1>; + altr,has-mul = <1>; + altr,implementation = "fast"; + altr,pid-num-bits = <8>; + altr,reset-addr = <0xd4000000>; + altr,tlb-num-entries = <256>; + altr,tlb-num-ways = <16>; + altr,tlb-ptr-sz = <8>; + clock-frequency = <75000000>; + dcache-line-size = <32>; + dcache-size = <32768>; + icache-line-size = <32>; + icache-size = <32768>; + }; + }; + + memory { + device_type = "memory"; + reg = <0x08000000 0x08000000>, + <0x00000000 0x00000400>; + }; + + sopc0: sopc@0 { + device_type = "soc"; + ranges; + #address-cells = <1>; + #size-cells = <1>; + compatible = "altr,avalon", "simple-bus"; + bus-frequency = <75000000>; + + jtag_uart: serial@18001530 { + compatible = "altr,juart-1.0"; + reg = <0x18001530 0x00000008>; + interrupt-parent = <&cpu>; + interrupts = <7>; + }; + + a_16550_uart_0: serial@18001600 { + compatible = "altr,16550-FIFO32", "ns16550a"; + reg = <0x18001600 0x00000200>; + interrupt-parent = <&cpu>; + interrupts = <1>; + auto-flow-control = <1>; + clock-frequency = <50000000>; + fifo-size = <32>; + reg-io-width = <4>; + reg-shift = <2>; + }; + + ext_flash: quadspi@0x180014a0 { + compatible = "altr,quadspi-1.0"; + reg = <0x180014a0 0x00000020>, + <0x14000000 0x04000000>; + reg-names = "avl_csr", "avl_mem"; + interrupt-parent = <&cpu>; + interrupts = <4>; + #address-cells = <1>; + #size-cells = <0>; + flash0: nor0@0 { + compatible = "micron,n25q512a"; + #address-cells = <1>; + #size-cells = <1>; + }; + }; + + sysid: sysid@18001528 { + compatible = "altr,sysid-1.0"; + reg = <0x18001528 0x00000008>; + }; + + rgmii_0_eth_tse_0: ethernet@400 { + compatible = "altr,tse-msgdma-1.0", "altr,tse-1.0"; + reg = <0x00000400 0x00000400>, + <0x00000820 0x00000020>, + <0x00000800 0x00000020>, + <0x000008c0 0x00000008>, + <0x00000840 0x00000020>, + <0x00000860 0x00000020>; + reg-names = "control_port", "rx_csr", "rx_desc", "rx_resp", + "tx_csr", "tx_desc"; + interrupt-parent = <&cpu>; + interrupts = <2 3>; + interrupt-names = "rx_irq", "tx_irq"; + rx-fifo-depth = <8192>; + tx-fifo-depth = <8192>; + address-bits = <48>; + max-frame-size = <1518>; + local-mac-address = [00 00 00 00 00 00]; + altr,has-supplementary-unicast; + altr,enable-sup-addr = <1>; + altr,has-hash-multicast-filter; + altr,enable-hash = <1>; + phy-mode = "rgmii-id"; + phy-handle = <&phy0>; + rgmii_0_eth_tse_0_mdio: mdio { + compatible = "altr,tse-mdio"; + #address-cells = <1>; + #size-cells = <0>; + phy0: ethernet-phy@0 { + reg = <0>; + device_type = "ethernet-phy"; + }; + }; + }; + + enet_pll: clock@0 { + compatible = "altr,pll-1.0"; + #clock-cells = <1>; + + enet_pll_c0: enet_pll_c0 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <125000000>; + clock-output-names = "enet_pll-c0"; + }; + + enet_pll_c1: enet_pll_c1 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + clock-output-names = "enet_pll-c1"; + }; + + enet_pll_c2: enet_pll_c2 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <2500000>; + clock-output-names = "enet_pll-c2"; + }; + }; + + sys_pll: clock@1 { + compatible = "altr,pll-1.0"; + #clock-cells = <1>; + + sys_pll_c0: sys_pll_c0 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <100000000>; + clock-output-names = "sys_pll-c0"; + }; + + sys_pll_c1: sys_pll_c1 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <50000000>; + clock-output-names = "sys_pll-c1"; + }; + + sys_pll_c2: sys_pll_c2 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <75000000>; + clock-output-names = "sys_pll-c2"; + }; + }; + + sys_clk_timer: timer@18001440 { + compatible = "altr,timer-1.0"; + reg = <0x18001440 0x00000020>; + interrupt-parent = <&cpu>; + interrupts = <0>; + clock-frequency = <75000000>; + }; + + led_pio: gpio@180014d0 { + compatible = "altr,pio-1.0"; + reg = <0x180014d0 0x00000010>; + altr,gpio-bank-width = <4>; + resetvalue = <15>; + #gpio-cells = <2>; + gpio-controller; + gpio-bank-name = "led"; + }; + + uart_0: serial@0x18001420 { + compatible = "altr,uart-1.0"; + reg = <0x18001420 0x00000020>; + interrupt-parent = <&cpu>; + interrupts = <1>; + clock-frequency = <75000000>; + current-speed = <115200>; + }; + + button_pio: gpio@180014c0 { + compatible = "altr,pio-1.0"; + reg = <0x180014c0 0x00000010>; + interrupt-parent = <&cpu>; + interrupts = <6>; + altr,gpio-bank-width = <3>; + altr,interrupt-type = <2>; + edge_type = <1>; + level_trigger = <0>; + resetvalue = <0>; + #gpio-cells = <2>; + gpio-controller; + gpio-bank-name = "button"; + }; + + sys_clk_timer_1: timer@880 { + compatible = "altr,timer-1.0"; + reg = <0x00000880 0x00000020>; + interrupt-parent = <&cpu>; + interrupts = <5>; + clock-frequency = <75000000>; + }; + + fpga_leds: leds { + compatible = "gpio-leds"; + + led_fpga0: fpga0 { + label = "fpga_led0"; + gpios = <&led_pio 0 1>; + }; + + led_fpga1: fpga1 { + label = "fpga_led1"; + gpios = <&led_pio 1 1>; + }; + + led_fpga2: fpga2 { + label = "fpga_led2"; + gpios = <&led_pio 2 1>; + }; + + led_fpga3: fpga3 { + label = "fpga_led3"; + gpios = <&led_pio 3 1>; + }; + }; + }; + + chosen { + bootargs = "debug console=ttyS0,115200"; + stdout-path = &a_16550_uart_0; + }; +}; diff --git a/roms/u-boot/arch/nios2/dts/3c120_devboard.dts b/roms/u-boot/arch/nios2/dts/3c120_devboard.dts new file mode 100644 index 000000000..5a8493576 --- /dev/null +++ b/roms/u-boot/arch/nios2/dts/3c120_devboard.dts @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 Altera Corporation + * + * This file is generated by sopc2dts. + */ + +/dts-v1/; + +/ { + model = "altr,qsys_ghrd_3c120"; + compatible = "altr,qsys_ghrd_3c120"; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu: cpu@0x0 { + device_type = "cpu"; + compatible = "altr,nios2-1.0"; + reg = <0x00000000>; + interrupt-controller; + #interrupt-cells = <1>; + clock-frequency = <125000000>; + dcache-line-size = <32>; + icache-line-size = <32>; + dcache-size = <32768>; + icache-size = <32768>; + altr,implementation = "fast"; + altr,pid-num-bits = <8>; + altr,tlb-num-ways = <16>; + altr,tlb-num-entries = <128>; + altr,tlb-ptr-sz = <7>; + altr,has-div = <1>; + altr,has-mul = <1>; + altr,reset-addr = <0xc2800000>; + altr,fast-tlb-miss-addr = <0xc7fff400>; + altr,exception-addr = <0xd0000020>; + altr,has-initda = <1>; + altr,has-mmu = <1>; + }; + }; + + memory@0 { + device_type = "memory"; + reg = <0x10000000 0x08000000>, + <0x07fff400 0x00000400>; + }; + + sopc@0 { + device_type = "soc"; + ranges; + #address-cells = <1>; + #size-cells = <1>; + compatible = "altr,avalon", "simple-bus"; + bus-frequency = <125000000>; + + pb_cpu_to_io: bridge@0x8000000 { + compatible = "simple-bus"; + reg = <0x08000000 0x00800000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00002000 0x08002000 0x00002000>, + <0x00004000 0x08004000 0x00000400>, + <0x00004400 0x08004400 0x00000040>, + <0x00004800 0x08004800 0x00000040>, + <0x00004c80 0x08004c80 0x00000020>, + <0x00004cc0 0x08004cc0 0x00000010>, + <0x00004ce0 0x08004ce0 0x00000010>, + <0x00004d00 0x08004d00 0x00000010>, + <0x00004d40 0x08004d40 0x00000008>, + <0x00004d50 0x08004d50 0x00000008>, + <0x00008000 0x08008000 0x00000020>, + <0x00400000 0x08400000 0x00000020>; + + timer_1ms: timer@0x400000 { + compatible = "altr,timer-1.0"; + reg = <0x00400000 0x00000020>; + interrupt-parent = <&cpu>; + interrupts = <11>; + clock-frequency = <125000000>; + }; + + timer_0: timer@0x8000 { + compatible = "altr,timer-1.0"; + reg = < 0x00008000 0x00000020 >; + interrupt-parent = < &cpu >; + interrupts = < 5 >; + clock-frequency = < 125000000 >; + }; + + sysid: sysid@0x4d40 { + compatible = "altr,sysid-1.0"; + reg = <0x00004d40 0x00000008>; + }; + + jtag_uart: serial@0x4d50 { + compatible = "altr,juart-1.0"; + reg = <0x00004d50 0x00000008>; + interrupt-parent = <&cpu>; + interrupts = <1>; + }; + + tse_mac: ethernet@0x4000 { + compatible = "altr,tse-1.0"; + reg = <0x00004000 0x00000400>, + <0x00004400 0x00000040>, + <0x00004800 0x00000040>, + <0x00002000 0x00002000>; + reg-names = "control_port", "rx_csr", "tx_csr", "s1"; + interrupt-parent = <&cpu>; + interrupts = <2 3>; + interrupt-names = "rx_irq", "tx_irq"; + rx-fifo-depth = <8192>; + tx-fifo-depth = <8192>; + max-frame-size = <1518>; + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-mode = "rgmii-id"; + phy-handle = <&phy0>; + tse_mac_mdio: mdio { + compatible = "altr,tse-mdio"; + #address-cells = <1>; + #size-cells = <0>; + phy0: ethernet-phy@18 { + reg = <18>; + device_type = "ethernet-phy"; + }; + }; + }; + + uart: serial@0x4c80 { + compatible = "altr,uart-1.0"; + reg = <0x00004c80 0x00000020>; + interrupt-parent = <&cpu>; + interrupts = <10>; + current-speed = <115200>; + clock-frequency = <62500000>; + }; + + user_led_pio_8out: gpio@0x4cc0 { + compatible = "altr,pio-1.0"; + reg = <0x00004cc0 0x00000010>; + resetvalue = <255>; + altr,gpio-bank-width = <8>; + #gpio-cells = <2>; + gpio-controller; + gpio-bank-name = "led"; + }; + + user_dipsw_pio_8in: gpio@0x4ce0 { + compatible = "altr,pio-1.0"; + reg = <0x00004ce0 0x00000010>; + interrupt-parent = <&cpu>; + interrupts = <8>; + edge_type = <2>; + level_trigger = <0>; + resetvalue = <0>; + altr,gpio-bank-width = <8>; + #gpio-cells = <2>; + gpio-controller; + gpio-bank-name = "dipsw"; + }; + + user_pb_pio_4in: gpio@0x4d00 { + compatible = "altr,pio-1.0"; + reg = <0x00004d00 0x00000010>; + interrupt-parent = <&cpu>; + interrupts = <9>; + edge_type = <2>; + level_trigger = <0>; + resetvalue = <0>; + altr,gpio-bank-width = <4>; + #gpio-cells = <2>; + gpio-controller; + gpio-bank-name = "pb"; + }; + }; + + cfi_flash_64m: flash@0x0 { + compatible = "cfi-flash"; + reg = <0x00000000 0x04000000>; + bank-width = <2>; + device-width = <1>; + #address-cells = <1>; + #size-cells = <1>; + + partition@800000 { + reg = <0x00800000 0x01e00000>; + label = "JFFS2 Filesystem"; + }; + }; + }; + + chosen { + bootargs = "debug console=ttyJ0,115200"; + stdout-path = &jtag_uart; + }; +}; diff --git a/roms/u-boot/arch/nios2/dts/Makefile b/roms/u-boot/arch/nios2/dts/Makefile new file mode 100644 index 000000000..0014acfdf --- /dev/null +++ b/roms/u-boot/arch/nios2/dts/Makefile @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0+ + +dtb-y += $(CONFIG_DEFAULT_DEVICE_TREE:"%"=%).dtb + +targets += $(dtb-y) + +DTC_FLAGS += -R 4 -p 0x1000 + +PHONY += dtbs +dtbs: $(addprefix $(obj)/, $(dtb-y)) + @: + +clean-files := *.dtb diff --git a/roms/u-boot/arch/nios2/dts/include/dt-bindings b/roms/u-boot/arch/nios2/dts/include/dt-bindings new file mode 120000 index 000000000..0cecb3d08 --- /dev/null +++ b/roms/u-boot/arch/nios2/dts/include/dt-bindings @@ -0,0 +1 @@ +../../../../include/dt-bindings
\ No newline at end of file diff --git a/roms/u-boot/arch/nios2/include/asm/bitops.h b/roms/u-boot/arch/nios2/include/asm/bitops.h new file mode 100644 index 000000000..289da1843 --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/bitops.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + */ + +#ifndef __ASM_NIOS2_BITOPS_H_ +#define __ASM_NIOS2_BITOPS_H_ + +/* copied from linux-2.6/include/asm-generic/bitops */ +#include <asm/bitops/atomic.h> +#include <asm/bitops/non-atomic.h> +#include <asm/bitops/ffs.h> + +#include <asm-generic/bitops/fls.h> +#include <asm-generic/bitops/__fls.h> +#include <asm-generic/bitops/fls64.h> +#include <asm-generic/bitops/__ffs.h> + +#endif /* __ASM_NIOS2_BITOPS_H */ diff --git a/roms/u-boot/arch/nios2/include/asm/bitops/atomic.h b/roms/u-boot/arch/nios2/include/asm/bitops/atomic.h new file mode 100644 index 000000000..c8946465e --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/bitops/atomic.h @@ -0,0 +1,189 @@ +#ifndef _ASM_GENERIC_BITOPS_ATOMIC_H_ +#define _ASM_GENERIC_BITOPS_ATOMIC_H_ + +#include <asm/types.h> +#include <asm/system.h> + +#ifdef CONFIG_SMP +#include <asm/spinlock.h> +#include <asm/cache.h> /* we use L1_CACHE_BYTES */ + +/* Use an array of spinlocks for our atomic_ts. + * Hash function to index into a different SPINLOCK. + * Since "a" is usually an address, use one spinlock per cacheline. + */ +# define ATOMIC_HASH_SIZE 4 +# define ATOMIC_HASH(a) (&(__atomic_hash[ (((unsigned long) a)/L1_CACHE_BYTES) & (ATOMIC_HASH_SIZE-1) ])) + +extern raw_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned; + +/* Can't use raw_spin_lock_irq because of #include problems, so + * this is the substitute */ +#define _atomic_spin_lock_irqsave(l,f) do { \ + raw_spinlock_t *s = ATOMIC_HASH(l); \ + local_irq_save(f); \ + __raw_spin_lock(s); \ +} while(0) + +#define _atomic_spin_unlock_irqrestore(l,f) do { \ + raw_spinlock_t *s = ATOMIC_HASH(l); \ + __raw_spin_unlock(s); \ + local_irq_restore(f); \ +} while(0) + + +#else +# define _atomic_spin_lock_irqsave(l,f) do { local_irq_save(f); } while (0) +# define _atomic_spin_unlock_irqrestore(l,f) do { local_irq_restore(f); } while (0) +#endif + +/* + * NMI events can occur at any time, including when interrupts have been + * disabled by *_irqsave(). So you can get NMI events occurring while a + * *_bit function is holding a spin lock. If the NMI handler also wants + * to do bit manipulation (and they do) then you can get a deadlock + * between the original caller of *_bit() and the NMI handler. + * + * by Keith Owens + */ + +/** + * set_bit - Atomically set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * This function is atomic and may not be reordered. See __set_bit() + * if you do not require the atomic guarantees. + * + * Note: there are no guarantees that this function will not be reordered + * on non x86 architectures, so if you are writing portable code, + * make sure not to rely on its reordering guarantees. + * + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static inline void set_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + unsigned long flags; + + _atomic_spin_lock_irqsave(p, flags); + *p |= mask; + _atomic_spin_unlock_irqrestore(p, flags); +} + +/** + * clear_bit - Clears a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * clear_bit() is atomic and may not be reordered. However, it does + * not contain a memory barrier, so if it is used for locking purposes, + * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() + * in order to ensure changes are visible on other processors. + */ +static inline void clear_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + unsigned long flags; + + _atomic_spin_lock_irqsave(p, flags); + *p &= ~mask; + _atomic_spin_unlock_irqrestore(p, flags); +} + +/** + * change_bit - Toggle a bit in memory + * @nr: Bit to change + * @addr: Address to start counting from + * + * change_bit() is atomic and may not be reordered. It may be + * reordered on other architectures than x86. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static inline void change_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + unsigned long flags; + + _atomic_spin_lock_irqsave(p, flags); + *p ^= mask; + _atomic_spin_unlock_irqrestore(p, flags); +} + +/** + * test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It may be reordered on other architectures than x86. + * It also implies a memory barrier. + */ +static inline int test_and_set_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + unsigned long old; + unsigned long flags; + + _atomic_spin_lock_irqsave(p, flags); + old = *p; + *p = old | mask; + _atomic_spin_unlock_irqrestore(p, flags); + + return (old & mask) != 0; +} + +/** + * test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to clear + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It can be reorderdered on other architectures other than x86. + * It also implies a memory barrier. + */ +static inline int test_and_clear_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + unsigned long old; + unsigned long flags; + + _atomic_spin_lock_irqsave(p, flags); + old = *p; + *p = old & ~mask; + _atomic_spin_unlock_irqrestore(p, flags); + + return (old & mask) != 0; +} + +/** + * test_and_change_bit - Change a bit and return its old value + * @nr: Bit to change + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +static inline int test_and_change_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + unsigned long old; + unsigned long flags; + + _atomic_spin_lock_irqsave(p, flags); + old = *p; + *p = old ^ mask; + _atomic_spin_unlock_irqrestore(p, flags); + + return (old & mask) != 0; +} + +#endif /* _ASM_GENERIC_BITOPS_ATOMIC_H */ diff --git a/roms/u-boot/arch/nios2/include/asm/bitops/ffs.h b/roms/u-boot/arch/nios2/include/asm/bitops/ffs.h new file mode 100644 index 000000000..fbbb43af7 --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/bitops/ffs.h @@ -0,0 +1,41 @@ +#ifndef _ASM_GENERIC_BITOPS_FFS_H_ +#define _ASM_GENERIC_BITOPS_FFS_H_ + +/** + * ffs - find first bit set + * @x: the word to search + * + * This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ +static inline int ffs(int x) +{ + int r = 1; + + if (!x) + return 0; + if (!(x & 0xffff)) { + x >>= 16; + r += 16; + } + if (!(x & 0xff)) { + x >>= 8; + r += 8; + } + if (!(x & 0xf)) { + x >>= 4; + r += 4; + } + if (!(x & 3)) { + x >>= 2; + r += 2; + } + if (!(x & 1)) { + x >>= 1; + r += 1; + } + return r; +} + +#endif /* _ASM_GENERIC_BITOPS_FFS_H_ */ diff --git a/roms/u-boot/arch/nios2/include/asm/bitops/non-atomic.h b/roms/u-boot/arch/nios2/include/asm/bitops/non-atomic.h new file mode 100644 index 000000000..f746819b4 --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/bitops/non-atomic.h @@ -0,0 +1,112 @@ +#ifndef _ASM_GENERIC_BITOPS_NON_ATOMIC_H_ +#define _ASM_GENERIC_BITOPS_NON_ATOMIC_H_ + +#include <asm/types.h> + +/** + * __set_bit - Set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike set_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +static inline void __set_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + + *p |= mask; +} + +#define PLATFORM__SET_BIT + +static inline void __clear_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + + *p &= ~mask; +} + +#define PLATFORM__CLEAR_BIT + +/** + * __change_bit - Toggle a bit in memory + * @nr: the bit to change + * @addr: the address to start counting from + * + * Unlike change_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +static inline void __change_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + + *p ^= mask; +} + +/** + * __test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + * If two examples of this operation race, one can appear to succeed + * but actually fail. You must protect multiple accesses with a lock. + */ +static inline int __test_and_set_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + unsigned long old = *p; + + *p = old | mask; + return (old & mask) != 0; +} + +/** + * __test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to clear + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + * If two examples of this operation race, one can appear to succeed + * but actually fail. You must protect multiple accesses with a lock. + */ +static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + unsigned long old = *p; + + *p = old & ~mask; + return (old & mask) != 0; +} + +/* WARNING: non atomic and it can be reordered! */ +static inline int __test_and_change_bit(int nr, + volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + unsigned long old = *p; + + *p = old ^ mask; + return (old & mask) != 0; +} + +/** + * test_bit - Determine whether a bit is set + * @nr: bit number to test + * @addr: Address to start counting from + */ +static inline int test_bit(int nr, const volatile unsigned long *addr) +{ + return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); +} + +#endif /* _ASM_GENERIC_BITOPS_NON_ATOMIC_H_ */ diff --git a/roms/u-boot/arch/nios2/include/asm/byteorder.h b/roms/u-boot/arch/nios2/include/asm/byteorder.h new file mode 100644 index 000000000..5d96b31c9 --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/byteorder.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + */ + +#ifndef __ASM_NIOS2_BYTEORDER_H_ +#define __ASM_NIOS2_BYTEORDER_H_ + +#include <asm/types.h> + +#if !defined(__STRICT_ANSI__) || defined(__KERNEL__) +# define __BYTEORDER_HAS_U64__ +# define __SWAB_64_THRU_32__ +#endif + +#include <linux/byteorder/little_endian.h> + +#endif /* __ASM_NIOS2_BYTEORDER_H_ */ diff --git a/roms/u-boot/arch/nios2/include/asm/cache.h b/roms/u-boot/arch/nios2/include/asm/cache.h new file mode 100644 index 000000000..57848840d --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/cache.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + */ + +#ifndef __ASM_NIOS2_CACHE_H_ +#define __ASM_NIOS2_CACHE_H_ + +/* + * Valid L1 data cache line sizes for the NIOS2 architecture are 4, + * 16, and 32 bytes. We default to the largest of these values for + * alignment of DMA buffers. + */ +#define ARCH_DMA_MINALIGN 32 + +#endif /* __ASM_NIOS2_CACHE_H_ */ diff --git a/roms/u-boot/arch/nios2/include/asm/config.h b/roms/u-boot/arch/nios2/include/asm/config.h new file mode 100644 index 000000000..bad002664 --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/config.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2009 Freescale Semiconductor, Inc. + */ + +#ifndef _ASM_CONFIG_H_ +#define _ASM_CONFIG_H_ + +#endif diff --git a/roms/u-boot/arch/nios2/include/asm/dma-mapping.h b/roms/u-boot/arch/nios2/include/asm/dma-mapping.h new file mode 100644 index 000000000..65f67bc1f --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/dma-mapping.h @@ -0,0 +1,24 @@ +#ifndef __ASM_NIOS2_DMA_MAPPING_H +#define __ASM_NIOS2_DMA_MAPPING_H + +#include <memalign.h> +#include <asm/io.h> + +/* + * dma_alloc_coherent() return cache-line aligned allocation which is mapped + * to uncached io region. + */ +static inline void *dma_alloc_coherent(size_t len, unsigned long *handle) +{ + unsigned long addr = (unsigned long)malloc_cache_aligned(len); + + if (!addr) + return NULL; + + invalidate_dcache_range(addr, addr + len); + if (handle) + *handle = addr; + + return map_physmem(addr, len, MAP_NOCACHE); +} +#endif /* __ASM_NIOS2_DMA_MAPPING_H */ diff --git a/roms/u-boot/arch/nios2/include/asm/global_data.h b/roms/u-boot/arch/nios2/include/asm/global_data.h new file mode 100644 index 000000000..1a0e7d25f --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/global_data.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + */ +#ifndef __ASM_NIOS2_GLOBALDATA_H_ +#define __ASM_NIOS2_GLOBALDATA_H_ + +/* Architecture-specific global data */ +struct arch_global_data { + u32 dcache_line_size; + u32 icache_line_size; + u32 dcache_size; + u32 icache_size; + u32 reset_addr; + u32 exception_addr; + int has_initda; + int has_mmu; + u32 io_region_base; + u32 mem_region_base; + u32 physaddr_mask; +}; + +#include <asm-generic/global_data.h> + +#define DECLARE_GLOBAL_DATA_PTR register gd_t *gd asm ("gp") + +#endif /* __ASM_NIOS2_GLOBALDATA_H_ */ diff --git a/roms/u-boot/arch/nios2/include/asm/gpio.h b/roms/u-boot/arch/nios2/include/asm/gpio.h new file mode 100644 index 000000000..306ab4c9f --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/gpio.h @@ -0,0 +1 @@ +#include <asm-generic/gpio.h> diff --git a/roms/u-boot/arch/nios2/include/asm/io.h b/roms/u-boot/arch/nios2/include/asm/io.h new file mode 100644 index 000000000..817cd72e0 --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/io.h @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + */ + +#ifndef __ASM_NIOS2_IO_H_ +#define __ASM_NIOS2_IO_H_ + +#include <asm/global_data.h> + +static inline void sync(void) +{ + __asm__ __volatile__ ("sync" : : : "memory"); +} + +/* + * Given a physical address and a length, return a virtual address + * that can be used to access the memory range with the caching + * properties specified by "flags". + */ +#define MAP_NOCACHE 1 + +static inline void * +map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags) +{ + DECLARE_GLOBAL_DATA_PTR; + if (flags) + return (void *)(paddr | gd->arch.io_region_base); + else + return (void *)(paddr | gd->arch.mem_region_base); +} +#define map_physmem map_physmem + +static inline void *phys_to_virt(phys_addr_t paddr) +{ + DECLARE_GLOBAL_DATA_PTR; + + return (void *)(paddr | gd->arch.mem_region_base); +} +#define phys_to_virt phys_to_virt + +static inline phys_addr_t virt_to_phys(void * vaddr) +{ + DECLARE_GLOBAL_DATA_PTR; + return (phys_addr_t)vaddr & gd->arch.physaddr_mask; +} +#define virt_to_phys virt_to_phys + +#define __raw_writeb(v,a) (*(volatile unsigned char *)(a) = (v)) +#define __raw_writew(v,a) (*(volatile unsigned short *)(a) = (v)) +#define __raw_writel(v,a) (*(volatile unsigned int *)(a) = (v)) + +#define __raw_readb(a) (*(volatile unsigned char *)(a)) +#define __raw_readw(a) (*(volatile unsigned short *)(a)) +#define __raw_readl(a) (*(volatile unsigned int *)(a)) + +#define readb(addr)\ + ({unsigned char val;\ + asm volatile( "ldbio %0, 0(%1)" :"=r"(val) : "r" (addr)); val;}) +#define readw(addr)\ + ({unsigned short val;\ + asm volatile( "ldhio %0, 0(%1)" :"=r"(val) : "r" (addr)); val;}) +#define readl(addr)\ + ({unsigned long val;\ + asm volatile( "ldwio %0, 0(%1)" :"=r"(val) : "r" (addr)); val;}) + +#define writeb(val,addr)\ + asm volatile ("stbio %0, 0(%1)" : : "r" (val), "r" (addr)) +#define writew(val,addr)\ + asm volatile ("sthio %0, 0(%1)" : : "r" (val), "r" (addr)) +#define writel(val,addr)\ + asm volatile ("stwio %0, 0(%1)" : : "r" (val), "r" (addr)) + +#define inb(addr) readb(addr) +#define inw(addr) readw(addr) +#define inl(addr) readl(addr) +#define outb(val, addr) writeb(val,addr) +#define outw(val, addr) writew(val,addr) +#define outl(val, addr) writel(val,addr) + +static inline void insb (unsigned long port, void *dst, unsigned long count) +{ + unsigned char *p = dst; + while (count--) *p++ = inb (port); +} +static inline void insw (unsigned long port, void *dst, unsigned long count) +{ + unsigned short *p = dst; + while (count--) *p++ = inw (port); +} +static inline void insl (unsigned long port, void *dst, unsigned long count) +{ + unsigned long *p = dst; + while (count--) *p++ = inl (port); +} + +static inline void outsb (unsigned long port, const void *src, unsigned long count) +{ + const unsigned char *p = src; + while (count--) outb (*p++, port); +} + +static inline void outsw (unsigned long port, const void *src, unsigned long count) +{ + const unsigned short *p = src; + while (count--) outw (*p++, port); +} +static inline void outsl (unsigned long port, const void *src, unsigned long count) +{ + const unsigned long *p = src; + while (count--) outl (*p++, port); +} + +/* + * Clear and set bits in one shot. These macros can be used to clear and + * set multiple bits in a register using a single call. These macros can + * also be used to set a multiple-bit bit pattern using a mask, by + * specifying the mask in the 'clear' parameter and the new bit pattern + * in the 'set' parameter. + */ + +#define out_arch(type,endian,a,v) __raw_write##type(cpu_to_##endian(v),a) +#define in_arch(type,endian,a) endian##_to_cpu(__raw_read##type(a)) + +#define out_le32(a,v) out_arch(l,le32,a,v) +#define out_le16(a,v) out_arch(w,le16,a,v) + +#define in_le32(a) in_arch(l,le32,a) +#define in_le16(a) in_arch(w,le16,a) + +#define out_be32(a,v) out_arch(l,be32,a,v) +#define out_be16(a,v) out_arch(w,be16,a,v) + +#define in_be32(a) in_arch(l,be32,a) +#define in_be16(a) in_arch(w,be16,a) + +#define out_8(a,v) __raw_writeb(v,a) +#define in_8(a) __raw_readb(a) + +#define clrbits(type, addr, clear) \ + out_##type((addr), in_##type(addr) & ~(clear)) + +#define setbits(type, addr, set) \ + out_##type((addr), in_##type(addr) | (set)) + +#define clrsetbits(type, addr, clear, set) \ + out_##type((addr), (in_##type(addr) & ~(clear)) | (set)) + +#define clrbits_be32(addr, clear) clrbits(be32, addr, clear) +#define setbits_be32(addr, set) setbits(be32, addr, set) +#define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set) + +#define clrbits_le32(addr, clear) clrbits(le32, addr, clear) +#define setbits_le32(addr, set) setbits(le32, addr, set) +#define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set) + +#define clrbits_be16(addr, clear) clrbits(be16, addr, clear) +#define setbits_be16(addr, set) setbits(be16, addr, set) +#define clrsetbits_be16(addr, clear, set) clrsetbits(be16, addr, clear, set) + +#define clrbits_le16(addr, clear) clrbits(le16, addr, clear) +#define setbits_le16(addr, set) setbits(le16, addr, set) +#define clrsetbits_le16(addr, clear, set) clrsetbits(le16, addr, clear, set) + +#define clrbits_8(addr, clear) clrbits(8, addr, clear) +#define setbits_8(addr, set) setbits(8, addr, set) +#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set) + +#define memset_io(a, b, c) memset((void *)(a), (b), (c)) +#define memcpy_fromio(a, b, c) memcpy((a), (void *)(b), (c)) +#define memcpy_toio(a, b, c) memcpy((void *)(a), (b), (c)) + +#include <asm-generic/io.h> +#include <asm/global_data.h> + +#endif /* __ASM_NIOS2_IO_H_ */ diff --git a/roms/u-boot/arch/nios2/include/asm/linkage.h b/roms/u-boot/arch/nios2/include/asm/linkage.h new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/linkage.h diff --git a/roms/u-boot/arch/nios2/include/asm/nios2.h b/roms/u-boot/arch/nios2/include/asm/nios2.h new file mode 100644 index 000000000..0872dd6ad --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/nios2.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + */ + +#ifndef __ASM_NIOS2_H__ +#define __ASM_NIOS2_H__ + +/*------------------------------------------------------------------------ + * Control registers -- use with wrctl() & rdctl() + *----------------------------------------------------------------------*/ +#define CTL_STATUS 0 /* Processor status reg */ +#define CTL_ESTATUS 1 /* Exception status reg */ +#define CTL_BSTATUS 2 /* Break status reg */ +#define CTL_IENABLE 3 /* Interrut enable reg */ +#define CTL_IPENDING 4 /* Interrut pending reg */ + +/*------------------------------------------------------------------------ + * Access to control regs + *----------------------------------------------------------------------*/ + +#define rdctl(reg) __builtin_rdctl(reg) +#define wrctl(reg, val) __builtin_wrctl(reg, val) + +/*------------------------------------------------------------------------ + * Control reg bit masks + *----------------------------------------------------------------------*/ +#define STATUS_IE (1<<0) /* Interrupt enable */ +#define STATUS_U (1<<1) /* User-mode */ + +/*------------------------------------------------------------------------ + * Bit-31 Cache bypass -- only valid for data access. When data cache + * is not implemented, bit 31 is ignored for compatibility. + *----------------------------------------------------------------------*/ +#define CACHE_BYPASS(a) ((a) | 0x80000000) +#define CACHE_NO_BYPASS(a) ((a) & ~0x80000000) + +#endif /* __ASM_NIOS2_H__ */ diff --git a/roms/u-boot/arch/nios2/include/asm/opcodes.h b/roms/u-boot/arch/nios2/include/asm/opcodes.h new file mode 100644 index 000000000..346cefa0a --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/opcodes.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + */ + +#ifndef __ASM_NIOS2_OPCODES_H_ +#define __ASM_NIOS2_OPCODES_H_ + +#define OPCODE_OP(inst) ((inst) & 0x3f) +#define OPCODE_OPX(inst) (((inst)>>11) & 0x3f) +#define OPCODE_RA(inst) (((inst)>>27) & 01f) +#define OPCODE_RB(inst) (((inst)>>22) & 01f) +#define OPCODE_RC(inst) (((inst)>>17) & 01f) + +/* I-TYPE (immediate) and J-TYPE (jump) opcodes + */ +#define OPCODE_CALL 0x00 +#define OPCODE_LDBU 0x03 +#define OPCODE_ADDI 0x04 +#define OPCODE_STB 0x05 +#define OPCODE_BR 0x06 +#define OPCODE_LDB 0x07 +#define OPCODE_CMPGEI 0x08 +#define OPCODE_LDHU 0x0B +#define OPCODE_ANDI 0x0C +#define OPCODE_STH 0x0D +#define OPCODE_BGE 0x0E +#define OPCODE_LDH 0x0F +#define OPCODE_CMPLTI 0x10 +#define OPCODE_XORI 0x1C +#define OPCODE_ORI 0x14 +#define OPCODE_STW 0x15 +#define OPCODE_BLT 0x16 +#define OPCODE_LDW 0x17 +#define OPCODE_CMPNEI 0x18 +#define OPCODE_BNE 0x1E +#define OPCODE_CMPEQI 0x20 +#define OPCODE_LDBUIO 0x23 +#define OPCODE_MULI 0x24 +#define OPCODE_STBIO 0x25 +#define OPCODE_BEQ 0x26 +#define OPCODE_LDBIO 0x27 +#define OPCODE_CMPGEUI 0x28 +#define OPCODE_ANDHI 0x2C +#define OPCODE_STHIO 0x2D +#define OPCODE_BGEU 0x2E +#define OPCODE_LDHIO 0x2F +#define OPCODE_CMPLTUI 0x30 +#define OPCODE_CUSTOM 0x32 +#define OPCODE_INITD 0x33 +#define OPCODE_ORHI 0x34 +#define OPCODE_STWIO 0x35 +#define OPCODE_BLTU 0x36 +#define OPCODE_LDWIO 0x37 +#define OPCODE_RTYPE 0x3A +#define OPCODE_LDHUIO 0x2B +#define OPCODE_FLUSHD 0x3B +#define OPCODE_XORHI 0x3C + +/* R-Type (register) OPX field encodings + */ +#define OPCODE_ERET 0x01 +#define OPCODE_ROLI 0x02 +#define OPCODE_ROL 0x03 +#define OPCODE_FLUSHP 0x04 +#define OPCODE_RET 0x05 +#define OPCODE_NOR 0x06 +#define OPCODE_MULXUU 0x07 +#define OPCODE_CMPGE 0x08 +#define OPCODE_BRET 0x09 +#define OPCODE_ROR 0x0B +#define OPCODE_FLUSHI 0x0C +#define OPCODE_JMP 0x0D +#define OPCODE_AND 0x0E + +#define OPCODE_CMPLT 0x10 +#define OPCODE_SLLI 0x12 +#define OPCODE_SLL 0x13 +#define OPCODE_OR 0x16 +#define OPCODE_MULXSU 0x17 +#define OPCODE_CMPNE 0x18 +#define OPCODE_SRLI 0x1A +#define OPCODE_SRL 0x1B +#define OPCODE_NEXTPC 0x1C +#define OPCODE_CALLR 0x1D +#define OPCODE_XOR 0x1E +#define OPCODE_MULXSS 0x1F + +#define OPCODE_CMPEQ 0x20 +#define OPCODE_CMPLTU 0x30 +#define OPCODE_ADD 0x31 +#define OPCODE_DIVU 0x24 +#define OPCODE_DIV 0x25 +#define OPCODE_RDCTL 0x26 +#define OPCODE_MUL 0x27 +#define OPCODE_CMPGEU 0x28 +#define OPCODE_TRAP 0x2D +#define OPCODE_WRCTL 0x2E + +#define OPCODE_BREAK 0x34 +#define OPCODE_SYNC 0x36 +#define OPCODE_INITI 0x29 +#define OPCODE_SUB 0x39 +#define OPCODE_SRAI 0x3A +#define OPCODE_SRA 0x3B + +/*Full instruction encodings for R-Type, without the R's ;-) + * + * TODO: BREAK, BRET, ERET, RET, SYNC (as needed) + */ +#define OPC_TRAP 0x003b683a + +#endif /* __ASM_NIOS2_OPCODES_H_ */ diff --git a/roms/u-boot/arch/nios2/include/asm/posix_types.h b/roms/u-boot/arch/nios2/include/asm/posix_types.h new file mode 100644 index 000000000..6b6c39bcc --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/posix_types.h @@ -0,0 +1,67 @@ +#ifndef __ASM_NIOS2_POSIX_TYPES_H_ +#define __ASM_NIOS2_POSIX_TYPES_H_ + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot + * assume GCC is being used. + */ + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +#ifdef __GNUC__ +typedef __SIZE_TYPE__ __kernel_size_t; +#else +typedef unsigned long __kernel_size_t; +#endif +typedef long __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; + +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; + +#ifdef __GNUC__ +typedef long long __kernel_loff_t; +#endif + +typedef struct { +#if defined(__KERNEL__) || defined(__USE_ALL) + int val[2]; +#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */ + int __val[2]; +#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */ +} __kernel_fsid_t; + +#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) + +#undef __FD_SET +#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d)) + +#undef __FD_CLR +#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d)) + +#undef __FD_ISSET +#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) + +#undef __FD_ZERO +#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp))) + +#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ + +#endif /* __ASM_NIOS2_POSIX_TYPES_H_ */ diff --git a/roms/u-boot/arch/nios2/include/asm/processor.h b/roms/u-boot/arch/nios2/include/asm/processor.h new file mode 100644 index 000000000..2ac4a4b4c --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/processor.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + */ + +#ifndef __ASM_NIOS2_PROCESSOR_H_ +#define __ASM_NIOS2_PROCESSOR_H_ +#endif /* __ASM_NIOS2_PROCESSOR_H_ */ diff --git a/roms/u-boot/arch/nios2/include/asm/ptrace.h b/roms/u-boot/arch/nios2/include/asm/ptrace.h new file mode 100644 index 000000000..317d8ae09 --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/ptrace.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + */ + +#ifndef __ASM_NIOS2_PTRACE_H_ +#define __ASM_NIOS2_PTRACE_H_ + +struct pt_regs { + unsigned reg[32]; + unsigned status; +}; + + +#endif /* __ASM_NIOS2_PTRACE_H_ */ diff --git a/roms/u-boot/arch/nios2/include/asm/sections.h b/roms/u-boot/arch/nios2/include/asm/sections.h new file mode 100644 index 000000000..2b8c51603 --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/sections.h @@ -0,0 +1 @@ +#include <asm-generic/sections.h> diff --git a/roms/u-boot/arch/nios2/include/asm/spl.h b/roms/u-boot/arch/nios2/include/asm/spl.h new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/spl.h diff --git a/roms/u-boot/arch/nios2/include/asm/string.h b/roms/u-boot/arch/nios2/include/asm/string.h new file mode 100644 index 000000000..69f4921fe --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/string.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + */ +#ifndef __ASM_NIOS2_STRING_H_ +#define __ASM_NIOS2_STRING_H_ + +#undef __HAVE_ARCH_STRRCHR +extern char * strrchr(const char * s, int c); + +#undef __HAVE_ARCH_STRCHR +extern char * strchr(const char * s, int c); + +#undef __HAVE_ARCH_MEMCPY +extern void * memcpy(void *, const void *, __kernel_size_t); + +#undef __HAVE_ARCH_MEMMOVE +extern void * memmove(void *, const void *, __kernel_size_t); + +#undef __HAVE_ARCH_MEMCHR +extern void * memchr(const void *, int, __kernel_size_t); + +#undef __HAVE_ARCH_MEMSET +extern void * memset(void *, int, __kernel_size_t); + +#undef __HAVE_ARCH_MEMZERO +extern void memzero(void *ptr, __kernel_size_t n); + +#endif /* __ASM_NIOS2_STRING_H_ */ diff --git a/roms/u-boot/arch/nios2/include/asm/system.h b/roms/u-boot/arch/nios2/include/asm/system.h new file mode 100644 index 000000000..33614d541 --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/system.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + */ +#ifndef __ASM_NIOS2_SYSTEM_H_ +#define __ASM_NIOS2_SYSTEM_H_ + +#define local_irq_enable() __asm__ __volatile__ ( \ + "rdctl r8, status\n" \ + "ori r8, r8, 1\n" \ + "wrctl status, r8\n" \ + : : : "r8") + +#define local_irq_disable() __asm__ __volatile__ ( \ + "rdctl r8, status\n" \ + "andi r8, r8, 0xfffe\n" \ + "wrctl status, r8\n" \ + : : : "r8") + +#define local_save_flags(x) __asm__ __volatile__ ( \ + "rdctl r8, status\n" \ + "mov %0, r8\n" \ + : "=r" (x) : : "r8", "memory") + +#define local_irq_restore(x) __asm__ __volatile__ ( \ + "mov r8, %0\n" \ + "wrctl status, r8\n" \ + : : "r" (x) : "r8", "memory") + +/* For spinlocks etc */ +#define local_irq_save(x) do { local_save_flags(x); local_irq_disable(); } \ + while (0) + +#define irqs_disabled() \ +({ \ + unsigned long flags; \ + local_save_flags(flags); \ + ((flags & NIOS2_STATUS_PIE_MSK) == 0x0); \ +}) + +/* indirect call to go beyond 256MB limitation of toolchain */ +#define nios2_callr(addr) __asm__ __volatile__ ( \ + "callr %0" \ + : : "r" (addr)) + +void display_sysid(void); + +#endif /* __ASM_NIOS2_SYSTEM_H */ diff --git a/roms/u-boot/arch/nios2/include/asm/types.h b/roms/u-boot/arch/nios2/include/asm/types.h new file mode 100644 index 000000000..ea859c077 --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/types.h @@ -0,0 +1,60 @@ +#ifndef __ASM_NIOS2_TYPES_H_ +#define __ASM_NIOS2_TYPES_H_ + +/* + * This file is never included by application software unless + * explicitly requested (e.g., via linux/types.h) in which case the + * application is Linux specific so (user-) name space pollution is + * not a major issue. However, for interoperability, libraries still + * need to be careful to avoid a name clashes. + */ + +typedef unsigned short umode_t; + +/* + * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the + * header files exported to user space + */ + +typedef __signed__ char __s8; +typedef unsigned char __u8; + +typedef __signed__ short __s16; +typedef unsigned short __u16; + +typedef __signed__ int __s32; +typedef unsigned int __u32; + +#if defined(__GNUC__) +__extension__ typedef __signed__ long long __s64; +__extension__ typedef unsigned long long __u64; +#endif + +/* + * These aren't exported outside the kernel to avoid name space clashes + */ +#ifdef __KERNEL__ + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long long s64; +typedef unsigned long long u64; + +#define BITS_PER_LONG 32 + +/* Dma addresses are 32-bits wide. */ + +typedef u32 dma_addr_t; + +typedef unsigned long phys_addr_t; +typedef unsigned long phys_size_t; +#endif /* __KERNEL__ */ + +#endif /* __ASM_NIOS2_TYPES_H */ diff --git a/roms/u-boot/arch/nios2/include/asm/u-boot.h b/roms/u-boot/arch/nios2/include/asm/u-boot.h new file mode 100644 index 000000000..f05006714 --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/u-boot.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + * + ******************************************************************** + * NOTE: This header file defines an interface to U-Boot. Including + * this (unmodified) header file in another file is considered normal + * use of U-Boot, and does *not* fall under the heading of "derived + * work". + ******************************************************************** + */ + +#ifndef __ASM_NIOS2_U_BOOT_H_ +#define __ASM_NIOS2_U_BOOT_H_ + +#include <asm-generic/u-boot.h> + +/* For image.h:image_check_target_arch() */ +#define IH_ARCH_DEFAULT IH_ARCH_NIOS2 + +#endif /* __ASM_NIOS2_U_BOOT_H_ */ diff --git a/roms/u-boot/arch/nios2/include/asm/unaligned.h b/roms/u-boot/arch/nios2/include/asm/unaligned.h new file mode 100644 index 000000000..6cecbbb21 --- /dev/null +++ b/roms/u-boot/arch/nios2/include/asm/unaligned.h @@ -0,0 +1 @@ +#include <asm-generic/unaligned.h> diff --git a/roms/u-boot/arch/nios2/lib/Makefile b/roms/u-boot/arch/nios2/lib/Makefile new file mode 100644 index 000000000..a9f3c7100 --- /dev/null +++ b/roms/u-boot/arch/nios2/lib/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +obj-y += cache.o +obj-$(CONFIG_CMD_BOOTM) += bootm.o +obj-y += libgcc.o diff --git a/roms/u-boot/arch/nios2/lib/bootm.c b/roms/u-boot/arch/nios2/lib/bootm.c new file mode 100644 index 000000000..2c8f9731c --- /dev/null +++ b/roms/u-boot/arch/nios2/lib/bootm.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2003, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + */ + +#include <common.h> +#include <cpu_func.h> +#include <env.h> +#include <image.h> +#include <irq_func.h> +#include <log.h> + +#define NIOS_MAGIC 0x534f494e /* enable command line and initrd passing */ + +int do_bootm_linux(int flag, int argc, char *const argv[], + bootm_headers_t *images) +{ + void (*kernel)(int, int, int, char *) = (void *)images->ep; + char *commandline = env_get("bootargs"); + ulong initrd_start = images->rd_start; + ulong initrd_end = images->rd_end; + char *of_flat_tree = NULL; +#if defined(CONFIG_OF_LIBFDT) + /* did generic code already find a device tree? */ + if (images->ft_len) + of_flat_tree = images->ft_addr; +#endif + if (!of_flat_tree && argc > 1) + of_flat_tree = (char *)simple_strtoul(argv[1], NULL, 16); + if (of_flat_tree) + initrd_end = (ulong)of_flat_tree; + + /* + * allow the PREP bootm subcommand, it is required for bootm to work + */ + if (flag & BOOTM_STATE_OS_PREP) + return 0; + + if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) + return 1; + + /* flushes data and instruction caches before calling the kernel */ + disable_interrupts(); + flush_dcache_all(); + + debug("bootargs=%s @ 0x%lx\n", commandline, (ulong)&commandline); + debug("initrd=0x%lx-0x%lx\n", (ulong)initrd_start, (ulong)initrd_end); + /* kernel parameters passing + * r4 : NIOS magic + * r5 : initrd start + * r6 : initrd end or fdt + * r7 : kernel command line + * fdt is passed to kernel via r6, the same as initrd_end. fdt will be + * verified with fdt magic. when both initrd and fdt are used at the + * same time, fdt must follow immediately after initrd. + */ + kernel(NIOS_MAGIC, initrd_start, initrd_end, commandline); + /* does not return */ + + return 1; +} diff --git a/roms/u-boot/arch/nios2/lib/cache.c b/roms/u-boot/arch/nios2/lib/cache.c new file mode 100644 index 000000000..5864d8f0f --- /dev/null +++ b/roms/u-boot/arch/nios2/lib/cache.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw> + * Copyright (C) 2009, Wind River Systems Inc + * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com + */ + +#include <common.h> +#include <cpu_func.h> +#include <asm/cache.h> +#include <asm/global_data.h> + +DECLARE_GLOBAL_DATA_PTR; + +static void __flush_dcache(unsigned long start, unsigned long end) +{ + unsigned long addr; + + start &= ~(gd->arch.dcache_line_size - 1); + end += (gd->arch.dcache_line_size - 1); + end &= ~(gd->arch.dcache_line_size - 1); + + for (addr = start; addr < end; addr += gd->arch.dcache_line_size) { + __asm__ __volatile__ (" flushda 0(%0)\n" + : /* Outputs */ + : /* Inputs */ "r"(addr) + /* : No clobber */); + } +} + +static void __flush_dcache_all(unsigned long start, unsigned long end) +{ + unsigned long addr; + + start &= ~(gd->arch.dcache_line_size - 1); + end += (gd->arch.dcache_line_size - 1); + end &= ~(gd->arch.dcache_line_size - 1); + + if (end > start + gd->arch.dcache_size) + end = start + gd->arch.dcache_size; + + for (addr = start; addr < end; addr += gd->arch.dcache_line_size) { + __asm__ __volatile__ (" flushd 0(%0)\n" + : /* Outputs */ + : /* Inputs */ "r"(addr) + /* : No clobber */); + } +} + +static void __invalidate_dcache(unsigned long start, unsigned long end) +{ + unsigned long addr; + + start &= ~(gd->arch.dcache_line_size - 1); + end += (gd->arch.dcache_line_size - 1); + end &= ~(gd->arch.dcache_line_size - 1); + + for (addr = start; addr < end; addr += gd->arch.dcache_line_size) { + __asm__ __volatile__ (" initda 0(%0)\n" + : /* Outputs */ + : /* Inputs */ "r"(addr) + /* : No clobber */); + } +} + +static void __flush_icache(unsigned long start, unsigned long end) +{ + unsigned long addr; + + start &= ~(gd->arch.icache_line_size - 1); + end += (gd->arch.icache_line_size - 1); + end &= ~(gd->arch.icache_line_size - 1); + + if (end > start + gd->arch.icache_size) + end = start + gd->arch.icache_size; + + for (addr = start; addr < end; addr += gd->arch.icache_line_size) { + __asm__ __volatile__ (" flushi %0\n" + : /* Outputs */ + : /* Inputs */ "r"(addr) + /* : No clobber */); + } + __asm__ __volatile(" flushp\n"); +} + +void flush_dcache_all(void) +{ + __flush_dcache_all(0, gd->arch.dcache_size); + __flush_icache(0, gd->arch.icache_size); +} + +void flush_dcache_range(unsigned long start, unsigned long end) +{ + if (gd->arch.has_initda) + __flush_dcache(start, end); + else + __flush_dcache_all(start, end); +} + +void flush_cache(unsigned long start, unsigned long size) +{ + if (gd->arch.has_initda) + __flush_dcache(start, start + size); + else + __flush_dcache_all(start, start + size); + __flush_icache(start, start + size); +} + +void invalidate_dcache_range(unsigned long start, unsigned long end) +{ + if (gd->arch.has_initda) + __invalidate_dcache(start, end); + else + __flush_dcache_all(start, end); +} + +int dcache_status(void) +{ + return 1; +} + +void dcache_enable(void) +{ + flush_dcache_all(); +} + +void dcache_disable(void) +{ + flush_dcache_all(); +} diff --git a/roms/u-boot/arch/nios2/lib/libgcc.c b/roms/u-boot/arch/nios2/lib/libgcc.c new file mode 100644 index 000000000..a45b3e82e --- /dev/null +++ b/roms/u-boot/arch/nios2/lib/libgcc.c @@ -0,0 +1,578 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * This file is part of GNU CC. + */ + +typedef unsigned int UWtype; +typedef unsigned int UHWtype; +typedef unsigned long long UDWtype; +#define W_TYPE_SIZE 32 + +typedef unsigned char UQItype; +typedef long SItype; +typedef unsigned long USItype; +typedef long long DItype; +typedef unsigned long long DSItype; + +#include "longlong.h" + + +typedef int word_type; +typedef long Wtype; +typedef long long DWtype; + +struct DWstruct { Wtype low, high;}; + +typedef union +{ + struct DWstruct s; + DWtype ll; +} DWunion; + +#define BITS_PER_UNIT 8 + +UDWtype +__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp); + +const UQItype __clz_tab[256] = +{ + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 +}; + + +DWtype +__ashldi3 (DWtype u, word_type b) +{ + if (b == 0) + return u; + + const DWunion uu = {.ll = u}; + const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b; + DWunion w; + + if (bm <= 0) + { + w.s.low = 0; + w.s.high = (UWtype) uu.s.low << -bm; + } + else + { + const UWtype carries = (UWtype) uu.s.low >> bm; + + w.s.low = (UWtype) uu.s.low << b; + w.s.high = ((UWtype) uu.s.high << b) | carries; + } + + return w.ll; +} + +DWtype +__ashrdi3 (DWtype u, word_type b) +{ + if (b == 0) + return u; + + const DWunion uu = {.ll = u}; + const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b; + DWunion w; + + if (bm <= 0) + { + /* w.s.high = 1..1 or 0..0 */ + w.s.high = uu.s.high >> (sizeof (Wtype) * BITS_PER_UNIT - 1); + w.s.low = uu.s.high >> -bm; + } + else + { + const UWtype carries = (UWtype) uu.s.high << bm; + + w.s.high = uu.s.high >> b; + w.s.low = ((UWtype) uu.s.low >> b) | carries; + } + + return w.ll; +} + +DWtype +__lshrdi3 (DWtype u, word_type b) +{ + if (b == 0) + return u; + + const DWunion uu = {.ll = u}; + const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b; + DWunion w; + + if (bm <= 0) + { + w.s.high = 0; + w.s.low = (UWtype) uu.s.high >> -bm; + } + else + { + const UWtype carries = (UWtype) uu.s.high << bm; + + w.s.high = (UWtype) uu.s.high >> b; + w.s.low = ((UWtype) uu.s.low >> b) | carries; + } + + return w.ll; +} + +word_type +__cmpdi2 (DWtype a, DWtype b) +{ + const DWunion au = {.ll = a}; + const DWunion bu = {.ll = b}; + + if (au.s.high < bu.s.high) + return 0; + else if (au.s.high > bu.s.high) + return 2; + if ((UWtype) au.s.low < (UWtype) bu.s.low) + return 0; + else if ((UWtype) au.s.low > (UWtype) bu.s.low) + return 2; + return 1; +} + +UDWtype +__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp) +{ + const DWunion nn = {.ll = n}; + const DWunion dd = {.ll = d}; + DWunion rr; + UWtype d0, d1, n0, n1, n2; + UWtype q0, q1; + UWtype b, bm; + + d0 = dd.s.low; + d1 = dd.s.high; + n0 = nn.s.low; + n1 = nn.s.high; + +#if !UDIV_NEEDS_NORMALIZATION + if (d1 == 0) + { + if (d0 > n1) + { + /* 0q = nn / 0D */ + + udiv_qrnnd (q0, n0, n1, n0, d0); + q1 = 0; + + /* Remainder in n0. */ + } + else + { + /* qq = NN / 0d */ + + if (d0 == 0) + d0 = 1 / d0; /* Divide intentionally by zero. */ + + udiv_qrnnd (q1, n1, 0, n1, d0); + udiv_qrnnd (q0, n0, n1, n0, d0); + + /* Remainder in n0. */ + } + + if (rp != 0) + { + rr.s.low = n0; + rr.s.high = 0; + *rp = rr.ll; + } + } + +#else /* UDIV_NEEDS_NORMALIZATION */ + + if (d1 == 0) + { + if (d0 > n1) + { + /* 0q = nn / 0D */ + + count_leading_zeros (bm, d0); + + if (bm != 0) + { + /* Normalize, i.e. make the most significant bit of the + denominator set. */ + + d0 = d0 << bm; + n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm)); + n0 = n0 << bm; + } + + udiv_qrnnd (q0, n0, n1, n0, d0); + q1 = 0; + + /* Remainder in n0 >> bm. */ + } + else + { + /* qq = NN / 0d */ + + if (d0 == 0) + d0 = 1 / d0; /* Divide intentionally by zero. */ + + count_leading_zeros (bm, d0); + + if (bm == 0) + { + /* From (n1 >= d0) /\ (the most significant bit of d0 is set), + conclude (the most significant bit of n1 is set) /\ (the + leading quotient digit q1 = 1). + + This special case is necessary, not an optimization. + (Shifts counts of W_TYPE_SIZE are undefined.) */ + + n1 -= d0; + q1 = 1; + } + else + { + /* Normalize. */ + + b = W_TYPE_SIZE - bm; + + d0 = d0 << bm; + n2 = n1 >> b; + n1 = (n1 << bm) | (n0 >> b); + n0 = n0 << bm; + + udiv_qrnnd (q1, n1, n2, n1, d0); + } + + /* n1 != d0... */ + + udiv_qrnnd (q0, n0, n1, n0, d0); + + /* Remainder in n0 >> bm. */ + } + + if (rp != 0) + { + rr.s.low = n0 >> bm; + rr.s.high = 0; + *rp = rr.ll; + } + } +#endif /* UDIV_NEEDS_NORMALIZATION */ + + else + { + if (d1 > n1) + { + /* 00 = nn / DD */ + + q0 = 0; + q1 = 0; + + /* Remainder in n1n0. */ + if (rp != 0) + { + rr.s.low = n0; + rr.s.high = n1; + *rp = rr.ll; + } + } + else + { + /* 0q = NN / dd */ + + count_leading_zeros (bm, d1); + if (bm == 0) + { + /* From (n1 >= d1) /\ (the most significant bit of d1 is set), + conclude (the most significant bit of n1 is set) /\ (the + quotient digit q0 = 0 or 1). + + This special case is necessary, not an optimization. */ + + /* The condition on the next line takes advantage of that + n1 >= d1 (true due to program flow). */ + if (n1 > d1 || n0 >= d0) + { + q0 = 1; + sub_ddmmss (n1, n0, n1, n0, d1, d0); + } + else + q0 = 0; + + q1 = 0; + + if (rp != 0) + { + rr.s.low = n0; + rr.s.high = n1; + *rp = rr.ll; + } + } + else + { + UWtype m1, m0; + /* Normalize. */ + + b = W_TYPE_SIZE - bm; + + d1 = (d1 << bm) | (d0 >> b); + d0 = d0 << bm; + n2 = n1 >> b; + n1 = (n1 << bm) | (n0 >> b); + n0 = n0 << bm; + + udiv_qrnnd (q0, n1, n2, n1, d1); + umul_ppmm (m1, m0, q0, d0); + + if (m1 > n1 || (m1 == n1 && m0 > n0)) + { + q0--; + sub_ddmmss (m1, m0, m1, m0, d1, d0); + } + + q1 = 0; + + /* Remainder in (n1n0 - m1m0) >> bm. */ + if (rp != 0) + { + sub_ddmmss (n1, n0, n1, n0, m1, m0); + rr.s.low = (n1 << b) | (n0 >> bm); + rr.s.high = n1 >> bm; + *rp = rr.ll; + } + } + } + } + + const DWunion ww = {{.low = q0, .high = q1}}; + return ww.ll; +} + +DWtype +__divdi3 (DWtype u, DWtype v) +{ + word_type c = 0; + DWunion uu = {.ll = u}; + DWunion vv = {.ll = v}; + DWtype w; + + if (uu.s.high < 0) + c = ~c, + uu.ll = -uu.ll; + if (vv.s.high < 0) + c = ~c, + vv.ll = -vv.ll; + + w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0); + if (c) + w = -w; + + return w; +} + +DWtype +__negdi2 (DWtype u) +{ + const DWunion uu = {.ll = u}; + const DWunion w = { {.low = -uu.s.low, + .high = -uu.s.high - ((UWtype) -uu.s.low > 0) } }; + + return w.ll; +} + + +DWtype +__muldi3 (DWtype u, DWtype v) +{ + const DWunion uu = {.ll = u}; + const DWunion vv = {.ll = v}; + DWunion w = {.ll = __umulsidi3 (uu.s.low, vv.s.low)}; + + w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high + + (UWtype) uu.s.high * (UWtype) vv.s.low); + + return w.ll; +} + +DWtype +__moddi3 (DWtype u, DWtype v) +{ + word_type c = 0; + DWunion uu = {.ll = u}; + DWunion vv = {.ll = v}; + DWtype w; + + if (uu.s.high < 0) + c = ~c, + uu.ll = -uu.ll; + if (vv.s.high < 0) + vv.ll = -vv.ll; + + (void) __udivmoddi4 (uu.ll, vv.ll, (UDWtype*)&w); + if (c) + w = -w; + + return w; +} + +word_type +__ucmpdi2 (DWtype a, DWtype b) +{ + const DWunion au = {.ll = a}; + const DWunion bu = {.ll = b}; + + if ((UWtype) au.s.high < (UWtype) bu.s.high) + return 0; + else if ((UWtype) au.s.high > (UWtype) bu.s.high) + return 2; + if ((UWtype) au.s.low < (UWtype) bu.s.low) + return 0; + else if ((UWtype) au.s.low > (UWtype) bu.s.low) + return 2; + return 1; +} + + +UDWtype +__udivdi3 (UDWtype n, UDWtype d) +{ + return __udivmoddi4 (n, d, (UDWtype *) 0); +} + +UDWtype +__umoddi3 (UDWtype u, UDWtype v) +{ + UDWtype w; + (void) __udivmoddi4 (u, v, &w); + + return w; +} + +static USItype +udivmodsi4(USItype num, USItype den, word_type modwanted) +{ + USItype bit = 1; + USItype res = 0; + + while (den < num && bit && !(den & (1L<<31))) + { + den <<=1; + bit <<=1; + } + while (bit) + { + if (num >= den) + { + num -= den; + res |= bit; + } + bit >>=1; + den >>=1; + } + if (modwanted) return num; + return res; +} + +SItype +__divsi3 (SItype a, SItype b) +{ + word_type neg = 0; + SItype res; + + if (a < 0) + { + a = -a; + neg = !neg; + } + + if (b < 0) + { + b = -b; + neg = !neg; + } + + res = udivmodsi4 (a, b, 0); + + if (neg) + res = -res; + + return res; +} + + +SItype +__udivsi3 (SItype a, SItype b) +{ + return udivmodsi4 (a, b, 0); +} + + +SItype +__modsi3 (SItype a, SItype b) +{ + word_type neg = 0; + SItype res; + + if (a < 0) + { + a = -a; + neg = 1; + } + + if (b < 0) + b = -b; + + res = udivmodsi4 (a, b, 1); + + if (neg) + res = -res; + + return res; +} + +SItype +__mulsi3 (SItype a, SItype b) +{ + SItype res = 0; + USItype cnt = a; + + while (cnt) + { + if (cnt & 1) + { + res += b; + } + b <<= 1; + cnt >>= 1; + } + + return res; +} + +SItype +__umodsi3 (SItype a, SItype b) + +{ + return udivmodsi4 (a, b, 1); +} + +int +__gcc_bcmp (const unsigned char *s1, const unsigned char *s2, unsigned long size) +{ + while (size > 0) + { + const unsigned char c1 = *s1++, c2 = *s2++; + if (c1 != c2) + return c1 - c2; + size--; + } + return 0; +} diff --git a/roms/u-boot/arch/nios2/lib/longlong.h b/roms/u-boot/arch/nios2/lib/longlong.h new file mode 100644 index 000000000..e46d45378 --- /dev/null +++ b/roms/u-boot/arch/nios2/lib/longlong.h @@ -0,0 +1,250 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. + Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2004, + 2005 Free Software Foundation, Inc. + */ + +/* You have to define the following before including this file: + + UWtype -- An unsigned type, default type for operations (typically a "word") + UHWtype -- An unsigned type, at least half the size of UWtype. + UDWtype -- An unsigned type, at least twice as large a UWtype + W_TYPE_SIZE -- size in bits of UWtype + + UQItype -- Unsigned 8 bit type. + SItype, USItype -- Signed and unsigned 32 bit types. + DItype, UDItype -- Signed and unsigned 64 bit types. + + On a 32 bit machine UWtype should typically be USItype; + on a 64 bit machine, UWtype should typically be UDItype. */ + +#define __BITS4 (W_TYPE_SIZE / 4) +#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) +#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) +#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) + +#ifndef W_TYPE_SIZE +#define W_TYPE_SIZE 32 +#define UWtype USItype +#define UHWtype USItype +#define UDWtype UDItype +#endif + +extern const UQItype __clz_tab[256]; + +/* Define auxiliary asm macros. + + 1) umul_ppmm(high_prod, low_prod, multiplier, multiplicand) multiplies two + UWtype integers MULTIPLIER and MULTIPLICAND, and generates a two UWtype + word product in HIGH_PROD and LOW_PROD. + + 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a + UDWtype product. This is just a variant of umul_ppmm. + + 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator) divides a UDWtype, composed by the UWtype integers + HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient + in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less + than DENOMINATOR for correct operation. If, in addition, the most + significant bit of DENOMINATOR must be 1, then the pre-processor symbol + UDIV_NEEDS_NORMALIZATION is defined to 1. + + 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator). Like udiv_qrnnd but the numbers are signed. The quotient + is rounded towards 0. + + 5) count_leading_zeros(count, x) counts the number of zero-bits from the + msb to the first nonzero bit in the UWtype X. This is the number of + steps X needs to be shifted left to set the msb. Undefined for X == 0, + unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value. + + 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts + from the least significant end. + + 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, + high_addend_2, low_addend_2) adds two UWtype integers, composed by + HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2 + respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow + (i.e. carry out) is not stored anywhere, and is lost. + + 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, + high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers, + composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and + LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE + and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, + and is lost. + + If any of these macros are left undefined for a particular CPU, + C macros are used. */ + +/* The CPUs come in alphabetical order below. + + Please add support for more CPUs here, or improve the current support + for the CPUs below! + (E.g. WE32100, IBM360.) */ + +/* Snipped per CPU support */ + +/* If this machine has no inline assembler, use C macros. */ + +#if !defined (add_ssaaaa) +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) + (bl); \ + (sh) = (ah) + (bh) + (__x < (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (sub_ddmmss) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) - (bl); \ + (sh) = (ah) - (bh) - (__x > (al)); \ + (sl) = __x; \ + } while (0) +#endif + +/* If we lack umul_ppmm but have smul_ppmm, define umul_ppmm in terms of + smul_ppmm. */ +#if !defined (umul_ppmm) && defined (smul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __w1; \ + UWtype __xm0 = (u), __xm1 = (v); \ + smul_ppmm (__w1, w0, __xm0, __xm1); \ + (w1) = __w1 + (-(__xm0 >> (W_TYPE_SIZE - 1)) & __xm1) \ + + (-(__xm1 >> (W_TYPE_SIZE - 1)) & __xm0); \ + } while (0) +#endif + +/* If we still don't have umul_ppmm, define it using plain C. */ +#if !defined (umul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __x0, __x1, __x2, __x3; \ + UHWtype __ul, __vl, __uh, __vh; \ + \ + __ul = __ll_lowpart (u); \ + __uh = __ll_highpart (u); \ + __vl = __ll_lowpart (v); \ + __vh = __ll_highpart (v); \ + \ + __x0 = (UWtype) __ul * __vl; \ + __x1 = (UWtype) __ul * __vh; \ + __x2 = (UWtype) __uh * __vl; \ + __x3 = (UWtype) __uh * __vh; \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ + } while (0) +#endif + +#if !defined (__umulsidi3) +#define __umulsidi3(u, v) \ + ({DWunion __w; \ + umul_ppmm (__w.s.high, __w.s.low, u, v); \ + __w.ll; }) +#endif + +/* Define this unconditionally, so it can be used for debugging. */ +#define __udiv_qrnnd_c(q, r, n1, n0, d) \ + do { \ + UWtype __d1, __d0, __q1, __q0; \ + UWtype __r1, __r0, __m; \ + __d1 = __ll_highpart (d); \ + __d0 = __ll_lowpart (d); \ + \ + __r1 = (n1) % __d1; \ + __q1 = (n1) / __d1; \ + __m = (UWtype) __q1 * __d0; \ + __r1 = __r1 * __ll_B | __ll_highpart (n0); \ + if (__r1 < __m) \ + { \ + __q1--, __r1 += (d); \ + if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ + if (__r1 < __m) \ + __q1--, __r1 += (d); \ + } \ + __r1 -= __m; \ + \ + __r0 = __r1 % __d1; \ + __q0 = __r1 / __d1; \ + __m = (UWtype) __q0 * __d0; \ + __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ + if (__r0 < __m) \ + { \ + __q0--, __r0 += (d); \ + if (__r0 >= (d)) \ + if (__r0 < __m) \ + __q0--, __r0 += (d); \ + } \ + __r0 -= __m; \ + \ + (q) = (UWtype) __q1 * __ll_B | __q0; \ + (r) = __r0; \ + } while (0) + +/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through + __udiv_w_sdiv (defined in libgcc or elsewhere). */ +#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd) +#define udiv_qrnnd(q, r, nh, nl, d) \ + do { \ + USItype __r; \ + (q) = __udiv_w_sdiv (&__r, nh, nl, d); \ + (r) = __r; \ + } while (0) +#endif + +/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */ +#if !defined (udiv_qrnnd) +#define UDIV_NEEDS_NORMALIZATION 1 +#define udiv_qrnnd __udiv_qrnnd_c +#endif + +#if !defined (count_leading_zeros) +#define count_leading_zeros(count, x) \ + do { \ + UWtype __xr = (x); \ + UWtype __a; \ + \ + if (W_TYPE_SIZE <= 32) \ + { \ + __a = __xr < ((UWtype)1<<2*__BITS4) \ + ? (__xr < ((UWtype)1<<__BITS4) ? 0 : __BITS4) \ + : (__xr < ((UWtype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \ + } \ + else \ + { \ + for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ + if (((__xr >> __a) & 0xff) != 0) \ + break; \ + } \ + \ + (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ + } while (0) +#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE +#endif + +#if !defined (count_trailing_zeros) +/* Define count_trailing_zeros using count_leading_zeros. The latter might be + defined in asm, but if it is not, the C version above is good enough. */ +#define count_trailing_zeros(count, x) \ + do { \ + UWtype __ctz_x = (x); \ + UWtype __ctz_c; \ + count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \ + (count) = W_TYPE_SIZE - 1 - __ctz_c; \ + } while (0) +#endif + +#ifndef UDIV_NEEDS_NORMALIZATION +#define UDIV_NEEDS_NORMALIZATION 0 +#endif |