Luc Verhaegen | 1 Apr 2007 01:10
Picon
Gravatar

Re: [PATCH] flashrom: board specific enables based on matching pci-ids.

On Mon, Mar 26, 2007 at 04:59:18PM +0200, Luc Verhaegen wrote:
> Done.
> 
> The island aruma got renamed to agami aruma at some point, the board 
> specific match has been adjusted to that now. I hope that the pci ids i 
> gathered from its src/mainboards/ directory are ok. I of course have no 
> way of testing this.
> 
> The rest is pretty much last patch. Except that board enable functions 
> only get passed the name now. The board enable function needs to claim 
> its own pci device, this is safer as the ordering of both found pci 
> devices (and the need for not having to match this and thus handing the 
> callbacks a NULL) was going to get us into trouble.
> 
> The difference for chipset enable and flash_enable is the much cleaner 
> chipset_flash_enable routine. iopl and preparing of the pci_access has 
> been relegated to flash_rom.c. Then there's only some extraneous
> whitespace removal and replacing // with /* */. I'm not sure how svn 
> handles moving of files, but that's usually a good point to do such 
> function-less changes.
> 
> Has been tested on all the same machines again. Needs a quick test on 
> the agami.
> 
> Luc Verhaegen.

ping :)

Anything in this patch that isn't acceptable?

(Continue reading)

Graeme Brett Houston | 1 Apr 2007 16:41

FlashRom

Hi can LinuxBios Take advantage of additional ROM space on addon cards?,
i.e i have a addon RTL1839B card with space of a rom, i also have a rom pulled from a broken motherboard that fits,
would it be possible to either flash with a backup emergancy rom or put LinuxBios on it and it can be part of normal bios startup options or in combination with the main flash chip on motherboard be used completely by LinuxBIOS and only the payloads put on the extra ROM
 
 
 
Thanks Graeme
--

-- 
linuxbios mailing list
linuxbios <at> linuxbios.org
http://www.linuxbios.org/mailman/listinfo/linuxbios
Quux | 1 Apr 2007 17:01
Picon
Favicon

FlashRom

so far there is do explicit support, but it would make some sense. PCI 
expansion ROM is not a full-scale replacement for main BIOS though. PCI 
ROM is called rather later during initialization from legacy BIOS. There 
is public linux code for flashing via RTL Nic cards around however, and 
it might be some kind of "auxiliary ROM" on unsocketed Gigabyte boards 
or play a similar role possibly (my 2 ct.)  --Q

Graeme Brett Houston schrieb:
> Hi can LinuxBios Take advantage of additional ROM space on addon cards?,
> i.e i have a addon RTL1839B card with space of a rom, i also have a 
> rom pulled from a broken motherboard that fits,
> would it be possible to either flash with a backup emergancy rom or 
> put LinuxBios on it and it can be part of normal bios startup options 
> or in combination with the main flash chip on motherboard be used 
> completely by LinuxBIOS and only the payloads put on the extra ROM
>  
>  
>  
> Thanks Graeme

--

-- 
linuxbios mailing list
linuxbios <at> linuxbios.org
http://www.linuxbios.org/mailman/listinfo/linuxbios

Uwe Hermann | 1 Apr 2007 18:50
Picon
Favicon
Gravatar

[PATCH] Intel 44BX RAM initialization framework

This is a first version of my RAM init code for the 440BX.

It does _not_ work, yet. Don't try to use it unless you know what you're
doing.

Uwe.
-- 
http://www.hermann-uwe.de  | http://www.holsham-traders.de
http://www.crazy-hacks.org | http://www.unmaintained-free-software.org
--

-- 
linuxbios mailing list
linuxbios <at> linuxbios.org
http://www.linuxbios.org/mailman/listinfo/linuxbios
Stefan Reinauer | 1 Apr 2007 18:59
Picon

Re: [PATCH] Intel 44BX RAM initialization framework

* Uwe Hermann <uwe <at> hermann-uwe.de> [070401 18:50]:
> This is a first version of my RAM init code for the 440BX.
> 
> It does _not_ work, yet. Don't try to use it unless you know what you're
> doing.

Acked-by: Stefan Reinauer <stepan <at> coresystems.de>
>

> Uwe.
> -- 
> http://www.hermann-uwe.de  | http://www.holsham-traders.de
> http://www.crazy-hacks.org | http://www.unmaintained-free-software.org

