From 1318f1543ca68f862d9baa459d1d3a5011c8534e Mon Sep 17 00:00:00 2001 From: Martin Hoff Date: Fri, 17 Jan 2025 10:42:22 +0100 Subject: [PATCH] driver: serial: split silabs series 2 and series 0/1 boards usart driver Split the USART driver into separate implementations for Silabs Series 2 and Series 0/1 boards. This change improves maintainability (especially with the support of pin-ctrl and clock-ctrl on series 2 boards). Signed-off-by: Martin Hoff --- drivers/serial/CMakeLists.txt | 1 + drivers/serial/Kconfig | 1 + drivers/serial/Kconfig.gecko | 4 +- drivers/serial/Kconfig.silabs_usart | 15 + drivers/serial/uart_gecko.c | 45 +- drivers/serial/uart_silabs_usart.c | 528 +++++++++++++++++++++ dts/bindings/serial/silabs,usart-uart.yaml | 27 ++ 7 files changed, 574 insertions(+), 47 deletions(-) create mode 100644 drivers/serial/Kconfig.silabs_usart create mode 100644 drivers/serial/uart_silabs_usart.c create mode 100644 dts/bindings/serial/silabs,usart-uart.yaml diff --git a/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt index ad64368ea9b..8aeea35684b 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -73,6 +73,7 @@ zephyr_library_sources_ifdef(CONFIG_UART_SEDI uart_sedi.c) zephyr_library_sources_ifdef(CONFIG_UART_SI32_USART uart_si32_usart.c) zephyr_library_sources_ifdef(CONFIG_UART_SIFIVE uart_sifive.c) zephyr_library_sources_ifdef(CONFIG_UART_SILABS_EUSART uart_silabs_eusart.c) +zephyr_library_sources_ifdef(CONFIG_UART_SILABS_USART uart_silabs_usart.c) zephyr_library_sources_ifdef(CONFIG_UART_SMARTBOND uart_smartbond.c) zephyr_library_sources_ifdef(CONFIG_UART_STELLARIS uart_stellaris.c) zephyr_library_sources_ifdef(CONFIG_UART_STM32 uart_stm32.c) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 3f2d534bd62..2b1ff32c566 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -215,6 +215,7 @@ rsource "Kconfig.sam0" rsource "Kconfig.sedi" rsource "Kconfig.sifive" rsource "Kconfig.silabs_eusart" +rsource "Kconfig.silabs_usart" rsource "Kconfig.smartbond" rsource "Kconfig.stellaris" rsource "Kconfig.stm32" diff --git a/drivers/serial/Kconfig.gecko b/drivers/serial/Kconfig.gecko index 6160845a363..8bc311cd523 100644 --- a/drivers/serial/Kconfig.gecko +++ b/drivers/serial/Kconfig.gecko @@ -10,8 +10,6 @@ config UART_GECKO select SERIAL_HAS_DRIVER select SERIAL_SUPPORT_INTERRUPT select SOC_GECKO_USART - select PINCTRL if (SOC_FAMILY_SILABS_S1 || SOC_FAMILY_SILABS_S2) - select CLOCK_CONTROL if SOC_FAMILY_SILABS_S2 - select PM_DEVICE if PM && SOC_FAMILY_SILABS_S2 + select PINCTRL if SOC_FAMILY_SILABS_S1 help Enable the Gecko uart driver. diff --git a/drivers/serial/Kconfig.silabs_usart b/drivers/serial/Kconfig.silabs_usart new file mode 100644 index 00000000000..53c4770a606 --- /dev/null +++ b/drivers/serial/Kconfig.silabs_usart @@ -0,0 +1,15 @@ +# Copyright (c) 2025, Silicon Laboratories Inc. +# SPDX-License-Identifier: Apache-2.0 + +config UART_SILABS_USART + bool "Silabs USART UART driver" + default y + depends on DT_HAS_SILABS_USART_UART_ENABLED + select SERIAL_HAS_DRIVER + select SERIAL_SUPPORT_INTERRUPT + select SOC_GECKO_USART + select PINCTRL + select CLOCK_CONTROL + select PM_DEVICE if PM + help + Enable the Silicon Labs usart driver. diff --git a/drivers/serial/uart_gecko.c b/drivers/serial/uart_gecko.c index a801ca5c5da..21b2ab21667 100644 --- a/drivers/serial/uart_gecko.c +++ b/drivers/serial/uart_gecko.c @@ -19,13 +19,7 @@ #include #endif /* CONFIG_PINCTRL */ -#ifdef CONFIG_CLOCK_CONTROL -#include -#include -#define GET_GECKO_USART_CLOCK(idx) \ - .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(idx)), \ - .clock_cfg = SILABS_DT_INST_CLOCK_CFG(idx), -#elif DT_NODE_HAS_PROP(id, peripheral_id) +#if DT_NODE_HAS_PROP(id, peripheral_id) #define USART_PREFIX cmuClock_USART #define UART_PREFIX cmuClock_UART #define CLOCK_USART(id) _CONCAT(USART_PREFIX, id) @@ -130,12 +124,7 @@ struct uart_gecko_config { const struct pinctrl_dev_config *pcfg; #endif /* CONFIG_PINCTRL */ USART_TypeDef *base; -#ifdef CONFIG_CLOCK_CONTROL - const struct device *clock_dev; - const struct silabs_clock_control_cmu_config clock_cfg; -#else CMU_Clock_TypeDef clock; -#endif #ifdef CONFIG_UART_INTERRUPT_DRIVEN void (*irq_config_func)(const struct device *dev); #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ @@ -650,14 +639,7 @@ static int uart_gecko_init(const struct device *dev) /* The peripheral and gpio clock are already enabled from soc and gpio driver */ /* Enable USART clock */ -#ifdef CONFIG_CLOCK_CONTROL - err = clock_control_on(config->clock_dev, (clock_control_subsys_t)&config->clock_cfg); - if (err < 0) { - return err; - } -#else CMU_ClockEnable(config->clock, true); -#endif /* Init USART */ usartInit.baudrate = uart_cfg->baudrate; @@ -687,31 +669,6 @@ static int uart_gecko_init(const struct device *dev) return 0; } -#ifdef CONFIG_PM_DEVICE -static int uart_gecko_pm_action(const struct device *dev, enum pm_device_action action) -{ - __maybe_unused const struct uart_gecko_config *config = dev->config; - - switch (action) { - case PM_DEVICE_ACTION_SUSPEND: -#ifdef USART_STATUS_TXIDLE - /* Wait for TX FIFO to flush before suspending */ - while (!(USART_StatusGet(config->base) & USART_STATUS_TXIDLE)) { - } -#endif - break; - - case PM_DEVICE_ACTION_RESUME: - break; - - default: - return -ENOTSUP; - } - - return 0; -} -#endif - static DEVICE_API(uart, uart_gecko_driver_api) = { .poll_in = uart_gecko_poll_in, .poll_out = uart_gecko_poll_out, diff --git a/drivers/serial/uart_silabs_usart.c b/drivers/serial/uart_silabs_usart.c new file mode 100644 index 00000000000..f77fb7470c0 --- /dev/null +++ b/drivers/serial/uart_silabs_usart.c @@ -0,0 +1,528 @@ +/* + * Copyright (c) 2025 Silicon Laboratories Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DT_DRV_COMPAT silabs_usart_uart + +/** + * @brief Config struct for UART + */ + +struct uart_silabs_config { + const struct pinctrl_dev_config *pcfg; + const struct device *clock_dev; + const struct silabs_clock_control_cmu_config clock_cfg; + USART_TypeDef *base; +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + void (*irq_config_func)(const struct device *dev); +#endif +}; + +struct uart_silabs_data { + struct uart_config *uart_cfg; +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + uart_irq_callback_user_data_t callback; + void *cb_data; +#endif +}; + +static int uart_silabs_poll_in(const struct device *dev, unsigned char *c) +{ + const struct uart_silabs_config *config = dev->config; + uint32_t flags = USART_StatusGet(config->base); + + if (flags & USART_STATUS_RXDATAV) { + *c = USART_Rx(config->base); + return 0; + } + + return -1; +} + +static void uart_silabs_poll_out(const struct device *dev, unsigned char c) +{ + const struct uart_silabs_config *config = dev->config; + + USART_Tx(config->base, c); +} + +static int uart_silabs_err_check(const struct device *dev) +{ + const struct uart_silabs_config *config = dev->config; + uint32_t flags = USART_IntGet(config->base); + int err = 0; + + if (flags & USART_IF_RXOF) { + err |= UART_ERROR_OVERRUN; + } + + if (flags & USART_IF_PERR) { + err |= UART_ERROR_PARITY; + } + + if (flags & USART_IF_FERR) { + err |= UART_ERROR_FRAMING; + } + + USART_IntClear(config->base, USART_IF_RXOF | USART_IF_PERR | USART_IF_FERR); + + return err; +} + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +static int uart_silabs_fifo_fill(const struct device *dev, const uint8_t *tx_data, int len) +{ + const struct uart_silabs_config *config = dev->config; + int i = 0; + + while ((i < len) && (config->base->STATUS & USART_STATUS_TXBL)) { + config->base->TXDATA = tx_data[i++]; + } + + return i; +} + +static int uart_silabs_fifo_read(const struct device *dev, uint8_t *rx_data, const int len) +{ + const struct uart_silabs_config *config = dev->config; + int i = 0; + + while ((i < len) && (config->base->STATUS & USART_STATUS_RXDATAV)) { + rx_data[i++] = (uint8_t)config->base->RXDATA; + } + + return i; +} + +static void uart_silabs_irq_tx_enable(const struct device *dev) +{ + const struct uart_silabs_config *config = dev->config; + + USART_IntEnable(config->base, USART_IEN_TXBL | USART_IEN_TXC); +} + +static void uart_silabs_irq_tx_disable(const struct device *dev) +{ + const struct uart_silabs_config *config = dev->config; + + USART_IntDisable(config->base, USART_IEN_TXBL | USART_IEN_TXC); +} + +static int uart_silabs_irq_tx_complete(const struct device *dev) +{ + const struct uart_silabs_config *config = dev->config; + uint32_t flags = USART_IntGet(config->base); + + USART_IntClear(config->base, USART_IF_TXC); + + return !!(flags & USART_IF_TXC); +} + +static int uart_silabs_irq_tx_ready(const struct device *dev) +{ + const struct uart_silabs_config *config = dev->config; + uint32_t flags = USART_IntGetEnabled(config->base); + + return !!(flags & USART_IF_TXBL); +} + +static void uart_silabs_irq_rx_enable(const struct device *dev) +{ + const struct uart_silabs_config *config = dev->config; + + USART_IntEnable(config->base, USART_IEN_RXDATAV); +} + +static void uart_silabs_irq_rx_disable(const struct device *dev) +{ + const struct uart_silabs_config *config = dev->config; + + USART_IntDisable(config->base, USART_IEN_RXDATAV); +} + +static int uart_silabs_irq_rx_full(const struct device *dev) +{ + const struct uart_silabs_config *config = dev->config; + uint32_t flags = USART_IntGet(config->base); + + return !!(flags & USART_IF_RXDATAV); +} + +static int uart_silabs_irq_rx_ready(const struct device *dev) +{ + const struct uart_silabs_config *config = dev->config; + + return (config->base->IEN & USART_IEN_RXDATAV) && uart_silabs_irq_rx_full(dev); +} + +static void uart_silabs_irq_err_enable(const struct device *dev) +{ + const struct uart_silabs_config *config = dev->config; + + USART_IntEnable(config->base, USART_IF_RXOF | USART_IF_PERR | USART_IF_FERR); +} + +static void uart_silabs_irq_err_disable(const struct device *dev) +{ + const struct uart_silabs_config *config = dev->config; + + USART_IntDisable(config->base, USART_IF_RXOF | USART_IF_PERR | USART_IF_FERR); +} + +static int uart_silabs_irq_is_pending(const struct device *dev) +{ + return uart_silabs_irq_tx_ready(dev) || uart_silabs_irq_rx_ready(dev); +} + +static int uart_silabs_irq_update(const struct device *dev) +{ + return 1; +} + +static void uart_silabs_irq_callback_set(const struct device *dev, uart_irq_callback_user_data_t cb, + void *cb_data) +{ + struct uart_silabs_data *data = dev->data; + + data->callback = cb; + data->cb_data = cb_data; +} + +static void uart_silabs_isr(const struct device *dev) +{ + struct uart_silabs_data *data = dev->data; + + if (data->callback) { + data->callback(dev, data->cb_data); + } +} +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + +static inline USART_Parity_TypeDef uart_silabs_cfg2ll_parity(enum uart_config_parity parity) +{ + switch (parity) { + case UART_CFG_PARITY_ODD: + return usartOddParity; + case UART_CFG_PARITY_EVEN: + return usartEvenParity; + case UART_CFG_PARITY_NONE: + default: + return usartNoParity; + } +} + +static inline enum uart_config_parity uart_silabs_ll2cfg_parity(USART_Parity_TypeDef parity) +{ + switch (parity) { + case usartOddParity: + return UART_CFG_PARITY_ODD; + case usartEvenParity: + return UART_CFG_PARITY_EVEN; + case usartNoParity: + default: + return UART_CFG_PARITY_NONE; + } +} + +static inline USART_Stopbits_TypeDef uart_silabs_cfg2ll_stopbits(enum uart_config_stop_bits sb) +{ + switch (sb) { + case UART_CFG_STOP_BITS_0_5: + return usartStopbits0p5; + case UART_CFG_STOP_BITS_1: + return usartStopbits1; + case UART_CFG_STOP_BITS_2: + return usartStopbits2; + case UART_CFG_STOP_BITS_1_5: + return usartStopbits1p5; + default: + return usartStopbits1; + } +} + +static inline enum uart_config_stop_bits uart_silabs_ll2cfg_stopbits(USART_Stopbits_TypeDef sb) +{ + switch (sb) { + case usartStopbits0p5: + return UART_CFG_STOP_BITS_0_5; + case usartStopbits1: + return UART_CFG_STOP_BITS_1; + case usartStopbits1p5: + return UART_CFG_STOP_BITS_1_5; + case usartStopbits2: + return UART_CFG_STOP_BITS_2; + default: + return UART_CFG_STOP_BITS_1; + } +} + +static inline USART_Databits_TypeDef uart_silabs_cfg2ll_databits(enum uart_config_data_bits db, + enum uart_config_parity p) +{ + switch (db) { + case UART_CFG_DATA_BITS_7: + if (p == UART_CFG_PARITY_NONE) { + return usartDatabits7; + } else { + return usartDatabits8; + } + case UART_CFG_DATA_BITS_9: + return usartDatabits9; + case UART_CFG_DATA_BITS_8: + default: + if (p == UART_CFG_PARITY_NONE) { + return usartDatabits8; + } else { + return usartDatabits9; + } + return usartDatabits8; + } +} + +static inline enum uart_config_data_bits uart_silabs_ll2cfg_databits(USART_Databits_TypeDef db, + USART_Parity_TypeDef p) +{ + switch (db) { + case usartDatabits7: + if (p == usartNoParity) { + return UART_CFG_DATA_BITS_7; + } else { + return UART_CFG_DATA_BITS_6; + } + case usartDatabits9: + if (p == usartNoParity) { + return UART_CFG_DATA_BITS_9; + } else { + return UART_CFG_DATA_BITS_8; + } + case usartDatabits8: + default: + if (p == usartNoParity) { + return UART_CFG_DATA_BITS_8; + } else { + return UART_CFG_DATA_BITS_7; + } + } +} + +static inline USART_HwFlowControl_TypeDef uart_silabs_cfg2ll_hwctrl( + enum uart_config_flow_control fc) +{ + if (fc == UART_CFG_FLOW_CTRL_RTS_CTS) { + return usartHwFlowControlCtsAndRts; + } + + return usartHwFlowControlNone; +} + +static inline enum uart_config_flow_control uart_silabs_ll2cfg_hwctrl( + USART_HwFlowControl_TypeDef fc) +{ + if (fc == usartHwFlowControlCtsAndRts) { + return UART_CFG_FLOW_CTRL_RTS_CTS; + } + + return UART_CFG_FLOW_CTRL_NONE; +} + +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE +static int uart_silabs_configure(const struct device *dev, + const struct uart_config *cfg) +{ + const struct uart_silabs_config *config = dev->config; + USART_TypeDef *base = config->base; + struct uart_silabs_data *data = dev->data; + struct uart_config *uart_cfg = data->uart_cfg; + USART_InitAsync_TypeDef usartInit = USART_INITASYNC_DEFAULT; + + if ((cfg->parity == UART_CFG_PARITY_MARK) || + (cfg->parity == UART_CFG_PARITY_SPACE)) { + return -ENOSYS; + } + + if (cfg->flow_ctrl == UART_CFG_FLOW_CTRL_DTR_DSR || + cfg->flow_ctrl == UART_CFG_FLOW_CTRL_RS485) { + return -ENOSYS; + } + + *uart_cfg = *cfg; + usartInit.baudrate = uart_cfg->baudrate; + usartInit.parity = uart_silabs_cfg2ll_parity(uart_cfg->parity); + usartInit.stopbits = uart_silabs_cfg2ll_stopbits(uart_cfg->stop_bits); + usartInit.databits = uart_silabs_cfg2ll_databits(uart_cfg->data_bits, + uart_cfg->parity); + usartInit.hwFlowControl = uart_silabs_cfg2ll_hwctrl(uart_cfg->flow_ctrl); + + USART_Enable(base, usartDisable); + + USART_InitAsync(base, &usartInit); + + USART_Enable(base, usartEnable); + + return 0; +}; + +static int uart_silabs_config_get(const struct device *dev, + struct uart_config *cfg) +{ + struct uart_silabs_data *data = dev->data; + struct uart_config *uart_cfg = data->uart_cfg; + + cfg->baudrate = uart_cfg->baudrate; + cfg->parity = uart_cfg->parity; + cfg->stop_bits = uart_cfg->stop_bits; + cfg->data_bits = uart_cfg->data_bits; + cfg->flow_ctrl = uart_cfg->flow_ctrl; + + return 0; +} +#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ + +static int uart_silabs_init(const struct device *dev) +{ + int err; + const struct uart_silabs_config *config = dev->config; + const struct uart_silabs_data *data = dev->data; + const struct uart_config *uart_cfg = data->uart_cfg; + USART_InitAsync_TypeDef usartInit = USART_INITASYNC_DEFAULT; + + /* The peripheral and gpio clock are already enabled from soc and gpio driver */ + /* Enable USART clock */ + err = clock_control_on(config->clock_dev, (clock_control_subsys_t)&config->clock_cfg); + if (err < 0) { + return err; + } + + err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (err < 0) { + return err; + } + + usartInit.baudrate = uart_cfg->baudrate; + usartInit.parity = uart_silabs_cfg2ll_parity(uart_cfg->parity); + usartInit.stopbits = uart_silabs_cfg2ll_stopbits(uart_cfg->stop_bits); + usartInit.databits = uart_silabs_cfg2ll_databits(uart_cfg->data_bits, uart_cfg->parity); + usartInit.hwFlowControl = + uart_cfg->flow_ctrl ? usartHwFlowControlCtsAndRts : usartHwFlowControlNone; + + USART_InitAsync(config->base, &usartInit); + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + config->irq_config_func(dev); +#endif + + return 0; +} + +#ifdef CONFIG_PM_DEVICE +static int uart_silabs_pm_action(const struct device *dev, enum pm_device_action action) +{ + __maybe_unused const struct uart_silabs_config *config = dev->config; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + /* Wait for TX FIFO to flush before suspending */ + while (!(USART_StatusGet(config->base) & USART_STATUS_TXIDLE)) { + } + break; + + case PM_DEVICE_ACTION_RESUME: + break; + + default: + return -ENOTSUP; + } + + return 0; +} +#endif + +static DEVICE_API(uart, uart_silabs_driver_api) = { + .poll_in = uart_silabs_poll_in, + .poll_out = uart_silabs_poll_out, + .err_check = uart_silabs_err_check, +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE + .configure = uart_silabs_configure, + .config_get = uart_silabs_config_get, +#endif +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + .fifo_fill = uart_silabs_fifo_fill, + .fifo_read = uart_silabs_fifo_read, + .irq_tx_enable = uart_silabs_irq_tx_enable, + .irq_tx_disable = uart_silabs_irq_tx_disable, + .irq_tx_complete = uart_silabs_irq_tx_complete, + .irq_tx_ready = uart_silabs_irq_tx_ready, + .irq_rx_enable = uart_silabs_irq_rx_enable, + .irq_rx_disable = uart_silabs_irq_rx_disable, + .irq_rx_ready = uart_silabs_irq_rx_ready, + .irq_err_enable = uart_silabs_irq_err_enable, + .irq_err_disable = uart_silabs_irq_err_disable, + .irq_is_pending = uart_silabs_irq_is_pending, + .irq_update = uart_silabs_irq_update, + .irq_callback_set = uart_silabs_irq_callback_set, +#endif +}; + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +#define SILABS_USART_IRQ_HANDLER_FUNC(idx) .irq_config_func = usart_silabs_config_func_##idx, +#define SILABS_USART_IRQ_HANDLER(idx) \ + static void usart_silabs_config_func_##idx(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(idx, rx, irq), \ + DT_INST_IRQ_BY_NAME(idx, rx, priority), uart_silabs_isr, \ + DEVICE_DT_INST_GET(idx), 0); \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(idx, tx, irq), \ + DT_INST_IRQ_BY_NAME(idx, tx, priority), uart_silabs_isr, \ + DEVICE_DT_INST_GET(idx), 0); \ + \ + irq_enable(DT_INST_IRQ_BY_NAME(idx, rx, irq)); \ + irq_enable(DT_INST_IRQ_BY_NAME(idx, tx, irq)); \ + } +#else +#define SILABS_USART_IRQ_HANDLER_FUNC(idx) +#define SILABS_USART_IRQ_HANDLER(idx) +#endif + +#define SILABS_USART_INIT(idx) \ + SILABS_USART_IRQ_HANDLER(idx); \ + PINCTRL_DT_INST_DEFINE(idx); \ + \ + static struct uart_config uart_cfg_##idx = { \ + .baudrate = DT_INST_PROP(idx, current_speed), \ + .parity = DT_INST_ENUM_IDX(idx, parity), \ + .stop_bits = DT_INST_ENUM_IDX(idx, stop_bits), \ + .data_bits = DT_INST_ENUM_IDX(idx, data_bits), \ + .flow_ctrl = DT_INST_PROP(idx, hw_flow_control) ? UART_CFG_FLOW_CTRL_RTS_CTS \ + : UART_CFG_FLOW_CTRL_NONE, \ + }; \ + \ + static const struct uart_silabs_config uart_silabs_cfg_##idx = { \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx), \ + .base = (USART_TypeDef *)DT_INST_REG_ADDR(idx), \ + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(idx)), \ + .clock_cfg = SILABS_DT_INST_CLOCK_CFG(idx), \ + SILABS_USART_IRQ_HANDLER_FUNC(idx) \ + }; \ + \ + static struct uart_silabs_data uart_silabs_data_##idx = { \ + .uart_cfg = &uart_cfg_##idx, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(idx, uart_silabs_init, PM_DEVICE_DT_INST_GET(idx), \ + &uart_silabs_data_##idx, &uart_silabs_cfg_##idx, PRE_KERNEL_1, \ + CONFIG_SERIAL_INIT_PRIORITY, &uart_silabs_driver_api); \ + \ + PM_DEVICE_DT_INST_DEFINE(idx, uart_silabs_pm_action); + +DT_INST_FOREACH_STATUS_OKAY(SILABS_USART_INIT) diff --git a/dts/bindings/serial/silabs,usart-uart.yaml b/dts/bindings/serial/silabs,usart-uart.yaml new file mode 100644 index 00000000000..9d01c3b05d5 --- /dev/null +++ b/dts/bindings/serial/silabs,usart-uart.yaml @@ -0,0 +1,27 @@ +description: Silabs USART UART + +compatible: "silabs,usart-uart" + +include: [uart-controller.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + current-speed: + description: | + Initial baud rate setting for UART. Defaults to standard baudrate of 115200 if not specified. + default: 115200 + + stop-bits: + description: | + Sets the number of stop bits. Defaults to standard of 1 if not specified. + default: "1" + + data-bits: + description: | + Sets the number of data bits. Defaults to standard of 8 if not specified. + default: 8