"ext Jouni Hogander" <[EMAIL PROTECTED]> writes:

> Current implementation makes it possible that printouts are
> written into UART while its clocks are disabled. This causes freeze.

Now I got how this new uart clock handling works. Event thought this
fix is not too sensible it actually does what is needed.

So the problem is that uart clocks are enabled in prcm_interrupt. Now
if some other interrupt handler is run before prcm_interrupt_handler
and it tries to printout something to uart -> system freezes.

Kevin, you should ensure some way that uart clocks are enabled right
away after wakeup. This patch presents one possibile
implementation. Another way could be to move uart_check_wakeup to be
run in idle loop rather than in interrupt handler.

>
> This patch contains possible fix for this.
>
> Signed-off-by: Jouni Hogander <[EMAIL PROTECTED]>
> ---
>  arch/arm/mach-omap2/pm34xx.c             |    6 ++++++
>  arch/arm/mach-omap2/serial.c             |   30 
> ++++++++++++++++++++++++++++++
>  arch/arm/plat-omap/include/mach/serial.h |    2 ++
>  3 files changed, 38 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> index d480c39..3838a19 100644
> --- a/arch/arm/mach-omap2/pm34xx.c
> +++ b/arch/arm/mach-omap2/pm34xx.c
> @@ -320,6 +320,7 @@ void omap_sram_idle(void)
>       /* PER */
>       per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
>       if (per_next_state < PWRDM_POWER_ON) {
> +             omap_uart_prepare_idle(2);
>               omap2_gpio_prepare_for_retention();
>               if (per_next_state == PWRDM_POWER_OFF)
>                       omap3_per_save_context();
> @@ -328,6 +329,8 @@ void omap_sram_idle(void)
>       /* CORE */
>       core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
>       if (core_next_state < PWRDM_POWER_ON) {
> +             omap_uart_prepare_idle(0);
> +             omap_uart_prepare_idle(1);
>               if (core_next_state == PWRDM_POWER_OFF) {
>                       prm_set_mod_reg_bits(OMAP3430_AUTO_OFF,
>                                            OMAP3430_GR_MOD,
> @@ -386,6 +389,8 @@ void omap_sram_idle(void)
>                       prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF,
>                                              OMAP3430_GR_MOD,
>                                              OMAP3_PRM_VOLTCTRL_OFFSET);
> +             omap_uart_resume_idle(0);
> +             omap_uart_resume_idle(1);
>       }
>  
>       /* PER */
> @@ -394,6 +399,7 @@ void omap_sram_idle(void)
>               if (per_prev_state == PWRDM_POWER_OFF)
>                       omap3_per_restore_context();
>               omap2_gpio_resume_after_retention();
> +             omap_uart_resume_idle(2);
>       }
>  
>       /* Enable smartreflex after WFI */
> diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
> index 65cce87..ef30d8d 100644
> --- a/arch/arm/mach-omap2/serial.c
> +++ b/arch/arm/mach-omap2/serial.c
> @@ -249,6 +249,36 @@ static void omap_uart_idle_timer(unsigned long data)
>       omap_uart_allow_sleep(uart);
>  }
>  
> +void omap_uart_prepare_idle(int num)
> +{
> +     struct omap_uart_state *uart;
> +
> +     if (!clocks_off_while_idle)
> +             return;
> +
> +     list_for_each_entry(uart, &uart_list, node) {
> +             if (num == uart->num && uart->can_sleep) {
> +                     omap_uart_disable_clocks(uart);
> +                     return;
> +             }
> +     }
> +}
> +
> +void omap_uart_resume_idle(int num)
> +{
> +     struct omap_uart_state *uart;
> +
> +     if (!clocks_off_while_idle)
> +             return;
> +
> +     list_for_each_entry(uart, &uart_list, node) {
> +             if (num == uart->num) {
> +                     omap_uart_enable_clocks(uart);
> +                     return;
> +             }
> +     }
> +}
> +
>  void omap_uart_check_wakeup(void)
>  {
>       struct omap_uart_state *uart;
> diff --git a/arch/arm/plat-omap/include/mach/serial.h 
> b/arch/arm/plat-omap/include/mach/serial.h
> index 11ff540..254a775 100644
> --- a/arch/arm/plat-omap/include/mach/serial.h
> +++ b/arch/arm/plat-omap/include/mach/serial.h
> @@ -44,6 +44,8 @@
>  extern void omap_serial_init(void);
>  extern int omap_uart_can_sleep(void);
>  extern void omap_uart_check_wakeup(void);
> +extern void omap_uart_prepare_idle(int num);
> +extern void omap_uart_resume_idle(int num);
>  #endif
>  
>  #endif
> -- 
> 1.6.0.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to [EMAIL PROTECTED]
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Jouni Högander

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to