soc: riscv: telink_b91: new Telink B91 (TLSR9) SoC system

A new RISC-V platform SoC for Telink B91 (TLSR9).

Signed-off-by: Yuriy Vynnychek <yura.vynnychek@telink-semi.com>
This commit is contained in:
Yuriy Vynnychek 2021-07-09 11:37:34 +03:00 committed by Christopher Friedt
commit 3de6c05f63
11 changed files with 515 additions and 0 deletions

View file

@ -0,0 +1,15 @@
# Copyright (c) 2021 Telink Semiconductor
# SPDX-License-Identifier: Apache-2.0
zephyr_sources(
start.S
soc_irq.S
soc.c
)
# Force using BFD-LD
zephyr_ld_options(-fuse-ld=bfd)
# Set compile options
zephyr_compile_options_ifdef(CONFIG_TELINK_B91_HWDSP -mext-dsp)
zephyr_compile_options(-mno-relax)

View file

@ -0,0 +1,46 @@
# Copyright (c) 2021 Telink Semiconductor
# SPDX-License-Identifier: Apache-2.0
if SOC_SERIES_RISCV_TELINK_B91
config SOC_SERIES
string
default "telink_b91"
config SYS_CLOCK_HW_CYCLES_PER_SEC
int
default 32000
config RISCV_SOC_INTERRUPT_INIT
bool
default y
config RISCV_HAS_CPU_IDLE
bool
default y
config RISCV_HAS_PLIC
bool
default y
config NUM_IRQS
int
default 64
config XIP
bool
default n
config MAIN_STACK_SIZE
int
default 2048
config IDLE_STACK_SIZE
int
default 1536
config TEST_EXTRA_STACKSIZE
int
default 1024
endif # SOC_SERIES_RISCV_TELINK_B91

View file

@ -0,0 +1,10 @@
# Copyright (c) 2021 Telink Semiconductor
# SPDX-License-Identifier: Apache-2.0
config SOC_SERIES_RISCV_TELINK_B91
bool "Telink B91 SoC Implementation"
select RISCV
select SOC_FAMILY_RISCV_PRIVILEGE
select HAS_TELINK_DRIVERS
help
Enable support for Telink B91 SoC

View file

@ -0,0 +1,33 @@
# Copyright (c) 2021 Telink Semiconductor
# SPDX-License-Identifier: Apache-2.0
choice
prompt "CPU Architecture of SoC"
depends on SOC_SERIES_RISCV_TELINK_B91
config B91_CPU_RISCV32
bool "RISCV32 CPU Architecture"
endchoice
config TELINK_B91_HWDSP
bool "Support Hardware DSP"
select RISCV_SOC_CONTEXT_SAVE
depends on SOC_SERIES_RISCV_TELINK_B91
config TELINK_B91_PFT_ARCH
bool "Support performance throttling"
default y
select RISCV_SOC_CONTEXT_SAVE
depends on SOC_SERIES_RISCV_TELINK_B91
choice
prompt "Telink B91 SoC implementation"
depends on SOC_SERIES_RISCV_TELINK_B91
config SOC_RISCV_TELINK_B91
bool "Telink B91 SoC implementation"
select ATOMIC_OPERATIONS_BUILTIN
select CPU_HAS_FPU
endchoice

