Skip to content

Commit

Permalink
imx: add polled io uart methods
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Saleem Abdulrasool authored and Greg Kroah-Hartman committed Jan 5, 2012
1 parent 0ad5a81 commit 01f56ab
Showing 1 changed file with 69 additions and 0 deletions.
69 changes: 69 additions & 0 deletions drivers/tty/serial/imx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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,
Expand All @@ -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];
Expand Down

0 comments on commit 01f56ab

Please sign in to comment.