soc: Introduce Qingke V4C-based CH32V208 SoC

This introduces the only CH32 Serie Qingke V4C SoC, CH32V208

Signed-off-by: Camille BAUD <mail@massdriver.space>
This commit is contained in:
Camille BAUD 2025-02-22 15:41:41 +01:00 committed by Benjamin Cabé
commit f67b321607
19 changed files with 445 additions and 1 deletions

View file

@ -0,0 +1,8 @@
# Copyright (c) 2024 MASSDRIVER EI (massdriver.space)
# SPDX-License-Identifier: Apache-2.0
description: WCH QingKe V4C RISC-V MCU
compatible: "wch,qingke-v4c"
include: riscv,cpus.yaml

View file

@ -0,0 +1,157 @@
/*
* Copyright (c) 2025 MASSDRIVER EI (massdriver.space)
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <freq.h>
#include <mem.h>
#include <wch/qingke-v4c.dtsi>
#include <zephyr/dt-bindings/gpio/gpio.h>
#include <zephyr/dt-bindings/i2c/i2c.h>
#include <zephyr/dt-bindings/clock/ch32v20x_30x-clocks.h>
/ {
clocks {
clk_hse: clk-hse {
#clock-cells = <0>;
compatible = "wch,ch32v00x-hse-clock";
clock-frequency = <DT_FREQ_M(32)>;
status = "disabled";
};
clk_hsi: clk-hsi {
#clock-cells = <0>;
compatible = "wch,ch32v00x-hsi-clock";
clock-frequency = <DT_FREQ_M(8)>;
status = "disabled";
};
clk_lsi: clk-lsi {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <DT_FREQ_K(32)>;
status = "disabled";
};
pll: pll {
#clock-cells = <0>;
compatible = "wch,ch32v20x_30x-pll-clock";
mul = <18>;
status = "disabled";
};
};
soc {
sram0: memory@20000000 {
compatible = "mmio-sram";
reg = <0x20000000 DT_SIZE_K(64)>;
};
flash: flash-controller@40022000 {
compatible = "wch,ch32v20x_30x-flash-controller";
reg = <0x40022000 0x400>;
#address-cells = <1>;
#size-cells = <1>;
flash0: flash@0 {
compatible = "soc-nv-flash";
reg = <0 DT_SIZE_K(128)>;
};
};
pwr: pwr@40007000 {
compatible = "wch,pwr";
reg = <0x40007000 16>;
};
pinctrl: pin-controller@40010000 {
compatible = "wch,20x_30x-afio";
reg = <0x40010000 16>;
#address-cells = <1>;
#size-cells = <1>;
gpioa: gpio@40010800 {
compatible = "wch,gpio";
reg = <0x40010800 0x20>;
gpio-controller;
#gpio-cells = <2>;
ngpios = <8>;
clocks = <&rcc CH32V20X_V30X_CLOCK_IOPA>;
};
gpiob: gpio@40010C00 {
compatible = "wch,gpio";
reg = <0x40010C00 0x20>;
gpio-controller;
#gpio-cells = <2>;
ngpios = <8>;
clocks = <&rcc CH32V20X_V30X_CLOCK_IOPB>;
};
gpioc: gpio@40011000 {
compatible = "wch,gpio";
reg = <0x40011000 0x20>;
gpio-controller;
#gpio-cells = <2>;
ngpios = <8>;
clocks = <&rcc CH32V20X_V30X_CLOCK_IOPC>;
};
gpiod: gpio@40011400 {
compatible = "wch,gpio";
reg = <0x40011400 0x20>;
gpio-controller;
#gpio-cells = <2>;
ngpios = <8>;
clocks = <&rcc CH32V20X_V30X_CLOCK_IOPD>;
};
};
usart1: uart@40013800 {
compatible = "wch,usart";
reg = <0x40013800 0x20>;
clocks = <&rcc CH32V20X_V30X_CLOCK_USART1>;
interrupt-parent = <&pfic>;
interrupts = <53>;
status = "disabled";
};
usart2: uart@40004400 {
compatible = "wch,usart";
reg = <0x40004400 0x20>;
clocks = <&rcc CH32V20X_V30X_CLOCK_USART2>;
interrupt-parent = <&pfic>;
interrupts = <54>;
status = "disabled";
};
usart3: uart@40004800 {
compatible = "wch,usart";
reg = <0x40004800 0x20>;
clocks = <&rcc CH32V20X_V30X_CLOCK_USART3>;
interrupt-parent = <&pfic>;
interrupts = <55>;
status = "disabled";
};
usart4: uart@40004c00 {
compatible = "wch,usart";
reg = <0x40004C00 0x20>;
clocks = <&rcc CH32V20X_V30X_CLOCK_USART4>;
interrupt-parent = <&pfic>;
interrupts = <68>;
status = "disabled";
};
rcc: rcc@40021000 {
compatible = "wch,rcc";
reg = <0x40021000 16>;
#clock-cells = <1>;
};
};
};
&cpu0 {
clock-frequency = <DT_FREQ_M(144)>;
};

View file

@ -0,0 +1,15 @@
/*
* Copyright (c) 2025 MASSDRIVER EI (massdriver.space)
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <wch/ch32v208/ch32v208.dtsi>
&gpioc {
gpio-reserved-ranges = <0 13>;
};
&gpiod {
gpio-reserved-ranges = <0 16>;
};

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2025 MASSDRIVER EI (massdriver.space)
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <wch/ch32v208/ch32v208.dtsi>
&gpioa {
gpio-reserved-ranges = <8 3>, <15 1>;
};
&gpiob {
gpio-reserved-ranges = <0 6>, <9 7>;
};
&gpioc {
gpio-reserved-ranges = <0 7>, <10 4>;
};
&gpiod {
gpio-reserved-ranges = <0 16>;
};

View file

@ -0,0 +1,11 @@
/*
* Copyright (c) 2025 MASSDRIVER EI (massdriver.space)
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <wch/ch32v208/ch32v208.dtsi>
&gpiod {
gpio-reserved-ranges = <0 2>, <3 12>;
};

View file

@ -0,0 +1,11 @@
/*
* Copyright (c) 2025 MASSDRIVER EI (massdriver.space)
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <wch/ch32v208/ch32v208.dtsi>
&gpiod {
gpio-reserved-ranges = <0 2>, <7 8>;
};

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2025 MASSDRIVER EI (massdriver.space)
*
* SPDX-License-Identifier: Apache-2.0
*/
/ {
#address-cells = <1>;
#size-cells = <1>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu0: cpu@0 {
device_type = "cpu";
compatible = "wch,qingke-v4c";
reg = <0>;
riscv,isa = "rv32imac_zicsr_zifencei";
};
};
soc {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges;
pfic: interrupt-controller@e000e000 {
compatible = "wch,pfic";
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-controller;
reg = <0xe000e000 0x10>;
status = "okay";
};
systick: systimer@e000f000 {
compatible = "wch,systick";
reg = <0xe000f000 0x10>;
status = "okay";
interrupt-parent = <&pfic>;
interrupts = <12>;
};
};
};

