1828d9af5SBin Meng /* 2828d9af5SBin Meng * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> 3828d9af5SBin Meng * 4828d9af5SBin Meng * SPDX-License-Identifier: GPL-2.0+ 5828d9af5SBin Meng */ 6828d9af5SBin Meng 7828d9af5SBin Meng #include <common.h> 820c34115SBin Meng #include <errno.h> 920c34115SBin Meng #include <fdtdec.h> 10*c6d4705fSBin Meng #include <asm/mtrr.h> 11828d9af5SBin Meng #include <asm/post.h> 1220c34115SBin Meng #include <asm/arch/mrc.h> 13*c6d4705fSBin Meng #include <asm/arch/msg_port.h> 14828d9af5SBin Meng #include <asm/arch/quark.h> 15828d9af5SBin Meng 16828d9af5SBin Meng DECLARE_GLOBAL_DATA_PTR; 17828d9af5SBin Meng 1820c34115SBin Meng static int mrc_configure_params(struct mrc_params *mrc_params) 1920c34115SBin Meng { 2020c34115SBin Meng const void *blob = gd->fdt_blob; 2120c34115SBin Meng int node; 2220c34115SBin Meng int mrc_flags; 2320c34115SBin Meng 2420c34115SBin Meng node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_QRK_MRC); 2520c34115SBin Meng if (node < 0) { 2620c34115SBin Meng debug("%s: Cannot find MRC node\n", __func__); 2720c34115SBin Meng return -EINVAL; 2820c34115SBin Meng } 2920c34115SBin Meng 3020c34115SBin Meng /* 3120c34115SBin Meng * TODO: 3220c34115SBin Meng * 3320c34115SBin Meng * We need support fast boot (MRC cache) in the future. 3420c34115SBin Meng * 3520c34115SBin Meng * Set boot mode to cold boot for now 3620c34115SBin Meng */ 3720c34115SBin Meng mrc_params->boot_mode = BM_COLD; 3820c34115SBin Meng 3920c34115SBin Meng /* 4020c34115SBin Meng * TODO: 4120c34115SBin Meng * 4220c34115SBin Meng * We need determine ECC by pin strap state 4320c34115SBin Meng * 4420c34115SBin Meng * Disable ECC by default for now 4520c34115SBin Meng */ 4620c34115SBin Meng mrc_params->ecc_enables = 0; 4720c34115SBin Meng 4820c34115SBin Meng mrc_flags = fdtdec_get_int(blob, node, "flags", 0); 4920c34115SBin Meng if (mrc_flags & MRC_FLAG_SCRAMBLE_EN) 5020c34115SBin Meng mrc_params->scrambling_enables = 1; 5120c34115SBin Meng else 5220c34115SBin Meng mrc_params->scrambling_enables = 0; 5320c34115SBin Meng 5420c34115SBin Meng mrc_params->dram_width = fdtdec_get_int(blob, node, "dram-width", 0); 5520c34115SBin Meng mrc_params->ddr_speed = fdtdec_get_int(blob, node, "dram-speed", 0); 5620c34115SBin Meng mrc_params->ddr_type = fdtdec_get_int(blob, node, "dram-type", 0); 5720c34115SBin Meng 5820c34115SBin Meng mrc_params->rank_enables = fdtdec_get_int(blob, node, "rank-mask", 0); 5920c34115SBin Meng mrc_params->channel_enables = fdtdec_get_int(blob, node, 6020c34115SBin Meng "chan-mask", 0); 6120c34115SBin Meng mrc_params->channel_width = fdtdec_get_int(blob, node, 6220c34115SBin Meng "chan-width", 0); 6320c34115SBin Meng mrc_params->address_mode = fdtdec_get_int(blob, node, "addr-mode", 0); 6420c34115SBin Meng 6520c34115SBin Meng mrc_params->refresh_rate = fdtdec_get_int(blob, node, 6620c34115SBin Meng "refresh-rate", 0); 6720c34115SBin Meng mrc_params->sr_temp_range = fdtdec_get_int(blob, node, 6820c34115SBin Meng "sr-temp-range", 0); 6920c34115SBin Meng mrc_params->ron_value = fdtdec_get_int(blob, node, 7020c34115SBin Meng "ron-value", 0); 7120c34115SBin Meng mrc_params->rtt_nom_value = fdtdec_get_int(blob, node, 7220c34115SBin Meng "rtt-nom-value", 0); 7320c34115SBin Meng mrc_params->rd_odt_value = fdtdec_get_int(blob, node, 7420c34115SBin Meng "rd-odt-value", 0); 7520c34115SBin Meng 7620c34115SBin Meng mrc_params->params.density = fdtdec_get_int(blob, node, 7720c34115SBin Meng "dram-density", 0); 7820c34115SBin Meng mrc_params->params.cl = fdtdec_get_int(blob, node, "dram-cl", 0); 7920c34115SBin Meng mrc_params->params.ras = fdtdec_get_int(blob, node, "dram-ras", 0); 8020c34115SBin Meng mrc_params->params.wtr = fdtdec_get_int(blob, node, "dram-wtr", 0); 8120c34115SBin Meng mrc_params->params.rrd = fdtdec_get_int(blob, node, "dram-rrd", 0); 8220c34115SBin Meng mrc_params->params.faw = fdtdec_get_int(blob, node, "dram-faw", 0); 8320c34115SBin Meng 8420c34115SBin Meng debug("MRC dram_width %d\n", mrc_params->dram_width); 8520c34115SBin Meng debug("MRC rank_enables %d\n", mrc_params->rank_enables); 8620c34115SBin Meng debug("MRC ddr_speed %d\n", mrc_params->ddr_speed); 8720c34115SBin Meng debug("MRC flags: %s\n", 8820c34115SBin Meng (mrc_params->scrambling_enables) ? "SCRAMBLE_EN" : ""); 8920c34115SBin Meng 9020c34115SBin Meng debug("MRC density=%d tCL=%d tRAS=%d tWTR=%d tRRD=%d tFAW=%d\n", 9120c34115SBin Meng mrc_params->params.density, mrc_params->params.cl, 9220c34115SBin Meng mrc_params->params.ras, mrc_params->params.wtr, 9320c34115SBin Meng mrc_params->params.rrd, mrc_params->params.faw); 9420c34115SBin Meng 9520c34115SBin Meng return 0; 9620c34115SBin Meng } 9720c34115SBin Meng 98828d9af5SBin Meng int dram_init(void) 99828d9af5SBin Meng { 10020c34115SBin Meng struct mrc_params mrc_params; 10120c34115SBin Meng int ret; 10220c34115SBin Meng 10320c34115SBin Meng memset(&mrc_params, 0, sizeof(struct mrc_params)); 10420c34115SBin Meng ret = mrc_configure_params(&mrc_params); 10520c34115SBin Meng if (ret) 10620c34115SBin Meng return ret; 10720c34115SBin Meng 10820c34115SBin Meng /* Set up the DRAM by calling the memory reference code */ 10920c34115SBin Meng mrc_init(&mrc_params); 11020c34115SBin Meng if (mrc_params.status) 11120c34115SBin Meng return -EIO; 11220c34115SBin Meng 11320c34115SBin Meng gd->ram_size = mrc_params.mem_size; 114828d9af5SBin Meng post_code(POST_DRAM); 115828d9af5SBin Meng 116*c6d4705fSBin Meng /* variable range MTRR#2: RAM area */ 117*c6d4705fSBin Meng disable_caches(); 118*c6d4705fSBin Meng msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYBASE(MTRR_VAR_RAM), 119*c6d4705fSBin Meng 0 | MTRR_TYPE_WRBACK); 120*c6d4705fSBin Meng msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYMASK(MTRR_VAR_RAM), 121*c6d4705fSBin Meng (~(gd->ram_size - 1)) | MTRR_PHYS_MASK_VALID); 122*c6d4705fSBin Meng enable_caches(); 123*c6d4705fSBin Meng 124828d9af5SBin Meng return 0; 125828d9af5SBin Meng } 126828d9af5SBin Meng 127828d9af5SBin Meng void dram_init_banksize(void) 128828d9af5SBin Meng { 129828d9af5SBin Meng gd->bd->bi_dram[0].start = 0; 130828d9af5SBin Meng gd->bd->bi_dram[0].size = gd->ram_size; 131828d9af5SBin Meng } 132828d9af5SBin Meng 133828d9af5SBin Meng /* 134828d9af5SBin Meng * This function looks for the highest region of memory lower than 4GB which 135828d9af5SBin Meng * has enough space for U-Boot where U-Boot is aligned on a page boundary. 136828d9af5SBin Meng * It overrides the default implementation found elsewhere which simply 137828d9af5SBin Meng * picks the end of ram, wherever that may be. The location of the stack, 138828d9af5SBin Meng * the relocation address, and how far U-Boot is moved by relocation are 139828d9af5SBin Meng * set in the global data structure. 140828d9af5SBin Meng */ 141828d9af5SBin Meng ulong board_get_usable_ram_top(ulong total_size) 142828d9af5SBin Meng { 143828d9af5SBin Meng return gd->ram_size; 144828d9af5SBin Meng } 145