commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=0df67eed2f9c6841a718313c5ea4e5361a701114
branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/2012R1

Move DMC and CGU init functions out of clock set up code.
Call DMC init functions to enter and exit DDR self refresh mode.
Wait till CGU PLL is locked after wake up and exit DDR self refresh mode.
Make asessembly function enter_deepsleep comply with C funtion ABI in
order to call other C functions.
Switch kernel stack by register EX_SCRATCH_REG.

Signed-off-by: Sonic Zhang <[email protected]>
---
 arch/blackfin/include/asm/context.S     |    9 +++
 arch/blackfin/include/asm/mem_init.h    |   96 ++++++++++++++++++++++++-------
 arch/blackfin/mach-bf609/hibernate.S    |   41 +++++++++----
 arch/blackfin/mach-bf609/pm.c           |   48 +++------------
 arch/blackfin/mach-common/clocks-init.c |   83 +++++++++------------------
 arch/blackfin/mach-common/entry.S       |    7 --
 6 files changed, 149 insertions(+), 135 deletions(-)

diff --git a/arch/blackfin/include/asm/context.S b/arch/blackfin/include/asm/context.S
index 1f90603..507e7aa 100644
--- a/arch/blackfin/include/asm/context.S
+++ b/arch/blackfin/include/asm/context.S
@@ -396,3 +396,12 @@
 	call \func;
 #endif
 .endm
+
+#if defined(CONFIG_BFIN_SCRATCH_REG_RETN)
+# define EX_SCRATCH_REG RETN
+#elif defined(CONFIG_BFIN_SCRATCH_REG_RETE)
+# define EX_SCRATCH_REG RETE
+#else
+# define EX_SCRATCH_REG CYCLES
+#endif
+
diff --git a/arch/blackfin/include/asm/mem_init.h b/arch/blackfin/include/asm/mem_init.h
index 23144c7..f019e9b 100644
--- a/arch/blackfin/include/asm/mem_init.h
+++ b/arch/blackfin/include/asm/mem_init.h
@@ -6,6 +6,9 @@
  * Licensed under the GPL-2 or later.
  */
 
+#ifndef __MEM_INIT_H__
+#define __MEM_INIT_H__
+
 #if defined(EBIU_SDGCTL)
 #if defined(CONFIG_MEM_MT48LC16M16A2TG_75) || \
     defined(CONFIG_MEM_MT48LC64M4A2FB_7E) || \
@@ -329,21 +332,6 @@
 #define MSEL_MASK		0x7F00
 #define DF_MASK			0x1
 
