1 \ *****************************************************************************
2 \ * Copyright (c) 2004, 2008 IBM Corporation
3 \ * All rights reserved.
4 \ * This program and the accompanying materials
5 \ * are made available under the terms of the BSD License
6 \ * which accompanies this distribution, and is available at
7 \ * http://www.opensource.org/licenses/bsd-license.php
10 \ * IBM Corporation - initial implementation
11 \ ****************************************************************************/
14 \ U4 DDR2 memory controller.
16 cr .( Setting up memory controller...)
19 \ First, I2C access to the SPDs.
25 : .i2c 80 0 DO i i2c@ . 10 +LOOP ;
27 : i2c-addr ( addr -- ) 50 i2c! 2 10 i2c! BEGIN 30 i2c@ 2 and UNTIL ;
28 : i2c-addr-subaddr ( addr suba -- ) 60 i2c! i2c-addr ;
29 : i2c-stop ( -- ) BEGIN 30 i2c@ dup 30 i2c! 4 and UNTIL ;
30 : i2c-nak? ( -- failed? ) 20 i2c@ 2 and 0= dup IF i2c-stop THEN ;
31 : i2c-short? ( -- failed? ) 30 i2c@ 4 and 0<> dup IF 0 10 i2c! i2c-stop THEN ;
32 : i2c-aak-if-more ( n -- ) 1 <> 1 and 10 i2c! ;
34 : i2c-sub-read ( buf len addr suba -- error? )
35 c 0 i2c! >r 1 or r> i2c-addr-subaddr i2c-nak? IF 2drop true EXIT THEN
36 dup i2c-aak-if-more 2 30 i2c!
39 1- >r 70 i2c@ over c! char+ r>
40 dup 0= IF i2c-stop 2drop false EXIT THEN
41 dup i2c-aak-if-more 1 30 i2c! THEN
42 i2c-short? IF 2drop true EXIT THEN
46 \ What slots are filled with working memory (bitmask).
49 : dimm-invalid 1 swap lshift invert dimms-valid and to dimms-valid ;
50 : dimm-invalid dup dimm-invalid 2 xor dimm-invalid ; \ DIMMs are paired
51 : dimm-valid? 1 swap lshift dimms-valid and ;
52 : dimm( +comp postpone 4 postpone 0 postpone DO
53 postpone i postpone dimm-valid? postpone IF ; immediate
54 : )dimm postpone THEN postpone LOOP -comp ; immediate
57 \ The data from the SPDs.
60 : spd@ ( dimm# off -- value ) swap 40 * + spds + c@ ;
62 CREATE addresses a0 c, a4 c, a2 c, a6 c,
63 dimm( spds i 40 * + 40 addresses i + c@ 0 i2c-sub-read IF i dimm-invalid THEN )dimm
70 : spd>ranks 5 spd@ 7 and 1+ ;
73 : spd>cas 12 spd@ ; \ bit mask of allowable CAS latencies
74 : spd>trp 1b spd@ ; \ in units of 0.25 ns
75 : spd>trrd 1c spd@ ; \ in units of 0.25 ns
76 : spd>trcd 1d spd@ ; \ in units of 0.25 ns
77 : spd>tras 1e spd@ ; \ in units of 1 ns
78 : spd>twr 24 spd@ ; \ in units of 0.25 ns
79 : spd>twtr 25 spd@ ; \ in units of 0.25 ns
80 : spd>trtp 26 spd@ ; \ in units of 0.25 ns
81 : spd>trc 29 spd@ ; \ in units of 1 ns XXX: should also look at byte 28
82 : spd>trfc 2a spd@ ; \ in units of 1 ns XXX: should also look at byte 28
84 cr .( rows cols ranks width banks trp trrd trcd tras twr twtr trtp trc trfc)
85 cr .( =====================================================================)
88 i spd>rows 4 .r i spd>cols 5 .r i spd>ranks 6 .r i spd>width 6 .r
89 i spd>banks 6 .r i spd>trp 4 .r i spd>trrd 5 .r i spd>trcd 5 .r
90 i spd>tras 5 .r i spd>twr 4 .r i spd>twtr 5 .r i spd>trtp 5 .r
91 i spd>trc 4 .r i spd>trfc 5 .r
95 ff dimm( i spd>cas and )dimm CONSTANT cl-supported
96 : max-cl -1 swap 8 0 DO dup 1 and IF nip i swap THEN u2/ LOOP drop ;
97 cl-supported max-cl VALUE cl
99 : tck>60*ns dup f and swap 4 rshift a * over + 6 * swap CASE
100 a OF 2d - ENDOF b OF 2e - ENDOF c OF 20 - ENDOF d OF 21 - ENDOF
102 : cl>tck 0 spd>cas max-cl swap -
103 CASE 0 OF 9 ENDOF 1 OF 17 ENDOF 2 OF 19 ENDOF
104 true ABORT" No supported CAS latency for this DIMM" ENDCASE
105 0 swap spd@ tck>60*ns ;
107 : spd>min-tck dup spd>cas max-cl cl -
108 CASE 0 OF 9 ENDOF 1 OF 17 ENDOF 2 OF 19 ENDOF
109 true ABORT" No supported CAS latency for this DIMM" ENDCASE
111 : spd>max-tck 2b spd@ tck>60*ns ;
113 : .tck base @ >r decimal dup d# 60 / 0 .r [char] . emit
114 d# 60 mod d# 1000 * d# 60 / 3 0.r ." ns" r> base ! ;
116 cr .( CAS latencies supported: )
117 8 0 DO cl-supported 1 i lshift and IF i . THEN LOOP
119 \ Find the lowest CL at the highest tCK.
120 8 0 DO cl-supported 1 i lshift and IF cl cl>tck i cl>tck = IF
121 i to cl LEAVE THEN THEN LOOP
126 0 dimm( i spd>min-tck max )dimm CONSTANT tck
127 dimm( i spd>max-tck tck < IF i dimm-invalid THEN )dimm
128 cr .( tCK is ) tck .tck
135 : // dup >r 1- + r> / ; \ round up
136 0 spd>tras d# 60 * tck // CONSTANT tras
137 0 spd>trtp d# 15 * tck // CONSTANT trtp
138 0 spd>twr d# 15 * tck // CONSTANT twr
139 0 spd>trp d# 15 * tck // CONSTANT trp
140 0 spd>trrd d# 15 * tck // CONSTANT trrd
141 0 spd>trrd d# 60 * tck // CONSTANT 4*trrd
142 0 spd>trcd d# 15 * tck // CONSTANT trcd
143 0 spd>trc d# 60 * tck // CONSTANT trc
144 0 spd>twtr d# 15 * tck // CONSTANT twtr
147 >r r@ spd>rows r@ spd>cols +
148 r@ spd>banks 2log + 4 * r> spd>width 2log 3 * + 6c - ;
149 : dimm-group-size ( dimm# -- size )
150 >r r@ spd>rows r@ spd>cols + 1 swap lshift
151 r@ spd>banks * r> spd>ranks * 10 * ;
152 VARIABLE start-address
153 VARIABLE was-prev-big
154 : assign-dimm-group ( dimm# -- config-value )
155 dup dimm-valid? 0= IF drop 0 EXIT THEN
156 \ MemMd, enable, single-sided or not
157 dup spd>memmd c lshift 1 or over spd>ranks 1 = IF 2 or THEN
160 dimm-group-size start-address @ 2dup + rot ( start end size )
162 dup 1000000000 < IF dup 4 rshift ELSE 08000000 THEN r> or >r \ Add2G
163 over 0<> IF over c rshift ELSE 00080000 THEN r> or >r \ Sub2G
166 was-prev-big @ IF 80000000 + swap 80000000 + swap THEN r> 08080000 or >r
169 swap 18 rshift r> or >r \ start address
170 dup 80000000 = IF drop 100000000 THEN start-address ! r> ;
173 \ Now set the frequency in the memory controller
174 d# 1800 tck / 4 - 12 lshift 33c or f8000800 rl!
175 f8000860 rl@ 80000000 or f8000860 rl! 10000 0 DO LOOP
177 : mc! f8002000 + rl! ;
178 : mc@ f8002000 + rl@ ;
181 \ memory timing regs (state machine)
184 5 lshift al trtp + 2- or
187 5 lshift trp 2- 0 spd>banks 8 = IF 1+ THEN or
191 5 lshift cl al + twr + trp + 1- or
201 5 lshift cl 1- twtr + or
212 2 lshift 060 mc! \ XXX joerg has different setting
214 cl 3 = IF 30801800 ( 30800d00 ) 070 mc! \ XXX memory refresh
215 ELSE 41002000 070 mc! THEN
219 1 dimm-group-size 0 dimm-group-size > 1 0 rot IF swap THEN \ biggest first
220 assign-dimm-group 200 mc!
221 assign-dimm-group 210 mc!
232 \ a0a00000 290 mc! \ a0000000 might be faster
237 \ 30413cc7 2c0 mc! \ have to calculate the low five bits
239 \ cl 3 = IF 76000050 2d0 mc! 70000000 2e0 mc! ELSE
240 cl 3 = IF 75000050 2d0 mc! 70000000 2e0 mc! ELSE
241 b8002080 2d0 mc! b0000000 2e0 mc! THEN
242 \ Should test for something else really
246 cl 3 = IF 00006000 890 mc! 00006000 8a0 mc! ELSE
247 00006500 890 mc! 00006500 8a0 mc! THEN
249 cl 3 = IF 1e008a8a ELSE 31000000 THEN
250 dup 800 mc! dup 810 mc! dup 820 mc! dup 830 mc!
251 dup 900 mc! dup 910 mc! dup 920 mc! dup 930 mc! dup 980 mc!
252 dup a00 mc! dup a10 mc! dup a20 mc! dup a30 mc!
253 dup b00 mc! dup b10 mc! dup b20 mc! dup b30 mc! b80 mc!
255 \ 0 8d0 mc! 0 9d0 mc! 0 ad0 mc! 0 bd0 mc!
266 8000153a 140 mc! ELSE
267 8000174a 140 mc! THEN
276 8ff0143a 180 mc! ELSE
277 8ff0164a 180 mc! THEN
280 0 1b0 mc! 0 1c0 mc! 0 1d0 mc! 0 1e0 mc! 0 1f0 mc!
287 \ after this point, setup is common for all speeds and sizes of dimms (sort of)
291 0 840 mc! 0 850 mc! 0 860 mc! 0 870 mc!
292 0 940 mc! 0 950 mc! 0 960 mc! 0 970 mc! 0 990 mc!
293 0 a40 mc! 0 a50 mc! 0 a60 mc! 0 a70 mc!
294 0 b40 mc! 0 b50 mc! 0 b60 mc! 0 b70 mc! 0 b90 mc!
304 80000000 b0 mc! BEGIN b0 mc@ 40000000 and UNTIL
309 0 410 mc! 27fffffc 420 mc!
311 c0000000 400 mc! BEGIN 400 mc@ c0000000 and 0= UNTIL