public inbox for linux-omap@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] Refreshed PM workaround patches 2.
@ 2008-08-15  7:44 Högander Jouni
  2008-08-15  7:47 ` [PATCH 1/4] 34XX: PM: Workaround to check wether any fck is active before entering sleep Jouni Hogander
                   ` (4 more replies)
  0 siblings, 5 replies; 21+ messages in thread
From: Högander Jouni @ 2008-08-15  7:44 UTC (permalink / raw)
  To: linux-omap

Refreshed PM workaround set without coding style errors and 24xx build
fixed. Here are instructions how to test them:

To get Omap into retention, this patch set still depends on:
1. ARCH: OMAP: MUSB: Do not block sleep (Felipe Balbi)

Test:
1. Apply dependency patch and workaround set on top of them

2. Enable disabling/enabling of gpio2-6 and uart clocks on idle:
   $ echo 1 > /sys/power/clocks_off_while_idle

3. Try out static suspend:
   $ echo mem > /sys/power/state
   Wake up from suspend by entering character to serial console. This
   should print out:
   "Successfully put all powerdomains to target state"

4. Try out dynamic sleep:
   $ echo 1 > /sys/power/sleep_while_idle
   On Omap3430 SDP board VCORE_EN led can be used as an indicator. If
   it starts to blink after a while then Omap enters retention on
   idle. To make this work also display needs to be blanked.

