diff --git a/devices/uart-grlib/uart.c b/devices/uart-grlib/uart.c index 1090df85..8b4ebd61 100644 --- a/devices/uart-grlib/uart.c +++ b/devices/uart-grlib/uart.c @@ -243,7 +243,9 @@ static int uart_done(unsigned int minor) *(uart->base + uart_scaler) = 0; hal_cpuDataStoreBarrier(); +#ifdef __CPU_GR716 _gr716_cguClkDisable(cgu_primary, cgudev_apbuart0 + minor); +#endif hal_interruptsSet(uart->irq, NULL, NULL); @@ -290,16 +292,18 @@ static int uart_init(unsigned int minor) uart_done(minor); +#ifdef __CPU_GR716 _gr716_cguClkEnable(cgu_primary, cgudev_apbuart0 + minor); +#endif cfg.opt = 0x1; cfg.pullup = 0; cfg.pulldn = 0; cfg.pin = info[minor].txPin; - _gr716_iomuxCfg(&cfg); + gaisler_iomuxCfg(&cfg); cfg.pin = info[minor].rxPin; - _gr716_iomuxCfg(&cfg); + gaisler_iomuxCfg(&cfg); lib_cbufInit(&uart->cbuffRx, uart->dataRx, BUFFER_SIZE); diff --git a/hal/sparcv8leon3/Makefile b/hal/sparcv8leon3/Makefile index 814b9ee3..fddfe579 100644 --- a/hal/sparcv8leon3/Makefile +++ b/hal/sparcv8leon3/Makefile @@ -6,8 +6,6 @@ # %LICENSE% # -include hal/sparcv8leon3/$(TARGET_SUBFAMILY)/Makefile +include hal/sparcv8leon3/gaisler/Makefile -CFLAGS += -Ihal/sparcv8leon3/$(TARGET_SUBFAMILY) - -OBJS += $(addprefix $(PREFIX_O)hal/$(TARGET_SUFF)/, cpu.o string.o interrupts.o exceptions.o _init.o _interrupts.o _traps.o) +OBJS += $(addprefix $(PREFIX_O)hal/$(TARGET_SUFF)/, string.o interrupts.o exceptions.o _interrupts.o _traps.o) diff --git a/hal/sparcv8leon3/_interrupts.S b/hal/sparcv8leon3/_interrupts.S index ee44115a..9610eb69 100644 --- a/hal/sparcv8leon3/_interrupts.S +++ b/hal/sparcv8leon3/_interrupts.S @@ -99,7 +99,11 @@ wovfl_done: mov %l3, %o0 /* Disable traps, we can't let a trap use the free stack space */ +#ifndef __CPU_GR712RC pwr 0, %psr +#else + wr %l0, %psr +#endif nop nop nop @@ -163,11 +167,33 @@ cwp_done: save wufl_done: + +#ifdef LEON3_TN_0018_FIX +1: + /* Wait for ICache flush to complete */ + lda [%g0] ASI_CCTRL, %l3 + srl %l3, 15, %l4 /* ICache flush pending bit */ + andcc %l4, 1, %g0 + bne 1b + andn %l3, 0x3, %l4 /* ICache state */ +#endif + /* restore %psr */ wr %l0, %psr nop nop nop + +#ifdef LEON3_TN_0018_FIX +.align 0x20 /* Align sta for performance */ + sta %l4, [%g0] ASI_CCTRL /* Disable ICache */ + nop /* Delay */ + or %l1, %l1, %l1 /* Delay + catch rf parity error on l1 */ + or %l2, %l2, %l2 /* Delay + catch rf parity error on l2 */ + sta %l3, [%g0] ASI_CCTRL /* Re-enable ICache after rett */ + nop /* Delay ensures insn after gets cached */ +#endif + jmp %l1 rett %l2 diff --git a/hal/sparcv8leon3/_traps.S b/hal/sparcv8leon3/_traps.S index 0e23e7df..f067d14b 100644 --- a/hal/sparcv8leon3/_traps.S +++ b/hal/sparcv8leon3/_traps.S @@ -156,6 +156,8 @@ _start: .section ".text" .align 4 +/* Underflow/overflow traps never return directly to 'jmpl' instruction - no TN-0018 fix needed */ + /* Window underflow handler * on entry: * %psr in %l0, PC in %l1, nPC in %l2 @@ -236,6 +238,7 @@ _traps_setPil: nop nop nop + /* TN-0018 fix done after 'ta' instruction */ jmp %l2 rett %l2 + 4 .size _traps_setPil, . - _traps_setPil @@ -307,7 +310,8 @@ _exceptions_dispatch: nop /* trap type */ - and %g1, TBR_TT_MSK, %o0 + set TBR_TT_MSK, %g2 + and %g1, %g2, %o0 srl %o0, TBR_TT_SHIFT, %o0 /* void exceptions_dispatch(unsigned int n, exc_context_t *ctx) */ diff --git a/hal/sparcv8leon3/cpu.c b/hal/sparcv8leon3/cpu.c deleted file mode 100644 index 233bb5f2..00000000 --- a/hal/sparcv8leon3/cpu.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Phoenix-RTOS - * - * Operating system loader - * - * Leon3 CPU related routines - * - * Copyright 2022 Phoenix Systems - * Author: Lukasz Leczkowski - * - * This file is part of Phoenix-RTOS. - * - * %LICENSE% - */ - -#include - - -#define BOOTSTRAP_ADDR 0x80008000 -#define BOOTSTRAP_SPIM 0x400BC003 - - -void hal_cpuReboot(void) -{ - /* Reset to the built-in bootloader */ - hal_interruptsDisableAll(); - - /* Reboot to SPIM */ - *(vu32 *)(BOOTSTRAP_ADDR) = BOOTSTRAP_SPIM; - - /* clang-format off */ - __asm__ volatile ( - "jmp %%g0\n\t" - "nop\n\t" - ::: - ); - /* clang-format on */ - - __builtin_unreachable(); -} diff --git a/hal/sparcv8leon3/cpu.h b/hal/sparcv8leon3/cpu.h index 51e879ab..f2ebfe92 100644 --- a/hal/sparcv8leon3/cpu.h +++ b/hal/sparcv8leon3/cpu.h @@ -41,13 +41,6 @@ #include -static inline void hal_cpuHalt(void) -{ - /* must be performed in supervisor mode with int enabled */ - __asm__ volatile("wr %g0, %asr19"); -} - - static inline void hal_cpuDataStoreBarrier(void) { __asm__ volatile("stbar"); diff --git a/hal/sparcv8leon3/gaisler/Makefile b/hal/sparcv8leon3/gaisler/Makefile new file mode 100644 index 00000000..788bd58e --- /dev/null +++ b/hal/sparcv8leon3/gaisler/Makefile @@ -0,0 +1,19 @@ +# +# Makefile for Phoenix-RTOS loader (SPARCV8 LEON3 HAL) +# +# Copyright 2023 Phoenix Systems +# +# %LICENSE% +# + +CFLAGS += -Ihal/sparcv8leon3/gaisler/ -Ihal/sparcv8leon3/gaisler/$(TARGET_SUBFAMILY) + +include hal/sparcv8leon3/gaisler/$(TARGET_SUBFAMILY)/Makefile + +OBJS += $(addprefix $(PREFIX_O)hal/$(TARGET_SUFF)/gaisler/, console.o timer.o) + +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) +endif diff --git a/hal/sparcv8leon3/gr716/console.c b/hal/sparcv8leon3/gaisler/console.c similarity index 76% rename from hal/sparcv8leon3/gr716/console.c rename to hal/sparcv8leon3/gaisler/console.c index 1a2c3976..4cb98381 100644 --- a/hal/sparcv8leon3/gr716/console.c +++ b/hal/sparcv8leon3/gaisler/console.c @@ -14,18 +14,19 @@ */ #include -#include - /* UART control bits */ #define TX_EN (1 << 1) #define TX_FIFO_FULL (1 << 9) +#define CONCAT_(a, b) a##b +#define CONCAT(a, b) CONCAT_(a, b) + /* Console config */ -#define UART_CONSOLE_RX UART2_RX -#define UART_CONSOLE_TX UART2_TX -#define UART_CONSOLE_BASE UART2_BASE -#define UART_CONSOLE_CGU cgudev_apbuart2 +#define UART_CONSOLE_RX CONCAT(UART, CONCAT(UART_CONSOLE_PLO, _RX)) +#define UART_CONSOLE_TX CONCAT(UART, CONCAT(UART_CONSOLE_PLO, _TX)) +#define UART_CONSOLE_BASE CONCAT(UART, CONCAT(UART_CONSOLE_PLO, _BASE)) +#define UART_CONSOLE_CGU CONCAT(cgudev_apbuart, UART_CONSOLE_PLO) enum { @@ -68,12 +69,15 @@ void console_init(void) cfg.pullup = 0; cfg.pulldn = 0; cfg.pin = UART_CONSOLE_TX; - _gr716_iomuxCfg(&cfg); + gaisler_iomuxCfg(&cfg); cfg.pin = UART_CONSOLE_RX; - _gr716_iomuxCfg(&cfg); + gaisler_iomuxCfg(&cfg); +#ifdef __CPU_GR716 _gr716_cguClkEnable(cgu_primary, UART_CONSOLE_CGU); +#endif + halconsole_common.uart = UART_CONSOLE_BASE; *(halconsole_common.uart + uart_ctrl) = TX_EN; *(halconsole_common.uart + uart_scaler) = console_calcScaler(UART_BAUDRATE); diff --git a/hal/sparcv8leon3/gaisler/gaisler.h b/hal/sparcv8leon3/gaisler/gaisler.h new file mode 100644 index 00000000..df657d88 --- /dev/null +++ b/hal/sparcv8leon3/gaisler/gaisler.h @@ -0,0 +1,34 @@ +/* + * Phoenix-RTOS + * + * Operating system loader + * + * Gaisler CPU specific functions + * + * Copyright 2023 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _GAISLER_H_ +#define _GAISLER_H_ + + +#include "types.h" + + +typedef struct { + u8 pin; + u8 opt; + u8 pullup; + u8 pulldn; +} iomux_cfg_t; + + +int gaisler_iomuxCfg(iomux_cfg_t *ioCfg); + + +#endif diff --git a/hal/sparcv8leon3/gaisler/gr712rc/Makefile b/hal/sparcv8leon3/gaisler/gr712rc/Makefile new file mode 100644 index 00000000..f4c15c24 --- /dev/null +++ b/hal/sparcv8leon3/gaisler/gr712rc/Makefile @@ -0,0 +1,16 @@ +# +# Makefile for Phoenix-RTOS loader (SPARCV8 LEON3 GR712RC HAL) +# +# Copyright 2023 Phoenix Systems +# +# %LICENSE% +# + +CFLAGS += -DVADDR_KERNEL_INIT=$(VADDR_KERNEL_INIT) + +PLO_COMMANDS := alias app call console copy dump echo go help kernel map mem phfs reboot script wait + +include devices/uart-grlib/Makefile +include devices/ram-storage/Makefile + +OBJS += $(addprefix $(PREFIX_O)hal/$(TARGET_SUFF)/gaisler/$(TARGET_SUBFAMILY)/, _init.o hal.o gr712rc.o) diff --git a/hal/sparcv8leon3/gaisler/gr712rc/_init.S b/hal/sparcv8leon3/gaisler/gr712rc/_init.S new file mode 100644 index 00000000..27868f66 --- /dev/null +++ b/hal/sparcv8leon3/gaisler/gr712rc/_init.S @@ -0,0 +1,62 @@ +/* + * Phoenix-RTOS + * + * Operating system loader + * + * Low level initialization + * + * Copyright 2022-2023 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + + #define __ASSEMBLY__ + +#include "config.h" +#include "../../cpu.h" + + +.section ".init", "ax" +.align 4 +.global _init +.type _init, #function +_init: + wr %g0, %wim + nop + nop + nop + + wr %g0, PSR_S, %psr + + /* Set up trap table */ + sethi %hi(_trap_table), %g1 + wr %g1, %tbr + + wr %g0, 0x2, %wim + + /* Flush and enable cache - section 4.5.7 GR712RC UM */ + 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 +.size _init, . - _init diff --git a/hal/sparcv8leon3/gaisler/gr712rc/config.h b/hal/sparcv8leon3/gaisler/gr712rc/config.h new file mode 100644 index 00000000..5afeddb7 --- /dev/null +++ b/hal/sparcv8leon3/gaisler/gr712rc/config.h @@ -0,0 +1,44 @@ +/* + * Phoenix-RTOS + * + * Operating system loader + * + * Platform configuration + * + * Copyright 2022-2023 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + + +#ifndef __ASSEMBLY__ + +#include "gr712rc.h" +#include "peripherals.h" +#include "../gaisler.h" +#include "../types.h" +#include "../../cpu.h" + +#include +#include + +#define PATH_KERNEL "phoenix-sparcv8leon3-gr712rc.elf" + +#endif /* __ASSEMBLY__ */ + + +#define NWINDOWS 8 + +#define ASI_CCTRL 0x02 + +/* Import platform specific definitions */ +#include "ld/sparcv8leon3-gr712rc.ldt" + + +#endif diff --git a/hal/sparcv8leon3/gaisler/gr712rc/gr712rc.c b/hal/sparcv8leon3/gaisler/gr712rc/gr712rc.c new file mode 100644 index 00000000..304fe246 --- /dev/null +++ b/hal/sparcv8leon3/gaisler/gr712rc/gr712rc.c @@ -0,0 +1,78 @@ +/* + * Phoenix-RTOS + * + * Operating system loader + * + * GR712RC specific functions + * + * Copyright 2023 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include "gr712rc.h" +#include "../gaisler.h" +#include "../cpu.h" + + +#define CGU_BASE ((void *)0x80000D00) + +/* Clock gating unit */ + +#define CGU_UNLOCK 0 /* Unlock register : 0x00 */ +#define CGU_CLK_EN 1 /* Clock enable register : 0x04 */ +#define CGU_CORE_RESET 2 /* Core reset register : 0x08 */ + + +static struct { + vu32 *cgu_base; +} gr712rc_common; + + +int gaisler_iomuxCfg(iomux_cfg_t *ioCfg) +{ + (void)ioCfg; + + return 0; +} + +/* CGU setup - section 28.2 GR712RC manual */ + +void _gr712rc_cguClkEnable(u32 device) +{ + u32 msk = 1 << device; + + *(gr712rc_common.cgu_base + CGU_UNLOCK) |= msk; + *(gr712rc_common.cgu_base + CGU_CORE_RESET) |= msk; + *(gr712rc_common.cgu_base + CGU_CLK_EN) |= msk; + *(gr712rc_common.cgu_base + CGU_CORE_RESET) &= ~msk; + *(gr712rc_common.cgu_base + CGU_UNLOCK) &= ~msk; +} + + +void _gr712rc_cguClkDisable(u32 device) +{ + u32 msk = 1 << device; + + *(gr712rc_common.cgu_base + CGU_UNLOCK) |= msk; + *(gr712rc_common.cgu_base + CGU_CORE_RESET) |= msk; + *(gr712rc_common.cgu_base + CGU_CLK_EN) &= ~msk; + *(gr712rc_common.cgu_base + CGU_UNLOCK) &= ~msk; +} + + +int _gr712rc_cguClkStatus(u32 device) +{ + u32 msk = 1 << device; + + return (*(gr712rc_common.cgu_base + CGU_CLK_EN) & msk) ? 1 : 0; +} + + +void _gr712rc_init(void) +{ + gr712rc_common.cgu_base = CGU_BASE; +} diff --git a/hal/sparcv8leon3/gaisler/gr712rc/gr712rc.h b/hal/sparcv8leon3/gaisler/gr712rc/gr712rc.h new file mode 100644 index 00000000..50b48506 --- /dev/null +++ b/hal/sparcv8leon3/gaisler/gr712rc/gr712rc.h @@ -0,0 +1,64 @@ +/* + * Phoenix-RTOS + * + * Operating system loader + * + * GR712RC specific functions + * + * Copyright 2023 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _GR712RC_H_ +#define _GR712RC_H_ + +#include "../types.h" + + +#define ASI_MMU_BYPASS 0x1c + + +/* clang-format off */ + +/* Clock gating unit devices */ + +enum { cgudev_eth = 0, cgudev_spw0, cgudev_spw1, cgudev_spw2, cgudev_spw3, cgudev_spw4, cgudev_spw5, cgudev_can, + cgudev_ccsdsEnc = 9, cgudev_ccsdsDec, cgudev_milStd1553 }; + +/* clang-format on */ + + +static inline void hal_cpuHalt(void) +{ + /* GR712RC errata 1.7.8 */ + u32 addr = 0xfffffff0u; + + /* clang-format off */ + + __asm__ volatile( + "wr %%g0, %%asr19\n\t" + "lda [%0] %c1, %%g0\n\t" + : + : "r"(addr), "i"(ASI_MMU_BYPASS) + ); + /* clang-format on */ +} + + +void _gr712rc_cguClkEnable(u32 device); + + +void _gr712rc_cguClkDisable(u32 device); + + +int _gr712rc_cguClkStatus(u32 device); + + +void _gr712rc_init(void); + + +#endif diff --git a/hal/sparcv8leon3/gr716/hal.c b/hal/sparcv8leon3/gaisler/gr712rc/hal.c similarity index 94% rename from hal/sparcv8leon3/gr716/hal.c rename to hal/sparcv8leon3/gaisler/gr712rc/hal.c index bde68cbd..76a8553a 100644 --- a/hal/sparcv8leon3/gr716/hal.c +++ b/hal/sparcv8leon3/gaisler/gr712rc/hal.c @@ -5,7 +5,7 @@ * * Hardware Abstraction Layer * - * Copyright 2022 Phoenix Systems + * Copyright 2022-2023 Phoenix Systems * Author: Lukasz Leczkowski * * This file is part of Phoenix-RTOS. @@ -47,10 +47,9 @@ void console_init(void); void hal_init(void) { - _gr716_init(); + _gr712rc_init(); interrupts_init(); - gpio_init(); timer_init(); console_init(); @@ -72,13 +71,13 @@ void hal_syspageSet(hal_syspage_t *hs) const char *hal_cpuInfo(void) { - return "LEON3FT GR716 MINI"; + return "LEON3FT GR712RC"; } addr_t hal_kernelGetAddress(addr_t addr) { - return addr; + return addr - VADDR_KERNEL_INIT + ADDR_SRAM; } @@ -191,3 +190,13 @@ int hal_cpuJump(void) return 0; } + + +void hal_cpuReboot(void) +{ + /* TODO */ + for (;;) { + } + + __builtin_unreachable(); +} diff --git a/hal/sparcv8leon3/gaisler/gr712rc/peripherals.h b/hal/sparcv8leon3/gaisler/gr712rc/peripherals.h new file mode 100644 index 00000000..ee21e586 --- /dev/null +++ b/hal/sparcv8leon3/gaisler/gr712rc/peripherals.h @@ -0,0 +1,47 @@ +/* + * Phoenix-RTOS + * + * Operating system loader + * + * Peripherals definitions for Leon3 GR712RC + * + * Copyright 2023 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _PERIPHERALS_H_ +#define _PERIPHERALS_H_ + +#include + +/* Timer registers */ + +#define GPT_SCALER 0 /* Scaler value register : 0x00 */ +#define GPT_SRELOAD 1 /* Scaler reload value register : 0x04 */ +#define GPT_CONFIG 2 /* Configuration register : 0x08 */ + +#define GPT_TCNTVAL1 4 /* Timer 1 counter value reg : 0x10 */ +#define GPT_TRLDVAL1 5 /* Timer 1 reload value reg : 0x14 */ +#define GPT_TCTRL1 6 /* Timer 1 control register : 0x18 */ + +#define GPT_TCNTVAL2 8 /* Timer 2 counter value reg : 0x20 */ +#define GPT_TRLDVAL2 9 /* Timer 2 reload value reg : 0x24 */ +#define GPT_TCTRL2 10 /* Timer 2 control register : 0x28 */ + +#define GPT_TCNTVAL3 12 /* Timer 3 counter value reg : 0x30 */ +#define GPT_TRLDVAL3 13 /* Timer 3 reload value reg : 0x34 */ +#define GPT_TCTRL3 14 /* Timer 3 control register : 0x38 */ + +#define GPT_TCNTVAL4 16 /* Timer 4 counter value reg : 0x40 */ +#define GPT_TRLDVAL4 17 /* Timer 4 reload value reg : 0x44 */ +#define GPT_TCTRL4 18 /* Timer 4 control register : 0x48 */ + +/* Arbitrarily chosen address */ +#define RAM_ADDR (0x47e00000) +#define RAM_BANK_SIZE (0x200000) + +#endif diff --git a/hal/sparcv8leon3/gr716/Makefile b/hal/sparcv8leon3/gaisler/gr716/Makefile similarity index 75% rename from hal/sparcv8leon3/gr716/Makefile rename to hal/sparcv8leon3/gaisler/gr716/Makefile index 746df551..04fe858b 100644 --- a/hal/sparcv8leon3/gr716/Makefile +++ b/hal/sparcv8leon3/gaisler/gr716/Makefile @@ -12,9 +12,6 @@ LDFLAGS:=$(filter-out -Tbss% , $(LDFLAGS)) LDFLAGS:=$(filter-out -Tdata% , $(LDFLAGS)) LDFLAGS:=$(filter-out -Wl$(comma)--section-start% , $(LDFLAGS)) -CFLAGS:=$(filter-out -mfloat-abi% , $(CFLAGS)) -CFLAGS:=$(filter-out -mfpu% , $(CFLAGS)) - CFLAGS += -DVADDR_KERNEL_INIT=$(VADDR_KERNEL_INIT) PLO_COMMANDS := alias app call console copy dump echo go help kernel map mem phfs reboot script wait @@ -25,4 +22,4 @@ ifeq ($(TARGET_PROJECT), mini) include devices/flash-gr716/Makefile endif -OBJS += $(addprefix $(PREFIX_O)hal/$(TARGET_SUFF)/$(TARGET_SUBFAMILY)/, hal.o gr716.o timer.o console.o) +OBJS += $(addprefix $(PREFIX_O)hal/$(TARGET_SUFF)/gaisler/$(TARGET_SUBFAMILY)/, _init.o hal.o gr716.o) diff --git a/hal/sparcv8leon3/_init.S b/hal/sparcv8leon3/gaisler/gr716/_init.S similarity index 99% rename from hal/sparcv8leon3/_init.S rename to hal/sparcv8leon3/gaisler/gr716/_init.S index 6754430b..72db5e4c 100644 --- a/hal/sparcv8leon3/_init.S +++ b/hal/sparcv8leon3/gaisler/gr716/_init.S @@ -16,7 +16,7 @@ #define __ASSEMBLY__ #include "config.h" -#include "../cpu.h" +#include "../../cpu.h" .extern _plo_load_addr .extern _plo_size diff --git a/hal/sparcv8leon3/gr716/config.h b/hal/sparcv8leon3/gaisler/gr716/config.h similarity index 87% rename from hal/sparcv8leon3/gr716/config.h rename to hal/sparcv8leon3/gaisler/gr716/config.h index 4e2b3c51..3c839088 100644 --- a/hal/sparcv8leon3/gr716/config.h +++ b/hal/sparcv8leon3/gaisler/gr716/config.h @@ -19,10 +19,11 @@ #ifndef __ASSEMBLY__ +#include "../types.h" #include "gr716.h" -#include "types.h" #include "peripherals.h" -#include "../cpu.h" +#include "../gaisler.h" +#include "../../cpu.h" #include #include @@ -34,7 +35,7 @@ #endif /* __ASSEMBLY__ */ -#define NWINDOWS 31 +#define NWINDOWS 31 /* Import platform specific definitions */ #include "ld/sparcv8leon3-gr716.ldt" diff --git a/hal/sparcv8leon3/gr716/gr716.c b/hal/sparcv8leon3/gaisler/gr716/gr716.c similarity index 92% rename from hal/sparcv8leon3/gr716/gr716.c rename to hal/sparcv8leon3/gaisler/gr716/gr716.c index f1c4ba6d..a9887c68 100644 --- a/hal/sparcv8leon3/gr716/gr716.c +++ b/hal/sparcv8leon3/gaisler/gr716/gr716.c @@ -14,7 +14,7 @@ */ #include "gr716.h" -#include "../cpu.h" +#include "../../cpu.h" #include @@ -23,7 +23,6 @@ #define PLL_BASE ((void *)0x8010D000) #define CGU_BASE0 ((void *)0x80006000) #define CGU_BASE1 ((void *)0x80007000) -#define MCTRL0_BASE ((void *)0x80000000) /* Oscillator frequency * PLL Multiplier (for 400 MHz) */ /*---------------------------|-------------------------------*/ @@ -88,23 +87,12 @@ enum { cgu_override, /* Override register - only primary CGU : 0x0C */ }; -/* External PROM & SRAM */ - -enum { - mctrl_cfg1 = 0, /* ROM timing and IO : 0x00 */ - mctrl_cfg2, /* SRAM timing and IO : 0x04 */ - mctrl_cfg3, /* EDAC control : 0x08 */ - mctrl_cfg5 = 4, /* ROM lead out cycles : 0x10 */ - mctrl_cfg6, /* SRAM lead out cycles : 0x14 */ -}; - static struct { vu32 *grgpreg_base; vu32 *pll_base; vu32 *cgu_base0; vu32 *cgu_base1; - vu32 *mctrl0_base; } gr716_common; @@ -138,7 +126,7 @@ static void _gr716_pllSetDefault(void) } -int _gr716_iomuxCfg(iomux_cfg_t *ioCfg) +int gaisler_iomuxCfg(iomux_cfg_t *ioCfg) { vu32 oldCfg; @@ -207,7 +195,6 @@ void _gr716_init(void) gr716_common.pll_base = PLL_BASE; gr716_common.cgu_base0 = CGU_BASE0; gr716_common.cgu_base1 = CGU_BASE1; - gr716_common.mctrl0_base = MCTRL0_BASE; _gr716_pllSetDefault(); } diff --git a/hal/sparcv8leon3/gr716/gr716.h b/hal/sparcv8leon3/gaisler/gr716/gr716.h similarity index 78% rename from hal/sparcv8leon3/gr716/gr716.h rename to hal/sparcv8leon3/gaisler/gr716/gr716.h index 15e5cb31..6df94044 100644 --- a/hal/sparcv8leon3/gr716/gr716.h +++ b/hal/sparcv8leon3/gaisler/gr716/gr716.h @@ -16,7 +16,7 @@ #ifndef _GR716_H_ #define _GR716_H_ -#include "types.h" +#include "../types.h" /* clang-format off */ @@ -38,27 +38,24 @@ cgudev_gradc3, cgudev_gradc4, cgudev_gradc5, cgudev_gradc6, cgudev_gradc7, cgude /* clang-format on */ -typedef struct { - u8 pin; - u8 opt; /* GR716 manual section 2.5 */ - u8 pullup; - u8 pulldn; -} iomux_cfg_t; +static inline void hal_cpuHalt(void) +{ + /* must be performed in supervisor mode with int enabled */ + __asm__ volatile("wr %g0, %asr19"); +} -extern int _gr716_iomuxCfg(iomux_cfg_t *ioCfg); +void _gr716_cguClkEnable(u32 cgu, u32 device); -extern void _gr716_cguClkEnable(u32 cgu, u32 device); +void _gr716_cguClkDisable(u32 cgu, u32 device); -extern void _gr716_cguClkDisable(u32 cgu, u32 device); +int _gr716_cguClkStatus(u32 cgu, u32 device); -extern int _gr716_cguClkStatus(u32 cgu, u32 device); - -extern void _gr716_init(void); +void _gr716_init(void); #endif diff --git a/hal/sparcv8leon3/gaisler/gr716/hal.c b/hal/sparcv8leon3/gaisler/gr716/hal.c new file mode 100644 index 00000000..98c9f230 --- /dev/null +++ b/hal/sparcv8leon3/gaisler/gr716/hal.c @@ -0,0 +1,217 @@ +/* + * Phoenix-RTOS + * + * Operating system loader + * + * Hardware Abstraction Layer + * + * Copyright 2022-2023 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include + + +#define BOOTSTRAP_ADDR 0x80008000 +#define BOOTSTRAP_SPIM 0x400BC003 + + +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) +{ + _gr716_init(); + interrupts_init(); + + gpio_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 "LEON3FT GR716 MINI"; +} + + +addr_t hal_kernelGetAddress(addr_t addr) +{ + return addr; +} + + +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; +} + + +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) +{ + /* Reset to the built-in bootloader */ + hal_interruptsDisableAll(); + + /* Reboot to SPIM */ + *(vu32 *)(BOOTSTRAP_ADDR) = BOOTSTRAP_SPIM; + + /* clang-format off */ + __asm__ volatile ( + "jmp %%g0\n\t" + "nop\n\t" + ::: + ); + /* clang-format on */ + + __builtin_unreachable(); +} diff --git a/hal/sparcv8leon3/gaisler/gr716/peripherals.h b/hal/sparcv8leon3/gaisler/gr716/peripherals.h new file mode 100644 index 00000000..94b3db76 --- /dev/null +++ b/hal/sparcv8leon3/gaisler/gr716/peripherals.h @@ -0,0 +1,67 @@ +/* + * Phoenix-RTOS + * + * Operating system loader + * + * Peripherals definitions for Leon3 GR716 + * + * Copyright 2022-2023 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _PERIPHERALS_H_ +#define _PERIPHERALS_H_ + +#include + +/* GPIO */ + +#define GRGPIO0_BASE ((void *)0x80000900) +#define GRGPIO1_BASE ((void *)0x80000a00) + +/* Timer registers */ + +#define GPT_SCALER 0 /* Scaler value register : 0x00 */ +#define GPT_SRELOAD 1 /* Scaler reload value register : 0x04 */ +#define GPT_CONFIG 2 /* Configuration register : 0x08 */ +#define GPT_LATCHCFG 3 /* Latch configuration register : 0x0C */ +#define GPT_TCNTVAL1 4 /* Timer 1 counter value reg : 0x10 */ +#define GPT_TRLDVAL1 5 /* Timer 1 reload value reg : 0x14 */ +#define GPT_TCTRL1 6 /* Timer 1 control register : 0x18 */ +#define GPT_TLATCH1 7 /* Timer 1 latch register : 0x1C */ +#define GPT_TCNTVAL2 8 /* Timer 2 counter value reg : 0x20 */ +#define GPT_TRLDVAL2 9 /* Timer 2 reload value reg : 0x24 */ +#define GPT_TCTRL2 10 /* Timer 2 control register : 0x28 */ +#define GPT_TLATCH2 11 /* Timer 2 latch register : 0x2C */ +#define GPT_TCNTVAL3 12 /* Timer 3 counter value reg : 0x30 */ +#define GPT_TRLDVAL3 13 /* Timer 3 reload value reg : 0x34 */ +#define GPT_TCTRL3 14 /* Timer 3 control register : 0x38 */ +#define GPT_TLATCH3 15 /* Timer 3 latch register : 0x3C */ +#define GPT_TCNTVAL4 16 /* Timer 4 counter value reg : 0x40 */ +#define GPT_TRLDVAL4 17 /* Timer 4 reload value reg : 0x44 */ +#define GPT_TCTRL4 18 /* Timer 4 control register : 0x48 */ +#define GPT_TLATCH4 19 /* Timer 4 latch register : 0x4C */ +#define GPT_TCNTVAL5 20 /* Timer 5 counter value reg : 0x50 */ +#define GPT_TRLDVAL5 21 /* Timer 5 reload value reg : 0x54 */ +#define GPT_TCTRL5 22 /* Timer 5 control register : 0x58 */ +#define GPT_TLATCH5 23 /* Timer 5 latch register : 0x5C */ +#define GPT_TCNTVAL6 24 /* Timer 6 counter value reg : 0x60 */ +#define GPT_TRLDVAL6 25 /* Timer 6 reload value reg : 0x64 */ +#define GPT_TCTRL6 26 /* Timer 6 control register : 0x68 */ +#define GPT_TLATCH6 27 /* Timer 6 latch register : 0x6C */ +#define GPT_TCNTVAL7 28 /* Timer 7 counter value reg : 0x70 */ +#define GPT_TRLDVAL7 29 /* Timer 7 reload value reg : 0x74 */ +#define GPT_TCTRL7 30 /* Timer 7 control register : 0x78 */ +#define GPT_TLATCH7 31 /* Timer 7 latch register : 0x7C */ + +/* SPI Flash */ + +#define SPIMCTRL0_BASE ((void *)0xfff00100) +#define SPIMCTRL1_BASE ((void *)0xfff00200) + + +#endif diff --git a/hal/sparcv8leon3/gaisler/irqamp.c b/hal/sparcv8leon3/gaisler/irqamp.c new file mode 100644 index 00000000..397f8648 --- /dev/null +++ b/hal/sparcv8leon3/gaisler/irqamp.c @@ -0,0 +1,135 @@ +/* + * Phoenix-RTOS + * + * Operating system loader + * + * Interrupt handling - IRQAMP controller + * + * Copyright 2022 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include + +/* Hardware interrupts */ + +#define SIZE_INTERRUPTS 32 + +/* clang-format off */ + +/* Interrupt controller */ +enum { + int_level = 0, /* Interrupt level register : 0x00 */ + int_pend, /* Interrupt pending register : 0x04 */ + int_force, /* Interrupt force register : 0x08 */ + int_clear, /* Interrupt clear register : 0x0C */ + int_mpstat, /* Status register : 0x10 */ + /* Reserved : 0x14 */ + errstat = 6, /* Error mode status register : 0x18 */ + wdogctrl, /* Watchdog control register : 0x1C */ + /* Reserved : 0x20 - 0x30 */ + eint_clear = 13, /* Extended interrupt clear register : 0x34 */ + /* Reserved : 0x38 - 0x3C */ + pi_mask = 16, /* Processor interrupt mask register : 0x40 */ + /* Reserved : 0x44 - 0x7C */ + pc_force = 32, /* Processor interrupt force register : 0x80 */ + /* Reserved : 0x84 - 0xBC */ + pextack = 48, /* Extended interrupt acknowledge register : 0xC0 */ + /* Reserved : 0xC4 - 0xFC */ + tcnt0 = 64, /* Interrupt timestamp 0 counter register : 0x100 */ + istmpc0, /* Timestamp 0 control register : 0x104 */ + itstmpas0, /* Interrupt assertion timestamp 0 register : 0x108 */ + itstmpack0, /* Interrupt acknowledge timestamp 0 register : 0x10C */ + tcnt1, /* Interrupt timestamp 1 counter register : 0x110 */ + istmpc1, /* Timestamp 1 control register : 0x114 */ + itstmpas1, /* Interrupt assertion timestamp 1 register : 0x118 */ + itstmpack1, /* Interrupt acknowledge timestamp 1 register : 0x11C */ + tcnt2, /* Interrupt timestamp 2 counter register : 0x120 */ + istmpc2, /* Timestamp 2 control register : 0x124 */ + itstmpas2, /* Interrupt assertion timestamp 2 register : 0x128 */ + itstmpack2, /* Interrupt acknowledge timestamp 2 register : 0x12C */ + tcnt3, /* Interrupt timestamp 3 counter register : 0x130 */ + istmpc3, /* Timestamp 3 control register : 0x134 */ + itstmpas3, /* Interrupt assertion timestamp 3 register : 0x138 */ + itstmpack3, /* Interrupt acknowledge timestamp 3 register : 0x13C */ + /* Reserved : 0x140 - 0x1FC */ + procbootadr = 128, /* Processor boot address register : 0x200 */ + /* Reserved : 0x204 - 0x2FC */ + irqmap = 192, /* Interrupt map register : 0x300 - 15 entries*/ +}; + +/* clang-format on */ + +typedef struct { + int (*isr)(unsigned int, void *); + void *data; +} irq_handler_t; + + +static struct { + vu32 *int_ctrl; + irq_handler_t handlers[SIZE_INTERRUPTS]; +} interrupts_common; + + +inline void hal_interruptsEnable(unsigned int irqn) +{ + *(interrupts_common.int_ctrl + pi_mask) |= (1 << irqn); +} + + +inline void hal_interruptsDisable(unsigned int irqn) +{ + *(interrupts_common.int_ctrl + pi_mask) &= ~(1 << irqn); +} + + +int interrupts_dispatch(unsigned int irq) +{ + if (irq == EXTENDED_IRQN) { + /* Extended interrupt (16 - 31) */ + irq = *(interrupts_common.int_ctrl + pextack) & 0x3F; + } + + if ((irq >= SIZE_INTERRUPTS) || (interrupts_common.handlers[irq].isr == NULL)) { + return -1; + } + + interrupts_common.handlers[irq].isr(irq, interrupts_common.handlers[irq].data); + + return 0; +} + + +int hal_interruptsSet(unsigned int n, int (*isr)(unsigned int, void *), void *data) +{ + if (n >= SIZE_INTERRUPTS || n == 0) { + return -1; + } + + hal_interruptsDisableAll(); + interrupts_common.handlers[n].data = data; + interrupts_common.handlers[n].isr = isr; + + if (isr == NULL) { + hal_interruptsDisable(n); + } + else { + hal_interruptsEnable(n); + } + + hal_interruptsEnableAll(); + + return 0; +} + + +void interrupts_init(void) +{ + interrupts_common.int_ctrl = (u32 *)INT_CTRL_BASE; + hal_interruptsEnableAll(); +} diff --git a/hal/sparcv8leon3/gaisler/irqmp.c b/hal/sparcv8leon3/gaisler/irqmp.c new file mode 100644 index 00000000..42afad3f --- /dev/null +++ b/hal/sparcv8leon3/gaisler/irqmp.c @@ -0,0 +1,106 @@ +/* + * Phoenix-RTOS + * + * Operating system loader + * + * Interrupt handling - IRQAMP controller + * + * Copyright 2022 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include + +/* Hardware interrupts */ + +#define SIZE_INTERRUPTS 32 + +/* Interrupt controller */ + +#define INT_LEVEL 0 /* Interrupt level register : 0x00 */ +#define INT_PEND 1 /* Interrupt pending register : 0x04 */ +#define INT_FORCE 2 /* Interrupt force register (CPU 0) : 0x08 */ +#define INT_CLEAR 3 /* Interrupt clear register : 0x0C */ +#define INT_MPSTAT 4 /* Multiprocessor status register : 0x10 */ +#define INT_BRDCAST 5 /* Broadcast register : 0x14 */ +#define INT_MASK_0 16 /* Interrupt mask register (CPU 0) : 0x40 */ +#define INT_MASK_1 17 /* Interrupt mask register (CPU 1) : 0x44 */ +#define INT_FORCE_0 32 /* Interrupt force register (CPU 0) : 0x80 */ +#define INT_FORCE_1 33 /* Interrupt force register (CPU 1) : 0x84 */ +#define INT_EXTID_0 48 /* Extended interrupt ID register (CPU 0) : 0xC0 */ +#define INT_EXTID_1 49 /* Extended interrupt ID register (CPU 1) : 0xC4 */ + + +typedef struct { + int (*isr)(unsigned int, void *); + void *data; +} irq_handler_t; + + +static struct { + vu32 *int_ctrl; + irq_handler_t handlers[SIZE_INTERRUPTS]; +} interrupts_common; + + +inline void hal_interruptsEnable(unsigned int irqn) +{ + *(interrupts_common.int_ctrl + INT_MASK_0) |= (1 << irqn); +} + + +inline void hal_interruptsDisable(unsigned int irqn) +{ + *(interrupts_common.int_ctrl + INT_MASK_0) &= ~(1 << irqn); +} + + +int interrupts_dispatch(unsigned int irq) +{ + if (irq == EXTENDED_IRQN) { + /* Extended interrupt (16 - 31) */ + irq = *(interrupts_common.int_ctrl + INT_EXTID_0) & 0x3F; + } + + if ((irq >= SIZE_INTERRUPTS) || (interrupts_common.handlers[irq].isr == NULL)) { + return -1; + } + + interrupts_common.handlers[irq].isr(irq, interrupts_common.handlers[irq].data); + + return 0; +} + + +int hal_interruptsSet(unsigned int n, int (*isr)(unsigned int, void *), void *data) +{ + if (n >= SIZE_INTERRUPTS || n == 0) { + return -1; + } + + hal_interruptsDisableAll(); + interrupts_common.handlers[n].data = data; + interrupts_common.handlers[n].isr = isr; + + if (isr == NULL) { + hal_interruptsDisable(n); + } + else { + hal_interruptsEnable(n); + } + + hal_interruptsEnableAll(); + + return 0; +} + + +void interrupts_init(void) +{ + interrupts_common.int_ctrl = (u32 *)INT_CTRL_BASE; + hal_interruptsEnableAll(); +} diff --git a/hal/sparcv8leon3/gaisler/timer.c b/hal/sparcv8leon3/gaisler/timer.c new file mode 100644 index 00000000..67565f43 --- /dev/null +++ b/hal/sparcv8leon3/gaisler/timer.c @@ -0,0 +1,126 @@ +/* + * Phoenix-RTOS + * + * Operating system loader + * + * Timer controller + * + * Copyright 2022 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include + +/* Timer control bitfields */ + +#define TIMER_ENABLE (1 << 0) +#define TIMER_PERIODIC (1 << 1) +#define TIMER_LOAD (1 << 2) +#define TIMER_INT_ENABLE (1 << 3) +#define TIMER_INT_PENDING (1 << 4) +#define TIMER_CHAIN (1 << 5) + +#define TIMER_DEFAULT_FREQ 1000 + + +/* clang-format off */ + +enum { timer1 = 0, timer2, timer3, timer4 }; + +/* clang-format on */ + + +static struct { + vu32 *gptimer0_base; + vu32 *gptimer1_base; + volatile time_t time; + u32 ticksPerFreq; +} timer_common; + + +static int timer_isr(unsigned int irq, void *data) +{ + vu32 st = *(timer_common.gptimer0_base + GPT_TCTRL1) & TIMER_INT_PENDING; + + if (st != 0) { + ++timer_common.time; + /* Clear irq status */ + *(timer_common.gptimer0_base + GPT_TCTRL1) |= TIMER_INT_PENDING; + } + + return 0; +} + + +static void timer_setPrescaler(int timer, u32 freq) +{ + u32 prescaler = SYSCLK_FREQ / 1000000; /* 1 MHz */ + u32 ticks = (SYSCLK_FREQ / prescaler) / freq; + + *(timer_common.gptimer0_base + GPT_TRLDVAL1 + timer * 4) = ticks - 1; + *(timer_common.gptimer0_base + GPT_SRELOAD) = prescaler - 1; + + timer_common.ticksPerFreq = ticks; +} + + +time_t hal_timerGet(void) +{ + time_t val; + + hal_interruptsDisableAll(); + val = timer_common.time; + hal_interruptsEnableAll(); + + return val; +} + + +void timer_done(void) +{ + int timer; + /* Disable timer interrupts - bits cleared when written 1 */ + vu32 st = *(timer_common.gptimer0_base + GPT_TCTRL1) & (TIMER_INT_ENABLE | TIMER_INT_PENDING); + *(timer_common.gptimer0_base + GPT_TCTRL1) = st; + st = *(timer_common.gptimer1_base + GPT_TCTRL1) & (TIMER_INT_ENABLE | TIMER_INT_PENDING); + *(timer_common.gptimer1_base + GPT_TCTRL1) = st; + + for (timer = 0; timer < TIMER0_CNT; ++timer) { + /* Disable timers */ + *(timer_common.gptimer0_base + GPT_TCTRL1 + timer * 4) = 0; + /* Reset counter and reload value */ + *(timer_common.gptimer0_base + GPT_TCNTVAL1 + timer * 4) = 0; + *(timer_common.gptimer0_base + GPT_TRLDVAL1 + timer * 4) = 0; + } + + for (timer = 0; timer < TIMER1_CNT; ++timer) { + *(timer_common.gptimer1_base + GPT_TCTRL1 + timer * 4) = 0; + *(timer_common.gptimer1_base + GPT_TCNTVAL1 + timer * 4) = 0; + *(timer_common.gptimer1_base + GPT_TRLDVAL1 + timer * 4) = 0; + } + + hal_interruptsSet(TIMER_IRQ, NULL, NULL); +} + + +void timer_init(void) +{ + timer_common.time = 0; + timer_common.gptimer0_base = (u32 *)GPTIMER0_BASE; + timer_common.gptimer1_base = (u32 *)GPTIMER1_BASE; + + /* Reset timer */ + timer_done(); + + timer_setPrescaler(timer1, TIMER_DEFAULT_FREQ); + + hal_interruptsSet(TIMER_IRQ, timer_isr, NULL); + + /* Enable timer and interrupts */ + /* Load reload value into counter register */ + *(timer_common.gptimer0_base + GPT_TCTRL1) |= TIMER_ENABLE | TIMER_PERIODIC | TIMER_LOAD | TIMER_INT_ENABLE; +} diff --git a/hal/sparcv8leon3/gr716/types.h b/hal/sparcv8leon3/gaisler/types.h similarity index 100% rename from hal/sparcv8leon3/gr716/types.h rename to hal/sparcv8leon3/gaisler/types.h diff --git a/hal/sparcv8leon3/gr716/peripherals.h b/hal/sparcv8leon3/gr716/peripherals.h deleted file mode 100644 index 0f2e3029..00000000 --- a/hal/sparcv8leon3/gr716/peripherals.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Phoenix-RTOS - * - * Operating system loader - * - * Peripherals definitions for Leon3 GR716 - * - * Copyright 2022 Phoenix Systems - * Author: Lukasz Leczkowski - * - * This file is part of Phoenix-RTOS. - * - * %LICENSE% - */ - -#ifndef _PERIPHERALS_H_ -#define _PERIPHERALS_H_ - -#include - -/* GPIO */ - -#define GRGPIO0_BASE ((void *)0x8030C000) -#define GRGPIO1_BASE ((void *)0x8030D000) - -/* Interrupts */ - -#define INT_CTRL_BASE ((void *)0x80002000) - -/* Timers */ - -#define TIMER_IRQ 9 -#define GPTIMER0_BASE ((void *)0x80003000) -#define GPTIMER1_BASE ((void *)0x80004000) - -/* SPI Flash */ - -#define SPIMCTRL0_BASE ((void *)0xFFF00100) -#define SPIMCTRL1_BASE ((void *)0xFFF00200) - - -#endif diff --git a/hal/sparcv8leon3/gr716/timer.c b/hal/sparcv8leon3/gr716/timer.c deleted file mode 100644 index def88d01..00000000 --- a/hal/sparcv8leon3/gr716/timer.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Phoenix-RTOS - * - * Operating system loader - * - * Timer controller - * - * Copyright 2022 Phoenix Systems - * Author: Lukasz Leczkowski - * - * This file is part of Phoenix-RTOS. - * - * %LICENSE% - */ - -#include - -/* Timer control bitfields */ -#define TIMER_ENABLE (1) -#define TIMER_PERIODIC (1 << 1) -#define TIMER_LOAD (1 << 2) -#define TIMER_INT_ENABLE (1 << 3) -#define TIMER_INT_PENDING (1 << 4) -#define TIMER_CHAIN (1 << 5) - -#define TIMER_DEFAULT_FREQ 1000 - - -enum { - gpt_scaler = 0, /* Scaler value register : 0x00 */ - gpt_sreload, /* Scaler reload value register : 0x04 */ - gpt_config, /* Configuration register : 0x08 */ - gpt_latchcfg, /* Latch configuration register : 0x0C */ - gpt_tcntval1, /* Timer 1 counter value reg : 0x10 */ - gpt_trldval1, /* Timer 1 reload value reg : 0x14 */ - gpt_tctrl1, /* Timer 1 control register : 0x18 */ - gpt_tlatch1, /* Timer 1 latch register : 0x1C */ - gpt_tcntval2, /* Timer 2 counter value reg : 0x20 */ - gpt_trldval2, /* Timer 2 reload value reg : 0x24 */ - gpt_tctrl2, /* Timer 2 control register : 0x28 */ - gpt_tlatch2, /* Timer 2 latch register : 0x2C */ - gpt_tcntval3, /* Timer 3 counter value reg : 0x30 */ - gpt_trldval3, /* Timer 3 reload value reg : 0x34 */ - gpt_tctrl3, /* Timer 3 control register : 0x38 */ - gpt_tlatch3, /* Timer 3 latch register : 0x3C */ - gpt_tcntval4, /* Timer 4 counter value reg : 0x40 */ - gpt_trldval4, /* Timer 4 reload value reg : 0x44 */ - gpt_tctrl4, /* Timer 4 control register : 0x48 */ - gpt_tlatch4, /* Timer 4 latch register : 0x4C */ - gpt_tcntval5, /* Timer 5 counter value reg : 0x50 */ - gpt_trldval5, /* Timer 5 reload value reg : 0x54 */ - gpt_tctrl5, /* Timer 5 control register : 0x58 */ - gpt_tlatch5, /* Timer 5 latch register : 0x5C */ - gpt_tcntval6, /* Timer 6 counter value reg : 0x60 */ - gpt_trldval6, /* Timer 6 reload value reg : 0x64 */ - gpt_tctrl6, /* Timer 6 control register : 0x68 */ - gpt_tlatch6, /* Timer 6 latch register : 0x6C */ - gpt_tcntval7, /* Timer 7 counter value reg : 0x70 */ - gpt_trldval7, /* Timer 7 reload value reg : 0x74 */ - gpt_tctrl7, /* Timer 7 control register : 0x78 */ - gpt_tlatch7, /* Timer 7 latch register : 0x7C */ -}; - -/* clang-format off */ - -enum { timer1 = 0, timer2, timer3, timer4, timer5, timer6, timer7 }; - -/* clang-format on */ - -static struct { - vu32 *gptimer0_base; - vu32 *gptimer1_base; - volatile time_t time; - u32 ticksPerFreq; -} timer_common; - - -static int timer_isr(unsigned int irq, void *data) -{ - vu32 st = *(timer_common.gptimer0_base + gpt_tctrl1) & TIMER_INT_PENDING; - - if (st != 0) { - ++timer_common.time; - /* Clear irq status */ - *(timer_common.gptimer0_base + gpt_tctrl1) |= TIMER_INT_PENDING; - } - - return 0; -} - - -static void timer_setPrescaler(int timer, u32 freq) -{ - u32 prescaler = SYSCLK_FREQ / 1000000; /* 1 MHz */ - u32 ticks = (SYSCLK_FREQ / prescaler) / freq; - - *(timer_common.gptimer0_base + gpt_trldval1 + timer * 4) = ticks - 1; - *(timer_common.gptimer0_base + gpt_sreload) = prescaler - 1; - - timer_common.ticksPerFreq = ticks; -} - - -time_t hal_timerGet(void) -{ - time_t val; - - hal_interruptsDisableAll(); - val = timer_common.time; - hal_interruptsEnableAll(); - - return val; -} - - -void timer_done(void) -{ - int timer; - /* Disable timer interrupts - bits cleared when written 1 */ - vu32 st = *(timer_common.gptimer0_base + gpt_tctrl1) & (TIMER_INT_ENABLE | TIMER_INT_PENDING); - *(timer_common.gptimer0_base + gpt_tctrl1) = st; - st = *(timer_common.gptimer1_base + gpt_tctrl1) & (TIMER_INT_ENABLE | TIMER_INT_PENDING); - *(timer_common.gptimer1_base + gpt_tctrl1) = st; - - for (timer = timer1; timer <= timer7; ++timer) { - /* Disable timers */ - *(timer_common.gptimer0_base + gpt_tctrl1 + timer * 4) = 0; - *(timer_common.gptimer1_base + gpt_tctrl1 + timer * 4) = 0; - /* Reset counter and reload value */ - *(timer_common.gptimer0_base + gpt_tcntval1 + timer * 4) = 0; - *(timer_common.gptimer0_base + gpt_trldval1 + timer * 4) = 0; - *(timer_common.gptimer1_base + gpt_tcntval1 + timer * 4) = 0; - *(timer_common.gptimer1_base + gpt_trldval1 + timer * 4) = 0; - } - - hal_interruptsSet(TIMER_IRQ, NULL, NULL); -} - - -void timer_init(void) -{ - timer_common.time = 0; - timer_common.gptimer0_base = (u32 *)GPTIMER0_BASE; - timer_common.gptimer1_base = (u32 *)GPTIMER1_BASE; - - /* Reset timer */ - timer_done(); - - timer_setPrescaler(timer1, TIMER_DEFAULT_FREQ); - - hal_interruptsSet(TIMER_IRQ, timer_isr, NULL); - - /* Enable timer and interrupts */ - /* Load reload value into counter register */ - *(timer_common.gptimer0_base + gpt_tctrl1) |= TIMER_ENABLE | TIMER_PERIODIC | TIMER_LOAD | TIMER_INT_ENABLE; -} diff --git a/hal/sparcv8leon3/interrupts.c b/hal/sparcv8leon3/interrupts.c index 38e55e48..2a5c0c5d 100644 --- a/hal/sparcv8leon3/interrupts.c +++ b/hal/sparcv8leon3/interrupts.c @@ -19,85 +19,16 @@ #define STR(x) #x #define XSTR(x) STR(x) -/* Hardware interrupts */ -#define SIZE_INTERRUPTS 64 - -/* clang-format off */ - -/* Interrupt controller */ -enum { - int_level = 0, /* Interrupt level register : 0x00 */ - int_pend, /* Interrupt pending register : 0x04 */ - int_force, /* Interrupt force register : 0x08 */ - int_clear, /* Interrupt clear register : 0x0C */ - int_mpstat, /* Status register : 0x10 */ - /* Reserved : 0x14 */ - errstat = 6, /* Error mode status register : 0x18 */ - wdogctrl, /* Watchdog control register : 0x1C */ - /* Reserved : 0x20 - 0x30 */ - eint_clear = 13, /* Extended interrupt clear register : 0x34 */ - /* Reserved : 0x38 - 0x3C */ - pi_mask = 16, /* Processor interrupt mask register : 0x40 */ - /* Reserved : 0x44 - 0x7C */ - pc_force = 32, /* Processor interrupt force register : 0x80 */ - /* Reserved : 0x84 - 0xBC */ - pextack = 48, /* Extended interrupt acknowledge register : 0xC0 */ - /* Reserved : 0xC4 - 0xFC */ - tcnt0 = 64, /* Interrupt timestamp 0 counter register : 0x100 */ - istmpc0, /* Timestamp 0 control register : 0x104 */ - itstmpas0, /* Interrupt assertion timestamp 0 register : 0x108 */ - itstmpack0, /* Interrupt acknowledge timestamp 0 register : 0x10C */ - tcnt1, /* Interrupt timestamp 1 counter register : 0x110 */ - istmpc1, /* Timestamp 1 control register : 0x114 */ - itstmpas1, /* Interrupt assertion timestamp 1 register : 0x118 */ - itstmpack1, /* Interrupt acknowledge timestamp 1 register : 0x11C */ - tcnt2, /* Interrupt timestamp 2 counter register : 0x120 */ - istmpc2, /* Timestamp 2 control register : 0x124 */ - itstmpas2, /* Interrupt assertion timestamp 2 register : 0x128 */ - itstmpack2, /* Interrupt acknowledge timestamp 2 register : 0x12C */ - tcnt3, /* Interrupt timestamp 3 counter register : 0x130 */ - istmpc3, /* Timestamp 3 control register : 0x134 */ - itstmpas3, /* Interrupt assertion timestamp 3 register : 0x138 */ - itstmpack3, /* Interrupt acknowledge timestamp 3 register : 0x13C */ - /* Reserved : 0x140 - 0x1FC */ - procbootadr = 128, /* Processor boot address register : 0x200 */ - /* Reserved : 0x204 - 0x2FC */ - irqmap = 192, /* Interrupt map register : 0x300 - 15 entries*/ -}; - -/* clang-format on */ - -typedef struct { - int (*isr)(unsigned int, void *); - void *data; -} irq_handler_t; - - -static struct { - vu32 *int_ctrl; - irq_handler_t handlers[SIZE_INTERRUPTS]; -} interrupts_common; - - -inline void hal_interruptsEnable(unsigned int irqn) -{ - *(interrupts_common.int_ctrl + pi_mask) |= (1 << irqn); -} - - -inline void hal_interruptsDisable(unsigned int irqn) -{ - *(interrupts_common.int_ctrl + pi_mask) &= ~(1 << irqn); -} - inline void hal_interruptsEnableAll(void) { /* clang-format off */ __asm__ volatile( - "mov 0, %%o0;" - "ta 0x09;" + "mov 0, %%o0\n\t" + "ta 0x09\n\t" + /* TN-0018 Errata */ + "nop\n\t" : : : "%o0", "memory"); @@ -111,52 +42,13 @@ inline void hal_interruptsDisableAll(void) /* clang-format off */ __asm__ volatile( - "mov " XSTR(PSR_PIL) ", %%o0;" - "ta 0x09;" + "mov " XSTR(PSR_PIL) ", %%o0\n\t" + "ta 0x09\n\t" + /* TN-0018 Errata */ + "nop\n\t" : : : "%o0", "memory"); /* clang-format on */ } - - -int interrupts_dispatch(unsigned int irq) -{ - if (interrupts_common.handlers[irq].isr == NULL) { - return -1; - } - interrupts_common.handlers[irq].isr(irq, interrupts_common.handlers[irq].data); - - return 0; -} - - -int hal_interruptsSet(unsigned int n, int (*isr)(unsigned int, void *), void *data) -{ - if (n >= SIZE_INTERRUPTS || n == 0) { - return -1; - } - - hal_interruptsDisableAll(); - interrupts_common.handlers[n].data = data; - interrupts_common.handlers[n].isr = isr; - - if (isr == NULL) { - hal_interruptsDisable(n); - } - else { - hal_interruptsEnable(n); - } - - hal_interruptsEnableAll(); - - return 0; -} - - -void interrupts_init(void) -{ - interrupts_common.int_ctrl = (u32 *)INT_CTRL_BASE; - hal_interruptsEnableAll(); -} diff --git a/ld/sparcv8leon3-gr712rc.ldt b/ld/sparcv8leon3-gr712rc.ldt new file mode 100644 index 00000000..8efffe5f --- /dev/null +++ b/ld/sparcv8leon3-gr712rc.ldt @@ -0,0 +1,48 @@ +/* + * Phoenix-RTOS + * + * Operating system loader + * + * Linker Template and Platform Config for SPARC V8 LEON3 GR712RC + * + * Copyright 2023 Phoenix Systems + * Author: Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef LEON3_GR712RC_LDT +#define LEON3_GR712RC_LDT + +#define SIZE_PAGE 0x1000 +#define SIZE_STACK (SIZE_PAGE) +#define SIZE_HEAP (SIZE_PAGE) + +#define ADDR_SRAM 0x40000000 + +#define SIZE_SRAM (128 * 1024 * 1024) +#define SIZE_PLO (4 * 1024 * 1024) + +#if defined(__LINKER__) + +/* Memory map setup */ +MEMORY +{ + m_prom (rx) : ORIGIN = 0x00000000, LENGTH = 64M + m_sram (rwx) : ORIGIN = ADDR_SRAM + SIZE_SRAM - SIZE_PLO, LENGTH = SIZE_PLO +} + +REGION_ALIAS("PLO_IMAGE", 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