| \ ***************************************************************************** |
| \ * Copyright (c) 2004, 2008 IBM Corporation |
| \ * All rights reserved. |
| \ * This program and the accompanying materials |
| \ * are made available under the terms of the BSD License |
| \ * which accompanies this distribution, and is available at |
| \ * http://www.opensource.org/licenses/bsd-license.php |
| \ * |
| \ * Contributors: |
| \ * IBM Corporation - initial implementation |
| \ ****************************************************************************/ |
| |
| |
| \ U4 DDR2 memory controller. |
| |
| cr .( Setting up memory controller...) |
| |
| |
| \ First, I2C access to the SPDs. |
| |
| : >i2c f8001000 + ; |
| : i2c@ >i2c rl@ ; |
| : i2c! >i2c rl! ; |
| |
| : .i2c 80 0 DO i i2c@ . 10 +LOOP ; |
| |
| : i2c-addr ( addr -- ) 50 i2c! 2 10 i2c! BEGIN 30 i2c@ 2 and UNTIL ; |
| : i2c-addr-subaddr ( addr suba -- ) 60 i2c! i2c-addr ; |
| : i2c-stop ( -- ) BEGIN 30 i2c@ dup 30 i2c! 4 and UNTIL ; |
| : i2c-nak? ( -- failed? ) 20 i2c@ 2 and 0= dup IF i2c-stop THEN ; |
| : i2c-short? ( -- failed? ) 30 i2c@ 4 and 0<> dup IF 0 10 i2c! i2c-stop THEN ; |
| : i2c-aak-if-more ( n -- ) 1 <> 1 and 10 i2c! ; |
| |
| : i2c-sub-read ( buf len addr suba -- error? ) |
| c 0 i2c! >r 1 or r> i2c-addr-subaddr i2c-nak? IF 2drop true EXIT THEN |
| dup i2c-aak-if-more 2 30 i2c! |
| BEGIN |
| 30 i2c@ 1 and IF |
| 1- >r 70 i2c@ over c! char+ r> |
| dup 0= IF i2c-stop 2drop false EXIT THEN |
| dup i2c-aak-if-more 1 30 i2c! THEN |
| i2c-short? IF 2drop true EXIT THEN |
| AGAIN ; |
| |
| |
| \ What slots are filled with working memory (bitmask). |
| |
| f VALUE dimms-valid |
| : dimm-invalid 1 swap lshift invert dimms-valid and to dimms-valid ; |
| : dimm-invalid dup dimm-invalid 2 xor dimm-invalid ; \ DIMMs are paired |
| : dimm-valid? 1 swap lshift dimms-valid and ; |
| : dimm( +comp postpone 4 postpone 0 postpone DO |
| postpone i postpone dimm-valid? postpone IF ; immediate |
| : )dimm postpone THEN postpone LOOP -comp ; immediate |
| |
| |
| \ The data from the SPDs. |
| |
| CREATE spds 100 allot |
| : spd@ ( dimm# off -- value ) swap 40 * + spds + c@ ; |
| |
| CREATE addresses a0 c, a4 c, a2 c, a6 c, |
| dimm( spds i 40 * + 40 addresses i + c@ 0 i2c-sub-read IF i dimm-invalid THEN )dimm |
| |
| |
| \ Accessors. |
| |
| : spd>rows 3 spd@ ; |
| : spd>cols 4 spd@ ; |
| : spd>ranks 5 spd@ 7 and 1+ ; |
| : spd>width d spd@ ; |
| : spd>banks 11 spd@ ; |
| : spd>cas 12 spd@ ; \ bit mask of allowable CAS latencies |
| : spd>trp 1b spd@ ; \ in units of 0.25 ns |
| : spd>trrd 1c spd@ ; \ in units of 0.25 ns |
| : spd>trcd 1d spd@ ; \ in units of 0.25 ns |
| : spd>tras 1e spd@ ; \ in units of 1 ns |
| : spd>twr 24 spd@ ; \ in units of 0.25 ns |
| : spd>twtr 25 spd@ ; \ in units of 0.25 ns |
| : spd>trtp 26 spd@ ; \ in units of 0.25 ns |
| : spd>trc 29 spd@ ; \ in units of 1 ns XXX: should also look at byte 28 |
| : spd>trfc 2a spd@ ; \ in units of 1 ns XXX: should also look at byte 28 |
| |
| cr .( rows cols ranks width banks trp trrd trcd tras twr twtr trtp trc trfc) |
| cr .( =====================================================================) |
| decimal |
| dimm( cr |
| i spd>rows 4 .r i spd>cols 5 .r i spd>ranks 6 .r i spd>width 6 .r |
| i spd>banks 6 .r i spd>trp 4 .r i spd>trrd 5 .r i spd>trcd 5 .r |
| i spd>tras 5 .r i spd>twr 4 .r i spd>twtr 5 .r i spd>trtp 5 .r |
| i spd>trc 4 .r i spd>trfc 5 .r |
| )dimm |
| hex |
| |
| ff dimm( i spd>cas and )dimm CONSTANT cl-supported |
| : max-cl -1 swap 8 0 DO dup 1 and IF nip i swap THEN u2/ LOOP drop ; |
| cl-supported max-cl VALUE cl |
| |
| : tck>60*ns dup f and swap 4 rshift a * over + 6 * swap CASE |
| a OF 2d - ENDOF b OF 2e - ENDOF c OF 20 - ENDOF d OF 21 - ENDOF |
| ENDCASE ; |
| : cl>tck 0 spd>cas max-cl swap - |
| CASE 0 OF 9 ENDOF 1 OF 17 ENDOF 2 OF 19 ENDOF |
| true ABORT" No supported CAS latency for this DIMM" ENDCASE |
| 0 swap spd@ tck>60*ns ; |
| |
| : spd>min-tck dup spd>cas max-cl cl - |
| CASE 0 OF 9 ENDOF 1 OF 17 ENDOF 2 OF 19 ENDOF |
| true ABORT" No supported CAS latency for this DIMM" ENDCASE |
| spd@ tck>60*ns ; |
| : spd>max-tck 2b spd@ tck>60*ns ; |
| |
| : .tck base @ >r decimal dup d# 60 / 0 .r [char] . emit |
| d# 60 mod d# 1000 * d# 60 / 3 0.r ." ns" r> base ! ; |
| |
| cr .( CAS latencies supported: ) |
| 8 0 DO cl-supported 1 i lshift and IF i . THEN LOOP |
| |
| \ Find the lowest CL at the highest tCK. |
| 8 0 DO cl-supported 1 i lshift and IF cl cl>tck i cl>tck = IF |
| i to cl LEAVE THEN THEN LOOP |
| |
| .( -- using ) cl . |
| |
| |
| 0 dimm( i spd>min-tck max )dimm CONSTANT tck |
| dimm( i spd>max-tck tck < IF i dimm-invalid THEN )dimm |
| cr .( tCK is ) tck .tck |
| |
| |
| 0 CONSTANT al |
| cl al + CONSTANT rl |
| rl 1- CONSTANT wl |
| |
| : // dup >r 1- + r> / ; \ round up |
| 0 spd>tras d# 60 * tck // CONSTANT tras |
| 0 spd>trtp d# 15 * tck // CONSTANT trtp |
| 0 spd>twr d# 15 * tck // CONSTANT twr |
| 0 spd>trp d# 15 * tck // CONSTANT trp |
| 0 spd>trrd d# 15 * tck // CONSTANT trrd |
| 0 spd>trrd d# 60 * tck // CONSTANT 4*trrd |
| 0 spd>trcd d# 15 * tck // CONSTANT trcd |
| 0 spd>trc d# 60 * tck // CONSTANT trc |
| 0 spd>twtr d# 15 * tck // CONSTANT twtr |
| |
| : spd>memmd |
| >r r@ spd>rows r@ spd>cols + |
| r@ spd>banks 2log + 4 * r> spd>width 2log 3 * + 6c - ; |
| : dimm-group-size ( dimm# -- size ) |
| >r r@ spd>rows r@ spd>cols + 1 swap lshift |
| r@ spd>banks * r> spd>ranks * 10 * ; |
| VARIABLE start-address |
| VARIABLE was-prev-big |
| : assign-dimm-group ( dimm# -- config-value ) |
| dup dimm-valid? 0= IF drop 0 EXIT THEN |
| \ MemMd, enable, single-sided or not |
| dup spd>memmd c lshift 1 or over spd>ranks 1 = IF 2 or THEN |
| cr ." ---> " dup . |
| >r |
| dimm-group-size start-address @ 2dup + rot ( start end size ) |
| 80000000 > IF |
| dup 1000000000 < IF dup 4 rshift ELSE 08000000 THEN r> or >r \ Add2G |
| over 0<> IF over c rshift ELSE 00080000 THEN r> or >r \ Sub2G |
| was-prev-big on |
| ELSE |
| was-prev-big @ IF 80000000 + swap 80000000 + swap THEN r> 08080000 or >r |
| was-prev-big off |
| THEN |
| swap 18 rshift r> or >r \ start address |
| dup 80000000 = IF drop 100000000 THEN start-address ! r> ; |
| |
| |
| \ Now set the frequency in the memory controller |
| d# 1800 tck / 4 - 12 lshift 33c or f8000800 rl! |
| f8000860 rl@ 80000000 or f8000860 rl! 10000 0 DO LOOP |
| |
| : mc! f8002000 + rl! ; |
| : mc@ f8002000 + rl@ ; |
| |
| |
| \ memory timing regs (state machine) |
| |
| tras 2- |
| 5 lshift al trtp + 2- or |
| 5 lshift wl twr + or |
| 5 lshift trp 2- or |
| 5 lshift trp 2- 0 spd>banks 8 = IF 1+ THEN or |
| 7 lshift 030 mc! |
| |
| al trtp + trp + 2- |
| 5 lshift cl al + twr + trp + 1- or |
| 5 lshift trrd 2- or |
| 5 lshift trc 2- or |
| 5 lshift trcd 2- or |
| 5 lshift 4*trrd or |
| 2 lshift 040 mc! |
| |
| 0 |
| 5 lshift 1 or |
| 5 lshift 1 or |
| 5 lshift cl 1- twtr + or |
| 5 lshift 1 or |
| 5 lshift 1 or |
| 2 lshift 050 mc! |
| |
| 0 |
| 5 lshift 1 or |
| 5 lshift 1 or |
| 5 lshift 2 or |
| 5 lshift 2 or |
| 5 lshift 2 or |
| 2 lshift 060 mc! \ XXX joerg has different setting |
| |
| cl 3 = IF 30801800 ( 30800d00 ) 070 mc! \ XXX memory refresh |
| ELSE 41002000 070 mc! THEN |
| |
| \ memory size regs |
| |
| 1 dimm-group-size 0 dimm-group-size > 1 0 rot IF swap THEN \ biggest first |
| assign-dimm-group 200 mc! |
| assign-dimm-group 210 mc! |
| 0 220 mc! 0 230 mc! |
| |
| |
| |
| |
| |
| \ arbiter tunables |
| \ 40041040 270 mc! |
| 04041040 270 mc! |
| 50000000 280 mc! |
| \ a0a00000 290 mc! \ a0000000 might be faster |
| 00000000 290 mc! |
| \ 20020820 2a0 mc! |
| 04020822 2a0 mc! |
| 00000000 2b0 mc! |
| \ 30413cc7 2c0 mc! \ have to calculate the low five bits |
| 30413dc5 2c0 mc! |
| \ cl 3 = IF 76000050 2d0 mc! 70000000 2e0 mc! ELSE |
| cl 3 = IF 75000050 2d0 mc! 70000000 2e0 mc! ELSE |
| b8002080 2d0 mc! b0000000 2e0 mc! THEN |
| \ Should test for something else really |
| |
| |
| |
| cl 3 = IF 00006000 890 mc! 00006000 8a0 mc! ELSE |
| 00006500 890 mc! 00006500 8a0 mc! THEN |
| |
| cl 3 = IF 1e008a8a ELSE 31000000 THEN |
| dup 800 mc! dup 810 mc! dup 820 mc! dup 830 mc! |
| dup 900 mc! dup 910 mc! dup 920 mc! dup 930 mc! dup 980 mc! |
| dup a00 mc! dup a10 mc! dup a20 mc! dup a30 mc! |
| dup b00 mc! dup b10 mc! dup b20 mc! dup b30 mc! b80 mc! |
| |
| \ 0 8d0 mc! 0 9d0 mc! 0 ad0 mc! 0 bd0 mc! |
| 61630000 8d0 mc! |
| 61630000 9d0 mc! |
| 52510000 ad0 mc! |
| 434e0000 bd0 mc! |
| |
| a0200400 100 mc! |
| 80020000 110 mc! |
| 80030000 120 mc! |
| 80010404 130 mc! |
| cl 3 = IF |
| 8000153a 140 mc! ELSE |
| 8000174a 140 mc! THEN |
| a0200400 150 mc! |
| \ 92000000 160 mc! |
| \ 92000000 170 mc! |
| \ 91300000 160 mc! |
| \ 91300000 170 mc! |
| 91800000 160 mc! |
| 91800000 170 mc! |
| cl 3 = IF |
| 8ff0143a 180 mc! ELSE |
| 8ff0164a 180 mc! THEN |
| 80010784 190 mc! |
| 80010404 1a0 mc! |
| 0 1b0 mc! 0 1c0 mc! 0 1d0 mc! 0 1e0 mc! 0 1f0 mc! |
| |
| cl 3 = IF |
| 143a 0c0 mc! ELSE |
| 164a 0c0 mc! THEN |
| 0404 0d0 mc! |
| |
| \ after this point, setup is common for all speeds and sizes of dimms (sort of) |
| |
| 60000000 3a0 mc! |
| |
| 0 840 mc! 0 850 mc! 0 860 mc! 0 870 mc! |
| 0 940 mc! 0 950 mc! 0 960 mc! 0 970 mc! 0 990 mc! |
| 0 a40 mc! 0 a50 mc! 0 a60 mc! 0 a70 mc! |
| 0 b40 mc! 0 b50 mc! 0 b60 mc! 0 b70 mc! 0 b90 mc! |
| |
| 0 880 mc! |
| |
| 001a4000 9a0 mc! |
| |
| 84800000 500 mc! |
| |
| 10000 0 DO LOOP |
| |
| 80000000 b0 mc! BEGIN b0 mc@ 40000000 and UNTIL |
| |
| 0 300 mc! 0 310 mc! |
| |
| 80000000 440 mc! |
| 0 410 mc! 27fffffc 420 mc! |
| fedcba98 430 mc! |
| c0000000 400 mc! BEGIN 400 mc@ c0000000 and 0= UNTIL |
| |
| cr .( mem done) |