Add support for KGDB in stm32 serial driver by implementing characters polling callbacks (poll_init, poll_get_char and poll_put_char). Signed-off-by: Erwan Le Ray <erwan.leray@xxxxxxxxxxx> Signed-off-by: Jean Philippe Romain <jean-philippe.romain@xxxxxxxxxxx> Signed-off-by: Valentin Caron <valentin.caron@xxxxxxxxxxx> --- drivers/tty/serial/stm32-usart.c | 38 ++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 83895da84891..d2cf789c7997 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -37,6 +37,7 @@ static void stm32_usart_stop_tx(struct uart_port *port); static void stm32_usart_transmit_chars(struct uart_port *port); +static void __maybe_unused stm32_usart_console_putchar(struct uart_port *port, unsigned char ch); static inline struct stm32_port *to_stm32_port(struct uart_port *port) { @@ -1222,6 +1223,34 @@ static void stm32_usart_pm(struct uart_port *port, unsigned int state, } } +#if defined(CONFIG_CONSOLE_POLL) + + /* Callbacks for characters polling in debug context (i.e. KGDB). */ +static int stm32_usart_poll_init(struct uart_port *port) +{ + struct stm32_port *stm32_port = to_stm32_port(port); + + return clk_prepare_enable(stm32_port->clk); +} + +static int stm32_usart_poll_get_char(struct uart_port *port) +{ + struct stm32_port *stm32_port = to_stm32_port(port); + const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; + unsigned int ret; + + if (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_RXNE)) + return NO_POLL_CHAR; + + return readl_relaxed(port->membase + ofs->rdr) & stm32_port->rdr_mask; +} + +static void stm32_usart_poll_put_char(struct uart_port *port, unsigned char ch) +{ + stm32_usart_console_putchar(port, ch); +} +#endif /* CONFIG_CONSOLE_POLL */ + static const struct uart_ops stm32_uart_ops = { .tx_empty = stm32_usart_tx_empty, .set_mctrl = stm32_usart_set_mctrl, @@ -1243,6 +1272,11 @@ static const struct uart_ops stm32_uart_ops = { .request_port = stm32_usart_request_port, .config_port = stm32_usart_config_port, .verify_port = stm32_usart_verify_port, +#if defined(CONFIG_CONSOLE_POLL) + .poll_init = stm32_usart_poll_init, + .poll_get_char = stm32_usart_poll_get_char, + .poll_put_char = stm32_usart_poll_put_char, +#endif /* CONFIG_CONSOLE_POLL */ }; /* @@ -1640,8 +1674,7 @@ static int stm32_usart_serial_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_SERIAL_STM32_CONSOLE -static void stm32_usart_console_putchar(struct uart_port *port, unsigned char ch) +static void __maybe_unused stm32_usart_console_putchar(struct uart_port *port, unsigned char ch) { struct stm32_port *stm32_port = to_stm32_port(port); const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; @@ -1658,6 +1691,7 @@ static void stm32_usart_console_putchar(struct uart_port *port, unsigned char ch writel_relaxed(ch, port->membase + ofs->tdr); } +#ifdef CONFIG_SERIAL_STM32_CONSOLE static void stm32_usart_console_write(struct console *co, const char *s, unsigned int cnt) { -- 2.25.1