> Initial Intel 440BX RAM initialization framework.
> 
> This does _not_ fully work, yet. You will _not_ be able to boot any
> payload with this code, yet.
> 
> Add missing license headers.
> 
> Base the northbridge.c file on the Intel 855PM version, that comes
> closer to what we want.
> 
> The raminit.c file is written from scratch and hardcodes several
> values for now. This needs to be fixed later by reading the
> correct values via SPD.
> 
> Signed-off-by: Uwe Hermann <uwe <at> hermann-uwe.de>
> 
> Index: src/northbridge/intel/i440bx/Config.lb
> ===================================================================
> --- src/northbridge/intel/i440bx/Config.lb	(Revision 2575)
> +++ src/northbridge/intel/i440bx/Config.lb	(Arbeitskopie)
>  <at>  <at>  -1,2 +1,22  <at>  <at> 
> +##
> +## This file is part of the LinuxBIOS 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
> +##
> +
>  config chip.h
>  object northbridge.o
> Index: src/northbridge/intel/i440bx/raminit.c
> ===================================================================
> --- src/northbridge/intel/i440bx/raminit.c	(Revision 2575)
> +++ src/northbridge/intel/i440bx/raminit.c	(Arbeitskopie)
>  <at>  <at>  -1,399 +1,540  <at>  <at> 
> -#include <cpu/x86/mtrr.h>
> -#include "raminit.h"
> -
>  /*
> -This software and ancillary information (herein called SOFTWARE )
> -called LinuxBIOS          is made available under the terms described
> -here.  The SOFTWARE has been approved for release with associated
> -LA-CC Number 00-34   .  Unless otherwise indicated, this SOFTWARE has
> -been authored by an employee or employees of the University of
> -California, operator of the Los Alamos National Laboratory under
> -Contract No. W-7405-ENG-36 with the U.S. Department of Energy.  The
> -U.S. Government has rights to use, reproduce, and distribute this
> -SOFTWARE.  The public may copy, distribute, prepare derivative works
> -and publicly display this SOFTWARE without charge, provided that this
> -Notice and any statement of authorship are reproduced on all copies.
> -Neither the Government nor the University makes any warranty, express 
> -or implied, or assumes any liability or responsibility for the use of
> -this SOFTWARE.  If SOFTWARE is modified to produce derivative works,
> -such modified SOFTWARE should be clearly marked, so as not to confuse
> -it with the version available from LANL.
> + * This file is part of the LinuxBIOS 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
>   */
> -/* Copyright 2000, Ron Minnich, Advanced Computing Lab, LANL
> - * rminnich <at> lanl.gov
> - */
> -/*
> - * 11/26/02 - kevinh <at> ispiri.com - The existing comments implied that
> - * this didn't work yet.  Therefore, I've updated it so that it works
> - * correctly - at least on my VIA epia motherboard.  64MB DIMM in slot 0.
> - */
>  
> -/* Added automatic detection of first equipped bank and its MA mapping type.
> - * (Rest of configuration is done in C)
> - * 5/19/03 by SONE Takeshi <ts1 <at> tsn.or.jp>
> - */
> -/* converted to C 9/2003 Ron Minnich */
> +#include <spd.h>
> +#include <sdram_mode.h>
> +#include <delay.h>
> +#include "i440bx.h"
>  
> -/* Modified for the i440bx Richard Smith 01/2005 */
> +/*-----------------------------------------------------------------------------
> +Macros and definitions.
> +-----------------------------------------------------------------------------*/
>  
> -/* Set to 1 if your DIMMs are PC133 Note that I'm assuming CPU's FSB
> - * frequency is 133MHz. If your CPU runs at another bus speed, you
> - * might need to change some of register values.
> - */
> -#ifndef DIMM_PC133
> -#define DIMM_PC133 0
> -#endif
> +/* Uncomment this to enable debugging output. */
> +#define DEBUG_RAM_SETUP 1
>  
> -// Set to 1 if your DIMMs are CL=2
> -#ifndef DIMM_CL2
> -#define DIMM_CL2 0
> +/* 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
>  
> -void dimms_read(unsigned long x) 
> -{
> -	uint8_t c;
> -	unsigned long eax; 
> -	volatile unsigned long y;
> -	eax =  x;
> -	for(c = 0; c < 6; c++) {
> -		y = * (volatile unsigned long *) eax;
> -		eax += 0x10000000;
> -	}
> -}
> +/* SDRAMC[7:5] - SDRAM Mode Select (SMS). */
> +#define RAM_COMMAND_NORMAL	0x0
> +#define RAM_COMMAND_NOP		0x1
> +#define RAM_COMMAND_PRECHARGE	0x2
> +#define RAM_COMMAND_MRS		0x3
> +#define RAM_COMMAND_CBR		0x4
>  
> -void dimms_write(int x) 
> -{
> -	uint8_t c;
> -	unsigned long eax = x;
> -	for(c = 0; c < 6; c++) {
> -		*(volatile unsigned long *) eax = 0;
> -		eax += 0x10000000;
> -	}
> -}
> +/* Map the JEDEC SPD refresh rates (array index) to 440BX refresh rates as
> + * defined in DRAMC[2:0].
> + *
> + * [0] == Normal        15.625 us ->  15.6 us
> + * [1] == Reduced(.25X)    3.9 us ->   7.8 ns
> + * [2] == Reduced(.5X)     7.8 us ->   7.8 us
> + * [3] == Extended(2x)    31.3 us ->  31.2 us
> + * [4] == Extended(4x)    62.5 us ->  62.4 us
> + * [5] == Extended(8x)     125 us -> 124.8 us
> + */
> +static const uint32_t refresh_rate_map[] = {
> +	1, 5, 5, 2, 3, 4
> +};
>  
> +/* Table format: register, bitmask, value. */
> +static const long register_values[] = {
> +	/* NBXCFG - NBX Configuration Register
> +	 * 0x50
> +	 *
> +	 * [31:24] SDRAM Row Without ECC
> +	 *         0 = ECC components are populated in this row
> +	 *         1 = ECC components are not populated in this row
> +	 * [23:19] Reserved
> +	 * [18:18] Host Bus Fast Data Ready Enable (HBFDRE)
> +	 *         Assertion of DRAM data on host bus occurs...
> +	 *         0 = ...one clock after sampling snoop results (default)
> +	 *         1 = ...on the same clock the snoop result is being sampled
> +	 *             (this mode is faster by one clock cycle)
> +	 * [17:17] ECC - EDO static Drive mode
> +	 *         0 = Normal mode (default)
> +	 *         1 = ECC signals are always driven
> +	 * [16:16] IDSEL_REDIRECT
> +	 *         0 = IDSEL1 is allocated to this bridge (default)
> +	 *         1 = IDSEL7 is allocated to this bridge
> +	 * [15:15] WSC# Handshake Disable
> +	 *         1 = Uni-processor mode
> +	 *         0 = Dual-processor mode with external IOAPIC (default)
> +	 * [14:14] Intel Reserved
> +	 * [13:12] Host/DRAM Frequency
> +	 *         00 = 100 MHz
> +	 *         01 = Reserved
> +	 *         10 = 66 MHz
> +	 *         11 = Reserved
> +	 * [11:11] AGP to PCI Access Enable
> +	 *         1 = Enable
> +	 *         0 = Disable
> +	 * [10:10] PCI Agent to Aperture Access Disable
> +	 *         1 = Disable
> +	 *         0 = Enable (default)
> +	 * [09:09] Aperture Access Global Enable
> +	 *         1 = Enable
> +	 *         0 = Disable
> +	 * [08:07] DRAM Data Integrity Mode (DDIM)
> +	 *         00 = Non-ECC
> +	 *         01 = EC-only
> +	 *         10 = ECC Mode
> +	 *         11 = ECC Mode with hardware scrubbing enabled
> +	 * [06:06] ECC Diagnostic Mode Enable (EDME)
> +	 *         1 = Enable
> +	 *         0 = Normal operation mode (default)
> +	 * [05:05] MDA Present (MDAP)
> +	 *         Works in conjunction with the VGA_EN bit.
> +	 *         VGA_EN MDAP
> +	 *           0     x   All VGA cycles are sent to PCI
> +	 *           1     0   All VGA cycles are sent to AGP
> +	 *           1     1   All VGA cycles are sent to AGP, except for
> +	 *                     cycles in the MDA range.
> +	 * [04:04] Reserved
> +	 * [03:03] USWC Write Post During I/O Bridge Access Enable (UWPIO)
> +	 *         1 = Enable
> +	 *         0 = Disable
> +	 * [02:02] In-Order Queue Depth (IOQD)
> +	 *         1 = In-order queue = maximum
> +	 *         0 = A7# is sampled asserted (i.e., 0)
> +	 * [01:00] Reserved
> +	 */
> +	// TODO
> +	NBXCFG, 0x00000000, 0xff00a00c,
>  
> +	/* DRAMC - DRAM Control Register
> +	 * 0x57
> +	 *
> +	 * [7:6] Reserved
> +	 * [5:5] Module Mode Configuration (MMCONFIG)
> +	 *       TODO
> +	 * [4:3] DRAM Type (DT)
> +	 *       00 = EDO
> +	 *       01 = SDRAM
> +	 *       10 = Registered SDRAM
> +	 *       11 = Reserved
> +	 *       Note: EDO, SDRAM and Registered SDRAM cannot be mixed.
> +	 * [2:0] DRAM Refresh Rate (DRR)
> +	 *       000 = Refresh disabled
> +	 *       001 = 15.6 us
> +	 *       010 = 31.2 us
> +	 *       011 = 62.4 us
> +	 *       100 = 124.8 us
> +	 *       101 = 249.6 us
> +	 *       110 = Reserved
> +	 *       111 = Reserved
> +	 */
> +	/* Choose SDRAM (not registered), and disable refresh for now. */
> +	DRAMC, 0x00, 0x8,
>  
> -#ifdef DEBUG_SETNORTHB
> -void setnorthb(device_t north, uint8_t reg, uint8_t val) 
> -{
> -	print_debug("setnorth: reg ");
> -	print_debug_hex8(reg);
> -	print_debug(" to ");
> -	print_debug_hex8(val);
> -	print_debug("\r\n");
> -	pci_write_config8(north, reg, val);
> -}
> -#else
> -#define setnorthb pci_write_config8
> -#endif
> +	/*
> +	 * PAM[6:0] - Programmable Attribute Map Registers
> +	 *
> +	 * 0x59 [3:0] Reserved
> +	 * 0x59 [5:4] 0xF0000 - 0xFFFFF BIOS area
> +	 * 0x5a [1:0] 0xC0000 - 0xC3FFF ISA add-on BIOS
> +	 * 0x5a [5:4] 0xC4000 - 0xC7FFF ISA add-on BIOS
> +	 * 0x5b [1:0] 0xC8000 - 0xCBFFF ISA add-on BIOS
> +	 * 0x5b [5:4] 0xCC000 - 0xCFFFF ISA add-on BIOS
> +	 * 0x5c [1:0] 0xD0000 - 0xD3FFF ISA add-on BIOS
> +	 * 0x5c [5:4] 0xD4000 - 0xD7FFF ISA add-on BIOS
> +	 * 0x5d [1:0] 0xD8000 - 0xDBFFF ISA add-on BIOS
> +	 * 0x5d [5:4] 0xDC000 - 0xDFFFF ISA add-on BIOS
> +	 * 0x5e [1:0] 0xE0000 - 0xE3FFF BIOS entension
> +	 * 0x5e [5:4] 0xE4000 - 0xE7FFF BIOS entension
> +	 * 0x5f [1:0] 0xE8000 - 0xEBFFF BIOS entension
> +	 * 0x5f [5:4] 0xEC000 - 0xEFFFF BIOS entension
> +	 *
> +	 * Bit assignment:
> +	 * 00 = DRAM Disabled (all access goes to memory mapped I/O space)
> +	 * 01 = Read Only (Reads to DRAM, writes to memory mapped I/O space)
> +	 * 10 = Write Only (Writes to DRAM, reads to memory mapped I/O space)
> +	 * 11 = Read/Write (all access goes to DRAM)
> +	 */
> +	// TODO
> +	PAM0, 0x00000000, 0x00,
> +	PAM1, 0x00000000, 0x00,
> +	PAM2, 0x00000000, 0x00,
> +	PAM3, 0x00000000, 0x00,
> +	PAM4, 0x00000000, 0x00,
> +	PAM5, 0x00000000, 0x00,
> +	PAM6, 0x00000000, 0x00,
>  
> -void
> -dumpnorth(device_t north) 
> -{
> -	unsigned int r, c;
> -	for(r = 0; ; r += 16) {
> -		print_debug_hex8(r);
> -		print_debug(":");
> -		for(c = 0; c < 16; c++) {
> -			print_debug_hex8(pci_read_config8(north, r+c));
> -			print_debug(" ");
> -		}
> -		print_debug("\r\n");
> -		if (r >= 240)
> -			break;
> -  }
> -}
> +	/* DRB[0:7] - DRAM Row Boundary Registers
> +	 * 0x60 - 0x67
> +	 *
> +	 * An array of 8 byte registers, which hold the ending memory address
> +	 * assigned to each pair of DIMMs, in 8MB granularity.   
> +	 *
> +	 * 0x60 DRB0 = Total memory in row0 (in 8 MB)
> +	 * 0x61 DRB1 = Total memory in row0+1 (in 8 MB)
> +	 * 0x62 DRB2 = Total memory in row0+1+2 (in 8 MB)
> +	 * 0x63 DRB3 = Total memory in row0+1+2+3 (in 8 MB)
> +	 * 0x64 DRB4 = Total memory in row0+1+2+3+4 (in 8 MB)
> +	 * 0x65 DRB5 = Total memory in row0+1+2+3+4+5 (in 8 MB)
> +	 * 0x66 DRB6 = Total memory in row0+1+2+3+4+5+6 (in 8 MB)
> +	 * 0x67 DRB7 = Total memory in row0+1+2+3+4+5+6+7 (in 8 MB)
> +	 */
> +	// TODO
> +	DRB0, 0x00, 0x00,
> +	DRB1, 0x00, 0x00,
> +	DRB2, 0x00, 0x00,
> +	DRB3, 0x00, 0x00,
> +	DRB4, 0x00, 0x00,
> +	DRB5, 0x00, 0x00,
> +	DRB6, 0x00, 0x00,
> +	DRB7, 0x00, 0x00,
>  
> -static void sdram_set_registers(const struct mem_controller *ctrl) 
> +	/* FDHC - Fixed DRAM Hole Control Register
> +	 * 0x68
> +	 *
> +	 * Controls two fixed DRAM holes: 512 KB - 640 KB and 15 MB - 16 MB.
> +	 *
> +	 * [7:6] Hole Enable (HEN)
> +	 *       00 = None
> +	 *       01 = 512 KB - 640 KB (128 KB)
> +	 *       10 = 15 MB - 16 MB (1 MB)
> +	 *       11 = Reserved
> +	 * [5:0] Reserved
> +	 */
> +	/* No memory holes. */
> +	FDHC, 0x00, 0x00,
> +
> +	/* RPS - SDRAM Row Page Size Register
> +	 * 0x74 - 0x75
> +	 *
> +	 * Sets the row page size for SDRAM. For EDO memory, the page
> +	 * size is fixed at 2 KB.
> +	 *
> +	 * [15:0] Page Size (PS)
> +	 *        TODO
> +	 */
> +	// TODO
> +	RPS, 0x0000, 0x0000,
> +
> +	/* SDRAMC - SDRAM Control Register
> +	 * 0x76-0x77
> +	 *
> +	 * [15:10] Reserved
> +	 * [09:08] Idle/Pipeline DRAM Leadoff Timing (IPDLT)
> +	 *         00 = Illegal
> +	 *         01 = Add a clock delay to the lead-off clock count
> +	 *         10 = Illegal
> +	 *         11 = Illegal
> +	 * [07:05] SDRAM Mode Select (SMS)
> +	 *         000 = Normal SDRAM Operation (default)
> +	 *         001 = NOP Command Enable
> +	 *         010 = All Banks Precharge Enable
> +	 *         011 = Mode Register Set Enable
> +	 *         100 = CBR Enable
> +	 *         101 = Reserved
> +	 *         110 = Reserved
> +	 *         111 = Reserved
> +	 * [04:04] SDRAMPWR
> +	 *         0 = 3 DIMM configuration
> +	 *         1 = 4 DIMM configuration
> +	 * [03:03] Leadoff Command Timing (LCT)
> +	 *         0 = 4 CS# Clock
> +	 *         1 = 3 CS# Clock
> +	 * [02:02] CAS# Latency (CL)
> +	 *         0 = 3 DCLK CAS# latency
> +	 *         1 = 2 DCLK CAS# latency
> +	 * [01:01] SDRAM RAS# to CAS# Delay (SRCD)
> +	 *         0 = 3 clocks between a row activate and a read or write cmd.
> +	 *         1 = 2 clocks between a row activate and a read or write cmd.
> +	 * [00:00] SDRAM RAS# Precharge (SRP)
> +	 *         0 = 3 clocks of RAS# precharge
> +	 *         1 = 2 clocks of RAS# precharge
> +	 */
> +	SDRAMC, 0x0000, 0x0000,
> +
> +	/* PGPOL - Paging Policy Register
> +	 * 0x78 - 0x79
> +	 *
> +	 * [15:08] Banks per Row (BPR)
> +	 *         TODO
> +	 *         0 = 2 banks
> +	 *         1 = 4 banks
> +	 * [07:05] Reserved
> +	 * [04:04] Intel Reserved
> +	 * [03:00] DRAM Idle Timer (DIT)
> +	 *         0000 = 0 clocks
> +	 *         0001 = 2 clocks
> +	 *         0010 = 4 clocks
> +	 *         0011 = 8 clocks
> +	 *         0100 = 10 clocks
> +	 *         0101 = 12 clocks
> +	 *         0110 = 16 clocks
> +	 *         0111 = 32 clocks
> +	 *         1xxx = Infinite (pages are not closed for idle condition)
> +	 */
> +	// TODO
> +	PGPOL, 0x0000, 0xff00,
> +
> +	/* PMCR - Power Management Control Register
> +	 * 0x7a
> +	 *
> +	 * [07:07] Power Down SDRAM Enable (PDSE)
> +	 *         1 = Enable
> +	 *         0 = Disable
> +	 * [06:06] ACPI Control Register Enable (SCRE)
> +	 *         1 = Enable
> +	 *         0 = Disable (default)
> +	 * [05:05] Suspend Refresh Type (SRT)
> +	 *         1 = Self refresh mode
> +	 *         0 = CBR fresh mode
> +	 * [04:04] Normal Refresh Enable (NREF_EN)
> +	 *         1 = Enable
> +	 *         0 = Disable
> +	 * [03:03] Quick Start Mode (QSTART)
> +	 *         1 = Quick start mode for the processor is enabled
> +	 * [02:02] Gated Clock Enable (GCLKEN)
> +	 *         1 = Enable
> +	 *         0 = Disable
> +	 * [01:01] AGP Disable (AGP_DIS)
> +	 *         1 = Disable
> +	 *         0 = Enable
> +	 * [00:00] CPU reset without PCIRST enable (CRst_En)
> +	 *         1 = Enable
> +	 *         0 = Disable
> +	 */
> +	/* Enable normal refresh and the gated clock. */
> +	// TODO: Only do this later?
> +	// PMCR, 0x00, 0x14,
> +	// PMCR, 0x00, 0x10,
> +	PMCR, 0x00, 0x00,
> +};
> +
> +/*-----------------------------------------------------------------------------
> +SDRAM configuration functions.
> +-----------------------------------------------------------------------------*/
> +
> +/**
> + * Send the specified RAM command to all DIMMs.
> + *
> + *  <at> param Memory controller
> + *  <at> param TODO
> + *  <at> param TODO
> + */
> +static void do_ram_command(const struct mem_controller *ctrl,
> +			   uint32_t command, uint32_t addr_offset)
>  {
> -	device_t north = (device_t) 0;
> -	uint8_t c, r;
> +	int i;
> +	uint16_t reg;
>  
> -	print_err("vt8601 init starting\r\n");
> -	north = pci_locate_device(PCI_ID(0x1106, 0x8601), 0);
> -	north = 0;
> -	print_debug_hex32(north);
> -	print_debug(" is the north\n");
> -	print_debug_hex16(pci_read_config16(north, 0));
> -	print_debug(" ");
> -	print_debug_hex16(pci_read_config16(north, 2));
> -	print_debug("\r\n");
> -	
> -	/* All we are doing now is setting initial known-good values that will
> -	 * be revised later as we read SPD
> -	 */	
> -	// memory clk enable. We are not using ECC
> -	pci_write_config8(north,0x78, 0x01);
> -	print_debug_hex8(pci_read_config8(north, 0x78));
> -	// dram control, see the book. 
> -#if DIMM_PC133
> -	pci_write_config8(north,0x68, 0x52);
> -#else
> -	pci_write_config8(north,0x68, 0x42);
> -#endif
> -	// dram control, see the book. 
> -	pci_write_config8(north,0x6B, 0x0c);
> -	// Initial setting, 256MB in each bank, will be rewritten later.
> -	pci_write_config8(north,0x5A, 0x20);
> -	print_debug_hex8(pci_read_config8(north, 0x5a));
> -	pci_write_config8(north,0x5B, 0x40);
> -	pci_write_config8(north,0x5C, 0x60);
> -	pci_write_config8(north,0x5D, 0x80);
> -	pci_write_config8(north,0x5E, 0xA0);
> -	pci_write_config8(north,0x5F, 0xC0);
> -	// It seems we have to take care of these 2 registers as if 
> -	// they are bank 6 and 7.
> -	pci_write_config8(north,0x56, 0xC0);
> -	pci_write_config8(north,0x57, 0xC0);
> -	
> -	// SDRAM in all banks
> -	pci_write_config8(north,0x60, 0x3F);
> -	// DRAM timing. I'm suspicious of this
> -	// This is for all banks, 64 is 0,1.  65 is 2,3. 66 is 4,5.
> -	// ras precharge 4T, RAS pulse 5T
> -	// cas2 is 0xd6, cas3 is 0xe6
> -	// we're also backing off write pulse width to 2T, so result is 0xee
> -#if DIMM_CL2
> -	pci_write_config8(north,0x64, 0xd4);
> -	pci_write_config8(north,0x65, 0xd4);
> -	pci_write_config8(north,0x66, 0xd4);
> -#else // CL=3
> -	pci_write_config8(north,0x64, 0xe4);
> -	pci_write_config8(north,0x65, 0xe4);
> -	pci_write_config8(north,0x66, 0xe4);
> -#endif
> +	/* TODO: Support for multiple DIMMs. */
>  
> -	// dram frequency select.
> -	// enable 4K pages for 64M dram. 
> -#if DIMM_PC133
> -	pci_write_config8(north,0x69, 0x3c);
> -#else
> -	pci_write_config8(north,0x69, 0xac);
> -#endif
> +	/* Configure the RAM command. */
> +	reg = pci_read_config16(ctrl->d0, SDRAMC);
> +	reg &= 0xff1f;		/* Clear bits 7-5. */
> +	reg |= (uint16_t) (command << 5);
> +	pci_write_config16(ctrl->d0, SDRAMC, reg);
>  
> -	/* IMPORTANT -- disable refresh counter */
> -	// refresh counter, disabled.
> -	pci_write_config8(north,0x6A, 0x00);
> -	
> +	/* RAM_COMMAND_NORMAL affects only the memory controller and
> +	   doesn't need to be "sent" to the DIMMs. */
> +	/* if (command == RAM_COMMAND_NORMAL) return; */
>  
> -	// clkenable configuration. kevinh FIXME - add precharge
> -	pci_write_config8(north,0x6C, 0x00);
> -	// dram read latch delay of 1 ns, MD drive 8 mA,
> -	// high drive strength on MA[2:	13], we#, cas#, ras#
> -	// As per Cindy Lee, set to 0x37, not 0x57
> -	pci_write_config8(north,0x6D, 0x7f);
> +	PRINT_DEBUG("    Sending RAM command 0x");
> +	PRINT_DEBUG_HEX16(reg);
> +	PRINT_DEBUG(" to 0x");
> +	PRINT_DEBUG_HEX32(0 + addr_offset); // FIXME
> +	PRINT_DEBUG("\r\n");
> +
> +	/* Read from (DIMM start address + addr_offset). */
> +	read32(0 + addr_offset); // FIXME
>  }
>  
> -/* slot is the dram slot. Return size of side0 in lower 16-bit,
> - * side1 in upper 16-bit, in units of 8MB */
> -static unsigned long 
> -spd_module_size(unsigned char slot) 
> -{ 
> -	/* for all the DRAMS, see if they are there and get the size of each
> -	 * module. This is just a very early first cut at sizing.
> -	 */
> -	/* we may run out of registers ... */
> -	unsigned int banks, rows, cols, reg;
> -	unsigned int value = 0;
> -	/* unsigned int module = ((0x50 + slot) << 1) + 1; */
> -	unsigned int module = 0x50 + slot;
> -	/* is the module there? if byte 2 is not 4, then we'll assume it 
> -	 * is useless. 
> -	 */
> -	print_info("Slot "); 
> -	print_info_hex8(slot); 
> -	if (smbus_read_byte(module, 2) != 4) {
> -		print_info(" is empty\r\n");
> -		return 0;
> -	}
> -	print_info(" is SDRAM ");
> -	
> -	banks = smbus_read_byte(module, 17);
> -	/* we're going to assume symmetric banks. Sorry. */
> -	cols = smbus_read_byte(module, 4)  & 0xf;
> -	rows = smbus_read_byte(module, 3)  & 0xf;
> -	/* grand total. You have rows+cols addressing, * times of banks, times
> -	 * width of data in bytes */
> -	/* Width is assumed to be 64 bits == 8 bytes */
> -	value = (1 << (cols + rows)) * banks * 8;
> -	print_info_hex32(value);
> -	print_info(" bytes ");
> -	/* Return in 8MB units */
> -	value >>= 23;
> +/*-----------------------------------------------------------------------------
> +DIMM-independant configuration functions.
> +-----------------------------------------------------------------------------*/
>  
> -	/* We should have single or double side */
> -	if (smbus_read_byte(module, 5) == 2) {
> -		print_info("x2");
> -		value = (value << 16) | value;
> +/**
> + * TODO.
> + *
> + *  <at> param Memory controller
> + */
> +static void spd_enable_refresh(const struct mem_controller *ctrl)
> +{
> +	int i, value;
> +	uint8_t reg;
> +
> +	reg = pci_read_config8(ctrl->d0, DRAMC);
> +
> +	for (i = 0; i < DIMM_SOCKETS; i++) {
> +		value = spd_read_byte(ctrl->channel0[i], SPD_REFRESH);
> +		if (value < 0)
> +			continue;
> +		reg = (reg & 0xf8) | refresh_rate_map[(value & 0x7f)];
> +
> +		PRINT_DEBUG("    Enabling refresh (DRAMC = 0x");
> +		PRINT_DEBUG_HEX8(reg);
> +		PRINT_DEBUG(") for DIMM ");
> +		PRINT_DEBUG_HEX8(i);
> +		PRINT_DEBUG("\r\n");
>  	}
> -	print_info("\r\n");
> -	return value;
>  
> +	pci_write_config8(ctrl->d0, DRAMC, reg);
>  }
>  
> -static int
> -spd_num_chips(unsigned char slot) 
> -{ 
> -/*	unsigned int module = ((0x50 + slot) << 1) + 1; */
> -	unsigned int module = 0x50 + slot;
> -	unsigned int width;
> +/*-----------------------------------------------------------------------------
> +Public interface.
> +-----------------------------------------------------------------------------*/
>  
> -	width = smbus_read_byte(module, 13);
> -	if (width == 0)
> -		width = 8;
> -	return 64 / width;
> +/**
> + * TODO.
> + *
> + *  <at> param Memory controller
> + */
> +static void sdram_set_registers(const struct mem_controller *ctrl)
> +{
> +	int i, max;
> +	uint32_t reg;
> +
> +	PRINT_DEBUG("Northbridge prior to SDRAM init:\r\n");
> +	DUMPNORTH();
> +
> +	max = sizeof(register_values) / sizeof(register_values[0]);
> +
> +	/* Set registers as specified in the register_values array. */
> +	for (i = 0; i < max; i += 3) {
> +		reg = pci_read_config32(ctrl->d0, register_values[i]);
> +		reg &= register_values[i + 1];
> +		reg |= register_values[i + 2] & ~(register_values[i + 1]);
> +		pci_write_config32(ctrl->d0, register_values[i], reg);
> +
> +		PRINT_DEBUG("    Set register 0x");
> +		PRINT_DEBUG_HEX32(register_values[i]);
> +		PRINT_DEBUG(" to 0x");
> +		PRINT_DEBUG_HEX32(reg);
> +		PRINT_DEBUG("\r\n");
> +	}
>  }
>  
> +/**
> + * TODO.
> + *
> + *  <at> param Memory controller
> + */
>  static void sdram_set_spd_registers(const struct mem_controller *ctrl)
>  {
> -#define T133 7
> -	unsigned char Trp = 1, Tras = 1, casl = 2, val;
> -	unsigned char timing = 0xe4;
> -	/* read Trp */
> -	val = smbus_read_byte(0x50, 27);
> -	if (val < 2*T133)
> -		Trp = 1;
> -	val = smbus_read_byte(0x50, 30);
> -	if (val < 5*T133)
> -		Tras = 0;
> -	val = smbus_read_byte(0x50, 18);
> -	if (val < 8)
> -		casl = 1;
> -	if (val < 4)
> -		casl = 0;
> -	
> -	val = (Trp << 7) | (Tras << 6) | (casl << 4) | 4;
> -	
> -	print_debug_hex8(val); print_debug(" is the computed timing\n");
> -	/* don't set it. Experience shows that this screwy chipset should just
> -	 * be run with the most conservative timing.
> -	 * pci_write_config8(0, 0x64, val);
> -	 */
> +	/* TODO: Don't hardcode the values here, get info via SPD. */
> +
> +	/* TODO: Set DRB0-DRB7. */
> +	pci_write_config8(ctrl->d0, DRB0, 0x08);
> +	pci_write_config8(ctrl->d0, DRB1, 0x08);
> +	pci_write_config8(ctrl->d0, DRB2, 0x08);
> +	pci_write_config8(ctrl->d0, DRB3, 0x08);
> +	pci_write_config8(ctrl->d0, DRB4, 0x08);
> +	pci_write_config8(ctrl->d0, DRB5, 0x08);
> +	pci_write_config8(ctrl->d0, DRB6, 0x08);
> +	pci_write_config8(ctrl->d0, DRB7, 0x08);
> +
> +	/* TODO: Set DRAMC. Don't enable refresh for now. */
> +	pci_write_config8(ctrl->d0, DRAMC, 0x08);
> +
> +	/* TODO: Set RPS. */
> +	pci_write_config16(ctrl->d0, RPS, 0x0001);
> +
> +	/* TODO: Set SDRAMC. */
> +	// pci_write_config16(ctrl->d0, SDRAMC, 0x0000);
> +
> +	/* TODO: Set PGPOL. */
> +	pci_write_config16(ctrl->d0, PGPOL, 0x0107);
> +
> +	/* TODO: Set NBXCFG. */
> +	// pci_write_config32(ctrl->d0, NBXCFG, 0x0100220c);
> +
> +	/* TODO: Set PMCR? */
> +	// pci_write_config8(ctrl->d0, PMCR, 0x14);
> +	// pci_write_config8(ctrl->d0, PMCR, 0x10);
> +
> +	/* TODO? */
> +	// pci_write_config8(ctrl->d0, MLT, 0x40);
> +	// pci_write_config8(ctrl->d0, DRAMT, 0x03);
> +	// pci_write_config8(ctrl->d0, MBSC, 0x03);
> +	// pci_write_config8(ctrl->d0, SCRR, 0x38);
>  }
>  
> -static void set_ma_mapping(device_t north, int slot, int type)
> +/**
> + * Enable SDRAM.
> + *
> + *  <at> param Number of controllers
> + *  <at> param Memory controller
> + */
> +static void sdram_enable(int controllers, const struct mem_controller *ctrl)
>  {
> -    unsigned char reg, val;
> -    int shift;
> +	int i;
>  
> -    reg = 0x58 + slot/2;
> -    if (slot%2 >= 1)
> -        shift = 0;
> -    else
> -        shift = 4;
> +	/* TODO: Use a delay here? Needed? */
> +	mdelay(200);
>  
> -    val = pci_read_config8(north, reg);
> -    val &= ~(0xf << shift);
> -    val |= type << shift;
> -    pci_write_config8(north, reg, val);
> -}
> +	/* TODO: How long should the delays be? Fix later. */
>  
> +	/* 1. Apply NOP. */
> +	PRINT_DEBUG("RAM Enable 1: Apply NOP\r\n");
> +	do_ram_command(ctrl, RAM_COMMAND_NOP, 0);
> +	mdelay(10);
>  
> -static void sdram_enable(int controllers, const struct mem_controller *ctrl) 
> -{
> -	unsigned char i;
> -	static const uint8_t ramregs[] = {
> -		0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x56, 0x57
> -	};
> -	device_t north = 0;
> -	uint32_t size, base, slot, ma;
> -	/* begin to initialize*/
> -	// I forget why we need this, but we do
> -	dimms_write(0xa55a5aa5);
> -	
> -	/* set NOP*/
> -	pci_write_config8(north,0x6C, 0x01);
> -	print_debug("NOP\r\n");
> -	/* wait 200us*/
> -	// You need to do the memory reference. That causes the nop cycle. 
> -	dimms_read(0);
> -	udelay(400);
> -	print_debug("PRECHARGE\r\n");
> -	/* set precharge */
> -	pci_write_config8(north,0x6C, 0x02);
> -	print_debug("DUMMY READS\r\n");
> -	/* dummy reads*/
> -	dimms_read(0);
> -	udelay(200);
> -	print_debug("CBR\r\n");
> -	/* set CBR*/
> -	pci_write_config8(north,0x6C, 0x04);
> -	
> -	/* do 8 reads and wait >100us between each - from via*/
> -	dimms_read(0);
> -	udelay(200);
> -	dimms_read(0);
> -	udelay(200);
> -	dimms_read(0);
> -	udelay(200);
> -	dimms_read(0);
> -	udelay(200);
> -	dimms_read(0);
> -	udelay(200);
> -	dimms_read(0);
> -	udelay(200);
> -	dimms_read(0);
> -	udelay(200);
> -	dimms_read(0);
> -	udelay(200);
> -	print_debug("MRS\r\n");
> -	/* set MRS*/
> -	pci_write_config8(north,0x6c, 0x03);
> -#if DIMM_CL2
> -	dimms_read(0x150);
> -#else // CL=3
> -	dimms_read(0x1d0);
> -#endif
> -	udelay(200);
> -	print_debug("NORMAL\r\n");
> -	/* set to normal mode */
> -	pci_write_config8(north,0x6C, 0x08);
> -	
> -	dimms_write(0x55aa55aa);
> -	dimms_read(0);
> -	udelay(200);
> -	print_debug("set ref. rate\r\n");
> -	// Set the refresh rate. 
> -#if DIMM_PC133
> -	pci_write_config8(north,0x6A, 0x86);
> -#else
> -	pci_write_config8(north,0x6A, 0x65);
> -#endif
> -	print_debug("enable multi-page open\r\n");
> -	// enable multi-page open
> -	pci_write_config8(north,0x6B, 0x0d);
> -	
> -	base = 0;
> -	for(slot = 0; slot < 4; slot++) {
> -		size = spd_module_size(slot);
> -		/* side 0 */
> -		base += size & 0xffff;
> -		pci_write_config8(north, ramregs[2*slot], base);
> -		/* side 1 */
> -		base += size >> 16;
> -		if (base > 0xff)
> -			base = 0xff;
> -		pci_write_config8(north, ramregs[2*slot + 1], base);
> +	/* 2. Precharge all. Wait tRP. */
> +	PRINT_DEBUG("RAM Enable 2: Precharge all\r\n");
> +	do_ram_command(ctrl, RAM_COMMAND_PRECHARGE, 0);
> +	mdelay(10);
>  
> -		if (!size)
> -			continue;
> +	/* 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(ctrl, RAM_COMMAND_CBR, 0);
> +		mdelay(10);
> +	}
>  
> -		/* Calculate the value of MA mapping type register,
> -		 * based on size of SDRAM chips. */
> -		size = (size & 0xffff) << (3 + 3);
> -			/* convert module size to be in Mbits */
> -		size /= spd_num_chips(slot);
> -		print_debug_hex16(size);
> -		print_debug(" is the chip size\r\n");
> -		if (size < 64)
> -			ma = 0;
> -		if (size < 256)
> -			ma = 8;
> -		else
> -			ma = 0xe;
> -		print_debug_hex16(ma);
> -		print_debug(" is the MA type\r\n");
> -		set_ma_mapping(north, slot, ma);
> -	}
> -	print_err("vt8601 done\r\n");
> +	/* 4. Mode register set. Wait two memory cycles. */
> +	PRINT_DEBUG("RAM Enable 4: Mode register set\r\n");
> +	do_ram_command(ctrl, RAM_COMMAND_MRS, 0x1d0);
> +	// TODO: Is 0x1d0 correct?
> +	// do_ram_command(ctrl, RAM_COMMAND_MRS, 0x1d0000);
> +	mdelay(10);
> +	mdelay(10);
> +
> +	/* 5. Normal operation. */
> +	PRINT_DEBUG("RAM Enable 5: Normal operation\r\n");
> +	do_ram_command(ctrl, RAM_COMMAND_NORMAL, 0);
> +	mdelay(10);
> +
> +	/* 6. Finally enable refresh. */
> +	PRINT_DEBUG("RAM Enable 6: Enable refresh\r\n");
> +	// pci_write_config8(ctrl->d0, PMCR, 0x10);
> +	spd_enable_refresh(ctrl);
> +	mdelay(10);
> +
> +	PRINT_DEBUG("Northbridge following SDRAM init:\r\n");
> +	DUMPNORTH();
>  }
> Index: src/northbridge/intel/i440bx/northbridge.c
> ===================================================================
> --- src/northbridge/intel/i440bx/northbridge.c	(Revision 2575)
> +++ src/northbridge/intel/i440bx/northbridge.c	(Arbeitskopie)
>  <at>  <at>  -9,15 +9,13  <at>  <at> 
>  #include <bitops.h>
>  #include "chip.h"
>  #include "northbridge.h"
> +#include "i440bx.h"
>  
> -/*
> -*/
>  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,
>  <at>  <at>  -34,20 +32,20  <at>  <at> 
>  };
>  
>  
> -
>  #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 = 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 = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
>          resource->limit = 0xffffffffULL;
>          resource->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
>  }
>  <at>  <at>  -93,36 +91,28  <at>  <at> 
>  
>  static void pci_domain_set_resources(device_t dev)
>  {
> -	static const uint8_t ramregs[] = {
> -		0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x56, 0x57
> -	};
>  	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) {
> +		/* 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;
>  		unsigned long tomk, tolmk;
> -		unsigned char rambits;
> -		int i, idx;
> +		int idx;
>  
> -		for(rambits = 0, i = 0; i < sizeof(ramregs)/sizeof(ramregs[0]); i++) {
> -			unsigned char reg;
> -			reg = pci_read_config8(mc_dev, ramregs[i]);
> -			/* these are ENDING addresses, not sizes. 
> -			 * if there is memory in this slot, then reg will be > rambits.
> -			 * So we just take the max, that gives us total. 
> -			 * We take the highest one to cover for once and future linuxbios
> -			 * bugs. We warn about bugs.
> -			 */
> -			if (reg > rambits)
> -				rambits = reg;
> -			if (reg < rambits)
> -				printk_err("ERROR! register 0x%x is not set!\n", 
> -					ramregs[i]);
> -		}
> -		printk_debug("I would set ram size to 0x%x Kbytes\n", (rambits)*8*1024);
> -		tomk = rambits*8*1024;
> +		/* Get the value of the highest DRB. This tells the end of
> +		 * the physical memory.  The units are ticks of 8MB
> +		 * i.e. 1 means 8MB.
> +		 */
> +		tomk = ((unsigned long)pci_read_config8(mc_dev, DRB7)) << 15;
>  		/* Compute the top of Low memory */
>  		tolmk = pci_tolm >> 10;
>  		if (tolmk >= tomk) {
>  <at>  <at>  -130,9 +120,17  <at>  <at> 
>  			 */
>  			tolmk = tomk;
>  		}
> +		/* Write the ram configuration registers,
> +		 * preserving the reserved bits.
> +		 */
> +		tolm_r = pci_read_config16(mc_dev, 0xc4);
> +		tolm_r = ((tolmk >> 10) << 3) | (tolm_r & 0xf);
> +		pci_write_config16(mc_dev, 0xc4, tolm_r);
> +
>  		/* Report the memory regions */
>  		idx = 10;
> -		ram_resource(dev, idx++, 0, tolmk);
> +		ram_resource(dev, idx++, 0, 640);
> +		ram_resource(dev, idx++, 768, tolmk - 768);
>  	}
>  	assign_resources(&dev->link[0]);
>  }
>  <at>  <at>  -170,6 +168,8  <at>  <at> 
>  
>  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;
>  <at>  <at>  -182,5 +182,5  <at>  <at> 
>  
>  struct chip_operations northbridge_intel_i440bx_ops = {
>  	CHIP_NAME("Intel 440BX Northbridge")
> -	.enable_dev = enable_dev, 
> +	.enable_dev = enable_dev,
>  };
> Index: src/northbridge/intel/i440bx/chip.h
> ===================================================================
> --- src/northbridge/intel/i440bx/chip.h	(Revision 2575)
> +++ src/northbridge/intel/i440bx/chip.h	(Arbeitskopie)
>  <at>  <at>  -1,3 +1,23  <at>  <at> 
> +/*
> + * This file is part of the LinuxBIOS 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
> + */
> +
>  struct northbridge_intel_i440bx_config
>  {
>  };
> Index: src/northbridge/intel/i440bx/raminit.h
> ===================================================================
> --- src/northbridge/intel/i440bx/raminit.h	(Revision 2575)
> +++ src/northbridge/intel/i440bx/raminit.h	(Arbeitskopie)
>  <at>  <at>  -1,11 +1,33  <at>  <at> 
> +/*
> + * This file is part of the LinuxBIOS 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
> + */
> +
>  #ifndef RAMINIT_H
>  #define RAMINIT_H
>  
> +/* The 440BX supports up to four (single- or double-sided) DIMMs. */
>  #define DIMM_SOCKETS 4
> +
> +/* The 440BX memory controller has one channel only. */
>  struct mem_controller {
> -  device_t d0;
> -  uint16_t channel0[DIMM_SOCKETS];
> +	device_t d0;
> +	uint16_t channel0[DIMM_SOCKETS];
>  };
>  
> -
> -#endif /* RAMINIT_H */
> +#endif				/* RAMINIT_H */
> Index: src/northbridge/intel/i440bx/northbridge.h
> ===================================================================
> --- src/northbridge/intel/i440bx/northbridge.h	(Revision 2575)
> +++ src/northbridge/intel/i440bx/northbridge.h	(Arbeitskopie)
>  <at>  <at>  -1,3 +1,23  <at>  <at> 
> +/*
> + * This file is part of the LinuxBIOS 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
> + */
> +
>  #ifndef NORTHBRIDGE_INTEL_440BX_H
>  #define NORTHBRIDGE_INTEL_440BX_H
>  
>  <at>  <at>  -3,3 +23,3  <at>  <at> 
>  extern unsigned int i440bx_scan_root_bus(device_t root, unsigned int max);
>  
> -#endif /* NORTHBRIDGE_INTEL_440BX_H */
> +#endif				/* NORTHBRIDGE_INTEL_440BX_H */

