Support a few more i945 variants. With this framework in place it should

be possible to support i955 and i975 relatively easy, too.

Signed-off-by: Stefan Reinauer <stepan@coresystems.de>
Acked-by: Ronald G. Minnich <rminnich@gmail.com>
Acked-by: Peter Stuge <peter@stuge.se>



git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5025 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Stefan Reinauer 2010-01-17 13:47:35 +00:00 committed by Stefan Reinauer
parent e6cf7c0d4f
commit 24b4df5f99
2 changed files with 451 additions and 233 deletions

View File

@ -92,22 +92,29 @@ static void i945_detect_chipset(void)
u8 reg8;
printk_info("\nIntel(R) ");
reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0x8);
reg8 = ((pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe7) >> 5) & 4) | ((pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe4) >> 4) & 3);
switch (reg8) {
case 0:
case 1:
printk_info("82945G");
break;
case 2:
printk_info("82945G/GZ/GC");
case 3:
printk_info("82945P");
break;
case 0x80:
case 0x81:
case 0x82:
printk_info("82945P/PL");
case 4:
printk_info("82945GC");
break;
case 5:
printk_info("82945GZ");
break;
case 6:
case 7:
printk_info("82945PL");
break;
default:
printk_info("Unknown (%02x)", reg8); /* Others unknown. */
break;
}
printk_info(" Chipset\n");
@ -794,32 +801,26 @@ static void i945_setup_root_complex_topology(void)
reg32 |= (1 << 16);
EPBAR32(EPESD) = reg32;
EPBAR32(EPLE1D) |= (1 << 16);
EPBAR32(EPLE1D) |= (1 << 0);
EPBAR32(EPLE1D) |= (1 << 16) | (1 << 0);
EPBAR32(EPLE1A) = DEFAULT_DMIBAR;
#if 0
EPBAR32(EPLE2D) |= (1 << 16);
#endif
EPBAR32(EPLE2D) |= (1 << 0);
EPBAR32(EPLE2D) |= (1 << 16) | (1 << 0);
/* DMI Port Root Topology */
reg32 = DMIBAR32(DMILE1D);
reg32 &= 0x00ffffff;
DMIBAR32(DMILE1D) = reg32;
reg32 = DMIBAR32(DMILE1D);
reg32 &= 0xff00ffff;
reg32 |= (2 << 16);
DMIBAR32(DMILE1D) = reg32;
DMIBAR32(DMILE1D) |= (1 << 0);
reg32 |= (1 << 0);
DMIBAR32(DMILE1D) = reg32;
DMIBAR32(DMILE1A) = DEFAULT_RCBA;
DMIBAR32(DMILE2D) |= (1 << 0);
DMIBAR32(DMILE2D) |= (1 << 16) | (1 << 0);
DMIBAR32(DMILE2A) = DEFAULT_EPBAR;

View File

@ -87,6 +87,46 @@ static void sdram_dump_mchbar_registers(void)
}
#endif
static int memclk(void)
{
int offset = 0;
#ifdef CHIPSET_I945GM
offset++;
#endif
switch (((MCHBAR32(CLKCFG) >> 4) & 7) - offset) {
case 1: return 400;
case 2: return 533;
case 3: return 667;
default: printk_debug("memclk: unknown register value %x\n", ((MCHBAR32(CLKCFG) >> 4) & 7) - offset);
}
return -1;
}
#ifdef CHIPSET_I945GM
static int fsbclk(void)
{
switch (MCHBAR32(CLKCFG) & 7) {
case 0: return 400;
case 1: return 533;
case 3: return 667;
default: printk_debug("fsbclk: unknown register value %x\n", MCHBAR32(CLKCFG) & 7);
}
return -1;
}
#endif
#ifdef CHIPSET_I945GC
static int fsbclk(void)
{
switch (MCHBAR32(CLKCFG) & 7) {
case 0: return 1066;
case 1: return 533;
case 2: return 800;
default: printk_debug("fsbclk: unknown register value %x\n", MCHBAR32(CLKCFG) & 7);
}
return -1;
}
#endif
static int sdram_capabilities_max_supported_memory_frequency(void)
{
u32 reg32;
@ -434,6 +474,9 @@ static void sdram_detect_cas_latency_and_ram_speed(struct sys_info * sysinfo, u8
case 667: max_ram_speed = 2; break;
}
if (fsbclk() == 533)
max_ram_speed = 1;
sysinfo->memory_frequency = 0;
sysinfo->cas = 0;
@ -827,8 +870,6 @@ static void sdram_write_slew_rates(u32 offset, const u32 *slew_rate_table)
MCHBAR32(offset+(i*4)) = slew_rate_table[i];
}
static void sdram_rcomp_buffer_strength_and_slew(struct sys_info *sysinfo)
{
static const u32 dq2030[] = {
0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
@ -885,68 +926,103 @@ static void sdram_rcomp_buffer_strength_and_slew(struct sys_info *sysinfo)
0x00000000, 0x00000000, 0x00000000, 0x00000000
};
static const u32 const * const dual_channel_slew_group_lookup[] = {
dq2030, cmd3210, ctl3215, ctl3215, clk2030, clk2030, dq2030, cmd3210,
dq2030, cmd3210, ctl3215, ctl3215, clk2030, clk2030, dq2030, cmd3210,
dq2030, cmd3210, nc, ctl3215, nc, clk2030, dq2030, cmd3210,
dq2030, cmd3210, ctl3215, ctl3215, clk2030, clk2030, dq2030, cmd2710,
dq2030, cmd3210, nc, ctl3215, nc, clk2030, nc, nc,
dq2030, cmd3210, ctl3215, ctl3215, clk2030, clk2030, dq2030, cmd3210,
dq2030, cmd3210, ctl3215, nc, clk2030, nc, dq2030, cmd3210,
dq2030, cmd3210, ctl3215, ctl3215, clk2030, clk2030, dq2030, cmd3210,
dq2030, cmd3210, ctl3215, nc, clk2030, nc, dq2030, cmd2710,
dq2030, cmd3210, ctl3215, nc, clk2030, nc, nc, nc,
dq2030, cmd3210, nc, ctl3215, nc, clk2030, dq2030, cmd3210,
dq2030, cmd3210, ctl3215, ctl3215, clk2030, clk2030, dq2030, cmd3210,
dq2030, cmd3210, nc, ctl3215, nc, clk2030, dq2030, cmd3210,
dq2030, cmd3210, ctl3215, ctl3215, clk2030, clk2030, dq2030, cmd2710,
dq2030, cmd3210, nc, ctl3215, nc, clk2030, nc, nc,
dq2030, cmd2710, ctl3215, ctl3215, clk2030, clk2030, dq2030, cmd3210,
dq2030, cmd2710, ctl3215, nc, clk2030, nc, dq2030, cmd3210,
dq2030, cmd2710, ctl3215, ctl3215, clk2030, clk2030, dq2030, cmd3210,
dq2030, cmd2710, ctl3215, nc, clk2030, nc, dq2030, cmd2710,
dq2030, cmd2710, ctl3215, nc, clk2030, nc, nc, nc,
nc, nc, nc, ctl3215, nc, clk2030, dq2030, cmd3210,
nc, nc, ctl3215, nc, clk2030, nc, dq2030, cmd3210,
nc, nc, nc, ctl3215, nc, clk2030, dq2030, cmd3210,
nc, nc, ctl3215, nc, clk2030, clk2030, dq2030, cmd2710
enum {
DQ2030,
DQ2330,
CMD2710,
CMD3210,
CLK2030,
CTL3215,
CTL3220,
NC,
};
static const u32 const * const single_channel_slew_group_lookup[] = {
dq2330, cmd3210, ctl3215, ctl3215, clk2030, clk2030, dq2330, cmd3210,
dq2330, cmd3210, ctl3215, ctl3215, clk2030, clk2030, dq2330, cmd3210,
dq2330, cmd3210, nc, ctl3215, nc, clk2030, dq2330, cmd3210,
dq2330, cmd3210, ctl3215, ctl3215, clk2030, clk2030, dq2330, cmd3210,
dq2330, cmd3210, nc, ctl3215, nc, clk2030, nc, nc,
static const u8 dual_channel_slew_group_lookup[] = {
DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
dq2330, cmd3210, ctl3215, ctl3215, clk2030, clk2030, dq2330, cmd3210,
dq2330, cmd3210, ctl3215, nc, clk2030, nc, dq2330, cmd3210,
dq2330, cmd3210, ctl3215, ctl3215, clk2030, clk2030, dq2330, cmd3210,
dq2330, cmd3210, ctl3215, nc, clk2030, nc, dq2330, cmd3210,
dq2330, cmd3210, ctl3215, nc, clk2030, nc, nc, nc,
DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
dq2330, cmd3210, nc, ctl3215, nc, clk2030, dq2330, cmd3210,
dq2330, cmd3210, ctl3215, ctl3215, clk2030, clk2030, dq2330, cmd3210,
dq2330, cmd3210, nc, ctl3215, nc, clk2030, dq2330, cmd3210,
dq2330, cmd3210, ctl3215, ctl3215, clk2030, clk2030, dq2330, cmd3210,
dq2330, cmd3210, nc, ctl3215, nc, clk2030, nc, nc,
DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
dq2330, cmd3210, ctl3215, ctl3215, clk2030, clk2030, dq2330, cmd3210,
dq2330, cmd3210, ctl3215, nc, clk2030, nc, dq2330, cmd3210,
dq2330, cmd3210, ctl3215, ctl3215, clk2030, clk2030, dq2330, cmd3210,
dq2330, cmd3210, ctl3215, nc, clk2030, nc, dq2330, cmd3210,
dq2330, cmd3210, ctl3215, nc, clk2030, nc, nc, nc,
DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, NC, NC,
dq2330, nc, nc, ctl3215, nc, clk2030, dq2030, cmd3210,
dq2330, nc, ctl3215, nc, clk2030, nc, dq2030, cmd3210,
dq2330, nc, nc, ctl3215, nc, clk2030, dq2030, cmd3210,
dq2330, nc, ctl3215, nc, clk2030, clk2030, dq2030, cmd3210
NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
NC, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
NC, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD2710
};
static const u8 single_channel_slew_group_lookup[] = {
DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
DQ2330, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
DQ2330, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD3210
};
static const u32 *slew_group_lookup(int dual_channel, int index)
{
const u8 *slew_group;
/* Dual Channel needs different tables. */
if (dual_channel)
slew_group = dual_channel_slew_group_lookup;
else
slew_group = single_channel_slew_group_lookup;
switch (slew_group[index]) {
case DQ2030: return dq2030;
case DQ2330: return dq2330;
case CMD2710: return cmd2710;
case CMD3210: return cmd3210;
case CLK2030: return clk2030;
case CTL3215: return ctl3215;
case CTL3220: return ctl3220;
case NC: return nc;
}
return nc;
}
#ifdef CHIPSET_I945GM
/* Strength multiplier tables */
static const u8 dual_channel_strength_multiplier[] = {
0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
@ -1001,10 +1077,67 @@ static void sdram_rcomp_buffer_strength_and_slew(struct sys_info *sysinfo)
0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
0x33, 0x00, 0x11, 0x00, 0x44, 0x44, 0x33, 0x11
};
#endif
#ifdef CHIPSET_I945GC
static const u8 dual_channel_strength_multiplier[] = {
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33
};
static const u8 single_channel_strength_multiplier[] = {
0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00
};
#endif
static void sdram_rcomp_buffer_strength_and_slew(struct sys_info *sysinfo)
{
const u8 * strength_multiplier;
const u32* const * slew_group_lookup;
int idx;
int idx, dual_channel;
/* Set Strength Multipliers */
@ -1012,12 +1145,12 @@ static void sdram_rcomp_buffer_strength_and_slew(struct sys_info *sysinfo)
if (sdram_capabilities_dual_channel()) {
printk_debug("Programming Dual Channel RCOMP\n");
strength_multiplier = dual_channel_strength_multiplier;
slew_group_lookup = dual_channel_slew_group_lookup;
dual_channel = 1;
idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[2];
} else {
printk_debug("Programming Single Channel RCOMP\n");
strength_multiplier = single_channel_strength_multiplier;
slew_group_lookup = single_channel_slew_group_lookup;
dual_channel = 0;
idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[1];
}
@ -1033,22 +1166,22 @@ static void sdram_rcomp_buffer_strength_and_slew(struct sys_info *sysinfo)
MCHBAR8(G8SC) = strength_multiplier[idx * 8 + 7];
/* Channel 0 */
sdram_write_slew_rates(G1SRPUT, slew_group_lookup[idx * 8 + 0]);
sdram_write_slew_rates(G2SRPUT, slew_group_lookup[idx * 8 + 1]);
if ((slew_group_lookup[idx * 8 + 2] != nc) && (sysinfo->package == SYSINFO_PACKAGE_STACKED)) {
sdram_write_slew_rates(G1SRPUT, slew_group_lookup(dual_channel, idx * 8 + 0));
sdram_write_slew_rates(G2SRPUT, slew_group_lookup(dual_channel, idx * 8 + 1));
if ((slew_group_lookup(dual_channel, idx * 8 + 2) != nc) && (sysinfo->package == SYSINFO_PACKAGE_STACKED)) {
sdram_write_slew_rates(G3SRPUT, ctl3220);
} else {
sdram_write_slew_rates(G3SRPUT, slew_group_lookup[idx * 8 + 2]);
sdram_write_slew_rates(G3SRPUT, slew_group_lookup(dual_channel, idx * 8 + 2));
}
sdram_write_slew_rates(G4SRPUT, slew_group_lookup[idx * 8 + 3]);
sdram_write_slew_rates(G5SRPUT, slew_group_lookup[idx * 8 + 4]);
sdram_write_slew_rates(G6SRPUT, slew_group_lookup[idx * 8 + 5]);
sdram_write_slew_rates(G4SRPUT, slew_group_lookup(dual_channel, idx * 8 + 3));
sdram_write_slew_rates(G5SRPUT, slew_group_lookup(dual_channel, idx * 8 + 4));
sdram_write_slew_rates(G6SRPUT, slew_group_lookup(dual_channel, idx * 8 + 5));
/* Channel 1 */
if (sysinfo->dual_channel) {
sdram_write_slew_rates(G7SRPUT, slew_group_lookup[idx * 8 + 6]);
sdram_write_slew_rates(G8SRPUT, slew_group_lookup[idx * 8 + 7]);
sdram_write_slew_rates(G7SRPUT, slew_group_lookup(dual_channel, idx * 8 + 6));
sdram_write_slew_rates(G8SRPUT, slew_group_lookup(dual_channel, idx * 8 + 7));
} else {
sdram_write_slew_rates(G7SRPUT, nc);
sdram_write_slew_rates(G8SRPUT, nc);
@ -1110,6 +1243,7 @@ static void sdram_force_rcomp(void)
reg8 = i945_silicon_revision();
if ((reg8 == 0 && (MCHBAR32(DCC) & (3 << 0)) == 0) || (reg8 == 1)) {
reg32 = MCHBAR32(GBRCOMPCTL);
reg32 |= (3 << 5);
MCHBAR32(GBRCOMPCTL) = reg32;
@ -1352,10 +1486,12 @@ static int sdram_program_row_boundaries(struct sys_info *sysinfo)
if (sysinfo->interleaved)
cum1 = 0;
#if 0
/* Exception: Channel 1 is not populated. C1DRB stays zero */
if (sysinfo->dimm[2] == SYSINFO_DIMM_NOT_POPULATED &&
sysinfo->dimm[3] == SYSINFO_DIMM_NOT_POPULATED)
cum1 = 0;
#endif
for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
cum1 += sysinfo->banksize[i + 4];
@ -1770,12 +1906,9 @@ static void sdram_program_pll_settings(struct sys_info *sysinfo)
MCHBAR32(PLLMON) = 0x80800000;
switch (MCHBAR32(CLKCFG) & 0x7) {
case 0: sysinfo->fsb_frequency = 400; break; /* FSB400 */
case 1: sysinfo->fsb_frequency = 533; break; /* FSB533 */
case 3: sysinfo->fsb_frequency = 667; break; /* FSB667 */
default: die("Unsupported FSB speed");
}
sysinfo->fsb_frequency = fsbclk();
if (sysinfo->fsb_frequency == -1)
die("Unsupported FSB speed");
/* Program CPCTL according to FSB speed */
/* Only write the lower byte */
@ -1918,6 +2051,10 @@ static void sdram_program_memory_frequency(struct sys_info *sysinfo)
{
u32 clkcfg;
u8 reg8;
u8 offset = 0;
#ifdef CHIPSET_I945GM
offset++;
#endif
printk_debug ("Setting Memory Frequency... ");
@ -1939,9 +2076,9 @@ static void sdram_program_memory_frequency(struct sys_info *sysinfo)
}
switch (sysinfo->memory_frequency) {
case 400: clkcfg |= (2 << 4); break;
case 533: clkcfg |= (3 << 4); break;
case 667: clkcfg |= (4 << 4); break;
case 400: clkcfg |= ((1+offset) << 4); break;
case 533: clkcfg |= ((2+offset) << 4); break;
case 667: clkcfg |= ((3+offset) << 4); break;
default: die("Target Memory Frequency Error");
}
@ -1993,52 +2130,126 @@ out:
static void sdram_program_clock_crossing(void)
{
u32 reg32;
int idx = 0;
/**
* We add the indices according to our clocks from CLKCFG.
*/
#ifdef CHIPSET_I945GM
static const u32 data_clock_crossing[] = {
0x00100401, 0x00000000, /* DDR400 FSB400 */
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
0x08040120, 0x00000000, /* DDR400 FSB533 */
0x00100401, 0x00000000, /* DDR533 FSB533 */
0xffffffff, 0xffffffff, /* nonexistant */
0x04020120, 0x00000010, /* DDR400 FSB667 */
0x10040280, 0x00000040, /* DDR533 FSB667 */
0x00100401, 0x00000000 /* DDR667 FSB667 */
0x00100401, 0x00000000, /* DDR667 FSB667 */
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
};
static const u32 command_clock_crossing[] = {
0x04020208, 0x00000000, /* DDR400 FSB400 */
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
0x00060108, 0x00000000, /* DDR400 FSB533 */
0x04020108, 0x00000000, /* DDR533 FSB533 */
0xffffffff, 0xffffffff, /* nonexistant */
0x00040318, 0x00000000, /* DDR400 FSB667 */
0x04020118, 0x00000000, /* DDR533 FSB667 */
0x02010804, 0x00000000 /* DDR667 FSB667 */
0x02010804, 0x00000000, /* DDR667 FSB667 */
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
};
#endif
#ifdef CHIPSET_I945GC
/* i945 G/P */
static const u32 data_clock_crossing[] = {
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
0x10080201, 0x00000000, /* DDR400 FSB533 */
0x00100401, 0x00000000, /* DDR533 FSB533 */
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
0x04020108, 0x00000000, /* DDR400 FSB800 */
0x00020108, 0x00000000, /* DDR533 FSB800 */
0x00080201, 0x00000000, /* DDR667 FSB800 */
0x00010402, 0x00000000, /* DDR400 FSB1066 */
0x04020108, 0x00000000, /* DDR533 FSB1066 */
0x08040110, 0x00000000, /* DDR667 FSB1066 */
};
static const u32 command_clock_crossing[] = {
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
0x00010800, 0x00000402, /* DDR400 FSB533 */
0x01000400, 0x00000200, /* DDR533 FSB533 */
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
0xffffffff, 0xffffffff, /* nonexistant */
0x02010804, 0x00000000, /* DDR400 FSB800 */
0x00010402, 0x00000000, /* DDR533 FSB800 */
0x04020180, 0x00000008, /* DDR667 FSB800 */
0x00020904, 0x00000000, /* DDR400 FSB1066 */
0x02010804, 0x00000000, /* DDR533 FSB1066 */
0x180601c0, 0x00000020, /* DDR667 FSB1066 */
};
#endif
printk_debug("Programming Clock Crossing...");
reg32 = MCHBAR32(CLKCFG);
printk_debug("MEM=");
switch ((reg32 >> 4) & 7) {
case 2: printk_debug("400"); idx += 0; break;
case 3: printk_debug("533"); idx += 2; break;
case 4: printk_debug("667"); idx += 4; break;
default: printk_debug("RSVD\n"); return;
switch (memclk()) {
case 400: printk_debug("400"); idx += 0; break;
case 533: printk_debug("533"); idx += 2; break;
case 667: printk_debug("667"); idx += 4; break;
default: printk_debug("RSVD %x", memclk()); return;
}
printk_debug(" FSB=");
switch (reg32 & 7) {
case 0: printk_debug("400\n"); idx += 0; break;
case 1: printk_debug("533"); idx += 2; break;
case 3: printk_debug("667"); idx += 6; break;
default: printk_debug("RSVD\n"); return;
switch (fsbclk()) {
case 400: printk_debug("400"); idx += 0; break;
case 533: printk_debug("533"); idx += 6; break;
case 667: printk_debug("667"); idx += 12; break;
case 800: printk_debug("800"); idx += 18; break;
case 1066: printk_debug("1066"); idx += 24; break;
default: printk_debug("RSVD %x\n", fsbclk()); return;
}
if (command_clock_crossing[idx]==0xffffffff) {
printk_debug("Invalid MEM/FSB combination!\n");
}
MCHBAR32(CCCFT + 0) = command_clock_crossing[idx];
@ -2560,17 +2771,23 @@ static void sdram_enable_memory_clocks(struct sys_info *sysinfo)
{
u8 clocks[2] = { 0, 0 };
#ifdef CHIPSET_I945GM
#define CLOCKS_WIDTH 2
#endif
#ifdef CHIPSET_I945GC
#define CLOCKS_WIDTH 3
#endif
if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED)
clocks[0] |= (1 << 0) | (1 << 1);
clocks[0] |= (1 << CLOCKS_WIDTH)-1;
if (sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
clocks[0] |= (1 << 2) | (1 << 3);
clocks[0] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED)
clocks[1] |= (1 << 0) | (1 << 1);
clocks[1] |= (1 << CLOCKS_WIDTH)-1;
if (sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
clocks[1] |= (1 << 2) | (1 << 3);
clocks[1] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
#ifdef OVERRIDE_CLOCK_DISABLE
/* Usually system firmware turns off system memory clock signals