diff mbox

[U-Boot,11/16] Blackfin: Bf60x: support clock init

Message ID 1344326875-348-11-git-send-email-lliubbo@gmail.com
State Superseded
Delegated to: Mike Frysinger
Headers show

Commit Message

Bob Liu Aug. 7, 2012, 8:07 a.m. UTC
Add a way to set clock to values getting from config file bf609-ezkit.h

Signed-off-by: Bob Liu <lliubbo@gmail.com>
---
 arch/blackfin/cpu/initcode.c                     |  221 +++++++++++++++++++++-
 arch/blackfin/include/asm/mach-common/bits/cgu.h |    2 +
 include/configs/bf609-ezkit.h                    |   35 ++--
 3 files changed, 234 insertions(+), 24 deletions(-)

Comments

Mike Frysinger Aug. 8, 2012, 5:06 a.m. UTC | #1
split & squash into earlier patches where appropriate
-mike
diff mbox

Patch

diff --git a/arch/blackfin/cpu/initcode.c b/arch/blackfin/cpu/initcode.c
index 9888f10..3bb2b98 100644
--- a/arch/blackfin/cpu/initcode.c
+++ b/arch/blackfin/cpu/initcode.c
@@ -29,6 +29,121 @@ 
 #include <asm/mach-common/bits/cgu.h>
 #endif
 
