diff options
| author | Soren Brinkmann <soren.brinkmann@xilinx.com> | 2013-10-17 17:08:12 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-10-19 22:47:38 -0400 |
| commit | 4b47d9aa1e3b54b73f9399f3d64b47495cc67a1e (patch) | |
| tree | 22a13755a4a6fc44c82cafa91ba8f0140678150e /drivers/tty | |
| parent | c4b0510cc1571ff44e1d6024d92683d49a8bcfde (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')
| -rw-r--r-- | drivers/tty/serial/xilinx_uartps.c | 114 |
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 | */ | ||
| 1208 | static 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 | */ | ||
| 1256 | static 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 | |||
| 1312 | static SIMPLE_DEV_PM_OPS(xuartps_dev_pm_ops, xuartps_suspend, xuartps_resume); | ||
| 1313 | |||
| 1201 | /** Structure Definitions | 1314 | /** Structure Definitions |
| 1202 | */ | 1315 | */ |
| 1203 | static struct uart_driver xuartps_uart_driver = { | 1316 | static 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 | ||
