From f6af8943e23b8ffa27df6ddb8e4a654387be0cb6 Mon Sep 17 00:00:00 2001 From: Martin Roth Date: Sun, 15 Oct 2017 14:58:49 -0600 Subject: Intel i5000 board & chips: Remove - using LATE_CBMEM_INIT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All boards and chips that are still using LATE_CBMEM_INIT are being removed as previously discussed. If these boards and chips are updated to not use LATE_CBMEM_INIT, they can be restored to the active codebase from the 4.7 branch. chips: northbridge/intel/i5000 Mainboards: mainboard/supermicro/x7db8 mainboard/asus/dsbf Change-Id: I6614c0033b4439d196f26819998d3f85e6d11c00 Signed-off-by: Martin Roth Reviewed-on: https://review.coreboot.org/22030 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki --- src/northbridge/intel/i5000/Kconfig | 31 - src/northbridge/intel/i5000/Makefile.inc | 22 - src/northbridge/intel/i5000/bootblock.c | 21 - src/northbridge/intel/i5000/halt_second_bsp.S | 58 - src/northbridge/intel/i5000/northbridge.c | 177 --- src/northbridge/intel/i5000/raminit.c | 1764 ------------------------- src/northbridge/intel/i5000/raminit.h | 331 ----- 7 files changed, 2404 deletions(-) delete mode 100644 src/northbridge/intel/i5000/Kconfig delete mode 100644 src/northbridge/intel/i5000/Makefile.inc delete mode 100644 src/northbridge/intel/i5000/bootblock.c delete mode 100644 src/northbridge/intel/i5000/halt_second_bsp.S delete mode 100644 src/northbridge/intel/i5000/northbridge.c delete mode 100644 src/northbridge/intel/i5000/raminit.c delete mode 100644 src/northbridge/intel/i5000/raminit.h (limited to 'src/northbridge') diff --git a/src/northbridge/intel/i5000/Kconfig b/src/northbridge/intel/i5000/Kconfig deleted file mode 100644 index 67a21fcbc7..0000000000 --- a/src/northbridge/intel/i5000/Kconfig +++ /dev/null @@ -1,31 +0,0 @@ -## -## This file is part of the coreboot project. -## -## Copyright (C) 2011 Sven Schnelle -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published by -## the Free Software Foundation; version 2 of the License. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## - -config NORTHBRIDGE_INTEL_I5000 - bool - select HAVE_DEBUG_RAM_SETUP - select LATE_CBMEM_INIT - -if NORTHBRIDGE_INTEL_I5000 - -config NORTHBRIDGE_INTEL_I5000_RAM_CHECK - bool - prompt "Run ramcheck after RAM initialization" - -config BOOTBLOCK_NORTHBRIDGE_INIT - string - default "northbridge/intel/i5000/bootblock.c" - -endif diff --git a/src/northbridge/intel/i5000/Makefile.inc b/src/northbridge/intel/i5000/Makefile.inc deleted file mode 100644 index 9f6c38e15f..0000000000 --- a/src/northbridge/intel/i5000/Makefile.inc +++ /dev/null @@ -1,22 +0,0 @@ -# -# This file is part of the coreboot project. -# -# Copyright (C) 2007-2009 coresystems GmbH -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# - -ifeq ($(CONFIG_NORTHBRIDGE_INTEL_I5000),y) - -ramstage-y += northbridge.c -romstage-y += raminit.c -cpu_incs-y += src/northbridge/intel/i5000/halt_second_bsp.S - -endif diff --git a/src/northbridge/intel/i5000/bootblock.c b/src/northbridge/intel/i5000/bootblock.c deleted file mode 100644 index ff7513a402..0000000000 --- a/src/northbridge/intel/i5000/bootblock.c +++ /dev/null @@ -1,21 +0,0 @@ -#include - -static void bootblock_northbridge_init(void) -{ - /* - * The "io" variant of the config access is explicitly used to - * setup the PCIEXBAR because CONFIG_MMCONF_SUPPORT is set to - * to true. That way all subsequent non-explicit config accesses use - * MCFG. This code also assumes that bootblock_northbridge_init() is - * the first thing called in the non-asm boot block code. The final - * assumption is that no assembly code is using the - * CONFIG_MMCONF_SUPPORT option to do PCI config acceses. - * - * The PCIEXBAR is assumed to live in the memory mapped IO space under - * 4GiB. - */ - - /* setup PCIe MMCONF base address */ - pci_io_write_config32(PCI_DEV(0, 16, 0), 0x64, - CONFIG_MMCONF_BASE_ADDRESS >> 16); -} diff --git a/src/northbridge/intel/i5000/halt_second_bsp.S b/src/northbridge/intel/i5000/halt_second_bsp.S deleted file mode 100644 index 041807ecc7..0000000000 --- a/src/northbridge/intel/i5000/halt_second_bsp.S +++ /dev/null @@ -1,58 +0,0 @@ - /* Save BIST result */ - - movl %eax, %ebp - - /* check if SPAD0 is cleared. If yes, it means this was a hard reset */ - movl $0x800080d0, %eax - movw $0xcf8, %dx - outl %eax, %dx - - addw $4, %dx - inl %dx, %eax - cmp $0, %eax - je no_reset - - /* perform hard reset */ - movw $0xcf9, %dx - movb $0x06, %al - outb %al, %dx - -loop0: hlt - jmp loop0 - -no_reset: - - /* Read the semaphore register of i5000 (BOFL0). - If it returns zero, it means there was already - another read by another CPU */ - - movl $0x800080c0, %eax - movw $0xcf8, %dx - outl %eax, %dx - - addw $4, %dx - inl %dx, %eax - cmp $0, %eax - jne 1f - - /* degrade BSP to AP */ - mov $0x1b, %ecx - rdmsr - andl $(~0x100), %eax - wrmsr - - cli -loop: hlt - jmp loop - -1: /* set magic value for soft reset detection */ - movl $0x800080d0, %eax - movw $0xcf8, %dx - outl %eax, %dx - - addw $4, %dx - movl $0x12345678, %eax - outl %eax, %dx - - /* Restore BIST */ - mov %ebp, %eax diff --git a/src/northbridge/intel/i5000/northbridge.c b/src/northbridge/intel/i5000/northbridge.c deleted file mode 100644 index f54ab5ed35..0000000000 --- a/src/northbridge/intel/i5000/northbridge.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2011 Sven Schnelle - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static void intel_set_subsystem(device_t dev, unsigned vendor, unsigned device) -{ - if (!vendor || !device) { - pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, - pci_read_config32(dev, PCI_VENDOR_ID)); - } else { - pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, - ((device & 0xffff) << 16) | (vendor & 0xffff)); - } -} - -static void mc_read_resources(device_t dev) -{ - struct resource *resource; - uint32_t hecbase, amsize, tolm; - uint64_t ambase, memsize; - int idx = 0; - - device_t dev16_0 = dev_find_slot(0, PCI_DEVFN(16, 0)); - device_t dev16_1 = dev_find_slot(0, PCI_DEVFN(16, 1)); - - pci_dev_read_resources(dev); - - tolm = pci_read_config16(dev_find_slot(0, PCI_DEVFN(16, 1)), 0x6c) << 16; - hecbase = pci_read_config16(dev16_0, 0x64) >> 12; - hecbase &= 0xffff; - - ambase = ((u64)pci_read_config32(dev16_0, 0x48) | - (u64)pci_read_config32(dev16_0, 0x4c) << 32); - - amsize = pci_read_config32(dev16_0, 0x50); - ambase &= 0x000000ffffff0000; - - printk(BIOS_DEBUG, "TOLM: 0x%08x AMBASE: 0x%016llx\n", tolm, ambase); - - /* Report the memory regions */ - ram_resource(dev, idx++, 0, 640); - ram_resource(dev, idx++, 768, ((tolm >> 10) - 768)); - - memsize = MAX(pci_read_config16(dev16_1, 0x80) & ~3, - pci_read_config16(dev16_1, 0x84) & ~3); - memsize = MAX(memsize, pci_read_config16(dev16_1, 0x88) & ~3); - - memsize <<= 24; - printk(BIOS_INFO, "MEMSIZE: %08llx\n", memsize); - if (memsize > 0xd0000000) { - memsize -= 0xd0000000; - printk(BIOS_INFO, "high memory: %lldMB\n", memsize / 1048576); - ram_resource(dev, idx++, 4096 * 1024, memsize / 1024); - } - - if (hecbase) { - printk(BIOS_DEBUG, "Adding PCIe config bar at 0x%016llx\n", (u64)hecbase << 28); - resource = new_resource(dev, idx++); - resource->base = (resource_t)(uint64_t)hecbase << 28; - resource->size = (resource_t)256 * 1024 * 1024; - resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE | - IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED; - } - - resource = new_resource(dev, idx++); - resource->base = (resource_t)(uint64_t)0xffe00000; - resource->size = (resource_t)0x200000; - resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE | - IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED; - - if (ambase && amsize) { - resource = new_resource(dev, idx++); - resource->base = (resource_t)ambase; - resource->size = (resource_t)amsize; - resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE | - IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED; - } - - /* add resource for 0xfe6xxxxx range. This range is used by i5000 for - various fixed address registers (BOFL, SPAD, SPADS */ - resource = new_resource(dev, idx++); - resource->base = (resource_t)0xfe600000; - resource->size = (resource_t)0x00100000; - resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE | - IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED; - - set_late_cbmem_top(tolm); -} - -static struct pci_operations intel_pci_ops = { - .set_subsystem = intel_set_subsystem, -}; - -static struct device_operations mc_ops = { - .read_resources = mc_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .scan_bus = 0, - .ops_pci = &intel_pci_ops, -}; - -static const unsigned short nb_ids[] = { - 0x25c0, /* 5000X */ - 0x25d0, /* 5000Z */ - 0x25d4, /* 5000V */ - 0x25d8, /* 5000P */ - 0}; - -static const struct pci_driver mc_driver __pci_driver = { - .ops = &mc_ops, - .vendor = PCI_VENDOR_ID_INTEL, - .devices = nb_ids, -}; - -static void cpu_bus_init(device_t dev) -{ - initialize_cpus(dev->link_list); -} - -static struct device_operations cpu_bus_ops = { - .read_resources = DEVICE_NOOP, - .set_resources = DEVICE_NOOP, - .enable_resources = DEVICE_NOOP, - .init = cpu_bus_init, - .scan_bus = 0, -}; -static void pci_domain_set_resources(device_t dev) -{ - assign_resources(dev->link_list); -} - -static struct device_operations pci_domain_ops = { - .read_resources = pci_domain_read_resources, - .set_resources = pci_domain_set_resources, - .enable_resources = NULL, - .init = NULL, - .scan_bus = pci_domain_scan_bus, - .ops_pci_bus = pci_bus_default_ops, -}; - -static void enable_dev(device_t dev) -{ - /* 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; - } -} - -struct chip_operations northbridge_intel_i5000_ops = { - CHIP_NAME("Intel i5000 Northbridge") - .enable_dev = enable_dev, -}; diff --git a/src/northbridge/intel/i5000/raminit.c b/src/northbridge/intel/i5000/raminit.c deleted file mode 100644 index 4c71a5a834..0000000000 --- a/src/northbridge/intel/i5000/raminit.c +++ /dev/null @@ -1,1764 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2011 Sven Schnelle - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; version 2 of - * the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "raminit.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int i5000_for_each_channel(struct i5000_fbd_branch *branch, - int (*cb)(struct i5000_fbd_channel *)) -{ - struct i5000_fbd_channel *c; - int ret; - - for (c = branch->channel; c < branch->channel + I5000_MAX_CHANNEL; c++) - if (c->used && (ret = cb(c))) - return ret; - return 0; -} - -static int i5000_for_each_branch(struct i5000_fbd_setup *setup, - int (*cb)(struct i5000_fbd_branch *)) -{ - struct i5000_fbd_branch *b; - int ret; - - for (b = setup->branch; b < setup->branch + I5000_MAX_BRANCH; b++) - if (b->used && (ret = cb(b))) - return ret; - return 0; -} - -static int i5000_for_each_dimm(struct i5000_fbd_setup *setup, - int (*cb)(struct i5000_fbdimm *)) -{ - struct i5000_fbdimm *d; - int ret, i; - - for (i = 0; i < I5000_MAX_DIMMS; i++) { - d = setup->dimms[i]; - if ((ret = cb(d))) { - return ret; - } - } - return 0; -} - -static int i5000_for_each_dimm_present(struct i5000_fbd_setup *setup, - int (*cb)(struct i5000_fbdimm *)) -{ - struct i5000_fbdimm *d; - int ret, i; - - for (i = 0; i < I5000_MAX_DIMMS; i++) { - d = setup->dimms[i]; - if (d->present && (ret = cb(d))) - return ret; - } - return 0; -} - -static int spd_read_byte(struct i5000_fbdimm *d, u8 addr, int count, u8 *out) -{ - u16 status; - pci_devfn_t dev = d->branch->branchdev; - - int cmdreg = d->channel->num ? I5000_SPDCMD1 : I5000_SPDCMD0; - int stsreg = d->channel->num ? I5000_SPD1 : I5000_SPD0; - - while (count-- > 0) { - pci_write_config32(dev, cmdreg, 0xa8000000 | \ - (d->num & 0x03) << 24 | addr++ << 16); - - int timeout = 1000; - while ((status = pci_read_config16(dev, stsreg)) & I5000_SPD_BUSY && timeout--) - udelay(10); - - if (status & I5000_SPD_SBE || !timeout) - return -1; - - if (status & I5000_SPD_RDO) { - *out = status & 0xff; - out++; - } - } - return 0; -} - -static void i5000_clear_fbd_errors(void) -{ - pci_devfn_t dev16_1, dev16_2; - - dev16_1 = PCI_ADDR(0, 16, 1, 0); - dev16_2 = PCI_ADDR(0, 16, 2, 0); - - pci_write_config32(dev16_1, I5000_EMASK_FBD, - pci_read_config32(dev16_1, I5000_EMASK_FBD)); - - pci_write_config32(dev16_1, I5000_NERR_FAT_FBD, - pci_read_config32(dev16_1, I5000_NERR_FAT_FBD)); - - pci_write_config32(dev16_1, I5000_FERR_FAT_FBD, - pci_read_config32(dev16_1, I5000_FERR_FAT_FBD)); - - pci_write_config32(dev16_1, I5000_NERR_NF_FBD, - pci_read_config32(dev16_1, I5000_NERR_NF_FBD)); - - pci_write_config32(dev16_1, I5000_FERR_NF_FBD, - pci_read_config32(dev16_1, I5000_FERR_NF_FBD)); - - pci_write_config32(dev16_2, I5000_FERR_GLOBAL, - pci_read_config32(dev16_2, I5000_FERR_GLOBAL)); - - pci_write_config32(dev16_2, I5000_NERR_GLOBAL, - pci_read_config32(dev16_2, I5000_NERR_GLOBAL)); -} - -static int i5000_branch_reset(struct i5000_fbd_branch *b) -{ - pci_devfn_t dev = b->branchdev; - - pci_write_config8(dev, I5000_FBDRST, 0x00); - - udelay(5000); - - pci_write_config8(dev, I5000_FBDRST, 0x05); - udelay(1); - pci_write_config8(dev, I5000_FBDRST, 0x04); - udelay(2); - pci_write_config8(dev, I5000_FBDRST, 0x05); - pci_write_config8(dev, I5000_FBDRST, 0x07); - return 0; -} - -static int delay_ns_to_clocks(struct i5000_fbdimm *d, int del) -{ - int div; - - switch (d->setup->ddr_speed) { - case DDR_533MHZ: - div = 375; - break; - - default: - printk(BIOS_ERR, "Invalid clock: %d, using 667MHz\n", - d->setup->ddr_speed); - - case DDR_667MHZ: - div = 300; - break; - } - - return (del * 100) / div; -} - -static int mtb2clks(struct i5000_fbdimm *d, int del) -{ - int val, div; - - switch (d->setup->ddr_speed) { - case DDR_533MHZ: - div = 375; - break; - default: - printk(BIOS_ERR, "Invalid clock: %d, using 667MHz\n", - d->setup->ddr_speed); - - case DDR_667MHZ: - div = 300; - break; - } - - val = (del * 1000 * d->mtb_dividend) / (d->mtb_divisor * div); - if ((val % 10) > 0) - val += 10; - return val / 10; -} - -static int i5000_read_spd_data(struct i5000_fbdimm *d) -{ - struct i5000_fbd_setup *s = d->setup; - u8 addr, val, org, ftb, cas, t_ras_rc_h, t_rtp, t_wtr; - u8 bb, bl, t_wr, t_rp, t_rcd, t_rc, t_ras, t_aa_min; - u8 cmd2data_addr; - int t_ck_min, dimmsize; - - if (spd_read_byte(d, SPD_MEMORY_TYPE, 1, &val)) { - printk(BIOS_DEBUG, "DIMM %d/%d/%d not present\n", - d->branch->num, d->channel->num, d->num); - return 0; // No FBDIMM present - } - - if (val != 0x09) - return -1; // SDRAM type not FBDIMM - - if (spd_read_byte(d, 0x65, 14, d->amb_personality_bytes)) - return -1; - - switch(s->ddr_speed) { - case DDR_533MHZ: - cmd2data_addr = FBDIMM_SPD_CMD2DATA_533; - break; - - case DDR_667MHZ: - cmd2data_addr = FBDIMM_SPD_CMD2DATA_667; - break; - - default: - printk(BIOS_ERR, "Unsupported FBDIMM clock\n"); - return -1; - } - - if (spd_read_byte(d, FBDIMM_SPD_SDRAM_ADDRESSING, 1, &addr) || - spd_read_byte(d, FBDIMM_SPD_MODULE_ORGANIZATION, 1, &org) || - spd_read_byte(d, FBDIMM_SPD_FTB, 1, &ftb) || - spd_read_byte(d, FBDIMM_SPD_MTB_DIVIDEND, 1, &d->mtb_dividend) || - spd_read_byte(d, FBDIMM_SPD_MTB_DIVISOR, 1, &d->mtb_divisor) || - spd_read_byte(d, FBDIMM_SPD_MIN_TCK, 1, &d->t_ck_min) || - spd_read_byte(d, FBDIMM_SPD_T_WR, 1, &t_wr) || - spd_read_byte(d, FBDIMM_SPD_T_RCD, 1, &t_rcd) || - spd_read_byte(d, FBDIMM_SPD_T_RRD, 1, &d->t_rrd) || - spd_read_byte(d, FBDIMM_SPD_T_RP, 1, &t_rp) || - spd_read_byte(d, FBDIMM_SPD_T_RAS_RC_MSB, 1, &t_ras_rc_h) || - spd_read_byte(d, FBDIMM_SPD_T_RAS, 1, (u8 *)&t_ras) || - spd_read_byte(d, FBDIMM_SPD_T_RC, 1, (u8 *)&t_rc) || - spd_read_byte(d, FBDIMM_SPD_T_RFC, 2, (u8 *)&d->t_rfc) || - spd_read_byte(d, FBDIMM_SPD_T_WTR, 1, &t_wtr) || - spd_read_byte(d, FBDIMM_SPD_T_RTP, 1, &t_rtp) || - spd_read_byte(d, FBDIMM_SPD_T_BB, 1, &bb) || - spd_read_byte(d, FBDIMM_SPD_BURST_LENGTHS_SUPPORTED, 1, &bl) || - spd_read_byte(d, FBDIMM_SPD_ODT, 1, &d->odt) || - spd_read_byte(d, FBDIMM_SPD_T_REFI, 1, &d->t_refi) || - spd_read_byte(d, FBDIMM_SPD_CAS_LATENCIES, 1, &cas) || - spd_read_byte(d, FBDIMM_SPD_CMD2DATA_533, 1, &d->cmd2datanxt[DDR_533MHZ]) || - spd_read_byte(d, FBDIMM_SPD_CMD2DATA_667, 1, &d->cmd2datanxt[DDR_667MHZ]) || - spd_read_byte(d, FBDIMM_SPD_CAS_MIN_LATENCY, 1, &t_aa_min)) { - printk(BIOS_ERR, "failed to read data from SPD\n"); - return 0; - } - - - t_ck_min = (d->t_ck_min * 100) / d->mtb_divisor; - if (t_ck_min <= 300) - d->speed = DDR_667MHZ; - else if (t_ck_min <= 375) - d->speed = DDR_533MHZ; - else { - printk(BIOS_ERR, "Unsupported t_ck_min: %d\n", t_ck_min); - return -1; - } - - d->sdram_width = org & 0x07; - if (d->sdram_width > 1) { - printk(BIOS_ERR, "SDRAM width %d not supported\n", d->sdram_width); - return -1; - } - - if (s->ddr_speed == DDR_667MHZ && d->speed == DDR_533MHZ) - s->ddr_speed = DDR_533MHZ; - - d->banks = 4 << (addr & 0x03); - d->columns = 9 + ((addr >> 2) & 0x03); - d->rows = 12 + ((addr >> 5) & 0x03); - d->ranks = (org >> 3) & 0x03; - d->min_cas_latency = cas & 0x0f; - - s->bl &= bl; - - if (!s->bl) { - printk(BIOS_ERR, "no compatible burst length found\n"); - return -1; - } - - s->t_rc = MAX(s->t_rc, mtb2clks(d, - t_rc | ((t_ras_rc_h & 0xf0) << 4))); - s->t_rrd = MAX(s->t_rrd, mtb2clks(d, d->t_rrd)); - s->t_rfc = MAX(s->t_rfc, mtb2clks(d, d->t_rfc)); - s->t_rcd = MAX(s->t_rcd, mtb2clks(d, t_rcd)); - s->t_cl = MAX(s->t_cl, mtb2clks(d, t_aa_min)); - s->t_wr = MAX(s->t_wr, mtb2clks(d, t_wr)); - s->t_rp = MAX(s->t_rp, mtb2clks(d, t_rp)); - s->t_rtp = MAX(s->t_rtp, mtb2clks(d, t_rtp)); - s->t_wtr = MAX(s->t_wtr, mtb2clks(d, t_wtr)); - s->t_ras = MAX(s->t_ras, mtb2clks(d, - t_ras | ((t_ras_rc_h & 0x0f) << 8))); - s->t_r2r = MAX(s->t_r2r, bb & 3); - s->t_r2w = MAX(s->t_r2w, (bb >> 4) & 3); - s->t_w2r = MAX(s->t_w2r, (bb >> 2) & 3); - - d->ranksize = (1 << (d->banks + d->columns + d->rows + 1)) >> 20; - dimmsize = d->ranksize * d->ranks; - d->branch->totalmem += dimmsize; - s->totalmem += dimmsize; - - d->channel->columns = d->columns; - d->channel->rows = d->rows; - d->channel->ranks = d->ranks; - d->channel->banks = d->banks; - d->channel->width = d->sdram_width; - - printk(BIOS_INFO, "DIMM %d/%d/%d %dMB: %d banks, " - "%d columns, %d rows, %d ranks\n", - d->branch->num, d->channel->num, d->num, dimmsize, - d->banks, d->columns, d->rows, d->ranks); - - d->present = 1; - d->branch->used |= 1; - d->channel->used |= 1; - d->channel->highest_amb = d->num; - return 0; -} - -static int i5000_amb_smbus_write(struct i5000_fbdimm *d, int byte1, int byte2) -{ - u16 status; - pci_devfn_t dev = PCI_DEV(0, d->branch->num ? 22 : 21, 0); - int cmdreg = d->channel->num ? I5000_SPDCMD1 : I5000_SPDCMD0; - int stsreg = d->channel->num ? I5000_SPD1 : I5000_SPD0; - int timeout = 1000; - - pci_write_config32(dev, cmdreg, 0xb8000000 | ((d->num & 0x03) << 24) | - (byte1 << 16) | (byte2 << 8) | 1); - - while (((status = pci_read_config16(dev, stsreg)) & I5000_SPD_BUSY) && timeout--) - udelay(10); - - if (status & I5000_SPD_WOD && timeout) - return 0; - - printk(BIOS_ERR, "SMBus write failed: %d/%d/%d, byte1 %02x, byte2 %02x status %04x\n", - d->branch->num, d->channel->num, d->num, byte1, byte2, status); - die("Error: SMBus write failed"); -} - -static int i5000_amb_smbus_read(struct i5000_fbdimm *d, int byte1, u8 *out) -{ - u16 status; - pci_devfn_t dev = PCI_DEV(0, d->branch->num ? 22 : 21, 0); - int cmdreg = d->channel->num ? I5000_SPDCMD1 : I5000_SPDCMD0; - int stsreg = d->channel->num ? I5000_SPD1 : I5000_SPD0; - int timeout = 1000; - - pci_write_config32(dev, cmdreg, 0xb8000000 | ((d->num & 0x03) << 24) | - (byte1 << 16)); - - while (((status = pci_read_config16(dev, stsreg)) & I5000_SPD_BUSY) && timeout--) - udelay(10); - - if ((status & I5000_SPD_RDO) && timeout) - *out = status & 0xff; - - if (status & I5000_SPD_SBE || !timeout) { - printk(BIOS_ERR, "SMBus write failed: %d/%d/%d, byte1 %02x status %04x\n", - d->branch->num, d->channel->num, d->num, byte1, status); - return -1; - } - return 0; - -} - -static int i5000_amb_smbus_write_config8(struct i5000_fbdimm *d, - int fn, int reg, u8 val) -{ - if (i5000_amb_smbus_write(d, 0x84, 00) || - i5000_amb_smbus_write(d, 0x04, fn) || - i5000_amb_smbus_write(d, 0x04, (reg >> 8) & 0xff) || - i5000_amb_smbus_write(d, 0x04, reg & 0xff) || - i5000_amb_smbus_write(d, 0x44, val)) { - printk(BIOS_ERR, "AMB SMBUS write failed\n"); - return 1; - } - return 0; -} - -static int i5000_amb_smbus_write_config16(struct i5000_fbdimm *d, - int fn, int reg, u16 val) -{ - if (i5000_amb_smbus_write(d, 0x88, 00) || - i5000_amb_smbus_write(d, 0x08, fn) || - i5000_amb_smbus_write(d, 0x08, (reg >> 8) & 0xff) || - i5000_amb_smbus_write(d, 0x08, reg & 0xff) || - i5000_amb_smbus_write(d, 0x08, (val >> 8) & 0xff) || - i5000_amb_smbus_write(d, 0x48, val & 0xff)) { - printk(BIOS_ERR, "AMB SMBUS write failed\n"); - return 1; - } - return 0; -} - -static int i5000_amb_smbus_write_config32(struct i5000_fbdimm *d, - int fn, int reg, u32 val) -{ - if (i5000_amb_smbus_write(d, 0x8c, 00) || - i5000_amb_smbus_write(d, 0x0c, fn) || - i5000_amb_smbus_write(d, 0x0c, (reg >> 8) & 0xff) || - i5000_amb_smbus_write(d, 0x0c, reg & 0xff) || - i5000_amb_smbus_write(d, 0x0c, (val >> 24) & 0xff) || - i5000_amb_smbus_write(d, 0x0c, (val >> 16) & 0xff) || - i5000_amb_smbus_write(d, 0x0c, (val >> 8) & 0xff) || - i5000_amb_smbus_write(d, 0x4c, val & 0xff)) { - printk(BIOS_ERR, "AMB SMBUS write failed\n"); - return 1; - } - return 0; -} - -static int i5000_amb_smbus_read_config32(struct i5000_fbdimm *d, - int fn, int reg, u32 *val) -{ - u8 byte3, byte2, byte1, byte0; - - if (i5000_amb_smbus_write(d, 0x80, 00) || - i5000_amb_smbus_write(d, 0x00, fn) || - i5000_amb_smbus_write(d, 0x00, (reg >> 8) & 0xff) || - i5000_amb_smbus_write(d, 0x40, reg & 0xff) || - i5000_amb_smbus_read(d, 0x80, &byte3) || - i5000_amb_smbus_read(d, 0x00, &byte3) || - i5000_amb_smbus_read(d, 0x00, &byte2) || - i5000_amb_smbus_read(d, 0x00, &byte1) || - i5000_amb_smbus_read(d, 0x40, &byte0)) { - printk(BIOS_ERR, "AMB SMBUS read failed\n"); - return 1; - } - *val = (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0; - return 0; -} - -static void i5000_amb_write_config8(struct i5000_fbdimm *d, - int fn, int reg, u32 val) -{ - write8(DEFAULT_AMBASE + AMB_ADDR(d->ambase, fn, reg), val); -} - -static void i5000_amb_write_config16(struct i5000_fbdimm *d, - int fn, int reg, u32 val) -{ - write16(DEFAULT_AMBASE + AMB_ADDR(d->ambase, fn, reg), val); -} - -static void i5000_amb_write_config32(struct i5000_fbdimm *d, - int fn, int reg, u32 val) -{ - write32(DEFAULT_AMBASE + AMB_ADDR(d->ambase, fn, reg), val); -} - -static u32 i5000_amb_read_config32(struct i5000_fbdimm *d, - int fn, int reg) -{ - return read32(DEFAULT_AMBASE + AMB_ADDR(d->ambase, fn, reg)); -} - -static int ddr_command(struct i5000_fbdimm *d, int rank, u32 addr, u32 command) -{ - u32 drc, status; - - printk(BIOS_SPEW, "DIMM %d/%d/%d: rank %d: sending command %x (addr %08x)...", - d->branch->num, d->channel->num, d->num, rank, command, addr); - - drc = i5000_amb_read_config32(d, 3, AMB_DRC); - drc &= ~((3 << 9) | (1 << 12)); - drc |= (rank << 9); - - command &= 0x0f; - command |= AMB_DCALCSR_START | (rank << 21); - - printk(BIOS_DEBUG, "%s: AMB_DCALADDR: %08x AMB_DCALCSR: %08x\n", __func__, addr, command); - i5000_amb_write_config32(d, 3, AMB_DRC, drc); - i5000_amb_write_config32(d, 4, AMB_DCALADDR, addr); - i5000_amb_write_config32(d, 4, AMB_DCALCSR, command); - - udelay(1000); - while ((status = (i5000_amb_read_config32(d, 4, AMB_DCALCSR))) - & (1 << 31)); - - if (status & (1 << 30)) { - printk(BIOS_SPEW, "failed (status 0x%08x)\n", status); - return -1; - } - - printk(BIOS_SPEW, "done\n"); - return 0; -} - -static int i5000_ddr_calibration(struct i5000_fbdimm *d) -{ - u32 status; - - i5000_amb_write_config32(d, 3, AMB_MBADDR, 0); - i5000_amb_write_config32(d, 3, AMB_MBCSR, 0x80100050); - while ((status = i5000_amb_read_config32(d, 3, AMB_MBCSR)) & (1 << 31)); - - i5000_amb_write_config32(d, 3, AMB_MBCSR, 0x80200050); - while ((status = i5000_amb_read_config32(d, 3, AMB_MBCSR)) & (1 << 31)); - - if (ddr_command(d, d->ranks == 2 ? 3 : 1, 0, AMB_DCALCSR_OPCODE_RECV_ENABLE_CAL) || - ddr_command(d, d->ranks == 2 ? 3 : 1, 0, AMB_DCALCSR_OPCODE_DQS_DELAY_CAL)) - return -1; - return 0; -} - -static int i5000_ddr_init(struct i5000_fbdimm *d) -{ - - int rank; - u32 val; - u8 odt; - - for (rank = 0; rank < d->ranks; rank++) { - printk(BIOS_DEBUG, "%s: %d/%d/%d rank %d\n", __func__, - d->branch->num, d->channel->num, d->num, rank); - - if (ddr_command(d, 1 << rank, - 0, AMB_DCALCSR_OPCODE_NOP)) - return -1; - - if (ddr_command(d, 1 << rank, - 0x4000000, AMB_DCALCSR_OPCODE_PRECHARGE)) - return -1; - - /* EMRS(2) */ - if (ddr_command(d, 1 << rank, - 2, AMB_DCALCSR_OPCODE_MRS_EMRS)) - return -1; - - /* EMRS(3) */ - if (ddr_command(d, 1 << rank, - 3, AMB_DCALCSR_OPCODE_MRS_EMRS)) - return -1; - - /* EMRS(1) */ - if (ddr_command(d, 1 << rank, - 1, AMB_DCALCSR_OPCODE_MRS_EMRS)) - return -1; - - /* MRS: DLL reset */ - if (ddr_command(d, 1 << rank, - 0x1000000, AMB_DCALCSR_OPCODE_MRS_EMRS)) - return -1; - - udelay(20); - - if (ddr_command(d, 1 << rank, - 0x4000000, AMB_DCALCSR_OPCODE_PRECHARGE)) - return -1; - - if (ddr_command(d, 1 << rank, - 0, AMB_DCALCSR_OPCODE_REFRESH)) - return -1; - - if (ddr_command(d, 1 << rank, 0, - AMB_DCALCSR_OPCODE_REFRESH)) - return -1; - - /* burst length + cas latency */ - val = (((d->setup->bl & BL_BL8) ? 3 : 2) << 16) | - (1 << 19) /* interleaved burst */ | - (d->setup->t_cl << 20) | - (((d->setup->t_wr - 1) & 7) << 25); - - printk(BIOS_DEBUG, "MRS: 0x%08x\n", val); - if (ddr_command(d, 1 << rank, - val, AMB_DCALCSR_OPCODE_MRS_EMRS)) - return -1; - - /* OCD calibration default */ - if (ddr_command(d, 1 << rank, 0x03800001, - AMB_DCALCSR_OPCODE_MRS_EMRS)) - return -1; - - - odt = d->odt; - if (rank) - odt >>= 4; - - val = (d->setup->t_al << 19) | - ((odt & 1) << 18) | - ((odt & 2) << 21) | 1; - - printk(BIOS_DEBUG, "EMRS(1): 0x%08x\n", val); - - /* ODT, OCD exit, additive latency */ - if (ddr_command(d, 1 << rank, val, AMB_DCALCSR_OPCODE_MRS_EMRS)) - return -1; - } - return 0; -} - -static int i5000_amb_preinit(struct i5000_fbdimm *d) -{ - u32 *p32 = (u32 *)d->amb_personality_bytes; - u16 *p16 = (u16 *)d->amb_personality_bytes; - u32 id, drc, fbdsbcfg = 0x0909; - - printk(BIOS_DEBUG, "%s: %d/%d/%d\n", __func__, - d->branch->num, d->channel->num, d->num); - - i5000_amb_smbus_write_config32(d, 1, 0xb0, p32[0]); - i5000_amb_smbus_write_config16(d, 1, 0xb4, p16[2]); - - drc = (d->setup->t_al << 4) | (d->setup->t_cl); - printk(BIOS_SPEW, "DRC: %02X, CMD2DATANXT: %02x\n", drc, - d->cmd2datanxt[d->setup->ddr_speed]); - - switch(d->setup->ddr_speed) { - case DDR_533MHZ: - fbdsbcfg |= (1 << 16); - break; - case DDR_667MHZ: - fbdsbcfg |= (2 << 16); - break; - default: - return -1; - } - - printk(BIOS_DEBUG, "FBDSBCFGNXT: %08x\n", fbdsbcfg); - i5000_amb_smbus_write_config32(d, 1, AMB_FBDSBCFGNXT, fbdsbcfg); - i5000_amb_smbus_write_config32(d, 1, AMB_FBDLOCKTO, 0x1651); - i5000_amb_smbus_write_config8(d, 1, AMB_CMD2DATANXT, - d->cmd2datanxt[d->setup->ddr_speed]); - - i5000_amb_smbus_write_config8(d, 3, AMB_DRC, drc); - - if (!i5000_amb_smbus_read_config32(d, 0, 0, &id)) { - d->vendor = id & 0xffff; - d->device = id >> 16; - } - - pci_write_config8(d->branch->branchdev, - d->channel->num ? I5000_FBDSBTXCFG1 : I5000_FBDSBTXCFG0, 0x04); - return 0; -} - -static void i5000_fbd_next_state(struct i5000_fbd_branch *b, int state) -{ - int timeout = 10000; - pci_devfn_t dev = b->branchdev; - - printk(BIOS_DEBUG, " FBD state branch %d: %02x,", b->num, state); - - pci_write_config8(dev, I5000_FBDHPC, state); - - printk(BIOS_DEBUG, "waiting for new state..."); - - while (pci_read_config8(dev, I5000_FBDST) != state && timeout--) - udelay(10); - - if (timeout) { - printk(BIOS_DEBUG, "done\n"); - return; - } - - printk(BIOS_ERR, "timeout while entering state %02x on branch %d\n", - state, b->num); -} - -static int i5000_wait_pattern_recognized(struct i5000_fbd_channel *c) -{ - int i = 10; - pci_devfn_t dev = PCI_ADDR(0, c->branch->num ? 22 : 21, 0, - c->num ? I5000_FBDISTS1 : I5000_FBDISTS0); - - printk(BIOS_DEBUG, " waiting for pattern recognition..."); - while (pci_read_config16(dev, 0) != 0x1fff && --i > 0) - udelay(5000); - - printk(BIOS_DEBUG, i ? "done\n" : "failed\n"); - printk(BIOS_DEBUG, "%d/%d Round trip latency: %d\n", c->branch->num, c->num, - pci_read_config8(c->branch->branchdev, c->num ? I5000_FBDLVL1 : I5000_FBDLVL0) & 0x3f); - return !i; -} - -static const char *pattern_names[16] = { - "EI", "EI", "EI", "EI", - "EI", "EI", "EI", "EI", - "TS0", "TS1", "TS2", "TS3", - "RESERVED", "TS2 (merge disabled)", "TS2 (merge enabled)","All ones", -}; - -static int i5000_drive_pattern(struct i5000_fbd_channel *c, int pattern, int wait) -{ - pci_devfn_t dev = PCI_ADDR(0, c->branch->num ? 22 : 21, 0, - c->num ? I5000_FBDICMD1 : I5000_FBDICMD0); - - printk(BIOS_DEBUG, " %d/%d driving pattern %s to AMB%d (%02x)\n", - c->branch->num, c->num, - pattern_names[(pattern >> 4) & 0xf], pattern & 3, pattern); - pci_write_config8(dev, 0, pattern); - - if (!wait) - return 0; - - return i5000_wait_pattern_recognized(c); -} - -static int i5000_set_ambpresent(struct i5000_fbd_channel *c) -{ - int i; - pci_devfn_t branchdev = c->branch->branchdev; - u16 ambpresent = 0x8000; - - for (i = 0; i < I5000_MAX_DIMM_PER_CHANNEL; i++) { - if (c->dimm[i].present) - ambpresent |= (1 << i); - } - - printk(BIOS_DEBUG, "AMBPRESENT: %04x\n", ambpresent); - pci_write_config16(branchdev, - c->num ? - I5000_AMBPRESENT1 : \ - I5000_AMBPRESENT0, ambpresent); - - return 0; -} - - -static int i5000_drive_test_patterns(struct i5000_fbd_channel *c, int highest_amb, int mchpad) -{ - pci_devfn_t branchdev = c->branch->branchdev; - int off = c->num ? 0x100 : 0; - u32 portctl; - int i, cnt = 1000; - - portctl = pci_read_config32(branchdev, I5000_FBD0IBPORTCTL + off); - portctl &= ~0x01000020; - if (mchpad) - portctl |= 0x00800000; - else - portctl &= ~0x00800000; - portctl &= ~0x01000020; - pci_write_config32(branchdev, I5000_FBD0IBPORTCTL + off, portctl); - - /* drive calibration patterns */ - if (i5000_drive_pattern(c, I5000_FBDICMD_TS0 | highest_amb, 1)) - return -1; - - if (i5000_drive_pattern(c, I5000_FBDICMD_TS1 | highest_amb, 1)) - return -1; - - while (!(pci_read_config32(branchdev, I5000_FBD0IBPORTCTL + off) & 4) && cnt--) - udelay(10); - - if (!cnt) { - printk(BIOS_ERR, "IBIST timeout\n"); - return -1; - } - - if (i5000_drive_pattern(c, I5000_FBDICMD_TS2 | highest_amb, 1)) - return -1; - - for (i = 0; i < highest_amb; i++) { - if ((i5000_drive_pattern(c, I5000_FBDICMD_TS2_NOMERGE | i, 1))) - return -1; - } - - if (i5000_drive_pattern(c, I5000_FBDICMD_TS2 | highest_amb, 1)) - return -1; - - if (i5000_drive_pattern(c, I5000_FBDICMD_TS3 | highest_amb, 1)) - return -1; - - if (i5000_set_ambpresent(c)) - return -1; - return 0; -} - -static int i5000_train_channel_idle(struct i5000_fbd_channel *c) -{ - int i; - u32 fbdsbcfg = 0x0b1b; - - switch(c->setup->ddr_speed) { - case DDR_533MHZ: - fbdsbcfg |= (1 << 16); - break; - case DDR_667MHZ: - fbdsbcfg |= (2 << 16); - break; - default: - return -1; - } - - pci_write_config8(c->branch->branchdev, - c->num ? I5000_FBDSBTXCFG1 : I5000_FBDSBTXCFG0, 0x05); - - for (i = 0; i < 4; i++) { - if (c->dimm[i].present) - i5000_amb_smbus_write_config32(c->dimm + i, 1, AMB_FBDSBCFGNXT, i ? (fbdsbcfg | 0x1000) : fbdsbcfg); - } - - return i5000_drive_pattern(c, I5000_FBDICMD_IDLE, 1); -} - -static int i5000_drive_test_patterns0(struct i5000_fbd_channel *c) -{ - if (i5000_train_channel_idle(c)) - return -1; - - return i5000_drive_test_patterns(c, c->highest_amb, 0); -} - -static int i5000_drive_test_patterns1(struct i5000_fbd_channel *c) -{ - if (i5000_train_channel_idle(c)) - return -1; - - return i5000_drive_test_patterns(c, c->highest_amb, 1); -} - -static int i5000_setup_channel(struct i5000_fbd_channel *c) -{ - pci_devfn_t branchdev = c->branch->branchdev; - int off = c->branch->num ? 0x100 : 0; - u32 val; - - pci_write_config32(branchdev, I5000_FBD0IBTXPAT2EN + off, 0); - pci_write_config32(branchdev, I5000_FBD0IBTXPAT2EN + off, 0); - pci_write_config32(branchdev, I5000_FBD0IBTXMSK + off, 0x3ff); - pci_write_config32(branchdev, I5000_FBD0IBRXMSK + off, 0x1fff); - - pci_write_config16(branchdev, off + 0x0162, c->used ? 0x20db : 0x18db); - - /* unknown */ - val = pci_read_config32(branchdev, off + 0x0164); - val &= 0xfffbcffc; - val |= 0x4004; - pci_write_config32(branchdev, off + 0x164, val); - - pci_write_config32(branchdev, off + 0x15c, 0xff); - i5000_drive_pattern(c, I5000_FBDICMD_ALL_ONES, 0); - return 0; -} - -static int i5000_link_training0(struct i5000_fbd_branch *b) -{ - pci_devfn_t branchdev = b->branchdev; - - pci_write_config8(branchdev, I5000_FBDPLLCTRL, b->used ? 0 : 1); - - if (i5000_for_each_channel(b, i5000_setup_channel)) - return -1; - - if (i5000_for_each_channel(b, i5000_train_channel_idle)) - return -1; - - i5000_fbd_next_state(b, I5000_FBDHPC_STATE_INIT); - - if (i5000_for_each_channel(b, i5000_drive_test_patterns0)) - return -1; - - i5000_fbd_next_state(b, I5000_FBDHPC_STATE_READY); - return 0; -} - -static int i5000_link_training1(struct i5000_fbd_branch *b) -{ - if (i5000_for_each_channel(b, i5000_train_channel_idle)) - return -1; - - i5000_fbd_next_state(b, I5000_FBDHPC_STATE_INIT); - - if (i5000_for_each_channel(b, i5000_drive_test_patterns1)) - return -1; - - i5000_fbd_next_state(b, I5000_FBDHPC_STATE_READY); - return 0; -} - - -static int i5000_amb_check(struct i5000_fbdimm *d) -{ - u32 id = i5000_amb_read_config32(d, 0, 0); - - printk(BIOS_DEBUG, "AMB %d/%d/%d ID: %04x:%04x\n", - d->branch->num, d->channel->num, d->num, - id & 0xffff, id >> 16); - - if ((id & 0xffff) != d->vendor || id >> 16 != d->device) { - printk(BIOS_ERR, "AMB mapping failed\n"); - return -1; - } - return 0; -} - -static int i5000_amb_postinit(struct i5000_fbdimm *d) -{ - u32 *p32 = (u32 *)d->amb_personality_bytes; - u16 *p16 = (u16 *)d->amb_personality_bytes; - - i5000_amb_write_config16(d, 1, 0xb6, p16[3]); - i5000_amb_write_config32(d, 1, 0xb8, p32[2]); - i5000_amb_write_config16(d, 1, 0xbc, p16[6]); - return 0; -} - -static int i5000_amb_dram_timing_init(struct i5000_fbdimm *d) -{ - struct i5000_fbd_setup *s; - u32 val, tref; - int refi; - - s = d->setup; - - printk(BIOS_DEBUG, "DIMM %d/%d/%d config:\n", - d->branch->num, d->channel->num, d->num); - - val = 0x44; - printk(BIOS_DEBUG, "\tDDR2ODTC: 0x%02x\n", val); - i5000_amb_write_config8(d, 4, AMB_DDR2ODTC, val); - - val = (0x0c << 24) | /* CLK control */ - (1 << 18) | /* ODTZ enabled */ - (((d->setup->bl & BL_BL8) ? 1 : 0) << 8) | /* 8 byte burst length supported */ - ((d->setup->t_al & 0x0f) << 4) | /* additive latency */ - (d->setup->t_cl & 0x0f); /* CAS latency */ - - if (d->ranks > 1) { - val |= (0x03 << 9); - } else { - val |= (0x01 << 9); - } - - printk(BIOS_DEBUG, "AMB_DRC: %08x\n", val); - i5000_amb_write_config32(d, 3, AMB_DRC, val); - - val = (d->sdram_width << 30) | - ((d->ranks == 2 ? 1 : 0) << 29) | - ((d->banks == 8 ? 1 : 0) << 28) | - ((d->rows - 13) << 26) | - ((d->columns - 10) << 24) | - (1 << 16) | /* Auto refresh exit */ - (0x27 << 8) | /* t_xsnr */ - (d->setup->t_rp << 4) | - (((d->t_ck_min * d->mtb_dividend) / d->mtb_divisor) & 0x0f); - - printk(BIOS_DEBUG, "\tAMB_DSREFTC: %08x\n", val); - i5000_amb_write_config32(d, 3, AMB_DSREFTC, val); - - tref = 15; - - switch(d->t_refi & 0x0f) { - case 0: - refi = 15625; - break; - case 1: - refi = 3900; - tref = 3; - break; - case 2: - refi = 7800; - tref = 7; - break; - case 3: - refi = 31250; - break; - case 4: - refi = 62500; - break; - case 5: - refi = 125000; - break; - default: - printk(BIOS_ERR, "unsupported t_refi value: %d, using 7.8us\n", - d->t_refi & 0x0f); - refi = 7800; - break; - } - - s->t_ref = tref; - val = delay_ns_to_clocks(d, refi) | (s->t_rfc << 16); - - printk(BIOS_DEBUG, "\tAMB_DAREFTC: %08x\n", val); - i5000_amb_write_config32(d, 3, AMB_DAREFTC, val); - - u8 t_r2w = ((s->bl & BL_BL8) ? 4 : 2) + - (((d->t_ck_min * d->mtb_dividend) / d->mtb_divisor)); - u8 t_w2r = (s->t_cl - 1) + ((s->bl & BL_BL8) ? 4 : 2) + s->t_wtr; - - val = ((6 - s->t_rp) << 8) | ((6 - s->t_rcd) << 10) | - ((26 - s->t_rc) << 12) | ((9 - s->t_wr) << 16) | - ((12 - t_w2r) << 20) | ((10 - t_r2w) << 24) | - ((s->t_rtp - 2) << 27); - - switch(s->t_ras) { - case 15: - val |= (1 << 29); - break; - case 12: - val |= (2 << 29); - break; - default: - break; - } - - printk(BIOS_DEBUG, "\tAMB_DRT: %08x\n", val); - i5000_amb_write_config32(d, 3, AMB_DRT, val); - return 0; -} - -static int i5000_do_amb_membist_start(struct i5000_fbdimm *d, int rank, int pattern) -{ - printk(BIOS_DEBUG, "DIMM %d/%d/%d rank %d pattern %d\n", - d->branch->num, d->channel->num, d->num, rank, pattern); - - i5000_amb_write_config32(d, 3, AMB_DAREFTC, - i5000_amb_read_config32(d, 3, AMB_DAREFTC) | 0x8000); - - i5000_amb_write_config32(d, 3, AMB_MBLFSRSED, 0x12345678); - i5000_amb_write_config32(d, 3, AMB_MBADDR, 0); - i5000_amb_write_config32(d, 3, AMB_MBCSR, 0x800000f0 | (rank << 20) | ((pattern & 3) << 8)); - return 0; -} - -static int i5000_do_amb_membist_status(struct i5000_fbdimm *d, int rank) -{ - int cnt = 1000; - u32 res; - - while ((res = i5000_amb_read_config32(d, 3, AMB_MBCSR)) & (1 << 31) && cnt--) - udelay(1000); - - if (cnt && !(res & (1 << 30))) - return 0; - - printk(BIOS_ERR, "DIMM %d/%d/%d rank %d failed membist check\n", - d->branch->num, d->channel->num, d->num, rank); - return -1; -} - -static int i5000_amb_membist_zero1_start(struct i5000_fbdimm *d) -{ - if (i5000_do_amb_membist_start(d, 1, 0)) - return -1; - return 0; -} - -static int i5000_amb_membist_zero2_start(struct i5000_fbdimm *d) -{ - - if (d->ranks < 2) - return 0; - if (i5000_do_amb_membist_start(d, 2, 0)) - return -1; - return 0; -} - -static int i5000_amb_membist_status1(struct i5000_fbdimm *d) -{ - if (i5000_do_amb_membist_status(d, 1)) - return -1; - return 0; -} - -static int i5000_amb_membist_status2(struct i5000_fbdimm *d) -{ - if (d->ranks < 2) - return 0; - - if (i5000_do_amb_membist_status(d, 2)) - return -1; - return 0; -} - -static int i5000_amb_membist_end(struct i5000_fbdimm *d) -{ - printk(BIOS_DEBUG, "AMB_DRC MEMBIST: %08x\n", i5000_amb_read_config32(d, 3, AMB_DRC)); - return 0; -} - -static int i5000_membist(struct i5000_fbd_setup *setup) -{ - return i5000_for_each_dimm_present(setup, i5000_amb_membist_zero1_start) || - i5000_for_each_dimm_present(setup, i5000_amb_membist_status1) || - i5000_for_each_dimm_present(setup, i5000_amb_membist_zero2_start) || - i5000_for_each_dimm_present(setup, i5000_amb_membist_status2) || - i5000_for_each_dimm_present(setup, i5000_amb_membist_end); -} - -static int i5000_enable_mc_autorefresh(struct i5000_fbdimm *d) -{ - u32 tmp = i5000_amb_read_config32(d, 3, AMB_DSREFTC); - tmp &= ~(1 << 16); - printk(BIOS_DEBUG, "new AMB_DSREFTC: 0x%08x\n", tmp); - i5000_amb_write_config32(d, 3, AMB_DSREFTC, tmp); - return 0; -} - -static int i5000_amb_clear_error_status(struct i5000_fbdimm *d) -{ - i5000_amb_write_config32(d, 1, AMB_FERR, 9); - i5000_amb_write_config32(d, 1, AMB_NERR, 9); - i5000_amb_write_config32(d, 1, AMB_EMASK, 0xf2); - i5000_amb_write_config8(d, 3, 0x80, 0xcf); - i5000_amb_write_config8(d, 3, 0x81, 0xd3); - i5000_amb_write_config8(d, 3, 0x82, 0xf8); - return 0; -} - -static void i5000_program_mtr(struct i5000_fbd_channel *c, int mtr) -{ - u32 val; - - if (c->dimm[0].present || c->dimm[1].present) { - val = (((c->columns - 10) & 3) | - (((c->rows - 13) & 3) << 2) | - (((c->ranks == 2) ? 1 : 0) << 4) | - (((c->banks == 8) ? 1 : 0) << 5) | - ((c->width ? 1 : 0) << 6) | - (1 << 7) | /* Electrical Throttling enabled */ - (1 << 8)); /* DIMM present and compatible */ - printk(BIOS_DEBUG, "MTR0: %04x\n", val); - pci_write_config16(c->branch->branchdev, mtr, val); - } - - if (c->dimm[2].present || c->dimm[3].present) { - val = (((c->columns - 10) & 3) | - (((c->rows - 13) & 3) << 4) | - ((c->ranks ? 1 : 0) << 4) | - (((c->banks == 8) ? 1 : 0) << 5) | - ((c->width ? 1 : 0) << 6) | - (1 << 7) | /* Electrical Throttling enabled */ - (1 << 8)); /* DIMM present and compatible */ - printk(BIOS_DEBUG, "MTR1: %04x\n", val); - pci_write_config16(c->branch->branchdev, mtr+2, val); - } -} - -static int get_dmir(u8 *rankmap, int *_set, int limit) -{ - int i, dmir = 0, set = 0; - - for (i = 7; set < limit && i >= 0; i--) { - if (!(*rankmap & (1 << i))) - continue; - - *rankmap &= ~(1 << i); - - switch(limit) { - case 1: - dmir |= (i | - (i << 3) | - (i << 6) | - (i << 9)); - break; - case 2: - dmir |= (i << (set * 3)) | - (i << (6 + set * 3)); - break; - case 4: - dmir |= (i << (set * 3)); - break; - - default: - break; - } - set++; - } - *_set = set; - return dmir; -} - -static int i5000_setup_dmir(struct i5000_fbd_branch *b) -{ - struct i5000_fbdimm *d; - pci_devfn_t dev = b->branchdev; - u8 rankmap = 0, dmir = 0; - u32 dmirval = 0; - int i, set, rankoffset = 0, ranksize = 0, ranks = 0; - - if (!b->used) - return 0; - - for (i = 0; i < I5000_MAX_DIMM_PER_CHANNEL; i++) { - rankmap >>= 2; - d = b->channel[0].dimm + i; - - if (!d->present) - continue; - - if (d->ranks == 2) { - rankmap |= 0xc0; - ranks += 2; - } else { - rankmap |= 0x40; - ranks++; - } - } - - printk(BIOS_DEBUG, "total ranks: %d, rankmap: %02x\n", ranks, rankmap); - - dmir = I5000_DMIR0; - - ranksize = b->channel[0].dimm[0].ranksize << 8; - - if (!b->setup->single_channel) - ranksize <<= 1; - - while (ranks) { - - if (ranks >= 4) - dmirval = get_dmir(&rankmap, &set, 4); - else if (ranks >= 2) - dmirval = get_dmir(&rankmap, &set, 2); - else - dmirval = get_dmir(&rankmap, &set, 1); - - ranks -= set; - - dmirval |= rankoffset + (set * ranksize); - - rankoffset += (set * ranksize); - - printk(BIOS_DEBUG, "DMIR%d: %08x\n", (dmir - I5000_DMIR0) >> 2, - dmirval); - pci_write_config32(dev, dmir, dmirval); - dmir += 4; - } - - for (; dmir <= I5000_DMIR4; dmir += 4) { - printk(BIOS_DEBUG, "DMIR%d: %08x\n", (dmir - I5000_DMIR0) >> 2, - dmirval); - pci_write_config32(dev, dmir, dmirval); - } - return rankoffset; -} - -static void i5000_setup_interleave(struct i5000_fbd_setup *setup) -{ - pci_devfn_t dev16 = PCI_ADDR(0, 16, 1, 0); - u32 mir0, mir1, mir2, size0, size1, minsize, tmp; - - size0 = i5000_setup_dmir(&setup->branch[1]) >> 12; - size1 = i5000_setup_dmir(&setup->branch[0]) >> 12; - - minsize = MIN(size0, size1); - - if (size0 > size1) { - tmp = size1; - size1 = size0; - size0 = tmp; - } - - if (size0 == size1) { - mir0 = (size0 << 1) | 3; - mir1 = (size0 << 1); - mir2 = (size0 << 1); - } else if (!size0) { - mir0 = size1 | 1; - mir1 = size1; - mir2 = size1; - } else { - mir0 = (size0 << 1) | 3; - mir1 = (size1 + size0) | 1; - mir2 = size1 + size0; - } - - printk(BIOS_DEBUG, "MIR0: %04x\n", mir0); - printk(BIOS_DEBUG, "MIR1: %04x\n", mir1); - printk(BIOS_DEBUG, "MIR2: %04x\n", mir2); - - pci_write_config16(dev16, I5000_MIR0, mir0); - pci_write_config16(dev16, I5000_MIR1, mir1); - pci_write_config16(dev16, I5000_MIR2, mir2); -} - -static int i5000_dram_timing_init(struct i5000_fbd_setup *setup) -{ - pci_devfn_t dev16 = PCI_ADDR(0, 16, 1, 0); - u32 tolm, drta, drtb, mc, mca; - int t_wrc, bl2; - - bl2 = (setup->bl & BL_BL8) ? 4 :2; - t_wrc = setup->t_rcd + (setup->t_cl - 1) + bl2 + - setup->t_wr + setup->t_rp; - - drta = (setup->t_ref & 0x0f) | - ((setup->t_rrd & 0x0f) << 4) | - ((setup->t_rfc & 0xff) << 8) | - ((setup->t_rc & 0x3f) << 16) | - ((t_wrc & 0x3f) << 22) | - (setup->t_al & 0x07) << 28; - - drtb = (bl2) | - (((1 + bl2 + setup->t_r2r) & 0x0f) << 4) | - (((setup->t_cl - 1 + bl2 + setup->t_wtr) & 0x0f) << 8) | - (((2 + bl2 + setup->t_r2w) & 0x0f) << 12) | - (((bl2 + setup->t_w2rdr) & 0x07) << 16); - - mc = (1 << 30) | /* enable retry */ - (3 << 25) | /* bad RAM threshold */ - (1 << 21) | /* INITDONE */ - (1 << 20) | /* FSB enable */ - /* Electrical throttling: 20 clocks */ - ((setup->ddr_speed == DDR_667MHZ ? 1 : 0) << 18) | - (1 << 8) | /* enhanced scrub mode */ - (1 << 7) | /* enable patrol scrub */ - (1 << 6) | /* enable demand scrubbing */ - (1 << 5); /* enable northbound error detection */ - - printk(BIOS_DEBUG, "DRTA: 0x%08x DRTB: 0x%08x MC: 0x%08x\n", drta, drtb, mc); - pci_write_config32(dev16, I5000_DRTA, drta); - pci_write_config32(dev16, I5000_DRTB, drtb); - pci_write_config32(dev16, I5000_MC, mc); - - mca = pci_read_config32(dev16, I5000_MCA); - - mca |= (7 << 28); - if (setup->single_channel) - mca |= (1 << 14); - else - mca &= ~(1 << 14); - printk(BIOS_DEBUG, "MCA: 0x%08x\n", mca); - pci_write_config32(dev16, I5000_MCA, mca); - - pci_write_config32(dev16, I5000_ERRPERR, 0xffffffff); - - i5000_program_mtr(&setup->branch[0].channel[0], I5000_MTR0); - i5000_program_mtr(&setup->branch[0].channel[1], I5000_MTR1); - i5000_program_mtr(&setup->branch[1].channel[0], I5000_MTR0); - i5000_program_mtr(&setup->branch[1].channel[1], I5000_MTR1); - - i5000_setup_interleave(setup); - - if ((tolm = MIN(setup->totalmem, 0xd00)) > 0xd00) - tolm = 0xd00; - - tolm <<= 4; - printk(BIOS_DEBUG, "TOLM: 0x%04x\n", tolm); - pci_write_config16(dev16, I5000_TOLM, tolm); - return 0; -} - -static void i5000_init_setup(struct i5000_fbd_setup *setup) -{ - int branch, channel, dimm, i = 0; - struct i5000_fbdimm *d; - struct i5000_fbd_channel *c; - struct i5000_fbd_branch *b; - - setup->bl = 3; - /* default to highest memory frequency. If a module doesn't - support it, it will decrease this setting in spd_read */ - setup->ddr_speed = DDR_667MHZ; - - for (branch = 0; branch < I5000_MAX_BRANCH; branch++) { - b = setup->branch + branch; - b->branchdev = PCI_ADDR(0, branch ? 22 : 21, 0, 0); - b->setup = setup; - b->num = branch; - - for (channel = 0; channel < I5000_MAX_CHANNEL; channel++) { - c = b->channel + channel; - c->branch = b; - c->setup = setup; - c->num = channel; - - for (dimm = 0; dimm < I5000_MAX_DIMM_PER_CHANNEL; dimm++) { - d = c->dimm + dimm; - setup->dimms[i++] = d; - d->channel = c; - d->branch = b; - d->setup = setup; - d->num = dimm; - d->ambase = (b->num << 16) | (c->num << 15) | (dimm << 11); - } - } - } -} - -static void i5000_reserved_register_init(struct i5000_fbd_setup *setup) -{ - /* register write captured from vendor BIOS, but undocumented by Intel */ - pci_write_config32(PCI_ADDR(0, 16, 0, 0), I5000_PROCENABLE, 0x487f7c); - - pci_write_config32(PCI_ADDR(0, 16, 0, 0), 0xf4, 0x1588106); - pci_write_config32(PCI_ADDR(0, 16, 0, 0), 0xfc, 0x80); - pci_write_config32(PCI_ADDR(0, 16, 1, 0), 0x5c, 0x08); - pci_write_config32(PCI_ADDR(0, 16, 0, 0), 0x70, 0xfe2c08d); - pci_write_config32(PCI_ADDR(0, 16, 0, 0), 0x78, 0xfe2c08d); - - pci_write_config32(PCI_ADDR(0, 16, 0, 0), 0x140, 0x18000000); - pci_write_config32(PCI_ADDR(0, 16, 0, 0), 0x440, 0x18000000); - pci_write_config32(PCI_ADDR(0, 17, 0, 0), 0x18c, 0x18000000); - pci_write_config32(PCI_ADDR(0, 16, 1, 0), 0x180, 0x18000000); - pci_write_config32(PCI_ADDR(0, 17, 0, 0), 0x180, 0x87ffffff); - - pci_write_config32(PCI_ADDR(0, 0, 0, 0), 0x200, 0x18000000); - pci_write_config32(PCI_ADDR(0, 4, 0, 0), 0x200, 0x18000000); - pci_write_config32(PCI_ADDR(0, 0, 0, 0), 0x208, 0x18000000); - pci_write_config32(PCI_ADDR(0, 4, 0, 0), 0x208, 0x18000000); - - pci_write_config32(PCI_ADDR(0, 17, 0, 0), 0x184, 0x01249249); - pci_write_config32(PCI_ADDR(0, 17, 0, 0), 0x154, 0x00000000); - pci_write_config32(PCI_ADDR(0, 17, 0, 0), 0x158, 0x02492492); - pci_write_config32(PCI_ADDR(0, 17, 0, 0), 0x15c, 0x00000000); - pci_write_config32(PCI_ADDR(0, 17, 0, 0), 0x160, 0x00000000); - - pci_write_config16(PCI_ADDR(0, 19, 0, 0), 0x0090, 0x00000007); - pci_write_config16(PCI_ADDR(0, 19, 0, 0), 0x0092, 0x0000000f); - - pci_write_config8(PCI_ADDR(0, 16, 0, 0), 0x0154, 0x10); - pci_write_config8(PCI_ADDR(0, 16, 0, 0), 0x0454, 0x10); - - pci_write_config32(PCI_ADDR(0, 19, 0, 0), 0x007C, 0x00000001); - pci_write_config32(PCI_ADDR(0, 19, 0, 0), 0x007C, 0x00000000); - pci_write_config32(PCI_ADDR(0, 17, 0, 0), 0x0108, 0x000003F0); - pci_write_config32(PCI_ADDR(0, 17, 0, 0), 0x010C, 0x00000042); - pci_write_config16(PCI_ADDR(0, 17, 0, 0), 0x0112, 0x0000); - pci_write_config32(PCI_ADDR(0, 17, 0, 0), 0x0114, 0x00A0494C); - pci_write_config32(PCI_ADDR(0, 17, 0, 0), 0x0118, 0x0002134C); - pci_write_config32(PCI_ADDR(0, 17, 0, 0), 0x013C, 0x0C008000); - pci_write_config32(PCI_ADDR(0, 17, 0, 0), 0x0140, 0x0C008000); - pci_write_config32(PCI_ADDR(0, 17, 0, 0), 0x0144, 0x00008000); - pci_write_config32(PCI_ADDR(0, 17, 0, 0), 0x0148, 0x00008000); - pci_write_config32(PCI_ADDR(0, 19, 0, 0), 0x007C, 0x00000002); - pci_write_config32(PCI_ADDR(0, 16, 1, 0), 0x01F4, 0x00000800); - - if (setup->branch[0].channel[0].used) - pci_write_config32(PCI_ADDR(0, 21, 0, 0), 0x010C, 0x004C0C10); - - if (setup->branch[0].channel[1].used) - pci_write_config32(PCI_ADDR(0, 21, 0, 0), 0x020C, 0x004C0C10); - - if (setup->branch[1].channel[0].used) - pci_write_config32(PCI_ADDR(0, 22, 0, 0), 0x010C, 0x004C0C10); - - if (setup->branch[1].channel[1].used) - pci_write_config32(PCI_ADDR(0, 22, 0, 0), 0x020C, 0x004C0C10); -} -static void i5000_dump_error_registers(void) -{ - pci_devfn_t dev = PCI_ADDR(0, 16, 1, 0); - - printk(BIOS_ERR, "Dump of FBD error registers:\n" - "FERR_FAT_FBD: 0x%08x NERR_FAT_FBD: 0x%08x\n" - "FERR_NF_FBD: 0x%08x NERR_NF_FBD: 0x%08x\n" - "EMASK_FBD: 0x%08x\n" - "ERR0_FBD: 0x%08x\n" - "ERR1_FBD: 0x%08x\n" - "ERR2_FBD: 0x%08x\n" - "MC_ERR_FBD: 0x%08x\n", - pci_read_config32(dev, I5000_FERR_FAT_FBD), - pci_read_config32(dev, I5000_NERR_FAT_FBD), - pci_read_config32(dev, I5000_FERR_NF_FBD), - pci_read_config32(dev, I5000_NERR_NF_FBD), - pci_read_config32(dev, I5000_EMASK_FBD), - pci_read_config32(dev, I5000_ERR0_FBD), - pci_read_config32(dev, I5000_ERR1_FBD), - pci_read_config32(dev, I5000_ERR2_FBD), - pci_read_config32(dev, I5000_MCERR_FBD)); - - printk(BIOS_ERR, "Non recoverable error registers:\n" - "NRECMEMA: 0x%08x NRECMEMB: 0x%08x\n" - "NRECFGLOG: 0x%08x\n", - pci_read_config32(dev, I5000_NRECMEMA), - pci_read_config32(dev, I5000_NRECMEMB), - pci_read_config32(dev, I5000_NRECFGLOG)); - - printk(BIOS_ERR, "Packet data:\n" - "NRECFBDA: 0x%08x\n" - "NRECFBDB: 0x%08x\n" - "NRECFBDC: 0x%08x\n" - "NRECFBDD: 0x%08x\n" - "NRECFBDE: 0x%08x\n", - pci_read_config32(dev, I5000_NRECFBDA), - pci_read_config32(dev, I5000_NRECFBDB), - pci_read_config32(dev, I5000_NRECFBDC), - pci_read_config32(dev, I5000_NRECFBDD), - pci_read_config32(dev, I5000_NRECFBDE)); - - printk(BIOS_ERR, "recoverable error registers:\n" - "RECMEMA: 0x%08x RECMEMB: 0x%08x\n" - "RECFGLOG: 0x%08x\n", - pci_read_config32(dev, I5000_RECMEMA), - pci_read_config32(dev, I5000_RECMEMB), - pci_read_config32(dev, I5000_RECFGLOG)); - - printk(BIOS_ERR, "Packet data:\n" - "RECFBDA: 0x%08x\n" - "RECFBDB: 0x%08x\n" - "RECFBDC: 0x%08x\n" - "RECFBDD: 0x%08x\n" - "RECFBDE: 0x%08x\n", - pci_read_config32(dev, I5000_RECFBDA), - pci_read_config32(dev, I5000_RECFBDB), - pci_read_config32(dev, I5000_RECFBDC), - pci_read_config32(dev, I5000_RECFBDD), - pci_read_config32(dev, I5000_RECFBDE)); - -} - -static void i5000_try_restart(const char *msg) -{ - printk(BIOS_INFO, "%s", msg); - i5000_dump_error_registers(); - outb(0x06, 0xcf9); - halt(); -} - -static void i5000_pam_setup(void) -{ - pci_write_config8(PCI_ADDR(0, 16, 0, 0), 0x59, 0x30); - pci_write_config8(PCI_ADDR(0, 16, 0, 0), 0x5a, 0x33); - pci_write_config8(PCI_ADDR(0, 16, 0, 0), 0x5b, 0x33); - pci_write_config8(PCI_ADDR(0, 16, 0, 0), 0x5c, 0x33); - pci_write_config8(PCI_ADDR(0, 16, 0, 0), 0x5d, 0x33); - pci_write_config8(PCI_ADDR(0, 16, 0, 0), 0x5e, 0x33); - pci_write_config8(PCI_ADDR(0, 16, 0, 0), 0x5f, 0x33); -} - -static int i5000_setup_clocking(struct i5000_fbd_setup *setup) -{ - int fbd, fsb, ddrfrq, ddrfrqnow; - msr_t msr; - pci_devfn_t dev = PCI_ADDR(0, 16, 1, 0); - - switch(setup->ddr_speed) { - case DDR_667MHZ: - fbd = 667; - break; - case DDR_533MHZ: - fbd = 533; - break; - default: - printk(BIOS_ERR, "%s: unsupported FBD speed\n", __func__); - return 1; - } - - /* mainboard specific callback */ - if (mainboard_set_fbd_clock(fbd)) { - printk(BIOS_ERR, "%s: failed to set FBD speed\n", __func__); - return 1; - } - - msr = rdmsr(MSR_FSB_FREQ); - - switch(msr.lo & 7) { - case 1: - fsb = 533; - break; - case 4: - fsb = 667; - break; - default: - printk(BIOS_ERR, "%s: unsupported FSB speed: %d\n", __func__, msr.lo & 7); - return 1; - } - - - ddrfrq = pci_read_config8(PCI_ADDR(0, 16, 1, 0), 0x56); - ddrfrqnow = ddrfrq; - ddrfrq &= ~0x3; - - if (fsb < fbd) - ddrfrq |= 2; - else if (fsb > fbd) - ddrfrq |= 3; - - switch((ddrfrq >> 4) & 3) { - case 0: /* 1:1 mapping */ - pci_write_config32(dev, I5000_FBDTOHOSTGRCFG0, 0xffffffff); - pci_write_config32(dev, I5000_FBDTOHOSTGRCFG1, 0x00000000); - pci_write_config32(dev, I5000_HOSTTOFBDGRCFG, 0xffffffff); - pci_write_config8(dev, I5000_GRFBDLVLDCFG, 0x00); - pci_write_config8(dev, I5000_GRHOSTFULLCFG, 0x00); - pci_write_config8(dev, I5000_GRBUBBLECFG, 0x00); - pci_write_config8(dev, I5000_GRFBDTOHOSTDBLCFG, 0x00); - break; - case 2: /* 4:5 mapping */ - pci_write_config32(dev, I5000_FBDTOHOSTGRCFG0, 0x00002323); - pci_write_config32(dev, I5000_FBDTOHOSTGRCFG1, 0x00000400); - pci_write_config32(dev, I5000_HOSTTOFBDGRCFG, 0x23023); - pci_write_config8(dev, I5000_GRFBDLVLDCFG, 0x04); - pci_write_config8(dev, I5000_GRHOSTFULLCFG, 0x08); - pci_write_config8(dev, I5000_GRBUBBLECFG, 0x00); - pci_write_config8(dev, I5000_GRFBDTOHOSTDBLCFG, 0x04); - break; - case 3: - /* 5:4 mapping */ - pci_write_config32(dev, I5000_FBDTOHOSTGRCFG0, 0x00023230); - pci_write_config32(dev, I5000_FBDTOHOSTGRCFG1, 0x00000000); - pci_write_config32(dev, I5000_HOSTTOFBDGRCFG, 0x4323); - pci_write_config8(dev, I5000_GRFBDLVLDCFG, 0x00); - pci_write_config8(dev, I5000_GRHOSTFULLCFG, 0x02); - pci_write_config8(dev, I5000_GRBUBBLECFG, 0x10); - pci_write_config8(dev, I5000_GRFBDTOHOSTDBLCFG, 0x00); - break; - default: - printk(BIOS_DEBUG, "invalid DDRFRQ: %02x\n", ddrfrq); - return -1; - } - - if (ddrfrq != ddrfrqnow) { - printk(BIOS_DEBUG, "old DDRFRQ: 0x%02x new DDRFRQ: 0x%02x\n", - ddrfrqnow, ddrfrq); - pci_write_config8(PCI_ADDR(0, 16, 1, 0), 0x56, ddrfrq); - /* FSB:FBD mapping changed, needs hard reset */ - outb(0x06, 0xcf9); - halt(); - } - return 0; -} - -void i5000_fbdimm_init(void) -{ - struct i5000_fbd_setup setup; - u32 mca, mc; - - memset(&setup, 0, sizeof(setup)); - - pci_write_config16(PCI_ADDR(0, 0, 0, 0), 0x4, 0x144); - - i5000_init_setup(&setup); - - pci_write_config32(PCI_DEV(0, 16, 0), 0xf0, - pci_read_config32(PCI_ADDR(0, 16, 0, 0), 0xf0) | 0x8000); - - i5000_clear_fbd_errors(); - - printk(BIOS_INFO, "detecting memory modules\n"); - if (i5000_for_each_dimm(&setup, i5000_read_spd_data)) { - printk(BIOS_ERR, "%s: failed to read SPD data\n", __func__); - return; - } - - if (i5000_setup_clocking(&setup)) { - printk(BIOS_ERR, "%s: failed to set FBD clock\n", __func__); - return; - } - - /* posted CAS requires t_AL = t_RCD - 1 */ - setup.t_al = setup.t_rcd - 1; - - printk(BIOS_DEBUG, "global timing parameters:\n" - "CL: %d RAS: %d WRC: %d RC: %d RFC: %d RRD: %d REF: %d W2RDR: %d\n" - "R2W: %d W2R: %d R2R: %d W2W: %d WTR: %d RCD: %d RP %d WR: %d RTP: %d AL: %d\n", - setup.t_cl, setup.t_ras, setup.t_wrc, setup.t_rc, setup.t_rfc, - setup.t_rrd, setup.t_ref, setup.t_w2rdr, setup.t_r2w, setup.t_w2r, - setup.t_r2r, setup.t_w2w, setup.t_wtr, setup.t_rcd, - setup.t_rp, setup.t_wr, setup.t_rtp, setup.t_al); - - setup.single_channel = (!(setup.branch[0].channel[1].used || - setup.branch[1].channel[0].used || - setup.branch[1].channel[1].used)); - - pci_write_config32(PCI_ADDR(0, 16, 1, 0), 0x019C, 0x8010c); - pci_write_config32(PCI_ADDR(0, 16, 1, 0), 0x01F4, 0); - - /* enable or disable single channel mode */ - mca = pci_read_config32(PCI_ADDR(0, 16, 1, 0), I5000_MCA); - if (setup.single_channel) - mca |= (1 << 14); - else - mca &= ~(1 << 14); - pci_write_config32(PCI_ADDR(0, 16, 1, 0), I5000_MCA, mca); - - /* - * i5000 supports burst length 8 only in single channel mode - * so strip BL_BL8 if we're operating in multichannel mode - */ - - if (!setup.single_channel) - setup.bl &= ~BL_BL8; - - if (!setup.bl) - die("No supported burst length found\n"); - - mc = pci_read_config32(PCI_ADDR(0, 16, 1, 0), I5000_MC); - /* disable error checking for training */ - pci_write_config32(PCI_ADDR(0, 16, 1, 0), I5000_MC, mc & ~0x20); - - printk(BIOS_INFO, "performing fbd link initialization..."); - if (i5000_for_each_branch(&setup, i5000_branch_reset) || - i5000_for_each_dimm_present(&setup, i5000_amb_preinit) || - i5000_for_each_branch(&setup, i5000_link_training0) || - i5000_for_each_dimm_present(&setup, i5000_amb_check) || - i5000_for_each_dimm_present(&setup, i5000_amb_postinit) || - i5000_for_each_branch(&setup, i5000_link_training1)) { - i5000_try_restart("failed\n"); - } - printk(BIOS_INFO, "done\n"); - printk(BIOS_INFO, "initializing memory..."); - - if (i5000_for_each_dimm_present(&setup, i5000_ddr_init) || - i5000_for_each_dimm_present(&setup, i5000_amb_dram_timing_init) || - i5000_for_each_dimm_present(&setup, i5000_ddr_calibration)) { - i5000_try_restart("failed\n"); - } - printk(BIOS_INFO,"done\n"); - printk(BIOS_INFO, "clearing memory..."); - - if (i5000_membist(&setup)) - i5000_try_restart("failed\n"); - else - printk(BIOS_INFO, "done\n"); - - if (i5000_for_each_dimm_present(&setup, i5000_enable_mc_autorefresh)) - i5000_try_restart("failed to enable auto refresh\n"); - - i5000_fbd_next_state(&setup.branch[0], I5000_FBDHPC_STATE_INIT); - i5000_fbd_next_state(&setup.branch[1], I5000_FBDHPC_STATE_INIT); - - if (i5000_for_each_branch(&setup, i5000_link_training0)) - i5000_try_restart("Channel training failed\n"); - - if (setup.branch[0].used) - i5000_fbd_next_state(&setup.branch[0], I5000_FBDHPC_STATE_READY); - - if (setup.branch[1].used) - i5000_fbd_next_state(&setup.branch[1], I5000_FBDHPC_STATE_READY); - - i5000_clear_fbd_errors(); - - /* enable error checking */ - pci_write_config32(PCI_ADDR(0, 16, 1, 0), I5000_MC, mc | 0x20); - - i5000_dram_timing_init(&setup); - - i5000_reserved_register_init(&setup); - - i5000_pam_setup(); - - if (i5000_for_each_dimm_present(&setup, i5000_amb_clear_error_status)) - i5000_try_restart("failed to clear error status\n"); - - if (setup.branch[0].used) - i5000_fbd_next_state(&setup.branch[0], I5000_FBDHPC_STATE_ACTIVE); - - if (setup.branch[1].used) - i5000_fbd_next_state(&setup.branch[1], I5000_FBDHPC_STATE_ACTIVE); - -#if IS_ENABLED(CONFIG_NORTHBRIDGE_INTEL_I5000_RAM_CHECK) - if (ram_check_nodie(0x000000, 0x0a0000) || - ram_check_nodie(0x100000, MIN(setup.totalmem * 1048576, 0xd0000000))) { - i5000_try_restart("RAM verification failed"); - - } -#endif - - printk(BIOS_INFO, "Memory initialization finished\n"); -} diff --git a/src/northbridge/intel/i5000/raminit.h b/src/northbridge/intel/i5000/raminit.h deleted file mode 100644 index 0c554439c4..0000000000 --- a/src/northbridge/intel/i5000/raminit.h +++ /dev/null @@ -1,331 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2011 Sven Schnelle - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; version 2 of - * the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef NORTHBRIDGE_I5000_RAMINIT_H -#define NORTHBRIDGE_I5000_RAMINIT_H - -#include -#include - -#define I5000_MAX_BRANCH 2 -#define I5000_MAX_CHANNEL 2 -#define I5000_MAX_DIMM_PER_CHANNEL 4 -#define I5000_MAX_DIMMS (I5000_MAX_BRANCH * I5000_MAX_CHANNEL * I5000_MAX_DIMM_PER_CHANNEL) - -#define I5000_FBDRST 0x53 - -#define I5000_SPD_BUSY (1 << 12) -#define I5000_SPD_SBE (1 << 13) -#define I5000_SPD_WOD (1 << 14) -#define I5000_SPD_RDO (1 << 15) - -#define I5000_SPD0 0x74 -#define I5000_SPD1 0x76 - -#define I5000_SPDCMD0 0x78 -#define I5000_SPDCMD1 0x7c - -#define I5000_FBDHPC 0x4f -#define I5000_FBDST 0x4b - -#define I5000_FBDHPC_STATE_RESET 0x00 -#define I5000_FBDHPC_STATE_INIT 0x10 -#define I5000_FBDHPC_STATE_READY 0x20 -#define I5000_FBDHPC_STATE_ACTIVE 0x30 - -#define I5000_FBDISTS0 0x58 -#define I5000_FBDISTS1 0x5a - -#define I5000_FBDLVL0 0x44 -#define I5000_FBDLVL1 0x45 - -#define I5000_FBDICMD0 0x46 -#define I5000_FBDICMD1 0x47 - -#define I5000_FBDICMD_IDLE 0x00 -#define I5000_FBDICMD_TS0 0x80 -#define I5000_FBDICMD_TS1 0x90 -#define I5000_FBDICMD_TS2 0xa0 -#define I5000_FBDICMD_TS3 0xb0 -#define I5000_FBDICMD_TS2_MERGE 0xd0 -#define I5000_FBDICMD_TS2_NOMERGE 0xe0 -#define I5000_FBDICMD_ALL_ONES 0xf0 - -#define I5000_AMBPRESENT0 0x64 -#define I5000_AMBPRESENT1 0x66 - -#define I5000_FBDSBTXCFG0 0xc0 -#define I5000_FBDSBTXCFG1 0xc1 - -#define I5000_PROCENABLE 0xf0 -#define I5000_FBD0IBPORTCTL 0x180 -#define I5000_FBD0IBTXPAT2EN 0x1a8 -#define I5000_FBD0IBRXPAT2EN 0x1ac - -#define I5000_FBD0IBTXMSK 0x18c -#define I5000_FBD0IBRXMSK 0x190 - -#define I5000_FBDPLLCTRL 0x1c0 - -/* dev 16, function 1 registers */ -#define I5000_MC 0x40 -#define I5000_DRTA 0x48 -#define I5000_DRTB 0x4c -#define I5000_ERRPERR 0x50 -#define I5000_MCA 0x58 -#define I5000_TOLM 0x6c -#define I5000_MIR0 0x80 -#define I5000_MIR1 0x84 -#define I5000_MIR2 0x88 -#define I5000_AMIR0 0x8c -#define I5000_AMIR1 0x90 -#define I5000_AMIR2 0x94 - -#define I5000_FERR_FAT_FBD 0x98 -#define I5000_NERR_FAT_FBD 0x9c -#define I5000_FERR_NF_FBD 0xa0 -#define I5000_NERR_NF_FBD 0xa4 -#define I5000_EMASK_FBD 0xa8 -#define I5000_ERR0_FBD 0xac -#define I5000_ERR1_FBD 0xb0 -#define I5000_ERR2_FBD 0xb4 -#define I5000_MCERR_FBD 0xb8 -#define I5000_NRECMEMA 0xbe -#define I5000_NRECMEMB 0xc0 -#define I5000_NRECFGLOG 0xc4 -#define I5000_NRECMEMA 0xbe -#define I5000_NRECFBDA 0xc8 -#define I5000_NRECFBDB 0xcc -#define I5000_NRECFBDC 0xd0 -#define I5000_NRECFBDD 0xd4 -#define I5000_NRECFBDE 0xd8 - -#define I5000_REDMEMB 0x7c -#define I5000_RECMEMA 0xe2 -#define I5000_RECMEMB 0xe4 -#define I5000_RECFGLOG 0xe8 -#define I5000_RECFBDA 0xec -#define I5000_RECFBDB 0xf0 -#define I5000_RECFBDC 0xf4 -#define I5000_RECFBDD 0xf8 -#define I5000_RECFBDE 0xfc - -#define I5000_FBDTOHOSTGRCFG0 0x160 -#define I5000_FBDTOHOSTGRCFG1 0x164 -#define I5000_HOSTTOFBDGRCFG 0x168 -#define I5000_GRFBDLVLDCFG 0x16c -#define I5000_GRHOSTFULLCFG 0x16d -#define I5000_GRBUBBLECFG 0x16e -#define I5000_GRFBDTOHOSTDBLCFG 0x16f - -/* dev 16, function 2 registers */ -#define I5000_FERR_GLOBAL 0x40 -#define I5000_NERR_GLOBAL 0x44 - -/* dev 21, function 0 registers */ -#define I5000_MTR0 0x80 -#define I5000_MTR1 0x84 -#define I5000_MTR2 0x88 -#define I5000_MTR3 0x8c -#define I5000_DMIR0 0x90 -#define I5000_DMIR1 0x94 -#define I5000_DMIR2 0x98 -#define I5000_DMIR3 0x9c -#define I5000_DMIR4 0xa0 - -#define DEFAULT_AMBASE ((u8 *)0xfe000000) - -/* AMB function 1 registers */ -#define AMB_FBDSBCFGNXT 0x54 -#define AMB_FBDLOCKTO 0x68 -#define AMB_EMASK 0x8c -#define AMB_FERR 0x90 -#define AMB_NERR 0x94 -#define AMB_CMD2DATANXT 0xe8 - -/* AMB function 3 registers */ -#define AMB_DAREFTC 0x70 -#define AMB_DSREFTC 0x74 -#define AMB_DRT 0x78 -#define AMB_DRC 0x7c - -#define AMB_MBCSR 0x40 -#define AMB_MBADDR 0x44 -#define AMB_MBLFSRSED 0xa4 - -/* AMB function 4 registers */ -#define AMB_DCALCSR 0x40 -#define AMB_DCALADDR 0x44 -#define AMB_DCALCSR_START (1 << 31) - -#define AMB_DCALCSR_OPCODE_NOP 0x00 -#define AMB_DCALCSR_OPCODE_REFRESH 0x01 -#define AMB_DCALCSR_OPCODE_PRECHARGE 0x02 -#define AMB_DCALCSR_OPCODE_MRS_EMRS 0x03 -#define AMB_DCALCSR_OPCODE_DQS_DELAY_CAL 0x05 -#define AMB_DCALCSR_OPCODE_RECV_ENABLE_CAL 0x0c -#define AMB_DCALCSR_OPCODE_SELF_REFRESH_ENTRY 0x0d - -#define AMB_DDR2ODTC 0xfc - -#define FBDIMM_SPD_SDRAM_ADDRESSING 0x04 -#define FBDIMM_SPD_MODULE_ORGANIZATION 0x07 -#define FBDIMM_SPD_FTB 0x08 -#define FBDIMM_SPD_MTB_DIVIDEND 0x09 -#define FBDIMM_SPD_MTB_DIVISOR 0x0a -#define FBDIMM_SPD_MIN_TCK 0x0b -#define FBDIMM_SPD_CAS_LATENCIES 0x0d -#define FBDIMM_SPD_CAS_MIN_LATENCY 0x0e -#define FBDIMM_SPD_T_WR 0x10 -#define FBDIMM_SPD_T_RCD 0x13 -#define FBDIMM_SPD_T_RRD 0x14 -#define FBDIMM_SPD_T_RP 0x15 -#define FBDIMM_SPD_T_RAS_RC_MSB 0x16 -#define FBDIMM_SPD_T_RAS 0x17 -#define FBDIMM_SPD_T_RC 0x18 -#define FBDIMM_SPD_T_RFC 0x19 -#define FBDIMM_SPD_T_WTR 0x1b -#define FBDIMM_SPD_T_RTP 0x1c -#define FBDIMM_SPD_BURST_LENGTHS_SUPPORTED 0x1d -#define FBDIMM_SPD_ODT 0x4f -#define FBDIMM_SPD_T_REFI 0x20 -#define FBDIMM_SPD_T_BB 0x83 -#define FBDIMM_SPD_CMD2DATA_800 0x54 -#define FBDIMM_SPD_CMD2DATA_667 0x55 -#define FBDIMM_SPD_CMD2DATA_533 0x56 - -void i5000_fbdimm_init(void); - -#define I5000_BURST4 0x01 -#define I5000_BURST8 0x02 -#define I5000_BURST_CHOP 0x80 - -#define I5000_ODT_50 4 -#define I5000_ODT_75 2 -#define I5000_ODT_150 1 - -enum ddr_speeds { - DDR_533MHZ, - DDR_667MHZ, - DDR_MAX, -}; - -struct i5000_fbdimm { - struct i5000_fbd_branch *branch; - struct i5000_fbd_channel *channel; - struct i5000_fbd_setup *setup; - enum ddr_speeds speed; - int num; - int present:1; - u32 ambase; - - /* SPD data */ - u8 amb_personality_bytes[14]; - u8 banks; - u8 rows; - u8 columns; - u8 ranks; - u8 odt; - u8 sdram_width; - u8 mtb_divisor; - u8 mtb_dividend; - u8 t_ck_min; - u8 min_cas_latency; - u8 t_rrd; - u16 t_rfc; - u8 t_wtr; - u8 t_refi; - u8 cmd2datanxt[DDR_MAX]; - - u16 vendor; - u16 device; - - /* memory rank size in MB */ - int ranksize; -}; - -struct i5000_fbd_channel { - struct i5000_fbdimm dimm[I5000_MAX_DIMM_PER_CHANNEL]; - struct i5000_fbd_branch *branch; - struct i5000_fbd_setup *setup; - int num; - int used; - int highest_amb; - int columns; - int rows; - int ranks; - int banks; - int width; - /* memory size in MB on this channel */ - int totalmem; -}; - -struct i5000_fbd_branch { - struct i5000_fbd_channel channel[I5000_MAX_CHANNEL]; - struct i5000_fbd_setup *setup; - pci_devfn_t branchdev; - int num; - int used; - /* memory size in MB on this branch */ - int totalmem; -}; - -enum odt { - ODT_150OHM=1, - ODT_50OHM=4, - ODT_75OHM=2, -}; - -enum bl { - BL_BL4=1, - BL_BL8=2, -}; - -struct i5000_fbd_setup { - struct i5000_fbd_branch branch[I5000_MAX_BRANCH]; - struct i5000_fbdimm *dimms[I5000_MAX_DIMMS]; - enum bl bl; - enum ddr_speeds ddr_speed; - - int single_channel:1; - u32 tolm; - - /* global SDRAM timing parameters */ - u8 t_al; - u8 t_cl; - u8 t_ras; - u8 t_wrc; - u8 t_rc; - u8 t_rfc; - u8 t_rrd; - u8 t_ref; - u8 t_w2rdr; - u8 t_r2w; - u8 t_w2r; - u8 t_r2r; - u8 t_w2w; - u8 t_wtr; - u8 t_rcd; - u8 t_rp; - u8 t_wr; - u8 t_rtp; - /* memory size in MB */ - int totalmem; -}; - -int mainboard_set_fbd_clock(int); -#define AMB_ADDR(base, fn, reg) (base | ((fn & 7) << 8) | ((reg & 0xff))) -#endif -- cgit v1.2.3