> -- 
> linuxbios mailing list
> linuxbios <at> linuxbios.org
> http://www.linuxbios.org/mailman/listinfo/linuxbios

-- 
coresystems GmbH • Brahmsstr. 16 • D-79104 Freiburg i. Br.
      Tel.: +49 761 7668825 • Fax: +49 761 7664613
Email: info <at> coresystems.de  • http://www.coresystems.de/

--

-- 
linuxbios mailing list
linuxbios <at> linuxbios.org
http://www.linuxbios.org/mailman/listinfo/linuxbios
svn | 1 Apr 2007 19:24

r2576 - trunk/LinuxBIOSv2/src/northbridge/intel/i440bx

Author: uwe
Date: 2007-04-01 19:24:03 +0200 (Sun, 01 Apr 2007)
New Revision: 2576

Modified:
   trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/Config.lb
   trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/chip.h
   trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/northbridge.c
   trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/northbridge.h
   trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/raminit.c
   trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/raminit.h
Log:
Initial Intel 440BX RAM initialization framework.

This does _not_ fully work, yet. You will _not_ be able to boot any
payload with this code, yet.

Add missing license headers.

Base the northbridge.c file on the Intel 855PM version, that comes
closer to what we want.

The raminit.c file is written from scratch and hardcodes several
values for now. This needs to be fixed later by reading the
correct values via SPD.

