Thread (2 messages) 2 messages, 2 authors, 2011-09-12
STALE5387d

[PATCH v4 09/11] OMAP2+: Serial: Use prepare and resume calls to gate uart clocks

From: Kevin Hilman <hidden>
Date: 2011-09-09 18:59:49
Also in: linux-omap, linux-serial

Possibly related (same subject, not in this thread)

"Govindraj.R" [off-list ref] writes:
Currently we are using uart prepare and resume calls to gate uart clocks
retaining the same method.

More details on reason to retain this design is provided here:
http://www.spinics.net/lists/linux-serial/msg04128.html
This type of thing can go after the '---' since it doesn't belong in the
permanent git history.
Since prepare and resume hooks are moved to driver itself we can just use
a single prepare and resume call. As in driver we traverse on number of uart
instance and handle it accordingly.
Some important functionality has been removed (and not documented.)
Namely, the current code checks the next power when deciding whether or
not to call prepare_idle, and vice versa for resume_idle.

It's quite possible that it is no longer needed with the runtime PM 
In 34xx uart can wakeup using module level PM_WKEN or IO PAD wakeup use
resume_call from prcm irq handler to wakeup uart, based on chk_wakeup_status
from io_pad or PM_WKST.
IMO, this patch should just replace the mulitple calls with a single
call, but still in the idle path.

Using the PRCM IRQ handler should be a separate patch with it's own
changelog.
Signed-off-by: Govindraj.R <redacted>
Also, moving these calls to the driver means that the driver cannot be
built as a module:

