Angel Pons has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/38359 )
Change subject: nb/intel/nehalem: Try to clean up code ......................................................................
nb/intel/nehalem: Try to clean up code
Looks like raminit.c desperately needs a serious refactor.
Using BUILD_TIMELESS=1, this does not change packardbell/ms2290 builds.
Change-Id: I4d2501317faf3e4a7cf8a0ccb471d334232bfeae Signed-off-by: Angel Pons th3fanbus@gmail.com --- M src/northbridge/intel/nehalem/acpi.c M src/northbridge/intel/nehalem/early_init.c M src/northbridge/intel/nehalem/finalize.c M src/northbridge/intel/nehalem/gma.c M src/northbridge/intel/nehalem/nehalem.h M src/northbridge/intel/nehalem/northbridge.c M src/northbridge/intel/nehalem/raminit.c 7 files changed, 1,504 insertions(+), 1,686 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/59/38359/1
diff --git a/src/northbridge/intel/nehalem/acpi.c b/src/northbridge/intel/nehalem/acpi.c index 462cdc0..42d7efe 100644 --- a/src/northbridge/intel/nehalem/acpi.c +++ b/src/northbridge/intel/nehalem/acpi.c @@ -38,32 +38,34 @@
switch ((pciexbar_reg >> 1) & 3) { case 0: // 256MB - pciexbar = - pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) | - (1 << 28)); + pciexbar = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) | (1 << 28)); + max_buses = 256; break; + case 1: // 128M - pciexbar = - pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) | - (1 << 28) | (1 << 27)); + pciexbar = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) | (1 << 28) + | (1 << 27)); + max_buses = 128; break; + case 2: // 64M - pciexbar = - pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) | - (1 << 28) | (1 << 27) | (1 << 26)); + pciexbar = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) | (1 << 28) + | (1 << 27) | (1 << 26)); + max_buses = 64; break; - default: // RSVD + + default: // RSVD return current; }
if (!pciexbar) return current;
- current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *) current, - pciexbar, 0x0, 0x0, max_buses - 1); + current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *) current, pciexbar, 0x0, + 0x0, max_buses - 1);
return current; } diff --git a/src/northbridge/intel/nehalem/early_init.c b/src/northbridge/intel/nehalem/early_init.c index a809121..f81ade4 100644 --- a/src/northbridge/intel/nehalem/early_init.c +++ b/src/northbridge/intel/nehalem/early_init.c @@ -41,23 +41,27 @@ printk(BIOS_DEBUG, " done.\n");
printk(BIOS_DEBUG, "Disabling Watchdog reboot..."); + /* No reset */ RCBA32(GCS) = RCBA32(GCS) | (1 << 5); + /* halt timer */ outw((1 << 11), DEFAULT_PMBASE | 0x60 | 0x08); + /* halt timer */ - outw(inw(DEFAULT_PMBASE | 0x60 | 0x06) | 2, - DEFAULT_PMBASE | 0x60 | 0x06); + outw(inw(DEFAULT_PMBASE | 0x60 | 0x06) | 2, DEFAULT_PMBASE | 0x60 | 0x06); + printk(BIOS_DEBUG, " done.\n");
printk(BIOS_DEBUG, "Setting up static northbridge registers..."); + /* Set up all hardcoded northbridge BARs */ pci_write_config32(PCI_DEV(0, 0x00, 0), EPBAR, DEFAULT_EPBAR | 1); - pci_write_config32(PCI_DEV(0, 0x00, 0), EPBAR + 4, - (0LL + DEFAULT_EPBAR) >> 32); + pci_write_config32(PCI_DEV(0, 0x00, 0), EPBAR + 4, (0LL + DEFAULT_EPBAR) >> 32); + pci_write_config32(PCI_DEV(0, 0x00, 0), MCHBAR, (uintptr_t)DEFAULT_MCHBAR | 1); pci_write_config32(PCI_DEV(0, 0x00, 0), MCHBAR + 4, - (0LL + (uintptr_t)DEFAULT_MCHBAR) >> 32); + (0LL + (uintptr_t)DEFAULT_MCHBAR) >> 32);
pci_write_config32(PCI_DEV(0, 0x00, 0), DMIBAR, (uintptr_t)DEFAULT_DMIBAR | 1); pci_write_config32(PCI_DEV(0, 0x00, 0), DMIBAR + 4, @@ -82,12 +86,12 @@ /* bit 0 = disable multicore, bit 1 = disable quadcore, bit 8 = disable hyperthreading. */ - pci_write_config32(PCI_DEV(0xff, 0x00, 0), 0x80, - (pci_read_config32(PCI_DEV(0xff, 0x0, 0x0), 0x80) & 0xfffffefc) | 0x10000); + pci_write_config32(PCI_DEV(0xff, 0x0, 0), 0x80, (pci_read_config32( + PCI_DEV(0xff, 0x0, 0), 0x80) & 0xfffffefc) | 0x10000);
u8 reg8; - struct cpuid_result result; - result = cpuid_ext(0x6, 0x8b); + struct cpuid_result result = cpuid_ext(0x6, 0x8b); + if (!(result.eax & 0x2)) { m = rdmsr(MSR_FSB_CLOCK_VCC); reg8 = ((m.lo & 0xff00) >> 8) + 1; @@ -122,6 +126,7 @@
/* Device ID Override Enable should be done very early */ capid0_a = pci_read_config32(PCI_DEV(0, 0, 0), 0xe4); + if (capid0_a & (1 << 10)) { reg8 = pci_read_config8(PCI_DEV(0, 0, 0), 0xf3); reg8 &= ~7; /* Clear 2:0 */ @@ -136,21 +141,20 @@ nehalem_setup_bars();
s3_resume = (inw(DEFAULT_PMBASE + PM1_STS) & WAK_STS) && - (((inl(DEFAULT_PMBASE + PM1_CNT) >> 10) & 7) == SLP_TYP_S3); + (((inl(DEFAULT_PMBASE + PM1_CNT) >> 10) & 7) == SLP_TYP_S3);
elog_boot_notify(s3_resume);
/* Device Enable */ - pci_write_config32(PCI_DEV(0, 0, 0), D0F0_DEVEN, - DEVEN_IGD | DEVEN_PEG10 | DEVEN_HOST); + pci_write_config32(PCI_DEV(0, 0, 0), D0F0_DEVEN, DEVEN_IGD | DEVEN_PEG10 | DEVEN_HOST);
early_cpu_init();
pci_write_config32(PCI_DEV(0, 0x16, 0), 0x10, (uintptr_t)DEFAULT_HECIBAR); - pci_write_config32(PCI_DEV(0, 0x16, 0), PCI_COMMAND, - PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); + pci_write_config32(PCI_DEV(0, 0x16, 0), PCI_COMMAND, PCI_COMMAND_MASTER | + PCI_COMMAND_MEMORY);
- /* Magic for S3 resume. Must be done early. */ + /* Magic for S3 resume. Must be done early. */ if (s3_resume) { MCHBAR32 (0x1e8) = (MCHBAR32(0x1e8) & ~1) | 6; MCHBAR32 (0x1e8) = (MCHBAR32(0x1e8) & ~3) | 4; diff --git a/src/northbridge/intel/nehalem/finalize.c b/src/northbridge/intel/nehalem/finalize.c index c03b067..c197f1b 100644 --- a/src/northbridge/intel/nehalem/finalize.c +++ b/src/northbridge/intel/nehalem/finalize.c @@ -16,8 +16,6 @@
#include "nehalem.h"
-#define PCI_DEV_SNB PCI_DEV(0, 0, 0) - void intel_nehalem_finalize_smm(void) { MCHBAR32_OR(0x5500, 1 << 0); /* PAVP */ diff --git a/src/northbridge/intel/nehalem/gma.c b/src/northbridge/intel/nehalem/gma.c index d717e48..fa07601 100644 --- a/src/northbridge/intel/nehalem/gma.c +++ b/src/northbridge/intel/nehalem/gma.c @@ -35,11 +35,10 @@ #include "chip.h" #include "nehalem.h"
-/* some vga option roms are used for several chipsets but they only have one - * PCI ID in their header. If we encounter such an option rom, we need to do - * the mapping ourselves +/* + * Some VGA option roms are used for several chipsets, but they only have one PCI ID in their + * header. If we encounter such an option rom, we need to do the mapping ourselves */ - u32 map_oprom_vendev(u32 vendev) { u32 new_vendev = vendev; @@ -71,6 +70,7 @@ data = gtt_read(reg); if ((data & mask) == value) return 1; + udelay(10); }
@@ -148,15 +148,15 @@ { u16 reg16;
- /* clear DMISCI status */ + /* Clear DMISCI status */ reg16 = inw(DEFAULT_PMBASE + TCO1_STS); reg16 &= DMISCI_STS; outw(DEFAULT_PMBASE + TCO1_STS, reg16);
- /* clear acpi tco status */ + /* Clear ACPI TCO status */ outl(DEFAULT_PMBASE + GPE0_STS, TCOSCI_STS);
- /* enable acpi tco scis */ + /* Enable ACPI TCO SCIs */ reg16 = inw(DEFAULT_PMBASE + GPE0_EN); reg16 |= TCOSCI_EN; outw(DEFAULT_PMBASE + GPE0_EN, reg16); @@ -175,16 +175,16 @@ if (!gtt_res || !gtt_res->base) return;
- if (!acpi_is_wakeup_s3() && - CONFIG(MAINBOARD_USE_LIBGFXINIT)) { + if (!acpi_is_wakeup_s3() && CONFIG(MAINBOARD_USE_LIBGFXINIT)) { + struct northbridge_intel_nehalem_config *conf = dev->chip_info; int lightup_ok; printk(BIOS_SPEW, "Initializing VGA without OPROM.");
gma_gfxinit(&lightup_ok); + /* Linux relies on VBT for panel info. */ - generate_fake_intel_oprom(&conf->gfx, dev, - "$VBT IRONLAKE-MOBILE"); + generate_fake_intel_oprom(&conf->gfx, dev, "$VBT IRONLAKE-MOBILE"); } else { /* PCI Init, will run VBIOS */ pci_dev_init(dev); @@ -216,8 +216,7 @@ res->size = (resource_t) 0x10000000; }
-const struct i915_gpu_controller_info * -intel_gma_get_controller_info(void) +const struct i915_gpu_controller_info *intel_gma_get_controller_info(void) { struct device *dev = pcidev_on_root(0x2, 0); if (!dev) { @@ -237,10 +236,8 @@ drivers_intel_gma_displays_ssdt_generate(gfx); }
-static unsigned long -gma_write_acpi_tables(struct device *const dev, - unsigned long current, - struct acpi_rsdp *const rsdp) +static unsigned long gma_write_acpi_tables(struct device *const dev, unsigned long current, + struct acpi_rsdp *const rsdp) { igd_opregion_t *opregion = (igd_opregion_t *)current; global_nvs_t *gnvs; @@ -255,6 +252,7 @@ if (gnvs) { /* IGD OpRegion Base Address */ gma_set_gnvs_aslb(gnvs, (uintptr_t)opregion); + } else { printk(BIOS_ERR, "Error: GNVS table not found.\n"); } @@ -276,14 +274,12 @@ .scan_bus = 0, .enable = 0, .ops_pci = &gma_pci_ops, - .write_acpi_tables = gma_write_acpi_tables, + .write_acpi_tables = gma_write_acpi_tables, };
+/* FIXME: Looks like some of these are for SNB/IVB. */ static const unsigned short pci_device_ids[] = { - 0x0046, 0x0102, 0x0106, 0x010a, 0x0112, - 0x0116, 0x0122, 0x0126, 0x0156, - 0x0166, - 0 + 0x0046, 0x0102, 0x0106, 0x010a, 0x0112, 0x0116, 0x0122, 0x0126, 0x0156, 0x0166, 0 };
static const struct pci_driver gma __pci_driver = { diff --git a/src/northbridge/intel/nehalem/nehalem.h b/src/northbridge/intel/nehalem/nehalem.h index 493c5b1..5705109 100644 --- a/src/northbridge/intel/nehalem/nehalem.h +++ b/src/northbridge/intel/nehalem/nehalem.h @@ -35,7 +35,7 @@
/* The setup is one DIMM per channel, so there's no need to find a common timing setup between multiple chips (but chip and controller - still need to be coordinated */ + still need to be coordinated) */ typedef struct { int txt_enabled; int cores; @@ -52,83 +52,73 @@
#define DEFAULT_HECIBAR ((u8 *)0xfed17000)
- -#define IOMMU_BASE1 0xfed90000 -#define IOMMU_BASE2 0xfed91000 -#define IOMMU_BASE3 0xfed92000 -#define IOMMU_BASE4 0xfed93000 +#define IOMMU_BASE1 0xfed90000 +#define IOMMU_BASE2 0xfed91000 +#define IOMMU_BASE3 0xfed92000 +#define IOMMU_BASE4 0xfed93000
/* * D0:F0 */ -#define D0F0_EPBAR_LO 0x40 -#define D0F0_EPBAR_HI 0x44 -#define D0F0_MCHBAR_LO 0x48 -#define D0F0_MCHBAR_HI 0x4c -#define D0F0_GGC 0x52 -#define D0F0_DEVEN 0x54 -#define DEVEN_IGD (1 << 3) -#define DEVEN_PEG10 (1 << 1) -#define DEVEN_HOST (1 << 0) -#define D0F0_PCIEXBAR_LO 0x60 -#define D0F0_PCIEXBAR_HI 0x64 -#define D0F0_DMIBAR_LO 0x68 -#define D0F0_DMIBAR_HI 0x6c -#define D0F0_PMBASE 0x78 -#define QPD0F1_PAM(x) (0x40+(x)) /* 0-6*/ -#define D0F0_REMAPBASE 0x98 -#define D0F0_REMAPLIMIT 0x9a -#define D0F0_TOM 0xa0 -#define D0F0_TOUUD 0xa2 -#define D0F0_IGD_BASE 0xa4 -#define D0F0_GTT_BASE 0xa8 -#define D0F0_TOLUD 0xb0 -#define D0F0_SKPD 0xdc /* Scratchpad Data */ +#define D0F0_EPBAR_LO 0x40 +#define D0F0_EPBAR_HI 0x44 +#define D0F0_MCHBAR_LO 0x48 +#define D0F0_MCHBAR_HI 0x4c +#define D0F0_GGC 0x52 +#define D0F0_DEVEN 0x54 +#define DEVEN_IGD (1 << 3) +#define DEVEN_PEG10 (1 << 1) +#define DEVEN_HOST (1 << 0) +#define D0F0_PCIEXBAR_LO 0x60 +#define D0F0_PCIEXBAR_HI 0x64 +#define D0F0_DMIBAR_LO 0x68 +#define D0F0_DMIBAR_HI 0x6c +#define D0F0_PMBASE 0x78 +#define QPD0F1_PAM(x) (0x40+(x)) /* 0-6*/ +#define D0F0_REMAPBASE 0x98 +#define D0F0_REMAPLIMIT 0x9a +#define D0F0_TOM 0xa0 +#define D0F0_TOUUD 0xa2 +#define D0F0_IGD_BASE 0xa4 +#define D0F0_GTT_BASE 0xa8 +#define D0F0_TOLUD 0xb0 +#define D0F0_SKPD 0xdc /* Scratchpad Data */
-#define D0F0_CAPID0 0xe0 +#define D0F0_CAPID0 0xe0
-#define TSEG 0xac /* TSEG base */ +#define TSEG 0xac /* TSEG base */
/* * D1:F0 PEG */ -#define PEG_CAP 0xa2 -#define SLOTCAP 0xb4 -#define PEGLC 0xec -#define D1F0_VCCAP 0x104 -#define D1F0_VC0RCTL 0x114 +#define PEG_CAP 0xa2 +#define SLOTCAP 0xb4 +#define PEGLC 0xec +#define D1F0_VCCAP 0x104 +#define D1F0_VC0RCTL 0x114
/* Chipset types */ #define NEHALEM_MOBILE 0 #define NEHALEM_DESKTOP 1 #define NEHALEM_SERVER 2
-/* Device ID for SandyBridge and IvyBridge */ +/* Device ID for SandyBridge */ #define BASE_REV_SNB 0x00 -#define BASE_REV_IVB 0x50 #define BASE_REV_MASK 0x50
/* SandyBridge CPU stepping */ #define SNB_STEP_D0 (BASE_REV_SNB + 5) /* Also J0 */ #define SNB_STEP_D1 (BASE_REV_SNB + 6) -#define SNB_STEP_D2 (BASE_REV_SNB + 7) /* Also J1/Q0 */ - -/* IvyBridge CPU stepping */ -#define IVB_STEP_A0 (BASE_REV_IVB + 0) -#define IVB_STEP_B0 (BASE_REV_IVB + 2) -#define IVB_STEP_C0 (BASE_REV_IVB + 4) -#define IVB_STEP_K0 (BASE_REV_IVB + 5) -#define IVB_STEP_D0 (BASE_REV_IVB + 6)
/* Northbridge BARs */ #ifndef __ACPI__ #define DEFAULT_MCHBAR ((u8 *)0xfed10000) /* 16 KB */ #define DEFAULT_DMIBAR ((u8 *)0xfed18000) /* 4 KB */ #else -#define DEFAULT_MCHBAR 0xfed10000 /* 16 KB */ -#define DEFAULT_DMIBAR 0xfed18000 /* 4 KB */ +#define DEFAULT_MCHBAR 0xfed10000 /* 16 KB */ +#define DEFAULT_DMIBAR 0xfed18000 /* 4 KB */ #endif -#define DEFAULT_EPBAR 0xfed19000 /* 4 KB */ +#define DEFAULT_EPBAR 0xfed19000 /* 4 KB */ #define DEFAULT_RCBABASE ((u8 *)0xfed1c000)
#define QUICKPATH_BUS 0xff @@ -138,8 +128,9 @@ /* Everything below this line is ignored in the DSDT */ #ifndef __ACPI__
-/* Device 0:0.0 PCI configuration space (Host Bridge) */ - +/* + * Device 0:0.0 PCI configuration space (Host Bridge) + */ #define EPBAR 0x40 #define MCHBAR 0x48 #define PCIEXBAR 0x60 @@ -147,41 +138,37 @@ #define X60BAR 0x60
#define LAC 0x87 /* Legacy Access Control */ -#define QPD0F1_SMRAM 0x4d /* System Management RAM Control */ +#define QPD0F1_SMRAM 0x4d /* System Management RAM Control */
#define SKPAD 0xdc /* Scratchpad Data */
- -/* Device 0:2.0 PCI configuration space (Graphics Device) */ - +/* + * Device 0:2.0 PCI configuration space (Graphics Device) + */ #define MSAC 0x62 /* Multi Size Aperture Control */
/* * MCHBAR */ +#define MCHBAR8(x) (*((volatile u8 *) (DEFAULT_MCHBAR + (x)))) +#define MCHBAR16(x) (*((volatile u16 *)(DEFAULT_MCHBAR + (x)))) +#define MCHBAR32(x) (*((volatile u32 *)(DEFAULT_MCHBAR + (x)))) +#define MCHBAR8_AND(x, and) (MCHBAR8(x) = MCHBAR8(x) & (and)) +#define MCHBAR16_AND(x, and) (MCHBAR16(x) = MCHBAR16(x) & (and)) +#define MCHBAR32_AND(x, and) (MCHBAR32(x) = MCHBAR32(x) & (and)) +#define MCHBAR8_OR(x, or) (MCHBAR8(x) = MCHBAR8(x) | (or)) +#define MCHBAR16_OR(x, or) (MCHBAR16(x) = MCHBAR16(x) | (or)) +#define MCHBAR32_OR(x, or) (MCHBAR32(x) = MCHBAR32(x) | (or)) +#define MCHBAR8_AND_OR(x, and, or) (MCHBAR8(x) = (MCHBAR8(x) & (and)) | (or)) +#define MCHBAR16_AND_OR(x, and, or) (MCHBAR16(x) = (MCHBAR16(x) & (and)) | (or)) +#define MCHBAR32_AND_OR(x, and, or) (MCHBAR32(x) = (MCHBAR32(x) & (and)) | (or))
-#define MCHBAR8(x) (*((volatile u8 *)(DEFAULT_MCHBAR + (x)))) -#define MCHBAR16(x) (*((volatile u16 *)(DEFAULT_MCHBAR + (x)))) -#define MCHBAR32(x) (*((volatile u32 *)(DEFAULT_MCHBAR + (x)))) -#define MCHBAR8_AND(x, and) (MCHBAR8(x) = MCHBAR8(x) & (and)) -#define MCHBAR8_OR(x, or) (MCHBAR8(x) = MCHBAR8(x) | (or)) -#define MCHBAR8_AND_OR(x, and, or) \ - (MCHBAR8(x) = (MCHBAR8(x) & (and)) | (or)) -#define MCHBAR16_AND(x, and) (MCHBAR16(x) = MCHBAR16(x) & (and)) -#define MCHBAR16_OR(x, or) (MCHBAR16(x) = MCHBAR16(x) | (or)) -#define MCHBAR16_AND_OR(x, and, or) \ - (MCHBAR16(x) = (MCHBAR16(x) & (and)) | (or)) -#define MCHBAR32_AND(x, and) (MCHBAR32(x) = MCHBAR32(x) & (and)) -#define MCHBAR32_OR(x, or) (MCHBAR32(x) = MCHBAR32(x) | (or)) -#define MCHBAR32_AND_OR(x, and, or) \ - (MCHBAR32(x) = (MCHBAR32(x) & (and)) | (or)) /* * EPBAR - Egress Port Root Complex Register Block */ - -#define EPBAR8(x) (*((volatile u8 *)(DEFAULT_EPBAR + (x)))) -#define EPBAR16(x) (*((volatile u16 *)(DEFAULT_EPBAR + (x)))) -#define EPBAR32(x) (*((volatile u32 *)(DEFAULT_EPBAR + (x)))) +#define EPBAR8(x) (*((volatile u8 *) (DEFAULT_EPBAR + (x)))) +#define EPBAR16(x) (*((volatile u16 *)(DEFAULT_EPBAR + (x)))) +#define EPBAR32(x) (*((volatile u32 *)(DEFAULT_EPBAR + (x))))
#define EPPVCCAP1 0x004 /* 32bit */ #define EPPVCCAP2 0x008 /* 32bit */ @@ -209,10 +196,9 @@ /* * DMIBAR */ - -#define DMIBAR8(x) (*((volatile u8 *)(DEFAULT_DMIBAR + (x)))) -#define DMIBAR16(x) (*((volatile u16 *)(DEFAULT_DMIBAR + (x)))) -#define DMIBAR32(x) (*((volatile u32 *)(DEFAULT_DMIBAR + (x)))) +#define DMIBAR8(x) (*((volatile u8 *) (DEFAULT_DMIBAR + (x)))) +#define DMIBAR16(x) (*((volatile u16 *)(DEFAULT_DMIBAR + (x)))) +#define DMIBAR32(x) (*((volatile u32 *)(DEFAULT_DMIBAR + (x))))
#define DMIVCECH 0x000 /* 32bit */ #define DMIPVCCAP1 0x004 /* 32bit */ @@ -246,9 +232,6 @@
#ifndef __ASSEMBLER__
-#define PCI_DEVICE_ID_SB 0x0104 -#define PCI_DEVICE_ID_IB 0x0154 - void intel_nehalem_finalize_smm(void);
int bridge_silicon_revision(void); diff --git a/src/northbridge/intel/nehalem/northbridge.c b/src/northbridge/intel/nehalem/northbridge.c index 1718307..bd4fc47 100644 --- a/src/northbridge/intel/nehalem/northbridge.c +++ b/src/northbridge/intel/nehalem/northbridge.c @@ -34,10 +34,10 @@ int bridge_silicon_revision(void) { if (bridge_revision_id < 0) { - uint8_t stepping = cpuid_eax(1) & 0xf; + uint8_t stepping = cpuid_eax(1) & 0xf; uint8_t bridge_id = - pci_read_config16(pcidev_on_root(0, 0), - PCI_DEVICE_ID) & 0xf0; + pci_read_config16(pcidev_on_root(0, 0), PCI_DEVICE_ID) & 0xf0; + bridge_revision_id = bridge_id | stepping; } return bridge_revision_id; @@ -67,13 +67,12 @@ resource = new_resource(dev, index++); resource->base = (resource_t) 0xfed00000; resource->size = (resource_t) 0x00100000; - resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE | - IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED; + resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE | IORESOURCE_FIXED | + IORESOURCE_STORED | IORESOURCE_ASSIGNED;
- mmio_resource(dev, index++, legacy_hole_base_k, - (0xc0000 >> 10) - legacy_hole_base_k); - reserved_ram_resource(dev, index++, 0xc0000 >> 10, - (0x100000 - 0xc0000) >> 10); + mmio_resource(dev, index++, legacy_hole_base_k, (0xc0000 >> 10) - legacy_hole_base_k); + + reserved_ram_resource(dev, index++, 0xc0000 >> 10, (0x100000 - 0xc0000) >> 10);
#if CONFIG(CHROMEOS_RAMOOPS) reserved_ram_resource(dev, index++, @@ -127,8 +126,7 @@ mmconf_resource(dev, 0x50);
tseg_base = pci_read_config32(pcidev_on_root(0, 0), TSEG); - TOUUD = pci_read_config16(pcidev_on_root(0, 0), - D0F0_TOUUD); + TOUUD = pci_read_config16(pcidev_on_root(0, 0), D0F0_TOUUD);
printk(BIOS_DEBUG, "ram_before_4g_top: 0x%x\n", tseg_base); printk(BIOS_DEBUG, "TOUUD: 0x%x\n", (unsigned int)TOUUD); @@ -140,22 +138,23 @@ mmio_resource(dev, 5, tseg_base >> 10, CONFIG_SMM_TSEG_SIZE >> 10);
reg16 = pci_read_config16(pcidev_on_root(0, 0), D0F0_GGC); - const int uma_sizes_gtt[16] = - { 0, 1, 0, 2, 0, 0, 0, 0, 0, 2, 3, 4, 42, 42, 42, 42 }; - /* Igd memory */ + + const int uma_sizes_gtt[16] = { 0, 1, 0, 2, 0, 0, 0, 0, 0, 2, 3, 4, 42, 42, 42, 42 }; + + /* IGD memory */ const int uma_sizes_igd[16] = { 0, 0, 0, 0, 0, 32, 48, 64, 128, 256, 96, 160, 224, 352, 256, 512 }; + u32 igd_base, gtt_base; int uma_size_igd, uma_size_gtt;
- uma_size_igd = uma_sizes_igd[(reg16 >> 4) & 0xF]; - uma_size_gtt = uma_sizes_gtt[(reg16 >> 8) & 0xF]; + uma_size_igd = uma_sizes_igd[(reg16 >> 4) & 0xf]; + uma_size_gtt = uma_sizes_gtt[(reg16 >> 8) & 0xf];
- igd_base = - pci_read_config32(pcidev_on_root(0, 0), D0F0_IGD_BASE); - gtt_base = - pci_read_config32(pcidev_on_root(0, 0), D0F0_GTT_BASE); + igd_base = pci_read_config32(pcidev_on_root(0, 0), D0F0_IGD_BASE); + gtt_base = pci_read_config32(pcidev_on_root(0, 0), D0F0_GTT_BASE); + mmio_resource(dev, 6, gtt_base >> 10, uma_size_gtt << 10); mmio_resource(dev, 7, igd_base >> 10, uma_size_igd << 10);
@@ -199,6 +198,7 @@ reg32 = DMIBAR32(0x1f8); reg32 |= (1 << 16); DMIBAR32(0x1f8) = reg32; + } else if (bridge_silicon_revision() >= SNB_STEP_D1) { reg32 = DMIBAR32(0x1f8); reg32 &= ~(1 << 26); @@ -210,7 +210,11 @@ DMIBAR32(0x1fc) = reg32; }
- /* Enable ASPM on SNB link, should happen before PCH link */ + /* + * Enable ASPM on SNB link, should happen before PCH link. + * + * FIXME: This is not Sandy Bridge! Is this correct? + */ if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_SNB) { reg32 = DMIBAR32(0xd04); reg32 |= (1 << 4); @@ -282,6 +286,7 @@ /* Set the operations if it is a special bus type */ if (dev->path.type == DEVICE_PATH_DOMAIN) { dev->ops = &pci_domain_ops; + } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) { dev->ops = &cpu_bus_ops; } diff --git a/src/northbridge/intel/nehalem/raminit.c b/src/northbridge/intel/nehalem/raminit.c index 7735522..852e733 100644 --- a/src/northbridge/intel/nehalem/raminit.c +++ b/src/northbridge/intel/nehalem/raminit.c @@ -44,11 +44,11 @@ #include "raminit.h" #include "raminit_tables.h"
-#define NORTHBRIDGE PCI_DEV(0, 0, 0) -#define SOUTHBRIDGE PCI_DEV(0, 0x1f, 0) -#define GMA PCI_DEV (0, 0x2, 0x0) -#define HECIDEV PCI_DEV(0, 0x16, 0) -#define HECIBAR 0x10 +#define NORTHBRIDGE PCI_DEV(0, 0, 0) +#define SOUTHBRIDGE PCI_DEV(0, 0x1f, 0) +#define GMA PCI_DEV(0, 0x2, 0x0) +#define HECIDEV PCI_DEV(0, 0x16, 0) +#define HECIBAR 0x10
#define FOR_ALL_RANKS \ for (channel = 0; channel < NUM_CHANNELS; channel++) \ @@ -125,8 +125,7 @@ MCHBAR32(0x1d0) = 0; while (MCHBAR32(0x1d0) & 0x800000) ; - MCHBAR32(0x1d4) = - (val & ((1 << bits) - 1)) | (2 << bits) | (flag << bits); + MCHBAR32(0x1d4) = (val & ((1 << bits) - 1)) | (2 << bits) | (flag << bits); MCHBAR32(0x1d0) = 0x40000000 | addr; while (MCHBAR32(0x1d0) & 0x800000) ; @@ -139,8 +138,7 @@ MCHBAR32(0x1d0) = 0; while (MCHBAR32(0x1d0) & 0x800000) ; - MCHBAR32(0x1d0) = - 0x80000000 | (((MCHBAR8(0x246) >> 2) & 3) + 0x361 - addr); + MCHBAR32(0x1d0) = 0x80000000 | (((MCHBAR8(0x246) >> 2) & 3) + 0x361 - addr); while (MCHBAR32(0x1d0) & 0x800000) ; val = MCHBAR32(0x1d8); @@ -187,10 +185,10 @@ #define gav(x) gav_real (__LINE__, (x))
struct raminfo { - u16 clock_speed_index; /* clock_speed (REAL, not DDR) / 133.(3) - 3 */ - u16 fsb_frequency; /* in 1.(1)/2 MHz. */ - u8 is_x16_module[2][2]; /* [CHANNEL][SLOT] */ - u8 density[2][2]; /* [CHANNEL][SLOT] */ + u16 clock_speed_index; /* clock_speed (REAL, not DDR) / 133.(3) - 3 */ + u16 fsb_frequency; /* in 1.(1)/2 MHz. */ + u8 is_x16_module[2][2]; /* [CHANNEL][SLOT] */ + u8 density[2][2]; /* [CHANNEL][SLOT] */ u8 populated_ranks[2][2][2]; /* [CHANNEL][SLOT][RANK] */ int rank_start[2][2][2]; u8 cas_latency; @@ -199,7 +197,7 @@ u8 revision; u8 max_supported_clock_speed_index; u8 uma_enabled; - u8 spd[2][2][151]; /* [CHANNEL][SLOT][BYTE] */ + u8 spd[2][2][151]; /* [CHANNEL][SLOT][BYTE] */ u8 silicon_revision; u8 populated_ranks_mask[2]; u8 max_slots_used_in_channel; @@ -230,13 +228,10 @@ /* Global allocation of timings_car */ timing_bounds_t timings_car[64];
-static void -write_500(struct raminfo *info, int channel, u32 val, u16 addr, int bits, - int flag); +static void write_500(struct raminfo *info, int channel, u32 val, u16 addr, int bits, int flag);
/* OK */ -static u16 -read_500(struct raminfo *info, int channel, u16 addr, int split) +static u16 read_500(struct raminfo *info, int channel, u16 addr, int split) { u32 val; info->last_500_command[channel] = 0x80000000; @@ -244,8 +239,7 @@ while (MCHBAR32(0x500 + (channel << 10)) & 0x800000) ; MCHBAR32(0x500 + (channel << 10)) = - 0x80000000 | (((MCHBAR8(0x246 + (channel << 10)) >> 2) & 3) - + 0xb88 - addr); + 0x80000000 | (((MCHBAR8(0x246 + (channel << 10)) >> 2) & 3) + 0xb88 - addr); while (MCHBAR32(0x500 + (channel << 10)) & 0x800000) ; val = MCHBAR32(0x508 + (channel << 10)); @@ -253,9 +247,7 @@ }
/* OK */ -static void -write_500(struct raminfo *info, int channel, u32 val, u16 addr, int bits, - int flag) +static void write_500(struct raminfo *info, int channel, u32 val, u16 addr, int bits, int flag) { if (info->last_500_command[channel] == 0x80000000) { info->last_500_command[channel] = 0x40000000; @@ -311,20 +303,16 @@ return ok; }
-static void -program_timings(struct raminfo *info, u16 base, int channel, int slot, int rank) +static void program_timings(struct raminfo *info, u16 base, int channel, int slot, int rank) { int lane; for (lane = 0; lane < 8; lane++) { - write_500(info, channel, - base + - info->training. - lane_timings[2][channel][slot][rank][lane], + write_500(info, channel, base + + info->training.lane_timings[2][channel][slot][rank][lane], get_timing_register_addr(lane, 2, slot, rank), 9, 0); - write_500(info, channel, - base + - info->training. - lane_timings[3][channel][slot][rank][lane], + + write_500(info, channel, base + + info->training.lane_timings[3][channel][slot][rank][lane], get_timing_register_addr(lane, 3, slot, rank), 9, 0); } } @@ -365,31 +353,21 @@ for (i = 0; i < 2; i++) for (lane = 0; lane < 8; lane++) write_500(info, channel, - info->training.lane_timings[i + - 1][channel][slot] - [rank][lane], get_timing_register_addr(lane, - i + 1, - slot, - rank), - 9, 0); + info->training.lane_timings[i + 1][channel][slot][rank][lane], + get_timing_register_addr(lane, i + 1, slot, rank), 9, 0);
write_1d0(1, 0x103, 6, 1); for (lane = 0; lane < 8; lane++) write_500(info, channel, - info->training. - lane_timings[0][channel][slot][rank][lane], + info->training.lane_timings[0][channel][slot][rank][lane], get_timing_register_addr(lane, 0, slot, rank), 9, 0);
for (i = 0; i < 2; i++) { for (lane = 0; lane < 8; lane++) write_500(info, channel, - info->training.lane_timings[i + - 1][channel][slot] - [rank][lane], get_timing_register_addr(lane, - i + 1, - slot, - rank), - 9, 0); + info->training.lane_timings[i + 1][channel][slot][rank][lane], + get_timing_register_addr(lane, i + 1, slot, rank), 9, 0); + gav(get_580(channel, ((i + 1) << 2) | (rank << 5))); }
@@ -398,14 +376,15 @@ MCHBAR8(0x5ff) = 0x80; write_1d0(0x2, 0x142, 3, 1); for (lane = 0; lane < 8; lane++) { - // printk (BIOS_ERR, "before: %x\n", info->training.lane_timings[2][channel][slot][rank][lane]); +// printk(BIOS_ERR, "before: %x\n", +// info->training.lane_timings[2][channel][slot][rank][lane]); info->training.lane_timings[2][channel][slot][rank][lane] = - read_500(info, channel, - get_timing_register_addr(lane, 2, slot, rank), 9); - //printk (BIOS_ERR, "after: %x\n", info->training.lane_timings[2][channel][slot][rank][lane]); + read_500(info, channel, get_timing_register_addr(lane, 2, slot, rank), 9); + +// printk(BIOS_ERR, "after: %x\n", +// info->training.lane_timings[2][channel][slot][rank][lane]); info->training.lane_timings[3][channel][slot][rank][lane] = - info->training.lane_timings[2][channel][slot][rank][lane] + - 0x20; + info->training.lane_timings[2][channel][slot][rank][lane] + 0x20; } }
@@ -419,8 +398,7 @@ return res; }
-static void -config_rank(struct raminfo *info, int s3resume, int channel, int slot, int rank) +static void config_rank(struct raminfo *info, int s3resume, int channel, int slot, int rank) { int add;
@@ -478,23 +456,19 @@ c = 0x5f5f;
for (k = 0; k < 2; k++) { - MCHBAR32(0x138 + 8 * k) = - (channel << 26) | (j << 24); + MCHBAR32(0x138 + 8 * k) = (channel << 26) | (j << 24); gav(vd8[1][(channel << 3) | (j << 1) | k] = - MCHBAR32(0x138 + 8 * k)); + MCHBAR32(0x138 + 8 * k)); gav(vd8[0][(channel << 3) | (j << 1) | k] = - MCHBAR32(0x13c + 8 * k)); + MCHBAR32(0x13c + 8 * k)); }
- MCHBAR32(0x334 + (channel << 10) + (j * 0x44)) = - zero ? 0 : val3[j]; + MCHBAR32(0x334 + (channel << 10) + (j * 0x44)) = zero ? 0 : val3[j]; MCHBAR32(0x32c + (channel << 10) + (j * 0x44)) = zero ? 0 : (0x18191819 & lmask); MCHBAR16(0x34a + (channel << 10) + (j * 0x44)) = c; - MCHBAR32(0x33c + (channel << 10) + (j * 0x44)) = - zero ? 0 : (a & lmask); - MCHBAR32(0x344 + (channel << 10) + (j * 0x44)) = - zero ? 0 : (a & lmask); + MCHBAR32(0x33c + (channel << 10) + (j * 0x44)) = zero ? 0 : (a & lmask); + MCHBAR32(0x344 + (channel << 10) + (j * 0x44)) = zero ? 0 : (a & lmask); } }
@@ -562,13 +536,9 @@ for (channel = 0; channel < NUM_CHANNELS; channel++) for (slot = 0; slot < NUM_SLOTS; slot++) if (info->populated_ranks[channel][slot][0]) - supported_cas_latencies &= - 2 * - (info-> - spd[channel][slot][CAS_LATENCIES_LSB] | - (info-> - spd[channel][slot][CAS_LATENCIES_MSB] << - 8)); + supported_cas_latencies &= 2 * + (info->spd[channel][slot][CAS_LATENCIES_LSB] | + (info->spd[channel][slot][CAS_LATENCIES_MSB] << 8));
max_clock_index = MIN(3, info->max_supported_clock_speed_index);
@@ -578,24 +548,20 @@ for (channel = 0; channel < NUM_CHANNELS; channel++) for (slot = 0; slot < NUM_SLOTS; slot++) if (info->populated_ranks[channel][slot][0]) { - unsigned int timebase; - timebase = - 1000 * - info-> - spd[channel][slot][TIMEBASE_DIVIDEND] / - info->spd[channel][slot][TIMEBASE_DIVISOR]; - cycletime = - MAX(cycletime, - timebase * + unsigned int timebase = 1000 + * info->spd[channel][slot][TIMEBASE_DIVIDEND] + / info->spd[channel][slot][TIMEBASE_DIVISOR]; + + cycletime = MAX(cycletime, timebase * info->spd[channel][slot][CYCLETIME]); - cas_latency_time = - MAX(cas_latency_time, - timebase * - info-> - spd[channel][slot][CAS_LATENCY_TIME]); + + cas_latency_time = MAX(cas_latency_time, timebase * + info->spd[channel][slot][CAS_LATENCY_TIME]); } + if (cycletime > min_cycletime[0]) die("RAM init: Decoded SPD DRAM freq is slower than the controller minimum!"); + for (clock_speed_index = 0; clock_speed_index < 3; clock_speed_index++) { if (cycletime == min_cycletime[clock_speed_index]) break; @@ -612,7 +578,7 @@ if (cas_latency <= min_cas_latency) break; supported_cas_latencies &= - ~(1 << find_highest_bit_set(supported_cas_latencies)); + ~(1 << find_highest_bit_set(supported_cas_latencies)); }
if (cas_latency != min_cas_latency && clock_speed_index) @@ -620,6 +586,7 @@
if (cas_latency * min_cycletime[clock_speed_index] > 20000) die("Couldn't configure DRAM"); + info->clock_speed_index = clock_speed_index; info->cas_latency = cas_latency; } @@ -635,139 +602,100 @@ if (info->silicon_revision == 0) for (channel = 0; channel < NUM_CHANNELS; channel++) for (slot = 0; slot < NUM_SLOTS; slot++) - if ((info-> - spd[channel][slot][MODULE_TYPE] & 0xF) == - 3) + if ((info->spd[channel][slot][MODULE_TYPE] & 0xf) == 3) extended_silicon_revision = 4;
for (channel = 0; channel < NUM_CHANNELS; channel++) { - for (slot = 0; slot < NUM_SLOTS; slot++) - for (rank = 0; rank < NUM_SLOTS; rank++) { - int card_timing_2; - if (!info->populated_ranks[channel][slot][rank]) - continue; + for (slot = 0; slot < NUM_SLOTS; slot++) { + for (rank = 0; rank < NUM_SLOTS; rank++) {
- for (lane = 0; lane < 9; lane++) { - int tm_reg; - int card_timing; + int card_timing_2; + if (!info->populated_ranks[channel][slot][rank]) + continue;
- card_timing = 0; - if ((info-> - spd[channel][slot][MODULE_TYPE] & - 0xF) == 3) { - int reference_card; - reference_card = - info-> - spd[channel][slot] - [REFERENCE_RAW_CARD_USED] & - 0x1f; - if (reference_card == 3) - card_timing = - u16_ffd1188[0][lane] - [info-> - clock_speed_index]; - if (reference_card == 5) - card_timing = - u16_ffd1188[1][lane] - [info-> - clock_speed_index]; - } + for (lane = 0; lane < 9; lane++) { + int tm_reg; + int card_timing;
- info->training. - lane_timings[0][channel][slot][rank] - [lane] = - u8_FFFD1218[info-> - clock_speed_index]; - info->training. - lane_timings[1][channel][slot][rank] - [lane] = 256; + card_timing = 0; + if ((info->spd[channel][slot][MODULE_TYPE] & 0xf) == 3) { + int reference_card = info->spd[channel][slot] + [REFERENCE_RAW_CARD_USED] & 0x1f;
- for (tm_reg = 2; tm_reg < 4; tm_reg++) - info->training. - lane_timings[tm_reg] - [channel][slot][rank][lane] - = - u8_FFFD1240[channel] - [extended_silicon_revision] - [lane][2 * slot + - rank][info-> - clock_speed_index] - + info->max4048[channel] - + - u8_FFFD0C78[channel] - [extended_silicon_revision] - [info-> - mode4030[channel]][slot] - [rank][info-> - clock_speed_index] - + card_timing; - for (tm_reg = 0; tm_reg < 4; tm_reg++) - write_500(info, channel, - info->training. - lane_timings[tm_reg] - [channel][slot][rank] - [lane], - get_timing_register_addr - (lane, tm_reg, slot, - rank), 9, 0); + if (reference_card == 3) + card_timing = + u16_ffd1188[0][lane][info->clock_speed_index]; + + if (reference_card == 5) + card_timing = + u16_ffd1188[1][lane][info->clock_speed_index]; }
- card_timing_2 = 0; - if (!(extended_silicon_revision != 4 - || (info-> - populated_ranks_mask[channel] & 5) == - 5)) { - if ((info-> - spd[channel][slot] - [REFERENCE_RAW_CARD_USED] & 0x1F) - == 3) - card_timing_2 = - u16_FFFE0EB8[0][info-> - clock_speed_index]; - if ((info-> - spd[channel][slot] - [REFERENCE_RAW_CARD_USED] & 0x1F) - == 5) - card_timing_2 = - u16_FFFE0EB8[1][info-> - clock_speed_index]; + info->training.lane_timings[0][channel][slot][rank][lane] = + u8_FFFD1218[info->clock_speed_index]; + + info->training.lane_timings[1][channel][slot][rank][lane] = 256; + + for (tm_reg = 2; tm_reg < 4; tm_reg++) { + info->training.lane_timings[tm_reg][channel][slot] + [rank][lane] + = + u8_FFFD1240[channel][extended_silicon_revision][lane] + [2 * slot + rank][info->clock_speed_index] + + + info->max4048[channel] + + + u8_FFFD0C78[channel][extended_silicon_revision] + [info->mode4030[channel]][slot][rank] + [info->clock_speed_index] + + + card_timing; }
- for (i = 0; i < 3; i++) - write_500(info, channel, - (card_timing_2 + - info->max4048[channel] - + - u8_FFFD0EF8[channel] - [extended_silicon_revision] - [info-> - mode4030[channel]][info-> - clock_speed_index]), - u16_fffd0c50[i][slot][rank], - 8, 1); - write_500(info, channel, - (info->max4048[channel] + - u8_FFFD0C78[channel] - [extended_silicon_revision][info-> - mode4030 - [channel]] - [slot][rank][info-> - clock_speed_index]), - u16_fffd0c70[slot][rank], 7, 1); + for (tm_reg = 0; tm_reg < 4; tm_reg++) + write_500( + info, channel, + info->training.lane_timings + [tm_reg][channel][slot][rank][lane], + get_timing_register_addr(lane, tm_reg, slot, rank), + 9, 0 + ); } + + card_timing_2 = 0; + if (!(extended_silicon_revision != 4 + || (info->populated_ranks_mask[channel] & 5) == 5)) { + + if ((info->spd[channel][slot][REFERENCE_RAW_CARD_USED] & 0x1F) + == 3) + card_timing_2 = + u16_FFFE0EB8[0][info->clock_speed_index]; + if ((info->spd[channel][slot][REFERENCE_RAW_CARD_USED] & 0x1F) + == 5) + card_timing_2 = + u16_FFFE0EB8[1][info->clock_speed_index]; + } + + for (i = 0; i < 3; i++) + write_500(info, channel, (card_timing_2 + info->max4048[channel] + + u8_FFFD0EF8[channel][extended_silicon_revision] + [info->mode4030[channel]][info->clock_speed_index]), + u16_fffd0c50[i][slot][rank], 8, 1); + + write_500(info, channel, (info->max4048[channel] + u8_FFFD0C78[channel] + [extended_silicon_revision][info->mode4030[channel]][slot][rank] + [info->clock_speed_index]), u16_fffd0c70[slot][rank], 7, 1); + + }} /* for each slot, rank */ if (!info->populated_ranks_mask[channel]) continue; + for (i = 0; i < 3; i++) - write_500(info, channel, - (info->max4048[channel] + - info->avg4044[channel] - + - u8_FFFD17E0[channel] - [extended_silicon_revision][info-> - mode4030 - [channel]][info-> - clock_speed_index]), - u16_fffd0c68[i], 8, 1); + write_500( + info, channel, (info->max4048[channel] + info->avg4044[channel] + + u8_FFFD17E0[channel][extended_silicon_revision][info->mode4030[channel]] + [info->clock_speed_index]), u16_fffd0c68[i], 8, 1 + ); } }
@@ -828,89 +756,106 @@ if (!info->silicon_revision) for (channel = 0; channel < NUM_CHANNELS; channel++) for (slot = 0; slot < NUM_SLOTS; slot++) - if ((info-> - spd[channel][slot][MODULE_TYPE] & 0xF) == - 3) + if ((info->spd[channel][slot][MODULE_TYPE] & 0xF) == 3) extended_silicon_revision = 4; + if (info->board_lane_delay[7] < 5) info->board_lane_delay[7] = 5; + info->revision_flag_1 = 2; if (info->silicon_revision == 2 || info->silicon_revision == 3) info->revision_flag_1 = 0; + if (info->revision < 16) info->revision_flag_1 = 0;
if (info->revision < 8) info->revision_flag_1 = 0; - if (info->revision >= 8 && (info->silicon_revision == 0 - || info->silicon_revision == 1)) + + if (info->revision >= 8 && + (info->silicon_revision == 0 || info->silicon_revision == 1)) some_delay_2_ps = 735; else some_delay_2_ps = 750;
- if (info->revision >= 0x10 && (info->silicon_revision == 0 - || info->silicon_revision == 1)) + if (info->revision >= 16 && + (info->silicon_revision == 0 || info->silicon_revision == 1)) some_delay_1_ps = 3929; else some_delay_1_ps = 3490;
some_delay_1_cycle_floor = some_delay_1_ps / cycle_ps(info); - some_delay_1_cycle_ceil = some_delay_1_ps / cycle_ps(info); + some_delay_1_cycle_ceil = some_delay_1_ps / cycle_ps(info); + if (some_delay_1_ps % cycle_ps(info)) some_delay_1_cycle_ceil++; else some_delay_1_cycle_floor--; + info->some_delay_1_cycle_floor = some_delay_1_cycle_floor; + if (info->revision_flag_1) some_delay_2_ps = halfcycle_ps(info) >> 6; - some_delay_2_ps += - MAX(some_delay_1_ps - 30, - 2 * halfcycle_ps(info) * (some_delay_1_cycle_ceil - 1) + 1000) + - 375; - some_delay_3_ps = - halfcycle_ps(info) - some_delay_2_ps % halfcycle_ps(info); + + some_delay_2_ps += MAX( + some_delay_1_ps - 30, + 2 * halfcycle_ps(info) * (some_delay_1_cycle_ceil - 1) + 1000 + ) + 375; + + some_delay_3_ps = halfcycle_ps(info) - some_delay_2_ps % halfcycle_ps(info); + if (info->revision_flag_1) { if (some_delay_3_ps >= 150) { const int some_delay_3_halfcycles = - (some_delay_3_ps << 6) / halfcycle_ps(info); + (some_delay_3_ps << 6) / halfcycle_ps(info); + some_delay_3_ps_rounded = - halfcycle_ps(info) * some_delay_3_halfcycles >> 6; + halfcycle_ps(info) * some_delay_3_halfcycles >> 6; } } some_delay_2_halfcycles_ceil = - (some_delay_2_ps + halfcycle_ps(info) - 1) / halfcycle_ps(info) - - 2 * (some_delay_1_cycle_ceil - 1); + (some_delay_2_ps + halfcycle_ps(info) - 1) / halfcycle_ps(info) - 2 * + (some_delay_1_cycle_ceil - 1); + if (info->revision_flag_1 && some_delay_3_ps < 150) some_delay_2_halfcycles_ceil++; + some_delay_2_halfcycles_floor = some_delay_2_halfcycles_ceil; - if (info->revision < 0x10) - some_delay_2_halfcycles_floor = - some_delay_2_halfcycles_ceil - 1; + + if (info->revision < 16) + some_delay_2_halfcycles_floor = some_delay_2_halfcycles_ceil - 1; + if (!info->revision_flag_1) some_delay_2_halfcycles_floor++; + info->some_delay_2_halfcycles_ceil = some_delay_2_halfcycles_ceil; + info->some_delay_3_ps_rounded = some_delay_3_ps_rounded; + if ((info->populated_ranks[0][0][0] && info->populated_ranks[0][1][0]) - || (info->populated_ranks[1][0][0] - && info->populated_ranks[1][1][0])) + || (info->populated_ranks[1][0][0] && info->populated_ranks[1][1][0])) info->max_slots_used_in_channel = 2; else info->max_slots_used_in_channel = 1; + for (channel = 0; channel < 2; channel++) - MCHBAR32(0x244 + (channel << 10)) = - ((info->revision < 8) ? 1 : 0x200) | - ((2 - info->max_slots_used_in_channel) << 17) | - (channel << 21) | + MCHBAR32(0x244 + (channel << 10)) = ((info->revision < 8) ? 1 : 0x200) | + ((2 - info->max_slots_used_in_channel) << 17) | (channel << 21) | (info->some_delay_1_cycle_floor << 18) | 0x9510; + if (info->max_slots_used_in_channel == 1) { info->mode4030[0] = (count_ranks_in_channel(info, 0) == 2); info->mode4030[1] = (count_ranks_in_channel(info, 1) == 2); } else { - info->mode4030[0] = ((count_ranks_in_channel(info, 0) == 1) || (count_ranks_in_channel(info, 0) == 2)) ? 2 : 3; /* 2 if 1 or 2 ranks */ - info->mode4030[1] = ((count_ranks_in_channel(info, 1) == 1) - || (count_ranks_in_channel(info, 1) == - 2)) ? 2 : 3; + /* 2 if 1 or 2 ranks, else 3 */ + info->mode4030[0] = + ((count_ranks_in_channel(info, 0) == 1) || + (count_ranks_in_channel(info, 0) == 2)) ? 2 : 3; + info->mode4030[1] = + ((count_ranks_in_channel(info, 1) == 1) || + (count_ranks_in_channel(info, 1) == 2)) ? 2 : 3; } + for (channel = 0; channel < NUM_CHANNELS; channel++) { int max_of_unk; int min_of_unk_2; @@ -928,84 +873,58 @@ count = 0; for (i = 0; i < 3; i++) { int unk1; + if (info->revision < 8) - unk1 = - u8_FFFD1891[0][channel][info-> - clock_speed_index] - [i]; - else if (! - (info->revision >= 0x10 - || info->revision_flag_1)) - unk1 = - u8_FFFD1891[1][channel][info-> - clock_speed_index] - [i]; + unk1 = u8_FFFD1891[0][channel][info->clock_speed_index][i]; + else if (!(info->revision >= 16 || info->revision_flag_1)) + unk1 = u8_FFFD1891[1][channel][info->clock_speed_index][i]; else unk1 = 0; - for (slot = 0; slot < NUM_SLOTS; slot++) - for (rank = 0; rank < NUM_RANKS; rank++) { - int a = 0; - int b = 0;
- if (!info-> - populated_ranks[channel][slot] - [rank]) - continue; - if (extended_silicon_revision == 4 - && (info-> - populated_ranks_mask[channel] & - 5) != 5) { - if ((info-> - spd[channel][slot] - [REFERENCE_RAW_CARD_USED] & - 0x1F) == 3) { - a = u16_ffd1178[0] - [info-> - clock_speed_index]; - b = u16_fe0eb8[0][info-> - clock_speed_index]; - } else - if ((info-> - spd[channel][slot] - [REFERENCE_RAW_CARD_USED] - & 0x1F) == 5) { - a = u16_ffd1178[1] - [info-> - clock_speed_index]; - b = u16_fe0eb8[1][info-> - clock_speed_index]; - } - } - min_of_unk_2 = MIN(min_of_unk_2, a); - min_of_unk_2 = MIN(min_of_unk_2, b); - if (rank == 0) { - sum += a; - count++; - } - { - int t; - t = b + - u8_FFFD0EF8[channel] - [extended_silicon_revision] - [info-> - mode4030[channel]][info-> - clock_speed_index]; - if (unk1 >= t) - max_of_unk = - MAX(max_of_unk, - unk1 - t); + for (slot = 0; slot < NUM_SLOTS; slot++) { + for (rank = 0; rank < NUM_RANKS; rank++) { + int a = 0; + int b = 0; + + if (!info->populated_ranks[channel][slot][rank]) + continue; + + if (extended_silicon_revision == 4 + && (info->populated_ranks_mask[channel] & 5) != 5) { + + if ((info->spd[channel][slot] + [REFERENCE_RAW_CARD_USED] & 0x1F) == 3) { + a = u16_ffd1178[0][info->clock_speed_index]; + b = u16_fe0eb8 [0][info->clock_speed_index]; + + } else if ((info->spd[channel][slot] + [REFERENCE_RAW_CARD_USED] & 0x1F) == 5) { + a = u16_ffd1178[1][info->clock_speed_index]; + b = u16_fe0eb8 [1][info->clock_speed_index]; } } - { - int t = - u8_FFFD17E0[channel] - [extended_silicon_revision][info-> - mode4030 - [channel]] - [info->clock_speed_index] + min_of_unk_2; + min_of_unk_2 = MIN(min_of_unk_2, a); + min_of_unk_2 = MIN(min_of_unk_2, b); + + if (rank == 0) { + sum += a; + count++; + } + + int t = b + u8_FFFD0EF8[channel][extended_silicon_revision] + [info->mode4030[channel]][info->clock_speed_index]; + if (unk1 >= t) max_of_unk = MAX(max_of_unk, unk1 - t); - } + + }} /* for each slot, rank */ + + int t = u8_FFFD17E0[channel][extended_silicon_revision] + [info->mode4030[channel]][info->clock_speed_index] + min_of_unk_2; + + if (unk1 >= t) + max_of_unk = MAX(max_of_unk, unk1 - t); + }
if (count == 0) @@ -1016,22 +935,19 @@ } }
-static void jedec_read(struct raminfo *info, - int channel, int slot, int rank, - int total_rank, u8 addr3, unsigned int value) +static void jedec_read(struct raminfo *info, int channel, int slot, int rank, int total_rank, + u8 addr3, unsigned int value) { /* Handle mirrored mapping. */ if ((rank & 1) && (info->spd[channel][slot][RANK1_ADDRESS_MAPPING] & 1)) - addr3 = (addr3 & 0xCF) | ((addr3 & 0x10) << 1) | - ((addr3 >> 1) & 0x10); + addr3 = (addr3 & 0xCF) | ((addr3 & 0x10) << 1) | ((addr3 >> 1) & 0x10); + MCHBAR8(0x271) = addr3 | (MCHBAR8(0x271) & 0xC1); MCHBAR8(0x671) = addr3 | (MCHBAR8(0x671) & 0xC1);
/* Handle mirrored mapping. */ if ((rank & 1) && (info->spd[channel][slot][RANK1_ADDRESS_MAPPING] & 1)) - value = - (value & ~0x1f8) | ((value >> 1) & 0xa8) | ((value & 0xa8) - << 1); + value = (value & ~0x1f8) | ((value >> 1) & 0xa8) | ((value & 0xa8) << 1);
read32p((value << 3) | (total_rank << 28));
@@ -1078,19 +994,15 @@ write_recovery = 6; } FOR_POPULATED_RANKS { - auto_self_refresh &= - (info->spd[channel][slot][THERMAL_AND_REFRESH] >> 2) & 1; - self_refresh_temperature &= - info->spd[channel][slot][THERMAL_AND_REFRESH] & 1; + auto_self_refresh &= (info->spd[channel][slot][THERMAL_AND_REFRESH] >> 2) & 1; + self_refresh_temperature &= info->spd[channel][slot][THERMAL_AND_REFRESH] & 1; } if (auto_self_refresh == 1) self_refresh_temperature = 0;
dll_on = ((info->silicon_revision != 2 && info->silicon_revision != 3) - || (info->populated_ranks[0][0][0] - && info->populated_ranks[0][1][0]) - || (info->populated_ranks[1][0][0] - && info->populated_ranks[1][1][0])); + || (info->populated_ranks[0][0][0] && info->populated_ranks[0][1][0]) + || (info->populated_ranks[1][0][0] && info->populated_ranks[1][1][0]));
total_rank = 0;
@@ -1123,31 +1035,28 @@ MCHBAR16(0x58e + (channel << 10)) = rzq_reg58e | 0x82; MCHBAR16(0x590 + (channel << 10)) = 0x1282;
- for (slot = 0; slot < NUM_SLOTS; slot++) - for (rank = 0; rank < NUM_RANKS; rank++) - if (info->populated_ranks[channel][slot][rank]) { - jedec_read(info, channel, slot, rank, - total_rank, 0x28, - rtt_wr | (info-> - clock_speed_index - << 3) - | (auto_self_refresh << 6) | - (self_refresh_temperature << - 7)); - jedec_read(info, channel, slot, rank, - total_rank, 0x38, 0); - jedec_read(info, channel, slot, rank, - total_rank, 0x18, - rtt | MR1_ODS34OHM); - jedec_read(info, channel, slot, rank, - total_rank, 6, - (dll_on << 12) | - (write_recovery << 9) - | ((info->cas_latency - 4) << - 4) | MR0_BT_INTERLEAVED | - MR0_DLL_RESET_ON); - total_rank++; - } + for (slot = 0; slot < NUM_SLOTS; slot++) { + for (rank = 0; rank < NUM_RANKS; rank++) { + if (info->populated_ranks[channel][slot][rank]) { + jedec_read(info, channel, slot, rank, total_rank, 0x28, + rtt_wr | (info->clock_speed_index << 3) | + (auto_self_refresh << 6) | (self_refresh_temperature << 7) + ); + + jedec_read(info, channel, slot, rank, total_rank, 0x38, 0); + + jedec_read(info, channel, slot, rank, total_rank, 0x18, + rtt | MR1_ODS34OHM + ); + + jedec_read(info, channel, slot, rank, total_rank, 6, + (dll_on << 12) | (write_recovery << 9) | + ((info->cas_latency - 4) << 4) | MR0_BT_INTERLEAVED | + MR0_DLL_RESET_ON + ); + + total_rank++; + }}} /* for each slot, rank, if populated */ } }
@@ -1159,15 +1068,12 @@
FOR_ALL_RANKS { if (info->populated_ranks[channel][slot][rank]) { - total_mb[channel] += - pre_jedec ? 256 : (256 << info-> - density[channel][slot] >> info-> - is_x16_module[channel][slot]); + total_mb[channel] += pre_jedec ? 256 : (256 << info->density[channel][slot] >> info->is_x16_module[channel][slot]); + MCHBAR8(0x208 + rank + 2 * slot + (channel << 10)) = - (pre_jedec ? (1 | ((1 + 1) << 1)) : - (info->is_x16_module[channel][slot] | - ((info->density[channel][slot] + 1) << 1))) | - 0x80; + (pre_jedec ? (1 | ((1 + 1) << 1)) + : (info->is_x16_module[channel][slot] | + ((info->density[channel][slot] + 1) << 1))) | 0x80; } MCHBAR16(0x200 + (channel << 10) + 4 * slot + 2 * rank) = total_mb[channel] >> 6; @@ -1175,13 +1081,14 @@
info->total_memory_mb = total_mb[0] + total_mb[1];
- info->interleaved_part_mb = - pre_jedec ? 0 : 2 * MIN(total_mb[0], total_mb[1]); - info->non_interleaved_part_mb = - total_mb[0] + total_mb[1] - info->interleaved_part_mb; + info->interleaved_part_mb = pre_jedec ? 0 : 2 * MIN(total_mb[0], total_mb[1]); + + info->non_interleaved_part_mb = total_mb[0] + total_mb[1] - info->interleaved_part_mb; + channel_0_non_interleaved = total_mb[0] - info->interleaved_part_mb / 2; - MCHBAR32(0x100) = channel_0_non_interleaved | - (info->non_interleaved_part_mb << 16); + + MCHBAR32(0x100) = channel_0_non_interleaved | (info->non_interleaved_part_mb << 16); + if (!pre_jedec) MCHBAR16(0x104) = info->interleaved_part_mb; } @@ -1200,103 +1107,98 @@ high_multiplier = 0; some_delay_ns = 200; some_delay_3_half_cycles = 4; - cas_latency_shift = info->silicon_revision == 0 - || info->silicon_revision == 1 ? 1 : 0; + cas_latency_shift = info->silicon_revision == 0 || info->silicon_revision == 1 ? 1 : 0; + if (info->revision < 8) { some_delay_ns = 600; cas_latency_shift = 0; } - { - int speed_bit; - speed_bit = - ((info->clock_speed_index > 1 - || (info->silicon_revision != 2 - && info->silicon_revision != 3))) ^ (info->revision >= - 0x10); - write_500(info, 0, speed_bit | ((!info->use_ecc) << 1), 0x60e, - 3, 1); - write_500(info, 1, speed_bit | ((!info->use_ecc) << 1), 0x60e, - 3, 1); - if (info->revision >= 0x10 && info->clock_speed_index <= 1 - && (info->silicon_revision == 2 - || info->silicon_revision == 3)) - rmw_1d0(0x116, 5, 2, 4, 1); - } - MCHBAR32(0x120) = (1 << (info->max_slots_used_in_channel + 28)) | - 0x188e7f9f;
- MCHBAR8(0x124) = info->board_lane_delay[4] + - ((frequency_01(info) + 999) / 1000); + int speed_bit = ((info->clock_speed_index > 1 || (info->silicon_revision != 2 && + info->silicon_revision != 3))) ^ (info->revision >= 16); + + write_500(info, 0, speed_bit | ((!info->use_ecc) << 1), 0x60e, 3, 1); + write_500(info, 1, speed_bit | ((!info->use_ecc) << 1), 0x60e, 3, 1); + + if (info->revision >= 16 && info->clock_speed_index <= 1 && + (info->silicon_revision == 2 || info->silicon_revision == 3)) { + rmw_1d0(0x116, 5, 2, 4, 1); + } + + MCHBAR32(0x120) = (1 << (info->max_slots_used_in_channel + 28)) | 0x188e7f9f; + MCHBAR8(0x124) = info->board_lane_delay[4] + ((frequency_01(info) + 999) / 1000); MCHBAR16(0x125) = 0x1360; - MCHBAR8(0x127) = 0x40; + MCHBAR8(0x127) = 0x40; if (info->fsb_frequency < frequency_11(info) / 2) { unsigned int some_delay_2_half_cycles; high_multiplier = 1; - some_delay_2_half_cycles = ps_to_halfcycles(info, - ((3 * - fsbcycle_ps(info)) - >> 1) + - (halfcycle_ps(info) - * - reg178_min[info-> - clock_speed_index] - >> 6) - + - 4 * - halfcycle_ps(info) - + 2230); - some_delay_3_half_cycles = - MIN((some_delay_2_half_cycles + - (frequency_11(info) * 2) * (28 - - some_delay_2_half_cycles) / - (frequency_11(info) * 2 - - 4 * (info->fsb_frequency))) >> 3, 7); + some_delay_2_half_cycles = ps_to_halfcycles(info, ( + (3 * fsbcycle_ps(info)) >> 1) + + + (halfcycle_ps(info) * reg178_min[info->clock_speed_index] >> 6) + + + 4 * halfcycle_ps(info) + 2230 + ); + + some_delay_3_half_cycles = MIN( + (some_delay_2_half_cycles + (frequency_11(info) * 2) + * + (28 - some_delay_2_half_cycles) / (frequency_11(info) * 2 + - + 4 * (info->fsb_frequency))) >> 3, + 7); } if (MCHBAR8(0x2ca9) & 1) some_delay_3_half_cycles = 3; + for (channel = 0; channel < NUM_CHANNELS; channel++) { MCHBAR32_OR(0x220 + (channel << 10), 0x18001117); MCHBAR32(0x224 + (channel << 10)) = - (info->max_slots_used_in_channel - 1) | - ((info->cas_latency - 5 - info->clock_speed_index) - << 21) | ((info->max_slots_used_in_channel + - info->cas_latency - cas_latency_shift - 4) << 16) | + ((info->max_slots_used_in_channel - 1) | + ((info->cas_latency - 5 - info->clock_speed_index) << 21) | + ((info->max_slots_used_in_channel + + info->cas_latency - cas_latency_shift - 4) << 16) | ((info->cas_latency - cas_latency_shift - 4) << 26) | - ((info->cas_latency - info->clock_speed_index + - info->max_slots_used_in_channel - 6) << 8); - MCHBAR32(0x228 + (channel << 10)) = - info->max_slots_used_in_channel; - MCHBAR8(0x239 + (channel << 10)) = 32; - MCHBAR32(0x248 + (channel << 10)) = (high_multiplier << 24) | - (some_delay_3_half_cycles << 25) | 0x840000; + ((info->cas_latency - info->clock_speed_index + + info->max_slots_used_in_channel - 6) << 8) + ); + + MCHBAR32(0x228 + (channel << 10)) = info->max_slots_used_in_channel; + MCHBAR8(0x239 + (channel << 10)) = 32; + MCHBAR32(0x248 + (channel << 10)) = + (high_multiplier << 24) | (some_delay_3_half_cycles << 25) | 0x840000; + MCHBAR32(0x278 + (channel << 10)) = 0xc362042; MCHBAR32(0x27c + (channel << 10)) = 0x8b000062; MCHBAR32(0x24c + (channel << 10)) = - ((!!info->clock_speed_index) << 17) | - (((2 + info->clock_speed_index - + ((!!info->clock_speed_index) << 17) | (((2 + info->clock_speed_index - (!!info->clock_speed_index))) << 12) | 0x10200;
- MCHBAR8(0x267 + (channel << 10)) = 0x4; + MCHBAR8(0x267 + (channel << 10)) = 0x4; MCHBAR16(0x272 + (channel << 10)) = 0x155; - MCHBAR32_AND_OR(0x2bc + (channel << 10), 0xFF000000, 0x707070); + MCHBAR32_AND_OR(0x2bc + (channel << 10), 0xff000000, 0x707070);
- write_500(info, channel, - ((!info->populated_ranks[channel][1][1]) - | (!info->populated_ranks[channel][1][0] << 1) - | (!info->populated_ranks[channel][0][1] << 2) - | (!info->populated_ranks[channel][0][0] << 3)), - 0x4c9, 4, 1); + write_500(info, channel, ( + (!info->populated_ranks[channel][1][1]) | + (!info->populated_ranks[channel][1][0] << 1) | + (!info->populated_ranks[channel][0][1] << 2) | + (!info->populated_ranks[channel][0][0] << 3) + ), 0x4c9, 4, 1); }
MCHBAR8(0x2c4) = ((1 + (info->clock_speed_index != 0)) << 6) | 0xC; { u8 freq_divisor = 2; + if (info->fsb_frequency == frequency_11(info)) freq_divisor = 3; + else if (2 * info->fsb_frequency < 3 * (frequency_11(info) / 2)) freq_divisor = 1; + else freq_divisor = 2; + MCHBAR32(0x2c0) = (freq_divisor << 11) | 0x6009c400; }
@@ -1308,61 +1210,65 @@ } else { lane_3_delay = 12; } + cas_latency_derived = info->cas_latency - info->clock_speed_index + 2; + if (info->clock_speed_index > 1) cas_latency_derived++; + for (channel = 0; channel < NUM_CHANNELS; channel++) { MCHBAR32(0x240 + (channel << 10)) = - ((info->clock_speed_index == 0) * 0x11000) | - 0x1002100 | ((2 + info->clock_speed_index) << 4) | - (info->cas_latency - 3); - write_500(info, channel, (info->clock_speed_index << 1) | 1, - 0x609, 6, 1); + ((info->clock_speed_index == 0) * 0x11000) | 0x1002100 | + ((2 + info->clock_speed_index) << 4) | (info->cas_latency - 3); + + write_500(info, channel, (info->clock_speed_index << 1) | 1, 0x609, 6, 1); write_500(info, channel, - info->clock_speed_index + 2 * info->cas_latency - 7, - 0x601, 6, 1); + info->clock_speed_index + 2 * info->cas_latency - 7, 0x601, 6, 1);
MCHBAR32(0x250 + (channel << 10)) = ((lane_3_delay + info->clock_speed_index + 9) << 6) | - (info->board_lane_delay[7] << 2) | + (info->board_lane_delay[7] << 2) | (info->board_lane_delay[4] << 16) | (info->board_lane_delay[1] << 25) | (info->board_lane_delay[1] << 29) | 1; - MCHBAR32(0x254 + (channel << 10)) = - (info->board_lane_delay[1] >> 3) | - ((info->board_lane_delay[8] + 4 * info->use_ecc) << 6) | - 0x80 | (info->board_lane_delay[6] << 1) | - (info->board_lane_delay[2] << 28) | + + MCHBAR32(0x254 + (channel << 10)) = (info->board_lane_delay[1] >> 3) | + ((info->board_lane_delay[8] + 4 * info->use_ecc) << 6) | 0x80 | + (info->board_lane_delay[6] << 1) | (info->board_lane_delay[2] << 28) | (cas_latency_derived << 16) | 0x4700000; + MCHBAR32(0x258 + (channel << 10)) = - ((info->board_lane_delay[5] + info->clock_speed_index + - 9) << 12) | ((info->clock_speed_index - - info->cas_latency + 12) << 8) | + ((info->board_lane_delay[5] + info->clock_speed_index + 9) << 12) | + ((info->clock_speed_index - info->cas_latency + 12) << 8) | (info->board_lane_delay[2] << 17) | (info->board_lane_delay[4] << 24) | 0x47; + MCHBAR32(0x25c + (channel << 10)) = (info->board_lane_delay[1] << 1) | (info->board_lane_delay[0] << 8) | 0x1da50000; + MCHBAR8(0x264 + (channel << 10)) = 0xff; - MCHBAR8(0x5f8 + (channel << 10)) = - (cas_latency_shift << 3) | info->use_ecc; + MCHBAR8(0x5f8 + (channel << 10)) = (cas_latency_shift << 3) | info->use_ecc; }
program_modules_memory_map(info, 1);
- MCHBAR16(0x610) = (MIN(ns_to_cycles(info, some_delay_ns) / 2, 127) << 9) - | (MCHBAR16(0x610) & 0x1C3) | 0x3C; + MCHBAR16(0x610) = (MIN(ns_to_cycles(info, some_delay_ns) / 2, 127) << 9) | + (MCHBAR16(0x610) & 0x1c3) | 0x3c; + MCHBAR16_OR(0x612, 0x100); - MCHBAR16_OR(0x214, 0x3E00); + MCHBAR16_OR(0x214, 0x3e00); + for (i = 0; i < 8; i++) { pci_write_config32(PCI_DEV (QUICKPATH_BUS, 0, 1), 0x80 + 4 * i, - (info->total_memory_mb - 64) | !i | 2); + (info->total_memory_mb - 64) | !i | 2); + pci_write_config32(PCI_DEV (QUICKPATH_BUS, 0, 1), 0xc0 + 4 * i, 0); } }
-#define DEFAULT_PCI_MMIO_SIZE 2048 -#define HOST_BRIDGE PCI_DEVFN(0, 0) +#define DEFAULT_PCI_MMIO_SIZE 2048 +#define HOST_BRIDGE PCI_DEVFN(0, 0)
static unsigned int get_mmio_size(void) { @@ -1380,38 +1286,37 @@ return cfg->pci_mmio_size; }
-#define BETTER_MEMORY_MAP 0 - static void program_total_memory_map(struct raminfo *info) { unsigned int TOM, TOLUD, TOUUD; unsigned int quickpath_reserved; - unsigned int REMAPbase; + unsigned int remapbase; unsigned int uma_base_igd; unsigned int uma_base_gtt; unsigned int mmio_size; - int memory_remap; unsigned int memory_map[8]; - int i; unsigned int current_limit; unsigned int tseg_base; - int uma_size_igd = 0, uma_size_gtt = 0; + int uma_size_igd = 0; + int uma_size_gtt = 0; + int memory_remap; + int i;
memset(memory_map, 0, sizeof(memory_map));
if (info->uma_enabled) { - u16 t = pci_read_config16(NORTHBRIDGE, D0F0_GGC); - gav(t); - const int uma_sizes_gtt[16] = - { 0, 1, 0, 2, 0, 0, 0, 0, 0, 2, 3, 4, 42, 42, 42, 42 }; - /* Igd memory */ - const int uma_sizes_igd[16] = { - 0, 0, 0, 0, 0, 32, 48, 64, 128, 256, 96, 160, 224, 352, - 256, 512 - }; + u16 ggc_val = pci_read_config16(NORTHBRIDGE, D0F0_GGC); + gav(ggc_val);
- uma_size_igd = uma_sizes_igd[(t >> 4) & 0xF]; - uma_size_gtt = uma_sizes_gtt[(t >> 8) & 0xF]; + const int uma_sizes_gtt[16] = + {0, 1, 0, 2, 0, 0, 0, 0, 0, 2, 3, 4, 42, 42, 42, 42}; + + /* IGD memory */ + const int uma_sizes_igd[16] = + {0, 0, 0, 0, 0, 32, 48, 64, 128, 256, 96, 160, 224, 352, 256, 512}; + + uma_size_igd = uma_sizes_igd[(ggc_val >> 4) & 0xF]; + uma_size_gtt = uma_sizes_gtt[(ggc_val >> 8) & 0xF]; }
mmio_size = get_mmio_size(); @@ -1419,17 +1324,23 @@ TOM = info->total_memory_mb; if (TOM == 4096) TOM = 4032; + TOUUD = ALIGN_DOWN(TOM - info->memory_reserved_for_heci_mb, 64); - TOLUD = ALIGN_DOWN(MIN(4096 - mmio_size + ALIGN_UP(uma_size_igd + uma_size_gtt, 64) - , TOUUD), 64); + TOLUD = ALIGN_DOWN(MIN( + 4096 - mmio_size + ALIGN_UP(uma_size_igd + uma_size_gtt, 64), TOUUD), + 64 + ); + memory_remap = 0; if (TOUUD - TOLUD > 64) { memory_remap = 1; - REMAPbase = MAX(4096, TOUUD); + remapbase = MAX(4096, TOUUD); TOUUD = TOUUD - TOLUD + 4096; } + if (TOUUD > 4096) memory_map[2] = TOUUD | 1; + quickpath_reserved = 0;
u32 t = pci_read_config32(PCI_DEV(QUICKPATH_BUS, 0, 1), 0x68); @@ -1440,6 +1351,7 @@ u32 shift = t >> 20; if (shift == 0) die("Quickpath value is 0\n"); + quickpath_reserved = (u32)1 << find_lowest_bit_set32(shift); }
@@ -1449,32 +1361,40 @@ uma_base_igd = TOLUD - uma_size_igd; uma_base_gtt = uma_base_igd - uma_size_gtt; tseg_base = ALIGN_DOWN(uma_base_gtt, 64) - (CONFIG_SMM_TSEG_SIZE >> 20); + if (!memory_remap) tseg_base -= quickpath_reserved; + tseg_base = ALIGN_DOWN(tseg_base, 8);
pci_write_config16(NORTHBRIDGE, D0F0_TOLUD, TOLUD << 4); pci_write_config16(NORTHBRIDGE, D0F0_TOM, TOM >> 6); + if (memory_remap) { - pci_write_config16(NORTHBRIDGE, D0F0_REMAPBASE, REMAPbase >> 6); + pci_write_config16(NORTHBRIDGE, D0F0_REMAPBASE, remapbase >> 6); pci_write_config16(NORTHBRIDGE, D0F0_REMAPLIMIT, (TOUUD - 64) >> 6); } + pci_write_config16(NORTHBRIDGE, D0F0_TOUUD, TOUUD);
if (info->uma_enabled) { pci_write_config32(NORTHBRIDGE, D0F0_IGD_BASE, uma_base_igd << 20); pci_write_config32(NORTHBRIDGE, D0F0_GTT_BASE, uma_base_gtt << 20); } + pci_write_config32(NORTHBRIDGE, TSEG, tseg_base << 20);
current_limit = 0; + memory_map[0] = ALIGN_DOWN(uma_base_gtt, 64) | 1; memory_map[1] = 4096; + for (i = 0; i < ARRAY_SIZE(memory_map); i++) { current_limit = MAX(current_limit, memory_map[i] & ~1); + pci_write_config32(PCI_DEV(QUICKPATH_BUS, 0, 1), 4 * i + 0x80, - (memory_map[i] & 1) | ALIGN_DOWN(current_limit - - 1, 64) | 2); + (memory_map[i] & 1) | ALIGN_DOWN(current_limit - 1, 64) | 2); + pci_write_config32(PCI_DEV(QUICKPATH_BUS, 0, 1), 4 * i + 0xc0, 0); } } @@ -1490,8 +1410,8 @@ ;
if (!info->heci_bar) - gav(info->heci_bar = - pci_read_config32(HECIDEV, HECIBAR) & 0xFFFFFFF8); + gav(info->heci_bar = pci_read_config32(HECIDEV, HECIBAR) & 0xFFFFFFF8); + if (!info->memory_reserved_for_heci_mb) { /* Wait for ME to be ready */ intel_early_me_init(); @@ -1499,26 +1419,30 @@ }
for (i = 0; i < 3; i++) - gav(capid0[i] = - pci_read_config32(NORTHBRIDGE, D0F0_CAPID0 | (i << 2))); + gav(capid0[i] = pci_read_config32(NORTHBRIDGE, D0F0_CAPID0 | (i << 2))); + gav(info->revision = pci_read_config8(NORTHBRIDGE, PCI_REVISION_ID)); + info->max_supported_clock_speed_index = (~capid0[1] & 7);
if ((capid0[1] >> 11) & 1) info->uma_enabled = 0; else - gav(info->uma_enabled = - pci_read_config8(NORTHBRIDGE, D0F0_DEVEN) & 8); - /* Unrecognised: [0000:fffd3d2d] 37f81.37f82 ! CPUID: eax: 00000001; ecx: 00000e00 => 00020655.00010800.029ae3ff.bfebfbff */ + gav(info->uma_enabled = pci_read_config8(NORTHBRIDGE, D0F0_DEVEN) & 8); + + /* + * Unrecognised: [0000:fffd3d2d] 37f81.37f82! + * CPUID: eax: 00000001; ecx: 00000e00 => 00020655.00010800.029ae3ff.bfebfbff + */ info->silicon_revision = 0;
if (capid0[2] & 2) { info->silicon_revision = 0; info->max_supported_clock_speed_index = 2; + for (channel = 0; channel < NUM_CHANNELS; channel++) if (info->populated_ranks[channel][0][0] - && (info->spd[channel][0][MODULE_TYPE] & 0xf) == - 3) { + && (info->spd[channel][0][MODULE_TYPE] & 0xf) == 3) { info->silicon_revision = 2; info->max_supported_clock_speed_index = 1; } @@ -1535,6 +1459,7 @@ info->silicon_revision = 2; break; } + switch (pci_read_config16(NORTHBRIDGE, PCI_DEVICE_ID)) { case 0x40: info->silicon_revision = 0; @@ -1549,23 +1474,22 @@ static void write_training_data(struct raminfo *info) { int tm, channel, slot, rank, lane; + if (info->revision < 8) return;
- for (tm = 0; tm < 4; tm++) - for (channel = 0; channel < NUM_CHANNELS; channel++) - for (slot = 0; slot < NUM_SLOTS; slot++) - for (rank = 0; rank < NUM_RANKS; rank++) - for (lane = 0; lane < 9; lane++) - write_500(info, channel, - info-> - cached_training-> - lane_timings[tm] - [channel][slot][rank] - [lane], - get_timing_register_addr - (lane, tm, slot, - rank), 9, 0); + for (tm = 0; tm < 4; tm++) { + for (channel = 0; channel < NUM_CHANNELS; channel++) { + for (slot = 0; slot < NUM_SLOTS; slot++) { + for (rank = 0; rank < NUM_RANKS; rank++) { + for (lane = 0; lane < 9; lane++) { + + write_500(info, channel, + info->cached_training->lane_timings[tm][channel][slot][rank][lane], + get_timing_register_addr(lane, tm, slot, rank), 9, 0); + }}}}} /* for each tm, channel, slot, rank, lane */ + + write_1d0(info->cached_training->reg_178, 0x178, 7, 1); write_1d0(info->cached_training->reg_10b, 0x10b, 6, 1); } @@ -1575,56 +1499,52 @@ int channel, slot, rank, lane, i; printk(RAM_SPEW, "Timings:\n"); FOR_POPULATED_RANKS { - printk(RAM_SPEW, "channel %d, slot %d, rank %d\n", channel, - slot, rank); + printk(RAM_SPEW, "channel %d, slot %d, rank %d\n", channel, slot, rank); + for (lane = 0; lane < 9; lane++) { printk(RAM_SPEW, "lane %d: ", lane); for (i = 0; i < 4; i++) { - printk(RAM_SPEW, "%x (%x) ", - read_500(info, channel, - get_timing_register_addr - (lane, i, slot, rank), - 9), - info->training. - lane_timings[i][channel][slot][rank] - [lane]); + printk(RAM_SPEW, "%x (%x) ", read_500(info, channel, + get_timing_register_addr(lane, i, slot, rank), 9), + info->training.lane_timings[i][channel][slot][rank][lane]); } printk(RAM_SPEW, "\n"); } } - printk(RAM_SPEW, "[178] = %x (%x)\n", read_1d0(0x178, 7), - info->training.reg_178); - printk(RAM_SPEW, "[10b] = %x (%x)\n", read_1d0(0x10b, 6), - info->training.reg_10b); + printk(RAM_SPEW, "[178] = %x (%x)\n", read_1d0(0x178, 7), info->training.reg_178); + printk(RAM_SPEW, "[10b] = %x (%x)\n", read_1d0(0x10b, 6), info->training.reg_10b); }
-/* Read timings and other registers that need to be restored verbatim and - put them to CBMEM. - */ +/* Read timings and other registers that need to be restored verbatim into CBMEM. */ static void save_timings(struct raminfo *info) { struct ram_training train; int channel, slot, rank, lane, i;
train = info->training; - FOR_POPULATED_RANKS for (lane = 0; lane < 9; lane++) - for (i = 0; i < 4; i++) - train.lane_timings[i][channel][slot][rank][lane] = - read_500(info, channel, - get_timing_register_addr(lane, i, slot, - rank), 9); + + FOR_POPULATED_RANKS { + for (lane = 0; lane < 9; lane++) { + for (i = 0; i < 4; i++) { + train.lane_timings[i][channel][slot][rank][lane] + = + read_500(info, channel, get_timing_register_addr(lane, i, slot, rank), 9); + }}} /* for each populated rank, lane, i */ + train.reg_178 = read_1d0(0x178, 7); train.reg_10b = read_1d0(0x10b, 6);
for (channel = 0; channel < NUM_CHANNELS; channel++) { - u32 reg32; - reg32 = MCHBAR32((channel << 10) + 0x274); + + u32 reg32 = MCHBAR32((channel << 10) + 0x274); + train.reg274265[channel][0] = reg32 >> 16; train.reg274265[channel][1] = reg32 & 0xffff; - train.reg274265[channel][2] = - MCHBAR16((channel << 10) + 0x265) >> 8; + train.reg274265[channel][2] = MCHBAR16((channel << 10) + 0x265) >> 8; } + train.reg2ca9_bit0 = MCHBAR8(0x2ca9) & 1; + train.reg_6dc = MCHBAR32(0x6dc); train.reg_6e8 = MCHBAR32(0x6e8);
@@ -1632,29 +1552,28 @@ printk(RAM_SPEW, "[6e8] = %x\n", train.reg_6e8);
/* Save the MRC S3 restore data to cbmem */ - mrc_cache_stash_data(MRC_TRAINING_DATA, MRC_CACHE_VERSION, - &train, sizeof(train)); + mrc_cache_stash_data(MRC_TRAINING_DATA, MRC_CACHE_VERSION, &train, sizeof(train)); }
static const struct ram_training *get_cached_training(void) { struct region_device rdev; - if (mrc_cache_get_current(MRC_TRAINING_DATA, MRC_CACHE_VERSION, - &rdev)) + if (mrc_cache_get_current(MRC_TRAINING_DATA, MRC_CACHE_VERSION, &rdev)) return 0; + return (void *)rdev_mmap_full(&rdev); }
-/* FIXME: add timeout. */ +/* FIXME: add timeout. */ static void wait_heci_ready(void) { while (!(read32(DEFAULT_HECIBAR + 0xc) & 8)) // = 0x8000000c ; - write32((DEFAULT_HECIBAR + 0x4), - (read32(DEFAULT_HECIBAR + 0x4) & ~0x10) | 0xc); + + write32((DEFAULT_HECIBAR + 0x4), (read32(DEFAULT_HECIBAR + 0x4) & ~0x10) | 0xc); }
-/* FIXME: add timeout. */ +/* FIXME: add timeout. */ static void wait_heci_cb_avail(int len) { union { @@ -1665,12 +1584,10 @@ while (!(read32(DEFAULT_HECIBAR + 0xc) & 8)) ;
- do + do { csr.raw = read32(DEFAULT_HECIBAR + 0x4); - while (len > - csr.csr.buffer_depth - (csr.csr.buffer_write_ptr - - csr.csr.buffer_read_ptr)) - ; + } while (len > csr.csr.buffer_depth - + (csr.csr.buffer_write_ptr - csr.csr.buffer_read_ptr)); }
static void send_heci_packet(struct mei_header *head, u32 *payload) @@ -1682,6 +1599,7 @@
/* FIXME: handle leftovers correctly. */ write32(DEFAULT_HECIBAR + 0, *(u32 *) head); + for (i = 0; i < len - 1; i++) write32(DEFAULT_HECIBAR + 0, payload[i]);
@@ -1689,8 +1607,7 @@ write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 0x4); }
-static void -send_heci_message(u8 *msg, int len, u8 hostaddress, u8 clientaddress) +static void send_heci_message(u8 *msg, int len, u8 hostaddress, u8 clientaddress) { struct mei_header head; int maxlen; @@ -1705,6 +1622,7 @@ head.is_complete = 0; } else head.is_complete = 1; + head.length = cur; head.reserved = 0; head.client_address = clientaddress; @@ -1716,68 +1634,70 @@ }
/* FIXME: Add timeout. */ -static int -recv_heci_packet(struct raminfo *info, struct mei_header *head, u32 *packet, - u32 *packet_size) +static int recv_heci_packet(struct raminfo *info, struct mei_header *head, u32 *packet, u32 *packet_size) { union { struct mei_csr csr; u32 raw; } csr; + int i = 0;
write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 2); + do { csr.raw = read32(DEFAULT_HECIBAR + 0xc); } - while (csr.csr.buffer_write_ptr == csr.csr.buffer_read_ptr) - ; + while (csr.csr.buffer_write_ptr == csr.csr.buffer_read_ptr); + *(u32 *) head = read32(DEFAULT_HECIBAR + 0x8); + if (!head->length) { - write32(DEFAULT_HECIBAR + 0x4, - read32(DEFAULT_HECIBAR + 0x4) | 2); + write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 2); *packet_size = 0; return 0; } - if (head->length + 4 > 4 * csr.csr.buffer_depth - || head->length > *packet_size) { + if (head->length + 4 > 4 * csr.csr.buffer_depth || head->length > *packet_size) { *packet_size = 0; return -1; }
- do + do { csr.raw = read32(DEFAULT_HECIBAR + 0xc); - while (((head->length + 3) >> 2) > - (csr.csr.buffer_write_ptr - csr.csr.buffer_read_ptr)) - ; + } while (((head->length + 3) >> 2) > + (csr.csr.buffer_write_ptr - csr.csr.buffer_read_ptr));
for (i = 0; i < (head->length + 3) >> 2; i++) packet[i++] = read32(DEFAULT_HECIBAR + 0x8); + *packet_size = head->length; if (!csr.csr.ready) *packet_size = 0; + write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 4); return 0; }
/* FIXME: Add timeout. */ -static int -recv_heci_message(struct raminfo *info, u32 *message, u32 *message_size) +static int recv_heci_message(struct raminfo *info, u32 *message, u32 *message_size) { struct mei_header head; int current_position;
current_position = 0; + while (1) { - u32 current_size; - current_size = *message_size - current_position; - if (recv_heci_packet - (info, &head, message + (current_position >> 2), - ¤t_size) == -1) + u32 current_size = *message_size - current_position; + + if (recv_heci_packet(info, &head, message + (current_position >> 2), + ¤t_size) == -1) break; + if (!current_size) break; + current_position += current_size; + if (head.is_complete) { *message_size = current_position; return 0; @@ -1786,6 +1706,7 @@ if (current_position >= *message_size) break; } + *message_size = 0; return -1; } @@ -1800,6 +1721,7 @@ u8 field2; u8 unk3[0x48 - 4 - 1]; } __packed reply; + struct uma_message { u8 group_id; u8 cmd; @@ -1810,14 +1732,15 @@ u32 memory_reserved_for_heci_mb; u16 c3; } __packed msg = { - 0, MKHI_SET_UMA, 0, 0, - 0x82, - info->heci_uma_addr, info->memory_reserved_for_heci_mb, 0}; + 0, MKHI_SET_UMA, 0, 0, 0x82, + info->heci_uma_addr, info->memory_reserved_for_heci_mb, 0 + }; + u32 reply_size;
send_heci_message((u8 *) & msg, sizeof(msg), 0, 7); - reply_size = sizeof(reply); + if (recv_heci_message(info, (u32 *) & reply, &reply_size) == -1) return;
@@ -1837,34 +1760,23 @@
info->heci_bar = pci_read_config32(HECIDEV, 0x10) & 0xFFFFFFF0; info->memory_reserved_for_heci_mb = reg44 & 0x3f; - info->heci_uma_addr = - ((u64) - ((((u64) pci_read_config16(NORTHBRIDGE, D0F0_TOM)) << 6) - - info->memory_reserved_for_heci_mb)) << 20; + info->heci_uma_addr = ((u64)((((u64) pci_read_config16(NORTHBRIDGE, D0F0_TOM)) << 6) - info->memory_reserved_for_heci_mb)) << 20;
pci_read_config32(NORTHBRIDGE, DMIBAR); if (info->memory_reserved_for_heci_mb) { - write32(DEFAULT_DMIBAR + 0x14, - read32(DEFAULT_DMIBAR + 0x14) & ~0x80); - write32(DEFAULT_RCBA + 0x14, - read32(DEFAULT_RCBA + 0x14) & ~0x80); - write32(DEFAULT_DMIBAR + 0x20, - read32(DEFAULT_DMIBAR + 0x20) & ~0x80); - write32(DEFAULT_RCBA + 0x20, - read32(DEFAULT_RCBA + 0x20) & ~0x80); - write32(DEFAULT_DMIBAR + 0x2c, - read32(DEFAULT_DMIBAR + 0x2c) & ~0x80); - write32(DEFAULT_RCBA + 0x30, - read32(DEFAULT_RCBA + 0x30) & ~0x80); - write32(DEFAULT_DMIBAR + 0x38, - read32(DEFAULT_DMIBAR + 0x38) & ~0x80); - write32(DEFAULT_RCBA + 0x40, - read32(DEFAULT_RCBA + 0x40) & ~0x80); + write32(DEFAULT_DMIBAR + 0x14, read32(DEFAULT_DMIBAR + 0x14) & ~0x80); + write32(DEFAULT_RCBA + 0x14, read32(DEFAULT_RCBA + 0x14) & ~0x80); + write32(DEFAULT_DMIBAR + 0x20, read32(DEFAULT_DMIBAR + 0x20) & ~0x80); + write32(DEFAULT_RCBA + 0x20, read32(DEFAULT_RCBA + 0x20) & ~0x80); + write32(DEFAULT_DMIBAR + 0x2c, read32(DEFAULT_DMIBAR + 0x2c) & ~0x80); + write32(DEFAULT_RCBA + 0x30, read32(DEFAULT_RCBA + 0x30) & ~0x80); + write32(DEFAULT_DMIBAR + 0x38, read32(DEFAULT_DMIBAR + 0x38) & ~0x80); + write32(DEFAULT_RCBA + 0x40, read32(DEFAULT_RCBA + 0x40) & ~0x80);
- write32(DEFAULT_RCBA + 0x40, 0x87000080); // OK + write32(DEFAULT_RCBA + 0x40, 0x87000080); // OK write32(DEFAULT_DMIBAR + 0x38, 0x87000080); // OK - while ((read16(DEFAULT_RCBA + 0x46) & 2) && - read16(DEFAULT_DMIBAR + 0x3e) & 2) + + while ((read16(DEFAULT_RCBA + 0x46) & 2) && read16(DEFAULT_DMIBAR + 0x3e) & 2) ; }
@@ -1879,11 +1791,11 @@
static int have_match_ranks(struct raminfo *info, int channel, int ranks) { - int ranks_in_channel; - ranks_in_channel = info->populated_ranks[channel][0][0] - + info->populated_ranks[channel][0][1] - + info->populated_ranks[channel][1][0] - + info->populated_ranks[channel][1][1]; + int ranks_in_channel = + info->populated_ranks[channel][0][0] + + info->populated_ranks[channel][0][1] + + info->populated_ranks[channel][1][0] + + info->populated_ranks[channel][1][1];
/* empty channel */ if (ranks_in_channel == 0) @@ -1891,45 +1803,50 @@
if (ranks_in_channel != ranks) return 0; + /* single slot */ if (info->populated_ranks[channel][0][0] != info->populated_ranks[channel][1][0]) return 1; + if (info->populated_ranks[channel][0][1] != info->populated_ranks[channel][1][1]) return 1; + if (info->is_x16_module[channel][0] != info->is_x16_module[channel][1]) return 0; + if (info->density[channel][0] != info->density[channel][1]) return 0; + return 1; }
static void read_4090(struct raminfo *info) { int i, channel, slot, rank, lane; - for (i = 0; i < 2; i++) - for (slot = 0; slot < NUM_SLOTS; slot++) - for (rank = 0; rank < NUM_RANKS; rank++) - for (lane = 0; lane < 9; lane++) - info->training. - lane_timings[0][i][slot][rank][lane] - = 32;
- for (i = 1; i < 4; i++) - for (channel = 0; channel < NUM_CHANNELS; channel++) - for (slot = 0; slot < NUM_SLOTS; slot++) - for (rank = 0; rank < NUM_RANKS; rank++) - for (lane = 0; lane < 9; lane++) { - info->training. - lane_timings[i][channel] - [slot][rank][lane] = - read_500(info, channel, - get_timing_register_addr - (lane, i, slot, - rank), 9) - + (i == 1) * 11; // !!!! - } + for (i = 0; i < 2; i++) { + for (slot = 0; slot < NUM_SLOTS; slot++) { + for (rank = 0; rank < NUM_RANKS; rank++) { + for (lane = 0; lane < 9; lane++) { + + info->training.lane_timings[0][i][slot][rank][lane] = 32; + }}}} /* for each i, slot, rank, lane */ + + for (i = 1; i < 4; i++) { + for (channel = 0; channel < NUM_CHANNELS; channel++) { + for (slot = 0; slot < NUM_SLOTS; slot++) { + for (rank = 0; rank < NUM_RANKS; rank++) { + for (lane = 0; lane < 9; lane++) { + + info->training.lane_timings[i][channel][slot][rank][lane] + = + read_500(info, channel, get_timing_register_addr(lane, i, slot, rank), 9) + + + (i == 1) * 11; // !!!! + + }}}}} /* for each i, channel, slot, lane */
}
@@ -1939,9 +1856,12 @@ 0xaaaa, 0x6db6, 0x4924, 0xeeee, 0xcccc, 0x8888, 0x7bde, 0x739c, 0x6318, 0x4210, 0xefbe, 0xcf3c, 0x8e38, 0x0c30, 0x0820 }; + u32 ret; u32 comp4 = addr / 480; + addr %= 480; + u32 comp1 = addr & 0xf; u32 comp2 = (addr >> 4) & 1; u32 comp3 = addr >> 5; @@ -1950,6 +1870,7 @@ ret = 0x1010101 << (comp4 - 1); else ret = 0; + if (flip ^ (((invmask[comp3] >> comp1) ^ comp2) & 1)) ret = ~ret;
@@ -1967,21 +1888,23 @@ static void enable_cache(unsigned int base, unsigned int size) { msr_t msr; + msr.lo = base | MTRR_TYPE_WRPROT; msr.hi = 0; + wrmsr(MTRR_PHYS_BASE(3), msr); - msr.lo = ((~(ALIGN_DOWN(size + 4096, 4096) - 1) | MTRR_DEF_TYPE_EN) - & 0xffffffff); + + msr.lo = ((~(ALIGN_DOWN(size + 4096, 4096) - 1) | MTRR_DEF_TYPE_EN) & 0xffffffff); msr.hi = 0x0000000f; + wrmsr(MTRR_PHYS_MASK(3), msr); }
static void flush_cache(u32 start, u32 size) { - u32 end; u32 addr; + u32 end = start + (ALIGN_DOWN(size + 4096, 4096));
- end = start + (ALIGN_DOWN(size + 4096, 4096)); for (addr = start; addr < end; addr += 64) clflush(addr); } @@ -1994,17 +1917,20 @@ static void write_testing(struct raminfo *info, int totalrank, int flip) { int nwrites = 0; + /* in 8-byte units. */ u32 offset; - u8 *base; + u8 *base = (u8 *)(totalrank << 28);
- base = (u8 *)(totalrank << 28); for (offset = 0; offset < 9 * 480; offset += 2) { - write32(base + offset * 8, get_etalon2(flip, offset)); - write32(base + offset * 8 + 4, get_etalon2(flip, offset)); - write32(base + offset * 8 + 8, get_etalon2(flip, offset + 1)); + + write32(base + offset * 8, get_etalon2(flip, offset)); + write32(base + offset * 8 + 4, get_etalon2(flip, offset)); + write32(base + offset * 8 + 8, get_etalon2(flip, offset + 1)); write32(base + offset * 8 + 12, get_etalon2(flip, offset + 1)); + nwrites += 4; + if (nwrites >= 320) { clear_errors(); nwrites = 0; @@ -2014,9 +1940,8 @@
static u8 check_testing(struct raminfo *info, u8 total_rank, int flip) { - u8 failmask = 0; - int i; - int comp1, comp2, comp3; + int i, comp1, comp2, comp3; + u8 failmask = 0; u32 failxor[2] = { 0, 0 };
enable_cache((total_rank << 28), 1728 * 5 * 4); @@ -2058,12 +1983,10 @@
static u32 get_seed2(int a, int b) { - const u32 seed2[5] = { - 0x55555555, 0x33333333, 0x2e555a55, 0x55555555, - 0x5b6db6db, - }; - u32 r; - r = seed2[(a + (a >= 10)) / 5]; + const u32 seed2[5] = {0x55555555, 0x33333333, 0x2e555a55, 0x55555555, 0x5b6db6db}; + + u32 r = seed2[(a + (a >= 10)) / 5]; + return b ? ~r : r; }
@@ -2081,75 +2004,68 @@
static u32 get_etalon(int flip, u32 addr) { - u32 mask_byte = 0; - int comp1 = (addr >> 1) & 1; - int comp2 = (addr >> 3) & 0x1f; - int comp3 = (addr >> 8) & 0xf; + int comp1 = (addr >> 1) & 1; + int comp2 = (addr >> 3) & 0x1f; + int comp3 = (addr >> 8) & 0xf; int comp4 = (addr >> 12) & 0xf; int comp5 = (addr >> 16) & 0x1f; u32 mask_bit = ~(0x10001 << comp3); - u32 part1; - u32 part2; + u32 mask_byte = 0; + u32 part1, part2; int byte;
- part2 = - ((seed1[comp5] >> - make_shift(comp2, comp5, - (comp3 >> 3) | (comp1 << 2) | 2)) & 1) ^ flip; - part1 = - ((seed1[comp5] >> - make_shift(comp2, comp5, - (comp3 >> 3) | (comp1 << 2) | 0)) & 1) ^ flip; + part2 = ((seed1[comp5] >> + make_shift(comp2, comp5, (comp3 >> 3) | (comp1 << 2) | 2)) & 1) ^ flip; + + part1 = ((seed1[comp5] >> + make_shift(comp2, comp5, (comp3 >> 3) | (comp1 << 2) | 0)) & 1) ^ flip;
for (byte = 0; byte < 4; byte++) if ((get_seed2(comp5, comp4) >> - make_shift(comp2, comp5, (byte | (comp1 << 2)))) & 1) + make_shift(comp2, comp5, (byte | (comp1 << 2)))) & 1) mask_byte |= 0xff << (8 * byte);
- return (mask_bit & mask_byte) | (part1 << comp3) | (part2 << - (comp3 + 16)); + return (mask_bit & mask_byte) | (part1 << comp3) | (part2 << (comp3 + 16)); }
static void -write_testing_type2(struct raminfo *info, u8 totalrank, u8 region, u8 block, - char flip) +write_testing_type2(struct raminfo *info, u8 totalrank, u8 region, u8 block, char flip) { int i; for (i = 0; i < 2048; i++) - write32p((totalrank << 28) | (region << 25) | (block << 16) | - (i << 2), get_etalon(flip, (block << 16) | (i << 2))); + write32p((totalrank << 28) | (region << 25) | (block << 16) | (i << 2), + get_etalon(flip, (block << 16) | (i << 2))); }
static u8 -check_testing_type2(struct raminfo *info, u8 totalrank, u8 region, u8 block, - char flip) +check_testing_type2(struct raminfo *info, u8 totalrank, u8 region, u8 block, char flip) { u8 failmask = 0; u32 failxor[2]; - int i; - int comp1, comp2, comp3; + int i, comp1, comp2, comp3;
failxor[0] = 0; failxor[1] = 0;
enable_cache(totalrank << 28, 134217728); + for (comp3 = 0; comp3 < 2 && failmask != 0xff; comp3++) { for (comp1 = 0; comp1 < 16; comp1++) - for (comp2 = 0; comp2 < 64; comp2++) { - u32 addr = - (totalrank << 28) | (region << 25) | (block - << 16) - | (comp3 << 12) | (comp2 << 6) | (comp1 << - 2); - failxor[comp1 & 1] |= - read32p(addr) ^ get_etalon(flip, addr); - } + for (comp2 = 0; comp2 < 64; comp2++) { + u32 addr = (totalrank << 28) | (region << 25) | (block << 16) | + (comp3 << 12) | (comp2 << 6) | (comp1 << 2); + + failxor[comp1 & 1] |= read32p(addr) ^ get_etalon(flip, addr); + } + for (i = 0; i < 8; i++) if ((0xff << (8 * (i % 4))) & failxor[i / 4]) failmask |= 1 << i; } + disable_cache(); flush_cache((totalrank << 28) | (region << 25) | (block << 16), 16384); + return failmask; }
@@ -2173,18 +2089,18 @@ for (i = 0; i < 8; i++) if (in[i] != COMPLETE) return 0; + return 1; }
-static void -do_fsm(enum state *state, u16 *counter, - u8 fail_mask, int margin, int uplimit, - u8 *res_low, u8 *res_high, u8 val) +static void do_fsm(enum state *state, u16 *counter, u8 fail_mask, int margin, int uplimit, + u8 *res_low, u8 *res_high, u8 val) { int lane;
for (lane = 0; lane < 8; lane++) { int is_fail = (fail_mask >> lane) & 1; + switch (state[lane]) { case BEFORE_USABLE: if (!is_fail) { @@ -2195,6 +2111,7 @@ counter[lane] = 0; state[lane] = BEFORE_USABLE; break; + case AT_USABLE: if (!is_fail) { ++counter[lane]; @@ -2209,6 +2126,7 @@ counter[lane] = 0; state[lane] = BEFORE_USABLE; break; + case AT_MARGIN: if (is_fail) { state[lane] = COMPLETE; @@ -2222,6 +2140,7 @@ } } break; + case COMPLETE: break; } @@ -2229,9 +2148,8 @@ }
static void -train_ram_at_178(struct raminfo *info, u8 channel, int slot, int rank, - u8 total_rank, u8 reg_178, int first_run, int niter, - timing_bounds_t * timings) +train_ram_at_178(struct raminfo *info, u8 channel, int slot, int rank, u8 total_rank, + u8 reg_178, int first_run, int niter, timing_bounds_t *timings) { int lane; enum state state[8]; @@ -2247,17 +2165,17 @@
if (!first_run) { int is_all_ok = 1; - for (lane = 0; lane < 8; lane++) - if (timings[reg_178][channel][slot][rank][lane]. - smallest == - timings[reg_178][channel][slot][rank][lane]. - largest) { - timings[reg_178][channel][slot][rank][lane]. - smallest = 0; - timings[reg_178][channel][slot][rank][lane]. - largest = 0; + for (lane = 0; lane < 8; lane++) { + + if (timings[reg_178][channel][slot][rank][lane].smallest + == timings[reg_178][channel][slot][rank][lane].largest) { + + timings[reg_178][channel][slot][rank][lane].smallest = 0; + timings[reg_178][channel][slot][rank][lane].largest = 0; is_all_ok = 0; } + } + if (is_all_ok) { for (i = 0; i < 8; i++) state[i] = COMPLETE; @@ -2266,258 +2184,200 @@
for (reg1b3 = 0; reg1b3 < 0x30 && !validate_state(state); reg1b3++) { u8 failmask = 0; + write_1d0(reg1b3 ^ 32, 0x1b3, 6, 1); write_1d0(reg1b3 ^ 32, 0x1a3, 6, 1); + failmask = check_testing(info, total_rank, 0); + MCHBAR32_OR(0xfb0, 0x00030000); - do_fsm(state, count, failmask, 5, 47, lower_usable, - upper_usable, reg1b3); + + do_fsm(state, count, failmask, 5, 47, lower_usable, upper_usable, reg1b3); }
if (reg1b3) { write_1d0(0, 0x1b3, 6, 1); write_1d0(0, 0x1a3, 6, 1); + for (lane = 0; lane < 8; lane++) { - if (state[lane] == COMPLETE) { - timings[reg_178][channel][slot][rank][lane]. - smallest = - lower_usable[lane] + - (info->training. - lane_timings[0][channel][slot][rank][lane] - & 0x3F) - 32; - timings[reg_178][channel][slot][rank][lane]. - largest = - upper_usable[lane] + - (info->training. - lane_timings[0][channel][slot][rank][lane] - & 0x3F) - 32; - } - } + if (state[lane] == COMPLETE) { + + timings[reg_178][channel][slot][rank][lane].smallest + = + lower_usable[lane] + + + (info->training.lane_timings[0][channel][slot][rank][lane] & 0x3F) + - + 32; + + timings[reg_178][channel][slot][rank][lane].largest + = + upper_usable[lane] + + + (info->training.lane_timings[0][channel][slot][rank][lane] & 0x3F) + - + 32; + + }} /* for each lane, if complete */ }
if (!first_run) { - for (lane = 0; lane < 8; lane++) - if (state[lane] == COMPLETE) { - write_500(info, channel, - timings[reg_178][channel][slot][rank] - [lane].smallest, - get_timing_register_addr(lane, 0, - slot, rank), - 9, 1); - write_500(info, channel, - timings[reg_178][channel][slot][rank] - [lane].smallest + - info->training. - lane_timings[1][channel][slot][rank] - [lane] - - - info->training. - lane_timings[0][channel][slot][rank] - [lane], get_timing_register_addr(lane, - 1, - slot, - rank), - 9, 1); - num_successfully_checked[lane] = 0; - } else - num_successfully_checked[lane] = -1; + + for (lane = 0; lane < 8; lane++) { + if (state[lane] == COMPLETE) { + write_500(info, channel, + timings[reg_178][channel][slot][rank][lane].smallest, + get_timing_register_addr(lane, 0, slot, rank), 9, 1); + + write_500(info, channel, + timings[reg_178][channel][slot][rank][lane].smallest + + info->training.lane_timings[1][channel][slot][rank][lane] - + info->training.lane_timings[0][channel][slot][rank][lane], + get_timing_register_addr(lane, 1, slot, rank), 9, 1); + + num_successfully_checked[lane] = 0; + + } else { + num_successfully_checked[lane] = -1; + }} /* for each lane, depending whether it's complete */
do { u8 failmask = 0; for (i = 0; i < niter; i++) { if (failmask == 0xFF) break; - failmask |= - check_testing_type2(info, total_rank, 2, i, - 0); - failmask |= - check_testing_type2(info, total_rank, 3, i, - 1); + + failmask |= check_testing_type2(info, total_rank, 2, i, 0); + failmask |= check_testing_type2(info, total_rank, 3, i, 1); } + MCHBAR32_OR(0xfb0, 0x00030000); - for (lane = 0; lane < 8; lane++) + + /* FIXME: Visually, this is hideously atrocious. */ + for (lane = 0; lane < 8; lane++) { if (num_successfully_checked[lane] != 0xffff) { if ((1 << lane) & failmask) { - if (timings[reg_178][channel] - [slot][rank][lane]. - largest <= - timings[reg_178][channel] - [slot][rank][lane].smallest) - num_successfully_checked - [lane] = -1; - else { - num_successfully_checked - [lane] = 0; - timings[reg_178] - [channel][slot] - [rank][lane]. - smallest++; - write_500(info, channel, - timings - [reg_178] - [channel] - [slot][rank] - [lane]. - smallest, - get_timing_register_addr - (lane, 0, - slot, rank), - 9, 1); - write_500(info, channel, - timings - [reg_178] - [channel] - [slot][rank] - [lane]. - smallest + - info-> - training. - lane_timings - [1][channel] - [slot][rank] - [lane] - - - info-> - training. - lane_timings - [0][channel] - [slot][rank] - [lane], - get_timing_register_addr - (lane, 1, - slot, rank), - 9, 1); - } - } else - num_successfully_checked[lane] - ++; - } - } - while (!check_bounded(num_successfully_checked, 2)) - ;
- for (lane = 0; lane < 8; lane++) - if (state[lane] == COMPLETE) { - write_500(info, channel, - timings[reg_178][channel][slot][rank] - [lane].largest, - get_timing_register_addr(lane, 0, - slot, rank), - 9, 1); - write_500(info, channel, - timings[reg_178][channel][slot][rank] - [lane].largest + - info->training. - lane_timings[1][channel][slot][rank] - [lane] - - - info->training. - lane_timings[0][channel][slot][rank] - [lane], get_timing_register_addr(lane, - 1, - slot, - rank), - 9, 1); - num_successfully_checked[lane] = 0; - } else - num_successfully_checked[lane] = -1; + if (timings[reg_178][channel][slot][rank] + [lane].largest <= timings[reg_178] + [channel][slot][rank][lane].smallest) { + + num_successfully_checked[lane] = -1; + + } else { + num_successfully_checked[lane] = 0; + + timings[reg_178][channel][slot][rank] + [lane].smallest++; + + write_500(info, channel, timings + [reg_178][channel][slot][rank] + [lane].smallest, + get_timing_register_addr + (lane, 0, slot, rank), 9, 1); + + write_500(info, channel, timings + [reg_178][channel][slot][rank] + [lane].smallest + info-> + training.lane_timings[1] + [channel][slot][rank][lane] - + info->training.lane_timings[0] + [channel][slot][rank][lane], + get_timing_register_addr + (lane, 1, slot, rank), 9, 1); + } + + } else { + num_successfully_checked[lane]++; + } + } + } + } while (!check_bounded(num_successfully_checked, 2)); + + for (lane = 0; lane < 8; lane++) { + if (state[lane] == COMPLETE) { + write_500(info, channel, + timings[reg_178][channel][slot][rank][lane].largest, + get_timing_register_addr(lane, 0, slot, rank), 9, 1); + + write_500(info, channel, + timings[reg_178][channel][slot][rank][lane].largest + + info->training.lane_timings[1][channel][slot][rank][lane] - + info->training.lane_timings[0][channel][slot][rank][lane], + get_timing_register_addr(lane, 1, slot, rank), 9, 1); + + num_successfully_checked[lane] = 0; + + } else { + num_successfully_checked[lane] = -1; + }} /* for each lane, depending whether it's complete */
do { int failmask = 0; for (i = 0; i < niter; i++) { - if (failmask == 0xFF) + if (failmask == 0xff) break; - failmask |= - check_testing_type2(info, total_rank, 2, i, - 0); - failmask |= - check_testing_type2(info, total_rank, 3, i, - 1); + + failmask |= check_testing_type2(info, total_rank, 2, i, 0); + failmask |= check_testing_type2(info, total_rank, 3, i, 1); }
MCHBAR32_OR(0xfb0, 0x00030000); + + /* FIXME: Visually, this is hideously atrocious. */ for (lane = 0; lane < 8; lane++) { if (num_successfully_checked[lane] != 0xffff) { if ((1 << lane) & failmask) { - if (timings[reg_178][channel] - [slot][rank][lane]. - largest <= - timings[reg_178][channel] - [slot][rank][lane]. - smallest) { - num_successfully_checked - [lane] = -1; + + if (timings[reg_178][channel][slot][rank] + [lane].largest <= timings[reg_178] + [channel][slot][rank][lane].smallest) { + + num_successfully_checked[lane] = -1; + } else { - num_successfully_checked - [lane] = 0; - timings[reg_178] - [channel][slot] - [rank][lane]. - largest--; - write_500(info, channel, - timings - [reg_178] - [channel] - [slot][rank] - [lane]. - largest, - get_timing_register_addr - (lane, 0, - slot, rank), - 9, 1); - write_500(info, channel, - timings - [reg_178] - [channel] - [slot][rank] - [lane]. - largest + - info-> - training. - lane_timings - [1][channel] - [slot][rank] - [lane] - - - info-> - training. - lane_timings - [0][channel] - [slot][rank] - [lane], - get_timing_register_addr - (lane, 1, - slot, rank), - 9, 1); + num_successfully_checked[lane] = 0; + + timings[reg_178][channel][slot][rank] + [lane].largest--; + + write_500(info, channel, timings + [reg_178][channel][slot][rank] + [lane].largest, + get_timing_register_addr + (lane, 0, slot, rank), 9, 1); + + write_500(info, channel, timings + [reg_178][channel][slot][rank] + [lane].largest + info-> + training.lane_timings[1] + [channel][slot][rank][lane] - + info->training.lane_timings[0] + [channel][slot][rank][lane], + get_timing_register_addr + (lane, 1, slot, rank), 9, 1); } - } else - num_successfully_checked[lane] - ++; + + } else { + num_successfully_checked[lane]++; + } } } - } - while (!check_bounded(num_successfully_checked, 3)) - ; + } while (!check_bounded(num_successfully_checked, 3));
for (lane = 0; lane < 8; lane++) { - write_500(info, channel, - info->training. + write_500(info, channel, info->training. lane_timings[0][channel][slot][rank][lane], - get_timing_register_addr(lane, 0, slot, rank), - 9, 1); - write_500(info, channel, - info->training. + get_timing_register_addr(lane, 0, slot, rank), 9, 1); + + write_500(info, channel, info->training. lane_timings[1][channel][slot][rank][lane], - get_timing_register_addr(lane, 1, slot, rank), - 9, 1); - if (timings[reg_178][channel][slot][rank][lane]. - largest <= - timings[reg_178][channel][slot][rank][lane]. - smallest) { - timings[reg_178][channel][slot][rank][lane]. - largest = 0; - timings[reg_178][channel][slot][rank][lane]. - smallest = 0; + get_timing_register_addr(lane, 1, slot, rank), 9, 1); + + if (timings[reg_178][channel][slot][rank][lane].largest + <= timings[reg_178][channel][slot][rank][lane].smallest) { + timings[reg_178][channel][slot][rank][lane].largest = 0; + timings[reg_178][channel][slot][rank][lane].smallest = 0; } } } @@ -2535,10 +2395,9 @@ write_1d0(val, 0x10b, 6, 1);
FOR_POPULATED_RANKS_BACKWARDS for (lane = 0; lane < 9; lane++) { - u16 reg_500; - reg_500 = read_500(info, channel, - get_timing_register_addr(lane, 0, slot, - rank), 9); + u16 reg_500 = read_500(info, channel, + get_timing_register_addr(lane, 0, slot, rank), 9); + if (val == 1) { if (lut16[info->clock_speed_index] <= reg_500) reg_500 -= lut16[info->clock_speed_index]; @@ -2548,7 +2407,7 @@ reg_500 += lut16[info->clock_speed_index]; } write_500(info, channel, reg_500, - get_timing_register_addr(lane, 0, slot, rank), 9, 1); + get_timing_register_addr(lane, 0, slot, rank), 9, 1); } }
@@ -2556,12 +2415,13 @@ { int channel; for (channel = 0; channel < NUM_CHANNELS; channel++) { - u8 t; - t = MCHBAR8((channel << 10) + 0x5f8); + + u8 t = MCHBAR8((channel << 10) + 0x5f8); if (onoff) t |= 1; else t &= ~1; + MCHBAR8((channel << 10) + 0x5f8) = t; } } @@ -2577,22 +2437,18 @@ }
static void -write_500_timings_type(struct raminfo *info, int channel, int slot, int rank, - int type) +write_500_timings_type(struct raminfo *info, int channel, int slot, int rank, int type) { int lane;
for (lane = 0; lane < 8; lane++) write_500(info, channel, - info->training. - lane_timings[type][channel][slot][rank][lane], - get_timing_register_addr(lane, type, slot, rank), 9, - 0); + info->training.lane_timings[type][channel][slot][rank][lane], + get_timing_register_addr(lane, type, slot, rank), 9, 0); }
static void -try_timing_offsets(struct raminfo *info, int channel, - int slot, int rank, int totalrank) +try_timing_offsets(struct raminfo *info, int channel, int slot, int rank, int totalrank) { u16 count[8]; enum state state[8]; @@ -2609,9 +2465,8 @@
for (lane = 0; lane < 8; lane++) write_500(info, channel, - info->training. - lane_timings[2][channel][slot][rank][lane] + 32, - get_timing_register_addr(lane, 3, slot, rank), 9, 1); + info->training.lane_timings[2][channel][slot][rank][lane] + 32, + get_timing_register_addr(lane, 3, slot, rank), 9, 1);
for (timing_offset = 0; !validate_state(state) && timing_offset < 64; timing_offset++) { @@ -2623,8 +2478,8 @@ write_testing(info, totalrank, flip); failmask |= check_testing(info, totalrank, flip); } - do_fsm(state, count, failmask, 10, 63, lower_usable, - upper_usable, timing_offset); + do_fsm(state, count, failmask, 10, 63, lower_usable, upper_usable, + timing_offset); } write_1d0(0, 0x1bb, 6, 1); dump_timings(info); @@ -2645,24 +2500,25 @@ } } write_500(info, channel, - info->training. - lane_timings[2][channel][slot][rank][lane] + - (upper_usable[lane] + lower_usable[lane]) / 2 - bias, - get_timing_register_addr(lane, 3, slot, rank), 9, 1); + info->training.lane_timings[2][channel][slot][rank][lane] + + (upper_usable[lane] + lower_usable[lane]) / 2 - bias, + get_timing_register_addr(lane, 3, slot, rank), 9, 1); + info->training.timing2_bounds[channel][slot][rank][lane][0] = - info->training.lane_timings[2][channel][slot][rank][lane] + - lower_usable[lane]; + info->training.lane_timings[2][channel][slot][rank][lane] + + lower_usable[lane]; + info->training.timing2_bounds[channel][slot][rank][lane][1] = - info->training.lane_timings[2][channel][slot][rank][lane] + - upper_usable[lane]; + info->training.lane_timings[2][channel][slot][rank][lane] + + upper_usable[lane]; + info->training.timing2_offset[channel][slot][rank][lane] = - info->training.lane_timings[2][channel][slot][rank][lane]; + info->training.lane_timings[2][channel][slot][rank][lane]; } }
-static u8 -choose_training(struct raminfo *info, int channel, int slot, int rank, - int lane, timing_bounds_t * timings, u8 center_178) +static u8 choose_training(struct raminfo *info, int channel, int slot, int rank, int lane, + timing_bounds_t * timings, u8 center_178) { u16 central_weight; u16 side_weight; @@ -2678,16 +2534,15 @@ if (info->silicon_revision == 1 && channel == 1) { central_weight = 5; side_weight = 20; - if ((info-> - populated_ranks_mask[1] ^ (info-> - populated_ranks_mask[1] >> 2)) & - 1) + if ((info->populated_ranks_mask[1] ^ (info->populated_ranks_mask[1] >> 2)) & 1) span = 18; } + if ((info->populated_ranks_mask[0] & 5) == 5) { central_weight = 20; side_weight = 20; } + if (info->clock_speed_index >= 2 && (info->populated_ranks_mask[0] & 5) == 5 && slot == 1) { if (info->silicon_revision == 1) { @@ -2711,18 +2566,20 @@ central_weight = 20; } } - for (reg_178 = center_178 - span; reg_178 <= center_178 + span; - reg_178 += span) { + for (reg_178 = center_178 - span; reg_178 <= center_178 + span; reg_178 += span) { u8 smallest; u8 largest; largest = timings[reg_178][channel][slot][rank][lane].largest; smallest = timings[reg_178][channel][slot][rank][lane].smallest; + if (largest - smallest + 1 >= 5) { + unsigned int weight; if (reg_178 == center_178) weight = central_weight; else weight = side_weight; + sum += weight * (largest + smallest); count += weight; } @@ -2730,21 +2587,23 @@ dump_timings(info); if (count == 0) die("Couldn't discover DRAM timings (2)\n"); + result = sum / (2 * count); - lower_margin = - result - timings[center_178][channel][slot][rank][lane].smallest; - upper_margin = - timings[center_178][channel][slot][rank][lane].largest - result; + lower_margin = result - timings[center_178][channel][slot][rank][lane].smallest; + upper_margin = timings[center_178][channel][slot][rank][lane].largest - result; + if (upper_margin < 10 && lower_margin > 10) result -= MIN(lower_margin - 10, 10 - upper_margin); + if (upper_margin > 10 && lower_margin < 10) result += MIN(upper_margin - 10, 10 - lower_margin); + return result; }
#define STANDARD_MIN_MARGIN 5
-static u8 choose_reg178(struct raminfo *info, timing_bounds_t * timings) +static u8 choose_reg178(struct raminfo *info, timing_bounds_t *timings) { u16 margin[64]; int lane, rank, slot, channel; @@ -2754,12 +2613,12 @@ for (reg178 = reg178_min[info->clock_speed_index]; reg178 < reg178_max[info->clock_speed_index]; reg178 += reg178_step[info->clock_speed_index]) { + margin[reg178] = -1; FOR_POPULATED_RANKS_BACKWARDS for (lane = 0; lane < 8; lane++) { - int curmargin = - timings[reg178][channel][slot][rank][lane].largest - - timings[reg178][channel][slot][rank][lane]. - smallest + 1; + int curmargin = timings[reg178][channel][slot][rank][lane].largest - + timings[reg178][channel][slot][rank][lane].smallest + 1; + if (curmargin < margin[reg178]) margin[reg178] = curmargin; } @@ -2778,23 +2637,21 @@
for (threshold = 30; threshold >= 5; threshold--) { int usable_length = 0; - int smallest_fount = 0; + int smallest_found = 0; for (reg178 = reg178_min[info->clock_speed_index]; reg178 < reg178_max[info->clock_speed_index]; reg178 += reg178_step[info->clock_speed_index]) if (margin[reg178] >= threshold) { - usable_length += - reg178_step[info->clock_speed_index]; - info->training.reg178_largest = - reg178 - - 2 * reg178_step[info->clock_speed_index];
- if (!smallest_fount) { - smallest_fount = 1; + usable_length += reg178_step[info->clock_speed_index]; + + info->training.reg178_largest = + reg178 - 2 * reg178_step[info->clock_speed_index]; + + if (!smallest_found) { + smallest_found = 1; info->training.reg178_smallest = - reg178 + - reg178_step[info-> - clock_speed_index]; + reg178 + reg178_step[info->clock_speed_index]; } } if (usable_length >= 0x21) @@ -2806,36 +2663,31 @@
static int check_cached_sanity(struct raminfo *info) { - int lane; - int slot, rank; - int channel; + int channel, slot, rank, lane;
if (!info->cached_training) return 0;
- for (channel = 0; channel < NUM_CHANNELS; channel++) - for (slot = 0; slot < NUM_SLOTS; slot++) - for (rank = 0; rank < NUM_RANKS; rank++) - for (lane = 0; lane < 8 + info->use_ecc; lane++) { - u16 cached_value, estimation_value; - cached_value = - info->cached_training-> - lane_timings[1][channel][slot][rank] - [lane]; - if (cached_value >= 0x18 - && cached_value <= 0x1E7) { - estimation_value = - info->training. - lane_timings[1][channel] - [slot][rank][lane]; - if (estimation_value < - cached_value - 24) - return 0; - if (estimation_value > - cached_value + 24) - return 0; - } - } + for (channel = 0; channel < NUM_CHANNELS; channel++) { + for (slot = 0; slot < NUM_SLOTS; slot++) { + for (rank = 0; rank < NUM_RANKS; rank++) { + for (lane = 0; lane < 8 + info->use_ecc; lane++) { + u16 cached_value, estimation_value; + + cached_value = info->cached_training->lane_timings[1] + [channel][slot][rank][lane]; + + if (cached_value >= 0x18 && cached_value <= 0x1e7) { + estimation_value = + info->training.lane_timings[1][channel][slot][rank][lane]; + + if (estimation_value < cached_value - 24) + return 0; + + if (estimation_value > cached_value + 24) + return 0; + } + }}}} /* For each channel, slot, rank, lane */ return 1; }
@@ -2851,15 +2703,15 @@ if (!check_cached_sanity(info)) return 0;
- info->training.reg178_center = info->cached_training->reg178_center; + info->training.reg178_center = info->cached_training->reg178_center; info->training.reg178_smallest = info->cached_training->reg178_smallest; - info->training.reg178_largest = info->cached_training->reg178_largest; - memcpy(&info->training.timing_bounds, - &info->cached_training->timing_bounds, - sizeof(info->training.timing_bounds)); - memcpy(&info->training.timing_offset, - &info->cached_training->timing_offset, - sizeof(info->training.timing_offset)); + info->training.reg178_largest = info->cached_training->reg178_largest; + + memcpy(&info->training.timing_bounds, &info->cached_training->timing_bounds, + sizeof(info->training.timing_bounds)); + + memcpy(&info->training.timing_offset, &info->cached_training->timing_offset, + sizeof(info->training.timing_offset));
write_1d0(2, 0x142, 3, 1); saved_243[0] = MCHBAR8(0x243); @@ -2868,13 +2720,15 @@ MCHBAR8(0x643) = saved_243[1] | 2; set_ecc(0); pci_write_config16(NORTHBRIDGE, 0xc8, 3); + if (read_1d0(0x10b, 6) & 1) set_10b(info, 0); + for (tm = 0; tm < 2; tm++) { int totalrank;
- set_178(tm ? info->cached_training->reg178_largest : info-> - cached_training->reg178_smallest); + set_178(tm ? info->cached_training->reg178_largest + : info->cached_training->reg178_smallest);
totalrank = 0; /* Check timing ranges. With i == 0 we check smallest one and with @@ -2885,76 +2739,51 @@ FOR_POPULATED_RANKS_BACKWARDS { for (i = 0; i < 2; i++) { for (lane = 0; lane < 8; lane++) { - write_500(info, channel, - info->cached_training-> - timing2_bounds[channel][slot] - [rank][lane][i], - get_timing_register_addr(lane, - 3, - slot, - rank), - 9, 1); + write_500(info, channel, info->cached_training-> + timing2_bounds[channel][slot][rank][lane][i], + get_timing_register_addr(lane, 3, slot, rank), + 9, 1);
if (!i) - write_500(info, channel, - info-> - cached_training-> - timing2_offset - [channel][slot][rank] - [lane], - get_timing_register_addr - (lane, 2, slot, rank), - 9, 1); - write_500(info, channel, - i ? info->cached_training-> - timing_bounds[tm][channel] - [slot][rank][lane]. - largest : info-> - cached_training-> - timing_bounds[tm][channel] - [slot][rank][lane].smallest, - get_timing_register_addr(lane, - 0, - slot, - rank), - 9, 1); - write_500(info, channel, - info->cached_training-> - timing_offset[channel][slot] - [rank][lane] + - (i ? info->cached_training-> - timing_bounds[tm][channel] - [slot][rank][lane]. - largest : info-> - cached_training-> - timing_bounds[tm][channel] - [slot][rank][lane]. - smallest) - 64, - get_timing_register_addr(lane, - 1, - slot, - rank), - 9, 1); + write_500(info, channel, info->cached_training-> + timing2_offset[channel][slot][rank] + [lane], get_timing_register_addr(lane, + 2, slot, rank), 9, 1); + + write_500(info, channel, i ? info->cached_training-> + timing_bounds[tm][channel][slot][rank][lane]. + largest : info->cached_training->timing_bounds + [tm][channel][slot][rank][lane].smallest, + get_timing_register_addr(lane, 0, slot, rank), + 9, 1); + + write_500(info, channel, info->cached_training-> + timing_offset[channel][slot][rank][lane] + + (i ? info->cached_training->timing_bounds[tm] + [channel][slot][rank][lane].largest + : info->cached_training->timing_bounds[tm] + [channel][slot][rank][lane].smallest + ) - 64, + get_timing_register_addr(lane, 1, slot, rank), + 9, 1); } for (j = 0; j < 2; j++) { - u8 failmask; - u8 expected_failmask; + u8 failmask, expected_failmask; char reg1b3;
reg1b3 = (j == 1) + 4; - reg1b3 = - j == i ? reg1b3 : (-reg1b3) & 0x3f; + reg1b3 = (j == i) ? reg1b3 : (-reg1b3) & 0x3f; + write_1d0(reg1b3, 0x1bb, 6, 1); write_1d0(reg1b3, 0x1b3, 6, 1); write_1d0(reg1b3, 0x1a3, 6, 1);
flip = !flip; write_testing(info, totalrank, flip); - failmask = - check_testing(info, totalrank, - flip); - expected_failmask = - j == 0 ? 0x00 : 0xff; + + failmask = check_testing(info, totalrank, flip); + expected_failmask = j == 0 ? 0x00 : 0xff; + if (failmask != expected_failmask) goto fail; } @@ -2964,8 +2793,10 @@ }
set_178(info->cached_training->reg178_center); + if (info->use_ecc) set_ecc(1); + write_training_data(info); write_1d0(0, 322, 3, 1); info->training = *info->cached_training; @@ -3010,6 +2841,7 @@ saved_243[1] = MCHBAR8(0x643); MCHBAR8(0x243) = saved_243[0] | 2; MCHBAR8(0x643) = saved_243[1] | 2; + switch (info->clock_speed_index) { case 0: niter = 5; @@ -3021,6 +2853,7 @@ niter = 19; break; } + set_ecc(0);
FOR_POPULATED_RANKS_BACKWARDS { @@ -3037,138 +2870,125 @@ totalrank++; }
- if (reg178_min[info->clock_speed_index] < - reg178_max[info->clock_speed_index]) - memset(timings[reg178_min[info->clock_speed_index]], 0, - sizeof(timings[0]) * - (reg178_max[info->clock_speed_index] - - reg178_min[info->clock_speed_index])); - for (reg_178 = reg178_min[info->clock_speed_index]; - reg_178 < reg178_max[info->clock_speed_index]; + if (reg178_min[info->clock_speed_index] < reg178_max[info->clock_speed_index]) { + memset(timings[reg178_min[info->clock_speed_index]], 0, sizeof(timings[0]) * + (reg178_max[info->clock_speed_index] - + reg178_min[info->clock_speed_index])); + } + + for (reg_178 = reg178_min[info->clock_speed_index]; + reg_178 < reg178_max[info->clock_speed_index]; reg_178 += reg178_step[info->clock_speed_index]) { + totalrank = 0; set_178(reg_178); - for (channel = NUM_CHANNELS - 1; channel >= 0; channel--) - for (slot = 0; slot < NUM_SLOTS; slot++) - for (rank = 0; rank < NUM_RANKS; rank++) { - memset(&timings[reg_178][channel][slot] - [rank][0].smallest, 0, 16); - if (info-> - populated_ranks[channel][slot] - [rank]) { - train_ram_at_178(info, channel, - slot, rank, - totalrank, - reg_178, 1, - niter, - timings); - totalrank++; - } - } + + for (channel = NUM_CHANNELS - 1; channel >= 0; channel--) { + for (slot = 0; slot < NUM_SLOTS; slot++) { + for (rank = 0; rank < NUM_RANKS; rank++) { + + memset(&timings[reg_178][channel][slot][rank][0].smallest, 0, 16); + + if (info->populated_ranks[channel][slot][rank]) { + + train_ram_at_178(info, channel, slot, rank, totalrank, + reg_178, 1, niter, timings); + + totalrank++; + } + }}} /* for each channel, slot, rank */ }
reg178_center = choose_reg178(info, timings);
FOR_POPULATED_RANKS_BACKWARDS for (lane = 0; lane < 8; lane++) { - info->training.timing_bounds[0][channel][slot][rank][lane]. - smallest = - timings[info->training. - reg178_smallest][channel][slot][rank][lane]. - smallest; - info->training.timing_bounds[0][channel][slot][rank][lane]. - largest = - timings[info->training. - reg178_smallest][channel][slot][rank][lane].largest; - info->training.timing_bounds[1][channel][slot][rank][lane]. - smallest = - timings[info->training. - reg178_largest][channel][slot][rank][lane].smallest; - info->training.timing_bounds[1][channel][slot][rank][lane]. - largest = - timings[info->training. - reg178_largest][channel][slot][rank][lane].largest; + + info->training.timing_bounds[0][channel][slot][rank][lane].smallest = timings + [info->training.reg178_smallest][channel][slot][rank][lane].smallest; + + info->training.timing_bounds[0][channel][slot][rank][lane].largest = timings + [info->training.reg178_smallest][channel][slot][rank][lane].largest; + + info->training.timing_bounds[1][channel][slot][rank][lane].smallest = timings + [info->training.reg178_largest][channel][slot][rank][lane].smallest; + + info->training.timing_bounds[1][channel][slot][rank][lane].largest = timings + [info->training.reg178_largest][channel][slot][rank][lane].largest; + info->training.timing_offset[channel][slot][rank][lane] = - info->training.lane_timings[1][channel][slot][rank][lane] - - - info->training.lane_timings[0][channel][slot][rank][lane] + - 64; + info->training.lane_timings[1][channel][slot][rank][lane] - + info->training.lane_timings[0][channel][slot][rank][lane] + 64; }
if (info->silicon_revision == 1 - && (info-> - populated_ranks_mask[1] ^ (info-> - populated_ranks_mask[1] >> 2)) & 1) { + && (info->populated_ranks_mask[1] ^ (info->populated_ranks_mask[1] >> 2)) & 1) { + int ranks_after_channel1;
totalrank = 0; - for (reg_178 = reg178_center - 18; + for (reg_178 = reg178_center - 18; reg_178 <= reg178_center + 18; reg_178 += 18) { + totalrank = 0; set_178(reg_178); - for (slot = 0; slot < NUM_SLOTS; slot++) - for (rank = 0; rank < NUM_RANKS; rank++) { - if (info-> - populated_ranks[1][slot][rank]) { - train_ram_at_178(info, 1, slot, - rank, - totalrank, - reg_178, 0, - niter, - timings); - totalrank++; - } + + for (slot = 0; slot < NUM_SLOTS; slot++) { + for (rank = 0; rank < NUM_RANKS; rank++) { + + if (info->populated_ranks[1][slot][rank]) { + train_ram_at_178(info, 1, slot, rank, totalrank, + reg_178, 0, niter, timings); + totalrank++; } + }} /* for each slot, rank */ } ranks_after_channel1 = totalrank;
- for (reg_178 = reg178_center - 12; + for (reg_178 = reg178_center - 12; reg_178 <= reg178_center + 12; reg_178 += 12) { + totalrank = ranks_after_channel1; set_178(reg_178); - for (slot = 0; slot < NUM_SLOTS; slot++) - for (rank = 0; rank < NUM_RANKS; rank++) - if (info-> - populated_ranks[0][slot][rank]) { - train_ram_at_178(info, 0, slot, - rank, - totalrank, - reg_178, 0, - niter, - timings); - totalrank++; - } + + for (slot = 0; slot < NUM_SLOTS; slot++) { + for (rank = 0; rank < NUM_RANKS; rank++) { + + if (info->populated_ranks[0][slot][rank]) { + train_ram_at_178(info, 0, slot, rank, totalrank, + reg_178, 0, niter, timings); + totalrank++; + } + }} /* for each slot, rank */
} } else { - for (reg_178 = reg178_center - 12; + for (reg_178 = reg178_center - 12; reg_178 <= reg178_center + 12; reg_178 += 12) { + totalrank = 0; set_178(reg_178); + FOR_POPULATED_RANKS_BACKWARDS { - train_ram_at_178(info, channel, slot, rank, - totalrank, reg_178, 0, niter, - timings); + train_ram_at_178(info, channel, slot, rank, totalrank, + reg_178, 0, niter, timings); totalrank++; } } } - set_178(reg178_center); - FOR_POPULATED_RANKS_BACKWARDS for (lane = 0; lane < 8; lane++) { - u16 tm0;
- tm0 = - choose_training(info, channel, slot, rank, lane, timings, - reg178_center); - write_500(info, channel, tm0, - get_timing_register_addr(lane, 0, slot, rank), 9, 1); + FOR_POPULATED_RANKS_BACKWARDS for (lane = 0; lane < 8; lane++) { + + u16 tm0; + tm0 = choose_training(info, channel, slot, rank, lane, timings, reg178_center); + + write_500(info, channel, tm0, get_timing_register_addr(lane, 0, slot, rank), + 9, 1); + write_500(info, channel, - tm0 + - info->training. - lane_timings[1][channel][slot][rank][lane] - - info->training. - lane_timings[0][channel][slot][rank][lane], - get_timing_register_addr(lane, 1, slot, rank), 9, 1); + tm0 + info->training.lane_timings[1][channel][slot][rank][lane] + - info->training.lane_timings[0][channel][slot][rank][lane], + get_timing_register_addr(lane, 1, slot, rank), 9, 1); }
totalrank = 0; @@ -3194,9 +3014,11 @@
if (!try_cached_training(info)) do_ram_training(info); + if ((info->silicon_revision == 2 || info->silicon_revision == 3) - && info->clock_speed_index < 2) + && info->clock_speed_index < 2) set_10b(info, 1); + MCHBAR16(0xfc4) = saved_fc4; }
@@ -3208,7 +3030,7 @@ a = b; b = t; } - /* invariant a < b. */ + /* invariant a < b. */ while (a) { t = b % a; b = a; @@ -3242,27 +3064,25 @@ int freq_max_reduced; };
-static void -compute_frequence_ratios(struct raminfo *info, u16 freq1, u16 freq2, - int num_cycles_2, int num_cycles_1, int round_it, - int add_freqs, struct stru1 *result) +static void compute_frequence_ratios(struct raminfo *info, u16 freq1, u16 freq2, + int num_cycles_2, int num_cycles_1, int round_it, + int add_freqs, struct stru1 *result) { - int g; - int common_time_unit_ps; - int freq1_reduced, freq2_reduced; - int freq_min_reduced; - int freq_max_reduced; - int freq3, freq4; + int g, common_time_unit_ps, freq1_reduced, freq2_reduced, freq3, freq4; + int freq_min_reduced, freq_max_reduced;
g = gcd(freq1, freq2); + freq1_reduced = freq1 / g; freq2_reduced = freq2 / g; + freq_min_reduced = MIN(freq1_reduced, freq2_reduced); freq_max_reduced = MAX(freq1_reduced, freq2_reduced);
common_time_unit_ps = div_roundup(900000, lcm(freq1, freq2)); freq3 = div_roundup(num_cycles_2, common_time_unit_ps) - 1; freq4 = div_roundup(num_cycles_1, common_time_unit_ps) - 1; + if (add_freqs) { freq3 += freq2_reduced; freq4 += freq1_reduced; @@ -3276,47 +3096,51 @@ result->divisor_f3_to_f1 = 0; } else { if (freq2_reduced < freq1_reduced) { - result->freq3_to_2_remainder = - result->freq3_to_2_remaindera = - freq3 % freq1_reduced - freq1_reduced + 1; - result->freq4_to_max_remainder = - -(freq4 % freq1_reduced); + + result->freq3_to_2_remainder = result->freq3_to_2_remaindera = + freq3 % freq1_reduced - freq1_reduced + 1; + + result->freq4_to_max_remainder = -(freq4 % freq1_reduced); + result->divisor_f3_to_f1 = freq3 / freq1_reduced; + result->divisor_f4_to_f2 = - (freq4 - - (freq1_reduced - freq2_reduced)) / freq2_reduced; + (freq4 - (freq1_reduced - freq2_reduced)) / freq2_reduced; + result->freq4_to_2_remainder = - -(char)((freq1_reduced - freq2_reduced) + - ((u8) freq4 - - (freq1_reduced - - freq2_reduced)) % (u8) freq2_reduced); + -(char)((freq1_reduced - freq2_reduced) + ((u8) freq4 - + (freq1_reduced - freq2_reduced)) % (u8) freq2_reduced); + } else { if (freq2_reduced > freq1_reduced) { + result->freq4_to_max_remainder = - (freq4 % freq2_reduced) - freq2_reduced + 1; + (freq4 % freq2_reduced) - freq2_reduced + 1; + result->freq4_to_2_remainder = - freq4 % freq_max_reduced - - freq_max_reduced + 1; + freq4 % freq_max_reduced - freq_max_reduced + 1; + } else { - result->freq4_to_max_remainder = - -(freq4 % freq2_reduced); + result->freq4_to_max_remainder = -(freq4 % freq2_reduced); + result->freq4_to_2_remainder = - -(char)(freq4 % freq_max_reduced); + -(char)(freq4 % freq_max_reduced); } result->divisor_f4_to_f2 = freq4 / freq2_reduced; + result->divisor_f3_to_f1 = - (freq3 - - (freq2_reduced - freq1_reduced)) / freq1_reduced; + (freq3 - (freq2_reduced - freq1_reduced)) / freq1_reduced; + result->freq3_to_2_remainder = -(freq3 % freq2_reduced); + result->freq3_to_2_remaindera = - -(char)((freq_max_reduced - freq_min_reduced) + - (freq3 - - (freq_max_reduced - - freq_min_reduced)) % freq1_reduced); + -(char)((freq_max_reduced - freq_min_reduced) + (freq3 - + (freq_max_reduced - freq_min_reduced)) % freq1_reduced); } } result->divisor_f3_to_fmax = freq3 / freq_max_reduced; result->divisor_f4_to_fmax = freq4 / freq_max_reduced; + if (round_it) { if (freq2_reduced > freq1_reduced) { if (freq3 % freq_max_reduced) @@ -3327,48 +3151,41 @@ result->divisor_f4_to_fmax++; } } - result->freqs_reversed = (freq2_reduced < freq1_reduced); - result->freq_diff_reduced = freq_max_reduced - freq_min_reduced; - result->freq_min_reduced = freq_min_reduced; + + result->freqs_reversed = (freq2_reduced < freq1_reduced); + result->freq_diff_reduced = freq_max_reduced - freq_min_reduced; + result->freq_min_reduced = freq_min_reduced; result->common_time_unit_ps = common_time_unit_ps; - result->freq_max_reduced = freq_max_reduced; + result->freq_max_reduced = freq_max_reduced; }
-static void -set_2d5x_reg(struct raminfo *info, u16 reg, u16 freq1, u16 freq2, - int num_cycles_2, int num_cycles_1, int num_cycles_3, - int num_cycles_4, int reverse) +static void set_2d5x_reg(struct raminfo *info, u16 reg, u16 freq1, u16 freq2, int num_cycles_2, + int num_cycles_1, int num_cycles_3, int num_cycles_4, int reverse) { struct stru1 vv; char multiplier;
- compute_frequence_ratios(info, freq1, freq2, num_cycles_2, num_cycles_1, - 0, 1, &vv); + compute_frequence_ratios(info, freq1, freq2, num_cycles_2, num_cycles_1, 0, 1, &vv);
- multiplier = - div_roundup(MAX - (div_roundup(num_cycles_2, vv.common_time_unit_ps) + - div_roundup(num_cycles_3, vv.common_time_unit_ps), - div_roundup(num_cycles_1, - vv.common_time_unit_ps) + - div_roundup(num_cycles_4, vv.common_time_unit_ps)) - + vv.freq_min_reduced - 1, vv.freq_max_reduced) - 1; + multiplier = div_roundup( + MAX( + div_roundup(num_cycles_2, vv.common_time_unit_ps) + + div_roundup(num_cycles_3, vv.common_time_unit_ps), + div_roundup(num_cycles_1, vv.common_time_unit_ps) + + div_roundup(num_cycles_4, vv.common_time_unit_ps) + ) + vv.freq_min_reduced - 1, vv.freq_max_reduced) - 1;
- u32 y = - (u8) ((vv.freq_max_reduced - vv.freq_min_reduced) + - vv.freq_max_reduced * multiplier) - | (vv. - freqs_reversed << 8) | ((u8) (vv.freq_min_reduced * - multiplier) << 16) | ((u8) (vv. - freq_min_reduced - * - multiplier) - << 24); - u32 x = - vv.freq3_to_2_remaindera | (vv.freq4_to_2_remainder << 8) | (vv. - divisor_f3_to_f1 - << 16) - | (vv.divisor_f4_to_f2 << 20) | (vv.freq_min_reduced << 24); + u32 y = (u8) ((vv.freq_max_reduced - vv.freq_min_reduced) + + vv.freq_max_reduced * multiplier)| (vv.freqs_reversed << 8) | + ((u8) (vv.freq_min_reduced * multiplier) << 16) | + ((u8) (vv.freq_min_reduced * multiplier) << 24); + + u32 x = vv.freq3_to_2_remaindera | + (vv.freq4_to_2_remainder << 8) | + (vv.divisor_f3_to_f1 << 16) | + (vv.divisor_f4_to_f2 << 20) | + (vv.freq_min_reduced << 24); + if (reverse) { MCHBAR32(reg) = y; MCHBAR32(reg + 4) = x; @@ -3378,135 +3195,118 @@ } }
-static void -set_6d_reg(struct raminfo *info, u16 reg, u16 freq1, u16 freq2, - int num_cycles_1, int num_cycles_2, int num_cycles_3, - int num_cycles_4) +static void set_6d_reg(struct raminfo *info, u16 reg, u16 freq1, u16 freq2, int num_cycles_1, + int num_cycles_2, int num_cycles_3, int num_cycles_4) { - struct stru1 ratios1; - struct stru1 ratios2; + struct stru1 vv1; + struct stru1 vv2;
- compute_frequence_ratios(info, freq1, freq2, num_cycles_1, num_cycles_2, - 0, 1, &ratios2); - compute_frequence_ratios(info, freq1, freq2, num_cycles_3, num_cycles_4, - 0, 1, &ratios1); + compute_frequence_ratios(info, freq1, freq2, num_cycles_1, num_cycles_2, 0, 1, &vv2); + compute_frequence_ratios(info, freq1, freq2, num_cycles_3, num_cycles_4, 0, 1, &vv1); + printk(RAM_SPEW, "[%x] <= %x\n", reg, - ratios1.freq4_to_max_remainder | (ratios2. - freq4_to_max_remainder - << 8) - | (ratios1.divisor_f4_to_fmax << 16) | (ratios2. - divisor_f4_to_fmax - << 20)); - MCHBAR32(reg) = ratios1.freq4_to_max_remainder | - (ratios2.freq4_to_max_remainder << 8) | - (ratios1.divisor_f4_to_fmax << 16) | - (ratios2.divisor_f4_to_fmax << 20); + vv1.freq4_to_max_remainder | (vv2.freq4_to_max_remainder << 8) | + (vv1.divisor_f4_to_fmax << 16) | (vv2.divisor_f4_to_fmax << 20)); + + MCHBAR32(reg) = vv1.freq4_to_max_remainder | (vv2.freq4_to_max_remainder << 8) | + (vv1.divisor_f4_to_fmax << 16) | (vv2.divisor_f4_to_fmax << 20); }
-static void -set_2dx8_reg(struct raminfo *info, u16 reg, u8 mode, u16 freq1, u16 freq2, - int num_cycles_2, int num_cycles_1, int round_it, int add_freqs) +static void set_2dx8_reg(struct raminfo *info, u16 reg, u8 mode, u16 freq1, u16 freq2, + int num_cycles_2, int num_cycles_1, int round_it, int add_freqs) { - struct stru1 ratios; + struct stru1 vv;
- compute_frequence_ratios(info, freq1, freq2, num_cycles_2, num_cycles_1, - round_it, add_freqs, &ratios); + compute_frequence_ratios(info, freq1, freq2, num_cycles_2, num_cycles_1, round_it, + add_freqs, &vv); + switch (mode) { case 0: - MCHBAR32(reg + 4) = ratios.freq_diff_reduced | - (ratios.freqs_reversed << 8); - MCHBAR32(reg) = ratios.freq3_to_2_remainder | - (ratios.freq4_to_max_remainder << 8) | - (ratios.divisor_f3_to_fmax << 16) | - (ratios.divisor_f4_to_fmax << 20) | - (ratios.freq_min_reduced << 24); + MCHBAR32(reg + 4) = vv.freq_diff_reduced | (vv.freqs_reversed << 8); + + MCHBAR32(reg) = vv.freq3_to_2_remainder | (vv.freq4_to_max_remainder << 8) | + (vv.divisor_f3_to_fmax << 16) | (vv.divisor_f4_to_fmax << 20) | + (vv.freq_min_reduced << 24); break;
case 1: - MCHBAR32(reg) = ratios.freq3_to_2_remainder | - (ratios.divisor_f3_to_fmax << 16); + MCHBAR32(reg) = vv.freq3_to_2_remainder | (vv.divisor_f3_to_fmax << 16); break;
case 2: - MCHBAR32(reg) = ratios.freq3_to_2_remainder | - (ratios.freq4_to_max_remainder << 8) | - (ratios.divisor_f3_to_fmax << 16) | - (ratios.divisor_f4_to_fmax << 20); + MCHBAR32(reg) = vv.freq3_to_2_remainder | (vv.freq4_to_max_remainder << 8) | + (vv.divisor_f3_to_fmax << 16) | (vv.divisor_f4_to_fmax << 20); break;
case 4: - MCHBAR32(reg) = (ratios.divisor_f3_to_fmax << 4) | - (ratios.divisor_f4_to_fmax << 8) | - (ratios.freqs_reversed << 12) | - (ratios.freq_min_reduced << 16) | - (ratios.freq_diff_reduced << 24); + MCHBAR32(reg) = (vv.divisor_f3_to_fmax << 4) | (vv.divisor_f4_to_fmax << 8) | + (vv.freqs_reversed << 12) | (vv.freq_min_reduced << 16) | + (vv.freq_diff_reduced << 24); break; } }
static void set_2dxx_series(struct raminfo *info, int s3resume) { - set_2dx8_reg(info, 0x2d00, 0, 0x78, frequency_11(info) / 2, 1359, 1005, - 0, 1); + set_2dx8_reg(info, 0x2d00, 0, 0x78, frequency_11(info) / 2, 1359, 1005, 0, 1); + set_2dx8_reg(info, 0x2d08, 0, 0x78, 0x78, 3273, 5033, 1, 1); - set_2dx8_reg(info, 0x2d10, 0, 0x78, info->fsb_frequency, 1475, 1131, 0, + + set_2dx8_reg(info, 0x2d10, 0, 0x78, info->fsb_frequency, 1475, 1131, 0, 1); + + set_2dx8_reg(info, 0x2d18, 0, 2 * info->fsb_frequency, frequency_11(info), 1231, 1524, + 0, 1); + set_2dx8_reg(info, 0x2d20, 0, 2 * info->fsb_frequency, frequency_11(info) / 2, 1278, + 2008, 0, 1); + set_2dx8_reg(info, 0x2d28, 0, info->fsb_frequency, frequency_11(info), 1167, 1539, 0, 1); - set_2dx8_reg(info, 0x2d18, 0, 2 * info->fsb_frequency, - frequency_11(info), 1231, 1524, 0, 1); - set_2dx8_reg(info, 0x2d20, 0, 2 * info->fsb_frequency, - frequency_11(info) / 2, 1278, 2008, 0, 1); - set_2dx8_reg(info, 0x2d28, 0, info->fsb_frequency, frequency_11(info), - 1167, 1539, 0, 1); - set_2dx8_reg(info, 0x2d30, 0, info->fsb_frequency, - frequency_11(info) / 2, 1403, 1318, 0, 1); - set_2dx8_reg(info, 0x2d38, 0, info->fsb_frequency, 0x78, 3460, 5363, 1, - 1); - set_2dx8_reg(info, 0x2d40, 0, info->fsb_frequency, 0x3c, 2792, 5178, 1, - 1); - set_2dx8_reg(info, 0x2d48, 0, 2 * info->fsb_frequency, 0x78, 2738, 4610, - 1, 1); - set_2dx8_reg(info, 0x2d50, 0, info->fsb_frequency, 0x78, 2819, 5932, 1, - 1); - set_2dx8_reg(info, 0x6d4, 1, info->fsb_frequency, - frequency_11(info) / 2, 4000, 0, 0, 0); - set_2dx8_reg(info, 0x6d8, 2, info->fsb_frequency, - frequency_11(info) / 2, 4000, 4000, 0, 0); + set_2dx8_reg(info, 0x2d30, 0, info->fsb_frequency, frequency_11(info) / 2, 1403, 1318, + 0, 1); + set_2dx8_reg(info, 0x2d38, 0, info->fsb_frequency, 0x78, 3460, 5363, 1, 1); + + set_2dx8_reg(info, 0x2d40, 0, info->fsb_frequency, 0x3c, 2792, 5178, 1, 1); + + set_2dx8_reg(info, 0x2d48, 0, 2 * info->fsb_frequency, 0x78, 2738, 4610, 1, 1); + + set_2dx8_reg(info, 0x2d50, 0, info->fsb_frequency, 0x78, 2819, 5932, 1, 1); + + set_2dx8_reg(info, 0x6d4, 1, info->fsb_frequency, frequency_11(info) / 2, 4000, 0, 0, + 0); + set_2dx8_reg(info, 0x6d8, 2, info->fsb_frequency, frequency_11(info) / 2, 4000, 4000, + 0, 0);
if (s3resume) { - printk(RAM_SPEW, "[6dc] <= %x\n", - info->cached_training->reg_6dc); + printk(RAM_SPEW, "[6dc] <= %x\n", info->cached_training->reg_6dc); MCHBAR32(0x6dc) = info->cached_training->reg_6dc; - } else + } else { set_6d_reg(info, 0x6dc, 2 * info->fsb_frequency, frequency_11(info), 0, - info->delay46_ps[0], 0, - info->delay54_ps[0]); - set_2dx8_reg(info, 0x6e0, 1, 2 * info->fsb_frequency, - frequency_11(info), 2500, 0, 0, 0); - set_2dx8_reg(info, 0x6e4, 1, 2 * info->fsb_frequency, - frequency_11(info) / 2, 3500, 0, 0, 0); + info->delay46_ps[0], 0, info->delay54_ps[0]); + } + + set_2dx8_reg(info, 0x6e0, 1, 2 * info->fsb_frequency, frequency_11(info), 2500, 0, 0, + 0); + set_2dx8_reg(info, 0x6e4, 1, 2 * info->fsb_frequency, frequency_11(info) / 2, 3500, 0, + 0, 0); + if (s3resume) { - printk(RAM_SPEW, "[6e8] <= %x\n", - info->cached_training->reg_6e8); + printk(RAM_SPEW, "[6e8] <= %x\n", info->cached_training->reg_6e8); MCHBAR32(0x6e8) = info->cached_training->reg_6e8; - } else + } else { set_6d_reg(info, 0x6e8, 2 * info->fsb_frequency, frequency_11(info), 0, - info->delay46_ps[1], 0, - info->delay54_ps[1]); + info->delay46_ps[1], 0, info->delay54_ps[1]); + } + set_2d5x_reg(info, 0x2d58, 0x78, 0x78, 864, 1195, 762, 786, 0); - set_2d5x_reg(info, 0x2d60, 0x195, info->fsb_frequency, 1352, 725, 455, - 470, 0); + set_2d5x_reg(info, 0x2d60, 0x195, info->fsb_frequency, 1352, 725, 455, 470, 0); set_2d5x_reg(info, 0x2d68, 0x195, 0x3c, 2707, 5632, 3277, 2207, 0); - set_2d5x_reg(info, 0x2d70, 0x195, frequency_11(info) / 2, 1276, 758, - 454, 459, 0); + set_2d5x_reg(info, 0x2d70, 0x195, frequency_11(info) / 2, 1276, 758, 454, 459, 0); set_2d5x_reg(info, 0x2d78, 0x195, 0x78, 1021, 799, 510, 513, 0); - set_2d5x_reg(info, 0x2d80, info->fsb_frequency, 0xe1, 0, 2862, 2579, - 2588, 0); - set_2d5x_reg(info, 0x2d88, info->fsb_frequency, 0xe1, 0, 2690, 2405, - 2405, 0); + set_2d5x_reg(info, 0x2d80, info->fsb_frequency, 0xe1, 0, 2862, 2579, 2588, 0); + set_2d5x_reg(info, 0x2d88, info->fsb_frequency, 0xe1, 0, 2690, 2405, 2405, 0); set_2d5x_reg(info, 0x2da0, 0x78, 0xe1, 0, 2560, 2264, 2251, 0); - set_2d5x_reg(info, 0x2da8, 0x195, frequency_11(info), 1060, 775, 484, - 480, 0); + set_2d5x_reg(info, 0x2da8, 0x195, frequency_11(info), 1060, 775, 484, 480, 0); set_2d5x_reg(info, 0x2db0, 0x195, 0x78, 4183, 6023, 2217, 2048, 0); + MCHBAR32(0x2dbc) = ((frequency_11(info) / 2) - 1) | 0xe00000; MCHBAR32(0x2db8) = ((info->fsb_frequency - 1) << 16) | 0x77; } @@ -3522,14 +3322,16 @@ if (info->revision < 8) return 256;
- for (slot = 0; slot < NUM_SLOTS; slot++) - for (rank = 0; rank < NUM_RANKS; rank++) - if (info->populated_ranks[channel][slot][rank]) - for (lane = 0; lane < 8 + info->use_ecc; lane++) - ret = MAX(ret, read_500(info, channel, - get_timing_register_addr - (lane, 0, slot, - rank), 9)); + for (slot = 0; slot < NUM_SLOTS; slot++) { + for (rank = 0; rank < NUM_RANKS; rank++) { + if (info->populated_ranks[channel][slot][rank]) { + for (lane = 0; lane < 8 + info->use_ecc; lane++) { + + ret = MAX(ret, read_500(info, channel, + get_timing_register_addr(lane, 0, slot, rank), 9)); + + }}}} /* for each slot, rank, if populated, for each lane */ + return ret; }
@@ -3543,49 +3345,58 @@
delay_a_ps = 4 * halfcycle_ps(info) + 6 * fsbcycle_ps(info); info->training.reg2ca9_bit0 = 0; + for (channel = 0; channel < NUM_CHANNELS; channel++) { - cycletime_ps = - 900000 / lcm(2 * info->fsb_frequency, frequency_11(info)); - delay_d_ps = - (halfcycle_ps(info) * get_max_timing(info, channel) >> 6) - - info->some_delay_3_ps_rounded + 200; - if (! - ((info->silicon_revision == 0 - || info->silicon_revision == 1) - && (info->revision >= 8))) + + cycletime_ps = 900000 / lcm(2 * info->fsb_frequency, frequency_11(info)); + + delay_d_ps = (halfcycle_ps(info) * get_max_timing(info, channel) >> 6) - + info->some_delay_3_ps_rounded + 200; + + if (!((info->silicon_revision == 0 || info->silicon_revision == 1) + && (info->revision >= 8))) { delay_d_ps += halfcycle_ps(info) * 2; - delay_d_ps += - halfcycle_ps(info) * (!info->revision_flag_1 + - info->some_delay_2_halfcycles_ceil + - 2 * info->some_delay_1_cycle_floor + - info->clock_speed_index + - 2 * info->cas_latency - 7 + 11); + } + + delay_d_ps += halfcycle_ps(info) * (!info->revision_flag_1 + + info->some_delay_2_halfcycles_ceil + 2 * + info->some_delay_1_cycle_floor + info->clock_speed_index + 2 * + info->cas_latency - 7 + 11); + delay_d_ps += info->revision >= 8 ? 2758 : 4428;
MCHBAR32_AND_OR(0x140, 0xfaffffff, 0x2000000); + MCHBAR32_AND_OR(0x138, 0xfaffffff, 0x2000000); + if ((MCHBAR8(0x144) & 0x1f) > 0x13) delay_d_ps += 650; + delay_c_ps = delay_d_ps + 1800; - if (delay_c_ps <= delay_a_ps) + + if (delay_c_ps <= delay_a_ps) { delay_e_ps = 0; - else - delay_e_ps = - cycletime_ps * div_roundup(delay_c_ps - delay_a_ps, - cycletime_ps); + } else { + delay_e_ps = cycletime_ps * + div_roundup(delay_c_ps - delay_a_ps, cycletime_ps); + }
delay_e_over_cycle_ps = delay_e_ps % (2 * halfcycle_ps(info)); + delay_e_cycles = delay_e_ps / (2 * halfcycle_ps(info)); - delay_f_cycles = - div_roundup(2500 - delay_e_over_cycle_ps, - 2 * halfcycle_ps(info)); + + delay_f_cycles = div_roundup(2500 - delay_e_over_cycle_ps, + 2 * halfcycle_ps(info)); + if (delay_f_cycles > delay_e_cycles) { + info->delay46_ps[channel] = delay_e_ps; delay_e_cycles = 0; + } else { info->delay46_ps[channel] = - delay_e_over_cycle_ps + - 2 * halfcycle_ps(info) * delay_f_cycles; + delay_e_over_cycle_ps + 2 * halfcycle_ps(info) * delay_f_cycles; + delay_e_cycles -= delay_f_cycles; }
@@ -3593,34 +3404,43 @@ info->delay46_ps[channel] = 2500; info->training.reg2ca9_bit0 = 1; } + delay_b_ps = halfcycle_ps(info) + delay_c_ps; - if (delay_b_ps <= delay_a_ps) + + if (delay_b_ps <= delay_a_ps) { delay_b_ps = 0; - else + } else { delay_b_ps -= delay_a_ps; + } + info->delay54_ps[channel] = - cycletime_ps * div_roundup(delay_b_ps, - cycletime_ps) - - 2 * halfcycle_ps(info) * delay_e_cycles; + cycletime_ps * div_roundup(delay_b_ps, cycletime_ps) - 2 * + halfcycle_ps(info) * delay_e_cycles; + if (info->delay54_ps[channel] < 2500) info->delay54_ps[channel] = 2500; + info->training.reg274265[channel][0] = delay_e_cycles; - if (delay_d_ps + 7 * halfcycle_ps(info) <= - 24 * halfcycle_ps(info)) + + if (delay_d_ps + 7 * halfcycle_ps(info) <= 24 * halfcycle_ps(info)) { + info->training.reg274265[channel][1] = 0; - else - info->training.reg274265[channel][1] = - div_roundup(delay_d_ps + 7 * halfcycle_ps(info), - 4 * halfcycle_ps(info)) - 6; + + } else { + info->training.reg274265[channel][1] = div_roundup(delay_d_ps + 7 * + halfcycle_ps(info), 4 * halfcycle_ps(info)) - 6; + } + MCHBAR32((channel << 10) + 0x274) = - info->training.reg274265[channel][1] | + info->training.reg274265[channel][1] | (info->training.reg274265[channel][0] << 16); - info->training.reg274265[channel][2] = - div_roundup(delay_c_ps + 3 * fsbcycle_ps(info), - 4 * halfcycle_ps(info)) + 1; - MCHBAR16((channel << 10) + 0x265) = - info->training.reg274265[channel][2] << 8; + + info->training.reg274265[channel][2] = div_roundup(delay_c_ps + 3 * + fsbcycle_ps(info), 4 * halfcycle_ps(info)) + 1; + + MCHBAR16((channel << 10) + 0x265) = info->training.reg274265[channel][2] << 8; } + if (info->training.reg2ca9_bit0) MCHBAR8_OR(0x2ca9, 1); else @@ -3634,10 +3454,12 @@ for (channel = 0; channel < NUM_CHANNELS; channel++) { MCHBAR32((channel << 10) + 0x274) = (info->cached_training->reg274265[channel][0] << 16) | - info->cached_training->reg274265[channel][1]; + info->cached_training->reg274265[channel][1]; + MCHBAR16((channel << 10) + 0x265) = info->cached_training->reg274265[channel][2] << 8; } + if (info->cached_training->reg2ca9_bit0) MCHBAR8_OR(0x2ca9, 1); else @@ -3647,24 +3469,27 @@ static void dmi_setup(void) { gav(read8(DEFAULT_DMIBAR + 0x254)); + write8(DEFAULT_DMIBAR + 0x254, 0x1); write16(DEFAULT_DMIBAR + 0x1b8, 0x18f2); + MCHBAR16_AND_OR(0x48, 0, 0x2);
write32(DEFAULT_DMIBAR + 0xd68, read32(DEFAULT_DMIBAR + 0xd68) | 0x08000000);
outl((gav(inl(DEFAULT_GPIOBASE | 0x38)) & ~0x140000) | 0x400000, - DEFAULT_GPIOBASE | 0x38); + DEFAULT_GPIOBASE | 0x38); + gav(inb(DEFAULT_GPIOBASE | 0xe)); // = 0xfdcaff6e }
void chipset_init(const int s3resume) { - u8 x2ca8; + u8 x2ca8, gfxsize; u16 ggc; - u8 gfxsize;
x2ca8 = MCHBAR8(0x2ca8); + if ((x2ca8 & 1) || (x2ca8 == 8 && !s3resume)) { printk(BIOS_DEBUG, "soft reset detected, rebooting properly\n"); MCHBAR8(0x2ca8) = 0; @@ -3680,7 +3505,7 @@ dmi_setup();
MCHBAR16(0x1170) = 0xa880; - MCHBAR8(0x11c1) = 0x1; + MCHBAR8(0x11c1) = 0x1; MCHBAR16(0x1170) = 0xb880; MCHBAR8_AND_OR(0x1210, 0, 0x84);
@@ -3693,26 +3518,30 @@
pci_write_config16(NORTHBRIDGE, D0F0_GGC, ggc | 2);
- u16 deven; - deven = pci_read_config16(NORTHBRIDGE, D0F0_DEVEN); // = 0x3 + u16 deven = pci_read_config16(NORTHBRIDGE, D0F0_DEVEN); // = 0x3
if (deven & 8) { MCHBAR8(0x2c30) = 0x20; + pci_read_config8(NORTHBRIDGE, 0x8); // = 0x18 + MCHBAR16_OR(0x2c30, 0x200); MCHBAR16(0x2c32) = 0x434; MCHBAR32_AND_OR(0x2c44, 0, 0x1053687); + pci_read_config8(GMA, 0x62); // = 0x2 pci_write_config8(GMA, 0x62, 0x2); - read8(DEFAULT_RCBA + 0x2318); + + read8(DEFAULT_RCBA + 0x2318); write8(DEFAULT_RCBA + 0x2318, 0x47); - read8(DEFAULT_RCBA + 0x2320); + read8(DEFAULT_RCBA + 0x2320); write8(DEFAULT_RCBA + 0x2320, 0xfc); }
MCHBAR32_AND_OR(0x30, 0, 0x40);
pci_write_config16(NORTHBRIDGE, D0F0_GGC, ggc); + gav(read32(DEFAULT_RCBA + 0x3428)); write32(DEFAULT_RCBA + 0x3428, 0x1d); } @@ -3767,38 +3596,28 @@ info.use_ecc = 1; for (channel = 0; channel < NUM_CHANNELS; channel++) for (slot = 0; slot < NUM_SLOTS; slot++) { - int v; - int try; - int addr; - const u8 useful_addresses[] = { - DEVICE_TYPE, - MODULE_TYPE, - DENSITY, - RANKS_AND_DQ, - MEMORY_BUS_WIDTH, - TIMEBASE_DIVIDEND, - TIMEBASE_DIVISOR, - CYCLETIME, - CAS_LATENCIES_LSB, - CAS_LATENCIES_MSB, + + int v, try, addr; + + const u8 spd_bytes[] = { + DEVICE_TYPE, MODULE_TYPE, DENSITY, RANKS_AND_DQ, + MEMORY_BUS_WIDTH, TIMEBASE_DIVIDEND, TIMEBASE_DIVISOR, + CYCLETIME, CAS_LATENCIES_LSB, CAS_LATENCIES_MSB, CAS_LATENCY_TIME, - 0x11, 0x12, 0x13, 0x14, 0x15, - 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x1c, 0x1d, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1a, 0x1b, 0x1c, 0x1d, THERMAL_AND_REFRESH, 0x20, - REFERENCE_RAW_CARD_USED, - RANK1_ADDRESS_MAPPING, - 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, - 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, - 0x85, 0x86, 0x87, 0x88, - 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, - 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, - 0x95 + REFERENCE_RAW_CARD_USED, RANK1_ADDRESS_MAPPING, + 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, + 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, + 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95 }; + if (!spd_addrmap[2 * channel + slot]) continue; + for (try = 0; try < 5; try++) { v = smbus_read_byte(spd_addrmap[2 * channel + slot], DEVICE_TYPE); @@ -3807,40 +3626,38 @@ } if (v < 0) continue; - for (addr = 0; - addr < - sizeof(useful_addresses) / - sizeof(useful_addresses[0]); addr++) - gav(info. - spd[channel][0][useful_addresses - [addr]] = - smbus_read_byte(spd_addrmap[2 * channel + slot], - useful_addresses - [addr])); + + for (addr = 0; addr < ARRAY_SIZE(spd_bytes); addr++) { + gav(info.spd[channel][0][spd_bytes[addr]] = + smbus_read_byte(spd_addrmap[2 * channel + slot], + spd_bytes[addr])); + } + if (info.spd[channel][0][DEVICE_TYPE] != 11) die("Only DDR3 is supported");
v = info.spd[channel][0][RANKS_AND_DQ]; + info.populated_ranks[channel][0][0] = 1; - info.populated_ranks[channel][0][1] = - ((v >> 3) & 7); + info.populated_ranks[channel][0][1] = ((v >> 3) & 7); + if (((v >> 3) & 7) > 1) die("At most 2 ranks are supported"); + if ((v & 7) == 0 || (v & 7) > 2) die("Only x8 and x16 modules are supported"); - if ((info. - spd[channel][slot][MODULE_TYPE] & 0xF) != 2 - && (info. - spd[channel][slot][MODULE_TYPE] & 0xF) - != 3) + + if ((info.spd[channel][slot][MODULE_TYPE] & 0xf) != 2 + && (info.spd[channel][slot][MODULE_TYPE] & 0xf) != 3) { + die("Registered memory is not supported"); + } + info.is_x16_module[channel][0] = (v & 7) - 1; info.density[channel][slot] = - info.spd[channel][slot][DENSITY] & 0xF; - if (! - (info. - spd[channel][slot][MEMORY_BUS_WIDTH] & - 0x18)) + info.spd[channel][slot][DENSITY] & 0xF; + + if (!(info.spd[channel][slot][MEMORY_BUS_WIDTH] & 0x18)) info.use_ecc = 0; }
@@ -3848,11 +3665,12 @@
for (channel = 0; channel < NUM_CHANNELS; channel++) { int v = 0; - for (slot = 0; slot < NUM_SLOTS; slot++) - for (rank = 0; rank < NUM_RANKS; rank++) - v |= info. - populated_ranks[channel][slot][rank] - << (2 * slot + rank); + for (slot = 0; slot < NUM_SLOTS; slot++) { + for (rank = 0; rank < NUM_RANKS; rank++) { + v |= info.populated_ranks[channel][slot][rank] << + (2 * slot + rank); + } + } info.populated_ranks_mask[channel] = v; }
@@ -3861,7 +3679,7 @@ gav(pci_read_config32(NORTHBRIDGE, D0F0_CAPID0 + 4)); }
- /* after SPD */ + /* After SPD */ timestamp_add_now(102);
MCHBAR8_AND(0x2ca8, 0xfc); @@ -3876,25 +3694,18 @@ if (!s3resume) { u8 reg8 = pci_read_config8(SOUTHBRIDGE, GEN_PMCON_2); if (x2ca8 == 0 && (reg8 & 0x80)) { - /* Don't enable S4-assertion stretch. Makes trouble on roda/rk9. - reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4); - pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, reg8 | 0x08); - */
/* Clear bit7. */ + pci_write_config8(SOUTHBRIDGE, GEN_PMCON_2, (reg8 & ~(1 << 7)));
- pci_write_config8(SOUTHBRIDGE, GEN_PMCON_2, - (reg8 & ~(1 << 7))); - - printk(BIOS_INFO, - "Interrupted RAM init, reset required.\n"); + printk(BIOS_INFO, "Interrupted RAM init, reset required.\n"); system_reset(); } }
if (!s3resume && x2ca8 == 0) - pci_write_config8(SOUTHBRIDGE, GEN_PMCON_2, - pci_read_config8(SOUTHBRIDGE, GEN_PMCON_2) | 0x80); + pci_write_config8(SOUTHBRIDGE, GEN_PMCON_2, pci_read_config8 + (SOUTHBRIDGE, GEN_PMCON_2) | 0x80);
compute_derived_timings(&info);
@@ -4007,21 +3818,24 @@ if (x2ca8 == 0) { int j; if (s3resume && info.cached_training) { + restore_274265(&info); printk(RAM_SPEW, "reg2ca9_bit0 = %x\n", info.cached_training->reg2ca9_bit0); + for (i = 0; i < 2; i++) for (j = 0; j < 3; j++) - printk(RAM_SPEW, "reg274265[%d][%d] = %x\n", - i, j, info.cached_training->reg274265[i][j]); + printk(RAM_SPEW, "reg274265[%d][%d] = %x\n", i, j, + info.cached_training->reg274265[i][j]); } else { set_274265(&info); printk(RAM_SPEW, "reg2ca9_bit0 = %x\n", info.training.reg2ca9_bit0); + for (i = 0; i < 2; i++) for (j = 0; j < 3; j++) - printk(RAM_SPEW, "reg274265[%d][%d] = %x\n", - i, j, info.training.reg274265[i][j]); + printk(RAM_SPEW, "reg274265[%d][%d] = %x\n", i, j, + info.training.reg274265[i][j]); }
set_2dxx_series(&info, s3resume); @@ -4238,13 +4052,15 @@ if (x2ca8 == 0) { MCHBAR8_AND(0x2ca8, ~3); MCHBAR8(0x2ca8) = MCHBAR8(0x2ca8) + 4; // "+" or "|"? + /* This issues a CPU reset without resetting the platform */ printk(BIOS_DEBUG, "Issuing a CPU reset\n"); - /* Write back the S3 state to PM1_CNT to let the reset CPU - know it also needs to take the s3 path. */ + + /* Write back the S3 state to PM1_CNT to let the reset CPU know it also needs + * to take the S3 path. */ if (s3resume) - write_pmbase32(PM1_CNT, read_pmbase32(PM1_CNT) - | (SLP_TYP_S3 << 10)); + write_pmbase32(PM1_CNT, read_pmbase32(PM1_CNT) | (SLP_TYP_S3 << 10)); + MCHBAR32_OR(0x1af0, 0x10); halt(); } @@ -4256,22 +4072,28 @@ MCHBAR16(0x2c10); // !!!! MCHBAR16(0x2c00); // !!!! MCHBAR16(0x2c00) = 0x8c0; + udelay(1000); + write_1d0(0, 0x33d, 0, 0); write_500(&info, 0, 0, 0xb61, 0, 0); write_500(&info, 1, 0, 0xb61, 0, 0); MCHBAR32(0x1a30) = 0x0; MCHBAR32(0x1a34) = 0x0; - MCHBAR16(0x614) = 0xb5b | (info.populated_ranks[1][0][0] * 0x404) | - (info.populated_ranks[0][0][0] * 0xa0); + + MCHBAR16(0x614) = 0xb5b | (info.populated_ranks[1][0][0] * 0x404) + | (info.populated_ranks[0][0][0] * 0xa0); + MCHBAR16(0x616) = 0x26a; MCHBAR32(0x134) = 0x856000; MCHBAR32(0x160) = 0x5ffffff; MCHBAR32_AND_OR(0x114, 0, 0xc2024440); // !!!! MCHBAR32_AND_OR(0x118, 0, 0x4); // !!!! + for (channel = 0; channel < NUM_CHANNELS; channel++) - MCHBAR32(0x260 + (channel << 10)) = 0x30809ff | - ((info.populated_ranks_mask[channel] & 3) << 20); + MCHBAR32(0x260 + (channel << 10)) = + 0x30809ff | ((info.populated_ranks_mask[channel] & 3) << 20); + for (channel = 0; channel < NUM_CHANNELS; channel++) { MCHBAR16(0x31c + (channel << 10)) = 0x101; MCHBAR16(0x360 + (channel << 10)) = 0x909; @@ -4296,10 +4118,9 @@
rmw_1d0(0x21c, 0x38, 0, 6, 1);
- write_1d0(((!info.populated_ranks[1][0][0]) << 1) | ((!info. - populated_ranks[0] - [0][0]) << 0), - 0x1d1, 3, 1); + write_1d0(((!info.populated_ranks[1][0][0]) << 1) | + ((!info.populated_ranks[0][0][0]) << 0), 0x1d1, 3, 1); + for (channel = 0; channel < NUM_CHANNELS; channel++) { MCHBAR16(0x38e + (channel << 10)) = 0x5f5f; MCHBAR16(0x3d2 + (channel << 10)) = 0x5f5f; @@ -4311,16 +4132,16 @@
MCHBAR8_OR(0x5ff, 0x80);
- write_1d0(0x2, 0x1d5, 2, 1); + write_1d0(0x02, 0x1d5, 2, 1); write_1d0(0x20, 0x166, 7, 1); - write_1d0(0x0, 0xeb, 3, 1); - write_1d0(0x0, 0xf3, 6, 1); + write_1d0(0x00, 0x0eb, 3, 1); + write_1d0(0x00, 0x0f3, 6, 1);
for (channel = 0; channel < NUM_CHANNELS; channel++) for (lane = 0; lane < 9; lane++) { + u16 addr = 0x125 + get_lane_offset(0, 0, lane); - u8 a; - a = read_500(&info, channel, addr, 6); // = 0x20040080 //!!!! + u8 a = read_500(&info, channel, addr, 6); // = 0x20040080 //!!!! write_500(&info, channel, a, addr, 6, 1); }
@@ -4328,31 +4149,28 @@
if (s3resume) { if (info.cached_training == NULL) { + u32 reg32; - printk(BIOS_ERR, - "Couldn't find training data. Rebooting\n"); + printk(BIOS_ERR, "Couldn't find training data. Rebooting\n"); reg32 = inl(DEFAULT_PMBASE + 0x04); outl(reg32 & ~(7 << 10), DEFAULT_PMBASE + 0x04); full_reset(); } int tm; info.training = *info.cached_training; - for (tm = 0; tm < 4; tm++) - for (channel = 0; channel < NUM_CHANNELS; channel++) - for (slot = 0; slot < NUM_SLOTS; slot++) - for (rank = 0; rank < NUM_RANKS; rank++) - for (lane = 0; lane < 9; lane++) - write_500(&info, - channel, - info.training. - lane_timings - [tm][channel] - [slot][rank] - [lane], - get_timing_register_addr - (lane, tm, - slot, rank), - 9, 0); + + for (tm = 0; tm < 4; tm++) { + for (channel = 0; channel < NUM_CHANNELS; channel++) { + for (slot = 0; slot < NUM_SLOTS; slot++) { + for (rank = 0; rank < NUM_RANKS; rank++) { + for (lane = 0; lane < 9; lane++) { + + write_500(&info, channel, + info.training.lane_timings[tm][channel][slot][rank][lane], + get_timing_register_addr(lane, tm, slot, rank), 9, 0); + + }}}}} /* for each tm, channel, slot, rank, lane */ + write_1d0(info.cached_training->reg_178, 0x178, 7, 1); write_1d0(info.cached_training->reg_10b, 0x10b, 6, 1); } @@ -4371,6 +4189,7 @@ MCHBAR32_AND(0x130, 0xfffffffd); // | 2 when ? while (MCHBAR32(0x130) & 1) ; + gav(read_1d0(0x14b, 7)); // = 0x81023100 write_1d0(0x30, 0x14b, 7, 1); read_1d0(0xd6, 6); // = 0xfa008080 // !!!! @@ -4379,8 +4198,7 @@ write_1d0(7, 0x328, 6, 1);
for (channel = 0; channel < NUM_CHANNELS; channel++) - set_4cf(&info, channel, - info.populated_ranks[channel][0][0] ? 8 : 0); + set_4cf(&info, channel, info.populated_ranks[channel][0][0] ? 8 : 0);
read_1d0(0x116, 4); // = 0x4040432 // !!!! write_1d0(2, 0x116, 4, 1); @@ -4393,49 +4211,46 @@ MCHBAR32_AND(0x140, ~0x07000000); MCHBAR32_AND(0x138, ~0x07000000); MCHBAR32(0x130) = 0x31111301; + /* Wait until REG130b0 is 1. */ while (MCHBAR32(0x130) & 1) ;
- { - u32 t; - u8 val_a1; - val_a1 = read_1d0(0xa1, 6); // = 0x1cf4040 // !!!! - t = read_1d0(0x2f3, 6); // = 0x10a4040 // !!!! - rmw_1d0(0x320, 0x07, - (t & 4) | ((t & 8) >> 2) | ((t & 0x10) >> 4), 6, 1); - rmw_1d0(0x14b, 0x78, - ((((val_a1 >> 2) & 4) | (val_a1 & 8)) >> 2) | (val_a1 & - 4), 7, - 1); - rmw_1d0(0xce, 0x38, - ((((val_a1 >> 2) & 4) | (val_a1 & 8)) >> 2) | (val_a1 & - 4), 6, - 1); - } + + u32 t; + u8 val_a1 = read_1d0(0xa1, 6); // = 0x1cf4040 // !!!! + t = read_1d0(0x2f3, 6); // = 0x10a4040 // !!!! + + rmw_1d0(0x320, 0x07, (t & 4) | ((t & 8) >> 2) | ((t & 0x10) >> 4), 6, 1); + rmw_1d0(0x14b, 0x78, ((((val_a1 >> 2) & 4) | (val_a1 & 8)) >> 2) | (val_a1 & 4), 7, 1); + rmw_1d0(0x0ce, 0x38, ((((val_a1 >> 2) & 4) | (val_a1 & 8)) >> 2) | (val_a1 & 4), 6, 1); +
for (channel = 0; channel < NUM_CHANNELS; channel++) - set_4cf(&info, channel, - info.populated_ranks[channel][0][0] ? 9 : 1); + set_4cf(&info, channel, info.populated_ranks[channel][0][0] ? 9 : 1);
rmw_1d0(0x116, 0xe, 1, 4, 1); // = 0x4040432 // !!!! MCHBAR32(0x144); // !!!! + write_1d0(2, 0xae, 6, 1); write_1d0(2, 0x300, 6, 1); write_1d0(2, 0x121, 3, 1); + read_1d0(0xd6, 6); // = 0xfa00c0c7 // !!!! write_1d0(4, 0xd6, 6, 1); read_1d0(0x328, 6); // = 0xfa00c0c7 // !!!! write_1d0(4, 0x328, 6, 1);
for (channel = 0; channel < NUM_CHANNELS; channel++) - set_4cf(&info, channel, - info.populated_ranks[channel][0][0] ? 9 : 0); + set_4cf(&info, channel, info.populated_ranks[channel][0][0] ? 9 : 0);
- MCHBAR32(0x130) = 0x11111301 | (info.populated_ranks[1][0][0] << 30) | - (info.populated_ranks[0][0][0] << 29); + MCHBAR32(0x130) = 0x11111301 + | (info.populated_ranks[1][0][0] << 30) + | (info.populated_ranks[0][0][0] << 29); + while (MCHBAR8(0x130) & 1) ; + read_1d0(0xa1, 6); // = 0x1cf4054 // !!!! read_1d0(0x2f3, 6); // = 0x10a4054 // !!!! read_1d0(0x21c, 6); // = 0xafa00c0 // !!!! @@ -4444,23 +4259,24 @@ write_1d0(0x35, 0x14b, 7, 1);
for (channel = 0; channel < NUM_CHANNELS; channel++) - set_4cf(&info, channel, - info.populated_ranks[channel][0][0] ? 0xb : 0x2); + set_4cf(&info, channel, info.populated_ranks[channel][0][0] ? 0xb : 0x2);
set_334(1);
MCHBAR8(0x1e8) = 0x4;
for (channel = 0; channel < NUM_CHANNELS; channel++) { - write_500(&info, channel, - 0x3 & ~(info.populated_ranks_mask[channel]), 0x6b7, 2, - 1); + + write_500(&info, channel, 0x3 & ~(info.populated_ranks_mask[channel]), 0x6b7, + 2, 1); write_500(&info, channel, 0x3, 0x69b, 2, 1); } + MCHBAR32_AND_OR(0x2d0, 0xff2c01ff, 0x200000); MCHBAR16(0x6c0) = 0x14a0; MCHBAR32_AND_OR(0x6d0, 0xff0080ff, 0x8000); MCHBAR16(0x232) = 0x8; + /* 0x40004 or 0 depending on ? */ MCHBAR32_AND_OR(0x234, 0xfffbfffb, 0x40004); MCHBAR32_AND_OR(0x34, 0xfffffffd, 5); @@ -4472,11 +4288,15 @@ MCHBAR8(0x271) = 0x2; MCHBAR8(0x671) = 0x2; MCHBAR8(0x1e8) = 0x4; - for (channel = 0; channel < NUM_CHANNELS; channel++) + + for (channel = 0; channel < NUM_CHANNELS; channel++) { MCHBAR32(0x294 + (channel << 10)) = (info.populated_ranks_mask[channel] & 3) << 16; + } + MCHBAR32_AND_OR(0x134, 0xfc01ffff, 0x10000); MCHBAR32_AND_OR(0x134, 0xfc85ffff, 0x850000); + for (channel = 0; channel < NUM_CHANNELS; channel++) MCHBAR32_AND_OR(0x260 + (channel << 10), ~0xf00000, 0x8000000 | ((info.populated_ranks_mask[channel] & 3) << 20)); @@ -4485,14 +4305,15 @@ jedec_init(&info);
int totalrank = 0; - for (channel = 0; channel < NUM_CHANNELS; channel++) - for (slot = 0; slot < NUM_SLOTS; slot++) - for (rank = 0; rank < NUM_RANKS; rank++) - if (info.populated_ranks[channel][slot][rank]) { - jedec_read(&info, channel, slot, rank, - totalrank, 0xa, 0x400); - totalrank++; - } + + for (channel = 0; channel < NUM_CHANNELS; channel++) { + for (slot = 0; slot < NUM_SLOTS; slot++) { + for (rank = 0; rank < NUM_RANKS; rank++) { + if (info.populated_ranks[channel][slot][rank]) { + jedec_read(&info, channel, slot, rank, totalrank, 0xa, 0x400); + totalrank++; + } + }}} /* for each channel, slot, rank */
MCHBAR8(0x12c) = 0x9f;
@@ -4503,39 +4324,42 @@ for (channel = 0; channel < NUM_CHANNELS; channel++) { MCHBAR32(0x294 + (channel << 10)) = (info.populated_ranks_mask[channel] & 3) << 16; + MCHBAR16(0x298 + (channel << 10)) = - info.populated_ranks[channel][0][0] | + info.populated_ranks[channel][0][0] | (info.populated_ranks[channel][0][1] << 5); + MCHBAR32(0x29c + (channel << 10)) = 0x77a; } MCHBAR32_AND_OR(0x2c0, 0, 0x6009cc00); // !!!!
- { - u8 a, b; - a = MCHBAR8(0x243); - b = MCHBAR8(0x643); - MCHBAR8(0x243) = a | 2; - MCHBAR8(0x643) = b | 2; - } + + u8 a, b; + a = MCHBAR8(0x243); + b = MCHBAR8(0x643); + MCHBAR8(0x243) = a | 2; + MCHBAR8(0x643) = b | 2; +
write_1d0(7, 0x19b, 3, 1); write_1d0(7, 0x1c0, 3, 1); write_1d0(4, 0x1c6, 4, 1); write_1d0(4, 0x1cc, 4, 1); + read_1d0(0x151, 4); // = 0x408c6d74 // !!!! write_1d0(4, 0x151, 4, 1); + MCHBAR32(0x584) = 0xfffff; MCHBAR32(0x984) = 0xfffff;
- for (channel = 0; channel < NUM_CHANNELS; channel++) - for (slot = 0; slot < NUM_SLOTS; slot++) - for (rank = 0; rank < NUM_RANKS; rank++) - if (info. - populated_ranks[channel][slot] - [rank]) - config_rank(&info, s3resume, - channel, slot, - rank); + for (channel = 0; channel < NUM_CHANNELS; channel++) { + for (slot = 0; slot < NUM_SLOTS; slot++) { + for (rank = 0; rank < NUM_RANKS; rank++) { + + if (info.populated_ranks[channel][slot][rank]) { + config_rank(&info, s3resume, channel, slot, rank); + } + }}} /* for each channel, slot, rank */
MCHBAR8(0x243) = 0x1; MCHBAR8(0x643) = 0x1; @@ -4552,9 +4376,11 @@ for (channel = 0; channel < NUM_CHANNELS; channel++) { MCHBAR32(0x294 + (channel << 10)) = (info.populated_ranks_mask[channel] & 3) << 16; + MCHBAR16(0x298 + (channel << 10)) = - info.populated_ranks[channel][0][0] | + info.populated_ranks[channel][0][0] | (info.populated_ranks[channel][0][1] << 5); + MCHBAR32(0x29c + (channel << 10)) = 0x77a; } MCHBAR32_AND_OR(0x2c0, 0, 0x6009cc00); // !!!! @@ -4579,10 +4405,13 @@
if (info.non_interleaved_part_mb != 0 && info.interleaved_part_mb != 0) MCHBAR8(0x111) = 0x20 | (0 << 2) | (1 << 6) | (0 << 7); + else if (have_match_ranks(&info, 0, 4) && have_match_ranks(&info, 1, 4)) MCHBAR8(0x111) = 0x20 | (3 << 2) | (0 << 6) | (1 << 7); + else if (have_match_ranks(&info, 0, 2) && have_match_ranks(&info, 1, 2)) MCHBAR8(0x111) = 0x20 | (3 << 2) | (0 << 6) | (0 << 7); + else MCHBAR8(0x111) = 0x20 | (3 << 2) | (1 << 6) | (0 << 7);
@@ -4622,38 +4451,35 @@ } #endif
- { - u32 eax; - - eax = info.fsb_frequency / 9; - MCHBAR32_AND_OR(0xfcc, 0xfffc0000, - (eax * 0x280) | (eax * 0x5000) | eax | 0x40000); - MCHBAR32(0x20) = 0x33001; - } + u32 eax = info.fsb_frequency / 9; + MCHBAR32_AND_OR(0xfcc, 0xfffc0000, (eax * 0x280) | (eax * 0x5000) | eax | 0x40000); + MCHBAR32(0x20) = 0x33001;
for (channel = 0; channel < NUM_CHANNELS; channel++) { MCHBAR32_AND(0x220 + (channel << 10), ~0x7770); + if (info.max_slots_used_in_channel == 1) - MCHBAR16_OR(0x237 + (channel << 10), 0x0201); + MCHBAR16_OR( 0x237 + (channel << 10), 0x0201); else MCHBAR16_AND(0x237 + (channel << 10), ~0x0201);
MCHBAR8_OR(0x241 + (channel << 10), 1);
- if (info.clock_speed_index <= 1 && (info.silicon_revision == 2 - || info.silicon_revision == 3)) + if (info.clock_speed_index <= 1 + && (info.silicon_revision == 2 || info.silicon_revision == 3)) { MCHBAR32_OR(0x248 + (channel << 10), 0x00102000); - else + } else { MCHBAR32_AND(0x248 + (channel << 10), ~0x00102000); + } }
MCHBAR32_OR(0x115, 0x1000000);
{ - u8 al; - al = 0xd; + u8 al = 0xd; if (!(info.silicon_revision == 0 || info.silicon_revision == 1)) al += 2; + al |= ((1 << (info.max_slots_used_in_channel - 1)) - 1) << 4; MCHBAR32(0x210) = (al << 16) | 0x20; } @@ -4664,6 +4490,7 @@ MCHBAR32(0x290 + (channel << 10)) = 0x282091c | ((info.max_slots_used_in_channel - 1) << 0x16); } + u32 reg1c; pci_read_config32(NORTHBRIDGE, 0x40); // = DEFAULT_EPBAR | 0x001 // OK reg1c = read32p(DEFAULT_EPBAR | 0x01c); // = 0x8001 // OK @@ -4689,9 +4516,9 @@ MCHBAR8(0x121c) = 0x3; MCHBAR16(0xc14) = 0x0; MCHBAR16(0xc20) = 0x0; - MCHBAR32(0x1c) = 0x0; + MCHBAR32(0x01c) = 0x0;
- /* revision dependent here. */ + /* revision dependent here. */
MCHBAR16_OR(0x1230, 0x1f07);
@@ -4702,13 +4529,12 @@ MCHBAR8_OR(0x1214, 1);
u8 bl, ebpb; - u16 reg_1020;
- reg_1020 = MCHBAR32(0x1020); // = 0x6c733c // OK - MCHBAR8(0x1070) = 0x1; + u16 reg_1020 = MCHBAR32(0x1020); // = 0x6c733c // OK
+ MCHBAR8(0x1070) = 0x1; MCHBAR32(0x1000) = 0x100; - MCHBAR8(0x1007) = 0x0; + MCHBAR8(0x1007) = 0x0;
if (reg_1020 != 0) { MCHBAR16(0x1018) = 0x0; @@ -4722,12 +4548,11 @@ rdmsr(0x1a2);
MCHBAR32(0x1014) = 0xffffffff; - MCHBAR32(0x1010) = ((((ebpb + 0x7d) << 7) / bl) & 0xff) * (!!reg_1020);
MCHBAR8(0x101c) = 0xb8; - MCHBAR8(0x123e) = (MCHBAR8(0x123e) & 0xf) | 0x60; + if (reg_1020 != 0) { MCHBAR32_AND_OR(0x123c, ~0x00900000, 0x600000); MCHBAR8(0x101c) = 0xb8; @@ -4750,20 +4575,25 @@ u16 ecx; for (ecx = 0xffff; ecx && (MCHBAR16(0x1170) & 0x1000); ecx--) ; + MCHBAR16_AND(0x1190, ~0x4000); }
pci_write_config8(SOUTHBRIDGE, GEN_PMCON_2, pci_read_config8(SOUTHBRIDGE, GEN_PMCON_2) & ~0x80); + udelay(10000); + MCHBAR16(0x2ca8) = 0x8;
udelay(1000); + dump_timings(&info); cbmem_wasnot_inited = cbmem_recovery(s3resume);
if (!s3resume) save_timings(&info); + if (s3resume && cbmem_wasnot_inited) { u32 reg32; printk(BIOS_ERR, "Failed S3 resume.\n");