ddr.c 15.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 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
/*
 * Copyright (C) 2014 Gateworks Corporation
 * Author: Tim Harvey <tharvey@gateworks.com>
 *
 * SPDX-License-Identifier:     GPL-2.0+
 */

#include <common.h>
#include <linux/types.h>
#include <asm/arch/mx6-ddr.h>
#include <asm/arch/sys_proto.h>
#include <asm/io.h>
#include <asm/types.h>

#if defined(CONFIG_MX6QDL) || defined(CONFIG_MX6Q) || defined(CONFIG_MX6D)
/* Configure MX6DQ mmdc iomux */
void mx6dq_dram_iocfg(unsigned width,
		      const struct mx6dq_iomux_ddr_regs *ddr,
		      const struct mx6dq_iomux_grp_regs *grp)
{
	volatile struct mx6dq_iomux_ddr_regs *mx6_ddr_iomux;
	volatile struct mx6dq_iomux_grp_regs *mx6_grp_iomux;

	mx6_ddr_iomux = (struct mx6dq_iomux_ddr_regs *)MX6DQ_IOM_DDR_BASE;
	mx6_grp_iomux = (struct mx6dq_iomux_grp_regs *)MX6DQ_IOM_GRP_BASE;

	/* DDR IO Type */
	mx6_grp_iomux->grp_ddr_type = grp->grp_ddr_type;
	mx6_grp_iomux->grp_ddrpke = grp->grp_ddrpke;

	/* Clock */
	mx6_ddr_iomux->dram_sdclk_0 = ddr->dram_sdclk_0;
	mx6_ddr_iomux->dram_sdclk_1 = ddr->dram_sdclk_1;

	/* Address */
	mx6_ddr_iomux->dram_cas = ddr->dram_cas;
	mx6_ddr_iomux->dram_ras = ddr->dram_ras;
	mx6_grp_iomux->grp_addds = grp->grp_addds;

	/* Control */
	mx6_ddr_iomux->dram_reset = ddr->dram_reset;
	mx6_ddr_iomux->dram_sdcke0 = ddr->dram_sdcke0;
	mx6_ddr_iomux->dram_sdcke1 = ddr->dram_sdcke1;
	mx6_ddr_iomux->dram_sdba2 = ddr->dram_sdba2;
	mx6_ddr_iomux->dram_sdodt0 = ddr->dram_sdodt0;
	mx6_ddr_iomux->dram_sdodt1 = ddr->dram_sdodt1;
	mx6_grp_iomux->grp_ctlds = grp->grp_ctlds;

	/* Data Strobes */
	mx6_grp_iomux->grp_ddrmode_ctl = grp->grp_ddrmode_ctl;
	mx6_ddr_iomux->dram_sdqs0 = ddr->dram_sdqs0;
	mx6_ddr_iomux->dram_sdqs1 = ddr->dram_sdqs1;
	if (width >= 32) {
		mx6_ddr_iomux->dram_sdqs2 = ddr->dram_sdqs2;
		mx6_ddr_iomux->dram_sdqs3 = ddr->dram_sdqs3;
	}
	if (width >= 64) {
		mx6_ddr_iomux->dram_sdqs4 = ddr->dram_sdqs4;
		mx6_ddr_iomux->dram_sdqs5 = ddr->dram_sdqs5;
		mx6_ddr_iomux->dram_sdqs6 = ddr->dram_sdqs6;
		mx6_ddr_iomux->dram_sdqs7 = ddr->dram_sdqs7;
	}

	/* Data */
	mx6_grp_iomux->grp_ddrmode = grp->grp_ddrmode;
	mx6_grp_iomux->grp_b0ds = grp->grp_b0ds;
	mx6_grp_iomux->grp_b1ds = grp->grp_b1ds;
	if (width >= 32) {
		mx6_grp_iomux->grp_b2ds = grp->grp_b2ds;
		mx6_grp_iomux->grp_b3ds = grp->grp_b3ds;
	}
	if (width >= 64) {
		mx6_grp_iomux->grp_b4ds = grp->grp_b4ds;
		mx6_grp_iomux->grp_b5ds = grp->grp_b5ds;
		mx6_grp_iomux->grp_b6ds = grp->grp_b6ds;
		mx6_grp_iomux->grp_b7ds = grp->grp_b7ds;
	}
	mx6_ddr_iomux->dram_dqm0 = ddr->dram_dqm0;
	mx6_ddr_iomux->dram_dqm1 = ddr->dram_dqm1;
	if (width >= 32) {
		mx6_ddr_iomux->dram_dqm2 = ddr->dram_dqm2;
		mx6_ddr_iomux->dram_dqm3 = ddr->dram_dqm3;
	}
	if (width >= 64) {
		mx6_ddr_iomux->dram_dqm4 = ddr->dram_dqm4;
		mx6_ddr_iomux->dram_dqm5 = ddr->dram_dqm5;
		mx6_ddr_iomux->dram_dqm6 = ddr->dram_dqm6;
		mx6_ddr_iomux->dram_dqm7 = ddr->dram_dqm7;
	}
}
#endif

