[U-Boot] [PATCH] keystone2: use SPD info to configure K2HK and K2E DDR3
Vitaly Andrianov
vitalya at ti.com
Mon Jun 15 14:32:21 CEST 2015
This commit replaces hard-coded EMIF and PHY DDR3 configurations for
predefined SODIMMs to a calculated configuration. The SODIMM parameters
are read from SODIMM's SPD and used to calculated the configuration.
The current commit supports calculation for DDR3 with 1600MHz and 1333MHz
only.
Signed-off-by: Vitaly Andrianov <vitalya at ti.com>
---
board/ti/ks2_evm/Makefile | 5 +-
board/ti/ks2_evm/ddr3_cfg.c | 2 +
board/ti/ks2_evm/ddr3_cfg.h | 10 +-
board/ti/ks2_evm/ddr3_k2e.c | 56 ++---
board/ti/ks2_evm/ddr3_k2hk.c | 103 ++++-----
board/ti/ks2_evm/ddr3_spd.c | 531 +++++++++++++++++++++++++++++++++++++++++++
6 files changed, 616 insertions(+), 91 deletions(-)
create mode 100644 board/ti/ks2_evm/ddr3_spd.c
diff --git a/board/ti/ks2_evm/Makefile b/board/ti/ks2_evm/Makefile
index 071dbee..c888ab3 100644
--- a/board/ti/ks2_evm/Makefile
+++ b/board/ti/ks2_evm/Makefile
@@ -1,6 +1,6 @@
#
# KS2-EVM: board Makefile
-# (C) Copyright 2012-2014
+# (C) Copyright 2012-2015
# Texas Instruments Incorporated, <www.ti.com>
# SPDX-License-Identifier: GPL-2.0+
#
@@ -9,7 +9,10 @@ obj-y += board.o
obj-y += ddr3_cfg.o
obj-$(CONFIG_K2HK_EVM) += board_k2hk.o
obj-$(CONFIG_K2HK_EVM) += ddr3_k2hk.o
+obj-$(CONFIG_K2HK_EVM) += ddr3_spd.o
obj-$(CONFIG_K2E_EVM) += board_k2e.o
obj-$(CONFIG_K2E_EVM) += ddr3_k2e.o
+obj-$(CONFIG_K2E_EVM) += ddr3_spd.o
obj-$(CONFIG_K2L_EVM) += board_k2l.o
obj-$(CONFIG_K2L_EVM) += ddr3_k2l.o
+
diff --git a/board/ti/ks2_evm/ddr3_cfg.c b/board/ti/ks2_evm/ddr3_cfg.c
index ab44676..34b4103 100644
--- a/board/ti/ks2_evm/ddr3_cfg.c
+++ b/board/ti/ks2_evm/ddr3_cfg.c
@@ -169,6 +169,7 @@ struct ddr3_emif_config ddr3_1600_2g = {
.sdrfc = 0x00001869ul,
};
+#ifndef CONFIG_SOC_K2HK
int ddr3_get_dimm_params(char *dimm_name)
{
int ret;
@@ -204,3 +205,4 @@ int ddr3_get_dimm_params(char *dimm_name)
return 0;
}
+#endif
diff --git a/board/ti/ks2_evm/ddr3_cfg.h b/board/ti/ks2_evm/ddr3_cfg.h
index 5bd786c..5084508 100644
--- a/board/ti/ks2_evm/ddr3_cfg.h
+++ b/board/ti/ks2_evm/ddr3_cfg.h
@@ -10,18 +10,22 @@
#ifndef __DDR3_CFG_H
#define __DDR3_CFG_H
+extern struct ddr3_phy_config phy_spd_cfg;
+extern struct ddr3_emif_config emif_spd_cfg;
+int ddr3_get_dimm_params_from_spd(u8 *spd_params, int *ddr_clk,
+ int *ddr_size);
+
extern struct ddr3_phy_config ddr3phy_1600_8g;
extern struct ddr3_emif_config ddr3_1600_8g;
extern struct ddr3_phy_config ddr3phy_1333_2g;
extern struct ddr3_emif_config ddr3_1333_2g;
-extern struct ddr3_phy_config ddr3phy_1600_4g;
-extern struct ddr3_emif_config ddr3_1600_4g;
-
extern struct ddr3_phy_config ddr3phy_1600_2g;
extern struct ddr3_emif_config ddr3_1600_2g;
int ddr3_get_dimm_params(char *dimm_name);
+
+
#endif /* __DDR3_CFG_H */
diff --git a/board/ti/ks2_evm/ddr3_k2e.c b/board/ti/ks2_evm/ddr3_k2e.c
index 35ffb42..adc2947 100644
--- a/board/ti/ks2_evm/ddr3_k2e.c
+++ b/board/ti/ks2_evm/ddr3_k2e.c
@@ -1,7 +1,7 @@
/*
* Keystone2: DDR3 initialization
*
- * (C) Copyright 2014
+ * (C) Copyright 2014-2015
* Texas Instruments Incorporated, <www.ti.com>
*
* SPDX-License-Identifier: GPL-2.0+
@@ -12,42 +12,46 @@
#include <asm/arch/ddr3.h>
static struct pll_init_data ddr3_400 = DDR3_PLL_400;
+static struct pll_init_data ddr3_333 = DDR3_PLL_333;
u32 ddr3_init(void)
{
- u32 ddr3_size;
char dimm_name[32];
+ u8 spd_buf[256];
+ int ddr_speed;
+ int ddr_size;
- if (~(readl(KS2_PLL_CNTRL_BASE + KS2_RSTCTRL_RSTYPE) & 0x1))
- init_pll(&ddr3_400);
+ struct ddr3_phy_config *phy_cfg = &phy_spd_cfg;
+ struct ddr3_emif_config *emif_cfg = &emif_spd_cfg;
- ddr3_get_dimm_params(dimm_name);
+ if (ddr3_get_dimm_params_from_spd(spd_buf, &ddr_speed, &ddr_size)) {
+ printf("Sorry, I don't know how to configure DDR3A.\n"
+ "Bye :(\n");
+ for (;;)
+ ;
+ }
+
+ strncpy(dimm_name, (char *)&spd_buf[0x80], 18);
+ dimm_name[18] = '\0';
printf("Detected SO-DIMM [%s]\n", dimm_name);
+ printf("DDR3 speed %d\n", ddr_speed);
+ if (ddr_speed == 1600)
+ init_pll(&ddr3_400);
+ else
+ init_pll(&ddr3_333);
+
/* Reset DDR3 PHY after PLL enabled */
ddr3_reset_ddrphy();
- if (!strcmp(dimm_name, "18KSF1G72HZ-1G6E2 ")) {
- /* 8G SO-DIMM */
- ddr3_size = 8;
- printf("DRAM: 8 GiB\n");
- ddr3phy_1600_8g.zq0cr1 |= 0x10000;
- ddr3phy_1600_8g.zq1cr1 |= 0x10000;
- ddr3phy_1600_8g.zq2cr1 |= 0x10000;
- ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, &ddr3phy_1600_8g);
- ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE, &ddr3_1600_8g);
- } else if (!strcmp(dimm_name, "18KSF51272HZ-1G6K2")) {
- /* 4G SO-DIMM */
- ddr3_size = 4;
- printf("DRAM: 4 GiB\n");
- ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, &ddr3phy_1600_4g);
- ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE, &ddr3_1600_4g);
- } else {
- printf("Unknown SO-DIMM. Cannot configure DDR3\n");
- while (1)
- ;
- }
+ phy_cfg->zq0cr1 |= 0x10000;
+ phy_cfg->zq1cr1 |= 0x10000;
+ phy_cfg->zq2cr1 |= 0x10000;
+ ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, phy_cfg);
+ ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE, emif_cfg);
+
+ printf("DRAM: %d GiB\n", ddr_size);
- return ddr3_size;
+ return (u32)ddr_size;
}
diff --git a/board/ti/ks2_evm/ddr3_k2hk.c b/board/ti/ks2_evm/ddr3_k2hk.c
index b36eb27..37f9420 100644
--- a/board/ti/ks2_evm/ddr3_k2hk.c
+++ b/board/ti/ks2_evm/ddr3_k2hk.c
@@ -20,74 +20,55 @@ u32 ddr3_init(void)
char dimm_name[32];
u32 ddr3_size;
- ddr3_get_dimm_params(dimm_name);
+ u8 spd_buf[256];
+ int ddr_speed;
+ int ddr_size;
+
+ struct ddr3_phy_config *phy_cfg = &phy_spd_cfg;
+ struct ddr3_emif_config *emif_cfg = &emif_spd_cfg;
+
+ if (ddr3_get_dimm_params_from_spd(spd_buf, &ddr_speed, &ddr_size)) {
+ printf("Sorry, I don't know how to configure DDR3A.\n"
+ "Bye :(\n");
+ for (;;)
+ ;
+ }
+
+ strncpy(dimm_name, (char *)&spd_buf[0x80], 18);
+ dimm_name[18] = '\0';
printf("Detected SO-DIMM [%s]\n", dimm_name);
- if (!strcmp(dimm_name, "18KSF1G72HZ-1G6E2 ")) {
- init_pll(&ddr3a_400);
- if (cpu_revision() > 0) {
- if (cpu_revision() > 1) {
- /* PG 2.0 */
- /* Reset DDR3A PHY after PLL enabled */
- ddr3_reset_ddrphy();
- ddr3phy_1600_8g.zq0cr1 |= 0x10000;
- ddr3phy_1600_8g.zq1cr1 |= 0x10000;
- ddr3phy_1600_8g.zq2cr1 |= 0x10000;
- ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC,
- &ddr3phy_1600_8g);
- } else {
- /* PG 1.1 */
- ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC,
- &ddr3phy_1600_8g);
- }
+ if ((cpu_revision() > 1) ||
+ (__raw_readl(KS2_PLL_CNTRL_BASE + KS2_RSTCTRL_RSTYPE) & 0x1)) {
+ printf("DDR3 speed %d\n", ddr_speed);
+ if (ddr_speed == 1600)
+ init_pll(&ddr3a_400);
+ else
+ init_pll(&ddr3a_333);
+ }
- ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE,
- &ddr3_1600_8g);
- printf("DRAM: Capacity 8 GiB (includes reported below)\n");
- ddr3_size = 8;
- } else {
- ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, &ddr3phy_1600_8g);
- ddr3_1600_8g.sdcfg |= 0x1000;
- ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE,
- &ddr3_1600_8g);
- printf("DRAM: Capacity 4 GiB (includes reported below)\n");
- ddr3_size = 4;
- }
- } else if (!strcmp(dimm_name, "SQR-SD3T-2G1333SED")) {
- init_pll(&ddr3a_333);
- if (cpu_revision() > 0) {
- if (cpu_revision() > 1) {
- /* PG 2.0 */
- /* Reset DDR3A PHY after PLL enabled */
- ddr3_reset_ddrphy();
- ddr3phy_1333_2g.zq0cr1 |= 0x10000;
- ddr3phy_1333_2g.zq1cr1 |= 0x10000;
- ddr3phy_1333_2g.zq2cr1 |= 0x10000;
- ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC,
- &ddr3phy_1333_2g);
- } else {
- /* PG 1.1 */
- ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC,
- &ddr3phy_1333_2g);
- }
- ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE,
- &ddr3_1333_2g);
- ddr3_size = 2;
- printf("DRAM: 2 GiB");
- } else {
- ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, &ddr3phy_1333_2g);
- ddr3_1333_2g.sdcfg |= 0x1000;
- ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE,
- &ddr3_1333_2g);
- ddr3_size = 1;
- printf("DRAM: 1 GiB");
+ if (cpu_revision() > 0) {
+ if (cpu_revision() > 1) {
+ /* PG 2.0 */
+ /* Reset DDR3A PHY after PLL enabled */
+ ddr3_reset_ddrphy();
+ phy_cfg->zq0cr1 |= 0x10000;
+ phy_cfg->zq1cr1 |= 0x10000;
+ phy_cfg->zq2cr1 |= 0x10000;
}
+ ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, phy_cfg);
+
+ ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE, emif_cfg);
+
+ ddr3_size = ddr_size;
} else {
- printf("Unknown SO-DIMM. Cannot configure DDR3\n");
- while (1)
- ;
+ ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, phy_cfg);
+ emif_cfg->sdcfg |= 0x1000;
+ ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE, emif_cfg);
+ ddr3_size = ddr_size / 2;
}
+ printf("DRAM: %d GiB (includes reported below)\n", ddr3_size);
/* Apply the workaround for PG 1.0 and 1.1 Silicons */
if (cpu_revision() <= 1)
diff --git a/board/ti/ks2_evm/ddr3_spd.c b/board/ti/ks2_evm/ddr3_spd.c
new file mode 100644
index 0000000..d5bed47
--- /dev/null
+++ b/board/ti/ks2_evm/ddr3_spd.c
@@ -0,0 +1,531 @@
+/*
+ * Keystone2: DDR3 SPD configuration
+ *
+ * (C) Copyright 2015
+ * Texas Instruments Incorporated, <www.ti.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+
+#include <i2c.h>
+#include <asm/arch/ddr3.h>
+#include <asm/arch/hardware.h>
+
+#ifdef DUMP_DDR_CONFIG
+static void dump_phy_config(struct ddr3_phy_config *ptr)
+{
+ printf("\npllcr 0x%08X\n", ptr->pllcr);
+ printf("pgcr1_mask 0x%08X\n", ptr->pgcr1_mask);
+ printf("pgcr1_val 0x%08X\n", ptr->pgcr1_val);
+ printf("ptr0 0x%08X\n", ptr->ptr0);
+ printf("ptr1 0x%08X\n", ptr->ptr1);
+ printf("ptr2 0x%08X\n", ptr->ptr2);
+ printf("ptr3 0x%08X\n", ptr->ptr3);
+ printf("ptr4 0x%08X\n", ptr->ptr4);
+ printf("dcr_mask 0x%08X\n", ptr->dcr_mask);
+ printf("dcr_val 0x%08X\n", ptr->dcr_val);
+ printf("dtpr0 0x%08X\n", ptr->dtpr0);
+ printf("dtpr1 0x%08X\n", ptr->dtpr1);
+ printf("dtpr2 0x%08X\n", ptr->dtpr2);
+ printf("mr0 0x%08X\n", ptr->mr0);
+ printf("mr1 0x%08X\n", ptr->mr1);
+ printf("mr2 0x%08X\n", ptr->mr2);
+ printf("dtcr 0x%08X\n", ptr->dtcr);
+ printf("pgcr2 0x%08X\n", ptr->pgcr2);
+ printf("zq0cr1 0x%08X\n", ptr->zq0cr1);
+ printf("zq1cr1 0x%08X\n", ptr->zq1cr1);
+ printf("zq2cr1 0x%08X\n", ptr->zq2cr1);
+ printf("pir_v1 0x%08X\n", ptr->pir_v1);
+ printf("pir_v2 0x%08X\n\n", ptr->pir_v2);
+};
+
+static void dump_emif_config(struct ddr3_emif_config *ptr)
+{
+ printf("\nsdcfg 0x%08X\n", ptr->sdcfg);
+ printf("sdtim1 0x%08X\n", ptr->sdtim1);
+ printf("sdtim2 0x%08X\n", ptr->sdtim2);
+ printf("sdtim3 0x%08X\n", ptr->sdtim3);
+ printf("sdtim4 0x%08X\n", ptr->sdtim4);
+ printf("zqcfg 0x%08X\n", ptr->zqcfg);
+ printf("sdrfc 0x%08X\n\n", ptr->sdrfc);
+};
+#endif
+
+#define TEMP NORMAL_TEMP
+#define VBUS_CLKPERIOD 1.875 /* Corresponds to vbus=533MHz, */
+#define PLLGS_VAL (4000.0 / VBUS_CLKPERIOD) /* 4 us */
+#define PLLPD_VAL (1000.0 / VBUS_CLKPERIOD) /* 1 us */
+#define PLLLOCK_VAL (100000.0 / VBUS_CLKPERIOD) /* 100 us */
+#define PLLRST_VAL (9000.0 / VBUS_CLKPERIOD) /* 9 us */
+#define PHYRST_VAL 0x10
+#define DDR_TERM RZQ_4_TERM
+#define SDRAM_DRIVE RZQ_7_IMP
+#define DYN_ODT ODT_DISABLE
+
+struct ddr3_phy_config phy_spd_cfg;
+struct ddr3_emif_config emif_spd_cfg;
+static unsigned int ddrspdclock;
+static int ddr_size_gbyte;
+
+enum ebank {
+ DCE0,
+ DCE0_DEC1
+};
+
+enum nm {
+ DDR3BUSWIDTH_64,
+ DDR3BUSWIDTH_32,
+ DDR3BUSWIDTH_16
+};
+
+enum srt {
+ NORMAL_TEMP,
+ EXTENDED_TEMP
+};
+
+enum out_impedance {
+ RZQ_6_IMP = 0,
+ RZQ_7_IMP
+};
+
+enum die_term {
+ ODT_DISABLE = 0,
+ RZQ_4_TERM,
+ RZQ_2_TERM,
+ RZQ_6_TERM,
+ RZQ_12_TERM,
+ RZQ_8_TERM
+};
+
+struct ddr3_sodimm {
+ float t_ck;
+ uint32_t freqsel;
+ uint32_t t_xp;
+ uint32_t t_cke;
+ uint32_t t_pllpd;
+ uint32_t t_pllgs;
+ uint32_t t_phyrst;
+ uint32_t t_plllock;
+ uint32_t t_pllrst;
+ uint32_t t_rfc;
+ uint32_t t_xs;
+ uint32_t t_dinit0;
+ uint32_t t_dinit1;
+ uint32_t t_dinit2;
+ uint32_t t_dinit3;
+ uint32_t t_rtp;
+ uint32_t t_wtr;
+ uint32_t t_rp;
+ uint32_t t_rcd;
+ uint32_t t_ras;
+ uint32_t t_rrd;
+ uint32_t t_rc;
+ uint32_t t_faw;
+ uint32_t t_mrd;
+ uint32_t t_mod;
+ uint32_t t_wlo;
+ uint32_t t_wlmrd;
+ uint32_t t_xsdll;
+ uint32_t t_xpdll;
+ uint32_t t_ckesr;
+ uint32_t t_dllk;
+ uint32_t t_wr;
+ uint32_t t_wr_bin;
+ uint32_t cas;
+ uint32_t cwl;
+ uint32_t asr;
+ uint32_t pasr;
+ float t_refprd;
+ uint8_t sdram_type;
+ uint8_t ibank;
+ uint8_t pagesize;
+ uint8_t t_rrd2;
+ uint8_t t_ras_max;
+ uint8_t t_zqcs;
+ uint32_t refresh_rate;
+ uint8_t t_csta;
+
+ uint8_t rank;
+ uint8_t mirrored;
+ uint8_t buswidth;
+} spd;
+
+static uint8_t cas_latancy(uint16_t temp)
+{
+ int loop;
+ uint8_t cas_bin = 0;
+
+ for (loop = 0; loop < 32; loop += 2, temp >>= 1) {
+ if (temp & 0x0001)
+ cas_bin = (loop > 15) ? loop - 15 : loop;
+ }
+
+ return cas_bin;
+}
+
+static int ddrtimingcalculation(uint8_t buf[])
+{
+ float mtb, clk_freq;
+
+ /* Determine Time Base */
+ mtb = (float)buf[10] / buf[11];
+
+ /* SDRAM Cycle Time */
+ spd.t_ck = buf[12] * mtb;
+ ddrspdclock = ((1 / spd.t_ck) * 1000) * 2;
+ clk_freq = ddrspdclock / 2;
+
+ if (buf[2] != 0x0b)
+ return 1;
+
+ spd.sdram_type = 0x03;
+
+ if ((buf[4] & 0x70) != 0x00)
+ return 1;
+
+ spd.ibank = 0x03;
+
+ /* Check number of ranks, stop if greater than two ranks */
+ switch ((buf[7] & 0x38) >> 3) {
+ case 0:
+ spd.rank = 1;
+ break;
+ case 1:
+ spd.rank = 2;
+ break;
+ default:
+ return 1;
+ }
+
+ /* Identify # of column address bits */
+ switch (buf[5] & 0x07) {
+ case 0:
+ spd.pagesize = 0x01;
+ break;
+ case 1:
+ spd.pagesize = 0x02;
+ break;
+ case 2:
+ spd.pagesize = 0x03;
+ break;
+ default:
+ return 1;
+ }
+
+ /* Identify Bus Width */
+ switch (buf[8] & 0x7) {
+ case 1:
+ spd.buswidth = DDR3BUSWIDTH_16;
+ break;
+ case 2:
+ spd.buswidth = DDR3BUSWIDTH_32;
+ break;
+ case 3:
+ spd.buswidth = DDR3BUSWIDTH_64;
+ break;
+ default:
+ return 1;
+ }
+
+ spd.mirrored = (buf[63] & 1) ? 1 : 0;
+
+ if (ddrspdclock == 1333) {
+ puts("DDR3A Speed will be configured for 1333 Operation.\n");
+
+ spd.t_xp = ((3 * spd.t_ck) > 6.0) ?
+ 3 : (6.0 / spd.t_ck) + 0.5;
+ spd.t_cke = ((3 * spd.t_ck) > 5.625) ?
+ 3 : (5.625 / spd.t_ck) + 0.5;
+ } else if (ddrspdclock == 1600) {
+ puts("DDR3A Speed will be configured for 1600 Operation.\n");
+
+ spd.t_xp = ((3 * spd.t_ck) > 6.0) ?
+ 3 : (6.0 / spd.t_ck) + 0.5;
+ spd.t_cke = ((3 * spd.t_ck) > 5.0) ?
+ 3 : (5.0 / spd.t_ck) + 0.5;
+ } else {
+ printf("Unsupported DDR3 speed %d\n", ddrspdclock);
+ return 1;
+ }
+
+ spd.t_xpdll = ((10 * spd.t_ck) > 24.0) ? 10 : 24.0 / spd.t_ck;
+ spd.t_ckesr = spd.t_cke + 1;
+
+ /* SPD Calculated Values */
+ spd.cas = cas_latancy(((buf[15] << 8) | buf[14]));
+
+ spd.t_wr = (buf[17] * mtb) / spd.t_ck;
+ spd.t_wr_bin = (spd.t_wr / 2) & 0x07;
+
+ spd.t_rcd = (((float)buf[18] * mtb) / spd.t_ck) + 0.5;
+ spd.t_rrd = (((float)buf[19] * mtb) / spd.t_ck) + 0.5;
+ spd.t_rp = (((float)buf[20] * mtb) / spd.t_ck) + 0.5;
+
+ spd.t_ras = (buf[21] & 0x0f) << 8;
+ spd.t_ras |= buf[22];
+ spd.t_ras = (((float)spd.t_ras * mtb) / spd.t_ck) + 0.5;
+
+
+ spd.t_rc = (buf[21] & 0xf0) << 4;
+ spd.t_rc |= buf[23];
+ spd.t_rc = (((float)spd.t_rc * mtb) / spd.t_ck) + 0.5;
+
+ spd.t_rfc = (buf[24] | (buf[25] << 8)) * mtb;
+ spd.t_wtr = ((float)buf[26] * mtb) / spd.t_ck;
+ spd.t_rtp = ((float)buf[27] * mtb) / spd.t_ck;
+
+ spd.t_xs = ((spd.t_rfc + 10) / spd.t_ck) + 0.5;
+ spd.t_rfc = (spd.t_rfc / spd.t_ck) + 0.5;
+
+ spd.t_faw = (((buf[28] << 8) | buf[29]) * mtb) / spd.t_ck;
+ spd.t_rrd2 = ((((buf[28] << 8) | buf[29]) * mtb) / (4 * spd.t_ck)) - 1;
+
+ /* Hard-coded values */
+ spd.t_mrd = 0x00;
+ spd.t_mod = 0x00;
+ spd.t_wlo = 0x0C;
+ spd.t_wlmrd = 0x28;
+ spd.t_xsdll = 0x200;
+ spd.t_ras_max = 0x0F;
+ spd.t_csta = 0x05;
+ spd.t_dllk = 0x200;
+
+ /* CAS Write Latency */
+ if (spd.t_ck >= 2.5)
+ spd.cwl = 0;
+ else if (spd.t_ck >= 1.875)
+ spd.cwl = 1;
+ else if (spd.t_ck >= 1.5)
+ spd.cwl = 2;
+ else if (spd.t_ck >= 1.25)
+ spd.cwl = 3;
+ else if (spd.t_ck >= 1.071)
+ spd.cwl = 4;
+ else
+ spd.cwl = 5;
+
+ /* SDRAM Thermal and Refresh Options */
+ spd.asr = (buf[31] & 0x04) >> 2;
+ spd.pasr = (buf[31] & 0x80) >> 7;
+ spd.t_zqcs = 64;
+
+ spd.t_refprd = ((TEMP == NORMAL_TEMP) ? 64000.00 : 32000.0) / 8192;
+ spd.t_refprd = (spd.t_refprd * 1000) / spd.t_ck;
+
+ spd.refresh_rate = spd.t_refprd;
+ spd.t_refprd = spd.t_refprd * 5;
+
+ /* Set MISC PHY space registers fields */
+ if (((int)clk_freq / 2) >= 166 && ((int)clk_freq / 2 < 275))
+ spd.freqsel = 0x03;
+ else if (((int)clk_freq / 2) > 225 && ((int)clk_freq / 2 < 385))
+ spd.freqsel = 0x01;
+ else if (((int)clk_freq / 2) > 335 && ((int)clk_freq / 2 < 534))
+ spd.freqsel = 0x00;
+
+ spd.t_dinit0 = 500000.0 / spd.t_ck; /* CKE low time 500 us */
+ spd.t_dinit1 = spd.t_xs;
+ spd.t_dinit2 = 200000.0 / spd.t_ck; /* Reset low time 200 us */
+ /* Time from ZQ initialization command to first command (1 us) */
+ spd.t_dinit3 = 1000.0 / spd.t_ck;
+
+ spd.t_pllgs = PLLGS_VAL + 1;
+ spd.t_pllpd = PLLPD_VAL + 1;
+ spd.t_plllock = PLLLOCK_VAL + 1;
+ spd.t_pllrst = PLLRST_VAL;
+ spd.t_phyrst = PHYRST_VAL;
+
+ ddr_size_gbyte = (spd.rank * (256 << (buf[4] & 0xf))) / 1024;
+
+ return 0;
+}
+
+static int crc16(uint8_t *ptr, int count)
+{
+ int crc, i;
+
+ crc = 0;
+ while (--count >= 0) {
+ crc = crc ^ (int)*ptr++ << 8;
+ for (i = 0; i < 8; ++i)
+ if (crc & 0x8000)
+ crc = crc << 1 ^ 0x1021;
+ else
+ crc = crc << 1;
+ }
+ return crc & 0xffff;
+}
+
+static unsigned int ddr3_spd_check(uint8_t spd[])
+{
+ int csum16;
+ int len;
+ unsigned char crc_lsb; /* byte 126 */
+ unsigned char crc_msb; /* byte 127 */
+
+ /*
+ * SPD byte0[7] - CRC coverage
+ * 0 = CRC covers bytes 0~125
+ * 1 = CRC covers bytes 0~116
+ */
+ len = !(spd[0] & 0x80) ? 126 : 117;
+ csum16 = crc16(spd, len);
+
+ crc_lsb = (unsigned char)(csum16 & 0xff);
+ crc_msb = (unsigned char)(csum16 >> 8);
+ if ((spd[126] == crc_lsb) && (spd[127] == crc_msb)) {
+ printf("SPD csum OK; in SPD: %02X %02X; computed %08X %02X\n",
+ spd[127], spd[126], crc_msb, crc_lsb);
+ return 0;
+ }
+
+ printf("SPD csum ERROR; in SPD: %02X %02X; computed %08X %02X\n",
+ spd[127], spd[126], crc_msb, crc_lsb);
+
+ return 1;
+}
+
+static void init_ddr3param(void)
+{
+ phy_spd_cfg.pllcr = (spd.freqsel & 3) << 18 | 0xE << 13;
+ phy_spd_cfg.pgcr1_mask = (IODDRM_MASK | ZCKSEL_MASK);
+ phy_spd_cfg.pgcr1_val = ((1 << 2) | (1 << 7) | (1 << 23));
+ phy_spd_cfg.ptr0 = ((spd.t_pllpd & 0x7ff) << 21) |
+ ((spd.t_pllgs & 0x7fff) << 6) | (spd.t_phyrst & 0x3f);
+ phy_spd_cfg.ptr1 = ((spd.t_plllock & 0xffff) << 16) |
+ (spd.t_pllrst & 0x1fff);
+ phy_spd_cfg.ptr2 = 0;
+ phy_spd_cfg.ptr3 = ((spd.t_dinit1 & 0x1ff) << 20) |
+ (spd.t_dinit0 & 0xfffff);
+ phy_spd_cfg.ptr4 = ((spd.t_dinit3 & 0x3ff) << 18) |
+ (spd.t_dinit2 & 0x3ffff);
+
+ phy_spd_cfg.dcr_mask = PDQ_MASK | MPRDQ_MASK | BYTEMASK_MASK;
+ phy_spd_cfg.dcr_val = 1 << 10;
+
+ if (spd.mirrored) {
+ phy_spd_cfg.dcr_mask |= NOSRA_MASK | UDIMM_MASK;
+ phy_spd_cfg.dcr_val |= (1 << 27) | (1 << 29);
+ }
+
+ phy_spd_cfg.dtpr0 = (spd.t_rc & 0x3f) << 26 | (spd.t_rrd & 0xf) << 22 |
+ (spd.t_ras & 0x3f) << 16 | (spd.t_rcd & 0xf) << 12 |
+ (spd.t_rp & 0xf) << 8 | (spd.t_wtr & 0xf) << 4 |
+ (spd.t_rtp & 0xf);
+ phy_spd_cfg.dtpr1 = (spd.t_wlo & 0xf) << 26 |
+ (spd.t_wlmrd & 0x3f) << 20 | (spd.t_rfc & 0x1ff) << 11 |
+ (spd.t_faw & 0x3f) << 5 | (spd.t_mod & 0x7) << 2|
+ (spd.t_mrd & 0x3);
+
+ phy_spd_cfg.dtpr2 = 0 << 31 | 1 << 30 | 0 << 29 |
+ (spd.t_dllk & 0x3ff) << 19 | (spd.t_ckesr & 0xf) << 15;
+
+ phy_spd_cfg.dtpr2 |= (((spd.t_xp > spd.t_xpdll) ?
+ spd.t_xp : spd.t_xpdll) &
+ 0x1f) << 10;
+
+ phy_spd_cfg.dtpr2 |= (((spd.t_xs > spd.t_xsdll) ?
+ spd.t_xs : spd.t_xsdll) &
+ 0x3ff);
+
+ phy_spd_cfg.mr0 = 1 << 12 | (spd.t_wr_bin & 0x7) << 9 | 0 << 8 |
+ 0 << 7 | ((spd.cas & 0x0E) >> 1) << 4 | 0 << 3 |
+ (spd.cas & 0x01) << 2;
+
+ phy_spd_cfg.mr1 = 0 << 12 | 0 << 11 | 0 << 7 | 0 << 3 |
+ ((DDR_TERM >> 2) & 1) << 9 | ((DDR_TERM >> 1) & 1) << 6 |
+ (DDR_TERM & 0x1) << 2 | ((SDRAM_DRIVE >> 1) & 1) << 5 |
+ (SDRAM_DRIVE & 1) << 1 | 0 << 0;
+
+ phy_spd_cfg.mr2 = DYN_ODT << 9 | TEMP << 7 | (spd.asr & 1) << 6 |
+ (spd.cwl & 7) << 3 | (spd.pasr & 7);
+
+ phy_spd_cfg.dtcr = (spd.rank == 2) ? 0x730035C7 : 0x710035C7;
+ phy_spd_cfg.pgcr2 = (0xF << 20) | ((int)spd.t_refprd & 0x3ffff);
+
+ phy_spd_cfg.zq0cr1 = 0x0000005D;
+ phy_spd_cfg.zq1cr1 = 0x0000005B;
+ phy_spd_cfg.zq2cr1 = 0x0000005B;
+
+ phy_spd_cfg.pir_v1 = 0x00000033;
+ phy_spd_cfg.pir_v2 = 0x0000FF81;
+
+
+ /* EMIF Registers */
+ emif_spd_cfg.sdcfg = spd.sdram_type << 29 | (DDR_TERM & 7) << 25 |
+ (DYN_ODT & 3) << 22 | (spd.cwl & 0x7) << 14 |
+ (spd.cas & 0xf) << 8 | (spd.ibank & 3) << 5 |
+ (spd.buswidth & 3) << 12 | (spd.pagesize & 3);
+
+ if (spd.rank == 2)
+ emif_spd_cfg.sdcfg |= DCE0_DEC1 << 3;
+
+ emif_spd_cfg.sdtim1 = ((spd.t_wr - 1) & 0x1f) << 25 |
+ ((spd.t_ras - 1) & 0x7f) << 18 |
+ ((spd.t_rc - 1) & 0xff) << 10 |
+ (spd.t_rrd2 & 0x3f) << 4 |
+ ((spd.t_wtr - 1) & 0xf);
+
+ emif_spd_cfg.sdtim2 = 0x07 << 10 | ((spd.t_rp - 1) & 0x1f) << 5 |
+ ((spd.t_rcd-1) & 0x1f);
+
+ emif_spd_cfg.sdtim3 = ((spd.t_xp - 2) & 0xf) << 28 |
+ ((spd.t_xs - 1) & 0x3ff) << 18 |
+ ((spd.t_xsdll - 1) & 0x3ff) << 8 |
+ ((spd.t_rtp - 1) & 0xf) << 4 | ((spd.t_cke) & 0xf);
+
+ emif_spd_cfg.sdtim4 = (spd.t_csta & 0xf) << 28 |
+ ((spd.t_ckesr - 1) & 0xf) << 24 |
+ ((spd.t_zqcs - 1) & 0xff) << 16 |
+ ((spd.t_rfc - 1) & 0x3ff) << 4 |
+ (spd.t_ras_max & 0xf);
+
+ emif_spd_cfg.sdrfc = (spd.refresh_rate-1) & 0xffff;
+
+ /* TODO zqcfg value fixed ,May be required correction for K2E evm. */
+ emif_spd_cfg.zqcfg = (spd.rank == 2) ? 0xF0073200 : 0x70073200;
+}
+
+int ddr3_get_dimm_params_from_spd(u8 *spd_params, int *ddr_clk,
+ int *ddr_size)
+{
+ int ret;
+ int old_bus;
+
+ i2c_init(CONFIG_SYS_DAVINCI_I2C_SPEED, CONFIG_SYS_DAVINCI_I2C_SLAVE);
+
+ old_bus = i2c_get_bus_num();
+ i2c_set_bus_num(1);
+
+ ret = i2c_read(0x53, 0, 1, spd_params, 256);
+
+ i2c_set_bus_num(old_bus);
+
+ if (ret) {
+ puts("Cannot read DIMM params\n");
+ return 1;
+ }
+
+ if (ddr3_spd_check(spd_params))
+ return 1;
+
+ if (ddrtimingcalculation(spd_params)) {
+ puts("Timing caclulation error\n");
+ return 1;
+ }
+
+ init_ddr3param();
+
+#ifdef DUMP_DDR_CONFIG
+ dump_emif_config(&emif_spd_cfg);
+ dump_phy_config(&phy_spd_cfg);
+#endif
+
+ *ddr_clk = ddrspdclock;
+ *ddr_size = ddr_size_gbyte;
+
+ return 0;
+}
+
--
1.9.1
More information about the U-Boot
mailing list