View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 2021 Telink Semiconductor
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @brief Linker script for the Telink B91 SoC
*/
#include <soc.h>
#include <autoconf.h>
#include <linker/linker-tool.h>
MEMORY
{
ROM_INIT (rx) : ORIGIN = DT_REG_ADDR(DT_CHOSEN(zephyr_flash)), LENGTH = DT_REG_SIZE(DT_CHOSEN(zephyr_flash))
RAM_ILM (rwx) : ORIGIN = DT_REG_ADDR(DT_NODELABEL(ram_ilm)), LENGTH = DT_REG_SIZE(DT_NODELABEL(ram_ilm))
}
SECTIONS
{
SECTION_PROLOGUE(vector,,)
{
. = ALIGN(4);
KEEP(*(.init.*))
} GROUP_LINK_IN(ROM_INIT)
}
#include <arch/riscv/common/linker.ld>
SECTIONS
{
SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,)
{
. = ALIGN(8);
PROVIDE (__global_pointer$ = __data_ram_start + 0x800);
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
SECTION_DATA_PROLOGUE(retention_data,,)
{
. = ALIGN(8);
*(.retention_data)
*(".retention_data.*")
PROVIDE (_RETENTION_DATA_VMA_END = .);
PROVIDE (_RETENTION_DATA_VMA_START = ADDR(retention_data));
PROVIDE (_RETENTION_DATA_LMA_START = LOADADDR(retention_data));
} GROUP_DATA_LINK_IN(RAM_ILM, ROMABLE_REGION)
SECTION_DATA_PROLOGUE(ram_code,,)
{
. = ALIGN(8);
*(.ram_code)
*(".ram_code.*")
PROVIDE (_RAMCODE_VMA_END = .);
PROVIDE (_RAMCODE_VMA_START = ADDR(ram_code));
PROVIDE (_RAMCODE_LMA_START = LOADADDR(ram_code));
} GROUP_DATA_LINK_IN(RAM_ILM, ROMABLE_REGION)
}

View file