-#define CGU_CTL_VAL ((CONFIG_VCO_MULT << 8) | CLKIN_HALF)
-#define CGU_DIV_VAL \
-	((CONFIG_CCLK_DIV   << CSEL_OFFSET)   | \
-	(CONFIG_SCLK_DIV << SYSSEL_OFFSET)   | \
-	(CONFIG_SCLK0_DIV  << S0SEL_OFFSET)  | \
-	(CONFIG_SCLK1_DIV  << S1SEL_OFFSET)  | \
-	(CONFIG_DCLK_DIV   << DSEL_OFFSET))
-
-#define CONFIG_BFIN_DCLK (((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT) / CONFIG_DCLK_DIV) / 1000000)
-#if ((CONFIG_BFIN_DCLK != 125) && \
-	(CONFIG_BFIN_DCLK != 133) && (CONFIG_BFIN_DCLK != 150) && \
-	(CONFIG_BFIN_DCLK != 166) && (CONFIG_BFIN_DCLK != 200) && \
-	(CONFIG_BFIN_DCLK != 225) && (CONFIG_BFIN_DCLK != 250))
-#error "DCLK must be in (125, 133, 150, 166, 200, 225, 250)MHz"
-#endif
 struct ddr_config {
 	u32 ddr_clk;
 	u32 dmc_ddrctl;
@@ -356,7 +344,7 @@ struct ddr_config {
 };
 
 #if defined(CONFIG_MEM_MT47H64M16)
-struct ddr_config ddr_config_table[] __attribute__((section(".data_l1"))) = {
+static struct ddr_config ddr_config_table[] __attribute__((section(".data_l1"))) = {
 	[0] = {
 		.ddr_clk    = 125,
 		.dmc_ddrctl = 0x00000904,
@@ -429,11 +417,75 @@ struct ddr_config ddr_config_table[] __attribute__((section(".data_l1"))) = {
 	},
 };
 #endif
-#else
-#define SDGCTL_WIDTH (1 << 31)	/* SDRAM external data path width */
-#define PLL_CTL_VAL \
-	(((CONFIG_VCO_MULT & 63) << 9) | CLKIN_HALF | \
-		(PLL_BYPASS << 8) | (ANOMALY_05000305 ? 0 : 0x8000))
-#endif
 
+static inline void dmc_enter_self_refresh(void)
+{
+	if (bfin_read_DMC0_STAT() & MEMINITDONE) {
+		bfin_write_DMC0_CTL(bfin_read_DMC0_CTL() | SRREQ);
+		while (!(bfin_read_DMC0_STAT() & SRACK))
+			continue;
+	}
+}
+
+static inline void dmc_exit_self_refresh(void)
+{
+	if (bfin_read_DMC0_STAT() & MEMINITDONE) {
+		bfin_write_DMC0_CTL(bfin_read_DMC0_CTL() & ~SRREQ);
+		while (bfin_read_DMC0_STAT() & SRACK)
+			continue;
+	}
+}
+
+static inline void init_cgu(u32 cgu_div, u32 cgu_ctl)
+{
+	dmc_enter_self_refresh();
+
+	/* Don't set the same value of MSEL and DF to CGU_CTL */
+	if ((bfin_read32(CGU0_CTL) & (MSEL_MASK | DF_MASK))
+		!= cgu_ctl) {
+		bfin_write32(CGU0_DIV, cgu_div);
+		bfin_write32(CGU0_CTL, cgu_ctl);
+		while ((bfin_read32(CGU0_STAT) & (CLKSALGN | PLLBP)) ||
+			!(bfin_read32(CGU0_STAT) & PLOCK))
+			continue;
+	}
+
+	bfin_write32(CGU0_DIV, cgu_div | UPDT);
+	while (bfin_read32(CGU0_STAT) & CLKSALGN)
+		continue;
+
+	dmc_exit_self_refresh();
+}
+
+static inline void init_dmc(u32 dmc_clk)
+{
+	int i, dlldatacycle, dll_ctl;
+
+	for (i = 0; i < 7; i++) {
+		if (ddr_config_table[i].ddr_clk == dmc_clk) {
+			bfin_write_DMC0_CFG(ddr_config_table[i].dmc_ddrcfg);
+			bfin_write_DMC0_TR0(ddr_config_table[i].dmc_ddrtr0);
+			bfin_write_DMC0_TR1(ddr_config_table[i].dmc_ddrtr1);
+			bfin_write_DMC0_TR2(ddr_config_table[i].dmc_ddrtr2);
+			bfin_write_DMC0_MR(ddr_config_table[i].dmc_ddrmr);
+			bfin_write_DMC0_EMR1(ddr_config_table[i].dmc_ddrmr1);
+			bfin_write_DMC0_CTL(ddr_config_table[i].dmc_ddrctl);
+			break;
+		}
+	}
+
+	while (!(bfin_read_DMC0_STAT() & MEMINITDONE))
+		continue;
+
+	dlldatacycle = (bfin_read_DMC0_STAT() & PHYRDPHASE) >> PHYRDPHASE_OFFSET;
+	dll_ctl = bfin_read_DMC0_DLLCTL();
+	dll_ctl &= ~DATACYC;
+	bfin_write_DMC0_DLLCTL(dll_ctl | (dlldatacycle << DATACYC_OFFSET));
+
+	while (!(bfin_read_DMC0_STAT() & DLLCALDONE))
+		continue;
+}
+#endif
+
+#endif /*__MEM_INIT_H__*/
 
diff --git a/arch/blackfin/mach-bf609/hibernate.S b/arch/blackfin/mach-bf609/hibernate.S
index 271402b..62cc319 100644
--- a/arch/blackfin/mach-bf609/hibernate.S
+++ b/arch/blackfin/mach-bf609/hibernate.S
@@ -2,6 +2,8 @@
 #include <asm/blackfin.h>
 #include <asm/dpmc.h>
 
+#include <asm/context.S>
+
 #define PM_STACK   (COREA_L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
 
 .section .l1.text
@@ -32,32 +34,45 @@ ENTRY(_enter_hibernate)
 	SSYNC;
 ENDPROC(_enter_hibernate)
 
-
+/* DPM wake up interrupt won't wake up core on bf60x if its core IMASK
+ * is disabled. This behavior differ from bf5xx serial processor.
+ */
 ENTRY(_dummy_deepsleep)
-	cli r0;
+	[--sp] = SYSCFG;
 	[--sp] = (R7:0,P5:0);
+	cli r0;
+
+	/* get wake up interrupt ID */
 	P0.l = LO(SEC_SCI_BASE + SEC_CSID);
 	P0.h = HI(SEC_SCI_BASE + SEC_CSID);
 	R0 = [P0];
 
+	/* ACK wake up interrupt in SEC */
 	P1.l = LO(SEC_END);
 	P1.h = HI(SEC_END);
 
 	[P1] = R0;
+	SSYNC;
 
+	/* restore EVT 11 entry */
 	p0.h = hi(EVT11);
 	p0.l = lo(EVT11);
 	p1.h = _evt_evt11;
 	p1.l = _evt_evt11;
 
 	[p0] = p1;
+	SSYNC;
 
-	(R7:0,P5:0) = [SP++];
+	(R7:0,P5:0) = [sp++];
+	SYSCFG = [sp++];
 	RTI;
 ENDPROC(_dummy_deepsleep)
 
 ENTRY(_enter_deepsleep)
+	LINK 0x0;
 	[--sp] = (R7:0,P5:0);
+
+	/* Change EVT 11 entry to dummy handler for wake up event */
 	p0.h = hi(EVT11);
 	p0.l = lo(EVT11);
 	p1.h = _dummy_deepsleep;
@@ -68,40 +83,42 @@ ENTRY(_enter_deepsleep)
 	P0.H = HI(PM_STACK);
 	P0.L = LO(PM_STACK);
 
-	i2 = SP;
+	EX_SCRATCH_REG = SP;
 	SP = P0;
 
 	SSYNC;
 
+	/* should put ddr to self refresh mode before sleep */
 	call _bf609_ddr_sr;
 
+	/* Set DPM controller to deep sleep mode */
 	P0.H = HI(DPM0_CTL);
 	P0.L = LO(DPM0_CTL);
 	R3.H = HI(0x00000008);
 	R3.L = LO(0x00000008);
 	[P0] = R3;
-
 	CSYNC;
 
-	r0.l = 0xffff;
+	/* Enable evt 11 in IMASK before idle, otherwise core doesn't wake up. */
+	r0.l = 0x800;
 	r0.h = 0;
 	sti r0;
 	SSYNC;
 
+	/* Fall into deep sleep in idle*/
 	idle;
 	SSYNC;
 
-	R3 = 0;
-1:
-	cc = R3;
-	if !cc jump 1b;
-
+	/* Restore PLL after wake up from deep sleep */
 	call _bf609_resume_ccbuf;
 
+	/* turn ddr out of self refresh mode */
 	call _bf609_ddr_sr_exit;
-	SP = i2;
+
+	SP = EX_SCRATCH_REG;
 
 	(R7:0,P5:0) = [SP++];
+	UNLINK;
 	RTS;
 ENDPROC(_enter_deepsleep)
 
diff --git a/arch/blackfin/mach-bf609/pm.c b/arch/blackfin/mach-bf609/pm.c
index 5f14540..0621818 100644
--- a/arch/blackfin/mach-bf609/pm.c
+++ b/arch/blackfin/mach-bf609/pm.c
@@ -18,6 +18,7 @@
 #include <asm/pm.h>
 #include <mach/pm.h>
 #include <asm/blackfin.h>
+#include <asm/mem_init.h>
 
 /***********************************************************/
 /*                                                         */
@@ -135,45 +136,19 @@ void bfin_cpu_suspend(void)
 __attribute__((l1_text))
 void bf609_ddr_sr(void)
 {
-	uint32_t reg;
-
-	reg = bfin_read_DMC0_CTL();
-	reg |= 0x8;
-	bfin_write_DMC0_CTL(reg);
-
-	while (!(bfin_read_DMC0_STAT() & 0x8))
-		continue;
+	dmc_enter_self_refresh();
 }
 
 __attribute__((l1_text))
 void bf609_ddr_sr_exit(void)
 {
-	int dlldatacycle;
-	int dll_ctl;
-
-	/* 250  Mhz */
-	bfin_write_DDR0_CFG(0x00000422);
-	bfin_write_DDR0_TR0(0x20E0A424);
-	bfin_write_DDR0_TR1(0x3020079E);
-	bfin_write_DDR0_TR2(0x0032020D);
-	bfin_write_DDR0_MR(0x00000842);
-	bfin_write_DDR0_EMR1(0x4);
-	bfin_write_DDR0_CTL(0x00000904);
-	while (!(bfin_read_DDR0_STAT() & 0x4))
-		continue;
-	dlldatacycle = (bfin_read_DDR0_STAT() & 0x00f00000) >> 20;
-	dll_ctl = bfin_read_DDR0_DLLCTL();
-	dll_ctl &= 0x0ff;
-	bfin_write_DDR0_DLLCTL(dll_ctl | (dlldatacycle << 8));
-
-	while (!(bfin_read_DDR0_STAT() & 0x2000))
-		continue;
+	dmc_exit_self_refresh();
 
-	while ((bfin_read_DMC0_STAT() & 0x8))
+	/* After wake up from deep sleep and exit DDR from self refress mode,
+	 * should wait till CGU PLL is locked.
+	 */
+	while (bfin_read32(CGU0_STAT) & CLKSALGN)
 		continue;
-	while (!(bfin_read_DDR0_STAT() & 0x1))
-		continue;
-
 }
 
 __attribute__((l1_text))
@@ -298,6 +273,7 @@ void bf609_cpu_pm_enter(suspend_state_t state)
 	else {
 		bfin_hibernate(wakeup);
 	}
+
 }
 
 int bf609_cpu_pm_prepare(void)
@@ -332,12 +308,8 @@ static irqreturn_t soft_isr(int irq, void *dev_id)
 
 static irqreturn_t dpm0_isr(int irq, void *dev_id)
 {
-	uint32_t wake_stat;
-
-	wake_stat = bfin_read32(DPM0_WAKE_STAT);
-//	printk(KERN_DEBUG "enter %s wake stat %08x\n", __func__, wake_stat);
-
-	bfin_write32(DPM0_WAKE_STAT, wake_stat);
+	bfin_write32(DPM0_WAKE_STAT, bfin_read32(DPM0_WAKE_STAT));
+	bfin_write32(CGU0_STAT, bfin_read32(CGU0_STAT));
 	return IRQ_HANDLED;
 }
 
diff --git a/arch/blackfin/mach-common/clocks-init.c b/arch/blackfin/mach-common/clocks-init.c
index 2ea8f22..2308ce5 100644
--- a/arch/blackfin/mach-common/clocks-init.c
+++ b/arch/blackfin/mach-common/clocks-init.c
@@ -15,6 +15,31 @@
 #include <asm/mem_init.h>
 #include <asm/dpmc.h>
 
+#ifdef CONFIG_BF60x
+
+#define CGU_CTL_VAL ((CONFIG_VCO_MULT << 8) | CLKIN_HALF)
+#define CGU_DIV_VAL \
+	((CONFIG_CCLK_DIV   << CSEL_OFFSET)   | \
+	(CONFIG_SCLK_DIV << SYSSEL_OFFSET)   | \
+	(CONFIG_SCLK0_DIV  << S0SEL_OFFSET)  | \
+	(CONFIG_SCLK1_DIV  << S1SEL_OFFSET)  | \
+	(CONFIG_DCLK_DIV   << DSEL_OFFSET))
+
+#define CONFIG_BFIN_DCLK (((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT) / CONFIG_DCLK_DIV) / 1000000)
+#if ((CONFIG_BFIN_DCLK != 125) && \
+	(CONFIG_BFIN_DCLK != 133) && (CONFIG_BFIN_DCLK != 150) && \
+	(CONFIG_BFIN_DCLK != 166) && (CONFIG_BFIN_DCLK != 200) && \
+	(CONFIG_BFIN_DCLK != 225) && (CONFIG_BFIN_DCLK != 250))
+#error "DCLK must be in (125, 133, 150, 166, 200, 225, 250)MHz"
+#endif
+
+#else
+#define SDGCTL_WIDTH (1 << 31)	/* SDRAM external data path width */
+#define PLL_CTL_VAL \
+	(((CONFIG_VCO_MULT & 63) << 9) | CLKIN_HALF | \
+		(PLL_BYPASS << 8) | (ANOMALY_05000305 ? 0 : 0x8000))
+#endif
+
 __attribute__((l1_text))
 static void do_sync(void)
 {
@@ -28,63 +53,9 @@ void init_clocks(void)
 	 * in the middle of reprogramming things, and that'll screw us up.
 	 * For example, any automatic DMAs left by U-Boot for splash screens.
 	 */
-
 #ifdef CONFIG_BF60x
-	int i, dlldatacycle, dll_ctl;
-
-	if (bfin_read_DMC0_STAT() & MEMINITDONE) {
-		bfin_write_DMC0_CTL(bfin_read_DMC0_CTL() | SRREQ);
-		do_sync();
-		while (!(bfin_read_DMC0_STAT() & SRACK))
-			continue;
-	}
-
-	/* Don't set the same value of MSEL and DF to CGU_CTL */
-	if ((bfin_read32(CGU0_CTL) & (MSEL_MASK | DF_MASK))
-		!= CGU_CTL_VAL) {
-		bfin_write32(CGU0_DIV, CGU_DIV_VAL);
-		bfin_write32(CGU0_CTL, CGU_CTL_VAL);
-		while ((bfin_read32(CGU0_STAT) & (CLKSALGN | PLLBP)) ||
-			!(bfin_read32(CGU0_STAT) & PLOCK))
-			continue;
-	}
-
-	bfin_write32(CGU0_DIV, CGU_DIV_VAL | UPDT);
-	while (bfin_read32(CGU0_STAT) & CLKSALGN)
-		continue;
-
-	if (bfin_read_DMC0_STAT() & MEMINITDONE) {
-		bfin_write_DMC0_CTL(bfin_read_DMC0_CTL() & ~SRREQ);
-		do_sync();
-		while (bfin_read_DMC0_STAT() & SRACK)
-			continue;
-	}
-
-	for (i = 0; i < 7; i++) {
-		if (ddr_config_table[i].ddr_clk == CONFIG_BFIN_DCLK) {
-			bfin_write_DMC0_CFG(ddr_config_table[i].dmc_ddrcfg);
-			bfin_write_DMC0_TR0(ddr_config_table[i].dmc_ddrtr0);
-			bfin_write_DMC0_TR1(ddr_config_table[i].dmc_ddrtr1);
-			bfin_write_DMC0_TR2(ddr_config_table[i].dmc_ddrtr2);
-			bfin_write_DMC0_MR(ddr_config_table[i].dmc_ddrmr);
-			bfin_write_DMC0_EMR1(ddr_config_table[i].dmc_ddrmr1);
-			bfin_write_DMC0_CTL(ddr_config_table[i].dmc_ddrctl);
-			break;
-		}
-	}
-
-	do_sync();
-	while (!(bfin_read_DMC0_STAT() & MEMINITDONE))
-		continue;
-
-	dlldatacycle = (bfin_read_DMC0_STAT() & PHYRDPHASE) >> PHYRDPHASE_OFFSET;
-	dll_ctl = bfin_read_DMC0_DLLCTL();
-	dll_ctl &= ~DATACYC;
-	bfin_write_DMC0_DLLCTL(dll_ctl | (dlldatacycle << DATACYC_OFFSET));
-
-	do_sync();
-	while (!(bfin_read_DMC0_STAT() & DLLCALDONE))
-		continue;
+	init_cgu(CGU_DIV_VAL, CGU_CTL_VAL);
+	init_dmc(CONFIG_BFIN_DCLK);
 #else
 	size_t i;
 	for (i = 0; i < MAX_DMA_CHANNELS; ++i) {
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index 84b5e3d..1e1d879 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -25,13 +25,6 @@
 
 #include <asm/context.S>
 
-#if defined(CONFIG_BFIN_SCRATCH_REG_RETN)
-# define EX_SCRATCH_REG RETN
-#elif defined(CONFIG_BFIN_SCRATCH_REG_RETE)
-# define EX_SCRATCH_REG RETE
-#else
-# define EX_SCRATCH_REG CYCLES
-#endif
 
 #ifdef CONFIG_EXCPT_IRQ_SYSC_L1
 .section .l1.text
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to