]> git.sur5r.net Git - u-boot/blobdiff - arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c
Merge branch 'u-boot/master' into u-boot-arm/master
[u-boot] / arch / powerpc / cpu / mpc8xxx / ddr / ctrl_regs.c
index 2592873c9f034b33dff21412043db9656cfa5b49..ff5812df55fbb0b925f7b034e2119b24d2d35165 100644 (file)
@@ -1,10 +1,7 @@
 /*
  * Copyright 2008-2012 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.
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 /*
 
 #include "ddr.h"
 
-#ifdef CONFIG_MPC83xx
-       #define _DDR_ADDR CONFIG_SYS_MPC83xx_DDR_ADDR
-#elif defined(CONFIG_MPC85xx)
-       #define _DDR_ADDR CONFIG_SYS_MPC85xx_DDR_ADDR
-#elif defined(CONFIG_MPC86xx)
-       #define _DDR_ADDR CONFIG_SYS_MPC86xx_DDR_ADDR
-#else
-       #error "Undefined _DDR_ADDR"
-#endif
+#define _DDR_ADDR CONFIG_SYS_MPC8xxx_DDR_ADDR
 
-u32 fsl_ddr_get_version(void)
+static u32 fsl_ddr_get_version(void)
 {
        ccsr_ddr_t *ddr;
        u32 ver_major_minor_errata;
@@ -229,6 +218,26 @@ static void set_csn_config_2(int i, fsl_ddr_cfg_regs_t *ddr)
 /* -3E = 667 CL5, -25 = CL6 800, -25E = CL5 800 */
 
 #if !defined(CONFIG_FSL_DDR1)
+static inline int avoid_odt_overlap(const dimm_params_t *dimm_params)
+{
+#if CONFIG_DIMM_SLOTS_PER_CTLR == 1
+       if (dimm_params[0].n_ranks == 4)
+               return 1;
+#endif
+
+#if CONFIG_DIMM_SLOTS_PER_CTLR == 2
+       if ((dimm_params[0].n_ranks == 2) &&
+               (dimm_params[1].n_ranks == 2))
+               return 1;
+
+#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
+       if (dimm_params[0].n_ranks == 4)
+               return 1;
+#endif
+#endif
+       return 0;
+}
+
 /*
  * DDR SDRAM Timing Configuration 0 (TIMING_CFG_0)
  *
@@ -236,7 +245,8 @@ static void set_csn_config_2(int i, fsl_ddr_cfg_regs_t *ddr)
  * dreams up non-zero default values to be backwards compatible.
  */
 static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr,
-                               const memctl_options_t *popts)
+                               const memctl_options_t *popts,
+                               const dimm_params_t *dimm_params)
 {
        unsigned char trwt_mclk = 0;   /* Read-to-write turnaround */
        unsigned char twrt_mclk = 0;   /* Write-to-read turnaround */
@@ -266,7 +276,18 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr,
        unsigned int data_rate = get_ddr_freq(0);
        tmrd_mclk = 4;
        /* set the turnaround time */
-       trwt_mclk = 1;
+
+       /*
+        * for single quad-rank DIMM and two dual-rank DIMMs
+        * to avoid ODT overlap
+        */
+       if (avoid_odt_overlap(dimm_params)) {
+               twwt_mclk = 2;
+               trrt_mclk = 1;
+       }
+       /* for faster clock, need more time for data setup */
+       trwt_mclk = (data_rate/1000000 > 1800) ? 2 : 1;
+
        if ((data_rate/1000000 > 1150) || (popts->memctl_interleaving))
                twrt_mclk = 1;
 
@@ -451,8 +472,8 @@ static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr,
                | ((caslat_ctrl & 0xF) << 16)
                | ((refrec_ctrl & 0xF) << 12)
                | ((wrrec_mclk & 0x0F) << 8)
-               | ((acttoact_mclk & 0x07) << 4)
-               | ((wrtord_mclk & 0x07) << 0)
+               | ((acttoact_mclk & 0x0F) << 4)
+               | ((wrtord_mclk & 0x0F) << 0)
                );
        debug("FSLDDR: timing_cfg_1 = 0x%08x\n", ddr->timing_cfg_1);
 }
@@ -659,6 +680,7 @@ static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
        unsigned int dqs_cfg;           /* DQS configuration */
        unsigned int odt_cfg = 0;       /* ODT configuration */
        unsigned int num_pr;            /* Number of posted refreshes */
+       unsigned int slow = 0;          /* DDR will be run less than 1250 */
        unsigned int obc_cfg;           /* On-The-Fly Burst Chop Cfg */
        unsigned int ap_en;             /* Address Parity Enable */
        unsigned int d_init;            /* DRAM data initialization */
@@ -692,6 +714,10 @@ static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
        obc_cfg = 0;
 #endif
 