-- 
Jouni Högander

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 21+ messages in thread
* [PATCH 1/4] 34XX: PM: Workaround to check wether any fck is active before entering sleep
@ 2008-08-07  8:43 Kalle Jokiniemi
  2008-08-07  8:43 ` [PATCH 2/4] 34XX: PM: Workaround for taking care of gpio clocks Kalle Jokiniemi
  0 siblings, 1 reply; 21+ messages in thread
From: Kalle Jokiniemi @ 2008-08-07  8:43 UTC (permalink / raw)
  To: linux-omap; +Cc: rnayak, jouni.hogander

From: ext Rajendra Nayak <rnayak@ti.com>

This workaround shouldn't be needed when all drivers are configuring
their sysconfig registers properly and using their clocks properly.

Signed-off-by: Jouni Hogander <jouni.hogander@nokia.com>
---
 arch/arm/mach-omap2/pm34xx.c |   31 +++++++++++++++++++++++++++++++
 1 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index fc72c11..bca1994 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -174,10 +174,41 @@ static void omap_sram_idle(void)
 	omap2_gpio_resume_after_retention();
 }
 
+static int omap3_fclks_active(void)
+{
+	u32 fck_core1 = 0, fck_core3 = 0, fck_sgx = 0, fck_dss = 0,
+		fck_cam = 0, fck_per = 0, fck_usbhost = 0;
+
+	fck_core1 = cm_read_mod_reg(CORE_MOD,
+				    CM_FCLKEN1);
+	if (is_sil_rev_greater_than(OMAP3430_REV_ES1_0)) {
+		fck_core3 = cm_read_mod_reg(CORE_MOD,
+					    OMAP3430ES2_CM_FCLKEN3);
+		fck_sgx = cm_read_mod_reg(OMAP3430ES2_SGX_MOD,
+					  CM_FCLKEN);
+		fck_usbhost = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
+					      CM_FCLKEN);
+	} else
+		fck_sgx = cm_read_mod_reg(GFX_MOD,
+					  OMAP3430ES2_CM_FCLKEN3);
+	fck_dss = cm_read_mod_reg(OMAP3430_DSS_MOD,
+				  CM_FCLKEN);
+	fck_cam = cm_read_mod_reg(OMAP3430_CAM_MOD,
+				  CM_FCLKEN);
+	fck_per = cm_read_mod_reg(OMAP3430_PER_MOD,
+				  CM_FCLKEN);
+	if (fck_core1 | fck_core3 | fck_sgx | fck_dss |
+	    fck_cam | fck_per | fck_usbhost)
+		return 1;
+	return 0;
+}
+
 static int omap3_can_sleep(void)
 {
 	if (!enable_dyn_sleep)
 		return 0;
+	if (omap3_fclks_active())
+		return 0;
 	if (atomic_read(&sleep_block) > 0)
 		return 0;
 	return 1;
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 21+ messages in thread
* [PATCH 3/4] Added sleep support to UART
@ 2008-08-06 13:01 Rajendra Nayak
  0 siblings, 0 replies; 21+ messages in thread
From: Rajendra Nayak @ 2008-08-06 13:01 UTC (permalink / raw)
  To: linux-omap; +Cc: jouni.hogander

From: Tero Kristo <tero.kristo@nokia.com>

UART usage (e.g. serial console) now denies sleep for 5 seconds. This
makes it possible to use serial console when dynamic idle is
enabled. Write 1 to /sys/power/clocks_off_while_sleep to enable uart
clock disable on idle. Without this omap won't enter retention.

Also moved code from pm-debug.c to serial.c, and made pm24xx.c use
this new implementation.

Signed-off-by: Jouni Hogander <jouni.hogander@nokia.com>
---
 arch/arm/mach-omap2/pm-debug.c     |  132 ---------------------------------
 arch/arm/mach-omap2/pm.h           |    8 --
 arch/arm/mach-omap2/pm24xx.c       |   53 ++++++++-----
 arch/arm/mach-omap2/pm34xx.c       |   26 ++++--
 arch/arm/mach-omap2/serial.c       |  148 +++++++++++++++++++++++++++++++++++++
 include/asm-arm/arch-omap/common.h |    3
 6 files changed, 202 insertions(+), 168 deletions(-)

Index: linux-omap-2.6/arch/arm/mach-omap2/pm-debug.c
===================================================================
--- linux-omap-2.6.orig/arch/arm/mach-omap2/pm-debug.c	2008-08-06
18:07:31.000000000 +0530
+++ linux-omap-2.6/arch/arm/mach-omap2/pm-debug.c	2008-08-06 18:08:02.000000000
+0530
@@ -37,138 +37,6 @@
 #ifdef CONFIG_PM_DEBUG
 int omap2_pm_debug = 0;

-static int serial_console_clock_disabled;
-static int serial_console_uart;
-static unsigned int serial_console_next_disable;
-
-static struct clk *console_iclk, *console_fclk;
-
-static void serial_console_kick(void)
-{
-	serial_console_next_disable = omap2_read_32k_sync_counter();
-	/* Keep the clocks on for 4 secs */
-	serial_console_next_disable += 4 * 32768;
-}
-
-static void serial_wait_tx(void)
-{
-	static const unsigned long uart_bases[3] = {
-		0x4806a000, 0x4806c000, 0x4806e000
-	};
-	unsigned long lsr_reg;
-	int looped = 0;
-
-	/* Wait for TX FIFO and THR to get empty */
-	lsr_reg = IO_ADDRESS(uart_bases[serial_console_uart - 1] + (5 << 2));
-	while ((__raw_readb(lsr_reg) & 0x60) != 0x60)
-		looped = 1;
-	if (looped)
-		serial_console_kick();
-}
-
-u32 omap2_read_32k_sync_counter(void)
-{
-        return omap_readl(OMAP2_32KSYNCT_BASE + 0x0010);
-}
-
-void serial_console_fclk_mask(u32 *f1, u32 *f2)
-{
-	switch (serial_console_uart)  {
-	case 1:
-		*f1 &= ~(1 << 21);
-		break;
-	case 2:
-		*f1 &= ~(1 << 22);
-		break;
-	case 3:
-		*f2 &= ~(1 << 2);
-		break;
-	}
-}
-
-void serial_console_sleep(int enable)
-{
-	if (console_iclk == NULL || console_fclk == NULL)
-		return;
-
-	if (enable) {
-		BUG_ON(serial_console_clock_disabled);
-		if (clk_get_usecount(console_fclk) == 0)
-			return;
-		if ((int) serial_console_next_disable - (int) omap2_read_32k_sync_counter()
>= 0)
-			return;
-		serial_wait_tx();
-		clk_disable(console_iclk);
-		clk_disable(console_fclk);
-		serial_console_clock_disabled = 1;
-	} else {
-		int serial_wakeup = 0;
-		u32 l;
-
-		switch (serial_console_uart)  {
-		case 1:
-			l = prm_read_mod_reg(CORE_MOD, PM_WKST1);
-			if (l & OMAP24XX_ST_UART1)
-				serial_wakeup = 1;
-			break;
-		case 2:
-			l = prm_read_mod_reg(CORE_MOD, PM_WKST1);
-			if (l & OMAP24XX_ST_UART2)
-				serial_wakeup = 1;
-			break;
-		case 3:
-			l = prm_read_mod_reg(CORE_MOD, OMAP24XX_PM_WKST2);
-			if (l & OMAP24XX_ST_UART3)
-				serial_wakeup = 1;
-			break;
-		}
-		if (serial_wakeup)
-			serial_console_kick();
-		if (!serial_console_clock_disabled)
-			return;
-		clk_enable(console_iclk);
-		clk_enable(console_fclk);
-		serial_console_clock_disabled = 0;
-	}
-}
-
-void pm_init_serial_console(void)
-{
-	const struct omap_serial_console_config *conf;
-	char name[16];
-
-	conf = omap_get_config(OMAP_TAG_SERIAL_CONSOLE,
-			       struct omap_serial_console_config);
-	if (conf == NULL)
-		return;
-	if (conf->console_uart > 3 || conf->console_uart < 1)
-		return;
-	serial_console_uart = conf->console_uart;
-	sprintf(name, "uart%d_fck", conf->console_uart);
-	console_fclk = clk_get(NULL, name);
-	if (IS_ERR(console_fclk))
-		console_fclk = NULL;
-	name[6] = 'i';
-	console_iclk = clk_get(NULL, name);
-	if (IS_ERR(console_fclk))
-		console_iclk = NULL;
-	if (console_fclk == NULL || console_iclk == NULL) {
-		serial_console_uart = 0;
-		return;
-	}
-	switch (serial_console_uart) {
-	case 1:
-		prm_set_mod_reg_bits(OMAP24XX_ST_UART1, CORE_MOD, PM_WKEN1);
-		break;
-	case 2:
-		prm_set_mod_reg_bits(OMAP24XX_ST_UART2, CORE_MOD, PM_WKEN1);
-		break;
-	case 3:
-		prm_set_mod_reg_bits(OMAP24XX_ST_UART3, CORE_MOD, OMAP24XX_PM_WKEN2);
-		break;
-	}
-}
-
 #define DUMP_PRM_MOD_REG(mod, reg)    \
 	regs[reg_count].name = #mod "." #reg; \
 	regs[reg_count++].val = prm_read_mod_reg(mod, reg)
Index: linux-omap-2.6/arch/arm/mach-omap2/pm.h
===================================================================
--- linux-omap-2.6.orig/arch/arm/mach-omap2/pm.h	2008-08-06 18:07:31.000000000
+0530
+++ linux-omap-2.6/arch/arm/mach-omap2/pm.h	2008-08-06 18:08:02.000000000 +0530
@@ -25,18 +25,10 @@ extern void omap2_allow_sleep(void);


 #ifdef CONFIG_PM_DEBUG
-extern u32 omap2_read_32k_sync_counter(void);
 extern void omap2_pm_dump(int mode, int resume, unsigned int us);
-extern void serial_console_fclk_mask(u32 *f1, u32 *f2);
-extern void pm_init_serial_console(void);
-extern void serial_console_sleep(int enable);
 extern int omap2_pm_debug;
 #else
-#define omap2_read_32k_sync_counter()		0
-#define serial_console_sleep(enable)		do {} while (0);
-#define pm_init_serial_console()		do {} while (0);
 #define omap2_pm_dump(mode, resume, us)		do {} while (0);
-#define serial_console_fclk_mask(f1, f2)		do {} while (0);
 #define omap2_pm_debug				0
 #endif /* CONFIG_PM_DEBUG */
 #endif
Index: linux-omap-2.6/arch/arm/mach-omap2/pm24xx.c
===================================================================
--- linux-omap-2.6.orig/arch/arm/mach-omap2/pm24xx.c	2008-08-06
18:07:31.000000000 +0530
+++ linux-omap-2.6/arch/arm/mach-omap2/pm24xx.c	2008-08-06 18:08:02.000000000
+0530
@@ -44,6 +44,7 @@
 #include <asm/arch/mux.h>
 #include <asm/arch/dma.h>
 #include <asm/arch/board.h>
+#include <asm/arch/common.h>

 #include "prm.h"
 #include "prm-regbits-24xx.h"
@@ -73,7 +74,10 @@ 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);
-	serial_console_fclk_mask(&f1, &f2);
+
+	if (uart_clocks_off_while_sleep)
+		omap_serial_fclk_mask(&f1, &f2);
+
 	if (f1 | f2)
 		return 1;
 	return 0;
@@ -81,7 +85,8 @@ static int omap2_fclks_active(void)

 static void omap2_enter_full_retention(void)
 {
-	u32 l, sleep_time = 0;
+	u32 l = 0;
+	struct timespec sleep_time;

 	/* There is 1 reference hold for all children of the oscillator
 	 * clock, the following will remove it. If no one else uses the
@@ -111,28 +116,33 @@ static void omap2_enter_full_retention(v

 	if (omap2_pm_debug) {
 		omap2_pm_dump(0, 0, 0);
-		sleep_time = omap2_read_32k_sync_counter();
+		getnstimeofday(&sleep_time);
 	}

+	if (uart_clocks_off_while_sleep)
+		omap_serial_enable_clocks(0);
+
 	/* One last check for pending IRQs to avoid extra latency due
 	 * to sleeping unnecessarily. */
 	if (omap_irq_pending())
 		goto no_sleep;

-	serial_console_sleep(1);
 	/* Jump to SRAM suspend code */
 	omap2_sram_suspend(OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL));
 no_sleep:
-	serial_console_sleep(0);
+	omap_serial_check_wakeup();
+	if (uart_clocks_off_while_sleep)
+		omap_serial_enable_clocks(1);

 	if (omap2_pm_debug) {
-		unsigned long long tmp;
-		u32 resume_time;
+		struct timespec t;
+		struct timespec ts_delta;

-		resume_time = omap2_read_32k_sync_counter();
-		tmp = resume_time - sleep_time;
-		tmp *= 1000000;
-		omap2_pm_dump(0, 1, tmp / 32768);
+		getnstimeofday(&t);
+		ts_delta = timespec_sub(t, sleep_time);
+		omap2_pm_dump(0, 1,
+			      div_s64(timespec_to_ns(&ts_delta),
+				      NSEC_PER_USEC));
 	}
 	omap2_gpio_resume_after_retention();

@@ -193,7 +203,7 @@ static int omap2_allow_mpu_retention(voi

 static void omap2_enter_mpu_retention(void)
 {
-	u32 sleep_time = 0;
+	struct timespec sleep_time;
 	int only_idle = 0;

 	/* Putting MPU into the WFI state while a transfer is active
@@ -222,19 +232,20 @@ static void omap2_enter_mpu_retention(vo

 	if (omap2_pm_debug) {
 		omap2_pm_dump(only_idle ? 2 : 1, 0, 0);
-		sleep_time = omap2_read_32k_sync_counter();
+		getnstimeofday(&sleep_time);
 	}

 	omap2_sram_idle();

 	if (omap2_pm_debug) {
-		unsigned long long tmp;
-		u32 resume_time;
+		struct timespec t;
+		struct timespec ts_delta;

-		resume_time = omap2_read_32k_sync_counter();
-		tmp = resume_time - sleep_time;
-		tmp *= 1000000;
-		omap2_pm_dump(only_idle ? 2 : 1, 1, tmp / 32768);
+		getnstimeofday(&t);
+		ts_delta = timespec_sub(t, sleep_time);
+		omap2_pm_dump(only_idle ? 2 : 1, 1,
+			      div_s64(timespec_to_ns(&ts_delta),
+				      NSEC_PER_USEC));
 	}
 }

@@ -250,6 +261,8 @@ static int omap2_can_sleep(void)
 		return 0;
 	if (omap_dma_running())
 		return 0;
+	if (!omap_serial_can_sleep())
+		return 0;

 	return 1;
 }
@@ -517,8 +530,6 @@ int __init omap2_pm_init(void)

 	prcm_setup_regs();

-	pm_init_serial_console();
-
 	/* Hack to prevent MPU retention when STI console is enabled. */
 	{
 		const struct omap_sti_console_config *sti;
Index: linux-omap-2.6/arch/arm/mach-omap2/pm34xx.c
===================================================================
--- linux-omap-2.6.orig/arch/arm/mach-omap2/pm34xx.c	2008-08-06
18:07:49.000000000 +0530
+++ linux-omap-2.6/arch/arm/mach-omap2/pm34xx.c	2008-08-06 18:08:02.000000000
+0530
@@ -29,6 +29,7 @@
 #include <asm/arch/pm.h>
 #include <asm/arch/clockdomain.h>
 #include <asm/arch/powerdomain.h>
+#include <asm/arch/common.h>

 #include "cm.h"
 #include "cm-regbits-34xx.h"
@@ -89,6 +90,9 @@ static irqreturn_t prcm_interrupt_handle
 	u32 wkst, irqstatus_mpu;
 	u32 fclk, iclk;

+	/* Check if we woke up to serial console activity */
+	omap_serial_check_wakeup();
+
 	/* WKUP */
 	wkst = prm_read_mod_reg(WKUP_MOD, PM_WKST);
 	if (wkst) {
@@ -199,17 +203,21 @@ static void omap_sram_idle(void)

 	omap2_gpio_prepare_for_retention();

-	/* XXX This is for gpio fclk hack. Will be removed as gpio driver
-	 * handles fcks correctly */
-	if (clocks_off_while_idle)
+	if (clocks_off_while_idle) {
+		omap_serial_enable_clocks(0);
+		/* XXX This is for gpio fclk hack. Will be removed as
+		 * gpio driver * handles fcks correctly */
 		per_gpio_clk_disable();
+	}

 	_omap_sram_idle(NULL, save_state, clocks_off_while_idle);

-	/* XXX This is for gpio fclk hack. Will be removed as gpio driver
-	 * handles fcks correctly */
-	if (clocks_off_while_idle)
+	if (clocks_off_while_idle) {
+		omap_serial_enable_clocks(1);
+		/* XXX This is for gpio fclk hack. Will be removed as
+		 * gpio driver * handles fcks correctly */
 		per_gpio_clk_enable();
+	}

 	omap2_gpio_resume_after_retention();
 }
@@ -238,8 +246,10 @@ static int omap3_fclks_active(void)
 	fck_per = cm_read_mod_reg(OMAP3430_PER_MOD,
 				  CM_FCLKEN);

-	if (clocks_off_while_idle)
+	if (clocks_off_while_idle) {
 		gpio_fclk_mask(&fck_per);
+		omap_serial_fclk_mask(&fck_core1, &fck_per);
+	}

 	if (fck_core1 | fck_core3 | fck_sgx | fck_dss |
 	    fck_cam | fck_per | fck_usbhost)
@@ -255,6 +265,8 @@ static int omap3_can_sleep(void)
 		return 0;
 	if (atomic_read(&sleep_block) > 0)
 		return 0;
+	if (!omap_serial_can_sleep())
+		return 0;
 	return 1;
 }

Index: linux-omap-2.6/arch/arm/mach-omap2/serial.c
===================================================================
--- linux-omap-2.6.orig/arch/arm/mach-omap2/serial.c	2008-08-06
18:07:31.000000000 +0530
+++ linux-omap-2.6/arch/arm/mach-omap2/serial.c	2008-08-06 18:08:02.000000000
+0530
@@ -22,9 +22,66 @@

 #include <asm/arch/common.h>
 #include <asm/arch/board.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/control.h>
+
+#include "prm.h"
+#include "pm.h"
+
+#define SERIAL_AWAKE_TIME 5

 static struct clk *uart_ick[OMAP_MAX_NR_PORTS];
 static struct clk *uart_fck[OMAP_MAX_NR_PORTS];
+static struct timespec omap_serial_next_sleep;
+
+#ifdef CONFIG_ARCH_OMAP24XX
+static const u32 omap2_uart_wk_st[OMAP_MAX_NR_PORTS] = {
+	OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKST1),
+	OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKST1),
+	OMAP2420_PRM_REGADDR(CORE_MOD, OMAP24XX_PM_WKST2)
+};
+static const u32 omap2_uart_wk_en[OMAP_MAX_NR_PORTS] = {
+	OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKEN1),
+	OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKEN1),
+	OMAP2420_PRM_REGADDR(CORE_MOD, OMAP24XX_PM_WKEN2),
+};
+static const u32 omap2_uart_wk_bit[OMAP_MAX_NR_PORTS] = {
+	OMAP24XX_ST_UART1, OMAP24XX_ST_UART2, OMAP24XX_ST_UART3
+};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP34XX
+static const u32 omap3_uart_wk_st[OMAP_MAX_NR_PORTS] = {
+	OMAP34XX_PRM_REGADDR(CORE_MOD, PM_WKST1),
+	OMAP34XX_PRM_REGADDR(CORE_MOD, PM_WKST1),
+	OMAP34XX_PRM_REGADDR(OMAP3430_PER_MOD, PM_WKST1)
+};
+static const u32 omap3_uart_wk_en[OMAP_MAX_NR_PORTS] = {
+	OMAP34XX_PRM_REGADDR(CORE_MOD, PM_WKEN1),
+	OMAP34XX_PRM_REGADDR(CORE_MOD, PM_WKEN1),
+	OMAP34XX_PRM_REGADDR(OMAP3430_PER_MOD, PM_WKEN1)
+};
+static const u32 omap3_uart_wk_bit[OMAP_MAX_NR_PORTS] = {
+	OMAP3430_ST_UART1, OMAP3430_ST_UART2, OMAP3430_ST_UART3
+};
+#endif
+
+static const u32 *omap_uart_wk_st;
+static const u32 *omap_uart_wk_en;
+static const u32 *omap_uart_wk_bit;
+
+/* UART padconfig registers, these may differ if non-default padconfig
+   is used */
+#define CONTROL_PADCONF_UART1_RX 0x182
+#define CONTROL_PADCONF_UART2_RX 0x17A
+#define CONTROL_PADCONF_UART3_RX 0x19E
+#define PADCONF_WAKEUP_ST 0x8000
+
+static const u32 omap34xx_uart_padconf[OMAP_MAX_NR_PORTS] = {
+	CONTROL_PADCONF_UART1_RX,
+	CONTROL_PADCONF_UART2_RX,
+	CONTROL_PADCONF_UART3_RX
+};

 static struct plat_serial8250_port serial_platform_data[] = {
 	{
@@ -83,6 +140,13 @@ static inline void __init omap_serial_re
 	serial_write_reg(p, UART_OMAP_SYSC, (0x02 << 3) | (1 << 2) | (1 << 0));
 }

+static void omap_serial_kick(void)
+{
+	getnstimeofday(&omap_serial_next_sleep);
+	timespec_add_ns(&omap_serial_next_sleep, (s64)SERIAL_AWAKE_TIME *
+		NSEC_PER_SEC);
+}
+
 void omap_serial_enable_clocks(int enable)
 {
 	int i;
@@ -99,6 +163,67 @@ void omap_serial_enable_clocks(int enabl
 	}
 }

+void omap_serial_fclk_mask(u32 *f1, u32 *f2)
+{
+	if (uart_ick[0])
+		*f1 &= ~(1 << uart_fck[0]->enable_bit);
+	if (uart_ick[1])
+		*f1 &= ~(1 << uart_fck[1]->enable_bit);
+	if (uart_ick[2])
+		*f2 &= ~(1 << uart_fck[2]->enable_bit);
+}
+
+void omap_serial_check_wakeup(void)
+{
+	int i;
+
+
+	for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
+		if (!uart_ick[i])
+			continue;
+
+		if (cpu_is_omap34xx())
+			if (omap_ctrl_readw(omap34xx_uart_padconf[i]) &
+			    PADCONF_WAKEUP_ST) {
+				omap_serial_kick();
+				return;
+			}
+
+		if (__raw_readl(omap_uart_wk_st[i]) &
+		    omap_uart_wk_bit[i]) {
+			omap_serial_kick();
+			return;
+		}
+	}
+}
+
+int omap_serial_can_sleep(void)
+{
+	int i;
+	struct timespec t;
+
+	struct plat_serial8250_port *p = serial_platform_data;
+
+	getnstimeofday(&t);
+
+	for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
+		if (!uart_ick[i])
+			continue;
+		/* Check if we have data in the transmit buffer */
+		if ((serial_read_reg(p + i, UART_LSR) &
+			(UART_LSR_TEMT|UART_LSR_THRE))
+			!= (UART_LSR_TEMT|UART_LSR_THRE)) {
+				omap_serial_kick();
+				return 0;
+		}
+	}
+
+	if (timespec_compare(&t, &omap_serial_next_sleep) < 0)
+		return 0;
+
+	return 1;
+}
+
 void __init omap_serial_init(void)
 {
 	int i;
@@ -116,8 +241,25 @@ void __init omap_serial_init(void)
 	if (info == NULL)
 		return;

+#ifdef CONFIG_ARCH_OMAP24XX
+	if (cpu_is_omap242x()) {
+		omap_uart_wk_st = omap2_uart_wk_st;
+		omap_uart_wk_en = omap2_uart_wk_en;
+		omap_uart_wk_bit = omap2_uart_wk_bit;
+	}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP34XX
+	if (cpu_is_omap34xx()) {
+		omap_uart_wk_st = omap3_uart_wk_st;
+		omap_uart_wk_en = omap3_uart_wk_en;
+		omap_uart_wk_bit = omap3_uart_wk_bit;
+	}
+#endif
+
 	for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
 		struct plat_serial8250_port *p = serial_platform_data + i;
+		u32 v;

 		if (!(info->enabled_uarts & (1 << i))) {
 			p->membase = NULL;
@@ -142,7 +284,13 @@ void __init omap_serial_init(void)
 			clk_enable(uart_fck[i]);

 		omap_serial_reset(p);
+
+		v = __raw_readl(omap_uart_wk_en[i]);
+		v |= omap_uart_wk_bit[i];
+		__raw_writel(v, omap_uart_wk_en[i]);
 	}
+
+	omap_serial_kick();
 }

 static struct platform_device serial_device = {
Index: linux-omap-2.6/include/asm-arm/arch-omap/common.h
===================================================================
--- linux-omap-2.6.orig/include/asm-arm/arch-omap/common.h	2008-08-06
18:07:31.000000000 +0530
+++ linux-omap-2.6/include/asm-arm/arch-omap/common.h	2008-08-06
18:08:02.000000000 +0530
@@ -35,6 +35,9 @@ extern void omap_map_common_io(void);
 extern struct sys_timer omap_timer;
 extern void omap_serial_init(void);
 extern void omap_serial_enable_clocks(int enable);
+extern int omap_serial_can_sleep(void);
+extern void omap_serial_fclk_mask(u32 *f1, u32 *f2);
+void omap_serial_check_wakeup(void);
 #ifdef CONFIG_I2C_OMAP
 extern int omap_register_i2c_bus(int bus_id, u32 clkrate,
 				 struct i2c_board_info const *info,



^ permalink raw reply	[flat|nested] 21+ messages in thread
* [PATCH 0/6] 34XX: PM: Workarounds to get omap3 to retention 4th.
@ 2008-06-30  8:50 Högander Jouni
  2008-08-15  6:18 ` [PATCH 3/4] Added sleep support to UART Jouni Hogander
  0 siblings, 1 reply; 21+ messages in thread
