summaryrefslogtreecommitdiff
path: root/src/northbridge/intel/i945
diff options
context:
space:
mode:
Diffstat (limited to 'src/northbridge/intel/i945')
-rw-r--r--src/northbridge/intel/i945/early_init.c32
-rw-r--r--src/northbridge/intel/i945/i945.h2
-rw-r--r--src/northbridge/intel/i945/raminit.c50
-rw-r--r--src/northbridge/intel/i945/udelay.c3
4 files changed, 62 insertions, 25 deletions
diff --git a/src/northbridge/intel/i945/early_init.c b/src/northbridge/intel/i945/early_init.c
index f6cdcca961..c892216dea 100644
--- a/src/northbridge/intel/i945/early_init.c
+++ b/src/northbridge/intel/i945/early_init.c
@@ -1,7 +1,7 @@
/*
* This file is part of the coreboot project.
*
- * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2007-2010 coresystems GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -154,7 +154,7 @@ static void i945_setup_bars(void)
printk(BIOS_DEBUG, " done.\n");
printk(BIOS_DEBUG, "Disabling Watchdog reboot...");
- RCBA32(GCS) = (RCBA32(0x3410)) | (1 << 5); /* No reset */
+ RCBA32(GCS) = RCBA32(GCS) | (1 << 5); /* No reset */
outw((1 << 11), DEFAULT_PMBASE | 0x60 | 0x08); /* halt timer */
printk(BIOS_DEBUG, " done.\n");
@@ -344,8 +344,7 @@ static void i945_setup_dmi_rcrb(void)
{
u32 reg32;
u32 timeout;
-
- int activate_aspm = 1;
+ int activate_aspm = 1; /* hardcode ASPM for now */
printk(BIOS_DEBUG, "Setting up DMI RCRB\n");
@@ -481,10 +480,12 @@ static void i945_setup_dmi_rcrb(void)
else
printk(BIOS_DEBUG, "ok\n");
+ /* Clear Error Status Bits! */
DMIBAR32(0x1c4) = 0xffffffff;
DMIBAR32(0x1d0) = 0xffffffff;
DMIBAR32(0x228) = 0xffffffff;
+ /* Program Read-Only Write-Once Registers */
DMIBAR32(0x308) = DMIBAR32(0x308);
DMIBAR32(0x314) = DMIBAR32(0x314);
DMIBAR32(0x324) = DMIBAR32(0x324);
@@ -500,7 +501,7 @@ static void i945_setup_dmi_rcrb(void)
reg32 |= (3 << 0);
DMIBAR32(0x224) = reg32;
outb(0x06, 0xcf9);
- for (;;) ; /* wait for reset */
+ for (;;) asm("hlt"); /* wait for reset */
}
}
}
@@ -530,11 +531,11 @@ static void i945_setup_pci_express_x16(void)
/* First we reset the secondary bus */
reg16 = pci_read_config16(PCI_DEV(0, 0x01, 0), 0x3e);
- reg16 |= (1 << 6);
+ reg16 |= (1 << 6); /* SRESET */
pci_write_config16(PCI_DEV(0, 0x01, 0), 0x3e, reg16);
/* Read back and clear reset bit. */
reg16 = pci_read_config16(PCI_DEV(0, 0x01, 0), 0x3e);
- reg16 &= ~(1 << 6);
+ reg16 &= ~(1 << 6); /* SRESET */
pci_write_config16(PCI_DEV(0, 0x01, 0), 0x3e, reg16);
reg16 = pci_read_config16(PCI_DEV(0, 0x01, 0), 0xba);
@@ -625,9 +626,11 @@ static void i945_setup_pci_express_x16(void)
if (reg16 == 1) {
reg32 |= 0x32b;
// TODO
+ /* pcie_write_config32(PCI_DEV(0, 0x01, 0), 0x204, reg32); */
} else if (reg16 == 16) {
reg32 |= 0x0f4;
// TODO
+ /* pcie_write_config32(PCI_DEV(0, 0x01, 0), 0x204, reg32); */
}
reg32 = (pci_read_config32(PCI_DEV(0xa, 0, 0), 0x8) >> 8);
@@ -745,8 +748,8 @@ static void i945_setup_pci_express_x16(void)
if (i945_silicon_revision() <= 2 ) {
/* Set voltage specific parameters */
reg32 = pcie_read_config32(PCI_DEV(0, 0x01, 0), 0xe80);
- reg32 &= (0xf << 4);
- if ((MCHBAR32(0xe08) & (1 << 20)) == 0) {
+ reg32 &= (0xf << 4); /* Default case 1.05V */
+ if ((MCHBAR32(0xe08) & (1 << 20)) == 0) { /* 1.50V */
reg32 |= (7 << 4);
}
pcie_write_config32(PCI_DEV(0, 0x01, 0), 0xe80, reg32);
@@ -843,7 +846,12 @@ static void ich7_setup_pci_express(void)
{
RCBA32(CG) |= (1 << 0);
+ /* Initialize slot power limit for root ports */
pci_write_config32(PCI_DEV(0, 0x1c, 0), 0x54, 0x00000060);
+#if 0
+ pci_write_config32(PCI_DEV(0, 0x1c, 4), 0x54, 0x00480ce0);
+ pci_write_config32(PCI_DEV(0, 0x1c, 5), 0x54, 0x00500ce0);
+#endif
pci_write_config32(PCI_DEV(0, 0x1c, 0), 0xd8, 0x00110000);
}
@@ -852,11 +860,11 @@ static void i945_early_initialization(void)
{
/* Print some chipset specific information */
switch (pci_read_config32(PCI_DEV(0, 0x00, 0), 0)) {
- case 0x27708086:
+ case 0x27708086: /* 82945G/GZ/GC/P/PL */
i945_detect_chipset();
break;
- case 0x27a08086:
- case 0x27ac8086:
+ case 0x27a08086: /* 945GME/GSE */
+ case 0x27ac8086: /* 945GM/PM/GMS/GU/GT, 943/940GML */
i945m_detect_chipset();
break;
}
diff --git a/src/northbridge/intel/i945/i945.h b/src/northbridge/intel/i945/i945.h
index a23e3a8f82..0d6f024673 100644
--- a/src/northbridge/intel/i945/i945.h
+++ b/src/northbridge/intel/i945/i945.h
@@ -331,5 +331,7 @@
#define DMIDRCCFG 0xeb4 /* 32bit */
+static inline void barrier(void) { asm("" ::: "memory"); }
+
#endif
#endif
diff --git a/src/northbridge/intel/i945/raminit.c b/src/northbridge/intel/i945/raminit.c
index 3c54b98855..1922fab4b6 100644
--- a/src/northbridge/intel/i945/raminit.c
+++ b/src/northbridge/intel/i945/raminit.c
@@ -132,7 +132,7 @@ static int sdram_capabilities_max_supported_memory_frequency(void)
return MAXIMUM_SUPPORTED_FREQUENCY;
#endif
- reg32 = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xe4);
+ reg32 = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xe4); /* CAPID0 + 4 */
reg32 &= (7 << 0);
switch (reg32) {
@@ -156,7 +156,7 @@ static int sdram_capabilities_interleave(void)
{
u32 reg32;
- reg32 = pci_read_config8(PCI_DEV(0, 0x00,0), 0xe4);
+ reg32 = pci_read_config32(PCI_DEV(0, 0x00,0), 0xe4); /* CAPID0 + 4 */
reg32 >>= 25;
reg32 &= 1;
@@ -172,7 +172,7 @@ static int sdram_capabilities_dual_channel(void)
{
u32 reg32;
- reg32 = pci_read_config8(PCI_DEV(0, 0x00,0), 0xe4);
+ reg32 = pci_read_config32(PCI_DEV(0, 0x00,0), 0xe4); /* CAPID0 + 4 */
reg32 >>= 24;
reg32 &= 1;
@@ -205,7 +205,7 @@ static int sdram_capabilities_MEM4G_disable(void)
{
u8 reg8;
- reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5);
+ reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
reg8 &= (1 << 0);
return (reg8 != 0);
@@ -228,7 +228,7 @@ static int sdram_capabilities_core_frequencies(void)
return (reg8);
}
-static void sdram_detect_errors(void)
+static void sdram_detect_errors(struct sys_info *sysinfo)
{
u8 reg8;
u8 do_reset = 0;
@@ -269,6 +269,29 @@ static void sdram_detect_errors(void)
reg8 |= (1<<7);
pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
+ /* clear self refresh if not wake-up from suspend */
+ if (sysinfo->boot_path != 2) {
+ MCHBAR8(0xf14) |= 3;
+ } else {
+ /* Validate self refresh config */
+ if (((sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED) ||
+ (sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)) &&
+ !(MCHBAR8(0xf14) & (1<<0))) {
+ do_reset = 1;
+ }
+ if (((sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED) ||
+ (sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)) &&
+ !(MCHBAR8(0xf14) & (1<<1))) {
+ do_reset = 1;
+ }
+ }
+
+ if (do_reset) {
+ printk(BIOS_DEBUG, "Reset required.\n");
+ outb(0x00, 0xcf9);
+ outb(0x0e, 0xcf9);
+ for (;;) asm("hlt"); /* Wait for reset! */
+ }
}
/**
@@ -1311,7 +1334,7 @@ static void sdram_enable_system_memory_io(struct sys_info *sysinfo)
reg32 |= (1 << 6) | (1 << 4);
MCHBAR32(DRTST) = reg32;
- asm volatile ("nop; nop;");
+ asm volatile ("nop; nop;" ::: "memory");
reg32 = MCHBAR32(DRTST);
@@ -1890,6 +1913,7 @@ static void sdram_set_channel_mode(struct sys_info *sysinfo)
printk(BIOS_DEBUG, "Single Channel 0 only.\n");
}
+ /* Now disable channel XORing */
reg32 |= (1 << 10);
MCHBAR32(DCC) = reg32;
@@ -1960,7 +1984,7 @@ static void sdram_program_graphics_frequency(struct sys_info *sysinfo)
if (voltage == VOLTAGE_1_05)
freq = CRCLK_250MHz;
else
- freq = CRCLK_400MHz;
+ freq = CRCLK_400MHz; /* 1.5V requires 400MHz */
break;
case GFX_FREQUENCY_CAP_250MHZ: freq = CRCLK_250MHz; break;
case GFX_FREQUENCY_CAP_200MHZ: freq = CRCLK_200MHz; break;
@@ -2096,7 +2120,7 @@ vco_update:
clkcfg |= (1 << 10);
MCHBAR32(CLKCFG) = clkcfg;
- __asm__ __volatile__ (
+ asm volatile (
" movl $0x100, %%ecx\n"
"delay_update:\n"
" nop\n"
@@ -2106,7 +2130,7 @@ vco_update:
" loop delay_update\n"
: /* No outputs */
: /* No inputs */
- : "%ecx"
+ : "%ecx", "memory"
);
clkcfg &= ~(1 << 10);
@@ -2136,7 +2160,7 @@ static void sdram_program_clock_crossing(void)
0x08040120, 0x00000000, /* DDR400 FSB533 */
0x00100401, 0x00000000, /* DDR533 FSB533 */
- 0xffffffff, 0xffffffff, /* nonexistant */
+ 0x00010402, 0x00000000, /* DDR667 FSB533 - fake values */
0x04020120, 0x00000010, /* DDR400 FSB667 */
0x10040280, 0x00000040, /* DDR533 FSB667 */
@@ -2615,6 +2639,7 @@ static void sdram_thermal_management(void)
* 0x30/0x32.
*/
+ /* TODO This is not implemented yet. Volunteers? */
}
static void sdram_save_receive_enable(void)
@@ -3007,8 +3032,6 @@ void sdram_initialize(int boot_path)
struct sys_info sysinfo;
u8 reg8, cas_mask;
- sdram_detect_errors();
-
printk(BIOS_DEBUG, "Setting up RAM controller.\n");
memset(&sysinfo, 0, sizeof(sysinfo));
@@ -3018,6 +3041,9 @@ void sdram_initialize(int boot_path)
/* Look at the type of DIMMs and verify all DIMMs are x8 or x16 width */
sdram_get_dram_configuration(&sysinfo);
+ /* If error, do cold boot */
+ sdram_detect_errors(&sysinfo);
+
/* Check whether we have stacked DIMMs */
sdram_verify_package_type(&sysinfo);
diff --git a/src/northbridge/intel/i945/udelay.c b/src/northbridge/intel/i945/udelay.c
index 965c890d1b..d5349c937e 100644
--- a/src/northbridge/intel/i945/udelay.c
+++ b/src/northbridge/intel/i945/udelay.c
@@ -17,6 +17,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <delay.h>
#include <cpu/x86/tsc.h>
#include <cpu/x86/msr.h>
@@ -24,7 +25,7 @@
* Intel Core(tm) cpus always run the TSC at the maximum possible CPU clock
*/
-static void udelay(u32 us)
+void udelay(u32 us)
{
u32 dword;
tsc_t tsc, tsc1, tscd;