Signed-off-by: Uwe Hermann <uwe <at> hermann-uwe.de>
Acked-by: Stefan Reinauer <stepan <at> coresystems.de>

Modified: trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/Config.lb
===================================================================
--- trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/Config.lb	2007-03-31 19:48:38 UTC (rev 2575)
+++ trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/Config.lb	2007-04-01 17:24:03 UTC (rev 2576)
 <at>  <at>  -1,2 +1,22  <at>  <at> 
+##
+## This file is part of the LinuxBIOS 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
+##
+
 config chip.h
 object northbridge.o

Modified: trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/chip.h
===================================================================
--- trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/chip.h	2007-03-31 19:48:38 UTC (rev 2575)
+++ trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/chip.h	2007-04-01 17:24:03 UTC (rev 2576)
 <at>  <at>  -1,3 +1,23  <at>  <at> 
+/*
+ * This file is part of the LinuxBIOS 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
+ */
+
 struct northbridge_intel_i440bx_config
 {
 };

Modified: trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/northbridge.c
===================================================================
--- trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/northbridge.c	2007-03-31 19:48:38 UTC (rev 2575)
+++ trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/northbridge.c	2007-04-01 17:24:03 UTC (rev 2576)
 <at>  <at>  -9,15 +9,13  <at>  <at> 
 #include <bitops.h>
 #include "chip.h"
 #include "northbridge.h"