#if defined(CONFIG_MX6QDL) || defined(CONFIG_MX6DL) || defined(CONFIG_MX6S)
/* Configure MX6SDL mmdc iomux */
void mx6sdl_dram_iocfg(unsigned width,
		       const struct mx6sdl_iomux_ddr_regs *ddr,
		       const struct mx6sdl_iomux_grp_regs *grp)
{
	volatile struct mx6sdl_iomux_ddr_regs *mx6_ddr_iomux;
	volatile struct mx6sdl_iomux_grp_regs *mx6_grp_iomux;

	mx6_ddr_iomux = (struct mx6sdl_iomux_ddr_regs *)MX6SDL_IOM_DDR_BASE;
	mx6_grp_iomux = (struct mx6sdl_iomux_grp_regs *)MX6SDL_IOM_GRP_BASE;

	/* DDR IO Type */
	mx6_grp_iomux->grp_ddr_type = grp->grp_ddr_type;
	mx6_grp_iomux->grp_ddrpke = grp->grp_ddrpke;

	/* Clock */
	mx6_ddr_iomux->dram_sdclk_0 = ddr->dram_sdclk_0;
	mx6_ddr_iomux->dram_sdclk_1 = ddr->dram_sdclk_1;

	/* Address */
	mx6_ddr_iomux->dram_cas = ddr->dram_cas;
	mx6_ddr_iomux->dram_ras = ddr->dram_ras;
	mx6_grp_iomux->grp_addds = grp->grp_addds;

	/* Control */
	mx6_ddr_iomux->dram_reset = ddr->dram_reset;
	mx6_ddr_iomux->dram_sdcke0 = ddr->dram_sdcke0;
	mx6_ddr_iomux->dram_sdcke1 = ddr->dram_sdcke1;
	mx6_ddr_iomux->dram_sdba2 = ddr->dram_sdba2;
	mx6_ddr_iomux->dram_sdodt0 = ddr->dram_sdodt0;
	mx6_ddr_iomux->dram_sdodt1 = ddr->dram_sdodt1;
	mx6_grp_iomux->grp_ctlds = grp->grp_ctlds;

	/* Data Strobes */
	mx6_grp_iomux->grp_ddrmode_ctl = grp->grp_ddrmode_ctl;
	mx6_ddr_iomux->dram_sdqs0 = ddr->dram_sdqs0;
	mx6_ddr_iomux->dram_sdqs1 = ddr->dram_sdqs1;
	if (width >= 32) {
		mx6_ddr_iomux->dram_sdqs2 = ddr->dram_sdqs2;
		mx6_ddr_iomux->dram_sdqs3 = ddr->dram_sdqs3;
	}
	if (width >= 64) {
		mx6_ddr_iomux->dram_sdqs4 = ddr->dram_sdqs4;
		mx6_ddr_iomux->dram_sdqs5 = ddr->dram_sdqs5;
		mx6_ddr_iomux->dram_sdqs6 = ddr->dram_sdqs6;
		mx6_ddr_iomux->dram_sdqs7 = ddr->dram_sdqs7;
	}

	/* Data */
	mx6_grp_iomux->grp_ddrmode = grp->grp_ddrmode;
	mx6_grp_iomux->grp_b0ds = grp->grp_b0ds;
	mx6_grp_iomux->grp_b1ds = grp->grp_b1ds;
	if (width >= 32) {
		mx6_grp_iomux->grp_b2ds = grp->grp_b2ds;
		mx6_grp_iomux->grp_b3ds = grp->grp_b3ds;
	}
	if (width >= 64) {
		mx6_grp_iomux->grp_b4ds = grp->grp_b4ds;
		mx6_grp_iomux->grp_b5ds = grp->grp_b5ds;
		mx6_grp_iomux->grp_b6ds = grp->grp_b6ds;
		mx6_grp_iomux->grp_b7ds = grp->grp_b7ds;
	}
	mx6_ddr_iomux->dram_dqm0 = ddr->dram_dqm0;
	mx6_ddr_iomux->dram_dqm1 = ddr->dram_dqm1;
	if (width >= 32) {
		mx6_ddr_iomux->dram_dqm2 = ddr->dram_dqm2;
		mx6_ddr_iomux->dram_dqm3 = ddr->dram_dqm3;
	}
	if (width >= 64) {
		mx6_ddr_iomux->dram_dqm4 = ddr->dram_dqm4;
		mx6_ddr_iomux->dram_dqm5 = ddr->dram_dqm5;
		mx6_ddr_iomux->dram_dqm6 = ddr->dram_dqm6;
		mx6_ddr_iomux->dram_dqm7 = ddr->dram_dqm7;
	}
}
#endif

