[coreboot] [commit] r4967 - in trunk/src/northbridge/intel: . i440lx

svn at coreboot.org svn at coreboot.org
Sat Nov 28 10:31:44 CET 2009


Author: stepan
Date: 2009-11-28 10:31:30 +0100 (Sat, 28 Nov 2009)
New Revision: 4967

Added:
   trunk/src/northbridge/intel/i440lx/
   trunk/src/northbridge/intel/i440lx/Config.lb
   trunk/src/northbridge/intel/i440lx/Kconfig
   trunk/src/northbridge/intel/i440lx/Makefile.inc
   trunk/src/northbridge/intel/i440lx/chip.h
   trunk/src/northbridge/intel/i440lx/i440lx.h
   trunk/src/northbridge/intel/i440lx/northbridge.c
   trunk/src/northbridge/intel/i440lx/northbridge.h
   trunk/src/northbridge/intel/i440lx/raminit.c
   trunk/src/northbridge/intel/i440lx/raminit.h
Modified:
   trunk/src/northbridge/intel/Kconfig
   trunk/src/northbridge/intel/Makefile.inc
Log:
Maciej Pijanka tried to get the Biostar M6TLD running, and created a patch for
440lx using the 440bx code as a template.

Signed-off-by: Maciej Pijanka <maciej.pijanka at gmail.com>
Acked-by: Ronald G. Minnich <rminnich at gmail.com>
Acked-by: Stefan Reinauer <stepan at coresystems.de>



Modified: trunk/src/northbridge/intel/Kconfig
===================================================================
--- trunk/src/northbridge/intel/Kconfig	2009-11-28 05:30:57 UTC (rev 4966)
+++ trunk/src/northbridge/intel/Kconfig	2009-11-28 09:31:30 UTC (rev 4967)
@@ -3,6 +3,7 @@
 source src/northbridge/intel/e7525/Kconfig
 source src/northbridge/intel/i3100/Kconfig
 source src/northbridge/intel/i440bx/Kconfig
+source src/northbridge/intel/i440lx/Kconfig
 source src/northbridge/intel/i82810/Kconfig
 source src/northbridge/intel/i82830/Kconfig
 source src/northbridge/intel/i855gme/Kconfig

Modified: trunk/src/northbridge/intel/Makefile.inc
===================================================================
--- trunk/src/northbridge/intel/Makefile.inc	2009-11-28 05:30:57 UTC (rev 4966)
+++ trunk/src/northbridge/intel/Makefile.inc	2009-11-28 09:31:30 UTC (rev 4967)
@@ -3,6 +3,7 @@
 subdirs-$(CONFIG_NORTHBRIDGE_INTEL_E7525) += e7525
 subdirs-$(CONFIG_NORTHBRIDGE_INTEL_I3100) += i3100
 subdirs-$(CONFIG_NORTHBRIDGE_INTEL_I440BX) += i440bx
+subdirs-$(CONFIG_NORTHBRIDGE_INTEL_I440LX) += i440lx
 subdirs-$(CONFIG_NORTHBRIDGE_INTEL_I82810) += i82810
 subdirs-$(CONFIG_NORTHBRIDGE_INTEL_I82830) += i82830
 subdirs-$(CONFIG_NORTHBRIDGE_INTEL_I855GME) += i855gme

Added: trunk/src/northbridge/intel/i440lx/Config.lb
===================================================================
--- trunk/src/northbridge/intel/i440lx/Config.lb	                        (rev 0)
+++ trunk/src/northbridge/intel/i440lx/Config.lb	2009-11-28 09:31:30 UTC (rev 4967)
@@ -0,0 +1,27 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2007 Uwe Hermann <uwe at hermann-uwe.de>
+##
+## 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
+##
+
+uses CONFIG_WRITE_HIGH_TABLES
+
+config chip.h
+
+driver northbridge.o
+
+default CONFIG_WRITE_HIGH_TABLES=1

Added: trunk/src/northbridge/intel/i440lx/Kconfig
===================================================================
--- trunk/src/northbridge/intel/i440lx/Kconfig	                        (rev 0)
+++ trunk/src/northbridge/intel/i440lx/Kconfig	2009-11-28 09:31:30 UTC (rev 4967)
@@ -0,0 +1,24 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe at hermann-uwe.de>
+##
+## 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 NORTHBRIDGE_INTEL_I440LX
+	bool
+	select HAVE_HIGH_TABLES
+

