tty: xuartps: Implement suspend/resume callbacks
Implement suspend and resume callbacks in order to support system suspend/hibernation. Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
c4b0510cc1
commit
4b47d9aa1e
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue