|
@@ -1198,6 +1198,119 @@ console_initcall(xuartps_console_init);
|
|
|
|
|
|
#endif /* CONFIG_SERIAL_XILINX_PS_UART_CONSOLE */
|
|
|
|
|
|
+#ifdef CONFIG_PM_SLEEP
|
|
|
+/**
|
|
|
+ * xuartps_suspend - suspend event
|
|
|
+ * @device: Pointer to the device structure
|
|
|
+ *
|
|
|
+ * Returns 0
|
|
|
+ */
|
|
|
+static int xuartps_suspend(struct device *device)
|
|
|
+{
|
|
|
+ struct uart_port *port = dev_get_drvdata(device);
|
|
|
+ struct tty_struct *tty;
|
|
|
+ struct device *tty_dev;
|
|
|
+ int may_wake = 0;
|
|
|
+
|
|
|
+ /* Get the tty which could be NULL so don't assume it's valid */
|
|
|
+ tty = tty_port_tty_get(&port->state->port);
|
|
|
+ if (tty) {
|
|
|
+ tty_dev = tty->dev;
|
|
|
+ may_wake = device_may_wakeup(tty_dev);
|
|
|
+ tty_kref_put(tty);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Call the API provided in serial_core.c file which handles
|
|
|
+ * the suspend.
|
|
|
+ */
|
|
|
+ uart_suspend_port(&xuartps_uart_driver, port);
|
|
|
+ if (console_suspend_enabled && !may_wake) {
|
|
|
+ struct xuartps *xuartps = port->private_data;
|
|
|
+
|
|
|
+ clk_disable(xuartps->refclk);
|
|
|
+ clk_disable(xuartps->aperclk);
|
|
|
+ } else {
|
|
|
+ unsigned long flags = 0;
|
|
|
+
|
|
|
+ spin_lock_irqsave(&port->lock, flags);
|
|
|
+ /* Empty the receive FIFO 1st before making changes */
|
|
|
+ while (!(xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_RXEMPTY))
|
|
|
+ xuartps_readl(XUARTPS_FIFO_OFFSET);
|
|
|
+ /* set RX trigger level to 1 */
|
|
|
+ xuartps_writel(1, XUARTPS_RXWM_OFFSET);
|
|
|
+ /* disable RX timeout interrups */
|
|
|
+ xuartps_writel(XUARTPS_IXR_TOUT, XUARTPS_IDR_OFFSET);
|
|
|
+ spin_unlock_irqrestore(&port->lock, flags);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * xuartps_resume - Resume after a previous suspend
|
|
|
+ * @device: Pointer to the device structure
|
|
|
+ *
|
|
|
+ * Returns 0
|
|
|
+ */
|
|
|
+static int xuartps_resume(struct device *device)
|
|
|
+{
|
|
|
+ struct uart_port *port = dev_get_drvdata(device);
|
|
|
+ unsigned long flags = 0;
|
|
|
+ u32 ctrl_reg;
|
|
|
+ struct tty_struct *tty;
|
|
|
+ struct device *tty_dev;
|
|
|
+ int may_wake = 0;
|
|
|
+
|
|
|
+ /* Get the tty which could be NULL so don't assume it's valid */
|
|
|
+ tty = tty_port_tty_get(&port->state->port);
|
|
|
+ if (tty) {
|
|
|
+ tty_dev = tty->dev;
|
|
|
+ may_wake = device_may_wakeup(tty_dev);
|
|
|
+ tty_kref_put(tty);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (console_suspend_enabled && !may_wake) {
|
|
|
+ struct xuartps *xuartps = port->private_data;
|
|
|
+
|
|
|
+ clk_enable(xuartps->aperclk);
|
|
|
+ clk_enable(xuartps->refclk);
|
|
|
+
|
|
|
+ spin_lock_irqsave(&port->lock, flags);
|
|
|
+
|
|
|
+ /* Set TX/RX Reset */
|
|
|
+ xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) |
|
|
|
+ (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST),
|
|
|
+ XUARTPS_CR_OFFSET);
|
|
|
+ while (xuartps_readl(XUARTPS_CR_OFFSET) &
|
|
|
+ (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST))
|
|
|
+ cpu_relax();
|
|
|
+
|
|
|
+ /* restore rx timeout value */
|
|
|
+ xuartps_writel(rx_timeout, XUARTPS_RXTOUT_OFFSET);
|
|
|
+ /* Enable Tx/Rx */
|
|
|
+ ctrl_reg = xuartps_readl(XUARTPS_CR_OFFSET);
|
|
|
+ xuartps_writel(
|
|
|
+ (ctrl_reg & ~(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS)) |
|
|
|
+ (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN),
|
|
|
+ XUARTPS_CR_OFFSET);
|
|
|
+
|
|
|
+ spin_unlock_irqrestore(&port->lock, flags);
|
|
|
+ } else {
|
|
|
+ spin_lock_irqsave(&port->lock, flags);
|
|
|
+ /* restore original rx trigger level */
|
|
|
+ xuartps_writel(rx_trigger_level, XUARTPS_RXWM_OFFSET);
|
|
|
+ /* enable RX timeout interrupt */
|
|
|
+ xuartps_writel(XUARTPS_IXR_TOUT, XUARTPS_IER_OFFSET);
|
|
|
+ spin_unlock_irqrestore(&port->lock, flags);
|
|
|
+ }
|
|
|
+
|
|
|
+ return uart_resume_port(&xuartps_uart_driver, port);
|
|
|
+}
|
|
|
+#endif /* ! CONFIG_PM_SLEEP */
|
|
|
+
|
|
|
+static SIMPLE_DEV_PM_OPS(xuartps_dev_pm_ops, xuartps_suspend, xuartps_resume);
|
|
|
+
|
|
|
/** Structure Definitions
|
|
|
*/
|
|
|
static struct uart_driver xuartps_uart_driver = {
|
|
@@ -1348,6 +1461,7 @@ static struct platform_driver xuartps_platform_driver = {
|
|
|
.owner = THIS_MODULE,
|
|
|
.name = XUARTPS_NAME, /* Driver name */
|
|
|
.of_match_table = xuartps_of_match,
|
|
|
+ .pm = &xuartps_dev_pm_ops,
|
|
|
},
|
|
|
};
|
|
|
|