Add support for Intel Sandybridge CPU (northbridge part)
[coreboot.git] / src / northbridge / intel / i440bx / raminit.c
index ebcd368511104e366578e2fd13a0339ad169dd91..232b87249c02165ca8508825a755563718e4e22d 100644 (file)
 
 #include <spd.h>
 #include <delay.h>
+#include <stdint.h>
 #include <stdlib.h>
+#include <arch/io.h>
+#include <arch/romcc_io.h>
+#include <device/pci_def.h>
+#include <console/console.h>
 #include "i440bx.h"
 #include "raminit.h"
 
@@ -33,16 +38,10 @@ Macros and definitions.
 
 /* Debugging macros. */
 #if CONFIG_DEBUG_RAM_SETUP
-#define PRINT_DEBUG(x)         print_debug(x)
-#define PRINT_DEBUG_HEX8(x)    print_debug_hex8(x)
-#define PRINT_DEBUG_HEX16(x)   print_debug_hex16(x)
-#define PRINT_DEBUG_HEX32(x)   print_debug_hex32(x)
+#define PRINT_DEBUG(x...)      printk(BIOS_DEBUG, x)
 #define DUMPNORTH()            dump_pci_device(NB)
 #else
-#define PRINT_DEBUG(x)
-#define PRINT_DEBUG_HEX8(x)
-#define PRINT_DEBUG_HEX16(x)
-#define PRINT_DEBUG_HEX32(x)
+#define PRINT_DEBUG(x...)
 #define DUMPNORTH()
 #endif
 
