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