Added: trunk/src/northbridge/intel/i440lx/Makefile.inc
===================================================================
--- trunk/src/northbridge/intel/i440lx/Makefile.inc	                        (rev 0)
+++ trunk/src/northbridge/intel/i440lx/Makefile.inc	2009-11-28 09:31:30 UTC (rev 4967)
@@ -0,0 +1,22 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe at hermann-uwe.de>
+##
+## 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
+##
+
+driver-y += northbridge.o 
+

Added: trunk/src/northbridge/intel/i440lx/chip.h
===================================================================
--- trunk/src/northbridge/intel/i440lx/chip.h	                        (rev 0)
+++ trunk/src/northbridge/intel/i440lx/chip.h	2009-11-28 09:31:30 UTC (rev 4967)
@@ -0,0 +1,25 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009 Maciej Pijanka <maciej.pijanka at 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_i440lx_config
+{
+};
+
+extern struct chip_operations northbridge_intel_i440lx_ops;

Added: trunk/src/northbridge/intel/i440lx/i440lx.h
===================================================================
--- trunk/src/northbridge/intel/i440lx/i440lx.h	                        (rev 0)
+++ trunk/src/northbridge/intel/i440lx/i440lx.h	2009-11-28 09:31:30 UTC (rev 4967)
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2006 Uwe Hermann <uwe at hermann-uwe.de>
+ * Copyright (C) 2009 Maciej Pijanka <maciej.pijanka at 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
+ */
+
+/*
+ * Datasheet:
+ *   - Name: Intel 440LX AGPset: 82443LX Host Bridge/Controller
+ *   - PDF: 29056402.pdf
+ */
+
+/*
+ * Host-to-PCI Bridge Registers.
+ * The values in parenthesis are the default values as per datasheet.
+ * Any addresses between 0x00 and 0xff not listed below are either
+ *
+ * i didnt listed every register that IS implemented, just usefull ones
+ *  -- Maciej `agaran` Pijanka
+ *
+ * Reserved or Intel Reserved and should not be touched.
+ */
+#define APBASE	0x34 /* Aperture Base Address (0x00000008) */
+#define PACCFG	0x50 /* 440LX PAC Configuration Register (0s00_s000_0000_0s00b) */
+#define DBC	0x53 /* DRAM Row Type Register (0x83) */
+#define DRT	0x55 /* DRAM Row Type Register (0x0000) */
+#define DRAMC	0x57 /* DRAM Control (0x01) */
+#define DRAMT   0x58 /* DRAM Timing (0x00) */
+#define PAM     0x59 /* Programmable Attribute Map, 7 registers (0x00). */
+#define DRB     0x60 /* DRAM Row Boundary, 8 registers (0x01). */
+#define FDHC    0x68 /* Fixed SDRAM Hole Control (0x00). */
+#define DRAMXC	0x6A /* Dram Extended Control Register (0x0000) */
+#define MBSC	0x6C /* Memory Buffer Strength Control: (0x55555555) */
+
+#define SMRAM   0x72 /* System Management RAM Control (0x02). */
+#define ERRCMD  0x90 /* Error Command Register (0x80). */
+#define ERRSTS0 0x91 /* Error Status (0x0000). */
+#define ERRSTS1 0x92 /* Error Status (0x0000). */
+// TODO: AGP stuff.
+
+/* For convenience: */
+#define DRB0    0x60
+#define DRB1    0x61
+#define DRB2    0x62
+#define DRB3    0x63
+#define DRB4    0x64
+#define DRB5    0x65
+#define DRB6    0x66
+#define DRB7    0x67
+
+#define PAM0    0x59
+#define PAM1    0x5a
+#define PAM2    0x5b
+#define PAM3    0x5c
+#define PAM4    0x5d
+#define PAM5    0x5e
+#define PAM6    0x5f
+

