Skip to contentSkip to conversation

ARM: OMAP2+: PRCM cleanup series for 3.17

PATCH New Tero Kristo 2 participants 12 messages Jul 4, 2014 – Jul 17, 2014

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

cover ARM: OMAP2+: PRCM cleanup series for 3.17

Hi,

Here's a small PRCM cleanup series against 3.16-rc1, meant for 3.17 if at all possible. Basically some cleanup to remove the direct CM/PRM register accesses outside PRCM drivers. This set is touching the OMAP2/ OMAP3 code only. This series is part of the ongoing work to make PRCM a separate driver.

Testing done:
- omap2430-sdp : boot
- omap3-beagle : boot, suspend/resume (ret), suspend/resume (off)

Working branch:
- tree: https://github.com/t-kristo/linux-pm.git
- branch: for-v3.17/cm-prm-cleanup

-Tero

#1 lore raw

PATCH 1/10 ARM: OMAP3: PRM: move prcm wakeup helper to prm driver

Done in preparation to make the prm an individual driver.

---
 arch/arm/mach-omap2/pm34xx.c  |   66 +++++++----------------------------------
 arch/arm/mach-omap2/prm3xxx.c |   53 +++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/prm3xxx.h |    1 +
 3 files changed, 64 insertions(+), 56 deletions(-)
arch/arm/mach-omap2/pm34xx.c +10 -56
index 507d8ee..74d03f2 100644
@@ -133,60 +133,13 @@ static void omap3_save_secure_ram_context(void)
 	}
 }
 
-/*
- * PRCM Interrupt Handler Helper Function
- *
- * The purpose of this function is to clear any wake-up events latched
- * in the PRCM PM_WKST_x registers. It is possible that a wake-up event
- * may occur whilst attempting to clear a PM_WKST_x register and thus
- * set another bit in this register. A while loop is used to ensure
- * that any peripheral wake-up events occurring while attempting to
- * clear the PM_WKST_x are detected and cleared.
- */
-static int prcm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits)
-{
-	u32 wkst, fclk, iclk, clken;
-	u16 wkst_off = (regs == 3) ? OMAP3430ES2_PM_WKST3 : PM_WKST1;
-	u16 fclk_off = (regs == 3) ? OMAP3430ES2_CM_FCLKEN3 : CM_FCLKEN1;
-	u16 iclk_off = (regs == 3) ? CM_ICLKEN3 : CM_ICLKEN1;
-	u16 grpsel_off = (regs == 3) ?
-		OMAP3430ES2_PM_MPUGRPSEL3 : OMAP3430_PM_MPUGRPSEL;
-	int c = 0;
-
-	wkst = omap2_prm_read_mod_reg(module, wkst_off);
-	wkst &= omap2_prm_read_mod_reg(module, grpsel_off);
-	wkst &= ~ignore_bits;
-	if (wkst) {
-		iclk = omap2_cm_read_mod_reg(module, iclk_off);
-		fclk = omap2_cm_read_mod_reg(module, fclk_off);
-		while (wkst) {
-			clken = wkst;
-			omap2_cm_set_mod_reg_bits(clken, module, iclk_off);
-			/*
-			 * For USBHOST, we don't know whether HOST1 or
-			 * HOST2 woke us up, so enable both f-clocks
-			 */
-			if (module == OMAP3430ES2_USBHOST_MOD)
-				clken |= 1 << OMAP3430ES2_EN_USBHOST2_SHIFT;
-			omap2_cm_set_mod_reg_bits(clken, module, fclk_off);
-			omap2_prm_write_mod_reg(wkst, module, wkst_off);
-			wkst = omap2_prm_read_mod_reg(module, wkst_off);
-			wkst &= ~ignore_bits;
-			c++;
-		}
-		omap2_cm_write_mod_reg(iclk, module, iclk_off);
-		omap2_cm_write_mod_reg(fclk, module, fclk_off);
-	}
-
-	return c;
-}
-
 static irqreturn_t _prcm_int_handle_io(int irq, void *unused)
 {
 	int c;
 
-	c = prcm_clear_mod_irqs(WKUP_MOD, 1,
-		~(OMAP3430_ST_IO_MASK | OMAP3430_ST_IO_CHAIN_MASK));
+	c = omap3xxx_prm_clear_mod_irqs(WKUP_MOD, 1,
+					~(OMAP3430_ST_IO_MASK |
+					  OMAP3430_ST_IO_CHAIN_MASK));
 
 	return c ? IRQ_HANDLED : IRQ_NONE;
 }
@@ -200,13 +153,14 @@ static irqreturn_t _prcm_int_handle_wakeup(int irq, void *unused)
 	 * these are handled in a separate handler to avoid acking
 	 * IO events before parsing in mux code
 	 */
