riscv32: rename to riscv
With the upcoming riscv64 support, it is best to use "riscv" as the subdirectory name and common symbols as riscv32 and riscv64 support code is almost identical. Then later decide whether 32-bit or 64-bit compilation is wanted. Redirects for the web documentation are also included. Then zephyrbot complained about this: " New files added that are not covered in CODEOWNERS: dts/riscv/microsemi-miv.dtsi dts/riscv/riscv32-fe310.dtsi Please add one or more entries in the CODEOWNERS file to cover those files " So I assigned them to those who created them. Feel free to readjust as necessary. Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
This commit is contained in:
parent
48b4ad4b33
commit
1f4b5ddd0f
159 changed files with 125 additions and 118 deletions
20
soc/riscv/openisa_rv32m1/CMakeLists.txt
Normal file
20
soc/riscv/openisa_rv32m1/CMakeLists.txt
Normal file
|
@ -0,0 +1,20 @@
|
|||
# Copyright (c) 2018 Foundries.io Ltd
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
if(CONFIG_SOC_OPENISA_RV32M1_RI5CY)
|
||||
if (CONFIG_RISCV_GENERIC_TOOLCHAIN)
|
||||
zephyr_compile_options(-march=rv32imc)
|
||||
else()
|
||||
zephyr_compile_options(-march=rv32imcxpulpv2)
|
||||
endif()
|
||||
elseif(CONFIG_SOC_OPENISA_RV32M1_ZERO_RISCY)
|
||||
zephyr_compile_options(-march=rv32imc)
|
||||
endif()
|
||||
|
||||
zephyr_sources(
|
||||
vector.S
|
||||
soc_irq.S
|
||||
wdog.S
|
||||
soc.c
|
||||
)
|
29
soc/riscv/openisa_rv32m1/Kconfig
Normal file
29
soc/riscv/openisa_rv32m1/Kconfig
Normal file
|
@ -0,0 +1,29 @@
|
|||
# Copyright (c) 2018 Foundries.io Ltd
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# The OpenISA RV32M1 SoC directory in riscv supports the RISC-V
|
||||
# cores on OpenISA RV32M1 SoCs.
|
||||
#
|
||||
# The Zephyr "soc" abstraction isn't a great fit here. These SoCs (in
|
||||
# the strict physical sense of "systems on chip") also contain Arm
|
||||
# cores, so this type of "soc" doesn't really belong to a single "arch".
|
||||
#
|
||||
# However, due to constraints imposed by Zephyr's file hierarchy
|
||||
# conventions, those "other" cores would need to be supported under a
|
||||
# different soc subdirectory, e.g. soc/arm instead of soc/riscv.
|
||||
|
||||
if SOC_OPENISA_RV32M1_RISCV32
|
||||
|
||||
choice
|
||||
prompt "OpenISA RV32M1 RISC-V Core Selection"
|
||||
|
||||
config SOC_OPENISA_RV32M1_RI5CY
|
||||
bool "OpenISA RV32M1 RI5CY core"
|
||||
|
||||
config SOC_OPENISA_RV32M1_ZERO_RISCY
|
||||
bool "OpenISA RV32M1 ZERO-RISCY core"
|
||||
|
||||
endchoice
|
||||
|
||||
endif # SOC_OPENISA_RV32M1_RISCV32
|
186
soc/riscv/openisa_rv32m1/Kconfig.defconfig
Normal file
186
soc/riscv/openisa_rv32m1/Kconfig.defconfig
Normal file
|
@ -0,0 +1,186 @@
|
|||
# Kconfig.defconfig: RV32M1 SoC RISC-V core default configuration values
|
||||
#
|
||||
# Copyright (c) 2018 Foundries.io Ltd
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
if SOC_OPENISA_RV32M1_RISCV32
|
||||
|
||||
config SOC
|
||||
string
|
||||
default "openisa_rv32m1"
|
||||
|
||||
# 32 from event unit + 32 * (1 + max enabled INTMUX channel)
|
||||
config NUM_IRQS
|
||||
int
|
||||
default 288 if RV32M1_INTMUX_CHANNEL_7
|
||||
default 256 if RV32M1_INTMUX_CHANNEL_6
|
||||
default 224 if RV32M1_INTMUX_CHANNEL_5
|
||||
default 192 if RV32M1_INTMUX_CHANNEL_4
|
||||
default 160 if RV32M1_INTMUX_CHANNEL_3
|
||||
default 128 if RV32M1_INTMUX_CHANNEL_2
|
||||
default 96 if RV32M1_INTMUX_CHANNEL_1
|
||||
default 64 if RV32M1_INTMUX_CHANNEL_0
|
||||
default 32
|
||||
|
||||
config XIP
|
||||
bool
|
||||
default y
|
||||
|
||||
config RISCV_GENERIC_TOOLCHAIN
|
||||
bool
|
||||
default y if "$(ZEPHYR_TOOLCHAIN_VARIANT)" = "zephyr"
|
||||
default n
|
||||
|
||||
config RISCV_SOC_CONTEXT_SAVE
|
||||
bool
|
||||
default y if SOC_OPENISA_RV32M1_RI5CY
|
||||
|
||||
config RISCV_SOC_OFFSETS
|
||||
bool
|
||||
default y
|
||||
|
||||
config RISCV_SOC_INTERRUPT_INIT
|
||||
bool
|
||||
default y
|
||||
|
||||
# We need to disable the watchdog out of reset, as it's enabled by
|
||||
# default. Use the WDOG_INIT hook for doing that.
|
||||
config WDOG_INIT
|
||||
def_bool y
|
||||
|
||||
# The event unit looks for vector tables at the end of each core's
|
||||
# flash space. These vector tables are not relocatable.
|
||||
config RISCV_RV32M1_VECTOR_BASE_ADDR
|
||||
hex
|
||||
default 0x000FFF00 if SOC_OPENISA_RV32M1_RI5CY
|
||||
default 0x0103FF00 if SOC_OPENISA_RV32M1_ZERO_RISCY
|
||||
|
||||
config RISCV_RV32M1_VECTOR_SIZE
|
||||
hex
|
||||
default 0x100
|
||||
|
||||
config SYS_CLOCK_HW_CYCLES_PER_SEC
|
||||
int
|
||||
default 8000000
|
||||
|
||||
if MULTI_LEVEL_INTERRUPTS
|
||||
|
||||
config MAX_IRQ_PER_AGGREGATOR
|
||||
int
|
||||
default 32
|
||||
|
||||
config 2ND_LEVEL_INTERRUPTS
|
||||
default y
|
||||
|
||||
config 2ND_LVL_ISR_TBL_OFFSET
|
||||
int
|
||||
default 32
|
||||
|
||||
config NUM_2ND_LEVEL_AGGREGATORS
|
||||
int
|
||||
default 8 if RV32M1_INTMUX_CHANNEL_7
|
||||
default 7 if RV32M1_INTMUX_CHANNEL_6
|
||||
default 6 if RV32M1_INTMUX_CHANNEL_5
|
||||
default 5 if RV32M1_INTMUX_CHANNEL_4
|
||||
default 4 if RV32M1_INTMUX_CHANNEL_3
|
||||
default 3 if RV32M1_INTMUX_CHANNEL_2
|
||||
default 2 if RV32M1_INTMUX_CHANNEL_1
|
||||
default 1 # just channel 0
|
||||
|
||||
config 2ND_LVL_INTR_00_OFFSET
|
||||
int
|
||||
default 24
|
||||
|
||||
config 2ND_LVL_INTR_01_OFFSET
|
||||
int
|
||||
default 25
|
||||
|
||||
config 2ND_LVL_INTR_02_OFFSET
|
||||
int
|
||||
default 26
|
||||
|
||||
config 2ND_LVL_INTR_03_OFFSET
|
||||
int
|
||||
default 27
|
||||
|
||||
config 2ND_LVL_INTR_04_OFFSET
|
||||
int
|
||||
default 28
|
||||
|
||||
config 2ND_LVL_INTR_05_OFFSET
|
||||
int
|
||||
default 29
|
||||
|
||||
config 2ND_LVL_INTR_06_OFFSET
|
||||
int
|
||||
default 30
|
||||
|
||||
config 2ND_LVL_INTR_07_OFFSET
|
||||
int
|
||||
default 31
|
||||
|
||||
config RV32M1_INTMUX
|
||||
default y
|
||||
|
||||
config RV32M1_INTMUX_CHANNEL_0
|
||||
default y
|
||||
|
||||
config RV32M1_INTMUX_CHANNEL_1
|
||||
default y
|
||||
|
||||
config RV32M1_INTMUX_CHANNEL_2
|
||||
default y
|
||||
|
||||
config RV32M1_INTMUX_CHANNEL_3
|
||||
default y
|
||||
|
||||
config RV32M1_INTMUX_CHANNEL_4
|
||||
default y
|
||||
|
||||
config RV32M1_INTMUX_CHANNEL_5
|
||||
default y
|
||||
|
||||
config RV32M1_INTMUX_CHANNEL_6
|
||||
default y
|
||||
|
||||
config RV32M1_INTMUX_CHANNEL_7
|
||||
default y
|
||||
|
||||
endif # MULTI_LEVEL_INTERRUPTS
|
||||
|
||||
config PINMUX_RV32M1
|
||||
default y
|
||||
|
||||
if GPIO
|
||||
|
||||
config GPIO_RV32M1
|
||||
default y
|
||||
|
||||
endif # GPIO
|
||||
|
||||
if SERIAL
|
||||
|
||||
config UART_RV32M1_LPUART
|
||||
def_bool y
|
||||
|
||||
endif # SERIAL
|
||||
|
||||
if I2C
|
||||
|
||||
config I2C_RV32M1_LPI2C
|
||||
def_bool y
|
||||
|
||||
endif # I2C
|
||||
|
||||
if FLASH
|
||||
|
||||
config SOC_FLASH_RV32M1
|
||||
default y
|
||||
|
||||
config FLASH_BASE_ADDRESS
|
||||
default $(dt_hex_val,DT_FLASH_BASE_ADDRESS)
|
||||
|
||||
endif # FLASH
|
||||
|
||||
endif # SOC_OPENISA_RV32M1_RISCV32
|
22
soc/riscv/openisa_rv32m1/Kconfig.soc
Normal file
22
soc/riscv/openisa_rv32m1/Kconfig.soc
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Copyright (c) 2018 Foundries.io Ltd
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config SOC_OPENISA_RV32M1_RISCV32
|
||||
bool "OpenISA RV32M1 RISC-V cores"
|
||||
depends on RISCV
|
||||
# The following select is due to limitations in the linker script.
|
||||
# (We can't make it a 'depends on' without causing a dependency loop).
|
||||
select XIP
|
||||
select HAS_RV32M1_LPUART
|
||||
select HAS_RV32M1_LPI2C
|
||||
select ATOMIC_OPERATIONS_C
|
||||
select VEGA_SDK_HAL
|
||||
select RISCV_SOC_INTERRUPT_INIT
|
||||
select CLOCK_CONTROL
|
||||
select HAS_RV32M1_FTFX
|
||||
select HAS_FLASH_LOAD_OFFSET
|
||||
help
|
||||
Enable support for OpenISA RV32M1 RISC-V processors. Choose
|
||||
this option to target the RI5CY or ZERO-RISCY core. This
|
||||
option should not be used to target either Arm core.
|
17
soc/riscv/openisa_rv32m1/dts_fixup.h
Normal file
17
soc/riscv/openisa_rv32m1/dts_fixup.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c) 2019 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* SoC level DTS fixup file */
|
||||
|
||||
#if defined(CONFIG_SOC_OPENISA_RV32M1_RISCV32)
|
||||
|
||||
#define DT_FLASH_DEV_BASE_ADDRESS DT_OPENISA_RV32M1_FTFE_40023000_BASE_ADDRESS
|
||||
#define DT_FLASH_DEV_NAME DT_OPENISA_RV32M1_FTFE_40023000_LABEL
|
||||
#define DT_START_UP_ENTRY_OFFSET 0x80
|
||||
|
||||
#endif /* CONFIG_SOC_OPENISA_RV32M1_RISCV32 */
|
||||
|
||||
/* End of SoC Level DTS fixup file */
|
282
soc/riscv/openisa_rv32m1/linker.ld
Normal file
282
soc/riscv/openisa_rv32m1/linker.ld
Normal file
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2014 Wind River Systems, Inc.
|
||||
* Copyright (c) 2016-2017 Jean-Paul Etienne <fractalclone@gmail.com>
|
||||
* Copyright (c) 2018 Foundries.io Ltd
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define _LINKER
|
||||
#define _ASMLANGUAGE
|
||||
|
||||
#include <generated_dts_board.h>
|
||||
#include <autoconf.h>
|
||||
|
||||
#include <linker/sections.h>
|
||||
#include <linker/linker-defs.h>
|
||||
#include <linker/linker-tool.h>
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
#define VECTOR_SIZE CONFIG_RISCV_RV32M1_VECTOR_SIZE
|
||||
|
||||
#ifdef CONFIG_USE_CODE_PARTITION
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_MCUBOOT
|
||||
|
||||
|
||||
#define ROM_BASE (DT_CODE_PARTITION_OFFSET)
|
||||
#define ROM_SIZE (DT_CODE_PARTITION_SIZE)
|
||||
|
||||
#define VECTOR_BASE (ROM_BASE + CONFIG_TEXT_SECTION_OFFSET)
|
||||
|
||||
#else
|
||||
|
||||
#define ROM_BASE DT_CODE_PARTITION_OFFSET
|
||||
#define ROM_SIZE (DT_CODE_PARTITION_SIZE - VECTOR_SIZE)
|
||||
|
||||
#define VECTOR_BASE (ROM_BASE + ROM_SIZE)
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define ROM_BASE DT_FLASH_BASE_ADDRESS
|
||||
#define ROM_SIZE (KB(DT_FLASH_SIZE) - VECTOR_SIZE)
|
||||
|
||||
#define VECTOR_BASE (ROM_BASE + ROM_SIZE)
|
||||
|
||||
#endif
|
||||
|
||||
#define RAM_BASE DT_SRAM_BASE_ADDRESS
|
||||
#define RAM_SIZE KB(DT_SRAM_SIZE)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
ROM (rx) : ORIGIN = ROM_BASE, LENGTH = ROM_SIZE
|
||||
/*
|
||||
* Each RISC-V core on this chip (RI5CY and ZERO-RISCY) has
|
||||
* a vector table at the end of its flash bank. They are relocatable
|
||||
* at runtime, but we need to put the reset vectors in hardcoded places.
|
||||
*
|
||||
* (The Arm core vector tables are at the beginning of each
|
||||
* flash bank.)
|
||||
*/
|
||||
#ifndef CONFIG_BOOTLOADER_MCUBOOT
|
||||
VECTORS (rx) : ORIGIN = VECTOR_BASE, LENGTH = VECTOR_SIZE
|
||||
#endif
|
||||
RAM (rwx) : ORIGIN = RAM_BASE, LENGTH = RAM_SIZE
|
||||
/*
|
||||
* Special section, not included in the final binary, used
|
||||
* to generate interrupt tables. See include/linker/intlist.ld.
|
||||
*/
|
||||
IDT_LIST (wx) : ORIGIN = 0xFFFFF7FF, LENGTH = 2K
|
||||
}
|
||||
|
||||
ENTRY(CONFIG_KERNEL_ENTRY)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
#include <linker/rel-sections.ld>
|
||||
|
||||
SECTION_PROLOGUE(.plt,,)
|
||||
{
|
||||
*(.plt)
|
||||
}
|
||||
|
||||
SECTION_PROLOGUE(.iplt,,)
|
||||
{
|
||||
*(.iplt)
|
||||
}
|
||||
|
||||
GROUP_START(ROM)
|
||||
_image_rom_start = ROM_BASE;
|
||||
|
||||
SECTION_PROLOGUE(_TEXT_SECTION_NAME,,)
|
||||
{
|
||||
. = CONFIG_TEXT_SECTION_OFFSET;
|
||||
. = ALIGN(4);
|
||||
|
||||
/*
|
||||
* Respect for CONFIG_TEXT_SECTION_OFFSET is mandatory
|
||||
* for MCUboot support, so .reset.* and .exception.*
|
||||
* must come after that offset from ROM_BASE.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_MCUBOOT
|
||||
/*
|
||||
* For CONFIG_BOOTLOADER_MCUBOOT, the vector table is located at the
|
||||
* end of the image header of the MCUboot. After the tagert image is
|
||||
* boot, the register Machine Trap-Vector Base Address (MTVEC) is
|
||||
* set with the value of _vector_start in the reset handler.
|
||||
*/
|
||||
_vector_start = .;
|
||||
KEEP(*(.vectors.*))
|
||||
_vector_end = .;
|
||||
. = ALIGN(4);
|
||||
#endif
|
||||
|
||||
KEEP(*(.reset.*))
|
||||
KEEP(*(".exception.entry.*")) /* contains __irq_wrapper */
|
||||
*(".exception.other.*")
|
||||
|
||||
KEEP(*(.openocd_debug))
|
||||
KEEP(*(".openocd_debug.*"))
|
||||
|
||||
_image_text_start = .;
|
||||
*(.text .text.*)
|
||||
*(.gnu.linkonce.t.*)
|
||||
*(.eh_frame)
|
||||
} GROUP_LINK_IN(ROM)
|
||||
|
||||
_image_text_end = .;
|
||||
|
||||
_image_rodata_start = .;
|
||||
|
||||
#include <linker/common-rom.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)
|
||||
|
||||
_image_rodata_end = .;
|
||||
_image_rom_end = .;
|
||||
|
||||
#ifndef CONFIG_BOOTLOADER_MCUBOOT
|
||||
/* The vector table goes into core-dependent flash locations. */
|
||||
SECTION_PROLOGUE(vectors,,)
|
||||
{
|
||||
_vector_start = .;
|
||||
KEEP(*(.vectors.*))
|
||||
} GROUP_LINK_IN(VECTORS)
|
||||
_vector_end = .;
|
||||
#endif
|
||||
|
||||
GROUP_END(ROM)
|
||||
|
||||
GROUP_START(RAM)
|
||||
|
||||
SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_image_ram_start = .;
|
||||
__data_ram_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>
|
||||
|
||||
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
|
||||
|
||||
#include <linker/common-ram.ld>
|
||||
|
||||
__data_ram_end = .;
|
||||
__data_rom_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>
|
||||
|
||||
_image_ram_end = .;
|
||||
_end = .; /* end of image */
|
||||
|
||||
GROUP_END(RAM)
|
||||
|
||||
#ifdef CONFIG_CUSTOM_SECTIONS_LD
|
||||
/* Located in project source directory */
|
||||
#include <custom-sections.ld>
|
||||
#endif
|
||||
/* Located in generated directory. This file is populated by the
|
||||
* zephyr_linker_sources() Cmake function.
|
||||
*/
|
||||
#include <snippets-sections.ld>
|
||||
|
||||
#ifdef CONFIG_GEN_ISR_TABLES
|
||||
/* Bogus section, post-processed during the build to initialize interrupts. */
|
||||
#include <linker/intlist.ld>
|
||||
#endif
|
||||
|
||||
#include <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.*)
|
||||
}
|
||||
|
||||
}
|
222
soc/riscv/openisa_rv32m1/soc.c
Normal file
222
soc/riscv/openisa_rv32m1/soc.c
Normal file
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Foundries.io
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
|
||||
#include <device.h>
|
||||
#include <init.h>
|
||||
#include <fsl_clock.h>
|
||||
#include <sys/util.h>
|
||||
|
||||
#if defined(CONFIG_MULTI_LEVEL_INTERRUPTS)
|
||||
#include <errno.h>
|
||||
#include <irq_nextlevel.h>
|
||||
#endif
|
||||
|
||||
#define LOG_LEVEL CONFIG_SOC_LOG_LEVEL
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_REGISTER(soc);
|
||||
|
||||
#define SCG_LPFLL_DISABLE 0U
|
||||
|
||||
static struct device *dev_intmux;
|
||||
|
||||
/*
|
||||
* Run-mode configuration for the fast internal reference clock (FIRC).
|
||||
*/
|
||||
static const scg_firc_config_t rv32m1_firc_config = {
|
||||
.enableMode = kSCG_FircEnable,
|
||||
.div1 = kSCG_AsyncClkDivBy1,
|
||||
.div2 = kSCG_AsyncClkDivBy1,
|
||||
.div3 = kSCG_AsyncClkDivBy1,
|
||||
.range = kSCG_FircRange48M,
|
||||
.trimConfig = NULL,
|
||||
};
|
||||
|
||||
/*
|
||||
* FIRC-based system clock configuration.
|
||||
*/
|
||||
static const scg_sys_clk_config_t rv32m1_sys_clk_config_firc = {
|
||||
.divSlow = kSCG_SysClkDivBy2,
|
||||
.divBus = kSCG_SysClkDivBy1,
|
||||
.divExt = kSCG_SysClkDivBy1,
|
||||
.divCore = kSCG_SysClkDivBy1,
|
||||
.src = kSCG_SysClkSrcFirc,
|
||||
};
|
||||
|
||||
/*
|
||||
* LPFLL configuration.
|
||||
*/
|
||||
static const scg_lpfll_config_t rv32m1_lpfll_cfg = {
|
||||
.enableMode = SCG_LPFLL_DISABLE,
|
||||
.div1 = kSCG_AsyncClkDivBy1,
|
||||
.div2 = kSCG_AsyncClkDisable,
|
||||
.div3 = kSCG_AsyncClkDisable,
|
||||
.range = kSCG_LpFllRange48M,
|
||||
.trimConfig = NULL,
|
||||
};
|
||||
|
||||
void sys_arch_reboot(int type)
|
||||
{
|
||||
ARG_UNUSED(type);
|
||||
|
||||
EVENT_UNIT->SLPCTRL |= EVENT_SLPCTRL_SYSRSTREQST_MASK;
|
||||
}
|
||||
|
||||
void z_arch_irq_enable(unsigned int irq)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_MULTI_LEVEL_INTERRUPTS)) {
|
||||
unsigned int level = rv32m1_irq_level(irq);
|
||||
|
||||
if (level == 1U) {
|
||||
EVENT_UNIT->INTPTEN |= BIT(rv32m1_level1_irq(irq));
|
||||
/* Ensures write has finished: */
|
||||
(void)(EVENT_UNIT->INTPTEN);
|
||||
} else {
|
||||
irq_enable_next_level(dev_intmux, irq);
|
||||
}
|
||||
} else {
|
||||
EVENT_UNIT->INTPTEN |= BIT(rv32m1_level1_irq(irq));
|
||||
(void)(EVENT_UNIT->INTPTEN);
|
||||
}
|
||||
}
|
||||
|
||||
void z_arch_irq_disable(unsigned int irq)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_MULTI_LEVEL_INTERRUPTS)) {
|
||||
unsigned int level = rv32m1_irq_level(irq);
|
||||
|
||||
if (level == 1U) {
|
||||
EVENT_UNIT->INTPTEN &= ~BIT(rv32m1_level1_irq(irq));
|
||||
/* Ensures write has finished: */
|
||||
(void)(EVENT_UNIT->INTPTEN);
|
||||
} else {
|
||||
irq_disable_next_level(dev_intmux, irq);
|
||||
}
|
||||
} else {
|
||||
EVENT_UNIT->INTPTEN &= ~BIT(rv32m1_level1_irq(irq));
|
||||
(void)(EVENT_UNIT->INTPTEN);
|
||||
}
|
||||
}
|
||||
|
||||
int z_arch_irq_is_enabled(unsigned int irq)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_MULTI_LEVEL_INTERRUPTS)) {
|
||||
unsigned int level = rv32m1_irq_level(irq);
|
||||
|
||||
if (level == 1U) {
|
||||
return (EVENT_UNIT->INTPTEN &
|
||||
BIT(rv32m1_level1_irq(irq))) != 0;
|
||||
} else {
|
||||
u32_t channel, line, ier;
|
||||
|
||||
/*
|
||||
* Here we break the abstraction and look
|
||||
* directly at the INTMUX registers. We can't
|
||||
* use the irq_nextlevel.h API, as that only
|
||||
* tells us whether some IRQ at the next level
|
||||
* is enabled or not.
|
||||
*/
|
||||
channel = rv32m1_intmux_channel(irq);
|
||||
line = rv32m1_intmux_line(irq);
|
||||
ier = INTMUX->CHANNEL[channel].CHn_IER_31_0 & BIT(line);
|
||||
|
||||
return ier != 0U;
|
||||
}
|
||||
} else {
|
||||
return (EVENT_UNIT->INTPTEN & BIT(rv32m1_level1_irq(irq))) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
EVENT_UNIT->INTPTPENDCLEAR = 0xFFFFFFFF;
|
||||
(void)(EVENT_UNIT->INTPTPENDCLEAR); /* Ensures write has finished. */
|
||||
EVENT_UNIT->EVTPENDCLEAR = 0xFFFFFFFF;
|
||||
(void)(EVENT_UNIT->EVTPENDCLEAR); /* Ensures write has finished. */
|
||||
|
||||
if (IS_ENABLED(CONFIG_MULTI_LEVEL_INTERRUPTS)) {
|
||||
dev_intmux = device_get_binding(DT_OPENISA_RV32M1_INTMUX_INTMUX_LABEL);
|
||||
__ASSERT(dev_intmux, "no INTMUX device found");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Switch system clock configuration in run mode.
|
||||
*
|
||||
* Blocks until the updated configuration takes effect.
|
||||
*
|
||||
* @param cfg New system clock configuration
|
||||
*/
|
||||
static void rv32m1_switch_sys_clk(const scg_sys_clk_config_t *cfg)
|
||||
{
|
||||
scg_sys_clk_config_t cur_cfg;
|
||||
|
||||
CLOCK_SetRunModeSysClkConfig(cfg);
|
||||
do {
|
||||
CLOCK_GetCurSysClkConfig(&cur_cfg);
|
||||
} while (cur_cfg.src != cfg->src);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes SIRC and switches system clock source to SIRC.
|
||||
*/
|
||||
static void rv32m1_switch_to_sirc(void)
|
||||
{
|
||||
const scg_sirc_config_t sirc_config = {
|
||||
.enableMode = kSCG_SircEnable,
|
||||
.div1 = kSCG_AsyncClkDisable,
|
||||
.div2 = kSCG_AsyncClkDivBy2,
|
||||
.range = kSCG_SircRangeHigh,
|
||||
};
|
||||
const scg_sys_clk_config_t sys_clk_config_sirc = {
|
||||
.divSlow = kSCG_SysClkDivBy4,
|
||||
.divCore = kSCG_SysClkDivBy1,
|
||||
.src = kSCG_SysClkSrcSirc,
|
||||
};
|
||||
|
||||
CLOCK_InitSirc(&sirc_config);
|
||||
rv32m1_switch_sys_clk(&sys_clk_config_sirc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform basic hardware initialization
|
||||
*
|
||||
* Initializes the base clocks and LPFLL using helpers provided by the HAL.
|
||||
*
|
||||
* @return 0
|
||||
*/
|
||||
static int soc_rv32m1_init(struct device *arg)
|
||||
{
|
||||
unsigned int key;
|
||||
|
||||
ARG_UNUSED(arg);
|
||||
|
||||
key = irq_lock();
|
||||
|
||||
/* Switch to SIRC so we can initialize the FIRC. */
|
||||
rv32m1_switch_to_sirc();
|
||||
|
||||
/* Now that we're running off of SIRC, set up and switch to FIRC. */
|
||||
CLOCK_InitFirc(&rv32m1_firc_config);
|
||||
rv32m1_switch_sys_clk(&rv32m1_sys_clk_config_firc);
|
||||
|
||||
/* Initialize LPFLL */
|
||||
CLOCK_InitLpFll(&rv32m1_lpfll_cfg);
|
||||
|
||||
irq_unlock(key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(soc_rv32m1_init, PRE_KERNEL_1, 0);
|
111
soc/riscv/openisa_rv32m1/soc.h
Normal file
111
soc/riscv/openisa_rv32m1/soc.h
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Foundries.io Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef SOC_RISCV32_OPENISA_RV32M1_SOC_H_
|
||||
#define SOC_RISCV32_OPENISA_RV32M1_SOC_H_
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
|
||||
#include "fsl_device_registers.h"
|
||||
#include <zephyr/types.h>
|
||||
|
||||
/*
|
||||
* Helpers related to interrupt handling. This SoC has two levels of
|
||||
* interrupts.
|
||||
*
|
||||
* Level 1 interrupts go straight to the SoC. Level 2 interrupts must
|
||||
* go through one of the 8 channels in the the INTMUX
|
||||
* peripheral. There are 32 level 1 interrupts, including 8 INTMUX
|
||||
* interrupts. Each INTMUX interrupt can mux at most
|
||||
* CONFIG_MAX_IRQ_PER_AGGREGATOR (which happens to be 32) interrupts
|
||||
* to its level 1 interrupt.
|
||||
*
|
||||
* See gen_isr_tables.py for details on the Zephyr multi-level IRQ
|
||||
* number encoding, which determines how these helpers work.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Get an IRQ's level
|
||||
* @param irq The IRQ number in the Zephyr irq.h numbering system
|
||||
* @return IRQ level, either 1 or 2
|
||||
*/
|
||||
static inline unsigned int rv32m1_irq_level(unsigned int irq)
|
||||
{
|
||||
return ((irq >> 8) & 0xff) == 0U ? 1 : 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Level 1 interrupt line associated with an IRQ
|
||||
*
|
||||
* Results are undefined if rv32m1_irq_level(irq) is not 1.
|
||||
*
|
||||
* @param The IRQ number in the Zephyr <irq.h> numbering system
|
||||
* @return Level 1 (i.e. event unit) IRQ number associated with irq
|
||||
*/
|
||||
static inline u32_t rv32m1_level1_irq(unsigned int irq)
|
||||
{
|
||||
/*
|
||||
* There's no need to do any math; the precondition is that
|
||||
* it's a level 1 IRQ.
|
||||
*/
|
||||
return irq;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief INTMUX channel (i.e. level 2 aggregator number) for an IRQ
|
||||
*
|
||||
* Results are undefined if rv32m1_irq_level(irq) is not 2.
|
||||
*
|
||||
* @param irq The IRQ number whose INTMUX channel / level 2 aggregator
|
||||
* to get, in the Zephyr <irq.h> numbering system
|
||||
* @return INTMUX channel number associated with the IRQ
|
||||
*/
|
||||
static inline u32_t rv32m1_intmux_channel(unsigned int irq)
|
||||
{
|
||||
/*
|
||||
* Here we make use of these facts:
|
||||
*
|
||||
* - the INTMUX output IRQ numbers are arranged consecutively
|
||||
* by channel in the event unit IRQ numbering assignment,
|
||||
* starting from channel 0.
|
||||
*
|
||||
* - CONFIG_2ND_LVL_INTR_00_OFFSET is defined to
|
||||
* be the offset of the first level 2 aggregator in the parent
|
||||
* interrupt controller's IRQ numbers, i.e. channel 0's
|
||||
* IRQ number in the event unit.
|
||||
*/
|
||||
return (irq & 0xff) - CONFIG_2ND_LVL_INTR_00_OFFSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief INTMUX interrupt ID number for an IRQ
|
||||
*
|
||||
* Results are undefined if rv32m1_irq_level(irq) is not 2.
|
||||
*
|
||||
* @param The IRQ number whose INTMUX interrupt ID to get, in the Zephyr
|
||||
* <irq.h> numbering system
|
||||
* @return The INTMUX interrupt ID, in the inclusive range 0 to 31
|
||||
*/
|
||||
static inline u32_t rv32m1_intmux_line(unsigned int irq)
|
||||
{
|
||||
return ((irq >> 8) & 0xff) - 1;
|
||||
}
|
||||
|
||||
void soc_interrupt_init(void);
|
||||
|
||||
#endif /* !_ASMLANGUAGE */
|
||||
|
||||
#if defined(CONFIG_SOC_OPENISA_RV32M1_RI5CY)
|
||||
#include "soc_ri5cy.h"
|
||||
#elif defined(CONFIG_SOC_OPENISA_RV32M1_ZERO_RISCY)
|
||||
#include "soc_zero_riscy.h"
|
||||
#endif
|
||||
|
||||
/* Newlib hooks (and potentially other things) use these defines. */
|
||||
#define RISCV_RAM_SIZE KB(DT_SRAM_SIZE)
|
||||
#define RISCV_RAM_BASE DT_SRAM_BASE_ADDRESS
|
||||
|
||||
#endif /* SOC_RISCV32_OPENISA_RV32M1_SOC_H_ */
|
36
soc/riscv/openisa_rv32m1/soc_context.h
Normal file
36
soc/riscv/openisa_rv32m1/soc_context.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Foundries.io Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extra definitions required for CONFIG_RISCV_SOC_CONTEXT_SAVE.
|
||||
*/
|
||||
|
||||
#ifndef SOC_RISCV32_OPENISA_RV32M1_SOC_CONTEXT_H_
|
||||
#define SOC_RISCV32_OPENISA_RV32M1_SOC_CONTEXT_H_
|
||||
|
||||
#ifdef CONFIG_SOC_OPENISA_RV32M1_RI5CY
|
||||
|
||||
/* Extra state for RI5CY hardware loop registers. */
|
||||
#define SOC_ESF_MEMBERS \
|
||||
u32_t lpstart0; \
|
||||
u32_t lpend0; \
|
||||
u32_t lpcount0; \
|
||||
u32_t lpstart1; \
|
||||
u32_t lpend1; \
|
||||
u32_t lpcount1
|
||||
|
||||
/* Initial saved state. */
|
||||
#define SOC_ESF_INIT \
|
||||
0xdeadbaad, \
|
||||
0xdeadbaad, \
|
||||
0xdeadbaad, \
|
||||
0xdeadbaad, \
|
||||
0xdeadbaad, \
|
||||
0xdeadbaad
|
||||
|
||||
#endif /* CONFIG_SOC_OPENISA_RV32M1_RI5CY */
|
||||
|
||||
#endif /* SOC_RISCV32_OPENISA_RV32M1_SOC_CONTEXT_H_ */
|
95
soc/riscv/openisa_rv32m1/soc_irq.S
Normal file
95
soc/riscv/openisa_rv32m1/soc_irq.S
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Foundries.io Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <offsets.h>
|
||||
#include <toolchain.h>
|
||||
|
||||
#include <soc.h>
|
||||
|
||||
/* Exports */
|
||||
GTEXT(__soc_is_irq)
|
||||
GTEXT(__soc_handle_irq)
|
||||
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE
|
||||
GTEXT(__soc_save_context)
|
||||
GTEXT(__soc_restore_context)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Whether we're in an IRQ is bog-standard RISC-V on this SoC:
|
||||
* yes if the top mcause bit is set, otherwise no.
|
||||
*/
|
||||
SECTION_FUNC(exception.other, __soc_is_irq)
|
||||
csrr a0, mcause
|
||||
srli a0, a0, 31
|
||||
ret
|
||||
|
||||
/*
|
||||
* With a0 == irq_num, this is equivalent to:
|
||||
*
|
||||
* EVENT_UNIT->INTPTPENDCLEAR = (1U << irq_num);
|
||||
*
|
||||
* We could write this routine in C, but the assembly
|
||||
* that's calling us requires that a0 still contain irq_num
|
||||
* on return, and assuming nobody would ever change a
|
||||
* C implementation in a way that silently clobbers it
|
||||
* is playing with fire. Instead, we play tricks in
|
||||
* soc_context.h so that offsets.h contains a pointer to
|
||||
* INTPTPENDCLEAR.
|
||||
*/
|
||||
SECTION_FUNC(exception.other, __soc_handle_irq)
|
||||
la t0, __EVENT_INTPTPENDCLEAR
|
||||
li t1, 1
|
||||
sll t1, t1, a0
|
||||
sw t1, 0x00(t0)
|
||||
ret
|
||||
|
||||
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE
|
||||
/*
|
||||
* The RI5CY core has ISA extensions for faster loop performance
|
||||
* that use extra registers.
|
||||
*
|
||||
* If the toolchain generates instructions that use them, they must be saved
|
||||
* prior to handling an interrupt/exception. This case is handled using
|
||||
* Zephyr's generic RISC-V mechanism for soc-specific context.
|
||||
*
|
||||
* For details, see the Kconfig help for CONFIG_RISCV_SOC_CONTEXT_SAVE.
|
||||
*/
|
||||
SECTION_FUNC(exception.other, __soc_save_context)
|
||||
#ifdef CONFIG_SOC_OPENISA_RV32M1_RI5CY
|
||||
csrr t0, RI5CY_LPSTART0
|
||||
csrr t1, RI5CY_LPEND0
|
||||
csrr t2, RI5CY_LPCOUNT0
|
||||
sw t0, __soc_esf_t_lpstart0_OFFSET(a0)
|
||||
sw t1, __soc_esf_t_lpend0_OFFSET(a0)
|
||||
sw t2, __soc_esf_t_lpcount0_OFFSET(a0)
|
||||
csrr t0, RI5CY_LPSTART1
|
||||
csrr t1, RI5CY_LPEND1
|
||||
csrr t2, RI5CY_LPCOUNT1
|
||||
sw t0, __soc_esf_t_lpstart1_OFFSET(a0)
|
||||
sw t1, __soc_esf_t_lpend1_OFFSET(a0)
|
||||
sw t2, __soc_esf_t_lpcount1_OFFSET(a0)
|
||||
#endif /* CONFIG_SOC_OPENISA_RV32M1_RI5CY */
|
||||
|
||||
ret
|
||||
|
||||
SECTION_FUNC(exception.other, __soc_restore_context)
|
||||
#ifdef CONFIG_SOC_OPENISA_RV32M1_RI5CY
|
||||
lw t0, __soc_esf_t_lpstart0_OFFSET(a0)
|
||||
lw t1, __soc_esf_t_lpend0_OFFSET(a0)
|
||||
lw t2, __soc_esf_t_lpcount0_OFFSET(a0)
|
||||
csrw RI5CY_LPSTART0, t0
|
||||
csrw RI5CY_LPEND0, t1
|
||||
csrw RI5CY_LPCOUNT0, t2
|
||||
lw t0, __soc_esf_t_lpstart1_OFFSET(a0)
|
||||
lw t1, __soc_esf_t_lpend1_OFFSET(a0)
|
||||
lw t2, __soc_esf_t_lpcount1_OFFSET(a0)
|
||||
csrw RI5CY_LPSTART1, t0
|
||||
csrw RI5CY_LPEND1, t1
|
||||
csrw RI5CY_LPCOUNT1, t2
|
||||
#endif /* CONFIG_SOC_OPENISA_RV32M1_RI5CY */
|
||||
|
||||
ret
|
||||
#endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */
|
42
soc/riscv/openisa_rv32m1/soc_offsets.h
Normal file
42
soc/riscv/openisa_rv32m1/soc_offsets.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Foundries.io Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extra definitions required for CONFIG_RISCV_SOC_OFFSETS.
|
||||
*/
|
||||
|
||||
#ifndef SOC_RISCV32_OPENISA_RV32M1_SOC_OFFSETS_H_
|
||||
#define SOC_RISCV32_OPENISA_RV32M1_SOC_OFFSETS_H_
|
||||
|
||||
#ifdef CONFIG_SOC_OPENISA_RV32M1_RI5CY
|
||||
|
||||
/*
|
||||
* Ensure offset macros are available in <offsets.h>.
|
||||
*
|
||||
* Also create a macro which contains the value of &EVENT0->INTPTPENDCLEAR,
|
||||
* for use in assembly.
|
||||
*/
|
||||
#define GEN_SOC_OFFSET_SYMS() \
|
||||
GEN_OFFSET_SYM(soc_esf_t, lpstart0); \
|
||||
GEN_OFFSET_SYM(soc_esf_t, lpend0); \
|
||||
GEN_OFFSET_SYM(soc_esf_t, lpcount0); \
|
||||
GEN_OFFSET_SYM(soc_esf_t, lpstart1); \
|
||||
GEN_OFFSET_SYM(soc_esf_t, lpend1); \
|
||||
GEN_OFFSET_SYM(soc_esf_t, lpcount1); \
|
||||
GEN_ABSOLUTE_SYM(__EVENT_INTPTPENDCLEAR, \
|
||||
(uint32_t)&EVENT0->INTPTPENDCLEAR)
|
||||
|
||||
#endif /* CONFIG_SOC_OPENISA_RV32M1_RI5CY */
|
||||
|
||||
#ifdef CONFIG_SOC_OPENISA_RV32M1_ZERO_RISCY
|
||||
|
||||
#define GEN_SOC_OFFSET_SYMS() \
|
||||
GEN_ABSOLUTE_SYM(__EVENT_INTPTPENDCLEAR, \
|
||||
(uint32_t)&EVENT1->INTPTPENDCLEAR)
|
||||
|
||||
#endif /* CONFIG_SOC_OPENISA_RV32M1_ZERO_RISCY */
|
||||
|
||||
#endif /* SOC_RISCV32_OPENISA_RV32M1_SOC_OFFSETS_H_ */
|
88
soc/riscv/openisa_rv32m1/soc_ri5cy.h
Normal file
88
soc/riscv/openisa_rv32m1/soc_ri5cy.h
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Foundries.io Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef SOC_RISCV32_OPENISA_RV32M1_SOC_RI5CY_H_
|
||||
#define SOC_RISCV32_OPENISA_RV32M1_SOC_RI5CY_H_
|
||||
|
||||
/* Control and Status Registers (CSRs) available for RI5CY. */
|
||||
#define RI5CY_USTATUS 0x000
|
||||
#define RI5CY_UTVEC 0x005
|
||||
#define RI5CY_UHARTID 0x014
|
||||
#define RI5CY_UEPC 0x041
|
||||
#define RI5CY_UCAUSE 0x042
|
||||
#define RI5CY_MSTATUS 0x300
|
||||
#define RI5CY_MTVEC 0x305
|
||||
#define RI5CY_MEPC 0x341
|
||||
#define RI5CY_MCAUSE 0x342
|
||||
#define RI5CY_PCCR0 0x780
|
||||
#define RI5CY_PCCR1 0x781
|
||||
#define RI5CY_PCCR2 0x782
|
||||
#define RI5CY_PCCR3 0x783
|
||||
#define RI5CY_PCCR4 0x784
|
||||
#define RI5CY_PCCR5 0x785
|
||||
#define RI5CY_PCCR6 0x786
|
||||
#define RI5CY_PCCR7 0x787
|
||||
#define RI5CY_PCCR8 0x788
|
||||
#define RI5CY_PCCR9 0x789
|
||||
#define RI5CY_PCCR10 0x78A
|
||||
#define RI5CY_PCCR11 0x78B
|
||||
#define RI5CY_PCER 0x7A0
|
||||
#define RI5CY_PCMR 0x7A1
|
||||
#define RI5CY_LPSTART0 0x7B0
|
||||
#define RI5CY_LPEND0 0x7B1
|
||||
#define RI5CY_LPCOUNT0 0x7B2
|
||||
#define RI5CY_LPSTART1 0x7B4
|
||||
#define RI5CY_LPEND1 0x7B5
|
||||
#define RI5CY_LPCOUNT1 0x7B6
|
||||
#define RI5CY_PRIVLV 0xC10
|
||||
#define RI5CY_MHARTID 0xF14
|
||||
|
||||
/*
|
||||
* Map from SoC-specific configuration to generic Zephyr macros.
|
||||
*
|
||||
* These are expected by the code in arch/, and must be provided for
|
||||
* the kernel to work (or even build at all).
|
||||
*
|
||||
* Some of these may also apply to ZERO-RISCY; needs investigation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MSTATUS CSR number. (Note this is the standard value in the RISC-V
|
||||
* privileged ISA v1.10).
|
||||
*/
|
||||
#define SOC_MSTATUS_REG RI5CY_MSTATUS
|
||||
/* MSTATUS's interrupt enable mask. This is also standard. */
|
||||
#define SOC_MSTATUS_IEN (1U << 3)
|
||||
/*
|
||||
* Exception code mask. Use of the bottom five bits is a subset of
|
||||
* what the standard allocates (which is XLEN-1 bits).
|
||||
*/
|
||||
#define SOC_MCAUSE_EXP_MASK 0x1F
|
||||
/*
|
||||
* Assembler instruction to exit from interrupt in machine mode.
|
||||
* The name "ERET" is a leftover from pre-v1.10 privileged ISA specs.
|
||||
* The "mret" mnemonic works properly with the Pulpino toolchain;
|
||||
* YMMV if using a generic toolchain.
|
||||
*/
|
||||
#define SOC_ERET mret
|
||||
/* The ecall exception number. This is a standard value. */
|
||||
#define SOC_MCAUSE_ECALL_EXP 11
|
||||
/*
|
||||
* Default MSTATUS value to write when scheduling in a new thread for
|
||||
* the first time.
|
||||
*
|
||||
* - Preserve machine privileges in MPP. If you see any documentation
|
||||
* telling you that MPP is read-only on this SoC, don't believe its
|
||||
* lies.
|
||||
* - Enable interrupts when exiting from exception into a new thread
|
||||
* by setting MPIE now, so it will be copied into IE on mret.
|
||||
*/
|
||||
#define RI5CY_MSTATUS_MPP_M (0x3U << 11)
|
||||
#define RI5CY_MSTATUS_MPIE_EN (1U << 7)
|
||||
#define SOC_MSTATUS_DEF_RESTORE (RI5CY_MSTATUS_MPP_M | \
|
||||
RI5CY_MSTATUS_MPIE_EN)
|
||||
|
||||
#endif /* SOC_RISCV32_OPENISA_RV32M1_SOC_RI5CY_H_ */
|
76
soc/riscv/openisa_rv32m1/soc_zero_riscy.h
Normal file
76
soc/riscv/openisa_rv32m1/soc_zero_riscy.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Foundries.io Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef SOC_RISCV32_OPENISA_RV32M1_SOC_ZERO_RISCY_H_
|
||||
#define SOC_RISCV32_OPENISA_RV32M1_SOC_ZERO_RISCY_H_
|
||||
|
||||
/* Control and Status Registers (CSRs) available for ZERO_RISCY. */
|
||||
#define ZERO_RISCY_MSTATUS 0x300U
|
||||
#define ZERO_RISCY_MTVEC 0x305U
|
||||
#define ZERO_RISCY_MEPC 0x341U
|
||||
#define ZERO_RISCY_MCAUSE 0x342U
|
||||
#define ZERO_RISCY_PCCR0 0x780U
|
||||
#define ZERO_RISCY_PCCR1 0x781U
|
||||
#define ZERO_RISCY_PCCR2 0x782U
|
||||
#define ZERO_RISCY_PCCR3 0x783U
|
||||
#define ZERO_RISCY_PCCR4 0x784U
|
||||
#define ZERO_RISCY_PCCR5 0x785U
|
||||
#define ZERO_RISCY_PCCR6 0x786U
|
||||
#define ZERO_RISCY_PCCR7 0x787U
|
||||
#define ZERO_RISCY_PCCR8 0x788U
|
||||
#define ZERO_RISCY_PCCR9 0x789U
|
||||
#define ZERO_RISCY_PCCR10 0x78AU
|
||||
#define ZERO_RISCY_PCCR 0x78BU
|
||||
#define ZERO_RISCY_PCER 0x7A0U
|
||||
#define ZERO_RISCY_PCMR 0x7A1U
|
||||
#define ZERO_RISCY_MHARTID 0xF14U
|
||||
|
||||
/*
|
||||
* Map from SoC-specific configuration to generic Zephyr macros.
|
||||
*
|
||||
* These are expected by the code in arch/, and must be provided for
|
||||
* the kernel to work (or even build at all).
|
||||
*
|
||||
* Some of these may also apply to ZERO-RISCY; needs investigation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MSTATUS CSR number. (Note this is the standard value in the RISC-V
|
||||
* privileged ISA v1.10).
|
||||
*/
|
||||
#define SOC_MSTATUS_REG ZERO_RISCY_MSTATUS
|
||||
/* MSTATUS's interrupt enable mask. This is also standard. */
|
||||
#define SOC_MSTATUS_IEN (1U << 3)
|
||||
/*
|
||||
* Exception code mask. Use of the bottom five bits is a subset of
|
||||
* what the standard allocates (which is XLEN-1 bits).
|
||||
*/
|
||||
#define SOC_MCAUSE_EXP_MASK 0x1F
|
||||
/*
|
||||
* Assembler instruction to exit from interrupt in machine mode.
|
||||
* The name "ERET" is a leftover from pre-v1.10 privileged ISA specs.
|
||||
* The "mret" mnemonic works properly with the Pulpino toolchain;
|
||||
* YMMV if using a generic toolchain.
|
||||
*/
|
||||
#define SOC_ERET mret
|
||||
/* The ecall exception number. This is a standard value. */
|
||||
#define SOC_MCAUSE_ECALL_EXP 11
|
||||
/*
|
||||
* Default MSTATUS value to write when scheduling in a new thread for
|
||||
* the first time.
|
||||
*
|
||||
* - Preserve machine privileges in MPP. If you see any documentation
|
||||
* telling you that MPP is read-only on this SoC, don't believe its
|
||||
* lies.
|
||||
* - Enable interrupts when exiting from exception into a new thread
|
||||
* by setting MPIE now, so it will be copied into IE on mret.
|
||||
*/
|
||||
#define ZERO_RISCY_MSTATUS_MPP_M (0x3U << 11)
|
||||
#define ZERO_RISCY_MSTATUS_MPIE_EN (1U << 7)
|
||||
#define SOC_MSTATUS_DEF_RESTORE (ZERO_RISCY_MSTATUS_MPP_M | \
|
||||
ZERO_RISCY_MSTATUS_MPIE_EN)
|
||||
|
||||
#endif /* SOC_RISCV32_OPENISA_RV32M1_SOC_ZERO_RISCY_H_ */
|
80
soc/riscv/openisa_rv32m1/vector.S
Normal file
80
soc/riscv/openisa_rv32m1/vector.S
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Foundries.io Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <toolchain.h>
|
||||
|
||||
/* Imports */
|
||||
GTEXT(__initialize)
|
||||
GTEXT(__irq_wrapper)
|
||||
|
||||
/* Exports */
|
||||
GTEXT(__start)
|
||||
|
||||
/*
|
||||
* Interrupts work the same way for both the RI5CY and ZERO-RISCY cores
|
||||
* in this SoC; the only difference is the location of the vectors section
|
||||
* on flash. We thus reuse this ivt definition for each core.
|
||||
*
|
||||
* On interrupt, the event unit sets pc to the address in this table
|
||||
* at byte offset 4 * (IRQ line number).
|
||||
*
|
||||
* The reset, illegal instruction, ecall, and load store unit error exceptions
|
||||
* are handled by the addresses right after the IRQ table.
|
||||
*
|
||||
* Note: Per RV32I restrictions, "j SOME_HANDLER" can jump within a +/- 1MiB
|
||||
* range. This is not a problem on this SoC: RI5CY is allocated 1MiB flash
|
||||
* and ZERO-RISCY is allocated 256 KiB, and these flash banks contain the
|
||||
* text and vectors sections, so the limits are satisfied.
|
||||
*/
|
||||
SECTION_FUNC(vectors, ivt)
|
||||
.option norvc
|
||||
|
||||
/* Interrupts */
|
||||
j __irq_wrapper /* IRQ 0 */
|
||||
j __irq_wrapper /* IRQ 1 */
|
||||
j __irq_wrapper /* IRQ 2 */
|
||||
j __irq_wrapper /* IRQ 3 */
|
||||
j __irq_wrapper /* IRQ 4 */
|
||||
j __irq_wrapper /* IRQ 5 */
|
||||
j __irq_wrapper /* IRQ 6 */
|
||||
j __irq_wrapper /* IRQ 7 */
|
||||
j __irq_wrapper /* IRQ 8 */
|
||||
j __irq_wrapper /* IRQ 9 */
|
||||
j __irq_wrapper /* IRQ 10 */
|
||||
j __irq_wrapper /* IRQ 11 */
|
||||
j __irq_wrapper /* IRQ 12 */
|
||||
j __irq_wrapper /* IRQ 13 */
|
||||
j __irq_wrapper /* IRQ 14 */
|
||||
j __irq_wrapper /* IRQ 15 */
|
||||
j __irq_wrapper /* IRQ 16 */
|
||||
j __irq_wrapper /* IRQ 17 */
|
||||
j __irq_wrapper /* IRQ 18 */
|
||||
j __irq_wrapper /* IRQ 19 */
|
||||
j __irq_wrapper /* IRQ 20 */
|
||||
j __irq_wrapper /* IRQ 21 */
|
||||
j __irq_wrapper /* IRQ 22 */
|
||||
j __irq_wrapper /* IRQ 23 */
|
||||
j __irq_wrapper /* IRQ 24 */
|
||||
j __irq_wrapper /* IRQ 25 */
|
||||
j __irq_wrapper /* IRQ 26 */
|
||||
j __irq_wrapper /* IRQ 27 */
|
||||
j __irq_wrapper /* IRQ 28 */
|
||||
j __irq_wrapper /* IRQ 29 */
|
||||
j __irq_wrapper /* IRQ 30 */
|
||||
j __irq_wrapper /* IRQ 31 */
|
||||
|
||||
/* Exceptions */
|
||||
j __start /* reset */
|
||||
j __irq_wrapper /* illegal instruction */
|
||||
j __irq_wrapper /* ecall */
|
||||
j __irq_wrapper /* load store eunit error */
|
||||
|
||||
SECTION_FUNC(vectors, __start)
|
||||
/* Set mtvec to point at ivt. */
|
||||
la t0, ivt
|
||||
csrw 0x305, t0
|
||||
/* Call into Zephyr initialization. */
|
||||
tail __initialize
|
63
soc/riscv/openisa_rv32m1/wdog.S
Normal file
63
soc/riscv/openisa_rv32m1/wdog.S
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Foundries.io Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <linker/sections.h>
|
||||
#include <toolchain.h>
|
||||
#include <soc.h>
|
||||
|
||||
/* Exports */
|
||||
GTEXT(_WdogInit)
|
||||
|
||||
/* WDOG instance base address. */
|
||||
#ifdef CONFIG_SOC_OPENISA_RV32M1_RI5CY
|
||||
#define WDOG_BASE 0x4002A000 /* WDOG0 */
|
||||
#else
|
||||
#define WDOG_BASE 0x41026000 /* WDOG1 */
|
||||
#endif
|
||||
|
||||
/* Register offsets. */
|
||||
#define WDOG_CS_OFFSET 0x00
|
||||
#define WDOG_CNT_OFFSET 0x04
|
||||
#define WDOG_TOVAL_OFFSET 0x08
|
||||
|
||||
/* Watchdog unlock key. */
|
||||
#define WDOG_CNT_UNLOCK 0xD928C520
|
||||
|
||||
/* TOVAL must be set when disabling watchdog after reset. */
|
||||
#define WDOG_TOVAL_SET 0xFFFF
|
||||
|
||||
/* Disable the WDOG_CS[EN] bit. */
|
||||
#define WDOG_CS_EN_DISABLED ~0x80
|
||||
/* Set WDOG_CS[UPDATE] bit. */
|
||||
#define WDOG_CS_UPDATE_ENABLED 0x20
|
||||
|
||||
/*
|
||||
* Unlock and disable the watchdog, which is enabled by default.
|
||||
*/
|
||||
SECTION_FUNC(TEXT, _WdogInit)
|
||||
/* Disable interrupts if they're on. This is timing-sensitive code. */
|
||||
csrrc t0, mstatus, SOC_MSTATUS_IEN
|
||||
|
||||
/* Get base address. */
|
||||
li t1, WDOG_BASE
|
||||
|
||||
/* Unlock the watchdog. */
|
||||
li t2, WDOG_CNT_UNLOCK
|
||||
sw t2, WDOG_CNT_OFFSET(t1)
|
||||
|
||||
/* Disable the watchdog. Allow updates later. */
|
||||
lw t2, WDOG_CS_OFFSET(t1)
|
||||
andi t2, t2, WDOG_CS_EN_DISABLED
|
||||
ori t2, t2, WDOG_CS_UPDATE_ENABLED
|
||||
sw t2, WDOG_CS_OFFSET(t1)
|
||||
|
||||
/* This must also be done per reference manual. */
|
||||
li t2, WDOG_TOVAL_SET
|
||||
sw t2, WDOG_TOVAL_OFFSET(t1)
|
||||
|
||||
/* Re-enable interrupts if they were disabled. */
|
||||
csrrs x0, mstatus, t0
|
||||
ret
|
Loading…
Add table
Add a link
Reference in a new issue