aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/xilinx_uartps.c
diff options
context:
space:
mode:
authorSoren Brinkmann <soren.brinkmann@xilinx.com>2013-10-17 17:08:12 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-10-19 22:47:38 -0400
commit4b47d9aa1e3b54b73f9399f3d64b47495cc67a1e (patch)
tree22a13755a4a6fc44c82cafa91ba8f0140678150e /drivers/tty/serial/xilinx_uartps.c
parentc4b0510cc1571ff44e1d6024d92683d49a8bcfde (diff)
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>
Diffstat (limited to 'drivers/tty/serial/xilinx_uartps.c')
-rw-r--r--drivers/tty/serial/xilinx_uartps.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index 82195040e906..9ecd8ea4f3ae 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -1198,6 +1198,119 @@ console_initcall(xuartps_console_init);
1198 1198
1199#endif /* CONFIG_SERIAL_XILINX_PS_UART_CONSOLE */ 1199#endif /* CONFIG_SERIAL_XILINX_PS_UART_CONSOLE */
1200 1200
1201#ifdef CONFIG_PM_SLEEP
1202/**
1203 * xuartps_suspend - suspend event
1204 * @device: Pointer to the device structure
1205 *
1206 * Returns 0
1207 */
1208static int xuartps_suspend(struct device *device)
1209{
1210 struct uart_port *port = dev_get_drvdata(device);
1211 struct tty_struct *tty;
1212 struct device *tty_dev;
1213 int may_wake = 0;
1214
1215 /* Get the tty which could be NULL so don't assume it's valid */
1216 tty = tty_port_tty_get(&port->state->port);
1217 if (tty) {
1218 tty_dev = tty->dev;
1219 may_wake = device_may_wakeup(tty_dev);
1220 tty_kref_put(tty);
1221 }
1222
1223 /*
1224 * Call the API provided in serial_core.c file which handles
1225 * the suspend.
1226 */
1227 uart_suspend_port(&xuartps_uart_driver, port);
1228 if (console_suspend_enabled && !may_wake) {
1229 struct xuartps *xuartps = port->private_data;
1230
1231 clk_disable(xuartps->refclk);
1232 clk_disable(xuartps->aperclk);
1233 } else {
1234 unsigned long flags = 0;
1235
1236 spin_lock_irqsave(&port->lock, flags);
1237 /* Empty the receive FIFO 1st before making changes */
1238 while (!(xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_RXEMPTY))
1239 xuartps_readl(XUARTPS_FIFO_OFFSET);
1240 /* set RX trigger level to 1 */
1241 xuartps_writel(1, XUARTPS_RXWM_OFFSET);
1242 /* disable RX timeout interrups */
1243 xuartps_writel(XUARTPS_IXR_TOUT, XUARTPS_IDR_OFFSET);
1244 spin_unlock_irqrestore(&port->lock, flags);
1245 }
1246
1247 return 0;
1248}
1249
1250/**
1251 * xuartps_resume - Resume after a previous suspend
1252 * @device: Pointer to the device structure
1253 *
1254 * Returns 0
1255 */
1256static int xuartps_resume(struct device *device)
1257{
1258 struct uart_port *port = dev_get_drvdata(device);
1259 unsigned long flags = 0;
1260 u32 ctrl_reg;
1261 struct tty_struct *tty;
1262 struct device *tty_dev;
1263 int may_wake = 0;
1264
1265 /* Get the tty which could be NULL so don't assume it's valid */
1266 tty = tty_port_tty_get(&port->state->port);
1267 if (tty) {
1268 tty_dev = tty->dev;
1269 may_wake = device_may_wakeup(tty_dev);
1270 tty_kref_put(tty);
1271 }
1272
1273 if (console_suspend_enabled && !may_wake) {
1274 struct xuartps *xuartps = port->private_data;
1275
1276 clk_enable(xuartps->aperclk);
1277 clk_enable(xuartps->refclk);
1278
1279 spin_lock_irqsave(&port->lock, flags);
1280
1281 /* Set TX/RX Reset */
1282 xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) |
1283 (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST),
1284 XUARTPS_CR_OFFSET);
1285 while (xuartps_readl(XUARTPS_CR_OFFSET) &
1286 (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST))
1287 cpu_relax();
1288
1289 /* restore rx timeout value */
1290 xuartps_writel(rx_timeout, XUARTPS_RXTOUT_OFFSET);
1291 /* Enable Tx/Rx */
1292 ctrl_reg = xuartps_readl(XUARTPS_CR_OFFSET);
1293 xuartps_writel(
1294 (ctrl_reg & ~(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS)) |
1295 (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN),
1296 XUARTPS_CR_OFFSET);
1297
1298 spin_unlock_irqrestore(&port->lock, flags);
1299 } else {
1300 spin_lock_irqsave(&port->lock, flags);
1301 /* restore original rx trigger level */
1302 xuartps_writel(rx_trigger_level, XUARTPS_RXWM_OFFSET);
1303 /* enable RX timeout interrupt */
1304 xuartps_writel(XUARTPS_IXR_TOUT, XUARTPS_IER_OFFSET);
1305 spin_unlock_irqrestore(&port->lock, flags);
1306 }
1307
1308 return uart_resume_port(&xuartps_uart_driver, port);
1309}
1310#endif /* ! CONFIG_PM_SLEEP */
1311
1312static SIMPLE_DEV_PM_OPS(xuartps_dev_pm_ops, xuartps_suspend, xuartps_resume);
1313
1201/** Structure Definitions 1314/** Structure Definitions
1202 */ 1315 */
1203static struct uart_driver xuartps_uart_driver = { 1316static struct uart_driver xuartps_uart_driver = {
@@ -1348,6 +1461,7 @@ static struct platform_driver xuartps_platform_driver = {
1348 .owner = THIS_MODULE, 1461 .owner = THIS_MODULE,
1349 .name = XUARTPS_NAME, /* Driver name */ 1462 .name = XUARTPS_NAME, /* Driver name */
1350 .of_match_table = xuartps_of_match, 1463 .of_match_table = xuartps_of_match,
1464 .pm = &xuartps_dev_pm_ops,
1351 }, 1465 },
1352}; 1466};
1353 1467