-	c = prcm_clear_mod_irqs(WKUP_MOD, 1,
-		OMAP3430_ST_IO_MASK | OMAP3430_ST_IO_CHAIN_MASK);
-	c += prcm_clear_mod_irqs(CORE_MOD, 1, 0);
-	c += prcm_clear_mod_irqs(OMAP3430_PER_MOD, 1, 0);
+	c = omap3xxx_prm_clear_mod_irqs(WKUP_MOD, 1,
+					OMAP3430_ST_IO_MASK |
+					OMAP3430_ST_IO_CHAIN_MASK);
+	c += omap3xxx_prm_clear_mod_irqs(CORE_MOD, 1, 0);
+	c += omap3xxx_prm_clear_mod_irqs(OMAP3430_PER_MOD, 1, 0);
 	if (omap_rev() > OMAP3430_REV_ES1_0) {
-		c += prcm_clear_mod_irqs(CORE_MOD, 3, 0);
-		c += prcm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1, 0);
+		c += omap3xxx_prm_clear_mod_irqs(CORE_MOD, 3, 0);
+		c += omap3xxx_prm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1, 0);
 	}
 
 	return c ? IRQ_HANDLED : IRQ_NONE;
arch/arm/mach-omap2/prm3xxx.c +53 -0

65 lines not on this page · raw message

arch/arm/mach-omap2/prm3xxx.h +1 -0
index 1dacfc5..14a5fbc 100644
@@ -162,6 +162,7 @@ extern void omap3xxx_prm_dpll3_reset(void);
 
 extern int __init omap3xxx_prm_init(void);
 extern u32 omap3xxx_prm_get_reset_sources(void);
+int omap3xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits);
 
 #endif /* __ASSEMBLER */
 
Signature · 1 line
1.7.9.5
#2 lore raw

PATCH 2/10 ARM: OMAP3: PRM: move iva reset to PRM driver

In reply to Tero Kristo

This is a more proper isolation of the code. Done in preparation of making PRM an individual driver.

---
 arch/arm/mach-omap2/pm34xx.c  |   49 +----------------------------------------
 arch/arm/mach-omap2/prm3xxx.c |   45 +++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/prm3xxx.h |    1 +
 3 files changed, 47 insertions(+), 48 deletions(-)
arch/arm/mach-omap2/pm34xx.c +1 -48
index 74d03f2..6d02573 100644
@@ -353,53 +353,6 @@ restore:
 #define omap3_pm_suspend NULL
 #endif /* CONFIG_SUSPEND */
 
-
-/**
- * omap3_iva_idle(): ensure IVA is in idle so it can be put into
- *                   retention
- *
- * In cases where IVA2 is activated by bootcode, it may prevent
- * full-chip retention or off-mode because it is not idle.  This
- * function forces the IVA2 into idle state so it can go
- * into retention/off and thus allow full-chip retention/off.
- *
- **/
-static void __init omap3_iva_idle(void)
-{
-	/* ensure IVA2 clock is disabled */
-	omap2_cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
-
-	/* if no clock activity, nothing else to do */
-	if (!(omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSTST) &
-	      OMAP3430_CLKACTIVITY_IVA2_MASK))
-		return;
-
-	/* Reset IVA2 */
-	omap2_prm_write_mod_reg(OMAP3430_RST1_IVA2_MASK |
-			  OMAP3430_RST2_IVA2_MASK |
-			  OMAP3430_RST3_IVA2_MASK,
-			  OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
-
-	/* Enable IVA2 clock */
-	omap2_cm_write_mod_reg(OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_MASK,
-			 OMAP3430_IVA2_MOD, CM_FCLKEN);
-
-	/* Set IVA2 boot mode to 'idle' */
-	omap3_ctrl_set_iva_bootmode_idle();
-
-	/* Un-reset IVA2 */
-	omap2_prm_write_mod_reg(0, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
-
-	/* Disable IVA2 clock */
-	omap2_cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
-
-	/* Reset IVA2 */
-	omap2_prm_write_mod_reg(OMAP3430_RST1_IVA2_MASK |
-			  OMAP3430_RST2_IVA2_MASK |
-			  OMAP3430_RST3_IVA2_MASK,
-			  OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
-}
-
 static void __init omap3_d2d_idle(void)
 {
 	u16 mask, padconf;
@@ -503,7 +456,7 @@ static void __init prcm_setup_regs(void)
 	/*
 	 * We need to idle iva2_pwrdm even on am3703 with no iva2.
 	 */
-	omap3_iva_idle();
+	omap3xxx_prm_iva_idle();
 
 	omap3_d2d_idle();
 }
arch/arm/mach-omap2/prm3xxx.c +45 -0

57 lines not on this page · raw message

arch/arm/mach-omap2/prm3xxx.h +1 -0
index 14a5fbc..007ff59 100644
@@ -163,6 +163,7 @@ extern void omap3xxx_prm_dpll3_reset(void);
 extern int __init omap3xxx_prm_init(void);
 extern u32 omap3xxx_prm_get_reset_sources(void);
 int omap3xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits);
+void omap3xxx_prm_iva_idle(void);
 
 #endif /* __ASSEMBLER */
 
Signature · 1 line
1.7.9.5
#3 lore raw

PATCH 3/10 ARM: OMAP3: PRM: move modem reset to PRM driver

In reply to Tero Kristo

This is a more proper isolation of the code. Done in preparation of making PRM an individual driver.

---
 arch/arm/mach-omap2/pm34xx.c  |    5 +----
 arch/arm/mach-omap2/prm3xxx.c |   15 +++++++++++++++
 arch/arm/mach-omap2/prm3xxx.h |    1 +
 3 files changed, 17 insertions(+), 4 deletions(-)
arch/arm/mach-omap2/pm34xx.c +1 -4
index 6d02573..acb895d 100644
@@ -371,10 +371,7 @@ static void __init omap3_d2d_idle(void)
 	omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_IDLEACK);
 
 	/* reset modem */
