> + serial_omap_port_enable(up);
> + serial_omap_port_disable(up);
> + }
> +
> ui[pdev->id] = up;
> serial_omap_add_console_port(up);
>
> ret = uart_add_one_port(&serial_omap_reg, &up->port);
> if (ret != 0)
> - goto do_release_region;
> + goto err1;
>
> + dev_set_drvdata(&pdev->dev, up);
> platform_set_drvdata(pdev, up);
> +
> return 0;
> err:
> dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n",
> pdev->id, __func__, ret);
> +err1:
> + kfree(up);
> do_release_region:
> release_mem_region(mem->start, (mem->end - mem->start) + 1);
> return ret;
> @@ -1318,20 +1421,76 @@ static int serial_omap_remove(struct platform_device *dev)
>
> platform_set_drvdata(dev, NULL);
> if (up) {
> + pm_runtime_disable(&up->pdev->dev);
> uart_remove_one_port(&serial_omap_reg, &up->port);
> kfree(up);
> }
> return 0;
> }
>
> +static void omap_uart_restore_context(struct uart_omap_port *up)
> +{
> + u16 efr = 0;
> +
> + serial_out(up, UART_OMAP_MDR1, up->mdr1);
> + serial_out(up, UART_LCR, 0xBF); /* Config B mode */
> + efr = serial_in(up, UART_EFR);
> + serial_out(up, UART_EFR, UART_EFR_ECB);
> + serial_out(up, UART_LCR, 0x0); /* Operational mode */
> + serial_out(up, UART_IER, 0x0);
> + serial_out(up, UART_LCR, 0xBF); /* Config B mode */
> + serial_out(up, UART_DLL, up->dll);
> + serial_out(up, UART_DLM, up->dlh);
> + serial_out(up, UART_LCR, 0x0); /* Operational mode */
> + serial_out(up, UART_IER, up->ier);
> + serial_out(up, UART_FCR, up->fcr);
> + serial_out(up, UART_LCR, 0x80);
> + serial_out(up, UART_MCR, up->mcr);
> + serial_out(up, UART_LCR, 0xBF); /* Config B mode */
> + serial_out(up, UART_EFR, efr);
> + serial_out(up, UART_LCR, UART_LCR_WLEN8);
> + /* UART 16x mode */
> + serial_out(up, UART_OMAP_MDR1, up->mdr1);
> +}
> +
> +static int omap_serial_runtime_suspend(struct device *dev)
> +{
> + struct uart_omap_port *up = dev_get_drvdata(dev);
> +
> + if (!up)
> + goto done;
> +
> + if (device_may_wakeup(dev))
> + up->enable_wakeup(up->pdev, true);
> + else
> + up->enable_wakeup(up->pdev, false);
> +done:
> + return 0;
> +}
> +
> +static int omap_serial_runtime_resume(struct device *dev)
> +{
> + struct uart_omap_port *up = dev_get_drvdata(dev);
> +
> + if (up)
> + omap_uart_restore_context(up);
> +
> + return 0;
> +}
> +
> +static const struct dev_pm_ops omap_serial_dev_pm_ops = {
> + .suspend = serial_omap_suspend,
> + .resume = serial_omap_resume,
> + .runtime_suspend = omap_serial_runtime_suspend,
> + .runtime_resume = omap_serial_runtime_resume,
> +};
> +
> static struct platform_driver serial_omap_driver = {
> .probe = serial_omap_probe,
> .remove = serial_omap_remove,
> -
> - .suspend = serial_omap_suspend,
> - .resume = serial_omap_resume,
> .driver = {
> .name = DRIVER_NAME,
> + .pm = &omap_serial_dev_pm_ops,
> },
> };