summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Tsunaev <vladimirt@motorola.com>2014-06-30 12:33:40 -0400
committerVladimir Tsunaev <vladimirt@motorola.com>2014-06-30 15:20:14 -0400
commit4ef0c4d2561955eeafc1585627736c561ea65bb7 (patch)
tree66cdef689301dd5dda29681514f0a6b0f54be04d
parent6bf795f69fc73cd5c0834256cb1c0b212eaee14d (diff)
downloadolio-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.c26
-rw-r--r--drivers/tty/serial/omap-serial.c3
-rw-r--r--include/linux/platform_data/serial-omap.h1
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);