-	omap2_prm_write_mod_reg(OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RSTPWRON_MASK |
-			  OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RST_MASK,
-			  CORE_MOD, OMAP2_RM_RSTCTRL);
-	omap2_prm_write_mod_reg(0, CORE_MOD, OMAP2_RM_RSTCTRL);
+	omap3_prm_reset_modem();
 }
 
 static void __init prcm_setup_regs(void)
arch/arm/mach-omap2/prm3xxx.c +15 -0
index a575b69..e46ff71 100644
@@ -260,6 +260,21 @@ int omap3xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits)
 }
 
 /**
+ * omap3_prm_reset_modem - toggle reset signal for modem
+ *
+ * Toggles the reset signal to modem IP block. Required to allow
+ * OMAP3430 without stacked modem to idle properly.
+ */
+void __init omap3_prm_reset_modem(void)
+{
+	omap2_prm_write_mod_reg(
+		OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RSTPWRON_MASK |
+		OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RST_MASK,
+				CORE_MOD, OMAP2_RM_RSTCTRL);
+	omap2_prm_write_mod_reg(0, CORE_MOD, OMAP2_RM_RSTCTRL);
+}
+
+/**
  * omap3xxx_prm_reconfigure_io_chain - clear latches and reconfigure I/O chain
  *
  * Clear any previously-latched I/O wakeup events and ensure that the
arch/arm/mach-omap2/prm3xxx.h +1 -0
index 007ff59..21eb1d5 100644
@@ -164,6 +164,7 @@ extern int __init omap3xxx_prm_init(void);
 extern u32 omap3xxx_prm_get_reset_sources(void);
 int omap3xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits);
 void omap3xxx_prm_iva_idle(void);
+void omap3_prm_reset_modem(void);
 
 #endif /* __ASSEMBLER */
 
Signature · 1 line
1.7.9.5
#4 lore raw

PATCH 4/10 ARM: OMAP3: PRM: add API for checking and clearing cold reset status

In reply to Tero Kristo

This isolates the PRM register access within the PRM driver.

---
 arch/arm/mach-omap2/control.c |    6 +-----
 arch/arm/mach-omap2/prm3xxx.c |   20 ++++++++++++++++++++
 arch/arm/mach-omap2/prm3xxx.h |    1 +
 3 files changed, 22 insertions(+), 5 deletions(-)
arch/arm/mach-omap2/control.c +1 -5
index 751f354..f8eb3e4 100644
@@ -282,13 +282,9 @@ void omap3_clear_scratchpad_contents(void)
 	void __iomem *v_addr;
 	u32 offset = 0;
 	v_addr = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD_ROM);
-	if (omap2_prm_read_mod_reg(OMAP3430_GR_MOD, OMAP3_PRM_RSTST_OFFSET) &
-	    OMAP3430_GLOBAL_COLD_RST_MASK) {
+	if (omap3xxx_prm_clear_global_cold_reset()) {
 		for ( ; offset <= max_offset; offset += 0x4)
 			writel_relaxed(0x0, (v_addr + offset));
-		omap2_prm_set_mod_reg_bits(OMAP3430_GLOBAL_COLD_RST_MASK,
-					   OMAP3430_GR_MOD,
-					   OMAP3_PRM_RSTST_OFFSET);
 	}
 }
 
arch/arm/mach-omap2/prm3xxx.c +20 -0
index e46ff71..4733c28 100644
@@ -389,6 +389,26 @@ void omap3xxx_prm_iva_idle(void)
 				OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
 }
 
+/**
+ * omap3xxx_prm_clear_global_cold_reset - checks the global cold reset status
+ *					  and clears it if asserted
+ *
+ * Checks if cold-reset has occurred and clears the status bit if yes. Returns
+ * 1 if cold-reset has occurred, 0 otherwise.
+ */
+int omap3xxx_prm_clear_global_cold_reset(void)
+{
+	if (omap2_prm_read_mod_reg(OMAP3430_GR_MOD, OMAP3_PRM_RSTST_OFFSET) &
+	    OMAP3430_GLOBAL_COLD_RST_MASK) {
+		omap2_prm_set_mod_reg_bits(OMAP3430_GLOBAL_COLD_RST_MASK,
+					   OMAP3430_GR_MOD,
+					   OMAP3_PRM_RSTST_OFFSET);
+		return 1;
+	}
+
+	return 0;
+}
+
 /* Powerdomain low-level functions */
 
 static int omap3_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
