diff options
Diffstat (limited to 'drivers/tty/serial/xilinx_uartps.c')
-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 | ||