Merge tag 'ti-v2020.07-rc3' of https://gitlab.denx.de/u-boot/custodians/u-boot-ti
[oweals/u-boot.git] / drivers / ddr / fsl / mpc85xx_ddr_gen3.c
index 9f0413309407e3771fd3f23e7193f8f829afa563..ab8d2deaf9f490d1e53a7ea25d454a7e94815fa9 100644 (file)
@@ -1,21 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * 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
- * Version 2 as published by the Free Software Foundation.
  */
 
 #include <common.h>
+#include <log.h>
 #include <asm/io.h>
 #include <fsl_ddr_sdram.h>
 #include <asm/processor.h>
+#include <linux/delay.h>
 
 #if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
 #error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
 #endif
 
-
 /*
  * regs has the to-be-set values for DDR controller registers
  * ctrl_num is the DDR controller number
@@ -39,22 +37,25 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
        unsigned int csn_bnds_backup = 0, cs_sa, cs_ea, *csn_bnds_t;
        int csn = -1;
 #endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_DDR_A003
+       u32 save1, save2;
+#endif
 
        switch (ctrl_num) {
        case 0:
                ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR;
                break;
-#if defined(CONFIG_SYS_FSL_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1)
+#if defined(CONFIG_SYS_FSL_DDR2_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 1)
        case 1:
                ddr = (void *)CONFIG_SYS_FSL_DDR2_ADDR;
                break;
 #endif
-#if defined(CONFIG_SYS_FSL_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2)
+#if defined(CONFIG_SYS_FSL_DDR3_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 2)
        case 2:
                ddr = (void *)CONFIG_SYS_FSL_DDR3_ADDR;
                break;
 #endif
-#if defined(CONFIG_SYS_FSL_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3)
+#if defined(CONFIG_SYS_FSL_DDR4_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 3)
        case 3:
                ddr = (void *)CONFIG_SYS_FSL_DDR4_ADDR;
                break;
@@ -116,7 +117,6 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
        out_be32(&ddr->timing_cfg_0, regs->timing_cfg_0);
        out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1);
        out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2);
-       out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
        out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode);
        out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2);
        out_be32(&ddr->sdram_mode_3, regs->ddr_sdram_mode_3);
@@ -129,9 +129,6 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
        out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
        out_be32(&ddr->sdram_data_init, regs->ddr_data_init);
        out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl);
-       out_be32(&ddr->init_addr, regs->ddr_init_addr);
-       out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
-
        out_be32(&ddr->timing_cfg_4, regs->timing_cfg_4);
        out_be32(&ddr->timing_cfg_5, regs->timing_cfg_5);
        out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl);
@@ -152,7 +149,24 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
        out_be32(&ddr->ddr_sdram_rcw_1, regs->ddr_sdram_rcw_1);
        out_be32(&ddr->ddr_sdram_rcw_2, regs->ddr_sdram_rcw_2);
        out_be32(&ddr->ddr_cdr1, regs->ddr_cdr1);
-       out_be32(&ddr->ddr_cdr2, regs->ddr_cdr2);
+#ifdef CONFIG_DEEP_SLEEP
+       if (is_warm_boot()) {
+               out_be32(&ddr->sdram_cfg_2,
+                        regs->ddr_sdram_cfg_2 & ~SDRAM_CFG2_D_INIT);
+               out_be32(&ddr->init_addr, CONFIG_SYS_SDRAM_BASE);
+               out_be32(&ddr->init_ext_addr, DDR_INIT_ADDR_EXT_UIA);
+
+               /* DRAM VRef will not be trained */
+               out_be32(&ddr->ddr_cdr2,
+                        regs->ddr_cdr2 & ~DDR_CDR2_VREF_TRAIN_EN);
+       } else
+#endif
+       {
+               out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+               out_be32(&ddr->init_addr, regs->ddr_init_addr);
+               out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
+               out_be32(&ddr->ddr_cdr2, regs->ddr_cdr2);
+       }
        out_be32(&ddr->err_disable, regs->err_disable);
        out_be32(&ddr->err_int_en, regs->err_int_en);
        for (i = 0; i < 32; i++) {
@@ -161,9 +175,6 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
                        out_be32(&ddr->debug[i], regs->debug[i]);
                }
        }
-#ifdef CONFIG_SYS_FSL_ERRATUM_A_004934
-       out_be32(&ddr->debug[28], 0x30003000);
-#endif
 
 #ifdef CONFIG_SYS_FSL_ERRATUM_DDR_A003474
        out_be32(&ddr->debug[12], 0x00000015);
@@ -197,6 +208,8 @@ step2:
                out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl & 0x7fffffff);
                out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2 & 0xffffffeb);
                out_be32(&ddr->mtcr, 0);
+               save1 = in_be32(&ddr->debug[12]);
+               save2 = in_be32(&ddr->debug[21]);
                out_be32(&ddr->debug[12], 0x00000015);
                out_be32(&ddr->debug[21], 0x24000000);
                out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval & 0xffff);
@@ -214,6 +227,18 @@ step2:
                                0x04000000              |
                                MD_CNTL_WRCW            |
                                MD_CNTL_MD_VALUE(0x02));
+#if (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
+                       if (!(regs->cs[2].config & SDRAM_CS_CONFIG_EN))
+                               break;
+                       while (in_be32(&ddr->sdram_md_cntl) & MD_CNTL_MD_EN)
+                               ;
+                       out_be32(&ddr->sdram_md_cntl,
+                                MD_CNTL_MD_EN          |
+                                MD_CNTL_CS_SEL_CS2_CS3 |
+                                0x04000000             |
+                                MD_CNTL_WRCW           |
+                                MD_CNTL_MD_VALUE(0x02));
+#endif
                        break;
                case 0x00100000:
                        out_be32(&ddr->sdram_md_cntl,
@@ -222,6 +247,18 @@ step2:
                                0x04000000              |
                                MD_CNTL_WRCW            |
                                MD_CNTL_MD_VALUE(0x0a));
