From 01f56abd089dd216e537817b61497c58bb66aab3 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 22 Dec 2011 09:57:53 +0100 Subject: imx: add polled io uart methods These methods are invoked if the iMX uart is used in conjuction with kgdb during early boot. In order to access the UART without the interrupts, the kernel uses the basic polling methods for IO with the device. With these methods implemented, it is now possible to enable kgdb during early boot over serial. Signed-off-by: Saleem Abdulrasool Signed-off-by: Dirk Behme CC: Sascha Hauer CC: Fabio Estevam CC: Uwe Kleine-Koenig CC: linux-serial@vger.kernel.org CC: Alan Cox Signed-off-by: Shawn Guo Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 225922c7ce99..6b98a524eca2 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -102,6 +102,7 @@ #define UCR2_STPB (1<<6) /* Stop */ #define UCR2_WS (1<<5) /* Word size */ #define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */ +#define UCR2_ATEN (1<<3) /* Aging Timer Enable */ #define UCR2_TXEN (1<<2) /* Transmitter enabled */ #define UCR2_RXEN (1<<1) /* Receiver enabled */ #define UCR2_SRST (1<<0) /* SW reset */ @@ -1109,6 +1110,70 @@ imx_verify_port(struct uart_port *port, struct serial_struct *ser) return ret; } +#if defined(CONFIG_CONSOLE_POLL) +static int imx_poll_get_char(struct uart_port *port) +{ + struct imx_port_ucrs old_ucr; + unsigned int status; + unsigned char c; + + /* save control registers */ + imx_port_ucrs_save(port, &old_ucr); + + /* disable interrupts */ + writel(UCR1_UARTEN, port->membase + UCR1); + writel(old_ucr.ucr2 & ~(UCR2_ATEN | UCR2_RTSEN | UCR2_ESCI), + port->membase + UCR2); + writel(old_ucr.ucr3 & ~(UCR3_DCD | UCR3_RI | UCR3_DTREN), + port->membase + UCR3); + + /* poll */ + do { + status = readl(port->membase + USR2); + } while (~status & USR2_RDR); + + /* read */ + c = readl(port->membase + URXD0); + + /* restore control registers */ + imx_port_ucrs_restore(port, &old_ucr); + + return c; +} + +static void imx_poll_put_char(struct uart_port *port, unsigned char c) +{ + struct imx_port_ucrs old_ucr; + unsigned int status; + + /* save control registers */ + imx_port_ucrs_save(port, &old_ucr); + + /* disable interrupts */ + writel(UCR1_UARTEN, port->membase + UCR1); + writel(old_ucr.ucr2 & ~(UCR2_ATEN | UCR2_RTSEN | UCR2_ESCI), + port->membase + UCR2); + writel(old_ucr.ucr3 & ~(UCR3_DCD | UCR3_RI | UCR3_DTREN), + port->membase + UCR3); + + /* drain */ + do { + status = readl(port->membase + USR1); + } while (~status & USR1_TRDY); + + /* write */ + writel(c, port->membase + URTX0); + + /* flush */ + do { + status = readl(port->membase + USR2); + } while (~status & USR2_TXDC); + + /* restore control registers */ + imx_port_ucrs_restore(port, &old_ucr); +} +#endif + static struct uart_ops imx_pops = { .tx_empty = imx_tx_empty, .set_mctrl = imx_set_mctrl, @@ -1126,6 +1191,10 @@ static struct uart_ops imx_pops = { .request_port = imx_request_port, .config_port = imx_config_port, .verify_port = imx_verify_port, +#if defined(CONFIG_CONSOLE_POLL) + .poll_get_char = imx_poll_get_char, + .poll_put_char = imx_poll_put_char, +#endif }; static struct imx_port *imx_ports[UART_NR]; -- cgit v1.2.3-59-g8ed1b