printk_foo -> printk(BIOS_FOO, ...)
[coreboot.git] / src / northbridge / intel / i440lx / raminit.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2007-2008 Uwe Hermann <uwe@hermann-uwe.de>
5  * Copyright (C) 2009 Maciej Pijanka <maciej.pijanka@gmail.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
20  */
21
22 #include <spd.h>
23 #include <sdram_mode.h>
24 #include <delay.h>
25 #include <stdlib.h>
26 #include "i440lx.h"
27
28 /*-----------------------------------------------------------------------------
29 Macros and definitions.
30 -----------------------------------------------------------------------------*/
31
32 /* Uncomment this to enable debugging output. */
33
34 /* Debugging macros. */
35 #if defined(DEBUG_RAM_SETUP)
36 #define PRINT_DEBUG(x)          print_debug(x)
37 #define PRINT_DEBUG_HEX8(x)     print_debug_hex8(x)
38 #define PRINT_DEBUG_HEX16(x)    print_debug_hex16(x)
39 #define PRINT_DEBUG_HEX32(x)    print_debug_hex32(x)
40 #define DUMPNORTH()             dump_pci_device(PCI_DEV(0, 0, 0))
41 #else
42 #define PRINT_DEBUG(x)
43 #define PRINT_DEBUG_HEX8(x)
44 #define PRINT_DEBUG_HEX16(x)
45 #define PRINT_DEBUG_HEX32(x)
46 #define DUMPNORTH()
47 #endif
48
49 #define NB PCI_DEV(0, 0, 0)
50
51 /* DRAMXC[7:5] - DRAM extended control register (SMS). */
52 #define RAM_COMMAND_NORMAL      0x0
53 #define RAM_COMMAND_NOP         0x1 // (NOPCE)
54 #define RAM_COMMAND_PRECHARGE   0x2 // ABPCE
55 #define RAM_COMMAND_MRS         0x3 // MRSCE
56 #define RAM_COMMAND_CBR         0x4 // CBRC
57 // rest are reserved
58
59 /* Table format: register, bitmask, value. */
60 static const long register_values[] = {
61         // ~0x02 == bit 9
62         //  0x04 == bit 10
63         // BASE is 0x8A but we dont want bit 9 or 10 have ENABLED so 0x8C
64         PACCFG + 1, 0x38, 0x8c,
65         
66         DBC, 0x00, 0xC3,
67
68         DRT,   0x00, 0xFF,
69         DRT+1, 0x00, 0xFF,
70
71         DRAMC, 0x00, 0x00, /* disable refresh for now. */
72         DRAMT, 0x00, 0x00, 
73
74         PAM0, 0x00, 0x30, // everything is a mem
75         PAM1, 0x00, 0x33,
76         PAM2, 0x00, 0x33,
77         PAM3, 0x00, 0x33,
78         PAM4, 0x00, 0x33,
79         PAM5, 0x00, 0x33,
80         PAM6, 0x00, 0x33,
81
82         /* Set the DRBs to zero for now, this will be fixed later. */
83         DRB0, 0x00, 0x00,
84         DRB1, 0x00, 0x00,
85         DRB2, 0x00, 0x00,
86         DRB3, 0x00, 0x00,
87         DRB4, 0x00, 0x00,
88         DRB5, 0x00, 0x00,
89         DRB6, 0x00, 0x00,
90         DRB7, 0x00, 0x00,
91
92         /* No memory holes. */
93         FDHC, 0x00, 0x00,
94 };
95
96 /*-----------------------------------------------------------------------------
97 SDRAM configuration functions.
98 -----------------------------------------------------------------------------*/
99
100 /**
101  * Send the specified RAM command to all DIMMs.
102  *
103  * @param command The RAM command to send to the DIMM(s).
104  */
105 static void do_ram_command(u32 command)
106 {
107         int i, caslatency;
108         u8 dimm_start, dimm_end;
109         u16 reg16;
110         u32 addr, addr_offset;
111
112         /* Configure the RAM command. */
113         reg16 = pci_read_config16(NB, DRAMXC); 
114         reg16 &= 0xff1f;                /* Clear bits 7-5. */
115         reg16 |= (u16) (command << 5);  /* Write command into bits 7-5. */
116         pci_write_config16(NB, DRAMXC, reg16);
117
118         /*
119          * RAM_COMMAND_NORMAL affects only the memory controller and
120          * doesn't need to be "sent" to the DIMMs.
121          */
122         if (command == RAM_COMMAND_NORMAL)
123                 return;
124
125         /* Send the RAM command to each row of memory. */
126         dimm_start = 0;
127         for (i = 0; i < (DIMM_SOCKETS * 2); i++) {
128                 addr_offset = 0;
129                 caslatency = 3; /* TODO: Dynamically get CAS latency later. */
130
131                 /* before translation it is 
132                  *
133                  * M[02:00] Burst Length
134                  * M[03:03] Burst Type
135                  * M[06:04] Cas Latency
136                  *          000 - Reserved
137                  *          001 - Reserved
138                  *          010 - CAS 2
139                  *          011 - CAS 3
140                  *          100 - Reserved
141                  *          101 - Reserved
142                  *          110 - Reserved
143                  *          111 - Reserved
144                  * M[08:07] Op Mode
145                  *          Must Be 00b (Defined mode)
146                  * M[09:09] Write Burst Mode
147                  *          0 - Programmed burst length
148                  *          1 - Single location access
149                  * M[11:10] Reserved
150                  *          write 0 to ensure compatibility with....
151                  */
152
153                 /* seems constructed value will be right shifted by 3 bit, thus constructed value
154                  * must be left shifted by 3
155                  * so possible formula is (caslatency <<4)|(burst_type << 1)|(burst length)
156                  * then << 3 shift to compensate shift in Memory Controller
157                  */ 
158                 if (command == RAM_COMMAND_MRS) {
159                         if (caslatency == 3)
160                                 addr_offset = 0x1d0;
161                         if (caslatency == 2)
162                                 addr_offset = 0x150;
163                 }
164
165                 dimm_end = pci_read_config8(NB, DRB + i);
166
167                 addr = (dimm_start * 8 * 1024 * 1024) + addr_offset;
168                 if (dimm_end > dimm_start) {
169 #if 0
170                         PRINT_DEBUG("    Sending RAM command 0x");
171                         PRINT_DEBUG_HEX16(reg16);
172                         PRINT_DEBUG(" to 0x");
173                         PRINT_DEBUG_HEX32(addr);
174                         PRINT_DEBUG("\r\n");
175 #endif
176
177                         read32(addr);
178                 }
179
180                 /* Set the start of the next DIMM. */
181                 dimm_start = dimm_end;
182         }
183 }
184
185 /*-----------------------------------------------------------------------------
186 DIMM-independant configuration functions.
187 -----------------------------------------------------------------------------*/
188
189 static void spd_enable_refresh(void)
190 {
191         uint8_t reg;
192
193         reg = pci_read_config8(NB, DRAMC);
194
195         /* this chipset offer only two choices regarding refresh
196          * refresh disabled, or refresh normal
197          */
198         
199         pci_write_config8(NB, DRAMC, reg | 0x01);
200         reg = pci_read_config8(NB, DRAMC);
201
202         PRINT_DEBUG("spd_enable_refresh: dramc = 0x");
203         PRINT_DEBUG_HEX8(reg);
204         PRINT_DEBUG("\r\n");
205 }
206
207 /*-----------------------------------------------------------------------------
208 Public interface.
209 -----------------------------------------------------------------------------*/
210
211 static void northbridge_init(void)
212 {
213         uint32_t reg32;
214
215         reg32 = pci_read_config32(NB, APBASE);
216         reg32 &= 0xe8000000U;
217         pci_write_config32(NB, APBASE, reg32);
218
219         #ifdef DEBUG_RAM_SETUP
220         /* 
221          * apbase dont get set still, no idea what i have doing wrong yet, 
222          * i am almost sure that somehow i set it by mistake once, but can't
223          * repeat that. 
224          */
225         reg32 = pci_read_config32(NB, APBASE);
226         PRINT_DEBUG("APBASE ");
227         PRINT_DEBUG_HEX32(reg32);
228         PRINT_DEBUG("\r\n");
229         #endif
230 }
231
232
233 /**
234  * This routine sets RAM controller inside northbridge to known state
235  *
236  */
237 static void sdram_set_registers(void)
238 {
239         int i, max;
240
241         /* nice banner with FSB shown? do we have
242          * any standart policy about such things? 
243          */
244 #if 0
245         uint16_t reg16;
246         reg16 = pci_read_config16(NB, PACCFG); 
247         printk(BIOS_DEBUG, "i82443LX Host Freq: 6%C MHz\r\n", (reg16 & 0x4000) ? '0' : '6');
248 #endif
249
250         PRINT_DEBUG("Northbridge prior to SDRAM init:\r\n");
251         DUMPNORTH();
252
253         northbridge_init();
254
255         max = ARRAY_SIZE(register_values);
256
257         /* Set registers as specified in the register_values[] array. */
258         for (i = 0; i < max; i += 3) {
259                 uint8_t reg,tmp;
260                 reg = pci_read_config8(NB, register_values[i]);
261                 reg &= register_values[i + 1];
262                 reg |= register_values[i + 2] & ~(register_values[i + 1]);
263                 pci_write_config8(NB, register_values[i], reg);
264
265                 /* 
266                  * i am not sure if that is needed, but was usefull 
267                  * for me to confirm what got written
268                  */
269 #ifdef DEBUG_RAM_SETUP
270                 PRINT_DEBUG("    Set register 0x");
271                 PRINT_DEBUG_HEX8(register_values[i]);
272                 PRINT_DEBUG(" to 0x");
273                 PRINT_DEBUG_HEX8(reg);
274                 tmp = pci_read_config8(NB, register_values[i]);
275                 PRINT_DEBUG(" readed 0x");
276                 PRINT_DEBUG_HEX8(tmp);
277                 if (tmp == reg) {
278                         PRINT_DEBUG(" OK ");
279                 } else {
280                         PRINT_DEBUG(" FAIL ");
281                 }
282                 PRINT_DEBUG("\r\n");
283 #endif
284         }
285
286         PRINT_DEBUG("Northbridge atexit sdram set registers\r\n");      
287         DUMPNORTH();
288 }
289
290
291 static void sdram_set_spd_registers(void)
292 {
293         int i;
294         u16 memsize = 0;
295
296         for (i = 0; i < DIMM_SOCKETS; i++) {
297                 uint16_t ds = 0; // dimm size 
298                 int j;
299                 /* this code skips second bank on each socket (no idea how to fix it now) 
300                  */
301
302                 PRINT_DEBUG("DIMM");
303                 PRINT_DEBUG_HEX8(i);
304                 PRINT_DEBUG(" rows: ");
305                 PRINT_DEBUG_HEX8(spd_read_byte(DIMM_SPD_BASE + i, SPD_NUM_DIMM_BANKS) & 0xFF);
306                 PRINT_DEBUG(" rowsize: ");
307                 PRINT_DEBUG_HEX8(spd_read_byte(DIMM_SPD_BASE + i, SPD_DENSITY_OF_EACH_ROW_ON_MODULE) & 0xFF);
308                 PRINT_DEBUG(" modulesize: ");
309
310                 j = spd_read_byte(DIMM_SPD_BASE + i, SPD_NUM_DIMM_BANKS);
311                 if (j < 0)
312                         j = 0;
313                 else
314                         ds = j;
315
316                 j = spd_read_byte(DIMM_SPD_BASE + i, SPD_DENSITY_OF_EACH_ROW_ON_MODULE);
317
318                 if (j < 0)
319                         j = 0;
320                 else
321                         ds = ds * (j >> 1); // convert from 4MB to 8MB units in place
322
323
324                 /* This is more or less crude hack
325                  * allowing to run this target under qemu (even if that is not really 
326                  * same hardware emulated), 
327                  * probably some kconfig expert option should be added to enable/disable
328                  * this nicelly
329                  */
330 #if 0
331                 if (ds == 0 && memsize == 0)
332                         ds = 0x8;
333 #endif
334
335
336                 // todo: support for bank with not equal sizes as per jedec standart?
337                 
338                 /*
339                  * because density is reported in units of 4Mbyte
340                  * and rows in device are just value, 
341                  * and for setting registers we need value in 8Mbyte units
342                  */
343
344                 PRINT_DEBUG_HEX16(ds);
345                 PRINT_DEBUG("\r\n");
346
347                 memsize += ds;
348
349                 pci_write_config8(NB, DRB + (2*i), memsize);
350                 pci_write_config8(NB, DRB + (2*i) + 1, memsize);
351                 if (ds > 0) {
352                         /* i have no idea why pci_read_config16 not work for 
353                          * me correctly here
354                          */
355                         ds = pci_read_config8(NB, DRT+1);
356                         ds <<=8;
357                         ds |= pci_read_config8(NB, DRT);
358
359                         PRINT_DEBUG("DRT ");
360                         PRINT_DEBUG_HEX16(ds);
361
362                         ds &= ~(0x01 << (4 * i));
363
364                         PRINT_DEBUG(" ");
365                         PRINT_DEBUG_HEX16(ds);
366                         PRINT_DEBUG("\r\n");
367
368                         /* 
369                          * modify DRT register if current row isn't empty
370                          * code assume its SDRAM plugged (should check if its sdram or EDO, 
371                          * edo would have 0x00 as constand instead 0x10 for SDRAM
372                          * also this code is buggy because ignores second row of each dimm socket
373                          */
374
375                         /* and as above write_config16 not work here too)
376                          * pci_write_config16(NB, DRT, j);
377                          */
378
379                         pci_write_config8(NB, DRT+1, ds >> 8);
380                         pci_write_config8(NB, DRT, ds & 0xFF);
381                 }
382         }
383
384 #if 0
385         PRINT_DEBUG("Mem: 0x");
386         PRINT_DEBUG_HEX16(memsize * 8);
387         PRINT_DEBUG(" MB\r\n");
388
389         if (memsize == 0) {
390                 /* maybe we should use some nice die/hlt sequence with printing on console
391                  * that no memory found, get lost, i can't run?
392                  * maybe such event_handler can be commonly defined routine to decrease
393                  * code duplication?
394                  */
395                 PRINT_DEBUG("No memory detected via SPD\r\n");
396                 PRINT_DEBUG("Reverting to hardcoded 64M single side dimm in first bank\r\n");
397         }
398 #endif
399
400         /* Set DRAMC. Don't enable refresh for now. */
401         pci_write_config8(NB, DRAMC, 0x00);
402
403         /* Cas latency 3, and other shouldbe properly from spd too */
404         pci_write_config8(NB, DRAMT, 0xAC); 
405
406         /* TODO? */
407         pci_write_config8(NB, PCI_LATENCY_TIMER, 0x40);
408
409         // set drive strength
410         pci_write_config32(NB, MBSC, 0x00000000);
411 }
412
413 static void sdram_enable(void)
414 {
415         int i;
416
417         /* 0. Wait until power/voltages and clocks are stable (200us). */
418         udelay(200);
419
420         /* 1. Apply NOP. Wait 200 clock cycles (clock might be 60 or 66 Mhz). */
421         PRINT_DEBUG("RAM Enable 1: Apply NOP\r\n");
422         do_ram_command(RAM_COMMAND_NOP);
423         udelay(200);
424
425         /* 2. Precharge all. Wait tRP. */
426         PRINT_DEBUG("RAM Enable 2: Precharge all\r\n");
427         do_ram_command(RAM_COMMAND_PRECHARGE);
428         udelay(1);
429
430         /* 3. Perform 8 refresh cycles. Wait tRC each time. */
431         PRINT_DEBUG("RAM Enable 3: CBR\r\n");
432         for (i = 0; i < 8; i++) {
433                 do_ram_command(RAM_COMMAND_CBR);
434                 udelay(1);
435         }
436
437         /* 4. Mode register set. Wait two memory cycles. */
438         PRINT_DEBUG("RAM Enable 4: Mode register set\r\n");
439         do_ram_command(RAM_COMMAND_MRS);
440         udelay(2);
441
442         /* 5. Normal operation. */
443         PRINT_DEBUG("RAM Enable 5: Normal operation\r\n");
444         do_ram_command(RAM_COMMAND_NORMAL);
445         udelay(1);
446
447         /* 6. Finally enable refresh. */
448         PRINT_DEBUG("RAM Enable 6: Enable refresh\r\n");
449         pci_write_config8(NB, DRAMC, 0x01);
450         spd_enable_refresh();
451         udelay(1);
452
453         PRINT_DEBUG("Northbridge following SDRAM init:\r\n");
454 }
455