fix mmcrval, small cosmetics to raminit
[coreboot.git] / src / cpu / amd / sc520 / raminit.c
1 /* this setupcpu function comes from: */
2 /*==============================================================================*/
3 /* FILE   :  start16.asm*/
4 /**/
5 /* DESC   : A  16 bit mode assembly language startup program, intended for*/
6 /*          use with on Aspen SC520 platforms.*/
7 /**/
8 /* 11/16/2000 Added support for the NetSC520*/
9 /* 12/28/2000 Modified to boot linux image*/
10 /**/
11 /* =============================================================================*/
12 /*                                                                             */
13 /*  Copyright 2000 Advanced Micro Devices, Inc.                                */
14 /*                                                                             */
15 /* This software is the property of Advanced Micro Devices, Inc  (AMD)  which */
16 /* specifically grants the user the right to modify, use and distribute this */
17 /* software provided this COPYRIGHT NOTICE is not removed or altered.  All */
18 /* other rights are reserved by AMD.                                                       */
19 /*                                                                            */
20 /* THE MATERIALS ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED WARRANTY */
21 /* OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT OF */
22 /* THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY PARTICULAR PURPOSE.*/
23 /* IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER*/
24 /* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS*/
25 /* INTERRUPTION, LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR INABILITY*/
26 /* TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY OF*/
27 /* SUCH DAMAGES.  BECAUSE SOME JURSIDICTIONS PROHIBIT THE EXCLUSION OR*/
28 /* LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE*/
29 /* LIMITATION MAY NOT APPLY TO YOU.*/
30 /**/
31 /* AMD does not assume any responsibility for any errors that may appear in*/
32 /* the Materials nor any responsibility to support or update the Materials.*/
33 /* AMD retains the right to make changes to its test specifications at any*/
34 /* time, without notice.*/
35 /**/
36 /* So that all may benefit from your experience, please report  any  problems */
37 /* or suggestions about this software back to AMD.  Please include your name, */
38 /* company,  telephone number,  AMD product requiring support and question or */
39 /* problem encountered.                                                       */
40 /*                                                                            */
41 /* Advanced Micro Devices, Inc.         Worldwide support and contact           */
42 /* Embedded Processor Division            information available at:               */
43 /* Systems Engineering                       epd.support@amd.com*/
44 /* 5204 E. Ben White Blvd.                          -or-*/
45 /* Austin, TX 78741                http://www.amd.com/html/support/techsup.html*/
46 /* ============================================================================*/
47
48
49 #define OUTC(addr, val) *(unsigned char *)(addr) = (val)
50
51 /* sadly, romcc can't quite handle what we want, so we do this ugly thing */
52 #define drcctl   (( volatile unsigned char *)0xfffef010)
53 #define drcmctl   (( volatile unsigned char *)0xfffef012)
54 #define drccfg   (( volatile unsigned char *)0xfffef014)
55
56 #define drcbendadr   (( volatile unsigned long *)0xfffef018)
57 #define eccctl   (( volatile unsigned char *)0xfffef020)
58 #define dbctl   (( volatile unsigned char *)0xfffef040)
59 void
60 setupsc520(void){
61   volatile unsigned char *cp;
62   volatile unsigned short *sp;
63   volatile unsigned long *edi;
64   volatile unsigned long *par;
65
66   /* do this to see if MMCR will start acting right. 
67    * we suspect you have to do SOMETHING to get things going. 
68    * I'm really starting to hate this processor. 
69    */
70   /* no, that did not help. I wonder what will? 
71    * outl(0x800df0cb, 0xfffc);
72    */
73   /* well, this is special! You have to do SHORT writes to the locations, 
74    * even though they are CHAR in size and CHAR aligned and technically, a 
75    * SHORT write will result in -- yoo ha! -- over writing the next location!
76    * Thanks to the u-boot guys for a reference code I can use. 
77    * with these short pointers, it now reliably comes up after power cycle
78    * with printk. Ah yi yi.
79    */
80   /* turn off the write buffer*/
81   /* per the note above, make this a short? Let's try it. 
82    */
83   sp = (unsigned short *)0xfffef040;
84   *sp = 0;
85
86   /* as per the book: */
87   /* PAR register setup */
88         /* set up the PAR registers as they are on the MSM586SEG */
89         par = (unsigned long *) 0xfffef088;
90
91         /* NOTE: move this to mainboard.c ASAP */
92 #if 1
93
94
95         *par++ = 0x607c00a0; /*PAR0: PCI:Base 0xa0000; size 0x1f000:*/
96         *par++ = 0x480400d8; /*PAR1: GP BUS MEM:CS2:Base 0xd8, size 0x4:*/
97         *par++ = 0x340100ea; /*PAR2: GP BUS IO:CS5:Base 0xea, size 0x1:*/
98         *par++ = 0x380701f0; /*PAR3: GP BUS IO:CS6:Base 0x1f0, size 0x7:*/
99         *par++ = 0x3c0003f6; /*PAR4: GP BUS IO:CS7:Base 0x3f6, size 0x0:*/
100         *par++ = 0x35ff0400; /*PAR5: GP BUS IO:CS5:Base 0x400, size 0xff:*/
101         *par++ = 0x35ff0600; /*PAR6: GP BUS IO:CS5:Base 0x600, size 0xff:*/
102         *par++ = 0x35ff0800; /*PAR7: GP BUS IO:CS5:Base 0x800, size 0xff:*/
103         *par++ = 0x35ff0a00; /*PAR8: GP BUS IO:CS5:Base 0xa00, size 0xff:*/
104         *par++ = 0x35ff0e00; /*PAR9: GP BUS IO:CS5:Base 0xe00, size 0xff:*/
105         *par++ = 0x34fb0104; /*PAR10: GP BUS IO:CS5:Base 0x104, size 0xfb:*/
106         *par++ = 0x35af0200; /*PAR11: GP BUS IO:CS5:Base 0x200, size 0xaf:*/
107         *par++ = 0x341f03e0; /*PAR12: GP BUS IO:CS5:Base 0x3e0, size 0x1f:*/
108         *par++ = 0xe41c00c0; /*PAR13: SDRAM:code:cache:nowrite:Base 0xc0000, size 0x7000:*/
109         *par++ = 0x545c00c8; /*PAR14: GP BUS MEM:CS5:Base 0xc8, size 0x5c:*/
110 #else
111         par += 15;
112 #endif
113         *par++ = 0x8a020200; /*PAR15: BOOTCS:code:nocache:write:Base 0x2000000, size 0x80000:*/
114
115
116         /* CPCSF register */
117
118         sp =  (unsigned short *)0xfffefc24;
119         *sp = 0xfe;
120
121         /* ADDDECTL */
122         sp =  (unsigned short *)0xfffefc80;
123         *sp = 0x10;
124
125         /* byte writes in AMD assembly */
126         /* we do short anyway, since u-boot does ... */
127         /*set the GP CS offset*/
128         sp =  (unsigned short *)0xfffefc08;
129         *sp = 0x00001;
130         /*set the GP CS width*/
131         sp =  (unsigned short *)0xfffefc09;
132         *sp = 0x00003;
133
134         /* short writes in AMD assembly */
135         /*set the GP CS width*/
136         sp =  (unsigned short *)0xfffefc0a;
137         *sp = 0x00001;
138         /*set the RD pulse width*/
139         sp =  (unsigned short *)0xfffefc0b;
140         *sp = 0x00003;
141         /*set the GP RD offset */
142         sp =  (unsigned short *)0xfffefc0c;
143         *sp = 0x00001;
144         /*set the GP WR pulse width*/ 
145         sp =  (unsigned short *)0xfffefc0d;
146         *sp = 0x00003;
147         /*set the GP WR offset*/
148         sp =  (unsigned short *)0xfffefc0e;
149         *sp = 0x00001;
150
151
152         /* set up the GP IO pins*/
153         /*set the GPIO directionreg*/
154         sp =  (unsigned short *)0xfffefc2c;
155         *sp = 0x00000;
156         /*set the GPIO directionreg*/
157         sp =  (unsigned short *)0xfffefc2a;
158         *sp = 0x00000;
159         /*set the GPIO pin function 31-16 reg*/
160         sp =  (unsigned short *)0xfffefc22;
161         *sp = 0x0FFFF;
162         /*set the GPIO pin function 15-0 reg*/
163         sp =  (unsigned short *)0xfffefc20;
164         *sp = 0x0FFFF;
165
166
167         /* the 0x80 led should now be working*/
168         outb(0xaa, 0x80);
169 #if 0
170         /* wtf are 680 leds ... */
171         par = (unsigned long *) 0xfffef0c4;
172         *par = 0x28000680;
173         /* well? */
174         outb(0x55, 0x80);
175 #endif
176
177 /*; set the uart baud rate clocks to the normal 1.8432 MHz.*/
178 /* enable interrupts here? Why not? */
179         cp = (unsigned char *)0xfffefcc0;
180         *cp = 4 | 3;                                    /* uart 1 clock source */
181         cp = (unsigned char *)0xfffefcc4;
182         *cp = 4;                                        /* uart 2 clock source */
183
184 #if 0
185 /*; set the interrupt mapping registers.*/
186         cp = (unsigned char *)0x0fffefd20;
187         *cp = 0x01;
188         
189         cp = (unsigned char *)0x0fffefd28;
190         *cp = 0x0c;
191         
192         cp = (unsigned char *)0x0fffefd29;
193         *cp = 0x0b;
194         
195         cp = (unsigned char *)0x0fffefd30;
196         *cp = 0x07;
197         
198         cp = (unsigned char *)0x0fffefd43;
199         *cp = 0x03;
200         
201         cp = (unsigned char *)0x0fffefd51;
202         *cp = 0x02;
203 #endif  
204 /*; "enumerate" the PCI. Mainly set the interrupt bits on the PCnetFast. */
205         outl(0xcf8, 0x08000683c);
206         outl(0xcfc, 0xc); /* set the interrupt line */
207
208 /*; Set the SC520 PCI host bridge to target mode to allow external*/
209 /*; bus mastering events*/
210
211         outl(0x0cf8,0x080000004);       /*index the status command register on device 0*/
212         outl(0xcfc, 0x2);                       /*set the memory access enable bit*/
213         OUTC(0x0fffef072, 1);           /* enable req bits in SYSARBMENB */
214
215
216
217 }
218         
219
220 /*
221  *
222  *
223  */
224
225
226
227 #define CACHELINESZ   0x00000010  /*  size of our cache line (read buffer)*/
228
229 #define COL11_ADR  *(unsigned int *)0x0e001e00 /* 11 col addrs*/
230 #define COL10_ADR  *(unsigned int *)0x0e000e00 /* 10 col addrs*/
231 #define COL09_ADR  *(unsigned int *)0x0e000600 /*  9 col addrs*/
232 #define COL08_ADR  *(unsigned int *)0x0e000200 /*  8 col addrs*/
233
234 #define ROW14_ADR  *(unsigned int *)0x0f000000 /* 14 row addrs*/
235 #define ROW13_ADR  *(unsigned int *)0x07000000 /* 13 row addrs*/
236 #define ROW12_ADR  *(unsigned int *)0x03000000 /* 12 row addrs*/
237 #define ROW11_ADR  *(unsigned int *)0x01000000 /* 11 row addrs/also bank switch*/
238 #define ROW10_ADR  *(unsigned int *)0x00000000 /* 10 row addrs/also bank switch*/
239
240 #define COL11_DATA 0x0b0b0b0b   /*  11 col addrs*/
241 #define COL10_DATA 0x0a0a0a0a   /*  10 col data*/
242 #define COL09_DATA 0x09090909   /*   9 col data*/
243 #define COL08_DATA 0x08080808   /*   8 col data*/
244
245 #define ROW14_DATA 0x3f3f3f3f   /*  14 row data (MASK)*/
246 #define ROW13_DATA 0x1f1f1f1f   /*  13 row data (MASK)*/
247 #define ROW12_DATA 0x0f0f0f0f   /*  12 row data (MASK)*/
248 #define ROW11_DATA 0x07070707   /*  11 row data/also bank switch (MASK)*/
249 #define ROW10_DATA 0xaaaaaaaa   /*  10 row data/also bank switch (MASK)*/
250
251 void 
252 dummy_write(void){
253   volatile unsigned short *ptr = (volatile unsigned short *)CACHELINESZ;
254   *ptr = 0;
255 }
256
257 void sc520_udelay(int microseconds) {
258         volatile int x;
259         for(x = 0; x < 1000; x++)
260                 ;
261 }
262
263 /* looks like we define this now */
264 void
265 udelay(int microseconds) {
266         sc520_udelay(microseconds);
267 }
268
269
270 static void dumpram(void){
271   print_err("ctl "); print_err_hex8(*drcctl); print_err("\r\n");
272   print_err("mctl "); print_err_hex8(*drcmctl); print_err("\r\n");
273   print_err("cfg "); print_err_hex8(*drccfg); print_err("\r\n");
274
275   print_err("bendadr0 "); print_err_hex8(*drcbendadr); print_err("\r\n");
276   print_err("bendadr1 "); print_err_hex8(*drcbendadr); print_err("\r\n");
277   print_err("bendadr2 "); print_err_hex8(*drcbendadr); print_err("\r\n");
278   print_err("bendadr3"); print_err_hex8(*drcbendadr); print_err("\r\n");
279 }
280
281 /* there is a lot of silliness in the amd code, and it is 
282  * causing romcc real headaches, so we're going to be be a little 
283  * less silly.
284  * so, the order of ops is: 
285  * for i in 3 to 0
286  * see if bank is there. 
287  * if we can write a word, and read it back, to hell with paranoia
288  * the bank is there. So write the magic byte, read it back, and 
289  * use that to get size, etc. Try to keep things very simple, 
290  * so people can actually follow the damned code. 
291  */
292
293 /* cache is assumed to be disabled */
294 int sizemem(void)
295 {
296
297         int rows,banks, cols, i, bank;
298         unsigned char al;
299         volatile unsigned long *lp = (volatile unsigned long *) CACHELINESZ;
300         unsigned long l;
301         /* initialize dram controller registers */
302         /* disable write buffer/read-ahead buffer */
303         *dbctl = 0;
304         /* no ecc interrupts of any kind. */
305         *eccctl = 0;
306         /* Set SDRAM timing for slowest speed. */
307         *drcmctl = 0x1e; 
308
309         /* setup dram register for all banks
310          * with max cols and max banks
311          * this is the oldest trick in the book. You are going to set up for max rows
312          * and cols, then do a write, then see if the data is wrapped to low memory. 
313          * you can actually tell by which data gets to which low memory, 
314          * exactly how many rows and cols you have. 
315          */
316         *drccfg=0xbbbb;
317
318         /* setup loop to do 4 external banks starting with bank 3 */
319         *drcbendadr=0x0ff000000;
320         /* for now, set it up for one loop of bank 0. Just to get it to go at all. */
321         *drcbendadr=0x0ff;
322
323         /* issue a NOP to all DRAMs */
324         /* Setup DRAM control register with Disable refresh,
325          * disable write buffer Test Mode and NOP command select
326          */
327         *drcctl=0x01;
328
329         /* dummy write for NOP to take effect */
330         dummy_write();
331         print_err("NOP\n");
332         /* 100? 200? */
333         udelay(100);
334         print_err("after sc520_udelay\r\n");
335
336         /* issue all banks precharge */
337         *drcctl=0x02;
338         print_err("set *drcctl to 2 \r\n");
339         dummy_write();
340         print_err("PRE\n");
341
342         /* issue 2 auto refreshes to all banks */
343         *drcctl=0x04;
344         dummy_write();
345         print_err("AUTO1\n");
346         dummy_write();
347         print_err("AUTO2\n");
348
349         /* issue LOAD MODE REGISTER command */
350         *drcctl=0x03;
351         dummy_write();
352         print_err("LOAD MODE REG\n");
353
354         *drcctl=0x04;
355         for (i=0; i<8; i++) /* refresh 8 times */{
356                 dummy_write();
357                 print_err("dummy write\r\n");
358         }
359         print_err("8 dummy writes\n");
360
361         /* set control register to NORMAL mode */
362         *drcctl=0x00;
363         print_err("normal\n");
364
365         print_err("HI done normal\r\n");
366
367         print_err("sizemem\n");
368         for(bank = 3; bank >= 0; bank--) {
369           print_err("Try to assign to l\r\n");
370           *lp = 0xdeadbeef;
371           print_err("assigned l ... \r\n");
372           if (*lp != 0xdeadbeef) {
373             print_err(" no memory at bank "); 
374             // print_err_hex8(bank); 
375             //   print_err(" value "); print_err_hex32(*lp);
376             print_err("\r\n"); 
377             //      continue;
378           }
379           *drcctl = 2;
380           dummy_write();
381           *drccfg = *drccfg >> 4;
382           l = *drcbendadr;
383           l >>= 8; 
384           *drcbendadr = l;
385           print_err("loop around\r\n");
386           *drcctl = 0;
387           dummy_write();
388         }
389 #if 0
390         /* enable last bank and setup ending address 
391          * register for max ram in last bank
392          */
393         *drcbendadr=0x0ff000000;
394
395
396 //      dumpram();
397
398         /* issue a NOP to all DRAMs */
399         /* Setup DRAM control register with Disable refresh,
400          * disable write buffer Test Mode and NOP command select
401          */
402         *drcctl=0x01;
403
404         /* dummy write for NOP to take effect */
405         dummy_write();
406         print_err("NOP\n");
407         /* 100? 200? */
408         //sc520_udelay(100);
409         print_err("after sc520_udelay\r\n");
410
411         /* issue all banks precharge */
412         *drcctl=0x02;
413         print_err("set *drcctl to 2 \r\n");
414         dummy_write();
415         print_err("PRE\n");
416
417         /* issue 2 auto refreshes to all banks */
418         *drcctl=0x04;
419         dummy_write();
420         print_err("AUTO1\n");
421         dummy_write();
422         print_err("AUTO2\n");
423
424         /* issue LOAD MODE REGISTER command */
425         *drcctl=0x03;
426         dummy_write();
427         print_err("LOAD MODE REG\n");
428
429         *drcctl=0x04;
430         for (i=0; i<8; i++) /* refresh 8 times */{
431                 dummy_write();
432                 print_err("dummy write\r\n");
433         }
434         print_err("8 dummy writes\n");
435
436         /* set control register to NORMAL mode */
437         *drcctl=0x00;
438         print_err("normal\n");
439
440         print_err("HI done normal\r\n");
441         bank = 3;
442
443
444         /* this is really ugly, it is right from assembly code. 
445          * we need to clean it up later
446          */
447         
448 start:
449         /* write col 11 wrap adr */
450         COL11_ADR=COL11_DATA;
451         if(COL11_ADR!=COL11_DATA)
452                 goto bad_ram;
453
454 print_err("11\n");
455         /* write col 10 wrap adr */
456         COL10_ADR=COL10_DATA;
457         if(COL10_ADR!=COL10_DATA)
458                 goto bad_ram;
459 print_err("10\n");
460
461         /* write col 9 wrap adr */
462         COL09_ADR=COL09_DATA;
463         if(COL09_ADR!=COL09_DATA)
464                 goto bad_ram;
465 print_err("9\n");
466
467         /* write col 8 wrap adr */
468         COL08_ADR=COL08_DATA;
469         if(COL08_ADR!=COL08_DATA)
470                 goto bad_ram;
471 print_err("8\n");
472
473         /* write row 14 wrap adr */
474         ROW14_ADR=ROW14_DATA;
475         if(ROW14_ADR!=ROW14_DATA)
476                 goto bad_ram;
477 print_err("14\n");
478
479         /* write row 13 wrap adr */
480         ROW13_ADR=ROW13_DATA;
481         if(ROW13_ADR!=ROW13_DATA)
482                 goto bad_ram;
483 print_err("13\n");
484
485         /* write row 12 wrap adr */
486         ROW12_ADR=ROW12_DATA;
487         if(ROW12_ADR!=ROW12_DATA)
488                 goto bad_ram;
489 print_err("12\n");
490
491         /* write row 11 wrap adr */
492         ROW11_ADR=ROW11_DATA;
493         if(ROW11_ADR!=ROW11_DATA)
494                 goto bad_ram;
495 print_err("11\n");
496
497         /* write row 10 wrap adr */
498         ROW10_ADR=ROW10_DATA;
499         if(ROW10_ADR!=ROW10_DATA)
500                 goto bad_ram;
501 print_err("10\n");
502
503 /*
504  * read data @ row 12 wrap adr to determine # banks,
505  *  and read data @ row 14 wrap adr to determine # rows.
506  *  if data @ row 12 wrap adr is not AA, 11 or 12 we have bad RAM.
507  * if data @ row 12 wrap == AA, we only have 2 banks, NOT 4
508  * if data @ row 12 wrap == 11 or 12, we have 4 banks
509  */
510
511         banks=2;
512         if (ROW12_ADR != ROW10_DATA) {
513                 banks=4;
514 print_err("4b\n");
515                 if(ROW12_ADR != ROW11_DATA) {
516                         if(ROW12_ADR != ROW12_DATA)
517                                 goto bad_ram;
518                 }
519         }
520
521         /* validate row mask */
522         rows=ROW14_ADR;
523         if (rows<ROW11_DATA)
524                 goto bad_ram;
525         if (rows>ROW14_DATA)
526                 goto bad_ram;
527         /* verify all 4 bytes of dword same */
528 /*
529         if(rows&0xffff!=(rows>>16)&0xffff)
530                 goto bad_ram;
531         if(rows&0xff!=(rows>>8)&0xff)
532                 goto bad_ram;
533 */
534         /* now just get one of them */
535         rows &= 0xff;
536         print_err("rows"); print_err_hex32(rows); print_err("\n");
537         /* validate column data */
538         cols=COL11_ADR;
539         if(cols<COL08_DATA)
540                 goto bad_ram;
541         if (cols>COL11_DATA)
542                 goto bad_ram;
543         /* verify all 4 bytes of dword same */
544 /*
545         if(cols&0xffff!=(cols>>16)&0xffff)
546                 goto bad_ram;
547         if(cols&0xff!=(cols>>8)&0xff)
548                 goto bad_ram;
549 */
550         print_err("cols"); print_err_hex32(cols); print_err("\n");
551         cols -= COL08_DATA;
552
553         /* cols now is in the range of 0 1 2 3 ... 
554          */
555         i = cols&3;
556         //      i = cols + rows;
557
558         /* wacky end addr calculation */
559 /*
560         al = 3;
561         al -= (i & 0xff);k
562  */
563
564         /* what a fookin' mess this is */
565         if(banks==4)
566                 i+=8; /* <-- i holds merged value */
567         /* i now has the col width in bits 0-1 and the bank count (2 or 4) 
568          * in bit 3.
569          * this is the format for the drccfg register 
570          */
571         
572         /* fix ending addr mask*/
573         /*FIXME*/
574         /* let's just go with this to start ... see if we can get ANYWHERE */
575         /* need to get end addr. Need to do it with the bank in mind. */
576 /*
577         al = 3; 
578         al -= i&3;
579         *drcbendaddr = rows >> al;
580         print_err("computed ending_adr = "); print_err_hex8(ending_adr); 
581         print_err("\r\n");
582         
583 */
584 bad_reinit:
585         /* issue all banks recharge */
586         *drcctl=0x02;
587         dummy_write();
588
589         /* update ending address register */
590 //      *drcbendadr = ending_adr;
591         
592         /* update config register */
593         *drccfg &= ~(0xff << bank*4);
594         if (ending_adr)
595           *drccfg = ((banks == 4 ? 8 : 0) | cols & 3)<< (bank*4);
596 //      dumpram();
597         /* skip the rest for now */
598         //      bank = 0;
599         //      *drccfg=*drccfg&YYY|ZZZZ;
600
601         if(bank!=0) {
602                 bank--;
603 //              drcbendaddr--;
604                 *drcbendaddr = 0xff000000;
605                 //*(&*drcbendadr+XXYYXX)=0xff;
606                 goto start;
607         }
608
609         /* set control register to NORMAL mode */
610         *drcctl=0x18;
611         dummy_write();
612         return bank;
613         
614 bad_ram:
615         print_info("bad ram!\r\n");
616         /* you are here because the read-after-write failed, 
617          * in most cases because: no ram in that bank! 
618          * set badbank to 1 and go to reinit
619          */
620         ending_adr = 0;
621         goto bad_reinit;
622         while(1)
623         print_err("DONE NEXTBANK\r\n");
624 #endif
625 }       
626
627 /* note: based on AMD code*/
628 /* This code is known to work on the digital logic board and on the technologic
629  * systems ts5300
630  */
631 int
632 staticmem(void){
633   volatile unsigned long *zero = (unsigned long *) CACHELINESZ;
634         /* set up 0x18 .. **/
635         *drcbendadr = 0x88;
636         *drcmctl = 0x1e;
637         *drccfg = 0x9;
638         /* nop mode */
639         *drcctl = 0x1;
640         /* do the dummy write */
641         *zero = 0;
642         
643         /* precharge */
644         *drcctl = 2;
645         *zero = 0;
646
647         /* two autorefreshes */
648         *drcctl = 4;
649         *zero = 0;
650         print_err("one zero out on refresh\r\n");
651         *zero = 0;
652         print_err("two zero out on refresh\r\n");
653
654         /* load mode register */
655         *drcctl = 3;
656         *zero = 0;
657         print_err("DONE the load mode reg\r\n");
658         
659         /* normal mode */
660         *drcctl = 0x0;
661         *zero = 0;
662         print_err("DONE one last write and then turn on refresh etc\r\n");
663         *drcctl = 0x18;
664         *zero = 0;
665         print_err("DONE the normal\r\n");
666         *zero = 0xdeadbeef;
667         if (*zero != 0xdeadbeef) 
668           print_err("NO LUCK\r\n");
669         else
670           print_err("did a store and load ...\r\n");
671         //print_err_hex32(*zero);
672         //      print_err(" zero is now "); print_err_hex32(*zero); print_err("\r\n");
673 }