Skip to content

Commit

Permalink
OMAP3: PM: UART: disable clocks when idle and off-mode support
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Kevin Hilman committed May 28, 2009
1 parent 5a1a5ab commit 4af4016
Show file tree
Hide file tree
Showing 5 changed files with 405 additions and 27 deletions.
16 changes: 15 additions & 1 deletion arch/arm/mach-omap2/pm24xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ static int omap2_fclks_active(void)

f1 = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
f2 = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);

/* Ignore UART clocks. These are handled by UART core (serial.c) */
f1 &= ~(OMAP24XX_EN_UART1 | OMAP24XX_EN_UART2);
f2 &= ~OMAP24XX_EN_UART3;

if (f1 | f2)
return 1;
return 0;
Expand Down Expand Up @@ -117,12 +122,20 @@ static void omap2_enter_full_retention(void)
if (omap_irq_pending())
goto no_sleep;

omap_uart_prepare_idle(0);
omap_uart_prepare_idle(1);
omap_uart_prepare_idle(2);

/* Jump to SRAM suspend code */
omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL),
OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL),
OMAP_SDRC_REGADDR(SDRC_POWER));
no_sleep:

omap_uart_resume_idle(2);
omap_uart_resume_idle(1);
omap_uart_resume_idle(0);

no_sleep:
if (omap2_pm_debug) {
unsigned long long tmp;

Expand Down Expand Up @@ -283,6 +296,7 @@ static int omap2_pm_suspend(void)
mir1 = omap_readl(0x480fe0a4);
omap_writel(1 << 5, 0x480fe0ac);

omap_uart_prepare_suspend();
omap2_enter_full_retention();

omap_writel(mir1, 0x480fe0a4);
Expand Down
15 changes: 15 additions & 0 deletions arch/arm/mach-omap2/pm34xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <mach/clockdomain.h>
#include <mach/powerdomain.h>
#include <mach/control.h>
#include <mach/serial.h>

#include "cm.h"
#include "cm-regbits-34xx.h"
Expand Down Expand Up @@ -168,10 +169,16 @@ static void omap_sram_idle(void)
return;
}
omap2_gpio_prepare_for_retention();
omap_uart_prepare_idle(0);
omap_uart_prepare_idle(1);
omap_uart_prepare_idle(2);

_omap_sram_idle(NULL, save_state);
cpu_init();

omap_uart_resume_idle(2);
omap_uart_resume_idle(1);
omap_uart_resume_idle(0);
omap2_gpio_resume_after_retention();
}

Expand Down Expand Up @@ -204,6 +211,11 @@ static int omap3_fclks_active(void)
CM_FCLKEN);
fck_per = cm_read_mod_reg(OMAP3430_PER_MOD,
CM_FCLKEN);

/* Ignore UART clocks. These are handled by UART core (serial.c) */
fck_core1 &= ~(OMAP3430_EN_UART1 | OMAP3430_EN_UART2);
fck_per &= ~OMAP3430_EN_UART3;

if (fck_core1 | fck_core3 | fck_sgx | fck_dss |
fck_cam | fck_per | fck_usbhost)
return 1;
Expand All @@ -212,6 +224,8 @@ static int omap3_fclks_active(void)

static int omap3_can_sleep(void)
{
if (!omap_uart_can_sleep())
return 0;
if (omap3_fclks_active())
return 0;
return 1;
Expand Down Expand Up @@ -301,6 +315,7 @@ static int omap3_pm_suspend(void)
goto restore;
}

omap_uart_prepare_suspend();
omap_sram_idle();

restore:
Expand Down
Loading

0 comments on commit 4af4016

Please sign in to comment.