#include <linux/nmi.h>
#include <linux/mutex.h>
#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/pm_runtime.h>
#ifdef CONFIG_SPARC
#include <linux/sunserialcore.h>
#endif
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_AFE,
},
+/* tx_loadsz is set to 63-bytes instead of 64-bytes to implement
+workaround of errata A-008006 which states that tx_loadsz should be
+configured less than Maximum supported fifo bytes */
+ [PORT_16550A_FSL64] = {
+ .name = "16550A_FSL64",
+ .fifo_size = 64,
+ .tx_loadsz = 63,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
+ UART_FCR7_64BYTE,
+ .flags = UART_CAP_FIFO,
+ },
};
/* Uart divisor latch read */
}
EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
+void serial8250_rpm_get(struct uart_8250_port *p)
+{
+ if (!(p->capabilities & UART_CAP_RPM))
+ return;
+ pm_runtime_get_sync(p->port.dev);
+}
+EXPORT_SYMBOL_GPL(serial8250_rpm_get);
+
+void serial8250_rpm_put(struct uart_8250_port *p)
+{
+ if (!(p->capabilities & UART_CAP_RPM))
+ return;
+ pm_runtime_mark_last_busy(p->port.dev);
+ pm_runtime_put_autosuspend(p->port.dev);
+}
+EXPORT_SYMBOL_GPL(serial8250_rpm_put);
+
+/*
+ * These two wrappers ensure that enable_runtime_pm_tx() can be called more than
+ * once and disable_runtime_pm_tx() will still disable RPM because the fifo is
+ * empty and the HW can idle again.
+ */
+static void serial8250_rpm_get_tx(struct uart_8250_port *p)
+{
+ unsigned char rpm_active;
+
+ if (!(p->capabilities & UART_CAP_RPM))
+ return;
+
+ rpm_active = xchg(&p->rpm_tx_active, 1);
+ if (rpm_active)
+ return;
+ pm_runtime_get_sync(p->port.dev);
+}
+
+static void serial8250_rpm_put_tx(struct uart_8250_port *p)
+{
+ unsigned char rpm_active;
+
+ if (!(p->capabilities & UART_CAP_RPM))
+ return;
+
+ rpm_active = xchg(&p->rpm_tx_active, 0);
+ if (!rpm_active)
+ return;
+ pm_runtime_mark_last_busy(p->port.dev);
+ pm_runtime_put_autosuspend(p->port.dev);
+}
+
/*
* IER sleep support. UARTs which have EFRs need the "extended
* capability" bit enabled. Note that on XR16C850s, we need to
*/
static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
{
+ unsigned char lcr = 0, efr = 0;
/*
* Exar UARTs have a SLEEP register that enables or disables
* each UART to enter sleep mode separately. On the XR17V35x the
* offset but the UART channel may only write to the corresponding
* bit.
*/
+ serial8250_rpm_get(p);
if ((p->port.type == PORT_XR17V35X) ||
(p->port.type == PORT_XR17D15X)) {
serial_out(p, UART_EXAR_SLEEP, sleep ? 0xff : 0);
- return;
+ goto out;
}
if (p->capabilities & UART_CAP_SLEEP) {
if (p->capabilities & UART_CAP_EFR) {
+ lcr = serial_in(p, UART_LCR);
+ efr = serial_in(p, UART_EFR);
serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
serial_out(p, UART_EFR, UART_EFR_ECB);
serial_out(p, UART_LCR, 0);
serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
if (p->capabilities & UART_CAP_EFR) {
serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_out(p, UART_EFR, 0);
- serial_out(p, UART_LCR, 0);
+ serial_out(p, UART_EFR, efr);
+ serial_out(p, UART_LCR, lcr);
}
}
+out:
+ serial8250_rpm_put(p);
}
#ifdef CONFIG_SERIAL_8250_RSA
up->port.type = PORT_16650;
up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
} else {
- DEBUG_AUTOCONF("Motorola 8xxx DUART ");
+ serial_out(up, UART_LCR, 0);
+ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
+ UART_FCR7_64BYTE);
+ status1 = serial_in(up, UART_IIR) >> 5;
+ serial_out(up, UART_FCR, 0);
+ serial_out(up, UART_LCR, 0);
+
+ if (status1 == 7)
+ up->port.type = PORT_16550A_FSL64;
+ else
+ DEBUG_AUTOCONF("Motorola 8xxx DUART ");
}
serial_out(up, UART_EFR, 0);
return;
if (p->ier & UART_IER_THRI) {
p->ier &= ~UART_IER_THRI;
serial_out(p, UART_IER, p->ier);
+ serial8250_rpm_put_tx(p);
}
}
{
struct uart_8250_port *up = up_to_u8250p(port);
+ serial8250_rpm_get(up);
__stop_tx(up);
/*
up->acr |= UART_ACR_TXDIS;
serial_icr_write(up, UART_ACR, up->acr);
}
+ serial8250_rpm_put(up);
}
static void serial8250_start_tx(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
- if (up->dma && !serial8250_tx_dma(up)) {
+ serial8250_rpm_get_tx(up);
+ if (up->dma && !up->dma->tx_dma(up)) {
return;
} else if (!(up->ier & UART_IER_THRI)) {
up->ier |= UART_IER_THRI;
}
}
+static void serial8250_throttle(struct uart_port *port)
+{
+ port->throttle(port);
+}
+
+static void serial8250_unthrottle(struct uart_port *port)
+{
+ port->unthrottle(port);
+}
+
static void serial8250_stop_rx(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
- up->ier &= ~UART_IER_RLSI;
+ serial8250_rpm_get(up);
+
+ up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
up->port.read_status_mask &= ~UART_LSR_DR;
serial_port_out(port, UART_IER, up->ier);
+
+ serial8250_rpm_put(up);
+}
+
+static void serial8250_disable_ms(struct uart_port *port)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+
+ /* no MSR capabilities */
+ if (up->bugs & UART_BUG_NOMSR)
+ return;
+
+ up->ier &= ~UART_IER_MSI;
+ serial_port_out(port, UART_IER, up->ier);
}
static void serial8250_enable_ms(struct uart_port *port)
return;
up->ier |= UART_IER_MSI;
+
+ serial8250_rpm_get(up);
serial_port_out(port, UART_IER, up->ier);
+ serial8250_rpm_put(up);
}
/*
ignore_char:
lsr = serial_in(up, UART_LSR);
- } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
+ } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (--max_count > 0));
spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
spin_lock(&port->lock);
DEBUG_INTR("THRE...");
- if (uart_circ_empty(xmit))
+ /*
+ * With RPM enabled, we have to wait until the FIFO is empty before the
+ * HW can go idle. So we get here once again with empty FIFO and disable
+ * the interrupt and RPM in __stop_tx()
+ */
+ if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM))
__stop_tx(up);
}
EXPORT_SYMBOL_GPL(serial8250_tx_chars);
+/* Caller holds uart port lock */
unsigned int serial8250_modem_status(struct uart_8250_port *up)
{
struct uart_port *port = &up->port;
if (status & (UART_LSR_DR | UART_LSR_BI)) {
if (up->dma)
- dma_err = serial8250_rx_dma(up, iir);
+ dma_err = up->dma->rx_dma(up, iir);
if (!up->dma || dma_err)
status = serial8250_rx_chars(up, status);
}
serial8250_modem_status(up);
- if (!up->dma && (status & UART_LSR_THRE))
+ if ((!up->dma || (up->dma && up->dma->tx_err)) &&
+ (status & UART_LSR_THRE))
serial8250_tx_chars(up);
spin_unlock_irqrestore(&port->lock, flags);
static int serial8250_default_handle_irq(struct uart_port *port)
{
- unsigned int iir = serial_port_in(port, UART_IIR);
+ struct uart_8250_port *up = up_to_u8250p(port);
+ unsigned int iir;
+ int ret;
+
+ serial8250_rpm_get(up);
+
+ iir = serial_port_in(port, UART_IIR);
+ ret = serial8250_handle_irq(port, iir);
- return serial8250_handle_irq(port, iir);
+ serial8250_rpm_put(up);
+ return ret;
}
/*
unsigned long flags;
unsigned int lsr;
+ serial8250_rpm_get(up);
+
spin_lock_irqsave(&port->lock, flags);
lsr = serial_port_in(port, UART_LSR);
up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
spin_unlock_irqrestore(&port->lock, flags);
+ serial8250_rpm_put(up);
+
return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
}
unsigned int status;
unsigned int ret;
+ serial8250_rpm_get(up);
status = serial8250_modem_status(up);
+ serial8250_rpm_put(up);
ret = 0;
if (status & UART_MSR_DCD)
return ret;
}
-static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
+void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned char mcr = 0;
serial_port_out(port, UART_MCR, mcr);
}
+EXPORT_SYMBOL_GPL(serial8250_do_set_mctrl);
+
+static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ if (port->set_mctrl)
+ return port->set_mctrl(port, mctrl);
+ return serial8250_do_set_mctrl(port, mctrl);
+}
static void serial8250_break_ctl(struct uart_port *port, int break_state)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
+ serial8250_rpm_get(up);
spin_lock_irqsave(&port->lock, flags);
if (break_state == -1)
up->lcr |= UART_LCR_SBC;
up->lcr &= ~UART_LCR_SBC;
serial_port_out(port, UART_LCR, up->lcr);
spin_unlock_irqrestore(&port->lock, flags);
+ serial8250_rpm_put(up);
}
/*
static int serial8250_get_poll_char(struct uart_port *port)
{
- unsigned char lsr = serial_port_in(port, UART_LSR);
+ struct uart_8250_port *up = up_to_u8250p(port);
+ unsigned char lsr;
+ int status;
+
+ serial8250_rpm_get(up);
+
+ lsr = serial_port_in(port, UART_LSR);
- if (!(lsr & UART_LSR_DR))
- return NO_POLL_CHAR;
+ if (!(lsr & UART_LSR_DR)) {
+ status = NO_POLL_CHAR;
+ goto out;
+ }
- return serial_port_in(port, UART_RX);
+ status = serial_port_in(port, UART_RX);
+out:
+ serial8250_rpm_put(up);
+ return status;
}
unsigned int ier;
struct uart_8250_port *up = up_to_u8250p(port);
+ serial8250_rpm_get(up);
/*
* First save the IER then disable the interrupts
*/
*/
wait_for_xmitr(up, BOTH_EMPTY);
serial_port_out(port, UART_IER, ier);
+ serial8250_rpm_put(up);
}
#endif /* CONFIG_CONSOLE_POLL */
-static int serial8250_startup(struct uart_port *port)
+int serial8250_do_startup(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
if (port->iotype != up->cur_iotype)
set_io_from_upio(port);
+ serial8250_rpm_get(up);
if (port->type == PORT_16C950) {
/* Wake up and initialize UART */
up->acr = 0;
*/
enable_rsa(up);
#endif
-
/*
* Clear the FIFO buffers and disable them.
* (they will be reenabled in set_termios())
/*
* Clear the interrupt registers.
*/
- serial_port_in(port, UART_LSR);
- serial_port_in(port, UART_RX);
+ if (serial_port_in(port, UART_LSR) & UART_LSR_DR)
+ serial_port_in(port, UART_RX);
serial_port_in(port, UART_IIR);
serial_port_in(port, UART_MSR);
(serial_port_in(port, UART_LSR) == 0xff)) {
printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
serial_index(port));
- return -ENODEV;
+ retval = -ENODEV;
+ goto out;
}
/*
} else {
retval = serial_link_irq_chain(up);
if (retval)
- return retval;
+ goto out;
}
/*
* saved flags to avoid getting false values from polling
* routines or the previous session.
*/
- serial_port_in(port, UART_LSR);
- serial_port_in(port, UART_RX);
+ if (serial_port_in(port, UART_LSR) & UART_LSR_DR)
+ serial_port_in(port, UART_RX);
serial_port_in(port, UART_IIR);
serial_port_in(port, UART_MSR);
up->lsr_saved_flags = 0;
outb_p(0x80, icp);
inb_p(icp);
}
+ retval = 0;
+out:
+ serial8250_rpm_put(up);
+ return retval;
+}
+EXPORT_SYMBOL_GPL(serial8250_do_startup);
- return 0;
+static int serial8250_startup(struct uart_port *port)
+{
+ if (port->startup)
+ return port->startup(port);
+ return serial8250_do_startup(port);
}
-static void serial8250_shutdown(struct uart_port *port)
+void serial8250_do_shutdown(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
+ serial8250_rpm_get(up);
/*
* Disable interrupts from this port
*/
* Read data port to reset things, and then unlink from
* the IRQ chain.
*/
- serial_port_in(port, UART_RX);
+ if (serial_port_in(port, UART_LSR) & UART_LSR_DR)
+ serial_port_in(port, UART_RX);
+ serial8250_rpm_put(up);
del_timer_sync(&up->timer);
up->timer.function = serial8250_timeout;
if (port->irq)
serial_unlink_irq_chain(up);
}
+EXPORT_SYMBOL_GPL(serial8250_do_shutdown);
+
+static void serial8250_shutdown(struct uart_port *port)
+{
+ if (port->shutdown)
+ port->shutdown(port);
+ else
+ serial8250_do_shutdown(port);
+}
static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
{
* the trigger, or the MCR RTS bit is cleared. In the case where
* the remote UART is not using CTS auto flow control, we must
* have sufficient FIFO entries for the latency of the remote
- * UART to respond. IOW, at least 32 bytes of FIFO. Also enable
- * AFE if hw flow control is supported
+ * UART to respond. IOW, at least 32 bytes of FIFO.
*/
- if ((up->capabilities & UART_CAP_AFE && (port->fifosize >= 32)) ||
- (port->flags & UPF_HARD_FLOW)) {
+ if (up->capabilities & UART_CAP_AFE && port->fifosize >= 32) {
up->mcr &= ~UART_MCR_AFE;
if (termios->c_cflag & CRTSCTS)
up->mcr |= UART_MCR_AFE;
* Ok, we're now changing the port state. Do it with
* interrupts disabled.
*/
+ serial8250_rpm_get(up);
spin_lock_irqsave(&port->lock, flags);
/*
}
serial8250_set_mctrl(port, port->mctrl);
spin_unlock_irqrestore(&port->lock, flags);
+ serial8250_rpm_put(up);
+
/* Don't rewrite B0 */
if (tty_termios_baud_rate(termios))
tty_termios_encode_baud_rate(termios, baud, baud);
}
static void
-serial8250_set_ldisc(struct uart_port *port, int new)
+serial8250_set_ldisc(struct uart_port *port, struct ktermios *termios)
{
- if (new == N_PPS) {
+ if (termios->c_line == N_PPS) {
port->flags |= UPF_HARDPPS_CD;
+ spin_lock_irq(&port->lock);
serial8250_enable_ms(port);
- } else
+ spin_unlock_irq(&port->lock);
+ } else {
port->flags &= ~UPF_HARDPPS_CD;
+ if (!UART_ENABLE_MS(port, termios->c_cflag)) {
+ spin_lock_irq(&port->lock);
+ serial8250_disable_ms(port);
+ spin_unlock_irq(&port->lock);
+ }
+ }
}
static unsigned int serial8250_port_size(struct uart_8250_port *pt)
{
- if (pt->port.iotype == UPIO_AU)
+ if (pt->port.iotype == UPIO_AU) {
+ if (pt->port.type == PORT_RT2880)
+ return 0x100;
return 0x1000;
+ }
if (is_omap1_8250(pt))
return 0x16 << pt->port.regshift;
.get_mctrl = serial8250_get_mctrl,
.stop_tx = serial8250_stop_tx,
.start_tx = serial8250_start_tx,
+ .throttle = serial8250_throttle,
+ .unthrottle = serial8250_unthrottle,
.stop_rx = serial8250_stop_rx,
.enable_ms = serial8250_enable_ms,
.break_ctl = serial8250_break_ctl,
static struct uart_8250_port serial8250_ports[UART_NR];
+/**
+ * serial8250_get_port - retrieve struct uart_8250_port
+ * @line: serial line number
+ *
+ * This function retrieves struct uart_8250_port for the specific line.
+ * This struct *must* *not* be used to perform a 8250 or serial core operation
+ * which is not accessible otherwise. Its only purpose is to make the struct
+ * accessible to the runtime-pm callbacks for context suspend/restore.
+ * The lock assumption made here is none because runtime-pm suspend/resume
+ * callbacks should not be invoked if there is any operation performed on the
+ * port.
+ */
+struct uart_8250_port *serial8250_get_port(int line)
+{
+ return &serial8250_ports[line];
+}
+EXPORT_SYMBOL_GPL(serial8250_get_port);
+
static void (*serial8250_isa_config)(int port, struct uart_port *up,
unsigned short *capabilities);
touch_nmi_watchdog();
- if (port->sysrq || oops_in_progress)
+ serial8250_rpm_get(up);
+
+ if (port->sysrq)
+ locked = 0;
+ else if (oops_in_progress)
locked = spin_trylock_irqsave(&port->lock, flags);
else
spin_lock_irqsave(&port->lock, flags);
if (locked)
spin_unlock_irqrestore(&port->lock, flags);
+ serial8250_rpm_put(up);
}
-static int __init serial8250_console_setup(struct console *co, char *options)
+static int serial8250_console_setup(struct console *co, char *options)
{
struct uart_port *port;
int baud = 9600;
.resume = serial8250_resume,
.driver = {
.name = "serial8250",
- .owner = THIS_MODULE,
},
};
if (uart_match_port(&serial8250_ports[i].port, port))
return &serial8250_ports[i];
+ /* try line number first if still available */
+ i = port->line;
+ if (i < nr_uarts && serial8250_ports[i].port.type == PORT_UNKNOWN &&
+ serial8250_ports[i].port.iobase == 0)
+ return &serial8250_ports[i];
/*
* We didn't find a matching entry, so look for the first
* free entry. We look for one which hasn't been previously
uart->port.fifosize = up->port.fifosize;
uart->tx_loadsz = up->tx_loadsz;
uart->capabilities = up->capabilities;
+ uart->port.throttle = up->port.throttle;
+ uart->port.unthrottle = up->port.unthrottle;
+ uart->port.rs485_config = up->port.rs485_config;
+ uart->port.rs485 = up->port.rs485;
/* Take tx_loadsz from fifosize if it wasn't set separately */
if (uart->port.fifosize && !uart->tx_loadsz)
/* Possibly override set_termios call */
if (up->port.set_termios)
uart->port.set_termios = up->port.set_termios;
+ if (up->port.set_mctrl)
+ uart->port.set_mctrl = up->port.set_mctrl;
+ if (up->port.startup)
+ uart->port.startup = up->port.startup;
+ if (up->port.shutdown)
+ uart->port.shutdown = up->port.shutdown;
if (up->port.pm)
uart->port.pm = up->port.pm;
if (up->port.handle_break)
uart->dl_read = up->dl_read;
if (up->dl_write)
uart->dl_write = up->dl_write;
- if (up->dma)
+ if (up->dma) {
uart->dma = up->dma;
+ if (!uart->dma->tx_dma)
+ uart->dma->tx_dma = serial8250_tx_dma;
+ if (!uart->dma->rx_dma)
+ uart->dma->rx_dma = serial8250_rx_dma;
+ }
if (serial8250_isa_config != NULL)
serial8250_isa_config(0, &uart->port,
#ifdef CONFIG_SERIAL_8250_RSA
__module_param_call(MODULE_PARAM_PREFIX, probe_rsa,
¶m_array_ops, .arr = &__param_arr_probe_rsa,
- 0444, -1);
+ 0444, -1, 0);
#endif
}
#else