sdram-nokia.c 6.3 KB
Newer Older
T
Tero Kristo 已提交
1
/*
2
 * SDRC register values for Nokia boards
T
Tero Kristo 已提交
3
 *
4
 * Copyright (C) 2008, 2010-2011 Nokia Corporation
T
Tero Kristo 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * Lauri Leukkunen <lauri.leukkunen@nokia.com>
 *
 * Original code by Juha Yrjola <juha.yrjola@solidboot.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>

20
#include "common.h"
T
Tero Kristo 已提交
21 22 23
#include <plat/clock.h>
#include <plat/sdrc.h>

A
Aaro Koskinen 已提交
24
#include "sdram-nokia.h"
T
Tero Kristo 已提交
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

/* In picoseconds, except for tREF (ns), tXP, tCKE, tWTR (clks) */
struct sdram_timings {
	u32 casl;
	u32 tDAL;
	u32 tDPL;
	u32 tRRD;
	u32 tRCD;
	u32 tRP;
	u32 tRAS;
	u32 tRC;
	u32 tRFC;
	u32 tXSR;

	u32 tREF; /* in ns */

	u32 tXP;
	u32 tCKE;
	u32 tWTR;
};

46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
static const struct sdram_timings nokia_97dot6mhz_timings[] = {
	{
		.casl = 3,
		.tDAL = 30725,
		.tDPL = 15362,
		.tRRD = 10241,
		.tRCD = 20483,
		.tRP = 15362,
		.tRAS = 40967,
		.tRC = 56330,
		.tRFC = 138266,
		.tXSR = 204839,

		.tREF = 7798,

		.tXP = 2,
		.tCKE = 4,
		.tWTR = 2,
	},
};

67
static const struct sdram_timings nokia_166mhz_timings[] = {
T
Tero Kristo 已提交
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
	{
		.casl = 3,
		.tDAL = 33000,
		.tDPL = 15000,
		.tRRD = 12000,
		.tRCD = 22500,
		.tRP = 18000,
		.tRAS = 42000,
		.tRC = 66000,
		.tRFC = 138000,
		.tXSR = 200000,

		.tREF = 7800,

		.tXP = 2,
		.tCKE = 2,
		.tWTR = 2
	},
};

88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
static const struct sdram_timings nokia_195dot2mhz_timings[] = {
	{
		.casl = 3,
		.tDAL = 30725,
		.tDPL = 15362,
		.tRRD = 10241,
		.tRCD = 20483,
		.tRP = 15362,
		.tRAS = 40967,
		.tRC = 56330,
		.tRFC = 138266,
		.tXSR = 204839,

		.tREF = 7752,

		.tXP = 2,
		.tCKE = 4,
		.tWTR = 2,
	},
};

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
static const struct sdram_timings nokia_200mhz_timings[] = {
	{
		.casl = 3,
		.tDAL = 30000,
		.tDPL = 15000,
		.tRRD = 10000,
		.tRCD = 20000,
		.tRP = 15000,
		.tRAS = 40000,
		.tRC = 55000,
		.tRFC = 140000,
		.tXSR = 200000,

		.tREF = 7800,

		.tXP = 2,
		.tCKE = 4,
		.tWTR = 2
	},
};

130 131 132 133 134
static const struct {
	long rate;
	struct sdram_timings const *data;
} nokia_timings[] = {
	{ 83000000, nokia_166mhz_timings },
135
	{ 97600000, nokia_97dot6mhz_timings },
136
	{ 100000000, nokia_200mhz_timings },
137
	{ 166000000, nokia_166mhz_timings },
138
	{ 195200000, nokia_195dot2mhz_timings },
139
	{ 200000000, nokia_200mhz_timings },
140 141 142
};
static struct omap_sdrc_params nokia_sdrc_params[ARRAY_SIZE(nokia_timings) + 1];

T
Tero Kristo 已提交
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
static unsigned long sdrc_get_fclk_period(long rate)
{
	/* In picoseconds */
	return 1000000000 / rate;
}

static unsigned int sdrc_ps_to_ticks(unsigned int time_ps, long rate)
{
	unsigned long tick_ps;

	/* Calculate in picosecs to yield more exact results */
	tick_ps = sdrc_get_fclk_period(rate);

	return (time_ps + tick_ps - 1) / tick_ps;
}
#undef DEBUG
#ifdef DEBUG
static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit,
				int ticks, long rate, const char *name)
#else
static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit,
			       int ticks)
#endif
{
	int mask, nr_bits;

	nr_bits = end_bit - st_bit + 1;
	if (ticks >= 1 << nr_bits)
		return -1;
	mask = (1 << nr_bits) - 1;
	*regval &= ~(mask << st_bit);
	*regval |= ticks << st_bit;
#ifdef DEBUG
	printk(KERN_INFO "SDRC %s: %i ticks %i ns\n", name, ticks,
			(unsigned int)sdrc_get_fclk_period(rate) * ticks /
			1000);
#endif

	return 0;
}

