<br><br><div class="gmail_quote">On Thu, May 5, 2011 at 2:05 AM, Kevin Hilman <span dir="ltr">&lt;<a href="mailto:khilman@ti.com">khilman@ti.com</a>&gt;</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">&quot;Govindraj.R&quot; &lt;<a href="mailto:govindraj.raja@ti.com">govindraj.raja@ti.com</a>&gt; writes:<br>
<br>
&gt; Adapts omap-serial driver to use pm_runtime api&#39;s.<br>
&gt;<br>
&gt; 1.) Populate reg values to uart port which can be used for context restore.<br>
&gt; 2.) Moving context_restore func to driver from serial.c<br>
&gt; 3.) Adding port_enable/disable func to enable/disable given uart port.<br>
&gt;     enable port using get_sync and disable using autosuspend.<br>
&gt; 4.) using runtime irq safe api to make get_sync be called from irq context.<br>
&gt;<br>
&gt; Signed-off-by: Govindraj.R &lt;<a href="mailto:govindraj.raja@ti.com">govindraj.raja@ti.com</a>&gt;<br>
&gt; ---<br>
&gt;  arch/arm/mach-omap2/serial.c                  |   16 ++<br>
&gt;  arch/arm/plat-omap/include/plat/omap-serial.h |    2 +<br>
&gt;  drivers/tty/serial/omap-serial.c              |  211 ++++++++++++++++++++++---<br>
&gt;  3 files changed, 203 insertions(+), 26 deletions(-)<br>
&gt;<br>
&gt; diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c<br>
&gt; index 8c1a4c7..314d82f 100644<br>
&gt; --- a/arch/arm/mach-omap2/serial.c<br>
&gt; +++ b/arch/arm/mach-omap2/serial.c<br>
&gt; @@ -189,6 +189,21 @@ static void omap_serial_fill_default_pads(struct omap_board_data *bdata)<br>
&gt;       }<br>
&gt;  }<br>
&gt;<br>
&gt; +static void omap_uart_wakeup_enable(struct platform_device *pdev, bool enable)<br>
&gt; +{<br>
&gt; +     struct omap_uart_port_info *up = pdev-&gt;dev.platform_data;<br>
&gt; +<br>
&gt; +     /* Set or clear wake-enable bit */<br>
&gt; +     if (up-&gt;wk_en &amp;&amp; up-&gt;wk_mask) {<br>
&gt; +             u32 v = __raw_readl(up-&gt;wk_en);<br>
&gt; +             if (enable)<br>
&gt; +                     v |= up-&gt;wk_mask;<br>
&gt; +             else<br>
&gt; +                     v &amp;= ~up-&gt;wk_mask;<br>
&gt; +             __raw_writel(v, up-&gt;wk_en);<br>
&gt; +     }<br>
&gt; +}<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&#39;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 &gt; /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&#39;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: &#39;Droid Sans&#39;, 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: &#39;Droid Sans&#39;, 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="&#39;Droid Sans&#39;, 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="&#39;Droid Sans&#39;, 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="&#39;Droid Sans&#39;, 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>
&gt;  static void omap_uart_idle_init(struct omap_uart_port_info *uart,<br>
&gt;                               unsigned short num)<br>
&gt;  {<br>
&gt; @@ -332,6 +347,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)<br>
&gt;<br>
&gt;       pdata-&gt;uartclk = OMAP24XX_BASE_BAUD * 16;<br>
&gt;       pdata-&gt;flags = UPF_BOOT_AUTOCONF;<br>
&gt; +     pdata-&gt;enable_wakeup = omap_uart_wakeup_enable;<br>
&gt;       if (bdata-&gt;id == omap_uart_con_id)<br>
&gt;               pdata-&gt;console_uart = true;<br>
&gt;<br><br></div></div></blockquote><div><br></div><div>&lt;&lt;SNIP&gt;&gt;</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">
&gt; +     pm_runtime_use_autosuspend(&amp;pdev-&gt;dev);<br>
&gt; +     pm_runtime_set_autosuspend_delay(&amp;pdev-&gt;dev,<br>
&gt; +                     OMAP_UART_AUTOSUSPEND_DELAY);<br>
&gt; +<br>
&gt; +     pm_runtime_enable(&amp;pdev-&gt;dev);<br>
&gt; +     pm_runtime_irq_safe(&amp;pdev-&gt;dev);<br>
&gt; +<br>
&gt; +     if (omap_up_info-&gt;console_uart) {<br>
&gt; +             od = to_omap_device(up-&gt;pdev);<br>
&gt; +             omap_hwmod_idle(od-&gt;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&#39;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>--&gt; _setup<br>   --&gt; _idle<br>    ---&gt; _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>
&gt; +             serial_omap_port_enable(up);<br>
&gt; +             serial_omap_port_disable(up);<br>
&gt; +     }<br>
&gt; +<br>
&gt;       ui[pdev-&gt;id] = up;<br>
&gt;       serial_omap_add_console_port(up);<br>
&gt;<br>
&gt;       ret = uart_add_one_port(&amp;serial_omap_reg, &amp;up-&gt;port);<br>
&gt;       if (ret != 0)<br>
&gt; -             goto do_release_region;<br>
&gt; +             goto err1;<br>
&gt;<br>
&gt; +     dev_set_drvdata(&amp;pdev-&gt;dev, up);<br>
&gt;       platform_set_drvdata(pdev, up);<br>
&gt; +<br>
&gt;       return 0;<br>
&gt;  err:<br>
&gt;       dev_err(&amp;pdev-&gt;dev, &quot;[UART%d]: failure [%s]: %d\n&quot;,<br>
&gt;                               pdev-&gt;id, __func__, ret);<br>
&gt; +err1:<br>
&gt; +     kfree(up);<br>
&gt;  do_release_region:<br>
&gt;       release_mem_region(mem-&gt;start, (mem-&gt;end - mem-&gt;start) + 1);<br>
&gt;       return ret;<br>
&gt; @@ -1318,20 +1421,76 @@ static int serial_omap_remove(struct platform_device *dev)<br>
&gt;<br>
&gt;       platform_set_drvdata(dev, NULL);<br>
&gt;       if (up) {<br>
&gt; +             pm_runtime_disable(&amp;up-&gt;pdev-&gt;dev);<br>
&gt;               uart_remove_one_port(&amp;serial_omap_reg, &amp;up-&gt;port);<br>
&gt;               kfree(up);<br>
&gt;       }<br>
&gt;       return 0;<br>
&gt;  }<br>
&gt;<br>
&gt; +static void omap_uart_restore_context(struct uart_omap_port *up)<br>
&gt; +{<br>
&gt; +     u16 efr = 0;<br>
&gt; +<br>
&gt; +     serial_out(up, UART_OMAP_MDR1, up-&gt;mdr1);<br>
&gt; +     serial_out(up, UART_LCR, 0xBF); /* Config B mode */<br>
&gt; +     efr = serial_in(up, UART_EFR);<br>
&gt; +     serial_out(up, UART_EFR, UART_EFR_ECB);<br>
&gt; +     serial_out(up, UART_LCR, 0x0); /* Operational mode */<br>
&gt; +     serial_out(up, UART_IER, 0x0);<br>
&gt; +     serial_out(up, UART_LCR, 0xBF); /* Config B mode */<br>
&gt; +     serial_out(up, UART_DLL, up-&gt;dll);<br>
&gt; +     serial_out(up, UART_DLM, up-&gt;dlh);<br>
&gt; +     serial_out(up, UART_LCR, 0x0); /* Operational mode */<br>
&gt; +     serial_out(up, UART_IER, up-&gt;ier);<br>
&gt; +     serial_out(up, UART_FCR, up-&gt;fcr);<br>
&gt; +     serial_out(up, UART_LCR, 0x80);<br>
&gt; +     serial_out(up, UART_MCR, up-&gt;mcr);<br>
&gt; +     serial_out(up, UART_LCR, 0xBF); /* Config B mode */<br>
&gt; +     serial_out(up, UART_EFR, efr);<br>
&gt; +     serial_out(up, UART_LCR, UART_LCR_WLEN8);<br>
&gt; +     /* UART 16x mode */<br>
&gt; +     serial_out(up, UART_OMAP_MDR1, up-&gt;mdr1);<br>
&gt; +}<br>
&gt; +<br>
&gt; +static int omap_serial_runtime_suspend(struct device *dev)<br>
&gt; +{<br>
&gt; +     struct uart_omap_port *up = dev_get_drvdata(dev);<br>
&gt; +<br>
&gt; +     if (!up)<br>
&gt; +             goto done;<br>
&gt; +<br>
&gt; +     if (device_may_wakeup(dev))<br>
&gt; +             up-&gt;enable_wakeup(up-&gt;pdev, true);<br>
&gt; +     else<br>
&gt; +             up-&gt;enable_wakeup(up-&gt;pdev, false);<br>
&gt; +done:<br>
&gt; +     return 0;<br>
&gt; +}<br>
&gt; +<br>
&gt; +static int omap_serial_runtime_resume(struct device *dev)<br>
&gt; +{<br>
&gt; +     struct uart_omap_port *up = dev_get_drvdata(dev);<br>
&gt; +<br>
&gt; +     if (up)<br>
&gt; +             omap_uart_restore_context(up);<br>
&gt; +<br>
&gt; +     return 0;<br>
&gt; +}<br>
&gt; +<br>
&gt; +static const struct dev_pm_ops omap_serial_dev_pm_ops = {<br>
&gt; +     .suspend = serial_omap_suspend,<br>
&gt; +     .resume = serial_omap_resume,<br>
&gt; +     .runtime_suspend = omap_serial_runtime_suspend,<br>
&gt; +     .runtime_resume = omap_serial_runtime_resume,<br>
&gt; +};<br>
&gt; +<br>
&gt;  static struct platform_driver serial_omap_driver = {<br>
&gt;       .probe          = serial_omap_probe,<br>
&gt;       .remove         = serial_omap_remove,<br>
&gt; -<br>
&gt; -     .suspend        = serial_omap_suspend,<br>
&gt; -     .resume         = serial_omap_resume,<br>
&gt;       .driver         = {<br>
&gt;               .name   = DRIVER_NAME,<br>
&gt; +             .pm = &amp;omap_serial_dev_pm_ops,<br>
&gt;       },<br>
&gt;  };<br>
</div></div></blockquote></div><br>