/* * 8250-core based driver for the OMAP internal UART * * based on omap-serial.c, Copyright (C) 2010 Texas Instruments. * * Copyright (C) 2014 Sebastian Andrzej Siewior * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "8250.h" #define DEFAULT_CLK_SPEED 48000000 #define UART_ERRATA_i202_MDR1_ACCESS (1 << 0) #define OMAP_UART_WER_HAS_TX_WAKEUP (1 << 1) #define OMAP_UART_FCR_RX_TRIG 6 #define OMAP_UART_FCR_TX_TRIG 4 /* SCR register bitmasks */ #define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK (1 << 7) #define OMAP_UART_SCR_TX_TRIG_GRANU1_MASK (1 << 6) #define OMAP_UART_SCR_TX_EMPTY (1 << 3) #define OMAP_UART_SCR_DMAMODE_MASK (3 << 1) #define OMAP_UART_SCR_DMAMODE_1 (1 << 1) #define OMAP_UART_SCR_DMAMODE_CTL (1 << 0) /* MVR register bitmasks */ #define OMAP_UART_MVR_SCHEME_SHIFT 30 #define OMAP_UART_LEGACY_MVR_MAJ_MASK 0xf0 #define OMAP_UART_LEGACY_MVR_MAJ_SHIFT 4 #define OMAP_UART_LEGACY_MVR_MIN_MASK 0x0f #define OMAP_UART_MVR_MAJ_MASK 0x700 #define OMAP_UART_MVR_MAJ_SHIFT 8 #define OMAP_UART_MVR_MIN_MASK 0x3f #define UART_TI752_TLR_TX 0 #define UART_TI752_TLR_RX 4 #define TRIGGER_TLR_MASK(x) ((x & 0x3c) >> 2) #define TRIGGER_FCR_MASK(x) (x & 3) /* Enable XON/XOFF flow control on output */ #define OMAP_UART_SW_TX 0x08 /* Enable XON/XOFF flow control on input */ #define OMAP_UART_SW_RX 0x02 #define OMAP_UART_WER_MOD_WKUP 0x7f #define OMAP_UART_TX_WAKEUP_EN (1 << 7) #define TX_TRIGGER 1 #define RX_TRIGGER 48 #define OMAP_UART_TCR_RESTORE(x) ((x / 4) << 4) #define OMAP_UART_TCR_HALT(x) ((x / 4) << 0) #define UART_BUILD_REVISION(x, y) (((x) << 8) | (y)) #define OMAP_UART_REV_46 0x0406 #define OMAP_UART_REV_52 0x0502 #define OMAP_UART_REV_63 0x0603 struct omap8250_priv { int line; u8 habit; u8 mdr1; u8 efr; u8 scr; u8 wer; u8 xon; u8 xoff; u16 quot; bool is_suspending; int wakeirq; int wakeups_enabled; u32 latency; u32 calc_latency; struct pm_qos_request pm_qos_request; struct work_struct qos_work; struct uart_8250_dma omap8250_dma; }; static u32 uart_read(struct uart_8250_port *up, u32 reg) { return readl(up->port.membase + (reg << up->port.regshift)); } /* * Work Around for Errata i202 (2430, 3430, 3630, 4430 and 4460) * The access to uart register after MDR1 Access * causes UART to corrupt data. * * Need a delay = * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS) * give 10 times as much */ static void omap_8250_mdr1_errataset(struct uart_8250_port *up, struct omap8250_priv *priv) { u8 timeout = 255; u8 old_mdr1; old_mdr1 = serial_in(up, UART_OMAP_MDR1); if (old_mdr1 == priv->mdr1) return; serial_out(up, UART_OMAP_MDR1, priv->mdr1); udelay(2); serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR); /* * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and * TX_FIFO_E bit is 1. */ while (UART_LSR_THRE != (serial_in(up, UART_LSR) & (UART_LSR_THRE | UART_LSR_DR))) { timeout--; if (!timeout) { /* Should *never* happen. we warn and carry on */ dev_crit(up->port.dev, "Errata i202: timedout %x\n", serial_in(up, UART_LSR)); break; } udelay(1); } } static void omap_8250_get_divisor(struct uart_port *port, unsigned int baud, struct omap8250_priv *priv) { unsigned int uartclk = port->uartclk; unsigned int div_13, div_16; unsigned int abs_d13, abs_d16; /* * Old custom speed handling. */ if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) { priv->quot = port->custom_divisor & 0xffff; /* * I assume that nobody is using this. But hey, if somebody * would like to specify the divisor _and_ the mode then the * driver is ready and waiting for it. */ if (port->custom_divisor & (1 << 16)) priv->mdr1 = UART_OMAP_MDR1_13X_MODE; else priv->mdr1 = UART_OMAP_MDR1_16X_MODE; return; } div_13 = DIV_ROUND_CLOSEST(uartclk, 13 * baud); div_16 = DIV_ROUND_CLOSEST(uartclk, 16 * baud); if (!div_13) div_13 = 1; if (!div_16) div_16 = 1; abs_d13 = abs(baud - uartclk / 13 / div_13); abs_d16 = abs(baud - uartclk / 16 / div_16); if (abs_d13 >= abs_d16) { priv->mdr1 = UART_OMAP_MDR1_16X_MODE; priv->quot = div_16; } else { priv->mdr1 = UART_OMAP_MDR1_13X_MODE; priv->quot = div_13; } } static void omap8250_update_scr(struct uart_8250_port *up, struct omap8250_priv *priv) { u8 old_scr; old_scr = serial_in(up, UART_OMAP_SCR); if (old_scr == priv->scr) return; /* * The manual recommends not to enable the DMA mode selector in the SCR * (instead of the FCR) register _and_ selecting the DMA mode as one * register write because this may lead to malfunction. */ if (priv->scr & OMAP_UART_SCR_DMAMODE_MASK) serial_out(up, UART_OMAP_SCR, priv->scr & ~OMAP_UART_SCR_DMAMODE_MASK); serial_out(up, UART_OMAP_SCR, priv->scr); } static void omap8250_restore_regs(struct uart_8250_port *up) { struct omap8250_priv *priv = up->port.private_data; serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_EFR, UART_EFR_ECB); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); serial_out(up, UART_MCR, UART_MCR_TCRTLR); serial_out(up, UART_FCR, up->fcr); omap8250_update_scr(up, priv); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_RESTORE(16) | OMAP_UART_TCR_HALT(52)); serial_out(up, UART_TI752_TLR, TRIGGER_TLR_MASK(TX_TRIGGER) << UART_TI752_TLR_TX | TRIGGER_TLR_MASK(RX_TRIGGER) << UART_TI752_TLR_RX); serial_out(up, UART_LCR, 0); /* drop TCR + TLR access, we setup XON/XOFF later */ serial_out(up, UART_MCR, up->mcr); serial_out(up, UART_IER, up->ier); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_dl_write(up, priv->quot); serial_out(up, UART_EFR, priv->efr); /* Configure flow control */ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_XON1, priv->xon); serial_out(up, UART_XOFF1, priv->xoff); serial_out(up, UART_LCR, up->lcr); /* need mode A for FCR */ if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS) omap_8250_mdr1_errataset(up, priv); else serial_out(up, UART_OMAP_MDR1, priv->mdr1); up->port.ops->set_mctrl(&up->port, up->port.mctrl); } /* * OMAP can use "CLK / (16 or 13) / div" for baud rate. And then we have have * some differences in how we want to handle flow control. */ static void omap_8250_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct uart_8250_port *up = container_of(port, struct uart_8250_port, port); struct omap8250_priv *priv = up->port.private_data; unsigned char cval = 0; unsigned int baud; switch (termios->c_cflag & CSIZE) { case CS5: cval = UART_LCR_WLEN5; break; case CS6: cval = UART_LCR_WLEN6; break; case CS7: cval = UART_LCR_WLEN7; break; default: case CS8: cval = UART_LCR_WLEN8; break; } if (termios->c_cflag & CSTOPB) cval |= UART_LCR_STOP; if (termios->c_cflag & PARENB) cval |= UART_LCR_PARITY; if (!(termios->c_cflag & PARODD)) cval |= UART_LCR_EPAR; if (termios->c_cflag & CMSPAR) cval |= UART_LCR_SPAR; /* * Ask the core to calculate the divisor for us. */ baud = uart_get_baud_rate(port, termios, old, port->uartclk / 16 / 0xffff, port->uartclk / 13); omap_8250_get_divisor(port, baud, priv); /* * Ok, we're now changing the port state. Do it with * interrupts disabled. */ pm_runtime_get_sync(port->dev); spin_lock_irq(&port->lock); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; if (termios->c_iflag & INPCK) up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; if (termios->c_iflag & (IGNBRK | PARMRK)) up->port.read_status_mask |= UART_LSR_BI; /* * Characters to ignore */ up->port.ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; if (termios->c_iflag & IGNBRK) { up->port.ignore_status_mask |= UART_LSR_BI; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) up->port.ignore_status_mask |= UART_LSR_OE; } /* * ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) up->port.ignore_status_mask |= UART_LSR_DR; /* * Modem status interrupts */ up->ier &= ~UART_IER_MSI; if (UART_ENABLE_MS(&up->port, termios->c_cflag)) up->ier |= UART_IER_MSI; up->lcr = cval; /* Up to here it was mostly serial8250_do_set_termios() */ /* * We enable TRIG_GRANU for RX and TX and additionaly we set * SCR_TX_EMPTY bit. The result is the following: * - RX_TRIGGER amount of bytes in the FIFO will cause an interrupt. * - less than RX_TRIGGER number of bytes will also cause an interrupt * once the UART decides that there no new bytes arriving. * - Once THRE is enabled, the interrupt will be fired once the FIFO is * empty - the trigger level is ignored here. * * Once DMA is enabled: * - UART will assert the TX DMA line once there is room for TX_TRIGGER * bytes in the TX FIFO. On each assert the DMA engine will move * TX_TRIGGER bytes into the FIFO. * - UART will assert the RX DMA line once there are RX_TRIGGER bytes in * the FIFO and move RX_TRIGGER bytes. * This is because threshold and trigger values are the same. */ up->fcr = UART_FCR_ENABLE_FIFO; up->fcr |= TRIGGER_FCR_MASK(TX_TRIGGER) << OMAP_UART_FCR_TX_TRIG; up->fcr |= TRIGGER_FCR_MASK(RX_TRIGGER) << OMAP_UART_FCR_RX_TRIG; priv->scr = OMAP_UART_SCR_RX_TRIG_GRANU1_MASK | OMAP_UART_SCR_TX_EMPTY | OMAP_UART_SCR_TX_TRIG_GRANU1_MASK; priv->xon = termios->c_cc[VSTART]; priv->xoff = termios->c_cc[VSTOP]; priv->efr = 0; up->mcr &= ~(UART_MCR_RTS | UART_MCR_XONANY); if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) { /* Enable AUTORTS and AUTOCTS */ priv->efr |= UART_EFR_CTS | UART_EFR_RTS; /* Ensure MCR RTS is asserted */ up->mcr |= UART_MCR_RTS; } else if (up->port.flags & UPF_SOFT_FLOW) { /* * IXON Flag: * Enable XON/XOFF flow control on input. * Receiver compares XON1, XOFF1. */ if (termios->c_iflag & IXON) priv->efr |= OMAP_UART_SW_RX; /* * IXOFF Flag: * Enable XON/XOFF flow control on output. * Transmit XON1, XOFF1 */ if (termios->c_iflag & IXOFF) priv->efr |= OMAP_UART_SW_TX; /* * IXANY Flag: * Enable any character to restart output. * Operation resumes after receiving any * character after recognition of the XOFF character */ if (termios->c_iflag & IXANY) up->mcr |= UART_MCR_XONANY; } omap8250_restore_regs(up); spin_unlock_irq(&up->port.lock); pm_runtime_mark_last_busy(port->dev); pm_runtime_put_autosuspend(port->dev); /* calculate wakeup latency constraint */ priv->calc_latency = USEC_PER_SEC * 64 * 8 / baud; priv->latency = priv->calc_latency; schedule_work(&priv->qos_work); /* Don't rewrite B0 */ if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); } /* same as 8250 except that we may have extra flow bits set in EFR */ static void omap_8250_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { struct uart_8250_port *up = container_of(port, struct uart_8250_port, port); struct omap8250_priv *priv = up->port.private_data; pm_runtime_get_sync(port->dev); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_EFR, priv->efr | UART_EFR_ECB); serial_out(up, UART_LCR, 0); serial_out(up, UART_IER, (state != 0) ? UART_IERX_SLEEP : 0); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_EFR, priv->efr); serial_out(up, UART_LCR, 0); pm_runtime_mark_last_busy(port->dev); pm_runtime_put_autosuspend(port->dev); } static void omap_serial_fill_features_erratas(struct uart_8250_port *up, struct omap8250_priv *priv) { u32 mvr, scheme; u16 revision, major, minor; mvr = uart_read(up, UART_OMAP_MVER); /* Check revision register scheme */ scheme = mvr >> OMAP_UART_MVR_SCHEME_SHIFT; switch (scheme) { case 0: /* Legacy Scheme: OMAP2/3 */ /* MINOR_REV[0:4], MAJOR_REV[4:7] */ major = (mvr & OMAP_UART_LEGACY_MVR_MAJ_MASK) >> OMAP_UART_LEGACY_MVR_MAJ_SHIFT; minor = (mvr & OMAP_UART_LEGACY_MVR_MIN_MASK); break; case 1: /* New Scheme: OMAP4+ */ /* MINOR_REV[0:5], MAJOR_REV[8:10] */ major = (mvr & OMAP_UART_MVR_MAJ_MASK) >> OMAP_UART_MVR_MAJ_SHIFT; minor = (mvr & OMAP_UART_MVR_MIN_MASK); break; default: dev_warn(up->port.dev, "Unknown revision, defaulting to highest\n"); /* highest possible revision */ major = 0xff; minor = 0xff; } /* normalize revision for the driver */ revision = UART_BUILD_REVISION(major, minor); switch (revision) { case OMAP_UART_REV_46: priv->habit = UART_ERRATA_i202_MDR1_ACCESS; break; case OMAP_UART_REV_52: priv->habit = UART_ERRATA_i202_MDR1_ACCESS | OMAP_UART_WER_HAS_TX_WAKEUP; break; case OMAP_UART_REV_63: priv->habit = UART_ERRATA_i202_MDR1_ACCESS | OMAP_UART_WER_HAS_TX_WAKEUP; break; default: break; } } static void omap8250_uart_qos_work(struct work_struct *work) { struct omap8250_priv *priv; priv = container_of(work, struct omap8250_priv, qos_work); pm_qos_update_request(&priv->pm_qos_request, priv->latency); } static irqreturn_t omap_wake_irq(int irq, void *dev_id) { struct uart_port *port = dev_id; int ret; ret = port->handle_irq(port); if (ret) return IRQ_HANDLED; return IRQ_NONE; } static int omap_8250_startup(struct uart_port *port) { struct uart_8250_port *up = container_of(port, struct uart_8250_port, port); struct omap8250_priv *priv = port->private_data; int ret; if (priv->wakeirq) { ret = request_irq(priv->wakeirq, omap_wake_irq, port->irqflags, "uart wakeup irq", port); if (ret) return ret; disable_irq(priv->wakeirq); } pm_runtime_get_sync(port->dev); ret = serial8250_do_startup(port); if (ret) goto err; #ifdef CONFIG_PM_RUNTIME up->capabilities |= UART_CAP_RPM; #endif /* Enable module level wake up */ priv->wer = OMAP_UART_WER_MOD_WKUP; if (priv->habit & OMAP_UART_WER_HAS_TX_WAKEUP) priv->wer |= OMAP_UART_TX_WAKEUP_EN; serial_out(up, UART_OMAP_WER, priv->wer); pm_runtime_mark_last_busy(port->dev); pm_runtime_put_autosuspend(port->dev); return 0; err: pm_runtime_mark_last_busy(port->dev); pm_runtime_put_autosuspend(port->dev); if (priv->wakeirq) free_irq(priv->wakeirq, port); return ret; } static void omap_8250_shutdown(struct uart_port *port) { struct uart_8250_port *up = container_of(port, struct uart_8250_port, port); struct omap8250_priv *priv = port->private_data; flush_work(&priv->qos_work); pm_runtime_get_sync(port->dev); serial_out(up, UART_OMAP_WER, 0); serial8250_do_shutdown(port); pm_runtime_mark_last_busy(port->dev); pm_runtime_put_autosuspend(port->dev); if (priv->wakeirq) free_irq(priv->wakeirq, port); } static void omap_8250_throttle(struct uart_port *port) { unsigned long flags; struct uart_8250_port *up = container_of(port, struct uart_8250_port, port); pm_runtime_get_sync(port->dev); spin_lock_irqsave(&port->lock, flags); up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); serial_out(up, UART_IER, up->ier); spin_unlock_irqrestore(&port->lock, flags); pm_runtime_mark_last_busy(port->dev); pm_runtime_put_autosuspend(port->dev); } static void omap_8250_unthrottle(struct uart_port *port) { unsigned long flags; struct uart_8250_port *up = container_of(port, struct uart_8250_port, port); pm_runtime_get_sync(port->dev); spin_lock_irqsave(&port->lock, flags); up->ier |= UART_IER_RLSI | UART_IER_RDI; serial_out(up, UART_IER, up->ier); spin_unlock_irqrestore(&port->lock, flags); pm_runtime_mark_last_busy(port->dev); pm_runtime_put_autosuspend(port->dev); } static int omap8250_probe(struct platform_device *pdev) { struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); struct omap8250_priv *priv; struct uart_8250_port up; int ret; void __iomem *membase; if (!regs || !irq) { dev_err(&pdev->dev, "missing registers or irq\n"); return -EINVAL; } priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; membase = devm_ioremap_nocache(&pdev->dev, regs->start, resource_size(regs)); if (!membase) return -ENODEV; memset(&up, 0, sizeof(up)); up.port.dev = &pdev->dev; up.port.mapbase = regs->start; up.port.membase = membase; up.port.irq = irq->start; /* * It claims to be 16C750 compatible however it is a little different. * It has EFR and has no FCR7_64byte bit. The AFE (which it claims to * have) is enabled via EFR instead of MCR. The type is set here 8250 * just to get things going. UNKNOWN does not work for a few reasons and * we don't need our own type since we don't use 8250's set_termios() * or pm callback. */ up.port.type = PORT_8250; up.port.iotype = UPIO_MEM; up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SOFT_FLOW | UPF_HARD_FLOW; up.port.private_data = priv; up.port.regshift = 2; up.port.fifosize = 64; up.tx_loadsz = 64; up.capabilities = UART_CAP_FIFO; #ifdef CONFIG_PM_RUNTIME /* * PM_RUNTIME is mostly transparent. However to do it right we need to a * TX empty interrupt before we can put the device to auto idle. So if * PM_RUNTIME is not enabled we don't add that flag and can spare that * one extra interrupt in the TX path. */ up.capabilities |= UART_CAP_RPM; #endif up.port.set_termios = omap_8250_set_termios; up.port.pm = omap_8250_pm; up.port.startup = omap_8250_startup; up.port.shutdown = omap_8250_shutdown; up.port.throttle = omap_8250_throttle; up.port.unthrottle = omap_8250_unthrottle; if (pdev->dev.of_node) { up.port.line = of_alias_get_id(pdev->dev.of_node, "serial"); of_property_read_u32(pdev->dev.of_node, "clock-frequency", &up.port.uartclk); priv->wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1); } else { up.port.line = pdev->id; } if (up.port.line < 0) { dev_err(&pdev->dev, "failed to get alias/pdev id, errno %d\n", up.port.line); return -ENODEV; } if (!up.port.uartclk) { up.port.uartclk = DEFAULT_CLK_SPEED; dev_warn(&pdev->dev, "No clock speed specified: using default: %d\n", DEFAULT_CLK_SPEED); } priv->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; priv->calc_latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; pm_qos_add_request(&priv->pm_qos_request, PM_QOS_CPU_DMA_LATENCY, priv->latency); INIT_WORK(&priv->qos_work, omap8250_uart_qos_work); device_init_wakeup(&pdev->dev, true); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, -1); pm_runtime_irq_safe(&pdev->dev); pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); omap_serial_fill_features_erratas(&up, priv); ret = serial8250_register_8250_port(&up); if (ret < 0) { dev_err(&pdev->dev, "unable to register 8250 port\n"); goto err; } priv->line = ret; platform_set_drvdata(pdev, priv); pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_put_autosuspend(&pdev->dev); return 0; err: pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); return ret; } static int omap8250_remove(struct platform_device *pdev) { struct omap8250_priv *priv = platform_get_drvdata(pdev); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); serial8250_unregister_port(priv->line); pm_qos_remove_request(&priv->pm_qos_request); device_init_wakeup(&pdev->dev, false); return 0; } #if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_RUNTIME) static inline void omap8250_enable_wakeirq(struct omap8250_priv *priv, bool enable) { if (!priv->wakeirq) return; if (enable) enable_irq(priv->wakeirq); else disable_irq_nosync(priv->wakeirq); } static void omap8250_enable_wakeup(struct omap8250_priv *priv, bool enable) { if (enable == priv->wakeups_enabled) return; omap8250_enable_wakeirq(priv, enable); priv->wakeups_enabled = enable; } #endif #ifdef CONFIG_PM_SLEEP static int omap8250_prepare(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); if (!priv) return 0; priv->is_suspending = true; return 0; } static void omap8250_complete(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); if (!priv) return; priv->is_suspending = false; } static int omap8250_suspend(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); serial8250_suspend_port(priv->line); flush_work(&priv->qos_work); if (device_may_wakeup(dev)) omap8250_enable_wakeup(priv, true); else omap8250_enable_wakeup(priv, false); return 0; } static int omap8250_resume(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); if (device_may_wakeup(dev)) omap8250_enable_wakeup(priv, false); serial8250_resume_port(priv->line); return 0; } #else #define omap8250_prepare NULL #define omap8250_complete NULL #endif #ifdef CONFIG_PM_RUNTIME static int omap8250_lost_context(struct uart_8250_port *up) { u32 val; val = serial_in(up, UART_OMAP_MDR1); /* * If we lose context, then MDR1 is set to its reset value which is * UART_OMAP_MDR1_DISABLE. After set_termios() we set it either to 13x * or 16x but never to disable again. */ if (val == UART_OMAP_MDR1_DISABLE) return 1; return 0; } static int omap8250_runtime_suspend(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); struct uart_8250_port *up; up = serial8250_get_port(priv->line); /* * When using 'no_console_suspend', the console UART must not be * suspended. Since driver suspend is managed by runtime suspend, * preventing runtime suspend (by returning error) will keep device * active during suspend. */ if (priv->is_suspending && !console_suspend_enabled) { if (uart_console(&up->port)) return -EBUSY; } omap8250_enable_wakeup(priv, true); priv->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; schedule_work(&priv->qos_work); return 0; } static int omap8250_runtime_resume(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); struct uart_8250_port *up; int loss_cntx; /* In case runtime-pm tries this before we are setup */ if (!priv) return 0; up = serial8250_get_port(priv->line); omap8250_enable_wakeup(priv, false); loss_cntx = omap8250_lost_context(up); if (loss_cntx) omap8250_restore_regs(up); priv->latency = priv->calc_latency; schedule_work(&priv->qos_work); return 0; } #endif static const struct dev_pm_ops omap8250_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(omap8250_suspend, omap8250_resume) SET_RUNTIME_PM_OPS(omap8250_runtime_suspend, omap8250_runtime_resume, NULL) .prepare = omap8250_prepare, .complete = omap8250_complete, }; static const struct of_device_id omap8250_dt_ids[] = { { .compatible = "ti,omap2-uart" }, { .compatible = "ti,omap3-uart" }, { .compatible = "ti,omap4-uart" }, {}, }; MODULE_DEVICE_TABLE(of, omap8250_dt_ids); static struct platform_driver omap8250_platform_driver = { .driver = { .name = "omap8250", .pm = &omap8250_dev_pm_ops, .of_match_table = omap8250_dt_ids, .owner = THIS_MODULE, }, .probe = omap8250_probe, .remove = omap8250_remove, }; module_platform_driver(omap8250_platform_driver); MODULE_AUTHOR("Sebastian Andrzej Siewior"); MODULE_DESCRIPTION("OMAP 8250 Driver"); MODULE_LICENSE("GPL v2");