* [PATCH 3/6] ppc: mpc8xxx: add DDR3 support
2014-03-13 18:09 [PATCH 0/6] ppc: add Freescale P1022DS board support Renaud Barbier
2014-03-13 18:09 ` [PATCH 1/6] ppc: add SoC support for Freescale P1022 Renaud Barbier
2014-03-13 18:09 ` [PATCH 2/6] common: DDR3 SPD verification support Renaud Barbier
@ 2014-03-13 18:10 ` Renaud Barbier
2014-03-13 18:10 ` [PATCH 4/6] ppc: add Freescale P1022DS board support Renaud Barbier
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Renaud Barbier @ 2014-03-13 18:10 UTC (permalink / raw)
To: barebox
Add DDR3 support into the MPC8xxx DDR driver.
To avoid confusion, the function set_ddr_sdram_mode is renamed
set_ddr2_sdram_mode.
Checking for errors is simplified in the DDR2 DIMM parameters
computation to be consistent with DDR3.
This code is derived from the files found in directory drivers/ddr/fsl
from U-Boot version git-be937b5.
Signed-off-by: Renaud Barbier <renaud.barbier@ge.com>
---
arch/ppc/ddr-8xxx/Makefile | 4 +-
arch/ppc/ddr-8xxx/common_timing_params.h | 2 +
arch/ppc/ddr-8xxx/ctrl_regs.c | 429 +++++++++++++++++++--
arch/ppc/ddr-8xxx/ddr.h | 15 +-
arch/ppc/ddr-8xxx/ddr2_dimm_params.c | 9 +-
arch/ppc/ddr-8xxx/ddr3_dimm_params.c | 193 +++++++++
.../ppc/ddr-8xxx/{ddr2_setctrl.c => ddr_setctrl.c} | 44 ++-
arch/ppc/ddr-8xxx/lc_common_dimm_params.c | 103 +++--
arch/ppc/ddr-8xxx/main.c | 12 +-
arch/ppc/ddr-8xxx/options.c | 58 ++-
arch/ppc/include/asm/fsl_ddr_dimm_params.h | 9 +
arch/ppc/include/asm/fsl_ddr_sdram.h | 35 +-
12 files changed, 813 insertions(+), 100 deletions(-)
create mode 100644 arch/ppc/ddr-8xxx/ddr3_dimm_params.c
rename arch/ppc/ddr-8xxx/{ddr2_setctrl.c => ddr_setctrl.c} (53%)
diff --git a/arch/ppc/ddr-8xxx/Makefile b/arch/ppc/ddr-8xxx/Makefile
index 54cb7ce..43ae3a4 100644
--- a/arch/ppc/ddr-8xxx/Makefile
+++ b/arch/ppc/ddr-8xxx/Makefile
@@ -1,2 +1,4 @@
obj-y += main.o util.o ctrl_regs.o options.o lc_common_dimm_params.o
-obj-$(CONFIG_FSL_DDR2) += ddr2_dimm_params.o ddr2_setctrl.o
+obj-y += ddr_setctrl.o
+obj-$(CONFIG_FSL_DDR2) += ddr2_dimm_params.o
+obj-$(CONFIG_FSL_DDR3) += ddr3_dimm_params.o
diff --git a/arch/ppc/ddr-8xxx/common_timing_params.h b/arch/ppc/ddr-8xxx/common_timing_params.h
index b262193..85a1e28 100644
--- a/arch/ppc/ddr-8xxx/common_timing_params.h
+++ b/arch/ppc/ddr-8xxx/common_timing_params.h
@@ -23,6 +23,7 @@ struct common_timing_params_s {
uint32_t tRRD_ps; /* maximum = 63750 ps */
uint32_t tRC_ps; /* maximum = 254 ns + .75 ns = 254750 ps */
uint32_t refresh_rate_ps;
+ uint32_t extended_op_srt;
uint32_t tIS_ps; /* byte 32, spd->ca_setup */
uint32_t tIH_ps; /* byte 33, spd->ca_hold */
uint32_t tDS_ps; /* byte 34, spd->data_setup */
@@ -36,6 +37,7 @@ struct common_timing_params_s {
uint32_t additive_latency;
uint32_t all_DIMMs_burst_lengths_bitmask;
uint32_t all_DIMMs_registered;
+ uint32_t all_DIMMs_unbuffered;
uint32_t all_DIMMs_ECC_capable;
uint64_t total_mem;
uint64_t base_address;
diff --git a/arch/ppc/ddr-8xxx/ctrl_regs.c b/arch/ppc/ddr-8xxx/ctrl_regs.c
index 1abc826..e3d43ab 100644
--- a/arch/ppc/ddr-8xxx/ctrl_regs.c
+++ b/arch/ppc/ddr-8xxx/ctrl_regs.c
@@ -8,7 +8,7 @@
*/
/*
- * Generic driver for Freescale DDR2 memory controller.
+ * Generic driver for Freescale DDR2/DDR3 memory controller.
* Based on code from spd_sdram.c
* Author: James Yang [at freescale.com]
*/
@@ -17,6 +17,33 @@
#include <asm/fsl_ddr_sdram.h>
#include "ddr.h"
+static uint32_t compute_cas_write_latency(void)
+{
+ uint32_t cwl;
+ const uint32_t mclk_ps = get_memory_clk_period_ps();
+
+ if (mclk_ps >= 2500)
+ cwl = 5;
+ else if (mclk_ps >= 1875)
+ cwl = 6;
+ else if (mclk_ps >= 1500)
+ cwl = 7;
+ else if (mclk_ps >= 1250)
+ cwl = 8;
+ else if (mclk_ps >= 1070)
+ cwl = 9;
+ else if (mclk_ps >= 935)
+ cwl = 10;
+ else if (mclk_ps >= 833)
+ cwl = 11;
+ else if (mclk_ps >= 750)
+ cwl = 12;
+ else
+ cwl = 12;
+
+ return cwl;
+}
+
static void set_csn_config(int dimm_number, int i,
struct fsl_ddr_cfg_regs_s *ddr,
const struct memctl_options_s *popts,
@@ -81,40 +108,91 @@ static void set_csn_config(int dimm_number, int i,
}
static void set_timing_cfg_0(struct fsl_ddr_cfg_regs_s *ddr,
- const struct memctl_options_s *popts)
+ const struct memctl_options_s *popts,
+ const struct dimm_params_s *dimm)
{
- uint32_t trwt_mclk = 0;
-
- if (popts->trwt_override)
- trwt_mclk = popts->trwt;
+ uint32_t trwt_mclk = 0, twrt_mclk = 0, act_pd_exit_mclk,
+ pre_pd_exit_mclk, taxpd_mclk, tmrd_mclk, txp,
+ data_rate = fsl_get_ddr_freq(0);
+
+ if (popts->sdram_type == SDRAM_TYPE_DDR2) {
+ act_pd_exit_mclk = popts->txard;
+ pre_pd_exit_mclk = popts->txp;
+ taxpd_mclk = popts->taxpd;
+ tmrd_mclk = popts->tmrd;
+ } else {
+ /*
+ * tXARD is not part of the DDR3 specification, use the
+ * parameter txp instead of it. That is:
+ * txp=max(3nCK, 7.5ns). As well, use tAXPD=1.
+ */
+ txp = max_t(uint32_t, (get_memory_clk_period_ps() * 3), 7500);
+ data_rate = fsl_get_ddr_freq(0);
+ tmrd_mclk = 4;
+
+ /* for faster clock, need more time for data setup */
+ if (popts->trwt_override)
+ trwt_mclk = popts->trwt;
+ else if (data_rate / 1000000 > 1800)
+ trwt_mclk = 2;
+ else
+ trwt_mclk = 0;
+
+ if (data_rate / 1000000 > 1150)
+ twrt_mclk = 1;
+ else
+ twrt_mclk = 0;
+
+ taxpd_mclk = 1;
+ if (popts->dynamic_power == 0) {
+ act_pd_exit_mclk = 1;
+ pre_pd_exit_mclk = 1;
+ } else {
+ /* act_pd_exit_mclk = tXARD, see above */
+ act_pd_exit_mclk = picos_to_mclk(txp);
+ /* Mode register MR0[A12] is '1' - fast exit */
+ pre_pd_exit_mclk = act_pd_exit_mclk;
+ }
+ }
ddr->timing_cfg_0 = (((trwt_mclk & 0x3) << 30)
- | ((popts->txard & 0x7) << 20)
- | ((popts->txp & 0xF) << 16)
- | ((popts->taxpd & 0xf) << 8)
- | ((popts->tmrd & 0xf) << 0));
+ | ((twrt_mclk & 0x3) << 28)
+ | ((act_pd_exit_mclk & 0xf) << 20)
+ | ((pre_pd_exit_mclk & 0xf) << 16)
+ | ((taxpd_mclk & 0xf) << 8)
+ | ((tmrd_mclk & 0x1f) << 0)
+ );
}
static void set_timing_cfg_3(struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts,
const struct common_timing_params_s *dimm,
- uint32_t cas_latency)
+ uint32_t cas_latency, uint32_t additive_latency)
{
- uint32_t ext_pretoact, ext_acttopre, ext_acttorw, ext_refrec;
+ uint32_t ext_pretoact, ext_acttopre, ext_acttorw, ext_refrec, ext_wrrec;
ext_pretoact = picos_to_mclk(dimm->tRP_ps) >> 4;
ext_acttopre = picos_to_mclk(dimm->tRAS_ps) >> 4;
ext_acttorw = picos_to_mclk(dimm->tRCD_ps) >> 4;
cas_latency = ((cas_latency << 1) - 1) >> 4;
+ additive_latency = additive_latency >> 4;
ext_refrec = (picos_to_mclk(dimm->tRFC_ps) - 8) >> 4;
+ /* ext_wrrec only deals with 16 clock and above, or 14 with OTF */
+ ext_wrrec = (picos_to_mclk(dimm->tWR_ps) +
+ (popts->otf_burst_chop_en ? 2 : 0)) >> 4;
ddr->timing_cfg_3 = (((ext_pretoact & 0x1) << 28)
- | ((ext_acttopre & 0x2) << 24)
+ | ((ext_acttopre & 0x3) << 24)
| ((ext_acttorw & 0x1) << 22)
| ((ext_refrec & 0x1F) << 16)
- | ((cas_latency & 0x3) << 12));
+ | ((cas_latency & 0x3) << 12)
+ | ((additive_latency & 0x1) << 10)
+ | ((ext_wrrec & 0x1) << 8)
+ );
}
static void set_timing_cfg_1(struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts,
const struct common_timing_params_s *dimm,
uint32_t cas_latency)
{
@@ -152,10 +230,19 @@ static void set_timing_cfg_1(struct fsl_ddr_cfg_regs_s *ddr,
wrrec_mclk = picos_to_mclk(dimm->tWR_ps);
if (wrrec_mclk <= 16)
wrrec_mclk = wrrec_table[wrrec_mclk - 1];
+ if (popts->otf_burst_chop_en)
+ wrrec_mclk += 2;
wrtord_mclk = picos_to_mclk(dimm->tWTR_ps);
- if (wrtord_mclk < 2)
- wrtord_mclk = 2;
+ if (popts->sdram_type == SDRAM_TYPE_DDR2) {
+ wrtord_mclk = max_t(uint32_t, wrtord_mclk, 2);
+ } else {
+ wrtord_mclk = max_t(uint32_t, wrtord_mclk, 4);
+ acttoact_mclk = max_t(uint32_t, acttoact_mclk, 4);
+ }
+
+ if (popts->otf_burst_chop_en)
+ wrtord_mclk += 2;
ddr->timing_cfg_1 = (((pretoact_mclk & 0x0F) << 28)
| ((acttopre_mclk & 0x0F) << 24)
@@ -176,11 +263,16 @@ static void set_timing_cfg_2(struct fsl_ddr_cfg_regs_s *ddr,
cpo = popts->cpo_override;
rd_to_pre = picos_to_mclk(dimm->tRTP_ps);
- if (rd_to_pre < 2)
- rd_to_pre = 2;
+ if (popts->sdram_type == SDRAM_TYPE_DDR2) {
+ cas_latency = cas_latency - 1;
+ rd_to_pre = max_t(uint32_t, rd_to_pre, 2);
+ } else {
+ cas_latency = compute_cas_write_latency();
+ rd_to_pre = max_t(uint32_t, rd_to_pre, 4);
+ }
- if (additive_latency)
- rd_to_pre += additive_latency;
+ if (popts->otf_burst_chop_en)
+ rd_to_pre += 2;
wr_data_delay = popts->write_data_delay;
cke_pls = picos_to_mclk(popts->tCKE_clock_pulse_width_ps);
@@ -188,7 +280,7 @@ static void set_timing_cfg_2(struct fsl_ddr_cfg_regs_s *ddr,
ddr->timing_cfg_2 = (((additive_latency & 0xf) << 28)
| ((cpo & 0x1f) << 23)
- | (((cas_latency - 1) & 0xf) << 19)
+ | ((cas_latency & 0xf) << 19)
| ((rd_to_pre & 7) << 13)
| ((wr_data_delay & 7) << 10)
| ((cke_pls & 0x7) << 6)
@@ -199,7 +291,8 @@ static void set_ddr_sdram_cfg(struct fsl_ddr_cfg_regs_s *ddr,
const struct memctl_options_s *popts,
const struct common_timing_params_s *dimm)
{
- uint32_t mem_en, sren, ecc_en, sdram_type, dyn_pwr, dbw, twoT_en, hse;
+ uint32_t mem_en, sren, ecc_en, sdram_type, dyn_pwr, dbw, twoT_en, hse,
+ threet_en, eight_be = 0;
mem_en = 1;
sren = popts->self_refresh_in_sleep;
@@ -208,15 +301,16 @@ static void set_ddr_sdram_cfg(struct fsl_ddr_cfg_regs_s *ddr,
else
ecc_en = 0;
- if (popts->sdram_type)
- sdram_type = popts->sdram_type;
- else
- sdram_type = FSL_SDRAM_TYPE;
-
+ sdram_type = popts->sdram_type;
twoT_en = popts->twoT_en;
dyn_pwr = popts->dynamic_power;
dbw = popts->data_bus_width;
hse = popts->half_strength_driver_enable;
+ threet_en = popts->threet_en;
+
+ if (sdram_type == SDRAM_TYPE_DDR3)
+ if ((popts->burst_length == DDR_BL8) || (dbw == 1))
+ eight_be = 1;
ddr->ddr_sdram_cfg = (((mem_en & 0x1) << 31)
| ((sren & 0x1) << 30)
@@ -224,6 +318,8 @@ static void set_ddr_sdram_cfg(struct fsl_ddr_cfg_regs_s *ddr,
| ((sdram_type & 0x7) << 24)
| ((dyn_pwr & 0x1) << 21)
| ((dbw & 0x3) << 19)
+ | ((eight_be & 0x1) << 18)
+ | ((threet_en & 0x1) << 16)
| ((twoT_en & 0x1) << 15)
| ((hse & 0x1) << 3));
}
@@ -232,7 +328,8 @@ static void set_ddr_sdram_cfg_2(struct fsl_ddr_cfg_regs_s *ddr,
const struct memctl_options_s *popts)
{
struct ddr_board_info_s *bi = popts->board_info;
- uint32_t i, dll_rst_dis, dqs_cfg, odt_cfg = 0, num_pr, d_init = 0;
+ uint32_t i, dll_rst_dis, dqs_cfg, odt_cfg = 0, num_pr, d_init = 0,
+ obc_cfg = 0, x4_en, md_en = 0, rcw_en = 0;
dll_rst_dis = popts->dll_rst_dis;
dqs_cfg = popts->DQS_config;
@@ -256,11 +353,48 @@ static void set_ddr_sdram_cfg_2(struct fsl_ddr_cfg_regs_s *ddr,
ddr->ddr_data_init = popts->data_init;
}
+ if (popts->sdram_type == SDRAM_TYPE_DDR3) {
+ obc_cfg = popts->otf_burst_chop_en;
+ md_en = popts->mirrored_dimm;
+ }
+
+ x4_en = popts->x4_en ? 1 : 0;
+
ddr->ddr_sdram_cfg_2 = (((dll_rst_dis & 0x1) << 29)
| ((dqs_cfg & 0x3) << 26)
| ((odt_cfg & 0x3) << 21)
| ((num_pr & 0xf) << 12)
- | ((d_init & 0x1) << 4));
+ | (x4_en << 10)
+ | ((obc_cfg & 0x1) << 6)
+ | ((d_init & 0x1) << 4)
+ | ((rcw_en & 0x1) << 2)
+ | ((md_en & 0x1) << 0)
+ );
+}
+
+static void set_ddr_sdram_mode_2(struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts,
+ const struct common_timing_params_s *dimm)
+{
+ uint16_t esdmode2;
+ uint32_t rtt_wr, srt = 0, cwl;
+
+ cwl = compute_cas_write_latency() - 5;
+
+ if (popts->rtt_override)
+ rtt_wr = popts->rtt_wr_override_value;
+ else
+ rtt_wr = popts->cs_local_opts[0].odt_rtt_wr;
+
+ if (dimm->extended_op_srt)
+ srt = dimm->extended_op_srt;
+
+ esdmode2 = (((rtt_wr & 0x3) << 9)
+ | ((srt & 0x1) << 7)
+ | ((cwl & 0x7) << 3)
+ );
+
+ ddr->ddr_sdram_mode_2 = (esdmode2 & 0xffff) << 16;
}
static void
@@ -277,12 +411,107 @@ set_ddr_sdram_interval(struct fsl_ddr_cfg_regs_s *ddr,
ddr->ddr_sdram_interval = (((refint & 0xFFFF) << 16)
| ((bstopre & 0x3FFF) << 0));
}
+void set_ddr3_sdram_mode(struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts,
+ const struct common_timing_params_s *dimm,
+ uint32_t cas_latency, uint32_t additive_latency)
+{
+ uint16_t esdmode, sdmode;
+ /* Mode Register - MR1 */
+ uint32_t rtt, al;
+ /* Mode Register - MR0 */
+ uint32_t dll_on, wr = 0, dll_rst, mode, caslat = 4, bt, bl, wr_mclk;
+ /*
+ * DDR_SDRAM_MODE doesn't support 9,11,13,15
+ * Please refer JEDEC Standard No. 79-3E for Mode Register MR0
+ * for this table
+ */
+ static const u8 wr_table[] = {1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 0, 0};
+ uint8_t cas_latency_table[] = { /* From 5 to 16 clocks */
+ 0x2, 0x4, 0x6, 0x8, 0xa, 0xc, 0xe, 0x1, 0x3, 0x5, 0x7, 0x9,
+ };
+ const unsigned int mclk_ps = get_memory_clk_period_ps();
+
+ if (popts->rtt_override)
+ rtt = popts->rtt_override_value;
+ else
+ rtt = popts->cs_local_opts[0].odt_rtt_norm;
+
+ if (additive_latency == (cas_latency - 1))
+ al = 1;
+ else if (additive_latency == (cas_latency - 2))
+ al = 2;
+ else
+ al = 0;
+
+ /*
+ * The esdmode value will also be used for writing
+ * MR1 during write leveling for DDR3, although the
+ * bits specifically related to the write leveling
+ * scheme will be handled automatically by the DDR
+ * controller. So wrlvl_en is set to 0 here.
+ */
+ esdmode = (((rtt & 0x4) << 7)
+ | ((rtt & 0x2) << 5)
+ | ((al & 0x3) << 3)
+ | ((rtt & 0x1) << 2)
+ );
-static void set_ddr_sdram_mode(struct fsl_ddr_cfg_regs_s *ddr,
+ /*
+ * DLL control for precharge PD
+ * 0=slow exit DLL off (tXPDLL)
+ * 1=fast exit DLL on (tXP)
+ */
+ dll_on = 1;
+
+ wr_mclk = (dimm->tWR_ps + mclk_ps - 1) / mclk_ps;
+ if (wr_mclk <= 16)
+ wr = wr_table[wr_mclk - 5];
+
+ dll_rst = 0; /* dll no reset */
+ mode = 0; /* normal mode */
+
+ /* look up table to get the cas latency bits */
+ if (cas_latency >= 5 && cas_latency <= 16)
+ caslat = cas_latency_table[cas_latency - 5];
+
+ /* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */
+ bt = 0;
+
+ switch (popts->burst_length) {
+ case DDR_BL8:
+ bl = 0;
+ break;
+ case DDR_OTF:
+ bl = 1;
+ break;
+ case DDR_BC4:
+ bl = 2;
+ break;
+ default:
+ bl = 1;
+ break;
+ }
+
+ sdmode = (((dll_on & 0x1) << 12)
+ | ((wr & 0x7) << 9)
+ | ((dll_rst & 0x1) << 8)
+ | ((mode & 0x1) << 7)
+ | (((caslat >> 1) & 0x7) << 4)
+ | ((bt & 0x1) << 3)
+ | ((caslat & 1) << 2)
+ | ((bl & 0x3) << 0)
+ );
+
+ ddr->ddr_sdram_mode = (((esdmode & 0xffff) << 16)
+ | ((sdmode & 0xffff) << 0)
+ );
+}
+
+void set_ddr2_sdram_mode(struct fsl_ddr_cfg_regs_s *ddr,
const struct memctl_options_s *popts,
const struct common_timing_params_s *dimm,
- uint32_t cas_latency,
- uint32_t additive_latency)
+ uint32_t cas_latency, uint32_t additive_latency)
{
uint16_t esdmode, sdmode;
uint32_t dqs_en, rtt, al, wr, bl;
@@ -342,6 +571,19 @@ static void set_ddr_sdram_mode(struct fsl_ddr_cfg_regs_s *ddr,
| ((sdmode & 0xFFFF) << 0));
}
+void set_ddrx_sdram_mode(struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts,
+ const struct common_timing_params_s *dimm,
+ uint32_t cas_latency, uint32_t additive_latency)
+{
+ if (popts->sdram_type == SDRAM_TYPE_DDR2)
+ set_ddr2_sdram_mode(ddr, popts, dimm, cas_latency,
+ additive_latency);
+ else
+ set_ddr3_sdram_mode(ddr, popts, dimm, cas_latency,
+ additive_latency);
+}
+
uint32_t check_fsl_memctl_config_regs(const struct fsl_ddr_cfg_regs_s *ddr)
{
/*
@@ -355,6 +597,98 @@ uint32_t check_fsl_memctl_config_regs(const struct fsl_ddr_cfg_regs_s *ddr)
return 0;
}
+static void set_timing_cfg_4(struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts)
+{
+ uint32_t rrt = 0, wwt = 0, dll_lock = 1;
+
+ if (popts->burst_length != DDR_BL8)
+ rrt = wwt = 2;
+
+ ddr->timing_cfg_4 = (((rrt & 0xf) << 20)
+ | ((wwt & 0xf) << 16)
+ | (dll_lock & 0x3)
+ );
+}
+
+static void set_timing_cfg_5(struct fsl_ddr_cfg_regs_s *ddr,
+ const struct memctl_options_s *popts,
+ uint32_t cas_latency)
+{
+ uint32_t rodt_on, rodt_off = 4, wodt_on = 1, wodt_off = 4;
+
+ /* rodt_on = timing_cfg_1[caslat] - timing_cfg_2[wrlat] + 1 */
+ rodt_on = cas_latency - ((ddr->timing_cfg_2 & 0x00780000) >> 19) + 1;
+
+ ddr->timing_cfg_5 = (((rodt_on & 0x1f) << 24)
+ | ((rodt_off & 0x7) << 20)
+ | ((wodt_on & 0x1f) << 12)
+ | ((wodt_off & 0x7) << 8)
+ );
+}
+
+static void set_ddr_zq_cntl(struct fsl_ddr_cfg_regs_s *ddr, uint32_t zq_en)
+{
+ uint32_t zqinit = 0, zqoper = 0, zqcs = 0;
+
+ if (zq_en) {
+ zqinit = 9;
+ zqoper = 8;
+ zqcs = 6;
+ }
+
+ ddr->ddr_zq_cntl = (((zq_en & 0x1) << 31)
+ | ((zqinit & 0xf) << 24)
+ | ((zqoper & 0xf) << 16)
+ | ((zqcs & 0xf) << 8)
+ );
+}
+
+static void set_ddr_wrlvl_cntl(struct fsl_ddr_cfg_regs_s *ddr,
+ uint32_t wrlvl_en, const struct memctl_options_s *popts)
+{
+ uint32_t wrlvl_mrd = 0, wrlvl_odten = 0, wrlvl_dqsen = 0,
+ wrlvl_wlr = 0, wrlvl_start = 0, wrlvl_smpl = 0;
+
+ /* Enable write leveling for DDR3 due to fly-by topology */
+ if (wrlvl_en) {
+ wrlvl_mrd = 0x6;
+ wrlvl_odten = 0x7;
+ wrlvl_dqsen = 0x5;
+ /*
+ * Write leveling sample time at least need 6 clocks
+ * higher than tWLO to allow enough time for progagation
+ * delay and sampling the prime data bits.
+ */
+ wrlvl_smpl = 0xf;
+ /*
+ * Write leveling repetition time. At least tWLO + 6 clocks
+ * Set it to 64
+ */
+ wrlvl_wlr = 0x6;
+ /*
+ * Write leveling start time
+ * The value use for the DQS_ADJUST for the first sample
+ * when write leveling is enabled. It probably needs to be
+ * overriden per platform.
+ */
+ wrlvl_start = 0x8;
+ if (popts->wrlvl_override) {
+ wrlvl_smpl = popts->wrlvl_sample;
+ wrlvl_start = popts->wrlvl_start;
+ }
+ }
+
+ ddr->ddr_wrlvl_cntl = (((wrlvl_en & 0x1) << 31)
+ | ((wrlvl_mrd & 0x7) << 24)
+ | ((wrlvl_odten & 0x7) << 20)
+ | ((wrlvl_dqsen & 0x7) << 16)
+ | ((wrlvl_smpl & 0xf) << 12)
+ | ((wrlvl_wlr & 0x7) << 8)
+ | ((wrlvl_start & 0x1f) << 0)
+ );
+}
+
uint32_t
compute_fsl_memctl_config_regs(const struct memctl_options_s *popts,
struct fsl_ddr_cfg_regs_s *ddr,
@@ -364,7 +698,7 @@ compute_fsl_memctl_config_regs(const struct memctl_options_s *popts,
{
struct ddr_board_info_s *binfo = popts->board_info;
uint32_t cas_latency, additive_latency, i, cs_per_dimm,
- dimm_number;
+ dimm_number, zq_en, wrlvl_en, sr_it = 0;
uint64_t ea, sa, rank_density;
if (dimm == NULL)
@@ -383,6 +717,9 @@ compute_fsl_memctl_config_regs(const struct memctl_options_s *popts,
else
additive_latency = dimm->additive_latency;
+ if (popts->auto_self_refresh_en)
+ sr_it = popts->sr_it;
+
/* Chip Select Memory Bounds (CSn_BNDS) */
for (i = 0; i < binfo->cs_per_ctrl; i++) {
cs_per_dimm = binfo->cs_per_ctrl / binfo->dimm_slots_per_ctrl;
@@ -405,21 +742,37 @@ compute_fsl_memctl_config_regs(const struct memctl_options_s *popts,
sa >>= 24;
ea >>= 24;
- ddr->cs[i].bnds = (((sa & 0xFFF) << 16) | ((ea & 0xFFF) << 0));
+ ddr->cs[i].bnds =
+ (((sa & 0xffff) << 16) | ((ea & 0xffff) << 0));
set_csn_config(dimm_number, i, ddr, popts, dimmp);
}
- set_timing_cfg_0(ddr, popts);
- set_timing_cfg_3(ddr, dimm, cas_latency);
- set_timing_cfg_1(ddr, dimm, cas_latency);
+ set_timing_cfg_0(ddr, popts, dimmp);
+ set_timing_cfg_3(ddr, popts, dimm, cas_latency, additive_latency);
+ set_timing_cfg_1(ddr, popts, dimm, cas_latency);
set_timing_cfg_2(ddr, popts, dimm, cas_latency, additive_latency);
+
+ ddr->ddr_cdr1 = popts->ddr_cdr1;
+ ddr->ddr_cdr1 = popts->ddr_cdr2;
+
set_ddr_sdram_cfg(ddr, popts, dimm);
set_ddr_sdram_cfg_2(ddr, popts);
- set_ddr_sdram_mode(ddr, popts, dimm, cas_latency, additive_latency);
+ set_ddrx_sdram_mode(ddr, popts, dimm, cas_latency, additive_latency);
+ if (popts->sdram_type == SDRAM_TYPE_DDR3) {
+ set_ddr_sdram_mode_2(ddr, popts, dimm);
+ set_timing_cfg_4(ddr, popts);
+ set_timing_cfg_5(ddr, popts, cas_latency);
+ zq_en = (popts->zq_en) ? 1 : 0;
+ set_ddr_zq_cntl(ddr, zq_en);
+ wrlvl_en = (popts->wrlvl_en) ? 1 : 0;
+ set_ddr_wrlvl_cntl(ddr, wrlvl_en, popts);
+ }
set_ddr_sdram_interval(ddr, popts, dimm);
ddr->ddr_data_init = popts->data_init;
ddr->ddr_sdram_clk_cntl = (popts->clk_adjust & 0xF) << 23;
+ ddr->ddr_sr_cntr = (sr_it & 0xf) << 16;
+
return check_fsl_memctl_config_regs(ddr);
}
diff --git a/arch/ppc/ddr-8xxx/ddr.h b/arch/ppc/ddr-8xxx/ddr.h
index 6574500..2ef87f2 100644
--- a/arch/ppc/ddr-8xxx/ddr.h
+++ b/arch/ppc/ddr-8xxx/ddr.h
@@ -47,6 +47,17 @@ struct fsl_ddr_cfg_regs_s {
uint32_t ddr_sdram_clk_cntl;
uint32_t ddr_init_addr;
uint32_t ddr_init_ext_addr;
+ uint32_t timing_cfg_4;
+ uint32_t timing_cfg_5;
+ uint32_t ddr_zq_cntl;
+ uint32_t ddr_wrlvl_cntl;
+ uint32_t ddr_wrlvl_cntl_2;
+ uint32_t ddr_wrlvl_cntl_3;
+ uint32_t ddr_sr_cntr;
+ uint32_t ddr_sdram_rcw_1;
+ uint32_t ddr_sdram_rcw_2;
+ uint32_t ddr_cdr1;
+ uint32_t ddr_cdr2;
uint32_t err_disable;
uint32_t err_int_en;
uint32_t debug[32];
@@ -82,8 +93,8 @@ uint32_t compute_fsl_memctl_config_regs(
uint32_t compute_dimm_parameters(
const generic_spd_eeprom_t *spdin,
struct dimm_params_s *pdimm);
-uint32_t compute_lowest_common_dimm_parameters(
- const struct dimm_params_s *dimm_params,
+void compute_lowest_common_dimm_parameters(
+ const struct fsl_ddr_info_s *pinfo,
struct common_timing_params_s *outpdimm,
uint32_t number_of_dimms);
uint32_t populate_memctl_options(
diff --git a/arch/ppc/ddr-8xxx/ddr2_dimm_params.c b/arch/ppc/ddr-8xxx/ddr2_dimm_params.c
index b36a888..cc7f3fa 100644
--- a/arch/ppc/ddr-8xxx/ddr2_dimm_params.c
+++ b/arch/ppc/ddr-8xxx/ddr2_dimm_params.c
@@ -193,17 +193,12 @@ compute_dimm_parameters(const generic_spd_eeprom_t *spdin,
const struct ddr2_spd_eeprom_s *spd = spdin;
uint32_t retval;
- if (!spd->mem_type) {
- memset(pdimm, 0, sizeof(struct dimm_params_s));
- goto error;
- }
-
if (spd->mem_type != SPD_MEMTYPE_DDR2)
goto error;
retval = ddr2_spd_checksum_pass(spd);
if (retval)
- goto spd_err;
+ goto error;
/*
* The part name in ASCII in the SPD EEPROM is not null terminated.
@@ -298,6 +293,4 @@ compute_dimm_parameters(const generic_spd_eeprom_t *spdin,
return 0;
error:
return 1;
-spd_err:
- return 2;
}
diff --git a/arch/ppc/ddr-8xxx/ddr3_dimm_params.c b/arch/ppc/ddr-8xxx/ddr3_dimm_params.c
new file mode 100644
index 0000000..d510c5b
--- /dev/null
+++ b/arch/ppc/ddr-8xxx/ddr3_dimm_params.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ * Dave Liu <daveliu@freescale.com>
+ *
+ * calculate the organization and timing parameter
+ * from ddr3 spd, please refer to the spec
+ * JEDEC standard No.21-C 4_01_02_11R18.pdf
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/fsl_ddr_sdram.h>
+#include "ddr.h"
+
+/*
+ * Calculate the Density of each Physical Rank.
+ * Returned size is in bytes.
+ *
+ * each rank size =
+ * sdram capacity(bit) / 8 * primary bus width / sdram width
+ *
+ * where: sdram capacity = spd byte4[3:0]
+ * primary bus width = spd byte8[2:0]
+ * sdram width = spd byte7[2:0]
+ *
+ * SPD byte4 - sdram density and banks
+ * bit[3:0] size(bit) size(byte)
+ * 0000 256Mb 32MB
+ * 0001 512Mb 64MB
+ * 0010 1Gb 128MB
+ * 0011 2Gb 256MB
+ * 0100 4Gb 512MB
+ * 0101 8Gb 1GB
+ * 0110 16Gb 2GB
+ *
+ * SPD byte8 - module memory bus width
+ * bit[2:0] primary bus width
+ * 000 8bits
+ * 001 16bits
+ * 010 32bits
+ * 011 64bits
+ *
+ * SPD byte7 - module organiztion
+ * bit[2:0] sdram device width
+ * 000 4bits
+ * 001 8bits
+ * 010 16bits
+ * 011 32bits
+ */
+static uint64_t compute_ranksize(const struct ddr3_spd_eeprom_s *spd)
+{
+ uint64_t bsize;
+ int sdram_cap_bsize = 0, prim_bus_width = 0, sdram_width = 0;
+
+ if ((spd->density_banks & 0xf) < 7)
+ sdram_cap_bsize = (spd->density_banks & 0xf) + 28;
+ if ((spd->bus_width & 0x7) < 4)
+ prim_bus_width = (spd->bus_width & 0x7) + 3;
+ if ((spd->organization & 0x7) < 4)
+ sdram_width = (spd->organization & 0x7) + 2;
+
+ bsize = 1ULL << (sdram_cap_bsize - 3 + prim_bus_width - sdram_width);
+
+ return bsize;
+}
+
+/*
+ * compute_dimm_parameters for DDR3 SPD
+ *
+ * Compute DIMM parameters based upon the SPD information in spd.
+ * Writes the results to the dimm_params_s structure pointed by pdimm.
+ *
+ */
+uint32_t
+compute_dimm_parameters(const generic_spd_eeprom_t *spdin,
+ struct dimm_params_s *pdimm)
+{
+ const struct ddr3_spd_eeprom_s *spd = spdin;
+ uint32_t retval, mtb_ps;
+ int ftb_tmp;
+
+ if (spd->mem_type != SPD_MEMTYPE_DDR3)
+ goto error;
+
+ retval = ddr3_spd_checksum_pass(spd);
+ if (retval)
+ goto error;
+
+ memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
+ if ((spd->info_size_crc & 0xf) > 1)
+ memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1);
+
+ /* DIMM organization parameters */
+ pdimm->n_ranks = ((spd->organization >> 3) & 0x7) + 1;
+ pdimm->rank_density = compute_ranksize(spd);
+ pdimm->capacity = pdimm->n_ranks * pdimm->rank_density;
+ pdimm->data_width = pdimm->primary_sdram_width + pdimm->ec_sdram_width;
+ pdimm->primary_sdram_width = 1 << (3 + (spd->bus_width & 0x7));
+ if ((spd->bus_width >> 3) & 0x3)
+ pdimm->ec_sdram_width = 8;
+ else
+ pdimm->ec_sdram_width = 0;
+ pdimm->device_width = 1 << ((spd->organization & 0x7) + 2);
+
+ /* These are the types defined by the JEDEC DDR3 SPD spec */
+ pdimm->mirrored_dimm = 0;
+ pdimm->registered_dimm = 0;
+ switch (spd->module_type & DDR3_SPD_MODULETYPE_MASK) {
+ case DDR3_SPD_MODULETYPE_UDIMM:
+ /* Unbuffered DIMMs */
+ if (spd->mod_section.unbuffered.addr_mapping & 0x1)
+ pdimm->mirrored_dimm = 1;
+ break;
+
+ default:
+ goto error;
+ }
+
+ /* SDRAM device parameters */
+ pdimm->n_row_addr = ((spd->addressing >> 3) & 0x7) + 12;
+ pdimm->n_col_addr = (spd->addressing & 0x7) + 9;
+ pdimm->n_banks_per_sdram_device =
+ 8 << ((spd->density_banks >> 4) & 0x7);
+
+ /*
+ * The SPD spec does not define an ECC bit. The DIMM is considered
+ * to have ECC capability if the extension bus exists.
+ */
+ if (pdimm->ec_sdram_width)
+ pdimm->edc_config = 0x02;
+ else
+ pdimm->edc_config = 0x00;
+
+ /*
+ * The SPD spec does not define the burst length byte.
+ * but the DDR3 spec defines BL8 and BC4, on bit 3 and
+ * bit 2.
+ */
+ pdimm->burst_lengths_bitmask = 0x0c;
+ pdimm->row_density = __ilog2(pdimm->rank_density);
+
+ mtb_ps = (spd->mtb_dividend * 1000) / spd->mtb_divisor;
+ pdimm->mtb_ps = mtb_ps;
+
+ ftb_tmp = spd->ftb_div & 0xf0;
+ pdimm->ftb_10th_ps = ((ftb_tmp >> 4) * 10) / ftb_tmp;
+
+ pdimm->tCKmin_X_ps = spd->tck_min * mtb_ps +
+ (spd->fine_tck_min * ftb_tmp) / 10;
+ pdimm->caslat_X = ((spd->caslat_msb << 8) | spd->caslat_lsb) << 4;
+
+ pdimm->taa_ps = spd->taa_min * mtb_ps +
+ (spd->fine_taa_min * ftb_tmp) / 10;
+
+ pdimm->tRCD_ps = spd->trcd_min * mtb_ps +
+ (spd->fine_trcd_min * ftb_tmp) / 10;
+
+ pdimm->tRP_ps = spd->trp_min * mtb_ps +
+ (spd->fine_trp_min * ftb_tmp) / 10;
+ pdimm->tRAS_ps = (((spd->tras_trc_ext & 0xf) << 8) | spd->tras_min_lsb)
+ * mtb_ps;
+ pdimm->tWR_ps = spd->twr_min * mtb_ps;
+ pdimm->tWTR_ps = spd->twtr_min * mtb_ps;
+ pdimm->tRFC_ps = ((spd->trfc_min_msb << 8) | spd->trfc_min_lsb)
+ * mtb_ps;
+ pdimm->tRRD_ps = spd->trrd_min * mtb_ps;
+ pdimm->tRC_ps = (((spd->tras_trc_ext & 0xf0) << 4) | spd->trc_min_lsb);
+ pdimm->tRC_ps *= mtb_ps;
+ pdimm->tRC_ps += (spd->fine_trc_min * ftb_tmp) / 10;
+
+ pdimm->tRTP_ps = spd->trtp_min * mtb_ps;
+
+ /*
+ * Average periodic refresh interval
+ * tREFI = 7.8 us at normal temperature range
+ * = 3.9 us at ext temperature range
+ */
+ pdimm->refresh_rate_ps = 7800000;
+ if ((spd->therm_ref_opt & 0x1) && !(spd->therm_ref_opt & 0x2)) {
+ pdimm->refresh_rate_ps = 3900000;
+ pdimm->extended_op_srt = 1;
+ }
+
+ pdimm->tfaw_ps = (((spd->tfaw_msb & 0xf) << 8) | spd->tfaw_min)
+ * mtb_ps;
+
+ return 0;
+error:
+ return 1;
+}
diff --git a/arch/ppc/ddr-8xxx/ddr2_setctrl.c b/arch/ppc/ddr-8xxx/ddr_setctrl.c
similarity index 53%
rename from arch/ppc/ddr-8xxx/ddr2_setctrl.c
rename to arch/ppc/ddr-8xxx/ddr_setctrl.c
index 14571b0..115fb42 100644
--- a/arch/ppc/ddr-8xxx/ddr2_setctrl.c
+++ b/arch/ppc/ddr-8xxx/ddr_setctrl.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Freescale Semiconductor, Inc.
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -10,12 +10,13 @@
#include <config.h>
#include <asm/io.h>
#include <asm/fsl_ddr_sdram.h>
+#include <asm/processor.h>
#include <mach/early_udelay.h>
#include "ddr.h"
int fsl_ddr_set_memctl_regs(const struct fsl_ddr_info_s *info)
{
- uint32_t i;
+ uint32_t i, temp_sdram_cfg;
void __iomem *ddr;
const struct fsl_ddr_cfg_regs_s *regs;
@@ -29,6 +30,9 @@ int fsl_ddr_set_memctl_regs(const struct fsl_ddr_info_s *info)
out_be32(ddr + DDR_OFF(CS0_BNDS) + (i << 3), regs->cs[i].bnds);
out_be32(ddr + DDR_OFF(CS0_CONFIG) + (i << 2),
regs->cs[i].config);
+ if (info->memctl_opts.sdram_type == SDRAM_TYPE_DDR3)
+ out_be32(ddr + DDR_OFF(CS0_CONFIG_2) + (i << 2),
+ regs->cs[i].config_2);
}
out_be32(ddr + DDR_OFF(TIMING_CFG_3), regs->timing_cfg_3);
@@ -45,12 +49,40 @@ int fsl_ddr_set_memctl_regs(const struct fsl_ddr_info_s *info)
out_be32(ddr + DDR_OFF(SDRAM_INIT_ADDR), regs->ddr_init_addr);
out_be32(ddr + DDR_OFF(SDRAM_INIT_ADDR_EXT), regs->ddr_init_ext_addr);
- early_udelay(200);
- asm volatile("sync;isync");
+ if (info->memctl_opts.sdram_type == SDRAM_TYPE_DDR3) {
+ out_be32(ddr + DDR_OFF(TIMING_CFG_4), regs->timing_cfg_4);
+ out_be32(ddr + DDR_OFF(TIMING_CFG_5), regs->timing_cfg_5);
+ out_be32(ddr + DDR_OFF(ZQ_CNTL), regs->ddr_zq_cntl);
+ out_be32(ddr + DDR_OFF(WRLVL_CNTL), regs->ddr_wrlvl_cntl);
+
+ if (regs->ddr_wrlvl_cntl_2)
+ out_be32(ddr + DDR_OFF(WRLVL_CNTL_2),
+ regs->ddr_wrlvl_cntl_2);
+ if (regs->ddr_wrlvl_cntl_3)
+ out_be32(ddr + DDR_OFF(WRLVL_CNTL_3),
+ regs->ddr_wrlvl_cntl_3);
+
+ out_be32(ddr + DDR_OFF(SR_CNTL), regs->ddr_sr_cntr);
+ out_be32(ddr + DDR_OFF(SDRAM_RCW_1), regs->ddr_sdram_rcw_1);
+ out_be32(ddr + DDR_OFF(SDRAM_RCW_2), regs->ddr_sdram_rcw_2);
+ out_be32(ddr + DDR_OFF(DDRCDR1), regs->ddr_cdr1);
+ out_be32(ddr + DDR_OFF(DDRCDR2), regs->ddr_cdr2);
+ }
- out_be32(ddr + DDR_OFF(SDRAM_CFG), regs->ddr_sdram_cfg);
+ out_be32(ddr + DDR_OFF(ERR_DISABLE), regs->err_disable);
+ out_be32(ddr + DDR_OFF(ERR_INT_EN), regs->err_int_en);
+
+ temp_sdram_cfg = regs->ddr_sdram_cfg;
+ temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN);
+ out_be32(ddr + DDR_OFF(SDRAM_CFG), temp_sdram_cfg);
+
+ early_udelay(500);
+ /* Make sure all instructions are completed before enabling memory.*/
+ asm volatile("sync;isync");
+ temp_sdram_cfg = in_be32(ddr + DDR_OFF(SDRAM_CFG)) & ~SDRAM_CFG_BI;
+ out_be32(ddr + DDR_OFF(SDRAM_CFG), temp_sdram_cfg | SDRAM_CFG_MEM_EN);
+ asm volatile("sync;isync");
- /* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done. */
while (in_be32(ddr + DDR_OFF(SDRAM_CFG_2)) & SDRAM_CFG2_D_INIT)
early_udelay(10000);
diff --git a/arch/ppc/ddr-8xxx/lc_common_dimm_params.c b/arch/ppc/ddr-8xxx/lc_common_dimm_params.c
index a1addb0..9d90fb7 100644
--- a/arch/ppc/ddr-8xxx/lc_common_dimm_params.c
+++ b/arch/ppc/ddr-8xxx/lc_common_dimm_params.c
@@ -12,6 +12,36 @@
#include "ddr.h"
+static uint32_t
+compute_cas_latency_ddr3(const struct dimm_params_s *dimm_params,
+ uint32_t number_of_dimms)
+{
+ uint32_t i, taamin_ps = 0, tckmin_x_ps = 0, common_caslat,
+ caslat_actual, retry = 16;
+ const uint32_t mclk_ps = get_memory_clk_period_ps();
+
+ /* compute the common CAS latency supported between slots */
+ common_caslat = dimm_params[0].caslat_X;
+ for (i = 1; i < number_of_dimms; i++) {
+ if (dimm_params[i].n_ranks)
+ common_caslat &= dimm_params[i].caslat_X;
+ }
+
+ for (i = 0; i < number_of_dimms; i++) {
+ taamin_ps = max(taamin_ps, dimm_params[i].taa_ps);
+ tckmin_x_ps = max(tckmin_x_ps, dimm_params[i].tCKmin_X_ps);
+ }
+
+ caslat_actual = (taamin_ps + mclk_ps - 1) / mclk_ps;
+ /* check if the dimms support the CAS latency */
+ while (!(common_caslat & (1 << caslat_actual)) && retry > 0) {
+ caslat_actual++;
+ retry--;
+ }
+
+ return caslat_actual;
+}
+
static unsigned int common_burst_length(
const struct dimm_params_s *dimm_params,
const unsigned int number_of_dimms)
@@ -22,7 +52,6 @@ static unsigned int common_burst_length(
for (i = 0; i < number_of_dimms; i++)
if (dimm_params[i].n_ranks)
temp &= dimm_params[i].burst_lengths_bitmask;
-
return temp;
}
@@ -115,16 +144,17 @@ static unsigned int compute_lowest_caslat(
* whose parameters have been computed into the array pointed to
* by dimm_params.
*/
-unsigned int
-compute_lowest_common_dimm_parameters(const struct dimm_params_s *dimm,
+void compute_lowest_common_dimm_parameters(const struct fsl_ddr_info_s *pinfo,
struct common_timing_params_s *out,
const unsigned int number_of_dimms)
{
- const uint32_t mclk_ps = get_memory_clk_period_ps();
uint32_t temp1, i;
struct common_timing_params_s tmp = {0};
+ const struct dimm_params_s *dimm = pinfo->dimm_params;
+ const struct memctl_options_s *popts = &pinfo->memctl_opts;
tmp.tCKmax_ps = 0xFFFFFFFF;
+ tmp.extended_op_srt = 1;
temp1 = 0;
for (i = 0; i < number_of_dimms; i++) {
if (dimm[i].n_ranks == 0) {
@@ -157,58 +187,69 @@ compute_lowest_common_dimm_parameters(const struct dimm_params_s *dimm,
tmp.tQHS_ps = max(tmp.tQHS_ps, dimm[i].tQHS_ps);
tmp.refresh_rate_ps = max(tmp.refresh_rate_ps,
dimm[i].refresh_rate_ps);
+ tmp.extended_op_srt = min(tmp.extended_op_srt,
+ dimm[i].extended_op_srt);
/* Find maximum tDQSQ_max_ps to find slowest timing. */
tmp.tDQSQ_max_ps = max(tmp.tDQSQ_max_ps, dimm[i].tDQSQ_max_ps);
}
tmp.ndimms_present = number_of_dimms - temp1;
if (temp1 == number_of_dimms)
- return 0;
+ return;
temp1 = common_burst_length(dimm, number_of_dimms);
tmp.all_DIMMs_burst_lengths_bitmask = temp1;
- tmp.all_DIMMs_registered = 0;
- tmp.lowest_common_SPD_caslat = compute_lowest_caslat(dimm,
- number_of_dimms);
- /*
- * Compute a common 'de-rated' CAS latency.
- *
- * The strategy here is to find the *highest* de-rated cas latency
- * with the assumption that all of the DIMMs will support a de-rated
- * CAS latency higher than or equal to their lowest de-rated value.
- */
- temp1 = 0;
- for (i = 0; i < number_of_dimms; i++)
- temp1 = max(temp1, dimm[i].caslat_lowest_derated);
- tmp.highest_common_derated_caslat = temp1;
+ /* Support only unbuffered DIMMs */
+ tmp.all_DIMMs_registered = 0;
+ tmp.all_DIMMs_unbuffered = 1;
+
+ if (popts->sdram_type == SDRAM_TYPE_DDR3) {
+ tmp.lowest_common_SPD_caslat = compute_cas_latency_ddr3(dimm,
+ number_of_dimms);
+ } else {
+ tmp.lowest_common_SPD_caslat = compute_lowest_caslat(dimm,
+ number_of_dimms);
+ /*
+ * Compute a common 'de-rated' CAS latency.
+ *
+ * The strategy here is to find the *highest* de-rated cas
+ * latency with the assumption that all of the DIMMs will
+ * support a de-rated CAS latency higher than or equal to
+ * their lowest de-rated value.
+ */
+ temp1 = 0;
+ for (i = 0; i < number_of_dimms; i++)
+ temp1 = max(temp1, dimm[i].caslat_lowest_derated);
+ tmp.highest_common_derated_caslat = temp1;
+ }
temp1 = 1;
for (i = 0; i < number_of_dimms; i++)
- if (dimm[i].n_ranks &&
- !(dimm[i].edc_config & EDC_ECC)) {
+ if (dimm[i].n_ranks && !(dimm[i].edc_config & EDC_ECC)) {
temp1 = 0;
break;
}
tmp.all_DIMMs_ECC_capable = temp1;
- if (mclk_ps > tmp.tCKmax_max_ps)
- return 1;
-
/*
* AL must be less or equal to tRCD. Typically, AL would
* be AL = tRCD - 1;
*
* When ODT read or write is enabled the sum of CAS latency +
* additive latency must be at least 3 cycles.
- *
*/
- if ((tmp.lowest_common_SPD_caslat < 4) && (picos_to_mclk(tmp.tRCD_ps) >
- tmp.lowest_common_SPD_caslat))
- tmp.additive_latency = picos_to_mclk(tmp.tRCD_ps) -
- tmp.lowest_common_SPD_caslat;
+ tmp.additive_latency = 0;
+ if (popts->sdram_type == SDRAM_TYPE_DDR2) {
+ if ((tmp.lowest_common_SPD_caslat < 4) &&
+ (picos_to_mclk(tmp.tRCD_ps) >
+ tmp.lowest_common_SPD_caslat))
+ tmp.additive_latency = picos_to_mclk(tmp.tRCD_ps) -
+ tmp.lowest_common_SPD_caslat;
+
+ if (mclk_to_picos(tmp.additive_latency) > tmp.tRCD_ps)
+ tmp.additive_latency = picos_to_mclk(tmp.tRCD_ps);
+ }
memcpy(out, &tmp, sizeof(struct common_timing_params_s));
-
- return 0;
}
diff --git a/arch/ppc/ddr-8xxx/main.c b/arch/ppc/ddr-8xxx/main.c
index 6e4a02d..99b877b 100644
--- a/arch/ppc/ddr-8xxx/main.c
+++ b/arch/ppc/ddr-8xxx/main.c
@@ -15,6 +15,7 @@
#include <common.h>
#include <config.h>
#include <asm/fsl_law.h>
+#include <asm/fsl_ddr_sdram.h>
#include "ddr.h"
static int get_spd(generic_spd_eeprom_t *spd,
@@ -143,6 +144,14 @@ static uint32_t compute_dimm_param(struct fsl_ddr_info_s *pinfo, uint32_t ndimm)
generic_spd_eeprom_t *spd;
uint32_t i, retval;
+ spd = &(pinfo->spd_installed_dimms[0]);
+ if (spd->mem_type == SPD_MEMTYPE_DDR3)
+ pinfo->memctl_opts.sdram_type = SDRAM_TYPE_DDR3;
+ else if (spd->mem_type == SPD_MEMTYPE_DDR2)
+ pinfo->memctl_opts.sdram_type = SDRAM_TYPE_DDR2;
+ else
+ return 1;
+
for (i = 0; i < ndimm; i++) {
spd = &(pinfo->spd_installed_dimms[i]);
pdimm = &(pinfo->dimm_params[i]);
@@ -185,8 +194,7 @@ uint64_t fsl_ddr_compute(struct fsl_ddr_info_s *pinfo)
* STEP 3: Compute a common set of timing parameters
* suitable for all of the DIMMs on each memory controller
*/
- compute_lowest_common_dimm_parameters(pinfo->dimm_params,
- timing_params, ndimm);
+ compute_lowest_common_dimm_parameters(pinfo, timing_params, ndimm);
/* STEP 4: Gather configuration requirements from user */
populate_memctl_options(timing_params->all_DIMMs_registered,
diff --git a/arch/ppc/ddr-8xxx/options.c b/arch/ppc/ddr-8xxx/options.c
index 9ce2bc1..ccf5d5e 100644
--- a/arch/ppc/ddr-8xxx/options.c
+++ b/arch/ppc/ddr-8xxx/options.c
@@ -46,18 +46,42 @@ uint32_t populate_memctl_options(int all_DIMMs_registered,
* 0 = 64-bit, 1 = 32-bit, 2 = 16-bit
*/
if (pdimm->n_ranks != 0) {
- if ((pdimm->data_width >= 64) && (pdimm->data_width <= 72))
- popts->data_bus_width = 0;
- else if ((pdimm->data_width >= 32) &&
- (pdimm->data_width <= 40))
- popts->data_bus_width = 1;
- else
- panic("data width %u is invalid!\n",
- pdimm->data_width);
+ if (popts->sdram_type == SDRAM_TYPE_DDR3) {
+ if (pdimm[0].primary_sdram_width == 64)
+ popts->data_bus_width = 0;
+ else if (pdimm[0].primary_sdram_width == 32)
+ popts->data_bus_width = 1;
+ else if (pdimm[0].primary_sdram_width == 16)
+ popts->data_bus_width = 2;
+ else
+ hang();
+ } else {
+ if ((pdimm->data_width >= 64) &&
+ (pdimm->data_width <= 72))
+ popts->data_bus_width = 0;
+ else if ((pdimm->data_width >= 32) &&
+ (pdimm->data_width <= 40))
+ popts->data_bus_width = 1;
+ else
+ hang();
+ }
+ }
+
+ if (popts->sdram_type == SDRAM_TYPE_DDR3) {
+ if (popts->data_bus_width == 0) {
+ popts->otf_burst_chop_en = 1;
+ popts->burst_length = DDR_OTF;
+ } else {
+ /* 32-bit or 16-bit bus */
+ popts->otf_burst_chop_en = 0;
+ popts->burst_length = DDR_BL8;
+ }
+ popts->mirrored_dimm = pdimm[0].mirrored_dimm;
+ } else {
+ /* Must be a burst length of 4 for DDR2 */
+ popts->burst_length = DDR_BL4;
}
- /* Must be a burst length of 4 for DD2 */
- popts->burst_length = DDR_BL4;
/* Decide whether to use the computed de-rated latency */
popts->use_derated_caslat = 0;
@@ -70,6 +94,7 @@ uint32_t populate_memctl_options(int all_DIMMs_registered,
* - how much time you want to spend playing around
*/
popts->twoT_en = 0;
+ popts->threet_en = 0;
/*
* Default BSTTOPRE precharge interval
@@ -90,7 +115,18 @@ uint32_t populate_memctl_options(int all_DIMMs_registered,
* The default value below would work for x4/x8 wide memory.
*
*/
- popts->tFAW_window_four_activates_ps = 37500;
+ if (popts->sdram_type == SDRAM_TYPE_DDR2) {
+ popts->tFAW_window_four_activates_ps = 37500;
+ } else {
+ /*
+ * Due to ddr3 dimm fly-by topology, enable write leveling
+ * to meet the tQDSS under different loading.
+ */
+ popts->tFAW_window_four_activates_ps = pdimm[0].tfaw_ps;
+ popts->wrlvl_en = 1;
+ popts->zq_en = 1;
+ popts->wrlvl_override = 0;
+ }
/*
* Default powerdown exit timings.
diff --git a/arch/ppc/include/asm/fsl_ddr_dimm_params.h b/arch/ppc/include/asm/fsl_ddr_dimm_params.h
index 73c239b..9e6f6b4 100644
--- a/arch/ppc/include/asm/fsl_ddr_dimm_params.h
+++ b/arch/ppc/include/asm/fsl_ddr_dimm_params.h
@@ -21,6 +21,8 @@ struct dimm_params_s {
uint32_t primary_sdram_width;
uint32_t ec_sdram_width;
uint32_t registered_dimm;
+ uint32_t device_width;
+ /* SDRAM device parameters */
uint32_t n_row_addr;
uint32_t n_col_addr;
uint32_t edc_config; /* 0 = none, 1 = parity, 2 = ECC */
@@ -28,6 +30,11 @@ struct dimm_params_s {
uint32_t burst_lengths_bitmask; /* BL=4 bit 2, BL=8 = bit 3 */
uint32_t row_density;
uint64_t base_address;
+ uint32_t mirrored_dimm;
+ uint32_t mtb_ps;
+ uint32_t ftb_10th_ps;
+ uint32_t taa_ps;
+ uint32_t tfaw_ps;
/* SDRAM clock periods */
uint32_t tCKmin_X_ps;
uint32_t tCKmin_X_minus_1_ps;
@@ -48,6 +55,7 @@ struct dimm_params_s {
uint32_t tRRD_ps; /* maximum = 63750 ps */
uint32_t tRC_ps; /* maximum = 254 ns + .75 ns = 254750 ps */
uint32_t refresh_rate_ps;
+ uint32_t extended_op_srt;
uint32_t tIS_ps; /* byte 32, spd->ca_setup */
uint32_t tIH_ps; /* byte 33, spd->ca_hold */
uint32_t tDS_ps; /* byte 34, spd->data_setup */
@@ -55,6 +63,7 @@ struct dimm_params_s {
uint32_t tRTP_ps; /* byte 38, spd->trtp */
uint32_t tDQSQ_max_ps; /* byte 44, spd->tdqsq */
uint32_t tQHS_ps; /* byte 45, spd->tqhs */
+ uint32_t rcw[16];
};
#endif
diff --git a/arch/ppc/include/asm/fsl_ddr_sdram.h b/arch/ppc/include/asm/fsl_ddr_sdram.h
index 444bcbc..8d3bd71 100644
--- a/arch/ppc/include/asm/fsl_ddr_sdram.h
+++ b/arch/ppc/include/asm/fsl_ddr_sdram.h
@@ -19,17 +19,26 @@
#define SDRAM_TYPE_DDR3 7
#define DDR_BL4 4
+#define DDR_BC4 DDR_BL4
+#define DDR_OTF 6
#define DDR_BL8 8
#define DDR2_RTT_OFF 0
#define DDR2_RTT_75_OHM 1
#define DDR2_RTT_150_OHM 2
#define DDR2_RTT_50_OHM 3
+#define DDR3_RTT_OFF 0
+#define DDR3_RTT_40_OHM 3
-#if defined(CONFIG_FSL_DDR2)
#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR (3)
+#if defined(CONFIG_FSL_DDR2)
typedef struct ddr2_spd_eeprom_s generic_spd_eeprom_t;
#define FSL_SDRAM_TYPE SDRAM_TYPE_DDR2
+#elif defined(CONFIG_FSL_DDR3)
+typedef struct ddr3_spd_eeprom_s generic_spd_eeprom_t;
+#define FSL_SDRAM_TYPE SDRAM_TYPE_DDR3
+#else
+#error "Undefined or unknown DDR type"
#endif
#define FSL_DDR_ODT_NEVER 0x0
@@ -121,6 +130,10 @@ struct memctl_options_s {
uint32_t dynamic_power;
uint32_t data_bus_width;
uint32_t burst_length;
+ uint32_t otf_burst_chop_en;
+ uint32_t mirrored_dimm;
+ uint32_t ap_en;
+ uint32_t x4_en;
/* Global Timing Parameters */
uint32_t cas_latency_override;
uint32_t cas_latency_override_value;
@@ -130,16 +143,36 @@ struct memctl_options_s {
uint32_t clk_adjust;
uint32_t cpo_override;
uint32_t write_data_delay;
+ /* Write leveling */
+ uint32_t wrlvl_override;
+ uint32_t wrlvl_sample;
+ uint32_t wrlvl_start;
+ uint32_t wrlvl_ctl_2;
+ uint32_t wrlvl_ctl_3;
uint32_t half_strength_driver_enable;
uint32_t twoT_en;
+ uint32_t threet_en;
uint32_t bstopre;
uint32_t tCKE_clock_pulse_width_ps;
uint32_t tFAW_window_four_activates_ps;
/* Rtt impedance */
uint32_t rtt_override;
uint32_t rtt_override_value;
+ uint32_t rtt_wr_override_value;
/* Automatic self refresh */
uint32_t auto_self_refresh_en;
+ uint32_t sr_it;
+ /* ZQ calibration */
+ uint32_t zq_en;
+ /* Write leveling */
+ uint32_t wrlvl_en;
+ /* RCW override for RDIMM */
+ uint32_t rcw_override;
+ uint32_t rcw_1;
+ uint32_t rcw_2;
+ /* control register 1 */
+ uint32_t ddr_cdr1;
+ uint32_t ddr_cdr2;
/* read-to-write turnaround */
uint32_t trwt_override;
uint32_t trwt;
--
1.8.4.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 4/6] ppc: add Freescale P1022DS board support
2014-03-13 18:09 [PATCH 0/6] ppc: add Freescale P1022DS board support Renaud Barbier
` (2 preceding siblings ...)
2014-03-13 18:10 ` [PATCH 3/6] ppc: mpc8xxx: add DDR3 support Renaud Barbier
@ 2014-03-13 18:10 ` Renaud Barbier
2014-03-13 18:10 ` [PATCH 5/7] ppc: mpc85xx: add stashing support Renaud Barbier
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Renaud Barbier @ 2014-03-13 18:10 UTC (permalink / raw)
To: barebox
Add support for the Freescale P1022DS. Driver support is limited to:
- I2C
- Ethernet
- Serial
- NOR flash
- PIXIS FPGA
System clock configuration is read from the FPGA but has only been
tested using a 133MHz system clock and 100MHz DDR clock.
Boot arguments are defined in the environment to boot over NFS with
a console configured at 115200 bauds.
Enabling branch prediction is moved from board support to the platform
support for all boards as it is a CPU feature.
Some the code is from U-Boot version git-be937b5.
Signed-off-by: Renaud Barbier <renaud.barbier@ge.com>
---
arch/ppc/boards/freescale-p1022ds/Makefile | 5 +
arch/ppc/boards/freescale-p1022ds/config.h | 55 ++++++++
arch/ppc/boards/freescale-p1022ds/ddr.c | 126 +++++++++++++++++
arch/ppc/boards/freescale-p1022ds/env/bin/init | 2 +
arch/ppc/boards/freescale-p1022ds/env/config | 2 +
arch/ppc/boards/freescale-p1022ds/ics307_clk.c | 46 +++++++
arch/ppc/boards/freescale-p1022ds/law.c | 27 ++++
arch/ppc/boards/freescale-p1022ds/p1022ds.c | 181 +++++++++++++++++++++++++
arch/ppc/boards/freescale-p1022ds/p1022ds.h | 14 ++
arch/ppc/boards/freescale-p1022ds/tlb.c | 59 ++++++++
arch/ppc/boards/freescale-p2020rdb/config.h | 2 -
arch/ppc/boards/geip-da923rc/config.h | 1 -
arch/ppc/configs/p1022ds_defconfig | 53 ++++++++
arch/ppc/cpu-85xx/start.S | 2 +-
arch/ppc/mach-mpc85xx/Kconfig | 4 +
15 files changed, 575 insertions(+), 4 deletions(-)
create mode 100644 arch/ppc/boards/freescale-p1022ds/Makefile
create mode 100644 arch/ppc/boards/freescale-p1022ds/config.h
create mode 100644 arch/ppc/boards/freescale-p1022ds/ddr.c
create mode 100644 arch/ppc/boards/freescale-p1022ds/env/bin/init
create mode 100644 arch/ppc/boards/freescale-p1022ds/env/config
create mode 100644 arch/ppc/boards/freescale-p1022ds/ics307_clk.c
create mode 100644 arch/ppc/boards/freescale-p1022ds/law.c
create mode 100644 arch/ppc/boards/freescale-p1022ds/p1022ds.c
create mode 100644 arch/ppc/boards/freescale-p1022ds/p1022ds.h
create mode 100644 arch/ppc/boards/freescale-p1022ds/tlb.c
create mode 100644 arch/ppc/configs/p1022ds_defconfig
diff --git a/arch/ppc/boards/freescale-p1022ds/Makefile b/arch/ppc/boards/freescale-p1022ds/Makefile
new file mode 100644
index 0000000..e9b59d5
--- /dev/null
+++ b/arch/ppc/boards/freescale-p1022ds/Makefile
@@ -0,0 +1,5 @@
+obj-y += p1022ds.o
+obj-y += law.o
+obj-y += tlb.o
+obj-y += ddr.o
+obj-y += ics307_clk.o
diff --git a/arch/ppc/boards/freescale-p1022ds/config.h b/arch/ppc/boards/freescale-p1022ds/config.h
new file mode 100644
index 0000000..666b9ff
--- /dev/null
+++ b/arch/ppc/boards/freescale-p1022ds/config.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#ifndef __ASSEMBLY__
+extern unsigned long ics307_clk_freq(unsigned int reg);
+#endif
+#define CFG_SYS_CLK_FREQ ics307_clk_freq(25)
+#define CFG_DDR_CLK_FREQ ics307_clk_freq(28)
+
+#define CFG_CHIP_SELECTS_PER_CTRL 2
+
+/*
+ * Memory map
+ *
+ * 0x0000_0000 0x7fff_ffff DDR 2G cacheable
+ *
+ * Localbus non-cacheable
+ * 0xe800_0000 0xefff_ffff FLASH 128M non-cacheable
+ * 0xffdf_0000 0xffdf_0fff PIXIS 4K Cacheable
+ * 0xffd0_0000 0xffd0_3fff L1 for stack 16K Cacheable TLB0
+ */
+#define CFG_SDRAM_BASE 0x00000000
+
+#define CFG_CCSRBAR_DEFAULT 0xff700000
+#define CFG_CCSRBAR 0xffe00000
+#define CFG_CCSRBAR_PHYS CFG_CCSRBAR
+#define CFG_IMMR CFG_CCSRBAR
+
+#define CFG_INIT_RAM_ADDR 0xffd00000
+#define CFG_INIT_RAM_SIZE 0x00004000
+#define CFG_INIT_BI_SIZE 0x00000100
+#define CFG_INIT_SP_OFFSET (CFG_INIT_RAM_SIZE - CFG_INIT_BI_SIZE)
+
+#define CFG_BOOT_BLOCK 0xe0000000
+#define CFG_BOOT_BLOCK_PHYS CFG_BOOT_BLOCK
+#define CFG_FLASH_BASE 0xe8000000
+#define CFG_FLASH_BASE_PHYS CFG_FLASH_BASE
+#define CFG_PIXIS_BASE 0xffdf0000
+#define CFG_PIXIS_BASE_PHYS CFG_PIXIS_BASE
+
+#endif /* __CONFIG_H */
diff --git a/arch/ppc/boards/freescale-p1022ds/ddr.c b/arch/ppc/boards/freescale-p1022ds/ddr.c
new file mode 100644
index 0000000..1944518
--- /dev/null
+++ b/arch/ppc/boards/freescale-p1022ds/ddr.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ * Authors: Srikanth Srinivasan <srikanth.srinivasan@freescale.com>
+ * Timur Tabi <timur@freescale.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <init.h>
+#include <mach/fsl_i2c.h>
+#include <mach/immap_85xx.h>
+#include <mach/clock.h>
+#include <asm/io.h>
+#include <asm/fsl_lbc.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/fsl_ddr_dimm_params.h>
+#include "p1022ds.h"
+
+static const u8 spd_addr = 0x51;
+
+int fsl_ddr_board_info(struct ddr_board_info_s *info)
+{
+ /*
+ * Early mapping is needed to access the clock
+ * parameters in the FPGA.
+ */
+ p1022ds_lbc_early_init();
+
+ info->fsl_ddr_ver = 0;
+ info->ddr_base = IOMEM(MPC85xx_DDR_ADDR);
+ /* Actual number of chip select used */
+ info->cs_per_ctrl = CFG_CHIP_SELECTS_PER_CTRL;
+ info->dimm_slots_per_ctrl = 1;
+ info->i2c_bus = 1;
+ info->i2c_slave = 0x7f;
+ info->i2c_speed = 400000;
+ info->i2c_base = IOMEM(I2C2_BASE_ADDR);
+ info->spd_i2c_addr = &spd_addr;
+
+ return 0;
+}
+
+struct board_specific_parameters {
+ u32 n_ranks;
+ u32 datarate_mhz_high;
+ u32 clk_adjust; /* Range: 0-8 */
+ u32 cpo; /* Range: 2-31 */
+ u32 write_data_delay; /* Range: 0-6 */
+ u32 force_2t;
+};
+
+/*
+ * This table contains all valid speeds we want to override with board
+ * specific parameters. datarate_mhz_high values need to be in ascending order
+ * for each n_ranks group.
+ */
+static const struct board_specific_parameters dimm0[] = {
+ /*
+ * memory controller 0
+ * num| hi| clk| cpo|wrdata|2T
+ * ranks| mhz|adjst| | delay|
+ */
+ { 1, 549, 5, 31, 3, 0 },
+ { 1, 850, 5, 31, 5, 0 },
+ { 2, 549, 5, 31, 3, 0 },
+ { 2, 850, 5, 31, 5, 0 },
+ { }
+};
+
+void fsl_ddr_board_options(struct memctl_options_s *popts,
+ struct dimm_params_s *pdimm)
+{
+ const struct board_specific_parameters *pbsp, *pbsp_highest = NULL;
+ unsigned long ddr_freq;
+ uint32_t i;
+
+ for (i = 0; i < popts->board_info->cs_per_ctrl; i++) {
+ popts->cs_local_opts[i].odt_rd_cfg = 0;
+ popts->cs_local_opts[i].odt_wr_cfg = 1;
+ popts->cs_local_opts[i].odt_rtt_wr = DDR3_RTT_OFF;
+ }
+ popts->cs_local_opts[0].odt_rtt_norm = DDR3_RTT_40_OHM;
+ popts->cs_local_opts[1].odt_rtt_norm = DDR3_RTT_OFF;
+
+ pbsp = dimm0;
+
+ ddr_freq = fsl_get_ddr_freq(0) / 1000000;
+ /*
+ * To have optimal parameters specific to the board, do a fine
+ * adjustment of DDR parameters depending on the DDR data rate.
+ */
+ while (pbsp->datarate_mhz_high) {
+ if (pbsp->n_ranks == pdimm->n_ranks) {
+ if (ddr_freq <= pbsp->datarate_mhz_high) {
+ popts->clk_adjust = pbsp->clk_adjust;
+ popts->cpo_override = pbsp->cpo;
+ popts->write_data_delay =
+ pbsp->write_data_delay;
+ popts->twoT_en = pbsp->force_2t;
+ goto found;
+ }
+ pbsp_highest = pbsp;
+ }
+ pbsp++;
+ }
+
+ /* Use highest parameters if none were found */
+ if (pbsp_highest) {
+ popts->clk_adjust = pbsp->clk_adjust;
+ popts->cpo_override = pbsp->cpo;
+ popts->write_data_delay = pbsp->write_data_delay;
+ popts->twoT_en = pbsp->force_2t;
+ }
+
+found:
+ popts->half_strength_driver_enable = 1;
+
+ /* Per AN4039, enable ZQ calibration. */
+ popts->zq_en = 1;
+
+ popts->auto_self_refresh_en = 1;
+ popts->sr_it = 0xb;
+
+ popts->dll_rst_dis = 1;
+}
diff --git a/arch/ppc/boards/freescale-p1022ds/env/bin/init b/arch/ppc/boards/freescale-p1022ds/env/bin/init
new file mode 100644
index 0000000..c0e04c1
--- /dev/null
+++ b/arch/ppc/boards/freescale-p1022ds/env/bin/init
@@ -0,0 +1,2 @@
+#!/bin/sh
+source /env/config
diff --git a/arch/ppc/boards/freescale-p1022ds/env/config b/arch/ppc/boards/freescale-p1022ds/env/config
new file mode 100644
index 0000000..bffd868
--- /dev/null
+++ b/arch/ppc/boards/freescale-p1022ds/env/config
@@ -0,0 +1,2 @@
+#!/bin/sh
+export bootargs="root=/dev/nfs rw ip=bootp console=ttyS0,115200"
\ No newline at end of file
diff --git a/arch/ppc/boards/freescale-p1022ds/ics307_clk.c b/arch/ppc/boards/freescale-p1022ds/ics307_clk.c
new file mode 100644
index 0000000..f7c5bbd
--- /dev/null
+++ b/arch/ppc/boards/freescale-p1022ds/ics307_clk.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+/* decode S[0-2] to Output Divider (OD) */
+static u8 ics307_s_to_od[] = {
+ 10, 2, 8, 4, 5, 7, 3, 6
+};
+
+/* Calculate frequency being generated by ICS307-02 clock chip. */
+unsigned long ics307_clk_freq(unsigned int reg)
+{
+ const unsigned long input_freq = 33333000;
+ void __iomem *fpga_base = IOMEM(CFG_PIXIS_BASE);
+ unsigned char cw0, cw1, cw2;
+ unsigned long vdw, rdw, od, freq;
+
+ cw0 = in_8(fpga_base + reg);
+ cw1 = in_8(fpga_base + reg + 1);
+ cw2 = in_8(fpga_base + reg + 2);
+ vdw = ((cw1 << 1) & 0x1fe) + ((cw2 >> 7) & 1);
+ rdw = cw2 & 0x7f;
+ od = ics307_s_to_od[cw0 & 0x7];
+ /*
+ * CLK1 Freq = Input Frequency * 2 * (VDW + 8) / ((RDW + 2) * OD)
+ *
+ * cw0: C1 C0 TTL F1 F0 S2 S1 S0
+ * cw1: V8 V7 V6 V5 V4 V3 V2 V1
+ * cw2: V0 R6 R5 R4 R3 R2 R1 R0
+ *
+ * R6:R0 = Reference Divider Word (RDW)
+ * V8:V0 = VCO Divider Word (VDW)
+ * S2:S0 = Output Divider Select (OD)
+ * F1:F0 = Function of CLK2 Output
+ * TTL = duty cycle
+ * C1:C0 = internal load capacitance for crystal
+ */
+ freq = input_freq * 2 * (vdw + 8) / ((rdw + 2) * od);
+
+ return freq;
+}
diff --git a/arch/ppc/boards/freescale-p1022ds/law.c b/arch/ppc/boards/freescale-p1022ds/law.c
new file mode 100644
index 0000000..167937a
--- /dev/null
+++ b/arch/ppc/boards/freescale-p1022ds/law.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <asm/fsl_law.h>
+
+struct law_entry law_table[] = {
+ FSL_SET_LAW(CFG_BOOT_BLOCK_PHYS, LAW_SIZE_256M, LAW_TRGT_IF_LBC),
+ FSL_SET_LAW(CFG_PIXIS_BASE_PHYS, LAW_SIZE_4K, LAW_TRGT_IF_LBC),
+};
+
+int num_law_entries = ARRAY_SIZE(law_table);
diff --git a/arch/ppc/boards/freescale-p1022ds/p1022ds.c b/arch/ppc/boards/freescale-p1022ds/p1022ds.c
new file mode 100644
index 0000000..c800064
--- /dev/null
+++ b/arch/ppc/boards/freescale-p1022ds/p1022ds.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2014 GE Intelligent Platforms, Inc.
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <ns16550.h>
+#include <net.h>
+#include <types.h>
+#include <i2c/i2c.h>
+#include <partition.h>
+#include <memory.h>
+#include <asm/cache.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/fsl_law.h>
+#include <mach/mpc85xx.h>
+#include <mach/mmu.h>
+#include <mach/immap_85xx.h>
+#include <mach/gianfar.h>
+#include <mach/clock.h>
+#include <mach/early_udelay.h>
+
+/* Define attributes for eTSEC1 and eTSEC2 */
+static struct gfar_info_struct gfar_info[] = {
+ {
+ .phyaddr = 1,
+ .tbiana = 0,
+ .tbicr = 0,
+ .mdiobus_tbi = 0,
+ },
+ {
+ .phyaddr = 2,
+ .tbiana = 0,
+ .tbicr = 0,
+ .mdiobus_tbi = 0,
+ },
+};
+
+struct i2c_platform_data i2cplat[] = {
+ { .bitrate = 400000, },
+ { .bitrate = 400000, },
+};
+
+void p1022ds_lbc_early_init(void)
+{
+ void __iomem *gur = IOMEM(MPC85xx_GUTS_ADDR);
+ void __iomem *lbc = LBC_BASE_ADDR;
+
+ /* Set the local bus monitor timeout value to the maximum */
+ clrsetbits_be32(lbc + FSL_LBC_LBCR_OFFSET, 0xff0f, 0xf);
+ /* Set the pin muxing to enable ETSEC2. */
+ clrbits_be32(gur + MPC85xx_GUTS_PMUXCR2_OFFSET, 0x001f8000);
+ /* Set pmuxcr to allow both i2c1 and i2c2 */
+ setbits_be32(gur + MPC85xx_GUTS_PMUXCR_OFFSET, 0x1000);
+
+ /* Map the boot flash and FPGA */
+ fsl_set_lbc_br(0, BR_PHYS_ADDR(CFG_FLASH_BASE_PHYS) | BR_PS_16 | BR_V);
+ fsl_set_lbc_or(0, 0xf8000ff7);
+ fsl_set_lbc_br(2, BR_PHYS_ADDR(CFG_PIXIS_BASE_PHYS) | BR_PS_8 | BR_V);
+ fsl_set_lbc_or(2, 0xffff8ff7);
+}
+
+static void board_eth_init(void)
+{
+ struct i2c_adapter *adapter;
+ struct i2c_client client;
+ char mac[6];
+ int ret, ix;
+
+ adapter = i2c_get_adapter(1);
+ client.addr = 0x57;
+ client.adapter = adapter;
+
+ for (ix = 0; ix < 2; ix++) {
+ int mac_offset;
+
+ mac_offset = 0x42 + (sizeof(mac) * ix);
+ ret = i2c_read_reg(&client, mac_offset, mac, sizeof(mac));
+ if (ret != sizeof(mac))
+ pr_err("Fail to retrieve MAC address\n");
+ else
+ eth_register_ethaddr(ix, mac);
+ }
+
+ fsl_eth_init(1, &gfar_info[0]);
+ fsl_eth_init(2, &gfar_info[1]);
+}
+
+static int p1022ds_devices_init(void)
+{
+ add_cfi_flash_device(DEVICE_ID_DYNAMIC, CFG_FLASH_BASE, 128 << 20, 0);
+ devfs_add_partition("nor0", 0x7f80000, 0x80000, DEVFS_PARTITION_FIXED,
+ "self0");
+ devfs_add_partition("nor0", 0x7f00000, 0x10000, DEVFS_PARTITION_FIXED,
+ "env0");
+ add_generic_device("i2c-fsl", 0, NULL, I2C1_BASE_ADDR, 0x100,
+ IORESOURCE_MEM, &i2cplat[0]);
+ add_generic_device("i2c-fsl", 1, NULL, I2C2_BASE_ADDR, 0x100,
+ IORESOURCE_MEM, &i2cplat[1]);
+
+ board_eth_init();
+
+ return 0;
+}
+
+device_initcall(p1022ds_devices_init);
+
+static struct NS16550_plat serial_plat = {
+ .clock = 0,
+ .shift = 0,
+};
+
+static int p1022ds_console_init(void)
+{
+ barebox_set_model("Freescale P1022DS");
+ barebox_set_hostname("p1022ds");
+
+ serial_plat.clock = fsl_get_bus_freq(0);
+ add_ns16550_device(DEVICE_ID_DYNAMIC, CFG_IMMR + 0x4500, 16,
+ IORESOURCE_MEM_8BIT, &serial_plat);
+ return 0;
+}
+
+console_initcall(p1022ds_console_init);
+
+static int p1022ds_mem_init(void)
+{
+ barebox_add_memory_bank("ram0", 0x0, fsl_get_effective_memsize());
+ return 0;
+}
+
+mem_initcall(p1022ds_mem_init);
+
+static int p1022ds_board_init_r(void)
+{
+ void __iomem *fpga = IOMEM(CFG_PIXIS_BASE);
+ const uint32_t flashbase = CFG_BOOT_BLOCK;
+ const u8 flash_esel = e500_find_tlb_idx((void *)flashbase, 1);
+
+ /* Enable SPI */
+ out_8(fpga + 8, (in_8(fpga + 8) & ~(0xc0)) | (0x80));
+
+ /* Map the NAND flash */
+ fsl_set_lbc_br(1, BR_PHYS_ADDR(0xff800000) | BR_PS_8 |
+ (2 << BR_DECC_SHIFT) | BR_MS_FCM | BR_V);
+ fsl_set_lbc_or(1, 0xffff8796);
+
+ /* Flush d-cache and invalidate i-cache of any FLASH data */
+ flush_dcache();
+ invalidate_icache();
+
+ /* invalidate existing TLB entry for flash */
+ e500_disable_tlb(flash_esel);
+
+ /*
+ * Remap Boot flash region to caching-inhibited
+ * so that flash can be erased properly.
+ */
+ e500_set_tlb(1, flashbase, CFG_BOOT_BLOCK_PHYS,
+ MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
+ 0, flash_esel, BOOKE_PAGESZ_256M, 1);
+
+ fsl_l2_cache_init();
+
+ return 0;
+}
+
+core_initcall(p1022ds_board_init_r);
diff --git a/arch/ppc/boards/freescale-p1022ds/p1022ds.h b/arch/ppc/boards/freescale-p1022ds/p1022ds.h
new file mode 100644
index 0000000..cbc2aca
--- /dev/null
+++ b/arch/ppc/boards/freescale-p1022ds/p1022ds.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2014 GE Intelligent Platforms, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+void p1022ds_lbc_early_init(void);
diff --git a/arch/ppc/boards/freescale-p1022ds/tlb.c b/arch/ppc/boards/freescale-p1022ds/tlb.c
new file mode 100644
index 0000000..86ab43a
--- /dev/null
+++ b/arch/ppc/boards/freescale-p1022ds/tlb.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <mach/mmu.h>
+
+struct fsl_e_tlb_entry tlb_table[] = {
+ /* TLB 0 - for temp stack in cache */
+ FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR, CFG_INIT_RAM_ADDR,
+ MAS3_SX | MAS3_SW | MAS3_SR, 0,
+ 0, 0, BOOKE_PAGESZ_4K, 0),
+ FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (4 * 1024),
+ CFG_INIT_RAM_ADDR + (4 * 1024),
+ MAS3_SX | MAS3_SW | MAS3_SR, 0,
+ 0, 0, BOOKE_PAGESZ_4K, 0),
+ FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (8 * 1024),
+ CFG_INIT_RAM_ADDR + (8 * 1024),
+ MAS3_SX | MAS3_SW | MAS3_SR, 0,
+ 0, 0, BOOKE_PAGESZ_4K, 0),
+ FSL_SET_TLB_ENTRY(0, CFG_INIT_RAM_ADDR + (12 * 1024),
+ CFG_INIT_RAM_ADDR + (12 * 1024),
+ MAS3_SX | MAS3_SW | MAS3_SR, 0,
+ 0, 0, BOOKE_PAGESZ_4K, 0),
+
+ /* TLB 1 */
+ /* *I*** - Covers boot page */
+ FSL_SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
+ MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
+ 0, 0, BOOKE_PAGESZ_4K, 1),
+
+ /* *I*G* - CCSRBAR */
+ FSL_SET_TLB_ENTRY(1, CFG_CCSRBAR, CFG_CCSRBAR_PHYS,
+ MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
+ 0, 1, BOOKE_PAGESZ_1M, 1),
+
+ /* W**G* - Flash/promjet, localbus */
+ /* This will be changed to *I*G* after relocation to RAM. */
+ FSL_SET_TLB_ENTRY(1, CFG_BOOT_BLOCK, CFG_BOOT_BLOCK_PHYS,
+ MAS3_SX | MAS3_SR, MAS2_M | MAS2_W | MAS2_G,
+ 0, 2, BOOKE_PAGESZ_256M, 1),
+
+ FSL_SET_TLB_ENTRY(1, CFG_PIXIS_BASE, CFG_PIXIS_BASE_PHYS,
+ MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
+ 0, 7, BOOKE_PAGESZ_4K, 1),
+};
+
+int num_tlb_entries = ARRAY_SIZE(tlb_table);
diff --git a/arch/ppc/boards/freescale-p2020rdb/config.h b/arch/ppc/boards/freescale-p2020rdb/config.h
index c6d3216..e607ee7 100644
--- a/arch/ppc/boards/freescale-p2020rdb/config.h
+++ b/arch/ppc/boards/freescale-p2020rdb/config.h
@@ -30,8 +30,6 @@ extern unsigned long get_board_sys_clk(unsigned long dummy);
#define CFG_SYS_CLK_FREQ get_board_sys_clk(0)
#define CFG_DDR_CLK_FREQ 66666666
-#define CFG_BTB /* toggle branch predition */
-
/*
* Base addresses -- Note these are effective addresses where the
* actual resources get mapped (not physical addresses)
diff --git a/arch/ppc/boards/geip-da923rc/config.h b/arch/ppc/boards/geip-da923rc/config.h
index 6e8684f..3895324 100644
--- a/arch/ppc/boards/geip-da923rc/config.h
+++ b/arch/ppc/boards/geip-da923rc/config.h
@@ -18,7 +18,6 @@
#define __CONFIG_H
#define CFG_SYS_CLK_FREQ 66666666
-#define CFG_BTB /* toggle branch prediction */
#define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT
#define CFG_CHIP_SELECTS_PER_CTRL 1
diff --git a/arch/ppc/configs/p1022ds_defconfig b/arch/ppc/configs/p1022ds_defconfig
new file mode 100644
index 0000000..878286b
--- /dev/null
+++ b/arch/ppc/configs/p1022ds_defconfig
@@ -0,0 +1,53 @@
+CONFIG_ARCH_MPC85XX=y
+CONFIG_P1022DS=y
+CONFIG_P1022=y
+CONFIG_LONGHELP=y
+CONFIG_GLOB=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_CMD_BOOTM_ZLIB=y
+CONFIG_CMD_BOOTM_BZLIB=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_ZLIB=y
+CONFIG_BZLIB=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_GO=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC=n
+CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/ppc/boards/freescale-p1022ds/env/"
+CONFIG_CMD_LOADENV=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_FSL_ELBC=y
+CONFIG_DRIVER_CFI=y
+CONFIG_DRIVER_CFI_AMD=y
+CONFIG_DRIVER_CFI_INTEL=n
+CONFIG_DRIVER_CFI_BANK_WIDTH_1=n
+CONFIG_DRIVER_CFI_BANK_WIDTH_2=y
+CONFIG_DRIVER_CFI_BANK_WIDTH_4=n
+CONFIG_MTD=y
+CONFIG_MTD_WRITE=y
+CONFIG_MALLOC_SIZE=0x4000000
+CONFIG_BAUDRATE=115200
+CONFIG_DRIVER_SERIAL_NS16550=y
+CONFIG_RELOCATABLE=y
+CONFIG_DRIVER_NET_GIANFAR=y
+CONFIG_NET=y
+CONFIG_NET_PING=y
+CONFIG_FS_TFTP=y
+CONFIG_NET_TFTP=y
+CONFIG_CMD_TFTP=y
+CONFIG_PING=y
+CONFIG_I2C=y
+CONFIG_I2C_IMX=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MIITOOL=y
+CONFIG_CMD_EXPORT=y
+CONFIG_OFTREE=y
+CONFIG_CMD_OFTREE_PROBE=y
+CONFIG_CMD_OFTREE=y
+CONFIG_CMD_BAREBOX_UPDATE=y
+CONFIG_CMD_IOMEM=y
+CONFIG_CMD_MEMTEST=y
diff --git a/arch/ppc/cpu-85xx/start.S b/arch/ppc/cpu-85xx/start.S
index 57f007b..514fd8c 100644
--- a/arch/ppc/cpu-85xx/start.S
+++ b/arch/ppc/cpu-85xx/start.S
@@ -172,7 +172,7 @@ _start_e500:
mtspr HID1,r0
/* Enable Branch Prediction */
-#if defined(CFG_BTB)
+#if defined(CONFIG_BTB)
lis r0,BUCSR_ENABLE@h
ori r0,r0,BUCSR_ENABLE@l
mtspr SPRN_BUCSR,r0
diff --git a/arch/ppc/mach-mpc85xx/Kconfig b/arch/ppc/mach-mpc85xx/Kconfig
index 74bad76..d02cf9b 100644
--- a/arch/ppc/mach-mpc85xx/Kconfig
+++ b/arch/ppc/mach-mpc85xx/Kconfig
@@ -3,6 +3,10 @@ if ARCH_MPC85XX
config MMU
default y if CMD_MEMTEST
+config BTB
+ bool
+ default y if P2020RDB || P1022DS || DA923RC
+
config TEXT_BASE
hex
default 0xeff80000 if P2020RDB
--
1.8.4.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread