-----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