From: Högander Jouni @ 2008-06-30  8:50 UTC (permalink / raw)
  To: linux-omap

Hi,

This patch set contains all workarounds that are needed to get omap3
to retention. Also patch from Tero Kristo to get PM to work if using
serial console is included in this set. Basically all patches in this
set should be reverted one by one as correct fixes are implemented and
applied.

This patch set superseeds earlier version sent 2008-06-25 9:11:49.

To get Omap into retention, this patch set still depends on:
1. ARCH: OMAP: MUSB: Do not block sleep (Felipe Balbi)

Test:
1. Apply dependency patch and workaround set on top of them

2. Enable disabling/enabling of gpio2-6 and uart clocks on idle:
   $ echo 1 > /sys/power/clocks_off_while_idle

3. Try out static suspend:
   $ echo mem > /sys/power/state
   Wake up from suspend by entering character to serial console. This
   should print out:
   "Successfully put all powerdomains to target state"

4. Try out dynamic sleep:
   $ echo 1 > /sys/power/sleep_while_idle
   On Omap3430 SDP board VCORE_EN led can be used as an indicator. If
   it starts to blink after a while then Omap enters retention on
   idle. To make this work also display needs to be blanked.

-- 
Jouni Högander

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2008-08-22 18:08 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-15  7:44 [PATCH 0/4] Refreshed PM workaround patches 2 Högander Jouni
2008-08-15  7:47 ` [PATCH 1/4] 34XX: PM: Workaround to check wether any fck is active before entering sleep Jouni Hogander
2008-08-20 11:35   ` Tony Lindgren
2008-08-22  5:45     ` Högander Jouni
2008-08-22 18:07       ` Tony Lindgren
2008-08-21  8:17   ` Rajendra Nayak
2008-08-21  9:41     ` Rajendra Nayak
2008-08-15  7:47 ` [PATCH 2/4] PM: Workaround for taking care of gpio clocks Jouni Hogander
2008-08-20 11:37   ` Tony Lindgren
2008-08-21 11:07     ` Tero.Kristo
2008-08-22 18:06       ` Tony Lindgren
2008-08-15  7:47 ` [PATCH 3/4] Added sleep support to UART Jouni Hogander
2008-08-20 11:40   ` Tony Lindgren
2008-08-20 12:26     ` Tero.Kristo
2008-08-15  7:47 ` [PATCH 4/4] 34XX: PM: Workaround to enable autoidle for clocks and plls Jouni Hogander
2008-08-20 11:51   ` Tony Lindgren
2008-08-15  7:49 ` [PATCH 0/4] Refreshed PM workaround patches 2 Felipe Balbi
2008-08-18 13:23   ` Tony Lindgren
  -- strict thread matches above, loose matches on Subject: below --
2008-08-07  8:43 [PATCH 1/4] 34XX: PM: Workaround to check wether any fck is active before entering sleep Kalle Jokiniemi
2008-08-07  8:43 ` [PATCH 2/4] 34XX: PM: Workaround for taking care of gpio clocks Kalle Jokiniemi
2008-08-07  8:43   ` [PATCH 3/4] Added sleep support to UART Kalle Jokiniemi
2008-08-06 13:01 Rajendra Nayak
2008-06-30  8:50 [PATCH 0/6] 34XX: PM: Workarounds to get omap3 to retention 4th Högander Jouni
2008-08-15  6:18 ` [PATCH 3/4] Added sleep support to UART Jouni Hogander

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox