Skip to content
Snippets Groups Projects
sdram.c 26.3 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*
     * Copyright Altera Corporation (C) 2014-2015
     *
     * SPDX-License-Identifier:	GPL-2.0+
     */
    #include <common.h>
    #include <div64.h>
    #include <watchdog.h>
    #include <asm/arch/fpga_manager.h>
    #include <asm/arch/sdram.h>
    #include <asm/arch/system_manager.h>
    #include <asm/io.h>
    
    
    /*
     * FIXME: This path is temporary until the SDRAM driver gets
     *        a proper thorough cleanup.
     */
    #include "../../../board/altera/socfpga/qts/sdram_config.h"
    
    
    /* define constant for 4G memory - used for SDRAM errata workaround */
    #define MEMSIZE_4G (4ULL * 1024ULL * 1024ULL * 1024ULL)
    
    DECLARE_GLOBAL_DATA_PTR;
    
    
    struct sdram_prot_rule {
    	u64	sdram_start;	/* SDRAM start address */
    	u64	sdram_end;	/* SDRAM end address */
    	u32	rule;		/* SDRAM protection rule number: 0-19 */
    	int	valid;		/* Rule valid or not? 1 - valid, 0 not*/
    
    	u32	security;
    	u32	portmask;
    	u32	result;
    	u32	lo_prot_id;
    	u32	hi_prot_id;
    };
    
    
    38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
    static struct socfpga_system_manager *sysmgr_regs =
    	(struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS;
    static struct socfpga_sdr_ctrl *sdr_ctrl =
    	(struct socfpga_sdr_ctrl *)(SOCFPGA_SDR_ADDRESS + SDR_CTRLGRP_ADDRESS);
    
    static int compute_errata_rows(unsigned long long memsize, int cs, int width,
    			       int rows, int banks, int cols)
    {
    	unsigned long long newrows;
    	int inewrowslog2;
    	int bits;
    
    	debug("workaround rows - memsize %lld\n", memsize);
    	debug("workaround rows - cs        %d\n", cs);
    	debug("workaround rows - width     %d\n", width);
    	debug("workaround rows - rows      %d\n", rows);
    	debug("workaround rows - banks     %d\n", banks);
    	debug("workaround rows - cols      %d\n", cols);
    
    	newrows = lldiv(memsize, (cs * (width / 8)));
    	debug("rows workaround - term1 %lld\n", newrows);
    
    	newrows = lldiv(newrows, ((1 << banks) * (1 << cols)));
    	debug("rows workaround - term2 %lld\n", newrows);
    
    	/* Compute the hamming weight - same as number of bits set.
    	 * Need to see if result is ordinal power of 2 before
    	 * attempting log2 of result.
    	 */
    	bits = hweight32(newrows);
    
    	debug("rows workaround - bits %d\n", bits);
    
    	if (bits != 1) {
    		printf("SDRAM workaround failed, bits set %d\n", bits);
    		return rows;
    	}
    
    	if (newrows > UINT_MAX) {
    		printf("SDRAM workaround rangecheck failed, %lld\n", newrows);
    		return rows;
    	}
    
    	inewrowslog2 = __ilog2((unsigned int)newrows);
    
    	debug("rows workaround - ilog2 %d, %d\n", inewrowslog2,
    	       (int)newrows);
    
    	if (inewrowslog2 == -1) {
    		printf("SDRAM workaround failed, newrows %d\n", (int)newrows);
    		return rows;
    	}
    
    	return inewrowslog2;
    }
    
    /* SDRAM protection rules vary from 0-19, a total of 20 rules. */
    static void sdram_set_rule(struct sdram_prot_rule *prule)
    {
    	uint32_t lo_addr_bits;
    	uint32_t hi_addr_bits;
    	int ruleno = prule->rule;
    
    	/* Select the rule */
    	writel(ruleno, &sdr_ctrl->prot_rule_rdwr);
    
    	/* Obtain the address bits */
    	lo_addr_bits = (uint32_t)(((prule->sdram_start) >> 20ULL) & 0xFFF);
    	hi_addr_bits = (uint32_t)((((prule->sdram_end-1) >> 20ULL)) & 0xFFF);
    
    	debug("sdram set rule start %x, %lld\n", lo_addr_bits,
    	      prule->sdram_start);
    	debug("sdram set rule end   %x, %lld\n", hi_addr_bits,
    	      prule->sdram_end);
    
    	/* Set rule addresses */
    	writel(lo_addr_bits | (hi_addr_bits << 12), &sdr_ctrl->prot_rule_addr);
    
    	/* Set rule protection ids */
    	writel(prule->lo_prot_id | (prule->hi_prot_id << 12),
    	       &sdr_ctrl->prot_rule_id);
    
    	/* Set the rule data */
    	writel(prule->security | (prule->valid << 2) |
    	       (prule->portmask << 3) | (prule->result << 13),
    	       &sdr_ctrl->prot_rule_data);
    
    	/* write the rule */
    	writel(ruleno | (1L << 5), &sdr_ctrl->prot_rule_rdwr);
    
    	/* Set rule number to 0 by default */
    	writel(0, &sdr_ctrl->prot_rule_rdwr);
    }
    
    static void sdram_get_rule(struct sdram_prot_rule *prule)
    {
    	uint32_t addr;
    	uint32_t id;
    	uint32_t data;
    	int ruleno = prule->rule;
    
    	/* Read the rule */
    	writel(ruleno, &sdr_ctrl->prot_rule_rdwr);
    	writel(ruleno | (1L << 6), &sdr_ctrl->prot_rule_rdwr);
    
    	/* Get the addresses */
    	addr = readl(&sdr_ctrl->prot_rule_addr);
    	prule->sdram_start = (addr & 0xFFF) << 20;
    	prule->sdram_end = ((addr >> 12) & 0xFFF) << 20;
    
    	/* Get the configured protection IDs */
    	id = readl(&sdr_ctrl->prot_rule_id);
    	prule->lo_prot_id = id & 0xFFF;
    	prule->hi_prot_id = (id >> 12) & 0xFFF;
    
    	/* Get protection data */
    	data = readl(&sdr_ctrl->prot_rule_data);
    
    	prule->security = data & 0x3;
    	prule->valid = (data >> 2) & 0x1;
    	prule->portmask = (data >> 3) & 0x3FF;
    	prule->result = (data >> 13) & 0x1;
    }
    
    static void sdram_set_protection_config(uint64_t sdram_start, uint64_t sdram_end)
    {
    	struct sdram_prot_rule rule;
    	int rules;
    
    	/* Start with accepting all SDRAM transaction */
    	writel(0x0, &sdr_ctrl->protport_default);
    
    	/* Clear all protection rules for warm boot case */
    	memset(&rule, 0, sizeof(struct sdram_prot_rule));
    
    	for (rules = 0; rules < 20; rules++) {
    		rule.rule = rules;
    		sdram_set_rule(&rule);
    	}
    
    	/* new rule: accept SDRAM */
    	rule.sdram_start = sdram_start;
    	rule.sdram_end = sdram_end;
    	rule.lo_prot_id = 0x0;
    	rule.hi_prot_id = 0xFFF;
    	rule.portmask = 0x3FF;
    	rule.security = 0x3;
    	rule.result = 0;
    	rule.valid = 1;
    	rule.rule = 0;
    
    	/* set new rule */
    	sdram_set_rule(&rule);
    
    	/* default rule: reject everything */
    	writel(0x3ff, &sdr_ctrl->protport_default);
    }
    
    static void sdram_dump_protection_config(void)
    {
    	struct sdram_prot_rule rule;
    	int rules;
    
    	debug("SDRAM Prot rule, default %x\n",
    	      readl(&sdr_ctrl->protport_default));
    
    	for (rules = 0; rules < 20; rules++) {
    		sdram_get_rule(&rule);
    		debug("Rule %d, rules ...\n", rules);
    		debug("    sdram start %llx\n", rule.sdram_start);
    		debug("    sdram end   %llx\n", rule.sdram_end);
    		debug("    low prot id %d, hi prot id %d\n",
    		      rule.lo_prot_id,
    		      rule.hi_prot_id);
    		debug("    portmask %x\n", rule.portmask);
    		debug("    security %d\n", rule.security);
    		debug("    result %d\n", rule.result);
    		debug("    valid %d\n", rule.valid);
    	}
    }
    
    /* Function to write to register and verify the write */
    static unsigned sdram_write_verify(unsigned int *addr, unsigned reg_value)
    {
    #ifndef SDRAM_MMR_SKIP_VERIFY
    	unsigned reg_value1;
    #endif
    	debug("   Write - Address ");
    	debug("0x%08x Data 0x%08x\n", (u32)addr, reg_value);
    	/* Write to register */
    	writel(reg_value, addr);
    #ifndef SDRAM_MMR_SKIP_VERIFY
    	debug("   Read and verify...");
    	/* Read back the wrote value */
    	reg_value1 = readl(addr);
    	/* Indicate failure if value not matched */
    	if (reg_value1 != reg_value) {
    		debug("FAIL - Address 0x%08x Expected 0x%08x Data 0x%08x\n",
    		      (u32)addr, reg_value, reg_value1);
    		return 1;
    	}
    	debug("correct!\n");
    #endif	/* SDRAM_MMR_SKIP_VERIFY */
    	return 0;
    }
    
    static void set_sdr_ctrlcfg(void)
    {
    	int addrorder;
    
    	debug("\nConfiguring CTRLCFG\n");
    	clrsetbits_le32(&sdr_ctrl->ctrl_cfg, SDR_CTRLGRP_CTRLCFG_MEMTYPE_MASK,
    		   CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_MEMTYPE <<
    		   SDR_CTRLGRP_CTRLCFG_MEMTYPE_LSB);
    	clrsetbits_le32(&sdr_ctrl->ctrl_cfg, SDR_CTRLGRP_CTRLCFG_MEMBL_MASK,
    		   CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_MEMBL <<
    		   SDR_CTRLGRP_CTRLCFG_MEMBL_LSB);
    
    
    	/* SDRAM Failure When Accessing Non-Existent Memory
    	 * Set the addrorder field of the SDRAM control register
    	 * based on the CSBITs setting.
    	 */
    	switch (CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_CSBITS) {
    	case 1:
    		addrorder = 0; /* chip, row, bank, column */
    		if (CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_ADDRORDER != 0)
    			debug("INFO: Changing address order to 0 (chip, row, \
    			      bank, column)\n");
    		break;
    	case 2:
    		addrorder = 2; /* row, chip, bank, column */
    		if (CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_ADDRORDER != 2)
    			debug("INFO: Changing address order to 2 (row, chip, \
    			      bank, column)\n");
    		break;
    	default:
    		addrorder = CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_ADDRORDER;
    		break;
    	}
    
    	clrsetbits_le32(&sdr_ctrl->ctrl_cfg, SDR_CTRLGRP_CTRLCFG_ADDRORDER_MASK,
    			addrorder << SDR_CTRLGRP_CTRLCFG_ADDRORDER_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->ctrl_cfg, SDR_CTRLGRP_CTRLCFG_ECCEN_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_ECCEN <<
    			SDR_CTRLGRP_CTRLCFG_ECCEN_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->ctrl_cfg, SDR_CTRLGRP_CTRLCFG_ECCCORREN_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_ECCCORREN <<
    			SDR_CTRLGRP_CTRLCFG_ECCCORREN_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->ctrl_cfg, SDR_CTRLGRP_CTRLCFG_REORDEREN_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_REORDEREN <<
    			SDR_CTRLGRP_CTRLCFG_REORDEREN_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->ctrl_cfg, SDR_CTRLGRP_CTRLCFG_STARVELIMIT_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_STARVELIMIT <<
    			SDR_CTRLGRP_CTRLCFG_STARVELIMIT_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->ctrl_cfg, SDR_CTRLGRP_CTRLCFG_DQSTRKEN_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_DQSTRKEN <<
    			SDR_CTRLGRP_CTRLCFG_DQSTRKEN_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->ctrl_cfg, SDR_CTRLGRP_CTRLCFG_NODMPINS_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_NODMPINS <<
    			SDR_CTRLGRP_CTRLCFG_NODMPINS_LSB);
    }
    
    static void set_sdr_dram_timing1(void)
    {
    	debug("Configuring DRAMTIMING1\n");
    	clrsetbits_le32(&sdr_ctrl->dram_timing1, SDR_CTRLGRP_DRAMTIMING1_TCWL_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING1_TCWL <<
    			SDR_CTRLGRP_DRAMTIMING1_TCWL_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->dram_timing1, SDR_CTRLGRP_DRAMTIMING1_TAL_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING1_AL <<
    			SDR_CTRLGRP_DRAMTIMING1_TAL_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->dram_timing1, SDR_CTRLGRP_DRAMTIMING1_TCL_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING1_TCL <<
    			SDR_CTRLGRP_DRAMTIMING1_TCL_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->dram_timing1, SDR_CTRLGRP_DRAMTIMING1_TRRD_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING1_TRRD <<
    			SDR_CTRLGRP_DRAMTIMING1_TRRD_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->dram_timing1, SDR_CTRLGRP_DRAMTIMING1_TFAW_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING1_TFAW <<
    			SDR_CTRLGRP_DRAMTIMING1_TFAW_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->dram_timing1, SDR_CTRLGRP_DRAMTIMING1_TRFC_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING1_TRFC <<
    			SDR_CTRLGRP_DRAMTIMING1_TRFC_LSB);
    }
    
    static void set_sdr_dram_timing2(void)
    {
    	debug("Configuring DRAMTIMING2\n");
    	clrsetbits_le32(&sdr_ctrl->dram_timing2, SDR_CTRLGRP_DRAMTIMING2_TREFI_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TREFI <<
    			SDR_CTRLGRP_DRAMTIMING2_TREFI_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->dram_timing2, SDR_CTRLGRP_DRAMTIMING2_TRCD_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TRCD <<
    			SDR_CTRLGRP_DRAMTIMING2_TRCD_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->dram_timing2, SDR_CTRLGRP_DRAMTIMING2_TRP_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TRP <<
    			SDR_CTRLGRP_DRAMTIMING2_TRP_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->dram_timing2, SDR_CTRLGRP_DRAMTIMING2_TWR_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TWR <<
    			SDR_CTRLGRP_DRAMTIMING2_TWR_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->dram_timing2, SDR_CTRLGRP_DRAMTIMING2_TWTR_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TWTR <<
    			SDR_CTRLGRP_DRAMTIMING2_TWTR_LSB);
    }
    
    static void set_sdr_dram_timing3(void)
    {
    	debug("Configuring DRAMTIMING3\n");
    	clrsetbits_le32(&sdr_ctrl->dram_timing3, SDR_CTRLGRP_DRAMTIMING3_TRTP_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING3_TRTP <<
    			SDR_CTRLGRP_DRAMTIMING3_TRTP_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->dram_timing3, SDR_CTRLGRP_DRAMTIMING3_TRAS_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING3_TRAS <<
    			SDR_CTRLGRP_DRAMTIMING3_TRAS_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->dram_timing3, SDR_CTRLGRP_DRAMTIMING3_TRC_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING3_TRC <<
    			SDR_CTRLGRP_DRAMTIMING3_TRC_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->dram_timing3, SDR_CTRLGRP_DRAMTIMING3_TMRD_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING3_TMRD <<
    			SDR_CTRLGRP_DRAMTIMING3_TMRD_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->dram_timing3, SDR_CTRLGRP_DRAMTIMING3_TCCD_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING3_TCCD <<
    			SDR_CTRLGRP_DRAMTIMING3_TCCD_LSB);
    }
    
    static void set_sdr_dram_timing4(void)
    {
    	debug("Configuring DRAMTIMING4\n");
    	clrsetbits_le32(&sdr_ctrl->dram_timing4,
    			SDR_CTRLGRP_DRAMTIMING4_SELFRFSHEXIT_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING4_SELFRFSHEXIT <<
    			SDR_CTRLGRP_DRAMTIMING4_SELFRFSHEXIT_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->dram_timing4,
    			SDR_CTRLGRP_DRAMTIMING4_PWRDOWNEXIT_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING4_PWRDOWNEXIT <<
    			SDR_CTRLGRP_DRAMTIMING4_PWRDOWNEXIT_LSB);
    }
    
    static void set_sdr_dram_lowpwr_timing(void)
    {
    	debug("Configuring LOWPWRTIMING\n");
    	clrsetbits_le32(&sdr_ctrl->lowpwr_timing,
    			SDR_CTRLGRP_LOWPWRTIMING_AUTOPDCYCLES_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_LOWPWRTIMING_AUTOPDCYCLES <<
    			SDR_CTRLGRP_LOWPWRTIMING_AUTOPDCYCLES_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->lowpwr_timing,
    			SDR_CTRLGRP_LOWPWRTIMING_CLKDISABLECYCLES_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_LOWPWRTIMING_CLKDISABLECYCLES <<
    			SDR_CTRLGRP_LOWPWRTIMING_CLKDISABLECYCLES_LSB);
    }
    
    static void set_sdr_addr_rw(void)
    {
    	int cs = CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_CSBITS;
    	int width = 8;
    	int rows = CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_ROWBITS;
    	int banks = CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_BANKBITS;
    	int cols = CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_COLBITS;
    	unsigned long long workaround_memsize = MEMSIZE_4G;
    
    	debug("Configuring DRAMADDRW\n");
    	clrsetbits_le32(&sdr_ctrl->dram_addrw, SDR_CTRLGRP_DRAMADDRW_COLBITS_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_COLBITS <<
    			SDR_CTRLGRP_DRAMADDRW_COLBITS_LSB);
    	/*
    	 * SDRAM Failure When Accessing Non-Existent Memory
    	 * Update Preloader to artificially increase the number of rows so
    	 * that the memory thinks it has 4GB of RAM.
    	 */
    	rows = compute_errata_rows(workaround_memsize, cs, width, rows, banks,
    				   cols);
    
    	clrsetbits_le32(&sdr_ctrl->dram_addrw, SDR_CTRLGRP_DRAMADDRW_ROWBITS_MASK,
    			rows << SDR_CTRLGRP_DRAMADDRW_ROWBITS_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->dram_addrw, SDR_CTRLGRP_DRAMADDRW_BANKBITS_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_BANKBITS <<
    			SDR_CTRLGRP_DRAMADDRW_BANKBITS_LSB);
    	/* SDRAM Failure When Accessing Non-Existent Memory
    	 * Set SDR_CTRLGRP_DRAMADDRW_CSBITS_LSB to
    	 * log2(number of chip select bits). Since there's only
    	 * 1 or 2 chip selects, log2(1) => 0, and log2(2) => 1,
    	 * which is the same as "chip selects" - 1.
    	 */
    	clrsetbits_le32(&sdr_ctrl->dram_addrw, SDR_CTRLGRP_DRAMADDRW_CSBITS_MASK,
    			(CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_CSBITS - 1) <<
    			SDR_CTRLGRP_DRAMADDRW_CSBITS_LSB);
    }
    
    static void set_sdr_static_cfg(void)
    {
    	debug("Configuring STATICCFG\n");
    	clrsetbits_le32(&sdr_ctrl->static_cfg, SDR_CTRLGRP_STATICCFG_MEMBL_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_STATICCFG_MEMBL <<
    			SDR_CTRLGRP_STATICCFG_MEMBL_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->static_cfg,
    			SDR_CTRLGRP_STATICCFG_USEECCASDATA_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_STATICCFG_USEECCASDATA <<
    			SDR_CTRLGRP_STATICCFG_USEECCASDATA_LSB);
    }
    
    static void set_sdr_fifo_cfg(void)
    {
    	debug("Configuring FIFOCFG\n");
    	clrsetbits_le32(&sdr_ctrl->fifo_cfg, SDR_CTRLGRP_FIFOCFG_SYNCMODE_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_FIFOCFG_SYNCMODE <<
    			SDR_CTRLGRP_FIFOCFG_SYNCMODE_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->fifo_cfg, SDR_CTRLGRP_FIFOCFG_INCSYNC_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_FIFOCFG_INCSYNC <<
    			SDR_CTRLGRP_FIFOCFG_INCSYNC_LSB);
    }
    
    static void set_sdr_mp_weight(void)
    {
    	debug("Configuring MPWEIGHT_MPWEIGHT_0\n");
    	clrsetbits_le32(&sdr_ctrl->mp_weight0,
    			SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_0_STATICWEIGHT_31_0_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_MPWIEIGHT_0_STATICWEIGHT_31_0 <<
    			SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_0_STATICWEIGHT_31_0_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->mp_weight1,
    			SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_1_STATICWEIGHT_49_32_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_MPWIEIGHT_1_STATICWEIGHT_49_32 <<
    			SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_1_STATICWEIGHT_49_32_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->mp_weight1,
    			SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_1_SUMOFWEIGHTS_13_0_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_MPWIEIGHT_1_SUMOFWEIGHT_13_0 <<
    			SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_1_SUMOFWEIGHTS_13_0_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->mp_weight2,
    			SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_2_SUMOFWEIGHTS_45_14_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_MPWIEIGHT_2_SUMOFWEIGHT_45_14 <<
    			SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_2_SUMOFWEIGHTS_45_14_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->mp_weight3,
    			SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_3_SUMOFWEIGHTS_63_46_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_MPWIEIGHT_3_SUMOFWEIGHT_63_46 <<
    			SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_3_SUMOFWEIGHTS_63_46_LSB);
    }
    
    static void set_sdr_mp_pacing(void)
    {
    	debug("Configuring MPPACING_MPPACING_0\n");
    	clrsetbits_le32(&sdr_ctrl->mp_pacing0,
    			SDR_CTRLGRP_MPPACING_MPPACING_0_THRESHOLD1_31_0_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_MPPACING_0_THRESHOLD1_31_0 <<
    			SDR_CTRLGRP_MPPACING_MPPACING_0_THRESHOLD1_31_0_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->mp_pacing1,
    			SDR_CTRLGRP_MPPACING_MPPACING_1_THRESHOLD1_59_32_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_MPPACING_1_THRESHOLD1_59_32 <<
    			SDR_CTRLGRP_MPPACING_MPPACING_1_THRESHOLD1_59_32_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->mp_pacing1,
    			SDR_CTRLGRP_MPPACING_MPPACING_1_THRESHOLD2_3_0_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_MPPACING_1_THRESHOLD2_3_0 <<
    			SDR_CTRLGRP_MPPACING_MPPACING_1_THRESHOLD2_3_0_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->mp_pacing2,
    			SDR_CTRLGRP_MPPACING_MPPACING_2_THRESHOLD2_35_4_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_MPPACING_2_THRESHOLD2_35_4 <<
    			SDR_CTRLGRP_MPPACING_MPPACING_2_THRESHOLD2_35_4_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->mp_pacing3,
    			SDR_CTRLGRP_MPPACING_MPPACING_3_THRESHOLD2_59_36_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_MPPACING_3_THRESHOLD2_59_36 <<
    			SDR_CTRLGRP_MPPACING_MPPACING_3_THRESHOLD2_59_36_LSB);
    }
    
    static void set_sdr_mp_threshold(void)
    {
    	debug("Configuring MPTHRESHOLDRST_MPTHRESHOLDRST_0\n");
    	clrsetbits_le32(&sdr_ctrl->mp_threshold0,
    			SDR_CTRLGRP_MPTHRESHOLDRST_0_THRESHOLDRSTCYCLES_31_0_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_MPTHRESHOLDRST_0_THRESHOLDRSTCYCLES_31_0 <<
    			SDR_CTRLGRP_MPTHRESHOLDRST_0_THRESHOLDRSTCYCLES_31_0_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->mp_threshold1,
    			SDR_CTRLGRP_MPTHRESHOLDRST_1_THRESHOLDRSTCYCLES_63_32_MASK,
    
    			CONFIG_HPS_SDR_CTRLCFG_MPTHRESHOLDRST_1_THRESHOLDRSTCYCLES_63_32 <<
    
    			SDR_CTRLGRP_MPTHRESHOLDRST_1_THRESHOLDRSTCYCLES_63_32_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->mp_threshold2,
    			SDR_CTRLGRP_MPTHRESHOLDRST_2_THRESHOLDRSTCYCLES_79_64_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_MPTHRESHOLDRST_2_THRESHOLDRSTCYCLES_79_64 <<
    			SDR_CTRLGRP_MPTHRESHOLDRST_2_THRESHOLDRSTCYCLES_79_64_LSB);
    }
    
    
    /* Function to initialize SDRAM MMR */
    unsigned sdram_mmr_init_full(unsigned int sdr_phy_reg)
    {
    	unsigned long reg_value;
    	unsigned long status = 0;
    
    #if defined(CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_CSBITS) && \
    defined(CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_ROWBITS) && \
    defined(CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_BANKBITS) && \
    defined(CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_COLBITS) && \
    defined(CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_ROWBITS)
    
    	writel(CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_ROWBITS,
    	       &sysmgr_regs->iswgrp_handoff[4]);
    #endif
    	set_sdr_ctrlcfg();
    	set_sdr_dram_timing1();
    	set_sdr_dram_timing2();
    	set_sdr_dram_timing3();
    	set_sdr_dram_timing4();
    	set_sdr_dram_lowpwr_timing();
    	set_sdr_addr_rw();
    
    	debug("Configuring DRAMIFWIDTH\n");
    	clrsetbits_le32(&sdr_ctrl->dram_if_width,
    			SDR_CTRLGRP_DRAMIFWIDTH_IFWIDTH_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMIFWIDTH_IFWIDTH <<
    			SDR_CTRLGRP_DRAMIFWIDTH_IFWIDTH_LSB);
    
    	debug("Configuring DRAMDEVWIDTH\n");
    	clrsetbits_le32(&sdr_ctrl->dram_dev_width,
    			SDR_CTRLGRP_DRAMDEVWIDTH_DEVWIDTH_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMDEVWIDTH_DEVWIDTH <<
    			SDR_CTRLGRP_DRAMDEVWIDTH_DEVWIDTH_LSB);
    
    	debug("Configuring LOWPWREQ\n");
    	clrsetbits_le32(&sdr_ctrl->lowpwr_eq,
    			SDR_CTRLGRP_LOWPWREQ_SELFRFSHMASK_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_LOWPWREQ_SELFRFSHMASK <<
    			SDR_CTRLGRP_LOWPWREQ_SELFRFSHMASK_LSB);
    
    	debug("Configuring DRAMINTR\n");
    	clrsetbits_le32(&sdr_ctrl->dram_intr, SDR_CTRLGRP_DRAMINTR_INTREN_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMINTR_INTREN <<
    			SDR_CTRLGRP_DRAMINTR_INTREN_LSB);
    
    	set_sdr_static_cfg();
    
    	debug("Configuring CTRLWIDTH\n");
    	clrsetbits_le32(&sdr_ctrl->ctrl_width,
    			SDR_CTRLGRP_CTRLWIDTH_CTRLWIDTH_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_CTRLWIDTH_CTRLWIDTH <<
    			SDR_CTRLGRP_CTRLWIDTH_CTRLWIDTH_LSB);
    
    	debug("Configuring PORTCFG\n");
    	clrsetbits_le32(&sdr_ctrl->port_cfg, SDR_CTRLGRP_PORTCFG_AUTOPCHEN_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_PORTCFG_AUTOPCHEN <<
    			SDR_CTRLGRP_PORTCFG_AUTOPCHEN_LSB);
    
    	set_sdr_fifo_cfg();
    
    	debug("Configuring MPPRIORITY\n");
    	clrsetbits_le32(&sdr_ctrl->mp_priority,
    			SDR_CTRLGRP_MPPRIORITY_USERPRIORITY_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_MPPRIORITY_USERPRIORITY <<
    			SDR_CTRLGRP_MPPRIORITY_USERPRIORITY_LSB);
    
    	set_sdr_mp_weight();
    	set_sdr_mp_pacing();
    	set_sdr_mp_threshold();
    
    	debug("Configuring PHYCTRL_PHYCTRL_0\n");
    	setbits_le32(&sdr_ctrl->phy_ctrl0,
    		     CONFIG_HPS_SDR_CTRLCFG_PHYCTRL_PHYCTRL_0);
    
    	debug("Configuring CPORTWIDTH\n");
    	clrsetbits_le32(&sdr_ctrl->cport_width,
    			SDR_CTRLGRP_CPORTWIDTH_CMDPORTWIDTH_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_CPORTWIDTH_CPORTWIDTH <<
    			SDR_CTRLGRP_CPORTWIDTH_CMDPORTWIDTH_LSB);
    	debug("   Write - Address ");
    	debug("0x%08x Data 0x%08x\n",
    		(unsigned)(&sdr_ctrl->cport_width),
    		(unsigned)reg_value);
    	reg_value = readl(&sdr_ctrl->cport_width);
    	debug("   Read value without verify 0x%08x\n", (unsigned)reg_value);
    
    	debug("Configuring CPORTWMAP\n");
    	clrsetbits_le32(&sdr_ctrl->cport_wmap,
    			SDR_CTRLGRP_CPORTWMAP_CPORTWFIFOMAP_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_CPORTWMAP_CPORTWMAP <<
    			SDR_CTRLGRP_CPORTWMAP_CPORTWFIFOMAP_LSB);
    	debug("   Write - Address ");
    	debug("0x%08x Data 0x%08x\n",
    		(unsigned)(&sdr_ctrl->cport_wmap),
    		(unsigned)reg_value);
    	reg_value = readl(&sdr_ctrl->cport_wmap);
    	debug("   Read value without verify 0x%08x\n", (unsigned)reg_value);
    
    	debug("Configuring CPORTRMAP\n");
    	clrsetbits_le32(&sdr_ctrl->cport_rmap,
    			SDR_CTRLGRP_CPORTRMAP_CPORTRFIFOMAP_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_CPORTRMAP_CPORTRMAP <<
    			SDR_CTRLGRP_CPORTRMAP_CPORTRFIFOMAP_LSB);
    	debug("   Write - Address ");
    	debug("0x%08x Data 0x%08x\n",
    		(unsigned)(&sdr_ctrl->cport_rmap),
    		(unsigned)reg_value);
    	reg_value = readl(&sdr_ctrl->cport_rmap);
    	debug("   Read value without verify 0x%08x\n", (unsigned)reg_value);
    
    	debug("Configuring RFIFOCMAP\n");
    	clrsetbits_le32(&sdr_ctrl->rfifo_cmap,
    			SDR_CTRLGRP_RFIFOCMAP_RFIFOCPORTMAP_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_RFIFOCMAP_RFIFOCMAP <<
    			SDR_CTRLGRP_RFIFOCMAP_RFIFOCPORTMAP_LSB);
    	debug("   Write - Address ");
    	debug("0x%08x Data 0x%08x\n",
    		(unsigned)(&sdr_ctrl->rfifo_cmap),
    		(unsigned)reg_value);
    	reg_value = readl(&sdr_ctrl->rfifo_cmap);
    	debug("   Read value without verify 0x%08x\n", (unsigned)reg_value);
    
    	debug("Configuring WFIFOCMAP\n");
    	reg_value = readl(&sdr_ctrl->wfifo_cmap);
    	clrsetbits_le32(&sdr_ctrl->wfifo_cmap,
    			SDR_CTRLGRP_WFIFOCMAP_WFIFOCPORTMAP_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_WFIFOCMAP_WFIFOCMAP <<
    			SDR_CTRLGRP_WFIFOCMAP_WFIFOCPORTMAP_LSB);
    	debug("   Write - Address ");
    	debug("0x%08x Data 0x%08x\n",
    		(unsigned)(&sdr_ctrl->wfifo_cmap),
    		(unsigned)reg_value);
    	reg_value = readl(&sdr_ctrl->wfifo_cmap);
    	debug("   Read value without verify 0x%08x\n", (unsigned)reg_value);
    
    	debug("Configuring CPORTRDWR\n");
    	clrsetbits_le32(&sdr_ctrl->cport_rdwr,
    			SDR_CTRLGRP_CPORTRDWR_CPORTRDWR_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_CPORTRDWR_CPORTRDWR <<
    			SDR_CTRLGRP_CPORTRDWR_CPORTRDWR_LSB);
    	debug("   Write - Address ");
    	debug("0x%08x Data 0x%08x\n",
    		(unsigned)(&sdr_ctrl->cport_rdwr),
    		(unsigned)reg_value);
    	reg_value = readl(&sdr_ctrl->cport_rdwr);
    	debug("   Read value without verify 0x%08x\n", (unsigned)reg_value);
    
    	debug("Configuring DRAMODT\n");
    	clrsetbits_le32(&sdr_ctrl->dram_odt,
    			SDR_CTRLGRP_DRAMODT_READ_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMODT_READ <<
    			SDR_CTRLGRP_DRAMODT_READ_LSB);
    
    	clrsetbits_le32(&sdr_ctrl->dram_odt,
    			SDR_CTRLGRP_DRAMODT_WRITE_MASK,
    			CONFIG_HPS_SDR_CTRLCFG_DRAMODT_WRITE <<
    			SDR_CTRLGRP_DRAMODT_WRITE_LSB);
    
    	/* saving this value to SYSMGR.ISWGRP.HANDOFF.FPGA2SDR */
    	writel(CONFIG_HPS_SDR_CTRLCFG_FPGAPORTRST,
    	       &sysmgr_regs->iswgrp_handoff[3]);
    
    	/* only enable if the FPGA is programmed */
    	if (fpgamgr_test_fpga_ready()) {
    		if (sdram_write_verify(&sdr_ctrl->fpgaport_rst,
    		    CONFIG_HPS_SDR_CTRLCFG_FPGAPORTRST) == 1) {
    			status = 1;
    			return 1;
    		}
    	}
    
    	/* Restore the SDR PHY Register if valid */
    	if (sdr_phy_reg != 0xffffffff)
    		writel(sdr_phy_reg, &sdr_ctrl->phy_ctrl0);
    
    /***** Final step - apply configuration changes *****/
    	debug("Configuring STATICCFG_\n");
    	clrsetbits_le32(&sdr_ctrl->static_cfg, SDR_CTRLGRP_STATICCFG_APPLYCFG_MASK,
    			1 << SDR_CTRLGRP_STATICCFG_APPLYCFG_LSB);
    	debug("   Write - Address ");
    	debug("0x%08x Data 0x%08x\n",
    		(unsigned)(&sdr_ctrl->static_cfg),
    		(unsigned)reg_value);
    	reg_value = readl(&sdr_ctrl->static_cfg);
    	debug("   Read value without verify 0x%08x\n", (unsigned)reg_value);
    
    	sdram_set_protection_config(0, sdram_calculate_size());
    
    	sdram_dump_protection_config();
    
    	return status;
    }
    
    /*
     * To calculate SDRAM device size based on SDRAM controller parameters.
     * Size is specified in bytes.
     *
     * NOTE:
     * This function is compiled and linked into the preloader and
     * Uboot (there may be others). So if this function changes, the Preloader
     * and UBoot must be updated simultaneously.
     */
    unsigned long sdram_calculate_size(void)
    {
    	unsigned long temp;
    	unsigned long row, bank, col, cs, width;
    
    	temp = readl(&sdr_ctrl->dram_addrw);
    	col = (temp & SDR_CTRLGRP_DRAMADDRW_COLBITS_MASK) >>
    		SDR_CTRLGRP_DRAMADDRW_COLBITS_LSB;
    
    	/* SDRAM Failure When Accessing Non-Existent Memory
    	 * Use ROWBITS from Quartus/QSys to calculate SDRAM size
    	 * since the FB specifies we modify ROWBITs to work around SDRAM
    	 * controller issue.
    	 *
    	 * If the stored handoff value for rows is 0, it probably means
    	 * the preloader is older than UBoot. Use the
    	 * #define from the SOCEDS Tools per Crucible review
    	 * uboot-socfpga-204. Note that this is not a supported
    	 * configuration and is not tested. The customer
    	 * should be using preloader and uboot built from the
    	 * same tag.
    	 */
    	row = readl(&sysmgr_regs->iswgrp_handoff[4]);
    	if (row == 0)
    		row = CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_ROWBITS;
    	/* If the stored handoff value for rows is greater than
    	 * the field width in the sdr.dramaddrw register then
    	 * something is very wrong. Revert to using the the #define
    	 * value handed off by the SOCEDS tool chain instead of
    	 * using a broken value.
    	 */
    	if (row > 31)
    		row = CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_ROWBITS;
    
    	bank = (temp & SDR_CTRLGRP_DRAMADDRW_BANKBITS_MASK) >>
    		SDR_CTRLGRP_DRAMADDRW_BANKBITS_LSB;
    
    	/* SDRAM Failure When Accessing Non-Existent Memory
    	 * Use CSBITs from Quartus/QSys to calculate SDRAM size
    	 * since the FB specifies we modify CSBITs to work around SDRAM
    	 * controller issue.
    	 */
    	cs = (temp & SDR_CTRLGRP_DRAMADDRW_CSBITS_MASK) >>
    	      SDR_CTRLGRP_DRAMADDRW_CSBITS_LSB;
    	cs += 1;
    
    	cs = CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_CSBITS;
    
    	width = readl(&sdr_ctrl->dram_if_width);
    	/* ECC would not be calculated as its not addressible */
    	if (width == SDRAM_WIDTH_32BIT_WITH_ECC)
    		width = 32;
    	if (width == SDRAM_WIDTH_16BIT_WITH_ECC)
    		width = 16;
    
    	/* calculate the SDRAM size base on this info */
    	temp = 1 << (row + bank + col);
    	temp = temp * cs * (width  / 8);
    
    	debug("sdram_calculate_memory returns %ld\n", temp);
    
    	return temp;
    }