soc: sensry: Add support for SY120-GBM and SY120-GEN1

Add soc support for Sensry's RISCV32 based SY1xx.
Variants of the soc are GBM and GEN1.

Signed-off-by: Sven Ginka <s.ginka@sensry.de>
This commit is contained in:
Sven Ginka 2024-09-05 21:03:14 +02:00 committed by Carles Cufí
commit 402f3d24c4
22 changed files with 1124 additions and 0 deletions

View file

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

View file

@ -588,6 +588,7 @@ seirobotics Shenzhen SEI Robotics Co., Ltd
semtech Semtech Corporation semtech Semtech Corporation
sensirion Sensirion AG sensirion Sensirion AG
sensortek Sensortek Technology Corporation sensortek Sensortek Technology Corporation
sensry sensry.io
sff Small Form Factor Committee sff Small Form Factor Committee
sgd Solomon Goldentek Display Corporation sgd Solomon Goldentek Display Corporation
sgmicro SG Micro Corp sgmicro SG Micro Corp

View file

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

8
soc/sensry/Kconfig Normal file
View file

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

View file

@ -0,0 +1,8 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2024 sensry.io
if SOC_FAMILY_GANYMED
rsource "*/Kconfig.defconfig"
endif

10
soc/sensry/Kconfig.soc Normal file
View file

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

View file

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

View file

@ -0,0 +1,8 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2024 sensry.io
if SOC_SERIES_SY1XX
rsource "*/Kconfig.defconfig"
endif

View file

@ -0,0 +1,4 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2024 sensry.io
rsource "*/Kconfig.soc"

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,144 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2024 sensry.io
#include <zephyr/toolchain.h>
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

View file

@ -0,0 +1,255 @@
/*
* Copyright (c) 2013-2014 Wind River Systems, Inc.
* Copyright (c) 2016-2017 Jean-Paul Etienne <fractalclone@gmail.com>
* 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 <zephyr/devicetree.h>
#include <zephyr/linker/sections.h>
#include <zephyr/linker/linker-defs.h>
#include <zephyr/linker/linker-tool.h>
#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 <zephyr/linker/rel-sections.ld>
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 <snippets-rom-start.ld>
__text_region_start = .;
*(.text .text.*)
*(.gnu.linkonce.t.*)
*(.eh_frame)
} GROUP_LINK_IN(ROM)
__text_region_end = .;
__rodata_region_start = .;
#include <zephyr/linker/common-rom.ld>
#include <zephyr/linker/thread-local-storage.ld>
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 <snippets-rodata.ld>
} GROUP_LINK_IN(ROMABLE_REGION)
#include <zephyr/linker/cplusplus-rom.ld>
__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 <snippets-rwdata.ld>
__data_end = .;
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
__data_size = __data_end - __data_start;
__data_load_start = LOADADDR(_DATA_SECTION_NAME);
#include <zephyr/linker/common-ram.ld>
#include <zephyr/linker/cplusplus-ram.ld>
/* Located in generated directory. This file is populated by the
* zephyr_linker_sources() Cmake function.
*/
#include <snippets-data-sections.ld>
__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 <snippets-noinit.ld>
} GROUP_LINK_IN(RAMABLE_REGION)
/* Located in generated directory. This file is populated by the
* zephyr_linker_sources() Cmake function.
*/
#include <snippets-ram-sections.ld>
/* Located in generated directory. This file is populated by the
* zephyr_linker_sources() Cmake function.
*/
#include <snippets-sections.ld>
#include <zephyr/linker/ram-end.ld>
GROUP_END(RAMABLE_REGION)
#ifdef CONFIG_GEN_ISR_TABLES
/* Bogus section, post-processed during the build to initialize interrupts. */
#include <zephyr/linker/intlist.ld>
#endif
#include <zephyr/linker/debug-sections.ld>
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.*)
}
}

View file

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

View file

@ -0,0 +1,91 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright (c) 2024 sensry.io
*/
#include <zephyr/device.h>
#include <zephyr/init.h>
#include <zephyr/sys/util.h>
#define LOG_LEVEL CONFIG_SOC_LOG_LEVEL
#include <zephyr/logging/log.h>
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);

View file

@ -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 <zephyr/types.h>
/* 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 */

View file

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

View file

@ -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 <stdint.h>
#include <zephyr/arch/common/sys_io.h>
#include <soc.h>
/* 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 */

View file

@ -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.*"))

10
soc/sensry/soc.yml Normal file
View file

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