Re: Suspend broken on 3.3?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



-----Original Message-----
From: "Raja, Govindraj" <govindraj.raja@xxxxxx>
To: Kevin Hilman <khilman@xxxxxx>
Cc: Joe Woodward <jw@xxxxxxxxxxxxxx>, "linux-omap@xxxxxxxxxxxxxxx" <linux-omap@xxxxxxxxxxxxxxx>, Felipe Balbi <balbi@xxxxxx>
Date: Wed, 28 Mar 2012 16:29:53 +0530
Subject: Re: Suspend broken on 3.3?

> On Wed, Mar 28, 2012 at 3:07 AM, Kevin Hilman <khilman@xxxxxx> wrote:
> > "Raja, Govindraj" <govindraj.raja@xxxxxx> writes:
> >
> >> Hi Kevin,
> >>
> >> On Tue, Mar 27, 2012 at 6:04 AM, Kevin Hilman <khilman@xxxxxx>
> wrote:
> >>> +Govindraj,
> >>>
> >>> "Joe Woodward" <jw@xxxxxxxxxxxxxx> writes:
> >>>
> >>>> Right, I've stepped back a bit and dug out a GUSMTIX Palo43
> carrier
> >>>> board on which to test the Overo OMAP3530 COM and I've found:
> >>>>  - Running a stock 3.3 (with absolutely no changes) does indeed
> suspend correctly.
> >>>>  - Running the 3.3 kernel with my (minor) board modifications
> >>>>  (basically defining some buttons) suspends correctly as well.
> >>>>
> >>>> Then I went back to my original board and the 3.3 still wakes up
> from
> >>>> suspend immediately. So I had a think, and the only real
> differences
> >>>> between my board the the GUMSTIX Palo43 board is that I am using
> >>>> multiple UARTs.
> >>>>
> >>>> Up to this point I've only wanted to wake on the console (ttyO2),
> and
> >>>> not any other UARTs so I've stopped them waking with:
> >>>>   echo disabled >
> /sys/devices/platform/omap/omap_uart.0/power/wakeup
> >>>>   echo disabled >
> /sys/devices/platform/omap/omap_uart.1/power/wakeup
> >>>>
> >>>> I wanted to check that this still worked, so tried disabling
> wakeup on
> >>>> the console (ttyO2):
> >>>>   echo disabled >
> /sys/devices/platform/omap/omap_uart.2/power/wakeup
> >>>>
> >>>> And if I do "echo mem > /sys/power/state" I was expecting to stay
> in
> >>>> suspend when I typed on my keyboard... However, the kernel still
> woke
> >>>> from suspend, which leads me to believe that the UART wakeup
> hasn't
> >>>> been disabled?
> >>>
> >>> Just to confirm: did the above work for you before v3.3?
> >>>
> >>>> Could you test if this is also the case your end?
> >>>
> >>> Yes, I get the same behavior, which is indeed broken.
> >>>
> >>> Govindraj, can you look into this?
> >>>
> >>> A quick glance suggests that disabling wakeups via the sysfs file
> is
> >>> only disabling runtime PM, but not actually disabling wakups at the
> >>> module-level or at the IO ring.
> >>>
> >>
> >> I have started looking into this, disabling and enabling of wake-ups
> >> from .runtime_suspend needs some changes as in here[1] with that I
> see pad
> >> wakeup getting disabled and it doesn't wake up after enabling off
> mode
> >> and suspending.
> >
> > Thanks for looking into this.
> >
> 
> Looks like the module wakeup event handling left to default
> value during runtime clean up is causing the wakeup to happen
> 
> Here is the patch[1] to fix the same tested on 3430SDP.
> 
> --
> Thanks,

Thanks,

This patch fixes the suspend problem for me, but there is another UART issue...

Basically I've got a fairly high speed data source (in UART terms, >900KBaud) pumping data to the OMAP (such as GPS positions).

I don't want this to wake me when suspended (which this patch fixes).

However, it seems on 3.3 that I get a lot of corruption/lost characters, which I'm assuming is because the UART is implementing runtime-PM.

So my next question is: How do I disable runtime-PM/force-always-on for a given UART? Can this be done via the sysfs?

Or where are the runtime-PM constraints set for the UART? I'm guessing they'll work for 115200Baud, but my high speed UART fowls these?

Cheers,
Joe