+#if (CONFIG_SYS_FSL_DDR_VER >= FSL_DDR_VER_4_7)
+       slow = get_ddr_freq(0) < 1249000000;
+#endif
+
        if (popts->registered_dimm_en) {
                rcw_en = 1;
                ap_en = popts->ap_en;
@@ -720,6 +746,7 @@ static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
                | ((dqs_cfg & 0x3) << 26)
                | ((odt_cfg & 0x3) << 21)
                | ((num_pr & 0xf) << 12)
+               | ((slow & 1) << 11)
                | (qd_en << 9)
                | (unq_mrs_en << 8)
                | ((obc_cfg & 0x1) << 6)
@@ -1160,7 +1187,11 @@ static void set_ddr_data_init(fsl_ddr_cfg_regs_t *ddr)
 {
        unsigned int init_value;        /* Initialization value */
 
+#ifdef CONFIG_MEM_INIT_VALUE
+       init_value = CONFIG_MEM_INIT_VALUE;
+#else
        init_value = 0xDEADBEEF;
+#endif
        ddr->ddr_data_init = init_value;
 }
 
@@ -1347,6 +1378,11 @@ static void set_ddr_wrlvl_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int wrlvl_en,
                               | ((wrlvl_start & 0x1F) << 0)
                               );
        debug("FSLDDR: wrlvl_cntl = 0x%08x\n", ddr->ddr_wrlvl_cntl);
+       ddr->ddr_wrlvl_cntl_2 = popts->wrlvl_ctl_2;
+       debug("FSLDDR: wrlvl_cntl_2 = 0x%08x\n", ddr->ddr_wrlvl_cntl_2);
+       ddr->ddr_wrlvl_cntl_3 = popts->wrlvl_ctl_3;
+       debug("FSLDDR: wrlvl_cntl_3 = 0x%08x\n", ddr->ddr_wrlvl_cntl_3);
+
 }
 
 /* DDR Self Refresh Counter (DDR_SR_CNTR) */
@@ -1370,6 +1406,12 @@ static void set_ddr_cdr1(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts)
        debug("FSLDDR: ddr_cdr1 = 0x%08x\n", ddr->ddr_cdr1);
 }
 
+static void set_ddr_cdr2(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts)
+{
+       ddr->ddr_cdr2 = popts->ddr_cdr2;
+       debug("FSLDDR: ddr_cdr2 = 0x%08x\n", ddr->ddr_cdr2);
+}
+
 unsigned int
 check_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr)
 {
@@ -1466,7 +1508,7 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
                                break;
                        }
                        sa = common_dimm->base_address;
-                       ea = common_dimm->total_mem - 1;
+                       ea = sa + common_dimm->total_mem - 1;
                } else if (!popts->memctl_interleaving) {
                        /*
                         * If memory interleaving between controllers is NOT
@@ -1480,7 +1522,7 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
                        switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) {
                        case FSL_DDR_CS0_CS1_CS2_CS3:
                                sa = common_dimm->base_address;
-                               ea = common_dimm->total_mem - 1;
+                               ea = sa + common_dimm->total_mem - 1;
                                break;
                        case FSL_DDR_CS0_CS1_AND_CS2_CS3:
                                if ((i >= 2) && (dimm_number == 0)) {
@@ -1537,17 +1579,19 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
                sa >>= 24;
                ea >>= 24;
 
-               ddr->cs[i].bnds = (0
-                       | ((sa & 0xFFF) << 16)  /* starting address MSB */
-                       | ((ea & 0xFFF) << 0)   /* ending address MSB */
-                       );
+               if (cs_en) {
+                       ddr->cs[i].bnds = (0
+                               | ((sa & 0xFFF) << 16)/* starting address MSB */
+                               | ((ea & 0xFFF) << 0)   /* ending address MSB */
+                               );
+               } else {
+                       debug("FSLDDR: setting bnds to 0 for inactive CS\n");
+                       ddr->cs[i].bnds = 0;
+               }
 
                debug("FSLDDR: cs[%d]_bnds = 0x%08x\n", i, ddr->cs[i].bnds);
-               if (cs_en) {
-                       set_csn_config(dimm_number, i, ddr, popts, dimm_params);
-                       set_csn_config_2(i, ddr);
-               } else
-                       debug("CS%d is disabled.\n", i);
+               set_csn_config(dimm_number, i, ddr, popts, dimm_params);
+               set_csn_config_2(i, ddr);
        }
 
        /*
@@ -1560,7 +1604,7 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
        set_ddr_eor(ddr, popts);
 
 #if !defined(CONFIG_FSL_DDR1)
-       set_timing_cfg_0(ddr, popts);
+       set_timing_cfg_0(ddr, popts, dimm_params);
 #endif
 
        set_timing_cfg_3(ddr, popts, common_dimm, cas_latency);
@@ -1569,6 +1613,7 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
                                cas_latency, additive_latency);
 
        set_ddr_cdr1(ddr, popts);
+       set_ddr_cdr2(ddr, popts);
        set_ddr_sdram_cfg(ddr, popts, common_dimm);
        ip_rev = fsl_ddr_get_version();
        if (ip_rev > 0x40400)