diff --git a/dts/bindings/cpu/sensry,ganymed-sy1xx.yaml b/dts/bindings/cpu/sensry,ganymed-sy1xx.yaml new file mode 100644 index 00000000000..307716bb520 --- /dev/null +++ b/dts/bindings/cpu/sensry,ganymed-sy1xx.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2024 sensry.io +# SPDX-License-Identifier: Apache-2.0 + +include: riscv,cpus.yaml + +description: Sensry Ganymed SY1xx Core CPU + +compatible: "sensry,sy1xx" diff --git a/dts/bindings/vendor-prefixes.txt b/dts/bindings/vendor-prefixes.txt index f5d378cf6ee..466ea9e3f3c 100644 --- a/dts/bindings/vendor-prefixes.txt +++ b/dts/bindings/vendor-prefixes.txt @@ -588,6 +588,7 @@ seirobotics Shenzhen SEI Robotics Co., Ltd semtech Semtech Corporation sensirion Sensirion AG sensortek Sensortek Technology Corporation +sensry sensry.io sff Small Form Factor Committee sgd Solomon Goldentek Display Corporation sgmicro SG Micro Corp diff --git a/soc/sensry/CMakeLists.txt b/soc/sensry/CMakeLists.txt new file mode 100644 index 00000000000..0820b6c4468 --- /dev/null +++ b/soc/sensry/CMakeLists.txt @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 sensry.io + +zephyr_include_directories(${SOC_FAMILY}/${SOC_SERIES}/common) + +add_subdirectory_ifdef(CONFIG_SOC_SERIES_SY1XX ganymed/sy1xx) diff --git a/soc/sensry/Kconfig b/soc/sensry/Kconfig new file mode 100644 index 00000000000..bc1354d83fc --- /dev/null +++ b/soc/sensry/Kconfig @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 sensry.io + +if SOC_FAMILY_GANYMED + +rsource "*/Kconfig" + +endif # SOC_FAMILY_GANYMED diff --git a/soc/sensry/Kconfig.defconfig b/soc/sensry/Kconfig.defconfig new file mode 100644 index 00000000000..c897a44a934 --- /dev/null +++ b/soc/sensry/Kconfig.defconfig @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 sensry.io + +if SOC_FAMILY_GANYMED + +rsource "*/Kconfig.defconfig" + +endif diff --git a/soc/sensry/Kconfig.soc b/soc/sensry/Kconfig.soc new file mode 100644 index 00000000000..8265f00bfe2 --- /dev/null +++ b/soc/sensry/Kconfig.soc @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 sensry.io + +config SOC_FAMILY_GANYMED + bool + +config SOC_FAMILY + default "ganymed" if SOC_FAMILY_GANYMED + +rsource "*/Kconfig.soc" diff --git a/soc/sensry/ganymed/Kconfig b/soc/sensry/ganymed/Kconfig new file mode 100644 index 00000000000..5eaf4d8b092 --- /dev/null +++ b/soc/sensry/ganymed/Kconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 sensry.io + +config SOC_FAMILY_GANYMED + select BUILD_OUTPUT_BIN + +if SOC_SERIES_SY1XX + +rsource "*/Kconfig" + +endif # SOC_SERIES_SY1XX diff --git a/soc/sensry/ganymed/Kconfig.defconfig b/soc/sensry/ganymed/Kconfig.defconfig new file mode 100644 index 00000000000..0ea55630825 --- /dev/null +++ b/soc/sensry/ganymed/Kconfig.defconfig @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 sensry.io + +if SOC_SERIES_SY1XX + +rsource "*/Kconfig.defconfig" + +endif diff --git a/soc/sensry/ganymed/Kconfig.soc b/soc/sensry/ganymed/Kconfig.soc new file mode 100644 index 00000000000..958008661bf --- /dev/null +++ b/soc/sensry/ganymed/Kconfig.soc @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 sensry.io + +rsource "*/Kconfig.soc" diff --git a/soc/sensry/ganymed/sy1xx/CMakeLists.txt b/soc/sensry/ganymed/sy1xx/CMakeLists.txt new file mode 100644 index 00000000000..d7fc1725229 --- /dev/null +++ b/soc/sensry/ganymed/sy1xx/CMakeLists.txt @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 sensry.io + +zephyr_include_directories(common) + +zephyr_compile_options(-march=rv32imc_zicsr -mabi=ilp32) + +zephyr_sources( + common/crt0.S + common/soc.c + common/udma.c +) + +zephyr_linker_sources(ROM_START SORT_KEY 0x0vectors common/vector_table.ld) + +set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/common/linker.ld CACHE INTERNAL "") diff --git a/soc/sensry/ganymed/sy1xx/Kconfig b/soc/sensry/ganymed/sy1xx/Kconfig new file mode 100644 index 00000000000..54d6d4930bb --- /dev/null +++ b/soc/sensry/ganymed/sy1xx/Kconfig @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 sensry.io + +config SOC_SERIES_SY1XX + select RISCV + select RISCV_ISA_RV32I + select RISCV_ISA_EXT_M + select RISCV_ISA_EXT_ZICSR + select RISCV_PRIVILEGED + select ATOMIC_OPERATIONS_C diff --git a/soc/sensry/ganymed/sy1xx/Kconfig.defconfig b/soc/sensry/ganymed/sy1xx/Kconfig.defconfig new file mode 100644 index 00000000000..3c60c5ce329 --- /dev/null +++ b/soc/sensry/ganymed/sy1xx/Kconfig.defconfig @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 sensry.io + +if SOC_SERIES_SY1XX + +config RISCV_PMP + default n + +config RISCV_HAS_CLIC + default n + +config RISCV_VECTORED_MODE + default y + +config INCLUDE_RESET_VECTOR + default y + +config GEN_IRQ_VECTOR_TABLE + default y + +config RISCV_GENERIC_TOOLCHAIN + default y if "$(ZEPHYR_TOOLCHAIN_VARIANT)" = "zephyr" + +config RV_BOOT_HART + # default cluster id 0x3e, core 0 (FC) => 0x3e0 == 992 + default 992 + +config RISCV_SOC_CONTEXT_SAVE + default n + +config RISCV_SOC_OFFSETS + default n + +config NUM_IRQS + default 32 + +config RISCV_SOC_INTERRUPT_INIT + default y + +config RISCV_SOC_HAS_ISR_STACKING + default n + +config DYNAMIC_INTERRUPTS + default y + +config GEN_ISR_TABLES + default y + +config RISCV_MCAUSE_EXCEPTION_MASK + default 0x1F + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 32768 + +config SYS_CLOCK_TICKS_PER_SEC + default 993 + +config USE_DT_CODE_PARTITION + default y + +config RISCV_SOC_HAS_CUSTOM_IRQ_LOCK_OPS + default n + +config RISCV_SOC_EXCEPTION_FROM_IRQ + default y + +config INIT_STACKS + default y + +config XIP + default n + +config TIMESLICE_SIZE + default 10 + +endif diff --git a/soc/sensry/ganymed/sy1xx/Kconfig.soc b/soc/sensry/ganymed/sy1xx/Kconfig.soc new file mode 100644 index 00000000000..b117738bc1b --- /dev/null +++ b/soc/sensry/ganymed/sy1xx/Kconfig.soc @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 sensry.io + +config SOC_SERIES_SY1XX + bool + select SOC_FAMILY_GANYMED + +config SOC_SERIES + default "sy1xx" if SOC_SERIES_SY1XX + +config SOC_SY120_GBM + bool + select SOC_SERIES_SY1XX + +config SOC_SY120_GEN1 + bool + select SOC_SERIES_SY1XX + +config SOC + default "sy120_gbm" if SOC_SY120_GBM + default "sy120_gen1" if SOC_SY120_GEN1 diff --git a/soc/sensry/ganymed/sy1xx/common/crt0.S b/soc/sensry/ganymed/sy1xx/common/crt0.S new file mode 100644 index 00000000000..bbffbec9258 --- /dev/null +++ b/soc/sensry/ganymed/sy1xx/common/crt0.S @@ -0,0 +1,144 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 sensry.io + +#include + + +GTEXT(__initialize) + + # abs 0x0000 - entry point after bootloader +.section .pre_start, "ax" +.global __pre_start +__pre_start: + jal x0, __prestart_routine + + + # abs 0x0080 - will be checked by bootloader +.section .validity_marker, "ax" + .word 0xAA551234 + + # abs 0x0100 - text +.section .text, "ax" +__prestart_routine: + /* things that will be done prior to actually starting zephyr */ + csrwi mstatus, 0x00 + + /* Call into Zephyr initialization. */ + jal x0, __start + +GTEXT(__soc_is_irq) +SECTION_FUNC(exception.other, __soc_is_irq) + csrr a0, mcause + srli a0, a0, 31 + ret + +GTEXT(__soc_handle_irq) +SECTION_FUNC(exception.other, __soc_handle_irq) + ## clear pending interrupt + ret + +# we provide a "backup" isr table, if generation (ex. in tests) is disabled +.global _irq_vector_table +.weak _irq_vector_table +.section .text, "ax" +_irq_vector_table: +.option norvc; + + j __no_irq_handler0 + j __no_irq_handler1 + j __no_irq_handler2 + j __no_irq_handler3 + j __no_irq_handler4 + j __no_irq_handler5 + j __no_irq_handler6 + j __no_irq_handler7 + j __no_irq_handler8 + j __no_irq_handler9 + j __no_irq_handler10 + j __no_irq_handler11 + j __no_irq_handler12 + j __no_irq_handler13 + j __no_irq_handler14 + j __no_irq_handler15 + j __no_irq_handler16 + j __no_irq_handler17 + j __no_irq_handler18 + j __no_irq_handler19 + j __no_irq_handler20 + j __no_irq_handler21 + j __no_irq_handler22 + j __no_irq_handler23 + j __no_irq_handler24 + j __no_irq_handler25 + j __no_irq_handler26 + j __no_irq_handler27 + j __no_irq_handler28 + j __no_irq_handler29 + j __no_irq_handler30 + j __no_irq_handler31 + + +__no_irq_handler0: + j __no_irq_handler0 +__no_irq_handler1: + j __no_irq_handler1 +__no_irq_handler2: + j __no_irq_handler2 +__no_irq_handler3: + j __no_irq_handler3 +__no_irq_handler4: + j __no_irq_handler4 +__no_irq_handler5: + j __no_irq_handler5 +__no_irq_handler6: + j __no_irq_handler6 +__no_irq_handler7: + j __no_irq_handler7 +__no_irq_handler8: + j __no_irq_handler8 +__no_irq_handler9: + j __no_irq_handler9 +__no_irq_handler10: + j __no_irq_handler10 +__no_irq_handler11: + j __no_irq_handler11 +__no_irq_handler12: + j __no_irq_handler12 +__no_irq_handler13: + j __no_irq_handler13 +__no_irq_handler14: + j __no_irq_handler14 +__no_irq_handler15: + j __no_irq_handler15 +__no_irq_handler16: + j __no_irq_handler16 +__no_irq_handler17: + j __no_irq_handler17 +__no_irq_handler18: + j __no_irq_handler18 +__no_irq_handler19: + j __no_irq_handler19 +__no_irq_handler20: + j __no_irq_handler20 +__no_irq_handler21: + j __no_irq_handler21 +__no_irq_handler22: + j __no_irq_handler22 +__no_irq_handler23: + j __no_irq_handler23 +__no_irq_handler24: + j __no_irq_handler24 +__no_irq_handler25: + j __no_irq_handler25 +__no_irq_handler26: + j __no_irq_handler26 +__no_irq_handler27: + j __no_irq_handler27 +__no_irq_handler28: + j __no_irq_handler28 +__no_irq_handler29: + j __no_irq_handler29 +__no_irq_handler30: + j __no_irq_handler30 +__no_irq_handler31: + j __no_irq_handler31 diff --git a/soc/sensry/ganymed/sy1xx/common/linker.ld b/soc/sensry/ganymed/sy1xx/common/linker.ld new file mode 100644 index 00000000000..49b38680a41 --- /dev/null +++ b/soc/sensry/ganymed/sy1xx/common/linker.ld @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * Copyright (c) 2016-2017 Jean-Paul Etienne + * Copyright (c) 2018 Foundries.io Ltd + * Copyright (c) 2024 sensry.io + * + * This file is based on: + * + * - include/arch/arm/cortex_m/scripts/linker.ld + * - include/arch/riscv/common/linker.ld + * - include/arch/riscv/pulpino/linker.ld + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include + +#define MPU_ALIGN(region_size) . = ALIGN(4) + +/* + * Extra efforts would need to be taken to ensure the IRQ handlers are within + * jumping distance of the vector table in non-XIP builds, so avoid them. + */ +#define ROMABLE_REGION ROM +#define RAMABLE_REGION RAM + +## ROM AREA ## +#define ROM_BASE 0x1C010100 +#define ROM_SIZE 0x5Fa00 + +## RAM AREA ## +#define RAM_BASE 0x1C070000 +#define RAM_SIZE 0x200000 + +MEMORY + { + L2_START (rx) : ORIGIN = 0x1c010000, LENGTH = 0x00000080 + L2_VALIDITY (rx) : ORIGIN = 0x1c010080, LENGTH = 0x00000080 + + ROM (rx) : ORIGIN = ROM_BASE, LENGTH = ROM_SIZE /* 392kb */ + RAM (rwx) : ORIGIN = RAM_BASE, LENGTH = RAM_SIZE /* 2097kb */ + + L2_PRIV_CH0 : ORIGIN = 0x1c004100, LENGTH = 0x2000 /* uDMA access */ + + /* + * Special section, not included in the final binary, used + * to generate interrupt tables. See include/linker/intlist.ld. + */ + IDT_LIST : ORIGIN = 0xFFFFF7FF, LENGTH = 2K + } + +ENTRY(CONFIG_KERNEL_ENTRY) + +SECTIONS + { + + .pre_start MAX(0x1c010000,ALIGN(0x80)) : + { + KEEP(*(.pre_start)) + } > L2_START + + .validity_marker MAX(0x1c010080,ALIGN(0x80)) : + { + KEEP(*(.validity_marker)) + } > L2_VALIDITY + + /* uninitialized space for uDMA access */ + .udma_access (NOLOAD): { + . = ALIGN(4); + _udma_space_start = .; + *(.udma_access) + _udma_space_end = .; + } > L2_PRIV_CH0 + + #include + + + SECTION_PROLOGUE(.plt,,) + { + *(.plt) + } + + + SECTION_PROLOGUE(.iplt,,) + { + *(.iplt) + } + + + GROUP_START(ROM) + __rom_region_start = ROM_BASE; + + SECTION_PROLOGUE(_TEXT_SECTION_NAME,,) + { + + /* Located in generated directory. This file is populated by calling + * zephyr_linker_sources(ROM_START ...). This typically contains the vector + * table and debug information. + */ + #include + + __text_region_start = .; + + *(.text .text.*) + *(.gnu.linkonce.t.*) + *(.eh_frame) + + } GROUP_LINK_IN(ROM) + + __text_region_end = .; + + + __rodata_region_start = .; + + #include + #include + + SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) + { + . = ALIGN(4); + *(.srodata) + *(".srodata.*") + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + + /* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ + #include + + } GROUP_LINK_IN(ROMABLE_REGION) + + #include + + __rodata_region_end = .; + + __rom_region_end = .; + GROUP_END(ROM) + + GROUP_START(RAM) + + SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,) + { + . = ALIGN(4); + _image_ram_start = .; + __data_region_start = .; + __data_start = .; + + *(.data) + *(.data.*) + *(.gnu.linkonce.s.*) + + /* https://groups.google.com/a/groups.riscv.org/d/msg/sw-dev/60IdaZj27dY/TKT3hbNlAgAJ */ + *(.sdata .sdata.* .gnu.linkonce.s.*) + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + + /* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ + #include + + __data_end = .; + + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + __data_size = __data_end - __data_start; + + + __data_load_start = LOADADDR(_DATA_SECTION_NAME); + + #include + #include + + /* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ + #include + + __data_region_end = .; + __data_region_load_start = LOADADDR(_DATA_SECTION_NAME); + + SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) + { + /* + * For performance, BSS section is assumed to be 4 byte aligned and + * a multiple of 4 bytes, so it can be cleared in words. + */ + . = ALIGN(4); + __bss_start = .; + + *(.bss .bss.*) + *(.sbss .sbss.*) + COMMON_SYMBOLS + + /* Ensure 4 byte alignment for the entire section. */ + . = ALIGN(4); + __bss_end = .; + } GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION) + + SECTION_PROLOGUE(_NOINIT_SECTION_NAME,(NOLOAD),) + { + /* + * This section is used for non-initialized objects that + * will not be cleared during the boot process. + */ + *(.noinit .noinit.*) + + /* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ + #include + + } GROUP_LINK_IN(RAMABLE_REGION) + + /* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ + #include + + /* Located in generated directory. This file is populated by the + * zephyr_linker_sources() Cmake function. + */ + #include + + #include + + GROUP_END(RAMABLE_REGION) + + #ifdef CONFIG_GEN_ISR_TABLES + /* Bogus section, post-processed during the build to initialize interrupts. */ + #include + #endif + + #include + + SECTION_PROLOGUE(.riscv.attributes, 0,) + { + KEEP(*(.riscv.attributes)) + KEEP(*(.gnu.attributes)) + } + + /* + * Pulpino toolchains emit these sections; we don't care about them, + * but need to avoid build system warnings about orphaned sections. + */ + SECTION_PROLOGUE(.Pulp_Chip.Info,,) + { + *(.Pulp_Chip.*) + } + + } diff --git a/soc/sensry/ganymed/sy1xx/common/pad_ctrl.h b/soc/sensry/ganymed/sy1xx/common/pad_ctrl.h new file mode 100644 index 00000000000..2fa2656c83d --- /dev/null +++ b/soc/sensry/ganymed/sy1xx/common/pad_ctrl.h @@ -0,0 +1,44 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2024 sensry.io + */ + +#ifndef GANYMED_SY1XX_PAD_CTRL_H +#define GANYMED_SY1XX_PAD_CTRL_H + +#define PAD_CONFIG(pin_offset, SMT, SLEW, PULLUP, PULLDOWN, DRV, PMOD, DIR) \ + (((SMT << 7) | (SLEW << 6) | (PULLUP << 5) | (PULLDOWN << 4) | (DRV << 2) | (PMOD << 1) | \ + DIR) \ + << pin_offset) + +#define PAD_CONFIG_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_SOC_CTRL_OFFSET) + +#define PAD_CONFIG_ADDR_UART (PAD_CONFIG_ADDR + 0x020) +#define PAD_CONFIG_ADDR_SPI (PAD_CONFIG_ADDR + 0x02c) +#define PAD_CONFIG_ADDR_I2C (PAD_CONFIG_ADDR + 0x100) +#define PAD_CONFIG_ADDR_MAC (PAD_CONFIG_ADDR + 0x130) + +#define PAD_SMT_DISABLE 0 +#define PAD_SMT_ENABLE 1 + +#define PAD_SLEW_LOW 0 +#define PAD_SLEW_HIGH 1 + +#define PAD_PULLUP_DIS 0 +#define PAD_PULLUP_EN 1 + +#define PAD_PULLDOWN_DIS 0 +#define PAD_PULLDOWN_EN 1 + +#define PAD_DRIVE_2PF 0 +#define PAD_DRIVE_4PF 1 +#define PAD_DRIVE_8PF 2 +#define PAD_DRIVE_16PF 3 + +#define PAD_PMOD_NORMAL 0 +#define PAD_PMOD_TRISTATE 1 + +#define PAD_DIR_OUTPUT 0 +#define PAD_DIR_INPUT 1 + +#endif /* GANYMED_SY1XX_PAD_CTRL_H */ diff --git a/soc/sensry/ganymed/sy1xx/common/soc.c b/soc/sensry/ganymed/sy1xx/common/soc.c new file mode 100644 index 00000000000..5f1ccb9ee86 --- /dev/null +++ b/soc/sensry/ganymed/sy1xx/common/soc.c @@ -0,0 +1,91 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2024 sensry.io + */ + +#include +#include + +#include + +#define LOG_LEVEL CONFIG_SOC_LOG_LEVEL +#include +LOG_MODULE_REGISTER(soc); + +#include "soc.h" + +/* ITC */ +#define ARCHI_ITC_MASK_OFFSET 0x0 +#define ARCHI_ITC_MASK_SET_OFFSET 0x4 +#define ARCHI_ITC_MASK_CLR_OFFSET 0x8 +#define ARCHI_ITC_STATUS_OFFSET 0xc +#define ARCHI_ITC_STATUS_SET_OFFSET 0x10 +#define ARCHI_ITC_STATUS_CLR_OFFSET 0x14 +#define ARCHI_ITC_ACK_OFFSET 0x18 +#define ARCHI_ITC_ACK_SET_OFFSET 0x1c +#define ARCHI_ITC_ACK_CLR_OFFSET 0x20 +#define ARCHI_ITC_FIFO_OFFSET 0x24 + +void sys_arch_reboot(int type) +{ + ARG_UNUSED(type); +} + +#define ARCHI_REF_CLOCK (32768) +#define ARCHI_PER_CLOCK (125000000) + +uint32_t soc_get_rts_clock_frequency(void) +{ + return ARCHI_REF_CLOCK; +} + +uint32_t soc_get_peripheral_clock(void) +{ + return ARCHI_PER_CLOCK; +} + +void riscv_clic_irq_priority_set(uint32_t irq, uint32_t prio, uint32_t flags) +{ + /* we do not support priorities */ +} + +void soc_enable_irq(uint32_t idx) +{ + uint32_t current = sys_read32(ARCHI_FC_ITC_ADDR + ARCHI_ITC_MASK_SET_OFFSET); + + sys_write32(current | (1 << (idx & 0x1f)), ARCHI_FC_ITC_ADDR + ARCHI_ITC_MASK_SET_OFFSET); +} + +void soc_disable_irq(uint32_t idx) +{ + uint32_t current = sys_read32(ARCHI_FC_ITC_ADDR + ARCHI_ITC_MASK_CLR_OFFSET); + + sys_write32(current & (~(1 << (idx & 0x1f))), + ARCHI_FC_ITC_ADDR + ARCHI_ITC_MASK_CLR_OFFSET); +} + +/* + * SoC-level interrupt initialization. Clear any pending interrupts or + * events, and find the INTMUX device if necessary. + * + * This gets called as almost the first thing z_cstart() does, so it + * will happen before any calls to the _arch_irq_xxx() routines above. + */ +void soc_interrupt_init(void) +{ +} + +/** + * @brief Perform basic hardware initialization + * + * Initializes the base clocks and LPFLL using helpers provided by the HAL. + * + * @return 0 + */ +static int soc_sy1xx_init(void) +{ + + return 0; +} + +SYS_INIT(soc_sy1xx_init, PRE_KERNEL_1, 0); diff --git a/soc/sensry/ganymed/sy1xx/common/soc.h b/soc/sensry/ganymed/sy1xx/common/soc.h new file mode 100644 index 00000000000..fc47a3125f8 --- /dev/null +++ b/soc/sensry/ganymed/sy1xx/common/soc.h @@ -0,0 +1,48 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2024 sensry.io + */ + +#ifndef GANYMED_SY1XX_SOC_H +#define GANYMED_SY1XX_SOC_H + +#ifndef _ASMLANGUAGE + +#include + +/* SOC PERIPHERALS */ + +#define ARCHI_SOC_PERIPHERALS_ADDR 0x1A100000 + +#define ARCHI_GPIO_OFFSET 0x00001000 +#define ARCHI_UDMA_OFFSET 0x00002000 +#define ARCHI_APB_SOC_CTRL_OFFSET 0x00004000 +#define ARCHI_SOC_EU_OFFSET 0x00006000 +#define ARCHI_FC_ITC_OFFSET 0x00009800 +#define ARCHI_FC_TIMER_OFFSET 0x0000B000 +#define ARCHI_STDOUT_OFFSET 0x0000F000 + +#define ARCHI_GPIO_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_GPIO_OFFSET) +#define ARCHI_UDMA_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_UDMA_OFFSET) +#define ARCHI_APB_SOC_CTRL_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_APB_SOC_CTRL_OFFSET) +#define ARCHI_SOC_EU_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_SOC_EU_OFFSET) +#define ARCHI_FC_ITC_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_ITC_OFFSET) +#define ARCHI_FC_TIMER_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_TIMER_OFFSET) +#define ARCHI_STDOUT_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_STDOUT_OFFSET) + +#define ARCHI_PLL_ADDR (ARCHI_SOC_PERIPHERALS_ADDR) +#define ARCHI_SECURE_MRAM_CTRL_ADDR 0x1D180000 +#define ARCHI_GLOBAL_MRAM_CTRL_ADDR 0x1E080000 +#define ARCHI_MRAM_EFUSE_ADDR 0x1D070100 +#define ARCHI_TSN_ADDR 0x1A120000 +#define ARCHI_CAN_ADDR 0x1A130000 + +uint32_t soc_get_rts_clock_frequency(void); +uint32_t soc_get_peripheral_clock(void); + +void soc_enable_irq(uint32_t idx); +void soc_disable_irq(uint32_t idx); + +#endif /* _ASMLANGUAGE */ + +#endif /* GANYMED_SY1XX_SOC_H */ diff --git a/soc/sensry/ganymed/sy1xx/common/udma.c b/soc/sensry/ganymed/sy1xx/common/udma.c new file mode 100644 index 00000000000..752c84b91ce --- /dev/null +++ b/soc/sensry/ganymed/sy1xx/common/udma.c @@ -0,0 +1,180 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2024 sensry.io + */ + +#include "soc.h" +#include "udma.h" + +#define UDMA_CTRL_PER_CG (ARCHI_UDMA_ADDR + UDMA_CONF_OFFSET) + +#define DRIVERS_MAX_UART_COUNT 3 +#define DRIVERS_MAX_I2C_COUNT 4 +#define DRIVERS_MAX_SPI_COUNT 7 +#define DEVICE_MAX_ETH_COUNT 1 + +void drivers_udma_enable_clock(udma_module_t module, uint32_t instance) +{ + + uint32_t udma_ctrl_per_cg = sys_read32(UDMA_CTRL_PER_CG); + + switch (module) { + + case DRIVERS_UDMA_UART: + if (instance >= DRIVERS_MAX_UART_COUNT) { + return; + } + udma_ctrl_per_cg |= 1 << (instance + 0); + break; + + case DRIVERS_UDMA_I2C: + if (instance >= DRIVERS_MAX_I2C_COUNT) { + return; + } + udma_ctrl_per_cg |= 1 << (instance + 10); + break; + + case DRIVERS_UDMA_SPI: + if (instance >= DRIVERS_MAX_SPI_COUNT) { + return; + } + udma_ctrl_per_cg |= 1 << (instance + 3); + break; + + case DRIVERS_UDMA_MAC: + if (instance >= DEVICE_MAX_ETH_COUNT) { + return; + } + udma_ctrl_per_cg |= 1 << (instance + 20); + break; + + case DRIVERS_MAX_UDMA_COUNT: + break; + } + + sys_write32(udma_ctrl_per_cg, UDMA_CTRL_PER_CG); +} + +void drivers_udma_disable_clock(udma_module_t module, uint32_t instance) +{ + + uint32_t udma_ctrl_per_cg = sys_read32(UDMA_CTRL_PER_CG); + + switch (module) { + + case DRIVERS_UDMA_UART: + if (instance >= DRIVERS_MAX_UART_COUNT) { + return; + } + udma_ctrl_per_cg &= ~(1 << (instance + 0)); + break; + + case DRIVERS_UDMA_I2C: + if (instance >= DRIVERS_MAX_I2C_COUNT) { + return; + } + udma_ctrl_per_cg &= ~(1 << (instance + 10)); + break; + + case DRIVERS_UDMA_SPI: + if (instance >= DRIVERS_MAX_SPI_COUNT) { + return; + } + udma_ctrl_per_cg &= ~(1 << (instance + 3)); + break; + + case DRIVERS_UDMA_MAC: + if (instance >= DEVICE_MAX_ETH_COUNT) { + return; + } + udma_ctrl_per_cg &= ~(1 << (instance + 20)); + break; + + case DRIVERS_MAX_UDMA_COUNT: + break; + } + + sys_write32(udma_ctrl_per_cg, UDMA_CTRL_PER_CG); +} + +void drivers_udma_busy_delay(uint32_t msec) +{ + uint32_t sec = 250000000; + uint32_t millis = (sec / 1000) * msec; + + for (uint32_t i = 0; i < millis; i++) { + __asm__("nop"); + } +} + +int32_t drivers_udma_cancel(uint32_t base, uint32_t channel) +{ + uint32_t channel_offset = channel == 0 ? 0x00 : 0x10; + + /* clear existing */ + UDMA_WRITE_REG(base, UDMA_CFG_REG + channel_offset, UDMA_CHANNEL_CFG_CLEAR); + return 0; +} + +int32_t drivers_udma_is_ready(uint32_t base, uint32_t channel) +{ + uint32_t channel_offset = channel == 0 ? 0x00 : 0x10; + + int32_t isBusy = UDMA_READ_REG(base, UDMA_CFG_REG + channel_offset) & (UDMA_CHANNEL_CFG_EN); + + return isBusy ? 0 : 1; +} + +int32_t drivers_udma_wait_for_finished(uint32_t base, uint32_t channel) +{ + uint32_t channel_offset = channel == 0 ? 0x00 : 0x10; + + volatile uint32_t timeout = 200; + + while (UDMA_READ_REG(base, UDMA_CFG_REG + channel_offset) & (UDMA_CHANNEL_CFG_EN)) { + drivers_udma_busy_delay(1); + timeout--; + if (timeout == 0) { + return -1; + } + } + + return 0; +} + +int32_t drivers_udma_wait_for_status(uint32_t base) +{ + + volatile uint32_t timeout = 200; + + while (UDMA_READ_REG(base, UDMA_STATUS) & (0x3)) { + drivers_udma_busy_delay(1); + timeout--; + if (timeout == 0) { + return -1; + } + } + + return 0; +} + +int32_t drivers_udma_start(uint32_t base, uint32_t channel, uint32_t saddr, uint32_t size, + uint32_t optional_cfg) +{ + uint32_t channel_offset = channel == 0 ? 0x00 : 0x10; + + UDMA_WRITE_REG(base, UDMA_SADDR_REG + channel_offset, saddr); + UDMA_WRITE_REG(base, UDMA_SIZE_REG + channel_offset, size); + UDMA_WRITE_REG(base, UDMA_CFG_REG + channel_offset, UDMA_CHANNEL_CFG_EN | optional_cfg); + + return 0; +} + +int32_t drivers_udma_get_remaining(uint32_t base, uint32_t channel) +{ + uint32_t channel_offset = channel == 0 ? 0x00 : 0x10; + + int32_t size = UDMA_READ_REG(base, UDMA_SIZE_REG + channel_offset); + + return size; +} diff --git a/soc/sensry/ganymed/sy1xx/common/udma.h b/soc/sensry/ganymed/sy1xx/common/udma.h new file mode 100644 index 00000000000..cbb36b172cc --- /dev/null +++ b/soc/sensry/ganymed/sy1xx/common/udma.h @@ -0,0 +1,151 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2024 sensry.io + */ + +#ifndef GANYMED_SY1XX_UDMA_H +#define GANYMED_SY1XX_UDMA_H + +#include +#include +#include + +/* UDMA */ +#define ARCHI_UDMA_ADDR (ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_UDMA_OFFSET) + +#define UDMA_PERIPH_AREA_SIZE_LOG2 7 +#define UDMA_PERIPH_OFFSET(id) (((id) << UDMA_PERIPH_AREA_SIZE_LOG2)) + +#define ARCHI_UDMA_UART_ID(id) (0 + (id)) +#define ARCHI_UDMA_SPIM_ID(id) (3 + (id)) +#define ARCHI_UDMA_I2C_ID(id) (10 + (id)) +#define ARCHI_UDMA_I2S_ID(id) (14 + (id)) +#define ARCHI_UDMA_HYPER_ID(id) (19 + (id)) +#define ARCHI_UDMA_TSN_ID(id) (20 + (id)) + +#define UDMA_CHANNEL_RX_OFFSET 0x00 +#define UDMA_CHANNEL_TX_OFFSET 0x10 +#define UDMA_CHANNEL_CUSTOM_OFFSET 0x20 + +/* + * For each channel, the RX and TX part have the following registers + * The offsets are given relative to the offset of the RX or TX part + */ + +/* Start address register */ +#define UDMA_CHANNEL_SADDR_OFFSET 0x0 +/* Size register */ +#define UDMA_CHANNEL_SIZE_OFFSET 0x4 +/* Configuration register */ +#define UDMA_CHANNEL_CFG_OFFSET 0x8 +/* Int configuration register */ +#define UDMA_CHANNEL_INTCFG_OFFSET 0xC + +/* + * The configuration register of the RX and TX parts for each channel can be accessed using the + * following bits + */ + +#define UDMA_CHANNEL_CFG_SHADOW_BIT (5) +#define UDMA_CHANNEL_CFG_CLEAR_BIT (5) +#define UDMA_CHANNEL_CFG_EN_BIT (4) +#define UDMA_CHANNEL_CFG_SIZE_BIT (1) +#define UDMA_CHANNEL_CFG_CONT_BIT (0) + +/* Indicates if a shadow transfer is there */ +#define UDMA_CHANNEL_CFG_SHADOW (1 << UDMA_CHANNEL_CFG_SHADOW_BIT) +/* Stop and clear all pending transfers */ +#define UDMA_CHANNEL_CFG_CLEAR (1 << UDMA_CHANNEL_CFG_CLEAR_BIT) +/* Start a transfer */ +#define UDMA_CHANNEL_CFG_EN (1 << UDMA_CHANNEL_CFG_EN_BIT) +/* Configure for 8-bits transfer */ +#define UDMA_CHANNEL_CFG_SIZE_8 (0 << UDMA_CHANNEL_CFG_SIZE_BIT) +/* Configure for 16-bits transfer */ +#define UDMA_CHANNEL_CFG_SIZE_16 (1 << UDMA_CHANNEL_CFG_SIZE_BIT) +/* Configure for 32-bits transfer */ +#define UDMA_CHANNEL_CFG_SIZE_32 (2 << UDMA_CHANNEL_CFG_SIZE_BIT) +/* Configure for continuous mode */ +#define UDMA_CHANNEL_CFG_CONT (1 << UDMA_CHANNEL_CFG_CONT_BIT) + +/* Configuration area offset */ +#define UDMA_CONF_OFFSET 0xF80 +/* Clock-gating control register */ +#define UDMA_CONF_CG_OFFSET 0x00 + +static inline void plp_udma_cg_set(unsigned int value) +{ + sys_write32(value, ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_UDMA_OFFSET + UDMA_CONF_OFFSET + + UDMA_CONF_CG_OFFSET); +} + +typedef enum { + DRIVERS_UDMA_UART, + DRIVERS_UDMA_I2C, + DRIVERS_UDMA_SPI, + DRIVERS_UDMA_MAC, + DRIVERS_MAX_UDMA_COUNT +} udma_module_t; + +void drivers_udma_enable_clock(udma_module_t module, uint32_t instance); +void drivers_udma_disable_clock(udma_module_t module, uint32_t instance); + +int32_t drivers_udma_cancel(uint32_t base, uint32_t channel); +int32_t drivers_udma_is_ready(uint32_t base, uint32_t channel); +int32_t drivers_udma_wait_for_finished(uint32_t base, uint32_t channel); +int32_t drivers_udma_wait_for_status(uint32_t base); +int32_t drivers_udma_start(uint32_t base, uint32_t channel, uint32_t saddr, uint32_t size, + uint32_t optional_cfg); +int32_t drivers_udma_get_remaining(uint32_t base, uint32_t channel); + +typedef enum { + UDMA_SADDR_REG = 0x00, + UDMA_SIZE_REG = 0x04, + UDMA_CFG_REG = 0x08, + +} udma_regs_t; + +typedef enum { + UDMA_RX_SADDR_REG = 0x00, + UDMA_RX_SIZE_REG = 0x04, + UDMA_RX_CFG_REG = 0x08, + + UDMA_TX_SADDR_REG = 0x10, + UDMA_TX_SIZE_REG = 0x14, + UDMA_TX_CFG_REG = 0x18, + + UDMA_STATUS = 0x20, + UDMA_SETUP_REG = 0x24, +} udma_reg_t; + +#define UDMA_RX_DATA_ADDR_INC_SIZE_8 (0x0 << 1) +#define UDMA_RX_DATA_ADDR_INC_SIZE_16 (0x1 << 1) +#define UDMA_RX_DATA_ADDR_INC_SIZE_32 (0x2 << 1) + +#define UDMA_RX_CHANNEL 0 +#define UDMA_TX_CHANNEL 1 + +#define UDMA_READ_REG(udma_base, reg) sys_read32(udma_base + reg) +#define UDMA_WRITE_REG(udma_base, reg, value) sys_write32(value, udma_base + reg) + +#define UDMA_CANCEL_RX(udma_base) drivers_udma_cancel(udma_base, UDMA_RX_CHANNEL) +#define UDMA_CANCEL_TX(udma_base) drivers_udma_cancel(udma_base, UDMA_TX_CHANNEL) + +#define UDMA_IS_FINISHED_RX(udma_base) drivers_udma_is_ready(udma_base, UDMA_RX_CHANNEL) +#define UDMA_IS_FINISHED_TX(udma_base) drivers_udma_is_ready(udma_base, UDMA_TX_CHANNEL) + +#define UDMA_WAIT_FOR_FINISHED_RX(udma_base) \ + drivers_udma_wait_for_finished(udma_base, UDMA_RX_CHANNEL) +#define UDMA_WAIT_FOR_FINISHED_TX(udma_base) \ + drivers_udma_wait_for_finished(udma_base, UDMA_TX_CHANNEL) + +#define UDMA_START_RX(base, addr, size, cfg) \ + drivers_udma_start(base, UDMA_RX_CHANNEL, addr, size, cfg) +#define UDMA_START_TX(base, addr, size, cfg) \ + drivers_udma_start(base, UDMA_TX_CHANNEL, addr, size, cfg) + +#define UDMA_GET_REMAINING_RX(base) drivers_udma_get_remaining(base, UDMA_RX_CHANNEL) +#define UDMA_GET_REMAINING_TX(base) drivers_udma_get_remaining(base, UDMA_TX_CHANNEL) + +#define UDMA_WAIT_FOR_STATUS_IDLE(udma_base) drivers_udma_wait_for_status(udma_base) + +#endif /* GANYMED_SY1XX_UDMA_H */ diff --git a/soc/sensry/ganymed/sy1xx/common/vector_table.ld b/soc/sensry/ganymed/sy1xx/common/vector_table.ld new file mode 100644 index 00000000000..374490a95c8 --- /dev/null +++ b/soc/sensry/ganymed/sy1xx/common/vector_table.ld @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2019 Foundries.io Ltd + * Copyright (c) 2019 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +KEEP(*(.reset.*)) +KEEP(*(".exception.entry.*")) /* contains _isr_wrapper */ +*(".exception.other.*") + +KEEP(*(.openocd_debug)) +KEEP(*(".openocd_debug.*")) diff --git a/soc/sensry/soc.yml b/soc/sensry/soc.yml new file mode 100644 index 00000000000..eaabb716db8 --- /dev/null +++ b/soc/sensry/soc.yml @@ -0,0 +1,10 @@ +# Copyright (c) 2024 sensry.io +# SPDX-License-Identifier: Apache-2.0 + +family: + - name: ganymed + series: + - name: sy1xx + socs: + - name: sy120_gbm + - name: sy120_gen1