From 2aa1bbb21f26de43b55a9d9cab9c0370c15a86ed Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Tue, 13 Apr 2021 19:40:15 +0200 Subject: serial: stm32: add FIFO threshold configuration Add the support for two optional DT properties, to configure RX and TX FIFO thresholds: - rx-threshold - tx-threshold This replaces hard-coded 8 bytes threshold. Keep 8 as the default value if not specified, for backward compatibility. Signed-off-by: Fabrice Gasnier Signed-off-by: Erwan Le Ray Changes in v2: Change added properties naming as proposed by Rob Herring. Link: https://lore.kernel.org/r/20210413174015.23011-5-erwan.leray@foss.st.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/stm32-usart.c | 53 +++++++++++++++++++++++++++++++++++----- drivers/tty/serial/stm32-usart.h | 8 ++---- 2 files changed, 49 insertions(+), 12 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 24a1dfe7058b..c2ae7b392b86 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -306,7 +306,7 @@ static void stm32_usart_tx_interrupt_enable(struct uart_port *port) * Enables TX FIFO threashold irq when FIFO is enabled, * or TX empty irq when FIFO is disabled */ - if (stm32_port->fifoen) + if (stm32_port->fifoen && stm32_port->txftcfg >= 0) stm32_usart_set_bits(port, ofs->cr3, USART_CR3_TXFTIE); else stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TXEIE); @@ -317,7 +317,7 @@ static void stm32_usart_tx_interrupt_disable(struct uart_port *port) struct stm32_port *stm32_port = to_stm32_port(port); const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; - if (stm32_port->fifoen) + if (stm32_port->fifoen && stm32_port->txftcfg >= 0) stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_TXFTIE); else stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TXEIE); @@ -796,9 +796,10 @@ static void stm32_usart_set_termios(struct uart_port *port, cr3 = readl_relaxed(port->membase + ofs->cr3); cr3 &= USART_CR3_TXFTIE | USART_CR3_RXFTIE; if (stm32_port->fifoen) { - cr3 &= ~(USART_CR3_TXFTCFG_MASK | USART_CR3_RXFTCFG_MASK); - cr3 |= USART_CR3_TXFTCFG_HALF << USART_CR3_TXFTCFG_SHIFT; - cr3 |= USART_CR3_RXFTCFG_HALF << USART_CR3_RXFTCFG_SHIFT; + if (stm32_port->txftcfg >= 0) + cr3 |= stm32_port->txftcfg << USART_CR3_TXFTCFG_SHIFT; + if (stm32_port->rxftcfg >= 0) + cr3 |= stm32_port->rxftcfg << USART_CR3_RXFTCFG_SHIFT; } if (cflag & CSTOPB) @@ -828,7 +829,8 @@ static void stm32_usart_set_termios(struct uart_port *port, , bits); if (ofs->rtor != UNDEF_REG && (stm32_port->rx_ch || - stm32_port->fifoen)) { + (stm32_port->fifoen && + stm32_port->rxftcfg >= 0))) { if (cflag & CSTOPB) bits = bits + 3; /* 1 start bit + 2 stop bits */ else @@ -1016,6 +1018,39 @@ static const struct uart_ops stm32_uart_ops = { .verify_port = stm32_usart_verify_port, }; +/* + * STM32H7 RX & TX FIFO threshold configuration (CR3 RXFTCFG / TXFTCFG) + * Note: 1 isn't a valid value in RXFTCFG / TXFTCFG. In this case, + * RXNEIE / TXEIE can be used instead of threshold irqs: RXFTIE / TXFTIE. + * So, RXFTCFG / TXFTCFG bitfields values are encoded as array index + 1. + */ +static const u32 stm32h7_usart_fifo_thresh_cfg[] = { 1, 2, 4, 8, 12, 14, 16 }; + +static void stm32_usart_get_ftcfg(struct platform_device *pdev, const char *p, + int *ftcfg) +{ + u32 bytes, i; + + /* DT option to get RX & TX FIFO threshold (default to 8 bytes) */ + if (of_property_read_u32(pdev->dev.of_node, p, &bytes)) + bytes = 8; + + for (i = 0; i < ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg); i++) + if (stm32h7_usart_fifo_thresh_cfg[i] >= bytes) + break; + if (i >= ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg)) + i = ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg) - 1; + + dev_dbg(&pdev->dev, "%s set to %d bytes\n", p, + stm32h7_usart_fifo_thresh_cfg[i]); + + /* Provide FIFO threshold ftcfg (1 is invalid: threshold irq unused) */ + if (i) + *ftcfg = i - 1; + else + *ftcfg = -EINVAL; +} + static void stm32_usart_deinit_port(struct stm32_port *stm32port) { clk_disable_unprepare(stm32port->clk); @@ -1052,6 +1087,12 @@ static int stm32_usart_init_port(struct stm32_port *stm32port, of_property_read_bool(pdev->dev.of_node, "rx-tx-swap"); stm32port->fifoen = stm32port->info->cfg.has_fifo; + if (stm32port->fifoen) { + stm32_usart_get_ftcfg(pdev, "rx-threshold", + &stm32port->rxftcfg); + stm32_usart_get_ftcfg(pdev, "tx-threshold", + &stm32port->txftcfg); + } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); port->membase = devm_ioremap_resource(&pdev->dev, res); diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h index 77d1ac082e89..07ac291328cd 100644 --- a/drivers/tty/serial/stm32-usart.h +++ b/drivers/tty/serial/stm32-usart.h @@ -216,12 +216,6 @@ struct stm32_usart_info stm32h7_info = { #define USART_CR3_TXFTCFG_MASK GENMASK(31, 29) /* H7 */ #define USART_CR3_TXFTCFG_SHIFT 29 /* H7 */ -/* TX FIFO threashold set to half of its depth */ -#define USART_CR3_TXFTCFG_HALF 0x2 - -/* RX FIFO threashold set to half of its depth */ -#define USART_CR3_RXFTCFG_HALF 0x2 - /* USART_GTPR */ #define USART_GTPR_PSC_MASK GENMASK(7, 0) #define USART_GTPR_GT_MASK GENMASK(15, 8) @@ -273,6 +267,8 @@ struct stm32_port { bool hw_flow_control; bool swap; /* swap RX & TX pins */ bool fifoen; + int rxftcfg; /* RX FIFO threshold CFG */ + int txftcfg; /* TX FIFO threshold CFG */ bool wakeup_src; int rdr_mask; /* receive data register mask */ struct mctrl_gpios *gpios; /* modem control gpios */ -- cgit v1.2.3