@ -0,0 +1,126 @@
/*
* Copyright (c) 2021 Telink Semiconductor
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sys.h"
#include "clock.h"
#include <device.h>
/* Software reset defines */
#define reg_reset REG_ADDR8(0x1401ef)
#define SOFT_RESET 0x20u
/* List of supported CCLK fregencies */
#define CLK_16MHZ 16000000u
#define CLK_24MHZ 24000000u
#define CLK_32MHZ 32000000u
#define CLK_48MHZ 48000000u
#define CLK_64MHZ 64000000u
#define CLK_96MHZ 96000000u
/* Define 48 MHz and 96 MHz CCLK clock options (not present in HAL) */
#define CCLK_64M_HCLK_32M_PCLK_16M clock_init(PLL_CLK_192M, \
PAD_PLL_DIV, \
PLL_DIV3_TO_CCLK, \
CCLK_DIV2_TO_HCLK, \
HCLK_DIV2_TO_PCLK, \
PLL_DIV4_TO_MSPI_CLK)
#define CCLK_96M_HCLK_48M_PCLK_24M clock_init(PLL_CLK_192M, \
PAD_PLL_DIV, \
PLL_DIV2_TO_CCLK, \
CCLK_DIV2_TO_HCLK, \
HCLK_DIV2_TO_PCLK, \
PLL_DIV4_TO_MSPI_CLK)
/* Power Mode value */
#if DT_ENUM_IDX(DT_NODELABEL(power), power_mode) == 0
#define POWER_MODE LDO_1P4_LDO_1P8
#elif DT_ENUM_IDX(DT_NODELABEL(power), power_mode) == 1
#define POWER_MODE DCDC_1P4_LDO_1P8
#elif DT_ENUM_IDX(DT_NODELABEL(power), power_mode) == 2
#define POWER_MODE DCDC_1P4_DCDC_1P8
#else
#error "Wrong value for power-mode parameter"
#endif
/* Vbat Type value */
#if DT_ENUM_IDX(DT_NODELABEL(power), vbat_type) == 0
#define VBAT_TYPE VBAT_MAX_VALUE_LESS_THAN_3V6
#elif DT_ENUM_IDX(DT_NODELABEL(power), vbat_type) == 1
#define VBAT_TYPE VBAT_MAX_VALUE_GREATER_THAN_3V6
#else
#error "Wrong value for vbat-type parameter"
#endif
/* Check System Clock value. */
#if ((DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency) != CLK_16MHZ) && \
(DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency) != CLK_24MHZ) && \
(DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency) != CLK_32MHZ) && \
(DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency) != CLK_48MHZ) && \
(DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency) != CLK_64MHZ) && \
(DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency) != CLK_96MHZ))
#error "Unsupported clock-frequency. Supported values: 16, 24, 32, 48, 64 and 96 MHz"
#endif
/**
* @brief Perform basic initialization at boot.
*
* @return 0
*/
static int soc_b91_init(const struct device *arg)
{
unsigned int cclk = DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency);
ARG_UNUSED(arg);
/* system init */
sys_init(POWER_MODE, VBAT_TYPE);
/* clocks init: CCLK, HCLK, PCLK */
switch (cclk) {
case CLK_16MHZ:
CCLK_16M_HCLK_16M_PCLK_16M;
break;
case CLK_24MHZ:
CCLK_24M_HCLK_24M_PCLK_24M;
break;
case CLK_32MHZ:
CCLK_32M_HCLK_32M_PCLK_16M;
break;
case CLK_48MHZ:
CCLK_48M_HCLK_48M_PCLK_24M;
break;
case CLK_64MHZ:
CCLK_64M_HCLK_32M_PCLK_16M;
break;
case CLK_96MHZ:
CCLK_96M_HCLK_48M_PCLK_24M;
break;
}
/* Init Machine Timer source clock: 32 KHz RC */
clock_32k_init(CLK_32K_RC);
clock_cal_32k_rc();
return 0;
}
/**
* @brief Reset the system.
*/
void sys_arch_reboot(int type)
{
ARG_UNUSED(type);
reg_reset = SOFT_RESET;
}
SYS_INIT(soc_b91_init, PRE_KERNEL_1, 0);

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2021 Telink Semiconductor
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef RISCV_TELINK_B91_SOC_H
#define RISCV_TELINK_B91_SOC_H
#include <soc_common.h>
#include <devicetree.h>
/* Machine timer memory-mapped registers */
#define RISCV_MTIME_BASE 0xE6000000
#define RISCV_MTIMECMP_BASE 0xE6000008
#endif /* RISCV_TELINK_B91_SOC_H */

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2021 Telink Semiconductor
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef SOC_RISCV_TELINK_B91_SOC_CONTEXT_H
#define SOC_RISCV_TELINK_B91_SOC_CONTEXT_H
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE
/* Telink B91 specific registers. */
#if defined(CONFIG_TELINK_B91_PFT_ARCH) && defined(__riscv_dsp)
#define SOC_ESF_MEMBERS \
uint32_t mxstatus; \
uint32_t ucode \
#define SOC_ESF_INIT \
0xdeadbaad, \
0xdeadbaad
#define SOC_ESF_THREAD_INIT(soc_context) \
(soc_context)->mxstatus = 0; \
(soc_context)->ucode = 0
#elif defined(CONFIG_TELINK_B91_PFT_ARCH)
#define SOC_ESF_MEMBERS \
uint32_t mxstatus
#define SOC_ESF_INIT \
0xdeadbaad
#define SOC_ESF_THREAD_INIT(soc_context) \
(soc_context)->mxstatus = 0
#elif defined(__riscv_dsp)
#define SOC_ESF_MEMBERS \
uint32_t ucode
#define SOC_ESF_INIT \
0xdeadbaad
#define SOC_ESF_THREAD_INIT(soc_context) \
(soc_context)->ucode = 0
#endif
#endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */
#endif /* SOC_RISCV_TELINK_B91_SOC_CONTEXT_H */

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2021 Telink Semiconductor
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <offsets.h>
#include <toolchain.h>
#include <soc.h>
#define NDS_MXSTATUS 0x7C4
/* Exports */
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE
GTEXT(__soc_save_context)
GTEXT(__soc_restore_context)
#endif
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE
SECTION_FUNC(exception.other, __soc_save_context)
#ifdef CONFIG_TELINK_B91_PFT_ARCH
csrr t0, NDS_MXSTATUS
#endif
#ifdef __riscv_dsp
csrr t1, ucode
#endif
#ifdef CONFIG_TELINK_B91_PFT_ARCH
sw t0, __soc_esf_t_mxstatus_OFFSET(a0)
#endif
#ifdef __riscv_dsp
sw t1, __soc_esf_t_ucode_OFFSET(a0)
#endif
ret
SECTION_FUNC(exception.other, __soc_restore_context)
#ifdef CONFIG_TELINK_B91_PFT_ARCH
lw t0, __soc_esf_t_mxstatus_OFFSET(a0)
#endif
#ifdef __riscv_dsp
lw t1, __soc_esf_t_ucode_OFFSET(a0)
#endif
#ifdef CONFIG_TELINK_B91_PFT_ARCH
csrw NDS_MXSTATUS, t0
#endif
#ifdef __riscv_dsp
csrw ucode, t1
#endif
ret
#endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2021 Telink Semiconductor
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef SOC_RISCV_TELINK_B91_SOC_OFFSETS_H
#define SOC_RISCV_TELINK_B91_SOC_OFFSETS_H
#ifdef CONFIG_RISCV_SOC_OFFSETS
/* Telink B91 specific registers. */
#if defined(CONFIG_TELINK_B91_PFT_ARCH) && defined(__riscv_dsp)
#define GEN_SOC_OFFSET_SYMS() \
GEN_OFFSET_SYM(soc_esf_t, mxstatus); \
GEN_OFFSET_SYM(soc_esf_t, ucode)
#elif defined(CONFIG_TELINK_B91_PFT_ARCH)
#define GEN_SOC_OFFSET_SYMS() \
GEN_OFFSET_SYM(soc_esf_t, mxstatus)
#elif defined(__riscv_dsp)
#define GEN_SOC_OFFSET_SYMS() \
GEN_OFFSET_SYM(soc_esf_t, ucode)
#endif
#endif /* CONFIG_RISCV_SOC_OFFSETS */
#endif /* SOC_RISCV_TELINK_B91_SOC_OFFSETS_H*/

