[PATCH v2] serial: sprd: Add polling IO support
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: Lanqing Liu --- Change from v1: - Add poll_init() support. --- drivers/tty/serial/sprd_serial.c | 33 + 1 file changed, 33 insertions(+) diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c index 73d71a4..d833160 100644 --- a/drivers/tty/serial/sprd_serial.c +++ b/drivers/tty/serial/sprd_serial.c @@ -911,6 +911,34 @@ static void sprd_pm(struct uart_port *port, unsigned int state, } } +#ifdef CONFIG_CONSOLE_POLL +static int sprd_poll_init(struct uart_port *port) +{ + if (port->state->pm_state != UART_PM_STATE_ON) { + sprd_pm(port, UART_PM_STATE_ON, 0); + port->state->pm_state = UART_PM_STATE_ON; + } + + return 0; +} + +static int sprd_poll_get_char(struct uart_port *port) +{ + while (!(serial_in(port, SPRD_STS1) & SPRD_RX_FIFO_CNT_MASK)) + cpu_relax(); + + return serial_in(port, SPRD_RXD); +} + +static void sprd_poll_put_char(struct uart_port *port, unsigned char ch) +{ + while (serial_in(port, SPRD_STS1) & SPRD_TX_FIFO_CNT_MASK) + cpu_relax(); + + serial_out(port, SPRD_TXD, ch); +} +#endif + static const struct uart_ops serial_sprd_ops = { .tx_empty = sprd_tx_empty, .get_mctrl = sprd_get_mctrl, @@ -928,6 +956,11 @@ static void sprd_pm(struct uart_port *port, unsigned int state, .config_port = sprd_config_port, .verify_port = sprd_verify_port, .pm = sprd_pm, +#ifdef CONFIG_CONSOLE_POLL + .poll_init = sprd_poll_init, + .poll_get_char = sprd_poll_get_char, + .poll_put_char = sprd_poll_put_char, +#endif }; #ifdef CONFIG_SERIAL_SPRD_CONSOLE -- 1.9.1
[PATCH] serial: sprd: Add polling IO support
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: Lanqing Liu --- drivers/tty/serial/sprd_serial.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c index 73d71a4..579ab41 100644 --- a/drivers/tty/serial/sprd_serial.c +++ b/drivers/tty/serial/sprd_serial.c @@ -911,6 +911,24 @@ static void sprd_pm(struct uart_port *port, unsigned int state, } } +#ifdef CONFIG_CONSOLE_POLL +static int sprd_poll_get_char(struct uart_port *port) +{ + while (!(serial_in(port, SPRD_STS1) & SPRD_RX_FIFO_CNT_MASK)) + cpu_relax(); + + return serial_in(port, SPRD_RXD); +} + +static void sprd_poll_put_char(struct uart_port *port, unsigned char ch) +{ + while (serial_in(port, SPRD_STS1) & SPRD_TX_FIFO_CNT_MASK) + cpu_relax(); + + serial_out(port, SPRD_TXD, ch); +} +#endif + static const struct uart_ops serial_sprd_ops = { .tx_empty = sprd_tx_empty, .get_mctrl = sprd_get_mctrl, @@ -928,6 +946,10 @@ static void sprd_pm(struct uart_port *port, unsigned int state, .config_port = sprd_config_port, .verify_port = sprd_verify_port, .pm = sprd_pm, +#ifdef CONFIG_CONSOLE_POLL + .poll_get_char = sprd_poll_get_char, + .poll_put_char = sprd_poll_put_char, +#endif }; #ifdef CONFIG_SERIAL_SPRD_CONSOLE -- 1.9.1
[PATCH] tty: serial_core: Fix the incorrect configuration of baud rate and data length at the console serial port resume
When userspace opens a serial port for console, uart_port_startup() is called. This function assigns the uport->cons->cflag value to TTY->termios.c_cflag, then it is cleared to 0. When the user space closes this serial port, the TTY structure will be released, and at this time uport->cons->cflag has also been cleared. On the Spreadtrum platform, in some special scenarios, like charging mode, userspace needs to close the console, which means the uport->cons->cflag has also been cleared. But printing logs is still needed in the kernel. So when system enters suspend and resume, the console needs to be configure the baud rate and data length of the serial port according to its own cflag when resuming the console port. At this time, the cflag is 0, which will cause serial port to produce configuration errors that do not meet user expectations. To fix this, assigning the TTY->termios.c_cflag value to uport->cons->cflag before the userspace closes this console serial port. It will ensure that the correct cflag value can be gotten when the console serial port was resumed. Signed-off-by: Lanqing Liu --- drivers/tty/serial/serial_core.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 351843f..f233cf8 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1539,6 +1539,7 @@ static void uart_set_termios(struct tty_struct *tty, static void uart_close(struct tty_struct *tty, struct file *filp) { struct uart_state *state = tty->driver_data; + struct uart_port *uport; if (!state) { struct uart_driver *drv = tty->driver->driver_state; @@ -1553,6 +1554,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp) } pr_debug("uart_close(%d) called\n", tty->index); + uport = uart_port_check(state); + if (uport && uart_console(uport)) + uport->cons->cflag = tty->termios.c_cflag; tty_port_close(tty->port, tty, filp); } -- 1.9.1