Revision: linuxbios@linuxbios.org--devel/freebios--devel--2.0--patch-45
[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 #define OUTC(addr, val) *(unsigned char *)(addr) = (val)
49
50
51 void
52 setupsc520(void){
53         unsigned char *cp;
54         unsigned short *sp;
55         unsigned long *edi;
56         unsigned long *par;
57
58         /* turn off the write buffer*/
59         cp = (unsigned char *)0xfffef040;
60         *cp = 0;
61
62         /*set the GP CS offset*/
63         sp =  (unsigned short *)0xfffefc08;
64         *sp = 0x00001;
65         /*set the GP CS width*/
66         sp =  (unsigned short *)0xfffefc09;
67         *sp = 0x00003;
68         /*set the GP CS width*/
69         sp =  (unsigned short *)0xfffefc0a;
70         *sp = 0x00001;
71         /*set the RD pulse width*/
72         sp =  (unsigned short *)0xfffefc0b;
73         *sp = 0x00003;
74         /*set the GP RD offse*/
75         sp =  (unsigned short *)0xfffefc0c;
76         *sp = 0x00001;
77         /*set the GP WR pulse width*/
78         sp =  (unsigned short *)0xfffefc0d;
79         *sp = 0x00003;
80         /*set the GP WR offset*/
81         sp =  (unsigned short *)0xfffefc0e;
82         *sp = 0x00001;
83         /* set up the GP IO pins*/
84         /*set the GPIO directionreg*/
85         sp =  (unsigned short *)0xfffefc2c;
86         *sp = 0x00000;
87         /*set the GPIO directionreg*/
88         sp =  (unsigned short *)0xfffefc2a;
89         *sp = 0x00000;
90         /*set the GPIO pin function 31-16 reg*/
91         sp =  (unsigned short *)0xfffefc22;
92         *sp = 0x0FFFF;
93         /*set the GPIO pin function 15-0 reg*/
94         sp =  (unsigned short *)0xfffefc20;
95         *sp = 0x0FFFF;
96
97 #ifdef NETSC520
98 if NetSC520
99 ; set the PIO regs correctly.
100         /*set the GPIO16-31 direction reg*/
101         sp =  (unsigned short *)0xfffefc2c;
102         *sp = 0x000ff;
103         /*set the PIODIR15_0 direction reg*/
104         sp =  (unsigned short *)0xfffefc2a;
105         *sp = 0x00440;
106         /*set the PIOPFS31_16 direction reg*/
107         sp =  (unsigned short *)0xfffefc22;
108         *sp = 0x00600;
109         /*set the PIOPFS15_0 direction reg*/
110         sp =  (unsigned short *)0xfffefc20;
111         *sp = 0x0FBBF;
112         /*set the PIODATA15_0 reg*/
113         sp =  (unsigned short *)0x0xfffefc30;
114         *sp = 0x0f000;
115         /*set the CSPFS reg*/
116         sp =  (unsigned short *)0xfffefc24;
117         *sp = 0x0000;
118
119 ; The NetSC520 uses PIOs 16-23 for LEDs instead of port 80
120 ; output a 1 to the leds
121         /*set the GPIO16-31 direction reg*/
122         sp =  (unsigned short *)0xfffefc32;
123         mov     al, not 1
124 else
125 #endif
126
127         /* setup for the CDP*/
128         /*set the GPIO directionreg*/
129         sp =  (unsigned short *)0xfffefc2c;
130         *sp = 0x00000;
131         /*set the GPIO directionreg*/
132         sp =  (unsigned short *)0xfffefc2a;
133         *sp = 0x00000;
134         /*set the GPIO pin function 31-16 reg*/
135         sp =  (unsigned short *)0xfffefc22;
136         *sp = 0x0FFFF;
137         /*set the GPIO pin function 15-0 reg*/
138         sp =  (unsigned short *)0xfffefc20;
139         *sp = 0x0FFFF;
140         /* the 0x80 led should now be working*/
141         outb(0xaa, 0x80);
142 /*
143 ; set up a PAR to allow access to the 680 leds
144 ;       WriteMMCR( 0xc4,0x28000680);            // PAR15
145  */
146         /*set PAR 15 for access to led 680*/
147 /* skip hairy pci hack for now *
148         sp =  (unsigned short *)0xfffef0c4;
149         mov     eax,028000680h
150         mov     dx,0680h
151         *sp = 0x02;     ; output a 2 to led 680
152         out     dx,ax
153 */
154 /*; set the uart baud rate clocks to the normal 1.8432 MHz.*/
155         cp = (unsigned char *)0xfffefcc0;
156         *cp = 4;                                        /* uart 1 clock source */
157         cp = (unsigned char *)0xfffefcc4;
158         *cp = 4;                                        /* uart 2 clock source */
159 /*; set the interrupt mapping registers.*/
160         cp = (unsigned char *)0x0fffefd20;
161         *cp = 0x01;
162         
163         cp = (unsigned char *)0x0fffefd28;
164         *cp = 0x0c;
165         
166         cp = (unsigned char *)0x0fffefd29;
167         *cp = 0x0b;
168         
169         cp = (unsigned char *)0x0fffefd30;
170         *cp = 0x07;
171         
172         cp = (unsigned char *)0x0fffefd43;
173         *cp = 0x03;
174         
175         cp = (unsigned char *)0x0fffefd51;
176         *cp = 0x02;
177         
178 /*; "enumerate" the PCI. Mainly set the interrupt bits on the PCnetFast. */
179         outl(0xcf8, 0x08000683c);
180         outl(0xcfc, 0xc); /* set the interrupt line */
181
182 /*; Set the SC520 PCI host bridge to target mode to allow external*/
183 /*; bus mastering events*/
184
185         outl(0x0cf8,0x080000004);       /*index the status command register on device 0*/
186         outl(0xcfc, 0x2);                       /*set the memory access enable bit*/
187         OUTC(0x0fffef072, 1);           /* enable req bits in SYSARBMENB */
188
189
190
191         /* set up the PAR registers as they are on the MSM586SEG */
192         par = (unsigned long *) 0xfffef080;
193         *par++ = 0x607c00a0; /*PAR0: PCI:Base 0xa0000; size 0x1f000:*/
194         *par++ = 0x480400d8; /*PAR1: GP BUS MEM:CS2:Base 0xd8, size 0x4:*/
195         *par++ = 0x340100ea; /*PAR2: GP BUS IO:CS5:Base 0xea, size 0x1:*/
196         *par++ = 0x380701f0; /*PAR3: GP BUS IO:CS6:Base 0x1f0, size 0x7:*/
197         *par++ = 0x3c0003f6; /*PAR4: GP BUS IO:CS7:Base 0x3f6, size 0x0:*/
198         *par++ = 0x35ff0400; /*PAR5: GP BUS IO:CS5:Base 0x400, size 0xff:*/
199         *par++ = 0x35ff0600; /*PAR6: GP BUS IO:CS5:Base 0x600, size 0xff:*/
200         *par++ = 0x35ff0800; /*PAR7: GP BUS IO:CS5:Base 0x800, size 0xff:*/
201         *par++ = 0x35ff0a00; /*PAR8: GP BUS IO:CS5:Base 0xa00, size 0xff:*/
202         *par++ = 0x35ff0e00; /*PAR9: GP BUS IO:CS5:Base 0xe00, size 0xff:*/
203         *par++ = 0x34fb0104; /*PAR10: GP BUS IO:CS5:Base 0x104, size 0xfb:*/
204         *par++ = 0x35af0200; /*PAR11: GP BUS IO:CS5:Base 0x200, size 0xaf:*/
205         *par++ = 0x341f03e0; /*PAR12: GP BUS IO:CS5:Base 0x3e0, size 0x1f:*/
206         *par++ = 0xe41c00c0; /*PAR13: SDRAM:code:cache:nowrite:Base 0xc0000, size 0x7000:*/
207         *par++ = 0x545c00c8; /*PAR14: GP BUS MEM:CS5:Base 0xc8, size 0x5c:*/
208         *par++ = 0x8a020200; /*PAR15: BOOTCS:code:nocache:write:Base 0x2000000, size 0x80000:*/
209
210
211 }
212         
213
214 /*
215  *
216  *
217  */
218
219 #define DRCCTL        *(char*)0x0fffef010  /* DRAM control register*/
220 #define DRCTMCTL      *(char*)0x0fffef012  /* DRAM timing control register*/
221 #define DRCCFG        *(char*)0x0fffef014  /* DRAM bank configuration register*/
222 #define DRCBENDADR    *(char*)0x0fffef018  /* DRAM bank ending address register*/
223 #define ECCCTL        *(char*)0x0fffef020  /* DRAM ECC control register*/
224 #define DBCTL         *(char*)0x0fffef040  /* DRAM buffer control register*/
225
226 #define CACHELINESZ   0x00000010  /*  size of our cache line (read buffer)*/
227
228 #define COL11_ADR  *(unsigned int *)0x0e001e00 /* 11 col addrs*/
229 #define COL10_ADR  *(unsigned int *)0x0e000e00 /* 10 col addrs*/
230 #define COL09_ADR  *(unsigned int *)0x0e000600 /*  9 col addrs*/
231 #define COL08_ADR  *(unsigned int *)0x0e000200 /*  8 col addrs*/
232
233 #define ROW14_ADR  *(unsigned int *)0x0f000000 /* 14 row addrs*/
234 #define ROW13_ADR  *(unsigned int *)0x07000000 /* 13 row addrs*/
235 #define ROW12_ADR  *(unsigned int *)0x03000000 /* 12 row addrs*/
236 #define ROW11_ADR  *(unsigned int *)0x01000000 /* 11 row addrs/also bank switch*/
237 #define ROW10_ADR  *(unsigned int *)0x00000000 /* 10 row addrs/also bank switch*/
238
239 #define COL11_DATA 0x0b0b0b0b   /*  11 col addrs*/
240 #define COL10_DATA 0x0a0a0a0a   /*  10 col data*/
241 #define COL09_DATA 0x09090909   /*   9 col data*/
242 #define COL08_DATA 0x08080808   /*   8 col data*/
243 #define ROW14_DATA 0x3f3f3f3f   /*  14 row data (MASK)*/
244 #define ROW13_DATA 0x1f1f1f1f   /*  13 row data (MASK)*/
245 #define ROW12_DATA 0x0f0f0f0f   /*  12 row data (MASK)*/
246 #define ROW11_DATA 0x07070707   /*  11 row data/also bank switch (MASK)*/
247 #define ROW10_DATA 0xaaaaaaaa   /*  10 row data/also bank switch (MASK)*/
248
249 #define dummy_write()   *(short *)CACHELINESZ=0x1010
250
251 void udelay(int microseconds) {
252         volatile int x;
253         for(x = 0; x < 1000; x++)
254                 ;
255 }
256
257 int nextbank(int bank)
258 {
259         int rows,banks, i, ending_adr;
260         
261 start:
262         /* write col 11 wrap adr */
263         COL11_ADR=COL11_DATA;
264         if(COL11_ADR!=COL11_DATA)
265                 goto bad_ram;
266
267         /* write col 10 wrap adr */
268         COL10_ADR=COL10_DATA;
269         if(COL10_ADR!=COL10_DATA)
270                 goto bad_ram;
271
272         /* write col 9 wrap adr */
273         COL09_ADR=COL09_DATA;
274         if(COL09_ADR!=COL09_DATA)
275                 goto bad_ram;
276
277         /* write col 8 wrap adr */
278         COL08_ADR=COL08_DATA;
279         if(COL08_ADR!=COL08_DATA)
280                 goto bad_ram;
281
282         /* write row 14 wrap adr */
283         ROW14_ADR=ROW14_DATA;
284         if(ROW14_ADR!=ROW14_DATA)
285                 goto bad_ram;
286
287         /* write row 13 wrap adr */
288         ROW13_ADR=ROW13_DATA;
289         if(ROW13_ADR!=ROW13_DATA)
290                 goto bad_ram;
291
292         /* write row 12 wrap adr */
293         ROW12_ADR=ROW12_DATA;
294         if(ROW12_ADR!=ROW12_DATA)
295                 goto bad_ram;
296
297         /* write row 11 wrap adr */
298         ROW11_ADR=ROW11_DATA;
299         if(ROW11_ADR!=ROW11_DATA)
300                 goto bad_ram;
301
302         /* write row 10 wrap adr */
303         ROW10_ADR=ROW10_DATA;
304         if(ROW10_ADR!=ROW10_DATA)
305                 goto bad_ram;
306
307 /*
308  * read data @ row 12 wrap adr to determine # banks,
309  *  and read data @ row 14 wrap adr to determine # rows.
310  *  if data @ row 12 wrap adr is not AA, 11 or 12 we have bad RAM.
311  * if data @ row 12 wrap == AA, we only have 2 banks, NOT 4
312  * if data @ row 12 wrap == 11 or 12, we have 4 banks
313  */
314
315         banks=2;
316         if (ROW12_ADR != ROW10_DATA) {
317                 banks=4;
318                 if(ROW12_ADR != ROW11_DATA) {
319                         if(ROW12_ADR != ROW12_DATA)
320                                 goto bad_ram;
321                 }
322         }
323
324         /* validate row mask */
325         i=ROW14_ADR;
326         if (i<ROW11_DATA)
327                 goto bad_ram;
328         if (i>ROW14_DATA)
329                 goto bad_ram;
330         /* verify all 4 bytes of dword same */
331         if(i&0xffff!=(i>>16)&0xffff)
332                 goto bad_ram;
333         if(i&0xff!=(i>>8)&0xff)
334                 goto bad_ram;
335         
336         
337         /* validate column data */
338         i=COL11_ADR;
339         if(i<COL08_DATA)
340                 goto bad_ram;
341         if (i>COL11_DATA)
342                 goto bad_ram;
343         /* verify all 4 bytes of dword same */
344         if(i&0xffff!=(i>>16)&0xffff)
345                 goto bad_ram;
346         if(i&0xff!=(i>>8)&0xff)
347                 goto bad_ram;
348         
349         if(banks==4)
350                 i+=8; /* <-- i holds merged value */
351         
352         /* fix ending addr mask*/
353         /*FIXME*/
354         ending_adr=0xff;
355
356 bad_reint:
357         /* issue all banks recharge */
358         DRCCTL=0x02;
359         dummy_write();
360
361         /* update ending address register */
362 #warning FIX ME NOW I AM BUSTED
363 //      *(DRCBENDADR+0)=ending_adr;
364         
365         /* update config register */
366 //      DRCCFG=DRCCFG&YYY|ZZZZ;
367
368         if(bank!=0) {
369                 bank--;
370                 //*(&DRCBENDADR+XXYYXX)=0xff;
371                 goto start;
372         }
373
374         /* set control register to NORMAL mode */
375         DRCCTL=0x00;
376         dummy_write();
377         return bank;
378         
379 bad_ram:
380         print_info("bad ram!\r\n");
381 }
382
383 /* cache is assumed to be disabled */
384 int sizemem(void)
385 {
386         int i;
387         /* initialize dram controller registers */
388
389         DBCTL=0; /* disable write buffer/read-ahead buffer */
390         ECCCTL=0; /* disable ECC */
391         DRCTMCTL=0x1e; /* Set SDRAM timing for slowest speed. */
392
393         /* setup loop to do 4 external banks starting with bank 3 */
394
395         /* enable last bank and setup ending address 
396          * register for max ram in last bank
397          */
398         DRCBENDADR=0x0ff000000;
399         /* setup dram register for all banks
400          * with max cols and max banks
401          */
402         DRCCFG=0xbbbb;
403
404         /* issue a NOP to all DRAMs */
405
406         /* Asetup DRAM control register with Disable refresh,
407          * disable write buffer Test Mode and NOP command select
408          */
409         DRCCTL=0x01;
410
411         /* dummy write for NOP to take effect */
412         dummy_write();
413
414         /* 100? 200? */
415         udelay(100);
416
417         /* issue all banks precharge */
418         DRCCTL=0x02;
419         dummy_write();
420
421         /* issue 2 auto refreshes to all banks */
422         DRCCTL=0x04;
423         dummy_write();
424         dummy_write();
425
426         /* issue LOAD MODE REGISTER command */
427         DRCCTL=0x03;
428         dummy_write();
429
430         DRCCTL=0x04;
431         for (i=0; i<8; i++) /* refresh 8 times */
432                 dummy_write();
433
434         /* set control register to NORMAL mode */
435         DRCCTL=0x00;
436
437         nextbank(3);
438
439 }