arch/arm/mach-omap2/prm3xxx.h +1 -0
index 21eb1d5..7548ae0 100644
@@ -165,6 +165,7 @@ extern u32 omap3xxx_prm_get_reset_sources(void);
 int omap3xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits);
 void omap3xxx_prm_iva_idle(void);
 void omap3_prm_reset_modem(void);
+int omap3xxx_prm_clear_global_cold_reset(void);
 
 #endif /* __ASSEMBLER */
 
Signature · 1 line
1.7.9.5
#5 lore raw

PATCH 5/10 ARM: OMAP3: PRM: add API for saving PRM scratchpad contents

In reply to Tero Kristo

This isolates the PRM register access within the PRM driver.

---
 arch/arm/mach-omap2/control.c |   11 ++---------
 arch/arm/mach-omap2/prm3xxx.c |    9 +++++++++
 arch/arm/mach-omap2/prm3xxx.h |    1 +
 3 files changed, 12 insertions(+), 9 deletions(-)
arch/arm/mach-omap2/control.c +2 -9
index f8eb3e4..8308094 100644
@@ -44,8 +44,7 @@ struct omap3_scratchpad {
 };
 
 struct omap3_scratchpad_prcm_block {
-	u32 prm_clksrc_ctrl;
-	u32 prm_clksel;
+	u32 prm_contents[2];
 	u32 cm_contents[11];
 	u32 prcm_block_size;
 };
@@ -327,13 +326,7 @@ void omap3_save_scratchpad_contents(void)
 	scratchpad_contents.sdrc_block_offset = 0x64;
 
 	/* Populate the PRCM block contents */
-	prcm_block_contents.prm_clksrc_ctrl =
-		omap2_prm_read_mod_reg(OMAP3430_GR_MOD,
-				       OMAP3_PRM_CLKSRC_CTRL_OFFSET);
-	prcm_block_contents.prm_clksel =
-		omap2_prm_read_mod_reg(OMAP3430_CCR_MOD,
-				       OMAP3_PRM_CLKSEL_OFFSET);
-
+	omap3_prm_save_scratchpad_contents(prcm_block_contents.prm_contents);
 	omap3_cm_save_scratchpad_contents(prcm_block_contents.cm_contents);
 
 	prcm_block_contents.prcm_block_size = 0x0;
arch/arm/mach-omap2/prm3xxx.c +9 -0
index 4733c28..4d93b84 100644
@@ -409,6 +409,15 @@ int omap3xxx_prm_clear_global_cold_reset(void)
 	return 0;
 }
 
+void omap3_prm_save_scratchpad_contents(u32 *ptr)
+{
+	*ptr++ = omap2_prm_read_mod_reg(OMAP3430_GR_MOD,
+					OMAP3_PRM_CLKSRC_CTRL_OFFSET);
+
+	*ptr++ = omap2_prm_read_mod_reg(OMAP3430_GR_MOD,
+					OMAP3_PRM_CLKSEL_OFFSET);
+}
+
 /* Powerdomain low-level functions */
 
 static int omap3_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
arch/arm/mach-omap2/prm3xxx.h +1 -0
index 7548ae0..c5f9cba 100644
@@ -166,6 +166,7 @@ int omap3xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits);
 void omap3xxx_prm_iva_idle(void);
 void omap3_prm_reset_modem(void);
 int omap3xxx_prm_clear_global_cold_reset(void);
+void omap3_prm_save_scratchpad_contents(u32 *ptr);
 
 #endif /* __ASSEMBLER */
 
Signature · 1 line
1.7.9.5
#6 lore raw

PATCH 6/10 ARM: OMAP24xx: PRM: add API for clearing wakeup status bits

In reply to Tero Kristo

This helps to isolate the PRM into its own driver.

---
 arch/arm/mach-omap2/pm24xx.c  |   31 +++++++++++++------------------
 arch/arm/mach-omap2/prm2xxx.c |   18 ++++++++++++++++++
 arch/arm/mach-omap2/prm2xxx.h |    1 +
 3 files changed, 32 insertions(+), 18 deletions(-)
arch/arm/mach-omap2/pm24xx.c +13 -18
index a5ea988..d76694b 100644
@@ -75,9 +75,9 @@ static int omap2_enter_full_retention(void)
 
 	/* Clear old wake-up events */
 	/* REVISIT: These write to reserved bits? */
-	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
-	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
-	omap2_prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
+	omap2xxx_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0);
+	omap2xxx_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0);
+	omap2xxx_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, ~0);
 
 	pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET);
 	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
@@ -104,23 +104,18 @@ no_sleep:
 	clk_enable(osc_ck);
 
 	/* clear CORE wake-up events */