View file

@ -1,3 +1,3 @@
if(CONFIG_SOC_CH32V003)
if(CONFIG_SOC_CH32V003 OR CONFIG_SOC_SERIES_QINGKE_V4C)
zephyr_include_directories(${ZEPHYR_HAL_WCH_MODULE_DIR}/ch32v003fun .)
endif()

View file

@ -12,4 +12,9 @@
#include <ch32v003fun.h>
#endif
#if defined(CONFIG_SOC_SERIES_QINGKE_V4C)
#define CH32V20x 1
#include <ch32v003fun.h>
#endif
#endif

View file

@ -0,0 +1,10 @@
# Copyright (c) 2024 Michael Hope
# Copyright (c) 2024 Jianxiong Gu
# SPDX-License-Identifier: Apache-2.0
zephyr_sources(
soc_irq.S
vector.S
)
zephyr_include_directories(.)

View file

@ -0,0 +1,10 @@
# Copyright (c) 2025 MASSDRIVER EI (massdriver.space)
# SPDX-License-Identifier: Apache-2.0
config SOC_SERIES_QINGKE_V4C
select RISCV_ISA_RV32I
select RISCV_ISA_EXT_M
select RISCV_ISA_EXT_A
select RISCV_ISA_EXT_C
select RISCV_ISA_EXT_ZICSR
select RISCV_ISA_EXT_ZIFENCEI

View file

