Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tty: serial: Add modem control gpio support for STM32 UART

STM32 UART controllers have the built in modem control support using
dedicated gpios which can be enabled using 'st,hw-flow-ctrl' flag in DT.
But there might be cases where the board design need to use different
gpios for modem control.

For supporting such cases, this commit adds modem control gpio support
to STM32 UART controller using mctrl_gpio driver.

Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Acked-by: Fabrice Gasnier <fabrice.gasnier@st.com>
Link: https://lore.kernel.org/r/20200420170204.24541-3-mani@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Manivannan Sadhasivam and committed by
Greg Kroah-Hartman
6cf61b9b 888ae871

+53 -2
+1
drivers/tty/serial/Kconfig
··· 1471 1471 tristate "STMicroelectronics STM32 serial port support" 1472 1472 select SERIAL_CORE 1473 1473 depends on ARCH_STM32 || COMPILE_TEST 1474 + select SERIAL_MCTRL_GPIO if GPIOLIB 1474 1475 help 1475 1476 This driver is for the on-chip Serial Controller on 1476 1477 STMicroelectronics STM32 MCUs.
+51 -2
drivers/tty/serial/stm32-usart.c
··· 31 31 #include <linux/tty_flip.h> 32 32 #include <linux/tty.h> 33 33 34 + #include "serial_mctrl_gpio.h" 34 35 #include "stm32-usart.h" 35 36 36 37 static void stm32_stop_tx(struct uart_port *port); ··· 511 510 stm32_set_bits(port, ofs->cr3, USART_CR3_RTSE); 512 511 else 513 512 stm32_clr_bits(port, ofs->cr3, USART_CR3_RTSE); 513 + 514 + mctrl_gpio_set(stm32_port->gpios, mctrl); 514 515 } 515 516 516 517 static unsigned int stm32_get_mctrl(struct uart_port *port) 517 518 { 519 + struct stm32_port *stm32_port = to_stm32_port(port); 520 + unsigned int ret; 521 + 518 522 /* This routine is used to get signals of: DCD, DSR, RI, and CTS */ 519 - return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; 523 + ret = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; 524 + 525 + return mctrl_gpio_get(stm32_port->gpios, &ret); 526 + } 527 + 528 + static void stm32_enable_ms(struct uart_port *port) 529 + { 530 + mctrl_gpio_enable_ms(to_stm32_port(port)->gpios); 531 + } 532 + 533 + static void stm32_disable_ms(struct uart_port *port) 534 + { 535 + mctrl_gpio_disable_ms(to_stm32_port(port)->gpios); 520 536 } 521 537 522 538 /* Transmit stop */ ··· 643 625 struct stm32_usart_config *cfg = &stm32_port->info->cfg; 644 626 u32 val, isr; 645 627 int ret; 628 + 629 + /* Disable modem control interrupts */ 630 + stm32_disable_ms(port); 646 631 647 632 val = USART_CR1_TXEIE | USART_CR1_TE; 648 633 val |= stm32_port->cr1_irq | USART_CR1_RE; ··· 785 764 cr3 |= USART_CR3_CTSE | USART_CR3_RTSE; 786 765 } 787 766 767 + /* Handle modem control interrupts */ 768 + if (UART_ENABLE_MS(port, termios->c_cflag)) 769 + stm32_enable_ms(port); 770 + else 771 + stm32_disable_ms(port); 772 + 788 773 usartdiv = DIV_ROUND_CLOSEST(port->uartclk, baud); 789 774 790 775 /* ··· 925 898 .throttle = stm32_throttle, 926 899 .unthrottle = stm32_unthrottle, 927 900 .stop_rx = stm32_stop_rx, 901 + .enable_ms = stm32_enable_ms, 928 902 .break_ctl = stm32_break_ctl, 929 903 .startup = stm32_startup, 930 904 .shutdown = stm32_shutdown, ··· 988 960 989 961 stm32port->port.uartclk = clk_get_rate(stm32port->clk); 990 962 if (!stm32port->port.uartclk) { 991 - clk_disable_unprepare(stm32port->clk); 992 963 ret = -EINVAL; 964 + goto err_clk; 993 965 } 966 + 967 + stm32port->gpios = mctrl_gpio_init(&stm32port->port, 0); 968 + if (IS_ERR(stm32port->gpios)) { 969 + ret = PTR_ERR(stm32port->gpios); 970 + goto err_clk; 971 + } 972 + 973 + /* Both CTS/RTS gpios and "st,hw-flow-ctrl" should not be specified */ 974 + if (stm32port->hw_flow_control) { 975 + if (mctrl_gpio_to_gpiod(stm32port->gpios, UART_GPIO_CTS) || 976 + mctrl_gpio_to_gpiod(stm32port->gpios, UART_GPIO_RTS)) { 977 + dev_err(&pdev->dev, "Conflicting RTS/CTS config\n"); 978 + ret = -EINVAL; 979 + goto err_clk; 980 + } 981 + } 982 + 983 + return ret; 984 + 985 + err_clk: 986 + clk_disable_unprepare(stm32port->clk); 994 987 995 988 return ret; 996 989 }
+1
drivers/tty/serial/stm32-usart.h
··· 274 274 bool fifoen; 275 275 int wakeirq; 276 276 int rdr_mask; /* receive data register mask */ 277 + struct mctrl_gpios *gpios; /* modem control gpios */ 277 278 }; 278 279 279 280 static struct stm32_port stm32_ports[STM32_MAX_PORTS];