summaryrefslogtreecommitdiff
path: root/src/cpu/amd/sc520/raminit.c
diff options
context:
space:
mode:
authorarch import user (historical) <svn@openbios.org>2005-07-06 17:16:15 +0000
committerarch import user (historical) <svn@openbios.org>2005-07-06 17:16:15 +0000
commit897c78bd152084e56c32206f76f5725e20ae6a9d (patch)
treee3ca93ac82daefa58d43822d798be29f383eebcc /src/cpu/amd/sc520/raminit.c
parent52871c4ad54e08e80da891bd399d63f71d9a87a3 (diff)
downloadcoreboot-897c78bd152084e56c32206f76f5725e20ae6a9d.tar.xz
Revision: linuxbios@linuxbios.org--devel/freebios--devel--2.0--patch-47
Creator: Ronald G. Minnich <rminnich@lanl.gov> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1963 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/cpu/amd/sc520/raminit.c')
-rw-r--r--src/cpu/amd/sc520/raminit.c378
1 files changed, 320 insertions, 58 deletions
diff --git a/src/cpu/amd/sc520/raminit.c b/src/cpu/amd/sc520/raminit.c
index 65f5dc44e4..79a7066cbb 100644
--- a/src/cpu/amd/sc520/raminit.c
+++ b/src/cpu/amd/sc520/raminit.c
@@ -45,6 +45,7 @@
/* Austin, TX 78741 http://www.amd.com/html/support/techsup.html*/
/* ============================================================================*/
+
#define OUTC(addr, val) *(unsigned char *)(addr) = (val)
@@ -60,26 +61,26 @@ setupsc520(void){
*cp = 0;
/*set the GP CS offset*/
- sp = (unsigned short *)0xfffefc08;
- *sp = 0x00001;
+ cp = (unsigned char *)0xfffefc08;
+ *cp = 0x00001;
/*set the GP CS width*/
- sp = (unsigned short *)0xfffefc09;
- *sp = 0x00003;
+ cp = (unsigned char *)0xfffefc09;
+ *cp = 0x00003;
/*set the GP CS width*/
- sp = (unsigned short *)0xfffefc0a;
- *sp = 0x00001;
+ cp = (unsigned char *)0xfffefc0a;
+ *cp = 0x00001;
/*set the RD pulse width*/
- sp = (unsigned short *)0xfffefc0b;
- *sp = 0x00003;
- /*set the GP RD offse*/
- sp = (unsigned short *)0xfffefc0c;
- *sp = 0x00001;
+ cp = (unsigned char *)0xfffefc0b;
+ *cp = 0x00003;
+ /*set the GP RD offset */
+ cp = (unsigned char *)0xfffefc0c;
+ *cp = 0x00001;
/*set the GP WR pulse width*/
- sp = (unsigned short *)0xfffefc0d;
- *sp = 0x00003;
+ cp = (unsigned char *)0xfffefc0d;
+ *cp = 0x00003;
/*set the GP WR offset*/
- sp = (unsigned short *)0xfffefc0e;
- *sp = 0x00001;
+ cp = (unsigned char *)0xfffefc0e;
+ *cp = 0x00001;
/* set up the GP IO pins*/
/*set the GPIO directionreg*/
sp = (unsigned short *)0xfffefc2c;
@@ -143,14 +144,6 @@ else
; 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.*/
cp = (unsigned char *)0xfffefcc0;
*cp = 4; /* uart 1 clock source */
@@ -205,7 +198,7 @@ else
*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:*/
+// *par++ = 0x8a020200; /*PAR15: BOOTCS:code:nocache:write:Base 0x2000000, size 0x80000:*/
}
@@ -216,12 +209,7 @@ else
*
*/
-#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,23 +228,72 @@ 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;
+}
-void udelay(int microseconds) {
+void sc520_udelay(int microseconds) {
volatile int x;
for(x = 0; x < 1000; x++)
;
}
+struct ramctl {
+ unsigned char drcctl;
+ unsigned char pad1;
+ unsigned char drcmctl;
+ unsigned char pad2;
+ unsigned char drccfg;
+ unsigned char pad[3];
+ unsigned char drcbendadr[4];
+};
+
+#define RAMCTL (struct ramctl *) 0xfffef010
+
+static void dumpram(void){
+ struct ramctl *ram = RAMCTL;
+ print_err("ctl "); print_err_hex8(ram->drcctl); print_err("\r\n");
+ print_err("mctl "); print_err_hex8(ram->drcmctl); print_err("\r\n");
+ print_err("cfg "); print_err_hex8(ram->drccfg); print_err("\r\n");
+
+ print_err("bendadr0 "); print_err_hex8(ram->drcbendadr[0]); print_err("\r\n");
+ print_err("bendadr1 "); print_err_hex8(ram->drcbendadr[1]); print_err("\r\n");
+ print_err("bendadr2 "); print_err_hex8(ram->drcbendadr[2]); print_err("\r\n");
+ print_err("bendadr3"); print_err_hex8(ram->drcbendadr[3]); print_err("\r\n");
+}
+
+struct eccctl {
+ unsigned char eccctl;
+ unsigned char eccsta;
+ unsigned char eccckbpos;
+ unsigned char ecccktest;
+ unsigned char eccsbadd;
+ unsigned char pad[3];
+ unsigned char eccmbad;
+};
+
+#define ECCCTL (struct eccctl *) 0xfffef020
+
+#define DBCTL (unsigned char *) 0xfffef040
+
+#if 0
int nextbank(int bank)
{
- int rows,banks, cols, i, ending_adr;
+ struct ramctl *ram = RAMCTL;
+ struct eccctl *ecc = ECCCTL;
+ unsigned char *dbctl = DBCTL;
+
+ int rows,banks, cols, i;
+ unsigned char ending_adr;
/* this is really ugly, it is right from assembly code.
* we need to clean it up later
@@ -267,7 +304,7 @@ start:
COL11_ADR=COL11_DATA;
if(COL11_ADR!=COL11_DATA)
goto bad_ram;
-
+//while(1)
print_err("11\n");
/* write col 10 wrap adr */
COL10_ADR=COL10_DATA;
@@ -381,94 +418,319 @@ print_err("4b\n");
bad_reint:
/* issue all banks recharge */
- DRCCTL=0x02;
+ ram->drcctl=0x02;
dummy_write();
/* update ending address register */
- DRCBENDADR=ending_adr;
+ ram->drcbendadr[bank] = ending_adr;
/* update config register */
- DRCCFG = (banks = 4 ? 8 : 0) | cols & 3;
+ ram->drccfg = (banks = 4 ? 8 : 0) | cols & 3;
/* skip the rest for now */
bank = 0;
-// DRCCFG=DRCCFG&YYY|ZZZZ;
+// *drccfg=*drccfg&YYY|ZZZZ;
if(bank!=0) {
bank--;
- //*(&DRCBENDADR+XXYYXX)=0xff;
+ //*(&*drcbendadr+XXYYXX)=0xff;
goto start;
}
/* set control register to NORMAL mode */
- DRCCTL=0x00;
+ ram->drcctl=0x00;
dummy_write();
return bank;
bad_ram:
print_info("bad ram!\r\n");
}
-
+#endif
/* cache is assumed to be disabled */
int sizemem(void)
{
- int i;
+ struct ramctl *ram = RAMCTL;
+ struct eccctl *ecc = ECCCTL;
+ unsigned char *dbctl = DBCTL;
+ int rows,banks, cols, i, bank;
+ unsigned char ending_adr, al;
+
/* initialize dram controller registers */
- DBCTL=0; /* disable write buffer/read-ahead buffer */
- ECCCTL=0; /* disable ECC */
- DRCTMCTL=0x1e; /* Set SDRAM timing for slowest speed. */
+ *dbctl = 0; /* disable write buffer/read-ahead buffer */
+ ecc->eccctl = 0;
+ ram->drcmctl = 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;
+ ram->drcbendadr[3]=0x0ff000000;
+
/* setup dram register for all banks
* with max cols and max banks
*/
- DRCCFG=0xbbbb;
+ ram->drccfg=0xbbbb;
- /* issue a NOP to all DRAMs */
+ dumpram();
- /* Asetup DRAM control register with Disable refresh,
+ /* issue a NOP to all DRAMs */
+ /* Setup DRAM control register with Disable refresh,
* disable write buffer Test Mode and NOP command select
*/
- DRCCTL=0x01;
+ ram->drcctl=0x01;
/* dummy write for NOP to take effect */
dummy_write();
-
print_err("NOP\n");
/* 100? 200? */
- udelay(100);
+ //sc520_udelay(100);
+ print_err("after sc520_udelay\r\n");
/* issue all banks precharge */
- DRCCTL=0x02;
+ ram->drcctl=0x02;
+ print_err("set *drcctl to 2 \r\n");
dummy_write();
print_err("PRE\n");
/* issue 2 auto refreshes to all banks */
- DRCCTL=0x04;
+ ram->drcctl=0x04;
dummy_write();
print_err("AUTO1\n");
dummy_write();
print_err("AUTO2\n");
/* issue LOAD MODE REGISTER command */
- DRCCTL=0x03;
+ ram->drcctl=0x03;
dummy_write();
print_err("LOAD MODE REG\n");
- DRCCTL=0x04;
- for (i=0; i<8; i++) /* refresh 8 times */
+ ram->drcctl=0x04;
+ for (i=0; i<8; i++) /* refresh 8 times */{
dummy_write();
+ print_err("dummy write\r\n");
+ }
print_err("8 dummy writes\n");
/* set control register to NORMAL mode */
- DRCCTL=0x00;
+ ram->drcctl=0x00;
print_err("normal\n");
+ print_err("HI done normal\r\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;
+ if(COL11_ADR!=COL11_DATA)
+ goto bad_ram;
+
+print_err("11\n");
+ /* write col 10 wrap adr */
+ COL10_ADR=COL10_DATA;
+ if(COL10_ADR!=COL10_DATA)
+ goto bad_ram;
+print_err("10\n");
+
+ /* write col 9 wrap adr */
+ COL09_ADR=COL09_DATA;
+ if(COL09_ADR!=COL09_DATA)
+ goto bad_ram;
+print_err("9\n");
+
+ /* write col 8 wrap adr */
+ COL08_ADR=COL08_DATA;
+ if(COL08_ADR!=COL08_DATA)
+ goto bad_ram;
+print_err("8\n");
+
+ /* write row 14 wrap adr */
+ ROW14_ADR=ROW14_DATA;
+ if(ROW14_ADR!=ROW14_DATA)
+ goto bad_ram;
+print_err("14\n");
+
+ /* write row 13 wrap adr */
+ ROW13_ADR=ROW13_DATA;
+ if(ROW13_ADR!=ROW13_DATA)
+ goto bad_ram;
+print_err("13\n");
+
+ /* write row 12 wrap adr */
+ ROW12_ADR=ROW12_DATA;
+ if(ROW12_ADR!=ROW12_DATA)
+ goto bad_ram;
+print_err("12\n");
+
+ /* write row 11 wrap adr */
+ ROW11_ADR=ROW11_DATA;
+ if(ROW11_ADR!=ROW11_DATA)
+ goto bad_ram;
+print_err("11\n");
+
+ /* write row 10 wrap adr */
+ ROW10_ADR=ROW10_DATA;
+ if(ROW10_ADR!=ROW10_DATA)
+ goto bad_ram;
+print_err("10\n");
+
+/*
+ * read data @ row 12 wrap adr to determine # banks,
+ * and read data @ row 14 wrap adr to determine # rows.
+ * if data @ row 12 wrap adr is not AA, 11 or 12 we have bad RAM.
+ * if data @ row 12 wrap == AA, we only have 2 banks, NOT 4
+ * if data @ row 12 wrap == 11 or 12, we have 4 banks
+ */
+
+ banks=2;
+ if (ROW12_ADR != ROW10_DATA) {
+ banks=4;
+print_err("4b\n");
+ if(ROW12_ADR != ROW11_DATA) {
+ if(ROW12_ADR != ROW12_DATA)
+ goto bad_ram;
+ }
+ }
+
+ /* validate row mask */
+ rows=ROW14_ADR;
+ if (rows<ROW11_DATA)
+ goto bad_ram;
+ 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;
+ if(cols<COL08_DATA)
+ goto bad_ram;
+ 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;
+
+ /* cols now is in the range of 0 1 2 3 ...
+ */
+ i = cols&3;
+ // i = cols + rows;
+
+ /* wacky end addr calculation */
+/*
+ al = 3;
+ 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 */
+ /* need to get end addr. Need to do it with the bank in mind. */
+ al = 3;
+ al -= i&3;
+ ending_adr = rows >> al;
+ print_err("computed ending_adr = "); print_err_hex8(ending_adr);
+ print_err("\r\n");
+
+bad_reinit:
+ /* issue all banks recharge */
+ ram->drcctl=0x02;
+ dummy_write();
+
+ /* update ending address register */
+ ram->drcbendadr[bank] = ending_adr;
+
+ /* update config register */
+ ram->drccfg &= ~(0xff << bank*4);
+ if (ending_adr)
+ ram->drccfg = ((banks = 4 ? 8 : 0) | cols & 3)<< (bank*4);
+ dumpram();
+ /* skip the rest for now */
+ // bank = 0;
+ // *drccfg=*drccfg&YYY|ZZZZ;
+
+ if(bank!=0) {
+ bank--;
+ ram->drcbendaddr[bank] = 0xff000000;
+ //*(&*drcbendadr+XXYYXX)=0xff;
+ goto start;
+ }
+
+ /* set control register to NORMAL mode */
+ ram->drcctl=0x18;
+ dummy_write();
+ return bank;
+
+bad_ram:
+ print_info("bad ram!\r\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;
nextbank(3);
+ while(1)
+ print_err("DONE NEXTBANK\r\n");
}
+
+/* note: based on AMD code, but AMD code is BROKEN AFAIK */
+
+int
+staticmem(void){
+ volatile unsigned char *zero = (unsigned char *) 0;
+ /* set up 0x18 .. **/
+ *drcbendadr = 0x88;
+ *drctmctl = 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_err("one zero out on refresh\r\n");
+ *zero = 0;
+ print_err("two zero out on refresh\r\n");
+
+ /* load mode register */
+ *drcctl = 3;
+ *zero = 0;
+ print_err("DONE the load mode reg\r\n");
+
+ /* normal mode */
+ *drcctl = 0x18;
+ *zero = 0;
+ print_err("DONE the normal\r\n");
+}