/*
 * Configure mx6 mmdc registers based on:
 *  - board-specific memory configuration
 *  - board-specific calibration data
 *  - ddr3 chip details
 *
 * The various calculations here are derived from the Freescale
 * i.Mx6DQSDL DDR3 Script Aid spreadsheet (DOC-94917) designed to generate MMDC
 * configuration registers based on memory system and memory chip parameters.
 *
 * The defaults here are those which were specified in the spreadsheet.
 * For details on each register, refer to the IMX6DQRM and/or IMX6SDLRM
 * section titled MMDC initialization
 */
#define MR(val, ba, cmd, cs1) \
	((val << 16) | (1 << 15) | (cmd << 4) | (cs1 << 3) | ba)
Nikita Kiryanov's avatar
Nikita Kiryanov committed
187 188 189
void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
		  const struct mx6_mmdc_calibration *calib,
		  const struct mx6_ddr3_cfg *ddr3_cfg)
190 191 192
{
	volatile struct mmdc_p_regs *mmdc0;
	volatile struct mmdc_p_regs *mmdc1;
Nikita Kiryanov's avatar
Nikita Kiryanov committed
193
	u32 val;
194 195 196 197
	u8 tcke, tcksrx, tcksre, txpdll, taofpd, taonpd, trrd;
	u8 todtlon, taxpd, tanpd, tcwl, txp, tfaw, tcl;
	u8 todt_idle_off = 0x4; /* from DDR3 Script Aid spreadsheet */
	u16 trcd, trc, tras, twr, tmrd, trtp, trp, twtr, trfc, txs, txpr;
Nikita Kiryanov's avatar
Nikita Kiryanov committed
198
	u16 cs0_end;
199
	u16 tdllk = 0x1ff; /* DLL locking time: 512 cycles (JEDEC DDR3) */
200
	u8 coladdr;
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
	int clkper; /* clock period in picoseconds */
	int clock; /* clock freq in mHz */
	int cs;

	mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR;
	mmdc1 = (struct mmdc_p_regs *)MMDC_P1_BASE_ADDR;

	/* MX6D/MX6Q: 1066 MHz memory clock, clkper = 1.894ns = 1894ps */
	if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D)) {
		clock = 528;
		tcwl = 4;
	}
	/* MX6S/MX6DL: 800 MHz memory clock, clkper = 2.5ns = 2500ps */
	else {
		clock = 400;
		tcwl = 3;
	}
Nikita Kiryanov's avatar
Nikita Kiryanov committed
218
	clkper = (1000 * 1000) / clock; /* pico seconds */
219 220 221 222
	todtlon = tcwl;
	taxpd = tcwl;
	tanpd = tcwl;

