tty: serial: meson_uart: Add support for kernel debugger
The kgdb invokes the poll_put_char and poll_get_char when communicating with the host. This patch implement the serial polling hooks for the meson_uart to be used for KGDB debugging over serial line. Signed-off-by: Julien Masson <jmasson@baylibre.com> Link: https://lore.kernel.org/r/867e1klo48.fsf@julienm-fedora-R90NQGV9.i-did-not-set--mail-host-address--so-tickle-me Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
101aa46bd2
commit
8412ba1db8
|
@ -10,6 +10,7 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
#include <linux/iopoll.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
@ -72,6 +73,8 @@
|
||||||
#define AML_UART_PORT_OFFSET 6
|
#define AML_UART_PORT_OFFSET 6
|
||||||
#define AML_UART_DEV_NAME "ttyAML"
|
#define AML_UART_DEV_NAME "ttyAML"
|
||||||
|
|
||||||
|
#define AML_UART_POLL_USEC 5
|
||||||
|
#define AML_UART_TIMEOUT_USEC 10000
|
||||||
|
|
||||||
static struct uart_driver meson_uart_driver;
|
static struct uart_driver meson_uart_driver;
|
||||||
|
|
||||||
|
@ -423,6 +426,64 @@ static void meson_uart_config_port(struct uart_port *port, int flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
/*
|
||||||
|
* Console polling routines for writing and reading from the uart while
|
||||||
|
* in an interrupt or debug context (i.e. kgdb).
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int meson_uart_poll_get_char(struct uart_port *port)
|
||||||
|
{
|
||||||
|
u32 c;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
|
||||||
|
if (readl(port->membase + AML_UART_STATUS) & AML_UART_RX_EMPTY)
|
||||||
|
c = NO_POLL_CHAR;
|
||||||
|
else
|
||||||
|
c = readl(port->membase + AML_UART_RFIFO);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void meson_uart_poll_put_char(struct uart_port *port, unsigned char c)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
u32 reg;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
|
||||||
|
/* Wait until FIFO is empty or timeout */
|
||||||
|
ret = readl_poll_timeout_atomic(port->membase + AML_UART_STATUS, reg,
|
||||||
|
reg & AML_UART_TX_EMPTY,
|
||||||
|
AML_UART_POLL_USEC,
|
||||||
|
AML_UART_TIMEOUT_USEC);
|
||||||
|
if (ret == -ETIMEDOUT) {
|
||||||
|
dev_err(port->dev, "Timeout waiting for UART TX EMPTY\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the character */
|
||||||
|
writel(c, port->membase + AML_UART_WFIFO);
|
||||||
|
|
||||||
|
/* Wait until FIFO is empty or timeout */
|
||||||
|
ret = readl_poll_timeout_atomic(port->membase + AML_UART_STATUS, reg,
|
||||||
|
reg & AML_UART_TX_EMPTY,
|
||||||
|
AML_UART_POLL_USEC,
|
||||||
|
AML_UART_TIMEOUT_USEC);
|
||||||
|
if (ret == -ETIMEDOUT)
|
||||||
|
dev_err(port->dev, "Timeout waiting for UART TX EMPTY\n");
|
||||||
|
|
||||||
|
out:
|
||||||
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_CONSOLE_POLL */
|
||||||
|
|
||||||
static const struct uart_ops meson_uart_ops = {
|
static const struct uart_ops meson_uart_ops = {
|
||||||
.set_mctrl = meson_uart_set_mctrl,
|
.set_mctrl = meson_uart_set_mctrl,
|
||||||
.get_mctrl = meson_uart_get_mctrl,
|
.get_mctrl = meson_uart_get_mctrl,
|
||||||
|
@ -438,6 +499,10 @@ static const struct uart_ops meson_uart_ops = {
|
||||||
.request_port = meson_uart_request_port,
|
.request_port = meson_uart_request_port,
|
||||||
.release_port = meson_uart_release_port,
|
.release_port = meson_uart_release_port,
|
||||||
.verify_port = meson_uart_verify_port,
|
.verify_port = meson_uart_verify_port,
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
.poll_get_char = meson_uart_poll_get_char,
|
||||||
|
.poll_put_char = meson_uart_poll_put_char,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_MESON_CONSOLE
|
#ifdef CONFIG_SERIAL_MESON_CONSOLE
|
||||||
|
|
Loading…
Reference in New Issue