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