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