drivers: add the ch32v00x usart driver
This commit adds the usart driver for WCH CH32V003. Signed-off-by: Michael Hope <michaelh@juju.nz> Signed-off-by: Dhiru Kholia <dhiru.kholia@gmail.com>
This commit is contained in:
parent
7e810abc05
commit
01a9061d67
5 changed files with 163 additions and 0 deletions
|
|
@ -73,6 +73,7 @@ zephyr_library_sources_ifdef(CONFIG_UART_STELLARIS uart_stellaris.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_UART_STM32 uart_stm32.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_UART_SY1XX uart_sy1xx.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_UART_TELINK_B91 uart_b91.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_UART_WCH_USART uart_wch_usart.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_UART_XEC uart_mchp_xec.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_UART_XEN_HVC uart_hvc_xen.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_UART_XEN_HVC_CONSOLEIO uart_hvc_xen_consoleio.c)
|
||||
|
|
|
|||
|
|
@ -221,4 +221,6 @@ rsource "Kconfig.xmc4xxx"
|
|||
|
||||
source "drivers/serial/Kconfig.si32"
|
||||
|
||||
source "drivers/serial/Kconfig.wch_usart"
|
||||
|
||||
endif # SERIAL
|
||||
|
|
|
|||
11
drivers/serial/Kconfig.wch_usart
Normal file
11
drivers/serial/Kconfig.wch_usart
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Copyright (c) 2024 Google LLC.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config UART_WCH_USART
|
||||
bool "CH32V00x USART driver"
|
||||
default y
|
||||
depends on DT_HAS_WCH_USART_ENABLED
|
||||
select SERIAL_HAS_DRIVER
|
||||
select PINCTRL
|
||||
help
|
||||
This option enables the USART driver for CH32V00x SoC family.
|
||||
140
drivers/serial/uart_wch_usart.c
Normal file
140
drivers/serial/uart_wch_usart.c
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Google LLC.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT wch_usart
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <zephyr/drivers/uart.h>
|
||||
#include <zephyr/drivers/clock_control.h>
|
||||
#include <zephyr/drivers/pinctrl.h>
|
||||
|
||||
#include <ch32fun.h>
|
||||
|
||||
struct usart_wch_config {
|
||||
USART_TypeDef *regs;
|
||||
const struct device *clock_dev;
|
||||
uint32_t current_speed;
|
||||
uint8_t parity;
|
||||
uint8_t clock_id;
|
||||
const struct pinctrl_dev_config *pin_cfg;
|
||||
};
|
||||
|
||||
struct usart_wch_data {
|
||||
};
|
||||
|
||||
static int usart_wch_init(const struct device *dev)
|
||||
{
|
||||
const struct usart_wch_config *config = dev->config;
|
||||
USART_TypeDef *regs = config->regs;
|
||||
uint32_t ctlr1 = USART_CTLR1_TE | USART_CTLR1_RE | USART_CTLR1_UE;
|
||||
uint32_t clock_rate;
|
||||
clock_control_subsys_t clock_sys = (clock_control_subsys_t *)(uintptr_t)config->clock_id;
|
||||
uint32_t divn;
|
||||
int err;
|
||||
|
||||
clock_control_on(config->clock_dev, clock_sys);
|
||||
|
||||
err = clock_control_get_rate(config->clock_dev, clock_sys, &clock_rate);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
divn = (clock_rate + config->current_speed / 2) / config->current_speed;
|
||||
|
||||
switch (config->parity) {
|
||||
case UART_CFG_PARITY_NONE:
|
||||
break;
|
||||
case UART_CFG_PARITY_ODD:
|
||||
ctlr1 |= USART_CTLR1_PCE | USART_CTLR1_PS;
|
||||
break;
|
||||
case UART_CFG_PARITY_EVEN:
|
||||
ctlr1 |= USART_CTLR1_PCE;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
regs->BRR = divn;
|
||||
regs->CTLR1 = ctlr1;
|
||||
regs->CTLR2 = 0;
|
||||
regs->CTLR3 = 0;
|
||||
|
||||
err = pinctrl_apply_state(config->pin_cfg, PINCTRL_STATE_DEFAULT);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usart_wch_poll_in(const struct device *dev, unsigned char *ch)
|
||||
{
|
||||
const struct usart_wch_config *config = dev->config;
|
||||
USART_TypeDef *regs = config->regs;
|
||||
|
||||
if ((regs->STATR & USART_STATR_RXNE) == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*ch = regs->DATAR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usart_wch_poll_out(const struct device *dev, unsigned char ch)
|
||||
{
|
||||
const struct usart_wch_config *config = dev->config;
|
||||
USART_TypeDef *regs = config->regs;
|
||||
|
||||
while ((regs->STATR & USART_STATR_TXE) == 0) {
|
||||
}
|
||||
|
||||
regs->DATAR = ch;
|
||||
}
|
||||
|
||||
static int usart_wch_err_check(const struct device *dev)
|
||||
{
|
||||
const struct usart_wch_config *config = dev->config;
|
||||
USART_TypeDef *regs = config->regs;
|
||||
uint32_t statr = regs->STATR;
|
||||
enum uart_rx_stop_reason errors = 0;
|
||||
|
||||
if ((statr & USART_STATR_PE) != 0) {
|
||||
errors |= UART_ERROR_PARITY;
|
||||
}
|
||||
if ((statr & USART_STATR_FE) != 0) {
|
||||
errors |= UART_ERROR_FRAMING;
|
||||
}
|
||||
if ((statr & USART_STATR_NE) != 0) {
|
||||
errors |= UART_ERROR_NOISE;
|
||||
}
|
||||
if ((statr & USART_STATR_ORE) != 0) {
|
||||
errors |= UART_ERROR_OVERRUN;
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
static const struct uart_driver_api usart_wch_driver_api = {
|
||||
.poll_in = usart_wch_poll_in,
|
||||
.poll_out = usart_wch_poll_out,
|
||||
.err_check = usart_wch_err_check,
|
||||
};
|
||||
|
||||
#define USART_WCH_INIT(idx) \
|
||||
PINCTRL_DT_INST_DEFINE(idx); \
|
||||
static struct usart_wch_data usart_wch_##idx##_data; \
|
||||
static const struct usart_wch_config usart_wch_##idx##_config = { \
|
||||
.regs = (USART_TypeDef *)DT_INST_REG_ADDR(idx), \
|
||||
.current_speed = DT_INST_PROP(idx, current_speed), \
|
||||
.parity = DT_INST_ENUM_IDX_OR(idx, parity, UART_CFG_PARITY_NONE), \
|
||||
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(idx)), \
|
||||
.clock_id = DT_INST_CLOCKS_CELL(idx, id), \
|
||||
.pin_cfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx), \
|
||||
}; \
|
||||
DEVICE_DT_INST_DEFINE(idx, &usart_wch_init, NULL, &usart_wch_##idx##_data, \
|
||||
&usart_wch_##idx##_config, PRE_KERNEL_1, \
|
||||
CONFIG_SERIAL_INIT_PRIORITY, &usart_wch_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(USART_WCH_INIT)
|
||||
9
dts/bindings/serial/wch,usart.yaml
Normal file
9
dts/bindings/serial/wch,usart.yaml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
description: WCH CH32V00x UART
|
||||
|
||||
compatible: "wch,usart"
|
||||
|
||||
include: [uart-controller.yaml, pinctrl-device.yaml]
|
||||
|
||||
properties:
|
||||
reg:
|
||||
required: true
|
||||
Loading…
Reference in a new issue