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