Skip to content

Commit acc5e09

Browse files
nzmichaelhDhiru Kholia
authored andcommitted
drivers: add the ch32v00x usart driver
This commit adds the usart driver for WCH CH32V003. Signed-off-by: Michael Hope <[email protected]> Signed-off-by: Dhiru Kholia <[email protected]>
1 parent da881c3 commit acc5e09

File tree

6 files changed

+178
-0
lines changed

6 files changed

+178
-0
lines changed

drivers/serial/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ zephyr_library_sources_ifdef(CONFIG_UART_STELLARIS uart_stellaris.c)
7373
zephyr_library_sources_ifdef(CONFIG_UART_STM32 uart_stm32.c)
7474
zephyr_library_sources_ifdef(CONFIG_UART_SY1XX uart_sy1xx.c)
7575
zephyr_library_sources_ifdef(CONFIG_UART_TELINK_B91 uart_b91.c)
76+
zephyr_library_sources_ifdef(CONFIG_UART_WCH_USART uart_wch_usart.c)
7677
zephyr_library_sources_ifdef(CONFIG_UART_XEC uart_mchp_xec.c)
7778
zephyr_library_sources_ifdef(CONFIG_UART_XEN_HVC uart_hvc_xen.c)
7879
zephyr_library_sources_ifdef(CONFIG_UART_XEN_HVC_CONSOLEIO uart_hvc_xen_consoleio.c)

drivers/serial/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,4 +221,6 @@ rsource "Kconfig.xmc4xxx"
221221

222222
source "drivers/serial/Kconfig.si32"
223223

224+
source "drivers/serial/Kconfig.wch_usart"
225+
224226
endif # SERIAL

drivers/serial/Kconfig.wch_usart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Copyright (c) 2024 Google LLC.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config UART_WCH_USART
5+
bool "CH32V00x USART driver"
6+
default y
7+
depends on DT_HAS_WCH_USART_ENABLED
8+
select SERIAL_HAS_DRIVER
9+
help
10+
This option enables the USART driver for CH32V00x SoC family.

