Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

serial: omap: Fix device tree based PM runtime

In the runtime_suspend function pdata is not being used, and
also blocks the function in device tree based booting. Fix it
by removing the unused pdata from the runtime_suspend function.

Further, context loss count is not being passed in pdata, so
let's just reinitialize the port every time for those case.
This can be further optimized later on for the device tree
case by adding detection for the hardware state and possibly
by adding a driver specific autosuspend timeout.

And doing this, we can then make the related dev_err into a
dev_dbg message instead of an error.

In order for the wake-up events to work, we also need to set
autosuspend_timeout to -1 if 0, and also device_init_wakeup()
as that's not being done by the platform init code for the
device tree case.

Note that this does not affect legacy booting, and in fact
might make it work for the cases where the context loss info
is not being passed in pdata.

Thanks to Kevin Hilman <khilman@linaro.org> for debugging
and suggesting fixes for the autosuspend_timeout and
device_init_wakeup() related initializiation.

Reviewed-by: Kevin Hilman <khilman@linaro.org>
Tested-by: Kevin Hilman <khilman@linaro.org>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Tony Lindgren and committed by
Greg Kroah-Hartman
a630fbfb 80c48497

+5 -6
+5 -6
drivers/tty/serial/omap-serial.c
··· 198 198 struct omap_uart_port_info *pdata = up->dev->platform_data; 199 199 200 200 if (!pdata || !pdata->get_context_loss_count) 201 - return 0; 201 + return -EINVAL; 202 202 203 203 return pdata->get_context_loss_count(up->dev); 204 204 } ··· 1502 1502 1503 1503 platform_set_drvdata(pdev, up); 1504 1504 pm_runtime_enable(&pdev->dev); 1505 + if (omap_up_info->autosuspend_timeout == 0) 1506 + omap_up_info->autosuspend_timeout = -1; 1507 + device_init_wakeup(up->dev, true); 1505 1508 pm_runtime_use_autosuspend(&pdev->dev); 1506 1509 pm_runtime_set_autosuspend_delay(&pdev->dev, 1507 1510 omap_up_info->autosuspend_timeout); ··· 1614 1611 static int serial_omap_runtime_suspend(struct device *dev) 1615 1612 { 1616 1613 struct uart_omap_port *up = dev_get_drvdata(dev); 1617 - struct omap_uart_port_info *pdata = dev->platform_data; 1618 1614 1619 1615 if (!up) 1620 1616 return -EINVAL; ··· 1627 1625 if (up->is_suspending && !console_suspend_enabled && 1628 1626 uart_console(&up->port)) 1629 1627 return -EBUSY; 1630 - 1631 - if (!pdata) 1632 - return 0; 1633 1628 1634 1629 up->context_loss_cnt = serial_omap_get_context_loss_count(up); 1635 1630 ··· 1655 1656 int loss_cnt = serial_omap_get_context_loss_count(up); 1656 1657 1657 1658 if (loss_cnt < 0) { 1658 - dev_err(dev, "serial_omap_get_context_loss_count failed : %d\n", 1659 + dev_dbg(dev, "serial_omap_get_context_loss_count failed : %d\n", 1659 1660 loss_cnt); 1660 1661 serial_omap_restore_context(up); 1661 1662 } else if (up->context_loss_cnt != loss_cnt) {