Hi all,
This thing is now ready for more exposure. Scratch my previous "patch" - this is my first real deal.
- Adds Asus P2B-LS mainboard - Adds RAM detection for i440bx (based on i82830 code). We're no longer hard coded for 64MB on one row! - Adds a proper Slot 1 cpu under src/cpu/intel/slot_1. It's a stub copied from slot_2 but addresses a few FIXMEs. My P2B-LS code refers to this. - Adds microcode for Intel Tualatin CPUs, cpuid 6B1 and 6B4.* Actually loading them is pending.
Signed-off-by: Keith Hui buurin@gmail.com
Enjoy.
Keith
* Microcodes for all Intel CPUs can be downloaded from Intel - downloadcenter.intel.com. So TODO for me is to add all microcode updates from Klamath to Tualatin as the Asus P2B family, with the right mods and/or adapter, can run anything in between that can fit either Slot 1 or Socket 370.
Hi Keith,
On Tue, Mar 02, 2010 at 11:19:24PM -0500, Keith Hui wrote:
This thing is now ready for more exposure. Scratch my previous "patch" - this is my first real deal.
- Adds Asus P2B-LS mainboard
- Adds RAM detection for i440bx (based on i82830 code). We're no longer hard
coded for 64MB on one row!
- Adds a proper Slot 1 cpu under src/cpu/intel/slot_1. It's a stub copied
from slot_2 but addresses a few FIXMEs. My P2B-LS code refers to this.
- Adds microcode for Intel Tualatin CPUs, cpuid 6B1 and 6B4.* Actually
loading them is pending.
Signed-off-by: Keith Hui buurin@gmail.com
Great stuff, thanks a lot!
I'll review and/or test the individual pieces one by one and commit them as I progress. (small note for the next patch: please split up the stuff in multiple smaller, independent patches, that makes it easier to review and test; no need to re-send this patch though).
Uwe.
On 03/03/10 04:19, Keith Hui wrote:
Hi all,
This thing is now ready for more exposure. Scratch my previous "patch" - this is my first real deal.
- Adds RAM detection for i440bx (based on i82830 code). We're no longer
hard coded for 64MB on one row!
Hi.
I've tried this with my ASUS P2B, and it's not quite there yet.
The first problem is that this motherboard only has three DIMM slots. This means you have to set SDRAMC to something different; 0x0103 works for me.
I'm guessing that we will need a motherboard config option for this - there doesn't seem to be one suitable? Something like:
src/mainboard/asus/p2b/Kconfig:
config DIMM_SOCKETS int default 3 depends on BOARD_ASUS_P2B
The second problem is that it doesn't work with more that 256 MB of memory. I've had one stick of 128 MB work, two sticks of 128 MB and one stick of 256 MB all work, but two sticks of 256 MB doesn't boot linux.
Has anyone got any idea as to what might be wrong? If I get the time I'll try to boot with the real BIOS and see what that sets the register up to in different configs.
This is great work though!
Many thanks,
MM
On Thu, Mar 04, 2010 at 10:05:57AM +0000, Mark Marshall wrote:
On 03/03/10 04:19, Keith Hui wrote:
Hi all,
This thing is now ready for more exposure. Scratch my previous "patch" - this is my first real deal.
- Adds RAM detection for i440bx (based on i82830 code). We're no longer
hard coded for 64MB on one row!
Hi.
I've tried this with my ASUS P2B, and it's not quite there yet.
The first problem is that this motherboard only has three DIMM slots. This means you have to set SDRAMC to something different; 0x0103 works for me.
I'm guessing that we will need a motherboard config option for this
- there doesn't seem to be one suitable? Something like:
src/mainboard/asus/p2b/Kconfig:
config DIMM_SOCKETS int default 3 depends on BOARD_ASUS_P2B
Yes, sounds good. We will either need this, or maybe the settings can be auto-detected / probed (need to check datasheet, but I guess it's unlikely).
Hm, seems to be determined by SDRAMPWR + MMCONFIG, and MMCONFIG seems to be a hardware-strap (so we can check it), but not sure about SDRAMPWR.
The second problem is that it doesn't work with more that 256 MB of memory. I've had one stick of 128 MB work, two sticks of 128 MB and one stick of 256 MB all work, but two sticks of 256 MB doesn't boot linux.
Hm, will investigate. Are you sure both 256MB DIMMs work under vendor BIOS (so we can exclude hardware issues)?
Thanks for testing!
Uwe.
On 03/04/2010 07:30 AM, Uwe Hermann wrote:
On Thu, Mar 04, 2010 at 10:05:57AM +0000, Mark Marshall wrote:
On 03/03/10 04:19, Keith Hui wrote:
Hi all,
This thing is now ready for more exposure. Scratch my previous "patch" - this is my first real deal.
- Adds RAM detection for i440bx (based on i82830 code). We're no longer
hard coded for 64MB on one row!
Hi.
I've tried this with my ASUS P2B, and it's not quite there yet.
The first problem is that this motherboard only has three DIMM slots. This means you have to set SDRAMC to something different; 0x0103 works for me.
I'm guessing that we will need a motherboard config option for this
- there doesn't seem to be one suitable? Something like:
src/mainboard/asus/p2b/Kconfig:
config DIMM_SOCKETS int default 3 depends on BOARD_ASUS_P2B
Yes, sounds good. We will either need this, or maybe the settings can be auto-detected / probed (need to check datasheet, but I guess it's unlikely).
Hm, seems to be determined by SDRAMPWR + MMCONFIG, and MMCONFIG seems to be a hardware-strap (so we can check it), but not sure about SDRAMPWR.
The second problem is that it doesn't work with more that 256 MB of memory. I've had one stick of 128 MB work, two sticks of 128 MB and one stick of 256 MB all work, but two sticks of 256 MB doesn't boot linux.
Hm, will investigate. Are you sure both 256MB DIMMs work under vendor BIOS (so we can exclude hardware issues)?
Thanks for testing!
One thing I noticed about Keith's code is he didn't impliment the initializing one row/side of memory at a time. I think it should really be visited, for multiple memory sticks.
On 03/04/2010 07:38 AM, Joseph Smith wrote:
On 03/04/2010 07:30 AM, Uwe Hermann wrote:
On Thu, Mar 04, 2010 at 10:05:57AM +0000, Mark Marshall wrote:
On 03/03/10 04:19, Keith Hui wrote:
Hi all,
This thing is now ready for more exposure. Scratch my previous "patch" - this is my first real deal.
- Adds RAM detection for i440bx (based on i82830 code). We're no longer
hard coded for 64MB on one row!
Hi.
I've tried this with my ASUS P2B, and it's not quite there yet.
The first problem is that this motherboard only has three DIMM slots. This means you have to set SDRAMC to something different; 0x0103 works for me.
Hm, seems to be determined by SDRAMPWR + MMCONFIG, and MMCONFIG seems to be a hardware-strap (so we can check it), but not sure about SDRAMPWR.
I think a simple SPD probe would work, if the correct value is returned you know you have memory in that slot, otherwise if 0xff is returned then no memory is present. Do this probe for as many slots as the 440 supports. Then set your registers based on that.
The second problem is that it doesn't work with more that 256 MB of memory. I've had one stick of 128 MB work, two sticks of 128 MB and one stick of 256 MB all work, but two sticks of 256 MB doesn't boot linux.
Hm, will investigate. Are you sure both 256MB DIMMs work under vendor BIOS (so we can exclude hardware issues)?
Thanks for testing!
One thing I noticed about Keith's code is he didn't impliment the initializing one row/side of memory at a time. I think it should really be visited, for multiple memory sticks.
On 04/03/10 13:10, Joseph Smith wrote:
On 03/04/2010 07:38 AM, Joseph Smith wrote:
On 03/04/2010 07:30 AM, Uwe Hermann wrote:
On Thu, Mar 04, 2010 at 10:05:57AM +0000, Mark Marshall wrote:
On 03/03/10 04:19, Keith Hui wrote: The first problem is that this motherboard only has three DIMM slots. This means you have to set SDRAMC to something different; 0x0103 works for me.
Hm, seems to be determined by SDRAMPWR + MMCONFIG, and MMCONFIG seems to be a hardware-strap (so we can check it), but not sure about SDRAMPWR.
I think a simple SPD probe would work, if the correct value is returned you know you have memory in that slot, otherwise if 0xff is returned then no memory is present. Do this probe for as many slots as the 440 supports. Then set your registers based on that.
The issue here is the number of DIMM slots on the motherboard, not the number of sticks in the slots. Some 440BX boards have four slots, while others only have three.
MM
On 03/05/2010 03:03 AM, Mark Marshall wrote:
On 04/03/10 13:10, Joseph Smith wrote:
On 03/04/2010 07:38 AM, Joseph Smith wrote:
On 03/04/2010 07:30 AM, Uwe Hermann wrote:
On Thu, Mar 04, 2010 at 10:05:57AM +0000, Mark Marshall wrote:
On 03/03/10 04:19, Keith Hui wrote: The first problem is that this motherboard only has three DIMM slots. This means you have to set SDRAMC to something different; 0x0103 works for me.
Hm, seems to be determined by SDRAMPWR + MMCONFIG, and MMCONFIG seems to be a hardware-strap (so we can check it), but not sure about SDRAMPWR.
I think a simple SPD probe would work, if the correct value is returned you know you have memory in that slot, otherwise if 0xff is returned then no memory is present. Do this probe for as many slots as the 440 supports. Then set your registers based on that.
The issue here is the number of DIMM slots on the motherboard, not the number of sticks in the slots. Some 440BX boards have four slots, while others only have three.
MM
That is fine. Then if 440bx datasheet says it supports 4 slots, then that should be the standard.
Joseph Smith wrote:
On 03/05/2010 03:03 AM, Mark Marshall wrote:
On 04/03/10 13:10, Joseph Smith wrote:
On 03/04/2010 07:38 AM, Joseph Smith wrote:
On 03/04/2010 07:30 AM, Uwe Hermann wrote:
On Thu, Mar 04, 2010 at 10:05:57AM +0000, Mark Marshall wrote:
On 03/03/10 04:19, Keith Hui wrote: The first problem is that this motherboard only has three DIMM slots. This means you have to set SDRAMC to something different; 0x0103 works for me.
Hm, seems to be determined by SDRAMPWR + MMCONFIG, and MMCONFIG seems to be a hardware-strap (so we can check it), but not sure about SDRAMPWR.
I think a simple SPD probe would work, if the correct value is returned you know you have memory in that slot, otherwise if 0xff is returned then no memory is present. Do this probe for as many slots as the 440 supports. Then set your registers based on that.
The issue here is the number of DIMM slots on the motherboard, not the number of sticks in the slots. Some 440BX boards have four slots, while others only have three.
MM
That is fine. Then if 440bx datasheet says it supports 4 slots, then that should be the standard.
Please check this section of the 440BX data sheet.
3.3.24 SDRAMC—SDRAM Control Register (Device 0)
We are interested in bit 4.
SDRAMPWR. The SDRAMPWR bit controls how the CKE signals are driven for different DRAM configurations. For a 3 DIMM configuration, SDRAMPWR should be set to ‘0’. For a 4 DIMM configuration, SDRAMPWR should be set to ‘1’. In this case the 82443BX drives a single CKE signal (GCKE). The combination of SDRAMPWR and MMCONFIG (DRAMC register) determine the functioning of the CKE signals. Refer to the DRAMC register (Section 3.3.15, “DRAMC—DRAM Control Register (Device 0)” on page 3-19) for more details.
Note: When PCIRST# assertion occurs during POS/STR, these bits are not reset to 0.
As far as I can tell we cannot auto-detect this. Some (many) 440BX boards only have three DIMM slots, and in these cases the clocks are routed differently to the boards with four DIMM slots.
MM
On Fri, 05 Mar 2010 13:04:27 +0000, Mark Marshall mark.marshall@csr.com wrote:
Joseph Smith wrote:
On 03/05/2010 03:03 AM, Mark Marshall wrote:
On 04/03/10 13:10, Joseph Smith wrote:
On 03/04/2010 07:38 AM, Joseph Smith wrote:
On 03/04/2010 07:30 AM, Uwe Hermann wrote:
On Thu, Mar 04, 2010 at 10:05:57AM +0000, Mark Marshall wrote: > On 03/03/10 04:19, Keith Hui wrote: > The first problem is that this motherboard only has three DIMM > slots. This means you have to set SDRAMC to something different; > 0x0103 works for me. > Hm, seems to be determined by SDRAMPWR + MMCONFIG, and MMCONFIG seems to be a hardware-strap (so we can check it), but not sure about
SDRAMPWR.
>
I think a simple SPD probe would work, if the correct value is
returned
you know you have memory in that slot, otherwise if 0xff is returned then no memory is present. Do this probe for as many slots as the 440 supports. Then set your registers based on that.
The issue here is the number of DIMM slots on the motherboard, not the number of sticks in the slots. Some 440BX boards have four slots, while others only have three.
MM
That is fine. Then if 440bx datasheet says it supports 4 slots, then that should be the standard.
Please check this section of the 440BX data sheet.
3.3.24 SDRAMC—SDRAM Control Register (Device 0)
We are interested in bit 4.
SDRAMPWR. The SDRAMPWR bit controls how the CKE signals are driven for different DRAM configurations. For a 3 DIMM configuration, SDRAMPWR should be set to ‘0’. For a 4 DIMM configuration, SDRAMPWR should be set to ‘1’. In this case the 82443BX drives a single CKE signal (GCKE). The combination of SDRAMPWR and MMCONFIG (DRAMC register) determine the functioning of the CKE signals. Refer to the DRAMC register (Section 3.3.15, “DRAMC—DRAM Control Register (Device 0)” on page 3-19) for more details.
Note: When PCIRST# assertion occurs during POS/STR, these bits are not reset to 0.
As far as I can tell we cannot auto-detect this. Some (many) 440BX boards only have three DIMM slots, and in these cases the clocks are routed differently to the boards with four DIMM slots.
That's easy... so you do something like this:
slot4_detect = (spd_read_byte((DIMM_SPD_BASE + 3), SPD_MEMORY_TYPE);
if (slot4_detect != 0xff) {
/* We have 4 slots */ ----Set bit 4 in SDRAMPWR---- #define DIMM_SOCKETS 4 } else {
/* We have 3 slots */ ----Set bit 4 in SDRAMPWR---- #define DIMM_SOCKETS 3 }
Hope that helps.
Joseph Smith wrote:
That's easy... so you do something like this:
As I understand it that only works if there is a DIMM in the 4th slot. Otherwise you'll set a four slot system with the 3 slot configuration leading to incorrect routing of clocks.
Andrew
On 03/02/2010 11:19 PM, Keith Hui wrote:
Hi all,
This thing is now ready for more exposure. Scratch my previous "patch" - this is my first real deal.
- Adds Asus P2B-LS mainboard
- Adds RAM detection for i440bx (based on i82830 code). We're no longer
hard coded for 64MB on one row!
- Adds a proper Slot 1 cpu under src/cpu/intel/slot_1. It's a stub
copied from slot_2 but addresses a few FIXMEs. My P2B-LS code refers to this.
- Adds microcode for Intel Tualatin CPUs, cpuid 6B1 and 6B4.* Actually
loading them is pending.
Signed-off-by: Keith Hui <buurin@gmail.com mailto:buurin@gmail.com>
Enjoy.
Keith
- Microcodes for all Intel CPUs can be downloaded from Intel -
downloadcenter.intel.com http://downloadcenter.intel.com. So TODO for me is to add all microcode updates from Klamath to Tualatin as the Asus P2B family, with the right mods and/or adapter, can run anything in between that can fit either Slot 1 or Socket 370.
I would not worry about the microcode updates right now. CAR for Intel 6bx is coming real soon and the microcode updates will be included :-)
See other comments below.
Index: src/northbridge/intel/i440bx/raminit.c =================================================================== --- src/northbridge/intel/i440bx/raminit.c (revision 5184) +++ src/northbridge/intel/i440bx/raminit.c (working copy) @@ -2,6 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2007-2008 Uwe Hermann uwe@hermann-uwe.de + * Copyright (C) 2010 Keith Hui buurin@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 @@ -23,6 +24,7 @@ #include <delay.h> #include <stdlib.h> #include "i440bx.h" +#include "raminit.h"
/*----------------------------------------------------------------------------- Macros and definitions. @@ -65,12 +67,24 @@ * [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 +static const unsigned int refresh_rate_map[] = { + 1, 1, 1, 2, 3, 4 };
/* Table format: register, bitmask, value. */ static const long register_values[] = { + /* MLT - Master Latency Timer Register + * 0x0d + * + * [07:03] Master Latency Timer Count Value for PCI Bus Access. + * MLT is an 8-bit register that controls the amount of + * time the 82443BX, as a PCI bus master, can burst data + * on the PCI Bus. The default value of MLT is 00h and + * disables this function. For example, if the MLT is + * programmed to 18h, then the value is 24 PCI clocks. + * [02:00] Reserved + */ + MLT, 0x00, 0x40, /* NBXCFG - NBX Configuration Register * 0x50 - 0x53 * @@ -188,14 +202,21 @@ * 10 = Write Only (Writes to DRAM, reads to memory mapped I/O space) * 11 = Read/Write (all access goes to DRAM) */ - // TODO - PAM0, 0x00, 0x00, - PAM1, 0x00, 0x00, - PAM2, 0x00, 0x00, - PAM3, 0x00, 0x00, - PAM4, 0x00, 0x00, - PAM5, 0x00, 0x00, - PAM6, 0x00, 0x00, + /* Map all legacy regions to RAM (read/write). This is required if + * you want to use the RAM area from 768 KB - 1 MB. If the PAM + * registers are not set here appropriately, the RAM in that region + * will not be accessible, thus a RAM check of it will also fail. + + * TODO: This was set in sdram_set_spd_registers() + * Test if it still works when set here + */ + PAM0, 0x00, 0x30, + PAM1, 0x00, 0x33, + PAM2, 0x00, 0x33, + PAM3, 0x00, 0x33, + PAM4, 0x00, 0x33, + PAM5, 0x00, 0x33, + PAM6, 0x00, 0x33,
/* DRB[0:7] - DRAM Row Boundary Registers * 0x60 - 0x67 @@ -343,6 +364,8 @@ // PMCR, 0x00, 0x14, // PMCR, 0x00, 0x10, PMCR, 0x00, 0x00, + /* Enable SCRR.SRRAEN and let BX choose the SRR */ + SCRR+1, 0x00, 0x10, };
/*----------------------------------------------------------------------------- @@ -396,7 +419,7 @@
dimm_end = pci_read_config8(NB, DRB + i);
- addr = (dimm_start * 8 * 1024 * 1024) + addr_offset; + addr = (dimm_start * 8 * 1048576) + addr_offset; if (dimm_end > dimm_start) { #if 0 PRINT_DEBUG(" Sending RAM command 0x"); @@ -414,6 +437,22 @@ } }
+static void set_dram_buffer_strength(void) +{ + /* TODO: This needs to be set according to the DRAM tech + * (x8, x16, or x32). Argh, Intel provides no docs on this! + * Currently, it needs to be pulled from the output of + * lspci -xxx Rx92 + Relevant registers: + * MBSC + * MBFS, BUFFC + */ + + pci_write_config8(NB, MBSC, 0x03); + +} + +
/*----------------------------------------------------------------------------- DIMM-independant configuration functions.
-----------------------------------------------------------------------------*/ @@ -461,71 +500,305 @@ reg &= register_values[i + 1]; reg |= register_values[i + 2] & ~(register_values[i + 1]); pci_write_config8(NB, register_values[i], reg); - +#if 0 PRINT_DEBUG(" Set register 0x"); PRINT_DEBUG_HEX8(register_values[i]); PRINT_DEBUG(" to 0x"); PRINT_DEBUG_HEX8(reg); PRINT_DEBUG("\r\n"); +#endif } }
-static void sdram_set_spd_registers(void) +/* Copied from i82830 northbridge code */ +struct dimm_size { + unsigned long side1; + unsigned long side2; +}; + +static struct dimm_size spd_get_dimm_size(unsigned device) { - /* TODO: Don't hardcode the values here, get info via SPD. */ + struct dimm_size sz; + int i, module_density, dimm_banks; + sz.side1 = 0; + module_density = spd_read_byte(device, SPD_DENSITY_OF_EACH_ROW_ON_MODULE); + dimm_banks = spd_read_byte(device, SPD_NUM_DIMM_BANKS);
- /* Map all legacy regions to RAM (read/write). This is required if - * you want to use the RAM area from 768 KB - 1 MB. If the PAM - * registers are not set here appropriately, the RAM in that region - * will not be accessible, thus a RAM check of it will also fail. + /* Find the size of side1. */ + /* Find the larger value. The larger value is always side1. */ + for (i = 512; i >= 0; i >>= 1) { + if ((module_density & i) == i) { + sz.side1 = i; + break; + } + } + + /* Set to 0 in case it's single sided. */ + sz.side2 = 0; + + /* Test if it's a dual-sided DIMM. */ + if (dimm_banks > 1) { + /* Test to see if there's a second value, if so it's asymmetrical. */ + if (module_density != i) { + /* Find the second value, picking up where we left off. */ + /* i >>= 1 done initially to make sure we don't get the same value again. */ + for (i >>= 1; i >= 0; i >>= 1) { + if (module_density == (sz.side1 | i)) { + sz.side2 = i; + break; + } + } + /* If not, it's symmetrical */ + } else { + sz.side2 = sz.side1; + } + } + + /* SPD byte 31 is the memory size divided by 4 so we + * need to muliply by 4 to get the total size. */ - pci_write_config8(NB, PAM0, 0x30); - pci_write_config8(NB, PAM1, 0x33); - pci_write_config8(NB, PAM2, 0x33); - pci_write_config8(NB, PAM3, 0x33); - pci_write_config8(NB, PAM4, 0x33); - pci_write_config8(NB, PAM5, 0x33); - pci_write_config8(NB, PAM6, 0x33); + sz.side1 *= 4; + sz.side2 *= 4; + return sz; +} +/* + Sets DRAM attributes one DIMM at a time, based on SPD data + Northbridge settings that got set here: + + NBXCFG[31:24] + DRB0-DRB7 + RPS + DRAMC + */ +static void set_dram_row_attributes(void)
**********You are setting alot more than just dra here, I would rename this function something like sdram_setup_registers().
+{ + int i, dra, drb, col, width, value, rps, edosd, ecc, nbxecc; + u8 bpr; // Top 8 bits of PGPOL + + edosd = 0; + rps = 0; + drb = 0; + bpr = 0; + nbxecc=0xff; + + for (i = 0; i < DIMM_SOCKETS; i++) { + unsigned device; + device = DIMM_SPD_BASE + i; + bpr >>= 2;
- /* TODO: Set DRB0-DRB7. */ - /* Currently this is hardcoded to one 64 MB DIMM in slot 0. */ - pci_write_config8(NB, DRB0, 0x08); - pci_write_config8(NB, DRB1, 0x08); - pci_write_config8(NB, DRB2, 0x08); - pci_write_config8(NB, DRB3, 0x08); - pci_write_config8(NB, DRB4, 0x08); - pci_write_config8(NB, DRB5, 0x08); - pci_write_config8(NB, DRB6, 0x08); - pci_write_config8(NB, DRB7, 0x08); + /* First check if a DIMM is actually present. */ + value = spd_read_byte(device, SPD_MEMORY_TYPE); + /* This is BX! We do EDO too! */ + if (value == SPD_MEMORY_TYPE_EDO || value == SPD_MEMORY_TYPE_SDRAM) {
- /* TODO: Set DRAMC. Don't enable refresh for now. */ - pci_write_config8(NB, DRAMC, 0x08); + PRINT_DEBUG("Found "); + if (value == SPD_MEMORY_TYPE_EDO) { + edosd |= 0x02; + } else if (value == SPD_MEMORY_TYPE_SDRAM) { + edosd = edosd | 0x04; + } + PRINT_DEBUG("DIMM in slot "); + PRINT_DEBUG_HEX8(i); + PRINT_DEBUG("\r\n");
- /* TODO: Set RPS. Needs to be fixed for multiple DIMM support. */ - pci_write_config16(NB, RPS, 0x0001); + if (edosd == 0x06) { + print_err("Mixing EDO/SDRAM not supported\r\n"); + die("HALT\r\n"); + } + + /* "DRA" is our RPS for the two rows on this DIMM */ + dra = 0;
+ /* columns */ + col = spd_read_byte(device, SPD_NUM_COLUMNS); + + /* Is this an ECC DIMM? (Actually this will be a 2 if so) */ + /* TODO: Other register than NBXCFG also needs this ECC information */ + ecc = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE); + + /* data width */ + width = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB); + + /* Exclude error checking data width from page size calculations */ + if (ecc) { + value = spd_read_byte(device, SPD_ERROR_CHECKING_SDRAM_WIDTH); + width -= value; + /* ### ECC */ + /* Top 2 bits are clear to help set up NBXCFG */ + ecc &= 0x3f; + } else { + /* Without ECC, these top 2 bits should be 11 */ + ecc |= 0xc0; + } + + /* calculate page size in bits */ + value = ((1 << col) * width); + + /* convert to Kilobytes */ + dra = (value >> 13); + + /* # of banks of DIMM (single or double sided) */ + value = spd_read_byte(device, SPD_NUM_DIMM_BANKS); + + /* Once we have dra, col is done and can be reused, + * So it's reused for number of banks + */ + col = spd_read_byte(device, SPD_NUM_BANKS_PER_SDRAM); + + if (value == 1) { + /* Second bank of 1-bank DIMMs "doesn't have ECC" - or anything */ + ecc |=0x80; + if (dra == 2) { + dra = 0x0; /* 2KB */ + } else if (dra == 4) { + dra = 0x1; /* 4KB */ + } else if (dra == 8) { + dra = 0x2; /* 8KB */ + } else { + dra = -1; + } + /* Sets a flag in PGPOL[BPR] if this DIMM has 4 banks per row */ + if (col == 4) { + bpr |= 0x40; + } + } else if (value == 2) { + if (dra == 2) { + dra = 0x0; /* 2KB */ + } else if (dra == 4) { + dra = 0x05; /* 4KB */ + } else if (dra == 8) { + dra = 0x0a; /* 8KB */ + } else { + dra = -1; + } + /* Ditto */ + if (col == 4) { + bpr |= 0xc0; + } + } else { + print_err("# of banks of DIMM not supported\r\n"); + die("HALT\r\n"); + } + if (dra == -1) { + print_err("Page size not supported\r\n"); + die("HALT\r\n"); + } + + /* The 440BX supports asymmetrical dual-sided dimms (I can't test though) + * but can't handle DIMMs smaller than 8MB per + * side or larger than 128MB per side. + */ + struct dimm_size sz = spd_get_dimm_size(device); + if ((sz.side1 < 8)) { + print_err("DIMMs smaller than 8MB per side\r\nare not supported on this northbridge\r\n"); + die("HALT\r\n"); + } + if ((sz.side1 > 128)) { + print_err ("DIMMs larger than 128MB per side\r\nare not supported on this northbridge\r\n"); + die("HALT\r\n"); + } + /* - End Memory compatibility checks - */ + + /* We need to divide size by 8 to set up the + * DRB registers. + */ + drb += (sz.side1 / 8); + /* Builds the DRB for the next row in MSB so it gets placed in DRB[n+1] + * where it belongs when written as a 16-bit word. + */ + drb &= 0xff; + drb |= (drb + (sz.side2 / 8)) << 8; + + } else { +#if 0 + PRINT_DEBUG("No DIMM found in slot "); + PRINT_DEBUG_HEX8(i); + PRINT_DEBUG("\r\n"); +#endif + + /* If there's no DIMM in the slot, set dra value to 0x00. */ + dra = 0x00; + ecc = 0xc0; + /* Still have to propagate DRB over */ + drb &= 0xff; + drb |= (drb << 8); + } + + pci_write_config16(NB, DRB+(2*i), drb); +#if 0 + PRINT_DEBUG("DRB has been set to 0x"); + PRINT_DEBUG_HEX16(drb); + PRINT_DEBUG("\r\n"); +#endif + + /* Brings the upper DRB back down to be base for + * DRB calculations for the next two rows. + */ + drb >>= 8; + + rps |= (dra & 0x0f) << (i*4); + nbxecc = (nbxecc >> 2) | (ecc & 0xc0); + } + /* Set Paging Policy Register */ + pci_write_config8(NB, PGPOL+1, bpr); + PRINT_DEBUG("PGPOL[BPR] has been set to 0x"); + PRINT_DEBUG_HEX8(bpr); + PRINT_DEBUG("\r\n"); + /* Set DRAM Row Page Size Register */ + pci_write_config16(NB, RPS, rps); + PRINT_DEBUG("RPS has been set to 0x"); + PRINT_DEBUG_HEX16(rps); + PRINT_DEBUG("\r\n"); + /* ### ECC */ + pci_write_config8(NB, NBXCFG+3, nbxecc); + PRINT_DEBUG("NBXECC[31:24] has been set to 0x"); + PRINT_DEBUG_HEX8(nbxecc); + PRINT_DEBUG("\r\n"); + + /* Set DRAMC[4:3] to proper memory type (EDO/SDRAM) + * TODO: Account for registered SDRAM + */ + edosd &= 0x07; + if (edosd & 0x02) { + edosd |= 0x00; + } else if (edosd & 0x04) { + edosd |= 0x08; + } + edosd &= 0x18; + /* edosd by now has been transformed to the value needed for DRAMC[4:3] */ + value = pci_read_config8(NB, DRAMC) & 0xe7; + value |= edosd; + pci_write_config8(NB, DRAMC, value); + PRINT_DEBUG("DRAMC has been set to 0x"); + PRINT_DEBUG_HEX8(value); + PRINT_DEBUG("\r\n"); + +} + +static void sdram_set_spd_registers(void) +{ + /* Setup DRAM Row Boundary Registers and other attributes */ + set_dram_row_attributes(); + /* TODO: Set SDRAMC. */ pci_write_config16(NB, SDRAMC, 0x0010); /* SDRAMPWR=1: 4 DIMM config */
- /* TODO: Set PGPOL. */ - // pci_write_config16(NB, PGPOL, 0x0107); - pci_write_config16(NB, PGPOL, 0x0123); - - /* TODO: Set NBXCFG. */ - // pci_write_config32(NB, NBXCFG, 0x0100220c); // FIXME? - pci_write_config32(NB, NBXCFG, 0xff00800c); - + /* TODO */ + set_dram_buffer_strength(); + /* TODO: Set PMCR? */ // pci_write_config8(NB, PMCR, 0x14); pci_write_config8(NB, PMCR, 0x10);
/* TODO? */ - pci_write_config8(NB, PCI_LATENCY_TIMER, 0x40); pci_write_config8(NB, DRAMT, 0x03); - pci_write_config8(NB, MBSC, 0x03); - pci_write_config8(NB, SCRR, 0x38); }
+static void sdram_set_timing(unsigned int mhz) { + /* TODO */ + +} + static void sdram_enable(void) { int i;
************I also noticed you did not use the memory initialize each row/side code from the i830. That code is extremely important for multiple memory sticks. Besides that everything else looks really good, great work!
On Thu, Mar 4, 2010 at 8:26 AM, Joseph Smith joe@settoplinux.org wrote:
I would not worry about the microcode updates right now. CAR for Intel 6bx is coming real soon and the microcode updates will be included :-)
CAN'T WAIT! :D Then I can say goodbye to the messiness that is romcc, lol.
**********You are setting alot more than just dra here, I would rename this function something like sdram_setup_registers().
Good point. Eventually I wanted to name it sdram_initalize() just like
i830, but there are a couple other references to the current names elsewhere. One step at a time I guess.
************I also noticed you did not use the memory initialize each row/side code from the i830. That code is extremely important for multiple memory sticks. Besides that everything else looks really good, great work!
There were some code that send RAM commands to the modules in the BX code.
I just kept them around, thinking that this code in i830 may be specific to i830.
Mark, the problem you saw might be MBFS and MBSC not being set properly. I have reversed how the factory BIOS programmed them and have the code in my working copy. I'll see if that makes a difference. We are still hardcoded to CAS3 latency. One step at a time again I guess.
On another front, with the board running factory BIOS, I dumped the BX's config space (lspci -s 0:0:0.0 -xxx) with various DIMM configurations, especially with two sticks in DIMM0&1, DIMM2&3, and 3 sticks. These three scenarios are where most of the logics are. I can post them if anyone wants to look at them. All my RAMs are double sided, one 128MB and the others are 256MB.
To figure out how this gets coded for the 3-slot P2B, Someone would need to reverse the vendor bios for that board or do same as above.
Also, P3B-F has 4 DIMM slots as well.
Thanks Keith
On 03/05/2010 12:53 AM, Keith Hui wrote:
On Thu, Mar 4, 2010 at 8:26 AM, Joseph Smith <joe@settoplinux.org mailto:joe@settoplinux.org> wrote:
I would not worry about the microcode updates right now. CAR for Intel 6bx is coming real soon and the microcode updates will be included :-)
CAN'T WAIT! :D Then I can say goodbye to the messiness that is romcc, lol.
**********You are setting alot more than just dra here, I would rename this function something like sdram_setup_registers().
Good point. Eventually I wanted to name it sdram_initalize() just like i830, but there are a couple other references to the current names elsewhere. One step at a time I guess.
************I also noticed you did not use the memory initialize each row/side code from the i830. That code is extremely important for multiple memory sticks. Besides that everything else looks really good, great work!
There were some code that send RAM commands to the modules in the BX code. I just kept them around, thinking that this code in i830 may be specific to i830.
The only code that may be specific to the i830 is the DRC regs. Also you may have to tweek:
dimm_end = pci_read_config8(NORTHBRIDGE, DRB + row);
for the 440bx. This basicly reading the sdram size to set as the start of the next row.
The rest of the routine (and I have researched it extensively) is pretty much the standard for sdram initialization.
Mark, the problem you saw might be MBFS and MBSC not being set properly. I have reversed how the factory BIOS programmed them and have the code in my working copy. I'll see if that makes a difference. We are still hardcoded to CAS3 latency. One step at a time again I guess.
On another front, with the board running factory BIOS, I dumped the BX's config space (lspci -s 0:0:0.0 -xxx) with various DIMM configurations, especially with two sticks in DIMM0&1, DIMM2&3, and 3 sticks. These three scenarios are where most of the logics are. I can post them if anyone wants to look at them. All my RAMs are double sided, one 128MB and the others are 256MB.
To figure out how this gets coded for the 3-slot P2B, Someone would need to reverse the vendor bios for that board or do same as above.
FYI, serialice is awesome at dumping raminit routines :-)
Hi,
I have been testing this patch on my Soyo SY-6BA+ III, i440BX based.
Good news: 128MB module on its own in any of the 4 slots works. 256MB module works (tested in one slot). 128MB + 128MB works.
Not so good: 128MB + 128MB + 256MB + 128MB boots but only with 512MB RAM. Should add up to 640MB. If this is a limitation of the chipset that's fine, but maybe it could print a warning message if that is the case? A single 16MB module did not boot. Log:
------
coreboot-4.0-r5184M-Andrew Thu Mar 4 21:19:28 GMT 2010 starting... SMBus controller enabled Northbridge prior to SDRAM init: PCI: 00:00.00 00: 86 80 90 71 06 00 10 22 03 00 00 06 00 00 00 00 10: 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 30: 00 00 00 00 a0 00 00 00 00 00 00 00 00 00 00 00 40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 50: 04 20 00 00 00 00 00 00 03 00 00 00 00 00 00 00 60: 01 01 01 01 01 01 01 01 00 00 00 00 00 00 00 00 70: 00 1f 02 38 00 00 00 00 00 00 00 38 00 00 00 00 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90: 80 00 00 00 04 61 00 00 00 05 00 00 00 00 00 00 a0: 02 00 10 00 03 02 00 1f 00 00 00 00 00 00 00 00 b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0: 00 00 00 00 00 00 00 00 18 0c 00 00 00 00 00 00 d0: 00 00 00 00 00 00 00 00 0c 00 00 00 00 00 00 00 e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f0: 00 00 00 00 00 f8 00 00 20 0f 00 00 00 00 00 00 Found DIMM in slot 00 DIMMs larger than 128MB per side are not supported on this northbridge HALT
------
But in all that's a very good result, thanks for the work and the patch! Now I'm not sure what else I need the vendor BIOS for... :)
Hi,
I think I reviewed and committed most of the stuff now, except for the microcode updates, IIRC there will be some bigger patch handling those in the near future anyway.
See some more notes below.
On Tue, Mar 02, 2010 at 11:19:24PM -0500, Keith Hui wrote:
- Adds Asus P2B-LS mainboard
Merged with some small cosmetic changes, thanks.
- Adds RAM detection for i440bx (based on i82830 code). We're no longer hard
coded for 64MB on one row!
Very nice! I did various smaller changes here, should be functionally equivalent mostly though, except for these:
- In i440bx.h: I dropped the generic PCI register definitions, those are not 440BX specific and already defined in pci_def.h.
- Dropped MLT / PCI_LATENCY_TIMER for now, should not be needed, and raminit.c is probably the wrong place for this stuff anyway, I guess.
- Not sure about this change, omitted it for now (need to re-check datasheets):
static const uint32_t refresh_rate_map[] = { - 1, 5, 5, 2, 3, 4 + 1, 1, 1, 2, 3, 4 };
Probably also some more stuff I forgot about. One thing I'd like to do next is to factor out some stuff from set_dram_row_attributes(), that's way too long and too nested for my taste.
- Adds a proper Slot 1 cpu under src/cpu/intel/slot_1. It's a stub copied
from slot_2 but addresses a few FIXMEs. My P2B-LS code refers to this.
Yep, thanks! I'll fixup the other slot 1 boards in a few minutes or so.
- Adds microcode for Intel Tualatin CPUs, cpuid 6B1 and 6B4.* Actually
loading them is pending.
Postponed for now, see above.
Will test the code on a few 440BX boards soonish, and fix the 3 vs. 4 DIMM slots issue.
Thanks, Uwe.
This activity is really impressive. It got me to wondering: how old is the 440bx chipset? I know it's been around a while. It sure seems to live one ...
ron
On Saturday 06 March 2010 20:01:11 ron minnich wrote:
This activity is really impressive. It got me to wondering: how old is the 440bx chipset?
it was released in april 1998
Christian
On 06/03/2010 20:05, Christian Leber wrote:
On Saturday 06 March 2010 20:01:11 ron minnich wrote:
This activity is really impressive. It got me to wondering: how old is the 440bx chipset?
it was released in april 1998
Old enough that most people would want to get rid of computers that old, but still new enough to be useful. (Flash not EPROM, PCI, DIMMs...) I have an i440BX based Soyo board which I got for free and I know that even if I broke it it wouldn't be a great loss, so re-programming the flash etc. is of no great risk. Even if I had to de-solder the flash chip I could use it for practice, although this board has a socket. And now (after surprisingly little effort on my part!) Coreboot runs on it. :)
So it is probably a good era of board for anyone wanting to get started with Coreboot without the risk of destroying something they care about or remembering how to do ISA.
Andrew Morgan wrote:
On 06/03/2010 20:05, Christian Leber wrote:
On Saturday 06 March 2010 20:01:11 ron minnich wrote:
This activity is really impressive. It got me to wondering: how old is the 440bx chipset?
it was released in april 1998
Old enough that most people would want to get rid of computers that old, but still new enough to be useful. (Flash not EPROM, PCI, DIMMs...) I have an i440BX based Soyo board which I got for free and I know that even if I broke it it wouldn't be a great loss, so re-programming the flash etc. is of no great risk. Even if I had to de-solder the flash chip I could use it for practice, although this board has a socket. And now (after surprisingly little effort on my part!) Coreboot runs on it. :)
So it is probably a good era of board for anyone wanting to get started with Coreboot without the risk of destroying something they care about or remembering how to do ISA.
That's why I bought a ASUS P2B off of e-bay for £5. ;-)
A lot of fun for the money.
MM