-	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
-	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
+	omap2xxx_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0);
+	omap2xxx_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0);
 
 	/* wakeup domain events - bit 1: GPT1, bit5 GPIO */
-	omap2_prm_clear_mod_reg_bits(0x4 | 0x1, WKUP_MOD, PM_WKST);
+	omap2xxx_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, 0x4 | 0x1);
 
 	/* MPU domain wake events */
-	l = omap2_prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
-	if (l & 0x01)
-		omap2_prm_write_mod_reg(0x01, OCP_MOD,
-				  OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
-	if (l & 0x20)
-		omap2_prm_write_mod_reg(0x20, OCP_MOD,
-				  OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
+	omap2xxx_prm_clear_mod_irqs(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET,
+				    0x1);
 
-	/* Mask future PRCM-to-MPU interrupts */
-	omap2_prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
+	omap2xxx_prm_clear_mod_irqs(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET,
+				    0x20);
 
 	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
 	pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_ON);
@@ -148,9 +143,9 @@ static void omap2_enter_mpu_retention(void)
 	 * it is in retention mode. */
 	if (omap2_allow_mpu_retention()) {
 		/* REVISIT: These write to reserved bits? */
-		omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
-		omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
-		omap2_prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
+		omap2xxx_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0);
+		omap2xxx_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0);
+		omap2xxx_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, ~0);
 
 		/* Try to enter MPU retention */
 		pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
arch/arm/mach-omap2/prm2xxx.c +18 -0
index a3a3cca..8695805 100644
@@ -114,6 +114,24 @@ void omap2xxx_prm_dpll_reset(void)
 	omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTCTRL);
 }
 
+/**
+ * omap2xxx_prm_clear_mod_irqs - clear wakeup status bits for a module
+ * @module: PRM module to clear wakeups from
+ * @regs: register offset to clear
+ * @wkst_mask: wakeup status mask to clear
+ *
+ * Clears wakeup status bits for a given module, so that the device can
+ * re-enter idle.
+ */
+void omap2xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 wkst_mask)
+{
+	u32 wkst;
+
+	wkst = omap2_prm_read_mod_reg(module, regs);
+	wkst &= wkst_mask;
+	omap2_prm_write_mod_reg(wkst, module, regs);
+}
+
 int omap2xxx_clkdm_sleep(struct clockdomain *clkdm)
 {
 	omap2_prm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
arch/arm/mach-omap2/prm2xxx.h +1 -0
index d2cb636..d734141 100644
@@ -125,6 +125,7 @@ extern int omap2xxx_clkdm_sleep(struct clockdomain *clkdm);
 extern int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm);
 
 extern void omap2xxx_prm_dpll_reset(void);
+void omap2xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 wkst_mask);
 
 extern int __init omap2xxx_prm_init(void);
 
Signature · 1 line
1.7.9.5
#7 lore raw

PATCH 7/10 ARM: OMAP3: PRM: move PRM init code from PM core to the driver

In reply to Tero Kristo

Helps to isolate the PRM driver.

---
 arch/arm/mach-omap2/pm34xx.c  |   71 +-------------------------------
 arch/arm/mach-omap2/prm3xxx.c |   90 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/prm3xxx.h |    1 +
 3 files changed, 92 insertions(+), 70 deletions(-)
