]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
imx: add polled io uart methods
authorSaleem Abdulrasool <compnerd@compnerd.org>
Thu, 22 Dec 2011 08:57:53 +0000 (09:57 +0100)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:34:35 +0000 (08:34 +0200)
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 <compnerd@compnerd.org>
Signed-off-by: Dirk Behme <dirk.behme@gmail.com>
CC: Sascha Hauer <s.hauer@pengutronix.de>
CC: Fabio Estevam <festevam@gmail.com>
CC: Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
CC: linux-serial@vger.kernel.org
CC: Alan Cox <alan@linux.intel.com>
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/tty/serial/imx.c

index d7acd41497d2b1e63f9b8130491fb1cd4c35371d..44564e3fcdbe4f901085db0d494a6e9676e4a7f5 100644 (file)
@@ -1428,6 +1428,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,
@@ -1445,6 +1509,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];