#ifdef DEBUG
#define SDRC_SET_ONE(reg, st, end, field, rate) \
	if (set_sdrc_timing_regval((reg), (st), (end), \
187
			memory_timings->field, (rate), #field) < 0) \
T
Tero Kristo 已提交
188 189 190 191
		err = -1;
#else
#define SDRC_SET_ONE(reg, st, end, field, rate) \
	if (set_sdrc_timing_regval((reg), (st), (end), \
192
			memory_timings->field) < 0) \
T
Tero Kristo 已提交
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
		err = -1;
#endif

#ifdef DEBUG
static int set_sdrc_timing_regval_ps(u32 *regval, int st_bit, int end_bit,
				int time, long rate, const char *name)
#else
static int set_sdrc_timing_regval_ps(u32 *regval, int st_bit, int end_bit,
				int time, long rate)
#endif
{
	int ticks, ret;
	ret = 0;

	if (time == 0)
		ticks = 0;
	else
		ticks = sdrc_ps_to_ticks(time, rate);

#ifdef DEBUG
	ret = set_sdrc_timing_regval(regval, st_bit, end_bit, ticks,
				     rate, name);
#else
	ret = set_sdrc_timing_regval(regval, st_bit, end_bit, ticks);
#endif

	return ret;
}

#ifdef DEBUG
#define SDRC_SET_ONE_PS(reg, st, end, field, rate) \
	if (set_sdrc_timing_regval_ps((reg), (st), (end), \
225
			memory_timings->field, \
T
Tero Kristo 已提交
226 227 228 229 230 231
			(rate), #field) < 0) \
		err = -1;

#else
#define SDRC_SET_ONE_PS(reg, st, end, field, rate) \
	if (set_sdrc_timing_regval_ps((reg), (st), (end), \
232
			memory_timings->field, (rate)) < 0) \
T
Tero Kristo 已提交
233 234 235
		err = -1;
#endif

236 237
static int sdrc_timings(int id, long rate,
			const struct sdram_timings *memory_timings)
T
Tero Kristo 已提交
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
{
	u32 ticks_per_ms;
	u32 rfr, l;
	u32 actim_ctrla = 0, actim_ctrlb = 0;
	u32 rfr_ctrl;
	int err = 0;
	long l3_rate = rate / 1000;

	SDRC_SET_ONE_PS(&actim_ctrla,  0,  4, tDAL, l3_rate);
	SDRC_SET_ONE_PS(&actim_ctrla,  6,  8, tDPL, l3_rate);
	SDRC_SET_ONE_PS(&actim_ctrla,  9, 11, tRRD, l3_rate);
	SDRC_SET_ONE_PS(&actim_ctrla, 12, 14, tRCD, l3_rate);
	SDRC_SET_ONE_PS(&actim_ctrla, 15, 17, tRP, l3_rate);
	SDRC_SET_ONE_PS(&actim_ctrla, 18, 21, tRAS, l3_rate);
	SDRC_SET_ONE_PS(&actim_ctrla, 22, 26, tRC, l3_rate);
	SDRC_SET_ONE_PS(&actim_ctrla, 27, 31, tRFC, l3_rate);

	SDRC_SET_ONE_PS(&actim_ctrlb,  0,  7, tXSR, l3_rate);

	SDRC_SET_ONE(&actim_ctrlb,  8, 10, tXP, l3_rate);
	SDRC_SET_ONE(&actim_ctrlb, 12, 14, tCKE, l3_rate);
	SDRC_SET_ONE(&actim_ctrlb, 16, 17, tWTR, l3_rate);

	ticks_per_ms = l3_rate;
262
	rfr = memory_timings[0].tREF * ticks_per_ms / 1000000;
T
Tero Kristo 已提交
263 264 265 266 267 268 269 270 271 272 273 274
	if (rfr > 65535 + 50)
		rfr = 65535;
	else
		rfr -= 50;

#ifdef DEBUG
	printk(KERN_INFO "SDRC tREF: %i ticks\n", rfr);
#endif

	l = rfr << 8;
	rfr_ctrl = l | 0x1; /* autorefresh, reload counter with 1xARCV */

275 276 277 278 279
	nokia_sdrc_params[id].rate = rate;
	nokia_sdrc_params[id].actim_ctrla = actim_ctrla;
	nokia_sdrc_params[id].actim_ctrlb = actim_ctrlb;
	nokia_sdrc_params[id].rfr_ctrl = rfr_ctrl;
	nokia_sdrc_params[id].mr = 0x32;
T
Tero Kristo 已提交
280

281
	nokia_sdrc_params[id + 1].rate = 0;
T
Tero Kristo 已提交
282 283 284 285

	return err;
}

286
struct omap_sdrc_params *nokia_get_sdram_timings(void)
T
Tero Kristo 已提交
287
{
288 289
	int err = 0;
	int i;
T
Tero Kristo 已提交
290

291
	for (i = 0; i < ARRAY_SIZE(nokia_timings); i++) {
292 293
		err |= sdrc_timings(i, nokia_timings[i].rate,
				       nokia_timings[i].data);
294 295 296 297
		if (err)
			pr_err("%s: error with rate %ld: %d\n", __func__,
			       nokia_timings[i].rate, err);
	}
T
Tero Kristo 已提交
298

299
	return err ? NULL : nokia_sdrc_params;
T
Tero Kristo 已提交
300 301
}