+#include "i440bx.h"

-/*
-*/
 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,
 <at>  <at>  -34,20 +32,20  <at>  <at> 
 };

 
-
 #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 = 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 = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
         resource->limit = 0xffffffffULL;
         resource->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
 }
 <at>  <at>  -93,36 +91,28  <at>  <at> 

 static void pci_domain_set_resources(device_t dev)
 {
-	static const uint8_t ramregs[] = {
-		0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x56, 0x57
-	};
 	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) {
+		/* 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;
 		unsigned long tomk, tolmk;
-		unsigned char rambits;
-		int i, idx;
+		int idx;

-		for(rambits = 0, i = 0; i < sizeof(ramregs)/sizeof(ramregs[0]); i++) {
-			unsigned char reg;
-			reg = pci_read_config8(mc_dev, ramregs[i]);
-			/* these are ENDING addresses, not sizes. 
-			 * if there is memory in this slot, then reg will be > rambits.
-			 * So we just take the max, that gives us total. 
-			 * We take the highest one to cover for once and future linuxbios
-			 * bugs. We warn about bugs.
-			 */
-			if (reg > rambits)
-				rambits = reg;
-			if (reg < rambits)
-				printk_err("ERROR! register 0x%x is not set!\n", 
-					ramregs[i]);
-		}
-		printk_debug("I would set ram size to 0x%x Kbytes\n", (rambits)*8*1024);
-		tomk = rambits*8*1024;
+		/* Get the value of the highest DRB. This tells the end of
+		 * the physical memory.  The units are ticks of 8MB
+		 * i.e. 1 means 8MB.
+		 */
+		tomk = ((unsigned long)pci_read_config8(mc_dev, DRB7)) << 15;
 		/* Compute the top of Low memory */
 		tolmk = pci_tolm >> 10;
 		if (tolmk >= tomk) {
 <at>  <at>  -130,9 +120,17  <at>  <at> 
 			 */
 			tolmk = tomk;
 		}
+		/* Write the ram configuration registers,
+		 * preserving the reserved bits.
+		 */
+		tolm_r = pci_read_config16(mc_dev, 0xc4);
+		tolm_r = ((tolmk >> 10) << 3) | (tolm_r & 0xf);
+		pci_write_config16(mc_dev, 0xc4, tolm_r);
+
 		/* Report the memory regions */
 		idx = 10;
-		ram_resource(dev, idx++, 0, tolmk);
+		ram_resource(dev, idx++, 0, 640);
+		ram_resource(dev, idx++, 768, tolmk - 768);
 	}
 	assign_resources(&dev->link[0]);
 }
 <at>  <at>  -170,6 +168,8  <at>  <at> 

 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;
 <at>  <at>  -182,5 +182,5  <at>  <at> 

 struct chip_operations northbridge_intel_i440bx_ops = {
 	CHIP_NAME("Intel 440BX Northbridge")
-	.enable_dev = enable_dev, 
+	.enable_dev = enable_dev,
 };

Modified: trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/northbridge.h
===================================================================
--- trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/northbridge.h	2007-03-31 19:48:38 UTC (rev 2575)
+++ trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/northbridge.h	2007-04-01 17:24:03 UTC (rev 2576)
 <at>  <at>  -1,3 +1,23  <at>  <at> 
+/*
+ * This file is part of the LinuxBIOS 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
+ */
+
 #ifndef NORTHBRIDGE_INTEL_440BX_H
 #define NORTHBRIDGE_INTEL_440BX_H

 <at>  <at>  -3,3 +23,3  <at>  <at> 
 extern unsigned int i440bx_scan_root_bus(device_t root, unsigned int max);

-#endif /* NORTHBRIDGE_INTEL_440BX_H */
+#endif				/* NORTHBRIDGE_INTEL_440BX_H */

Modified: trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/raminit.c
===================================================================
--- trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/raminit.c	2007-03-31 19:48:38 UTC (rev 2575)
+++ trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/raminit.c	2007-04-01 17:24:03 UTC (rev 2576)
 <at>  <at>  -1,399 +1,540  <at>  <at> 
-#include <cpu/x86/mtrr.h>
-#include "raminit.h"
-
 /*
-This software and ancillary information (herein called SOFTWARE )
-called LinuxBIOS          is made available under the terms described
-here.  The SOFTWARE has been approved for release with associated
-LA-CC Number 00-34   .  Unless otherwise indicated, this SOFTWARE has
-been authored by an employee or employees of the University of
-California, operator of the Los Alamos National Laboratory under
-Contract No. W-7405-ENG-36 with the U.S. Department of Energy.  The
-U.S. Government has rights to use, reproduce, and distribute this
-SOFTWARE.  The public may copy, distribute, prepare derivative works
-and publicly display this SOFTWARE without charge, provided that this
-Notice and any statement of authorship are reproduced on all copies.
-Neither the Government nor the University makes any warranty, express 
-or implied, or assumes any liability or responsibility for the use of
-this SOFTWARE.  If SOFTWARE is modified to produce derivative works,
-such modified SOFTWARE should be clearly marked, so as not to confuse
-it with the version available from LANL.
+ * This file is part of the LinuxBIOS 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
  */
-/* Copyright 2000, Ron Minnich, Advanced Computing Lab, LANL
- * rminnich <at> lanl.gov
- */
-/*
- * 11/26/02 - kevinh <at> ispiri.com - The existing comments implied that
- * this didn't work yet.  Therefore, I've updated it so that it works
- * correctly - at least on my VIA epia motherboard.  64MB DIMM in slot 0.
- */

-/* Added automatic detection of first equipped bank and its MA mapping type.
- * (Rest of configuration is done in C)
- * 5/19/03 by SONE Takeshi <ts1 <at> tsn.or.jp>
- */
-/* converted to C 9/2003 Ron Minnich */
+#include <spd.h>
+#include <sdram_mode.h>
+#include <delay.h>
+#include "i440bx.h"

-/* Modified for the i440bx Richard Smith 01/2005 */
+/*-----------------------------------------------------------------------------
+Macros and definitions.
+-----------------------------------------------------------------------------*/

-/* Set to 1 if your DIMMs are PC133 Note that I'm assuming CPU's FSB
- * frequency is 133MHz. If your CPU runs at another bus speed, you
- * might need to change some of register values.
- */
-#ifndef DIMM_PC133
-#define DIMM_PC133 0
-#endif
+/* Uncomment this to enable debugging output. */
+#define DEBUG_RAM_SETUP 1

-// Set to 1 if your DIMMs are CL=2
-#ifndef DIMM_CL2
-#define DIMM_CL2 0
+/* 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

-void dimms_read(unsigned long x) 
-{
-	uint8_t c;
-	unsigned long eax; 
-	volatile unsigned long y;
-	eax =  x;
-	for(c = 0; c < 6; c++) {
-		y = * (volatile unsigned long *) eax;
-		eax += 0x10000000;
-	}
-}
+/* SDRAMC[7:5] - SDRAM Mode Select (SMS). */
+#define RAM_COMMAND_NORMAL	0x0
+#define RAM_COMMAND_NOP		0x1
+#define RAM_COMMAND_PRECHARGE	0x2
+#define RAM_COMMAND_MRS		0x3
+#define RAM_COMMAND_CBR		0x4

-void dimms_write(int x) 
-{
-	uint8_t c;
-	unsigned long eax = x;
-	for(c = 0; c < 6; c++) {
-		*(volatile unsigned long *) eax = 0;
-		eax += 0x10000000;
-	}
-}
+/* Map the JEDEC SPD refresh rates (array index) to 440BX refresh rates as
+ * defined in DRAMC[2:0].
+ *
+ * [0] == Normal        15.625 us ->  15.6 us
+ * [1] == Reduced(.25X)    3.9 us ->   7.8 ns
+ * [2] == Reduced(.5X)     7.8 us ->   7.8 us
+ * [3] == Extended(2x)    31.3 us ->  31.2 us
+ * [4] == Extended(4x)    62.5 us ->  62.4 us
+ * [5] == Extended(8x)     125 us -> 124.8 us
+ */
+static const uint32_t refresh_rate_map[] = {
+	1, 5, 5, 2, 3, 4
+};

