diff --git a/hal/sparcv8leon3/_interrupts.S b/hal/sparcv8leon3/_interrupts.S index 8f12b1e7..8e054280 100644 --- a/hal/sparcv8leon3/_interrupts.S +++ b/hal/sparcv8leon3/_interrupts.S @@ -100,7 +100,7 @@ wovfl_done: mov %l3, %o0 /* Disable traps, we can't let a trap use the free stack space */ -#ifndef __CPU_GR712RC +#ifdef LEON3_USE_PWR pwr 0, %psr #else wr %l0, %psr diff --git a/hal/sparcv8leon3/gaisler/Makefile b/hal/sparcv8leon3/gaisler/Makefile index 788bd58e..9204921e 100644 --- a/hal/sparcv8leon3/gaisler/Makefile +++ b/hal/sparcv8leon3/gaisler/Makefile @@ -16,4 +16,6 @@ ifeq ($(TARGET_SUBFAMILY), gr712rc) OBJS += $(addprefix $(PREFIX_O)hal/$(TARGET_SUFF)/gaisler/, irqmp.o) else ifeq ($(TARGET_SUBFAMILY), gr716) OBJS += $(addprefix $(PREFIX_O)hal/$(TARGET_SUFF)/gaisler/, irqamp.o) +else ifeq ($(TARGET_SUBFAMILY), generic) + OBJS += $(addprefix $(PREFIX_O)hal/$(TARGET_SUFF)/gaisler/, irqmp.o) endif diff --git a/hal/sparcv8leon3/gaisler/generic/Makefile b/hal/sparcv8leon3/gaisler/generic/Makefile new file mode 100644 index 00000000..2a41b4e6 --- /dev/null +++ b/hal/sparcv8leon3/gaisler/generic/Makefile @@ -0,0 +1,15 @@ +# +# Makefile for Phoenix-RTOS loader (SPARCV8 LEON3 Generic HAL) +# +# Copyright 2024 Phoenix Systems +# +# %LICENSE% +# + +CFLAGS += -DVADDR_KERNEL_INIT=$(VADDR_KERNEL_INIT) + +PLO_COMMANDS ?= alias app blob call console copy dump echo go help jffs2 kernel map mem phfs reboot script stop wait test-dev + +PLO_ALLDEVICES := uart-grlib ram-storage + +OBJS += $(addprefix $(PREFIX_O)hal/$(TARGET_SUFF)/gaisler/$(TARGET_SUBFAMILY)/, _init.o hal.o generic.o) diff --git a/hal/sparcv8leon3/gaisler/generic/_init.S b/hal/sparcv8leon3/gaisler/generic/_init.S new file mode 100644 index 00000000..7a01cdee --- /dev/null +++ b/hal/sparcv8leon3/gaisler/generic/_init.S @@ -0,0 +1,80 @@ +/* + * Phoenix-RTOS + * + * Operating system loader + * + * Low level initialization + * + * Copyright 2024 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + + #define __ASSEMBLY__ + +#include "config.h" +#include "../../cpu.h" + + +.extern syspage_common + + +.section ".init", "ax" +.align 4 +.global _init +.type _init, #function +_init: + wr %g0, %wim + nop + nop + nop + + wr %g0, PSR_S, %psr + + /* Get CPU ID */ + rd %asr17, %g1 + srl %g1, 28, %g1 + cmp %g1, %g0 + bnz jmp_core + nop + + /* Set up trap table */ + sethi %hi(_trap_table), %g1 + wr %g1, %tbr + + wr %g0, 0x2, %wim + + flush + set 0x81000f, %g1 + sta %g1, [%g0] ASI_CCTRL + + clr %fp + + /* Stack pointer */ + set _stack, %sp + sub %sp, 0x60, %sp + + /* Set PSR to supervisor, enable traps, disable irq */ + wr %g0, (PSR_ET | PSR_S | PSR_PIL), %psr + nop + nop + nop + + wr %g0, 0x2, %wim + + sethi %hi(_startc), %g1 + jmpl %g1 + %lo(_startc), %g0 + clr %g1 + +jmp_core: + set syspage_common, %g1 + ld [%g1], %g1 /* syspage_common->syspage */ + ld [%g1 + 8], %g1 /* syspage->pkernel */ + + /* Jump to kernel */ + jmp %g1 + nop +.size _init, . - _init diff --git a/hal/sparcv8leon3/gaisler/generic/config.h b/hal/sparcv8leon3/gaisler/generic/config.h new file mode 100644 index 00000000..a31423c7 --- /dev/null +++ b/hal/sparcv8leon3/gaisler/generic/config.h @@ -0,0 +1,42 @@ +/* + * Phoenix-RTOS + * + * Operating system loader + * + * Platform configuration + * + * Copyright 2024 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + + +#ifndef __ASSEMBLY__ + +#include "generic.h" +#include "peripherals.h" +#include "hal/sparcv8leon3/gaisler/gaisler.h" +#include "hal/sparcv8leon3/gaisler/types.h" +#include "hal/sparcv8leon3/cpu.h" + +#include +#include + +#define PATH_KERNEL "phoenix-sparcv8leon3-generic.elf" + +#endif /* __ASSEMBLY__ */ + + +#define NWINDOWS 8 + +/* Import platform specific definitions */ +#include "ld/sparcv8leon3-generic.ldt" + + +#endif diff --git a/hal/sparcv8leon3/gaisler/generic/generic.c b/hal/sparcv8leon3/gaisler/generic/generic.c new file mode 100644 index 00000000..a81282c5 --- /dev/null +++ b/hal/sparcv8leon3/gaisler/generic/generic.c @@ -0,0 +1,25 @@ +/* + * Phoenix-RTOS + * + * Operating system loader + * + * LEON3 Generic specific functions + * + * Copyright 2024 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include "generic.h" +#include "hal/sparcv8leon3/gaisler/gaisler.h" + + +int gaisler_iomuxCfg(iomux_cfg_t *ioCfg) +{ + (void)ioCfg; + + return 0; +} diff --git a/hal/sparcv8leon3/gaisler/generic/generic.h b/hal/sparcv8leon3/gaisler/generic/generic.h new file mode 100644 index 00000000..477d5312 --- /dev/null +++ b/hal/sparcv8leon3/gaisler/generic/generic.h @@ -0,0 +1,30 @@ +/* + * Phoenix-RTOS + * + * Operating system loader + * + * LEON3 Generic specific functions + * + * Copyright 2024 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _GENERIC_H_ +#define _GENERIC_H_ + +#include "../types.h" + + +static inline void hal_cpuHalt(void) +{ + /* clang-format off */ + __asm__ volatile ("wr %g0, %asr19"); + /* clang-format on */ +} + + +#endif diff --git a/hal/sparcv8leon3/gaisler/generic/hal.c b/hal/sparcv8leon3/gaisler/generic/hal.c new file mode 100644 index 00000000..28da2e81 --- /dev/null +++ b/hal/sparcv8leon3/gaisler/generic/hal.c @@ -0,0 +1,222 @@ +/* + * Phoenix-RTOS + * + * Operating system loader + * + * Hardware Abstraction Layer + * + * Copyright 2024 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include + + +#define ASI_FLUSH_DCACHE 0x11 + + +static struct { + hal_syspage_t *hs; + addr_t entry; +} hal_common; + + +/* Linker symbols */ +extern char __init_start[], __init_end[]; +extern char __text_start[], __etext[]; +extern char __rodata_start[], __rodata_end[]; +extern char __init_array_start[], __init_array_end[]; +extern char __fini_array_start[], __fini_array_end[]; +extern char __ramtext_start[], __ramtext_end[]; +extern char __data_start[], __data_end[]; +extern char __bss_start[], __bss_end[]; +extern char __heap_base[], __heap_limit[]; +extern char __stack_top[], __stack_limit[]; + +/* Timer */ +extern void timer_init(void); +extern void timer_done(void); + +/* Interrupts */ +extern void interrupts_init(void); + +/* Console */ +void console_init(void); + + +void hal_init(void) +{ + interrupts_init(); + + timer_init(); + console_init(); + + hal_common.entry = (addr_t)-1; +} + + +void hal_done(void) +{ + timer_done(); +} + + +void hal_syspageSet(hal_syspage_t *hs) +{ + hal_common.hs = hs; +} + + +const char *hal_cpuInfo(void) +{ + return "Generic LEON3"; +} + + +addr_t hal_kernelGetAddress(addr_t addr) +{ + return addr - VADDR_KERNEL_INIT + ADDR_SRAM; +} + + +void hal_kernelGetEntryPointOffset(addr_t *off, int *indirect) +{ + *off = 0; + *indirect = 1; +} + + +void hal_kernelEntryPoint(addr_t addr) +{ + hal_common.entry = addr; +} + + +int hal_memoryAddMap(addr_t start, addr_t end, u32 attr, u32 mapId) +{ + return 0; +} + + +static void hal_getMinOverlappedRange(addr_t start, addr_t end, mapent_t *entry, mapent_t *minEntry) +{ + if ((start < entry->end) && (end > entry->start)) { + if (start > entry->start) { + entry->start = start; + } + + if (end < entry->end) { + entry->end = end; + } + + if (entry->start < minEntry->start) { + minEntry->start = entry->start; + minEntry->end = entry->end; + minEntry->type = entry->type; + } + } +} + + +int hal_memoryGetNextEntry(addr_t start, addr_t end, mapent_t *entry) +{ + int i; + mapent_t tempEntry, minEntry; + + static const mapent_t entries[] = { + { .start = (addr_t)__init_start, .end = (addr_t)__init_end, .type = hal_entryTemp }, + { .start = (addr_t)__text_start, .end = (addr_t)__etext, .type = hal_entryTemp }, + { .start = (addr_t)__rodata_start, .end = (addr_t)__rodata_end, .type = hal_entryTemp }, + { .start = (addr_t)__init_array_start, .end = (addr_t)__init_array_end, .type = hal_entryTemp }, + { .start = (addr_t)__fini_array_start, .end = (addr_t)__fini_array_end, .type = hal_entryTemp }, + { .start = (addr_t)__ramtext_start, .end = (addr_t)__ramtext_end, .type = hal_entryTemp }, + { .start = (addr_t)__data_start, .end = (addr_t)__data_end, .type = hal_entryTemp }, + { .start = (addr_t)__bss_start, .end = (addr_t)__bss_end, .type = hal_entryTemp }, + { .start = (addr_t)__heap_base, .end = (addr_t)__heap_limit, .type = hal_entryTemp }, + { .start = (addr_t)__stack_limit, .end = (addr_t)__stack_top, .type = hal_entryTemp }, + }; + + if (start == end) { + return -1; + } + + minEntry.start = (addr_t)-1; + minEntry.end = 0; + minEntry.type = 0; + + /* Syspage entry */ + tempEntry.start = (addr_t)hal_common.hs; + tempEntry.end = (addr_t)__heap_limit; + tempEntry.type = hal_entryReserved; + hal_getMinOverlappedRange(start, end, &tempEntry, &minEntry); + + for (i = 0; i < sizeof(entries) / sizeof(entries[0]); ++i) { + if (entries[i].start >= entries[i].end) { + continue; + } + tempEntry.start = entries[i].start; + tempEntry.end = entries[i].end; + tempEntry.type = entries[i].type; + hal_getMinOverlappedRange(start, end, &tempEntry, &minEntry); + } + + if (minEntry.start != (addr_t)-1) { + entry->start = minEntry.start; + entry->end = minEntry.end; + entry->type = minEntry.type; + + return 0; + } + + return -1; +} + + +void hal_cpuFlushDCache(void) +{ + /* clang-format off */ + __asm__ volatile( + "sta %%g0, [%%g0] %c0\n\t" + : + : "i"(ASI_FLUSH_DCACHE) + ); + /* clang-format on */ +} + + +void hal_cpuFlushICache(void) +{ + __asm__ volatile("flush"); +} + + +int hal_cpuJump(void) +{ + if (hal_common.entry == (addr_t)-1) { + return -1; + } + hal_interruptsDisableAll(); + + __asm__ volatile( + "jmp %0;" + "mov %1, %%g2;" + : + : "r"(hal_common.entry), "r"(hal_common.hs) + :); + + return 0; +} + + +void hal_cpuReboot(void) +{ + /* TODO */ + for (;;) { + } + + __builtin_unreachable(); +} diff --git a/hal/sparcv8leon3/gaisler/generic/peripherals.h b/hal/sparcv8leon3/gaisler/generic/peripherals.h new file mode 100644 index 00000000..2efd6771 --- /dev/null +++ b/hal/sparcv8leon3/gaisler/generic/peripherals.h @@ -0,0 +1,25 @@ +/* + * Phoenix-RTOS + * + * Operating system loader + * + * Peripherals definitions for Leon3 Generic + * + * Copyright 2024 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _PERIPHERALS_H_ +#define _PERIPHERALS_H_ + +#include + +/* Arbitrarily chosen address */ +#define RAM_ADDR (0x47e00000) +#define RAM_BANK_SIZE (0x200000) + +#endif diff --git a/hal/sparcv8leon3/gaisler/timer.c b/hal/sparcv8leon3/gaisler/timer.c index 0a45f087..8ea268a8 100644 --- a/hal/sparcv8leon3/gaisler/timer.c +++ b/hal/sparcv8leon3/gaisler/timer.c @@ -90,11 +90,10 @@ time_t hal_timerGet(void) void timer_done(void) { int timer; + vu32 st; /* Disable timer interrupts - bits cleared when written 1 */ - vu32 st = *(timer_common.gptimer0_base + GPT_TCTRL(TIMER_DEFAULT)) & (TIMER_INT_ENABLE | TIMER_INT_PENDING); + st = *(timer_common.gptimer0_base + GPT_TCTRL(TIMER_DEFAULT)) & (TIMER_INT_ENABLE | TIMER_INT_PENDING); *(timer_common.gptimer0_base + GPT_TCTRL(TIMER_DEFAULT)) = st; - st = *(timer_common.gptimer1_base + GPT_TCTRL(TIMER_DEFAULT)) & (TIMER_INT_ENABLE | TIMER_INT_PENDING); - *(timer_common.gptimer1_base + GPT_TCTRL(TIMER_DEFAULT)) = st; for (timer = 1; timer <= TIMER0_CNT; ++timer) { /* Disable timers */ @@ -104,10 +103,16 @@ void timer_done(void) *(timer_common.gptimer0_base + GPT_TRLDVAL(timer)) = 0; } - for (timer = 1; timer <= TIMER1_CNT; ++timer) { - *(timer_common.gptimer1_base + GPT_TCTRL(TIMER_DEFAULT)) = 0; - *(timer_common.gptimer1_base + GPT_TCNTVAL(timer)) = 0; - *(timer_common.gptimer1_base + GPT_TRLDVAL(timer)) = 0; + /* We might not have second timer core */ + if (timer_common.gptimer1_base != NULL) { + st = *(timer_common.gptimer1_base + GPT_TCTRL(TIMER_DEFAULT)) & (TIMER_INT_ENABLE | TIMER_INT_PENDING); + *(timer_common.gptimer1_base + GPT_TCTRL(TIMER_DEFAULT)) = st; + + for (timer = 1; timer <= TIMER1_CNT; ++timer) { + *(timer_common.gptimer1_base + GPT_TCTRL(TIMER_DEFAULT)) = 0; + *(timer_common.gptimer1_base + GPT_TCNTVAL(timer)) = 0; + *(timer_common.gptimer1_base + GPT_TRLDVAL(timer)) = 0; + } } hal_interruptsSet(TIMER_IRQ, NULL, NULL); diff --git a/ld/sparcv8leon3-generic.ldt b/ld/sparcv8leon3-generic.ldt new file mode 100644 index 00000000..71a3c251 --- /dev/null +++ b/ld/sparcv8leon3-generic.ldt @@ -0,0 +1,49 @@ +/* + * Phoenix-RTOS + * + * Operating system loader + * + * Linker Template and Platform Config for SPARC V8 LEON3 Generic + * + * Copyright 2023, 2024 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef LEON3_GENERIC_LDT +#define LEON3_GENERIC_LDT + +#define SIZE_PAGE 0x1000 +#define SIZE_STACK (SIZE_PAGE) +#define SIZE_HEAP (SIZE_PAGE) + +#define ADDR_SRAM 0x40000000 + +#define SIZE_SRAM (4 * 1024 * 1024) +#define SIZE_PLO (2 * 1024 * 1024) + +#if defined(__LINKER__) + +/* Memory map setup */ +MEMORY +{ + m_prom (rx) : ORIGIN = 0x00000000, LENGTH = 8M + m_sram (rwx) : ORIGIN = ADDR_SRAM + SIZE_SRAM - SIZE_PLO, LENGTH = SIZE_PLO +} + +REGION_ALIAS("PLO_IMAGE", m_sram) +REGION_ALIAS("RAM_TEXT", m_sram) +REGION_ALIAS("RODATA", m_sram) +REGION_ALIAS("DATA", m_sram) +REGION_ALIAS("BSS", m_sram) +REGION_ALIAS("HEAP", m_sram) +REGION_ALIAS("STACK", m_sram) + +#include "common/plo-sparc.lds" + +#endif /* __LINKER__ */ + +#endif