diff options
| author | Vladimir Tsunaev <vladimirt@motorola.com> | 2014-06-30 12:33:40 -0400 |
|---|---|---|
| committer | Vladimir Tsunaev <vladimirt@motorola.com> | 2014-06-30 15:20:14 -0400 |
| commit | 4ef0c4d2561955eeafc1585627736c561ea65bb7 (patch) | |
| tree | 66cdef689301dd5dda29681514f0a6b0f54be04d | |
| parent | 6bf795f69fc73cd5c0834256cb1c0b212eaee14d (diff) | |
| download | olio-linux-3.10-4ef0c4d2561955eeafc1585627736c561ea65bb7.tar.xz olio-linux-3.10-4ef0c4d2561955eeafc1585627736c561ea65bb7.zip | |
IKXCLOCK-2630 serial: Failed to hit offmode due to UART1 being non-idle
When c55 driver is changing pad configuration than PRCM detects
wake event from pad and it happens after PRCM get suspended
Evidence of this behavior is line:
"omap34xx_do_sram_idle: OMAP3_PRM_IRQENABLE_MPU_OFFSET 0x00000000"
and status bit in:
PRM__CORE (48004a00) b0 => 0x00002000 0x00000000)
As result event still pending and system can not get into requested
low power state.
UART1 is not wakeup-capable and to avoid this false wake ups the wakeup
event has to be disabled in all levels (uart module and PRCM module).
Change-Id: I9aba9503f91ddd15965d23755f3293c0f333adc2
Signed-off-by: Vladimir Tsunaev <vladimirt@motorola.com>
| -rw-r--r-- | arch/arm/mach-omap2/serial.c | 26 | ||||
| -rw-r--r-- | drivers/tty/serial/omap-serial.c | 3 | ||||
| -rw-r--r-- | include/linux/platform_data/serial-omap.h | 1 |
3 files changed, 30 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 80cd45fa8d8..b570d93cbb7 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -22,6 +22,7 @@ #include <linux/clk.h> #include <linux/io.h> #include <linux/delay.h> +#include <linux/spinlock.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/pm_runtime.h> @@ -94,10 +95,35 @@ void omap_uart_enable_wakeup(struct device *dev, bool enable) else omap_hwmod_disable_wakeup(od->hwmods[0]); } +void omap_uart_remove_wakeup(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct omap_device *od = to_omap_device(pdev); + struct omap_hwmod *oh = od->hwmods[0]; + u16 offs; + unsigned long flags; + + spin_lock_irqsave(&oh->_lock, flags); + omap_hwmod_disable_wakeup(oh); + if (oh->class->sysc) + oh->class->sysc->sysc_flags &= ~SYSC_HAS_ENAWAKEUP; + offs = (oh->prcm.omap2.prcm_reg_id == 3) ? + OMAP3430ES2_PM_WKEN3 : PM_WKEN1; + omap2_prm_clear_mod_reg_bits((1<<oh->prcm.omap2.module_bit), + oh->prcm.omap2.module_offs, offs); + offs = (oh->prcm.omap2.prcm_reg_id == 3) ? + OMAP3430ES2_PM_WKST3 : PM_WKST1; + omap2_prm_set_mod_reg_bits((1<<oh->prcm.omap2.module_bit), + oh->prcm.omap2.module_offs, offs); + spin_unlock_irqrestore(&oh->_lock, flags); +} #else void omap_uart_enable_wakeup(struct device *dev, bool enable) {} +void omap_uart_remove_wakeup(struct device *dev) +{ +} #endif /* CONFIG_PM */ #ifdef CONFIG_OMAP_MUX diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 780c5c28545..e077e996b50 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1558,6 +1558,9 @@ static int serial_omap_probe(struct platform_device *pdev) if (omap_up_info->wakeup_capable) device_init_wakeup(&pdev->dev, true); + else + omap_uart_remove_wakeup(&pdev->dev); + omap_serial_fill_features_erratas(up); diff --git a/include/linux/platform_data/serial-omap.h b/include/linux/platform_data/serial-omap.h index 838132af5d8..a2f2a8c45a2 100644 --- a/include/linux/platform_data/serial-omap.h +++ b/include/linux/platform_data/serial-omap.h @@ -49,6 +49,7 @@ struct omap_uart_port_info { void (*enable_wakeup)(struct device *, bool); }; +extern void omap_uart_remove_wakeup(struct device *dev); extern void omap_uart_enable_wakeup(struct device *dev, bool enable); extern int omap_pm_get_dev_context_loss_count(struct device *dev); |