+#ifdef __ADSPBF60x__
+#define CONFIG_BFIN_GET_DCLK_M 		(CONFIG_BFIN_GET_DCLK/1000000)
+
+#ifndef CONFIG_DMC_DDRCFG
+#if ((CONFIG_BFIN_GET_DCLK_M != 125) && \
+	(CONFIG_BFIN_GET_DCLK_M != 133) && \
+	(CONFIG_BFIN_GET_DCLK_M != 150) && \
+	(CONFIG_BFIN_GET_DCLK_M != 166) && \
+	(CONFIG_BFIN_GET_DCLK_M != 200) && \
+	(CONFIG_BFIN_GET_DCLK_M != 225) && \
+	(CONFIG_BFIN_GET_DCLK_M != 250))
+#error "DDR2 CLK must be in (125, 133, 150, 166, 200, 225, 250)MHz"
+#endif
+#endif
+
+/* DMC status bits */
+#define IDLE                    0x1
+#define MEMINITDONE             0x4
+#define SRACK                   0x8
+#define PDACK                   0x10
+#define DPDACK                  0x20
+#define DLLCALDONE              0x2000
+#define PENDREF                 0xF0000
+#define PHYRDPHASE              0xF00000
+#define PHYRDPHASE_OFFSET       20
+
+/* DMC DLL control bits */
+#define DLLCALRDCNT             0xFF
+#define DATACYC_OFFSET          8
+
+struct ddr_config {
+	u32 ddr_clk;
+	u32 dmc_ddrctl;
+	u32 dmc_ddrcfg;
+	u32 dmc_ddrtr0;
+	u32 dmc_ddrtr1;
+	u32 dmc_ddrtr2;
+	u32 dmc_ddrmr;
+	u32 dmc_ddrmr1;
+};
+
+static struct ddr_config ddr_config_table[] = {
+	[0] = {
+		.ddr_clk    = 125, 	/* 125MHz */
+		.dmc_ddrctl = 0x00000904,
+		.dmc_ddrcfg = 0x00000422,
+		.dmc_ddrtr0 = 0x20705212,
+		.dmc_ddrtr1 = 0x201003CF,
+		.dmc_ddrtr2 = 0x00320107,
+		.dmc_ddrmr  = 0x00000422,
+		.dmc_ddrmr1 = 0x4,
+	},
+	[1] = {
+		.ddr_clk    = 133, 	/* 133MHz */
+		.dmc_ddrctl = 0x00000904,
+		.dmc_ddrcfg = 0x00000422,
+		.dmc_ddrtr0 = 0x20806313,
+		.dmc_ddrtr1 = 0x2013040D,
+		.dmc_ddrtr2 = 0x00320108,
+		.dmc_ddrmr  = 0x00000632,
+		.dmc_ddrmr1 = 0x4,
+	},
+	[2] = {
+		.ddr_clk    = 150, 	/* 150MHz */
+		.dmc_ddrctl = 0x00000904,
+		.dmc_ddrcfg = 0x00000422,
+		.dmc_ddrtr0 = 0x20A07323,
+		.dmc_ddrtr1 = 0x20160492,
+		.dmc_ddrtr2 = 0x00320209,
+		.dmc_ddrmr  = 0x00000632,
+		.dmc_ddrmr1 = 0x4,
+	},
+	[3] = {
+		.ddr_clk    = 166, 	/* 166MHz */
+		.dmc_ddrctl = 0x00000904,
+		.dmc_ddrcfg = 0x00000422,
+		.dmc_ddrtr0 = 0x20A07323,
+		.dmc_ddrtr1 = 0x2016050E,
+		.dmc_ddrtr2 = 0x00320209,
+		.dmc_ddrmr  = 0x00000632,
+		.dmc_ddrmr1 = 0x4,
+	},
+	[4] = {
+		.ddr_clk    = 200, 	/* 200MHz */
+		.dmc_ddrctl = 0x00000904,
+		.dmc_ddrcfg = 0x00000422,
+		.dmc_ddrtr0 = 0x20a07323,
+		.dmc_ddrtr1 = 0x2016050f,
+		.dmc_ddrtr2 = 0x00320509,
+		.dmc_ddrmr  = 0x00000632,
+		.dmc_ddrmr1 = 0x4,
+	},
+	[5] = {
+		.ddr_clk    = 225, 	/* 225MHz */
+		.dmc_ddrctl = 0x00000904,
+		.dmc_ddrcfg = 0x00000422,
+		.dmc_ddrtr0 = 0x20E0A424,
+		.dmc_ddrtr1 = 0x302006DB,
+		.dmc_ddrtr2 = 0x0032020D,
+		.dmc_ddrmr  = 0x00000842,
+		.dmc_ddrmr1 = 0x4,
+	},
+	[6] = {
+		.ddr_clk    = 250, 	/* 250MHz */
+		.dmc_ddrctl = 0x00000904,
+		.dmc_ddrcfg = 0x00000422,
+		.dmc_ddrtr0 = 0x20E0A424,
+		.dmc_ddrtr1 = 0x3020079E,
+		.dmc_ddrtr2 = 0x0032020D,
+		.dmc_ddrmr  = 0x00000842,
+		.dmc_ddrmr1 = 0x4,
+	},
+};
+#endif
+
 __attribute__((always_inline))
 static inline void serial_init(void)
 {
@@ -174,7 +289,6 @@  program_nmi_handler(void)
 
 #ifndef CONFIG_CGU_DIV_VAL
 # define CONFIG_CGU_DIV_VAL \
-	(1 << UPDT_P) | \
 	((CONFIG_CCLK_DIV   << CSEL_P)   | \
 	 (CONFIG_SCLK0_DIV  << S0SEL_P)  | \
 	 (CONFIG_SCLK_DIV << SYSSEL_P) | \
@@ -409,12 +523,34 @@  program_clocks(ADI_BOOT_DATA *bs, bool put_into_srfs)
 	serial_putc('a');
 
 #ifdef __ADSPBF60x__
+	if (bfin_read_DMC0_STAT() & MEMINITDONE) {
+		bfin_write_DMC0_CTL(bfin_read_DMC0_CTL() | SRREQ);
+		__builtin_bfin_ssync();
+		while (!(bfin_read_DMC0_STAT() & SRACK))
+			continue;
+	}
+
+	/* Don't set the same value of MSEL and DF to CGU_CTL */
+	if ((bfin_read_CGU_CTL() & (MSEL_MASK | DF_MASK))
+			!= CONFIG_CGU_CTL_VAL) {
+		bfin_write_CGU_DIV(CONFIG_CGU_DIV_VAL);
+		bfin_write_CGU_CTL(CONFIG_CGU_CTL_VAL);
+		while ((bfin_read_CGU_STAT() & (CLKSALGN | PLLBP)) ||
+				!(bfin_read_CGU_STAT() & PLLLK))
+			continue;
+	}
 
-	bfin_write_CGU_CTL(CONFIG_CGU_CTL_VAL);
-	bfin_write_CGU_DIV(CONFIG_CGU_DIV_VAL);
-	while (!(bfin_read_CGU_STAT() & CLKSALGN))
+	bfin_write_CGU_DIV(CONFIG_CGU_DIV_VAL | UPDT);
+	while (bfin_read_CGU_STAT() & CLKSALGN)
 		continue;
 
+	if (bfin_read_DMC0_STAT() & MEMINITDONE) {
+		bfin_write_DMC0_CTL(bfin_read_DMC0_CTL() & ~SRREQ);
+		__builtin_bfin_ssync();
+		while (bfin_read_DMC0_STAT() & SRACK)
+			continue;
+	}
+
 #else /* __ADSPBF60x__ */
 
 	vr_ctl = bfin_read_VR_CTL();
@@ -586,14 +722,87 @@  __attribute__((always_inline)) static inline void
 program_memory_controller(ADI_BOOT_DATA *bs, bool put_into_srfs)
 {
 	serial_putc('a');
-
+/*
 	if (!CONFIG_MEM_SIZE)
 		return;
-
+*/
 	serial_putc('b');
 
 #ifdef __ADSPBF60x__
+	int dlldatacycle;
+	int dll_ctl;
+	int i = 0;
+
+	if (CONFIG_BFIN_GET_DCLK_M ==  125)
+		i = 0;
+	else if (CONFIG_BFIN_GET_DCLK_M ==  133)
+		i = 1;
+	else if (CONFIG_BFIN_GET_DCLK_M ==  150)
+		i = 2;
+	else if (CONFIG_BFIN_GET_DCLK_M ==  166)
+		i = 3;
+	else if (CONFIG_BFIN_GET_DCLK_M ==  200)
+		i = 4;
+	else if (CONFIG_BFIN_GET_DCLK_M ==  225)
+		i = 5;
+	else if (CONFIG_BFIN_GET_DCLK_M ==  250)
+		i = 6;
+
+#if 0
+	for (i = 0; i < ARRAY_SIZE(ddr_config_table); i++)
+		if (CONFIG_BFIN_GET_DCLK_M == ddr_config_table[i].ddr_clk)
+			break;
+#endif
+
+#ifndef CONFIG_DMC_DDRCFG
+	bfin_write_DMC0_CFG(ddr_config_table[i].dmc_ddrcfg);
+#else
+	bfin_write_DMC0_CFG(CONFIG_DMC_DDRCFG);
+#endif
+#ifndef CONFIG_DMC_DDRTR0
+	bfin_write_DMC0_TR0(ddr_config_table[i].dmc_ddrtr0);
+#else
+	bfin_write_DMC0_TR0(CONFIG_DMC_DDRTR0);
+#endif
+#ifndef CONFIG_DMC_DDRTR1
+	bfin_write_DMC0_TR1(ddr_config_table[i].dmc_ddrtr1);
+#else
+	bfin_write_DMC0_TR1(CONFIG_DMC_DDRTR1);
+#endif
+#ifndef CONFIG_DMC_DDRTR2
+	bfin_write_DMC0_TR2(ddr_config_table[i].dmc_ddrtr2);
+#else
+	bfin_write_DMC0_TR2(CONFIG_DMC_DDRTR2);
+#endif
+#ifndef CONFIG_DMC_DDRMR
+	bfin_write_DMC0_MR(ddr_config_table[i].dmc_ddrmr);
+#else
+	bfin_write_DMC0_MR(CONFIG_DMC_DDRMR);
+#endif
+#ifndef CONFIG_DMC_DDREMR1
+	bfin_write_DMC0_EMR1(ddr_config_table[i].dmc_ddrmr1);
+#else
+	bfin_write_DMC0_EMR1(CONFIG_DMC_DDREMR1);
+#endif
+#ifndef CONFIG_DMC_DDRCTL
+	bfin_write_DMC0_CTL(ddr_config_table[i].dmc_ddrctl);
+#else
+	bfin_write_DMC0_CTL(CONFIG_DMC_DDRCTL);
+#endif
 
+	__builtin_bfin_ssync();
+	while (!(bfin_read_DMC0_STAT() & MEMINITDONE))
+		continue;
+
+	dlldatacycle = (bfin_read_DMC0_STAT() & PHYRDPHASE) >> PHYRDPHASE_OFFSET;
+	dll_ctl = bfin_read_DMC0_DLLCTL();
+	dll_ctl &= 0x0ff;
+	bfin_write_DMC0_DLLCTL(dll_ctl | (dlldatacycle << DATACYC_OFFSET));
+
+	__builtin_bfin_ssync();
+	while (!(bfin_read_DMC0_STAT() & DLLCALDONE))
+		continue;
+	serial_putc('!');
 #else /* __ADSPBF60x__ */
 
 	/* Program the external memory controller before we come out of
diff --git a/arch/blackfin/include/asm/mach-common/bits/cgu.h b/arch/blackfin/include/asm/mach-common/bits/cgu.h
index a1c1940..cdf7349 100644
--- a/arch/blackfin/include/asm/mach-common/bits/cgu.h
+++ b/arch/blackfin/include/asm/mach-common/bits/cgu.h
@@ -15,6 +15,8 @@ 
 #define MSEL_P			8
 #define WIDLE_P			30
 #define LOCK_P			31
+#define MSEL_MASK               0x7F00
+#define DF_MASK                 0x1
 
 /* CGU_STAT Masks */
 #define PLLEN			(1 << 0)
diff --git a/include/configs/bf609-ezkit.h b/include/configs/bf609-ezkit.h
index c7cb834..311b2e4 100644
--- a/include/configs/bf609-ezkit.h
+++ b/include/configs/bf609-ezkit.h
@@ -7,7 +7,6 @@ 
 
 #include <asm/config-pre.h>
 
-
 /*
  * Processor Settings
  */
@@ -30,41 +29,41 @@ 
  *	SCLK1 = SCLK / SCLK1_DIV
  */
 /* CONFIG_CLKIN_HZ is any value in Hz					*/
-#define CONFIG_CLKIN_HZ			25000000
+#define CONFIG_CLKIN_HZ			(25000000)
 /* CLKIN_HALF controls the DF bit in PLL_CTL      0 = CLKIN		*/
 /*                                                1 = CLKIN / 2		*/
-#define CONFIG_CLKIN_HALF		0
+#define CONFIG_CLKIN_HALF		(0)
 
 /* VCO_MULT controls the MSEL (multiplier) bits in PLL_CTL		*/
 /* Values can range from 0-127 (where 0 means 128)			*/
-#define CONFIG_VCO_MULT			15
+#define CONFIG_VCO_MULT			(20)
 
 /* CCLK_DIV controls the core clock divider				*/
 /* Values can range from 0-31 (where 0 means 32)			*/
-#define CONFIG_CCLK_DIV			1
+#define CONFIG_CCLK_DIV			(1)
 /* SCLK_DIV controls the system clock divider				*/
 /* Values can range from 0-31 (where 0 means 32)			*/
-#define CONFIG_SYSCLK_DIV		3
+#define CONFIG_SCLK_DIV		(4)
 /* Values can range from 0-7 (where 0 means 8)				*/
-#define CONFIG_SCLK0_DIV		1
-#define CONFIG_SCLK1_DIV		1
+#define CONFIG_SCLK0_DIV		(1)
+#define CONFIG_SCLK1_DIV		(1)
 /* DCLK_DIV controls the DDR clock divider				*/
 /* Values can range from 0-31 (where 0 means 32)			*/
-#define CONFIG_DCLK_DIV			2
+#define CONFIG_DCLK_DIV			(2)
 /* OCLK_DIV controls the output clock divider				*/
 /* Values can range from 0-127 (where 0 means 128)			*/
-#define CONFIG_OCLK_DIV			16
+#define CONFIG_OCLK_DIV			(16)
 
-#define CONFIG_BFIN_GET_VCO CONFIG_CLKIN_HZ
-#define CONFIG_PLL_CLK  (get_vco()*CONFIG_VCO_MULT)
+#define CONFIG_BFIN_GET_VCO 		(CONFIG_CLKIN_HZ)
+#define CONFIG_PLL_CLK  		(get_vco()*CONFIG_VCO_MULT)
 
-#define CONFIG_BFIN_GET_CCLK (CONFIG_PLL_CLK/CONFIG_CCLK_DIV)
-#define CONFIG_CCLK_HZ CONFIG_BFIN_GET_CCLK
+#define CONFIG_BFIN_GET_CCLK 		(CONFIG_PLL_CLK/CONFIG_CCLK_DIV)
+#define CONFIG_CCLK_HZ 			(CONFIG_BFIN_GET_CCLK)
 
-#define CONFIG_BFIN_GET_SCLK (CONFIG_PLL_CLK/CONFIG_SYSCLK_DIV)
-#define CONFIG_BFIN_GET_SCLK0 (get_sclk()/CONFIG_SCLK0_DIV)
-#define CONFIG_BFIN_GET_SCLK1 (get_sclk()/CONFIG_SCLK1_DIV)
-#define CONFIG_BFIN_GET_DCLK (get_cclk()/CONFIG_DCLK_DIV)
+#define CONFIG_BFIN_GET_SCLK 		(CONFIG_PLL_CLK/CONFIG_SCLK_DIV)
+#define CONFIG_BFIN_GET_SCLK0 		(get_sclk()/CONFIG_SCLK0_DIV)
+#define CONFIG_BFIN_GET_SCLK1 		(get_sclk()/CONFIG_SCLK1_DIV)
+#define CONFIG_BFIN_GET_DCLK 		((CONFIG_CLKIN_HZ*CONFIG_VCO_MULT)/CONFIG_DCLK_DIV)
 
 /*
  * Memory Settings