arch/arm/mach-omap2/built-in.o: In function `omap2_enter_full_retention':
/work/kernel/omap/pm/arch/arm/mach-omap2/pm24xx.c:141: undefined reference to `omap_uart_prepare_idle'
/work/kernel/omap/pm/arch/arm/mach-omap2/pm24xx.c:148: undefined reference to `omap_uart_resume_idle'
arch/arm/mach-omap2/built-in.o: In function `prcm_clear_mod_irqs':
/work/kernel/omap/pm/arch/arm/mach-omap2/pm34xx.c:213: undefined reference to `omap_uart_resume_idle'
arch/arm/mach-omap2/built-in.o: In function `omap_sram_idle':
/work/kernel/omap/pm/arch/arm/mach-omap2/pm34xx.c:390: undefined reference to `omap_uart_prepare_idle'
quoted hunk
---
 arch/arm/mach-omap2/pm24xx.c             |    8 +----
 arch/arm/mach-omap2/pm34xx.c             |   17 +++++-------
 arch/arm/plat-omap/include/plat/serial.h |    4 +-
 drivers/tty/serial/omap-serial.c         |   40 ++++++++++++++++++++++++++++++
 4 files changed, 51 insertions(+), 18 deletions(-)
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 39f26af..91eacef 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -138,18 +138,14 @@ static void omap2_enter_full_retention(void)
 		if (!console_trylock())
 			goto no_sleep;
 
-	omap_uart_prepare_idle(0);
-	omap_uart_prepare_idle(1);
-	omap_uart_prepare_idle(2);
+	omap_uart_prepare_idle();
 
 	/* 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));
 
-	omap_uart_resume_idle(2);
-	omap_uart_resume_idle(1);
-	omap_uart_resume_idle(0);
+	omap_uart_resume_idle();
 
 	if (!is_suspending())
 		console_unlock();
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 9f3bf2c..26ddd56 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -210,6 +210,7 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs)
 
 	wkst = omap2_prm_read_mod_reg(module, wkst_off);
 	wkst &= omap2_prm_read_mod_reg(module, grpsel_off);
+	c += omap_uart_resume_idle();
 	if (wkst) {
 		iclk = omap2_cm_read_mod_reg(module, iclk_off);
 		fclk = omap2_cm_read_mod_reg(module, fclk_off);
@@ -380,17 +381,19 @@ void omap_sram_idle(void)
 	}
 
 	/* Block console output in case it is on one of the OMAP UARTs */
-	if (!is_suspending())
+	if (!is_suspending()) {
 		if (per_next_state < PWRDM_POWER_ON ||
-		    core_next_state < PWRDM_POWER_ON)
+		    core_next_state < PWRDM_POWER_ON) {
 			if (!console_trylock())
 				goto console_still_active;
+			else
+				omap_uart_prepare_idle();
+		}
+	}
 
 	/* PER */
 	if (per_next_state < PWRDM_POWER_ON) {
 		per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
-		omap_uart_prepare_idle(2);
-		omap_uart_prepare_idle(3);
 		omap2_gpio_prepare_for_idle(per_going_off);
 		if (per_next_state == PWRDM_POWER_OFF)
 				omap3_per_save_context();
@@ -398,8 +401,6 @@ void omap_sram_idle(void)
 
 	/* CORE */
 	if (core_next_state < PWRDM_POWER_ON) {
-		omap_uart_prepare_idle(0);
-		omap_uart_prepare_idle(1);
 		if (core_next_state == PWRDM_POWER_OFF) {
 			omap3_core_save_context();
 			omap3_cm_save_context();
@@ -446,8 +447,6 @@ void omap_sram_idle(void)
 			omap3_sram_restore_context();
 			omap2_sms_restore_context();
 		}
-		omap_uart_resume_idle(0);
-		omap_uart_resume_idle(1);
 		if (core_next_state == PWRDM_POWER_OFF)
 			omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK,
 					       OMAP3430_GR_MOD,
@@ -461,8 +460,6 @@ void omap_sram_idle(void)
 		omap2_gpio_resume_after_idle();
 		if (per_prev_state == PWRDM_POWER_OFF)
 			omap3_per_restore_context();
-		omap_uart_resume_idle(2);
-		omap_uart_resume_idle(3);
 	}
 
 	if (!is_suspending())
diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h
index bfd73b7..5b8c8f2 100644
--- a/arch/arm/plat-omap/include/plat/serial.h
+++ b/arch/arm/plat-omap/include/plat/serial.h
@@ -109,8 +109,8 @@ struct omap_board_data;
 
 extern void omap_serial_init(void);
 extern void omap_serial_init_port(struct omap_board_data *bdata);
-extern void omap_uart_prepare_idle(int num);
-extern void omap_uart_resume_idle(int num);
+extern void omap_uart_prepare_idle(void);
+extern int omap_uart_resume_idle(void);
 #endif
 
 #endif
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 96fc860..05c2f52 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -54,6 +54,46 @@ static void serial_omap_rx_timeout(unsigned long uart_no);
 static int serial_omap_start_rxdma(struct uart_omap_port *up);
 static void omap_uart_mdr1_errataset(struct uart_omap_port *up, u8 mdr1);
 
+int omap_uart_resume_idle()
+{
+	struct uart_omap_port *up;
+	int i, ret = 0;
+
+	for (i = 0; i < OMAP_MAX_HSUART_PORTS; i++) {
+		up = ui[i];
+		if (!up)
+			continue;
+
+		if (!up->clocked && up->chk_wakeup(up->pdev)) {
+			pm_runtime_get_sync(&up->pdev->dev);
+			up->clocked = 1;
+			ret++;
+		}
+	}
+
+	return ret;
+}
+
+void omap_uart_prepare_idle()
+{
+	struct uart_omap_port *up;
+	int i;
+
+	for (i = 0; i < OMAP_MAX_HSUART_PORTS; i++) {
+		up = ui[i];
+		if (!up)
+			continue;
+
+		if (up->clocked &&
+				jiffies_to_msecs(jiffies - up->port_activity)
+					> 3000) {
What is this check for?
+			pm_runtime_mark_last_busy(&up->pdev->dev);
+			pm_runtime_put_autosuspend(&up->pdev->dev);
+			up->clocked = 0;
+		}
+	}
+}
+
 static inline unsigned int serial_in(struct uart_omap_port *up, int offset)
 {
 	offset <<= up->port.regshift;
Kevin
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help