View file

@ -0,0 +1,71 @@
/*
* Copyright (c) 2021 Telink Semiconductor
*
* SPDX-License-Identifier: Apache-2.0
*/
#define NDS_MCACHE_CTL 0x7CA
#define NDS_MMISC_CTL 0x7D0
#include <toolchain.h>
.option push
.option norelax
.org 0x0
/* exports */
GTEXT(entry)
SECTION_FUNC(init, init)
entry:
j start
.org 0x20
.word ('T'<<24 | 'L'<<16 | 'N'<<8 | 'K')
.org 0x26
.short (0x173B)
.option pop
.align 2
start:
/* Enable I/D-Cache */
csrr t0, NDS_MCACHE_CTL
ori t0, t0, 1 #/I-Cache
ori t0, t0, 2 #/D-Cache
csrw NDS_MCACHE_CTL, t0
fence.i
/* Enable misaligned access and non-blocking load */
li t0, (1 << 8) | (1 << 6)
csrs NDS_MMISC_CTL, t0
_RETENTION_DATA_INIT:
la t1, _RETENTION_DATA_LMA_START
la t2, _RETENTION_DATA_VMA_START
la t3, _RETENTION_DATA_VMA_END
_RETENTION_DATA_INIT_BEGIN:
bleu t3, t2, _RAMCODE_INIT
lw t0, 0(t1)
sw t0, 0(t2)
addi t1, t1, 4
addi t2, t2, 4
j _RETENTION_DATA_INIT_BEGIN
_RAMCODE_INIT:
la t1, _RAMCODE_LMA_START
la t2, _RAMCODE_VMA_START
la t3, _RAMCODE_VMA_END
_RAMCODE_INIT_BEGIN:
bleu t3, t2, _START
lw t0, 0(t1)
sw t0, 0(t2)
addi t1, t1, 4
addi t2, t2, 4
j _RAMCODE_INIT_BEGIN
_START:
j __start