<br><br><div class="gmail_quote">On Thu, May 5, 2011 at 2:05 AM, Kevin Hilman <span dir="ltr"><<a href="mailto:khilman@ti.com">khilman@ti.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div><div></div><div class="h5">"Govindraj.R" <<a href="mailto:govindraj.raja@ti.com">govindraj.raja@ti.com</a>> writes:<br>
<br>
> Adapts omap-serial driver to use pm_runtime api's.<br>
><br>
> 1.) Populate reg values to uart port which can be used for context restore.<br>
> 2.) Moving context_restore func to driver from serial.c<br>
> 3.) Adding port_enable/disable func to enable/disable given uart port.<br>
> enable port using get_sync and disable using autosuspend.<br>
> 4.) using runtime irq safe api to make get_sync be called from irq context.<br>
><br>
> Signed-off-by: Govindraj.R <<a href="mailto:govindraj.raja@ti.com">govindraj.raja@ti.com</a>><br>
> ---<br>
> arch/arm/mach-omap2/serial.c | 16 ++<br>
> arch/arm/plat-omap/include/plat/omap-serial.h | 2 +<br>
> drivers/tty/serial/omap-serial.c | 211 ++++++++++++++++++++++---<br>
> 3 files changed, 203 insertions(+), 26 deletions(-)<br>
><br>
> diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c<br>
> index 8c1a4c7..314d82f 100644<br>
> --- a/arch/arm/mach-omap2/serial.c<br>
> +++ b/arch/arm/mach-omap2/serial.c<br>
> @@ -189,6 +189,21 @@ static void omap_serial_fill_default_pads(struct omap_board_data *bdata)<br>
> }<br>
> }<br>
><br>
> +static void omap_uart_wakeup_enable(struct platform_device *pdev, bool enable)<br>
> +{<br>
> + struct omap_uart_port_info *up = pdev->dev.platform_data;<br>
> +<br>
> + /* Set or clear wake-enable bit */<br>
> + if (up->wk_en && up->wk_mask) {<br>
> + u32 v = __raw_readl(up->wk_en);<br>
> + if (enable)<br>
> + v |= up->wk_mask;<br>
> + else<br>
> + v &= ~up->wk_mask;<br>
> + __raw_writel(v, up->wk_en);<br>
> + }<br>
> +}<br>
<br>
</div></div>Rather than having the driver do this via the PRCM, can you do an<br>
experiment? Can you try to leave the module-level wakeup enabled all<br>
the time in the PRCM, and the driver can then enable/disable<br>
module-level wakeups simply by toggling ENAWAKEUP in the module's<br>
SYSCONFIG? If that works, than you can just use<br>
omap_hwmod_enable_wakeup() for this and not need the above function.<br></blockquote><div><br></div><div><br></div><div>If we leave PRCM uart module level bit enabled all time and we disable</div><div>wakeup using sysfs</div>
<div> </div><div>echo disabled > /sys/devices/platform/omap/omap_uart.0/power/wakeup</div><div><br></div><div>it wakes up after clock disable, however unsetting the bit ensures it doesn't</div><div>wakeup after uart clocks are cut.</div>
<div><br></div><div>As Paul suggested, How about adding <span class="Apple-style-span" style="border-collapse: collapse; color: rgb(32, 32, 32); font-family: 'Droid Sans', arial, sans-serif; font-size: 13px; ">omap_device/omap_hwmod function</span></div>
<div><span class="Apple-style-span" style="border-collapse: collapse; color: rgb(32, 32, 32); font-family: 'Droid Sans', arial, sans-serif; font-size: 13px; ">to set and unset the bit?</span></div><div><br></div>
<div>
Using</div><div><br></div><div><font class="Apple-style-span" color="#202020" face="'Droid Sans', arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">.module_bit = OMAP3430_EN_UART1_SHIFT,</span></font></div>
<div><font class="Apple-style-span" color="#202020" face="'Droid Sans', arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;"><br></span></font></div><div><font class="Apple-style-span" color="#202020" face="'Droid Sans', arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">from hwmod data?</span></font></div>
<div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div><div></div><div class="h5"><br>
> static void omap_uart_idle_init(struct omap_uart_port_info *uart,<br>
> unsigned short num)<br>
> {<br>
> @@ -332,6 +347,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)<br>
><br>
> pdata->uartclk = OMAP24XX_BASE_BAUD * 16;<br>
> pdata->flags = UPF_BOOT_AUTOCONF;<br>
> + pdata->enable_wakeup = omap_uart_wakeup_enable;<br>
> if (bdata->id == omap_uart_con_id)<br>
> pdata->console_uart = true;<br>
><br><br></div></div></blockquote><div><br></div><div><<SNIP>></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div><div class="h5">
> + pm_runtime_use_autosuspend(&pdev->dev);<br>
> + pm_runtime_set_autosuspend_delay(&pdev->dev,<br>
> + OMAP_UART_AUTOSUSPEND_DELAY);<br>
> +<br>
> + pm_runtime_enable(&pdev->dev);<br>
> + pm_runtime_irq_safe(&pdev->dev);<br>
> +<br>
> + if (omap_up_info->console_uart) {<br>
> + od = to_omap_device(up->pdev);<br>
> + omap_hwmod_idle(od->hwmods[0]);<br>
<br>
</div></div>Driver should have know knowlege of the underlying hwmod.<br>
<br>
I assume this is here because of the usage of HWMOD_INIT_NO_IDLE and<br>
HWMOD_INIT_NO_RESET, right? </blockquote><div><br></div><div> Yes correct.</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"> With proper runtime PM, we should be able to<br>
remove the need for using those flags.<br></blockquote><div><br></div><div><br></div><div><meta http-equiv="content-type" content="text/html; charset=utf-8"><span class="Apple-style-span" style="border-collapse: collapse; font-family: arial, sans-serif; font-size: 13px; ">For omap-uart used for earlyprintk's the early_console driver will</span><span class="Apple-style-span" style="border-collapse: collapse; font-family: arial, sans-serif; font-size: 13px; "><br>
</span><span class="Apple-style-span" style="border-collapse: collapse; font-family: arial, sans-serif; font-size: 13px; ">use printch from debug macro to print through uart.</span><span class="Apple-style-span" style="border-collapse: collapse; font-family: arial, sans-serif; font-size: 13px; "><br>
</span><span class="Apple-style-span" style="border-collapse: collapse; font-family: arial, sans-serif; font-size: 13px; "><br></span></div><div><span class="Apple-style-span" style="border-collapse: collapse; font-family: arial, sans-serif; font-size: 13px; ">During omap-hwmod is getting initialized<br>
<br>--> _setup<br> --> _idle<br> ---> _disable_clocks<br><br>at this point of time while printch is happening and<br>hwmod disables uart clocks I dont have uart-console<br>driver available which can enable clocks back.<br>
<br>So I have to use those flags when earlyprintk is enabled.</span></div><div><br></div><div>--</div><div>Thanks,</div><div>Govindraj.R</div><div><br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<font color="#888888"><br>
Kevin<br>
</font><div><div></div><div class="h5"><br>
> + serial_omap_port_enable(up);<br>
> + serial_omap_port_disable(up);<br>
> + }<br>
> +<br>
> ui[pdev->id] = up;<br>
> serial_omap_add_console_port(up);<br>
><br>
> ret = uart_add_one_port(&serial_omap_reg, &up->port);<br>
> if (ret != 0)<br>
> - goto do_release_region;<br>
> + goto err1;<br>
><br>
> + dev_set_drvdata(&pdev->dev, up);<br>
> platform_set_drvdata(pdev, up);<br>
> +<br>
> return 0;<br>
> err:<br>
> dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n",<br>
> pdev->id, __func__, ret);<br>
> +err1:<br>
> + kfree(up);<br>
> do_release_region:<br>
> release_mem_region(mem->start, (mem->end - mem->start) + 1);<br>
> return ret;<br>
> @@ -1318,20 +1421,76 @@ static int serial_omap_remove(struct platform_device *dev)<br>
><br>
> platform_set_drvdata(dev, NULL);<br>
> if (up) {<br>
> + pm_runtime_disable(&up->pdev->dev);<br>
> uart_remove_one_port(&serial_omap_reg, &up->port);<br>
> kfree(up);<br>
> }<br>
> return 0;<br>
> }<br>
><br>
> +static void omap_uart_restore_context(struct uart_omap_port *up)<br>
> +{<br>
> + u16 efr = 0;<br>
> +<br>
> + serial_out(up, UART_OMAP_MDR1, up->mdr1);<br>
> + serial_out(up, UART_LCR, 0xBF); /* Config B mode */<br>
> + efr = serial_in(up, UART_EFR);<br>
> + serial_out(up, UART_EFR, UART_EFR_ECB);<br>
> + serial_out(up, UART_LCR, 0x0); /* Operational mode */<br>
> + serial_out(up, UART_IER, 0x0);<br>
> + serial_out(up, UART_LCR, 0xBF); /* Config B mode */<br>
> + serial_out(up, UART_DLL, up->dll);<br>
> + serial_out(up, UART_DLM, up->dlh);<br>
> + serial_out(up, UART_LCR, 0x0); /* Operational mode */<br>
> + serial_out(up, UART_IER, up->ier);<br>
> + serial_out(up, UART_FCR, up->fcr);<br>
> + serial_out(up, UART_LCR, 0x80);<br>
> + serial_out(up, UART_MCR, up->mcr);<br>
> + serial_out(up, UART_LCR, 0xBF); /* Config B mode */<br>
> + serial_out(up, UART_EFR, efr);<br>
> + serial_out(up, UART_LCR, UART_LCR_WLEN8);<br>
> + /* UART 16x mode */<br>
> + serial_out(up, UART_OMAP_MDR1, up->mdr1);<br>
> +}<br>
> +<br>
> +static int omap_serial_runtime_suspend(struct device *dev)<br>
> +{<br>
> + struct uart_omap_port *up = dev_get_drvdata(dev);<br>
> +<br>
> + if (!up)<br>
> + goto done;<br>
> +<br>
> + if (device_may_wakeup(dev))<br>
> + up->enable_wakeup(up->pdev, true);<br>
> + else<br>
> + up->enable_wakeup(up->pdev, false);<br>
> +done:<br>
> + return 0;<br>
> +}<br>
> +<br>
> +static int omap_serial_runtime_resume(struct device *dev)<br>
> +{<br>
> + struct uart_omap_port *up = dev_get_drvdata(dev);<br>
> +<br>
> + if (up)<br>
> + omap_uart_restore_context(up);<br>
> +<br>
> + return 0;<br>
> +}<br>
> +<br>
> +static const struct dev_pm_ops omap_serial_dev_pm_ops = {<br>
> + .suspend = serial_omap_suspend,<br>
> + .resume = serial_omap_resume,<br>
> + .runtime_suspend = omap_serial_runtime_suspend,<br>
> + .runtime_resume = omap_serial_runtime_resume,<br>
> +};<br>
> +<br>
> static struct platform_driver serial_omap_driver = {<br>
> .probe = serial_omap_probe,<br>
> .remove = serial_omap_remove,<br>
> -<br>
> - .suspend = serial_omap_suspend,<br>
> - .resume = serial_omap_resume,<br>
> .driver = {<br>
> .name = DRIVER_NAME,<br>
> + .pm = &omap_serial_dev_pm_ops,<br>
> },<br>
> };<br>
</div></div></blockquote></div><br>