Since some people disapprove of white space cleanups mixed in regular commits
[coreboot.git] / src / cpu / amd / sc520 / raminit.c
index 65f5dc44e4627f7aa48f4e602f1aad22be67986f..e6232a8eb4aeaaeb83c414de83940221e392cbaf 100644 (file)
 /* Austin, TX 78741                http://www.amd.com/html/support/techsup.html*/
 /* ============================================================================*/
 
+
 #define OUTC(addr, val) *(unsigned char *)(addr) = (val)
 
+/* sadly, romcc can't quite handle what we want, so we do this ugly thing */
+#define drcctl   (( volatile unsigned char *)0xfffef010)
+#define drcmctl   (( volatile unsigned char *)0xfffef012)
+#define drccfg   (( volatile unsigned char *)0xfffef014)
 
-void
-setupsc520(void){
-       unsigned char *cp;
-       unsigned short *sp;
-       unsigned long *edi;
-       unsigned long *par;
+#define drcbendadr   (( volatile unsigned long *)0xfffef018)
+#define eccctl   (( volatile unsigned char *)0xfffef020)
+#define dbctl   (( volatile unsigned char *)0xfffef040)
+
+void setupsc520(void)
+{
+       volatile unsigned char *cp;
+       volatile unsigned short *sp;
+       volatile unsigned long *edi;
+
+       /* do this to see if MMCR will start acting right. we suspect
+        * you have to do SOMETHING to get things going. I'm really
+        * starting to hate this processor.
+        */
+
+       /* no, that did not help. I wonder what will?
+        * outl(0x800df0cb, 0xfffc);
+        */
+
+       /* well, this is special! You have to do SHORT writes to the
+        * locations, even though they are CHAR in size and CHAR aligned
+        * and technically, a SHORT write will result in -- yoo ha! --
+        * over writing the next location! Thanks to the u-boot guys
+        * for a reference code I can use. with these short pointers,
+        * it now reliably comes up after power cycle with printk. Ah yi
+        * yi.
+        */
 
        /* turn off the write buffer*/
-       cp = (unsigned char *)0xfffef040;
-       *cp = 0;
+       /* per the note above, make this a short? Let's try it. */
+       sp = (unsigned short *)0xfffef040;
+       *sp = 0;
+
+       /* as per the book: */
+       /* PAR register setup */
+       /* set up the PAR registers as they are on the MSM586SEG */
+       /*    moved to romstage.c by Stepan, Ron says: */
+       /* NOTE: move this to mainboard.c ASAP */
+       setup_pars();
+
+       /* CPCSF register */
+       sp =  (unsigned short *)0xfffefc24;
+       *sp = 0xfe;
 
+       /* ADDDECTL */
+       sp =  (unsigned short *)0xfffefc80;
+       *sp = 0x10;
+
+       /* byte writes in AMD assembly */
+       /* we do short anyway, since u-boot does ... */
        /*set the GP CS offset*/
        sp =  (unsigned short *)0xfffefc08;
        *sp = 0x00001;
        /*set the GP CS width*/
        sp =  (unsigned short *)0xfffefc09;
        *sp = 0x00003;
+
+       /* short writes in AMD assembly */
        /*set the GP CS width*/
        sp =  (unsigned short *)0xfffefc0a;
        *sp = 0x00001;
        /*set the RD pulse width*/
        sp =  (unsigned short *)0xfffefc0b;
        *sp = 0x00003;
-       /*set the GP RD offse*/
+       /*set the GP RD offse*/
        sp =  (unsigned short *)0xfffefc0c;
        *sp = 0x00001;
        /*set the GP WR pulse width*/
@@ -80,6 +126,8 @@ setupsc520(void){
        /*set the GP WR offset*/
        sp =  (unsigned short *)0xfffefc0e;
        *sp = 0x00001;
+
+
        /* set up the GP IO pins*/
        /*set the GPIO directionreg*/
        sp =  (unsigned short *)0xfffefc2c;
@@ -94,134 +142,67 @@ setupsc520(void){
        sp =  (unsigned short *)0xfffefc20;
        *sp = 0x0FFFF;
 
-#ifdef NETSC520
-if NetSC520
-; set the PIO regs correctly.
-       /*set the GPIO16-31 direction reg*/
-       sp =  (unsigned short *)0xfffefc2c;
-       *sp = 0x000ff;
-       /*set the PIODIR15_0 direction reg*/
-       sp =  (unsigned short *)0xfffefc2a;
-       *sp = 0x00440;
-       /*set the PIOPFS31_16 direction reg*/
-       sp =  (unsigned short *)0xfffefc22;
-       *sp = 0x00600;
-       /*set the PIOPFS15_0 direction reg*/
-       sp =  (unsigned short *)0xfffefc20;
-       *sp = 0x0FBBF;
-       /*set the PIODATA15_0 reg*/
-       sp =  (unsigned short *)0x0xfffefc30;
-       *sp = 0x0f000;
-       /*set the CSPFS reg*/
-       sp =  (unsigned short *)0xfffefc24;
-       *sp = 0x0000;
-
-; The NetSC520 uses PIOs 16-23 for LEDs instead of port 80
-; output a 1 to the leds
-       /*set the GPIO16-31 direction reg*/
-       sp =  (unsigned short *)0xfffefc32;
-       mov     al, not 1
-else
-#endif
 
-       /* setup for the CDP*/
-       /*set the GPIO directionreg*/
-       sp =  (unsigned short *)0xfffefc2c;
-       *sp = 0x00000;
-       /*set the GPIO directionreg*/
-       sp =  (unsigned short *)0xfffefc2a;
-       *sp = 0x00000;
-       /*set the GPIO pin function 31-16 reg*/
-       sp =  (unsigned short *)0xfffefc22;
-       *sp = 0x0FFFF;
-       /*set the GPIO pin function 15-0 reg*/
-       sp =  (unsigned short *)0xfffefc20;
-       *sp = 0x0FFFF;
        /* the 0x80 led should now be working*/
        outb(0xaa, 0x80);
-/*
-; set up a PAR to allow access to the 680 leds
-;      WriteMMCR( 0xc4,0x28000680);            // PAR15
- */
-       /*set PAR 15 for access to led 680*/
-/* skip hairy pci hack for now *
-       sp =  (unsigned short *)0xfffef0c4;
-       mov     eax,028000680h
-       mov     dx,0680h
-       *sp = 0x02;     ; output a 2 to led 680
-       out     dx,ax
-*/
-/*; set the uart baud rate clocks to the normal 1.8432 MHz.*/
+#if 0
+       /* wtf are 680 leds ... */
+       par = (unsigned long *) 0xfffef0c4;
+       *par = 0x28000680;
+       /* well? */
+       outb(0x55, 0x80);
+#endif
+
+       /* set the uart baud rate clocks to the normal 1.8432 MHz.*/
+       /* enable interrupts here? Why not? */
        cp = (unsigned char *)0xfffefcc0;
-       *cp = 4;                                        /* uart 1 clock source */
+       *cp = 4 | 3;                    /* uart 1 clock source */
        cp = (unsigned char *)0xfffefcc4;
-       *cp = 4;                                        /* uart 2 clock source */
+       *cp = 4;                        /* uart 2 clock source */
+
+#if 0
 /*; set the interrupt mapping registers.*/
        cp = (unsigned char *)0x0fffefd20;
        *cp = 0x01;
-       
+
        cp = (unsigned char *)0x0fffefd28;
        *cp = 0x0c;
-       
+
        cp = (unsigned char *)0x0fffefd29;
        *cp = 0x0b;
-       
+
        cp = (unsigned char *)0x0fffefd30;
        *cp = 0x07;
-       
+
        cp = (unsigned char *)0x0fffefd43;
        *cp = 0x03;
-       
+
        cp = (unsigned char *)0x0fffefd51;
        *cp = 0x02;
-       
-/*; "enumerate" the PCI. Mainly set the interrupt bits on the PCnetFast. */
-       outl(0xcf8, 0x08000683c);
-       outl(0xcfc, 0xc); /* set the interrupt line */
-
-/*; Set the SC520 PCI host bridge to target mode to allow external*/
-/*; bus mastering events*/
-
-       outl(0x0cf8,0x080000004);       /*index the status command register on device 0*/
-       outl(0xcfc, 0x2);                       /*set the memory access enable bit*/
-       OUTC(0x0fffef072, 1);           /* enable req bits in SYSARBMENB */
-
-
+#endif
 
-       /* set up the PAR registers as they are on the MSM586SEG */
-       par = (unsigned long *) 0xfffef080;
-       *par++ = 0x607c00a0; /*PAR0: PCI:Base 0xa0000; size 0x1f000:*/
-       *par++ = 0x480400d8; /*PAR1: GP BUS MEM:CS2:Base 0xd8, size 0x4:*/
-       *par++ = 0x340100ea; /*PAR2: GP BUS IO:CS5:Base 0xea, size 0x1:*/
-       *par++ = 0x380701f0; /*PAR3: GP BUS IO:CS6:Base 0x1f0, size 0x7:*/
-       *par++ = 0x3c0003f6; /*PAR4: GP BUS IO:CS7:Base 0x3f6, size 0x0:*/
-       *par++ = 0x35ff0400; /*PAR5: GP BUS IO:CS5:Base 0x400, size 0xff:*/
-       *par++ = 0x35ff0600; /*PAR6: GP BUS IO:CS5:Base 0x600, size 0xff:*/
-       *par++ = 0x35ff0800; /*PAR7: GP BUS IO:CS5:Base 0x800, size 0xff:*/
-       *par++ = 0x35ff0a00; /*PAR8: GP BUS IO:CS5:Base 0xa00, size 0xff:*/
-       *par++ = 0x35ff0e00; /*PAR9: GP BUS IO:CS5:Base 0xe00, size 0xff:*/
-       *par++ = 0x34fb0104; /*PAR10: GP BUS IO:CS5:Base 0x104, size 0xfb:*/
-       *par++ = 0x35af0200; /*PAR11: GP BUS IO:CS5:Base 0x200, size 0xaf:*/
-       *par++ = 0x341f03e0; /*PAR12: GP BUS IO:CS5:Base 0x3e0, size 0x1f:*/
-       *par++ = 0xe41c00c0; /*PAR13: SDRAM:code:cache:nowrite:Base 0xc0000, size 0x7000:*/
-       *par++ = 0x545c00c8; /*PAR14: GP BUS MEM:CS5:Base 0xc8, size 0x5c:*/
-       *par++ = 0x8a020200; /*PAR15: BOOTCS:code:nocache:write:Base 0x2000000, size 0x80000:*/
+/* Stepan says: This needs to go to the msm586seg code */
+/* "enumerate" the PCI. Mainly set the interrupt bits on the PCnetFast. */
+       outl(0x08000683c, 0xcf8);
+       outl(0xc, 0xcfc); /* set the interrupt line */
 
 
+       /* Set the SC520 PCI host bridge to target mode to
+        * allow external bus mastering events
+        */
+       /* index the status command register on device 0*/
+       outl(0x080000004, 0x0cf8);
+       outl(0x2, 0xcfc);               /*set the memory access enable bit*/
+       OUTC(0x0fffef072, 1);           /* enable req bits in SYSARBMENB */
 }
-       
+
 
 /*
  *
  *
  */
 
-#define DRCCTL        *(char*)0x0fffef010  /* DRAM control register*/
-#define DRCTMCTL      *(char*)0x0fffef012  /* DRAM timing control register*/
-#define DRCCFG        *(char*)0x0fffef014  /* DRAM bank configuration register*/
-#define DRCBENDADR    *(char*)0x0fffef018  /* DRAM bank ending address register*/
-#define ECCCTL        *(char*)0x0fffef020  /* DRAM ECC control register*/
-#define DBCTL         *(char*)0x0fffef040  /* DRAM buffer control register*/
+
 
 #define CACHELINESZ   0x00000010  /*  size of our cache line (read buffer)*/
 
@@ -240,28 +221,199 @@ else
 #define COL10_DATA 0x0a0a0a0a  /*  10 col data*/
 #define COL09_DATA 0x09090909  /*   9 col data*/
 #define COL08_DATA 0x08080808  /*   8 col data*/
+
 #define ROW14_DATA 0x3f3f3f3f  /*  14 row data (MASK)*/
 #define ROW13_DATA 0x1f1f1f1f  /*  13 row data (MASK)*/
 #define ROW12_DATA 0x0f0f0f0f  /*  12 row data (MASK)*/
 #define ROW11_DATA 0x07070707  /*  11 row data/also bank switch (MASK)*/
 #define ROW10_DATA 0xaaaaaaaa  /*  10 row data/also bank switch (MASK)*/
 
-#define dummy_write()   *(short *)CACHELINESZ=0x1010
+void
+dummy_write(void){
+  volatile unsigned short *ptr = (volatile unsigned short *)CACHELINESZ;
+  *ptr = 0;
+}
+
+#include "pc80/udelay_io.c"
+
+static void dumpram(void){
+  print_err("ctl "); print_err_hex8(*drcctl); print_err("\n");
+  print_err("mctl "); print_err_hex8(*drcmctl); print_err("\n");
+  print_err("cfg "); print_err_hex8(*drccfg); print_err("\n");
 
-void udelay(int microseconds) {
-       volatile int x;
-       for(x = 0; x < 1000; x++)
-               ;
+  print_err("bendadr0 "); print_err_hex8(*drcbendadr); print_err("\n");
+  print_err("bendadr1 "); print_err_hex8(*drcbendadr); print_err("\n");
+  print_err("bendadr2 "); print_err_hex8(*drcbendadr); print_err("\n");
+  print_err("bendadr3"); print_err_hex8(*drcbendadr); print_err("\n");
 }
 
-int nextbank(int bank)
+/* there is a lot of silliness in the amd code, and it is
+ * causing romcc real headaches, so we're going to be be a little
+ * less silly.
+ * so, the order of ops is:
+ * for i in 3 to 0
+ * see if bank is there.
+ * if we can write a word, and read it back, to hell with paranoia
+ * the bank is there. So write the magic byte, read it back, and
+ * use that to get size, etc. Try to keep things very simple,
+ * so people can actually follow the damned code.
+ */
+
+/* cache is assumed to be disabled */
+int sizemem(void)
 {
-       int rows,banks, cols, i, ending_adr;
 
-       /* this is really ugly, it is right from assembly code. 
+       int rows,banks, cols, i, bank;
+       unsigned char al;
+       volatile unsigned long *lp = (volatile unsigned long *) CACHELINESZ;
+       unsigned long l;
+       /* initialize dram controller registers */
+       /* disable write buffer/read-ahead buffer */
+       *dbctl = 0;
+       /* no ecc interrupts of any kind. */
+       *eccctl = 0;
+       /* Set SDRAM timing for slowest speed. */
+       *drcmctl = 0x1e;
+
+       /* setup dram register for all banks
+        * with max cols and max banks
+        * this is the oldest trick in the book. You are going to set up for max rows
+        * and cols, then do a write, then see if the data is wrapped to low memory.
+        * you can actually tell by which data gets to which low memory,
+        * exactly how many rows and cols you have.
+        */
+       *drccfg=0xbbbb;
+
+       /* setup loop to do 4 external banks starting with bank 3 */
+       *drcbendadr=0x0ff000000;
+       /* for now, set it up for one loop of bank 0. Just to get it to go at all. */
+       *drcbendadr=0x0ff;
+
+       /* issue a NOP to all DRAMs */
+       /* Setup DRAM control register with Disable refresh,
+        * disable write buffer Test Mode and NOP command select
+        */
+       *drcctl=0x01;
+
+       /* dummy write for NOP to take effect */
+       dummy_write();
+       print_err("NOP\n");
+       /* 100? 200? */
+       udelay(100);
+       print_err("after udelay\n");
+
+       /* issue all banks precharge */
+       *drcctl=0x02;
+       print_err("set *drcctl to 2 \n");
+       dummy_write();
+       print_err("PRE\n");
+
+       /* issue 2 auto refreshes to all banks */
+       *drcctl=0x04;
+       dummy_write();
+       print_err("AUTO1\n");
+       dummy_write();
+       print_err("AUTO2\n");
+
+       /* issue LOAD MODE REGISTER command */
+       *drcctl=0x03;
+       dummy_write();
+       print_err("LOAD MODE REG\n");
+
+       *drcctl=0x04;
+       for (i=0; i<8; i++) /* refresh 8 times */{
+               dummy_write();
+               print_err("dummy write\n");
+       }
+       print_err("8 dummy writes\n");
+
+       /* set control register to NORMAL mode */
+       *drcctl=0x00;
+       print_err("normal\n");
+
+       print_err("HI done normal\n");
+
+       print_err("sizemem\n");
+       for(bank = 3; bank >= 0; bank--) {
+         print_err("Try to assign to l\n");
+         *lp = 0xdeadbeef;
+         print_err("assigned l ... \n");
+         if (*lp != 0xdeadbeef) {
+           print_err(" no memory at bank ");
+           // print_err_hex8(bank);
+           //   print_err(" value "); print_err_hex32(*lp);
+           print_err("\n");
+           //      continue;
+         }
+         *drcctl = 2;
+         dummy_write();
+         *drccfg = *drccfg >> 4;
+         l = *drcbendadr;
+         l >>= 8;
+         *drcbendadr = l;
+         print_err("loop around\n");
+         *drcctl = 0;
+         dummy_write();
+       }
+#if 0
+       /* enable last bank and setup ending address
+        * register for max ram in last bank
+        */
+       *drcbendadr=0x0ff000000;
+
+
+//     dumpram();
+
+       /* issue a NOP to all DRAMs */
+       /* Setup DRAM control register with Disable refresh,
+        * disable write buffer Test Mode and NOP command select
+        */
+       *drcctl=0x01;
+
+       /* dummy write for NOP to take effect */
+       dummy_write();
+       print_err("NOP\n");
+       /* 100? 200? */
+       //udelay(100);
+       print_err("after udelay\n");
+
+       /* issue all banks precharge */
+       *drcctl=0x02;
+       print_err("set *drcctl to 2 \n");
+       dummy_write();
+       print_err("PRE\n");
+
+       /* issue 2 auto refreshes to all banks */
+       *drcctl=0x04;
+       dummy_write();
+       print_err("AUTO1\n");
+       dummy_write();
+       print_err("AUTO2\n");
+
+       /* issue LOAD MODE REGISTER command */
+       *drcctl=0x03;
+       dummy_write();
+       print_err("LOAD MODE REG\n");
+
+       *drcctl=0x04;
+       for (i=0; i<8; i++) /* refresh 8 times */{
+               dummy_write();
+               print_err("dummy write\n");
+       }
+       print_err("8 dummy writes\n");
+
+       /* set control register to NORMAL mode */
+       *drcctl=0x00;
+       print_err("normal\n");
+
+       print_err("HI done normal\n");
+       bank = 3;
+
+
+       /* this is really ugly, it is right from assembly code.
         * we need to clean it up later
         */
-       
+
 start:
        /* write col 11 wrap adr */
        COL11_ADR=COL11_DATA;
@@ -342,11 +494,14 @@ print_err("4b\n");
        if (rows>ROW14_DATA)
                goto bad_ram;
        /* verify all 4 bytes of dword same */
+/*
        if(rows&0xffff!=(rows>>16)&0xffff)
                goto bad_ram;
        if(rows&0xff!=(rows>>8)&0xff)
                goto bad_ram;
-       
+*/
+       /* now just get one of them */
+       rows &= 0xff;
        print_err("rows"); print_err_hex32(rows); print_err("\n");
        /* validate column data */
        cols=COL11_ADR;
@@ -355,14 +510,19 @@ print_err("4b\n");
        if (cols>COL11_DATA)
                goto bad_ram;
        /* verify all 4 bytes of dword same */
+/*
        if(cols&0xffff!=(cols>>16)&0xffff)
                goto bad_ram;
        if(cols&0xff!=(cols>>8)&0xff)
                goto bad_ram;
+*/
        print_err("cols"); print_err_hex32(cols); print_err("\n");
        cols -= COL08_DATA;
 
-       i = cols + rows;
+       /* cols now is in the range of 0 1 2 3 ...
+        */
+       i = cols&3;
+       //      i = cols + rows;
 
        /* wacky end addr calculation */
 /*
@@ -370,105 +530,114 @@ print_err("4b\n");
        al -= (i & 0xff);k
  */
 
-       
+       /* what a fookin' mess this is */
        if(banks==4)
                i+=8; /* <-- i holds merged value */
-       
+       /* i now has the col width in bits 0-1 and the bank count (2 or 4)
+        * in bit 3.
+        * this is the format for the drccfg register
+        */
+
        /* fix ending addr mask*/
        /*FIXME*/
        /* let's just go with this to start ... see if we can get ANYWHERE */
-       ending_adr=0xff;
+       /* need to get end addr. Need to do it with the bank in mind. */
+/*
+       al = 3;
+       al -= i&3;
+       *drcbendaddr = rows >> al;
+       print_err("computed ending_adr = "); print_err_hex8(ending_adr);
+       print_err("\n");
 
-bad_reint:
+*/
+bad_reinit:
        /* issue all banks recharge */
-       DRCCTL=0x02;
+       *drcctl=0x02;
        dummy_write();
 
        /* update ending address register */
-       DRCBENDADR=ending_adr;
-       
+//     *drcbendadr = ending_adr;
+
        /* update config register */
-       DRCCFG = (banks = 4 ? 8 : 0) | cols & 3;
+       *drccfg &= ~(0xff << bank*4);
+       if (ending_adr)
+         *drccfg = ((banks == 4 ? 8 : 0) | cols & 3)<< (bank*4);
+//     dumpram();
        /* skip the rest for now */
-       bank = 0;
-//     DRCCFG=DRCCFG&YYY|ZZZZ;
+       //      bank = 0;
+       //      *drccfg=*drccfg&YYY|ZZZZ;
 
        if(bank!=0) {
                bank--;
-               //*(&DRCBENDADR+XXYYXX)=0xff;
+//             drcbendaddr--;
+               *drcbendaddr = 0xff000000;
+               //*(&*drcbendadr+XXYYXX)=0xff;
                goto start;
        }
 
        /* set control register to NORMAL mode */
-       DRCCTL=0x00;
+       *drcctl=0x18;
        dummy_write();
        return bank;
-       
+
 bad_ram:
-       print_info("bad ram!\r\n");
+       print_info("bad ram!\n");
+       /* you are here because the read-after-write failed,
+        * in most cases because: no ram in that bank!
+        * set badbank to 1 and go to reinit
+        */
+       ending_adr = 0;
+       goto bad_reinit;
+       while(1)
+       print_err("DONE NEXTBANK\n");
+#endif
 }
 
-/* cache is assumed to be disabled */
-int sizemem(void)
+/* note: based on AMD code*/
+/* This code is known to work on the digital logic board and on the technologic
+ * systems ts5300
+ */
+int staticmem(void)
 {
-       int i;
-       /* initialize dram controller registers */
-
-       DBCTL=0; /* disable write buffer/read-ahead buffer */
-       ECCCTL=0; /* disable ECC */
-       DRCTMCTL=0x1e; /* Set SDRAM timing for slowest speed. */
-
-       /* setup loop to do 4 external banks starting with bank 3 */
-       print_err("sizemem\n");
-       /* enable last bank and setup ending address 
-        * register for max ram in last bank
-        */
-       DRCBENDADR=0x0ff000000;
-       /* setup dram register for all banks
-        * with max cols and max banks
-        */
-       DRCCFG=0xbbbb;
-
-       /* issue a NOP to all DRAMs */
-
-       /* Asetup DRAM control register with Disable refresh,
-        * disable write buffer Test Mode and NOP command select
-        */
-       DRCCTL=0x01;
-
-       /* dummy write for NOP to take effect */
-       dummy_write();
-
-       print_err("NOP\n");
-       /* 100? 200? */
-       udelay(100);
-
-       /* issue all banks precharge */
-       DRCCTL=0x02;
-       dummy_write();
-       print_err("PRE\n");
-
-       /* issue 2 auto refreshes to all banks */
-       DRCCTL=0x04;
-       dummy_write();
-       print_err("AUTO1\n");
-       dummy_write();
-       print_err("AUTO2\n");
-
-       /* issue LOAD MODE REGISTER command */
-       DRCCTL=0x03;
-       dummy_write();
-       print_err("LOAD MODE REG\n");
-
-       DRCCTL=0x04;
-       for (i=0; i<8; i++) /* refresh 8 times */
-               dummy_write();
-       print_err("8 dummy writes\n");
-
-       /* set control register to NORMAL mode */
-       DRCCTL=0x00;
-       print_err("normal\n");
-
-       nextbank(3);
-
-}      
+       volatile unsigned long *zero = (unsigned long *) CACHELINESZ;
+
+       /* set up 0x18 .. **/
+       *drcbendadr = 0x88;
+       *drcmctl = 0x1e;
+       *drccfg = 0x9;
+       /* nop mode */
+       *drcctl = 0x1;
+       /* do the dummy write */
+       *zero = 0;
+
+       /* precharge */
+       *drcctl = 2;
+       *zero = 0;
+
+       /* two autorefreshes */
+       *drcctl = 4;
+       *zero = 0;
+       print_debug("one zero out on refresh\n");
+       *zero = 0;
+       print_debug("two zero out on refresh\n");
+
+       /* load mode register */
+       *drcctl = 3;
+       *zero = 0;
+       print_debug("DONE the load mode reg\n");
+
+       /* normal mode */
+       *drcctl = 0x0;
+       *zero = 0;
+       print_debug("DONE one last write and then turn on refresh etc\n");
+       *drcctl = 0x18;
+       *zero = 0;
+       print_debug("DONE the normal\n");
+       *zero = 0xdeadbeef;
+       if (*zero != 0xdeadbeef)
+         print_debug("NO LUCK\n");
+       else
+         print_debug("did a store and load ...\n");
+       //print_err_hex32(*zero);
+       //      print_err(" zero is now "); print_err_hex32(*zero); print_err("\n");
+}