SDR_CTRLGRP_DRAMODT_READ_LSB) |
(CONFIG_HPS_SDR_CTRLCFG_DRAMODT_WRITE <<
SDR_CTRLGRP_DRAMODT_WRITE_LSB),
+#if (CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_MEMTYPE == 2) /* DDR3 */
.extratime1 =
- (CONFIG_HPS_SDR_CTRLCFG_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR <<
- SDR_CTRLGRP_EXTRATIME1_RD_TO_WR_LSB) |
- (CONFIG_HPS_SDR_CTRLCFG_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR_BC <<
- SDR_CTRLGRP_EXTRATIME1_RD_TO_WR_BC_LSB) |
-(CONFIG_HPS_SDR_CTRLCFG_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR_DIFF_CHIP <<
- SDR_CTRLGRP_EXTRATIME1_RD_TO_WR_DIFF_LSB),
+ (CONFIG_HPS_SDR_CTRLCFG_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR <<
+ SDR_CTRLGRP_EXTRATIME1_RD_TO_WR_LSB) |
+ (CONFIG_HPS_SDR_CTRLCFG_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR_BC <<
+ SDR_CTRLGRP_EXTRATIME1_RD_TO_WR_BC_LSB) |
+ (CONFIG_HPS_SDR_CTRLCFG_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR_DIFF_CHIP <<
+ SDR_CTRLGRP_EXTRATIME1_RD_TO_WR_DIFF_LSB),
+#endif
.dram_addrw =
(CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_COLBITS <<
SDR_CTRLGRP_DRAMADDRW_COLBITS_LSB) |
.activate_0_and_1 = RW_MGR_ACTIVATE_0_AND_1,
.activate_0_and_1_wait1 = RW_MGR_ACTIVATE_0_AND_1_WAIT1,
.activate_0_and_1_wait2 = RW_MGR_ACTIVATE_0_AND_1_WAIT2,
- .activate_1 = RW_MGR_ACTIVATE_1,
.clear_dqs_enable = RW_MGR_CLEAR_DQS_ENABLE,
.guaranteed_read = RW_MGR_GUARANTEED_READ,
.guaranteed_read_cont = RW_MGR_GUARANTEED_READ_CONT,
.guaranteed_write_wait1 = RW_MGR_GUARANTEED_WRITE_WAIT1,
.guaranteed_write_wait2 = RW_MGR_GUARANTEED_WRITE_WAIT2,
.guaranteed_write_wait3 = RW_MGR_GUARANTEED_WRITE_WAIT3,
- .idle = RW_MGR_IDLE,
.idle_loop1 = RW_MGR_IDLE_LOOP1,
.idle_loop2 = RW_MGR_IDLE_LOOP2,
+#if (CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_MEMTYPE == 1) /* DDR2 */
+ .emr = RW_MGR_EMR,
+ .emr2 = RW_MGR_EMR2,
+ .emr3 = RW_MGR_EMR3,
+ .init_reset_0_cke_0 = RW_MGR_INIT_CKE_0,
+ .nop = RW_MGR_NOP,
+ .refresh = RW_MGR_REFRESH,
+ .mr_calib = RW_MGR_MR_CALIB,
+ .mr_user = RW_MGR_MR_USER,
+ .mr_dll_reset = RW_MGR_MR_DLL_RESET,
+ .emr_ocd_enable = RW_MGR_EMR_OCD_ENABLE,
+#elif (CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_MEMTYPE == 2) /* DDR3 */
+ .activate_1 = RW_MGR_ACTIVATE_1,
+ .idle = RW_MGR_IDLE,
.init_reset_0_cke_0 = RW_MGR_INIT_RESET_0_CKE_0,
.init_reset_1_cke_0 = RW_MGR_INIT_RESET_1_CKE_0,
+ .mrs1 = RW_MGR_MRS1,
+ .mrs1_mirr = RW_MGR_MRS1_MIRR,
+ .mrs2 = RW_MGR_MRS2,
+ .mrs2_mirr = RW_MGR_MRS2_MIRR,
+ .mrs3 = RW_MGR_MRS3,
+ .mrs3_mirr = RW_MGR_MRS3_MIRR,
+ .refresh_all = RW_MGR_REFRESH_ALL,
+ .rreturn = RW_MGR_RETURN,
+ .sgle_read = RW_MGR_SGLE_READ,
+ .zqcl = RW_MGR_ZQCL,
+ .mrs0_dll_reset = RW_MGR_MRS0_DLL_RESET,
+ .mrs0_dll_reset_mirr = RW_MGR_MRS0_DLL_RESET_MIRR,
+ .mrs0_user = RW_MGR_MRS0_USER,
+ .mrs0_user_mirr = RW_MGR_MRS0_USER_MIRR,
+#else
+#error LPDDR2 and other DRAM types are not yet supported
+#endif
.lfsr_wr_rd_bank_0 = RW_MGR_LFSR_WR_RD_BANK_0,
.lfsr_wr_rd_bank_0_data = RW_MGR_LFSR_WR_RD_BANK_0_DATA,
.lfsr_wr_rd_bank_0_dqs = RW_MGR_LFSR_WR_RD_BANK_0_DQS,
.lfsr_wr_rd_dm_bank_0_nop = RW_MGR_LFSR_WR_RD_DM_BANK_0_NOP,
.lfsr_wr_rd_dm_bank_0_wait = RW_MGR_LFSR_WR_RD_DM_BANK_0_WAIT,
.lfsr_wr_rd_dm_bank_0_wl_1 = RW_MGR_LFSR_WR_RD_DM_BANK_0_WL_1,
- .mrs0_dll_reset = RW_MGR_MRS0_DLL_RESET,
- .mrs0_dll_reset_mirr = RW_MGR_MRS0_DLL_RESET_MIRR,
- .mrs0_user = RW_MGR_MRS0_USER,
- .mrs0_user_mirr = RW_MGR_MRS0_USER_MIRR,
- .mrs1 = RW_MGR_MRS1,
- .mrs1_mirr = RW_MGR_MRS1_MIRR,
- .mrs2 = RW_MGR_MRS2,
- .mrs2_mirr = RW_MGR_MRS2_MIRR,
- .mrs3 = RW_MGR_MRS3,
- .mrs3_mirr = RW_MGR_MRS3_MIRR,
.precharge_all = RW_MGR_PRECHARGE_ALL,
.read_b2b = RW_MGR_READ_B2B,
.read_b2b_wait1 = RW_MGR_READ_B2B_WAIT1,
.read_b2b_wait2 = RW_MGR_READ_B2B_WAIT2,
- .refresh_all = RW_MGR_REFRESH_ALL,
- .rreturn = RW_MGR_RETURN,
- .sgle_read = RW_MGR_SGLE_READ,
- .zqcl = RW_MGR_ZQCL,
.true_mem_data_mask_width = RW_MGR_TRUE_MEM_DATA_MASK_WIDTH,
.mem_address_mirroring = RW_MGR_MEM_ADDRESS_MIRRORING,
};
static const struct socfpga_sdram_misc_config misc_config = {
+#if (CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_MEMTYPE == 1) /* DDR2 */
+ .afi_clk_freq = AFI_CLK_FREQ,
+#endif
.afi_rate_ratio = AFI_RATE_RATIO,
.calib_lfifo_offset = CALIB_LFIFO_OFFSET,
.calib_vfifo_offset = CALIB_VFIFO_OFFSET,
#include <asm/io.h>
#include <asm/arch/sdram.h>
#include <errno.h>
+#include <hang.h>
#include "sequencer.h"
static const struct socfpga_sdr_rw_load_manager *sdr_rw_load_mgr_regs =
#define SKIP_DELAY_LOOP_VALUE_OR_ZERO(non_skip_value) \
((non_skip_value) & seq->skip_delay_mask)
+bool dram_is_ddr(const u8 ddr)
+{
+ const struct socfpga_sdram_config *cfg = socfpga_get_sdram_config();
+ const u8 type = (cfg->ctrl_cfg >> SDR_CTRLGRP_CTRLCFG_MEMTYPE_LSB) &
+ SDR_CTRLGRP_CTRLCFG_MEMTYPE_MASK;
+
+ if (ddr == 2 && type == 1) /* DDR2 */
+ return true;
+
+ if (ddr == 3 && type == 2) /* DDR3 */
+ return true;
+
+ return false;
+}
+
static void set_failing_group_stage(struct socfpga_sdrseq *seq,
u32 group, u32 stage, u32 substage)
{
*/
odt_mask_0 = 0x3 & ~(1 << rank);
odt_mask_1 = 0x3;
+ if (dram_is_ddr(2))
+ odt_mask_1 &= ~(1 << rank);
} else {
/*
* - Single-Slot , Dual-Rank (2 CS per DIMM)
}
break;
case 4: /* 4 Ranks */
- /* Read:
+ /*
+ * DDR3 Read, DDR2 Read/Write:
* ----------+-----------------------+
* | ODT |
- * Read From +-----------------------+
+ * +-----------------------+
* Rank | 3 | 2 | 1 | 0 |
* ----------+-----+-----+-----+-----+
* 0 | 0 | 1 | 0 | 0 |
* 3 | 0 | 0 | 1 | 0 |
* ----------+-----+-----+-----+-----+
*
- * Write:
+ * DDR3 Write:
* ----------+-----------------------+
* | ODT |
* Write To +-----------------------+
switch (rank) {
case 0:
odt_mask_0 = 0x4;
- odt_mask_1 = 0x5;
+ if (dram_is_ddr(2))
+ odt_mask_1 = 0x4;
+ else if (dram_is_ddr(3))
+ odt_mask_1 = 0x5;
break;
case 1:
odt_mask_0 = 0x8;
- odt_mask_1 = 0xA;
+ if (dram_is_ddr(2))
+ odt_mask_1 = 0x8;
+ else if (dram_is_ddr(3))
+ odt_mask_1 = 0xA;
break;
case 2:
odt_mask_0 = 0x1;
- odt_mask_1 = 0x5;
+ if (dram_is_ddr(2))
+ odt_mask_1 = 0x1;
+ else if (dram_is_ddr(3))
+ odt_mask_1 = 0x5;
break;
case 3:
odt_mask_0 = 0x2;
- odt_mask_1 = 0xA;
+ if (dram_is_ddr(2))
+ odt_mask_1 = 0x2;
+ else if (dram_is_ddr(3))
+ odt_mask_1 = 0xA;
break;
}
break;
debug("%s:%d clocks=%u ... end\n", __func__, __LINE__, clocks);
}
+static void delay_for_n_ns(struct socfpga_sdrseq *seq, const u32 ns)
+{
+ delay_for_n_mem_clocks(seq, (ns * seq->misccfg->afi_clk_freq *
+ seq->misccfg->afi_rate_ratio) / 1000);
+}
+
/**
* rw_mgr_mem_init_load_regs() - Load instruction registers
* @cntr0: Counter 0 value
}
/**
- * rw_mgr_mem_load_user() - Load user calibration values
+ * rw_mgr_mem_load_user_ddr2() - Load user calibration values for DDR2
+ * @handoff: Indicate whether this is initialization or handoff phase
+ *
+ * Load user calibration values and optionally precharge the banks.
+ */
+static void rw_mgr_mem_load_user_ddr2(struct socfpga_sdrseq *seq,
+ const int handoff)
+{
+ u32 grpaddr = SDR_PHYGRP_RWMGRGRP_ADDRESS |
+ RW_MGR_RUN_SINGLE_GROUP_OFFSET;
+ u32 r;
+
+ for (r = 0; r < seq->rwcfg->mem_number_of_ranks; r++) {
+ /* set rank */
+ set_rank_and_odt_mask(seq, r, RW_MGR_ODT_MODE_OFF);
+
+ /* precharge all banks ... */
+ writel(seq->rwcfg->precharge_all, grpaddr);
+
+ writel(seq->rwcfg->emr2, grpaddr);
+ writel(seq->rwcfg->emr3, grpaddr);
+ writel(seq->rwcfg->emr, grpaddr);
+
+ if (handoff) {
+ writel(seq->rwcfg->mr_user, grpaddr);
+ continue;
+ }
+
+ writel(seq->rwcfg->mr_dll_reset, grpaddr);
+
+ writel(seq->rwcfg->precharge_all, grpaddr);
+
+ writel(seq->rwcfg->refresh, grpaddr);
+ delay_for_n_ns(seq, 200);
+ writel(seq->rwcfg->refresh, grpaddr);
+ delay_for_n_ns(seq, 200);
+
+ writel(seq->rwcfg->mr_calib, grpaddr);
+ writel(/*seq->rwcfg->*/0x0b, grpaddr); // EMR_OCD_ENABLE
+ writel(seq->rwcfg->emr, grpaddr);
+ delay_for_n_mem_clocks(seq, 200);
+ }
+}
+
+/**
+ * rw_mgr_mem_load_user_ddr3() - Load user calibration values
* @fin1: Final instruction 1
* @fin2: Final instruction 2
* @precharge: If 1, precharge the banks at the end
*
* Load user calibration values and optionally precharge the banks.
*/
-static void rw_mgr_mem_load_user(struct socfpga_sdrseq *seq,
+static void rw_mgr_mem_load_user_ddr3(struct socfpga_sdrseq *seq,
const u32 fin1, const u32 fin2,
const int precharge)
{
}
}
+/**
+ * rw_mgr_mem_load_user() - Load user calibration values
+ * @fin1: Final instruction 1
+ * @fin2: Final instruction 2
+ * @precharge: If 1, precharge the banks at the end
+ *
+ * Load user calibration values and optionally precharge the banks.
+ */
+static void rw_mgr_mem_load_user(struct socfpga_sdrseq *seq,
+ const u32 fin1, const u32 fin2,
+ const int precharge)
+{
+ if (dram_is_ddr(2))
+ rw_mgr_mem_load_user_ddr2(seq, precharge);
+ else if (dram_is_ddr(3))
+ rw_mgr_mem_load_user_ddr3(seq, fin1, fin2, precharge);
+ else
+ hang();
+}
/**
* rw_mgr_mem_initialize() - Initialize RW Manager
*
debug("%s:%d\n", __func__, __LINE__);
/* The reset / cke part of initialization is broadcasted to all ranks */
- writel(RW_MGR_RANK_ALL, SDR_PHYGRP_RWMGRGRP_ADDRESS |
- RW_MGR_SET_CS_AND_ODT_MASK_OFFSET);
+ if (dram_is_ddr(3)) {
+ writel(RW_MGR_RANK_ALL, SDR_PHYGRP_RWMGRGRP_ADDRESS |
+ RW_MGR_SET_CS_AND_ODT_MASK_OFFSET);
+ }
/*
* Here's how you load register for a loop
/* Indicate that memory is stable. */
writel(1, &phy_mgr_cfg->reset_mem_stbl);
- /*
- * transition the RESET to high
- * Wait for 500us
- */
+ if (dram_is_ddr(2)) {
+ writel(seq->rwcfg->nop, SDR_PHYGRP_RWMGRGRP_ADDRESS |
+ RW_MGR_RUN_SINGLE_GROUP_OFFSET);
- /*
- * 500us @ 266MHz (3.75 ns) ~ 134000 clock cycles
- * If a and b are the number of iteration in 2 nested loops
- * it takes the following number of cycles to complete the operation
- * number_of_cycles = ((2 + n) * a + 2) * b
- * where n is the number of instruction in the inner loop
- * One possible solution is n = 2 , a = 131 , b = 256 => a = 83,
- * b = FF
- */
- rw_mgr_mem_init_load_regs(seq, seq->misccfg->treset_cntr0_val,
- seq->misccfg->treset_cntr1_val,
- seq->misccfg->treset_cntr2_val,
- seq->rwcfg->init_reset_1_cke_0);
+ /* Bring up clock enable. */
- /* Bring up clock enable. */
+ /* tXRP < 400 ck cycles */
+ delay_for_n_ns(seq, 400);
+ } else if (dram_is_ddr(3)) {
+ /*
+ * transition the RESET to high
+ * Wait for 500us
+ */
+
+ /*
+ * 500us @ 266MHz (3.75 ns) ~ 134000 clock cycles
+ * If a and b are the number of iteration in 2 nested loops
+ * it takes the following number of cycles to complete the
+ * operation number_of_cycles = ((2 + n) * a + 2) * b
+ * where n is the number of instruction in the inner loop
+ * One possible solution is
+ * n = 2 , a = 131 , b = 256 => a = 83, b = FF
+ */
+ rw_mgr_mem_init_load_regs(seq, seq->misccfg->treset_cntr0_val,
+ seq->misccfg->treset_cntr1_val,
+ seq->misccfg->treset_cntr2_val,
+ seq->rwcfg->init_reset_1_cke_0);
+ /* Bring up clock enable. */
- /* tXRP < 250 ck cycles */
- delay_for_n_mem_clocks(seq, 250);
+ /* tXRP < 250 ck cycles */
+ delay_for_n_mem_clocks(seq, 250);
+ }
rw_mgr_mem_load_user(seq, seq->rwcfg->mrs0_dll_reset_mirr,
seq->rwcfg->mrs0_dll_reset, 0);
&sdr_reg_file->delays);
/* mux delay */
- writel((seq->rwcfg->idle << 24) | (seq->rwcfg->activate_1 << 16) |
- (seq->rwcfg->sgle_read << 8) | (seq->rwcfg->precharge_all << 0),
- &sdr_reg_file->trk_rw_mgr_addr);
+ if (dram_is_ddr(2)) {
+ writel(0, &sdr_reg_file->trk_rw_mgr_addr);
+ } else if (dram_is_ddr(3)) {
+ writel((seq->rwcfg->idle << 24) |
+ (seq->rwcfg->activate_1 << 16) |
+ (seq->rwcfg->sgle_read << 8) |
+ (seq->rwcfg->precharge_all << 0),
+ &sdr_reg_file->trk_rw_mgr_addr);
+ }
writel(seq->rwcfg->mem_if_read_dqs_width,
&sdr_reg_file->trk_read_dqs_width);
/* trefi [7:0] */
- writel((seq->rwcfg->refresh_all << 24) | (1000 << 0),
- &sdr_reg_file->trk_rfsh);
+ if (dram_is_ddr(2)) {
+ writel(1000 << 0, &sdr_reg_file->trk_rfsh);
+ } else if (dram_is_ddr(3)) {
+ writel((seq->rwcfg->refresh_all << 24) | (1000 << 0),
+ &sdr_reg_file->trk_rfsh);
+ }
}
int sdram_calibration_full(struct socfpga_sdr *sdr)