Connect dramcore to SoC bus in ECPIX-5 example
[gram.git] / gram / init.py
1 # This file is Copyright (c) 2013-2014 Sebastien Bourdeauducq <sb@m-labs.hk>
2 # This file is Copyright (c) 2013-2020 Florent Kermarrec <florent@enjoy-digital.fr>
3 # This file is Copyright (c) 2017 whitequark <whitequark@whitequark.org>
4 # This file is Copyright (c) 2014 Yann Sionneau <ys@m-labs.hk>
5 # This file is Copyright (c) 2018 bunnie <bunnie@kosagi.com>
6 # This file is Copyright (c) 2019 Gabriel L. Somlo <gsomlo@gmail.com>
7 # License: BSD
8
9 from nmigen.utils import log2_int
10
11 cmds = {
12 "PRECHARGE_ALL": "DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS",
13 "MODE_REGISTER": "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS",
14 "AUTO_REFRESH": "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS",
15 "UNRESET": "DFII_CONTROL_ODT|DFII_CONTROL_RESET_N",
16 "CKE": "DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N"
17 }
18
19 # SDR ----------------------------------------------------------------------------------------------
20
21 def get_sdr_phy_init_sequence(phy_settings, timing_settings):
22 cl = phy_settings.cl
23 bl = 1
24 mr = log2_int(bl) + (cl << 4)
25 reset_dll = 1 << 8
26
27 init_sequence = [
28 ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
29 ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
30 ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
31 ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
32 ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
33 ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
34 ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
35 ]
36
37 return init_sequence, None
38
39 # DDR ----------------------------------------------------------------------------------------------
40
41 def get_ddr_phy_init_sequence(phy_settings, timing_settings):
42 cl = phy_settings.cl
43 bl = 4
44 mr = log2_int(bl) + (cl << 4)
45 emr = 0
46 reset_dll = 1 << 8
47
48 init_sequence = [
49 ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
50 ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
51 ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0),
52 ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
53 ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
54 ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
55 ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
56 ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
57 ]
58
59 return init_sequence, None
60
61 # LPDDR --------------------------------------------------------------------------------------------
62
63 def get_lpddr_phy_init_sequence(phy_settings, timing_settings):
64 cl = phy_settings.cl
65 bl = 4
66 mr = log2_int(bl) + (cl << 4)
67 emr = 0
68 reset_dll = 1 << 8
69
70 init_sequence = [
71 ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
72 ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
73 ("Load Extended Mode Register", emr, 2, cmds["MODE_REGISTER"], 0),
74 ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
75 ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
76 ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
77 ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
78 ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
79 ]
80
81 return init_sequence, None
82
83 # DDR2 ---------------------------------------------------------------------------------------------
84
85 def get_ddr2_phy_init_sequence(phy_settings, timing_settings):
86 cl = phy_settings.cl
87 bl = 4
88 wr = 2
89 mr = log2_int(bl) + (cl << 4) + (wr << 9)
90 emr = 0
91 emr2 = 0
92 emr3 = 0
93 ocd = 7 << 7
94 reset_dll = 1 << 8
95
96 init_sequence = [
97 ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
98 ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
99 ("Load Extended Mode Register 3", emr3, 3, cmds["MODE_REGISTER"], 0),
100 ("Load Extended Mode Register 2", emr2, 2, cmds["MODE_REGISTER"], 0),
101 ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0),
102 ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
103 ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
104 ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
105 ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
106 ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200),
107 ("Load Extended Mode Register / OCD Default", emr+ocd, 1, cmds["MODE_REGISTER"], 0),
108 ("Load Extended Mode Register / OCD Exit", emr, 1, cmds["MODE_REGISTER"], 0),
109 ]
110
111 return init_sequence, None
112
113 # DDR3 ---------------------------------------------------------------------------------------------
114
115 def get_ddr3_phy_init_sequence(phy_settings, timing_settings):
116 cl = phy_settings.cl
117 bl = 8
118 cwl = phy_settings.cwl
119
120 def format_mr0(bl, cl, wr, dll_reset):
121 bl_to_mr0 = {
122 4: 0b10,
123 8: 0b00
124 }
125 cl_to_mr0 = {
126 5: 0b0010,
127 6: 0b0100,
128 7: 0b0110,
129 8: 0b1000,
130 9: 0b1010,
131 10: 0b1100,
132 11: 0b1110,
133 12: 0b0001,
134 13: 0b0011,
135 14: 0b0101
136 }
137 wr_to_mr0 = {
138 16: 0b000,
139 5: 0b001,
140 6: 0b010,
141 7: 0b011,
142 8: 0b100,
143 10: 0b101,
144 12: 0b110,
145 14: 0b111
146 }
147 mr0 = bl_to_mr0[bl]
148 mr0 |= (cl_to_mr0[cl] & 1) << 2
149 mr0 |= ((cl_to_mr0[cl] >> 1) & 0b111) << 4
150 mr0 |= dll_reset << 8
151 mr0 |= wr_to_mr0[wr] << 9
152 return mr0
153
154 def format_mr1(ron, rtt_nom):
155 mr1 = ((ron >> 0) & 1) << 1
156 mr1 |= ((ron >> 1) & 1) << 5
157 mr1 |= ((rtt_nom >> 0) & 1) << 2
158 mr1 |= ((rtt_nom >> 1) & 1) << 6
159 mr1 |= ((rtt_nom >> 2) & 1) << 9
160 return mr1
161
162 def format_mr2(cwl, rtt_wr):
163 mr2 = (cwl-5) << 3
164 mr2 |= rtt_wr << 9
165 return mr2
166
167 z_to_rtt_nom = {
168 "disabled" : 0,
169 "60ohm" : 1,
170 "120ohm" : 2,
171 "40ohm" : 3,
172 "20ohm" : 4,
173 "30ohm" : 5
174 }
175
176 z_to_rtt_wr = {
177 "disabled" : 0,
178 "60ohm" : 1,
179 "120ohm" : 2,
180 }
181
182 z_to_ron = {
183 "40ohm" : 0,
184 "34ohm" : 1,
185 }
186
187 # default electrical settings (point to point)
188 rtt_nom = "60ohm"
189 rtt_wr = "60ohm"
190 ron = "34ohm"
191
192 # override electrical settings if specified
193 if hasattr(phy_settings, "rtt_nom"):
194 rtt_nom = phy_settings.rtt_nom
195 if hasattr(phy_settings, "rtt_wr"):
196 rtt_wr = phy_settings.rtt_wr
197 if hasattr(phy_settings, "ron"):
198 ron = phy_settings.ron
199
200 wr = max(timing_settings.tWTR*phy_settings.nphases, 5) # >= ceiling(tWR/tCK)
201 mr0 = format_mr0(bl, cl, wr, 1)
202 mr1 = format_mr1(z_to_ron[ron], z_to_rtt_nom[rtt_nom])
203 mr2 = format_mr2(cwl, z_to_rtt_wr[rtt_wr])
204 mr3 = 0
205
206 init_sequence = [
207 ("Release reset", 0x0000, 0, cmds["UNRESET"], 50000),
208 ("Bring CKE high", 0x0000, 0, cmds["CKE"], 10000),
209 ("Load Mode Register 2, CWL={0:d}".format(cwl), mr2, 2, cmds["MODE_REGISTER"], 0),
210 ("Load Mode Register 3", mr3, 3, cmds["MODE_REGISTER"], 0),
211 ("Load Mode Register 1", mr1, 1, cmds["MODE_REGISTER"], 0),
212 ("Load Mode Register 0, CL={0:d}, BL={1:d}".format(cl, bl), mr0, 0, cmds["MODE_REGISTER"], 200),
213 ("ZQ Calibration", 0x0400, 0, "DFII_COMMAND_WE|DFII_COMMAND_CS", 200),
214 ]
215
216 return init_sequence, mr1
217
218 # DDR4 ---------------------------------------------------------------------------------------------
219
220 def get_ddr4_phy_init_sequence(phy_settings, timing_settings):
221 cl = phy_settings.cl
222 bl = 8
223 cwl = phy_settings.cwl
224
225 def format_mr0(bl, cl, wr, dll_reset):
226 bl_to_mr0 = {
227 4: 0b10,
228 8: 0b00
229 }
230 cl_to_mr0 = {
231 9: 0b00000,
232 10: 0b00001,
233 11: 0b00010,
234 12: 0b00011,
235 13: 0b00100,
236 14: 0b00101,
237 15: 0b00110,
238 16: 0b00111,
239 18: 0b01000,
240 20: 0b01001,
241 22: 0b01010,
242 24: 0b01011,
243 23: 0b01100,
244 17: 0b01101,
245 19: 0b01110,
246 21: 0b01111,
247 25: 0b10000,
248 26: 0b10001,
249 27: 0b10010,
250 28: 0b10011,
251 29: 0b10100,
252 30: 0b10101,
253 31: 0b10110,
254 32: 0b10111,
255 }
256 wr_to_mr0 = {
257 10: 0b0000,
258 12: 0b0001,
259 14: 0b0010,
260 16: 0b0011,
261 18: 0b0100,
262 20: 0b0101,
263 24: 0b0110,
264 22: 0b0111,
265 26: 0b1000,
266 28: 0b1001,
267 }
268 mr0 = bl_to_mr0[bl]
269 mr0 |= (cl_to_mr0[cl] & 0b1) << 2
270 mr0 |= ((cl_to_mr0[cl] >> 1) & 0b111) << 4
271 mr0 |= ((cl_to_mr0[cl] >> 4) & 0b1) << 12
272 mr0 |= dll_reset << 8
273 mr0 |= (wr_to_mr0[wr] & 0b111) << 9
274 mr0 |= (wr_to_mr0[wr] >> 3) << 13
275 return mr0
276
277 def format_mr1(dll_enable, ron, rtt_nom):
278 mr1 = dll_enable
279 mr1 |= ((ron >> 0) & 0b1) << 1
280 mr1 |= ((ron >> 1) & 0b1) << 2
281 mr1 |= ((rtt_nom >> 0) & 0b1) << 8
282 mr1 |= ((rtt_nom >> 1) & 0b1) << 9
283 mr1 |= ((rtt_nom >> 2) & 0b1) << 10
284 return mr1
285
286 def format_mr2(cwl, rtt_wr):
287 cwl_to_mr2 = {
288 9: 0b000,
289 10: 0b001,
290 11: 0b010,
291 12: 0b011,
292 14: 0b100,
293 16: 0b101,
294 18: 0b110,
295 20: 0b111
296 }
297 mr2 = cwl_to_mr2[cwl] << 3
298 mr2 |= rtt_wr << 9
299 return mr2
300
301 def format_mr3(fine_refresh_mode):
302 fine_refresh_mode_to_mr3 = {
303 "1x": 0b000,
304 "2x": 0b001,
305 "4x": 0b010
306 }
307 mr3 = fine_refresh_mode_to_mr3[fine_refresh_mode] << 6
308 return mr3
309
310 def format_mr6(tccd):
311 tccd_to_mr6 = {
312 4: 0b000,
313 5: 0b001,
314 6: 0b010,
315 7: 0b011,
316 8: 0b100
317 }
318 mr6 = tccd_to_mr6[tccd] << 10
319 return mr6
320
321 z_to_rtt_nom = {
322 "disabled" : 0b000,
323 "60ohm" : 0b001,
324 "120ohm" : 0b010,
325 "40ohm" : 0b011,
326 "240ohm" : 0b100,
327 "48ohm" : 0b101,
328 "80ohm" : 0b110,
329 "34ohm" : 0b111
330 }
331
332 z_to_rtt_wr = {
333 "disabled" : 0b000,
334 "120ohm" : 0b001,
335 "240ohm" : 0b010,
336 "high-z" : 0b011,
337 "80ohm" : 0b100,
338 }
339
340 z_to_ron = {
341 "34ohm" : 0b00,
342 "48ohm" : 0b01,
343 }
344
345 # default electrical settings (point to point)
346 rtt_nom = "40ohm"
347 rtt_wr = "120ohm"
348 ron = "34ohm"
349
350 # override electrical settings if specified
351 if hasattr(phy_settings, "rtt_nom"):
352 rtt_nom = phy_settings.rtt_nom
353 if hasattr(phy_settings, "rtt_wr"):
354 rtt_wr = phy_settings.rtt_wr
355 if hasattr(phy_settings, "ron"):
356 ron = phy_settings.ron
357
358 wr = max(timing_settings.tWTR*phy_settings.nphases, 10) # >= ceiling(tWR/tCK)
359 mr0 = format_mr0(bl, cl, wr, 1)
360 mr1 = format_mr1(1, z_to_ron[ron], z_to_rtt_nom[rtt_nom])
361 mr2 = format_mr2(cwl, z_to_rtt_wr[rtt_wr])
362 mr3 = format_mr3(timing_settings.fine_refresh_mode)
363 mr4 = 0
364 mr5 = 0
365 mr6 = format_mr6(4) # FIXME: tCCD
366
367 rdimm_init = []
368 if phy_settings.is_rdimm:
369 def get_coarse_speed(tck, pll_bypass):
370 # JESD82-31A page 78
371 f_to_coarse_speed = {
372 1600e6: 0,
373 1866e6: 1,
374 2133e6: 2,
375 2400e6: 3,
376 2666e6: 4,
377 2933e6: 5,
378 3200e6: 6,
379 }
380 if pll_bypass:
381 return 7
382 else:
383 for f, speed in f_to_coarse_speed.items():
384 if tck >= 2/f:
385 return speed
386 raise ValueError
387 def get_fine_speed(tck):
388 # JESD82-31A page 83
389 freq = 2/tck
390 fine_speed = (freq - 1240e6) // 20e6
391 fine_speed = max(fine_speed, 0)
392 fine_speed = min(fine_speed, 0b1100001)
393 return fine_speed
394
395 coarse_speed = get_coarse_speed(phy_settings.tck, phy_settings.rcd_pll_bypass)
396 fine_speed = get_fine_speed(phy_settings.tck)
397
398 rcd_reset = 0x060 | 0x0 # F0RC06: command space control; 0: reset RCD
399
400 f0rc0f = 0x0F0 | 0x4 # F0RC05: 0 nCK latency adder
401
402 f0rc03 = 0x030 | phy_settings.rcd_ca_cs_drive # F0RC03: CA/CS drive strength
403 f0rc04 = 0x040 | phy_settings.rcd_odt_cke_drive # F0RC04: ODT/CKE drive strength
404 f0rc05 = 0x050 | phy_settings.rcd_clk_drive # F0RC04: ODT/CKE drive strength
405
406 f0rc0a = 0x0A0 | coarse_speed # F0RC0A: coarse speed selection and PLL bypass
407 f0rc3x = 0x300 | fine_speed # F0RC3x: fine speed selection
408
409 rdimm_init = [
410 ("Reset RCD", rcd_reset, 7, cmds["MODE_REGISTER"], 50000),
411 ("Load RCD F0RC0F", f0rc0f, 7, cmds["MODE_REGISTER"], 100),
412 ("Load RCD F0RC03", f0rc03, 7, cmds["MODE_REGISTER"], 100),
413 ("Load RCD F0RC04", f0rc04, 7, cmds["MODE_REGISTER"], 100),
414 ("Load RCD F0RC05", f0rc05, 7, cmds["MODE_REGISTER"], 100),
415 ("Load RCD F0RC0A", f0rc0a, 7, cmds["MODE_REGISTER"], 100),
416 ("Load RCD F0RC3X", f0rc3x, 7, cmds["MODE_REGISTER"], 100),
417 ]
418
419 init_sequence = [
420 ("Release reset", 0x0000, 0, cmds["UNRESET"], 50000),
421 ("Bring CKE high", 0x0000, 0, cmds["CKE"], 10000),
422 ] + rdimm_init + [
423 ("Load Mode Register 3", mr3, 3, cmds["MODE_REGISTER"], 0),
424 ("Load Mode Register 6", mr6, 6, cmds["MODE_REGISTER"], 0),
425 ("Load Mode Register 5", mr5, 5, cmds["MODE_REGISTER"], 0),
426 ("Load Mode Register 4", mr4, 4, cmds["MODE_REGISTER"], 0),
427 ("Load Mode Register 2, CWL={0:d}".format(cwl), mr2, 2, cmds["MODE_REGISTER"], 0),
428 ("Load Mode Register 1", mr1, 1, cmds["MODE_REGISTER"], 0),
429 ("Load Mode Register 0, CL={0:d}, BL={1:d}".format(cl, bl), mr0, 0, cmds["MODE_REGISTER"], 200),
430 ("ZQ Calibration", 0x0400, 0, "DFII_COMMAND_WE|DFII_COMMAND_CS", 200),
431 ]
432
433 return init_sequence, mr1
434
435 # Init Sequence ------------------------------------------------------------------------------------
436
437 def get_sdram_phy_init_sequence(phy_settings, timing_settings):
438 return {
439 "SDR" : get_sdr_phy_init_sequence,
440 "DDR" : get_ddr_phy_init_sequence,
441 "LPDDR": get_lpddr_phy_init_sequence,
442 "DDR2" : get_ddr2_phy_init_sequence,
443 "DDR3" : get_ddr3_phy_init_sequence,
444 "DDR4" : get_ddr4_phy_init_sequence,
445 }[phy_settings.memtype](phy_settings, timing_settings)
446
447 # C Header -----------------------------------------------------------------------------------------
448
449 def get_sdram_phy_c_header(phy_settings, timing_settings):
450 r = "#ifndef __GENERATED_SDRAM_PHY_H\n#define __GENERATED_SDRAM_PHY_H\n"
451 r += "#include <hw/common.h>\n"
452 r += "#include <generated/csr.h>\n"
453 r += "\n"
454
455 r += "#define DFII_CONTROL_SEL 0x01\n"
456 r += "#define DFII_CONTROL_CKE 0x02\n"
457 r += "#define DFII_CONTROL_ODT 0x04\n"
458 r += "#define DFII_CONTROL_RESET_N 0x08\n"
459 r += "\n"
460
461 r += "#define DFII_COMMAND_CS 0x01\n"
462 r += "#define DFII_COMMAND_WE 0x02\n"
463 r += "#define DFII_COMMAND_CAS 0x04\n"
464 r += "#define DFII_COMMAND_RAS 0x08\n"
465 r += "#define DFII_COMMAND_WRDATA 0x10\n"
466 r += "#define DFII_COMMAND_RDDATA 0x20\n"
467 r += "\n"
468
469 phytype = phy_settings.phytype.upper()
470 nphases = phy_settings.nphases
471
472 # Define PHY type and number of phases
473 r += "#define SDRAM_PHY_"+phytype+"\n"
474 r += "#define SDRAM_PHY_PHASES "+str(nphases)+"\n"
475
476 # Define Read/Write Leveling capability
477 if phytype in ["USDDRPHY", "USPDDRPHY", "K7DDRPHY", "V7DDRPHY"]:
478 r += "#define SDRAM_PHY_WRITE_LEVELING_CAPABLE\n"
479 if phytype in ["USDDRPHY", "USPDDRPHY"]:
480 r += "#define SDRAM_PHY_WRITE_LEVELING_REINIT\n"
481 if phytype in ["USDDRPHY", "USPDDRPHY", "A7DDRPHY", "K7DDRPHY", "V7DDRPHY", "ECP5DDRPHY"]:
482 r += "#define SDRAM_PHY_READ_LEVELING_CAPABLE\n"
483
484 # Define number of modules/delays/bitslips
485 if phytype in ["USDDRPHY", "USPDDRPHY"]:
486 r += "#define SDRAM_PHY_MODULES DFII_PIX_DATA_BYTES/2\n"
487 r += "#define SDRAM_PHY_DELAYS 512\n"
488 r += "#define SDRAM_PHY_BITSLIPS 16\n"
489 elif phytype in ["A7DDRPHY", "K7DDRPHY", "V7DDRPHY"]:
490 r += "#define SDRAM_PHY_MODULES DFII_PIX_DATA_BYTES/2\n"
491 r += "#define SDRAM_PHY_DELAYS 32\n"
492 r += "#define SDRAM_PHY_BITSLIPS 16\n"
493 elif phytype in ["ECP5DDRPHY"]:
494 r += "#define SDRAM_PHY_MODULES DFII_PIX_DATA_BYTES/4\n"
495 r += "#define SDRAM_PHY_DELAYS 8\n"
496 r += "#define SDRAM_PHY_BITSLIPS 4\n"
497
498 if phy_settings.is_rdimm:
499 assert phy_settings.memtype == "DDR4"
500 r += "#define SDRAM_PHY_DDR4_RDIMM\n"
501
502 r += "\n"
503
504 r += "static void cdelay(int i);\n"
505
506 # commands_px functions
507 for n in range(nphases):
508 r += """
509 __attribute__((unused)) static void command_p{n}(int cmd)
510 {{
511 sdram_dfii_pi{n}_command_write(cmd);
512 sdram_dfii_pi{n}_command_issue_write(1);
513 }}""".format(n=str(n))
514 r += "\n\n"
515
516 # rd/wr access macros
517 r += """
518 #define sdram_dfii_pird_address_write(X) sdram_dfii_pi{rdphase}_address_write(X)
519 #define sdram_dfii_piwr_address_write(X) sdram_dfii_pi{wrphase}_address_write(X)
520 #define sdram_dfii_pird_baddress_write(X) sdram_dfii_pi{rdphase}_baddress_write(X)
521 #define sdram_dfii_piwr_baddress_write(X) sdram_dfii_pi{wrphase}_baddress_write(X)
522 #define command_prd(X) command_p{rdphase}(X)
523 #define command_pwr(X) command_p{wrphase}(X)
524 """.format(rdphase=str(phy_settings.rdphase), wrphase=str(phy_settings.wrphase))
525 r += "\n"
526
527 #
528 # sdrrd/sdrwr functions utilities
529 #
530 r += "#define DFII_PIX_DATA_SIZE CSR_SDRAM_DFII_PI0_WRDATA_SIZE\n"
531 sdram_dfii_pix_wrdata_addr = []
532 for n in range(nphases):
533 sdram_dfii_pix_wrdata_addr.append("CSR_SDRAM_DFII_PI{n}_WRDATA_ADDR".format(n=n))
534 r += """
535 const unsigned long sdram_dfii_pix_wrdata_addr[SDRAM_PHY_PHASES] = {{
536 \t{sdram_dfii_pix_wrdata_addr}
537 }};
538 """.format(sdram_dfii_pix_wrdata_addr=",\n\t".join(sdram_dfii_pix_wrdata_addr))
539
540 sdram_dfii_pix_rddata_addr = []
541 for n in range(nphases):
542 sdram_dfii_pix_rddata_addr.append("CSR_SDRAM_DFII_PI{n}_RDDATA_ADDR".format(n=n))
543 r += """
544 const unsigned long sdram_dfii_pix_rddata_addr[SDRAM_PHY_PHASES] = {{
545 \t{sdram_dfii_pix_rddata_addr}
546 }};
547 """.format(sdram_dfii_pix_rddata_addr=",\n\t".join(sdram_dfii_pix_rddata_addr))
548 r += "\n"
549
550 init_sequence, mr1 = get_sdram_phy_init_sequence(phy_settings, timing_settings)
551
552 if phy_settings.memtype in ["DDR3", "DDR4"]:
553 # the value of MR1 needs to be modified during write leveling
554 r += "#define DDRX_MR1 {}\n\n".format(mr1)
555
556 r += "static void init_sequence(void)\n{\n"
557 for comment, a, ba, cmd, delay in init_sequence:
558 invert_masks = [(0, 0), ]
559 if phy_settings.is_rdimm:
560 assert phy_settings.memtype == "DDR4"
561 # JESD82-31A page 38
562 #
563 # B-side chips have certain usually-inconsequential address and BA
564 # bits inverted by the RCD to reduce SSO current. For mode register
565 # writes, however, we must compensate for this. BG[1] also directs
566 # writes either to the A side (BG[1]=0) or B side (BG[1]=1)
567 #
568 # The 'ba != 7' is because we don't do this to writes to the RCD
569 # itself.
570 if ba != 7:
571 invert_masks.append((0b10101111111000, 0b1111))
572
573 for a_inv, ba_inv in invert_masks:
574 r += "\t/* {0} */\n".format(comment)
575 r += "\tsdram_dfii_pi0_address_write({0:#x});\n".format(a ^ a_inv)
576 r += "\tsdram_dfii_pi0_baddress_write({0:d});\n".format(ba ^ ba_inv)
577 if cmd[:12] == "DFII_CONTROL":
578 r += "\tsdram_dfii_control_write({0});\n".format(cmd)
579 else:
580 r += "\tcommand_p0({0});\n".format(cmd)
581 if delay:
582 r += "\tcdelay({0:d});\n".format(delay)
583 r += "\n"
584 r += "}\n"
585
586 r += "#endif\n"
587
588 return r
589
590 # Python Header ------------------------------------------------------------------------------------
591
592 def get_sdram_phy_py_header(phy_settings, timing_settings):
593 r = ""
594 r += "dfii_control_sel = 0x01\n"
595 r += "dfii_control_cke = 0x02\n"
596 r += "dfii_control_odt = 0x04\n"
597 r += "dfii_control_reset_n = 0x08\n"
598 r += "\n"
599 r += "dfii_command_cs = 0x01\n"
600 r += "dfii_command_we = 0x02\n"
601 r += "dfii_command_cas = 0x04\n"
602 r += "dfii_command_ras = 0x08\n"
603 r += "dfii_command_wrdata = 0x10\n"
604 r += "dfii_command_rddata = 0x20\n"
605 r += "\n"
606
607 init_sequence, mr1 = get_sdram_phy_init_sequence(phy_settings, timing_settings)
608
609 if mr1 is not None:
610 r += "ddrx_mr1 = 0x{:x}\n".format(mr1)
611 r += "\n"
612
613 r += "init_sequence = [\n"
614 for comment, a, ba, cmd, delay in init_sequence:
615 r += " "
616 r += "(\"" + comment + "\", "
617 r += str(a) + ", "
618 r += str(ba) + ", "
619 r += cmd.lower() + ", "
620 r += str(delay) + "),"
621 r += "\n"
622 r += "]\n"
623 return r