#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"
/* 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
* 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
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);
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);
Public interface.
-----------------------------------------------------------------------------*/
-static void sdram_set_registers(void)
+void sdram_set_registers(void)
{
int i, max;
uint8_t reg;
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)
* 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;
}
}
*/
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);
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");
}
* 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);
* Second bank of 1-bank DIMMs "doesn't have
* ECC" - or anything.
*/
- ecc |= 0x80;
if (dra == 2) {
dra = 0x0; /* 2KB */
} else if (dra == 4) {
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);
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
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();
pci_write_config8(NB, DRAMT, 0x03);
}
-static void sdram_enable(void)
+void sdram_enable(void)
{
int i;