Added: trunk/src/northbridge/intel/i440lx/northbridge.c
===================================================================
--- trunk/src/northbridge/intel/i440lx/northbridge.c	                        (rev 0)
+++ trunk/src/northbridge/intel/i440lx/northbridge.c	2009-11-28 09:31:30 UTC (rev 4967)
@@ -0,0 +1,192 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Uwe Hermann <uwe at hermann-uwe.de>
+ * Copyright (C) 2009 Maciej Pijanka <maciej.pijanka at 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 <device/pci_ids.h>
+#include <stdlib.h>
+#include <string.h>
+#include <bitops.h>
+#include <cpu/cpu.h>
+#include <pc80/keyboard.h>
+#include "chip.h"
+#include "northbridge.h"
+#include "i440lx.h"
+
+/* This code is mostly same as 440BX created by Uwe Hermann, 
+ * i done only very minor changes like renamed functions to 440lx etc
+ * Maciej
+ */
+
+/* TODO:
+ * - maybe this could print Northbridge i440LX Init?
+ */
+static void northbridge_init(device_t dev)
+{
+	printk_spew("Northbridge Init\n");
+}
+
+static struct device_operations northbridge_operations = {
+	.read_resources   = pci_dev_read_resources,
+	.set_resources    = pci_dev_set_resources,
+	.enable_resources = pci_dev_enable_resources,
+	.init             = northbridge_init,
+	.enable           = 0,
+	.ops_pci          = 0,
+};
+
+static const struct pci_driver northbridge_driver __pci_driver = {
+	.ops = &northbridge_operations,
+	.vendor = PCI_VENDOR_ID_INTEL,
+	.device = 0x7180,
+};
+
+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;
+}
+
+#if CONFIG_WRITE_HIGH_TABLES==1
+#define HIGH_TABLES_SIZE 64	// maximum size of high tables in KB
+extern uint64_t high_tables_base, high_tables_size;
+#endif
+
+static void i440lx_domain_set_resources(device_t dev)
+{
+	device_t mc_dev;
+	uint32_t pci_tolm;
+
+	pci_tolm = find_pci_tolm(&dev->link[0]);
+	mc_dev = dev->link[0].children;
+	if (mc_dev) {
+		unsigned long tomk, tolmk;
+		int idx;
+
+		/* Figure out which areas are/should be occupied by RAM. The
+		 * value of the highest DRB denotes the end of the physical
+		 * memory (in units of 8MB).
+		 */
+		tomk = ((unsigned long)pci_read_config8(mc_dev, DRB7));
+
+		/* Convert to KB. */
+		tomk *= (8 * 1024);
+
+		printk_debug("Setting RAM size to %lu MB\n", tomk / 1024);
+
+		/* Compute the top of low memory. */
+		tolmk = pci_tolm / 1024;
+
+		if (tolmk >= tomk) {
+			/* The PCI hole does not overlap the memory. */
+			tolmk = tomk;
+		}
+
+		/* Report the memory regions. */
+		idx = 10;
+		ram_resource(dev, idx++, 0, 640);
+		ram_resource(dev, idx++, 768, tolmk - 768);
+
+#if CONFIG_WRITE_HIGH_TABLES==1
+		/* Leave some space for ACPI, PIRQ and MP tables */
+		high_tables_base = (tomk - HIGH_TABLES_SIZE) * 1024;
+		high_tables_size = HIGH_TABLES_SIZE * 1024;
+#endif
+	}
+	assign_resources(&dev->link[0]);
+}
+
+static struct device_operations pci_domain_ops = {
+	.read_resources		= pci_domain_read_resources,
+	.set_resources		= i440lx_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)
+{
+	/* 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_i440lx_ops = {
+	CHIP_NAME("Intel 82443LX (440LX) Northbridge")
+	.enable_dev = enable_dev,
+};

Added: trunk/src/northbridge/intel/i440lx/northbridge.h
===================================================================
--- trunk/src/northbridge/intel/i440lx/northbridge.h	                        (rev 0)
+++ trunk/src/northbridge/intel/i440lx/northbridge.h	2009-11-28 09:31:30 UTC (rev 4967)
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009 Maciej Pijanka <maciej.pijanka at 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 NORTHBRIDGE_INTEL_440LX_H
+#define NORTHBRIDGE_INTEL_440LX_H
+
+extern unsigned int i440lx_scan_root_bus(device_t root, unsigned int max);
+
+#endif				/* NORTHBRIDGE_INTEL_440LX_H */

Added: trunk/src/northbridge/intel/i440lx/raminit.c
===================================================================
--- trunk/src/northbridge/intel/i440lx/raminit.c	                        (rev 0)
+++ trunk/src/northbridge/intel/i440lx/raminit.c	2009-11-28 09:31:30 UTC (rev 4967)
@@ -0,0 +1,455 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2008 Uwe Hermann <uwe at hermann-uwe.de>
+ * Copyright (C) 2009 Maciej Pijanka <maciej.pijanka at 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 <spd.h>
+#include <sdram_mode.h>
+#include <delay.h>
+#include <stdlib.h>
+#include "i440lx.h"
+
+/*-----------------------------------------------------------------------------
+Macros and definitions.
+-----------------------------------------------------------------------------*/
+
+/* Uncomment this to enable debugging output. */
+
+/* Debugging macros. */
+#if defined(DEBUG_RAM_SETUP)
+#define PRINT_DEBUG(x)		print_debug(x)
+#define PRINT_DEBUG_HEX8(x)	print_debug_hex8(x)
+#define PRINT_DEBUG_HEX16(x)	print_debug_hex16(x)
+#define PRINT_DEBUG_HEX32(x)	print_debug_hex32(x)
+#define DUMPNORTH()		dump_pci_device(PCI_DEV(0, 0, 0))
+#else
+#define PRINT_DEBUG(x)
+#define PRINT_DEBUG_HEX8(x)
+#define PRINT_DEBUG_HEX16(x)
+#define PRINT_DEBUG_HEX32(x)
+#define DUMPNORTH()
+#endif
+
+#define NB PCI_DEV(0, 0, 0)
+
+/* DRAMXC[7:5] - DRAM extended control register (SMS). */
+#define RAM_COMMAND_NORMAL	0x0
+#define RAM_COMMAND_NOP		0x1 // (NOPCE)
+#define RAM_COMMAND_PRECHARGE	0x2 // ABPCE
+#define RAM_COMMAND_MRS		0x3 // MRSCE
+#define RAM_COMMAND_CBR		0x4 // CBRC
+// rest are reserved
+
+/* Table format: register, bitmask, value. */
+static const long register_values[] = {
+	// ~0x02 == bit 9
+	//  0x04 == bit 10
+	// BASE is 0x8A but we dont want bit 9 or 10 have ENABLED so 0x8C
+	PACCFG + 1, 0x38, 0x8c,
+	
+	DBC, 0x00, 0xC3,
+
+	DRT,   0x00, 0xFF,
+	DRT+1, 0x00, 0xFF,
+
+	DRAMC, 0x00, 0x00, /* disable refresh for now. */
+	DRAMT, 0x00, 0x00, 
+
+	PAM0, 0x00, 0x30, // everything is a mem
+	PAM1, 0x00, 0x33,
+	PAM2, 0x00, 0x33,
+	PAM3, 0x00, 0x33,
+	PAM4, 0x00, 0x33,
+	PAM5, 0x00, 0x33,
+	PAM6, 0x00, 0x33,
+
+	/* Set the DRBs to zero for now, this will be fixed later. */
+	DRB0, 0x00, 0x00,
+	DRB1, 0x00, 0x00,
+	DRB2, 0x00, 0x00,
+	DRB3, 0x00, 0x00,
+	DRB4, 0x00, 0x00,
+	DRB5, 0x00, 0x00,
+	DRB6, 0x00, 0x00,
+	DRB7, 0x00, 0x00,
+
+	/* No memory holes. */
+	FDHC, 0x00, 0x00,
+};
+
+/*-----------------------------------------------------------------------------
+SDRAM configuration functions.
+-----------------------------------------------------------------------------*/
+
+/**
+ * Send the specified RAM command to all DIMMs.
+ *
+ * @param command The RAM command to send to the DIMM(s).
+ */
+static void do_ram_command(u32 command)
+{
+	int i, caslatency;
+	u8 dimm_start, dimm_end;
+	u16 reg16;
+	u32 addr, addr_offset;
+
+	/* Configure the RAM command. */
+	reg16 = pci_read_config16(NB, DRAMXC); 
+	reg16 &= 0xff1f;		/* Clear bits 7-5. */
+	reg16 |= (u16) (command << 5);	/* Write command into bits 7-5. */
+	pci_write_config16(NB, DRAMXC, reg16);
+
+	/*
+	 * RAM_COMMAND_NORMAL affects only the memory controller and
+	 * doesn't need to be "sent" to the DIMMs.
+	 */
+	if (command == RAM_COMMAND_NORMAL)
+		return;
+
+	/* Send the RAM command to each row of memory. */
+	dimm_start = 0;
+	for (i = 0; i < (DIMM_SOCKETS * 2); i++) {
+                addr_offset = 0;
+                caslatency = 3; /* TODO: Dynamically get CAS latency later. */
+
+		/* before translation it is 
+		 *
+		 * M[02:00] Burst Length
+		 * M[03:03] Burst Type
+		 * M[06:04] Cas Latency
+		 *          000 - Reserved
+		 *          001 - Reserved
+		 *          010 - CAS 2
+		 *          011 - CAS 3
+		 *          100 - Reserved
+		 *          101 - Reserved
+		 *          110 - Reserved
+		 *          111 - Reserved
+		 * M[08:07] Op Mode
+		 *          Must Be 00b (Defined mode)
+		 * M[09:09] Write Burst Mode
+		 *          0 - Programmed burst length
+		 *          1 - Single location access
+		 * M[11:10] Reserved
+                 *          write 0 to ensure compatibility with....
+		 */
+
+		/* seems constructed value will be right shifted by 3 bit, thus constructed value
+		 * must be left shifted by 3
+		 * so possible formula is (caslatency <<4)|(burst_type << 1)|(burst length)
+		 * then << 3 shift to compensate shift in Memory Controller
+		 */ 
+		if (command == RAM_COMMAND_MRS) {
+			if (caslatency == 3)
+				addr_offset = 0x1d0;
+			if (caslatency == 2)
+				addr_offset = 0x150;
+		}
+
+		dimm_end = pci_read_config8(NB, DRB + i);
+
+		addr = (dimm_start * 8 * 1024 * 1024) + addr_offset;
+		if (dimm_end > dimm_start) {
+#if 0
+			PRINT_DEBUG("    Sending RAM command 0x");
+			PRINT_DEBUG_HEX16(reg16);
+			PRINT_DEBUG(" to 0x");
+			PRINT_DEBUG_HEX32(addr);
+			PRINT_DEBUG("\r\n");
+#endif
+
+			read32(addr);
+		}
+
+		/* Set the start of the next DIMM. */
+		dimm_start = dimm_end;
+	}
+}
+
+/*-----------------------------------------------------------------------------
+DIMM-independant configuration functions.
+-----------------------------------------------------------------------------*/
+
+static void spd_enable_refresh(void)
+{
+	uint8_t reg;
+
+	reg = pci_read_config8(NB, DRAMC);
+
+	/* this chipset offer only two choices regarding refresh
+	 * refresh disabled, or refresh normal
+	 */
+	
+	pci_write_config8(NB, DRAMC, reg | 0x01);
+	reg = pci_read_config8(NB, DRAMC);
+
+	PRINT_DEBUG("spd_enable_refresh: dramc = 0x");
+	PRINT_DEBUG_HEX8(reg);
+	PRINT_DEBUG("\r\n");
+}
+
+/*-----------------------------------------------------------------------------
+Public interface.
+-----------------------------------------------------------------------------*/
+
+static void northbridge_init(void)
+{
+	uint32_t reg32;
+
+	reg32 = pci_read_config32(NB, APBASE);
+	reg32 &= 0xe8000000U;
+	pci_write_config32(NB, APBASE, reg32);
+
+	#ifdef DEBUG_RAM_SETUP
+	/* 
+	 * apbase dont get set still, no idea what i have doing wrong yet, 
+	 * i am almost sure that somehow i set it by mistake once, but can't
+	 * repeat that. 
+	 */
+	reg32 = pci_read_config32(NB, APBASE);
+	PRINT_DEBUG("APBASE ");
+	PRINT_DEBUG_HEX32(reg32);
+	PRINT_DEBUG("\r\n");
+	#endif
+}
+
+
+/**
+ * This routine sets RAM controller inside northbridge to known state
+ *
+ */
+static void sdram_set_registers(void)
+{
+	int i, max;
+
+	/* nice banner with FSB shown? do we have
+	 * any standart policy about such things? 
+	 */
+#if 0
+	uint16_t reg16;
+	reg16 = pci_read_config16(NB, PACCFG); 
+	printk_debug("i82443LX Host Freq: 6%C MHz\r\n", (reg16 & 0x4000) ? '0' : '6');
+#endif
+
+	PRINT_DEBUG("Northbridge prior to SDRAM init:\r\n");
+	DUMPNORTH();
+
+	northbridge_init();
+
+	max = ARRAY_SIZE(register_values);
+
+	/* Set registers as specified in the register_values[] array. */
+	for (i = 0; i < max; i += 3) {
+		uint8_t reg,tmp;
+		reg = pci_read_config8(NB, register_values[i]);
+		reg &= register_values[i + 1];
+		reg |= register_values[i + 2] & ~(register_values[i + 1]);
+		pci_write_config8(NB, register_values[i], reg);
+
+		/* 
+		 * i am not sure if that is needed, but was usefull 
+		 * for me to confirm what got written
+		 */
+#ifdef DEBUG_RAM_SETUP
+		PRINT_DEBUG("    Set register 0x");
+		PRINT_DEBUG_HEX8(register_values[i]);
+		PRINT_DEBUG(" to 0x");
+		PRINT_DEBUG_HEX8(reg);
+		tmp = pci_read_config8(NB, register_values[i]);
+		PRINT_DEBUG(" readed 0x");
+		PRINT_DEBUG_HEX8(tmp);
+		if (tmp == reg) {
+			PRINT_DEBUG(" OK ");
+		} else {
+			PRINT_DEBUG(" FAIL ");
+		}
+		PRINT_DEBUG("\r\n");
+#endif
+	}
+
+	PRINT_DEBUG("Northbridge atexit sdram set registers\r\n");	
+	DUMPNORTH();
+}
+
+
+static void sdram_set_spd_registers(void)
+{
+	int i;
+	u16 memsize = 0;
+
+	for (i = 0; i < DIMM_SOCKETS; i++) {
+		uint16_t ds = 0; // dimm size 
+		int j;
+		/* this code skips second bank on each socket (no idea how to fix it now) 
+		 */
+
+		PRINT_DEBUG("DIMM");
+		PRINT_DEBUG_HEX8(i);
+		PRINT_DEBUG(" rows: ");
+		PRINT_DEBUG_HEX8(spd_read_byte(DIMM_SPD_BASE + i, SPD_NUM_DIMM_BANKS) & 0xFF);
+		PRINT_DEBUG(" rowsize: ");
+		PRINT_DEBUG_HEX8(spd_read_byte(DIMM_SPD_BASE + i, SPD_DENSITY_OF_EACH_ROW_ON_MODULE) & 0xFF);
+		PRINT_DEBUG(" modulesize: ");
+
+		j = spd_read_byte(DIMM_SPD_BASE + i, SPD_NUM_DIMM_BANKS);
+		if (j < 0)
+			j = 0;
+		else
+			ds = j;
+
+		j = spd_read_byte(DIMM_SPD_BASE + i, SPD_DENSITY_OF_EACH_ROW_ON_MODULE);
+
+		if (j < 0)
+			j = 0;
+		else
+			ds = ds * (j >> 1); // convert from 4MB to 8MB units in place
+
+
+		/* This is more or less crude hack
+		 * allowing to run this target under qemu (even if that is not really 
+		 * same hardware emulated), 
+		 * probably some kconfig expert option should be added to enable/disable
+		 * this nicelly
+		 */
+#if 0
+		if (ds == 0 && memsize == 0)
+			ds = 0x8;
+#endif
+
+
+		// todo: support for bank with not equal sizes as per jedec standart?
+		
+		/*
+		 * because density is reported in units of 4Mbyte
+		 * and rows in device are just value, 
+		 * and for setting registers we need value in 8Mbyte units
+		 */
+
+		PRINT_DEBUG_HEX16(ds);
+		PRINT_DEBUG("\r\n");
+
+		memsize += ds;
+
+		pci_write_config8(NB, DRB + (2*i), memsize);
+		pci_write_config8(NB, DRB + (2*i) + 1, memsize);
+		if (ds > 0) {
+			/* i have no idea why pci_read_config16 not work for 
+			 * me correctly here
+			 */
+			ds = pci_read_config8(NB, DRT+1);
+			ds <<=8;
+			ds |= pci_read_config8(NB, DRT);
+
+			PRINT_DEBUG("DRT ");
+			PRINT_DEBUG_HEX16(ds);
+
+			ds &= ~(0x01 << (4 * i));
+
+			PRINT_DEBUG(" ");
+			PRINT_DEBUG_HEX16(ds);
+			PRINT_DEBUG("\r\n");
+
+			/* 
+			 * modify DRT register if current row isn't empty
+			 * code assume its SDRAM plugged (should check if its sdram or EDO, 
+			 * edo would have 0x00 as constand instead 0x10 for SDRAM
+			 * also this code is buggy because ignores second row of each dimm socket
+			 */
+
+			/* and as above write_config16 not work here too)
+			 * pci_write_config16(NB, DRT, j);
+			 */
+
+			pci_write_config8(NB, DRT+1, ds >> 8);
+			pci_write_config8(NB, DRT, ds & 0xFF);
+		}
+	}
+
+#if 0
+	PRINT_DEBUG("Mem: 0x");
+	PRINT_DEBUG_HEX16(memsize * 8);
+	PRINT_DEBUG(" MB\r\n");
+
+	if (memsize == 0) {
+		/* maybe we should use some nice die/hlt sequence with printing on console
+		 * that no memory found, get lost, i can't run?
+		 * maybe such event_handler can be commonly defined routine to decrease
+		 * code duplication?
+		 */
+		PRINT_DEBUG("No memory detected via SPD\r\n");
+		PRINT_DEBUG("Reverting to hardcoded 64M single side dimm in first bank\r\n");
+	}
+#endif
+
+	/* Set DRAMC. Don't enable refresh for now. */
+	pci_write_config8(NB, DRAMC, 0x00);
+
+	/* Cas latency 3, and other shouldbe properly from spd too */
+	pci_write_config8(NB, DRAMT, 0xAC); 
+
+	/* TODO? */
+	pci_write_config8(NB, PCI_LATENCY_TIMER, 0x40);
+
+	// set drive strength
+	pci_write_config32(NB, MBSC, 0x00000000);
+}
+
+static void sdram_enable(void)
+{
+	int i;
+
+	/* 0. Wait until power/voltages and clocks are stable (200us). */
+	udelay(200);
+
+	/* 1. Apply NOP. Wait 200 clock cycles (clock might be 60 or 66 Mhz). */
+	PRINT_DEBUG("RAM Enable 1: Apply NOP\r\n");
+	do_ram_command(RAM_COMMAND_NOP);
+	udelay(200);
+
+	/* 2. Precharge all. Wait tRP. */
+	PRINT_DEBUG("RAM Enable 2: Precharge all\r\n");
+	do_ram_command(RAM_COMMAND_PRECHARGE);
+	udelay(1);
+
+	/* 3. Perform 8 refresh cycles. Wait tRC each time. */
+	PRINT_DEBUG("RAM Enable 3: CBR\r\n");
+	for (i = 0; i < 8; i++) {
+		do_ram_command(RAM_COMMAND_CBR);
+		udelay(1);
+	}
+
+	/* 4. Mode register set. Wait two memory cycles. */
+	PRINT_DEBUG("RAM Enable 4: Mode register set\r\n");
+	do_ram_command(RAM_COMMAND_MRS);
+	udelay(2);
+
+	/* 5. Normal operation. */
+	PRINT_DEBUG("RAM Enable 5: Normal operation\r\n");
+	do_ram_command(RAM_COMMAND_NORMAL);
+	udelay(1);
+
+	/* 6. Finally enable refresh. */
+	PRINT_DEBUG("RAM Enable 6: Enable refresh\r\n");
+	pci_write_config8(NB, DRAMC, 0x01);
+	spd_enable_refresh();
+	udelay(1);
+
+	PRINT_DEBUG("Northbridge following SDRAM init:\r\n");
+}
+

Added: trunk/src/northbridge/intel/i440lx/raminit.h
===================================================================
--- trunk/src/northbridge/intel/i440lx/raminit.h	                        (rev 0)
+++ trunk/src/northbridge/intel/i440lx/raminit.h	2009-11-28 09:31:30 UTC (rev 4967)
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Uwe Hermann <uwe at hermann-uwe.de>
+ * Copyright (C) 2009 Maciej Pijanka <maciej.pijanka at 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
+
+/* The 440LX supports up to four (single- or double-sided) DIMMs. */
+#define DIMM_SOCKETS 4
+
+/* DIMMs 1-4 are at 0x50, 0x51, 0x52, 0x53. */
+#define DIMM_SPD_BASE 0x50
+
+#endif				/* RAMINIT_H */





More information about the coreboot mailing list