![]() |
coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
|
#include <stdint.h>
#include <device/pci_def.h>
#include <arch/io.h>
#include <device/mmio.h>
#include <device/pci_ops.h>
#include <device/smbus_host.h>
#include <lib.h>
#include <commonlib/helpers.h>
#include <console/console.h>
#include <assert.h>
#include <spd.h>
#include <sdram_mode.h>
#include <timestamp.h>
#include "raminit.h"
#include "e7505.h"
Go to the source code of this file.
Data Structures | |
struct | dimm_size |
Macros | |
#define | RAM_DEBUG_MESSAGE(x) |
#define | RAM_DEBUG_HEX32(x) |
#define | RAM_DEBUG_HEX8(x) |
#define | E7501_SDRAM_MODE (SDRAM_BURST_INTERLEAVED | SDRAM_BURST_4) |
#define | SPD_ERROR "Error reading SPD info\n" |
#define | MCHDEV PCI_DEV(0, 0, 0) |
#define | RASDEV PCI_DEV(0, 0, 1) |
#define | AGPDEV PCI_DEV(0, 1, 0) |
#define | D060DEV PCI_DEV(0, 6, 0) |
#define | RCOMP_MMIO ((u8 *)0x200000) |
#define | MAX_SPD_REFRESH_RATE (ARRAY_SIZE(refresh_rate_map) - 1) |
#define | SLOW_DOWN_IO inb(0x80) |
#define | DO_DELAY local_udelay(200) |
#define | EXTRA_DELAY DO_DELAY |
Enumerations | |
enum | mchtst_cc { MCHTST_CMD_0 , D060_ENABLE , D060_DISABLE , RCOMP_BAR_ENABLE , RCOMP_BAR_DISABLE } |
enum | d060_cc { D060_CMD_0 , D060_CMD_1 } |
enum | rcomp_smr_cc { RCOMP_HOLD , RCOMP_RELEASE , RCOMP_SMR_00 , RCOMP_SMR_01 } |
Functions | |
static void | local_udelay (int i) |
static void | mchtest_control (mchtst_cc cmd) |
MCHTST - 0xF4 - 0xF7 – Based on similarity to 855PM. More... | |
static void | d060_control (d060_cc cmd) |
static void | rcomp_smr_control (rcomp_smr_cc cmd) |
static void | die_on_spd_error (int spd_return_value) |
static struct dimm_size | sdram_spd_get_page_size (uint16_t dimm_socket_address) |
Calculate the page size for each physical bank of the DIMM: log2(page size) = (# columns) + log2(data width) More... | |
static struct dimm_size | sdram_spd_get_width (uint16_t dimm_socket_address) |
Read the width in bits of each DIMM side's DRAMs via SPD (i.e. More... | |
static struct dimm_size | spd_get_dimm_size (unsigned int dimm_socket_address) |
Calculate the log base 2 size in bits of both DIMM sides. More... | |
static uint8_t | are_spd_values_equal (uint8_t spd_byte_number, uint16_t dimm0_address, uint16_t dimm1_address) |
Determine whether two DIMMs have the same value for an SPD parameter. More... | |
static uint8_t | spd_get_supported_dimms (const struct mem_controller *ctrl) |
Scan for compatible DIMMs. More... | |
static void | do_ram_command (uint8_t command, uint16_t jedec_mode_bits) |
Send the specified command to all DIMMs. More... | |
static void | set_ram_mode (uint16_t jedec_mode_bits) |
Set the mode register of all DIMMs. More... | |
static uint8_t | configure_dimm_row_boundaries (struct dimm_size dimm_log2_num_bits, uint8_t total_dram_64M_multiple, unsigned int dimm_index) |
Configure the E7501's DRAM Row Boundary (DRB) registers for the memory present in the specified DIMM. More... | |
static void | configure_e7501_ram_addresses (const struct mem_controller *ctrl, uint8_t dimm_mask) |
Set the E7501's DRAM row boundary addresses & its Top Of Low Memory (TOLM). More... | |
static void | configure_e7501_dram_timing (const struct mem_controller *ctrl, uint8_t dimm_mask) |
Program the DRAM Timing register (DRT) of the E7501 (except for CAS# latency, which is assumed to have been programmed already), based on the parameters of the various installed DIMMs. More... | |
static void | configure_e7501_cas_latency (const struct mem_controller *ctrl, uint8_t dimm_mask) |
Determine the shortest CAS# latency that the E7501 and all DIMMs have in common, and program the E7501 to use it. More... | |
static void | configure_e7501_dram_controller_mode (const struct mem_controller *ctrl, uint8_t dimm_mask) |
Configure the refresh interval so that we refresh no more often than required by the "most needy" DIMM. More... | |
static void | configure_e7501_row_attributes (const struct mem_controller *ctrl, uint8_t dimm_mask) |
Configure the E7501's DRAM Row Attributes (DRA) registers based on DIMM parameters read via SPD. More... | |
static void | enable_e7501_clocks (uint8_t dimm_mask) |
static void | RAM_RESET_DDR_PTR (void) |
DDR Receive FIFO RE-Sync (?) More... | |
static void | write_8dwords (const uint32_t *src_addr, u8 *dst_addr) |
Copy 64 bytes from one location to another. More... | |
static void | rcomp_copy_registers (void) |
Set the E7501's (undocumented) RCOMP registers. More... | |
static void | ram_set_rcomp_regs (void) |
static void | sdram_enable (const struct mem_controller *ctrl) |
Go through the JEDEC initialization sequence for all DIMMs, then enable refresh and initialize ECC and memory to zero. More... | |
static void | sdram_post_ecc (const struct mem_controller *ctrl) |
static void | sdram_set_spd_registers (const struct mem_controller *ctrl) |
Configure SDRAM controller parameters that depend on characteristics of the DIMMs installed in the system. More... | |
static void | sdram_set_registers (const struct mem_controller *ctrl) |
Do basic RAM setup that does NOT depend on serial presence detect information (i.e. More... | |
static int | e7505_mch_is_ready (void) |
void | sdram_initialize (void) |
Variables | |
static const uint32_t | refresh_frequency [] |
static const uint32_t | refresh_rate_map [] |
static const uint8_t | dual_channel_parameters [] |
static const uint32_t | slew_2x [] |
static const uint32_t | pull_updown_offset_table [] |
#define DO_DELAY local_udelay(200) |
#define E7501_SDRAM_MODE (SDRAM_BURST_INTERLEAVED | SDRAM_BURST_4) |
#define MAX_SPD_REFRESH_RATE (ARRAY_SIZE(refresh_rate_map) - 1) |
enum mchtst_cc |
enum rcomp_smr_cc |
|
static |
Determine whether two DIMMs have the same value for an SPD parameter.
spd_byte_number | The SPD byte number to compare in both DIMMs. |
dimm0_address | SMBus address of the 1st DIMM socket to interrogate. |
dimm1_address | SMBus address of the 2nd DIMM socket to interrogate. |
Definition at line 453 of file raminit.c.
References smbus_read_byte().
Referenced by spd_get_supported_dimms().
|
static |
Configure the E7501's DRAM Row Boundary (DRB) registers for the memory present in the specified DIMM.
dimm_log2_num_bits | Specifies log2(number of bits) for each side of the DIMM. |
total_dram_64M_multiple | Total DRAM in the system (as a multiple of 64 MB) for DIMMs < dimm_index. |
dimm_index | Which DIMM pair is being processed (0..MAX_DIMM_SOCKETS_PER_CHANNEL). |
Definition at line 719 of file raminit.c.
References ASSERT, DRB_ROW_0, DRB_ROW_1, MAX_DIMM_SOCKETS_PER_CHANNEL, MCHDEV, pci_write_config8(), dimm_size::side1, and dimm_size::side2.
Referenced by configure_e7501_ram_addresses().
|
static |
Determine the shortest CAS# latency that the E7501 and all DIMMs have in common, and program the E7501 to use it.
ctrl | PCI addresses of memory controller functions, and SMBus addresses of DIMM slots on the mainboard. |
dimm_mask | Bitmask of populated DIMMs, spd_get_supported_dimms(). |
Definition at line 1006 of file raminit.c.
References mem_controller::channel0, mem_controller::channel1, die(), DRA, dram_timing(), DRDCTL, DRT, DRT_CAS_2_0, DRT_CAS_2_5, DRT_CAS_MASK, log2(), MAX_DIMM_SOCKETS, MAX_DIMM_SOCKETS_PER_CHANNEL, MCHDEV, pci_read_config16(), pci_read_config32(), pci_write_config16(), pci_write_config32(), smbus_read_byte(), SPD_ACCEPTABLE_CAS_LATENCIES, SPD_CAS_LATENCY_2_0, SPD_CAS_LATENCY_2_5, SPD_ERROR, SPD_MIN_CYCLE_TIME_AT_CAS_MAX, SPD_SDRAM_CYCLE_TIME_2ND, SPD_SDRAM_CYCLE_TIME_3RD, and value.
Referenced by sdram_set_spd_registers().
|
static |
Configure the refresh interval so that we refresh no more often than required by the "most needy" DIMM.
Also disable ECC if any of the DIMMs don't support it.
ctrl | PCI addresses of memory controller functions, and SMBus addresses of DIMM slots on the mainboard. |
dimm_mask | Bitmask of populated DIMMs, spd_get_supported_dimms(). |
Definition at line 1158 of file raminit.c.
References ASSERT, BIOS_ERR, mem_controller::channel0, mem_controller::channel1, die_on_spd_error(), DRC, ERROR_SCHEME_ECC, MAX_DIMM_SOCKETS, MAX_DIMM_SOCKETS_PER_CHANNEL, MAX_SPD_REFRESH_RATE, MCHDEV, pci_read_config32(), pci_write_config32(), printk, refresh_frequency, refresh_rate_map, smbus_read_byte(), SPD_DIMM_CONFIG_TYPE, SPD_REFRESH, and value.
Referenced by sdram_set_spd_registers().
|
static |
Program the DRAM Timing register (DRT) of the E7501 (except for CAS# latency, which is assumed to have been programmed already), based on the parameters of the various installed DIMMs.
ctrl | PCI addresses of memory controller functions, and SMBus addresses of DIMM slots on the mainboard. |
dimm_mask | Bitmask of populated DIMMs, see spd_get_supported_dimms(). |
Definition at line 875 of file raminit.c.
References ASSERT, mem_controller::channel0, mem_controller::channel1, die(), dram_timing(), DRT, DRT_CAS_2_0, DRT_CAS_2_5, DRT_CAS_MASK, MAX_DIMM_SOCKETS, MAX_DIMM_SOCKETS_PER_CHANNEL, MCHDEV, pci_read_config32(), pci_write_config32(), smbus_read_byte(), SPD_ERROR, SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY, SPD_MIN_RAS_TO_CAS_DELAY, SPD_MIN_ROW_PRECHARGE_TIME, and value.
Referenced by sdram_set_spd_registers().
|
static |
Set the E7501's DRAM row boundary addresses & its Top Of Low Memory (TOLM).
If necessary, set up a remap window so we don't waste DRAM that ordinarily would lie behind addresses reserved for memory-mapped I/O.
ctrl | PCI addresses of memory controller functions, and SMBus addresses of DIMM slots on the mainboard. |
dimm_mask | Bitmask of populated DIMMs, see spd_get_supported_dimms(). |
Definition at line 782 of file raminit.c.
References AGPDEV, APSIZE, APSIZE1, mem_controller::channel0, configure_dimm_row_boundaries(), die(), DRB_ROW_0, DRB_ROW_4, GiB, MAX, MAX_DIMM_SOCKETS_PER_CHANNEL, MCHDEV, MiB, MIN, pci_read_config16(), pci_write_config16(), pci_write_config32(), pci_write_config8(), RAM_DEBUG_HEX32, RAM_DEBUG_MESSAGE, REMAPBASE, REMAPLIMIT, dimm_size::side1, dimm_size::side2, spd_get_dimm_size(), and TOLM.
Referenced by sdram_enable().
|
static |
Configure the E7501's DRAM Row Attributes (DRA) registers based on DIMM parameters read via SPD.
This tells the controller the width of the SDRAM chips on each DIMM side (x4 or x8) and the page size of each DIMM side (4, 8, 16, or 32 KB).
ctrl | PCI addresses of memory controller functions, and SMBus addresses of DIMM slots on the mainboard. |
dimm_mask | Bitmask of populated DIMMs, spd_get_supported_dimms(). |
Definition at line 1248 of file raminit.c.
References mem_controller::channel0, DRA, MAX_DIMM_SOCKETS_PER_CHANNEL, MCHDEV, pci_write_config32(), sdram_spd_get_page_size(), sdram_spd_get_width(), dimm_size::side1, and dimm_size::side2.
Referenced by sdram_set_spd_registers().
Definition at line 249 of file raminit.c.
References D060_CMD_0, D060_CMD_1, D060_DISABLE, D060_ENABLE, D060DEV, mchtest_control(), pci_read_config32(), and pci_write_config32().
Referenced by ram_set_rcomp_regs(), and sdram_set_registers().
|
static |
Definition at line 293 of file raminit.c.
References die().
Referenced by configure_e7501_dram_controller_mode().
Send the specified command to all DIMMs.
command | Specifies the command to be sent to the DIMMs. |
jedec_mode_bits | For the MRS & EMRS commands, bits 0-12 contain the register value in JEDEC format. |
Definition at line 611 of file raminit.c.
References ASSERT, DRB_ROW_0, DRC, EXTRA_DELAY, MAX_DIMM_SOCKETS_PER_CHANNEL, MAX_NUM_CHANNELS, MCHDEV, pci_read_config32(), pci_read_config8(), pci_write_config32(), RAM_COMMAND_EMRS, RAM_COMMAND_MRS, RAM_COMMAND_NORMAL, and read32().
Referenced by sdram_enable(), and set_ram_mode().
|
static |
Definition at line 1686 of file raminit.c.
References DRC, DRC_DONE, MCHDEV, and pci_read_config32().
Referenced by sdram_initialize().
Definition at line 1297 of file raminit.c.
References CKDIS, clock_disable, MAX_DIMM_SOCKETS_PER_CHANNEL, MCHDEV, pci_read_config8(), and pci_write_config8().
Referenced by sdram_set_spd_registers().
|
static |
Definition at line 173 of file raminit.c.
References SLOW_DOWN_IO.
MCHTST - 0xF4 - 0xF7 – Based on similarity to 855PM.
[31:31] Purpose unknown [30:30] Purpose unknown [29:23] Unknown - not used? [22:22] System Memory MMR Enable 0 == Disable: mem space and BAR at 0x14 are not accessible 1 == Enable: mem space and BAR at 0x14 are accessible [21:20] Purpose unknown [19:02] Unknown - not used? [01:01] D6EN (Device #6 enable) 0 == Disable 1 == Enable [00:00] Unknown - not used?
Definition at line 223 of file raminit.c.
References D060_DISABLE, D060_ENABLE, MCHDEV, MCHTST, MCHTST_CMD_0, pci_read_config32(), pci_write_config32(), RCOMP_BAR_DISABLE, and RCOMP_BAR_ENABLE.
Referenced by d060_control(), and ram_set_rcomp_regs().
DDR Receive FIFO RE-Sync (?)
Definition at line 1322 of file raminit.c.
References MCHDEV, pci_read_config8(), and pci_write_config8().
Referenced by sdram_enable(), and sdram_set_spd_registers().
Definition at line 1442 of file raminit.c.
References D060_CMD_0, d060_control(), MCHDEV, mchtest_control(), MCHTST_CMD_0, pci_read_config8(), pci_write_config32(), RCOMP_BAR_DISABLE, RCOMP_BAR_ENABLE, rcomp_copy_registers(), RCOMP_HOLD, RCOMP_MMIO, RCOMP_RELEASE, RCOMP_SMR_00, RCOMP_SMR_01, rcomp_smr_control(), SLOW_DOWN_IO, and SMRBASE.
Referenced by sdram_set_registers().
Set the E7501's (undocumented) RCOMP registers.
Per the 855PM datasheet and IXP2800 HW Initialization Reference Manual, RCOMP registers appear to affect drive strength, pullup/pulldown offset, and slew rate of various signal groups.
Comments below are conjecture based on apparent similarity between the E7501 and these two chips.
Definition at line 1360 of file raminit.c.
References CKESTR, CKSTR, CSBSTR, DQCMDSTR, pull_updown_offset_table, RAM_DEBUG_MESSAGE, RCOMP_MMIO, RCVENSTR, read32(), read8(), slew_2x, write16(), write32(), write8(), and write_8dwords().
Referenced by ram_set_rcomp_regs().
|
static |
Definition at line 268 of file raminit.c.
References RCOMP_HOLD, RCOMP_MMIO, RCOMP_RELEASE, RCOMP_SMR_00, RCOMP_SMR_01, read32(), SMRCTL, and write32().
Referenced by ram_set_rcomp_regs().
|
static |
Go through the JEDEC initialization sequence for all DIMMs, then enable refresh and initialize ECC and memory to zero.
Upon exit, SDRAM is up and running.
ctrl | PCI addresses of memory controller functions, and SMBus addresses of DIMM slots on the mainboard. |
Definition at line 1481 of file raminit.c.
References configure_e7501_ram_addresses(), DO_DELAY, do_ram_command(), DRC, E7501_SDRAM_MODE, EXTRA_DELAY, MCHDEV, pci_read_config16(), pci_read_config32(), pci_write_config32(), RAM_COMMAND_CBR, RAM_COMMAND_EMRS, RAM_COMMAND_NOP, RAM_COMMAND_NORMAL, RAM_COMMAND_PRECHARGE, RAM_DEBUG_MESSAGE, RAM_RESET_DDR_PTR(), SDRAM_EXTMODE_DLL_ENABLE, SDRAM_EXTMODE_DRIVE_NORMAL, SDRAM_MODE_DLL_RESET, SDRAM_MODE_NORMAL, set_ram_mode(), and SKPD.
Referenced by sdram_initialize().
Definition at line 1692 of file raminit.c.
References BIOS_DEBUG, mem_controller::d0, e7505_mch_is_ready(), PCI_DEV, printk, sdram_enable(), sdram_post_ecc(), sdram_set_registers(), sdram_set_spd_registers(), timestamp_add_now(), TS_INITRAM_END, and TS_INITRAM_START.
Referenced by mainboard_romstage_entry(), and perform_raminit().
|
static |
ctrl | PCI addresses of memory controller functions, and SMBus addresses of DIMM slots on the mainboard. |
Definition at line 1560 of file raminit.c.
References DRC, MCHDEV, pci_read_config32(), and pci_write_config32().
Referenced by sdram_initialize().
|
static |
Do basic RAM setup that does NOT depend on serial presence detect information (i.e.
independent of DIMM specifics).
ctrl | PCI addresses of memory controller functions, and SMBus addresses of DIMM slots on the mainboard. |
Definition at line 1622 of file raminit.c.
References CKDIS, D060_CMD_1, d060_control(), DRA, DRB_ROW_0, DRB_ROW_4, DRC, DRT, DVNP, MCHDEV, PAM_0, pci_read_config16(), pci_read_config32(), pci_read_config8(), pci_write_config16(), pci_write_config32(), pci_write_config8(), ram_set_rcomp_regs(), REMAPBASE, REMAPLIMIT, TOLM, and word.
Referenced by sdram_initialize().
|
static |
Configure SDRAM controller parameters that depend on characteristics of the DIMMs installed in the system.
These characteristics are read from the DIMMs via the standard Serial Presence Detect (SPD) interface.
ctrl | PCI addresses of memory controller functions, and SMBus addresses of DIMM slots on the mainboard. |
Definition at line 1577 of file raminit.c.
References BIOS_DEBUG, configure_e7501_cas_latency(), configure_e7501_dram_controller_mode(), configure_e7501_dram_timing(), configure_e7501_row_attributes(), DO_DELAY, enable_e7501_clocks(), MCHDEV, pci_write_config16(), printk, RAM_DEBUG_MESSAGE, RAM_RESET_DDR_PTR(), SKPD, and spd_get_supported_dimms().
Referenced by sdram_initialize().
Calculate the page size for each physical bank of the DIMM: log2(page size) = (# columns) + log2(data width)
NOTE: Page size is the total number of data bits in a row.
dimm_socket_address | SMBus address of DIMM socket to interrogate. |
Definition at line 293 of file raminit.c.
Referenced by configure_e7501_row_attributes(), and spd_get_supported_dimms().
Read the width in bits of each DIMM side's DRAMs via SPD (i.e.
4, 8, 16).
dimm_socket_address | SMBus address of DIMM socket to interrogate. |
Definition at line 293 of file raminit.c.
Referenced by configure_e7501_row_attributes(), and spd_get_supported_dimms().
Set the mode register of all DIMMs.
The proper CAS# latency setting is added to the mode bits specified by the caller.
jedec_mode_bits | For the MRS & EMRS commands, bits 0-12 contain the register value in JEDEC format. |
Definition at line 679 of file raminit.c.
References ASSERT, BUG, do_ram_command(), DRT, DRT_CAS_2_0, DRT_CAS_2_5, DRT_CAS_MASK, MCHDEV, pci_read_config32(), RAM_COMMAND_MRS, SDRAM_CAS_2_0, SDRAM_CAS_2_5, and SDRAM_CAS_MASK.
Referenced by sdram_enable().
Calculate the log base 2 size in bits of both DIMM sides.
log2(# bits) = (# columns) + log2(data width) + (# rows) + log2(banks per SDRAM)
Note that it might be easier to use SPD byte 31 here, it has the DIMM size as a multiple of 4MB. The way we do it now we can size both sides of an asymmetric DIMM.
dimm_socket_address | SMBus address of DIMM socket to interrogate. |
Definition at line 293 of file raminit.c.
Referenced by configure_e7501_ram_addresses().
|
static |
Scan for compatible DIMMs.
The code in this module only supports dual-channel operation, so we test that compatible DIMMs are paired.
ctrl | PCI addresses of memory controller functions, and SMBus addresses of DIMM slots on the mainboard. |
Definition at line 486 of file raminit.c.
References are_spd_values_equal(), ASSERT, BIOS_DEBUG, mem_controller::channel0, mem_controller::channel1, dual_channel_parameters, MAX_DIMM_SOCKETS_PER_CHANNEL, MODULE_REGISTERED, printk, sdram_spd_get_page_size(), sdram_spd_get_width(), dimm_size::side1, dimm_size::side2, smbus_read_byte(), SPD_BURST_LENGTH_4, SPD_MEMORY_TYPE, SPD_MEMORY_TYPE_SDRAM_DDR, SPD_MODULE_ATTRIBUTES, SPD_MODULE_VOLTAGE, SPD_SUPPORTED_BURST_LENGTHS, and SPD_VOLTAGE_SSTL2.
Referenced by sdram_set_spd_registers().
Copy 64 bytes from one location to another.
src_addr | TODO |
dst_addr | TODO |
Definition at line 1340 of file raminit.c.
References write32().
Referenced by rcomp_copy_registers().
|
static |
Definition at line 98 of file raminit.c.
Referenced by spd_get_supported_dimms().
|
static |
Definition at line 162 of file raminit.c.
Referenced by rcomp_copy_registers().
|
static |
Definition at line 63 of file raminit.c.
Referenced by configure_e7501_dram_controller_mode().
|
static |
Definition at line 79 of file raminit.c.
Referenced by configure_e7501_dram_controller_mode().
|
static |
Definition at line 156 of file raminit.c.
Referenced by rcomp_copy_registers().