From 04dd17822334871b23ea2862f7798fb0e0007777 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Sat, 11 May 2024 08:53:19 +0000 Subject: [PATCH] change otg to host mode --- kernel/drivers/tty/serial/8250/8250_port.c | 562 +++++++++++++++++++++++++++++++------------------------ 1 files changed, 316 insertions(+), 246 deletions(-) diff --git a/kernel/drivers/tty/serial/8250/8250_port.c b/kernel/drivers/tty/serial/8250/8250_port.c index ad452d6..9eadc7f 100644 --- a/kernel/drivers/tty/serial/8250/8250_port.c +++ b/kernel/drivers/tty/serial/8250/8250_port.c @@ -11,15 +11,13 @@ * membase is an 'ioremapped' cookie. */ -#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/ioport.h> #include <linux/init.h> +#include <linux/irq.h> #include <linux/console.h> +#include <linux/gpio/consumer.h> #include <linux/sysrq.h> #include <linux/delay.h> #include <linux/platform_device.h> @@ -31,7 +29,6 @@ #include <linux/nmi.h> #include <linux/mutex.h> #include <linux/slab.h> -#include <linux/kdb.h> #include <linux/uaccess.h> #include <linux/pm_runtime.h> #include <linux/ktime.h> @@ -40,13 +37,6 @@ #include <asm/irq.h> #include "8250.h" - -/* - * These are definitions for the Exar XR17V35X and XR17(C|D)15X - */ -#define UART_EXAR_INT0 0x80 -#define UART_EXAR_SLEEP 0x8b /* Sleep mode */ -#define UART_EXAR_DVID 0x8d /* Device identification */ /* Nuvoton NPCM timeout register */ #define UART_NPCM_TOR 7 @@ -67,6 +57,7 @@ * Here we define the default xmit fifo size used for each type of UART. */ static const struct serial8250_config uart_config[] = { +#ifndef CONFIG_ROCKCHIP_MINI_KERNEL [PORT_UNKNOWN] = { .name = "unknown", .fifo_size = 1, @@ -87,6 +78,7 @@ .fifo_size = 1, .tx_loadsz = 1, }, +#endif [PORT_16550A] = { .name = "16550A", .fifo_size = 16, @@ -95,6 +87,7 @@ .rxtrig_bytes = {1, 4, 8, 14}, .flags = UART_CAP_FIFO, }, +#ifndef CONFIG_ROCKCHIP_MINI_KERNEL [PORT_CIRRUS] = { .name = "Cirrus", .fifo_size = 1, @@ -310,6 +303,15 @@ .rxtrig_bytes = {1, 4, 8, 14}, .flags = UART_CAP_FIFO, }, + [PORT_SUNIX] = { + .name = "Sunix", + .fifo_size = 128, + .tx_loadsz = 128, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .rxtrig_bytes = {1, 32, 64, 112}, + .flags = UART_CAP_FIFO | UART_CAP_SLEEP, + }, +#endif }; /* Uart divisor latch read */ @@ -387,6 +389,7 @@ #endif +#ifndef CONFIG_ROCKCHIP_MINI_KERNEL static unsigned int hub6_serial_in(struct uart_port *p, int offset) { offset = offset << p->regshift; @@ -460,6 +463,7 @@ offset = offset << p->regshift; outb(value, p->iobase + offset); } +#endif static int serial8250_default_handle_irq(struct uart_port *port); @@ -470,6 +474,7 @@ up->dl_read = default_serial_dl_read; up->dl_write = default_serial_dl_write; +#ifndef CONFIG_ROCKCHIP_MINI_KERNEL switch (p->iotype) { case UPIO_HUB6: p->serial_in = hub6_serial_in; @@ -510,6 +515,7 @@ p->serial_out = io_serial_out; break; } +#endif /* Remember loaded iotype */ up->cur_iotype = p->iotype; p->handle_irq = serial8250_default_handle_irq; @@ -533,27 +539,6 @@ } /* - * For the 16C950 - */ -static void serial_icr_write(struct uart_8250_port *up, int offset, int value) -{ - serial_out(up, UART_SCR, offset); - serial_out(up, UART_ICR, value); -} - -static unsigned int serial_icr_read(struct uart_8250_port *up, int offset) -{ - unsigned int value; - - serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD); - serial_out(up, UART_SCR, offset); - value = serial_in(up, UART_ICR); - serial_icr_write(up, UART_ACR, up->acr); - - return value; -} - -/* * FIFO support. */ static void serial8250_clear_fifos(struct uart_8250_port *p) @@ -564,17 +549,6 @@ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); serial_out(p, UART_FCR, 0); } -} - -static inline void serial8250_em485_rts_after_send(struct uart_8250_port *p) -{ - unsigned char mcr = serial8250_in_MCR(p); - - if (p->port.rs485.flags & SER_RS485_RTS_AFTER_SEND) - mcr |= UART_MCR_RTS; - else - mcr &= ~UART_MCR_RTS; - serial8250_out_MCR(p, mcr); } static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t); @@ -624,10 +598,10 @@ * * Return 0 - success, -errno - otherwise */ -int serial8250_em485_init(struct uart_8250_port *p) +static int serial8250_em485_init(struct uart_8250_port *p) { if (p->em485) - return 0; + goto deassert_rts; p->em485 = kmalloc(sizeof(struct uart_8250_em485), GFP_ATOMIC); if (!p->em485) @@ -641,11 +615,14 @@ p->em485->start_tx_timer.function = &serial8250_em485_handle_start_tx; p->em485->port = p; p->em485->active_timer = NULL; - serial8250_em485_rts_after_send(p); + p->em485->tx_stopped = true; + +deassert_rts: + if (p->em485->tx_stopped) + p->rs485_stop_tx(p); return 0; } -EXPORT_SYMBOL_GPL(serial8250_em485_init); /** * serial8250_em485_destroy() - put uart_8250_port into normal state @@ -672,6 +649,41 @@ p->em485 = NULL; } EXPORT_SYMBOL_GPL(serial8250_em485_destroy); + +/** + * serial8250_em485_config() - generic ->rs485_config() callback + * @port: uart port + * @rs485: rs485 settings + * + * Generic callback usable by 8250 uart drivers to activate rs485 settings + * if the uart is incapable of driving RTS as a Transmit Enable signal in + * hardware, relying on software emulation instead. + */ +int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + /* pick sane settings if the user hasn't */ + if (!!(rs485->flags & SER_RS485_RTS_ON_SEND) == + !!(rs485->flags & SER_RS485_RTS_AFTER_SEND)) { + rs485->flags |= SER_RS485_RTS_ON_SEND; + rs485->flags &= ~SER_RS485_RTS_AFTER_SEND; + } + + gpiod_set_value(port->rs485_term_gpio, + rs485->flags & SER_RS485_TERMINATE_BUS); + + /* + * Both serial8250_em485_init() and serial8250_em485_destroy() + * are idempotent. + */ + if (rs485->flags & SER_RS485_ENABLED) + return serial8250_em485_init(up); + + serial8250_em485_destroy(up); + return 0; +} +EXPORT_SYMBOL_GPL(serial8250_em485_config); /* * These two wrappers ensure that enable_runtime_pm_tx() can be called more than @@ -715,19 +727,8 @@ 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 - * register is accessible to each UART at the UART_EXAR_SLEEP - * 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); - goto out; - } if (p->capabilities & UART_CAP_SLEEP) { if (p->capabilities & UART_CAP_EFR) { @@ -744,7 +745,7 @@ serial_out(p, UART_LCR, lcr); } } -out: + serial8250_rpm_put(p); } @@ -1017,26 +1018,8 @@ up->port.type = PORT_16550A; up->capabilities |= UART_CAP_FIFO; - /* - * XR17V35x UARTs have an extra divisor register, DLD - * that gets enabled with when DLAB is set which will - * cause the device to incorrectly match and assign - * port type to PORT_16650. The EFR for this UART is - * found at offset 0x09. Instead check the Deice ID (DVID) - * register for a 2, 4 or 8 port UART. - */ - if (up->port.flags & UPF_EXAR_EFR) { - status1 = serial_in(up, UART_EXAR_DVID); - if (status1 == 0x82 || status1 == 0x84 || status1 == 0x88) { - DEBUG_AUTOCONF("Exar XR17V35x "); - up->port.type = PORT_XR17V35X; - up->capabilities |= UART_CAP_AFE | UART_CAP_EFR | - UART_CAP_SLEEP; - - return; - } - - } + if (!IS_ENABLED(CONFIG_SERIAL_8250_16550A_VARIANTS)) + return; /* * Check for presence of the EFR when DLAB is set. @@ -1175,18 +1158,6 @@ DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 "); } serial_out(up, UART_IER, iersave); - - /* - * Exar uarts have EFR in a weird location - */ - if (up->port.flags & UPF_EXAR_EFR) { - DEBUG_AUTOCONF("Exar XR17D15x "); - up->port.type = PORT_XR17D15X; - up->capabilities |= UART_CAP_AFE | UART_CAP_EFR | - UART_CAP_SLEEP; - - return; - } /* * We distinguish between 16550A and U6 16550A by counting @@ -1370,8 +1341,8 @@ fintek_8250_probe(up); if (up->capabilities != old_capabilities) { - pr_warn("%s: detected caps %08x should be %08x\n", - port->name, old_capabilities, up->capabilities); + dev_warn(port->dev, "detected caps %08x should be %08x\n", + old_capabilities, up->capabilities); } out: DEBUG_AUTOCONF("iir=%d ", scratch); @@ -1446,9 +1417,21 @@ serial8250_rpm_put(up); } -static void __do_stop_tx_rs485(struct uart_8250_port *p) +/** + * serial8250_em485_stop_tx() - generic ->rs485_stop_tx() callback + * @p: uart 8250 port + * + * Generic callback usable by 8250 uart drivers to stop rs485 transmission. + */ +void serial8250_em485_stop_tx(struct uart_8250_port *p) { - serial8250_em485_rts_after_send(p); + unsigned char mcr = serial8250_in_MCR(p); + + if (p->port.rs485.flags & SER_RS485_RTS_AFTER_SEND) + mcr |= UART_MCR_RTS; + else + mcr &= ~UART_MCR_RTS; + serial8250_out_MCR(p, mcr); /* * Empty the RX FIFO, we are not interested in anything @@ -1462,6 +1445,8 @@ serial_port_out(&p->port, UART_IER, p->ier); } } +EXPORT_SYMBOL_GPL(serial8250_em485_stop_tx); + static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t) { struct uart_8250_em485 *em485; @@ -1474,8 +1459,9 @@ serial8250_rpm_get(p); spin_lock_irqsave(&p->port.lock, flags); if (em485->active_timer == &em485->stop_tx_timer) { - __do_stop_tx_rs485(p); + p->rs485_stop_tx(p); em485->active_timer = NULL; + em485->tx_stopped = true; } spin_unlock_irqrestore(&p->port.lock, flags); serial8250_rpm_put(p); @@ -1496,7 +1482,7 @@ struct uart_8250_em485 *em485 = p->em485; /* - * __do_stop_tx_rs485 is going to set RTS according to config + * rs485_stop_tx() is going to set RTS according to config * AND flush RX FIFO if required. */ if (p->port.rs485.delay_rts_after_send > 0) { @@ -1504,20 +1490,16 @@ start_hrtimer_ms(&em485->stop_tx_timer, p->port.rs485.delay_rts_after_send); } else { - __do_stop_tx_rs485(p); + p->rs485_stop_tx(p); + em485->active_timer = NULL; + em485->tx_stopped = true; } } static inline void __do_stop_tx(struct uart_8250_port *p) { - if (p->ier & UART_IER_THRI) { - p->ier &= ~UART_IER_THRI; -#ifdef CONFIG_ARCH_ROCKCHIP - p->ier &= ~UART_IER_PTIME; -#endif - serial_out(p, UART_IER, p->ier); + if (serial8250_clear_THRI(p)) serial8250_rpm_put_tx(p); - } } static inline void __stop_tx(struct uart_8250_port *p) @@ -1526,6 +1508,8 @@ if (em485) { unsigned char lsr = serial_in(p, UART_LSR); + p->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; + /* * To provide required timeing and allow FIFO transfer, * __stop_tx_rs485() must be called only when both FIFO and @@ -1534,8 +1518,6 @@ */ if ((lsr & BOTH_EMPTY) != BOTH_EMPTY) return; - - em485->active_timer = NULL; __stop_tx_rs485(p); } @@ -1571,13 +1553,7 @@ return; #endif - if (!(up->ier & UART_IER_THRI)) { - up->ier |= UART_IER_THRI; -#ifdef CONFIG_ARCH_ROCKCHIP - up->ier |= UART_IER_PTIME; -#endif - serial_port_out(port, UART_IER, up->ier); - + if (serial8250_set_THRI(up)) { if (up->bugs & UART_BUG_TXEN) { unsigned char lsr; @@ -1597,25 +1573,54 @@ } } -static inline void start_tx_rs485(struct uart_port *port) +/** + * serial8250_em485_start_tx() - generic ->rs485_start_tx() callback + * @up: uart 8250 port + * + * Generic callback usable by 8250 uart drivers to start rs485 transmission. + * Assumes that setting the RTS bit in the MCR register means RTS is high. + * (Some chips use inverse semantics.) Further assumes that reception is + * stoppable by disabling the UART_IER_RDI interrupt. (Some chips set the + * UART_LSR_DR bit even when UART_IER_RDI is disabled, foiling this approach.) + */ +void serial8250_em485_start_tx(struct uart_8250_port *up) { - struct uart_8250_port *up = up_to_u8250p(port); - struct uart_8250_em485 *em485 = up->em485; - unsigned char mcr; + unsigned char mcr = serial8250_in_MCR(up); if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) serial8250_stop_rx(&up->port); + if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND) + mcr |= UART_MCR_RTS; + else + mcr &= ~UART_MCR_RTS; + serial8250_out_MCR(up, mcr); +} +EXPORT_SYMBOL_GPL(serial8250_em485_start_tx); + +static inline void start_tx_rs485(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + struct uart_8250_em485 *em485 = up->em485; + + /* + * While serial8250_em485_handle_stop_tx() is a noop if + * em485->active_timer != &em485->stop_tx_timer, it might happen that + * the timer is still armed and triggers only after the current bunch of + * chars is send and em485->active_timer == &em485->stop_tx_timer again. + * So cancel the timer. There is still a theoretical race condition if + * the timer is already running and only comes around to check for + * em485->active_timer when &em485->stop_tx_timer is armed again. + */ + if (em485->active_timer == &em485->stop_tx_timer) + hrtimer_try_to_cancel(&em485->stop_tx_timer); + em485->active_timer = NULL; - mcr = serial8250_in_MCR(up); - if (!!(up->port.rs485.flags & SER_RS485_RTS_ON_SEND) != - !!(mcr & UART_MCR_RTS)) { - if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND) - mcr |= UART_MCR_RTS; - else - mcr &= ~UART_MCR_RTS; - serial8250_out_MCR(up, mcr); + if (em485->tx_stopped) { + em485->tx_stopped = false; + + up->rs485_start_tx(up); if (up->port.rs485.delay_rts_before_send > 0) { em485->active_timer = &em485->start_tx_timer; @@ -1681,6 +1686,8 @@ if (up->bugs & UART_BUG_NOMSR) return; + mctrl_gpio_disable_ms(up->gpios); + up->ier &= ~UART_IER_MSI; serial_port_out(port, UART_IER, up->ier); } @@ -1692,6 +1699,8 @@ /* no MSR capabilities */ if (up->bugs & UART_BUG_NOMSR) return; + + mctrl_gpio_enable_ms(up->gpios); up->ier |= UART_IER_MSI; @@ -1748,14 +1757,14 @@ lsr &= port->read_status_mask; if (lsr & UART_LSR_BI) { - pr_debug("%s: handling break\n", __func__); + dev_dbg(port->dev, "handling break\n"); flag = TTY_BREAK; } else if (lsr & UART_LSR_PE) flag = TTY_PARITY; else if (lsr & UART_LSR_FE) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(port, ch)) + if (uart_prepare_sysrq_char(port, ch)) return; uart_insert_char(port, lsr, UART_LSR_OE, ch, flag); @@ -1791,9 +1800,7 @@ int count; if (port->x_char) { - serial_out(up, UART_TX, port->x_char); - port->icount.tx++; - port->x_char = 0; + uart_xchar_out(port, UART_TX); return; } if (uart_tx_stopped(port)) { @@ -1808,6 +1815,18 @@ count = up->tx_loadsz; do { serial_out(up, UART_TX, xmit->buf[xmit->tail]); + if (up->bugs & UART_BUG_TXRACE) { + /* + * The Aspeed BMC virtual UARTs have a bug where data + * may get stuck in the BMC's Tx FIFO from bursts of + * writes on the APB interface. + * + * Delay back-to-back writes by a read cycle to avoid + * stalling the VUART. Read a register that won't have + * side-effects and discard the result. + */ + serial_in(up, UART_SCR); + } xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; if (uart_circ_empty(xmit)) @@ -1869,10 +1888,13 @@ return up->dma->rx_dma(up); #else switch (iir & 0x3f) { + case UART_IIR_RDI: + if (!up->dma->rx_running) + break; + fallthrough; + case UART_IIR_RLSI: case UART_IIR_RX_TIMEOUT: serial8250_rx_dma_flush(up); - /* fall-through */ - case UART_IIR_RLSI: return true; } return up->dma->rx_dma(up); @@ -1887,7 +1909,10 @@ unsigned char status; unsigned long flags; struct uart_8250_port *up = up_to_u8250p(port); +#ifndef CONFIG_ARCH_ROCKCHIP + struct tty_port *tport = &port->state->port; bool skip_rx = false; +#endif if (iir & UART_IIR_NO_INT) return 0; @@ -1896,6 +1921,17 @@ status = serial_port_in(port, UART_LSR); +#ifdef CONFIG_ARCH_ROCKCHIP + if (status & (UART_LSR_DR | UART_LSR_BI)) { + int dma_err = -1; + + if (up->dma && up->dma->rxchan) + dma_err = handle_rx_dma(up, iir); + + if (!up->dma || dma_err) + status = serial8250_rx_chars(up, status); + } +#else /* * If port is stopped and there are no error conditions in the * FIFO, then don't drain the FIFO, as this may lead to TTY buffer @@ -1910,27 +1946,23 @@ skip_rx = true; if (status & (UART_LSR_DR | UART_LSR_BI) && !skip_rx) { -#ifdef CONFIG_ARCH_ROCKCHIP - int dma_err = -1; + struct irq_data *d; - if (up->dma && up->dma->rxchan) - dma_err = handle_rx_dma(up, iir); - - if (!up->dma || dma_err) - status = serial8250_rx_chars(up, status); -#else + d = irq_get_irq_data(port->irq); + if (d && irqd_is_wakeup_set(d)) + pm_wakeup_event(tport->tty->dev, 0); if (!up->dma || handle_rx_dma(up, iir)) status = serial8250_rx_chars(up, status); -#endif } +#endif serial8250_modem_status(up); #ifdef CONFIG_ARCH_ROCKCHIP if ((!up->dma || (up->dma && (!up->dma->txchan || up->dma->tx_err))) && ((iir & 0xf) == UART_IIR_THRI)) serial8250_tx_chars(up); #else - if ((!up->dma || up->dma->tx_err) && (status & UART_LSR_THRE) && - (up->ier & UART_IER_THRI)) + if ((!up->dma || (up->dma && up->dma->tx_err)) && + (status & UART_LSR_THRE)) serial8250_tx_chars(up); #endif @@ -1950,7 +1982,7 @@ port->name); } #endif - spin_unlock_irqrestore(&port->lock, flags); + uart_unlock_and_check_sysrq(port, flags); return 1; } EXPORT_SYMBOL_GPL(serial8250_handle_irq); @@ -1997,41 +2029,42 @@ static unsigned int serial8250_tx_empty(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); + unsigned int result = 0; 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; + if (!serial8250_tx_dma_running(up)) { + lsr = serial_port_in(port, UART_LSR); + up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; + + if ((lsr & BOTH_EMPTY) == BOTH_EMPTY) + result = TIOCSER_TEMT; + } spin_unlock_irqrestore(&port->lock, flags); serial8250_rpm_put(up); - return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0; + return result; } unsigned int serial8250_do_get_mctrl(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); unsigned int status; - unsigned int ret; + unsigned int val; serial8250_rpm_get(up); status = serial8250_modem_status(up); serial8250_rpm_put(up); - ret = 0; - if (status & UART_MSR_DCD) - ret |= TIOCM_CAR; - if (status & UART_MSR_RI) - ret |= TIOCM_RNG; - if (status & UART_MSR_DSR) - ret |= TIOCM_DSR; - if (status & UART_MSR_CTS) - ret |= TIOCM_CTS; - return ret; + val = serial8250_MSR_to_TIOCM(status); + if (up->gpios) + return mctrl_gpio_get(up->gpios, &val); + + return val; } EXPORT_SYMBOL_GPL(serial8250_do_get_mctrl); @@ -2045,18 +2078,9 @@ 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; + unsigned char mcr; - if (mctrl & TIOCM_RTS) - mcr |= UART_MCR_RTS; - if (mctrl & TIOCM_DTR) - mcr |= UART_MCR_DTR; - if (mctrl & TIOCM_OUT1) - mcr |= UART_MCR_OUT1; - if (mctrl & TIOCM_OUT2) - mcr |= UART_MCR_OUT2; - if (mctrl & TIOCM_LOOP) - mcr |= UART_MCR_LOOP; + mcr = serial8250_TIOCM_to_MCR(mctrl); mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr; @@ -2066,6 +2090,9 @@ static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl) { + if (port->rs485.flags & SER_RS485_ENABLED) + return; + if (port->set_mctrl) port->set_mctrl(port, mctrl); else @@ -2245,20 +2272,6 @@ enable_rsa(up); #endif - if (port->type == PORT_XR17V35X) { - /* - * First enable access to IER [7:5], ISR [5:4], FCR [5:4], - * MCR [7:5] and MSR [7:0] - */ - serial_port_out(port, UART_XR_EFR, UART_EFR_ECB); - - /* - * Make sure all interrups are masked until initialization is - * complete and the FIFOs are cleared - */ - serial_port_out(port, UART_IER, 0); - } - /* * Clear the FIFO buffers and disable them. * (they will be reenabled in set_termios()) @@ -2272,8 +2285,6 @@ serial_port_in(port, UART_RX); serial_port_in(port, UART_IIR); serial_port_in(port, UART_MSR); - if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X)) - serial_port_in(port, UART_EXAR_INT0); /* * At this point, there's no way the LSR could still be 0xff; @@ -2282,7 +2293,7 @@ */ if (!(port->flags & UPF_BUGGY_UART) && (serial_port_in(port, UART_LSR) == 0xff)) { - pr_info_ratelimited("%s: LSR safety check engaged!\n", port->name); + dev_info_ratelimited(port->dev, "LSR safety check engaged!\n"); retval = -ENODEV; goto out; } @@ -2314,8 +2325,7 @@ (port->type == PORT_ALTR_16550_F128)) && (port->fifosize > 1)) { /* Bounds checking of TX threshold (valid 0 to fifosize-2) */ if ((up->tx_loadsz < 2) || (up->tx_loadsz > port->fifosize)) { - pr_err("%s TX FIFO Threshold errors, skipping\n", - port->name); + dev_err(port->dev, "TX FIFO Threshold errors, skipping\n"); } else { serial_port_out(port, UART_ALTR_AFR, UART_ALTR_EN_TXFIFO_LW); @@ -2419,8 +2429,7 @@ if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) { if (!(up->bugs & UART_BUG_TXEN)) { up->bugs |= UART_BUG_TXEN; - pr_debug("%s - enabling bad tx status workarounds\n", - port->name); + dev_dbg(port->dev, "enabling bad tx status workarounds\n"); } } else { up->bugs &= ~UART_BUG_TXEN; @@ -2438,8 +2447,6 @@ serial_port_in(port, UART_RX); serial_port_in(port, UART_IIR); serial_port_in(port, UART_MSR); - if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X)) - serial_port_in(port, UART_EXAR_INT0); up->lsr_saved_flags = 0; up->msr_saved_flags = 0; @@ -2447,15 +2454,18 @@ * Request DMA channels for both RX and TX. */ if (up->dma) { - retval = serial8250_request_dma(up); - if (retval) { + const char *msg = NULL; + + if (uart_console(port)) + msg = "forbid DMA for kernel console"; + else if (serial8250_request_dma(up)) #ifdef CONFIG_ARCH_ROCKCHIP - pr_warn_ratelimited("%s - failed to request DMA, use interrupt mode\n", - port->name); + msg = "failed to request DMA, use interrupt mode"; #else - pr_warn_ratelimited("%s - failed to request DMA\n", - port->name); + msg = "failed to request DMA"; #endif + if (msg) { + dev_warn_ratelimited(port->dev, "%s\n", msg); up->dma = NULL; } } @@ -2553,23 +2563,6 @@ serial8250_do_shutdown(port); } -/* - * XR17V35x UARTs have an extra fractional divisor register (DLD) - * Calculate divisor with extra 4-bit fractional portion - */ -static unsigned int xr17v35x_get_divisor(struct uart_8250_port *up, - unsigned int baud, - unsigned int *frac) -{ - struct uart_port *port = &up->port; - unsigned int quot_16; - - quot_16 = DIV_ROUND_CLOSEST(port->uartclk, baud); - *frac = quot_16 & 0x0f; - - return quot_16 >> 4; -} - /* Nuvoton NPCM UARTs have a custom divisor calculation */ static unsigned int npcm_get_divisor(struct uart_8250_port *up, unsigned int baud) @@ -2597,8 +2590,6 @@ else if ((port->flags & UPF_MAGIC_MULTIPLIER) && baud == (port->uartclk/8)) quot = 0x8002; - else if (up->port.type == PORT_XR17V35X) - quot = xr17v35x_get_divisor(up, baud, frac); else if (up->port.type == PORT_NPCM) quot = npcm_get_divisor(up, baud); else @@ -2700,13 +2691,6 @@ #ifdef CONFIG_ARCH_ROCKCHIP serial_port_out(port, UART_MCR, up->mcr); #endif - - /* XR17V35x UARTs have an extra fractional divisor register (DLD) */ - if (up->port.type == PORT_XR17V35X) { - /* Preserve bits not related to baudrate; DLD[7:4]. */ - quot_frac |= serial_port_in(port, 0x2) & 0xf0; - serial_port_out(port, 0x2, quot_frac); - } } EXPORT_SYMBOL_GPL(serial8250_do_set_divisor); @@ -2748,6 +2732,62 @@ */ return uart_get_baud_rate(port, termios, old, min, max); } + +/* + * Note in order to avoid the tty port mutex deadlock don't use the next method + * within the uart port callbacks. Primarily it's supposed to be utilized to + * handle a sudden reference clock rate change. + */ +void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk) +{ + struct uart_8250_port *up = up_to_u8250p(port); + struct tty_port *tport = &port->state->port; + unsigned int baud, quot, frac = 0; + struct ktermios *termios; + struct tty_struct *tty; + unsigned long flags; + + tty = tty_port_tty_get(tport); + if (!tty) { + mutex_lock(&tport->mutex); + port->uartclk = uartclk; + mutex_unlock(&tport->mutex); + return; + } + + down_write(&tty->termios_rwsem); + mutex_lock(&tport->mutex); + + if (port->uartclk == uartclk) + goto out_lock; + + port->uartclk = uartclk; + + if (!tty_port_initialized(tport)) + goto out_lock; + + termios = &tty->termios; + + baud = serial8250_get_baud_rate(port, termios, NULL); + quot = serial8250_get_divisor(port, baud, &frac); + + serial8250_rpm_get(up); + spin_lock_irqsave(&port->lock, flags); + + uart_update_timeout(port, termios->c_cflag, baud); + + serial8250_set_divisor(port, baud, quot, frac); + serial_port_out(port, UART_LCR, up->lcr); + + spin_unlock_irqrestore(&port->lock, flags); + serial8250_rpm_put(up); + +out_lock: + mutex_unlock(&tport->mutex); + up_write(&tty->termios_rwsem); + tty_kref_put(tty); +} +EXPORT_SYMBOL_GPL(serial8250_update_uartclk); void serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, @@ -2864,7 +2904,7 @@ } #ifdef CONFIG_ARCH_ROCKCHIP - /* Reset uart to make sure it is idle, then set buad rate */ + /* Reset uart to make sure it is idle, then set baud rate */ serial_port_out(port, 0x88 >> 2, 0x7); #endif @@ -3002,8 +3042,10 @@ case UPIO_MEM32BE: case UPIO_MEM16: case UPIO_MEM: - if (!port->mapbase) + if (!port->mapbase) { + ret = -EINVAL; break; + } if (!request_mem_region(port->mapbase, size, "serial")) { ret = -EBUSY; @@ -3011,7 +3053,7 @@ } if (port->flags & UPF_IOREMAP) { - port->membase = ioremap_nocache(port->mapbase, size); + port->membase = ioremap(port->mapbase, size); if (!port->membase) { release_mem_region(port->mapbase, size); ret = -ENOMEM; @@ -3122,7 +3164,7 @@ return rxtrig_bytes; } -static ssize_t serial8250_get_attr_rx_trig_bytes(struct device *dev, +static ssize_t rx_trig_bytes_show(struct device *dev, struct device_attribute *attr, char *buf) { struct tty_port *port = dev_get_drvdata(dev); @@ -3168,7 +3210,7 @@ return ret; } -static ssize_t serial8250_set_attr_rx_trig_bytes(struct device *dev, +static ssize_t rx_trig_bytes_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct tty_port *port = dev_get_drvdata(dev); @@ -3189,18 +3231,16 @@ return count; } -static DEVICE_ATTR(rx_trig_bytes, S_IRUSR | S_IWUSR | S_IRGRP, - serial8250_get_attr_rx_trig_bytes, - serial8250_set_attr_rx_trig_bytes); +static DEVICE_ATTR_RW(rx_trig_bytes); static struct attribute *serial8250_dev_attrs[] = { &dev_attr_rx_trig_bytes.attr, - NULL, - }; + NULL +}; static struct attribute_group serial8250_dev_attr_group = { .attrs = serial8250_dev_attrs, - }; +}; static void register_dev_spec_attr_grp(struct uart_8250_port *up) { @@ -3299,7 +3339,9 @@ struct uart_port *port = &up->port; spin_lock_init(&port->lock); + port->pm = NULL; port->ops = &serial8250_pops; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); up->cur_iotype = 0xFF; } @@ -3360,7 +3402,7 @@ serial8250_set_divisor(port, baud, quot, frac); serial_port_out(port, UART_LCR, up->lcr); - serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS); + serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS); } /* @@ -3368,10 +3410,14 @@ * any possible real use of the port... * * The console_lock must be held when we get here. + * + * Doing runtime PM is really a bad idea for the kernel console. + * Thus, we assume the function is called when device is powered up. */ void serial8250_console_write(struct uart_8250_port *up, const char *s, unsigned int count) { + struct uart_8250_em485 *em485 = up->em485; struct uart_port *port = &up->port; unsigned long flags; unsigned int ier; @@ -3379,11 +3425,7 @@ touch_nmi_watchdog(); - serial8250_rpm_get(up); - - if (port->sysrq || oops_in_progress) - locked = 0; - else if (in_kdb_printk()) + if (oops_in_progress) locked = spin_trylock_irqsave(&port->lock, flags); else spin_lock_irqsave(&port->lock, flags); @@ -3404,6 +3446,12 @@ up->canary = 0; } + if (em485) { + if (em485->tx_stopped) + up->rs485_start_tx(up); + mdelay(port->rs485.delay_rts_before_send); + } + uart_console_write(port, s, count, serial8250_console_putchar); /* @@ -3411,6 +3459,13 @@ * and restore the IER */ wait_for_xmitr(up, BOTH_EMPTY); + + if (em485) { + mdelay(port->rs485.delay_rts_after_send); + if (em485->tx_stopped) + up->rs485_stop_tx(up); + } + serial_port_out(port, UART_IER, ier); /* @@ -3425,7 +3480,6 @@ if (locked) spin_unlock_irqrestore(&port->lock, flags); - serial8250_rpm_put(up); } static unsigned int probe_baud(struct uart_port *port) @@ -3449,6 +3503,7 @@ int bits = 8; int parity = 'n'; int flow = 'n'; + int ret; if (!port->iobase && !port->membase) return -ENODEV; @@ -3458,7 +3513,22 @@ else if (probe) baud = probe_baud(port); - return uart_set_options(port, port->cons, baud, parity, bits, flow); + ret = uart_set_options(port, port->cons, baud, parity, bits, flow); + if (ret) + return ret; + + if (port->dev) + pm_runtime_get_sync(port->dev); + + return 0; +} + +int serial8250_console_exit(struct uart_port *port) +{ + if (port->dev) + pm_runtime_put_sync(port->dev); + + return 0; } #endif /* CONFIG_SERIAL_8250_CONSOLE */ -- Gitblit v1.6.2