arch/arm/mach-omap2/pm34xx.c +1 -70
index acb895d..3ea04ac 100644
@@ -376,79 +376,10 @@ static void __init omap3_d2d_idle(void)
 
 static void __init prcm_setup_regs(void)
 {
-	u32 omap3630_en_uart4_mask = cpu_is_omap3630() ?
-					OMAP3630_EN_UART4_MASK : 0;
-	u32 omap3630_grpsel_uart4_mask = cpu_is_omap3630() ?
-					OMAP3630_GRPSEL_UART4_MASK : 0;
-
 	/* XXX This should be handled by hwmod code or SCM init code */
 	omap_ctrl_writel(OMAP3430_AUTOIDLE_MASK, OMAP2_CONTROL_SYSCONFIG);
 
-	/*
-	 * Enable control of expternal oscillator through
-	 * sys_clkreq. In the long run clock framework should
-	 * take care of this.
-	 */
-	omap2_prm_rmw_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK,
-			     1 << OMAP_AUTOEXTCLKMODE_SHIFT,
-			     OMAP3430_GR_MOD,
-			     OMAP3_PRM_CLKSRC_CTRL_OFFSET);
-
-	/* setup wakup source */
-	omap2_prm_write_mod_reg(OMAP3430_EN_IO_MASK | OMAP3430_EN_GPIO1_MASK |
-			  OMAP3430_EN_GPT1_MASK | OMAP3430_EN_GPT12_MASK,
-			  WKUP_MOD, PM_WKEN);
-	/* No need to write EN_IO, that is always enabled */
-	omap2_prm_write_mod_reg(OMAP3430_GRPSEL_GPIO1_MASK |
-			  OMAP3430_GRPSEL_GPT1_MASK |
-			  OMAP3430_GRPSEL_GPT12_MASK,
-			  WKUP_MOD, OMAP3430_PM_MPUGRPSEL);
-
-	/* Enable PM_WKEN to support DSS LPR */
-	omap2_prm_write_mod_reg(OMAP3430_PM_WKEN_DSS_EN_DSS_MASK,
-				OMAP3430_DSS_MOD, PM_WKEN);
-
-	/* Enable wakeups in PER */
-	omap2_prm_write_mod_reg(omap3630_en_uart4_mask |
-			  OMAP3430_EN_GPIO2_MASK | OMAP3430_EN_GPIO3_MASK |
-			  OMAP3430_EN_GPIO4_MASK | OMAP3430_EN_GPIO5_MASK |
-			  OMAP3430_EN_GPIO6_MASK | OMAP3430_EN_UART3_MASK |
-			  OMAP3430_EN_MCBSP2_MASK | OMAP3430_EN_MCBSP3_MASK |
-			  OMAP3430_EN_MCBSP4_MASK,
-			  OMAP3430_PER_MOD, PM_WKEN);
-	/* and allow them to wake up MPU */
-	omap2_prm_write_mod_reg(omap3630_grpsel_uart4_mask |
-			  OMAP3430_GRPSEL_GPIO2_MASK |
-			  OMAP3430_GRPSEL_GPIO3_MASK |
-			  OMAP3430_GRPSEL_GPIO4_MASK |
-			  OMAP3430_GRPSEL_GPIO5_MASK |
-			  OMAP3430_GRPSEL_GPIO6_MASK |
-			  OMAP3430_GRPSEL_UART3_MASK |
-			  OMAP3430_GRPSEL_MCBSP2_MASK |
-			  OMAP3430_GRPSEL_MCBSP3_MASK |
-			  OMAP3430_GRPSEL_MCBSP4_MASK,
-			  OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL);
-
-	/* Don't attach IVA interrupts */
-	if (omap3_has_iva()) {
-		omap2_prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
-		omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
-		omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
-		omap2_prm_write_mod_reg(0, OMAP3430_PER_MOD,
-					OMAP3430_PM_IVAGRPSEL);
-	}
-
-	/* Clear any pending 'reset' flags */
-	omap2_prm_write_mod_reg(0xffffffff, MPU_MOD, OMAP2_RM_RSTST);
-	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP2_RM_RSTST);
-	omap2_prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, OMAP2_RM_RSTST);
-	omap2_prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, OMAP2_RM_RSTST);
-	omap2_prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, OMAP2_RM_RSTST);
-	omap2_prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, OMAP2_RM_RSTST);
-	omap2_prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, OMAP2_RM_RSTST);
-
-	/* Clear any pending PRCM interrupts */
-	omap2_prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+	omap3_prm_init_pm(cpu_is_omap3630(), omap3_has_iva());
 
 	/*
 	 * We need to idle iva2_pwrdm even on am3703 with no iva2.
arch/arm/mach-omap2/prm3xxx.c +90 -0

96 lines not on this page · raw message

arch/arm/mach-omap2/prm3xxx.h +1 -0
index c5f9cba..bc37d42 100644
@@ -167,6 +167,7 @@ void omap3xxx_prm_iva_idle(void);
 void omap3_prm_reset_modem(void);
 int omap3xxx_prm_clear_global_cold_reset(void);
 void omap3_prm_save_scratchpad_contents(u32 *ptr);
+void omap3_prm_init_pm(bool has_uart4, bool has_iva);
 
 #endif /* __ASSEMBLER */
 
Signature · 1 line
1.7.9.5
#8 lore raw

PATCH 8/10 ARM: OMAP3: control: add API for setting up the modem pads

In reply to Tero Kristo

This patch moves the functionality from PM core to control driver.

---
 arch/arm/mach-omap2/control.c |   26 ++++++++++++++++++++++++++
 arch/arm/mach-omap2/control.h |    1 +
 arch/arm/mach-omap2/pm34xx.c  |   15 +--------------
 3 files changed, 28 insertions(+), 14 deletions(-)
arch/arm/mach-omap2/control.c +26 -0
index 8308094..f432ffc 100644
@@ -569,4 +569,30 @@ void omap3_ctrl_set_iva_bootmode_idle(void)
 	omap_ctrl_writel(OMAP3_IVA2_BOOTMOD_IDLE,
 			 OMAP343X_CONTROL_IVA2_BOOTMOD);
 }
+
+/**
+ * omap3_ctrl_setup_d2d_padconf - setup stacked modem pads for idle
+ *
+ * Sets up the pads controlling the stacked modem in such way that the
+ * device can enter idle.
+ */
+void omap3_ctrl_setup_d2d_padconf(void)
+{
+	u16 mask, padconf;
+
+	/*
+	 * In a stand alone OMAP3430 where there is not a stacked
+	 * modem for the D2D Idle Ack and D2D MStandby must be pulled
+	 * high. S CONTROL_PADCONF_SAD2D_IDLEACK and
+	 * CONTROL_PADCONF_SAD2D_MSTDBY to have a pull up.
+	 */
+	mask = (1 << 4) | (1 << 3); /* pull-up, enabled */
+	padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_MSTANDBY);
+	padconf |= mask;
+	omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_MSTANDBY);
+
+	padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_IDLEACK);
+	padconf |= mask;
+	omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_IDLEACK);
+}
 #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