+#if (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
+                       if (!(regs->cs[2].config & SDRAM_CS_CONFIG_EN))
+                               break;
+                       while (in_be32(&ddr->sdram_md_cntl) & MD_CNTL_MD_EN)
+                               ;
+                       out_be32(&ddr->sdram_md_cntl,
+                                MD_CNTL_MD_EN          |
+                                MD_CNTL_CS_SEL_CS2_CS3 |
+                                0x04000000             |
+                                MD_CNTL_WRCW           |
+                                MD_CNTL_MD_VALUE(0x0a));
+#endif
                        break;
                case 0x00200000:
                        out_be32(&ddr->sdram_md_cntl,
@@ -230,6 +267,18 @@ step2:
                                0x04000000              |
                                MD_CNTL_WRCW            |
                                MD_CNTL_MD_VALUE(0x12));
+#if (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
+                       if (!(regs->cs[2].config & SDRAM_CS_CONFIG_EN))
+                               break;
+                       while (in_be32(&ddr->sdram_md_cntl) & MD_CNTL_MD_EN)
+                               ;
+                       out_be32(&ddr->sdram_md_cntl,
+                                MD_CNTL_MD_EN          |
+                                MD_CNTL_CS_SEL_CS2_CS3 |
+                                0x04000000             |
+                                MD_CNTL_WRCW           |
+                                MD_CNTL_MD_VALUE(0x12));
+#endif
                        break;
                case 0x00300000:
                        out_be32(&ddr->sdram_md_cntl,
@@ -238,6 +287,18 @@ step2:
                                0x04000000              |
                                MD_CNTL_WRCW            |
                                MD_CNTL_MD_VALUE(0x1a));
+#if (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
+                       if (!(regs->cs[2].config & SDRAM_CS_CONFIG_EN))
+                               break;
+                       while (in_be32(&ddr->sdram_md_cntl) & MD_CNTL_MD_EN)
+                               ;
+                       out_be32(&ddr->sdram_md_cntl,
+                                MD_CNTL_MD_EN          |
+                                MD_CNTL_CS_SEL_CS2_CS3 |
+                                0x04000000             |
+                                MD_CNTL_WRCW           |
+                                MD_CNTL_MD_VALUE(0x1a));
+#endif
                        break;
                default:
                        out_be32(&ddr->sdram_md_cntl,
@@ -246,6 +307,18 @@ step2:
                                0x04000000              |
                                MD_CNTL_WRCW            |
                                MD_CNTL_MD_VALUE(0x02));
+#if (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
+                       if (!(regs->cs[2].config & SDRAM_CS_CONFIG_EN))
+                               break;
+                       while (in_be32(&ddr->sdram_md_cntl) & MD_CNTL_MD_EN)
+                               ;
+                       out_be32(&ddr->sdram_md_cntl,
+                                MD_CNTL_MD_EN          |
+                                MD_CNTL_CS_SEL_CS2_CS3 |
+                                0x04000000             |
+                                MD_CNTL_WRCW           |
+                                MD_CNTL_MD_VALUE(0x02));
+#endif
                        printf("Unsupported RC10\n");
                        break;
                }
@@ -259,8 +332,8 @@ step2:
                out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl);
                out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl);
                out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
-               out_be32(&ddr->debug[12], 0x0);
-               out_be32(&ddr->debug[21], 0x0);
+               out_be32(&ddr->debug[12], save1);
+               out_be32(&ddr->debug[21], save2);
                out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
 
        }
@@ -309,8 +382,18 @@ step2:
        udelay(500);
        asm volatile("sync;isync");
 
+#ifdef CONFIG_DEEP_SLEEP
+       if (is_warm_boot()) {
+               /* enter self-refresh */
+               setbits_be32(&ddr->sdram_cfg_2, SDRAM_CFG2_FRC_SR);
+               /* do board specific memory setup */
+               board_mem_sleep_setup();
+               temp_sdram_cfg = (in_be32(&ddr->sdram_cfg) | SDRAM_CFG_BI);
+       } else
+#endif
+               temp_sdram_cfg = (in_be32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI);
+
        /* Let the controller go */
-       temp_sdram_cfg = in_be32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI;
        out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN);
        asm volatile("sync;isync");
 
@@ -339,7 +422,7 @@ step2:
        bus_width = 3 - ((ddr->sdram_cfg & SDRAM_CFG_DBW_MASK)
                        >> SDRAM_CFG_DBW_SHIFT);
        timeout = ((total_gb_size_per_controller << (6 - bus_width)) * 100 /
-               (get_ddr_freq(0) >> 20)) << 1;
+               (get_ddr_freq(ctrl_num) >> 20)) << 1;
 #ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134
        timeout_save = timeout;
 #endif
@@ -451,14 +534,21 @@ step2:
                case 1:
                        out_be32(&ddr->cs1_bnds, regs->cs[csn].bnds);
                        break;
+#if CONFIG_CHIP_SELECTS_PER_CTRL > 2
                case 2:
                        out_be32(&ddr->cs2_bnds, regs->cs[csn].bnds);
                        break;
                case 3:
                        out_be32(&ddr->cs3_bnds, regs->cs[csn].bnds);
                        break;
+#endif
                }
                clrbits_be32(&ddr->sdram_cfg, 0x2);
        }
 #endif /* CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 */
+#ifdef CONFIG_DEEP_SLEEP
+       if (is_warm_boot())
+               /* exit self-refresh */
+               clrbits_be32(&ddr->sdram_cfg_2, SDRAM_CFG2_FRC_SR);
+#endif
 }