Commit | Line | Data |
---|---|---|
2000655e TK |
1 | /* |
2 | * SDRC register values for RX51 | |
3 | * | |
4 | * Copyright (C) 2008 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 <plat/io.h> | |
21 | #include <plat/common.h> | |
22 | #include <plat/clock.h> | |
23 | #include <plat/sdrc.h> | |
24 | ||
25 | ||
26 | /* In picoseconds, except for tREF (ns), tXP, tCKE, tWTR (clks) */ | |
27 | struct sdram_timings { | |
28 | u32 casl; | |
29 | u32 tDAL; | |
30 | u32 tDPL; | |
31 | u32 tRRD; | |
32 | u32 tRCD; | |
33 | u32 tRP; | |
34 | u32 tRAS; | |
35 | u32 tRC; | |
36 | u32 tRFC; | |
37 | u32 tXSR; | |
38 | ||
39 | u32 tREF; /* in ns */ | |
40 | ||
41 | u32 tXP; | |
42 | u32 tCKE; | |
43 | u32 tWTR; | |
44 | }; | |
45 | ||
46 | struct omap_sdrc_params rx51_sdrc_params[4]; | |
47 | ||
48 | static const struct sdram_timings rx51_timings[] = { | |
49 | { | |
50 | .casl = 3, | |
51 | .tDAL = 33000, | |
52 | .tDPL = 15000, | |
53 | .tRRD = 12000, | |
54 | .tRCD = 22500, | |
55 | .tRP = 18000, | |
56 | .tRAS = 42000, | |
57 | .tRC = 66000, | |
58 | .tRFC = 138000, | |
59 | .tXSR = 200000, | |
60 | ||
61 | .tREF = 7800, | |
62 | ||
63 | .tXP = 2, | |
64 | .tCKE = 2, | |
65 | .tWTR = 2 | |
66 | }, | |
67 | }; | |
68 | ||
69 | static unsigned long sdrc_get_fclk_period(long rate) | |
70 | { | |
71 | /* In picoseconds */ | |
72 | return 1000000000 / rate; | |
73 | } | |
74 | ||
75 | static unsigned int sdrc_ps_to_ticks(unsigned int time_ps, long rate) | |
76 | { | |
77 | unsigned long tick_ps; | |
78 | ||
79 | /* Calculate in picosecs to yield more exact results */ | |
80 | tick_ps = sdrc_get_fclk_period(rate); | |
81 | ||
82 | return (time_ps + tick_ps - 1) / tick_ps; | |
83 | } | |
84 | #undef DEBUG | |
85 | #ifdef DEBUG | |
86 | static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit, | |
87 | int ticks, long rate, const char *name) | |
88 | #else | |
89 | static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit, | |
90 | int ticks) | |
91 | #endif | |
92 | { | |
93 | int mask, nr_bits; | |
94 | ||
95 | nr_bits = end_bit - st_bit + 1; | |
96 | if (ticks >= 1 << nr_bits) | |
97 | return -1; | |
98 | mask = (1 << nr_bits) - 1; | |
99 | *regval &= ~(mask << st_bit); | |
100 | *regval |= ticks << st_bit; | |
101 | #ifdef DEBUG | |
102 | printk(KERN_INFO "SDRC %s: %i ticks %i ns\n", name, ticks, | |
103 | (unsigned int)sdrc_get_fclk_period(rate) * ticks / | |
104 | 1000); | |
105 | #endif | |
106 | ||
107 | return 0; | |
108 | } | |
109 | ||
110 | #ifdef DEBUG | |
111 | #define SDRC_SET_ONE(reg, st, end, field, rate) \ | |
112 | if (set_sdrc_timing_regval((reg), (st), (end), \ | |
113 | rx51_timings->field, (rate), #field) < 0) \ | |
114 | err = -1; | |
115 | #else | |
116 | #define SDRC_SET_ONE(reg, st, end, field, rate) \ | |
117 | if (set_sdrc_timing_regval((reg), (st), (end), \ | |
118 | rx51_timings->field) < 0) \ | |
119 | err = -1; | |
120 | #endif | |
121 | ||
122 | #ifdef DEBUG | |
123 | static int set_sdrc_timing_regval_ps(u32 *regval, int st_bit, int end_bit, | |
124 | int time, long rate, const char *name) | |
125 | #else | |
126 | static int set_sdrc_timing_regval_ps(u32 *regval, int st_bit, int end_bit, | |
127 | int time, long rate) | |
128 | #endif | |
129 | { | |
130 | int ticks, ret; | |
131 | ret = 0; | |
132 | ||
133 | if (time == 0) | |
134 | ticks = 0; | |
135 | else | |
136 | ticks = sdrc_ps_to_ticks(time, rate); | |
137 | ||
138 | #ifdef DEBUG | |
139 | ret = set_sdrc_timing_regval(regval, st_bit, end_bit, ticks, | |
140 | rate, name); | |
141 | #else | |
142 | ret = set_sdrc_timing_regval(regval, st_bit, end_bit, ticks); | |
143 | #endif | |
144 | ||
145 | return ret; | |
146 | } | |
147 | ||
148 | #ifdef DEBUG | |
149 | #define SDRC_SET_ONE_PS(reg, st, end, field, rate) \ | |
150 | if (set_sdrc_timing_regval_ps((reg), (st), (end), \ | |
151 | rx51_timings->field, \ | |
152 | (rate), #field) < 0) \ | |
153 | err = -1; | |
154 | ||
155 | #else | |
156 | #define SDRC_SET_ONE_PS(reg, st, end, field, rate) \ | |
157 | if (set_sdrc_timing_regval_ps((reg), (st), (end), \ | |
158 | rx51_timings->field, (rate)) < 0) \ | |
159 | err = -1; | |
160 | #endif | |
161 | ||
162 | static int sdrc_timings(int id, long rate) | |
163 | { | |
164 | u32 ticks_per_ms; | |
165 | u32 rfr, l; | |
166 | u32 actim_ctrla = 0, actim_ctrlb = 0; | |
167 | u32 rfr_ctrl; | |
168 | int err = 0; | |
169 | long l3_rate = rate / 1000; | |
170 | ||
171 | SDRC_SET_ONE_PS(&actim_ctrla, 0, 4, tDAL, l3_rate); | |
172 | SDRC_SET_ONE_PS(&actim_ctrla, 6, 8, tDPL, l3_rate); | |
173 | SDRC_SET_ONE_PS(&actim_ctrla, 9, 11, tRRD, l3_rate); | |
174 | SDRC_SET_ONE_PS(&actim_ctrla, 12, 14, tRCD, l3_rate); | |
175 | SDRC_SET_ONE_PS(&actim_ctrla, 15, 17, tRP, l3_rate); | |
176 | SDRC_SET_ONE_PS(&actim_ctrla, 18, 21, tRAS, l3_rate); | |
177 | SDRC_SET_ONE_PS(&actim_ctrla, 22, 26, tRC, l3_rate); | |
178 | SDRC_SET_ONE_PS(&actim_ctrla, 27, 31, tRFC, l3_rate); | |
179 | ||
180 | SDRC_SET_ONE_PS(&actim_ctrlb, 0, 7, tXSR, l3_rate); | |
181 | ||
182 | SDRC_SET_ONE(&actim_ctrlb, 8, 10, tXP, l3_rate); | |
183 | SDRC_SET_ONE(&actim_ctrlb, 12, 14, tCKE, l3_rate); | |
184 | SDRC_SET_ONE(&actim_ctrlb, 16, 17, tWTR, l3_rate); | |
185 | ||
186 | ticks_per_ms = l3_rate; | |
187 | rfr = rx51_timings[0].tREF * ticks_per_ms / 1000000; | |
188 | if (rfr > 65535 + 50) | |
189 | rfr = 65535; | |
190 | else | |
191 | rfr -= 50; | |
192 | ||
193 | #ifdef DEBUG | |
194 | printk(KERN_INFO "SDRC tREF: %i ticks\n", rfr); | |
195 | #endif | |
196 | ||
197 | l = rfr << 8; | |
198 | rfr_ctrl = l | 0x1; /* autorefresh, reload counter with 1xARCV */ | |
199 | ||
200 | rx51_sdrc_params[id].rate = rate; | |
201 | rx51_sdrc_params[id].actim_ctrla = actim_ctrla; | |
202 | rx51_sdrc_params[id].actim_ctrlb = actim_ctrlb; | |
203 | rx51_sdrc_params[id].rfr_ctrl = rfr_ctrl; | |
204 | rx51_sdrc_params[id].mr = 0x32; | |
205 | ||
206 | rx51_sdrc_params[id + 1].rate = 0; | |
207 | ||
208 | return err; | |
209 | } | |
210 | ||
211 | struct omap_sdrc_params *rx51_get_sdram_timings(void) | |
212 | { | |
213 | int err; | |
214 | ||
215 | err = sdrc_timings(0, 41500000); | |
216 | err |= sdrc_timings(1, 83000000); | |
217 | err |= sdrc_timings(2, 166000000); | |
218 | ||
219 | return &rx51_sdrc_params[0]; | |
220 | } | |
221 |