arch/arm/mach-omap2/control.h +1 -0
index da05480..fc00158 100644
@@ -428,6 +428,7 @@ extern void omap_ctrl_write_dsp_boot_mode(u8 bootmode);
 extern void omap3630_ctrl_disable_rta(void);
 extern int omap3_ctrl_save_padconf(void);
 extern void omap3_ctrl_set_iva_bootmode_idle(void);
+void omap3_ctrl_setup_d2d_padconf(void);
 extern void omap2_set_globals_control(void __iomem *ctrl,
 				      void __iomem *ctrl_pad);
 #else
arch/arm/mach-omap2/pm34xx.c +1 -14
index 3ea04ac..126f3ec 100644
@@ -355,20 +355,7 @@ restore:
 
 static void __init omap3_d2d_idle(void)
 {
-	u16 mask, padconf;
-
-	/* In a stand alone OMAP3430 where there is not a stacked
-	 * modem for the D2D Idle Ack and D2D MStandby must be pulled
-	 * high. S CONTROL_PADCONF_SAD2D_IDLEACK and
-	 * CONTROL_PADCONF_SAD2D_MSTDBY to have a pull up. */
-	mask = (1 << 4) | (1 << 3); /* pull-up, enabled */
-	padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_MSTANDBY);
-	padconf |= mask;
-	omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_MSTANDBY);
-
-	padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_IDLEACK);
-	padconf |= mask;
-	omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_IDLEACK);
+	omap3_ctrl_setup_d2d_padconf();
 
 	/* reset modem */
 	omap3_prm_reset_modem();
Signature · 1 line
1.7.9.5
#9 lore raw

PATCH 9/10 ARM: OMAP3: PRM: move modem reset and iva2 idle to PRM driver

In reply to Tero Kristo

Done in preparation to move PRM into its own driver.

---
 arch/arm/mach-omap2/pm34xx.c  |   15 ---------------
 arch/arm/mach-omap2/prm3xxx.c |    7 +++++++
 2 files changed, 7 insertions(+), 15 deletions(-)
arch/arm/mach-omap2/pm34xx.c +0 -15
index 126f3ec..9410b4a 100644
@@ -353,27 +353,12 @@ restore:
 #define omap3_pm_suspend NULL
 #endif /* CONFIG_SUSPEND */
 
-static void __init omap3_d2d_idle(void)
-{
-	omap3_ctrl_setup_d2d_padconf();
-
-	/* reset modem */
-	omap3_prm_reset_modem();
-}
-
 static void __init prcm_setup_regs(void)
 {
 	/* XXX This should be handled by hwmod code or SCM init code */
 	omap_ctrl_writel(OMAP3430_AUTOIDLE_MASK, OMAP2_CONTROL_SYSCONFIG);
 
 	omap3_prm_init_pm(cpu_is_omap3630(), omap3_has_iva());
-
-	/*
-	 * We need to idle iva2_pwrdm even on am3703 with no iva2.
-	 */
-	omap3xxx_prm_iva_idle();
-
-	omap3_d2d_idle();
 }
 
 void omap3_pm_off_mode_enable(int enable)
arch/arm/mach-omap2/prm3xxx.c +7 -0
index 48218a4..75dfe8e 100644
@@ -362,6 +362,13 @@ void __init omap3_prm_init_pm(bool has_uart4, bool has_iva)
 
 	/* Clear any pending PRCM interrupts */
 	omap2_prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+
+	/* We need to idle iva2_pwrdm even on am3703 with no iva2. */
+	omap3xxx_prm_iva_idle();
+
+	omap3_ctrl_setup_d2d_padconf();
+
+	omap3_prm_reset_modem();
 }
 
 /**
Signature · 1 line
1.7.9.5
#10 lore raw

PATCH 10/10 ARM: OMAP3: control: isolate control module init to its own function

In reply to Tero Kristo

Control module related PM initializations are now moved within control module driver. Done in preparation to isolate the code to its own driver.

---
 arch/arm/mach-omap2/control.c |   19 +++++++++++++++++--
 arch/arm/mach-omap2/control.h |    3 +--
 arch/arm/mach-omap2/pm34xx.c  |    3 +--
 arch/arm/mach-omap2/prm3xxx.c |    6 ------
 4 files changed, 19 insertions(+), 12 deletions(-)
arch/arm/mach-omap2/control.c +17 -2
index f432ffc..f4796c0 100644
@@ -564,7 +564,7 @@ int omap3_ctrl_save_padconf(void)
  * Sets the bootmode for IVA2 to idle. This is needed by the PM code to
  * force disable IVA2 so that it does not prevent any low-power states.
  */
