Add support for DRAM initialization on ar7240 and similar SoC

Signed-off-by: Nikolaos Pasaloukos <nikolaos.pasalou...@imgtec.com>
Cc: Daniel Schwierzeck <daniel.schwierz...@gmail.com>
---
 arch/mips/cpu/mips32/ar7240/Makefile      |   7 +
 arch/mips/cpu/mips32/ar7240/ar7240_dram.c | 298 ++++++++++++++++++++++++++++++
 2 files changed, 305 insertions(+)
 create mode 100644 arch/mips/cpu/mips32/ar7240/Makefile
 create mode 100644 arch/mips/cpu/mips32/ar7240/ar7240_dram.c

diff --git a/arch/mips/cpu/mips32/ar7240/Makefile 
b/arch/mips/cpu/mips32/ar7240/Makefile
new file mode 100644
index 0000000..75fee0a
--- /dev/null
+++ b/arch/mips/cpu/mips32/ar7240/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2013 Imagination Technologies
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y = ar7240_dram.o
diff --git a/arch/mips/cpu/mips32/ar7240/ar7240_dram.c 
b/arch/mips/cpu/mips32/ar7240/ar7240_dram.c
new file mode 100644
index 0000000..575882e
--- /dev/null
+++ b/arch/mips/cpu/mips32/ar7240/ar7240_dram.c
@@ -0,0 +1,298 @@
+/*
+ * Memory controller config:
+ * Assumes that the caches are initialized.
+ *
+ * 0) Figure out the Tap controller settings.
+ * 1) Figure out whether the interface is 16bit or 32bit.
+ * 2) Size the DRAM
+ *
+ *  0) Tap controller settings
+ *  --------------------------
+ * The Table below provides all possible values of TAP controllers. We need to
+ * find the extreme left and extreme right of the spectrum (of max_udelay and
+ * min_udelay). We then program the TAP to be in the middle.
+ * Note for this we would need to be able to read and write memory. So,
+ * initially we assume that a 16bit interface, which will always work unless
+ * there is exactly _1_ 32 bit part...for now we assume this is not the case.
+ *
+ * The algo:
+ * 0) Program the controller in 16bit mode.
+ * 1) Start with the extreme left of the table
+ * 2) Write 0xa4, 0xb5, 0xc6, 0xd7 to 0, 2, 4, 6
+ * 3) Read 0 - this will fetch the entire cacheline.
+ * 4) If the value at address 4 is good, record this table entry, goto 6
+ * 5) Increment to get the next table entry. Goto 2.
+ * 6) Start with extreme right. Do the same as above.
+ *
+ * 1) 16bit or 32bit
+ * -----------------
+ *  31st bit of reg 0x1800_0000 will  determine the mode. By default,
+ *  controller is set to 32-bit mode. In 32 bit mode, full data bus DQ [31:0]
+ *  will be used to write 32 bit data. Suppose you have 16bit DDR memory
+ *  (it will have 16bit wide data bus). If you try to write 16 bit DDR in 32
+ *  bit mode, you are going to miss upper 16 bits of data. Reading to that
+ *  location will give you only lower 16 bits correctly, upper 16 bits will
+ *  have some junk value. E.g.,
+ *
+ *  write to 0x0000_0000 0x12345678
+ *  write to 0x0000_1000 0x00000000 (just to discharge DQ[31:16] )
+ *  read from 0x0000_0000
+ *  if u see something like 0x0000_5678 (or XXXX_5678 but not equal to
+ *  0x12345678) - its a 16 bit interface
+ *
+ *  2) Size the DRAM
+ *  -------------------
+ *  DDR wraps around. Write a pattern to 0x0000_0000. Write an address
+ *  pattern at 4M, 8M, 16M etc. and check when 0x0000_0000 gets overwritten.
+ *
+ *  Copyright (C) 2013 Imagination Technologies
+ *
+ *  Derived from works by OpenWRT
+ *
+ *  SPDX-License-Identifier:   GPL-2.0
+ */
+#include <common.h>
+#include <config.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
+#include <asm/ar7240_addrspace.h>
+#include <asm/ar934x_reg_cfg.h>
+
+/*
+ * WASP BootStrap Register
+ */
+
+#define WASP_RAM_TYPE(a)                       ((a) & 0x3)
+
+#define CONFIG_934X_SDRAM_CONFIG_VAL           0x7fbe8cd0
+#define CONFIG_934X_SDRAM_MODE_VAL_INIT                0x133
+#define CONFIG_934X_SDRAM_MODE_VAL             0x33
+#define CONFIG_934X_SDRAM_CONFIG2_VAL          0x959f66a8
+#define CONFIG_934X_SDRAM_TAP_VAL              0x1f1f
+
+#define CONFIG_934X_DDR1_CONFIG_VAL            0x7fd48cd0
+#define CONFIG_934X_DDR1_MODE_VAL_INIT         0x133
+#define CONFIG_934X_DDR1_EXT_MODE_VAL          0x2
+#define CONFIG_934X_DDR1_MODE_VAL              0x33
+#define CONFIG_934X_DDR1_CONFIG2_VAL           0x99d0e6a8
+#define CONFIG_934X_DDR1_TAP_VAL               0x14
+
+#if (CONFIG_SYS_PLL_FREQ == CONFIG_PLL_500_500_250)
+#define CONFIG_934X_DDR2_CONFIG_VAL            0xcfbc8cd0
+#define CONFIG_934X_DDR2_MODE_VAL_INIT         0x143
+#define CONFIG_934X_DDR2_EXT_MODE_VAL          0x402
+#define CONFIG_934X_DDR2_MODE_VAL              0x43
+#define CONFIG_934X_DDR2_CONFIG2_VAL           0xa5d0e6a8
+#define CONFIG_934X_DDR2_EN_TWL_VAL            0x1659
+#define CONFIG_934X_DDR2_TAP_VAL               0
+#elif (CONFIG_SYS_PLL_FREQ == CONFIG_PLL_650_600_300) || \
+       (CONFIG_SYS_PLL_FREQ == CONFIG_PLL_600_600_300) || \
+       (CONFIG_SYS_PLL_FREQ == CONFIG_PLL_600_550_275) || \
+       (CONFIG_SYS_PLL_FREQ == CONFIG_PLL_600_575_287)
+
+#define CONFIG_934X_DDR2_CONFIG_VAL            0xcfd48cd0
+#define CONFIG_934X_DDR2_MODE_VAL_INIT         0x143
+#define CONFIG_934X_DDR2_EXT_MODE_VAL          0x402
+#define CONFIG_934X_DDR2_MODE_VAL              0x43
+#define CONFIG_934X_DDR2_CONFIG2_VAL           0xa1d0e6a8
+#define CONFIG_934X_DDR2_EN_TWL_VAL            0x1659
+#define CONFIG_934X_DDR2_TAP_VAL               0x5
+#else
+#define CONFIG_934X_DDR2_CONFIG_VAL            0xc7d48cd0
+#define CONFIG_934X_DDR2_MODE_VAL_INIT         0x133
+#define CONFIG_934X_DDR2_EXT_MODE_VAL_INIT     0x382
+#define CONFIG_934X_DDR2_EXT_MODE_VAL          0x402
+#define CONFIG_934X_DDR2_MODE_VAL              0x33
+#define CONFIG_934X_DDR2_CONFIG2_VAL           0x9dd0e6a8
+#define CONFIG_934X_DDR2_EN_TWL_VAL            0xe59
+#define CONFIG_934X_DDR2_TAP_VAL               0x10012
+#endif
+
+#define DRAM_TYPE_SDRAM                                0
+#define DRAM_TYPE_DDR2                         1
+#define DRAM_TYPE_DDR1                         2
+
+#define FORCE_MRS_UPDATE                       0x01
+#define FORCE_EMRS_UPDATE                      0x02
+#define FORCE_AUTO_REFRESH                     0x04
+#define FORCE_PRECHARGE_ALL                    0x08
+#define FORCE_EMR2_UPDATE                      0x10
+#define FORCE_EMR3_UPDATE                      0x20
+
+#define dram_init_wait()                       udelay(1000)
+#define dram_wait()                            udelay(100)
+#define tap_wait()                             udelay(10)
+
+/* ram type */
+int wasp_ddr_initial_config(uint32_t refresh)
+{
+       int             ddr_config, ddr_config2, ext_mod, mod_val,
+                       mod_val_init, cycle_val, tap_val, type;
+       uint32_t        *pll = (unsigned *)PLL_CONFIG_VAL_F;
+
+       debug("Wasp 1.%d\n", ar_reg_rd(&ar7240_rst2->rev_id) & 0xf);
+
+       switch (WASP_RAM_TYPE(ar_reg_rd(&ar7240_rst2->bootstrap))) {
+       case 0:
+       case 1: /* SDRAM */
+               debug("Wasp sdram\n");
+               ddr_config      = CONFIG_934X_SDRAM_CONFIG_VAL;
+               ddr_config2     = CONFIG_934X_SDRAM_CONFIG2_VAL;
+               mod_val_init    = CONFIG_934X_SDRAM_MODE_VAL_INIT;
+               mod_val         = CONFIG_934X_SDRAM_MODE_VAL;
+               cycle_val       = CONFIG_SDRAM_RD_DATA_THIS_CYCLE_VAL;
+               tap_val         = CONFIG_934X_SDRAM_TAP_VAL;
+
+               ar_reg_wr(&ar7240_ddr_ctl->config, 0x13b);
+               dram_wait();
+
+               ar_reg_wr(&ar7240_ddr_ctl->debug_read_ctrl, 0x3000001f);
+               dram_wait();
+
+               type = DRAM_TYPE_SDRAM;
+
+               break;
+       case 2: /* DDR2 */
+               ddr_config      = CONFIG_934X_DDR2_CONFIG_VAL;
+               ddr_config2     = CONFIG_934X_DDR2_CONFIG2_VAL;
+               ext_mod         = CONFIG_934X_DDR2_EXT_MODE_VAL;
+               mod_val_init    = CONFIG_934X_DDR2_MODE_VAL_INIT;
+               mod_val         = CONFIG_934X_DDR2_MODE_VAL;
+               cycle_val       = CONFIG_DDR2_RD_DATA_THIS_CYCLE_VAL;
+               tap_val         = CONFIG_934X_DDR2_TAP_VAL;
+
+               ar_reg_wr(&ar7240_ddr2->config, CONFIG_934X_DDR2_EN_TWL_VAL);
+               dram_wait();
+               ar_reg_wr(&ar7240_ddr->ctrl, FORCE_EMR2_UPDATE);
+               tap_wait();
+               ar_reg_wr(&ar7240_ddr->ctrl, FORCE_EMR3_UPDATE);
+               tap_wait();
+               if (ar_reg_rd(&ar7240_rst2->rev_id) & 0xf) {
+                       /* NAND Clear */
+                       if (ar_reg_rd(&ar7240_rst2->bootstrap) &
+                           (1 << RST_BOOTSTRAP_DDR_WIDTH_LSB)) {
+                               debug("Wasp DDR2 32bit init\n");
+                               ar_reg_wr(&ar7240_ddr_ctl->config,
+                                         DDR_CTL_CONFIG_DDR2_EN_SET(1));
+                       } else {
+                               debug("Wasp DDR2 16bit init\n");
+                               ar_reg_rd_set(&ar7240_ddr_ctl->config,
+                                             DDR_CTL_CONFIG_DDR2_EN_SET(1));
+                       }
+               } else {
+#if DDR2_32BIT_SUPPORT
+                       debug("DDR2 32bit init\n");
+                       ar_reg_wr(&ar7240_ddr_ctl->config, 0);
+#else
+                       debug("DDR2 16bit init\n");
+#endif
+               }
+               type = DRAM_TYPE_DDR2;
+
+               break;
+       case 3: /* DDR1 */
+               debug("Wasp DDR1 16bit init\n");
+               ddr_config      = CONFIG_934X_DDR1_CONFIG_VAL;
+               ddr_config2     = CONFIG_934X_DDR1_CONFIG2_VAL;
+               ext_mod         = CONFIG_934X_DDR1_EXT_MODE_VAL;
+               mod_val_init    = CONFIG_934X_DDR1_MODE_VAL_INIT;
+               mod_val         = CONFIG_934X_DDR1_MODE_VAL;
+               cycle_val       = CONFIG_DDR1_RD_DATA_THIS_CYCLE_VAL;
+               tap_val         = CONFIG_934X_DDR1_TAP_VAL;
+               type = DRAM_TYPE_DDR1;
+               break;
+       }
+       if (*pll == PLL_MAGIC) {
+               uint32_t cas = pll[5];
+               if (cas == 3 || cas == 4) {
+                       cas = (cas * 2) + 2;
+                       ddr_config &= ~(DDR_CONFIG_CAS_LATENCY_MSB_MASK |
+                                       DDR_CONFIG_CAS_LATENCY_MASK);
+                       ddr_config |= DDR_CONFIG_CAS_LATENCY_SET(cas & 0x7) |
+                               DDR_CONFIG_CAS_LATENCY_MSB_SET((cas >> 3) & 1);
+
+                       cas = pll[5];
+
+                       ddr_config2 &= ~DDR_CONFIG2_GATE_OPEN_LATENCY_MASK;
+                       ddr_config2 |= DDR_CONFIG2_GATE_OPEN_LATENCY_SET(
+                                                                (2 * cas) + 1);
+
+                       if (type == DRAM_TYPE_DDR2) {
+                               uint32_t tmp;
+                               tmp = ar_reg_rd(&ar7240_ddr2->config);
+                               tmp &= ~DDR2_CONFIG_DDR2_TWL_MASK;
+                               tmp |= DDR2_CONFIG_DDR2_TWL_SET(cas == 3 ? 3 :
+                                                                          5);
+                               ar_reg_wr(&ar7240_ddr2->config, tmp);
+                       }
+
+                       mod_val_init = (cas == 3) ?
+                                      CONFIG_934X_DDR1_MODE_VAL_INIT :
+                                      CONFIG_934X_DDR2_MODE_VAL_INIT;
+               }
+       }
+
+       ar_reg_wr(&ar7240_ddr->config, ddr_config);
+       dram_wait();
+       ar_reg_wr(&ar7240_ddr->config2, ddr_config2 | 0x80);
+       dram_wait();
+       ar_reg_wr(&ar7240_ddr->ctrl, FORCE_PRECHARGE_ALL);
+       tap_wait();
+
+       ar_reg_wr(&ar7240_ddr->mode, mod_val_init);
+       dram_init_wait();
+
+       ar_reg_wr(&ar7240_ddr->ctrl, FORCE_MRS_UPDATE);
+       tap_wait();
+
+       if (type == DRAM_TYPE_DDR2) {
+               ar_reg_wr(&ar7240_ddr->ext_mode,
+                         CONFIG_934X_DDR2_EXT_MODE_VAL_INIT);
+               dram_wait();
+               ar_reg_wr(&ar7240_ddr->ctrl, FORCE_EMRS_UPDATE);
+               tap_wait();
+       }
+       if (type != DRAM_TYPE_SDRAM)
+               ar_reg_wr(&ar7240_ddr->ext_mode, ext_mod);
+
+       dram_wait();
+       ar_reg_wr(&ar7240_ddr->ctrl, FORCE_EMRS_UPDATE);
+       tap_wait();
+       ar_reg_wr(&ar7240_ddr->ctrl, FORCE_PRECHARGE_ALL);
+       tap_wait();
+       ar_reg_wr(&ar7240_ddr->mode, mod_val);
+       dram_wait();
+       ar_reg_wr(&ar7240_ddr->ctrl, FORCE_MRS_UPDATE);
+       tap_wait();
+       ar_reg_wr(&ar7240_ddr->refresh, refresh);
+       dram_wait();
+
+       ar_reg_wr(&ar7240_ddr->tap_ctrl0, tap_val);
+       ar_reg_wr(&ar7240_ddr->tap_ctrl1, tap_val);
+
+       if (ar_reg_rd(&ar7240_rst2->rev_id) & 0xf) {
+               /* NAND Clear */
+               if ((ar_reg_rd(&ar7240_rst2->bootstrap) & (1 << 3)) && type) {
+                       ar_reg_wr(&ar7240_ddr->tap_ctrl2, tap_val);
+                       ar_reg_wr(&ar7240_ddr->tap_ctrl3, tap_val);
+               }
+       } else {
+#if DDR2_32BIT_SUPPORT
+               if (type != DRAM_TYPE_SDRAM) {
+                       ar_reg_wr(&ar7240_ddr->tap_ctrl2, tap_val);
+                       ar_reg_wr(&ar7240_ddr->tap_ctrl3, tap_val);
+               }
+#endif
+       }
+
+       ar_reg_wr(&ar7240_ddr->rd_data_this_cycle, cycle_val);
+       dram_wait();
+#if ((CONFIG_SYS_PLL_FREQ == CONFIG_PLL_600_500_250) || \
+       (CONFIG_SYS_PLL_FREQ == CONFIG_PLL_500_500_250))
+       /* PMU2 ddr ldo tune */
+       /* Address differs in Qualcomm's Datasheet */
+       ar_reg_rd_set(AR7240_PMU2, PMU2_LDO_TUNE_SET(3));
+       dram_wait();
+#endif
+       return type;
+}
-- 
1.8.3.2


_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to