diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-08 18:49:23 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-08 18:49:23 -0700 |
commit | 8f3207c7eab9d885cc64c778416537034a7d9c5b (patch) | |
tree | 733ec3a8c62b1906a72a6075966c1f57a37b0387 /drivers/tty/serial/xilinx_uartps.c | |
parent | bf5f89463f5b3109a72ed13ca62b57e90213387d (diff) | |
parent | 8e1c21f486944bf92f2a981f23ee811a45f5eaff (diff) | |
download | linux-8f3207c7eab9d885cc64c778416537034a7d9c5b.tar.bz2 |
Merge tag 'tty-4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial updates from Greg KH:
"Here is the "big" TTY/Serial patch updates for 4.12-rc1
Not a lot of new things here, the normal number of serial driver
updates and additions, tiny bugs fixed, and some core files split up
to make future changes a bit easier for Nicolas's "tiny-tty" work.
All of these have been in linux-next for a while"
* tag 'tty-4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (62 commits)
serial: small Makefile reordering
tty: split job control support into a file of its own
tty: move baudrate handling code to a file of its own
console: move console_init() out of tty_io.c
serial: 8250_early: Add earlycon support for Palmchip UART
tty: pl011: use "qdf2400_e44" as the earlycon name for QDF2400 E44
vt: make mouse selection of non-ASCII consistent
vt: set mouse selection word-chars to gpm's default
imx-serial: Reduce RX DMA startup latency when opening for reading
serial: omap: suspend device on probe errors
serial: omap: fix runtime-pm handling on unbind
tty: serial: omap: add UPF_BOOT_AUTOCONF flag for DT init
serial: samsung: Remove useless spinlock
serial: samsung: Add missing checks for dma_map_single failure
serial: samsung: Use right device for DMA-mapping calls
serial: imx: setup DCEDTE early and ensure DCD and RI irqs to be off
tty: fix comment typo s/repsonsible/responsible/
tty: amba-pl011: Fix spurious TX interrupts
serial: xuartps: Enable clocks in the pm disable case also
serial: core: Re-use struct uart_port {name} field
...
Diffstat (limited to 'drivers/tty/serial/xilinx_uartps.c')
-rw-r--r-- | drivers/tty/serial/xilinx_uartps.c | 71 |
1 files changed, 51 insertions, 20 deletions
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index ad77d0ed0c46..c0539950f8d7 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -30,6 +30,7 @@ #include <linux/io.h> #include <linux/of.h> #include <linux/module.h> +#include <linux/pm_runtime.h> #define CDNS_UART_TTY_NAME "ttyPS" #define CDNS_UART_NAME "xuartps" @@ -176,6 +177,7 @@ MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255"); #define CDNS_UART_BDIV_MIN 4 #define CDNS_UART_BDIV_MAX 255 #define CDNS_UART_CD_MAX 65535 +#define UART_AUTOSUSPEND_TIMEOUT 3000 /** * struct cdns_uart - device data @@ -1065,16 +1067,13 @@ static void cdns_uart_poll_put_char(struct uart_port *port, unsigned char c) static void cdns_uart_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { - struct cdns_uart *cdns_uart = port->private_data; - switch (state) { case UART_PM_STATE_OFF: - clk_disable(cdns_uart->uartclk); - clk_disable(cdns_uart->pclk); + pm_runtime_mark_last_busy(port->dev); + pm_runtime_put_autosuspend(port->dev); break; default: - clk_enable(cdns_uart->pclk); - clk_enable(cdns_uart->uartclk); + pm_runtime_get_sync(port->dev); break; } } @@ -1353,12 +1352,7 @@ static int cdns_uart_suspend(struct device *device) * the suspend. */ uart_suspend_port(&cdns_uart_uart_driver, port); - if (console_suspend_enabled && !may_wake) { - struct cdns_uart *cdns_uart = port->private_data; - - clk_disable(cdns_uart->uartclk); - clk_disable(cdns_uart->pclk); - } else { + if (!(console_suspend_enabled && !may_wake)) { unsigned long flags = 0; spin_lock_irqsave(&port->lock, flags); @@ -1423,6 +1417,8 @@ static int cdns_uart_resume(struct device *device) ctrl_reg |= CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN; writel(ctrl_reg, port->membase + CDNS_UART_CR); + clk_disable(cdns_uart->uartclk); + clk_disable(cdns_uart->pclk); spin_unlock_irqrestore(&port->lock, flags); } else { spin_lock_irqsave(&port->lock, flags); @@ -1436,9 +1432,33 @@ static int cdns_uart_resume(struct device *device) return uart_resume_port(&cdns_uart_uart_driver, port); } #endif /* ! CONFIG_PM_SLEEP */ +static int __maybe_unused cdns_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct uart_port *port = platform_get_drvdata(pdev); + struct cdns_uart *cdns_uart = port->private_data; + + clk_disable(cdns_uart->uartclk); + clk_disable(cdns_uart->pclk); + return 0; +}; + +static int __maybe_unused cdns_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct uart_port *port = platform_get_drvdata(pdev); + struct cdns_uart *cdns_uart = port->private_data; -static SIMPLE_DEV_PM_OPS(cdns_uart_dev_pm_ops, cdns_uart_suspend, - cdns_uart_resume); + clk_enable(cdns_uart->pclk); + clk_enable(cdns_uart->uartclk); + return 0; +}; + +static const struct dev_pm_ops cdns_uart_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(cdns_uart_suspend, cdns_uart_resume) + SET_RUNTIME_PM_OPS(cdns_runtime_suspend, + cdns_runtime_resume, NULL) +}; static const struct cdns_platform_data zynqmp_uart_def = { .quirks = CDNS_UART_RXBS_SUPPORT, }; @@ -1501,12 +1521,12 @@ static int cdns_uart_probe(struct platform_device *pdev) return PTR_ERR(cdns_uart_data->uartclk); } - rc = clk_prepare(cdns_uart_data->pclk); + rc = clk_prepare_enable(cdns_uart_data->pclk); if (rc) { dev_err(&pdev->dev, "Unable to enable pclk clock.\n"); return rc; } - rc = clk_prepare(cdns_uart_data->uartclk); + rc = clk_prepare_enable(cdns_uart_data->uartclk); if (rc) { dev_err(&pdev->dev, "Unable to enable device clock.\n"); goto err_out_clk_dis_pclk; @@ -1558,6 +1578,11 @@ static int cdns_uart_probe(struct platform_device *pdev) cdns_uart_data->port = port; platform_set_drvdata(pdev, port); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + rc = uart_add_one_port(&cdns_uart_uart_driver, port); if (rc) { dev_err(&pdev->dev, @@ -1573,9 +1598,12 @@ err_out_notif_unreg: &cdns_uart_data->clk_rate_change_nb); #endif err_out_clk_disable: - clk_unprepare(cdns_uart_data->uartclk); + pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); + clk_disable_unprepare(cdns_uart_data->uartclk); err_out_clk_dis_pclk: - clk_unprepare(cdns_uart_data->pclk); + clk_disable_unprepare(cdns_uart_data->pclk); return rc; } @@ -1599,8 +1627,11 @@ static int cdns_uart_remove(struct platform_device *pdev) #endif rc = uart_remove_one_port(&cdns_uart_uart_driver, port); port->mapbase = 0; - clk_unprepare(cdns_uart_data->uartclk); - clk_unprepare(cdns_uart_data->pclk); + clk_disable_unprepare(cdns_uart_data->uartclk); + clk_disable_unprepare(cdns_uart_data->pclk); + pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); return rc; } |