aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/pm24xx.c
diff options
context:
space:
mode:
authorKevin Hilman <khilman@deeprootsystems.com>2009-02-04 13:51:40 -0500
committerKevin Hilman <khilman@deeprootsystems.com>2009-05-28 13:59:06 -0400
commit4af4016c53f52b26461b8030211f8427a58fa5ed (patch)
tree984ffcb57bcc8158332c10ef799203bd905d7147 /arch/arm/mach-omap2/pm24xx.c
parent5a1a5abdb2e9a301f1ac62feb37228f3f4d3117c (diff)
OMAP3: PM: UART: disable clocks when idle and off-mode support
This patch allows the UART clocks to be disabled when the OMAP UARTs are inactive, thus permitting the chip to hit retention in idle. After the expiration of an activity timer, each UART is allowed to disable its clocks so the system can enter retention. The activity timer is (re)activated on any UART interrupt, UART wake event or any IO pad wakeup. The actual disable of the UART clocks is done in the 'prepare_idle' hook called from the OMAP idle loop. While the activity timer is active, the smart-idle mode of the UART is also disabled. This is due to a "feature" of the UART module that after a UART wakeup, the smart-idle mode may be entered before the UART has communicated the interrupt, or upon TX, an idle mode may be entered before the TX FIFOs are emptied. Upon suspend, the 'prepare_suspend' hook cancels any pending activity timers and allows the clocks to be disabled immediately. In addition, upon disabling clocks the UART state is saved in case of an off-mode transition while clocks are off. Special thanks to Tero Kristo for the initial ideas and first versions of UART idle support, and to Jouni Hogander for extra testing and bugfixes. Tested on OMAP3 (Beagle, RX51, SDP, EVM) and OMAP2 (n810) Cc: Tero Kristo <tero.kristo@nokia.com> Cc: Jouni Hogander <jouni.hogander@nokia.com> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Diffstat (limited to 'arch/arm/mach-omap2/pm24xx.c')
-rw-r--r--arch/arm/mach-omap2/pm24xx.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index d38f3121dde9..db1025562fb0 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -71,6 +71,11 @@ static int omap2_fclks_active(void)
71 71
72 f1 = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1); 72 f1 = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
73 f2 = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2); 73 f2 = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
74
75 /* Ignore UART clocks. These are handled by UART core (serial.c) */
76 f1 &= ~(OMAP24XX_EN_UART1 | OMAP24XX_EN_UART2);
77 f2 &= ~OMAP24XX_EN_UART3;
78
74 if (f1 | f2) 79 if (f1 | f2)
75 return 1; 80 return 1;
76 return 0; 81 return 0;
@@ -117,12 +122,20 @@ static void omap2_enter_full_retention(void)
117 if (omap_irq_pending()) 122 if (omap_irq_pending())
118 goto no_sleep; 123 goto no_sleep;
119 124
125 omap_uart_prepare_idle(0);
126 omap_uart_prepare_idle(1);
127 omap_uart_prepare_idle(2);
128
120 /* Jump to SRAM suspend code */ 129 /* Jump to SRAM suspend code */
121 omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL), 130 omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL),
122 OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL), 131 OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL),
123 OMAP_SDRC_REGADDR(SDRC_POWER)); 132 OMAP_SDRC_REGADDR(SDRC_POWER));
124no_sleep:
125 133
134 omap_uart_resume_idle(2);
135 omap_uart_resume_idle(1);
136 omap_uart_resume_idle(0);
137
138no_sleep:
126 if (omap2_pm_debug) { 139 if (omap2_pm_debug) {
127 unsigned long long tmp; 140 unsigned long long tmp;
128 141
@@ -283,6 +296,7 @@ static int omap2_pm_suspend(void)
283 mir1 = omap_readl(0x480fe0a4); 296 mir1 = omap_readl(0x480fe0a4);
284 omap_writel(1 << 5, 0x480fe0ac); 297 omap_writel(1 << 5, 0x480fe0ac);
285 298
299 omap_uart_prepare_suspend();
286 omap2_enter_full_retention(); 300 omap2_enter_full_retention();
287 301
288 omap_writel(mir1, 0x480fe0a4); 302 omap_writel(mir1, 0x480fe0a4);