162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 8250-core based driver for the OMAP internal UART 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * based on omap-serial.c, Copyright (C) 2010 Texas Instruments. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2014 Sebastian Andrzej Siewior 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/clk.h> 1262306a36Sopenharmony_ci#include <linux/device.h> 1362306a36Sopenharmony_ci#include <linux/io.h> 1462306a36Sopenharmony_ci#include <linux/module.h> 1562306a36Sopenharmony_ci#include <linux/serial_8250.h> 1662306a36Sopenharmony_ci#include <linux/serial_reg.h> 1762306a36Sopenharmony_ci#include <linux/tty_flip.h> 1862306a36Sopenharmony_ci#include <linux/platform_device.h> 1962306a36Sopenharmony_ci#include <linux/slab.h> 2062306a36Sopenharmony_ci#include <linux/of.h> 2162306a36Sopenharmony_ci#include <linux/of_gpio.h> 2262306a36Sopenharmony_ci#include <linux/of_irq.h> 2362306a36Sopenharmony_ci#include <linux/delay.h> 2462306a36Sopenharmony_ci#include <linux/pm_runtime.h> 2562306a36Sopenharmony_ci#include <linux/console.h> 2662306a36Sopenharmony_ci#include <linux/pm_qos.h> 2762306a36Sopenharmony_ci#include <linux/pm_wakeirq.h> 2862306a36Sopenharmony_ci#include <linux/dma-mapping.h> 2962306a36Sopenharmony_ci#include <linux/sys_soc.h> 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#include "8250.h" 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#define DEFAULT_CLK_SPEED 48000000 3462306a36Sopenharmony_ci#define OMAP_UART_REGSHIFT 2 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#define UART_ERRATA_i202_MDR1_ACCESS (1 << 0) 3762306a36Sopenharmony_ci#define OMAP_UART_WER_HAS_TX_WAKEUP (1 << 1) 3862306a36Sopenharmony_ci#define OMAP_DMA_TX_KICK (1 << 2) 3962306a36Sopenharmony_ci/* 4062306a36Sopenharmony_ci * See Advisory 21 in AM437x errata SPRZ408B, updated April 2015. 4162306a36Sopenharmony_ci * The same errata is applicable to AM335x and DRA7x processors too. 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_ci#define UART_ERRATA_CLOCK_DISABLE (1 << 3) 4462306a36Sopenharmony_ci#define UART_HAS_EFR2 BIT(4) 4562306a36Sopenharmony_ci#define UART_HAS_RHR_IT_DIS BIT(5) 4662306a36Sopenharmony_ci#define UART_RX_TIMEOUT_QUIRK BIT(6) 4762306a36Sopenharmony_ci#define UART_HAS_NATIVE_RS485 BIT(7) 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define OMAP_UART_FCR_RX_TRIG 6 5062306a36Sopenharmony_ci#define OMAP_UART_FCR_TX_TRIG 4 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/* SCR register bitmasks */ 5362306a36Sopenharmony_ci#define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK (1 << 7) 5462306a36Sopenharmony_ci#define OMAP_UART_SCR_TX_TRIG_GRANU1_MASK (1 << 6) 5562306a36Sopenharmony_ci#define OMAP_UART_SCR_TX_EMPTY (1 << 3) 5662306a36Sopenharmony_ci#define OMAP_UART_SCR_DMAMODE_MASK (3 << 1) 5762306a36Sopenharmony_ci#define OMAP_UART_SCR_DMAMODE_1 (1 << 1) 5862306a36Sopenharmony_ci#define OMAP_UART_SCR_DMAMODE_CTL (1 << 0) 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/* MVR register bitmasks */ 6162306a36Sopenharmony_ci#define OMAP_UART_MVR_SCHEME_SHIFT 30 6262306a36Sopenharmony_ci#define OMAP_UART_LEGACY_MVR_MAJ_MASK 0xf0 6362306a36Sopenharmony_ci#define OMAP_UART_LEGACY_MVR_MAJ_SHIFT 4 6462306a36Sopenharmony_ci#define OMAP_UART_LEGACY_MVR_MIN_MASK 0x0f 6562306a36Sopenharmony_ci#define OMAP_UART_MVR_MAJ_MASK 0x700 6662306a36Sopenharmony_ci#define OMAP_UART_MVR_MAJ_SHIFT 8 6762306a36Sopenharmony_ci#define OMAP_UART_MVR_MIN_MASK 0x3f 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci/* SYSC register bitmasks */ 7062306a36Sopenharmony_ci#define OMAP_UART_SYSC_SOFTRESET (1 << 1) 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci/* SYSS register bitmasks */ 7362306a36Sopenharmony_ci#define OMAP_UART_SYSS_RESETDONE (1 << 0) 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci#define UART_TI752_TLR_TX 0 7662306a36Sopenharmony_ci#define UART_TI752_TLR_RX 4 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci#define TRIGGER_TLR_MASK(x) ((x & 0x3c) >> 2) 7962306a36Sopenharmony_ci#define TRIGGER_FCR_MASK(x) (x & 3) 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/* Enable XON/XOFF flow control on output */ 8262306a36Sopenharmony_ci#define OMAP_UART_SW_TX 0x08 8362306a36Sopenharmony_ci/* Enable XON/XOFF flow control on input */ 8462306a36Sopenharmony_ci#define OMAP_UART_SW_RX 0x02 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci#define OMAP_UART_WER_MOD_WKUP 0x7f 8762306a36Sopenharmony_ci#define OMAP_UART_TX_WAKEUP_EN (1 << 7) 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci#define TX_TRIGGER 1 9062306a36Sopenharmony_ci#define RX_TRIGGER 48 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci#define OMAP_UART_TCR_RESTORE(x) ((x / 4) << 4) 9362306a36Sopenharmony_ci#define OMAP_UART_TCR_HALT(x) ((x / 4) << 0) 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci#define UART_BUILD_REVISION(x, y) (((x) << 8) | (y)) 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci#define OMAP_UART_REV_46 0x0406 9862306a36Sopenharmony_ci#define OMAP_UART_REV_52 0x0502 9962306a36Sopenharmony_ci#define OMAP_UART_REV_63 0x0603 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci/* Interrupt Enable Register 2 */ 10262306a36Sopenharmony_ci#define UART_OMAP_IER2 0x1B 10362306a36Sopenharmony_ci#define UART_OMAP_IER2_RHR_IT_DIS BIT(2) 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci/* Mode Definition Register 3 */ 10662306a36Sopenharmony_ci#define UART_OMAP_MDR3 0x20 10762306a36Sopenharmony_ci#define UART_OMAP_MDR3_DIR_POL BIT(3) 10862306a36Sopenharmony_ci#define UART_OMAP_MDR3_DIR_EN BIT(4) 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci/* Enhanced features register 2 */ 11162306a36Sopenharmony_ci#define UART_OMAP_EFR2 0x23 11262306a36Sopenharmony_ci#define UART_OMAP_EFR2_TIMEOUT_BEHAVE BIT(6) 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci/* RX FIFO occupancy indicator */ 11562306a36Sopenharmony_ci#define UART_OMAP_RX_LVL 0x19 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_cistruct omap8250_priv { 11862306a36Sopenharmony_ci void __iomem *membase; 11962306a36Sopenharmony_ci int line; 12062306a36Sopenharmony_ci u8 habit; 12162306a36Sopenharmony_ci u8 mdr1; 12262306a36Sopenharmony_ci u8 mdr3; 12362306a36Sopenharmony_ci u8 efr; 12462306a36Sopenharmony_ci u8 scr; 12562306a36Sopenharmony_ci u8 wer; 12662306a36Sopenharmony_ci u8 xon; 12762306a36Sopenharmony_ci u8 xoff; 12862306a36Sopenharmony_ci u8 delayed_restore; 12962306a36Sopenharmony_ci u16 quot; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci u8 tx_trigger; 13262306a36Sopenharmony_ci u8 rx_trigger; 13362306a36Sopenharmony_ci bool is_suspending; 13462306a36Sopenharmony_ci int wakeirq; 13562306a36Sopenharmony_ci int wakeups_enabled; 13662306a36Sopenharmony_ci u32 latency; 13762306a36Sopenharmony_ci u32 calc_latency; 13862306a36Sopenharmony_ci struct pm_qos_request pm_qos_request; 13962306a36Sopenharmony_ci struct work_struct qos_work; 14062306a36Sopenharmony_ci struct uart_8250_dma omap8250_dma; 14162306a36Sopenharmony_ci spinlock_t rx_dma_lock; 14262306a36Sopenharmony_ci bool rx_dma_broken; 14362306a36Sopenharmony_ci bool throttled; 14462306a36Sopenharmony_ci}; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistruct omap8250_dma_params { 14762306a36Sopenharmony_ci u32 rx_size; 14862306a36Sopenharmony_ci u8 rx_trigger; 14962306a36Sopenharmony_ci u8 tx_trigger; 15062306a36Sopenharmony_ci}; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_cistruct omap8250_platdata { 15362306a36Sopenharmony_ci struct omap8250_dma_params *dma_params; 15462306a36Sopenharmony_ci u8 habit; 15562306a36Sopenharmony_ci}; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci#ifdef CONFIG_SERIAL_8250_DMA 15862306a36Sopenharmony_cistatic void omap_8250_rx_dma_flush(struct uart_8250_port *p); 15962306a36Sopenharmony_ci#else 16062306a36Sopenharmony_cistatic inline void omap_8250_rx_dma_flush(struct uart_8250_port *p) { } 16162306a36Sopenharmony_ci#endif 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic u32 uart_read(struct omap8250_priv *priv, u32 reg) 16462306a36Sopenharmony_ci{ 16562306a36Sopenharmony_ci return readl(priv->membase + (reg << OMAP_UART_REGSHIFT)); 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci/* 16962306a36Sopenharmony_ci * Called on runtime PM resume path from omap8250_restore_regs(), and 17062306a36Sopenharmony_ci * omap8250_set_mctrl(). 17162306a36Sopenharmony_ci */ 17262306a36Sopenharmony_cistatic void __omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci struct uart_8250_port *up = up_to_u8250p(port); 17562306a36Sopenharmony_ci struct omap8250_priv *priv = up->port.private_data; 17662306a36Sopenharmony_ci u8 lcr; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci serial8250_do_set_mctrl(port, mctrl); 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci if (!mctrl_gpio_to_gpiod(up->gpios, UART_GPIO_RTS)) { 18162306a36Sopenharmony_ci /* 18262306a36Sopenharmony_ci * Turn off autoRTS if RTS is lowered and restore autoRTS 18362306a36Sopenharmony_ci * setting if RTS is raised 18462306a36Sopenharmony_ci */ 18562306a36Sopenharmony_ci lcr = serial_in(up, UART_LCR); 18662306a36Sopenharmony_ci serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); 18762306a36Sopenharmony_ci if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS)) 18862306a36Sopenharmony_ci priv->efr |= UART_EFR_RTS; 18962306a36Sopenharmony_ci else 19062306a36Sopenharmony_ci priv->efr &= ~UART_EFR_RTS; 19162306a36Sopenharmony_ci serial_out(up, UART_EFR, priv->efr); 19262306a36Sopenharmony_ci serial_out(up, UART_LCR, lcr); 19362306a36Sopenharmony_ci } 19462306a36Sopenharmony_ci} 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cistatic void omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci int err; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci err = pm_runtime_resume_and_get(port->dev); 20162306a36Sopenharmony_ci if (err) 20262306a36Sopenharmony_ci return; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci __omap8250_set_mctrl(port, mctrl); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci pm_runtime_mark_last_busy(port->dev); 20762306a36Sopenharmony_ci pm_runtime_put_autosuspend(port->dev); 20862306a36Sopenharmony_ci} 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci/* 21162306a36Sopenharmony_ci * Work Around for Errata i202 (2430, 3430, 3630, 4430 and 4460) 21262306a36Sopenharmony_ci * The access to uart register after MDR1 Access 21362306a36Sopenharmony_ci * causes UART to corrupt data. 21462306a36Sopenharmony_ci * 21562306a36Sopenharmony_ci * Need a delay = 21662306a36Sopenharmony_ci * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS) 21762306a36Sopenharmony_ci * give 10 times as much 21862306a36Sopenharmony_ci */ 21962306a36Sopenharmony_cistatic void omap_8250_mdr1_errataset(struct uart_8250_port *up, 22062306a36Sopenharmony_ci struct omap8250_priv *priv) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci serial_out(up, UART_OMAP_MDR1, priv->mdr1); 22362306a36Sopenharmony_ci udelay(2); 22462306a36Sopenharmony_ci serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_XMIT | 22562306a36Sopenharmony_ci UART_FCR_CLEAR_RCVR); 22662306a36Sopenharmony_ci} 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_cistatic void omap_8250_get_divisor(struct uart_port *port, unsigned int baud, 22962306a36Sopenharmony_ci struct omap8250_priv *priv) 23062306a36Sopenharmony_ci{ 23162306a36Sopenharmony_ci unsigned int uartclk = port->uartclk; 23262306a36Sopenharmony_ci unsigned int div_13, div_16; 23362306a36Sopenharmony_ci unsigned int abs_d13, abs_d16; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci /* 23662306a36Sopenharmony_ci * Old custom speed handling. 23762306a36Sopenharmony_ci */ 23862306a36Sopenharmony_ci if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) { 23962306a36Sopenharmony_ci priv->quot = port->custom_divisor & UART_DIV_MAX; 24062306a36Sopenharmony_ci /* 24162306a36Sopenharmony_ci * I assume that nobody is using this. But hey, if somebody 24262306a36Sopenharmony_ci * would like to specify the divisor _and_ the mode then the 24362306a36Sopenharmony_ci * driver is ready and waiting for it. 24462306a36Sopenharmony_ci */ 24562306a36Sopenharmony_ci if (port->custom_divisor & (1 << 16)) 24662306a36Sopenharmony_ci priv->mdr1 = UART_OMAP_MDR1_13X_MODE; 24762306a36Sopenharmony_ci else 24862306a36Sopenharmony_ci priv->mdr1 = UART_OMAP_MDR1_16X_MODE; 24962306a36Sopenharmony_ci return; 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci div_13 = DIV_ROUND_CLOSEST(uartclk, 13 * baud); 25262306a36Sopenharmony_ci div_16 = DIV_ROUND_CLOSEST(uartclk, 16 * baud); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci if (!div_13) 25562306a36Sopenharmony_ci div_13 = 1; 25662306a36Sopenharmony_ci if (!div_16) 25762306a36Sopenharmony_ci div_16 = 1; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci abs_d13 = abs(baud - uartclk / 13 / div_13); 26062306a36Sopenharmony_ci abs_d16 = abs(baud - uartclk / 16 / div_16); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci if (abs_d13 >= abs_d16) { 26362306a36Sopenharmony_ci priv->mdr1 = UART_OMAP_MDR1_16X_MODE; 26462306a36Sopenharmony_ci priv->quot = div_16; 26562306a36Sopenharmony_ci } else { 26662306a36Sopenharmony_ci priv->mdr1 = UART_OMAP_MDR1_13X_MODE; 26762306a36Sopenharmony_ci priv->quot = div_13; 26862306a36Sopenharmony_ci } 26962306a36Sopenharmony_ci} 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_cistatic void omap8250_update_scr(struct uart_8250_port *up, 27262306a36Sopenharmony_ci struct omap8250_priv *priv) 27362306a36Sopenharmony_ci{ 27462306a36Sopenharmony_ci u8 old_scr; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci old_scr = serial_in(up, UART_OMAP_SCR); 27762306a36Sopenharmony_ci if (old_scr == priv->scr) 27862306a36Sopenharmony_ci return; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci /* 28162306a36Sopenharmony_ci * The manual recommends not to enable the DMA mode selector in the SCR 28262306a36Sopenharmony_ci * (instead of the FCR) register _and_ selecting the DMA mode as one 28362306a36Sopenharmony_ci * register write because this may lead to malfunction. 28462306a36Sopenharmony_ci */ 28562306a36Sopenharmony_ci if (priv->scr & OMAP_UART_SCR_DMAMODE_MASK) 28662306a36Sopenharmony_ci serial_out(up, UART_OMAP_SCR, 28762306a36Sopenharmony_ci priv->scr & ~OMAP_UART_SCR_DMAMODE_MASK); 28862306a36Sopenharmony_ci serial_out(up, UART_OMAP_SCR, priv->scr); 28962306a36Sopenharmony_ci} 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_cistatic void omap8250_update_mdr1(struct uart_8250_port *up, 29262306a36Sopenharmony_ci struct omap8250_priv *priv) 29362306a36Sopenharmony_ci{ 29462306a36Sopenharmony_ci if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS) 29562306a36Sopenharmony_ci omap_8250_mdr1_errataset(up, priv); 29662306a36Sopenharmony_ci else 29762306a36Sopenharmony_ci serial_out(up, UART_OMAP_MDR1, priv->mdr1); 29862306a36Sopenharmony_ci} 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_cistatic void omap8250_restore_regs(struct uart_8250_port *up) 30162306a36Sopenharmony_ci{ 30262306a36Sopenharmony_ci struct omap8250_priv *priv = up->port.private_data; 30362306a36Sopenharmony_ci struct uart_8250_dma *dma = up->dma; 30462306a36Sopenharmony_ci u8 mcr = serial8250_in_MCR(up); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci /* Port locked to synchronize UART_IER access against the console. */ 30762306a36Sopenharmony_ci lockdep_assert_held_once(&up->port.lock); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci if (dma && dma->tx_running) { 31062306a36Sopenharmony_ci /* 31162306a36Sopenharmony_ci * TCSANOW requests the change to occur immediately however if 31262306a36Sopenharmony_ci * we have a TX-DMA operation in progress then it has been 31362306a36Sopenharmony_ci * observed that it might stall and never complete. Therefore we 31462306a36Sopenharmony_ci * delay DMA completes to prevent this hang from happen. 31562306a36Sopenharmony_ci */ 31662306a36Sopenharmony_ci priv->delayed_restore = 1; 31762306a36Sopenharmony_ci return; 31862306a36Sopenharmony_ci } 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); 32162306a36Sopenharmony_ci serial_out(up, UART_EFR, UART_EFR_ECB); 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); 32462306a36Sopenharmony_ci serial8250_out_MCR(up, mcr | UART_MCR_TCRTLR); 32562306a36Sopenharmony_ci serial_out(up, UART_FCR, up->fcr); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci omap8250_update_scr(up, priv); 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_RESTORE(16) | 33262306a36Sopenharmony_ci OMAP_UART_TCR_HALT(52)); 33362306a36Sopenharmony_ci serial_out(up, UART_TI752_TLR, 33462306a36Sopenharmony_ci TRIGGER_TLR_MASK(priv->tx_trigger) << UART_TI752_TLR_TX | 33562306a36Sopenharmony_ci TRIGGER_TLR_MASK(priv->rx_trigger) << UART_TI752_TLR_RX); 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci serial_out(up, UART_LCR, 0); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci /* drop TCR + TLR access, we setup XON/XOFF later */ 34062306a36Sopenharmony_ci serial8250_out_MCR(up, mcr); 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci serial_out(up, UART_IER, up->ier); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); 34562306a36Sopenharmony_ci serial_dl_write(up, priv->quot); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci serial_out(up, UART_EFR, priv->efr); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci /* Configure flow control */ 35062306a36Sopenharmony_ci serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); 35162306a36Sopenharmony_ci serial_out(up, UART_XON1, priv->xon); 35262306a36Sopenharmony_ci serial_out(up, UART_XOFF1, priv->xoff); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci serial_out(up, UART_LCR, up->lcr); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci omap8250_update_mdr1(up, priv); 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci __omap8250_set_mctrl(&up->port, up->port.mctrl); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci serial_out(up, UART_OMAP_MDR3, priv->mdr3); 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci if (up->port.rs485.flags & SER_RS485_ENABLED && 36362306a36Sopenharmony_ci up->port.rs485_config == serial8250_em485_config) 36462306a36Sopenharmony_ci serial8250_em485_stop_tx(up); 36562306a36Sopenharmony_ci} 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci/* 36862306a36Sopenharmony_ci * OMAP can use "CLK / (16 or 13) / div" for baud rate. And then we have have 36962306a36Sopenharmony_ci * some differences in how we want to handle flow control. 37062306a36Sopenharmony_ci */ 37162306a36Sopenharmony_cistatic void omap_8250_set_termios(struct uart_port *port, 37262306a36Sopenharmony_ci struct ktermios *termios, 37362306a36Sopenharmony_ci const struct ktermios *old) 37462306a36Sopenharmony_ci{ 37562306a36Sopenharmony_ci struct uart_8250_port *up = up_to_u8250p(port); 37662306a36Sopenharmony_ci struct omap8250_priv *priv = up->port.private_data; 37762306a36Sopenharmony_ci unsigned char cval = 0; 37862306a36Sopenharmony_ci unsigned int baud; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci cval = UART_LCR_WLEN(tty_get_char_size(termios->c_cflag)); 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci if (termios->c_cflag & CSTOPB) 38362306a36Sopenharmony_ci cval |= UART_LCR_STOP; 38462306a36Sopenharmony_ci if (termios->c_cflag & PARENB) 38562306a36Sopenharmony_ci cval |= UART_LCR_PARITY; 38662306a36Sopenharmony_ci if (!(termios->c_cflag & PARODD)) 38762306a36Sopenharmony_ci cval |= UART_LCR_EPAR; 38862306a36Sopenharmony_ci if (termios->c_cflag & CMSPAR) 38962306a36Sopenharmony_ci cval |= UART_LCR_SPAR; 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci /* 39262306a36Sopenharmony_ci * Ask the core to calculate the divisor for us. 39362306a36Sopenharmony_ci */ 39462306a36Sopenharmony_ci baud = uart_get_baud_rate(port, termios, old, 39562306a36Sopenharmony_ci port->uartclk / 16 / UART_DIV_MAX, 39662306a36Sopenharmony_ci port->uartclk / 13); 39762306a36Sopenharmony_ci omap_8250_get_divisor(port, baud, priv); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci /* 40062306a36Sopenharmony_ci * Ok, we're now changing the port state. Do it with 40162306a36Sopenharmony_ci * interrupts disabled. 40262306a36Sopenharmony_ci */ 40362306a36Sopenharmony_ci pm_runtime_get_sync(port->dev); 40462306a36Sopenharmony_ci spin_lock_irq(&port->lock); 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci /* 40762306a36Sopenharmony_ci * Update the per-port timeout. 40862306a36Sopenharmony_ci */ 40962306a36Sopenharmony_ci uart_update_timeout(port, termios->c_cflag, baud); 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; 41262306a36Sopenharmony_ci if (termios->c_iflag & INPCK) 41362306a36Sopenharmony_ci up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; 41462306a36Sopenharmony_ci if (termios->c_iflag & (IGNBRK | PARMRK)) 41562306a36Sopenharmony_ci up->port.read_status_mask |= UART_LSR_BI; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci /* 41862306a36Sopenharmony_ci * Characters to ignore 41962306a36Sopenharmony_ci */ 42062306a36Sopenharmony_ci up->port.ignore_status_mask = 0; 42162306a36Sopenharmony_ci if (termios->c_iflag & IGNPAR) 42262306a36Sopenharmony_ci up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; 42362306a36Sopenharmony_ci if (termios->c_iflag & IGNBRK) { 42462306a36Sopenharmony_ci up->port.ignore_status_mask |= UART_LSR_BI; 42562306a36Sopenharmony_ci /* 42662306a36Sopenharmony_ci * If we're ignoring parity and break indicators, 42762306a36Sopenharmony_ci * ignore overruns too (for real raw support). 42862306a36Sopenharmony_ci */ 42962306a36Sopenharmony_ci if (termios->c_iflag & IGNPAR) 43062306a36Sopenharmony_ci up->port.ignore_status_mask |= UART_LSR_OE; 43162306a36Sopenharmony_ci } 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci /* 43462306a36Sopenharmony_ci * ignore all characters if CREAD is not set 43562306a36Sopenharmony_ci */ 43662306a36Sopenharmony_ci if ((termios->c_cflag & CREAD) == 0) 43762306a36Sopenharmony_ci up->port.ignore_status_mask |= UART_LSR_DR; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci /* 44062306a36Sopenharmony_ci * Modem status interrupts 44162306a36Sopenharmony_ci */ 44262306a36Sopenharmony_ci up->ier &= ~UART_IER_MSI; 44362306a36Sopenharmony_ci if (UART_ENABLE_MS(&up->port, termios->c_cflag)) 44462306a36Sopenharmony_ci up->ier |= UART_IER_MSI; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci up->lcr = cval; 44762306a36Sopenharmony_ci /* Up to here it was mostly serial8250_do_set_termios() */ 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci /* 45062306a36Sopenharmony_ci * We enable TRIG_GRANU for RX and TX and additionally we set 45162306a36Sopenharmony_ci * SCR_TX_EMPTY bit. The result is the following: 45262306a36Sopenharmony_ci * - RX_TRIGGER amount of bytes in the FIFO will cause an interrupt. 45362306a36Sopenharmony_ci * - less than RX_TRIGGER number of bytes will also cause an interrupt 45462306a36Sopenharmony_ci * once the UART decides that there no new bytes arriving. 45562306a36Sopenharmony_ci * - Once THRE is enabled, the interrupt will be fired once the FIFO is 45662306a36Sopenharmony_ci * empty - the trigger level is ignored here. 45762306a36Sopenharmony_ci * 45862306a36Sopenharmony_ci * Once DMA is enabled: 45962306a36Sopenharmony_ci * - UART will assert the TX DMA line once there is room for TX_TRIGGER 46062306a36Sopenharmony_ci * bytes in the TX FIFO. On each assert the DMA engine will move 46162306a36Sopenharmony_ci * TX_TRIGGER bytes into the FIFO. 46262306a36Sopenharmony_ci * - UART will assert the RX DMA line once there are RX_TRIGGER bytes in 46362306a36Sopenharmony_ci * the FIFO and move RX_TRIGGER bytes. 46462306a36Sopenharmony_ci * This is because threshold and trigger values are the same. 46562306a36Sopenharmony_ci */ 46662306a36Sopenharmony_ci up->fcr = UART_FCR_ENABLE_FIFO; 46762306a36Sopenharmony_ci up->fcr |= TRIGGER_FCR_MASK(priv->tx_trigger) << OMAP_UART_FCR_TX_TRIG; 46862306a36Sopenharmony_ci up->fcr |= TRIGGER_FCR_MASK(priv->rx_trigger) << OMAP_UART_FCR_RX_TRIG; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci priv->scr = OMAP_UART_SCR_RX_TRIG_GRANU1_MASK | OMAP_UART_SCR_TX_EMPTY | 47162306a36Sopenharmony_ci OMAP_UART_SCR_TX_TRIG_GRANU1_MASK; 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci if (up->dma) 47462306a36Sopenharmony_ci priv->scr |= OMAP_UART_SCR_DMAMODE_1 | 47562306a36Sopenharmony_ci OMAP_UART_SCR_DMAMODE_CTL; 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci priv->xon = termios->c_cc[VSTART]; 47862306a36Sopenharmony_ci priv->xoff = termios->c_cc[VSTOP]; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci priv->efr = 0; 48162306a36Sopenharmony_ci up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF); 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW && 48462306a36Sopenharmony_ci !mctrl_gpio_to_gpiod(up->gpios, UART_GPIO_RTS) && 48562306a36Sopenharmony_ci !mctrl_gpio_to_gpiod(up->gpios, UART_GPIO_CTS)) { 48662306a36Sopenharmony_ci /* Enable AUTOCTS (autoRTS is enabled when RTS is raised) */ 48762306a36Sopenharmony_ci up->port.status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS; 48862306a36Sopenharmony_ci priv->efr |= UART_EFR_CTS; 48962306a36Sopenharmony_ci } else if (up->port.flags & UPF_SOFT_FLOW) { 49062306a36Sopenharmony_ci /* 49162306a36Sopenharmony_ci * OMAP rx s/w flow control is borked; the transmitter remains 49262306a36Sopenharmony_ci * stuck off even if rx flow control is subsequently disabled 49362306a36Sopenharmony_ci */ 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci /* 49662306a36Sopenharmony_ci * IXOFF Flag: 49762306a36Sopenharmony_ci * Enable XON/XOFF flow control on output. 49862306a36Sopenharmony_ci * Transmit XON1, XOFF1 49962306a36Sopenharmony_ci */ 50062306a36Sopenharmony_ci if (termios->c_iflag & IXOFF) { 50162306a36Sopenharmony_ci up->port.status |= UPSTAT_AUTOXOFF; 50262306a36Sopenharmony_ci priv->efr |= OMAP_UART_SW_TX; 50362306a36Sopenharmony_ci } 50462306a36Sopenharmony_ci } 50562306a36Sopenharmony_ci omap8250_restore_regs(up); 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci spin_unlock_irq(&up->port.lock); 50862306a36Sopenharmony_ci pm_runtime_mark_last_busy(port->dev); 50962306a36Sopenharmony_ci pm_runtime_put_autosuspend(port->dev); 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci /* calculate wakeup latency constraint */ 51262306a36Sopenharmony_ci priv->calc_latency = USEC_PER_SEC * 64 * 8 / baud; 51362306a36Sopenharmony_ci priv->latency = priv->calc_latency; 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci schedule_work(&priv->qos_work); 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci /* Don't rewrite B0 */ 51862306a36Sopenharmony_ci if (tty_termios_baud_rate(termios)) 51962306a36Sopenharmony_ci tty_termios_encode_baud_rate(termios, baud, baud); 52062306a36Sopenharmony_ci} 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci/* same as 8250 except that we may have extra flow bits set in EFR */ 52362306a36Sopenharmony_cistatic void omap_8250_pm(struct uart_port *port, unsigned int state, 52462306a36Sopenharmony_ci unsigned int oldstate) 52562306a36Sopenharmony_ci{ 52662306a36Sopenharmony_ci struct uart_8250_port *up = up_to_u8250p(port); 52762306a36Sopenharmony_ci u8 efr; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci pm_runtime_get_sync(port->dev); 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci /* Synchronize UART_IER access against the console. */ 53262306a36Sopenharmony_ci spin_lock_irq(&port->lock); 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); 53562306a36Sopenharmony_ci efr = serial_in(up, UART_EFR); 53662306a36Sopenharmony_ci serial_out(up, UART_EFR, efr | UART_EFR_ECB); 53762306a36Sopenharmony_ci serial_out(up, UART_LCR, 0); 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci serial_out(up, UART_IER, (state != 0) ? UART_IERX_SLEEP : 0); 54062306a36Sopenharmony_ci serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); 54162306a36Sopenharmony_ci serial_out(up, UART_EFR, efr); 54262306a36Sopenharmony_ci serial_out(up, UART_LCR, 0); 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci spin_unlock_irq(&port->lock); 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci pm_runtime_mark_last_busy(port->dev); 54762306a36Sopenharmony_ci pm_runtime_put_autosuspend(port->dev); 54862306a36Sopenharmony_ci} 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_cistatic void omap_serial_fill_features_erratas(struct uart_8250_port *up, 55162306a36Sopenharmony_ci struct omap8250_priv *priv) 55262306a36Sopenharmony_ci{ 55362306a36Sopenharmony_ci static const struct soc_device_attribute k3_soc_devices[] = { 55462306a36Sopenharmony_ci { .family = "AM65X", }, 55562306a36Sopenharmony_ci { .family = "J721E", .revision = "SR1.0" }, 55662306a36Sopenharmony_ci { /* sentinel */ } 55762306a36Sopenharmony_ci }; 55862306a36Sopenharmony_ci u32 mvr, scheme; 55962306a36Sopenharmony_ci u16 revision, major, minor; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci mvr = uart_read(priv, UART_OMAP_MVER); 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci /* Check revision register scheme */ 56462306a36Sopenharmony_ci scheme = mvr >> OMAP_UART_MVR_SCHEME_SHIFT; 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci switch (scheme) { 56762306a36Sopenharmony_ci case 0: /* Legacy Scheme: OMAP2/3 */ 56862306a36Sopenharmony_ci /* MINOR_REV[0:4], MAJOR_REV[4:7] */ 56962306a36Sopenharmony_ci major = (mvr & OMAP_UART_LEGACY_MVR_MAJ_MASK) >> 57062306a36Sopenharmony_ci OMAP_UART_LEGACY_MVR_MAJ_SHIFT; 57162306a36Sopenharmony_ci minor = (mvr & OMAP_UART_LEGACY_MVR_MIN_MASK); 57262306a36Sopenharmony_ci break; 57362306a36Sopenharmony_ci case 1: 57462306a36Sopenharmony_ci /* New Scheme: OMAP4+ */ 57562306a36Sopenharmony_ci /* MINOR_REV[0:5], MAJOR_REV[8:10] */ 57662306a36Sopenharmony_ci major = (mvr & OMAP_UART_MVR_MAJ_MASK) >> 57762306a36Sopenharmony_ci OMAP_UART_MVR_MAJ_SHIFT; 57862306a36Sopenharmony_ci minor = (mvr & OMAP_UART_MVR_MIN_MASK); 57962306a36Sopenharmony_ci break; 58062306a36Sopenharmony_ci default: 58162306a36Sopenharmony_ci dev_warn(up->port.dev, 58262306a36Sopenharmony_ci "Unknown revision, defaulting to highest\n"); 58362306a36Sopenharmony_ci /* highest possible revision */ 58462306a36Sopenharmony_ci major = 0xff; 58562306a36Sopenharmony_ci minor = 0xff; 58662306a36Sopenharmony_ci } 58762306a36Sopenharmony_ci /* normalize revision for the driver */ 58862306a36Sopenharmony_ci revision = UART_BUILD_REVISION(major, minor); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci switch (revision) { 59162306a36Sopenharmony_ci case OMAP_UART_REV_46: 59262306a36Sopenharmony_ci priv->habit |= UART_ERRATA_i202_MDR1_ACCESS; 59362306a36Sopenharmony_ci break; 59462306a36Sopenharmony_ci case OMAP_UART_REV_52: 59562306a36Sopenharmony_ci priv->habit |= UART_ERRATA_i202_MDR1_ACCESS | 59662306a36Sopenharmony_ci OMAP_UART_WER_HAS_TX_WAKEUP; 59762306a36Sopenharmony_ci break; 59862306a36Sopenharmony_ci case OMAP_UART_REV_63: 59962306a36Sopenharmony_ci priv->habit |= UART_ERRATA_i202_MDR1_ACCESS | 60062306a36Sopenharmony_ci OMAP_UART_WER_HAS_TX_WAKEUP; 60162306a36Sopenharmony_ci break; 60262306a36Sopenharmony_ci default: 60362306a36Sopenharmony_ci break; 60462306a36Sopenharmony_ci } 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci /* 60762306a36Sopenharmony_ci * AM65x SR1.0, AM65x SR2.0 and J721e SR1.0 don't 60862306a36Sopenharmony_ci * don't have RHR_IT_DIS bit in IER2 register. So drop to flag 60962306a36Sopenharmony_ci * to enable errata workaround. 61062306a36Sopenharmony_ci */ 61162306a36Sopenharmony_ci if (soc_device_match(k3_soc_devices)) 61262306a36Sopenharmony_ci priv->habit &= ~UART_HAS_RHR_IT_DIS; 61362306a36Sopenharmony_ci} 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_cistatic void omap8250_uart_qos_work(struct work_struct *work) 61662306a36Sopenharmony_ci{ 61762306a36Sopenharmony_ci struct omap8250_priv *priv; 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci priv = container_of(work, struct omap8250_priv, qos_work); 62062306a36Sopenharmony_ci cpu_latency_qos_update_request(&priv->pm_qos_request, priv->latency); 62162306a36Sopenharmony_ci} 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci#ifdef CONFIG_SERIAL_8250_DMA 62462306a36Sopenharmony_cistatic int omap_8250_dma_handle_irq(struct uart_port *port); 62562306a36Sopenharmony_ci#endif 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_cistatic irqreturn_t omap8250_irq(int irq, void *dev_id) 62862306a36Sopenharmony_ci{ 62962306a36Sopenharmony_ci struct omap8250_priv *priv = dev_id; 63062306a36Sopenharmony_ci struct uart_8250_port *up = serial8250_get_port(priv->line); 63162306a36Sopenharmony_ci struct uart_port *port = &up->port; 63262306a36Sopenharmony_ci unsigned int iir, lsr; 63362306a36Sopenharmony_ci int ret; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci#ifdef CONFIG_SERIAL_8250_DMA 63662306a36Sopenharmony_ci if (up->dma) { 63762306a36Sopenharmony_ci ret = omap_8250_dma_handle_irq(port); 63862306a36Sopenharmony_ci return IRQ_RETVAL(ret); 63962306a36Sopenharmony_ci } 64062306a36Sopenharmony_ci#endif 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci serial8250_rpm_get(up); 64362306a36Sopenharmony_ci lsr = serial_port_in(port, UART_LSR); 64462306a36Sopenharmony_ci iir = serial_port_in(port, UART_IIR); 64562306a36Sopenharmony_ci ret = serial8250_handle_irq(port, iir); 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci /* 64862306a36Sopenharmony_ci * On K3 SoCs, it is observed that RX TIMEOUT is signalled after 64962306a36Sopenharmony_ci * FIFO has been drained, in which case a dummy read of RX FIFO 65062306a36Sopenharmony_ci * is required to clear RX TIMEOUT condition. 65162306a36Sopenharmony_ci */ 65262306a36Sopenharmony_ci if (priv->habit & UART_RX_TIMEOUT_QUIRK && 65362306a36Sopenharmony_ci (iir & UART_IIR_RX_TIMEOUT) == UART_IIR_RX_TIMEOUT && 65462306a36Sopenharmony_ci serial_port_in(port, UART_OMAP_RX_LVL) == 0) { 65562306a36Sopenharmony_ci serial_port_in(port, UART_RX); 65662306a36Sopenharmony_ci } 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci /* Stop processing interrupts on input overrun */ 65962306a36Sopenharmony_ci if ((lsr & UART_LSR_OE) && up->overrun_backoff_time_ms > 0) { 66062306a36Sopenharmony_ci unsigned long delay; 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci /* Synchronize UART_IER access against the console. */ 66362306a36Sopenharmony_ci spin_lock(&port->lock); 66462306a36Sopenharmony_ci up->ier = port->serial_in(port, UART_IER); 66562306a36Sopenharmony_ci if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) { 66662306a36Sopenharmony_ci port->ops->stop_rx(port); 66762306a36Sopenharmony_ci } else { 66862306a36Sopenharmony_ci /* Keep restarting the timer until 66962306a36Sopenharmony_ci * the input overrun subsides. 67062306a36Sopenharmony_ci */ 67162306a36Sopenharmony_ci cancel_delayed_work(&up->overrun_backoff); 67262306a36Sopenharmony_ci } 67362306a36Sopenharmony_ci spin_unlock(&port->lock); 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci delay = msecs_to_jiffies(up->overrun_backoff_time_ms); 67662306a36Sopenharmony_ci schedule_delayed_work(&up->overrun_backoff, delay); 67762306a36Sopenharmony_ci } 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci serial8250_rpm_put(up); 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci return IRQ_RETVAL(ret); 68262306a36Sopenharmony_ci} 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_cistatic int omap_8250_startup(struct uart_port *port) 68562306a36Sopenharmony_ci{ 68662306a36Sopenharmony_ci struct uart_8250_port *up = up_to_u8250p(port); 68762306a36Sopenharmony_ci struct omap8250_priv *priv = port->private_data; 68862306a36Sopenharmony_ci struct uart_8250_dma *dma = &priv->omap8250_dma; 68962306a36Sopenharmony_ci int ret; 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci if (priv->wakeirq) { 69262306a36Sopenharmony_ci ret = dev_pm_set_dedicated_wake_irq(port->dev, priv->wakeirq); 69362306a36Sopenharmony_ci if (ret) 69462306a36Sopenharmony_ci return ret; 69562306a36Sopenharmony_ci } 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci pm_runtime_get_sync(port->dev); 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci serial_out(up, UART_FCR, UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci serial_out(up, UART_LCR, UART_LCR_WLEN8); 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci up->lsr_saved_flags = 0; 70462306a36Sopenharmony_ci up->msr_saved_flags = 0; 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci /* Disable DMA for console UART */ 70762306a36Sopenharmony_ci if (dma->fn && !uart_console(port)) { 70862306a36Sopenharmony_ci up->dma = &priv->omap8250_dma; 70962306a36Sopenharmony_ci ret = serial8250_request_dma(up); 71062306a36Sopenharmony_ci if (ret) { 71162306a36Sopenharmony_ci dev_warn_ratelimited(port->dev, 71262306a36Sopenharmony_ci "failed to request DMA\n"); 71362306a36Sopenharmony_ci up->dma = NULL; 71462306a36Sopenharmony_ci } 71562306a36Sopenharmony_ci } else { 71662306a36Sopenharmony_ci up->dma = NULL; 71762306a36Sopenharmony_ci } 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci /* Synchronize UART_IER access against the console. */ 72062306a36Sopenharmony_ci spin_lock_irq(&port->lock); 72162306a36Sopenharmony_ci up->ier = UART_IER_RLSI | UART_IER_RDI; 72262306a36Sopenharmony_ci serial_out(up, UART_IER, up->ier); 72362306a36Sopenharmony_ci spin_unlock_irq(&port->lock); 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci#ifdef CONFIG_PM 72662306a36Sopenharmony_ci up->capabilities |= UART_CAP_RPM; 72762306a36Sopenharmony_ci#endif 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci /* Enable module level wake up */ 73062306a36Sopenharmony_ci priv->wer = OMAP_UART_WER_MOD_WKUP; 73162306a36Sopenharmony_ci if (priv->habit & OMAP_UART_WER_HAS_TX_WAKEUP) 73262306a36Sopenharmony_ci priv->wer |= OMAP_UART_TX_WAKEUP_EN; 73362306a36Sopenharmony_ci serial_out(up, UART_OMAP_WER, priv->wer); 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci if (up->dma && !(priv->habit & UART_HAS_EFR2)) { 73662306a36Sopenharmony_ci spin_lock_irq(&port->lock); 73762306a36Sopenharmony_ci up->dma->rx_dma(up); 73862306a36Sopenharmony_ci spin_unlock_irq(&port->lock); 73962306a36Sopenharmony_ci } 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci enable_irq(up->port.irq); 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci pm_runtime_mark_last_busy(port->dev); 74462306a36Sopenharmony_ci pm_runtime_put_autosuspend(port->dev); 74562306a36Sopenharmony_ci return 0; 74662306a36Sopenharmony_ci} 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_cistatic void omap_8250_shutdown(struct uart_port *port) 74962306a36Sopenharmony_ci{ 75062306a36Sopenharmony_ci struct uart_8250_port *up = up_to_u8250p(port); 75162306a36Sopenharmony_ci struct omap8250_priv *priv = port->private_data; 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci flush_work(&priv->qos_work); 75462306a36Sopenharmony_ci if (up->dma) 75562306a36Sopenharmony_ci omap_8250_rx_dma_flush(up); 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci pm_runtime_get_sync(port->dev); 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci serial_out(up, UART_OMAP_WER, 0); 76062306a36Sopenharmony_ci if (priv->habit & UART_HAS_EFR2) 76162306a36Sopenharmony_ci serial_out(up, UART_OMAP_EFR2, 0x0); 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci /* Synchronize UART_IER access against the console. */ 76462306a36Sopenharmony_ci spin_lock_irq(&port->lock); 76562306a36Sopenharmony_ci up->ier = 0; 76662306a36Sopenharmony_ci serial_out(up, UART_IER, 0); 76762306a36Sopenharmony_ci spin_unlock_irq(&port->lock); 76862306a36Sopenharmony_ci disable_irq_nosync(up->port.irq); 76962306a36Sopenharmony_ci dev_pm_clear_wake_irq(port->dev); 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci serial8250_release_dma(up); 77262306a36Sopenharmony_ci up->dma = NULL; 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci /* 77562306a36Sopenharmony_ci * Disable break condition and FIFOs 77662306a36Sopenharmony_ci */ 77762306a36Sopenharmony_ci if (up->lcr & UART_LCR_SBC) 77862306a36Sopenharmony_ci serial_out(up, UART_LCR, up->lcr & ~UART_LCR_SBC); 77962306a36Sopenharmony_ci serial_out(up, UART_FCR, UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci pm_runtime_mark_last_busy(port->dev); 78262306a36Sopenharmony_ci pm_runtime_put_autosuspend(port->dev); 78362306a36Sopenharmony_ci} 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_cistatic void omap_8250_throttle(struct uart_port *port) 78662306a36Sopenharmony_ci{ 78762306a36Sopenharmony_ci struct omap8250_priv *priv = port->private_data; 78862306a36Sopenharmony_ci unsigned long flags; 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci pm_runtime_get_sync(port->dev); 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci spin_lock_irqsave(&port->lock, flags); 79362306a36Sopenharmony_ci port->ops->stop_rx(port); 79462306a36Sopenharmony_ci priv->throttled = true; 79562306a36Sopenharmony_ci spin_unlock_irqrestore(&port->lock, flags); 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci pm_runtime_mark_last_busy(port->dev); 79862306a36Sopenharmony_ci pm_runtime_put_autosuspend(port->dev); 79962306a36Sopenharmony_ci} 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_cistatic void omap_8250_unthrottle(struct uart_port *port) 80262306a36Sopenharmony_ci{ 80362306a36Sopenharmony_ci struct omap8250_priv *priv = port->private_data; 80462306a36Sopenharmony_ci struct uart_8250_port *up = up_to_u8250p(port); 80562306a36Sopenharmony_ci unsigned long flags; 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci pm_runtime_get_sync(port->dev); 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci /* Synchronize UART_IER access against the console. */ 81062306a36Sopenharmony_ci spin_lock_irqsave(&port->lock, flags); 81162306a36Sopenharmony_ci priv->throttled = false; 81262306a36Sopenharmony_ci if (up->dma) 81362306a36Sopenharmony_ci up->dma->rx_dma(up); 81462306a36Sopenharmony_ci up->ier |= UART_IER_RLSI | UART_IER_RDI; 81562306a36Sopenharmony_ci port->read_status_mask |= UART_LSR_DR; 81662306a36Sopenharmony_ci serial_out(up, UART_IER, up->ier); 81762306a36Sopenharmony_ci spin_unlock_irqrestore(&port->lock, flags); 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci pm_runtime_mark_last_busy(port->dev); 82062306a36Sopenharmony_ci pm_runtime_put_autosuspend(port->dev); 82162306a36Sopenharmony_ci} 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_cistatic int omap8250_rs485_config(struct uart_port *port, 82462306a36Sopenharmony_ci struct ktermios *termios, 82562306a36Sopenharmony_ci struct serial_rs485 *rs485) 82662306a36Sopenharmony_ci{ 82762306a36Sopenharmony_ci struct omap8250_priv *priv = port->private_data; 82862306a36Sopenharmony_ci struct uart_8250_port *up = up_to_u8250p(port); 82962306a36Sopenharmony_ci u32 fixed_delay_rts_before_send = 0; 83062306a36Sopenharmony_ci u32 fixed_delay_rts_after_send = 0; 83162306a36Sopenharmony_ci unsigned int baud; 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci /* 83462306a36Sopenharmony_ci * There is a fixed delay of 3 bit clock cycles after the TX shift 83562306a36Sopenharmony_ci * register is going empty to allow time for the stop bit to transition 83662306a36Sopenharmony_ci * through the transceiver before direction is changed to receive. 83762306a36Sopenharmony_ci * 83862306a36Sopenharmony_ci * Additionally there appears to be a 1 bit clock delay between writing 83962306a36Sopenharmony_ci * to the THR register and transmission of the start bit, per page 8783 84062306a36Sopenharmony_ci * of the AM65 TRM: https://www.ti.com/lit/ug/spruid7e/spruid7e.pdf 84162306a36Sopenharmony_ci */ 84262306a36Sopenharmony_ci if (priv->quot) { 84362306a36Sopenharmony_ci if (priv->mdr1 == UART_OMAP_MDR1_16X_MODE) 84462306a36Sopenharmony_ci baud = port->uartclk / (16 * priv->quot); 84562306a36Sopenharmony_ci else 84662306a36Sopenharmony_ci baud = port->uartclk / (13 * priv->quot); 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci fixed_delay_rts_after_send = 3 * MSEC_PER_SEC / baud; 84962306a36Sopenharmony_ci fixed_delay_rts_before_send = 1 * MSEC_PER_SEC / baud; 85062306a36Sopenharmony_ci } 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci /* 85362306a36Sopenharmony_ci * Fall back to RS485 software emulation if the UART is missing 85462306a36Sopenharmony_ci * hardware support, if the device tree specifies an mctrl_gpio 85562306a36Sopenharmony_ci * (indicates that RTS is unavailable due to a pinmux conflict) 85662306a36Sopenharmony_ci * or if the requested delays exceed the fixed hardware delays. 85762306a36Sopenharmony_ci */ 85862306a36Sopenharmony_ci if (!(priv->habit & UART_HAS_NATIVE_RS485) || 85962306a36Sopenharmony_ci mctrl_gpio_to_gpiod(up->gpios, UART_GPIO_RTS) || 86062306a36Sopenharmony_ci rs485->delay_rts_after_send > fixed_delay_rts_after_send || 86162306a36Sopenharmony_ci rs485->delay_rts_before_send > fixed_delay_rts_before_send) { 86262306a36Sopenharmony_ci priv->mdr3 &= ~UART_OMAP_MDR3_DIR_EN; 86362306a36Sopenharmony_ci serial_out(up, UART_OMAP_MDR3, priv->mdr3); 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci port->rs485_config = serial8250_em485_config; 86662306a36Sopenharmony_ci return serial8250_em485_config(port, termios, rs485); 86762306a36Sopenharmony_ci } 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci rs485->delay_rts_after_send = fixed_delay_rts_after_send; 87062306a36Sopenharmony_ci rs485->delay_rts_before_send = fixed_delay_rts_before_send; 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci if (rs485->flags & SER_RS485_ENABLED) 87362306a36Sopenharmony_ci priv->mdr3 |= UART_OMAP_MDR3_DIR_EN; 87462306a36Sopenharmony_ci else 87562306a36Sopenharmony_ci priv->mdr3 &= ~UART_OMAP_MDR3_DIR_EN; 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci /* 87862306a36Sopenharmony_ci * Retain same polarity semantics as RS485 software emulation, 87962306a36Sopenharmony_ci * i.e. SER_RS485_RTS_ON_SEND means driving RTS low on send. 88062306a36Sopenharmony_ci */ 88162306a36Sopenharmony_ci if (rs485->flags & SER_RS485_RTS_ON_SEND) 88262306a36Sopenharmony_ci priv->mdr3 &= ~UART_OMAP_MDR3_DIR_POL; 88362306a36Sopenharmony_ci else 88462306a36Sopenharmony_ci priv->mdr3 |= UART_OMAP_MDR3_DIR_POL; 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci serial_out(up, UART_OMAP_MDR3, priv->mdr3); 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci return 0; 88962306a36Sopenharmony_ci} 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci#ifdef CONFIG_SERIAL_8250_DMA 89262306a36Sopenharmony_cistatic int omap_8250_rx_dma(struct uart_8250_port *p); 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_ci/* Must be called while priv->rx_dma_lock is held */ 89562306a36Sopenharmony_cistatic void __dma_rx_do_complete(struct uart_8250_port *p) 89662306a36Sopenharmony_ci{ 89762306a36Sopenharmony_ci struct uart_8250_dma *dma = p->dma; 89862306a36Sopenharmony_ci struct tty_port *tty_port = &p->port.state->port; 89962306a36Sopenharmony_ci struct omap8250_priv *priv = p->port.private_data; 90062306a36Sopenharmony_ci struct dma_chan *rxchan = dma->rxchan; 90162306a36Sopenharmony_ci dma_cookie_t cookie; 90262306a36Sopenharmony_ci struct dma_tx_state state; 90362306a36Sopenharmony_ci int count; 90462306a36Sopenharmony_ci int ret; 90562306a36Sopenharmony_ci u32 reg; 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci if (!dma->rx_running) 90862306a36Sopenharmony_ci goto out; 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci cookie = dma->rx_cookie; 91162306a36Sopenharmony_ci dma->rx_running = 0; 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci /* Re-enable RX FIFO interrupt now that transfer is complete */ 91462306a36Sopenharmony_ci if (priv->habit & UART_HAS_RHR_IT_DIS) { 91562306a36Sopenharmony_ci reg = serial_in(p, UART_OMAP_IER2); 91662306a36Sopenharmony_ci reg &= ~UART_OMAP_IER2_RHR_IT_DIS; 91762306a36Sopenharmony_ci serial_out(p, UART_OMAP_IER2, reg); 91862306a36Sopenharmony_ci } 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci dmaengine_tx_status(rxchan, cookie, &state); 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci count = dma->rx_size - state.residue + state.in_flight_bytes; 92362306a36Sopenharmony_ci if (count < dma->rx_size) { 92462306a36Sopenharmony_ci dmaengine_terminate_async(rxchan); 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_ci /* 92762306a36Sopenharmony_ci * Poll for teardown to complete which guarantees in 92862306a36Sopenharmony_ci * flight data is drained. 92962306a36Sopenharmony_ci */ 93062306a36Sopenharmony_ci if (state.in_flight_bytes) { 93162306a36Sopenharmony_ci int poll_count = 25; 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci while (dmaengine_tx_status(rxchan, cookie, NULL) && 93462306a36Sopenharmony_ci poll_count--) 93562306a36Sopenharmony_ci cpu_relax(); 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci if (poll_count == -1) 93862306a36Sopenharmony_ci dev_err(p->port.dev, "teardown incomplete\n"); 93962306a36Sopenharmony_ci } 94062306a36Sopenharmony_ci } 94162306a36Sopenharmony_ci if (!count) 94262306a36Sopenharmony_ci goto out; 94362306a36Sopenharmony_ci ret = tty_insert_flip_string(tty_port, dma->rx_buf, count); 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci p->port.icount.rx += ret; 94662306a36Sopenharmony_ci p->port.icount.buf_overrun += count - ret; 94762306a36Sopenharmony_ciout: 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci tty_flip_buffer_push(tty_port); 95062306a36Sopenharmony_ci} 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_cistatic void __dma_rx_complete(void *param) 95362306a36Sopenharmony_ci{ 95462306a36Sopenharmony_ci struct uart_8250_port *p = param; 95562306a36Sopenharmony_ci struct omap8250_priv *priv = p->port.private_data; 95662306a36Sopenharmony_ci struct uart_8250_dma *dma = p->dma; 95762306a36Sopenharmony_ci struct dma_tx_state state; 95862306a36Sopenharmony_ci unsigned long flags; 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci /* Synchronize UART_IER access against the console. */ 96162306a36Sopenharmony_ci spin_lock_irqsave(&p->port.lock, flags); 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci /* 96462306a36Sopenharmony_ci * If the tx status is not DMA_COMPLETE, then this is a delayed 96562306a36Sopenharmony_ci * completion callback. A previous RX timeout flush would have 96662306a36Sopenharmony_ci * already pushed the data, so exit. 96762306a36Sopenharmony_ci */ 96862306a36Sopenharmony_ci if (dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state) != 96962306a36Sopenharmony_ci DMA_COMPLETE) { 97062306a36Sopenharmony_ci spin_unlock_irqrestore(&p->port.lock, flags); 97162306a36Sopenharmony_ci return; 97262306a36Sopenharmony_ci } 97362306a36Sopenharmony_ci __dma_rx_do_complete(p); 97462306a36Sopenharmony_ci if (!priv->throttled) { 97562306a36Sopenharmony_ci p->ier |= UART_IER_RLSI | UART_IER_RDI; 97662306a36Sopenharmony_ci serial_out(p, UART_IER, p->ier); 97762306a36Sopenharmony_ci if (!(priv->habit & UART_HAS_EFR2)) 97862306a36Sopenharmony_ci omap_8250_rx_dma(p); 97962306a36Sopenharmony_ci } 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci spin_unlock_irqrestore(&p->port.lock, flags); 98262306a36Sopenharmony_ci} 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_cistatic void omap_8250_rx_dma_flush(struct uart_8250_port *p) 98562306a36Sopenharmony_ci{ 98662306a36Sopenharmony_ci struct omap8250_priv *priv = p->port.private_data; 98762306a36Sopenharmony_ci struct uart_8250_dma *dma = p->dma; 98862306a36Sopenharmony_ci struct dma_tx_state state; 98962306a36Sopenharmony_ci unsigned long flags; 99062306a36Sopenharmony_ci int ret; 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci spin_lock_irqsave(&priv->rx_dma_lock, flags); 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci if (!dma->rx_running) { 99562306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->rx_dma_lock, flags); 99662306a36Sopenharmony_ci return; 99762306a36Sopenharmony_ci } 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci ret = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); 100062306a36Sopenharmony_ci if (ret == DMA_IN_PROGRESS) { 100162306a36Sopenharmony_ci ret = dmaengine_pause(dma->rxchan); 100262306a36Sopenharmony_ci if (WARN_ON_ONCE(ret)) 100362306a36Sopenharmony_ci priv->rx_dma_broken = true; 100462306a36Sopenharmony_ci } 100562306a36Sopenharmony_ci __dma_rx_do_complete(p); 100662306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->rx_dma_lock, flags); 100762306a36Sopenharmony_ci} 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_cistatic int omap_8250_rx_dma(struct uart_8250_port *p) 101062306a36Sopenharmony_ci{ 101162306a36Sopenharmony_ci struct omap8250_priv *priv = p->port.private_data; 101262306a36Sopenharmony_ci struct uart_8250_dma *dma = p->dma; 101362306a36Sopenharmony_ci int err = 0; 101462306a36Sopenharmony_ci struct dma_async_tx_descriptor *desc; 101562306a36Sopenharmony_ci unsigned long flags; 101662306a36Sopenharmony_ci u32 reg; 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ci /* Port locked to synchronize UART_IER access against the console. */ 101962306a36Sopenharmony_ci lockdep_assert_held_once(&p->port.lock); 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci if (priv->rx_dma_broken) 102262306a36Sopenharmony_ci return -EINVAL; 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci spin_lock_irqsave(&priv->rx_dma_lock, flags); 102562306a36Sopenharmony_ci 102662306a36Sopenharmony_ci if (dma->rx_running) { 102762306a36Sopenharmony_ci enum dma_status state; 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci state = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, NULL); 103062306a36Sopenharmony_ci if (state == DMA_COMPLETE) { 103162306a36Sopenharmony_ci /* 103262306a36Sopenharmony_ci * Disable RX interrupts to allow RX DMA completion 103362306a36Sopenharmony_ci * callback to run. 103462306a36Sopenharmony_ci */ 103562306a36Sopenharmony_ci p->ier &= ~(UART_IER_RLSI | UART_IER_RDI); 103662306a36Sopenharmony_ci serial_out(p, UART_IER, p->ier); 103762306a36Sopenharmony_ci } 103862306a36Sopenharmony_ci goto out; 103962306a36Sopenharmony_ci } 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_ci desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr, 104262306a36Sopenharmony_ci dma->rx_size, DMA_DEV_TO_MEM, 104362306a36Sopenharmony_ci DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 104462306a36Sopenharmony_ci if (!desc) { 104562306a36Sopenharmony_ci err = -EBUSY; 104662306a36Sopenharmony_ci goto out; 104762306a36Sopenharmony_ci } 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci dma->rx_running = 1; 105062306a36Sopenharmony_ci desc->callback = __dma_rx_complete; 105162306a36Sopenharmony_ci desc->callback_param = p; 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci dma->rx_cookie = dmaengine_submit(desc); 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_ci /* 105662306a36Sopenharmony_ci * Disable RX FIFO interrupt while RX DMA is enabled, else 105762306a36Sopenharmony_ci * spurious interrupt may be raised when data is in the RX FIFO 105862306a36Sopenharmony_ci * but is yet to be drained by DMA. 105962306a36Sopenharmony_ci */ 106062306a36Sopenharmony_ci if (priv->habit & UART_HAS_RHR_IT_DIS) { 106162306a36Sopenharmony_ci reg = serial_in(p, UART_OMAP_IER2); 106262306a36Sopenharmony_ci reg |= UART_OMAP_IER2_RHR_IT_DIS; 106362306a36Sopenharmony_ci serial_out(p, UART_OMAP_IER2, reg); 106462306a36Sopenharmony_ci } 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci dma_async_issue_pending(dma->rxchan); 106762306a36Sopenharmony_ciout: 106862306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->rx_dma_lock, flags); 106962306a36Sopenharmony_ci return err; 107062306a36Sopenharmony_ci} 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_cistatic int omap_8250_tx_dma(struct uart_8250_port *p); 107362306a36Sopenharmony_ci 107462306a36Sopenharmony_cistatic void omap_8250_dma_tx_complete(void *param) 107562306a36Sopenharmony_ci{ 107662306a36Sopenharmony_ci struct uart_8250_port *p = param; 107762306a36Sopenharmony_ci struct uart_8250_dma *dma = p->dma; 107862306a36Sopenharmony_ci struct circ_buf *xmit = &p->port.state->xmit; 107962306a36Sopenharmony_ci unsigned long flags; 108062306a36Sopenharmony_ci bool en_thri = false; 108162306a36Sopenharmony_ci struct omap8250_priv *priv = p->port.private_data; 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr, 108462306a36Sopenharmony_ci UART_XMIT_SIZE, DMA_TO_DEVICE); 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci spin_lock_irqsave(&p->port.lock, flags); 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci dma->tx_running = 0; 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci uart_xmit_advance(&p->port, dma->tx_size); 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci if (priv->delayed_restore) { 109362306a36Sopenharmony_ci priv->delayed_restore = 0; 109462306a36Sopenharmony_ci omap8250_restore_regs(p); 109562306a36Sopenharmony_ci } 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 109862306a36Sopenharmony_ci uart_write_wakeup(&p->port); 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port)) { 110162306a36Sopenharmony_ci int ret; 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci ret = omap_8250_tx_dma(p); 110462306a36Sopenharmony_ci if (ret) 110562306a36Sopenharmony_ci en_thri = true; 110662306a36Sopenharmony_ci } else if (p->capabilities & UART_CAP_RPM) { 110762306a36Sopenharmony_ci en_thri = true; 110862306a36Sopenharmony_ci } 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci if (en_thri) { 111162306a36Sopenharmony_ci dma->tx_err = 1; 111262306a36Sopenharmony_ci serial8250_set_THRI(p); 111362306a36Sopenharmony_ci } 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ci spin_unlock_irqrestore(&p->port.lock, flags); 111662306a36Sopenharmony_ci} 111762306a36Sopenharmony_ci 111862306a36Sopenharmony_cistatic int omap_8250_tx_dma(struct uart_8250_port *p) 111962306a36Sopenharmony_ci{ 112062306a36Sopenharmony_ci struct uart_8250_dma *dma = p->dma; 112162306a36Sopenharmony_ci struct omap8250_priv *priv = p->port.private_data; 112262306a36Sopenharmony_ci struct circ_buf *xmit = &p->port.state->xmit; 112362306a36Sopenharmony_ci struct dma_async_tx_descriptor *desc; 112462306a36Sopenharmony_ci unsigned int skip_byte = 0; 112562306a36Sopenharmony_ci int ret; 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci if (dma->tx_running) 112862306a36Sopenharmony_ci return 0; 112962306a36Sopenharmony_ci if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) { 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci /* 113262306a36Sopenharmony_ci * Even if no data, we need to return an error for the two cases 113362306a36Sopenharmony_ci * below so serial8250_tx_chars() is invoked and properly clears 113462306a36Sopenharmony_ci * THRI and/or runtime suspend. 113562306a36Sopenharmony_ci */ 113662306a36Sopenharmony_ci if (dma->tx_err || p->capabilities & UART_CAP_RPM) { 113762306a36Sopenharmony_ci ret = -EBUSY; 113862306a36Sopenharmony_ci goto err; 113962306a36Sopenharmony_ci } 114062306a36Sopenharmony_ci serial8250_clear_THRI(p); 114162306a36Sopenharmony_ci return 0; 114262306a36Sopenharmony_ci } 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); 114562306a36Sopenharmony_ci if (priv->habit & OMAP_DMA_TX_KICK) { 114662306a36Sopenharmony_ci u8 tx_lvl; 114762306a36Sopenharmony_ci 114862306a36Sopenharmony_ci /* 114962306a36Sopenharmony_ci * We need to put the first byte into the FIFO in order to start 115062306a36Sopenharmony_ci * the DMA transfer. For transfers smaller than four bytes we 115162306a36Sopenharmony_ci * don't bother doing DMA at all. It seem not matter if there 115262306a36Sopenharmony_ci * are still bytes in the FIFO from the last transfer (in case 115362306a36Sopenharmony_ci * we got here directly from omap_8250_dma_tx_complete()). Bytes 115462306a36Sopenharmony_ci * leaving the FIFO seem not to trigger the DMA transfer. It is 115562306a36Sopenharmony_ci * really the byte that we put into the FIFO. 115662306a36Sopenharmony_ci * If the FIFO is already full then we most likely got here from 115762306a36Sopenharmony_ci * omap_8250_dma_tx_complete(). And this means the DMA engine 115862306a36Sopenharmony_ci * just completed its work. We don't have to wait the complete 115962306a36Sopenharmony_ci * 86us at 115200,8n1 but around 60us (not to mention lower 116062306a36Sopenharmony_ci * baudrates). So in that case we take the interrupt and try 116162306a36Sopenharmony_ci * again with an empty FIFO. 116262306a36Sopenharmony_ci */ 116362306a36Sopenharmony_ci tx_lvl = serial_in(p, UART_OMAP_TX_LVL); 116462306a36Sopenharmony_ci if (tx_lvl == p->tx_loadsz) { 116562306a36Sopenharmony_ci ret = -EBUSY; 116662306a36Sopenharmony_ci goto err; 116762306a36Sopenharmony_ci } 116862306a36Sopenharmony_ci if (dma->tx_size < 4) { 116962306a36Sopenharmony_ci ret = -EINVAL; 117062306a36Sopenharmony_ci goto err; 117162306a36Sopenharmony_ci } 117262306a36Sopenharmony_ci skip_byte = 1; 117362306a36Sopenharmony_ci } 117462306a36Sopenharmony_ci 117562306a36Sopenharmony_ci desc = dmaengine_prep_slave_single(dma->txchan, 117662306a36Sopenharmony_ci dma->tx_addr + xmit->tail + skip_byte, 117762306a36Sopenharmony_ci dma->tx_size - skip_byte, DMA_MEM_TO_DEV, 117862306a36Sopenharmony_ci DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 117962306a36Sopenharmony_ci if (!desc) { 118062306a36Sopenharmony_ci ret = -EBUSY; 118162306a36Sopenharmony_ci goto err; 118262306a36Sopenharmony_ci } 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_ci dma->tx_running = 1; 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci desc->callback = omap_8250_dma_tx_complete; 118762306a36Sopenharmony_ci desc->callback_param = p; 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_ci dma->tx_cookie = dmaengine_submit(desc); 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci dma_sync_single_for_device(dma->txchan->device->dev, dma->tx_addr, 119262306a36Sopenharmony_ci UART_XMIT_SIZE, DMA_TO_DEVICE); 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci dma_async_issue_pending(dma->txchan); 119562306a36Sopenharmony_ci if (dma->tx_err) 119662306a36Sopenharmony_ci dma->tx_err = 0; 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci serial8250_clear_THRI(p); 119962306a36Sopenharmony_ci if (skip_byte) 120062306a36Sopenharmony_ci serial_out(p, UART_TX, xmit->buf[xmit->tail]); 120162306a36Sopenharmony_ci return 0; 120262306a36Sopenharmony_cierr: 120362306a36Sopenharmony_ci dma->tx_err = 1; 120462306a36Sopenharmony_ci return ret; 120562306a36Sopenharmony_ci} 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_cistatic bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir) 120862306a36Sopenharmony_ci{ 120962306a36Sopenharmony_ci switch (iir & 0x3f) { 121062306a36Sopenharmony_ci case UART_IIR_RLSI: 121162306a36Sopenharmony_ci case UART_IIR_RX_TIMEOUT: 121262306a36Sopenharmony_ci case UART_IIR_RDI: 121362306a36Sopenharmony_ci omap_8250_rx_dma_flush(up); 121462306a36Sopenharmony_ci return true; 121562306a36Sopenharmony_ci } 121662306a36Sopenharmony_ci return omap_8250_rx_dma(up); 121762306a36Sopenharmony_ci} 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_cistatic u16 omap_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir, u16 status) 122062306a36Sopenharmony_ci{ 122162306a36Sopenharmony_ci if ((status & (UART_LSR_DR | UART_LSR_BI)) && 122262306a36Sopenharmony_ci (iir & UART_IIR_RDI)) { 122362306a36Sopenharmony_ci if (handle_rx_dma(up, iir)) { 122462306a36Sopenharmony_ci status = serial8250_rx_chars(up, status); 122562306a36Sopenharmony_ci omap_8250_rx_dma(up); 122662306a36Sopenharmony_ci } 122762306a36Sopenharmony_ci } 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci return status; 123062306a36Sopenharmony_ci} 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_cistatic void am654_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir, 123362306a36Sopenharmony_ci u16 status) 123462306a36Sopenharmony_ci{ 123562306a36Sopenharmony_ci /* Port locked to synchronize UART_IER access against the console. */ 123662306a36Sopenharmony_ci lockdep_assert_held_once(&up->port.lock); 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_ci /* 123962306a36Sopenharmony_ci * Queue a new transfer if FIFO has data. 124062306a36Sopenharmony_ci */ 124162306a36Sopenharmony_ci if ((status & (UART_LSR_DR | UART_LSR_BI)) && 124262306a36Sopenharmony_ci (up->ier & UART_IER_RDI)) { 124362306a36Sopenharmony_ci omap_8250_rx_dma(up); 124462306a36Sopenharmony_ci serial_out(up, UART_OMAP_EFR2, UART_OMAP_EFR2_TIMEOUT_BEHAVE); 124562306a36Sopenharmony_ci } else if ((iir & 0x3f) == UART_IIR_RX_TIMEOUT) { 124662306a36Sopenharmony_ci /* 124762306a36Sopenharmony_ci * Disable RX timeout, read IIR to clear 124862306a36Sopenharmony_ci * current timeout condition, clear EFR2 to 124962306a36Sopenharmony_ci * periodic timeouts, re-enable interrupts. 125062306a36Sopenharmony_ci */ 125162306a36Sopenharmony_ci up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); 125262306a36Sopenharmony_ci serial_out(up, UART_IER, up->ier); 125362306a36Sopenharmony_ci omap_8250_rx_dma_flush(up); 125462306a36Sopenharmony_ci serial_in(up, UART_IIR); 125562306a36Sopenharmony_ci serial_out(up, UART_OMAP_EFR2, 0x0); 125662306a36Sopenharmony_ci up->ier |= UART_IER_RLSI | UART_IER_RDI; 125762306a36Sopenharmony_ci serial_out(up, UART_IER, up->ier); 125862306a36Sopenharmony_ci } 125962306a36Sopenharmony_ci} 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_ci/* 126262306a36Sopenharmony_ci * This is mostly serial8250_handle_irq(). We have a slightly different DMA 126362306a36Sopenharmony_ci * hoook for RX/TX and need different logic for them in the ISR. Therefore we 126462306a36Sopenharmony_ci * use the default routine in the non-DMA case and this one for with DMA. 126562306a36Sopenharmony_ci */ 126662306a36Sopenharmony_cistatic int omap_8250_dma_handle_irq(struct uart_port *port) 126762306a36Sopenharmony_ci{ 126862306a36Sopenharmony_ci struct uart_8250_port *up = up_to_u8250p(port); 126962306a36Sopenharmony_ci struct omap8250_priv *priv = up->port.private_data; 127062306a36Sopenharmony_ci u16 status; 127162306a36Sopenharmony_ci u8 iir; 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_ci serial8250_rpm_get(up); 127462306a36Sopenharmony_ci 127562306a36Sopenharmony_ci iir = serial_port_in(port, UART_IIR); 127662306a36Sopenharmony_ci if (iir & UART_IIR_NO_INT) { 127762306a36Sopenharmony_ci serial8250_rpm_put(up); 127862306a36Sopenharmony_ci return IRQ_HANDLED; 127962306a36Sopenharmony_ci } 128062306a36Sopenharmony_ci 128162306a36Sopenharmony_ci spin_lock(&port->lock); 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci status = serial_port_in(port, UART_LSR); 128462306a36Sopenharmony_ci 128562306a36Sopenharmony_ci if ((iir & 0x3f) != UART_IIR_THRI) { 128662306a36Sopenharmony_ci if (priv->habit & UART_HAS_EFR2) 128762306a36Sopenharmony_ci am654_8250_handle_rx_dma(up, iir, status); 128862306a36Sopenharmony_ci else 128962306a36Sopenharmony_ci status = omap_8250_handle_rx_dma(up, iir, status); 129062306a36Sopenharmony_ci } 129162306a36Sopenharmony_ci 129262306a36Sopenharmony_ci serial8250_modem_status(up); 129362306a36Sopenharmony_ci if (status & UART_LSR_THRE && up->dma->tx_err) { 129462306a36Sopenharmony_ci if (uart_tx_stopped(&up->port) || 129562306a36Sopenharmony_ci uart_circ_empty(&up->port.state->xmit)) { 129662306a36Sopenharmony_ci up->dma->tx_err = 0; 129762306a36Sopenharmony_ci serial8250_tx_chars(up); 129862306a36Sopenharmony_ci } else { 129962306a36Sopenharmony_ci /* 130062306a36Sopenharmony_ci * try again due to an earlier failer which 130162306a36Sopenharmony_ci * might have been resolved by now. 130262306a36Sopenharmony_ci */ 130362306a36Sopenharmony_ci if (omap_8250_tx_dma(up)) 130462306a36Sopenharmony_ci serial8250_tx_chars(up); 130562306a36Sopenharmony_ci } 130662306a36Sopenharmony_ci } 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci uart_unlock_and_check_sysrq(port); 130962306a36Sopenharmony_ci 131062306a36Sopenharmony_ci serial8250_rpm_put(up); 131162306a36Sopenharmony_ci return 1; 131262306a36Sopenharmony_ci} 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_cistatic bool the_no_dma_filter_fn(struct dma_chan *chan, void *param) 131562306a36Sopenharmony_ci{ 131662306a36Sopenharmony_ci return false; 131762306a36Sopenharmony_ci} 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci#else 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_cistatic inline int omap_8250_rx_dma(struct uart_8250_port *p) 132262306a36Sopenharmony_ci{ 132362306a36Sopenharmony_ci return -EINVAL; 132462306a36Sopenharmony_ci} 132562306a36Sopenharmony_ci#endif 132662306a36Sopenharmony_ci 132762306a36Sopenharmony_cistatic int omap8250_no_handle_irq(struct uart_port *port) 132862306a36Sopenharmony_ci{ 132962306a36Sopenharmony_ci /* IRQ has not been requested but handling irq? */ 133062306a36Sopenharmony_ci WARN_ONCE(1, "Unexpected irq handling before port startup\n"); 133162306a36Sopenharmony_ci return 0; 133262306a36Sopenharmony_ci} 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_cistatic struct omap8250_dma_params am654_dma = { 133562306a36Sopenharmony_ci .rx_size = SZ_2K, 133662306a36Sopenharmony_ci .rx_trigger = 1, 133762306a36Sopenharmony_ci .tx_trigger = TX_TRIGGER, 133862306a36Sopenharmony_ci}; 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_cistatic struct omap8250_dma_params am33xx_dma = { 134162306a36Sopenharmony_ci .rx_size = RX_TRIGGER, 134262306a36Sopenharmony_ci .rx_trigger = RX_TRIGGER, 134362306a36Sopenharmony_ci .tx_trigger = TX_TRIGGER, 134462306a36Sopenharmony_ci}; 134562306a36Sopenharmony_ci 134662306a36Sopenharmony_cistatic struct omap8250_platdata am654_platdata = { 134762306a36Sopenharmony_ci .dma_params = &am654_dma, 134862306a36Sopenharmony_ci .habit = UART_HAS_EFR2 | UART_HAS_RHR_IT_DIS | 134962306a36Sopenharmony_ci UART_RX_TIMEOUT_QUIRK | UART_HAS_NATIVE_RS485, 135062306a36Sopenharmony_ci}; 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_cistatic struct omap8250_platdata am33xx_platdata = { 135362306a36Sopenharmony_ci .dma_params = &am33xx_dma, 135462306a36Sopenharmony_ci .habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE, 135562306a36Sopenharmony_ci}; 135662306a36Sopenharmony_ci 135762306a36Sopenharmony_cistatic struct omap8250_platdata omap4_platdata = { 135862306a36Sopenharmony_ci .dma_params = &am33xx_dma, 135962306a36Sopenharmony_ci .habit = UART_ERRATA_CLOCK_DISABLE, 136062306a36Sopenharmony_ci}; 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_cistatic const struct of_device_id omap8250_dt_ids[] = { 136362306a36Sopenharmony_ci { .compatible = "ti,am654-uart", .data = &am654_platdata, }, 136462306a36Sopenharmony_ci { .compatible = "ti,omap2-uart" }, 136562306a36Sopenharmony_ci { .compatible = "ti,omap3-uart" }, 136662306a36Sopenharmony_ci { .compatible = "ti,omap4-uart", .data = &omap4_platdata, }, 136762306a36Sopenharmony_ci { .compatible = "ti,am3352-uart", .data = &am33xx_platdata, }, 136862306a36Sopenharmony_ci { .compatible = "ti,am4372-uart", .data = &am33xx_platdata, }, 136962306a36Sopenharmony_ci { .compatible = "ti,dra742-uart", .data = &omap4_platdata, }, 137062306a36Sopenharmony_ci {}, 137162306a36Sopenharmony_ci}; 137262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, omap8250_dt_ids); 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_cistatic int omap8250_probe(struct platform_device *pdev) 137562306a36Sopenharmony_ci{ 137662306a36Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 137762306a36Sopenharmony_ci struct omap8250_priv *priv; 137862306a36Sopenharmony_ci const struct omap8250_platdata *pdata; 137962306a36Sopenharmony_ci struct uart_8250_port up; 138062306a36Sopenharmony_ci struct resource *regs; 138162306a36Sopenharmony_ci void __iomem *membase; 138262306a36Sopenharmony_ci int irq, ret; 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_ci irq = platform_get_irq(pdev, 0); 138562306a36Sopenharmony_ci if (irq < 0) 138662306a36Sopenharmony_ci return irq; 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ci regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 138962306a36Sopenharmony_ci if (!regs) { 139062306a36Sopenharmony_ci dev_err(&pdev->dev, "missing registers\n"); 139162306a36Sopenharmony_ci return -EINVAL; 139262306a36Sopenharmony_ci } 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 139562306a36Sopenharmony_ci if (!priv) 139662306a36Sopenharmony_ci return -ENOMEM; 139762306a36Sopenharmony_ci 139862306a36Sopenharmony_ci membase = devm_ioremap(&pdev->dev, regs->start, 139962306a36Sopenharmony_ci resource_size(regs)); 140062306a36Sopenharmony_ci if (!membase) 140162306a36Sopenharmony_ci return -ENODEV; 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci memset(&up, 0, sizeof(up)); 140462306a36Sopenharmony_ci up.port.dev = &pdev->dev; 140562306a36Sopenharmony_ci up.port.mapbase = regs->start; 140662306a36Sopenharmony_ci up.port.membase = membase; 140762306a36Sopenharmony_ci up.port.irq = irq; 140862306a36Sopenharmony_ci /* 140962306a36Sopenharmony_ci * It claims to be 16C750 compatible however it is a little different. 141062306a36Sopenharmony_ci * It has EFR and has no FCR7_64byte bit. The AFE (which it claims to 141162306a36Sopenharmony_ci * have) is enabled via EFR instead of MCR. The type is set here 8250 141262306a36Sopenharmony_ci * just to get things going. UNKNOWN does not work for a few reasons and 141362306a36Sopenharmony_ci * we don't need our own type since we don't use 8250's set_termios() 141462306a36Sopenharmony_ci * or pm callback. 141562306a36Sopenharmony_ci */ 141662306a36Sopenharmony_ci up.port.type = PORT_8250; 141762306a36Sopenharmony_ci up.port.iotype = UPIO_MEM; 141862306a36Sopenharmony_ci up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SOFT_FLOW | 141962306a36Sopenharmony_ci UPF_HARD_FLOW; 142062306a36Sopenharmony_ci up.port.private_data = priv; 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ci up.port.regshift = OMAP_UART_REGSHIFT; 142362306a36Sopenharmony_ci up.port.fifosize = 64; 142462306a36Sopenharmony_ci up.tx_loadsz = 64; 142562306a36Sopenharmony_ci up.capabilities = UART_CAP_FIFO; 142662306a36Sopenharmony_ci#ifdef CONFIG_PM 142762306a36Sopenharmony_ci /* 142862306a36Sopenharmony_ci * Runtime PM is mostly transparent. However to do it right we need to a 142962306a36Sopenharmony_ci * TX empty interrupt before we can put the device to auto idle. So if 143062306a36Sopenharmony_ci * PM is not enabled we don't add that flag and can spare that one extra 143162306a36Sopenharmony_ci * interrupt in the TX path. 143262306a36Sopenharmony_ci */ 143362306a36Sopenharmony_ci up.capabilities |= UART_CAP_RPM; 143462306a36Sopenharmony_ci#endif 143562306a36Sopenharmony_ci up.port.set_termios = omap_8250_set_termios; 143662306a36Sopenharmony_ci up.port.set_mctrl = omap8250_set_mctrl; 143762306a36Sopenharmony_ci up.port.pm = omap_8250_pm; 143862306a36Sopenharmony_ci up.port.startup = omap_8250_startup; 143962306a36Sopenharmony_ci up.port.shutdown = omap_8250_shutdown; 144062306a36Sopenharmony_ci up.port.throttle = omap_8250_throttle; 144162306a36Sopenharmony_ci up.port.unthrottle = omap_8250_unthrottle; 144262306a36Sopenharmony_ci up.port.rs485_config = omap8250_rs485_config; 144362306a36Sopenharmony_ci /* same rs485_supported for software emulation and native RS485 */ 144462306a36Sopenharmony_ci up.port.rs485_supported = serial8250_em485_supported; 144562306a36Sopenharmony_ci up.rs485_start_tx = serial8250_em485_start_tx; 144662306a36Sopenharmony_ci up.rs485_stop_tx = serial8250_em485_stop_tx; 144762306a36Sopenharmony_ci up.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); 144862306a36Sopenharmony_ci 144962306a36Sopenharmony_ci ret = of_alias_get_id(np, "serial"); 145062306a36Sopenharmony_ci if (ret < 0) { 145162306a36Sopenharmony_ci dev_err(&pdev->dev, "failed to get alias\n"); 145262306a36Sopenharmony_ci return ret; 145362306a36Sopenharmony_ci } 145462306a36Sopenharmony_ci up.port.line = ret; 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_ci if (of_property_read_u32(np, "clock-frequency", &up.port.uartclk)) { 145762306a36Sopenharmony_ci struct clk *clk; 145862306a36Sopenharmony_ci 145962306a36Sopenharmony_ci clk = devm_clk_get(&pdev->dev, NULL); 146062306a36Sopenharmony_ci if (IS_ERR(clk)) { 146162306a36Sopenharmony_ci if (PTR_ERR(clk) == -EPROBE_DEFER) 146262306a36Sopenharmony_ci return -EPROBE_DEFER; 146362306a36Sopenharmony_ci } else { 146462306a36Sopenharmony_ci up.port.uartclk = clk_get_rate(clk); 146562306a36Sopenharmony_ci } 146662306a36Sopenharmony_ci } 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_ci if (of_property_read_u32(np, "overrun-throttle-ms", 146962306a36Sopenharmony_ci &up.overrun_backoff_time_ms) != 0) 147062306a36Sopenharmony_ci up.overrun_backoff_time_ms = 0; 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_ci pdata = of_device_get_match_data(&pdev->dev); 147362306a36Sopenharmony_ci if (pdata) 147462306a36Sopenharmony_ci priv->habit |= pdata->habit; 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_ci if (!up.port.uartclk) { 147762306a36Sopenharmony_ci up.port.uartclk = DEFAULT_CLK_SPEED; 147862306a36Sopenharmony_ci dev_warn(&pdev->dev, 147962306a36Sopenharmony_ci "No clock speed specified: using default: %d\n", 148062306a36Sopenharmony_ci DEFAULT_CLK_SPEED); 148162306a36Sopenharmony_ci } 148262306a36Sopenharmony_ci 148362306a36Sopenharmony_ci priv->membase = membase; 148462306a36Sopenharmony_ci priv->line = -ENODEV; 148562306a36Sopenharmony_ci priv->latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE; 148662306a36Sopenharmony_ci priv->calc_latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE; 148762306a36Sopenharmony_ci cpu_latency_qos_add_request(&priv->pm_qos_request, priv->latency); 148862306a36Sopenharmony_ci INIT_WORK(&priv->qos_work, omap8250_uart_qos_work); 148962306a36Sopenharmony_ci 149062306a36Sopenharmony_ci spin_lock_init(&priv->rx_dma_lock); 149162306a36Sopenharmony_ci 149262306a36Sopenharmony_ci platform_set_drvdata(pdev, priv); 149362306a36Sopenharmony_ci 149462306a36Sopenharmony_ci device_init_wakeup(&pdev->dev, true); 149562306a36Sopenharmony_ci pm_runtime_enable(&pdev->dev); 149662306a36Sopenharmony_ci pm_runtime_use_autosuspend(&pdev->dev); 149762306a36Sopenharmony_ci 149862306a36Sopenharmony_ci /* 149962306a36Sopenharmony_ci * Disable runtime PM until autosuspend delay unless specifically 150062306a36Sopenharmony_ci * enabled by the user via sysfs. This is the historic way to 150162306a36Sopenharmony_ci * prevent an unsafe default policy with lossy characters on wake-up. 150262306a36Sopenharmony_ci * For serdev devices this is not needed, the policy can be managed by 150362306a36Sopenharmony_ci * the serdev driver. 150462306a36Sopenharmony_ci */ 150562306a36Sopenharmony_ci if (!of_get_available_child_count(pdev->dev.of_node)) 150662306a36Sopenharmony_ci pm_runtime_set_autosuspend_delay(&pdev->dev, -1); 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_ci pm_runtime_irq_safe(&pdev->dev); 150962306a36Sopenharmony_ci 151062306a36Sopenharmony_ci pm_runtime_get_sync(&pdev->dev); 151162306a36Sopenharmony_ci 151262306a36Sopenharmony_ci omap_serial_fill_features_erratas(&up, priv); 151362306a36Sopenharmony_ci up.port.handle_irq = omap8250_no_handle_irq; 151462306a36Sopenharmony_ci priv->rx_trigger = RX_TRIGGER; 151562306a36Sopenharmony_ci priv->tx_trigger = TX_TRIGGER; 151662306a36Sopenharmony_ci#ifdef CONFIG_SERIAL_8250_DMA 151762306a36Sopenharmony_ci /* 151862306a36Sopenharmony_ci * Oh DMA support. If there are no DMA properties in the DT then 151962306a36Sopenharmony_ci * we will fall back to a generic DMA channel which does not 152062306a36Sopenharmony_ci * really work here. To ensure that we do not get a generic DMA 152162306a36Sopenharmony_ci * channel assigned, we have the the_no_dma_filter_fn() here. 152262306a36Sopenharmony_ci * To avoid "failed to request DMA" messages we check for DMA 152362306a36Sopenharmony_ci * properties in DT. 152462306a36Sopenharmony_ci */ 152562306a36Sopenharmony_ci ret = of_property_count_strings(np, "dma-names"); 152662306a36Sopenharmony_ci if (ret == 2) { 152762306a36Sopenharmony_ci struct omap8250_dma_params *dma_params = NULL; 152862306a36Sopenharmony_ci struct uart_8250_dma *dma = &priv->omap8250_dma; 152962306a36Sopenharmony_ci 153062306a36Sopenharmony_ci dma->fn = the_no_dma_filter_fn; 153162306a36Sopenharmony_ci dma->tx_dma = omap_8250_tx_dma; 153262306a36Sopenharmony_ci dma->rx_dma = omap_8250_rx_dma; 153362306a36Sopenharmony_ci if (pdata) 153462306a36Sopenharmony_ci dma_params = pdata->dma_params; 153562306a36Sopenharmony_ci 153662306a36Sopenharmony_ci if (dma_params) { 153762306a36Sopenharmony_ci dma->rx_size = dma_params->rx_size; 153862306a36Sopenharmony_ci dma->rxconf.src_maxburst = dma_params->rx_trigger; 153962306a36Sopenharmony_ci dma->txconf.dst_maxburst = dma_params->tx_trigger; 154062306a36Sopenharmony_ci priv->rx_trigger = dma_params->rx_trigger; 154162306a36Sopenharmony_ci priv->tx_trigger = dma_params->tx_trigger; 154262306a36Sopenharmony_ci } else { 154362306a36Sopenharmony_ci dma->rx_size = RX_TRIGGER; 154462306a36Sopenharmony_ci dma->rxconf.src_maxburst = RX_TRIGGER; 154562306a36Sopenharmony_ci dma->txconf.dst_maxburst = TX_TRIGGER; 154662306a36Sopenharmony_ci } 154762306a36Sopenharmony_ci } 154862306a36Sopenharmony_ci#endif 154962306a36Sopenharmony_ci 155062306a36Sopenharmony_ci irq_set_status_flags(irq, IRQ_NOAUTOEN); 155162306a36Sopenharmony_ci ret = devm_request_irq(&pdev->dev, irq, omap8250_irq, 0, 155262306a36Sopenharmony_ci dev_name(&pdev->dev), priv); 155362306a36Sopenharmony_ci if (ret < 0) 155462306a36Sopenharmony_ci return ret; 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_ci priv->wakeirq = irq_of_parse_and_map(np, 1); 155762306a36Sopenharmony_ci 155862306a36Sopenharmony_ci ret = serial8250_register_8250_port(&up); 155962306a36Sopenharmony_ci if (ret < 0) { 156062306a36Sopenharmony_ci dev_err(&pdev->dev, "unable to register 8250 port\n"); 156162306a36Sopenharmony_ci goto err; 156262306a36Sopenharmony_ci } 156362306a36Sopenharmony_ci priv->line = ret; 156462306a36Sopenharmony_ci pm_runtime_mark_last_busy(&pdev->dev); 156562306a36Sopenharmony_ci pm_runtime_put_autosuspend(&pdev->dev); 156662306a36Sopenharmony_ci return 0; 156762306a36Sopenharmony_cierr: 156862306a36Sopenharmony_ci pm_runtime_dont_use_autosuspend(&pdev->dev); 156962306a36Sopenharmony_ci pm_runtime_put_sync(&pdev->dev); 157062306a36Sopenharmony_ci flush_work(&priv->qos_work); 157162306a36Sopenharmony_ci pm_runtime_disable(&pdev->dev); 157262306a36Sopenharmony_ci cpu_latency_qos_remove_request(&priv->pm_qos_request); 157362306a36Sopenharmony_ci return ret; 157462306a36Sopenharmony_ci} 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_cistatic int omap8250_remove(struct platform_device *pdev) 157762306a36Sopenharmony_ci{ 157862306a36Sopenharmony_ci struct omap8250_priv *priv = platform_get_drvdata(pdev); 157962306a36Sopenharmony_ci struct uart_8250_port *up; 158062306a36Sopenharmony_ci int err; 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_ci err = pm_runtime_resume_and_get(&pdev->dev); 158362306a36Sopenharmony_ci if (err) 158462306a36Sopenharmony_ci dev_err(&pdev->dev, "Failed to resume hardware\n"); 158562306a36Sopenharmony_ci 158662306a36Sopenharmony_ci up = serial8250_get_port(priv->line); 158762306a36Sopenharmony_ci omap_8250_shutdown(&up->port); 158862306a36Sopenharmony_ci serial8250_unregister_port(priv->line); 158962306a36Sopenharmony_ci priv->line = -ENODEV; 159062306a36Sopenharmony_ci pm_runtime_dont_use_autosuspend(&pdev->dev); 159162306a36Sopenharmony_ci pm_runtime_put_sync(&pdev->dev); 159262306a36Sopenharmony_ci flush_work(&priv->qos_work); 159362306a36Sopenharmony_ci pm_runtime_disable(&pdev->dev); 159462306a36Sopenharmony_ci cpu_latency_qos_remove_request(&priv->pm_qos_request); 159562306a36Sopenharmony_ci device_init_wakeup(&pdev->dev, false); 159662306a36Sopenharmony_ci return 0; 159762306a36Sopenharmony_ci} 159862306a36Sopenharmony_ci 159962306a36Sopenharmony_cistatic int omap8250_prepare(struct device *dev) 160062306a36Sopenharmony_ci{ 160162306a36Sopenharmony_ci struct omap8250_priv *priv = dev_get_drvdata(dev); 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_ci if (!priv) 160462306a36Sopenharmony_ci return 0; 160562306a36Sopenharmony_ci priv->is_suspending = true; 160662306a36Sopenharmony_ci return 0; 160762306a36Sopenharmony_ci} 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_cistatic void omap8250_complete(struct device *dev) 161062306a36Sopenharmony_ci{ 161162306a36Sopenharmony_ci struct omap8250_priv *priv = dev_get_drvdata(dev); 161262306a36Sopenharmony_ci 161362306a36Sopenharmony_ci if (!priv) 161462306a36Sopenharmony_ci return; 161562306a36Sopenharmony_ci priv->is_suspending = false; 161662306a36Sopenharmony_ci} 161762306a36Sopenharmony_ci 161862306a36Sopenharmony_cistatic int omap8250_suspend(struct device *dev) 161962306a36Sopenharmony_ci{ 162062306a36Sopenharmony_ci struct omap8250_priv *priv = dev_get_drvdata(dev); 162162306a36Sopenharmony_ci struct uart_8250_port *up = serial8250_get_port(priv->line); 162262306a36Sopenharmony_ci int err = 0; 162362306a36Sopenharmony_ci 162462306a36Sopenharmony_ci serial8250_suspend_port(priv->line); 162562306a36Sopenharmony_ci 162662306a36Sopenharmony_ci err = pm_runtime_resume_and_get(dev); 162762306a36Sopenharmony_ci if (err) 162862306a36Sopenharmony_ci return err; 162962306a36Sopenharmony_ci if (!device_may_wakeup(dev)) 163062306a36Sopenharmony_ci priv->wer = 0; 163162306a36Sopenharmony_ci serial_out(up, UART_OMAP_WER, priv->wer); 163262306a36Sopenharmony_ci if (uart_console(&up->port) && console_suspend_enabled) 163362306a36Sopenharmony_ci err = pm_runtime_force_suspend(dev); 163462306a36Sopenharmony_ci flush_work(&priv->qos_work); 163562306a36Sopenharmony_ci 163662306a36Sopenharmony_ci return err; 163762306a36Sopenharmony_ci} 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_cistatic int omap8250_resume(struct device *dev) 164062306a36Sopenharmony_ci{ 164162306a36Sopenharmony_ci struct omap8250_priv *priv = dev_get_drvdata(dev); 164262306a36Sopenharmony_ci struct uart_8250_port *up = serial8250_get_port(priv->line); 164362306a36Sopenharmony_ci int err; 164462306a36Sopenharmony_ci 164562306a36Sopenharmony_ci if (uart_console(&up->port) && console_suspend_enabled) { 164662306a36Sopenharmony_ci err = pm_runtime_force_resume(dev); 164762306a36Sopenharmony_ci if (err) 164862306a36Sopenharmony_ci return err; 164962306a36Sopenharmony_ci } 165062306a36Sopenharmony_ci 165162306a36Sopenharmony_ci serial8250_resume_port(priv->line); 165262306a36Sopenharmony_ci /* Paired with pm_runtime_resume_and_get() in omap8250_suspend() */ 165362306a36Sopenharmony_ci pm_runtime_mark_last_busy(dev); 165462306a36Sopenharmony_ci pm_runtime_put_autosuspend(dev); 165562306a36Sopenharmony_ci 165662306a36Sopenharmony_ci return 0; 165762306a36Sopenharmony_ci} 165862306a36Sopenharmony_ci 165962306a36Sopenharmony_cistatic int omap8250_lost_context(struct uart_8250_port *up) 166062306a36Sopenharmony_ci{ 166162306a36Sopenharmony_ci u32 val; 166262306a36Sopenharmony_ci 166362306a36Sopenharmony_ci val = serial_in(up, UART_OMAP_SCR); 166462306a36Sopenharmony_ci /* 166562306a36Sopenharmony_ci * If we lose context, then SCR is set to its reset value of zero. 166662306a36Sopenharmony_ci * After set_termios() we set bit 3 of SCR (TX_EMPTY_CTL_IT) to 1, 166762306a36Sopenharmony_ci * among other bits, to never set the register back to zero again. 166862306a36Sopenharmony_ci */ 166962306a36Sopenharmony_ci if (!val) 167062306a36Sopenharmony_ci return 1; 167162306a36Sopenharmony_ci return 0; 167262306a36Sopenharmony_ci} 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_cistatic void uart_write(struct omap8250_priv *priv, u32 reg, u32 val) 167562306a36Sopenharmony_ci{ 167662306a36Sopenharmony_ci writel(val, priv->membase + (reg << OMAP_UART_REGSHIFT)); 167762306a36Sopenharmony_ci} 167862306a36Sopenharmony_ci 167962306a36Sopenharmony_ci/* TODO: in future, this should happen via API in drivers/reset/ */ 168062306a36Sopenharmony_cistatic int omap8250_soft_reset(struct device *dev) 168162306a36Sopenharmony_ci{ 168262306a36Sopenharmony_ci struct omap8250_priv *priv = dev_get_drvdata(dev); 168362306a36Sopenharmony_ci int timeout = 100; 168462306a36Sopenharmony_ci int sysc; 168562306a36Sopenharmony_ci int syss; 168662306a36Sopenharmony_ci 168762306a36Sopenharmony_ci /* 168862306a36Sopenharmony_ci * At least on omap4, unused uarts may not idle after reset without 168962306a36Sopenharmony_ci * a basic scr dma configuration even with no dma in use. The 169062306a36Sopenharmony_ci * module clkctrl status bits will be 1 instead of 3 blocking idle 169162306a36Sopenharmony_ci * for the whole clockdomain. The softreset below will clear scr, 169262306a36Sopenharmony_ci * and we restore it on resume so this is safe to do on all SoCs 169362306a36Sopenharmony_ci * needing omap8250_soft_reset() quirk. Do it in two writes as 169462306a36Sopenharmony_ci * recommended in the comment for omap8250_update_scr(). 169562306a36Sopenharmony_ci */ 169662306a36Sopenharmony_ci uart_write(priv, UART_OMAP_SCR, OMAP_UART_SCR_DMAMODE_1); 169762306a36Sopenharmony_ci uart_write(priv, UART_OMAP_SCR, 169862306a36Sopenharmony_ci OMAP_UART_SCR_DMAMODE_1 | OMAP_UART_SCR_DMAMODE_CTL); 169962306a36Sopenharmony_ci 170062306a36Sopenharmony_ci sysc = uart_read(priv, UART_OMAP_SYSC); 170162306a36Sopenharmony_ci 170262306a36Sopenharmony_ci /* softreset the UART */ 170362306a36Sopenharmony_ci sysc |= OMAP_UART_SYSC_SOFTRESET; 170462306a36Sopenharmony_ci uart_write(priv, UART_OMAP_SYSC, sysc); 170562306a36Sopenharmony_ci 170662306a36Sopenharmony_ci /* By experiments, 1us enough for reset complete on AM335x */ 170762306a36Sopenharmony_ci do { 170862306a36Sopenharmony_ci udelay(1); 170962306a36Sopenharmony_ci syss = uart_read(priv, UART_OMAP_SYSS); 171062306a36Sopenharmony_ci } while (--timeout && !(syss & OMAP_UART_SYSS_RESETDONE)); 171162306a36Sopenharmony_ci 171262306a36Sopenharmony_ci if (!timeout) { 171362306a36Sopenharmony_ci dev_err(dev, "timed out waiting for reset done\n"); 171462306a36Sopenharmony_ci return -ETIMEDOUT; 171562306a36Sopenharmony_ci } 171662306a36Sopenharmony_ci 171762306a36Sopenharmony_ci return 0; 171862306a36Sopenharmony_ci} 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_cistatic int omap8250_runtime_suspend(struct device *dev) 172162306a36Sopenharmony_ci{ 172262306a36Sopenharmony_ci struct omap8250_priv *priv = dev_get_drvdata(dev); 172362306a36Sopenharmony_ci struct uart_8250_port *up = NULL; 172462306a36Sopenharmony_ci 172562306a36Sopenharmony_ci if (priv->line >= 0) 172662306a36Sopenharmony_ci up = serial8250_get_port(priv->line); 172762306a36Sopenharmony_ci 172862306a36Sopenharmony_ci if (priv->habit & UART_ERRATA_CLOCK_DISABLE) { 172962306a36Sopenharmony_ci int ret; 173062306a36Sopenharmony_ci 173162306a36Sopenharmony_ci ret = omap8250_soft_reset(dev); 173262306a36Sopenharmony_ci if (ret) 173362306a36Sopenharmony_ci return ret; 173462306a36Sopenharmony_ci 173562306a36Sopenharmony_ci if (up) { 173662306a36Sopenharmony_ci /* Restore to UART mode after reset (for wakeup) */ 173762306a36Sopenharmony_ci omap8250_update_mdr1(up, priv); 173862306a36Sopenharmony_ci /* Restore wakeup enable register */ 173962306a36Sopenharmony_ci serial_out(up, UART_OMAP_WER, priv->wer); 174062306a36Sopenharmony_ci } 174162306a36Sopenharmony_ci } 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_ci if (up && up->dma && up->dma->rxchan) 174462306a36Sopenharmony_ci omap_8250_rx_dma_flush(up); 174562306a36Sopenharmony_ci 174662306a36Sopenharmony_ci priv->latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE; 174762306a36Sopenharmony_ci schedule_work(&priv->qos_work); 174862306a36Sopenharmony_ci 174962306a36Sopenharmony_ci return 0; 175062306a36Sopenharmony_ci} 175162306a36Sopenharmony_ci 175262306a36Sopenharmony_cistatic int omap8250_runtime_resume(struct device *dev) 175362306a36Sopenharmony_ci{ 175462306a36Sopenharmony_ci struct omap8250_priv *priv = dev_get_drvdata(dev); 175562306a36Sopenharmony_ci struct uart_8250_port *up = NULL; 175662306a36Sopenharmony_ci 175762306a36Sopenharmony_ci if (priv->line >= 0) 175862306a36Sopenharmony_ci up = serial8250_get_port(priv->line); 175962306a36Sopenharmony_ci 176062306a36Sopenharmony_ci if (up && omap8250_lost_context(up)) { 176162306a36Sopenharmony_ci spin_lock_irq(&up->port.lock); 176262306a36Sopenharmony_ci omap8250_restore_regs(up); 176362306a36Sopenharmony_ci spin_unlock_irq(&up->port.lock); 176462306a36Sopenharmony_ci } 176562306a36Sopenharmony_ci 176662306a36Sopenharmony_ci if (up && up->dma && up->dma->rxchan && !(priv->habit & UART_HAS_EFR2)) { 176762306a36Sopenharmony_ci spin_lock_irq(&up->port.lock); 176862306a36Sopenharmony_ci omap_8250_rx_dma(up); 176962306a36Sopenharmony_ci spin_unlock_irq(&up->port.lock); 177062306a36Sopenharmony_ci } 177162306a36Sopenharmony_ci 177262306a36Sopenharmony_ci priv->latency = priv->calc_latency; 177362306a36Sopenharmony_ci schedule_work(&priv->qos_work); 177462306a36Sopenharmony_ci return 0; 177562306a36Sopenharmony_ci} 177662306a36Sopenharmony_ci 177762306a36Sopenharmony_ci#ifdef CONFIG_SERIAL_8250_OMAP_TTYO_FIXUP 177862306a36Sopenharmony_cistatic int __init omap8250_console_fixup(void) 177962306a36Sopenharmony_ci{ 178062306a36Sopenharmony_ci char *omap_str; 178162306a36Sopenharmony_ci char *options; 178262306a36Sopenharmony_ci u8 idx; 178362306a36Sopenharmony_ci 178462306a36Sopenharmony_ci if (strstr(boot_command_line, "console=ttyS")) 178562306a36Sopenharmony_ci /* user set a ttyS based name for the console */ 178662306a36Sopenharmony_ci return 0; 178762306a36Sopenharmony_ci 178862306a36Sopenharmony_ci omap_str = strstr(boot_command_line, "console=ttyO"); 178962306a36Sopenharmony_ci if (!omap_str) 179062306a36Sopenharmony_ci /* user did not set ttyO based console, so we don't care */ 179162306a36Sopenharmony_ci return 0; 179262306a36Sopenharmony_ci 179362306a36Sopenharmony_ci omap_str += 12; 179462306a36Sopenharmony_ci if ('0' <= *omap_str && *omap_str <= '9') 179562306a36Sopenharmony_ci idx = *omap_str - '0'; 179662306a36Sopenharmony_ci else 179762306a36Sopenharmony_ci return 0; 179862306a36Sopenharmony_ci 179962306a36Sopenharmony_ci omap_str++; 180062306a36Sopenharmony_ci if (omap_str[0] == ',') { 180162306a36Sopenharmony_ci omap_str++; 180262306a36Sopenharmony_ci options = omap_str; 180362306a36Sopenharmony_ci } else { 180462306a36Sopenharmony_ci options = NULL; 180562306a36Sopenharmony_ci } 180662306a36Sopenharmony_ci 180762306a36Sopenharmony_ci add_preferred_console("ttyS", idx, options); 180862306a36Sopenharmony_ci pr_err("WARNING: Your 'console=ttyO%d' has been replaced by 'ttyS%d'\n", 180962306a36Sopenharmony_ci idx, idx); 181062306a36Sopenharmony_ci pr_err("This ensures that you still see kernel messages. Please\n"); 181162306a36Sopenharmony_ci pr_err("update your kernel commandline.\n"); 181262306a36Sopenharmony_ci return 0; 181362306a36Sopenharmony_ci} 181462306a36Sopenharmony_ciconsole_initcall(omap8250_console_fixup); 181562306a36Sopenharmony_ci#endif 181662306a36Sopenharmony_ci 181762306a36Sopenharmony_cistatic const struct dev_pm_ops omap8250_dev_pm_ops = { 181862306a36Sopenharmony_ci SYSTEM_SLEEP_PM_OPS(omap8250_suspend, omap8250_resume) 181962306a36Sopenharmony_ci RUNTIME_PM_OPS(omap8250_runtime_suspend, 182062306a36Sopenharmony_ci omap8250_runtime_resume, NULL) 182162306a36Sopenharmony_ci .prepare = pm_sleep_ptr(omap8250_prepare), 182262306a36Sopenharmony_ci .complete = pm_sleep_ptr(omap8250_complete), 182362306a36Sopenharmony_ci}; 182462306a36Sopenharmony_ci 182562306a36Sopenharmony_cistatic struct platform_driver omap8250_platform_driver = { 182662306a36Sopenharmony_ci .driver = { 182762306a36Sopenharmony_ci .name = "omap8250", 182862306a36Sopenharmony_ci .pm = pm_ptr(&omap8250_dev_pm_ops), 182962306a36Sopenharmony_ci .of_match_table = omap8250_dt_ids, 183062306a36Sopenharmony_ci }, 183162306a36Sopenharmony_ci .probe = omap8250_probe, 183262306a36Sopenharmony_ci .remove = omap8250_remove, 183362306a36Sopenharmony_ci}; 183462306a36Sopenharmony_cimodule_platform_driver(omap8250_platform_driver); 183562306a36Sopenharmony_ci 183662306a36Sopenharmony_ciMODULE_AUTHOR("Sebastian Andrzej Siewior"); 183762306a36Sopenharmony_ciMODULE_DESCRIPTION("OMAP 8250 Driver"); 183862306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 1839