-void omap3_ctrl_set_iva_bootmode_idle(void)
+static void __init omap3_ctrl_set_iva_bootmode_idle(void)
 {
 	omap_ctrl_writel(OMAP3_IVA2_BOOTMOD_IDLE,
 			 OMAP343X_CONTROL_IVA2_BOOTMOD);
@@ -576,7 +576,7 @@ void omap3_ctrl_set_iva_bootmode_idle(void)
  * Sets up the pads controlling the stacked modem in such way that the
  * device can enter idle.
  */
-void omap3_ctrl_setup_d2d_padconf(void)
+static void __init omap3_ctrl_setup_d2d_padconf(void)
 {
 	u16 mask, padconf;
 
@@ -595,4 +595,19 @@ void omap3_ctrl_setup_d2d_padconf(void)
 	padconf |= mask;
 	omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_IDLEACK);
 }
+
+/**
+ * omap3_ctrl_init - does static initializations for control module
+ *
+ * Initializes system control module. This sets up the sysconfig autoidle,
+ * and sets up modem and iva2 so that they can be idled properly.
+ */
+void __init omap3_ctrl_init(void)
+{
+	omap_ctrl_writel(OMAP3430_AUTOIDLE_MASK, OMAP2_CONTROL_SYSCONFIG);
+
+	omap3_ctrl_set_iva_bootmode_idle();
+
+	omap3_ctrl_setup_d2d_padconf();
+}
 #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
arch/arm/mach-omap2/control.h +1 -2
index fc00158..ccbd70c 100644
@@ -427,8 +427,7 @@ extern void omap_ctrl_write_dsp_boot_addr(u32 bootaddr);
 extern void omap_ctrl_write_dsp_boot_mode(u8 bootmode);
 extern void omap3630_ctrl_disable_rta(void);
 extern int omap3_ctrl_save_padconf(void);
-extern void omap3_ctrl_set_iva_bootmode_idle(void);
-void omap3_ctrl_setup_d2d_padconf(void);
+void omap3_ctrl_init(void);
 extern void omap2_set_globals_control(void __iomem *ctrl,
 				      void __iomem *ctrl_pad);
 #else
arch/arm/mach-omap2/pm34xx.c +1 -2
index 9410b4a..3f80929 100644
@@ -355,8 +355,7 @@ restore:
 
 static void __init prcm_setup_regs(void)
 {
-	/* XXX This should be handled by hwmod code or SCM init code */
-	omap_ctrl_writel(OMAP3430_AUTOIDLE_MASK, OMAP2_CONTROL_SYSCONFIG);
+	omap3_ctrl_init();
 
 	omap3_prm_init_pm(cpu_is_omap3630(), omap3_has_iva());
 }
arch/arm/mach-omap2/prm3xxx.c +0 -6
index 75dfe8e..2458be6 100644
@@ -28,7 +28,6 @@
 #include "prm-regbits-34xx.h"
 #include "cm3xxx.h"
 #include "cm-regbits-34xx.h"
-#include "control.h"
 
 static const struct omap_prcm_irq omap3_prcm_irqs[] = {
 	OMAP_PRCM_IRQ("wkup",	0,	0),
@@ -366,8 +365,6 @@ void __init omap3_prm_init_pm(bool has_uart4, bool has_iva)
 	/* We need to idle iva2_pwrdm even on am3703 with no iva2. */
 	omap3xxx_prm_iva_idle();
 
-	omap3_ctrl_setup_d2d_padconf();
-
 	omap3_prm_reset_modem();
 }
 
@@ -470,9 +467,6 @@ void omap3xxx_prm_iva_idle(void)
 	omap2_cm_write_mod_reg(OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_MASK,
 			       OMAP3430_IVA2_MOD, CM_FCLKEN);
 
-	/* Set IVA2 boot mode to 'idle' */
-	omap3_ctrl_set_iva_bootmode_idle();
-
 	/* Un-reset IVA2 */
 	omap2_prm_write_mod_reg(0, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
 
Signature · 1 line
1.7.9.5
maintainer
#11 lore raw

cover ARM: OMAP2+: PRCM cleanup series for 3.17

In reply to Tero Kristo
Quoted 8 lines · Tero Kristo

Hi,

Here's a small PRCM cleanup series against 3.16-rc1, meant for 3.17 if at all possible. Basically some cleanup to remove the direct CM/PRM register accesses outside PRCM drivers. This set is touching the OMAP2/ OMAP3 code only. This series is part of the ongoing work to make PRCM a separate driver.

Quoted 7 lines

Testing done:
- omap2430-sdp : boot
- omap3-beagle : boot, suspend/resume (ret), suspend/resume (off)

Working branch:
- tree: https://github.com/t-kristo/linux-pm.git
- branch: for-v3.17/cm-prm-cleanup

Great seems to work for me for my omap3 off-idle test cases, so pulling this into omap-for-v3.17/soc.

Regards,

Tony