Nikita Kiryanov's avatar
Nikita Kiryanov committed
223
	switch (ddr3_cfg->density) {
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
	case 1: /* 1Gb per chip */
		trfc = DIV_ROUND_UP(110000, clkper) - 1;
		txs = DIV_ROUND_UP(120000, clkper) - 1;
		break;
	case 2: /* 2Gb per chip */
		trfc = DIV_ROUND_UP(160000, clkper) - 1;
		txs = DIV_ROUND_UP(170000, clkper) - 1;
		break;
	case 4: /* 4Gb per chip */
		trfc = DIV_ROUND_UP(260000, clkper) - 1;
		txs = DIV_ROUND_UP(270000, clkper) - 1;
		break;
	case 8: /* 8Gb per chip */
		trfc = DIV_ROUND_UP(350000, clkper) - 1;
		txs = DIV_ROUND_UP(360000, clkper) - 1;
		break;
	default:
		/* invalid density */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
242
		puts("invalid chip density\n");
243 244 245 246 247
		hang();
		break;
	}
	txpr = txs;

Nikita Kiryanov's avatar
Nikita Kiryanov committed
248
	switch (ddr3_cfg->mem_speed) {
249
	case 800:
Nikita Kiryanov's avatar
Nikita Kiryanov committed
250 251 252
		txp = DIV_ROUND_UP(MAX(3 * clkper, 7500), clkper) - 1;
		tcke = DIV_ROUND_UP(MAX(3 * clkper, 7500), clkper) - 1;
		if (ddr3_cfg->pagesz == 1) {
253
			tfaw = DIV_ROUND_UP(40000, clkper) - 1;
Nikita Kiryanov's avatar
Nikita Kiryanov committed
254
			trrd = DIV_ROUND_UP(MAX(4 * clkper, 10000), clkper) - 1;
255 256
		} else {
			tfaw = DIV_ROUND_UP(50000, clkper) - 1;
Nikita Kiryanov's avatar
Nikita Kiryanov committed
257
			trrd = DIV_ROUND_UP(MAX(4 * clkper, 10000), clkper) - 1;
258 259 260
		}
		break;
	case 1066:
Nikita Kiryanov's avatar
Nikita Kiryanov committed
261 262 263
		txp = DIV_ROUND_UP(MAX(3 * clkper, 7500), clkper) - 1;
		tcke = DIV_ROUND_UP(MAX(3 * clkper, 5625), clkper) - 1;
		if (ddr3_cfg->pagesz == 1) {
264
			tfaw = DIV_ROUND_UP(37500, clkper) - 1;
Nikita Kiryanov's avatar
Nikita Kiryanov committed
265
			trrd = DIV_ROUND_UP(MAX(4 * clkper, 7500), clkper) - 1;
266 267
		} else {
			tfaw = DIV_ROUND_UP(50000, clkper) - 1;
Nikita Kiryanov's avatar
Nikita Kiryanov committed
268
			trrd = DIV_ROUND_UP(MAX(4 * clkper, 10000), clkper) - 1;
269 270 271
		}
		break;
	case 1333:
Nikita Kiryanov's avatar
Nikita Kiryanov committed
272 273 274
		txp = DIV_ROUND_UP(MAX(3 * clkper, 6000), clkper) - 1;
		tcke = DIV_ROUND_UP(MAX(3 * clkper, 5625), clkper) - 1;
		if (ddr3_cfg->pagesz == 1) {
275
			tfaw = DIV_ROUND_UP(30000, clkper) - 1;
Nikita Kiryanov's avatar
Nikita Kiryanov committed
276
			trrd = DIV_ROUND_UP(MAX(4 * clkper, 6000), clkper) - 1;
277 278
		} else {
			tfaw = DIV_ROUND_UP(45000, clkper) - 1;
Nikita Kiryanov's avatar
Nikita Kiryanov committed
279
			trrd = DIV_ROUND_UP(MAX(4 * clkper, 7500), clkper) - 1;
280 281 282
		}
		break;
	case 1600:
Nikita Kiryanov's avatar
Nikita Kiryanov committed
283 284 285
		txp = DIV_ROUND_UP(MAX(3 * clkper, 6000), clkper) - 1;
		tcke = DIV_ROUND_UP(MAX(3 * clkper, 5000), clkper) - 1;
		if (ddr3_cfg->pagesz == 1) {
286
			tfaw = DIV_ROUND_UP(30000, clkper) - 1;
Nikita Kiryanov's avatar
Nikita Kiryanov committed
287
			trrd = DIV_ROUND_UP(MAX(4 * clkper, 6000), clkper) - 1;
288 289
		} else {
			tfaw = DIV_ROUND_UP(40000, clkper) - 1;
Nikita Kiryanov's avatar
Nikita Kiryanov committed
290
			trrd = DIV_ROUND_UP(MAX(4 * clkper, 7500), clkper) - 1;
291 292 293
		}
		break;
	default:
Nikita Kiryanov's avatar
Nikita Kiryanov committed
294
		puts("invalid memory speed\n");
295 296 297
		hang();
		break;
	}