> Govindraj.R
> 
> [1]:
> 
> 
> From 5a5126750d527811547a45de9546c3e0f0fac77d Mon Sep 17 00:00:00 2001
> From: "Govindraj.R" <govindraj.raja@xxxxxx>
> Date: Tue, 27 Mar 2012 18:55:00 +0530
> Subject: [PATCH] OMAP2+: UART: Correct the module level wakeup
> enable/disable
>  mechanism
> 
> The commit (62f3ec5  ARM: OMAP2+: UART: Add wakeup mechanism for
> omap-uarts)
> removed module level wakeup enable/disable mechanism and retained only
> the pad wakeup handling.
> 
> On 24xx/34xx/36xx Module level wakeup events are enabled/disabled using
> PM_WKEN1_CORE/PM_WKEN_PER regs. The module level wakeups are enabled by
> default from bootloader, however the wakeups can be enabled/disabled
> using sysfs entry
> echo disabled > /sys/devices/platform/omap/omap_uart.X/power/wakeup
> [X=0,1,2,3]
> 
> Since module level wakeups were left enabled from bootup and when
> wakeups were disabled from sysfs uart module level wakeups were
> still happening as they were not getting disabled.
> 
> Adding the support to handle module level wakeups for omap2/3 socs.
> 
> Signed-off-by: Govindraj.R <govindraj.raja@xxxxxx>
> ---
>  arch/arm/mach-omap2/serial.c |   95
> +++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 93 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/serial.c
> b/arch/arm/mach-omap2/serial.c
> index f590afc..92ff94c 100644
> --- a/arch/arm/mach-omap2/serial.c
> +++ b/arch/arm/mach-omap2/serial.c
> @@ -56,6 +56,10 @@ struct omap_uart_state {
>  	int num;
>  	int can_sleep;
> 
> +	void __iomem *wk_st;
> +	void __iomem *wk_en;
> +	u32 wk_mask;
> +
>  	struct list_head node;
>  	struct omap_hwmod *oh;
>  	struct platform_device *pdev;
> @@ -82,17 +86,46 @@ static struct omap_uart_port_info
> omap_serial_default_info[] __initdata = {
>  };
> 
>  #ifdef CONFIG_PM
> +
> +static void omap_uart_disable_module_wakeup(struct omap_uart_state
> *uart)
> +{
> +	/* Clear wake-enable bit */
> +	if (uart->wk_en && uart->wk_mask) {
> +		u32 v = __raw_readl(uart->wk_en);
> +		v &= ~uart->wk_mask;
> +		__raw_writel(v, uart->wk_en);
> +	}
> +}
> +
> +static void omap_uart_enable_module_wakeup(struct omap_uart_state
> *uart)
> +{
> +	/* Set wake-enable bit */
> +	if (uart->wk_en && uart->wk_mask) {
> +		u32 v = __raw_readl(uart->wk_en);
> +		v |= uart->wk_mask;
> +		__raw_writel(v, uart->wk_en);
> +	}
> +}
> +
>  static void omap_uart_enable_wakeup(struct platform_device *pdev, bool
> enable)
>  {
>  	struct omap_device *od = to_omap_device(pdev);
> +	struct omap_uart_state *uart;
> 
>  	if (!od)
>  		return;
> 
> -	if (enable)
> +	list_for_each_entry(uart, &uart_list, node)
> +		if (pdev->id == uart->num)
> +			break;
> +
> +	if (enable) {
> +		omap_uart_enable_module_wakeup(uart);
>  		omap_hwmod_enable_wakeup(od->hwmods[0]);
> -	else
> +	} else {
> +		omap_uart_disable_module_wakeup(uart);
>  		omap_hwmod_disable_wakeup(od->hwmods[0]);
> +	}
>  }
> 
>  /*
> @@ -114,7 +147,64 @@ static void omap_uart_set_smartidle(struct
> platform_device *pdev)
>  	omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_SMART);
>  }
> 
> +static void omap_uart_idle_init(struct omap_uart_state *uart)
> +{
> +	if (cpu_is_omap34xx() && !cpu_is_ti816x()) {
> +		u32 mod = (uart->num == 2) ? OMAP3430_PER_MOD : CORE_MOD;
> +
> +		uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1);
> +		uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1);
> +		switch (uart->num) {
> +		case 0:
> +			uart->wk_mask = OMAP3430_ST_UART1_MASK;
> +			break;
> +		case 1:
> +			uart->wk_mask = OMAP3430_ST_UART2_MASK;
> +			break;
> +		case 2:
> +			uart->wk_mask = OMAP3430_ST_UART3_MASK;
> +			break;
> +		case 3:
> +			uart->wk_mask = OMAP3630_ST_UART4_MASK;
> +			break;
> +		}
> +	} else if (cpu_is_omap24xx()) {
> +
> +		if (cpu_is_omap2430()) {
> +			uart->wk_en = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKEN1);
> +			uart->wk_st = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKST1);
> +		} else if (cpu_is_omap2420()) {
> +			uart->wk_en = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKEN1);
> +			uart->wk_st = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKST1);
> +		}
> +		switch (uart->num) {
> +		case 0:
> +			uart->wk_mask = OMAP24XX_ST_UART1_MASK;
> +			break;
> +		case 1:
> +			uart->wk_mask = OMAP24XX_ST_UART2_MASK;
> +			break;
> +		case 2:
> +			uart->wk_mask = OMAP24XX_ST_UART3_MASK;
> +			break;
> +		}
> +	} else {
> +		uart->wk_en = 0;
> +		uart->wk_st = 0;
> +		uart->wk_mask = 0;
> +	}
> +
> +	/* Module level wakeups might be left enabled from
> +	 * bootloader disable it. Module level wakeup/pad_wakeup
> +	 * will be enabled if port is wakeup capaable after gating uart
> +	 * port clocks from omap-serial driver.
> +	 * Wakeup capability can be enabled or disbaled using sysfs entry.
> +	 */
> +	omap_uart_disable_module_wakeup(uart);
> +}
> +
>  #else
> +static void omap_uart_idle_init(struct omap_uart_state *uart) {}
>  static void omap_uart_enable_wakeup(struct platform_device *pdev, bool
> enable)
>  {}
>  static void omap_uart_set_noidle(struct platform_device *pdev) {}
> @@ -345,6 +435,7 @@ void __init omap_serial_init_port(struct
> omap_board_data *bdata,
>  	oh = uart->oh;
>  	name = DRIVER_NAME;
> 
> +	omap_uart_idle_init(uart);
>  	omap_up.dma_enabled = info->dma_enabled;
>  	omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
>  	omap_up.flags = UPF_BOOT_AUTOCONF;
> -- 
> 1.7.5.4
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap"
> in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


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


[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux