linux/arch/arm/mach-omap2/sdram-nokia.c
<<
>>
Prefs
   1/*
   2 * SDRC register values for Nokia boards
   3 *
   4 * Copyright (C) 2008, 2010-2011 Nokia Corporation
   5 *
   6 * Lauri Leukkunen <lauri.leukkunen@nokia.com>
   7 *
   8 * Original code by Juha Yrjola <juha.yrjola@solidboot.com>
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2 as
  12 * published by the Free Software Foundation.
  13 */
  14
  15#include <linux/kernel.h>
  16#include <linux/clk.h>
  17#include <linux/err.h>
  18#include <linux/io.h>
  19
  20#include "common.h"
  21#include "sdram-nokia.h"
  22#include "sdrc.h"
  23
  24/* In picoseconds, except for tREF (ns), tXP, tCKE, tWTR (clks) */
  25struct sdram_timings {
  26        u32 casl;
  27        u32 tDAL;
  28        u32 tDPL;
  29        u32 tRRD;
  30        u32 tRCD;
  31        u32 tRP;
  32        u32 tRAS;
  33        u32 tRC;
  34        u32 tRFC;
  35        u32 tXSR;
  36
  37        u32 tREF; /* in ns */
  38
  39        u32 tXP;
  40        u32 tCKE;
  41        u32 tWTR;
  42};
  43
  44static const struct sdram_timings nokia_97dot6mhz_timings[] = {
  45        {
  46                .casl = 3,
  47                .tDAL = 30725,
  48                .tDPL = 15362,
  49                .tRRD = 10241,
  50                .tRCD = 20483,
  51                .tRP = 15362,
  52                .tRAS = 40967,
  53                .tRC = 56330,
  54                .tRFC = 138266,
  55                .tXSR = 204839,
  56
  57                .tREF = 7798,
  58
  59                .tXP = 2,
  60                .tCKE = 4,
  61                .tWTR = 2,
  62        },
  63};
  64
  65static const struct sdram_timings nokia_166mhz_timings[] = {
  66        {
  67                .casl = 3,
  68                .tDAL = 33000,
  69                .tDPL = 15000,
  70                .tRRD = 12000,
  71                .tRCD = 22500,
  72                .tRP = 18000,
  73                .tRAS = 42000,
  74                .tRC = 66000,
  75                .tRFC = 138000,
  76                .tXSR = 200000,
  77
  78                .tREF = 7800,
  79
  80                .tXP = 2,
  81                .tCKE = 2,
  82                .tWTR = 2
  83        },
  84};
  85
  86static const struct sdram_timings nokia_195dot2mhz_timings[] = {
  87        {
  88                .casl = 3,
  89                .tDAL = 30725,
  90                .tDPL = 15362,
  91                .tRRD = 10241,
  92                .tRCD = 20483,
  93                .tRP = 15362,
  94                .tRAS = 40967,
  95                .tRC = 56330,
  96                .tRFC = 138266,
  97                .tXSR = 204839,
  98
  99                .tREF = 7752,
 100
 101                .tXP = 2,
 102                .tCKE = 4,
 103                .tWTR = 2,
 104        },
 105};
 106
 107static const struct sdram_timings nokia_200mhz_timings[] = {
 108        {
 109                .casl = 3,
 110                .tDAL = 30000,
 111                .tDPL = 15000,
 112                .tRRD = 10000,
 113                .tRCD = 20000,
 114                .tRP = 15000,
 115                .tRAS = 40000,
 116                .tRC = 55000,
 117                .tRFC = 140000,
 118                .tXSR = 200000,
 119
 120                .tREF = 7800,
 121
 122                .tXP = 2,
 123                .tCKE = 4,
 124                .tWTR = 2
 125        },
 126};
 127
 128static const struct {
 129        long rate;
 130        struct sdram_timings const *data;
 131} nokia_timings[] = {
 132        { 83000000, nokia_166mhz_timings },
 133        { 97600000, nokia_97dot6mhz_timings },
 134        { 100000000, nokia_200mhz_timings },
 135        { 166000000, nokia_166mhz_timings },
 136        { 195200000, nokia_195dot2mhz_timings },
 137        { 200000000, nokia_200mhz_timings },
 138};
 139static struct omap_sdrc_params nokia_sdrc_params[ARRAY_SIZE(nokia_timings) + 1];
 140
 141static unsigned long sdrc_get_fclk_period(long rate)
 142{
 143        /* In picoseconds */
 144        return 1000000000 / rate;
 145}
 146
 147static unsigned int sdrc_ps_to_ticks(unsigned int time_ps, long rate)
 148{
 149        unsigned long tick_ps;
 150
 151        /* Calculate in picosecs to yield more exact results */
 152        tick_ps = sdrc_get_fclk_period(rate);
 153
 154        return (time_ps + tick_ps - 1) / tick_ps;
 155}
 156#undef DEBUG
 157#ifdef DEBUG
 158static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit,
 159                                int ticks, long rate, const char *name)
 160#else
 161static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit,
 162                               int ticks)
 163#endif
 164{
 165        int mask, nr_bits;
 166
 167        nr_bits = end_bit - st_bit + 1;
 168        if (ticks >= 1 << nr_bits)
 169                return -1;
 170        mask = (1 << nr_bits) - 1;
 171        *regval &= ~(mask << st_bit);
 172        *regval |= ticks << st_bit;
 173#ifdef DEBUG
 174        printk(KERN_INFO "SDRC %s: %i ticks %i ns\n", name, ticks,
 175                        (unsigned int)sdrc_get_fclk_period(rate) * ticks /
 176                        1000);
 177#endif
 178
 179        return 0;
 180}
 181
 182#ifdef DEBUG
 183#define SDRC_SET_ONE(reg, st, end, field, rate) \
 184        if (set_sdrc_timing_regval((reg), (st), (end), \
 185                        memory_timings->field, (rate), #field) < 0) \
 186                err = -1;
 187#else
 188#define SDRC_SET_ONE(reg, st, end, field, rate) \
 189        if (set_sdrc_timing_regval((reg), (st), (end), \
 190                        memory_timings->field) < 0) \
 191                err = -1;
 192#endif
 193
 194#ifdef DEBUG
 195static int set_sdrc_timing_regval_ps(u32 *regval, int st_bit, int end_bit,
 196                                int time, long rate, const char *name)
 197#else
 198static int set_sdrc_timing_regval_ps(u32 *regval, int st_bit, int end_bit,
 199                                int time, long rate)
 200#endif
 201{
 202        int ticks, ret;
 203        ret = 0;
 204
 205        if (time == 0)
 206                ticks = 0;
 207        else
 208                ticks = sdrc_ps_to_ticks(time, rate);
 209
 210#ifdef DEBUG
 211        ret = set_sdrc_timing_regval(regval, st_bit, end_bit, ticks,
 212                                     rate, name);
 213#else
 214        ret = set_sdrc_timing_regval(regval, st_bit, end_bit, ticks);
 215#endif
 216
 217        return ret;
 218}
 219
 220#ifdef DEBUG
 221#define SDRC_SET_ONE_PS(reg, st, end, field, rate) \
 222        if (set_sdrc_timing_regval_ps((reg), (st), (end), \
 223                        memory_timings->field, \
 224                        (rate), #field) < 0) \
 225                err = -1;
 226
 227#else
 228#define SDRC_SET_ONE_PS(reg, st, end, field, rate) \
 229        if (set_sdrc_timing_regval_ps((reg), (st), (end), \
 230                        memory_timings->field, (rate)) < 0) \
 231                err = -1;
 232#endif
 233
 234static int sdrc_timings(int id, long rate,
 235                        const struct sdram_timings *memory_timings)
 236{
 237        u32 ticks_per_ms;
 238        u32 rfr, l;
 239        u32 actim_ctrla = 0, actim_ctrlb = 0;
 240        u32 rfr_ctrl;
 241        int err = 0;
 242        long l3_rate = rate / 1000;
 243
 244        SDRC_SET_ONE_PS(&actim_ctrla,  0,  4, tDAL, l3_rate);
 245        SDRC_SET_ONE_PS(&actim_ctrla,  6,  8, tDPL, l3_rate);
 246        SDRC_SET_ONE_PS(&actim_ctrla,  9, 11, tRRD, l3_rate);
 247        SDRC_SET_ONE_PS(&actim_ctrla, 12, 14, tRCD, l3_rate);
 248        SDRC_SET_ONE_PS(&actim_ctrla, 15, 17, tRP, l3_rate);
 249        SDRC_SET_ONE_PS(&actim_ctrla, 18, 21, tRAS, l3_rate);
 250        SDRC_SET_ONE_PS(&actim_ctrla, 22, 26, tRC, l3_rate);
 251        SDRC_SET_ONE_PS(&actim_ctrla, 27, 31, tRFC, l3_rate);
 252
 253        SDRC_SET_ONE_PS(&actim_ctrlb,  0,  7, tXSR, l3_rate);
 254
 255        SDRC_SET_ONE(&actim_ctrlb,  8, 10, tXP, l3_rate);
 256        SDRC_SET_ONE(&actim_ctrlb, 12, 14, tCKE, l3_rate);
 257        SDRC_SET_ONE(&actim_ctrlb, 16, 17, tWTR, l3_rate);
 258
 259        ticks_per_ms = l3_rate;
 260        rfr = memory_timings[0].tREF * ticks_per_ms / 1000000;
 261        if (rfr > 65535 + 50)
 262                rfr = 65535;
 263        else
 264                rfr -= 50;
 265
 266#ifdef DEBUG
 267        printk(KERN_INFO "SDRC tREF: %i ticks\n", rfr);
 268#endif
 269
 270        l = rfr << 8;
 271        rfr_ctrl = l | 0x1; /* autorefresh, reload counter with 1xARCV */
 272
 273        nokia_sdrc_params[id].rate = rate;
 274        nokia_sdrc_params[id].actim_ctrla = actim_ctrla;
 275        nokia_sdrc_params[id].actim_ctrlb = actim_ctrlb;
 276        nokia_sdrc_params[id].rfr_ctrl = rfr_ctrl;
 277        nokia_sdrc_params[id].mr = 0x32;
 278
 279        nokia_sdrc_params[id + 1].rate = 0;
 280
 281        return err;
 282}
 283
 284struct omap_sdrc_params *nokia_get_sdram_timings(void)
 285{
 286        int err = 0;
 287        int i;
 288
 289        for (i = 0; i < ARRAY_SIZE(nokia_timings); i++) {
 290                err |= sdrc_timings(i, nokia_timings[i].rate,
 291                                       nokia_timings[i].data);
 292                if (err)
 293                        pr_err("%s: error with rate %ld: %d\n", __func__,
 294                               nokia_timings[i].rate, err);
 295        }
 296
 297        return err ? NULL : nokia_sdrc_params;
 298}
 299
 300