Nikita Kiryanov's avatar
Nikita Kiryanov committed
298 299
	txpdll = DIV_ROUND_UP(MAX(10 * clkper, 24000), clkper) - 1;
	tcksre = DIV_ROUND_UP(MAX(5 * clkper, 10000), clkper);
300
	taonpd = DIV_ROUND_UP(2000, clkper) - 1;
Nikita Kiryanov's avatar
Nikita Kiryanov committed
301
	tcksrx = tcksre;
302
	taofpd = taonpd;
Nikita Kiryanov's avatar
Nikita Kiryanov committed
303 304 305 306 307 308 309
	twr  = DIV_ROUND_UP(15000, clkper) - 1;
	tmrd = DIV_ROUND_UP(MAX(12 * clkper, 15000), clkper) - 1;
	trc  = DIV_ROUND_UP(ddr3_cfg->trcmin, clkper / 10) - 1;
	tras = DIV_ROUND_UP(ddr3_cfg->trasmin, clkper / 10) - 1;
	tcl  = DIV_ROUND_UP(ddr3_cfg->trcd, clkper / 10) - 3;
	trp  = DIV_ROUND_UP(ddr3_cfg->trcd, clkper / 10) - 1;
	twtr = ROUND(MAX(4 * clkper, 7500) / clkper, 1) - 1;
310 311
	trcd = trp;
	trtp = twtr;
312
	cs0_end = 4 * sysinfo->cs_density - 1;
Nikita Kiryanov's avatar
Nikita Kiryanov committed
313 314 315

	debug("density:%d Gb (%d Gb per chip)\n",
	      sysinfo->cs_density, ddr3_cfg->density);
316
	debug("clock: %dMHz (%d ps)\n", clock, clkper);
Nikita Kiryanov's avatar
Nikita Kiryanov committed
317
	debug("memspd:%d\n", ddr3_cfg->mem_speed);
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
	debug("tcke=%d\n", tcke);
	debug("tcksrx=%d\n", tcksrx);
	debug("tcksre=%d\n", tcksre);
	debug("taofpd=%d\n", taofpd);
	debug("taonpd=%d\n", taonpd);
	debug("todtlon=%d\n", todtlon);
	debug("tanpd=%d\n", tanpd);
	debug("taxpd=%d\n", taxpd);
	debug("trfc=%d\n", trfc);
	debug("txs=%d\n", txs);
	debug("txp=%d\n", txp);
	debug("txpdll=%d\n", txpdll);
	debug("tfaw=%d\n", tfaw);
	debug("tcl=%d\n", tcl);
	debug("trcd=%d\n", trcd);
	debug("trp=%d\n", trp);
	debug("trc=%d\n", trc);
	debug("tras=%d\n", tras);
	debug("twr=%d\n", twr);
	debug("tmrd=%d\n", tmrd);
	debug("tcwl=%d\n", tcwl);
	debug("tdllk=%d\n", tdllk);
	debug("trtp=%d\n", trtp);
	debug("twtr=%d\n", twtr);
	debug("trrd=%d\n", trrd);
	debug("txpr=%d\n", txpr);
Nikita Kiryanov's avatar
Nikita Kiryanov committed
344 345 346 347 348
	debug("cs0_end=%d\n", cs0_end);
	debug("ncs=%d\n", sysinfo->ncs);
	debug("Rtt_wr=%d\n", sysinfo->rtt_wr);
	debug("Rtt_nom=%d\n", sysinfo->rtt_nom);
	debug("SRT=%d\n", ddr3_cfg->SRT);