@@ -259,7 +258,7 @@ static const u8 register_values[] = {
         * 01        4 KB
         * 10        8 KB
         * 11        Reserved
-        * 
+        *
         * RPS bits Corresponding DRB register
         * [01:00]  DRB[0], row 0
         * [03:02]  DRB[1], row 1
@@ -429,11 +428,8 @@ static void do_ram_command(u32 command)
                addr = (dimm_start * 8 * 1024 * 1024) + addr_offset;
                if (dimm_end > dimm_start) {
 #if 0
-                       PRINT_DEBUG("    Sending RAM command 0x");
-                       PRINT_DEBUG_HEX16(reg16);
-                       PRINT_DEBUG(" to 0x");
-                       PRINT_DEBUG_HEX32(addr);
-                       PRINT_DEBUG("\n");
+                       PRINT_DEBUG("    Sending RAM command 0x%04x to 0x%08x\n",
+                                       reg16, addr);
 #endif
 
                        read32(addr);
@@ -611,16 +607,12 @@ static void spd_enable_refresh(void)
        reg = pci_read_config8(NB, DRAMC);
 
        for (i = 0; i < DIMM_SOCKETS; i++) {
-               value = spd_read_byte(DIMM_SPD_BASE + i, SPD_REFRESH);
+               value = spd_read_byte(DIMM0 + i, SPD_REFRESH);
                if (value < 0)
                        continue;
                reg = (reg & 0xf8) | refresh_rate_map[(value & 0x7f)];
 
-               PRINT_DEBUG("    Enabling refresh (DRAMC = 0x");
-               PRINT_DEBUG_HEX8(reg);
-               PRINT_DEBUG(") for DIMM ");
-               PRINT_DEBUG_HEX8(i);
-               PRINT_DEBUG("\n");
+               PRINT_DEBUG("    Enabling refresh (DRAMC = 0x%02x) for DIMM %02x\n", reg, i);
        }
 
        pci_write_config8(NB, DRAMC, reg);
@@ -630,7 +622,7 @@ static void spd_enable_refresh(void)
 Public interface.
 -----------------------------------------------------------------------------*/
 
-static void sdram_set_registers(void)
+void sdram_set_registers(void)
 {
        int i, max;
        uint8_t reg;
@@ -647,18 +639,15 @@ static void sdram_set_registers(void)
                reg |= register_values[i + 2] & ~(register_values[i + 1]);
                pci_write_config8(NB, register_values[i], reg);
 #if 0
-               PRINT_DEBUG("    Set register 0x");
-               PRINT_DEBUG_HEX8(register_values[i]);
-               PRINT_DEBUG(" to 0x");
-               PRINT_DEBUG_HEX8(reg);
-               PRINT_DEBUG("\n");
+               PRINT_DEBUG("    Set register 0x%02x to 0x%02x\n",
+                               register_values[i], reg);
 #endif
        }
 }
 
 struct dimm_size {
-       unsigned long side1;
-       unsigned long side2;
+       u32 side1;
+       u32 side2;
 };
 
 static struct dimm_size spd_get_dimm_size(unsigned int device)
@@ -713,15 +702,13 @@ static struct dimm_size spd_get_dimm_size(unsigned int device)
         * modules by setting them to a supported size.
         */
        if(sz.side1 > 128) {
-               PRINT_DEBUG("Side1 was 0x");
-               PRINT_DEBUG_HEX16(sz.side1);
-               PRINT_DEBUG(" but only 128MB will be used.\n");
+               PRINT_DEBUG("Side1 was %dMB but only 128MB will be used.\n",
+                       sz.side1);
                sz.side1 = 128;
 
                if(sz.side2 > 128) {
-                       PRINT_DEBUG("Side2 was 0x");
-                       PRINT_DEBUG_HEX16(sz.side2);
-                       PRINT_DEBUG(" but only 128MB will be used.\n");
+                       PRINT_DEBUG("Side2 was %dMB but only 128MB will be used.\n",
+                               sz.side2);
                        sz.side2 = 128;
                }
        }
@@ -734,19 +721,23 @@ static struct dimm_size spd_get_dimm_size(unsigned int device)
  */
 static void set_dram_row_attributes(void)
 {
-       int i, dra, drb, col, width, value, rps, edosd, ecc, nbxecc;
+       int i, dra, drb, col, width, value, rps;
        u8 bpr; /* Top 8 bits of PGPOL */
+       u8 nbxecc = 0; /* NBXCFG[31:24] */
+       u8 edo, sd, regsd; /* EDO, SDRAM, registered SDRAM */
 
-       edosd = 0;
+       edo = 0;
+       sd = 0;
+       regsd = 1;
        rps = 0;
        drb = 0;
        bpr = 0;
-       nbxecc = 0xff;
 
        for (i = 0; i < DIMM_SOCKETS; i++) {
                unsigned int device;
-               device = DIMM_SPD_BASE + i;
+               device = DIMM0 + i;
                bpr >>= 2;
+               nbxecc >>= 2;
 
                /* First check if a DIMM is actually present. */
                value = spd_read_byte(device, SPD_MEMORY_TYPE);
@@ -754,17 +745,14 @@ static void set_dram_row_attributes(void)
                if (value == SPD_MEMORY_TYPE_EDO
                        || value == SPD_MEMORY_TYPE_SDRAM) {
 
-                       PRINT_DEBUG("Found ");
                        if (value == SPD_MEMORY_TYPE_EDO) {
-                               edosd |= 0x02;
+                               edo = 1;
                        } else if (value == SPD_MEMORY_TYPE_SDRAM) {
-                               edosd |= 0x04;
+                               sd = 1;
                        }
-                       PRINT_DEBUG("DIMM in slot ");
-                       PRINT_DEBUG_HEX8(i);
-                       PRINT_DEBUG("\n");
+                       PRINT_DEBUG("Found DIMM in slot %d\n", i);
 
-                       if (edosd == 0x06) {
+                       if (edo && sd) {
                                print_err("Mixing EDO/SDRAM unsupported!\n");
                                die("HALT\n");
                        }
@@ -780,23 +768,37 @@ static void set_dram_row_attributes(void)
                         * TODO: Other register than NBXCFG also needs this
                         * ECC information.
                         */
-                       ecc = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE);
+                       value = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE);
 
                        /* Data width */
                        width = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB);
 
                        /* Exclude error checking data width from page size calculations */
-                       if (ecc) {
+                       if (value) {
                                value = spd_read_byte(device,
                                        SPD_ERROR_CHECKING_SDRAM_WIDTH);
                                width -= value;
                                /* ### ECC */
                                /* Clear top 2 bits to help set up NBXCFG. */
-                               ecc &= 0x3f;
+                               nbxecc &= 0x3f;
                        } else {
                                /* Without ECC, top 2 bits should be 11. */
-                               ecc |= 0xc0;
+                               nbxecc |= 0xc0;
+                       }
+
+                       /* If any installed DIMM is *not* registered, this system cannot be
+                        * configured for registered SDRAM.
+                        * By registered, only the address and control lines need to be, which
+                        * we can tell by reading SPD byte 21, bit 1.
+                        */
+                       value = spd_read_byte(device, SPD_MODULE_ATTRIBUTES);
+
+                       PRINT_DEBUG("DIMM is ");
+                       if ((value & MODULE_REGISTERED) == 0) {
+                               regsd = 0;
+                               PRINT_DEBUG("not ");
                        }
+                       PRINT_DEBUG("registered\n");
 
                        /* Calculate page size in bits. */
                        value = ((1 << col) * width);
@@ -817,7 +819,6 @@ static void set_dram_row_attributes(void)
                                 * Second bank of 1-bank DIMMs "doesn't have
                                 * ECC" - or anything.
                                 */
-                               ecc |= 0x80;
                                if (dra == 2) {
                                        dra = 0x0; /* 2KB */
                                } else if (dra == 4) {
@@ -889,14 +890,11 @@ static void set_dram_row_attributes(void)
                        drb |= (drb + (sz.side2 / 8)) << 8;
                } else {
 #if 0
-                       PRINT_DEBUG("No DIMM found in slot ");
-                       PRINT_DEBUG_HEX8(i);
-                       PRINT_DEBUG("\n");
+                       PRINT_DEBUG("No DIMM found in slot %d\n", i);
 #endif
 
                        /* If there's no DIMM in the slot, set dra to 0x00. */
                        dra = 0x00;
-                       ecc = 0xc0;
                        /* Still have to propagate DRB over. */
                        drb &= 0xff;
                        drb |= (drb << 8);
@@ -904,9 +902,7 @@ static void set_dram_row_attributes(void)
 
                pci_write_config16(NB, DRB + (2 * i), drb);
 #if 0
-               PRINT_DEBUG("DRB has been set to 0x");
-               PRINT_DEBUG_HEX16(drb);
-               PRINT_DEBUG("\n");
+               PRINT_DEBUG("DRB has been set to 0x%04x\n", drb);
 #endif
 
                /* Brings the upper DRB back down to be base for
@@ -915,48 +911,38 @@ static void set_dram_row_attributes(void)
                drb >>= 8;
 
                rps |= (dra & 0x0f) << (i * 4);
-               nbxecc = (nbxecc >> 2) | (ecc & 0xc0);
        }
 
        /* Set paging policy register. */
        pci_write_config8(NB, PGPOL + 1, bpr);
-       PRINT_DEBUG("PGPOL[BPR] has been set to 0x");
-       PRINT_DEBUG_HEX8(bpr);
-       PRINT_DEBUG("\n");
+       PRINT_DEBUG("PGPOL[BPR] has been set to 0x%02x\n", bpr);
 
        /* Set DRAM row page size register. */
        pci_write_config16(NB, RPS, rps);
-       PRINT_DEBUG("RPS has been set to 0x");
-       PRINT_DEBUG_HEX16(rps);
-       PRINT_DEBUG("\n");
+       PRINT_DEBUG("RPS has been set to 0x%04x\n", rps);
 
        /* ### ECC */
        pci_write_config8(NB, NBXCFG + 3, nbxecc);
-       PRINT_DEBUG("NBXECC[31:24] has been set to 0x");
-       PRINT_DEBUG_HEX8(nbxecc);
-       PRINT_DEBUG("\n");
+       PRINT_DEBUG("NBXECC[31:24] has been set to 0x%02x\n", nbxecc);
 
-       /* Set DRAMC[4:3] to proper memory type (EDO/SDRAM).
-        * TODO: Registered SDRAM support.
-        */
-       edosd &= 0x07;
-       if (edosd & 0x02) {
-               edosd |= 0x00;
-       } else if (edosd & 0x04) {
-               edosd |= 0x08;
+       /* Set DRAMC[4:3] to proper memory type (EDO/SDRAM/Registered SDRAM). */
+
+       /* i will be used to set DRAMC[4:3]. */
+       if (regsd && sd) {
+               i = 0x10; // Registered SDRAM
+       } else if (sd) {
+               i = 0x08; // SDRAM
+       } else {
+               i = 0; // EDO
        }
-       edosd &= 0x18;
 
-       /* edosd is now in the form needed for DRAMC[4:3]. */
        value = pci_read_config8(NB, DRAMC) & 0xe7;
-       value |= edosd;
+       value |= i;
        pci_write_config8(NB, DRAMC, value);
-       PRINT_DEBUG("DRAMC has been set to 0x");
-       PRINT_DEBUG_HEX8(value);
-       PRINT_DEBUG("\n");
+       PRINT_DEBUG("DRAMC has been set to 0x%02x\n", value);
 }
 
-static void sdram_set_spd_registers(void)
+void sdram_set_spd_registers(void)
 {
        /* Setup DRAM row boundary registers and other attributes. */
        set_dram_row_attributes();
@@ -972,7 +958,7 @@ static void sdram_set_spd_registers(void)
        pci_write_config8(NB, DRAMT, 0x03);
 }
 
-static void sdram_enable(void)
+void sdram_enable(void)
 {
        int i;