+/* Table format: register, bitmask, value. */
+static const long register_values[] = {
+	/* NBXCFG - NBX Configuration Register
+	 * 0x50
+	 *
+	 * [31:24] SDRAM Row Without ECC
+	 *         0 = ECC components are populated in this row
+	 *         1 = ECC components are not populated in this row
+	 * [23:19] Reserved
+	 * [18:18] Host Bus Fast Data Ready Enable (HBFDRE)
+	 *         Assertion of DRAM data on host bus occurs...
+	 *         0 = ...one clock after sampling snoop results (default)
+	 *         1 = ...on the same clock the snoop result is being sampled
+	 *             (this mode is faster by one clock cycle)
+	 * [17:17] ECC - EDO static Drive mode
+	 *         0 = Normal mode (default)
+	 *         1 = ECC signals are always driven
+	 * [16:16] IDSEL_REDIRECT
+	 *         0 = IDSEL1 is allocated to this bridge (default)
+	 *         1 = IDSEL7 is allocated to this bridge
+	 * [15:15] WSC# Handshake Disable
+	 *         1 = Uni-processor mode
+	 *         0 = Dual-processor mode with external IOAPIC (default)
+	 * [14:14] Intel Reserved
+	 * [13:12] Host/DRAM Frequency
+	 *         00 = 100 MHz
+	 *         01 = Reserved
+	 *         10 = 66 MHz
+	 *         11 = Reserved
+	 * [11:11] AGP to PCI Access Enable
+	 *         1 = Enable
+	 *         0 = Disable
+	 * [10:10] PCI Agent to Aperture Access Disable
+	 *         1 = Disable
+	 *         0 = Enable (default)
+	 * [09:09] Aperture Access Global Enable
+	 *         1 = Enable
+	 *         0 = Disable
+	 * [08:07] DRAM Data Integrity Mode (DDIM)
+	 *         00 = Non-ECC
+	 *         01 = EC-only
+	 *         10 = ECC Mode
+	 *         11 = ECC Mode with hardware scrubbing enabled
+	 * [06:06] ECC Diagnostic Mode Enable (EDME)
+	 *         1 = Enable
+	 *         0 = Normal operation mode (default)
+	 * [05:05] MDA Present (MDAP)
+	 *         Works in conjunction with the VGA_EN bit.
+	 *         VGA_EN MDAP
+	 *           0     x   All VGA cycles are sent to PCI
+	 *           1     0   All VGA cycles are sent to AGP
+	 *           1     1   All VGA cycles are sent to AGP, except for
+	 *                     cycles in the MDA range.
+	 * [04:04] Reserved
+	 * [03:03] USWC Write Post During I/O Bridge Access Enable (UWPIO)
+	 *         1 = Enable
+	 *         0 = Disable
+	 * [02:02] In-Order Queue Depth (IOQD)
+	 *         1 = In-order queue = maximum
+	 *         0 = A7# is sampled asserted (i.e., 0)
+	 * [01:00] Reserved
+	 */
+	// TODO
+	NBXCFG, 0x00000000, 0xff00a00c,

+	/* DRAMC - DRAM Control Register
+	 * 0x57
+	 *
+	 * [7:6] Reserved
+	 * [5:5] Module Mode Configuration (MMCONFIG)
+	 *       TODO
+	 * [4:3] DRAM Type (DT)
+	 *       00 = EDO
+	 *       01 = SDRAM
+	 *       10 = Registered SDRAM
+	 *       11 = Reserved
+	 *       Note: EDO, SDRAM and Registered SDRAM cannot be mixed.
+	 * [2:0] DRAM Refresh Rate (DRR)
+	 *       000 = Refresh disabled
+	 *       001 = 15.6 us
+	 *       010 = 31.2 us
+	 *       011 = 62.4 us
+	 *       100 = 124.8 us
+	 *       101 = 249.6 us
+	 *       110 = Reserved
+	 *       111 = Reserved
+	 */
+	/* Choose SDRAM (not registered), and disable refresh for now. */
+	DRAMC, 0x00, 0x8,

-#ifdef DEBUG_SETNORTHB
-void setnorthb(device_t north, uint8_t reg, uint8_t val) 
-{
-	print_debug("setnorth: reg ");
-	print_debug_hex8(reg);
-	print_debug(" to ");
-	print_debug_hex8(val);
-	print_debug("\r\n");
-	pci_write_config8(north, reg, val);
-}
-#else
-#define setnorthb pci_write_config8
-#endif
+	/*
+	 * PAM[6:0] - Programmable Attribute Map Registers
+	 *
+	 * 0x59 [3:0] Reserved
+	 * 0x59 [5:4] 0xF0000 - 0xFFFFF BIOS area
+	 * 0x5a [1:0] 0xC0000 - 0xC3FFF ISA add-on BIOS
+	 * 0x5a [5:4] 0xC4000 - 0xC7FFF ISA add-on BIOS
+	 * 0x5b [1:0] 0xC8000 - 0xCBFFF ISA add-on BIOS
+	 * 0x5b [5:4] 0xCC000 - 0xCFFFF ISA add-on BIOS
+	 * 0x5c [1:0] 0xD0000 - 0xD3FFF ISA add-on BIOS
+	 * 0x5c [5:4] 0xD4000 - 0xD7FFF ISA add-on BIOS
+	 * 0x5d [1:0] 0xD8000 - 0xDBFFF ISA add-on BIOS
+	 * 0x5d [5:4] 0xDC000 - 0xDFFFF ISA add-on BIOS
+	 * 0x5e [1:0] 0xE0000 - 0xE3FFF BIOS entension
+	 * 0x5e [5:4] 0xE4000 - 0xE7FFF BIOS entension
+	 * 0x5f [1:0] 0xE8000 - 0xEBFFF BIOS entension
+	 * 0x5f [5:4] 0xEC000 - 0xEFFFF BIOS entension
+	 *
+	 * Bit assignment:
+	 * 00 = DRAM Disabled (all access goes to memory mapped I/O space)
+	 * 01 = Read Only (Reads to DRAM, writes to memory mapped I/O space)
+	 * 10 = Write Only (Writes to DRAM, reads to memory mapped I/O space)
+	 * 11 = Read/Write (all access goes to DRAM)
+	 */
+	// TODO
+	PAM0, 0x00000000, 0x00,
+	PAM1, 0x00000000, 0x00,
+	PAM2, 0x00000000, 0x00,
+	PAM3, 0x00000000, 0x00,
+	PAM4, 0x00000000, 0x00,
+	PAM5, 0x00000000, 0x00,
+	PAM6, 0x00000000, 0x00,

-void
-dumpnorth(device_t north) 
-{
-	unsigned int r, c;
-	for(r = 0; ; r += 16) {
-		print_debug_hex8(r);
-		print_debug(":");
-		for(c = 0; c < 16; c++) {
-			print_debug_hex8(pci_read_config8(north, r+c));
-			print_debug(" ");
-		}
-		print_debug("\r\n");
-		if (r >= 240)
-			break;
-  }
-}
+	/* DRB[0:7] - DRAM Row Boundary Registers
+	 * 0x60 - 0x67
+	 *
+	 * An array of 8 byte registers, which hold the ending memory address
+	 * assigned to each pair of DIMMs, in 8MB granularity.   
+	 *
+	 * 0x60 DRB0 = Total memory in row0 (in 8 MB)
+	 * 0x61 DRB1 = Total memory in row0+1 (in 8 MB)
+	 * 0x62 DRB2 = Total memory in row0+1+2 (in 8 MB)
+	 * 0x63 DRB3 = Total memory in row0+1+2+3 (in 8 MB)
+	 * 0x64 DRB4 = Total memory in row0+1+2+3+4 (in 8 MB)
+	 * 0x65 DRB5 = Total memory in row0+1+2+3+4+5 (in 8 MB)
+	 * 0x66 DRB6 = Total memory in row0+1+2+3+4+5+6 (in 8 MB)
+	 * 0x67 DRB7 = Total memory in row0+1+2+3+4+5+6+7 (in 8 MB)
+	 */
+	// TODO
+	DRB0, 0x00, 0x00,
+	DRB1, 0x00, 0x00,
+	DRB2, 0x00, 0x00,
+	DRB3, 0x00, 0x00,
+	DRB4, 0x00, 0x00,
+	DRB5, 0x00, 0x00,
+	DRB6, 0x00, 0x00,
+	DRB7, 0x00, 0x00,

-static void sdram_set_registers(const struct mem_controller *ctrl) 
+	/* FDHC - Fixed DRAM Hole Control Register
+	 * 0x68
+	 *
+	 * Controls two fixed DRAM holes: 512 KB - 640 KB and 15 MB - 16 MB.
+	 *
+	 * [7:6] Hole Enable (HEN)
+	 *       00 = None
+	 *       01 = 512 KB - 640 KB (128 KB)
+	 *       10 = 15 MB - 16 MB (1 MB)
+	 *       11 = Reserved
+	 * [5:0] Reserved
+	 */
+	/* No memory holes. */
+	FDHC, 0x00, 0x00,
+
+	/* RPS - SDRAM Row Page Size Register
+	 * 0x74 - 0x75
+	 *
+	 * Sets the row page size for SDRAM. For EDO memory, the page
+	 * size is fixed at 2 KB.
+	 *
+	 * [15:0] Page Size (PS)
+	 *        TODO
+	 */
+	// TODO
+	RPS, 0x0000, 0x0000,
+
+	/* SDRAMC - SDRAM Control Register
+	 * 0x76-0x77
+	 *
+	 * [15:10] Reserved
+	 * [09:08] Idle/Pipeline DRAM Leadoff Timing (IPDLT)
+	 *         00 = Illegal
+	 *         01 = Add a clock delay to the lead-off clock count
+	 *         10 = Illegal
+	 *         11 = Illegal
+	 * [07:05] SDRAM Mode Select (SMS)
+	 *         000 = Normal SDRAM Operation (default)
+	 *         001 = NOP Command Enable
+	 *         010 = All Banks Precharge Enable
+	 *         011 = Mode Register Set Enable
+	 *         100 = CBR Enable
+	 *         101 = Reserved
+	 *         110 = Reserved
+	 *         111 = Reserved
+	 * [04:04] SDRAMPWR
+	 *         0 = 3 DIMM configuration
+	 *         1 = 4 DIMM configuration
+	 * [03:03] Leadoff Command Timing (LCT)
+	 *         0 = 4 CS# Clock
+	 *         1 = 3 CS# Clock
+	 * [02:02] CAS# Latency (CL)
+	 *         0 = 3 DCLK CAS# latency
+	 *         1 = 2 DCLK CAS# latency
+	 * [01:01] SDRAM RAS# to CAS# Delay (SRCD)
+	 *         0 = 3 clocks between a row activate and a read or write cmd.
+	 *         1 = 2 clocks between a row activate and a read or write cmd.
+	 * [00:00] SDRAM RAS# Precharge (SRP)
+	 *         0 = 3 clocks of RAS# precharge
+	 *         1 = 2 clocks of RAS# precharge
+	 */
+	SDRAMC, 0x0000, 0x0000,
+
+	/* PGPOL - Paging Policy Register
+	 * 0x78 - 0x79
+	 *
+	 * [15:08] Banks per Row (BPR)
+	 *         TODO
+	 *         0 = 2 banks
+	 *         1 = 4 banks
+	 * [07:05] Reserved
+	 * [04:04] Intel Reserved
+	 * [03:00] DRAM Idle Timer (DIT)
+	 *         0000 = 0 clocks
+	 *         0001 = 2 clocks
+	 *         0010 = 4 clocks
+	 *         0011 = 8 clocks
+	 *         0100 = 10 clocks
+	 *         0101 = 12 clocks
+	 *         0110 = 16 clocks
+	 *         0111 = 32 clocks
+	 *         1xxx = Infinite (pages are not closed for idle condition)
+	 */
+	// TODO
+	PGPOL, 0x0000, 0xff00,
+
+	/* PMCR - Power Management Control Register
+	 * 0x7a
+	 *
+	 * [07:07] Power Down SDRAM Enable (PDSE)
+	 *         1 = Enable
+	 *         0 = Disable
+	 * [06:06] ACPI Control Register Enable (SCRE)
+	 *         1 = Enable
+	 *         0 = Disable (default)
+	 * [05:05] Suspend Refresh Type (SRT)
+	 *         1 = Self refresh mode
+	 *         0 = CBR fresh mode
+	 * [04:04] Normal Refresh Enable (NREF_EN)
+	 *         1 = Enable
+	 *         0 = Disable
+	 * [03:03] Quick Start Mode (QSTART)
+	 *         1 = Quick start mode for the processor is enabled
+	 * [02:02] Gated Clock Enable (GCLKEN)
+	 *         1 = Enable
+	 *         0 = Disable
+	 * [01:01] AGP Disable (AGP_DIS)
+	 *         1 = Disable
+	 *         0 = Enable
+	 * [00:00] CPU reset without PCIRST enable (CRst_En)
+	 *         1 = Enable
+	 *         0 = Disable
+	 */
+	/* Enable normal refresh and the gated clock. */
+	// TODO: Only do this later?
+	// PMCR, 0x00, 0x14,
+	// PMCR, 0x00, 0x10,
+	PMCR, 0x00, 0x00,
+};
+
+/*-----------------------------------------------------------------------------
+SDRAM configuration functions.
+-----------------------------------------------------------------------------*/
+
+/**
+ * Send the specified RAM command to all DIMMs.
+ *
+ *  <at> param Memory controller
+ *  <at> param TODO
+ *  <at> param TODO
+ */
+static void do_ram_command(const struct mem_controller *ctrl,
+			   uint32_t command, uint32_t addr_offset)
 {
-	device_t north = (device_t) 0;
-	uint8_t c, r;
+	int i;
+	uint16_t reg;

-	print_err("vt8601 init starting\r\n");
-	north = pci_locate_device(PCI_ID(0x1106, 0x8601), 0);
-	north = 0;
-	print_debug_hex32(north);
-	print_debug(" is the north\n");
-	print_debug_hex16(pci_read_config16(north, 0));
-	print_debug(" ");
-	print_debug_hex16(pci_read_config16(north, 2));
-	print_debug("\r\n");
-	
-	/* All we are doing now is setting initial known-good values that will
-	 * be revised later as we read SPD
-	 */	
-	// memory clk enable. We are not using ECC
-	pci_write_config8(north,0x78, 0x01);
-	print_debug_hex8(pci_read_config8(north, 0x78));
-	// dram control, see the book. 
-#if DIMM_PC133
-	pci_write_config8(north,0x68, 0x52);
-#else
-	pci_write_config8(north,0x68, 0x42);
-#endif
-	// dram control, see the book. 
-	pci_write_config8(north,0x6B, 0x0c);
-	// Initial setting, 256MB in each bank, will be rewritten later.
-	pci_write_config8(north,0x5A, 0x20);
-	print_debug_hex8(pci_read_config8(north, 0x5a));
-	pci_write_config8(north,0x5B, 0x40);
-	pci_write_config8(north,0x5C, 0x60);
-	pci_write_config8(north,0x5D, 0x80);
-	pci_write_config8(north,0x5E, 0xA0);
-	pci_write_config8(north,0x5F, 0xC0);
-	// It seems we have to take care of these 2 registers as if 
-	// they are bank 6 and 7.
-	pci_write_config8(north,0x56, 0xC0);
-	pci_write_config8(north,0x57, 0xC0);
-	
-	// SDRAM in all banks
-	pci_write_config8(north,0x60, 0x3F);
-	// DRAM timing. I'm suspicious of this
-	// This is for all banks, 64 is 0,1.  65 is 2,3. 66 is 4,5.
-	// ras precharge 4T, RAS pulse 5T
-	// cas2 is 0xd6, cas3 is 0xe6
-	// we're also backing off write pulse width to 2T, so result is 0xee
-#if DIMM_CL2
-	pci_write_config8(north,0x64, 0xd4);
-	pci_write_config8(north,0x65, 0xd4);
-	pci_write_config8(north,0x66, 0xd4);
-#else // CL=3
-	pci_write_config8(north,0x64, 0xe4);
-	pci_write_config8(north,0x65, 0xe4);
-	pci_write_config8(north,0x66, 0xe4);
-#endif
+	/* TODO: Support for multiple DIMMs. */

-	// dram frequency select.
-	// enable 4K pages for 64M dram. 
-#if DIMM_PC133
-	pci_write_config8(north,0x69, 0x3c);
-#else
-	pci_write_config8(north,0x69, 0xac);
-#endif
+	/* Configure the RAM command. */
+	reg = pci_read_config16(ctrl->d0, SDRAMC);
+	reg &= 0xff1f;		/* Clear bits 7-5. */
+	reg |= (uint16_t) (command << 5);
+	pci_write_config16(ctrl->d0, SDRAMC, reg);

-	/* IMPORTANT -- disable refresh counter */
-	// refresh counter, disabled.
-	pci_write_config8(north,0x6A, 0x00);
-	
+	/* RAM_COMMAND_NORMAL affects only the memory controller and
+	   doesn't need to be "sent" to the DIMMs. */
+	/* if (command == RAM_COMMAND_NORMAL) return; */

-	// clkenable configuration. kevinh FIXME - add precharge
-	pci_write_config8(north,0x6C, 0x00);
-	// dram read latch delay of 1 ns, MD drive 8 mA,
-	// high drive strength on MA[2:	13], we#, cas#, ras#
-	// As per Cindy Lee, set to 0x37, not 0x57
-	pci_write_config8(north,0x6D, 0x7f);
+	PRINT_DEBUG("    Sending RAM command 0x");
+	PRINT_DEBUG_HEX16(reg);
+	PRINT_DEBUG(" to 0x");
+	PRINT_DEBUG_HEX32(0 + addr_offset); // FIXME
+	PRINT_DEBUG("\r\n");
+
+	/* Read from (DIMM start address + addr_offset). */
+	read32(0 + addr_offset); // FIXME
 }