drivers/serial/uart_wch_usart.c

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
* Copyright (c) 2024 Google LLC.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#define DT_DRV_COMPAT wch_usart
7+
8+
#include <errno.h>
9+
10+
#include <zephyr/drivers/uart.h>
11+
#include <zephyr/drivers/clock_control.h>
12+
#include <zephyr/drivers/pinctrl.h>
13+
14+
#include <ch32_uart.h>
15+
16+
struct usart_wch_config {
17+
USART_TypeDef *regs;
18+
const struct device *clock_dev;
19+
uint32_t current_speed;
20+
uint8_t parity;
21+
uint8_t clock_id;
22+
const struct pinctrl_dev_config *pin_cfg;
23+
};
24+
25+
struct usart_wch_data {
26+
};
27+
28+
static int usart_wch_init(const struct device *dev)
29+
{
30+
const struct usart_wch_config *config = dev->config;
31+
USART_TypeDef *regs = config->regs;
32+
uint32_t ctlr1 = USART_CTLR1_TE | USART_CTLR1_RE | USART_CTLR1_UE;
33+
uint32_t clock_rate;
34+
clock_control_subsys_t clock_sys = (clock_control_subsys_t *)(uintptr_t)config->clock_id;
35+
uint32_t divn;
36+
int err;
37+
38+
clock_control_on(config->clock_dev, clock_sys);
39+
40+
err = clock_control_get_rate(config->clock_dev, clock_sys, &clock_rate);
41+
if (err != 0) {
42+
return err;
43+
}
44+
divn = (clock_rate + config->current_speed / 2) / config->current_speed;
45+
46+
switch (config->parity) {
47+
case UART_CFG_PARITY_NONE:
48+
break;
49+
case UART_CFG_PARITY_ODD:
50+
ctlr1 |= USART_CTLR1_PCE | USART_CTLR1_PS;
51+
break;
52+
case UART_CFG_PARITY_EVEN:
53+
ctlr1 |= USART_CTLR1_PCE;
54+
break;
55+
default:
56+
return -EINVAL;
57+
}
58+
59+
regs->BRR = divn;
60+
regs->CTLR1 = ctlr1;
61+
regs->CTLR2 = 0;
62+
regs->CTLR3 = 0;
63+
64+
err = pinctrl_apply_state(config->pin_cfg, PINCTRL_STATE_DEFAULT);
65+
if (err != 0) {
66+
return err;
67+
}
68+
69+
return 0;
70+
}
71+
72+
static int usart_wch_poll_in(const struct device *dev, unsigned char *ch)
73+
{
74+
const struct usart_wch_config *config = dev->config;
75+
USART_TypeDef *regs = config->regs;
76+
77+
if ((regs->STATR & USART_STATR_RXNE) == 0) {
78+
return -1;
79+
}
80+
81+
*ch = regs->DATAR;
82+
return 0;
83+
}
84+
85+
static void usart_wch_poll_out(const struct device *dev, unsigned char ch)
86+
{
87+
const struct usart_wch_config *config = dev->config;
88+
USART_TypeDef *regs = config->regs;
89+
90+
while ((regs->STATR & USART_STATR_TXE) == 0) {
91+
}
92+
93+
regs->DATAR = ch;
94+
}
95+
96+
static int usart_wch_err_check(const struct device *dev)
97+
{
98+
const struct usart_wch_config *config = dev->config;
99+
USART_TypeDef *regs = config->regs;
100+
uint32_t statr = regs->STATR;
101+
enum uart_rx_stop_reason errors = 0;
102+
103+
if ((statr & USART_STATR_PE) != 0) {
104+
errors |= UART_ERROR_PARITY;
105+
}
106+
if ((statr & USART_STATR_FE) != 0) {
107+
errors |= UART_ERROR_FRAMING;
108+
}
109+
if ((statr & USART_STATR_NE) != 0) {
110+
errors |= UART_ERROR_NOISE;
111+
}
112+
if ((statr & USART_STATR_ORE) != 0) {
113+
errors |= UART_ERROR_OVERRUN;
114+
}
115+
116+
return errors;
117+
}
118+
119+
static const struct uart_driver_api usart_wch_driver_api = {
120+
.poll_in = usart_wch_poll_in,
121+
.poll_out = usart_wch_poll_out,
122+
.err_check = usart_wch_err_check,
123+
};
124+
125+
#define USART_WCH_INIT(idx) \
126+
PINCTRL_DT_INST_DEFINE(idx); \
127+
static struct usart_wch_data usart_wch_##idx##_data; \
128+
static const struct usart_wch_config usart_wch_##idx##_config = { \
129+
.regs = (USART_TypeDef *)DT_INST_REG_ADDR(idx), \
130+
.current_speed = DT_INST_PROP(idx, current_speed), \
131+
.parity = DT_INST_ENUM_IDX_OR(idx, parity, UART_CFG_PARITY_NONE), \
132+
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(idx)), \
133+
.clock_id = DT_INST_CLOCKS_CELL(idx, id), \
134+
.pin_cfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx), \
135+
}; \
136+
DEVICE_DT_INST_DEFINE(idx, &usart_wch_init, NULL, &usart_wch_##idx##_data, \
137+
&usart_wch_##idx##_config, PRE_KERNEL_1, \
138+
CONFIG_SERIAL_INIT_PRIORITY, &usart_wch_driver_api);
139+
140+
DT_INST_FOREACH_STATUS_OKAY(USART_WCH_INIT)

dts/bindings/serial/wch,usart.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
description: WCH CH32V00x UART
2+
3+
compatible: "wch,usart"
4+
5+
include: [uart-controller.yaml, pinctrl-device.yaml]
6+
7+
properties:
8+
reg:
9+
required: true

modules/hal_wch/ch32_uart.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* Copyright (c) 2024 Dhiru Kholia
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef _CH32_UART_H
8+
#define _CH32_UART_H
9+
10+
#ifdef CONFIG_SOC_CH32V003
11+
#include <ch32v003fun.h>
12+
#else
13+
#error "SoC not supported!"
14+
#endif
15+
16+
#endif

0 commit comments

Comments
 (0)