diff options
author | Jon Dufresne <jon.dufresne@gmail.com> | 2009-01-20 20:25:48 +0000 |
---|---|---|
committer | Stefan Reinauer <stepan@openbios.org> | 2009-01-20 20:25:48 +0000 |
commit | 8c4af2b9e278d0c48cc6820ae2d1a300915425cb (patch) | |
tree | 4a25cba3f6d261f250b1c16ae4fa62a106196ddf /src/northbridge/intel | |
parent | ef6cb094b83b2717fba379a2c6670c19b12c676d (diff) | |
download | coreboot-8c4af2b9e278d0c48cc6820ae2d1a300915425cb.tar.xz |
This fine work by Jon Dufresne was awkwardly rotting on the mailing list for
almost three years. Let's put it somewher so people find it if they're looking
for it. Someone dare sending a late announcement to the coreboot-announce list?
:-)
Add (preliminary) support for Intel 855GME (Mobile version of the 855) chipset
to coreboot.
There are some holes in the code to be filled out, but unlike the code for the
855pm this has booted a mainboard before.
Signed-off-by: Jon Dufresne <jon.dufresne@gmail.com>
Acked-by: Stefan Reinauer <stepan@coresystems.de>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3877 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/northbridge/intel')
-rw-r--r-- | src/northbridge/intel/i855gme/Config.lb | 24 | ||||
-rw-r--r-- | src/northbridge/intel/i855gme/chip.h | 25 | ||||
-rw-r--r-- | src/northbridge/intel/i855gme/debug.c | 197 | ||||
-rw-r--r-- | src/northbridge/intel/i855gme/northbridge.c | 198 | ||||
-rw-r--r-- | src/northbridge/intel/i855gme/raminit.c | 297 | ||||
-rw-r--r-- | src/northbridge/intel/i855gme/raminit.h | 32 | ||||
-rw-r--r-- | src/northbridge/intel/i855gme/reset_test.c | 39 |
7 files changed, 812 insertions, 0 deletions
diff --git a/src/northbridge/intel/i855gme/Config.lb b/src/northbridge/intel/i855gme/Config.lb new file mode 100644 index 0000000000..5a7cd14600 --- /dev/null +++ b/src/northbridge/intel/i855gme/Config.lb @@ -0,0 +1,24 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2006 Jon Dufresne <jon.dufresne@gmail.com> + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +config chip.h +object northbridge.o +#driver misc_control.o + diff --git a/src/northbridge/intel/i855gme/chip.h b/src/northbridge/intel/i855gme/chip.h new file mode 100644 index 0000000000..3e1514a59c --- /dev/null +++ b/src/northbridge/intel/i855gme/chip.h @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2006 Jon Dufresne <jon.dufresne@gmail.com> + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +struct northbridge_intel_i855gme_config +{ +}; + +extern struct chip_operations northbridge_intel_i855gme_ops; diff --git a/src/northbridge/intel/i855gme/debug.c b/src/northbridge/intel/i855gme/debug.c new file mode 100644 index 0000000000..46d629b01e --- /dev/null +++ b/src/northbridge/intel/i855gme/debug.c @@ -0,0 +1,197 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2003 Ronald G. Minnich + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * generic K8 debug code, used by mainboard specific auto.c + * + */ +#if 1 +/* +static void print_debug_pci_dev(unsigned dev) +{ + print_debug("PCI: "); + print_debug_hex8((dev >> 16) & 0xff); + print_debug_char(':'); + print_debug_hex8((dev >> 11) & 0x1f); + print_debug_char('.'); + print_debug_hex8((dev >> 8) & 7); +} +*/ + + +static void print_debug_pci_dev(unsigned dev) +{ + print_debug("PCI: "); + print_debug_hex8((dev >> 20) & 0xff); + print_debug_char(':'); + print_debug_hex8((dev >> 15) & 0x1f); + print_debug_char('.'); + print_debug_hex8((dev >> 12) & 0x07); +} + +static void print_pci_devices(void) +{ + device_t dev; + for(dev = PCI_DEV(0, 0, 0); + dev <= PCI_DEV(0, 0x1f, 0x7); + dev += PCI_DEV(0,0,1)) { + uint32_t id; + id = pci_read_config32(dev, PCI_VENDOR_ID); + if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0x0000)) { + continue; + } + print_debug_pci_dev(dev); + print_debug("\r\n"); + } +} + +static void dump_pci_device(unsigned dev) +{ + int i; + print_debug_pci_dev(dev); + print_debug("\r\n"); + + for(i = 0; i <= 255; i++) { + unsigned char val; + if ((i & 0x0f) == 0) { + print_debug_hex8(i); + print_debug_char(':'); + } + val = pci_read_config8(dev, i); + print_debug_char(' '); + print_debug_hex8(val); + if ((i & 0x0f) == 0x0f) { + print_debug("\r\n"); + } + } +} + +static void dump_pci_devices(void) +{ + device_t dev; + for(dev = PCI_DEV(0, 0, 0); + dev <= PCI_DEV(0, 0x1f, 0x7); + dev += PCI_DEV(0,0,1)) { + uint32_t id; + id = pci_read_config32(dev, PCI_VENDOR_ID); + if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0x0000)) { + continue; + } + dump_pci_device(dev); + } +} + +static void dump_spd_registers(const struct mem_controller *ctrl) +{ + int i; + print_debug("\r\n"); + for(i = 0; i < 2; i++) { + unsigned device; + device = ctrl->channel0[i]; + if (device) { + int j; + print_debug("dimm: "); + print_debug_hex8(i); + print_debug(".0: "); + print_debug_hex8(device); + for(j = 0; j < 256; j++) { + int status; + unsigned char byte; + if ((j & 0xf) == 0) { + print_debug("\r\n"); + print_debug_hex8(j); + print_debug(": "); + } + status = smbus_read_byte(device, j); + if (status < 0) { + print_debug("bad device\r\n"); + break; + } + byte = status & 0xff; + print_debug_hex8(byte); + print_debug_char(' '); + } + print_debug("\r\n"); + } +#if 0 + device = ctrl->channel1[i]; + if (device) { + int j; + print_debug("dimm: "); + print_debug_hex8(i); + print_debug(".1: "); + print_debug_hex8(device); + for(j = 0; j < 256; j++) { + int status; + unsigned char byte; + if ((j & 0xf) == 0) { + print_debug("\r\n"); + print_debug_hex8(j); + print_debug(": "); + } + status = smbus_read_byte(device, j); + if (status < 0) { + print_debug("bad device\r\n"); + break; + } + byte = status & 0xff; + print_debug_hex8(byte); + print_debug_char(' '); + } + print_debug("\r\n"); + } +#endif + } +} +static void dump_smbus_registers(void) +{ + int i; + print_debug("\r\n"); + for(i = 1; i < 0x80; i++) { + unsigned device; + device = i; + int j; + print_debug("smbus: "); + print_debug_hex8(device); + for(j = 0; j < 256; j++) { + int status; + unsigned char byte; + if ((j & 0xf) == 0) { + print_debug("\r\n"); + print_debug_hex8(j); + print_debug(": "); + } + status = smbus_read_byte(device, j); + if (status < 0) { + print_debug("bad device\r\n"); + break; + } + byte = status & 0xff; + print_debug_hex8(byte); + print_debug_char(' '); + } + print_debug("\r\n"); + } +} +#endif diff --git a/src/northbridge/intel/i855gme/northbridge.c b/src/northbridge/intel/i855gme/northbridge.c new file mode 100644 index 0000000000..e5fecf16ee --- /dev/null +++ b/src/northbridge/intel/i855gme/northbridge.c @@ -0,0 +1,198 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2003 Ronald G. Minnich + * Copyright (C) 2003-2004 Eric W. Biederman + * Copyright (C) 2006 Jon Dufresne <jon.dufresne@gmail.com> + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <console/console.h> +#include <arch/io.h> +#include <stdint.h> +#include <device/device.h> +#include <device/pci.h> +#include <stdlib.h> +#include <string.h> +#include <bitops.h> +#include <cpu/x86/cache.h> +#include "chip.h" + +#define BRIDGE_IO_MASK (IORESOURCE_IO | IORESOURCE_MEM) + +static void pci_domain_read_resources(device_t dev) +{ + struct resource *resource; + unsigned reg; + + /* Initialize the system wide io space constraints */ + resource = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0)); + resource->limit = 0xffffUL; + resource->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED; + + /* Initialize the system wide memory resources constraints */ + resource = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0)); + resource->limit = 0xffffffffULL; + resource->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED; +} + +static void ram_resource(device_t dev, unsigned long index, + unsigned long basek, unsigned long sizek) +{ + struct resource *resource; + + if (!sizek) { + return; + } + resource = new_resource(dev, index); + resource->base = ((resource_t)basek) << 10; + resource->size = ((resource_t)sizek) << 10; + resource->flags = IORESOURCE_MEM | IORESOURCE_CACHEABLE | \ + IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED; +} + +static void tolm_test(void *gp, struct device *dev, struct resource *new) +{ + struct resource **best_p = gp; + struct resource *best; + best = *best_p; + if (!best || (best->base > new->base)) { + best = new; + } + *best_p = best; +} + +static uint32_t find_pci_tolm(struct bus *bus) +{ + struct resource *min; + uint32_t tolm; + min = 0; + search_bus_resources(bus, IORESOURCE_MEM, IORESOURCE_MEM, tolm_test, &min); + tolm = 0xffffffffUL; + if (min && tolm > min->base) { + tolm = min->base; + } + return tolm; +} + +static void pci_domain_set_resources(device_t dev) +{ + device_t mc_dev; + uint32_t pci_tolm; + + printk_debug("Entered with dev vid = %x\n", dev->vendor); + printk_debug("Entered with dev did = %x\n", dev->device); + + pci_tolm = find_pci_tolm(&dev->link[0]); + mc_dev = dev->link[0].children->sibling; + printk_debug("MC dev vendor = %x\n", mc_dev->vendor); + printk_debug("MC dev device = %x\n", mc_dev->device); + + if (mc_dev) { + /* Figure out which areas are/should be occupied by RAM. + * This is all computed in kilobytes and converted to/from + * the memory controller right at the edges. + * Having different variables in different units is + * too confusing to get right. Kilobytes are good up to + * 4 Terabytes of RAM... + */ + uint16_t tolm_r, vga_mem; + unsigned long tomk, tolmk; + unsigned long remapbasek, remaplimitk; + int idx; + + /* Get the value of the highest DRB. This tells the end of + * the physical memory. The units are ticks of 32MB + * i.e. 1 means 32MB. + */ + tomk = (unsigned long)pci_read_config8(mc_dev, 0x43); + tomk = tomk * 32 * 1024; + /* add vga_mem detection */ + tomk = tomk - 16 * 1024; + /* Compute the top of Low memory */ + tolmk = pci_tolm >> 10; + if (tolmk >= tomk) { + /* The PCI hole does not overlap memory + */ + tolmk = tomk; + } + /* Write the ram configuration registers, + * preserving the reserved bits. + */ + + /* Report the memory regions */ + printk_debug("tomk = %d\n", tomk); + printk_debug("tolmk = %d\n", tolmk); + + idx = 10; + /* avoid pam region */ + ram_resource(dev, idx++, 0, 640); + /* ram_resource(dev, idx++, 1024, tolmk - 1024); */ + ram_resource(dev, idx++, 768, tolmk - 768); + + } + assign_resources(&dev->link[0]); +} + +static unsigned int pci_domain_scan_bus(device_t dev, unsigned int max) +{ + max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0, 0), 0xff, max); + return max; +} + +static struct device_operations pci_domain_ops = { + .read_resources = pci_domain_read_resources, + .set_resources = pci_domain_set_resources, + .enable_resources = enable_childrens_resources, + .init = 0, + .scan_bus = pci_domain_scan_bus, +}; + +static void cpu_bus_init(device_t dev) +{ + initialize_cpus(&dev->link[0]); +} + +static void cpu_bus_noop(device_t dev) +{ +} + +static struct device_operations cpu_bus_ops = { + .read_resources = cpu_bus_noop, + .set_resources = cpu_bus_noop, + .enable_resources = cpu_bus_noop, + .init = cpu_bus_init, + .scan_bus = 0, +}; + +static void enable_dev(struct device *dev) +{ + struct device_path path; + + /* Set the operations if it is a special bus type */ + if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) { + dev->ops = &pci_domain_ops; + pci_set_method(dev); + } + else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) { + dev->ops = &cpu_bus_ops; + } +} + +struct chip_operations northbridge_intel_i855gme_ops = { + CHIP_NAME("Intel 855GME Northbridge") + .enable_dev = enable_dev, +}; diff --git a/src/northbridge/intel/i855gme/raminit.c b/src/northbridge/intel/i855gme/raminit.c new file mode 100644 index 0000000000..8e928bd279 --- /dev/null +++ b/src/northbridge/intel/i855gme/raminit.c @@ -0,0 +1,297 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2006 Jon Dufresne <jon.dufresne@gmail.com> + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <sdram_mode.h> + +#define dumpnorth() dump_pci_device(PCI_DEV(0, 0, 1)) +#define VG85X_MODE (SDRAM_BURST_4 | SDRAM_BURST_INTERLEAVED | SDRAM_CAS_2_5) + +/** + * Set only what I need until it works, then make it figure things out on boot + * assumes only one dimm is populated + */ + +static void sdram_set_registers(const struct mem_controller *ctrl) +{ + /* + print_debug("Before configuration:\r\n"); + dump_pci_devices(); + */ +} + +static void spd_set_row_attributes(const struct mem_controller *ctrl) +{ + uint16_t dra_reg; + + dra_reg = 0x7733; + pci_write_config16(ctrl->d0, 0x50, dra_reg); +} + +static void spd_set_dram_controller_mode(const struct mem_controller *ctrl) +{ + uint32_t drc_reg; + + /* drc_reg = 0x00009101; */ + drc_reg = 0x00009901; + pci_write_config32(ctrl->d0, 0x70, drc_reg); +} + +static void spd_set_dram_timing(const struct mem_controller *ctrl) +{ + uint32_t drt_reg; + + drt_reg = 0x2a004405; + pci_write_config32(ctrl->d0, 0x60, drt_reg); +} + +static void spd_set_dram_size(const struct mem_controller *ctrl) +{ + uint32_t drb_reg; + + drb_reg = 0x20202010; + pci_write_config32(ctrl->d0, 0x40, drb_reg); +} + +static void spd_set_dram_pwr_management(const struct mem_controller *ctrl) +{ + uint32_t pwrmg_reg; + + pwrmg_reg = 0x10f10430; + pci_write_config32(ctrl->d0, 0x68, pwrmg_reg); +} + +static void spd_set_dram_throttle_control(const struct mem_controller *ctrl) +{ + uint32_t dtc_reg; + + dtc_reg = 0x300aa2ff; + pci_write_config32(ctrl->d0, 0xa0, dtc_reg); +} + +void udelay(int usecs) +{ + int i; + for(i = 0; i < usecs; i++) + outb(i & 0xff, 0x80); +} + +#define delay() udelay(200) + +/* if ram still doesn't work do this function */ +static void spd_set_undocumented_registers(const struct mem_controller *ctrl) +{ + uint16_t word; + + /* 0:0.0 */ + /* + pci_write_config32(PCI_DEV(0, 0, 0), 0x10, 0xe0000008); + pci_write_config32(PCI_DEV(0, 0, 0), 0x2c, 0x35808086); + pci_write_config32(PCI_DEV(0, 0, 0), 0x48, 0xfec10000); + pci_write_config32(PCI_DEV(0, 0, 0), 0x50, 0x00440100); + + pci_write_config32(PCI_DEV(0, 0, 0), 0x58, 0x11111000); + + pci_write_config16(PCI_DEV(0, 0, 0), 0x52, 0x0002); + */ + pci_write_config16(PCI_DEV(0, 0, 0), 0x52, 0x0044); + /* + pci_write_config16(PCI_DEV(0, 0, 0), 0x52, 0x0000); + */ + pci_write_config32(PCI_DEV(0, 0, 0), 0x58, 0x33333000); + pci_write_config32(PCI_DEV(0, 0, 0), 0x5c, 0x33333333); + /* + pci_write_config32(PCI_DEV(0, 0, 0), 0x60, 0x0000390a); + pci_write_config32(PCI_DEV(0, 0, 0), 0x74, 0x02006056); + pci_write_config32(PCI_DEV(0, 0, 0), 0x78, 0x00800001); + */ + pci_write_config32(PCI_DEV(0, 0, 0), 0xa8, 0x00000001); + + pci_write_config32(PCI_DEV(0, 0, 0), 0xbc, 0x00001020); + /* + pci_write_config32(PCI_DEV(0, 0, 0), 0xfc, 0x00000109); + */ + + /* 0:0.1 */ + pci_write_config32(ctrl->d0, 0x74, 0x00000001); + pci_write_config32(ctrl->d0, 0x78, 0x001fe974); + pci_write_config32(ctrl->d0, 0x80, 0x00af0039); + pci_write_config32(ctrl->d0, 0x84, 0x0000033c); + pci_write_config32(ctrl->d0, 0x88, 0x00000010); + pci_write_config32(ctrl->d0, 0x98, 0xde5a868c); + pci_write_config32(ctrl->d0, 0x9c, 0x404e0046); + pci_write_config32(ctrl->d0, 0xa8, 0x00020e1a); + pci_write_config32(ctrl->d0, 0xb4, 0x0044cdac); + pci_write_config32(ctrl->d0, 0xb8, 0x000055d4); + pci_write_config32(ctrl->d0, 0xbc, 0x024acd38); + pci_write_config32(ctrl->d0, 0xc0, 0x00000003); + + /* 0:0.3 */ + /* + pci_write_config32(PCI_DEV(0, 0, 3), 0x2c, 0x35858086); + pci_write_config32(PCI_DEV(0, 0, 3), 0x44, 0x11110000); + pci_write_config32(PCI_DEV(0, 0, 3), 0x48, 0x09614a3c); + pci_write_config32(PCI_DEV(0, 0, 3), 0x4c, 0x4b09604a); + pci_write_config32(PCI_DEV(0, 0, 3), 0x50, 0x00000962); + pci_write_config32(PCI_DEV(0, 0, 3), 0x5c, 0x0b023331); + pci_write_config32(PCI_DEV(0, 0, 3), 0x6c, 0x0000402e); + pci_write_config32(PCI_DEV(0, 0, 3), 0x78, 0xe7c70f7f); + pci_write_config32(PCI_DEV(0, 0, 3), 0x7c, 0x0284007f); + pci_write_config32(PCI_DEV(0, 0, 3), 0x84, 0x000000ef); + */ + + /* + pci_write_config16(PCI_DEV(0, 0, 3), 0xc0, 0x0200); + pci_write_config16(PCI_DEV(0, 0, 3), 0xc0, 0x0400); + */ + + /* + pci_write_config32(PCI_DEV(0, 0, 3), 0xc4, 0x00000000); + pci_write_config32(PCI_DEV(0, 0, 3), 0xd8, 0xff00c308); + pci_write_config32(PCI_DEV(0, 0, 3), 0xdc, 0x00000025); + pci_write_config32(PCI_DEV(0, 0, 3), 0xe0, 0x001f002a); + pci_write_config32(PCI_DEV(0, 0, 3), 0xe4, 0x009f0098); + pci_write_config32(PCI_DEV(0, 0, 3), 0xec, 0x00000400); + pci_write_config32(PCI_DEV(0, 0, 3), 0xf0, 0xc0000000); + */ +} + +static void sdram_set_spd_registers(const struct mem_controller *ctrl) +{ + spd_set_row_attributes(ctrl); + spd_set_dram_controller_mode(ctrl); + spd_set_dram_timing(ctrl); + spd_set_dram_size(ctrl); + spd_set_dram_pwr_management(ctrl); + spd_set_dram_throttle_control(ctrl); + spd_set_undocumented_registers(ctrl); +} + +static void ram_command(const struct mem_controller *ctrl, + uint8_t command, + uint32_t addr) +{ + uint32_t drc_reg; + + drc_reg = pci_read_config32(ctrl->d0, 0x70); + drc_reg &= ~(7 << 4); + drc_reg |= (command << 4); + pci_write_config8(ctrl->d0, 0x70, drc_reg); + read32(addr); +} + +static void ram_command_mrs(const struct mem_controller *ctrl, + uint8_t command, + uint32_t mode, + uint32_t addr) +{ + uint32_t drc_reg; + uint32_t adjusted_mode; + + drc_reg = pci_read_config32(ctrl->d0, 0x70); + drc_reg &= ~(7 << 4); + drc_reg |= (command << 4); + pci_write_config8(ctrl->d0, 0x70, drc_reg); + /* Host address lines [13:3] map to DIMM address lines [11, 9:0] */ + adjusted_mode = ((mode & 0x800) << (13 - 11)) | ((mode & 0x3ff) << (12 - 9)); + print_debug("Setting mode: "); + print_debug_hex32(adjusted_mode + addr); + print_debug("\r\n"); + read32(adjusted_mode + addr); +} + +static void set_initialize_complete(const struct mem_controller *ctrl) +{ + uint32_t drc_reg; + + drc_reg = pci_read_config32(ctrl->d0, 0x70); + drc_reg |= (1 << 29); + pci_write_config32(ctrl->d0, 0x70, drc_reg); +} + +static void sdram_enable(int controllers, const struct mem_controller *ctrl) +{ + int i; + uint32_t rank1 = (1 << 30) / 2; + print_debug("Ram enable 1\r\n"); + delay(); + delay(); + + print_debug("Ram enable 2\r\n"); + ram_command(ctrl, 1, 0); + ram_command(ctrl, 1, rank1); + delay(); + delay(); + + print_debug("Ram enable 3\r\n"); + ram_command(ctrl, 2, 0); + ram_command(ctrl, 2, rank1); + delay(); + delay(); + + print_debug("Ram enable 4\r\n"); + ram_command_mrs(ctrl, 4, SDRAM_EXTMODE_DLL_ENABLE, 0); + ram_command_mrs(ctrl, 4, SDRAM_EXTMODE_DLL_ENABLE, rank1); + delay(); + delay(); + + print_debug("Ram enable 5\r\n"); + ram_command_mrs(ctrl, 3, VG85X_MODE | SDRAM_MODE_DLL_RESET, 0); + ram_command_mrs(ctrl, 3, VG85X_MODE | SDRAM_MODE_DLL_RESET, rank1); + + print_debug("Ram enable 6\r\n"); + ram_command(ctrl, 2, 0); + ram_command(ctrl, 2, rank1); + delay(); + delay(); + + print_debug("Ram enable 7\r\n"); + for(i = 0; i < 8; i++) { + ram_command(ctrl, 6, 0); + ram_command(ctrl, 6, rank1); + delay(); + delay(); + } + + print_debug("Ram enable 8\r\n"); + ram_command_mrs(ctrl, 3, VG85X_MODE | SDRAM_MODE_NORMAL, 0); + ram_command_mrs(ctrl, 3, VG85X_MODE | SDRAM_MODE_NORMAL, rank1); + + print_debug("Ram enable 9\r\n"); + ram_command(ctrl, 7, 0); + ram_command(ctrl, 7, rank1); + delay(); + delay(); + + print_debug("Ram enable 9\r\n"); + set_initialize_complete(ctrl); + + delay(); + delay(); + delay(); + + print_debug("After configuration:\r\n"); + /* dump_pci_devices(); */ + + /* + print_debug("\n\n***** RAM TEST *****\r\n"); + ram_check(0, 0xa0000); + ram_check(0x100000, 0x40000000); + */ +} diff --git a/src/northbridge/intel/i855gme/raminit.h b/src/northbridge/intel/i855gme/raminit.h new file mode 100644 index 0000000000..a312ee511f --- /dev/null +++ b/src/northbridge/intel/i855gme/raminit.h @@ -0,0 +1,32 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2006 Jon Dufresne <jon.dufresne@gmail.com> + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef RAMINIT_H +#define RAMINIT_H + +#define DIMM_SOCKETS 2 + +struct mem_controller { + device_t d0; + uint16_t channel0[DIMM_SOCKETS]; +}; + + +#endif /* RAMINIT_H */ diff --git a/src/northbridge/intel/i855gme/reset_test.c b/src/northbridge/intel/i855gme/reset_test.c new file mode 100644 index 0000000000..b48b4a3764 --- /dev/null +++ b/src/northbridge/intel/i855gme/reset_test.c @@ -0,0 +1,39 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2006 Jon Dufresne <jon.dufresne@gmail.com> + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define MCH_DRC 0x70 +#define DRC_DONE (1 << 29) + + /* If I have already booted once skip a bunch of initialization */ + /* To see if I have already booted I check to see if memory + * has been enabled. + */ +static int bios_reset_detected(void) +{ + uint32_t dword; + + dword = pci_read_config32(PCI_DEV(0, 0, 0), MCH_DRC); + + if( (dword & DRC_DONE) != 0 ) { + return 1; + } + + return 0; +} |