349 350 351 352 353 354 355 356 357
	debug("tcl=%d\n", tcl);
	debug("twr=%d\n", twr);

	/*
	 * board-specific configuration:
	 *  These values are determined empirically and vary per board layout
	 *  see:
	 *   appnote, ddr3 spreadsheet
	 */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
358 359 360 361 362 363 364 365 366 367 368 369 370
	mmdc0->mpwldectrl0 = calib->p0_mpwldectrl0;
	mmdc0->mpwldectrl1 = calib->p0_mpwldectrl1;
	mmdc0->mpdgctrl0 = calib->p0_mpdgctrl0;
	mmdc0->mpdgctrl1 = calib->p0_mpdgctrl1;
	mmdc0->mprddlctl = calib->p0_mprddlctl;
	mmdc0->mpwrdlctl = calib->p0_mpwrdlctl;
	if (sysinfo->dsize > 1) {
		mmdc1->mpwldectrl0 = calib->p1_mpwldectrl0;
		mmdc1->mpwldectrl1 = calib->p1_mpwldectrl1;
		mmdc1->mpdgctrl0 = calib->p1_mpdgctrl0;
		mmdc1->mpdgctrl1 = calib->p1_mpdgctrl1;
		mmdc1->mprddlctl = calib->p1_mprddlctl;
		mmdc1->mpwrdlctl = calib->p1_mpwrdlctl;
371 372 373
	}

	/* Read data DQ Byte0-3 delay */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
374 375 376 377 378
	mmdc0->mprddqby0dl = 0x33333333;
	mmdc0->mprddqby1dl = 0x33333333;
	if (sysinfo->dsize > 0) {
		mmdc0->mprddqby2dl = 0x33333333;
		mmdc0->mprddqby3dl = 0x33333333;
379
	}
Nikita Kiryanov's avatar
Nikita Kiryanov committed
380 381 382 383 384 385

	if (sysinfo->dsize > 1) {
		mmdc1->mprddqby0dl = 0x33333333;
		mmdc1->mprddqby1dl = 0x33333333;
		mmdc1->mprddqby2dl = 0x33333333;
		mmdc1->mprddqby3dl = 0x33333333;
386 387 388
	}

	/* MMDC Termination: rtt_nom:2 RZQ/2(120ohm), rtt_nom:1 RZQ/4(60ohm) */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
389 390 391 392
	val = (sysinfo->rtt_nom == 2) ? 0x00011117 : 0x00022227;
	mmdc0->mpodtctrl = val;
	if (sysinfo->dsize > 1)
		mmdc1->mpodtctrl = val;
393 394

	/* complete calibration */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
395 396 397 398
	val = (1 << 11); /* Force measurement on delay-lines */
	mmdc0->mpmur0 = val;
	if (sysinfo->dsize > 1)
		mmdc1->mpmur0 = val;
399 400 401 402 403

	/* Step 1: configuration request */
	mmdc0->mdscr = (u32)(1 << 15); /* config request */

	/* Step 2: Timing configuration */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
404 405 406 407 408 409 410 411 412
	mmdc0->mdcfg0 = (trfc << 24) | (txs << 16) | (txp << 13) |
			(txpdll << 9) | (tfaw << 4) | tcl;
	mmdc0->mdcfg1 = (trcd << 29) | (trp << 26) | (trc << 21) |
			(tras << 16) | (1 << 15) /* trpa */ |
			(twr << 9) | (tmrd << 5) | tcwl;
	mmdc0->mdcfg2 = (tdllk << 16) | (trtp << 6) | (twtr << 3) | trrd;
	mmdc0->mdotc = (taofpd << 27) | (taonpd << 24) | (tanpd << 20) |
		       (taxpd << 16) | (todtlon << 12) | (todt_idle_off << 4);
	mmdc0->mdasp = cs0_end; /* CS addressing */
413 414

	/* Step 3: Configure DDR type */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
415 416 417
	mmdc0->mdmisc = (sysinfo->cs1_mirror << 19) | (sysinfo->walat << 16) |
			(sysinfo->bi_on << 12) | (sysinfo->mif3_mode << 9) |
			(sysinfo->ralat << 6);
418 419

	/* Step 4: Configure delay while leaving reset */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
420 421
	mmdc0->mdor = (txpr << 16) | (sysinfo->sde_to_rst << 8) |
		      (sysinfo->rst_to_cke << 0);
