From 45d60c4d4cfbf052b27cde5bd6172c2bff82c455 Mon Sep 17 00:00:00 2001 From: Gerson Fernando Budke Date: Fri, 17 Sep 2021 17:16:30 -0300 Subject: [PATCH] drivers: serial: Add gd32 uart driver Introduce minimal serial driver support for gigadevice soc. Signed-off-by: Gerson Fernando Budke --- drivers/serial/CMakeLists.txt | 1 + drivers/serial/Kconfig | 2 + drivers/serial/Kconfig.gd32 | 14 +++ drivers/serial/usart_gd32.c | 117 +++++++++++++++++++++++++ dts/arm/gigadevice/gd32f403.dtsi | 8 ++ dts/bindings/serial/gd,gd32-usart.yaml | 17 ++++ 6 files changed, 159 insertions(+) create mode 100644 drivers/serial/Kconfig.gd32 create mode 100644 drivers/serial/usart_gd32.c create mode 100644 dts/bindings/serial/gd,gd32-usart.yaml diff --git a/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt index 3b9339022d0..5bfc1bf927a 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -44,6 +44,7 @@ zephyr_library_sources_ifdef(CONFIG_USB_CDC_ACM ${ZEPHYR_BASE}/misc/empty_file.c zephyr_library_sources_ifdef(CONFIG_UART_RCAR uart_rcar.c) zephyr_library_sources_ifdef(CONFIG_UART_XEC uart_mchp_xec.c) zephyr_library_sources_ifdef(CONFIG_UART_NEORV32 uart_neorv32.c) +zephyr_library_sources_ifdef(CONFIG_USART_GD32 usart_gd32.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE uart_handlers.c) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 8c326fea7e6..475c17f2e88 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -165,6 +165,8 @@ source "drivers/serial/Kconfig.rcar" source "drivers/serial/Kconfig.xec" +source "drivers/serial/Kconfig.gd32" + source "drivers/serial/Kconfig.test" source "drivers/serial/Kconfig.neorv32" diff --git a/drivers/serial/Kconfig.gd32 b/drivers/serial/Kconfig.gd32 new file mode 100644 index 00000000000..4cadbd139cd --- /dev/null +++ b/drivers/serial/Kconfig.gd32 @@ -0,0 +1,14 @@ +# Copyright (c) 2021 ATL Electronics +# SPDX-License-Identifier: Apache-2.0 + +# Workaround for not being able to have commas in macro arguments +DT_COMPAT_GIGADEVICE_GD32_USART := gd,gd32-usart + +config USART_GD32 + bool "GD32 serial driver" + default $(dt_compat_enabled,$(DT_COMPAT_GIGADEVICE_GD32_USART)) + depends on SOC_FAMILY_GD32 + select SERIAL_HAS_DRIVER + select USE_GD32_USART + help + This option enables the USART driver for GD32 SoC family. diff --git a/drivers/serial/usart_gd32.c b/drivers/serial/usart_gd32.c new file mode 100644 index 00000000000..012824a7c20 --- /dev/null +++ b/drivers/serial/usart_gd32.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2021, ATL Electronics + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT gd_gd32_usart + +#include + +struct gd32_usart_config { + uint32_t reg; + uint32_t rcu_periph_clock; +}; + +struct gd32_usart_data { + uint32_t baud_rate; +}; + +static int usart_gd32_init(const struct device *dev) +{ + const struct gd32_usart_config *const cfg = dev->config; + struct gd32_usart_data *const data = dev->data; + + /* NOTE: pins are configured at board_init till pinctrl be available */ + + rcu_periph_clock_enable(cfg->rcu_periph_clock); + usart_deinit(cfg->reg); + usart_baudrate_set(cfg->reg, data->baud_rate); + usart_word_length_set(cfg->reg, USART_WL_8BIT); + usart_parity_config(cfg->reg, USART_PM_NONE); + usart_stop_bit_set(cfg->reg, USART_STB_1BIT); + usart_parity_config(cfg->reg, USART_PM_NONE); + usart_receive_config(cfg->reg, USART_RECEIVE_ENABLE); + usart_transmit_config(cfg->reg, USART_TRANSMIT_ENABLE); + usart_enable(cfg->reg); + + return 0; +} + +static int usart_gd32_poll_in(const struct device *dev, unsigned char *c) +{ + const struct gd32_usart_config *const cfg = dev->config; + uint32_t status; + + status = usart_flag_get(cfg->reg, USART_FLAG_RBNE); + + if (!status) { + return -EPERM; + } + + *c = usart_data_receive(cfg->reg); + + return 0; +} + +static void usart_gd32_poll_out(const struct device *dev, unsigned char c) +{ + const struct gd32_usart_config *const cfg = dev->config; + + usart_data_transmit(cfg->reg, c); + + while (usart_flag_get(cfg->reg, USART_FLAG_TBE) == RESET) { + ; + } +} + +static int usart_gd32_err_check(const struct device *dev) +{ + const struct gd32_usart_config *const cfg = dev->config; + uint32_t status = USART_STAT0(cfg->reg); + int errors = 0; + + if (status & USART_FLAG_ORERR) { + usart_flag_clear(cfg->reg, USART_FLAG_ORERR); + + errors |= UART_ERROR_OVERRUN; + } + + if (status & USART_FLAG_PERR) { + usart_flag_clear(cfg->reg, USART_FLAG_PERR); + + errors |= UART_ERROR_PARITY; + } + + if (status & USART_FLAG_FERR) { + usart_flag_clear(cfg->reg, USART_FLAG_FERR); + + errors |= UART_ERROR_FRAMING; + } + + usart_flag_clear(cfg->reg, USART_FLAG_NERR); + + return errors; +} + +static const struct uart_driver_api usart_gd32_driver_api = { + .poll_in = usart_gd32_poll_in, + .poll_out = usart_gd32_poll_out, + .err_check = usart_gd32_err_check, +}; + +#define GD32_USART_INIT(n) \ + static struct gd32_usart_data usart##n##_gd32_data = { \ + .baud_rate = DT_INST_PROP(n, current_speed), \ + }; \ + static const struct gd32_usart_config usart##n##_gd32_config = { \ + .reg = DT_INST_REG_ADDR(n), \ + .rcu_periph_clock = DT_INST_PROP(n, rcu_periph_clock), \ + }; \ + DEVICE_DT_INST_DEFINE(n, &usart_gd32_init, \ + NULL, \ + &usart##n##_gd32_data, \ + &usart##n##_gd32_config, PRE_KERNEL_1, \ + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ + &usart_gd32_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(GD32_USART_INIT) diff --git a/dts/arm/gigadevice/gd32f403.dtsi b/dts/arm/gigadevice/gd32f403.dtsi index d03e9f76511..c6b81fea778 100644 --- a/dts/arm/gigadevice/gd32f403.dtsi +++ b/dts/arm/gigadevice/gd32f403.dtsi @@ -45,6 +45,14 @@ label = "FLASH_0"; }; }; + + usart0: usart@40013800 { + compatible = "gd,gd32-usart"; + reg = <0x40013800 0x400>; + rcu-periph-clock = <0x60e>; + status = "disabled"; + label = "usart_0"; + }; }; }; diff --git a/dts/bindings/serial/gd,gd32-usart.yaml b/dts/bindings/serial/gd,gd32-usart.yaml new file mode 100644 index 00000000000..b12eca41327 --- /dev/null +++ b/dts/bindings/serial/gd,gd32-usart.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2021, ATL Electronics +# SPDX-License-Identifier: Apache-2.0 + +description: GigaDevice USART + +compatible: "gd,gd32-usart" + +include: uart-controller.yaml + +properties: + reg: + required: true + + rcu-periph-clock: + type: int + description: Reset Control Unit Peripheral Clock ID + required: true