diff options
Diffstat (limited to 'drivers/tty/serial/8250/8250_omap.c')
| -rw-r--r-- | drivers/tty/serial/8250/8250_omap.c | 1131 |
1 files changed, 744 insertions, 387 deletions
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index ad7ba7d0f28d..9e49ef48b851 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -8,10 +8,8 @@ * */ -#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - +#include <linux/atomic.h> +#include <linux/clk.h> #include <linux/device.h> #include <linux/io.h> #include <linux/module.h> @@ -21,8 +19,6 @@ #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_gpio.h> #include <linux/of_irq.h> #include <linux/delay.h> #include <linux/pm_runtime.h> @@ -30,10 +26,14 @@ #include <linux/pm_qos.h> #include <linux/pm_wakeirq.h> #include <linux/dma-mapping.h> +#include <linux/sys_soc.h> +#include <linux/reboot.h> +#include <linux/pinctrl/consumer.h> #include "8250.h" #define DEFAULT_CLK_SPEED 48000000 +#define OMAP_UART_REGSHIFT 2 #define UART_ERRATA_i202_MDR1_ACCESS (1 << 0) #define OMAP_UART_WER_HAS_TX_WAKEUP (1 << 1) @@ -43,6 +43,10 @@ * The same errata is applicable to AM335x and DRA7x processors too. */ #define UART_ERRATA_CLOCK_DISABLE (1 << 3) +#define UART_HAS_EFR2 BIT(4) +#define UART_HAS_RHR_IT_DIS BIT(5) +#define UART_RX_TIMEOUT_QUIRK BIT(6) +#define UART_HAS_NATIVE_RS485 BIT(7) #define OMAP_UART_FCR_RX_TRIG 6 #define OMAP_UART_FCR_TX_TRIG 4 @@ -96,10 +100,32 @@ #define OMAP_UART_REV_52 0x0502 #define OMAP_UART_REV_63 0x0603 +/* Interrupt Enable Register 2 */ +#define UART_OMAP_IER2 0x1B +#define UART_OMAP_IER2_RHR_IT_DIS BIT(2) + +/* Mode Definition Register 3 */ +#define UART_OMAP_MDR3 0x20 +#define UART_OMAP_MDR3_DIR_POL BIT(3) +#define UART_OMAP_MDR3_DIR_EN BIT(4) + +/* Enhanced features register 2 */ +#define UART_OMAP_EFR2 0x23 +#define UART_OMAP_EFR2_TIMEOUT_BEHAVE BIT(6) + +/* RX FIFO occupancy indicator */ +#define UART_OMAP_RX_LVL 0x19 + +/* Timeout low and High */ +#define UART_OMAP_TO_L 0x26 +#define UART_OMAP_TO_H 0x27 + struct omap8250_priv { + void __iomem *membase; int line; u8 habit; u8 mdr1; + u8 mdr3; u8 efr; u8 scr; u8 wer; @@ -108,9 +134,11 @@ struct omap8250_priv { u8 delayed_restore; u16 quot; + u8 tx_trigger; + u8 rx_trigger; + atomic_t active; bool is_suspending; int wakeirq; - int wakeups_enabled; u32 latency; u32 calc_latency; struct pm_qos_request pm_qos_request; @@ -119,6 +147,20 @@ struct omap8250_priv { spinlock_t rx_dma_lock; bool rx_dma_broken; bool throttled; + + struct pinctrl *pinctrl; + struct pinctrl_state *pinctrl_wakeup; +}; + +struct omap8250_dma_params { + u32 rx_size; + u8 rx_trigger; + u8 tx_trigger; +}; + +struct omap8250_platdata { + struct omap8250_dma_params *dma_params; + u8 habit; }; #ifdef CONFIG_SERIAL_8250_DMA @@ -127,31 +169,51 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p); static inline void omap_8250_rx_dma_flush(struct uart_8250_port *p) { } #endif -static u32 uart_read(struct uart_8250_port *up, u32 reg) +static u32 uart_read(struct omap8250_priv *priv, u32 reg) { - return readl(up->port.membase + (reg << up->port.regshift)); + return readl(priv->membase + (reg << OMAP_UART_REGSHIFT)); } -static void omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl) +/* + * Called on runtime PM resume path from omap8250_restore_regs(), and + * omap8250_set_mctrl(). + */ +static void __omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl) { struct uart_8250_port *up = up_to_u8250p(port); - struct omap8250_priv *priv = up->port.private_data; + struct omap8250_priv *priv = port->private_data; u8 lcr; serial8250_do_set_mctrl(port, mctrl); - /* - * Turn off autoRTS if RTS is lowered and restore autoRTS setting - * if RTS is raised - */ - lcr = serial_in(up, UART_LCR); - serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); - if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS)) - priv->efr |= UART_EFR_RTS; - else - priv->efr &= ~UART_EFR_RTS; - serial_out(up, UART_EFR, priv->efr); - serial_out(up, UART_LCR, lcr); + if (!mctrl_gpio_to_gpiod(up->gpios, UART_GPIO_RTS)) { + /* + * Turn off autoRTS if RTS is lowered and restore autoRTS + * setting if RTS is raised + */ + lcr = serial_in(up, UART_LCR); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); + if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS)) + priv->efr |= UART_EFR_RTS; + else + priv->efr &= ~UART_EFR_RTS; + serial_out(up, UART_EFR, priv->efr); + serial_out(up, UART_LCR, lcr); + } +} + +static void omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + int err; + + err = pm_runtime_resume_and_get(port->dev); + if (err) + return; + + __omap8250_set_mctrl(port, mctrl); + + pm_runtime_mark_last_busy(port->dev); + pm_runtime_put_autosuspend(port->dev); } /* @@ -166,32 +228,10 @@ static void omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl) static void omap_8250_mdr1_errataset(struct uart_8250_port *up, struct omap8250_priv *priv) { - u8 timeout = 255; - u8 old_mdr1; - - old_mdr1 = serial_in(up, UART_OMAP_MDR1); - if (old_mdr1 == priv->mdr1) - return; - serial_out(up, UART_OMAP_MDR1, priv->mdr1); udelay(2); serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR); - /* - * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and - * TX_FIFO_E bit is 1. - */ - while (UART_LSR_THRE != (serial_in(up, UART_LSR) & - (UART_LSR_THRE | UART_LSR_DR))) { - timeout--; - if (!timeout) { - /* Should *never* happen. we warn and carry on */ - dev_crit(up->port.dev, "Errata i202: timedout %x\n", - serial_in(up, UART_LSR)); - break; - } - udelay(1); - } } static void omap_8250_get_divisor(struct uart_port *port, unsigned int baud, @@ -268,8 +308,13 @@ static void omap8250_update_mdr1(struct uart_8250_port *up, static void omap8250_restore_regs(struct uart_8250_port *up) { - struct omap8250_priv *priv = up->port.private_data; + struct uart_port *port = &up->port; + struct omap8250_priv *priv = port->private_data; struct uart_8250_dma *dma = up->dma; + u8 mcr = serial8250_in_MCR(up); + + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&port->lock); if (dma && dma->tx_running) { /* @@ -286,7 +331,7 @@ static void omap8250_restore_regs(struct uart_8250_port *up) serial_out(up, UART_EFR, UART_EFR_ECB); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); - serial8250_out_MCR(up, UART_MCR_TCRTLR); + serial8250_out_MCR(up, mcr | UART_MCR_TCRTLR); serial_out(up, UART_FCR, up->fcr); omap8250_update_scr(up, priv); @@ -296,13 +341,14 @@ static void omap8250_restore_regs(struct uart_8250_port *up) serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_RESTORE(16) | OMAP_UART_TCR_HALT(52)); serial_out(up, UART_TI752_TLR, - TRIGGER_TLR_MASK(TX_TRIGGER) << UART_TI752_TLR_TX | - TRIGGER_TLR_MASK(RX_TRIGGER) << UART_TI752_TLR_RX); + TRIGGER_TLR_MASK(priv->tx_trigger) << UART_TI752_TLR_TX | + TRIGGER_TLR_MASK(priv->rx_trigger) << UART_TI752_TLR_RX); serial_out(up, UART_LCR, 0); /* drop TCR + TLR access, we setup XON/XOFF later */ - serial8250_out_MCR(up, up->mcr); + serial8250_out_MCR(up, mcr); + serial_out(up, UART_IER, up->ier); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); @@ -319,37 +365,23 @@ static void omap8250_restore_regs(struct uart_8250_port *up) omap8250_update_mdr1(up, priv); - up->port.ops->set_mctrl(&up->port, up->port.mctrl); + __omap8250_set_mctrl(port, port->mctrl); + + serial_out(up, UART_OMAP_MDR3, priv->mdr3); + + if (port->rs485.flags & SER_RS485_ENABLED && + port->rs485_config == serial8250_em485_config) + serial8250_em485_stop_tx(up, true); } -/* - * OMAP can use "CLK / (16 or 13) / div" for baud rate. And then we have have - * some differences in how we want to handle flow control. - */ -static void omap_8250_set_termios(struct uart_port *port, - struct ktermios *termios, - struct ktermios *old) +static void omap_8250_set_termios_atomic(struct uart_port *port, struct ktermios *termios, + const struct ktermios *old, unsigned int baud) { struct uart_8250_port *up = up_to_u8250p(port); - struct omap8250_priv *priv = up->port.private_data; - unsigned char cval = 0; - unsigned int baud; + struct omap8250_priv *priv = port->private_data; + u8 cval; - switch (termios->c_cflag & CSIZE) { - case CS5: - cval = UART_LCR_WLEN5; - break; - case CS6: - cval = UART_LCR_WLEN6; - break; - case CS7: - cval = UART_LCR_WLEN7; - break; - default: - case CS8: - cval = UART_LCR_WLEN8; - break; - } + cval = UART_LCR_WLEN(tty_get_char_size(termios->c_cflag)); if (termios->c_cflag & CSTOPB) cval |= UART_LCR_STOP; @@ -360,59 +392,59 @@ static void omap_8250_set_termios(struct uart_port *port, if (termios->c_cflag & CMSPAR) cval |= UART_LCR_SPAR; - /* - * Ask the core to calculate the divisor for us. - */ - baud = uart_get_baud_rate(port, termios, old, - port->uartclk / 16 / UART_DIV_MAX, - port->uartclk / 13); omap_8250_get_divisor(port, baud, priv); /* * Ok, we're now changing the port state. Do it with * interrupts disabled. */ - pm_runtime_get_sync(port->dev); - spin_lock_irq(&port->lock); + guard(serial8250_rpm)(up); + guard(uart_port_lock_irq)(port); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); - up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; + /* + * Specify which conditions may be considered for error + * handling and the ignoring of characters. The actual + * ignoring of characters only occurs if the bit is set + * in @ignore_status_mask as well. + */ + port->read_status_mask = UART_LSR_OE | UART_LSR_DR; if (termios->c_iflag & INPCK) - up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; + port->read_status_mask |= UART_LSR_FE | UART_LSR_PE; if (termios->c_iflag & (IGNBRK | PARMRK)) - up->port.read_status_mask |= UART_LSR_BI; + port->read_status_mask |= UART_LSR_BI; /* * Characters to ignore */ - up->port.ignore_status_mask = 0; + port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) - up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; + port->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; if (termios->c_iflag & IGNBRK) { - up->port.ignore_status_mask |= UART_LSR_BI; + port->ignore_status_mask |= UART_LSR_BI; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) - up->port.ignore_status_mask |= UART_LSR_OE; + port->ignore_status_mask |= UART_LSR_OE; } /* * ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) - up->port.ignore_status_mask |= UART_LSR_DR; + port->ignore_status_mask |= UART_LSR_DR; /* * Modem status interrupts */ up->ier &= ~UART_IER_MSI; - if (UART_ENABLE_MS(&up->port, termios->c_cflag)) + if (UART_ENABLE_MS(port, termios->c_cflag)) up->ier |= UART_IER_MSI; up->lcr = cval; @@ -436,8 +468,8 @@ static void omap_8250_set_termios(struct uart_port *port, * This is because threshold and trigger values are the same. */ up->fcr = UART_FCR_ENABLE_FIFO; - up->fcr |= TRIGGER_FCR_MASK(TX_TRIGGER) << OMAP_UART_FCR_TX_TRIG; - up->fcr |= TRIGGER_FCR_MASK(RX_TRIGGER) << OMAP_UART_FCR_RX_TRIG; + up->fcr |= TRIGGER_FCR_MASK(priv->tx_trigger) << OMAP_UART_FCR_TX_TRIG; + up->fcr |= TRIGGER_FCR_MASK(priv->rx_trigger) << OMAP_UART_FCR_RX_TRIG; priv->scr = OMAP_UART_SCR_RX_TRIG_GRANU1_MASK | OMAP_UART_SCR_TX_EMPTY | OMAP_UART_SCR_TX_TRIG_GRANU1_MASK; @@ -450,13 +482,15 @@ static void omap_8250_set_termios(struct uart_port *port, priv->xoff = termios->c_cc[VSTOP]; priv->efr = 0; - up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF); + port->status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF); - if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) { + if (termios->c_cflag & CRTSCTS && port->flags & UPF_HARD_FLOW && + !mctrl_gpio_to_gpiod(up->gpios, UART_GPIO_RTS) && + !mctrl_gpio_to_gpiod(up->gpios, UART_GPIO_CTS)) { /* Enable AUTOCTS (autoRTS is enabled when RTS is raised) */ - up->port.status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS; + port->status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS; priv->efr |= UART_EFR_CTS; - } else if (up->port.flags & UPF_SOFT_FLOW) { + } else if (port->flags & UPF_SOFT_FLOW) { /* * OMAP rx s/w flow control is borked; the transmitter remains * stuck off even if rx flow control is subsequently disabled @@ -468,15 +502,32 @@ static void omap_8250_set_termios(struct uart_port *port, * Transmit XON1, XOFF1 */ if (termios->c_iflag & IXOFF) { - up->port.status |= UPSTAT_AUTOXOFF; + port->status |= UPSTAT_AUTOXOFF; priv->efr |= OMAP_UART_SW_TX; } } omap8250_restore_regs(up); +} - spin_unlock_irq(&up->port.lock); - pm_runtime_mark_last_busy(port->dev); - pm_runtime_put_autosuspend(port->dev); +/* + * OMAP can use "CLK / (16 or 13) / div" for baud rate. And then we have have + * some differences in how we want to handle flow control. + */ +static void omap_8250_set_termios(struct uart_port *port, + struct ktermios *termios, + const struct ktermios *old) +{ + struct omap8250_priv *priv = port->private_data; + unsigned int baud; + + /* + * Ask the core to calculate the divisor for us. + */ + baud = uart_get_baud_rate(port, termios, old, + port->uartclk / 16 / UART_DIV_MAX, + port->uartclk / 13); + + omap_8250_set_termios_atomic(port, termios, old, baud); /* calculate wakeup latency constraint */ priv->calc_latency = USEC_PER_SEC * 64 * 8 / baud; @@ -496,7 +547,10 @@ static void omap_8250_pm(struct uart_port *port, unsigned int state, struct uart_8250_port *up = up_to_u8250p(port); u8 efr; - pm_runtime_get_sync(port->dev); + guard(serial8250_rpm)(up); + /* Synchronize UART_IER access against the console. */ + guard(uart_port_lock_irq)(port); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); efr = serial_in(up, UART_EFR); serial_out(up, UART_EFR, efr | UART_EFR_ECB); @@ -506,18 +560,20 @@ static void omap_8250_pm(struct uart_port *port, unsigned int state, serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_EFR, efr); serial_out(up, UART_LCR, 0); - - pm_runtime_mark_last_busy(port->dev); - pm_runtime_put_autosuspend(port->dev); } static void omap_serial_fill_features_erratas(struct uart_8250_port *up, struct omap8250_priv *priv) { + static const struct soc_device_attribute k3_soc_devices[] = { + { .family = "AM65X", }, + { .family = "J721E", .revision = "SR1.0" }, + { /* sentinel */ } + }; u32 mvr, scheme; u16 revision, major, minor; - mvr = uart_read(up, UART_OMAP_MVER); + mvr = uart_read(priv, UART_OMAP_MVER); /* Check revision register scheme */ scheme = mvr >> OMAP_UART_MVR_SCHEME_SHIFT; @@ -561,6 +617,14 @@ static void omap_serial_fill_features_erratas(struct uart_8250_port *up, default: break; } + + /* + * AM65x SR1.0, AM65x SR2.0 and J721e SR1.0 don't + * don't have RHR_IT_DIS bit in IER2 register. So drop to flag + * to enable errata workaround. + */ + if (soc_device_match(k3_soc_devices)) + priv->habit &= ~UART_HAS_RHR_IT_DIS; } static void omap8250_uart_qos_work(struct work_struct *work) @@ -568,7 +632,7 @@ static void omap8250_uart_qos_work(struct work_struct *work) struct omap8250_priv *priv; priv = container_of(work, struct omap8250_priv, qos_work); - pm_qos_update_request(&priv->pm_qos_request, priv->latency); + cpu_latency_qos_update_request(&priv->pm_qos_request, priv->latency); } #ifdef CONFIG_SERIAL_8250_DMA @@ -577,22 +641,79 @@ static int omap_8250_dma_handle_irq(struct uart_port *port); static irqreturn_t omap8250_irq(int irq, void *dev_id) { - struct uart_port *port = dev_id; - struct uart_8250_port *up = up_to_u8250p(port); - unsigned int iir; + struct omap8250_priv *priv = dev_id; + struct uart_8250_port *up = serial8250_get_port(priv->line); + struct uart_port *port = &up->port; + unsigned int iir, lsr; int ret; + pm_runtime_get_noresume(port->dev); + + /* Shallow idle state wake-up to an IO interrupt? */ + if (atomic_add_unless(&priv->active, 1, 1)) { + priv->latency = priv->calc_latency; + schedule_work(&priv->qos_work); + } + #ifdef CONFIG_SERIAL_8250_DMA if (up->dma) { ret = omap_8250_dma_handle_irq(port); + pm_runtime_mark_last_busy(port->dev); + pm_runtime_put(port->dev); return IRQ_RETVAL(ret); } #endif - serial8250_rpm_get(up); + lsr = serial_port_in(port, UART_LSR); iir = serial_port_in(port, UART_IIR); ret = serial8250_handle_irq(port, iir); - serial8250_rpm_put(up); + + /* + * On K3 SoCs, it is observed that RX TIMEOUT is signalled after + * FIFO has been drained or erroneously. + * So apply solution of Errata i2310 as mentioned in + * https://www.ti.com/lit/pdf/sprz536 + */ + if (priv->habit & UART_RX_TIMEOUT_QUIRK && + (iir & UART_IIR_RX_TIMEOUT) == UART_IIR_RX_TIMEOUT && + serial_port_in(port, UART_OMAP_RX_LVL) == 0) { + unsigned char efr2, timeout_h, timeout_l; + + efr2 = serial_in(up, UART_OMAP_EFR2); + timeout_h = serial_in(up, UART_OMAP_TO_H); + timeout_l = serial_in(up, UART_OMAP_TO_L); + serial_out(up, UART_OMAP_TO_H, 0xFF); + serial_out(up, UART_OMAP_TO_L, 0xFF); + serial_out(up, UART_OMAP_EFR2, UART_OMAP_EFR2_TIMEOUT_BEHAVE); + serial_in(up, UART_IIR); + serial_out(up, UART_OMAP_EFR2, efr2); + serial_out(up, UART_OMAP_TO_H, timeout_h); + serial_out(up, UART_OMAP_TO_L, timeout_l); + } + + /* Stop processing interrupts on input overrun */ + if ((lsr & UART_LSR_OE) && up->overrun_backoff_time_ms > 0) { + unsigned long delay; + + /* Synchronize UART_IER access against the console. */ + uart_port_lock(port); + up->ier = serial_port_in(port, UART_IER); + if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) { + port->ops->stop_rx(port); + } else { + /* Keep restarting the timer until + * the input overrun subsides. + */ + cancel_delayed_work(&up->overrun_backoff); + } + uart_port_unlock(port); + + delay = msecs_to_jiffies(up->overrun_backoff_time_ms); + schedule_delayed_work(&up->overrun_backoff, delay); + } + + pm_runtime_mark_last_busy(port->dev); + pm_runtime_put(port->dev); return IRQ_RETVAL(ret); } @@ -601,6 +722,7 @@ static int omap_8250_startup(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); struct omap8250_priv *priv = port->private_data; + struct uart_8250_dma *dma = &priv->omap8250_dma; int ret; if (priv->wakeirq) { @@ -609,9 +731,12 @@ static int omap_8250_startup(struct uart_port *port) return ret; } - pm_runtime_get_sync(port->dev); +#ifdef CONFIG_PM + up->capabilities |= UART_CAP_RPM; +#endif + + guard(serial8250_rpm)(up); - up->mcr = 0; serial_out(up, UART_FCR, UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); serial_out(up, UART_LCR, UART_LCR_WLEN8); @@ -620,29 +745,23 @@ static int omap_8250_startup(struct uart_port *port) up->msr_saved_flags = 0; /* Disable DMA for console UART */ - if (uart_console(port)) - up->dma = NULL; - - if (up->dma) { + if (dma->fn && !uart_console(port)) { + up->dma = &priv->omap8250_dma; ret = serial8250_request_dma(up); if (ret) { dev_warn_ratelimited(port->dev, "failed to request DMA\n"); up->dma = NULL; } + } else { + up->dma = NULL; } - ret = request_irq(port->irq, omap8250_irq, IRQF_SHARED, - dev_name(port->dev), port); - if (ret < 0) - goto err; - - up->ier = UART_IER_RLSI | UART_IER_RDI; - serial_out(up, UART_IER, up->ier); - -#ifdef CONFIG_PM - up->capabilities |= UART_CAP_RPM; -#endif + /* Synchronize UART_IER access against the console. */ + scoped_guard(uart_port_lock_irq, port) { + up->ier = UART_IER_RLSI | UART_IER_RDI; + serial_out(up, UART_IER, up->ier); + } /* Enable module level wake up */ priv->wer = OMAP_UART_WER_MOD_WKUP; @@ -650,17 +769,14 @@ static int omap_8250_startup(struct uart_port *port) priv->wer |= OMAP_UART_TX_WAKEUP_EN; serial_out(up, UART_OMAP_WER, priv->wer); - if (up->dma) + if (up->dma && !(priv->habit & UART_HAS_EFR2)) { + guard(uart_port_lock_irq)(port); up->dma->rx_dma(up); + } + + enable_irq(port->irq); - pm_runtime_mark_last_busy(port->dev); - pm_runtime_put_autosuspend(port->dev); return 0; -err: - pm_runtime_mark_last_busy(port->dev); - pm_runtime_put_autosuspend(port->dev); - dev_pm_clear_wake_irq(port->dev); - return ret; } static void omap_8250_shutdown(struct uart_port *port) @@ -668,19 +784,27 @@ static void omap_8250_shutdown(struct uart_port *port) struct uart_8250_port *up = up_to_u8250p(port); struct omap8250_priv *priv = port->private_data; + guard(serial8250_rpm)(up); + flush_work(&priv->qos_work); if (up->dma) omap_8250_rx_dma_flush(up); - pm_runtime_get_sync(port->dev); - serial_out(up, UART_OMAP_WER, 0); + if (priv->habit & UART_HAS_EFR2) + serial_out(up, UART_OMAP_EFR2, 0x0); - up->ier = 0; - serial_out(up, UART_IER, 0); + /* Synchronize UART_IER access against the console. */ + scoped_guard(uart_port_lock_irq, port) { + up->ier = 0; + serial_out(up, UART_IER, 0); + } - if (up->dma) - serial8250_release_dma(up); + disable_irq_nosync(port->irq); + dev_pm_clear_wake_irq(port->dev); + + serial8250_release_dma(up); + up->dma = NULL; /* * Disable break condition and FIFOs @@ -688,110 +812,160 @@ static void omap_8250_shutdown(struct uart_port *port) if (up->lcr & UART_LCR_SBC) serial_out(up, UART_LCR, up->lcr & ~UART_LCR_SBC); serial_out(up, UART_FCR, UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); - - pm_runtime_mark_last_busy(port->dev); - pm_runtime_put_autosuspend(port->dev); - free_irq(port->irq, port); - dev_pm_clear_wake_irq(port->dev); } static void omap_8250_throttle(struct uart_port *port) { struct omap8250_priv *priv = port->private_data; - struct uart_8250_port *up = up_to_u8250p(port); - unsigned long flags; - pm_runtime_get_sync(port->dev); + guard(serial8250_rpm)(up_to_u8250p(port)); + guard(uart_port_lock_irqsave)(port); - spin_lock_irqsave(&port->lock, flags); - up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); - serial_out(up, UART_IER, up->ier); + port->ops->stop_rx(port); priv->throttled = true; - spin_unlock_irqrestore(&port->lock, flags); - - pm_runtime_mark_last_busy(port->dev); - pm_runtime_put_autosuspend(port->dev); } -static int omap_8250_rs485_config(struct uart_port *port, - struct serial_rs485 *rs485) +static void omap_8250_unthrottle(struct uart_port *port) { + struct omap8250_priv *priv = port->private_data; struct uart_8250_port *up = up_to_u8250p(port); - /* Clamp the delays to [0, 100ms] */ - rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U); - rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U); + guard(serial8250_rpm)(up); + /* Synchronize UART_IER access against the console. */ + guard(uart_port_lock_irqsave)(port); + + priv->throttled = false; + if (up->dma) + up->dma->rx_dma(up); + up->ier |= UART_IER_RLSI | UART_IER_RDI; + serial_out(up, UART_IER, up->ier); +} - port->rs485 = *rs485; +static int omap8250_rs485_config(struct uart_port *port, + struct ktermios *termios, + struct serial_rs485 *rs485) +{ + struct omap8250_priv *priv = port->private_data; + struct uart_8250_port *up = up_to_u8250p(port); + u32 fixed_delay_rts_before_send = 0; + u32 fixed_delay_rts_after_send = 0; + unsigned int baud; /* - * Both serial8250_em485_init and serial8250_em485_destroy - * are idempotent + * There is a fixed delay of 3 bit clock cycles after the TX shift + * register is going empty to allow time for the stop bit to transition + * through the transceiver before direction is changed to receive. + * + * Additionally there appears to be a 1 bit clock delay between writing + * to the THR register and transmission of the start bit, per page 8783 + * of the AM65 TRM: https://www.ti.com/lit/ug/spruid7e/spruid7e.pdf */ - if (rs485->flags & SER_RS485_ENABLED) { - int ret = serial8250_em485_init(up); + if (priv->quot) { + if (priv->mdr1 == UART_OMAP_MDR1_16X_MODE) + baud = port->uartclk / (16 * priv->quot); + else + baud = port->uartclk / (13 * priv->quot); - if (ret) { - rs485->flags &= ~SER_RS485_ENABLED; - port->rs485.flags &= ~SER_RS485_ENABLED; - } - return ret; + fixed_delay_rts_after_send = 3 * MSEC_PER_SEC / baud; + fixed_delay_rts_before_send = 1 * MSEC_PER_SEC / baud; } - serial8250_em485_destroy(up); + /* + * Fall back to RS485 software emulation if the UART is missing + * hardware support, if the device tree specifies an mctrl_gpio + * (indicates that RTS is unavailable due to a pinmux conflict) + * or if the requested delays exceed the fixed hardware delays. + */ + if (!(priv->habit & UART_HAS_NATIVE_RS485) || + mctrl_gpio_to_gpiod(up->gpios, UART_GPIO_RTS) || + rs485->delay_rts_after_send > fixed_delay_rts_after_send || + rs485->delay_rts_before_send > fixed_delay_rts_before_send) { + priv->mdr3 &= ~UART_OMAP_MDR3_DIR_EN; + serial_out(up, UART_OMAP_MDR3, priv->mdr3); + + port->rs485_config = serial8250_em485_config; + return serial8250_em485_config(port, termios, rs485); + } - return 0; -} + rs485->delay_rts_after_send = fixed_delay_rts_after_send; + rs485->delay_rts_before_send = fixed_delay_rts_before_send; -static void omap_8250_unthrottle(struct uart_port *port) -{ - struct omap8250_priv *priv = port->private_data; - struct uart_8250_port *up = up_to_u8250p(port); - unsigned long flags; + if (rs485->flags & SER_RS485_ENABLED) + priv->mdr3 |= UART_OMAP_MDR3_DIR_EN; + else + priv->mdr3 &= ~UART_OMAP_MDR3_DIR_EN; - pm_runtime_get_sync(port->dev); + /* + * Retain same polarity semantics as RS485 software emulation, + * i.e. SER_RS485_RTS_ON_SEND means driving RTS low on send. + */ + if (rs485->flags & SER_RS485_RTS_ON_SEND) + priv->mdr3 &= ~UART_OMAP_MDR3_DIR_POL; + else + priv->mdr3 |= UART_OMAP_MDR3_DIR_POL; - spin_lock_irqsave(&port->lock, flags); - priv->throttled = false; - if (up->dma) - up->dma->rx_dma(up); - up->ier |= UART_IER_RLSI | UART_IER_RDI; - serial_out(up, UART_IER, up->ier); - spin_unlock_irqrestore(&port->lock, flags); + serial_out(up, UART_OMAP_MDR3, priv->mdr3); - pm_runtime_mark_last_busy(port->dev); - pm_runtime_put_autosuspend(port->dev); + return 0; } #ifdef CONFIG_SERIAL_8250_DMA static int omap_8250_rx_dma(struct uart_8250_port *p); +/* Must be called while priv->rx_dma_lock is held */ static void __dma_rx_do_complete(struct uart_8250_port *p) { - struct omap8250_priv *priv = p->port.private_data; struct uart_8250_dma *dma = p->dma; struct tty_port *tty_port = &p->port.state->port; + struct omap8250_priv *priv = p->port.private_data; + struct dma_chan *rxchan = dma->rxchan; + dma_cookie_t cookie; struct dma_tx_state state; int count; - unsigned long flags; int ret; - - spin_lock_irqsave(&priv->rx_dma_lock, flags); + u32 reg; if (!dma->rx_running) - goto unlock; + goto out; + cookie = dma->rx_cookie; dma->rx_running = 0; - dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); - count = dma->rx_size - state.residue; + /* Re-enable RX FIFO interrupt now that transfer is complete */ + if (priv->habit & UART_HAS_RHR_IT_DIS) { + reg = serial_in(p, UART_OMAP_IER2); + reg &= ~UART_OMAP_IER2_RHR_IT_DIS; + serial_out(p, UART_OMAP_IER2, reg); + } + + dmaengine_tx_status(rxchan, cookie, &state); + count = dma->rx_size - state.residue + state.in_flight_bytes; + if (count < dma->rx_size) { + dmaengine_terminate_async(rxchan); + + /* + * Poll for teardown to complete which guarantees in + * flight data is drained. + */ + if (state.in_flight_bytes) { + int poll_count = 25; + + while (dmaengine_tx_status(rxchan, cookie, NULL) && + poll_count--) + cpu_relax(); + + if (poll_count == -1) + dev_err(p->port.dev, "teardown incomplete\n"); + } + } + if (!count) + goto out; ret = tty_insert_flip_string(tty_port, dma->rx_buf, count); p->port.icount.rx += ret; p->port.icount.buf_overrun += count - ret; -unlock: - spin_unlock_irqrestore(&priv->rx_dma_lock, flags); +out: tty_flip_buffer_push(tty_port); } @@ -802,25 +976,26 @@ static void __dma_rx_complete(void *param) struct omap8250_priv *priv = p->port.private_data; struct uart_8250_dma *dma = p->dma; struct dma_tx_state state; - unsigned long flags; - spin_lock_irqsave(&p->port.lock, flags); + /* Synchronize UART_IER access against the console. */ + guard(uart_port_lock_irqsave)(&p->port); /* * If the tx status is not DMA_COMPLETE, then this is a delayed * completion callback. A previous RX timeout flush would have * already pushed the data, so exit. */ - if (dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state) != - DMA_COMPLETE) { - spin_unlock_irqrestore(&p->port.lock, flags); + if (dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state) != DMA_COMPLETE) return; - } + __dma_rx_do_complete(p); - if (!priv->throttled) - omap_8250_rx_dma(p); + if (priv->throttled) + return; - spin_unlock_irqrestore(&p->port.lock, flags); + p->ier |= UART_IER_RLSI | UART_IER_RDI; + serial_out(p, UART_IER, p->ier); + if (!(priv->habit & UART_HAS_EFR2)) + omap_8250_rx_dma(p); } static void omap_8250_rx_dma_flush(struct uart_8250_port *p) @@ -844,10 +1019,8 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p) if (WARN_ON_ONCE(ret)) priv->rx_dma_broken = true; } - spin_unlock_irqrestore(&priv->rx_dma_lock, flags); - __dma_rx_do_complete(p); - dmaengine_terminate_all(dma->rxchan); + spin_unlock_irqrestore(&priv->rx_dma_lock, flags); } static int omap_8250_rx_dma(struct uart_8250_port *p) @@ -857,14 +1030,30 @@ static int omap_8250_rx_dma(struct uart_8250_port *p) int err = 0; struct dma_async_tx_descriptor *desc; unsigned long flags; + u32 reg; + + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&p->port.lock); if (priv->rx_dma_broken) return -EINVAL; spin_lock_irqsave(&priv->rx_dma_lock, flags); - if (dma->rx_running) + if (dma->rx_running) { + enum dma_status state; + + state = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, NULL); + if (state == DMA_COMPLETE) { + /* + * Disable RX interrupts to allow RX DMA completion + * callback to run. + */ + p->ier &= ~(UART_IER_RLSI | UART_IER_RDI); + serial_out(p, UART_IER, p->ier); + } goto out; + } desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr, dma->rx_size, DMA_DEV_TO_MEM, @@ -880,6 +1069,17 @@ static int omap_8250_rx_dma(struct uart_8250_port *p) dma->rx_cookie = dmaengine_submit(desc); + /* + * Disable RX FIFO interrupt while RX DMA is enabled, else + * spurious interrupt may be raised when data is in the RX FIFO + * but is yet to be drained by DMA. + */ + if (priv->habit & UART_HAS_RHR_IT_DIS) { + reg = serial_in(p, UART_OMAP_IER2); + reg |= UART_OMAP_IER2_RHR_IT_DIS; + serial_out(p, UART_OMAP_IER2, reg); + } + dma_async_issue_pending(dma->rxchan); out: spin_unlock_irqrestore(&priv->rx_dma_lock, flags); @@ -892,62 +1092,56 @@ static void omap_8250_dma_tx_complete(void *param) { struct uart_8250_port *p = param; struct uart_8250_dma *dma = p->dma; - struct circ_buf *xmit = &p->port.state->xmit; - unsigned long flags; + struct tty_port *tport = &p->port.state->port; bool en_thri = false; struct omap8250_priv *priv = p->port.private_data; dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr, UART_XMIT_SIZE, DMA_TO_DEVICE); - spin_lock_irqsave(&p->port.lock, flags); + guard(uart_port_lock_irqsave)(&p->port); dma->tx_running = 0; - xmit->tail += dma->tx_size; - xmit->tail &= UART_XMIT_SIZE - 1; - p->port.icount.tx += dma->tx_size; + uart_xmit_advance(&p->port, dma->tx_size); if (priv->delayed_restore) { priv->delayed_restore = 0; omap8250_restore_regs(p); } - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(&p->port); - if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port)) { + if (!kfifo_is_empty(&tport->xmit_fifo) && !uart_tx_stopped(&p->port)) { int ret; ret = omap_8250_tx_dma(p); if (ret) en_thri = true; - } else if (p->capabilities & UART_CAP_RPM) { en_thri = true; } if (en_thri) { dma->tx_err = 1; - p->ier |= UART_IER_THRI; - serial_port_out(&p->port, UART_IER, p->ier); + serial8250_set_THRI(p); } - - spin_unlock_irqrestore(&p->port.lock, flags); } static int omap_8250_tx_dma(struct uart_8250_port *p) { struct uart_8250_dma *dma = p->dma; struct omap8250_priv *priv = p->port.private_data; - struct circ_buf *xmit = &p->port.state->xmit; + struct tty_port *tport = &p->port.state->port; struct dma_async_tx_descriptor *desc; - unsigned int skip_byte = 0; + struct scatterlist sg; + int skip_byte = -1; int ret; if (dma->tx_running) return 0; - if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) { + if (uart_tx_stopped(&p->port) || kfifo_is_empty(&tport->xmit_fifo)) { /* * Even if no data, we need to return an error for the two cases @@ -958,15 +1152,12 @@ static int omap_8250_tx_dma(struct uart_8250_port *p) ret = -EBUSY; goto err; } - if (p->ier & UART_IER_THRI) { - p->ier &= ~UART_IER_THRI; - serial_out(p, UART_IER, p->ier); - } + serial8250_clear_THRI(p); return 0; } - dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); if (priv->habit & OMAP_DMA_TX_KICK) { + unsigned char c; u8 tx_lvl; /* @@ -989,22 +1180,32 @@ static int omap_8250_tx_dma(struct uart_8250_port *p) ret = -EBUSY; goto err; } - if (dma->tx_size < 4) { + if (kfifo_len(&tport->xmit_fifo) < 4) { + ret = -EINVAL; + goto err; + } + if (!uart_fifo_out(&p->port, &c, 1)) { ret = -EINVAL; goto err; } - skip_byte = 1; + skip_byte = c; + } + + sg_init_table(&sg, 1); + ret = kfifo_dma_out_prepare_mapped(&tport->xmit_fifo, &sg, 1, UART_XMIT_SIZE, dma->tx_addr); + if (ret != 1) { + ret = -EINVAL; + goto err; } - desc = dmaengine_prep_slave_single(dma->txchan, - dma->tx_addr + xmit->tail + skip_byte, - dma->tx_size - skip_byte, DMA_MEM_TO_DEV, + desc = dmaengine_prep_slave_sg(dma->txchan, &sg, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { ret = -EBUSY; goto err; } + dma->tx_size = sg_dma_len(&sg); dma->tx_running = 1; desc->callback = omap_8250_dma_tx_complete; @@ -1019,15 +1220,14 @@ static int omap_8250_tx_dma(struct uart_8250_port *p) if (dma->tx_err) dma->tx_err = 0; - if (p->ier & UART_IER_THRI) { - p->ier &= ~UART_IER_THRI; - serial_out(p, UART_IER, p->ier); - } - if (skip_byte) - serial_out(p, UART_TX, xmit->buf[xmit->tail]); - return 0; + serial8250_clear_THRI(p); + ret = 0; + goto out_skip; err: dma->tx_err = 1; +out_skip: + if (skip_byte >= 0) + serial_out(p, UART_TX, skip_byte); return ret; } @@ -1043,45 +1243,85 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir) return omap_8250_rx_dma(up); } +static u16 omap_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir, u16 status) +{ + if ((status & (UART_LSR_DR | UART_LSR_BI)) && + (iir & UART_IIR_RDI)) { + if (handle_rx_dma(up, iir)) { + status = serial8250_rx_chars(up, status); + omap_8250_rx_dma(up); + } + } + + return status; +} + +static void am654_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir, + u16 status) +{ + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&up->port.lock); + + /* + * Queue a new transfer if FIFO has data. + */ + if ((status & (UART_LSR_DR | UART_LSR_BI)) && + (up->ier & UART_IER_RDI)) { + omap_8250_rx_dma(up); + serial_out(up, UART_OMAP_EFR2, UART_OMAP_EFR2_TIMEOUT_BEHAVE); + } else if ((iir & 0x3f) == UART_IIR_RX_TIMEOUT) { + /* + * Disable RX timeout, read IIR to clear + * current timeout condition, clear EFR2 to + * periodic timeouts, re-enable interrupts. + */ + up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); + serial_out(up, UART_IER, up->ier); + omap_8250_rx_dma_flush(up); + serial_in(up, UART_IIR); + serial_out(up, UART_OMAP_EFR2, 0x0); + up->ier |= UART_IER_RLSI | UART_IER_RDI; + serial_out(up, UART_IER, up->ier); + } +} + /* * This is mostly serial8250_handle_irq(). We have a slightly different DMA - * hoook for RX/TX and need different logic for them in the ISR. Therefore we + * hook for RX/TX and need different logic for them in the ISR. Therefore we * use the default routine in the non-DMA case and this one for with DMA. */ static int omap_8250_dma_handle_irq(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); - unsigned char status; - unsigned long flags; + struct omap8250_priv *priv = port->private_data; + u16 status; u8 iir; - serial8250_rpm_get(up); - iir = serial_port_in(port, UART_IIR); if (iir & UART_IIR_NO_INT) { - serial8250_rpm_put(up); - return 0; + return IRQ_HANDLED; } - spin_lock_irqsave(&port->lock, flags); + uart_port_lock(port); status = serial_port_in(port, UART_LSR); - if (status & (UART_LSR_DR | UART_LSR_BI)) { - if (handle_rx_dma(up, iir)) { - status = serial8250_rx_chars(up, status); - omap_8250_rx_dma(up); - } + if ((iir & 0x3f) != UART_IIR_THRI) { + if (priv->habit & UART_HAS_EFR2) + am654_8250_handle_rx_dma(up, iir, status); + else + status = omap_8250_handle_rx_dma(up, iir, status); } + serial8250_modem_status(up); if (status & UART_LSR_THRE && up->dma->tx_err) { - if (uart_tx_stopped(&up->port) || - uart_circ_empty(&up->port.state->xmit)) { + if (uart_tx_stopped(port) || + kfifo_is_empty(&port->state->port.xmit_fifo)) { up->dma->tx_err = 0; serial8250_tx_chars(up); } else { /* - * try again due to an earlier failer which + * try again due to an earlier failure which * might have been resolved by now. */ if (omap_8250_tx_dma(up)) @@ -1089,8 +1329,8 @@ static int omap_8250_dma_handle_irq(struct uart_port *port) } } - uart_unlock_and_check_sysrq(port, flags); - serial8250_rpm_put(up); + uart_unlock_and_check_sysrq(port); + return 1; } @@ -1114,33 +1354,71 @@ static int omap8250_no_handle_irq(struct uart_port *port) return 0; } -static const u8 omap4_habit = UART_ERRATA_CLOCK_DISABLE; -static const u8 am3352_habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE; -static const u8 dra742_habit = UART_ERRATA_CLOCK_DISABLE; +static int omap8250_select_wakeup_pinctrl(struct device *dev, + struct omap8250_priv *priv) +{ + if (IS_ERR_OR_NULL(priv->pinctrl_wakeup)) + return 0; + + if (!device_may_wakeup(dev)) + return 0; + + return pinctrl_select_state(priv->pinctrl, priv->pinctrl_wakeup); +} + +static struct omap8250_dma_params am654_dma = { + .rx_size = SZ_2K, + .rx_trigger = 1, + .tx_trigger = TX_TRIGGER, +}; + +static struct omap8250_dma_params am33xx_dma = { + .rx_size = RX_TRIGGER, + .rx_trigger = RX_TRIGGER, + .tx_trigger = TX_TRIGGER, +}; + +static struct omap8250_platdata am654_platdata = { + .dma_params = &am654_dma, + .habit = UART_HAS_EFR2 | UART_HAS_RHR_IT_DIS | + UART_RX_TIMEOUT_QUIRK | UART_HAS_NATIVE_RS485, +}; + +static struct omap8250_platdata am33xx_platdata = { + .dma_params = &am33xx_dma, + .habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE, +}; + +static struct omap8250_platdata omap4_platdata = { + .dma_params = &am33xx_dma, + .habit = UART_ERRATA_CLOCK_DISABLE, +}; static const struct of_device_id omap8250_dt_ids[] = { - { .compatible = "ti,am654-uart" }, + { .compatible = "ti,am654-uart", .data = &am654_platdata, }, { .compatible = "ti,omap2-uart" }, { .compatible = "ti,omap3-uart" }, - { .compatible = "ti,omap4-uart", .data = &omap4_habit, }, - { .compatible = "ti,am3352-uart", .data = &am3352_habit, }, - { .compatible = "ti,am4372-uart", .data = &am3352_habit, }, - { .compatible = "ti,dra742-uart", .data = &dra742_habit, }, + { .compatible = "ti,omap4-uart", .data = &omap4_platdata, }, + { .compatible = "ti,am3352-uart", .data = &am33xx_platdata, }, + { .compatible = "ti,am4372-uart", .data = &am33xx_platdata, }, + { .compatible = "ti,dra742-uart", .data = &omap4_platdata, }, {}, }; MODULE_DEVICE_TABLE(of, omap8250_dt_ids); static int omap8250_probe(struct platform_device *pdev) { - struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + struct device_node *np = pdev->dev.of_node; struct omap8250_priv *priv; + const struct omap8250_platdata *pdata; struct uart_8250_port up; - int ret; + struct resource *regs; void __iomem *membase; + int ret; - if (!regs || !irq) { - dev_err(&pdev->dev, "missing registers or irq\n"); + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(&pdev->dev, "missing registers\n"); return -EINVAL; } @@ -1148,7 +1426,7 @@ static int omap8250_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - membase = devm_ioremap_nocache(&pdev->dev, regs->start, + membase = devm_ioremap(&pdev->dev, regs->start, resource_size(regs)); if (!membase) return -ENODEV; @@ -1157,7 +1435,6 @@ static int omap8250_probe(struct platform_device *pdev) up.port.dev = &pdev->dev; up.port.mapbase = regs->start; up.port.membase = membase; - up.port.irq = irq->start; /* * It claims to be 16C750 compatible however it is a little different. * It has EFR and has no FCR7_64byte bit. The AFE (which it claims to @@ -1167,13 +1444,9 @@ static int omap8250_probe(struct platform_device *pdev) * or pm callback. */ up.port.type = PORT_8250; - up.port.iotype = UPIO_MEM; - up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SOFT_FLOW | - UPF_HARD_FLOW; + up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SOFT_FLOW | UPF_HARD_FLOW; up.port.private_data = priv; - up.port.regshift = 2; - up.port.fifosize = 64; up.tx_loadsz = 64; up.capabilities = UART_CAP_FIFO; #ifdef CONFIG_PM @@ -1192,28 +1465,39 @@ static int omap8250_probe(struct platform_device *pdev) up.port.shutdown = omap_8250_shutdown; up.port.throttle = omap_8250_throttle; up.port.unthrottle = omap_8250_unthrottle; - up.port.rs485_config = omap_8250_rs485_config; + up.port.rs485_config = omap8250_rs485_config; + /* same rs485_supported for software emulation and native RS485 */ + up.port.rs485_supported = serial8250_em485_supported; + up.rs485_start_tx = serial8250_em485_start_tx; + up.rs485_stop_tx = serial8250_em485_stop_tx; + up.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); + + ret = uart_read_port_properties(&up.port); + if (ret) + return ret; - if (pdev->dev.of_node) { - const struct of_device_id *id; + up.port.regshift = OMAP_UART_REGSHIFT; + up.port.fifosize = 64; - ret = of_alias_get_id(pdev->dev.of_node, "serial"); + if (!up.port.uartclk) { + struct clk *clk; + + clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(clk)) { + if (PTR_ERR(clk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + } else { + up.port.uartclk = clk_get_rate(clk); + } + } - of_property_read_u32(pdev->dev.of_node, "clock-frequency", - &up.port.uartclk); - priv->wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1); + if (of_property_read_u32(np, "overrun-throttle-ms", + &up.overrun_backoff_time_ms) != 0) + up.overrun_backoff_time_ms = 0; - id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev); - if (id && id->data) - priv->habit |= *(u8 *)id->data; - } else { - ret = pdev->id; - } - if (ret < 0) { - dev_err(&pdev->dev, "failed to get alias/pdev id\n"); - return ret; - } - up.port.line = ret; + pdata = of_device_get_match_data(&pdev->dev); + if (pdata) + priv->habit |= pdata->habit; if (!up.port.uartclk) { up.port.uartclk = DEFAULT_CLK_SPEED; @@ -1222,78 +1506,127 @@ static int omap8250_probe(struct platform_device *pdev) DEFAULT_CLK_SPEED); } - priv->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; - priv->calc_latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; - pm_qos_add_request(&priv->pm_qos_request, PM_QOS_CPU_DMA_LATENCY, - priv->latency); + priv->membase = membase; + priv->line = -ENODEV; + priv->latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE; + priv->calc_latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE; + cpu_latency_qos_add_request(&priv->pm_qos_request, priv->latency); INIT_WORK(&priv->qos_work, omap8250_uart_qos_work); spin_lock_init(&priv->rx_dma_lock); - device_init_wakeup(&pdev->dev, true); - pm_runtime_use_autosuspend(&pdev->dev); - pm_runtime_set_autosuspend_delay(&pdev->dev, -1); + platform_set_drvdata(pdev, priv); + + device_set_wakeup_capable(&pdev->dev, true); + if (of_property_read_bool(np, "wakeup-source")) + device_set_wakeup_enable(&pdev->dev, true); - pm_runtime_irq_safe(&pdev->dev); pm_runtime_enable(&pdev->dev); + pm_runtime_use_autosuspend(&pdev->dev); + + /* + * Disable runtime PM until autosuspend delay unless specifically + * enabled by the user via sysfs. This is the historic way to + * prevent an unsafe default policy with lossy characters on wake-up. + * For serdev devices this is not needed, the policy can be managed by + * the serdev driver. + */ + if (!of_get_available_child_count(pdev->dev.of_node)) + pm_runtime_set_autosuspend_delay(&pdev->dev, -1); pm_runtime_get_sync(&pdev->dev); omap_serial_fill_features_erratas(&up, priv); up.port.handle_irq = omap8250_no_handle_irq; + priv->rx_trigger = RX_TRIGGER; + priv->tx_trigger = TX_TRIGGER; #ifdef CONFIG_SERIAL_8250_DMA - if (pdev->dev.of_node) { - /* - * Oh DMA support. If there are no DMA properties in the DT then - * we will fall back to a generic DMA channel which does not - * really work here. To ensure that we do not get a generic DMA - * channel assigned, we have the the_no_dma_filter_fn() here. - * To avoid "failed to request DMA" messages we check for DMA - * properties in DT. - */ - ret = of_property_count_strings(pdev->dev.of_node, "dma-names"); - if (ret == 2) { - up.dma = &priv->omap8250_dma; - priv->omap8250_dma.fn = the_no_dma_filter_fn; - priv->omap8250_dma.tx_dma = omap_8250_tx_dma; - priv->omap8250_dma.rx_dma = omap_8250_rx_dma; - priv->omap8250_dma.rx_size = RX_TRIGGER; - priv->omap8250_dma.rxconf.src_maxburst = RX_TRIGGER; - priv->omap8250_dma.txconf.dst_maxburst = TX_TRIGGER; + /* + * Oh DMA support. If there are no DMA properties in the DT then + * we will fall back to a generic DMA channel which does not + * really work here. To ensure that we do not get a generic DMA + * channel assigned, we have the the_no_dma_filter_fn() here. + * To avoid "failed to request DMA" messages we check for DMA + * properties in DT. + */ + ret = of_property_count_strings(np, "dma-names"); + if (ret == 2) { + struct omap8250_dma_params *dma_params = NULL; + struct uart_8250_dma *dma = &priv->omap8250_dma; + + dma->fn = the_no_dma_filter_fn; + dma->tx_dma = omap_8250_tx_dma; + dma->rx_dma = omap_8250_rx_dma; + if (pdata) + dma_params = pdata->dma_params; + + if (dma_params) { + dma->rx_size = dma_params->rx_size; + dma->rxconf.src_maxburst = dma_params->rx_trigger; + dma->txconf.dst_maxburst = dma_params->tx_trigger; + priv->rx_trigger = dma_params->rx_trigger; + priv->tx_trigger = dma_params->tx_trigger; + } else { + dma->rx_size = RX_TRIGGER; + dma->rxconf.src_maxburst = RX_TRIGGER; + dma->txconf.dst_maxburst = TX_TRIGGER; } } #endif + + irq_set_status_flags(up.port.irq, IRQ_NOAUTOEN); + ret = devm_request_irq(&pdev->dev, up.port.irq, omap8250_irq, 0, + dev_name(&pdev->dev), priv); + if (ret < 0) + goto err; + + priv->wakeirq = irq_of_parse_and_map(np, 1); + ret = serial8250_register_8250_port(&up); if (ret < 0) { dev_err(&pdev->dev, "unable to register 8250 port\n"); goto err; } priv->line = ret; - platform_set_drvdata(pdev, priv); pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_put_autosuspend(&pdev->dev); + + priv->pinctrl = devm_pinctrl_get(&pdev->dev); + if (!IS_ERR_OR_NULL(priv->pinctrl)) + priv->pinctrl_wakeup = pinctrl_lookup_state(priv->pinctrl, "wakeup"); + return 0; err: pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_put_sync(&pdev->dev); + flush_work(&priv->qos_work); pm_runtime_disable(&pdev->dev); + cpu_latency_qos_remove_request(&priv->pm_qos_request); return ret; } -static int omap8250_remove(struct platform_device *pdev) +static void omap8250_remove(struct platform_device *pdev) { struct omap8250_priv *priv = platform_get_drvdata(pdev); + struct uart_8250_port *up; + int err; + + err = pm_runtime_resume_and_get(&pdev->dev); + if (err) + dev_err(&pdev->dev, "Failed to resume hardware\n"); + up = serial8250_get_port(priv->line); + omap_8250_shutdown(&up->port); + serial8250_unregister_port(priv->line); + priv->line = -ENODEV; pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_put_sync(&pdev->dev); + flush_work(&priv->qos_work); pm_runtime_disable(&pdev->dev); - serial8250_unregister_port(priv->line); - pm_qos_remove_request(&priv->pm_qos_request); - device_init_wakeup(&pdev->dev, false); - return 0; + cpu_latency_qos_remove_request(&priv->pm_qos_request); + device_set_wakeup_capable(&pdev->dev, false); } -#ifdef CONFIG_PM_SLEEP static int omap8250_prepare(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); @@ -1317,33 +1650,57 @@ static int omap8250_suspend(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); struct uart_8250_port *up = serial8250_get_port(priv->line); + int err = 0; + + err = omap8250_select_wakeup_pinctrl(dev, priv); + if (err) { + dev_err(dev, "Failed to select wakeup pinctrl, aborting suspend %pe\n", + ERR_PTR(err)); + return err; + } serial8250_suspend_port(priv->line); - pm_runtime_get_sync(dev); + err = pm_runtime_resume_and_get(dev); + if (err) + return err; if (!device_may_wakeup(dev)) priv->wer = 0; serial_out(up, UART_OMAP_WER, priv->wer); - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); - + if (uart_console(&up->port) && console_suspend_enabled) + err = pm_runtime_force_suspend(dev); flush_work(&priv->qos_work); - return 0; + + return err; } static int omap8250_resume(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); + struct uart_8250_port *up = serial8250_get_port(priv->line); + int err; + + err = pinctrl_select_default_state(dev); + if (err) { + dev_err(dev, "Failed to select default pinctrl state on resume: %pe\n", + ERR_PTR(err)); + return err; + } + + if (uart_console(&up->port) && console_suspend_enabled) { + err = pm_runtime_force_resume(dev); + if (err) + return err; + } serial8250_resume_port(priv->line); + /* Paired with pm_runtime_resume_and_get() in omap8250_suspend() */ + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + return 0; } -#else -#define omap8250_prepare NULL -#define omap8250_complete NULL -#endif -#ifdef CONFIG_PM static int omap8250_lost_context(struct uart_8250_port *up) { u32 val; @@ -1359,11 +1716,15 @@ static int omap8250_lost_context(struct uart_8250_port *up) return 0; } +static void uart_write(struct omap8250_priv *priv, u32 reg, u32 val) +{ + writel(val, priv->membase + (reg << OMAP_UART_REGSHIFT)); +} + /* TODO: in future, this should happen via API in drivers/reset/ */ static int omap8250_soft_reset(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); - struct uart_8250_port *up = serial8250_get_port(priv->line); int timeout = 100; int sysc; int syss; @@ -1377,20 +1738,20 @@ static int omap8250_soft_reset(struct device *dev) * needing omap8250_soft_reset() quirk. Do it in two writes as * recommended in the comment for omap8250_update_scr(). */ - serial_out(up, UART_OMAP_SCR, OMAP_UART_SCR_DMAMODE_1); - serial_out(up, UART_OMAP_SCR, + uart_write(priv, UART_OMAP_SCR, OMAP_UART_SCR_DMAMODE_1); + uart_write(priv, UART_OMAP_SCR, OMAP_UART_SCR_DMAMODE_1 | OMAP_UART_SCR_DMAMODE_CTL); - sysc = serial_in(up, UART_OMAP_SYSC); + sysc = uart_read(priv, UART_OMAP_SYSC); /* softreset the UART */ sysc |= OMAP_UART_SYSC_SOFTRESET; - serial_out(up, UART_OMAP_SYSC, sysc); + uart_write(priv, UART_OMAP_SYSC, sysc); /* By experiments, 1us enough for reset complete on AM335x */ do { udelay(1); - syss = serial_in(up, UART_OMAP_SYSS); + syss = uart_read(priv, UART_OMAP_SYSS); } while (--timeout && !(syss & OMAP_UART_SYSS_RESETDONE)); if (!timeout) { @@ -1404,23 +1765,10 @@ static int omap8250_soft_reset(struct device *dev) static int omap8250_runtime_suspend(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); - struct uart_8250_port *up; + struct uart_8250_port *up = NULL; - /* In case runtime-pm tries this before we are setup */ - if (!priv) - return 0; - - up = serial8250_get_port(priv->line); - /* - * When using 'no_console_suspend', the console UART must not be - * suspended. Since driver suspend is managed by runtime suspend, - * preventing runtime suspend (by returning error) will keep device - * active during suspend. - */ - if (priv->is_suspending && !console_suspend_enabled) { - if (uart_console(&up->port)) - return -EBUSY; - } + if (priv->line >= 0) + up = serial8250_get_port(priv->line); if (priv->habit & UART_ERRATA_CLOCK_DISABLE) { int ret; @@ -1429,17 +1777,20 @@ static int omap8250_runtime_suspend(struct device *dev) if (ret) return ret; - /* Restore to UART mode after reset (for wakeup) */ - omap8250_update_mdr1(up, priv); - /* Restore wakeup enable register */ - serial_out(up, UART_OMAP_WER, priv->wer); + if (up) { + /* Restore to UART mode after reset (for wakeup) */ + omap8250_update_mdr1(up, priv); + /* Restore wakeup enable register */ + serial_out(up, UART_OMAP_WER, priv->wer); + } } - if (up->dma && up->dma->rxchan) + if (up && up->dma && up->dma->rxchan) omap_8250_rx_dma_flush(up); - priv->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; + priv->latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE; schedule_work(&priv->qos_work); + atomic_set(&priv->active, 0); return 0; } @@ -1447,25 +1798,31 @@ static int omap8250_runtime_suspend(struct device *dev) static int omap8250_runtime_resume(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); - struct uart_8250_port *up; + struct uart_8250_port *up = NULL; - /* In case runtime-pm tries this before we are setup */ - if (!priv) + /* Did the hardware wake to a device IO interrupt before a wakeirq? */ + if (atomic_read(&priv->active)) return 0; - up = serial8250_get_port(priv->line); + if (priv->line >= 0) + up = serial8250_get_port(priv->line); - if (omap8250_lost_context(up)) + if (up && omap8250_lost_context(up)) { + guard(uart_port_lock_irq)(&up->port); omap8250_restore_regs(up); + } - if (up->dma && up->dma->rxchan) + if (up && up->dma && up->dma->rxchan && !(priv->habit & UART_HAS_EFR2)) { + guard(uart_port_lock_irq)(&up->port); omap_8250_rx_dma(up); + } + atomic_set(&priv->active, 1); priv->latency = priv->calc_latency; schedule_work(&priv->qos_work); + return 0; } -#endif #ifdef CONFIG_SERIAL_8250_OMAP_TTYO_FIXUP static int __init omap8250_console_fixup(void) @@ -1508,17 +1865,17 @@ console_initcall(omap8250_console_fixup); #endif static const struct dev_pm_ops omap8250_dev_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(omap8250_suspend, omap8250_resume) - SET_RUNTIME_PM_OPS(omap8250_runtime_suspend, + SYSTEM_SLEEP_PM_OPS(omap8250_suspend, omap8250_resume) + RUNTIME_PM_OPS(omap8250_runtime_suspend, omap8250_runtime_resume, NULL) - .prepare = omap8250_prepare, - .complete = omap8250_complete, + .prepare = pm_sleep_ptr(omap8250_prepare), + .complete = pm_sleep_ptr(omap8250_complete), }; static struct platform_driver omap8250_platform_driver = { .driver = { .name = "omap8250", - .pm = &omap8250_dev_pm_ops, + .pm = pm_ptr(&omap8250_dev_pm_ops), .of_match_table = omap8250_dt_ids, }, .probe = omap8250_probe, |
