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