-/* slot is the dram slot. Return size of side0 in lower 16-bit,
- * side1 in upper 16-bit, in units of 8MB */
-static unsigned long 
-spd_module_size(unsigned char slot) 
-{ 
-	/* for all the DRAMS, see if they are there and get the size of each
-	 * module. This is just a very early first cut at sizing.
-	 */
-	/* we may run out of registers ... */
-	unsigned int banks, rows, cols, reg;
-	unsigned int value = 0;
-	/* unsigned int module = ((0x50 + slot) << 1) + 1; */
-	unsigned int module = 0x50 + slot;
-	/* is the module there? if byte 2 is not 4, then we'll assume it 
-	 * is useless. 
-	 */
-	print_info("Slot "); 
-	print_info_hex8(slot); 
-	if (smbus_read_byte(module, 2) != 4) {
-		print_info(" is empty\r\n");
-		return 0;
-	}
-	print_info(" is SDRAM ");
-	
-	banks = smbus_read_byte(module, 17);
-	/* we're going to assume symmetric banks. Sorry. */
-	cols = smbus_read_byte(module, 4)  & 0xf;
-	rows = smbus_read_byte(module, 3)  & 0xf;
-	/* grand total. You have rows+cols addressing, * times of banks, times
-	 * width of data in bytes */
-	/* Width is assumed to be 64 bits == 8 bytes */
-	value = (1 << (cols + rows)) * banks * 8;
-	print_info_hex32(value);
-	print_info(" bytes ");
-	/* Return in 8MB units */
-	value >>= 23;
+/*-----------------------------------------------------------------------------
+DIMM-independant configuration functions.
+-----------------------------------------------------------------------------*/

-	/* We should have single or double side */
-	if (smbus_read_byte(module, 5) == 2) {
-		print_info("x2");
-		value = (value << 16) | value;
+/**
+ * TODO.
+ *
+ *  <at> param Memory controller
+ */
+static void spd_enable_refresh(const struct mem_controller *ctrl)
+{
+	int i, value;
+	uint8_t reg;
+
+	reg = pci_read_config8(ctrl->d0, DRAMC);
+
+	for (i = 0; i < DIMM_SOCKETS; i++) {
+		value = spd_read_byte(ctrl->channel0[i], SPD_REFRESH);
+		if (value < 0)
+			continue;
+		reg = (reg & 0xf8) | refresh_rate_map[(value & 0x7f)];
+
+		PRINT_DEBUG("    Enabling refresh (DRAMC = 0x");
+		PRINT_DEBUG_HEX8(reg);
+		PRINT_DEBUG(") for DIMM ");
+		PRINT_DEBUG_HEX8(i);
+		PRINT_DEBUG("\r\n");
 	}
-	print_info("\r\n");
-	return value;

+	pci_write_config8(ctrl->d0, DRAMC, reg);
 }

-static int
-spd_num_chips(unsigned char slot) 
-{ 
-/*	unsigned int module = ((0x50 + slot) << 1) + 1; */
-	unsigned int module = 0x50 + slot;
-	unsigned int width;
+/*-----------------------------------------------------------------------------
+Public interface.
+-----------------------------------------------------------------------------*/

-	width = smbus_read_byte(module, 13);
-	if (width == 0)
-		width = 8;
-	return 64 / width;
+/**
+ * TODO.
+ *
+ *  <at> param Memory controller
+ */
+static void sdram_set_registers(const struct mem_controller *ctrl)
+{
+	int i, max;
+	uint32_t reg;
+
+	PRINT_DEBUG("Northbridge prior to SDRAM init:\r\n");
+	DUMPNORTH();
+
+	max = sizeof(register_values) / sizeof(register_values[0]);
+
+	/* Set registers as specified in the register_values array. */
+	for (i = 0; i < max; i += 3) {
+		reg = pci_read_config32(ctrl->d0, register_values[i]);
+		reg &= register_values[i + 1];
+		reg |= register_values[i + 2] & ~(register_values[i + 1]);
+		pci_write_config32(ctrl->d0, register_values[i], reg);
+
+		PRINT_DEBUG("    Set register 0x");
+		PRINT_DEBUG_HEX32(register_values[i]);
+		PRINT_DEBUG(" to 0x");
+		PRINT_DEBUG_HEX32(reg);
+		PRINT_DEBUG("\r\n");
+	}
 }

+/**
+ * TODO.
+ *
+ *  <at> param Memory controller
+ */
 static void sdram_set_spd_registers(const struct mem_controller *ctrl)
 {
-#define T133 7
-	unsigned char Trp = 1, Tras = 1, casl = 2, val;
-	unsigned char timing = 0xe4;
-	/* read Trp */
-	val = smbus_read_byte(0x50, 27);
-	if (val < 2*T133)
-		Trp = 1;
-	val = smbus_read_byte(0x50, 30);
-	if (val < 5*T133)
-		Tras = 0;
-	val = smbus_read_byte(0x50, 18);
-	if (val < 8)
-		casl = 1;
-	if (val < 4)
-		casl = 0;
-	
-	val = (Trp << 7) | (Tras << 6) | (casl << 4) | 4;
-	
-	print_debug_hex8(val); print_debug(" is the computed timing\n");
-	/* don't set it. Experience shows that this screwy chipset should just
-	 * be run with the most conservative timing.
-	 * pci_write_config8(0, 0x64, val);
-	 */
+	/* TODO: Don't hardcode the values here, get info via SPD. */
+
+	/* TODO: Set DRB0-DRB7. */
+	pci_write_config8(ctrl->d0, DRB0, 0x08);
+	pci_write_config8(ctrl->d0, DRB1, 0x08);
+	pci_write_config8(ctrl->d0, DRB2, 0x08);
+	pci_write_config8(ctrl->d0, DRB3, 0x08);
+	pci_write_config8(ctrl->d0, DRB4, 0x08);
+	pci_write_config8(ctrl->d0, DRB5, 0x08);
+	pci_write_config8(ctrl->d0, DRB6, 0x08);
+	pci_write_config8(ctrl->d0, DRB7, 0x08);
+
+	/* TODO: Set DRAMC. Don't enable refresh for now. */
+	pci_write_config8(ctrl->d0, DRAMC, 0x08);
+
+	/* TODO: Set RPS. */
+	pci_write_config16(ctrl->d0, RPS, 0x0001);
+
+	/* TODO: Set SDRAMC. */
+	// pci_write_config16(ctrl->d0, SDRAMC, 0x0000);
+
+	/* TODO: Set PGPOL. */
+	pci_write_config16(ctrl->d0, PGPOL, 0x0107);
+
+	/* TODO: Set NBXCFG. */
+	// pci_write_config32(ctrl->d0, NBXCFG, 0x0100220c);
+
+	/* TODO: Set PMCR? */
+	// pci_write_config8(ctrl->d0, PMCR, 0x14);
+	// pci_write_config8(ctrl->d0, PMCR, 0x10);
+
+	/* TODO? */
+	// pci_write_config8(ctrl->d0, MLT, 0x40);
+	// pci_write_config8(ctrl->d0, DRAMT, 0x03);
+	// pci_write_config8(ctrl->d0, MBSC, 0x03);
+	// pci_write_config8(ctrl->d0, SCRR, 0x38);
 }

-static void set_ma_mapping(device_t north, int slot, int type)
+/**
+ * Enable SDRAM.
+ *
+ *  <at> param Number of controllers
+ *  <at> param Memory controller
+ */
+static void sdram_enable(int controllers, const struct mem_controller *ctrl)
 {
-    unsigned char reg, val;
-    int shift;
+	int i;

-    reg = 0x58 + slot/2;
-    if (slot%2 >= 1)
-        shift = 0;
-    else
-        shift = 4;
+	/* TODO: Use a delay here? Needed? */
+	mdelay(200);

-    val = pci_read_config8(north, reg);
-    val &= ~(0xf << shift);
-    val |= type << shift;
-    pci_write_config8(north, reg, val);
-}
+	/* TODO: How long should the delays be? Fix later. */

+	/* 1. Apply NOP. */
+	PRINT_DEBUG("RAM Enable 1: Apply NOP\r\n");
+	do_ram_command(ctrl, RAM_COMMAND_NOP, 0);
+	mdelay(10);

-static void sdram_enable(int controllers, const struct mem_controller *ctrl) 
-{
-	unsigned char i;
-	static const uint8_t ramregs[] = {
-		0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x56, 0x57
-	};
-	device_t north = 0;
-	uint32_t size, base, slot, ma;
-	/* begin to initialize*/
-	// I forget why we need this, but we do
-	dimms_write(0xa55a5aa5);
-	
-	/* set NOP*/
-	pci_write_config8(north,0x6C, 0x01);
-	print_debug("NOP\r\n");
-	/* wait 200us*/
-	// You need to do the memory reference. That causes the nop cycle. 
-	dimms_read(0);
-	udelay(400);
-	print_debug("PRECHARGE\r\n");
-	/* set precharge */
-	pci_write_config8(north,0x6C, 0x02);
-	print_debug("DUMMY READS\r\n");
-	/* dummy reads*/
-	dimms_read(0);
-	udelay(200);
-	print_debug("CBR\r\n");
-	/* set CBR*/
-	pci_write_config8(north,0x6C, 0x04);
-	
-	/* do 8 reads and wait >100us between each - from via*/
-	dimms_read(0);
-	udelay(200);
-	dimms_read(0);
-	udelay(200);
-	dimms_read(0);
-	udelay(200);
-	dimms_read(0);
-	udelay(200);
-	dimms_read(0);
-	udelay(200);
-	dimms_read(0);
-	udelay(200);
-	dimms_read(0);
-	udelay(200);
-	dimms_read(0);
-	udelay(200);
-	print_debug("MRS\r\n");
-	/* set MRS*/
-	pci_write_config8(north,0x6c, 0x03);
-#if DIMM_CL2
-	dimms_read(0x150);
-#else // CL=3
-	dimms_read(0x1d0);
-#endif
-	udelay(200);
-	print_debug("NORMAL\r\n");
-	/* set to normal mode */
-	pci_write_config8(north,0x6C, 0x08);
-	
-	dimms_write(0x55aa55aa);
-	dimms_read(0);
-	udelay(200);
-	print_debug("set ref. rate\r\n");
-	// Set the refresh rate. 
-#if DIMM_PC133
-	pci_write_config8(north,0x6A, 0x86);
-#else
-	pci_write_config8(north,0x6A, 0x65);
-#endif
-	print_debug("enable multi-page open\r\n");
-	// enable multi-page open
-	pci_write_config8(north,0x6B, 0x0d);
-	
-	base = 0;
-	for(slot = 0; slot < 4; slot++) {
-		size = spd_module_size(slot);
-		/* side 0 */
-		base += size & 0xffff;
-		pci_write_config8(north, ramregs[2*slot], base);
-		/* side 1 */
-		base += size >> 16;
-		if (base > 0xff)
-			base = 0xff;
-		pci_write_config8(north, ramregs[2*slot + 1], base);
+	/* 2. Precharge all. Wait tRP. */
+	PRINT_DEBUG("RAM Enable 2: Precharge all\r\n");
+	do_ram_command(ctrl, RAM_COMMAND_PRECHARGE, 0);
+	mdelay(10);

-		if (!size)
-			continue;
+	/* 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(ctrl, RAM_COMMAND_CBR, 0);
+		mdelay(10);
+	}

-		/* Calculate the value of MA mapping type register,
-		 * based on size of SDRAM chips. */
-		size = (size & 0xffff) << (3 + 3);
-			/* convert module size to be in Mbits */
-		size /= spd_num_chips(slot);
-		print_debug_hex16(size);
-		print_debug(" is the chip size\r\n");
-		if (size < 64)
-			ma = 0;
-		if (size < 256)
-			ma = 8;
-		else
-			ma = 0xe;
-		print_debug_hex16(ma);
-		print_debug(" is the MA type\r\n");
-		set_ma_mapping(north, slot, ma);
-	}
-	print_err("vt8601 done\r\n");
+	/* 4. Mode register set. Wait two memory cycles. */
+	PRINT_DEBUG("RAM Enable 4: Mode register set\r\n");
+	do_ram_command(ctrl, RAM_COMMAND_MRS, 0x1d0);
+	// TODO: Is 0x1d0 correct?
+	// do_ram_command(ctrl, RAM_COMMAND_MRS, 0x1d0000);
+	mdelay(10);
+	mdelay(10);
+
+	/* 5. Normal operation. */
+	PRINT_DEBUG("RAM Enable 5: Normal operation\r\n");
+	do_ram_command(ctrl, RAM_COMMAND_NORMAL, 0);
+	mdelay(10);
+
+	/* 6. Finally enable refresh. */
+	PRINT_DEBUG("RAM Enable 6: Enable refresh\r\n");
+	// pci_write_config8(ctrl->d0, PMCR, 0x10);
+	spd_enable_refresh(ctrl);
+	mdelay(10);
+
+	PRINT_DEBUG("Northbridge following SDRAM init:\r\n");
+	DUMPNORTH();
 }

Modified: trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/raminit.h
===================================================================
--- trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/raminit.h	2007-03-31 19:48:38 UTC (rev 2575)
+++ trunk/LinuxBIOSv2/src/northbridge/intel/i440bx/raminit.h	2007-04-01 17:24:03 UTC (rev 2576)
 <at>  <at>  -1,11 +1,33  <at>  <at> 
+/*
+ * This file is part of the LinuxBIOS 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
+ */
+
 #ifndef RAMINIT_H
 #define RAMINIT_H

+/* The 440BX supports up to four (single- or double-sided) DIMMs. */
 #define DIMM_SOCKETS 4
+
+/* The 440BX memory controller has one channel only. */
 struct mem_controller {
-  device_t d0;
-  uint16_t channel0[DIMM_SOCKETS];
+	device_t d0;
+	uint16_t channel0[DIMM_SOCKETS];
 };

-
-#endif /* RAMINIT_H */
+#endif				/* RAMINIT_H */

--

-- 
linuxbios mailing list
linuxbios <at> linuxbios.org
http://www.linuxbios.org/mailman/listinfo/linuxbios

Uwe Hermann | 1 Apr 2007 19:25
Picon
Favicon
Gravatar

Re: [PATCH] Intel 44BX RAM initialization framework

On Sun, Apr 01, 2007 at 06:59:20PM +0200, Stefan Reinauer wrote:
> * Uwe Hermann <uwe <at> hermann-uwe.de> [070401 18:50]:
> > This is a first version of my RAM init code for the 440BX.
> > 
> > It does _not_ work, yet. Don't try to use it unless you know what you're
> > doing.
>  
> Acked-by: Stefan Reinauer <stepan <at> coresystems.de>

Thanks, committed in r2576.

(no need to quote the full patch, though :)

Uwe.
-- 
http://www.hermann-uwe.de  | http://www.holsham-traders.de
http://www.crazy-hacks.org | http://www.unmaintained-free-software.org
--

-- 
linuxbios mailing list
linuxbios <at> linuxbios.org
http://www.linuxbios.org/mailman/listinfo/linuxbios
LinuxBIOS information | 1 Apr 2007 20:05
Picon

r2576 build service

Dear LinuxBIOS readers!

This is the automated build check service of LinuxBIOS.

The developer "uwe" checked in revision 2576 to
the LinuxBIOS source repository and caused the following 
changes:

Change Log:
Initial Intel 440BX RAM initialization framework.

This does _not_ fully work, yet. You will _not_ be able to boot any
payload with this code, yet.

Add missing license headers.

Base the northbridge.c file on the Intel 855PM version, that comes
closer to what we want.

The raminit.c file is written from scratch and hardcodes several
values for now. This needs to be fixed later by reading the
correct values via SPD.

Signed-off-by: Uwe Hermann <uwe <at> hermann-uwe.de>
Acked-by: Stefan Reinauer <stepan <at> coresystems.de>

Build Log:
Compilation of gigabyte:m57sli is still broken
Configuration of msi:ms9282 is still broken
Compilation of nvidia:l1_2pvv is still broken
Compilation of supermicro:h8dmr is still broken
Compilation of tyan:s2912 is still broken

If something broke during this checkin please be a pain 
in uwe's neck until the issue is fixed.

If this issue is not fixed within 24h the revision will 
be backed out.

   Yours truely,
     LinuxBIOS automatic build system

--

-- 
linuxbios mailing list
linuxbios <at> linuxbios.org
http://www.linuxbios.org/mailman/listinfo/linuxbios

Anton | 1 Apr 2007 20:53
Picon

id1 & id2 - not chip ids

flashrom seems to work on ICH6 (and obviously on ICH7 in my previous post),
despite the fact that BIOS_CNTL register isn't correctly set
"Enabling flash write on ICH6-M...tried to set 0xdc to 0x3 on ICH6-M failed (WARNING ONLY)"

Unfortunately, I can't say for sure which flashchip is hidden inside board (no data, this's
from laptop) - but when

Trying Am29F040B, 512 KB
probe_29f040b: id1 0x55, id2 0xaa
Trying Am29LV040B, 512 KB
probe_29f040b: id1 0x55, id2 0xaa

	id1 & id2 are first bytes of original BIOS. What if change probe_29f040b() onto jedec_probe()?
	Will it give me correct chip IDs?

Thanks.

--

-- 
linuxbios mailing list
linuxbios <at> linuxbios.org
http://www.linuxbios.org/mailman/listinfo/linuxbios

Uwe Hermann | 1 Apr 2007 21:10
Picon
Favicon
Gravatar

[PATCH] *_early_serial.c Super I/O fixes

I messed up the ITE Super I/Os, time to fix them...
More patches will follow.

Uwe.
-- 
http://www.hermann-uwe.de  | http://www.holsham-traders.de
http://www.crazy-hacks.org | http://www.unmaintained-free-software.org
--

-- 
linuxbios mailing list
linuxbios <at> linuxbios.org
http://www.linuxbios.org/mailman/listinfo/linuxbios

Gmane