drivers: serial: uart_xmc4xxx: Enable run time configuration

This patch enables run time configuration for the XMC4xxx serial ports.

Signed-off-by: Marcelo Roberto Jimenez <marcelo.jimenez@gmail.com>
This commit is contained in:
Marcelo Roberto Jimenez
2025-12-08 23:16:41 -03:00
committed by Maureen Helm
parent 7744d20840
commit 62a49211b1
5 changed files with 213 additions and 3 deletions

View File

@@ -111,6 +111,8 @@
fifo-start-offset = <0>;
fifo-tx-size = <16>;
fifo-rx-size = <16>;
data-bits = <8>;
stop-bits = "1";
status = "okay";
};

View File

@@ -102,6 +102,8 @@
fifo-start-offset = <0>;
fifo-tx-size = <16>;
fifo-rx-size = <16>;
data-bits = <8>;
stop-bits = "1";
status = "okay";
};
@@ -116,6 +118,8 @@
fifo-start-offset = <0>;
fifo-tx-size = <0>;
fifo-rx-size = <0>;
data-bits = <8>;
stop-bits = "1";
status = "okay";
};

View File

@@ -53,6 +53,7 @@ struct uart_dma_stream {
struct uart_xmc4xxx_data {
XMC_UART_CH_CONFIG_t config;
struct uart_config *uart_cfg;
#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
uart_irq_callback_user_data_t user_cb;
void *user_data;
@@ -102,6 +103,162 @@ static void uart_xmc4xxx_poll_out(const struct device *dev, unsigned char c)
XMC_UART_CH_Transmit(config->uart, c);
}
static int convert_config_xmc4xxx_to_zephyr(struct uart_config *zephyr,
const XMC_UART_CH_CONFIG_t *x)
{
struct uart_config z;
z.baudrate = x->baudrate;
switch (x->parity_mode) {
case XMC_USIC_CH_PARITY_MODE_NONE:
z.parity = UART_CFG_PARITY_NONE;
break;
case XMC_USIC_CH_PARITY_MODE_ODD:
z.parity = UART_CFG_PARITY_ODD;
break;
case XMC_USIC_CH_PARITY_MODE_EVEN:
z.parity = UART_CFG_PARITY_EVEN;
break;
/* XMC4xxx has no support for MARK and SPACE parity */
/*
* case XMC_USIC_CH_PARITY_MODE_MARK:
* z.parity = UART_CFG_PARITY_MARK;
* break;
* case XMC_USIC_CH_PARITY_MODE_SPACE:
* z.parity = UART_CFG_PARITY_SPACE;
* break;
*/
default:
return -EINVAL;
}
switch (x->stop_bits) {
case 1:
z.stop_bits = UART_CFG_STOP_BITS_1;
break;
case 2:
z.stop_bits = UART_CFG_STOP_BITS_2;
break;
default:
return -EINVAL;
}
switch (x->data_bits) {
case 5:
z.data_bits = UART_CFG_DATA_BITS_5;
break;
case 6:
z.data_bits = UART_CFG_DATA_BITS_6;
break;
case 7:
z.data_bits = UART_CFG_DATA_BITS_7;
break;
case 8:
z.data_bits = UART_CFG_DATA_BITS_8;
break;
case 9:
z.data_bits = UART_CFG_DATA_BITS_9;
break;
default:
return -EINVAL;
}
z.flow_ctrl = UART_CFG_FLOW_CTRL_NONE;
*zephyr = z;
return 0;
}
static int convert_config_zephyr_to_xmc4xxx(XMC_UART_CH_CONFIG_t *xmc, const struct uart_config *z)
{
XMC_UART_CH_CONFIG_t x;
x.baudrate = z->baudrate;
/* When zero -> will always use "fractional divider mode". */
x.normal_divider_mode = 0;
switch (z->data_bits) {
case UART_CFG_DATA_BITS_5:
x.data_bits = 5;
break;
case UART_CFG_DATA_BITS_6:
x.data_bits = 6;
break;
case UART_CFG_DATA_BITS_7:
x.data_bits = 7;
break;
case UART_CFG_DATA_BITS_8:
x.data_bits = 8;
break;
case UART_CFG_DATA_BITS_9:
x.data_bits = 9;
break;
default:
return -EINVAL;
}
/* When zero -> driver takes care. */
x.frame_length = 0;
switch (z->stop_bits) {
case UART_CFG_STOP_BITS_0_5:
x.stop_bits = 1;
return -EINVAL;
case UART_CFG_STOP_BITS_1:
x.stop_bits = 1;
break;
case UART_CFG_STOP_BITS_1_5:
x.stop_bits = 1;
return -EINVAL;
case UART_CFG_STOP_BITS_2:
x.stop_bits = 2;
break;
default:
x.stop_bits = 1;
return -EINVAL;
}
/* When zero -> driver actual oversampling == 16 */
x.oversampling = 0;
switch (z->parity) {
case UART_CFG_PARITY_NONE:
x.parity_mode = XMC_USIC_CH_PARITY_MODE_NONE;
break;
case UART_CFG_PARITY_ODD:
x.parity_mode = XMC_USIC_CH_PARITY_MODE_ODD;
break;
case UART_CFG_PARITY_EVEN:
x.parity_mode = XMC_USIC_CH_PARITY_MODE_EVEN;
break;
case UART_CFG_PARITY_MARK:
x.parity_mode = UART_CFG_PARITY_NONE;
return -ENOTSUP;
case UART_CFG_PARITY_SPACE:
x.parity_mode = UART_CFG_PARITY_NONE;
return -ENOTSUP;
default:
return -EINVAL;
}
switch (z->flow_ctrl) {
case UART_CFG_FLOW_CTRL_NONE:
break;
case UART_CFG_FLOW_CTRL_RTS_CTS:
case UART_CFG_FLOW_CTRL_DTR_DSR:
case UART_CFG_FLOW_CTRL_RS485:
return -ENOTSUP;
default:
return -EINVAL;
}
*xmc = x;
return 0;
}
#if defined(CONFIG_UART_ASYNC_API)
static inline void async_timer_start(struct k_work_delayable *work, int32_t timeout)
{
@@ -892,8 +1049,10 @@ static int uart_xmc4xxx_init(const struct device *dev)
struct uart_xmc4xxx_data *data = dev->data;
uint8_t fifo_offset = config->fifo_start_offset;
data->config.data_bits = 8U;
data->config.stop_bits = 1U;
ret = convert_config_zephyr_to_xmc4xxx(&data->config, data->uart_cfg);
if (ret) {
return ret;
}
XMC_UART_CH_Init(config->uart, &(data->config));
@@ -941,9 +1100,41 @@ static int uart_xmc4xxx_init(const struct device *dev)
return ret;
}
#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
static int uart_xmc4xxx_configure(const struct device *dev, const struct uart_config *cfg)
{
int ret;
struct uart_xmc4xxx_data *data = dev->data;
struct uart_config uart_cfg_bak = *data->uart_cfg;
*data->uart_cfg = *cfg;
ret = uart_xmc4xxx_init(dev);
if (ret) {
*data->uart_cfg = uart_cfg_bak;
}
return ret;
}
static int uart_xmc4xxx_config_get(const struct device *dev, struct uart_config *cfg)
{
int ret;
struct uart_xmc4xxx_data *data = dev->data;
ret = convert_config_xmc4xxx_to_zephyr(data->uart_cfg, &data->config);
*cfg = *data->uart_cfg;
return ret;
}
#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */
static DEVICE_API(uart, uart_xmc4xxx_driver_api) = {
.poll_in = uart_xmc4xxx_poll_in,
.poll_out = uart_xmc4xxx_poll_out,
#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
.configure = uart_xmc4xxx_configure,
.config_get = uart_xmc4xxx_config_get,
#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */
#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
.fifo_fill = uart_xmc4xxx_fifo_fill,
.fifo_read = uart_xmc4xxx_fifo_read,
@@ -1018,8 +1209,17 @@ static DEVICE_API(uart, uart_xmc4xxx_driver_api) = {
PINCTRL_DT_INST_DEFINE(index); \
XMC4XXX_IRQ_HANDLER(index) \
\
static struct uart_config uart_cfg_##index = { \
.baudrate = DT_INST_PROP(index, current_speed), \
.parity = DT_INST_ENUM_IDX(index, parity), \
.stop_bits = DT_INST_ENUM_IDX(index, stop_bits), \
.data_bits = DT_INST_ENUM_IDX(index, data_bits), \
.flow_ctrl = DT_INST_PROP(index, hw_flow_control) ? UART_CFG_FLOW_CTRL_RTS_CTS \
: UART_CFG_FLOW_CTRL_NONE, \
}; \
\
static struct uart_xmc4xxx_data xmc4xxx_data_##index = { \
.config.baudrate = DT_INST_PROP(index, current_speed), \
.uart_cfg = &uart_cfg_##index, \
UART_DMA_CHANNEL(index, tx, MEMORY_TO_PERIPHERAL, 8, 1) \
UART_DMA_CHANNEL(index, rx, PERIPHERAL_TO_MEMORY, 1, 8)}; \
\

View File

@@ -15,6 +15,8 @@ dut: &usic2ch0 {
fifo-start-offset = <0>;
fifo-tx-size = <0>;
fifo-rx-size = <0>;
data-bits = <8>;
stop-bits = "1";
status = "okay";
};

View File

@@ -20,6 +20,8 @@ dut: &usic1ch1 {
fifo-start-offset = <0>;
fifo-tx-size = <0>;
fifo-rx-size = <0>;
data-bits = <8>;
stop-bits = "1";
};
&uart_tx_p3_15_u1c1 {