f97eaa893d4936636860202b4728cdce20889959
[coreboot.git] / src / northbridge / intel / i82830 / raminit.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2008-2010 Joseph Smith <joe@settoplinux.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  *
20  */
21
22 #include <spd.h>
23 #include <sdram_mode.h>
24 #include <delay.h>
25 #include "lib/debug.c"
26 #include "i82830.h"
27
28 /*-----------------------------------------------------------------------------
29 Macros and definitions.
30 -----------------------------------------------------------------------------*/
31
32 /* Debugging macros. */
33 #if CONFIG_DEBUG_RAM_SETUP
34 #define PRINT_DEBUG(x)          print_debug(x)
35 #define PRINT_DEBUG_HEX8(x)     print_debug_hex8(x)
36 #define PRINT_DEBUG_HEX16(x)    print_debug_hex16(x)
37 #define PRINT_DEBUG_HEX32(x)    print_debug_hex32(x)
38 #define DUMPNORTH()             dump_pci_device(PCI_DEV(0, 0, 0))
39 #else
40 #define PRINT_DEBUG(x)
41 #define PRINT_DEBUG_HEX8(x)
42 #define PRINT_DEBUG_HEX16(x)
43 #define PRINT_DEBUG_HEX32(x)
44 #define DUMPNORTH()
45 #endif
46
47 /* DRC[10:8] - Refresh Mode Select (RMS).
48  * 0x0 for Refresh Disabled (Self Refresh)
49  * 0x1 for Refresh interval 15.6 us for 133MHz
50  * 0x2 for Refresh interval 7.8 us for 133MHz
51  * 0x7 for Refresh interval 128 Clocks. (Fast Refresh Mode)
52  */
53 #define RAM_COMMAND_REFRESH             0x1
54
55 /* DRC[6:4] - SDRAM Mode Select (SMS). */
56 #define RAM_COMMAND_SELF_REFRESH        0x0
57 #define RAM_COMMAND_NOP                 0x1
58 #define RAM_COMMAND_PRECHARGE           0x2
59 #define RAM_COMMAND_MRS                 0x3
60 #define RAM_COMMAND_CBR                 0x6
61 #define RAM_COMMAND_NORMAL              0x7
62
63 /* DRC[29] - Initialization Complete (IC). */
64 #define RAM_COMMAND_IC                  0x1
65
66 /*-----------------------------------------------------------------------------
67 DIMM-initialization functions.
68 -----------------------------------------------------------------------------*/
69
70 static void do_ram_command(u32 command)
71 {
72         u32 reg32;
73
74         /* Configure the RAM command. */
75         reg32 = pci_read_config32(NORTHBRIDGE, DRC);
76         /* Clear bits 29, 10-8, 6-4. */
77         reg32 &= 0xdffff88f;
78         reg32 |= command << 4;
79         pci_write_config32(NORTHBRIDGE, DRC, reg32);
80         PRINT_DEBUG("RAM command 0x");
81         PRINT_DEBUG_HEX32(reg32);
82         PRINT_DEBUG("\r\n");
83 }
84
85 static void ram_read32(u8 dimm_start, u32 offset)
86 {
87         if (offset == 0x55aa55aa) {
88                 PRINT_DEBUG("  Reading RAM at 0x");
89                 PRINT_DEBUG_HEX32(dimm_start * 32 * 1024 * 1024);
90                 PRINT_DEBUG(" => 0x");
91                 PRINT_DEBUG_HEX32(read32(dimm_start * 32 * 1024 * 1024));
92                 PRINT_DEBUG("\r\n");
93
94                 PRINT_DEBUG("  Writing RAM at 0x");
95                 PRINT_DEBUG_HEX32(dimm_start * 32 * 1024 * 1024);
96                 PRINT_DEBUG(" <= 0x");
97                 PRINT_DEBUG_HEX32(offset);
98                 PRINT_DEBUG("\r\n");
99                 write32(dimm_start * 32 * 1024 * 1024, offset);
100
101                 PRINT_DEBUG("  Reading RAM at 0x");
102                 PRINT_DEBUG_HEX32(dimm_start * 32 * 1024 * 1024);
103                 PRINT_DEBUG(" => 0x");
104                 PRINT_DEBUG_HEX32(read32(dimm_start * 32 * 1024 * 1024));
105                 PRINT_DEBUG("\r\n");
106         } else {
107                 PRINT_DEBUG("  Sending RAM command to 0x");
108                 PRINT_DEBUG_HEX32((dimm_start * 32 * 1024 * 1024) + offset);
109                 PRINT_DEBUG("\r\n");
110                 read32((dimm_start * 32 * 1024 * 1024) + offset);
111         }
112 }
113
114 static void initialize_dimm_rows(void)
115 {
116         int i, row;
117         u8 dimm_start, dimm_end;
118         unsigned device;
119
120         dimm_start = 0;
121
122         for (row = 0; row < (DIMM_SOCKETS * 2); row++) {
123
124                 switch (row) {
125                         case 0:
126                                 device = DIMM_SPD_BASE;
127                                 break;
128                         case 1:
129                                 device = DIMM_SPD_BASE;
130                                 break;
131                         case 2:
132                                 device = DIMM_SPD_BASE + 1;
133                                 break;
134                         case 3:
135                                 device = DIMM_SPD_BASE + 1;
136                                 break;
137                 }
138
139                 dimm_end = pci_read_config8(NORTHBRIDGE, DRB + row);
140
141                 if (dimm_end > dimm_start) {
142                         print_debug("Initializing SDRAM Row ");
143                         print_debug_hex8(row);
144                         print_debug("\r\n");
145
146                         /* NOP command */
147                         PRINT_DEBUG(" NOP ");
148                         do_ram_command(RAM_COMMAND_NOP);
149                         ram_read32(dimm_start, 0);
150                         udelay(200);
151
152                         /* Pre-charge all banks (at least 200 us after NOP) */
153                         PRINT_DEBUG(" Pre-charging all banks ");
154                         do_ram_command(RAM_COMMAND_PRECHARGE);
155                         ram_read32(dimm_start, 0);
156                         udelay(1);
157
158                         /* 8 CBR refreshes (Auto Refresh) */
159                         PRINT_DEBUG(" 8 CBR refreshes ");
160                         for (i = 0; i < 8; i++) {
161                                 do_ram_command(RAM_COMMAND_CBR);
162                                 ram_read32(dimm_start, 0);
163                                 udelay(1);
164                         }
165
166                         /* MRS command */
167                         /* TODO: Set offset 0x1d0 according to DRT values */
168                         PRINT_DEBUG(" MRS ");
169                         do_ram_command(RAM_COMMAND_MRS);
170                         ram_read32(dimm_start, 0x1d0);
171                         udelay(2);
172
173                         /* Set GMCH-M Mode Select bits back to NORMAL operation mode */
174                         PRINT_DEBUG(" Normal operation mode ");
175                         do_ram_command(RAM_COMMAND_NORMAL);
176                         ram_read32(dimm_start, 0);
177                         udelay(1);
178
179                         /* Perform a dummy memory read/write cycle */
180                         PRINT_DEBUG(" Performing dummy read/write\r\n");
181                         ram_read32(dimm_start, 0x55aa55aa);
182                         udelay(1);
183                 }
184                 /* Set the start of the next DIMM. */
185                 dimm_start = dimm_end;
186         }
187 }
188
189 /*-----------------------------------------------------------------------------
190 DIMM-independant configuration functions.
191 -----------------------------------------------------------------------------*/
192
193 struct dimm_size {
194         unsigned long side1;
195         unsigned long side2;
196 };
197
198 static struct dimm_size spd_get_dimm_size(unsigned device)
199 {
200         struct dimm_size sz;
201         int i, module_density, dimm_banks;
202         sz.side1 = 0;
203         module_density = spd_read_byte(device, SPD_DENSITY_OF_EACH_ROW_ON_MODULE);
204         dimm_banks = spd_read_byte(device, SPD_NUM_DIMM_BANKS);
205
206         /* Find the size of side1. */
207         /* Find the larger value. The larger value is always side1. */
208         for (i = 512; i >= 0; i >>= 1) {
209                 if ((module_density & i) == i) {
210                         sz.side1 = i;
211                         break;
212                 }
213         }
214
215         /* Set to 0 in case it's single sided. */
216         sz.side2 = 0;
217
218         /* Test if it's a dual-sided DIMM. */
219         if (dimm_banks > 1) {
220                 /* Test to see if there's a second value, if so it's asymmetrical. */
221                 if (module_density != i) {
222                         /* Find the second value, picking up where we left off. */
223                         /* i >>= 1 done initially to make sure we don't get the same value again. */
224                         for (i >>= 1; i >= 0; i >>= 1) {
225                                 if (module_density == (sz.side1 | i)) {
226                                         sz.side2 = i;
227                                         break;
228                                 }
229                         }
230                         /* If not, it's symmetrical */
231                 } else {
232                         sz.side2 = sz.side1;
233                 }
234         }
235
236         /* SPD byte 31 is the memory size divided by 4 so we
237          * need to muliply by 4 to get the total size.
238          */
239         sz.side1 *= 4;
240         sz.side2 *= 4;
241         return sz;
242 }
243
244 static void set_dram_row_boundaries(void)
245 {
246         int i, value, drb1, drb2;
247
248         for (i = 0; i < DIMM_SOCKETS; i++) {
249                 struct dimm_size sz;
250                 unsigned device;
251                 device = DIMM_SPD_BASE + i;
252                 drb1 = 0;
253                 drb2 = 0;
254
255                 /* First check if a DIMM is actually present. */
256                 if (spd_read_byte(device, SPD_MEMORY_TYPE) == 0x4) {
257                         print_debug("Found DIMM in slot ");
258                         print_debug_hex8(i);
259                         print_debug("\r\n");
260
261                         sz = spd_get_dimm_size(device);
262
263                         /* WISHLIST: would be nice to display it as decimal? */
264                         print_debug("DIMM is 0x");
265                         print_debug_hex16(sz.side1);
266                         print_debug(" on side 1\r\n");
267                         print_debug("DIMM is 0x");
268                         print_debug_hex16(sz.side2);
269                         print_debug(" on side 2\r\n");
270
271                         /* - Memory compatibility checks - */
272                         /* Test for PC133 (i82830 only supports PC133) */
273                         /* PC133 SPD9 - cycle time is always 75 */
274                         if (spd_read_byte(device, SPD_MIN_CYCLE_TIME_AT_CAS_MAX) != 0x75) {
275                                 print_err("SPD9 DIMM Is Not PC133 Compatable\r\n");
276                                 die("HALT\r\n");
277                         }
278                         /* PC133 SPD10 - access time is always 54 */
279                         if (spd_read_byte(device, SPD_ACCESS_TIME_FROM_CLOCK) != 0x54) {
280                                 print_err("SPD10 DIMM Is Not PC133 Compatable\r\n");
281                                 die("HALT\r\n");
282                         }
283
284                         /* The i82830 only supports a symmetrical dual-sided dimms
285                          * and can't handle DIMMs smaller than 32MB per
286                          * side or larger than 256MB per side.
287                          */
288                         if ((sz.side2 != 0) && (sz.side1 != sz.side2)) {
289                                 print_err("This northbridge only supports\r\n");
290                                 print_err("symmetrical dual-sided DIMMs\r\n");
291                                 print_err("booting as a single-sided DIMM\r\n");
292                                 sz.side2 = 0;
293                         }
294                         if ((sz.side1 < 32)) {
295                                 print_err("DIMMs smaller than 32MB per side\r\n");
296                                 print_err("are not supported on this northbridge\r\n");
297                                 die("HALT\r\n");
298                         }
299
300                         if ((sz.side1 > 256)) {
301                                 print_err
302                                     ("DIMMs larger than 256MB per side\r\n");
303                                 print_err
304                                     ("are not supported on this northbridge\r\n");
305                                 die("HALT\r\n");
306                         }
307                         /* - End Memory compatibility checks - */
308
309                         /* We need to divide size by 32 to set up the
310                          * DRB registers.
311                          */
312                         if (sz.side1)
313                                 drb1 = sz.side1 / 32;
314                         if (sz.side2)
315                                 drb2 = sz.side2 / 32;
316                 } else {
317                         PRINT_DEBUG("No DIMM found in slot ");
318                         PRINT_DEBUG_HEX8(i);
319                         PRINT_DEBUG("\r\n");
320
321                         /* If there's no DIMM in the slot, set value to 0. */
322                         drb1 = 0;
323                         drb2 = 0;
324                 }
325                 /* Set the value for DRAM Row Boundary Registers */
326                 if (i == 0) {
327                         pci_write_config8(NORTHBRIDGE, DRB, drb1);
328                         pci_write_config8(NORTHBRIDGE, DRB + 1, drb1 + drb2);
329                         PRINT_DEBUG("DRB 0x");
330                         PRINT_DEBUG_HEX8(DRB);
331                         PRINT_DEBUG(" has been set to 0x");
332                         PRINT_DEBUG_HEX8(drb1);
333                         PRINT_DEBUG("\r\n");
334                         PRINT_DEBUG("DRB1 0x");
335                         PRINT_DEBUG_HEX8(DRB + 1);
336                         PRINT_DEBUG(" has been set to 0x");
337                         PRINT_DEBUG_HEX8(drb1 + drb2);
338                         PRINT_DEBUG("\r\n");
339                 } else if (i == 1) {
340                         value = pci_read_config8(NORTHBRIDGE, DRB + 1);
341                         pci_write_config8(NORTHBRIDGE, DRB + 2, value + drb1);
342                         pci_write_config8(NORTHBRIDGE, DRB + 3, value + drb1 + drb2);
343                         PRINT_DEBUG("DRB2 0x");
344                         PRINT_DEBUG_HEX8(DRB + 2);
345                         PRINT_DEBUG(" has been set to 0x");
346                         PRINT_DEBUG_HEX8(value + drb1);
347                         PRINT_DEBUG("\r\n");
348                         PRINT_DEBUG("DRB3 0x");
349                         PRINT_DEBUG_HEX8(DRB + 3);
350                         PRINT_DEBUG(" has been set to 0x");
351                         PRINT_DEBUG_HEX8(value + drb1 + drb2);
352                         PRINT_DEBUG("\r\n");
353
354                         /* We need to set the highest DRB value to 0x64 and 0x65.
355                          * These are supposed to be "Reserved" but memory will
356                          * not initialize properly if we don't.
357                          */
358                         value = pci_read_config8(NORTHBRIDGE, DRB + 3);
359                         pci_write_config8(NORTHBRIDGE, DRB + 4, value);
360                         pci_write_config8(NORTHBRIDGE, DRB + 5, value);
361                 }
362         }
363 }
364
365 static void set_dram_row_attributes(void)
366 {
367         int i, dra, col, width, value;
368
369         for (i = 0; i < DIMM_SOCKETS; i++) {
370                 unsigned device;
371                 device = DIMM_SPD_BASE + i;
372
373                 /* First check if a DIMM is actually present. */
374                 if (spd_read_byte(device, SPD_MEMORY_TYPE) == 0x4) {
375                         print_debug("Found DIMM in slot ");
376                         print_debug_hex8(i);
377                         print_debug(", setting DRA...\r\n");
378
379                         dra = 0x00;
380
381                         /* columns */
382                         col = spd_read_byte(device, SPD_NUM_COLUMNS);
383
384                         /* data width */
385                         width = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB);
386
387                         /* calculate page size in bits */
388                         value = ((1 << col) * width);
389
390                         /* convert to Kilobytes */
391                         dra = ((value / 8) >> 10);
392
393                         /* # of banks of DIMM (single or double sided) */
394                         value = spd_read_byte(device, SPD_NUM_DIMM_BANKS);
395
396                         if (value == 1) {
397                                 if (dra == 2) {
398                                         dra = 0xF0; /* 2KB */
399                                 } else if (dra == 4) {
400                                         dra = 0xF1; /* 4KB */
401                                 } else if (dra == 8) {
402                                         dra = 0xF2; /* 8KB */
403                                 } else if (dra == 16) {
404                                         dra = 0xF3; /* 16KB */
405                                 } else {
406                                         print_err("Page size not supported\r\n");
407                                         die("HALT\r\n");
408                                 }
409                         } else if (value == 2) {
410                                 if (dra == 2) {
411                                         dra = 0x00; /* 2KB */
412                                 } else if (dra == 4) {
413                                         dra = 0x11; /* 4KB */
414                                 } else if (dra == 8) {
415                                         dra = 0x22; /* 8KB */
416                                 } else if (dra == 16) {
417                                         dra = 0x33; /* 16KB */
418                                 } else {
419                                         print_err("Page size not supported\r\n");
420                                         die("HALT\r\n");
421                                 }
422                         } else {
423                                 print_err("# of banks of DIMM not supported\r\n");
424                                 die("HALT\r\n");
425                         }
426
427                 } else {
428                         PRINT_DEBUG("No DIMM found in slot ");
429                         PRINT_DEBUG_HEX8(i);
430                         PRINT_DEBUG(", setting DRA to 0xFF\r\n");
431
432                         /* If there's no DIMM in the slot, set dra value to 0xFF. */
433                         dra = 0xFF;
434                 }
435
436                 /* Set the value for DRAM Row Attribute Registers */
437                 pci_write_config8(NORTHBRIDGE, DRA + i, dra);
438                 PRINT_DEBUG("DRA 0x");
439                 PRINT_DEBUG_HEX8(DRA + i);
440                 PRINT_DEBUG(" has been set to 0x");
441                 PRINT_DEBUG_HEX8(dra);
442                 PRINT_DEBUG("\r\n");
443         }
444 }
445
446 static void set_dram_timing(void)
447 {
448         /* Set the value for DRAM Timing Register */
449         /* TODO: Configure the value according to SPD values. */
450         pci_write_config32(NORTHBRIDGE, DRT, 0x00000010);
451 }
452
453 static void set_dram_buffer_strength(void)
454 {
455         /* TODO: This needs to be set according to the DRAM tech
456          * (x8, x16, or x32). Argh, Intel provides no docs on this!
457          * Currently, it needs to be pulled from the output of
458          * lspci -xxx Rx92
459          */
460
461         /* Set the value for System Memory Buffer Strength Control Registers */
462         pci_write_config32(NORTHBRIDGE, BUFF_SC, 0xFC9B491B);
463 }
464
465 /*-----------------------------------------------------------------------------
466 Public interface.
467 -----------------------------------------------------------------------------*/
468
469 static void sdram_set_registers(void)
470 {
471         PRINT_DEBUG("Setting initial sdram registers....\r\n");
472
473         /* Calculate the value for DRT DRAM Timing Register */
474         set_dram_timing();
475
476         /* Setup System Memory Buffer Strength Control Registers */
477         set_dram_buffer_strength();
478
479         /* Setup DRAM Row Boundary Registers */
480         set_dram_row_boundaries();
481
482         /* Setup DRAM Row Attribute Registers */
483         set_dram_row_attributes();
484
485         PRINT_DEBUG("Initial sdram registers have been set.\r\n");
486 }
487
488 static void northbridge_set_registers(void)
489 {
490         u16 value;
491         int igd_memory = 0;
492
493         PRINT_DEBUG("Setting initial nothbridge registers....\r\n");
494
495         /* Set the value for Fixed DRAM Hole Control Register */
496         pci_write_config8(NORTHBRIDGE, FDHC, 0x00);
497
498         /* Set the value for Programable Attribute Map Registers
499          * Ideally, this should be R/W for as many ranges as possible.
500          */
501         pci_write_config8(NORTHBRIDGE, PAM0, 0x30);
502         pci_write_config8(NORTHBRIDGE, PAM1, 0x33);
503         pci_write_config8(NORTHBRIDGE, PAM2, 0x33);
504         pci_write_config8(NORTHBRIDGE, PAM3, 0x33);
505         pci_write_config8(NORTHBRIDGE, PAM4, 0x33);
506         pci_write_config8(NORTHBRIDGE, PAM5, 0x33);
507         pci_write_config8(NORTHBRIDGE, PAM6, 0x33);
508
509         /* Set the value for System Management RAM Control Register */
510         pci_write_config8(NORTHBRIDGE, SMRAM, 0x02);
511
512         /* Set the value for GMCH Control Register #0 */
513         pci_write_config16(NORTHBRIDGE, GCC0, 0xA072);
514
515         /* Set the value for Aperture Base Configuration Register */
516         pci_write_config32(NORTHBRIDGE, APBASE, 0x00000008);
517
518         /* Set the value for GMCH Control Register #1 */
519         switch (CONFIG_VIDEO_MB) {
520         case 512: /* 512K of memory */
521                 igd_memory = 0x2;
522                 break;
523         case 1: /* 1M of memory */
524                 igd_memory = 0x3;
525                 break;
526         case 8: /* 8M of memory */
527                 igd_memory = 0x4;
528                 break;
529         default: /* No memory */
530                 pci_write_config16(NORTHBRIDGE, GCC1, 0x0002);
531                 igd_memory = 0x0;
532         }
533
534         value = pci_read_config16(NORTHBRIDGE, GCC1);
535         value |= igd_memory << 4;
536         value |= 1; // 64MB aperture
537         pci_write_config16(NORTHBRIDGE, GCC1, value);
538
539         PRINT_DEBUG("Initial northbridge registers have been set.\r\n");
540 }
541
542 static void sdram_initialize(void)
543 {
544         int i;
545         u32 reg32;
546
547         /* Setup Initial SDRAM Registers */
548         sdram_set_registers();
549
550         /* 0. Wait until power/voltages and clocks are stable (200us). */
551         udelay(200);
552
553         /* Initialize each row of memory one at a time */
554         initialize_dimm_rows();
555
556         /* Enable Refresh */
557         PRINT_DEBUG("Enabling Refresh\r\n");
558         reg32 = pci_read_config32(NORTHBRIDGE, DRC);
559         reg32 |= (RAM_COMMAND_REFRESH << 8);
560         pci_write_config32(NORTHBRIDGE, DRC, reg32);
561
562         /* Set initialization complete */
563         PRINT_DEBUG("Setting initialization complete\r\n");
564         reg32 = pci_read_config32(NORTHBRIDGE, DRC);
565         reg32 |= (RAM_COMMAND_IC << 29);
566         pci_write_config32(NORTHBRIDGE, DRC, reg32);
567
568         /* Setup Initial Northbridge Registers */
569         northbridge_set_registers();
570
571         PRINT_DEBUG("Northbridge following SDRAM init:\r\n");
572         DUMPNORTH();
573 }