Those 2 patches are one step towards having a working Onboard-VGA
and 512MB (the max for i810). The raminit.c patch fixes some
misconfigurations and probes the DIMMs correctly (all dual-sided are
now recognized properly), and also set buffer_strength to handle 2
DIMMs although atm this doesn't work. The i82810/northbridge.c patch
takes care of allocating Onboard-VGA memory.
Signed-off-by: Elia Yehuda <[EMAIL PROTECTED]>
Index: coreboot-v2/src/northbridge/intel/i82810/raminit.c
===================================================================
--- coreboot-v2/src/northbridge/intel/i82810/raminit.c (revision 3698)
+++ coreboot-v2/src/northbridge/intel/i82810/raminit.c (working copy)
@@ -29,7 +29,7 @@
-----------------------------------------------------------------------------*/
/* Uncomment this to enable debugging output. */
-// #define DEBUG_RAM_SETUP 1
+//#define DEBUG_RAM_SETUP 1
/* Debugging macros. */
#if defined(DEBUG_RAM_SETUP)
@@ -69,10 +69,10 @@
static void do_ram_command(const struct mem_controller *ctrl, uint32_t command,
uint32_t addr_offset, uint32_t row_offset)
{
+ uint16_t dimm_size, dimm_start, dimm_banks;
uint8_t reg;
+ int i;
- /* TODO: Support for multiple DIMMs. */
-
/* Configure the RAM command. */
reg = pci_read_config8(ctrl->d0, DRAMT);
reg &= 0x1f; /* Clear bits 7-5. */
@@ -83,21 +83,38 @@
doesn't need to be "sent" to the DIMMs. */
/* if (command == RAM_COMMAND_NORMAL) return; */
- PRINT_DEBUG(" Sending RAM command 0x");
- PRINT_DEBUG_HEX8(reg);
- PRINT_DEBUG(" to 0x");
- PRINT_DEBUG_HEX32(0 + addr_offset); // FIXME
- PRINT_DEBUG("\r\n");
+ dimm_start = 0;
- /* Read from (DIMM start address + addr_offset). */
- read32(0 + addr_offset); //first offset is always 0
- read32(row_offset + addr_offset);
+ for (i = 0; i < DIMM_SOCKETS ; i++) {
+ dimm_size = smbus_read_byte(ctrl->channel0[i], 31);
+ dimm_banks = smbus_read_byte(ctrl->channel0[i], 5);
+ if (dimm_size) {
+ PRINT_DEBUG(" Sending RAM command 0x");
+ PRINT_DEBUG_HEX8(reg);
+ PRINT_DEBUG(" to 0x");
+ PRINT_DEBUG_HEX32((dimm_start * 4 * 1024 * 1024) + addr_offset);
+ PRINT_DEBUG("\r\n");
+ read32((dimm_start * 4 * 1024 * 1024) + addr_offset);
+ if (dimm_banks > 1) {
+ /* send command to bank #2 of the DIMM */
+ dimm_start += dimm_size;
+ read32((dimm_start * 4 * 1024 * 1024) + addr_offset);
+ }
+ }
+ dimm_start += dimm_size;
+ }
+ /* TODO */
+ //read32((dimm_start * 4 * 1024 * 1024) + addr_offset);
}
+
/*-----------------------------------------------------------------------------
DIMM-independant configuration functions.
-----------------------------------------------------------------------------*/
+/*
+ * Setting DRP - DRAM Row Population Register (Device 0)
+ */
static void spd_set_dram_size(const struct mem_controller *ctrl,
uint32_t row_offset)
{
@@ -105,6 +122,7 @@
* SMBus-related functions return ints, and its just easier this way.
*/
int i, drp, dimm_size;
+ //struct dimm_size_s sz;
drp = 0x00;
@@ -118,7 +136,7 @@
dimm_size = smbus_read_byte(ctrl->channel0[i], 31);
/* WISHLIST: would be nice to display it as decimal? */
- print_debug("DIMM is 0x");
+ print_debug(" DIMM is 0x");
print_debug_hex8(dimm_size * 4);
print_debug("MB\r\n");
@@ -126,14 +144,15 @@
* side. This will fail if the DIMM uses a
* non-supported DRAM tech, and can't be used until
* buffers are done dynamically.
- * Note: the factory BIOS just dies if it spots this :D
+ * Note: old factory BIOS just dies if it spots this :D
+ * and new ones treat it as 128MB.
*/
if (dimm_size > 32) {
- print_err("DIMM row sizes larger than 128MB not"
- "supported on i810\r\n");
- print_err
- ("Attempting to treat as 128MB DIMM\r\n");
- dimm_size = 32;
+ print_err("DIMM row sizes larger than 128MB not"
+ "supported on i810\r\n");
+ print_err
+ ("Attempting to treat as 128MB DIMM\r\n");
+ dimm_size = 32;
}
/* Set the row offset, in KBytes (should this be
@@ -142,47 +161,47 @@
*/
row_offset = (dimm_size * 4 * 1024);
- /* This is the way I was doing this, it's provided
- * mainly as an alternative to the "new" way.
- */
-#if 0
- /* 8MB */
- if (dimm_size == 0x2)
- dimm_size = 0x1;
- /* 16MB */
- else if (dimm_size == 0x4)
- dimm_size = 0x4;
- /* 32MB */
- else if (dimm_size == 0x8)
- dimm_size = 0x7;
- /* 64 MB */
- else if (dimm_size == 0x10)
- dimm_size = 0xa;
- /* 128 MB */
- else if (dimm_size == 0x20)
- dimm_size = 0xd;
- else
- print_debug("Ram Size not supported\r\n");
-#endif
-
/* This array is provided in raminit.h, because it got
- * extremely messy. The above way is cleaner, but
+ * extremely messy. The old way is cleaner, but
* doesn't support any asymetrical/odd configurations.
*/
dimm_size = translate_spd_to_i82810[dimm_size];
- print_debug("After translation, dimm_size is 0x");
- print_debug_hex8(dimm_size);
- print_debug("\r\n");
-
/* If the DIMM is dual-sided, the DRP value is +2 */
/* TODO: Figure out asymetrical configurations. */
- if ((smbus_read_byte(ctrl->channel0[i], 127) | 0xf) ==
- 0xff) {
- print_debug("DIMM is dual-sided\r\n");
- dimm_size += 2;
+
+ /* this doesn't always recognize dual-sided DIMM */
+ /*
+ if ((smbus_read_byte(ctrl->channel0[i], 127) | 0xf) == 0xff) {
+ print_debug(" DIMM is dual-sided\r\n");
+ dimm_size += 2;
}
+ */
+ /* the correct way to check if DIMM is dual-side
+ * using byte 5.
+
+ * FROM INTEL DATASHEET:
+ * The GMCH supports 2 DIMM slots with each slot
+ * supporting two rows of memory. Slots are numbered 0
+ * through 1. Rows of Slots 0 are numbered 0 through 1.
+ * Rows of Slot 1 are numbed 2 through 3. The
+ * DIMMâs SPD Byte 5 describes the number of sides in a
+ * DIMM; SPD Byte 13 provides information on
+ * the DRAM width (x8, x16, or x32). BIOS uses these
+ * two SPD bytes to calculate loads on memory signals.
+ * Load calculation is made based on populated memory
+ * rows.
+
+ */
+ if (smbus_read_byte(ctrl->channel0[i], 5) > 1) {
+ print_debug(" DIMM is dual-sided\r\n");
+ dimm_size += 2;
+ }
+
+ print_debug(" After translation, dimm_size is 0x");
+ print_debug_hex8(dimm_size);
+ print_debug("\r\n");
} else {
print_debug("No DIMM found in slot ");
print_debug_hex8(i);
@@ -199,7 +218,6 @@
print_debug("DRP calculated to 0x");
print_debug_hex8(drp);
print_debug("\r\n");
-
pci_write_config8(ctrl->d0, DRP, drp);
}
@@ -207,16 +225,35 @@
{
/* TODO, for now using default, hopefully safe values. */
// pci_write_config8(ctrl->d0, DRAMT, 0x00);
+ uint8_t val;
+ val = pci_read_config8(ctrl->d0, DRAMT);
+ val |= 0x18;
+ pci_write_config8(ctrl->d0, DRAMT, val);
}
static void set_dram_buffer_strength(const struct mem_controller *ctrl)
{
- /* TODO: This needs to be set according to the DRAM tech
+ /* TODO: This needs to be calculated according to the DRAM tech
* (x8, x16, or x32). Argh, Intel provides no docs on this!
* Currently, it needs to be pulled from the output of
* lspci -xxx Rx92
+ * here are some common results:
+ * value: tom: config:
+ * 0x3356 256MB 1 x 256MB DIMM(s), dual sided
+ * 0x0001 512MB 2 x 256MB DIMM(s), dual sided
+ * 0x77da 128MB 1 x 128MB DIMM(s), single sided
+ * 0x55c6 128MB 2 x 128MB DIMM(s), single sided
+ * 0x3356 128MB 1 x 128MB DIMM(s), dual sided
+ * 0x0001 256MB 2 x 128MB DIMM(s), dual sided
*/
- pci_write_config16(ctrl->d0, BUFF_SC, 0x77da);
+ /* use 2 dual sided DIMMs - this also works with only 1 DIMM */
+ pci_write_config16(ctrl->d0, BUFF_SC, 0x0001);
+
+ /* use 1 single sided DIMM - max 128MB */
+ //pci_write_config16(ctrl->d0, BUFF_SC, 0x77da);
+
+ /* or we can use defaults - bad idea... */
+ //pci_write_config16(ctrl->d0, BUFF_SC, 0x0ffff);
}
/*-----------------------------------------------------------------------------
@@ -230,10 +267,17 @@
*/
static void sdram_set_registers(const struct mem_controller *ctrl)
{
+ uint8_t value;
unsigned long val;
/* TODO */
- pci_write_config8(ctrl->d0, GMCHCFG, 0x60);
+ //pci_write_config8(ctrl->d0, GMCHCFG, 0x60);
+ value = pci_read_config8(ctrl->d0, GMCHCFG);
+ /* Preserve reserved bits. */
+ val &= 0xa4;
+ /* set the GMCH to prechange all during the service of a page miss */
+ val |= 0x28;
+ pci_write_config8(ctrl->d0, GMCHCFG, val);
/* PAMR: Programmable Attributes Register
* Every pair of bits controls an address range:
@@ -251,24 +295,54 @@
/* Ideally, this should be R/W for as many ranges as possible. */
pci_write_config8(ctrl->d0, PAM, 0xff);
+ /* or we can use sane defaults, but VGA won't work for unknown reason */
+ //pci_write_config8(ctrl->d0, PAM, 0x41);
+
+ /* PCICMD PCI Command Register (Device 1) */
+ val = pci_read_config16(ctrl->d0, 4);
+ /* vga ? */
+ val |= 3;
+ pci_write_config16(ctrl->d0, 4, val);
- /* Enabling the VGA Framebuffer currently screws up the rest of the boot.
- * Disable for now */
-
+ /* set System Management RAM Control Register / Graphics Mode Select */
+ value = pci_read_config8(ctrl->d0, SMRAM);
/* Enable 1MB framebuffer. */
- //pci_write_config8(ctrl->d0, SMRAM, 0xC0);
+ value |= 0xC0;
+ /* set AB segment Enabled as SMM RAM */
+ value |= 0x0C;
+ pci_write_config8(ctrl->d0, SMRAM, value);
- //val = pci_read_config16(ctrl->d0, MISSC);
+ /* Set the value for Fixed DRAM Hole Control Register */
+ pci_write_config8(ctrl->d0, FDHC, 0x00);
+
+ val = pci_read_config16(ctrl->d0, MISSC);
/* Preserve reserved bits. */
- //val &= 0xff06;
- /* Set graphics cache window to 32MB, no power throttling. */
+ val &= 0xff06;
+ /* Set graphics cache window to 32MB, no power throttling. 0 for 64MB.*/
//val |= 0x0001;
- //pci_write_config16(ctrl->d0, MISSC, val);
+ pci_write_config16(ctrl->d0, MISSC, val);
- //val = pci_read_config8(ctrl->d0, MISSC2);
+ val = 0;
+ val = pci_read_config8(ctrl->d0, MISSC2);
+ /* Preserve reserved bits. */
+ val &= 0xf9;
/* Enable graphics palettes and clock gating (not optional!) */
- //val |= 0x06;
- //pci_write_config8(ctrl->d0, MISSC2, val);
+ val |= 0x06;
+
+ val |= 0xc6;
+ pci_write_config8(ctrl->d0, MISSC2, val);
+
+ /* setting Vendor/Device ids - there must be a better way of doing
+ * this...
+ */
+ /* set vendor id */
+ val = pci_read_config16(ctrl->d0, 0);
+ pci_write_config16(ctrl->d0, 0x2c, val);
+ /* set device id */
+ val = pci_read_config16(ctrl->d0, 2);
+ pci_write_config16(ctrl->d0, 0x2e, val);
+
+ print_debug("i810 Initial registers have been set.\r\n");
}
/**
@@ -295,10 +369,47 @@
static void sdram_enable(int controllers, const struct mem_controller *ctrl)
{
int i;
+ uint8_t reg8;
- /* Todo: this will currently work with either one dual sided or two
- * single sided DIMMs. Needs to work with 2 dual sided DIMMs in the
- * long run.
+ /* TODO: this currently works with one DIMM only, dual or single sided.
+ * Must figure out how to activate the 2nd DIMM (coreboot recognizes
+ * the tomk properly but the system restart itself when the payload is
+ * trying to relocate its code to the end of tomk which is in DIMM 2.
+ * something like this :
+ *
+ * Jumping to boot code at 0x100084
+ * entry = 0x00100084
+ * lb_start = 0x00004000
+ * lb_size = 0x00026000
+ * adjust = 0x17dd6000
+ * buffer = 0x17db4000
+ * elf_boot_notes = 0x00020920
+ * adjusted_boot_notes = 0x17df6920
+ * FILO version 0.6.0rc1 ([EMAIL PROTECTED]) Wed Nov 12 06:57:33 IST 2008
+ * Bootloader: elfboot
+ * Version: 1.3
+ * Current location: 0x100000-0x498cf7
+ * Relocating to 0x17a67000-0x17dffcf7...
+ *
+ * coreboot-2.0.0.0Fallback Mon Nov 17 03:08:18 IST 2008 starting...
+ * ...
+ *
+ *
+ * and sometimes something like this :
+ *
+ * Jumping to boot code at 0x100084
+ * entry = 0x00100084
+ * lb_start = 0x00004000
+ * lb_size = 0x00026000
+ * adjust = 0x1fdd6000
+ * buffer = 0x1fdb4000
+ * elf_boot_notes = 0x00020920
+ * adjusted_boot_notes = 0x1fdf6920
+ * Unexpected Exception: 6 @ 10:4b8415d5 - Halting
+ * Code: 0 eflags: 00010086
+ * eax: 1fde229f ebx: 1fdd6000 ecx: 00000000 edx: 00026000
+ * edi: 00004000 esi: 1fdb4000 ebp: 00025ebc esp: 1fdfbe70
+ *
*/
uint32_t row_offset;
@@ -316,8 +427,9 @@
/* 3. Perform 8 refresh cycles. Wait tRC each time. */
PRINT_DEBUG("RAM Enable 3: CBR\r\n");
- do_ram_command(ctrl, RAM_COMMAND_CBR, 0, row_offset);
for (i = 0; i < 8; i++) {
+ do_ram_command(ctrl, RAM_COMMAND_CBR, 0, row_offset);
+ /* FIXME: are those read32() needed? */
read32(0);
read32(row_offset);
udelay(1);
@@ -333,6 +445,19 @@
do_ram_command(ctrl, RAM_COMMAND_NORMAL, 0, row_offset);
udelay(1);
+ /* 6. Enable refresh */
+ PRINT_DEBUG("RAM Enable 6: Enable Refresh\r\n");
+ reg8 = pci_read_config8(ctrl->d0, DRAMT);
+ /* set SDRAM Mode Select for Normal Operation, refresh 15.6usec */
+ reg8 |= 0x20;
+ pci_write_config8(ctrl->d0, DRAMT, reg8);
+
+ /* Intel reserved, which seems to be needed */
+ pci_write_config8(ctrl->d0, 0x81, 0x78);
+ pci_write_config8(ctrl->d0, 0x82, 0x1d);
+
PRINT_DEBUG("Northbridge following SDRAM init:\r\n");
DUMPNORTH();
+
}
+
Index: coreboot-v2/src/northbridge/intel/i82810/northbridge.c
===================================================================
--- coreboot-v2/src/northbridge/intel/i82810/northbridge.c (revision 3698)
+++ coreboot-v2/src/northbridge/intel/i82810/northbridge.c (working copy)
@@ -31,6 +31,10 @@
#include "northbridge.h"
#include "i82810.h"
+
+/* TODO: Add VGA initalize */
+
+
static void northbridge_init(device_t dev)
{
printk_spew("Northbridge init\n");
@@ -149,6 +153,18 @@
drp_value = drp_value >> 4; // >>= 4; //? mess with later
tomk += (unsigned long)(translate_i82810_to_mb[drp_value]);
+#ifdef CONFIG_VIDEO_MB
+ /* check for VGA reserved memory
+ * possible CONFIG_VIDEO_MB values are 512(kb) and 1(mb)
+ */
+ if (CONFIG_VIDEO_MB == 512) {
+ /* FIXME: we round up the 1/2mb to 1 */
+ tomk -= 1;
+ } else {
+ tomk -= CONFIG_VIDEO_MB ;
+ }
+#endif
+
printk_debug("Setting RAM size to %d MB\n", tomk);
/* Convert tomk from MB to KB. */
--
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot