Alot of it is trivial clean ups and 830 is now able to initialize one row/side of memory at a time.
Signed-off-by: Joseph Smith <joe@settoplinux.org> Acked-by: Stefan Reinauer <stepan@coresystems.de> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5073 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
parent
14be4d0d52
commit
fa742da56b
|
@ -69,7 +69,6 @@ static inline int spd_read_byte(unsigned device, unsigned address)
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "northbridge/intel/i82830/raminit.c"
|
#include "northbridge/intel/i82830/raminit.c"
|
||||||
#include "lib/generic_sdram.c"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup mainboard specific registers pre raminit.
|
* Setup mainboard specific registers pre raminit.
|
||||||
|
@ -103,13 +102,6 @@ static void mb_early_setup(void)
|
||||||
|
|
||||||
static void main(unsigned long bist)
|
static void main(unsigned long bist)
|
||||||
{
|
{
|
||||||
static const struct mem_controller memctrl[] = {
|
|
||||||
{
|
|
||||||
.d0 = PCI_DEV(0, 0, 0),
|
|
||||||
.channel0 = {0x50, 0x51},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (bist == 0)
|
if (bist == 0)
|
||||||
early_mtrr_init();
|
early_mtrr_init();
|
||||||
if (memory_initialized()) {
|
if (memory_initialized()) {
|
||||||
|
@ -129,10 +121,8 @@ static void main(unsigned long bist)
|
||||||
/* Setup mainboard specific registers */
|
/* Setup mainboard specific registers */
|
||||||
mb_early_setup();
|
mb_early_setup();
|
||||||
|
|
||||||
/* SDRAM init */
|
/* Initialize memory */
|
||||||
sdram_set_registers(memctrl);
|
sdram_initialize();
|
||||||
sdram_set_spd_registers(memctrl);
|
|
||||||
sdram_enable(0, memctrl);
|
|
||||||
|
|
||||||
/* Check RAM. */
|
/* Check RAM. */
|
||||||
/* ram_check(0, 640 * 1024); */
|
/* ram_check(0, 640 * 1024); */
|
||||||
|
|
|
@ -69,7 +69,6 @@ static inline int spd_read_byte(unsigned device, unsigned address)
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "northbridge/intel/i82830/raminit.c"
|
#include "northbridge/intel/i82830/raminit.c"
|
||||||
#include "lib/generic_sdram.c"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup mainboard specific registers pre raminit.
|
* Setup mainboard specific registers pre raminit.
|
||||||
|
@ -103,13 +102,6 @@ static void mb_early_setup(void)
|
||||||
|
|
||||||
static void main(unsigned long bist)
|
static void main(unsigned long bist)
|
||||||
{
|
{
|
||||||
static const struct mem_controller memctrl[] = {
|
|
||||||
{
|
|
||||||
.d0 = PCI_DEV(0, 0, 0),
|
|
||||||
.channel0 = {0x50, 0x51},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (bist == 0)
|
if (bist == 0)
|
||||||
early_mtrr_init();
|
early_mtrr_init();
|
||||||
if (memory_initialized()) {
|
if (memory_initialized()) {
|
||||||
|
@ -129,10 +121,8 @@ static void main(unsigned long bist)
|
||||||
/* Setup mainboard specific registers */
|
/* Setup mainboard specific registers */
|
||||||
mb_early_setup();
|
mb_early_setup();
|
||||||
|
|
||||||
/* SDRAM init */
|
/* Initialize memory */
|
||||||
sdram_set_registers(memctrl);
|
sdram_initialize();
|
||||||
sdram_set_spd_registers(memctrl);
|
|
||||||
sdram_enable(0, memctrl);
|
|
||||||
|
|
||||||
/* Check RAM. */
|
/* Check RAM. */
|
||||||
/* ram_check(0, 640 * 1024); */
|
/* ram_check(0, 640 * 1024); */
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the coreboot project.
|
* This file is part of the coreboot project.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2008 Joseph Smith <joe@smittys.pointclark.net>
|
* Copyright (C) 2008-2010 Joseph Smith <joe@settoplinux.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -67,41 +67,122 @@ Macros and definitions.
|
||||||
#define RAM_COMMAND_IC 0x1
|
#define RAM_COMMAND_IC 0x1
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
/*-----------------------------------------------------------------------------
|
||||||
SDRAM configuration functions.
|
DIMM-initialization functions.
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/* Send the specified RAM command to all DIMMs. */
|
static void do_ram_command(uint32_t command)
|
||||||
|
|
||||||
static void do_ram_command(const struct mem_controller *ctrl, uint32_t command,
|
|
||||||
uint32_t addr_offset)
|
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
uint8_t dimm_start, dimm_end;
|
|
||||||
uint32_t reg32;
|
uint32_t reg32;
|
||||||
|
|
||||||
/* Configure the RAM command. */
|
/* Configure the RAM command. */
|
||||||
reg32 = pci_read_config32(ctrl->d0, DRC);
|
reg32 = pci_read_config32(NORTHBRIDGE, DRC);
|
||||||
/* Clear bits 29, 10-8, 6-4. */
|
/* Clear bits 29, 10-8, 6-4. */
|
||||||
reg32 &= 0xdffff88f;
|
reg32 &= 0xdffff88f;
|
||||||
reg32 |= command << 4;
|
reg32 |= command << 4;
|
||||||
pci_write_config32(ctrl->d0, DRC, reg32);
|
pci_write_config32(NORTHBRIDGE, DRC, reg32);
|
||||||
|
PRINT_DEBUG("RAM command 0x");
|
||||||
|
PRINT_DEBUG_HEX32(reg32);
|
||||||
|
PRINT_DEBUG("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ram_read32(uint8_t dimm_start, uint32_t offset)
|
||||||
|
{
|
||||||
|
if (offset == 0x55aa55aa) {
|
||||||
|
PRINT_DEBUG(" Reading RAM at 0x");
|
||||||
|
PRINT_DEBUG_HEX32(dimm_start * 32 * 1024 * 1024);
|
||||||
|
PRINT_DEBUG(" => 0x");
|
||||||
|
PRINT_DEBUG_HEX32(read32(dimm_start * 32 * 1024 * 1024));
|
||||||
|
PRINT_DEBUG("\r\n");
|
||||||
|
|
||||||
|
PRINT_DEBUG(" Writing RAM at 0x");
|
||||||
|
PRINT_DEBUG_HEX32(dimm_start * 32 * 1024 * 1024);
|
||||||
|
PRINT_DEBUG(" <= 0x");
|
||||||
|
PRINT_DEBUG_HEX32(offset);
|
||||||
|
PRINT_DEBUG("\r\n");
|
||||||
|
write32(dimm_start * 32 * 1024 * 1024, offset);
|
||||||
|
|
||||||
|
PRINT_DEBUG(" Reading RAM at 0x");
|
||||||
|
PRINT_DEBUG_HEX32(dimm_start * 32 * 1024 * 1024);
|
||||||
|
PRINT_DEBUG(" => 0x");
|
||||||
|
PRINT_DEBUG_HEX32(read32(dimm_start * 32 * 1024 * 1024));
|
||||||
|
PRINT_DEBUG("\r\n");
|
||||||
|
} else {
|
||||||
|
PRINT_DEBUG(" Sending RAM command to 0x");
|
||||||
|
PRINT_DEBUG_HEX32((dimm_start * 32 * 1024 * 1024) + offset);
|
||||||
|
PRINT_DEBUG("\r\n");
|
||||||
|
read32((dimm_start * 32 * 1024 * 1024) + offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void initialize_dimm_rows(void)
|
||||||
|
{
|
||||||
|
int i, row;
|
||||||
|
uint8_t dimm_start, dimm_end;
|
||||||
|
unsigned device;
|
||||||
|
|
||||||
/* Send the ram command to each row of memory.
|
|
||||||
* (DIMM_SOCKETS * 2) is the maximum number of rows possible.
|
|
||||||
* Note: Each DRB defines the upper boundary address of
|
|
||||||
* each SDRAM row in 32-MB granularity.
|
|
||||||
*/
|
|
||||||
dimm_start = 0;
|
dimm_start = 0;
|
||||||
|
|
||||||
for (i = 0; i < (DIMM_SOCKETS * 2); i++) {
|
for (row = 0; row < (DIMM_SOCKETS * 2); row++) {
|
||||||
dimm_end = pci_read_config8(ctrl->d0, DRB + i);
|
|
||||||
|
switch (row) {
|
||||||
|
case 0:
|
||||||
|
device = DIMM_SPD_BASE;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
device = DIMM_SPD_BASE;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
device = DIMM_SPD_BASE + 1;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
device = DIMM_SPD_BASE + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dimm_end = pci_read_config8(NORTHBRIDGE, DRB + row);
|
||||||
|
|
||||||
if (dimm_end > dimm_start) {
|
if (dimm_end > dimm_start) {
|
||||||
PRINT_DEBUG(" Sending RAM command 0x");
|
print_debug("Initializing SDRAM Row ");
|
||||||
PRINT_DEBUG_HEX32(reg32);
|
print_debug_hex8(row);
|
||||||
PRINT_DEBUG(" to 0x");
|
print_debug("\r\n");
|
||||||
PRINT_DEBUG_HEX32((dimm_start * 32 * 1024 * 1024) + addr_offset);
|
|
||||||
PRINT_DEBUG("\r\n");
|
/* NOP command */
|
||||||
read32((dimm_start * 32 * 1024 * 1024) + addr_offset);
|
PRINT_DEBUG(" NOP ");
|
||||||
|
do_ram_command(RAM_COMMAND_NOP);
|
||||||
|
ram_read32(dimm_start, 0);
|
||||||
|
udelay(200);
|
||||||
|
|
||||||
|
/* Pre-charge all banks (at least 200 us after NOP) */
|
||||||
|
PRINT_DEBUG(" Pre-charging all banks ");
|
||||||
|
do_ram_command(RAM_COMMAND_PRECHARGE);
|
||||||
|
ram_read32(dimm_start, 0);
|
||||||
|
udelay(1);
|
||||||
|
|
||||||
|
/* 8 CBR refreshes (Auto Refresh) */
|
||||||
|
PRINT_DEBUG(" 8 CBR refreshes ");
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
do_ram_command(RAM_COMMAND_CBR);
|
||||||
|
ram_read32(dimm_start, 0);
|
||||||
|
udelay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MRS command */
|
||||||
|
/* TODO: Set offset 0x1d0 according to DRT values */
|
||||||
|
PRINT_DEBUG(" MRS ");
|
||||||
|
do_ram_command(RAM_COMMAND_MRS);
|
||||||
|
ram_read32(dimm_start, 0x1d0);
|
||||||
|
udelay(2);
|
||||||
|
|
||||||
|
/* Set GMCH-M Mode Select bits back to NORMAL operation mode */
|
||||||
|
PRINT_DEBUG(" Normal operation mode ");
|
||||||
|
do_ram_command(RAM_COMMAND_NORMAL);
|
||||||
|
ram_read32(dimm_start, 0);
|
||||||
|
udelay(1);
|
||||||
|
|
||||||
|
/* Perform a dummy memory read/write cycle */
|
||||||
|
PRINT_DEBUG(" Performing dummy read/write\r\n");
|
||||||
|
ram_read32(dimm_start, 0x55aa55aa);
|
||||||
|
udelay(1);
|
||||||
}
|
}
|
||||||
/* Set the start of the next DIMM. */
|
/* Set the start of the next DIMM. */
|
||||||
dimm_start = dimm_end;
|
dimm_start = dimm_end;
|
||||||
|
@ -122,8 +203,8 @@ static struct dimm_size spd_get_dimm_size(unsigned device)
|
||||||
struct dimm_size sz;
|
struct dimm_size sz;
|
||||||
int i, module_density, dimm_banks;
|
int i, module_density, dimm_banks;
|
||||||
sz.side1 = 0;
|
sz.side1 = 0;
|
||||||
module_density = spd_read_byte(device, 31);
|
module_density = spd_read_byte(device, SPD_DENSITY_OF_EACH_ROW_ON_MODULE);
|
||||||
dimm_banks = spd_read_byte(device, 5);
|
dimm_banks = spd_read_byte(device, SPD_NUM_DIMM_BANKS);
|
||||||
|
|
||||||
/* Find the size of side1. */
|
/* Find the size of side1. */
|
||||||
/* Find the larger value. The larger value is always side1. */
|
/* Find the larger value. The larger value is always side1. */
|
||||||
|
@ -163,19 +244,19 @@ static struct dimm_size spd_get_dimm_size(unsigned device)
|
||||||
return sz;
|
return sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spd_set_dram_size(const struct mem_controller *ctrl)
|
static void set_dram_row_boundaries(void)
|
||||||
{
|
{
|
||||||
int i, value, drb1, drb2;
|
int i, value, drb1, drb2;
|
||||||
|
|
||||||
for (i = 0; i < DIMM_SOCKETS; i++) {
|
for (i = 0; i < DIMM_SOCKETS; i++) {
|
||||||
struct dimm_size sz;
|
struct dimm_size sz;
|
||||||
unsigned device;
|
unsigned device;
|
||||||
device = ctrl->channel0[i];
|
device = DIMM_SPD_BASE + i;
|
||||||
drb1 = 0;
|
drb1 = 0;
|
||||||
drb2 = 0;
|
drb2 = 0;
|
||||||
|
|
||||||
/* First check if a DIMM is actually present. */
|
/* First check if a DIMM is actually present. */
|
||||||
if (spd_read_byte(device, 2) == 0x4) {
|
if (spd_read_byte(device, SPD_MEMORY_TYPE) == 0x4) {
|
||||||
print_debug("Found DIMM in slot ");
|
print_debug("Found DIMM in slot ");
|
||||||
print_debug_hex8(i);
|
print_debug_hex8(i);
|
||||||
print_debug("\r\n");
|
print_debug("\r\n");
|
||||||
|
@ -190,14 +271,15 @@ static void spd_set_dram_size(const struct mem_controller *ctrl)
|
||||||
print_debug_hex16(sz.side2);
|
print_debug_hex16(sz.side2);
|
||||||
print_debug(" on side 2\r\n");
|
print_debug(" on side 2\r\n");
|
||||||
|
|
||||||
|
/* - Memory compatibility checks - */
|
||||||
/* Test for PC133 (i82830 only supports PC133) */
|
/* Test for PC133 (i82830 only supports PC133) */
|
||||||
/* PC133 SPD9 - cycle time is always 75 */
|
/* PC133 SPD9 - cycle time is always 75 */
|
||||||
if (spd_read_byte(device, 9) != 0x75) {
|
if (spd_read_byte(device, SPD_MIN_CYCLE_TIME_AT_CAS_MAX) != 0x75) {
|
||||||
print_err("SPD9 DIMM Is Not PC133 Compatable\r\n");
|
print_err("SPD9 DIMM Is Not PC133 Compatable\r\n");
|
||||||
die("HALT\r\n");
|
die("HALT\r\n");
|
||||||
}
|
}
|
||||||
/* PC133 SPD10 - access time is always 54 */
|
/* PC133 SPD10 - access time is always 54 */
|
||||||
if (spd_read_byte(device, 10) != 0x54) {
|
if (spd_read_byte(device, SPD_ACCESS_TIME_FROM_CLOCK) != 0x54) {
|
||||||
print_err("SPD10 DIMM Is Not PC133 Compatable\r\n");
|
print_err("SPD10 DIMM Is Not PC133 Compatable\r\n");
|
||||||
die("HALT\r\n");
|
die("HALT\r\n");
|
||||||
}
|
}
|
||||||
|
@ -225,6 +307,7 @@ static void spd_set_dram_size(const struct mem_controller *ctrl)
|
||||||
("are not supported on this northbridge\r\n");
|
("are not supported on this northbridge\r\n");
|
||||||
die("HALT\r\n");
|
die("HALT\r\n");
|
||||||
}
|
}
|
||||||
|
/* - End Memory compatibility checks - */
|
||||||
|
|
||||||
/* We need to divide size by 32 to set up the
|
/* We need to divide size by 32 to set up the
|
||||||
* DRB registers.
|
* DRB registers.
|
||||||
|
@ -244,8 +327,8 @@ static void spd_set_dram_size(const struct mem_controller *ctrl)
|
||||||
}
|
}
|
||||||
/* Set the value for DRAM Row Boundary Registers */
|
/* Set the value for DRAM Row Boundary Registers */
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
pci_write_config8(ctrl->d0, DRB, drb1);
|
pci_write_config8(NORTHBRIDGE, DRB, drb1);
|
||||||
pci_write_config8(ctrl->d0, DRB + 1, drb1 + drb2);
|
pci_write_config8(NORTHBRIDGE, DRB + 1, drb1 + drb2);
|
||||||
PRINT_DEBUG("DRB 0x");
|
PRINT_DEBUG("DRB 0x");
|
||||||
PRINT_DEBUG_HEX8(DRB);
|
PRINT_DEBUG_HEX8(DRB);
|
||||||
PRINT_DEBUG(" has been set to 0x");
|
PRINT_DEBUG(" has been set to 0x");
|
||||||
|
@ -257,10 +340,9 @@ static void spd_set_dram_size(const struct mem_controller *ctrl)
|
||||||
PRINT_DEBUG_HEX8(drb1 + drb2);
|
PRINT_DEBUG_HEX8(drb1 + drb2);
|
||||||
PRINT_DEBUG("\r\n");
|
PRINT_DEBUG("\r\n");
|
||||||
} else if (i == 1) {
|
} else if (i == 1) {
|
||||||
value = pci_read_config8(ctrl->d0, DRB + 1);
|
value = pci_read_config8(NORTHBRIDGE, DRB + 1);
|
||||||
pci_write_config8(ctrl->d0, DRB + 2, value + drb1);
|
pci_write_config8(NORTHBRIDGE, DRB + 2, value + drb1);
|
||||||
pci_write_config8(ctrl->d0, DRB + 3,
|
pci_write_config8(NORTHBRIDGE, DRB + 3, value + drb1 + drb2);
|
||||||
value + drb1 + drb2);
|
|
||||||
PRINT_DEBUG("DRB2 0x");
|
PRINT_DEBUG("DRB2 0x");
|
||||||
PRINT_DEBUG_HEX8(DRB + 2);
|
PRINT_DEBUG_HEX8(DRB + 2);
|
||||||
PRINT_DEBUG(" has been set to 0x");
|
PRINT_DEBUG(" has been set to 0x");
|
||||||
|
@ -276,23 +358,23 @@ static void spd_set_dram_size(const struct mem_controller *ctrl)
|
||||||
* These are supposed to be "Reserved" but memory will
|
* These are supposed to be "Reserved" but memory will
|
||||||
* not initialize properly if we don't.
|
* not initialize properly if we don't.
|
||||||
*/
|
*/
|
||||||
value = pci_read_config8(ctrl->d0, DRB + 3);
|
value = pci_read_config8(NORTHBRIDGE, DRB + 3);
|
||||||
pci_write_config8(ctrl->d0, DRB + 4, value);
|
pci_write_config8(NORTHBRIDGE, DRB + 4, value);
|
||||||
pci_write_config8(ctrl->d0, DRB + 5, value);
|
pci_write_config8(NORTHBRIDGE, DRB + 5, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_dram_row_attributes(const struct mem_controller *ctrl)
|
static void set_dram_row_attributes(void)
|
||||||
{
|
{
|
||||||
int i, dra, col, width, value;
|
int i, dra, col, width, value;
|
||||||
|
|
||||||
for (i = 0; i < DIMM_SOCKETS; i++) {
|
for (i = 0; i < DIMM_SOCKETS; i++) {
|
||||||
unsigned device;
|
unsigned device;
|
||||||
device = ctrl->channel0[i];
|
device = DIMM_SPD_BASE + i;
|
||||||
|
|
||||||
/* First check if a DIMM is actually present. */
|
/* First check if a DIMM is actually present. */
|
||||||
if (spd_read_byte(device, 2) == 0x4) {
|
if (spd_read_byte(device, SPD_MEMORY_TYPE) == 0x4) {
|
||||||
print_debug("Found DIMM in slot ");
|
print_debug("Found DIMM in slot ");
|
||||||
print_debug_hex8(i);
|
print_debug_hex8(i);
|
||||||
print_debug(", setting DRA...\r\n");
|
print_debug(", setting DRA...\r\n");
|
||||||
|
@ -300,10 +382,10 @@ static void set_dram_row_attributes(const struct mem_controller *ctrl)
|
||||||
dra = 0x00;
|
dra = 0x00;
|
||||||
|
|
||||||
/* columns */
|
/* columns */
|
||||||
col = spd_read_byte(device, 4);
|
col = spd_read_byte(device, SPD_NUM_COLUMNS);
|
||||||
|
|
||||||
/* data width */
|
/* data width */
|
||||||
width = spd_read_byte(device, 6);
|
width = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB);
|
||||||
|
|
||||||
/* calculate page size in bits */
|
/* calculate page size in bits */
|
||||||
value = ((1 << col) * width);
|
value = ((1 << col) * width);
|
||||||
|
@ -312,7 +394,7 @@ static void set_dram_row_attributes(const struct mem_controller *ctrl)
|
||||||
dra = ((value / 8) >> 10);
|
dra = ((value / 8) >> 10);
|
||||||
|
|
||||||
/* # of banks of DIMM (single or double sided) */
|
/* # of banks of DIMM (single or double sided) */
|
||||||
value = spd_read_byte(device, 5);
|
value = spd_read_byte(device, SPD_NUM_DIMM_BANKS);
|
||||||
|
|
||||||
if (value == 1) {
|
if (value == 1) {
|
||||||
if (dra == 2) {
|
if (dra == 2) {
|
||||||
|
@ -355,7 +437,7 @@ static void set_dram_row_attributes(const struct mem_controller *ctrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the value for DRAM Row Attribute Registers */
|
/* Set the value for DRAM Row Attribute Registers */
|
||||||
pci_write_config8(ctrl->d0, DRA + i, dra);
|
pci_write_config8(NORTHBRIDGE, DRA + i, dra);
|
||||||
PRINT_DEBUG("DRA 0x");
|
PRINT_DEBUG("DRA 0x");
|
||||||
PRINT_DEBUG_HEX8(DRA + i);
|
PRINT_DEBUG_HEX8(DRA + i);
|
||||||
PRINT_DEBUG(" has been set to 0x");
|
PRINT_DEBUG(" has been set to 0x");
|
||||||
|
@ -364,14 +446,14 @@ static void set_dram_row_attributes(const struct mem_controller *ctrl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_dram_timing(const struct mem_controller *ctrl)
|
static void set_dram_timing(void)
|
||||||
{
|
{
|
||||||
/* Set the value for DRAM Timing Register */
|
/* Set the value for DRAM Timing Register */
|
||||||
/* TODO: Configure the value according to SPD values. */
|
/* TODO: Configure the value according to SPD values. */
|
||||||
pci_write_config32(ctrl->d0, DRT, 0x00000010);
|
pci_write_config32(NORTHBRIDGE, DRT, 0x00000010);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_dram_buffer_strength(const struct mem_controller *ctrl)
|
static void set_dram_buffer_strength(void)
|
||||||
{
|
{
|
||||||
/* TODO: This needs to be set according to the DRAM tech
|
/* TODO: This needs to be set according to the DRAM tech
|
||||||
* (x8, x16, or x32). Argh, Intel provides no docs on this!
|
* (x8, x16, or x32). Argh, Intel provides no docs on this!
|
||||||
|
@ -380,22 +462,61 @@ static void set_dram_buffer_strength(const struct mem_controller *ctrl)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Set the value for System Memory Buffer Strength Control Registers */
|
/* Set the value for System Memory Buffer Strength Control Registers */
|
||||||
pci_write_config32(ctrl->d0, BUFF_SC, 0xFC9B491B);
|
pci_write_config32(NORTHBRIDGE, BUFF_SC, 0xFC9B491B);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
/*-----------------------------------------------------------------------------
|
||||||
Public interface.
|
Public interface.
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static void sdram_set_registers(const struct mem_controller *ctrl)
|
static void sdram_set_registers(void)
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("Setting initial sdram registers....\r\n");
|
||||||
|
|
||||||
|
/* Calculate the value for DRT DRAM Timing Register */
|
||||||
|
set_dram_timing();
|
||||||
|
|
||||||
|
/* Setup System Memory Buffer Strength Control Registers */
|
||||||
|
set_dram_buffer_strength();
|
||||||
|
|
||||||
|
/* Setup DRAM Row Boundary Registers */
|
||||||
|
set_dram_row_boundaries();
|
||||||
|
|
||||||
|
/* Setup DRAM Row Attribute Registers */
|
||||||
|
set_dram_row_attributes();
|
||||||
|
|
||||||
|
PRINT_DEBUG("Initial sdram registers have been set.\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void northbridge_set_registers(void)
|
||||||
{
|
{
|
||||||
uint16_t value;
|
uint16_t value;
|
||||||
int igd_memory = 0;
|
int igd_memory = 0;
|
||||||
|
|
||||||
PRINT_DEBUG("Setting initial registers....\r\n");
|
PRINT_DEBUG("Setting initial nothbridge registers....\r\n");
|
||||||
|
|
||||||
|
/* Set the value for Fixed DRAM Hole Control Register */
|
||||||
|
pci_write_config8(NORTHBRIDGE, FDHC, 0x00);
|
||||||
|
|
||||||
|
/* Set the value for Programable Attribute Map Registers
|
||||||
|
* Ideally, this should be R/W for as many ranges as possible.
|
||||||
|
*/
|
||||||
|
pci_write_config8(NORTHBRIDGE, PAM0, 0x30);
|
||||||
|
pci_write_config8(NORTHBRIDGE, PAM1, 0x33);
|
||||||
|
pci_write_config8(NORTHBRIDGE, PAM2, 0x33);
|
||||||
|
pci_write_config8(NORTHBRIDGE, PAM3, 0x33);
|
||||||
|
pci_write_config8(NORTHBRIDGE, PAM4, 0x33);
|
||||||
|
pci_write_config8(NORTHBRIDGE, PAM5, 0x33);
|
||||||
|
pci_write_config8(NORTHBRIDGE, PAM6, 0x33);
|
||||||
|
|
||||||
|
/* Set the value for System Management RAM Control Register */
|
||||||
|
pci_write_config8(NORTHBRIDGE, SMRAM, 0x02);
|
||||||
|
|
||||||
/* Set the value for GMCH Control Register #0 */
|
/* Set the value for GMCH Control Register #0 */
|
||||||
pci_write_config16(ctrl->d0, GCC0, 0xA072);
|
pci_write_config16(NORTHBRIDGE, GCC0, 0xA072);
|
||||||
|
|
||||||
|
/* Set the value for Aperture Base Configuration Register */
|
||||||
|
pci_write_config32(NORTHBRIDGE, APBASE, 0x00000008);
|
||||||
|
|
||||||
/* Set the value for GMCH Control Register #1 */
|
/* Set the value for GMCH Control Register #1 */
|
||||||
switch (CONFIG_VIDEO_MB) {
|
switch (CONFIG_VIDEO_MB) {
|
||||||
|
@ -409,95 +530,45 @@ static void sdram_set_registers(const struct mem_controller *ctrl)
|
||||||
igd_memory = 0x4;
|
igd_memory = 0x4;
|
||||||
break;
|
break;
|
||||||
default: /* No memory */
|
default: /* No memory */
|
||||||
pci_write_config16(ctrl->d0, GCC1, 0x0002);
|
pci_write_config16(NORTHBRIDGE, GCC1, 0x0002);
|
||||||
igd_memory = 0x0;
|
igd_memory = 0x0;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = pci_read_config16(ctrl->d0, GCC1);
|
value = pci_read_config16(NORTHBRIDGE, GCC1);
|
||||||
value |= igd_memory << 4;
|
value |= igd_memory << 4;
|
||||||
pci_write_config16(ctrl->d0, GCC1, value);
|
pci_write_config16(NORTHBRIDGE, GCC1, value);
|
||||||
|
|
||||||
/* Set the value for Aperture Base Configuration Register */
|
PRINT_DEBUG("Initial northbridge registers have been set.\r\n");
|
||||||
pci_write_config32(ctrl->d0, APBASE, 0x00000008);
|
|
||||||
|
|
||||||
/* Set the value for Register Range Base Address Register */
|
|
||||||
pci_write_config32(ctrl->d0, RRBAR, 0x00000000);
|
|
||||||
|
|
||||||
/* Set the value for Fixed DRAM Hole Control Register */
|
|
||||||
pci_write_config8(ctrl->d0, FDHC, 0x00);
|
|
||||||
|
|
||||||
/* Set the value for Programable Attribute Map Registers
|
|
||||||
* Ideally, this should be R/W for as many ranges as possible.
|
|
||||||
*/
|
|
||||||
pci_write_config8(ctrl->d0, PAM0, 0x30);
|
|
||||||
pci_write_config8(ctrl->d0, PAM1, 0x33);
|
|
||||||
pci_write_config8(ctrl->d0, PAM2, 0x33);
|
|
||||||
pci_write_config8(ctrl->d0, PAM3, 0x33);
|
|
||||||
pci_write_config8(ctrl->d0, PAM4, 0x33);
|
|
||||||
pci_write_config8(ctrl->d0, PAM5, 0x33);
|
|
||||||
pci_write_config8(ctrl->d0, PAM6, 0x33);
|
|
||||||
|
|
||||||
/* Set the value for DRAM Throttling Control Register */
|
|
||||||
pci_write_config32(ctrl->d0, DTC, 0x00000000);
|
|
||||||
|
|
||||||
/* Set the value for System Management RAM Control Register */
|
|
||||||
pci_write_config8(ctrl->d0, SMRAM, 0x02);
|
|
||||||
|
|
||||||
/* Set the value for Extended System Management RAM Control Register */
|
|
||||||
pci_write_config8(ctrl->d0, ESMRAMC, 0x38);
|
|
||||||
|
|
||||||
PRINT_DEBUG("Initial registers have been set.\r\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sdram_set_spd_registers(const struct mem_controller *ctrl)
|
static void sdram_initialize(void)
|
||||||
{
|
|
||||||
spd_set_dram_size(ctrl);
|
|
||||||
set_dram_row_attributes(ctrl);
|
|
||||||
set_dram_timing(ctrl);
|
|
||||||
set_dram_buffer_strength(ctrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sdram_enable(int controllers, const struct mem_controller *ctrl)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
uint32_t reg32;
|
uint32_t reg32;
|
||||||
|
|
||||||
|
/* Setup Initial SDRAM Registers */
|
||||||
|
sdram_set_registers();
|
||||||
|
|
||||||
/* 0. Wait until power/voltages and clocks are stable (200us). */
|
/* 0. Wait until power/voltages and clocks are stable (200us). */
|
||||||
udelay(200);
|
udelay(200);
|
||||||
|
|
||||||
/* 1. Apply NOP. */
|
/* Initialize each row of memory one at a time */
|
||||||
PRINT_DEBUG("RAM Enable 1: Apply NOP\r\n");
|
initialize_dimm_rows();
|
||||||
do_ram_command(ctrl, RAM_COMMAND_NOP, 0);
|
|
||||||
udelay(200);
|
|
||||||
|
|
||||||
/* 2. Precharge all. Wait tRP. */
|
/* Enable Refresh */
|
||||||
PRINT_DEBUG("RAM Enable 2: Precharge all\r\n");
|
PRINT_DEBUG("Enabling Refresh\r\n");
|
||||||
do_ram_command(ctrl, RAM_COMMAND_PRECHARGE, 0);
|
reg32 = pci_read_config32(NORTHBRIDGE, DRC);
|
||||||
udelay(1);
|
reg32 |= (RAM_COMMAND_REFRESH << 8);
|
||||||
|
pci_write_config32(NORTHBRIDGE, DRC, reg32);
|
||||||
|
|
||||||
/* 3. Perform 8 refresh cycles. Wait tRC each time. */
|
/* Set initialization complete */
|
||||||
PRINT_DEBUG("RAM Enable 3: CBR\r\n");
|
PRINT_DEBUG("Setting initialization complete\r\n");
|
||||||
for (i = 0; i < 8; i++) {
|
reg32 = pci_read_config32(NORTHBRIDGE, DRC);
|
||||||
do_ram_command(ctrl, RAM_COMMAND_CBR, 0);
|
reg32 |= (RAM_COMMAND_IC << 29);
|
||||||
udelay(1);
|
pci_write_config32(NORTHBRIDGE, DRC, reg32);
|
||||||
}
|
|
||||||
|
|
||||||
/* 4. Mode register set. Wait two memory cycles. */
|
/* Setup Initial Northbridge Registers */
|
||||||
/* TODO: Set offset according to DRT values */
|
northbridge_set_registers();
|
||||||
PRINT_DEBUG("RAM Enable 4: Mode register set\r\n");
|
|
||||||
do_ram_command(ctrl, RAM_COMMAND_MRS, 0x1d0);
|
|
||||||
udelay(2);
|
|
||||||
|
|
||||||
/* 5. Normal operation (enables refresh) */
|
|
||||||
PRINT_DEBUG("RAM Enable 5: Normal operation\r\n");
|
|
||||||
do_ram_command(ctrl, RAM_COMMAND_NORMAL, 0);
|
|
||||||
udelay(1);
|
|
||||||
|
|
||||||
/* 6. Enable refresh and Set initialization complete. */
|
|
||||||
PRINT_DEBUG("RAM Enable 6: Enable Refresh and IC\r\n");
|
|
||||||
reg32 = pci_read_config32(ctrl->d0, DRC);
|
|
||||||
reg32 |= ((RAM_COMMAND_REFRESH << 8) | (RAM_COMMAND_IC << 29));
|
|
||||||
pci_write_config32(ctrl->d0, DRC, reg32);
|
|
||||||
|
|
||||||
PRINT_DEBUG("Northbridge following SDRAM init:\r\n");
|
PRINT_DEBUG("Northbridge following SDRAM init:\r\n");
|
||||||
DUMPNORTH();
|
DUMPNORTH();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the coreboot project.
|
* This file is part of the coreboot project.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2008 Joseph Smith <joe@smittys.pointclark.net>
|
* Copyright (C) 2008-2010 Joseph Smith <joe@settoplinux.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -21,12 +21,13 @@
|
||||||
#ifndef NORTHBRIDGE_INTEL_I82830_RAMINIT_H
|
#ifndef NORTHBRIDGE_INTEL_I82830_RAMINIT_H
|
||||||
#define NORTHBRIDGE_INTEL_I82830_RAMINIT_H
|
#define NORTHBRIDGE_INTEL_I82830_RAMINIT_H
|
||||||
|
|
||||||
|
/* 82830 Northbridge PCI device */
|
||||||
|
#define NORTHBRIDGE PCI_DEV(0, 0, 0)
|
||||||
|
|
||||||
/* The 82830 supports max. 2 dual-sided SO-DIMMs. */
|
/* The 82830 supports max. 2 dual-sided SO-DIMMs. */
|
||||||
#define DIMM_SOCKETS 2
|
#define DIMM_SOCKETS 2
|
||||||
|
|
||||||
struct mem_controller {
|
/* DIMM0 is at 0x50, DIMM1 is at 0x51. */
|
||||||
device_t d0;
|
#define DIMM_SPD_BASE 0x50
|
||||||
uint16_t channel0[DIMM_SOCKETS];
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* NORTHBRIDGE_INTEL_I82830_RAMINIT_H */
|
#endif /* NORTHBRIDGE_INTEL_I82830_RAMINIT_H */
|
||||||
|
|
Loading…
Reference in New Issue