422 423

	/* Step 5: Configure DDR physical parameters (density and burst len) */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
424 425
	coladdr = ddr3_cfg->coladdr;
	if (ddr3_cfg->coladdr == 8)		/* 8-bit COL is 0x3 */
426
		coladdr += 4;
Nikita Kiryanov's avatar
Nikita Kiryanov committed
427
	else if (ddr3_cfg->coladdr == 12)	/* 12-bit COL is 0x4 */
428
		coladdr += 1;
Nikita Kiryanov's avatar
Nikita Kiryanov committed
429 430 431 432
	mmdc0->mdctl =  (ddr3_cfg->rowaddr - 11) << 24 |	/* ROW */
			(coladdr - 9) << 20 |			/* COL */
			(1 << 19) |		/* Burst Length = 8 for DDR3 */
			(sysinfo->dsize << 16);		/* DDR data bus size */
433 434

	/* Step 6: Perform ZQ calibration */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
435 436 437 438
	val = 0xa1390001; /* one-time HW ZQ calib */
	mmdc0->mpzqhwctrl = val;
	if (sysinfo->dsize > 1)
		mmdc1->mpzqhwctrl = val;
439 440

	/* Step 7: Enable MMDC with desired chip select */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
441 442
	mmdc0->mdctl |= (1 << 31) |			     /* SDE_0 for CS0 */
			((sysinfo->ncs == 2) ? 1 : 0) << 30; /* SDE_1 for CS1 */
443 444

	/* Step 8: Write Mode Registers to Init DDR3 devices */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
445
	for (cs = 0; cs < sysinfo->ncs; cs++) {
446
		/* MR2 */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
447
		val = (sysinfo->rtt_wr & 3) << 9 | (ddr3_cfg->SRT & 1) << 7 |
448
		      ((tcwl - 3) & 3) << 3;
Nikita Kiryanov's avatar
Nikita Kiryanov committed
449
		mmdc0->mdscr = MR(val, 2, 3, cs);
450
		/* MR3 */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
451
		mmdc0->mdscr = MR(0, 3, 3, cs);
452
		/* MR1 */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
453 454 455 456 457
		val = ((sysinfo->rtt_nom & 1) ? 1 : 0) << 2 |
		      ((sysinfo->rtt_nom & 2) ? 1 : 0) << 6;
		mmdc0->mdscr = MR(val, 1, 3, cs);
		/* MR0 */
		val = ((tcl - 1) << 4) |	/* CAS */
458 459
		      (1 << 8)   |		/* DLL Reset */
		      ((twr - 3) << 9);		/* Write Recovery */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
460
		mmdc0->mdscr = MR(val, 0, 3, cs);
461
		/* ZQ calibration */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
462 463
		val = (1 << 10);
		mmdc0->mdscr = MR(val, 0, 4, cs);
464 465 466
	}

	/* Step 10: Power down control and self-refresh */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
467 468 469
	mmdc0->mdpdc = (tcke & 0x7) << 16 |
			5            << 12 |  /* PWDT_1: 256 cycles */
			5            <<  8 |  /* PWDT_0: 256 cycles */
470
			1            <<  7 |  /* SLOW_PD */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
471 472 473
			1            <<  6 |  /* BOTH_CS_PD */
			(tcksrx & 0x7) << 3 |
			(tcksre & 0x7);
474
	mmdc0->mapsr = 0x00001006; /* ADOPT power down enabled */
475 476

	/* Step 11: Configure ZQ calibration: one-time and periodic 1ms */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
477 478 479 480
	val = 0xa1390003;
	mmdc0->mpzqhwctrl = val;
	if (sysinfo->dsize > 1)
		mmdc1->mpzqhwctrl = val;
481 482

	/* Step 12: Configure and activate periodic refresh */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
483 484
	mmdc0->mdref = (1 << 14) | /* REF_SEL: Periodic refresh cycle: 32kHz */
		       (7 << 11);  /* REFR: Refresh Rate - 8 refreshes */
485 486

	/* Step 13: Deassert config request - init complete */
Nikita Kiryanov's avatar
Nikita Kiryanov committed
487
	mmdc0->mdscr = 0x00000000;
488 489 490 491

	/* wait for auto-ZQ calibration to complete */
	mdelay(1);
}