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