@ -0,0 +1,23 @@
# Copyright (c) 2025 MASSDRIVER EI (massdriver.space)
# SPDX-License-Identifier: Apache-2.0
if SOC_SERIES_QINGKE_V4C
config SYS_CLOCK_HW_CYCLES_PER_SEC
default $(dt_node_int_prop_int,/cpus/cpu@0,clock-frequency)
config MAIN_STACK_SIZE
default 512
config IDLE_STACK_SIZE
default 256
config ISR_STACK_SIZE
default 256
config CLOCK_CONTROL
default y
rsource "Kconfig.defconfig.*"
endif # SOC_SERIES_QINGKE_V4C

View file

@ -0,0 +1,12 @@
# Copyright (c) 2025 MASSDRIVER EI (massdriver.space)
# SPDX-License-Identifier: Apache-2.0
if SOC_CH32V208
config VECTOR_TABLE_SIZE
default 103
config NUM_IRQS
default 128
endif # SOC_CH32V208

View file

@ -0,0 +1,11 @@
# Copyright (c) 2025 MASSDRIVER EI (massdriver.space)
# SPDX-License-Identifier: Apache-2.0
config SOC_SERIES_QINGKE_V4C
bool
select SOC_FAMILY_CH32V
config SOC_SERIES
default "qingke_v4c" if SOC_SERIES_QINGKE_V4C
rsource "Kconfig.soc.*"

View file

@ -0,0 +1,9 @@
# Copyright (c) 2025 MASSDRIVER EI (massdriver.space)
# SPDX-License-Identifier: Apache-2.0
config SOC_CH32V208
bool
select SOC_SERIES_QINGKE_V4C
config SOC
default "ch32v208" if SOC_CH32V208

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2024 Michael Hope
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __PINCTRL_SOC_H__
#define __PINCTRL_SOC_H__
/**
* @brief Type to hold a pin's pinctrl configuration.
*/
struct ch32v208_pinctrl_soc_pin {
uint32_t config: 22;
bool bias_pull_up: 1;
bool bias_pull_down: 1;
bool drive_open_drain: 1;
bool drive_push_pull: 1;
bool output_high: 1;
bool output_low: 1;
uint8_t slew_rate: 2;
};
typedef struct ch32v208_pinctrl_soc_pin pinctrl_soc_pin_t;
#define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) \
{ \
.config = DT_PROP_BY_IDX(node_id, prop, idx), \
.bias_pull_up = DT_PROP(node_id, bias_pull_up), \
.bias_pull_down = DT_PROP(node_id, bias_pull_down), \
.drive_open_drain = DT_PROP(node_id, drive_open_drain), \
.drive_push_pull = DT_PROP(node_id, drive_push_pull), \
.output_high = DT_PROP(node_id, output_high), \
.output_low = DT_PROP(node_id, output_low), \
.slew_rate = DT_ENUM_IDX(node_id, slew_rate), \
},
#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \
{DT_FOREACH_CHILD_VARGS(DT_PHANDLE(node_id, prop), DT_FOREACH_PROP_ELEM, pinmux, \
Z_PINCTRL_STATE_PIN_INIT)}
#endif

View file

@ -0,0 +1,19 @@
/* Copyright (c) 2024 Michael Hope
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <offsets.h>
#include <zephyr/toolchain.h>
/* Exports */
GTEXT(__soc_is_irq)
GTEXT(__soc_handle_irq)
SECTION_FUNC(exception.other, __soc_is_irq)
csrr a0, mcause
srli a0, a0, 31
ret
SECTION_FUNC(exception.other, __soc_handle_irq)
ret

View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2024 Michael Hope
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/toolchain.h>
#ifndef CONFIG_VECTOR_TABLE_SIZE
#error "VECTOR_TABLE_SIZE must be defined"
#endif
/* Exports */
GTEXT(__start)
/* Imports */
GTEXT(__initialize)
SECTION_FUNC(vectors, ivt)
.option norvc
j __start
.rept CONFIG_VECTOR_TABLE_SIZE
.word _isr_wrapper
.endr
SECTION_FUNC(vectors, __start)
li a0, 3
csrw mtvec, a0
j __initialize

View file

@ -7,3 +7,6 @@ family:
- name: qingke-v2
socs:
- name: ch32v003
- name: qingke-v4c
socs:
- name: ch32v208