[coreboot] New patch to review for coreboot: 653c1c6 haswell: resource allocation

Stefan Reinauer (stefan.reinauer@coreboot.org) gerrit at coreboot.org
Wed Mar 13 02:25:10 CET 2013


Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2687

-gerrit

commit 653c1c6674e1e426fd78a09834becefa2ad891e1
Author: Aaron Durbin <adurbin at chromium.org>
Date:   Tue Dec 18 14:22:49 2012 -0600

    haswell: resource allocation
    
    The previous code w.r.t. resource allocation was getting lucky
    based on the way fixed mmio resources on the system were being
    chosen. Namely, PCIEXBAR was the lowest mmio space and the other
    fixed non-standar BARs were above it. The resource allocator would
    then start allocating standard BARs below that.
    
    On top of that other resources were being added when
    dev_ops->set_resources() was being called on the PCI domain. At that
    point the PCI range limit were already picked for where to start
    allocating from.
    
    To ensure we no longer get lucky during resource allocation add the
    fixed resources in the host bridge and add the memory controller
    cacheable memory areas. With those resources added the range limit
    for standard PCI BARs is chosen properly.
    
    Depending on haswell board configurations we may need to adjust and
    pass in the size of physical address space needed for PCI resources
    to the reference code. For the time being the CRBs appear to be OK.
    
    Lastly, remove the SNB workaround for reserving 2MiB at 1GiB and 512MiB.
    
    Output from 6GiB memory configuration:
    	MC MAP: TOM: 0x140000000
    	MC MAP: TOUUD: 0x18f600000
    	MC MAP: MESEG_BASE: 0x13f000000
    	MC MAP: MESEG_LIMIT: 0x7fff0fffff
    	MC MAP: REMAP_BASE: 0x13f000000
    	MC MAP: REMAP_LIMIT: 0x18f5fffff
    	MC MAP: TOLUD: 0xafa00000
    	MC MAP: BDSM: 0xada00000
    	MC MAP: BGSM: 0xad800000
    	MC MAP: TESGMB: 0xad000000
    	MC MAP: GGC: 0x209
    
    	coreboot memory table:
    	 0. 0000000000000000-0000000000000fff: CONFIGURATION TABLES
    	 1. 0000000000001000-000000000009ffff: RAM
    	 2. 00000000000a0000-00000000000fffff: RESERVED
    	 3. 0000000000100000-0000000000efffff: RAM
    	 4. 0000000000f00000-0000000000ffffff: RESERVED
    	 5. 0000000001000000-00000000acebffff: RAM
    	 6. 00000000acec0000-00000000acffffff: CONFIGURATION TABLES
    	 7. 00000000ad000000-00000000af9fffff: RESERVED
    	 8. 00000000f0000000-00000000f3ffffff: RESERVED
    	 9. 00000000fed10000-00000000fed17fff: RESERVED
    	10. 00000000fed18000-00000000fed18fff: RESERVED
    	11. 00000000fed19000-00000000fed19fff: RESERVED
    	12. 00000000fed84000-00000000fed84fff: RESERVED
    	13. 0000000100000000-000000018f5fffff: RAM
    
    	e820 map has 11 items:
    	  0: 0000000000000000 - 000000000009fc00 = 1 RAM
    	  1: 000000000009fc00 - 00000000000a0000 = 2 RESERVED
    	  2: 00000000000f0000 - 0000000000100000 = 2 RESERVED
    	  3: 0000000000100000 - 0000000000f00000 = 1 RAM
    	  4: 0000000000f00000 - 0000000001000000 = 2 RESERVED
    	  5: 0000000001000000 - 00000000acec0000 = 1 RAM
    	  6: 00000000acec0000 - 00000000afa00000 = 2 RESERVED
    	  7: 00000000f0000000 - 00000000f4000000 = 2 RESERVED
    	  8: 00000000fed10000 - 00000000fed1a000 = 2 RESERVED
    	  9: 00000000fed84000 - 00000000fed85000 = 2 RESERVED
    	  10: 0000000100000000 - 000000018f600000 = 1 RAM
    
    Output from 4GiB memory configuration:
    	MC MAP: TOM: 0x100000000
    	MC MAP: TOUUD: 0x14f600000
    	MC MAP: MESEG_BASE: 0xff000000
    	MC MAP: MESEG_LIMIT: 0x7fff0fffff
    	MC MAP: REMAP_BASE: 0x100000000
    	MC MAP: REMAP_LIMIT: 0x14f5fffff
    	MC MAP: TOLUD: 0xafa00000
    	MC MAP: BDSM: 0xada00000
    	MC MAP: BGSM: 0xad800000
    	MC MAP: TESGMB: 0xad000000
    	MC MAP: GGC: 0x209
    
    	coreboot memory table:
    	 0. 0000000000000000-0000000000000fff: CONFIGURATION TABLES
    	 1. 0000000000001000-000000000009ffff: RAM
    	 2. 00000000000a0000-00000000000fffff: RESERVED
    	 3. 0000000000100000-0000000000efffff: RAM
    	 4. 0000000000f00000-0000000000ffffff: RESERVED
    	 5. 0000000001000000-00000000acebffff: RAM
    	 6. 00000000acec0000-00000000acffffff: CONFIGURATION TABLES
    	 7. 00000000ad000000-00000000af9fffff: RESERVED
    	 8. 00000000f0000000-00000000f3ffffff: RESERVED
    	 9. 00000000fed10000-00000000fed17fff: RESERVED
    	10. 00000000fed18000-00000000fed18fff: RESERVED
    	11. 00000000fed19000-00000000fed19fff: RESERVED
    	12. 00000000fed84000-00000000fed84fff: RESERVED
    	13. 0000000100000000-000000014f5fffff: RAM
    
    	e820 map has 11 items:
    	  0: 0000000000000000 - 000000000009fc00 = 1 RAM
    	  1: 000000000009fc00 - 00000000000a0000 = 2 RESERVED
    	  2: 00000000000f0000 - 0000000000100000 = 2 RESERVED
    	  3: 0000000000100000 - 0000000000f00000 = 1 RAM
    	  4: 0000000000f00000 - 0000000001000000 = 2 RESERVED
    	  5: 0000000001000000 - 00000000acec0000 = 1 RAM
    	  6: 00000000acec0000 - 00000000afa00000 = 2 RESERVED
    	  7: 00000000f0000000 - 00000000f4000000 = 2 RESERVED
    	  8: 00000000fed10000 - 00000000fed1a000 = 2 RESERVED
    	  9: 00000000fed84000 - 00000000fed85000 = 2 RESERVED
    	  10: 0000000100000000 - 000000014f600000 = 1 RAM
    
    Output from 2GiB memory configuration:
    	MC MAP: TOM: 0x40000000
    	MC MAP: TOUUD: 0x100600000
    	MC MAP: MESEG_BASE: 0x3f000000
    	MC MAP: MESEG_LIMIT: 0x7fff0fffff
    	MC MAP: REMAP_BASE: 0x100000000
    	MC MAP: REMAP_LIMIT: 0x1005fffff
    	MC MAP: TOLUD: 0x3ea00000
    	MC MAP: BDSM: 0x3ca00000
    	MC MAP: BGSM: 0x3c800000
    	MC MAP: TESGMB: 0x3c000000
    	MC MAP: GGC: 0x209
    
    	coreboot memory table:
    	 0. 0000000000000000-0000000000000fff: CONFIGURATION TABLES
    	 1. 0000000000001000-000000000009ffff: RAM
    	 2. 00000000000a0000-00000000000fffff: RESERVED
    	 3. 0000000000100000-0000000000efffff: RAM
    	 4. 0000000000f00000-0000000000ffffff: RESERVED
    	 5. 0000000001000000-000000003bebffff: RAM
    	 6. 000000003bec0000-000000003bffffff: CONFIGURATION TABLES
    	 7. 000000003c000000-000000003e9fffff: RESERVED
    	 8. 00000000f0000000-00000000f3ffffff: RESERVED
    	 9. 00000000fed10000-00000000fed17fff: RESERVED
    	10. 00000000fed18000-00000000fed18fff: RESERVED
    	11. 00000000fed19000-00000000fed19fff: RESERVED
    	12. 00000000fed84000-00000000fed84fff: RESERVED
    	13. 0000000100000000-00000001005fffff: RAM
    
    	e820 map has 11 items:
    	  0: 0000000000000000 - 000000000009fc00 = 1 RAM
    	  1: 000000000009fc00 - 00000000000a0000 = 2 RESERVED
    	  2: 00000000000f0000 - 0000000000100000 = 2 RESERVED
    	  3: 0000000000100000 - 0000000000f00000 = 1 RAM
    	  4: 0000000000f00000 - 0000000001000000 = 2 RESERVED
    	  5: 0000000001000000 - 000000003bec0000 = 1 RAM
    	  6: 000000003bec0000 - 000000003ea00000 = 2 RESERVED
    	  7: 00000000f0000000 - 00000000f4000000 = 2 RESERVED
    	  8: 00000000fed10000 - 00000000fed1a000 = 2 RESERVED
    	  9: 00000000fed84000 - 00000000fed85000 = 2 RESERVED
    	  10: 0000000100000000 - 0000000100600000 = 1 RAM
    
    Verified through debug messages that range limits as well as
    resources were being properly honored.
    
    Change-Id: I2faa7d8a2a34a6a411a2885afb3b5c3fa1ad9c23
    Signed-off-by: Aaron Durbin <adurbin at chromium.org>
---
 src/northbridge/intel/haswell/haswell.h     |   9 +-
 src/northbridge/intel/haswell/northbridge.c | 457 ++++++++++++++++------------
 2 files changed, 275 insertions(+), 191 deletions(-)

diff --git a/src/northbridge/intel/haswell/haswell.h b/src/northbridge/intel/haswell/haswell.h
index 967a186..bbb51aa 100644
--- a/src/northbridge/intel/haswell/haswell.h
+++ b/src/northbridge/intel/haswell/haswell.h
@@ -63,7 +63,6 @@
 #define MCHBAR		0x48
 #define PCIEXBAR	0x60
 #define DMIBAR		0x68
-#define X60BAR		0x60
 
 #define GGC		0x50			/* GMCH Graphics Control */
 
@@ -91,8 +90,14 @@
 #define  G_SMRAME	(1 << 3)
 #define  C_BASE_SEG	((0 << 2) | (1 << 1) | (0 << 0))
 
-#define TOM		0xa0
+#define MESEG_BASE	0x70	/* Management Engine Base. */
+#define MESEG_LIMIT	0x78	/* Management Engine Limit. */
+#define REMAPBASE	0x90	/* Remap base. */
+#define REMAPLIMIT	0x98	/* Remap limit. */
+#define TOM		0xa0	/* Top of DRAM in memory controller space. */
 #define TOUUD		0xa8	/* Top of Upper Usable DRAM */
+#define BDSM		0xb0	/* Base Data Stolen Memory */
+#define BGSM		0xb4	/* Base GTT Stolen Memory */
 #define TSEG		0xb8	/* TSEG base */
 #define TOLUD		0xbc	/* Top of Low Used Memory */
 
diff --git a/src/northbridge/intel/haswell/northbridge.c b/src/northbridge/intel/haswell/northbridge.c
index 5731077..e97ef55 100644
--- a/src/northbridge/intel/haswell/northbridge.c
+++ b/src/northbridge/intel/haswell/northbridge.c
@@ -65,19 +65,14 @@ void cbmem_post_handling(void)
 	update_mrc_cache();
 }
 
-static int get_pcie_bar(u32 *base, u32 *len)
+static int get_pcie_bar(device_t dev, unsigned int index, u32 *base, u32 *len)
 {
-	device_t dev;
 	u32 pciexbar_reg;
 
 	*base = 0;
 	*len = 0;
 
-	dev = dev_find_slot(0, PCI_DEVFN(0, 0));
-	if (!dev)
-		return 0;
-
-	pciexbar_reg = pci_read_config32(dev, PCIEXBAR);
+	pciexbar_reg = pci_read_config32(dev, index);
 
 	if (!(pciexbar_reg & (1 << 0)))
 		return 0;
@@ -100,221 +95,305 @@ static int get_pcie_bar(u32 *base, u32 *len)
 	return 0;
 }
 
-static void add_fixed_resources(struct device *dev, int index)
+static void pci_domain_set_resources(device_t dev)
 {
-	struct resource *resource;
-	u32 pcie_config_base, pcie_config_size;
-
-	printk(BIOS_DEBUG, "Adding UMA memory area base=0x%llx "
-	       "size=0x%llx\n", uma_memory_base, uma_memory_size);
-	resource = new_resource(dev, index);
-	resource->base = (resource_t) uma_memory_base;
-	resource->size = (resource_t) uma_memory_size;
-	resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE |
-	    IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
-
-	/* Clear these values here so they don't get used by MTRR code */
-	uma_memory_base = 0;
-	uma_memory_size = 0;
-
-	if (get_pcie_bar(&pcie_config_base, &pcie_config_size)) {
-		printk(BIOS_DEBUG, "Adding PCIe config bar base=0x%08x "
-		       "size=0x%x\n", pcie_config_base, pcie_config_size);
-		resource = new_resource(dev, index+1);
-		resource->base = (resource_t) pcie_config_base;
-		resource->size = (resource_t) pcie_config_size;
-		resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE |
-		    IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
-	}
-
-	mmio_resource(dev, index++, legacy_hole_base_k, legacy_hole_size_k);
+	assign_resources(dev->link_list);
+}
 
-#if CONFIG_CHROMEOS_RAMOOPS
-	mmio_resource(dev, index++, CONFIG_CHROMEOS_RAMOOPS_RAM_START >> 10,
-			CONFIG_CHROMEOS_RAMOOPS_RAM_SIZE >> 10);
+	/* TODO We could determine how many PCIe busses we need in
+	 * the bar. For now that number is hardcoded to a max of 64.
+	 * See e7525/northbridge.c for an example.
+	 */
+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,
+#if CONFIG_MMCONF_SUPPORT_DEFAULT
+	.ops_pci_bus	  = &pci_ops_mmconf,
+#else
+	.ops_pci_bus	  = &pci_cf8_conf1,
 #endif
+};
 
-	/* Required for SandyBridge sighting 3715511 */
-	bad_ram_resource(dev, index++, 0x20000000 >> 10, 0x00200000 >> 10);
-	bad_ram_resource(dev, index++, 0x40000000 >> 10, 0x00200000 >> 10);
+static int get_bar(device_t dev, unsigned int index, u32 *base, u32 *len)
+{
+	u32 bar;
+
+	bar = pci_read_config32(dev, index);
+
+	/* If not enabled don't report it. */
+	if (!(bar & 0x1))
+		return 0;
+
+	/* Knock down the enable bit. */
+	*base = bar & ~1;
+
+	return 1;
 }
 
-static void pci_domain_set_resources(device_t dev)
+/* There are special BARs that actually are programmed in the MCHBAR. These
+ * Intel special features, but they do consume resources that need to be
+ * accounted for. */
+static int get_bar_in_mchbar(device_t dev, unsigned int index, u32 *base,
+                             u32 *len)
 {
-	uint64_t tom, me_base, touud;
-	uint32_t tseg_base, uma_size, tolud;
-	uint16_t ggc;
-	unsigned long long tomk;
+	u32 bar;
 
-	/* Total Memory 2GB example:
-	 *
-	 *  00000000  0000MB-1992MB  1992MB  RAM     (writeback)
-	 *  7c800000  1992MB-2000MB     8MB  TSEG    (SMRR)
-	 *  7d000000  2000MB-2002MB     2MB  GFX GTT (uncached)
-	 *  7d200000  2002MB-2034MB    32MB  GFX UMA (uncached)
-	 *  7f200000   2034MB TOLUD
-	 *  7f800000   2040MB MEBASE
-	 *  7f800000  2040MB-2048MB     8MB  ME UMA  (uncached)
-	 *  80000000   2048MB TOM
-	 * 100000000  4096MB-4102MB     6MB  RAM     (writeback)
-	 *
-	 * Total Memory 4GB example:
-	 *
-	 *  00000000  0000MB-2768MB  2768MB  RAM     (writeback)
-	 *  ad000000  2768MB-2776MB     8MB  TSEG    (SMRR)
-	 *  ad800000  2776MB-2778MB     2MB  GFX GTT (uncached)
-	 *  ada00000  2778MB-2810MB    32MB  GFX UMA (uncached)
-	 *  afa00000   2810MB TOLUD
-	 *  ff800000   4088MB MEBASE
-	 *  ff800000  4088MB-4096MB     8MB  ME UMA  (uncached)
-	 * 100000000   4096MB TOM
-	 * 100000000  4096MB-5374MB  1278MB  RAM     (writeback)
-	 * 14fe00000   5368MB TOUUD
-	 */
+	bar = MCHBAR32(index);
 
-	/* Top of Upper Usable DRAM, including remap */
-	touud = pci_read_config32(dev, TOUUD+4);
-	touud <<= 32;
-	touud |= pci_read_config32(dev, TOUUD) & ~1;
-
-	/* Top of Lower Usable DRAM */
-	tolud = pci_read_config32(dev, TOLUD) & ~1;
-
-	/* Top of Memory - does not account for any UMA */
-	tom = pci_read_config32(dev, 0xa4);
-	tom <<= 32;
-	tom |= pci_read_config32(dev, 0xa0) & ~1;
-
-	printk(BIOS_DEBUG, "TOUUD 0x%llx TOLUD 0x%08x TOM 0x%llx\n",
-	       touud, tolud, tom);
-
-	/* ME UMA needs excluding if total memory <4GB */
-	me_base = pci_read_config32(dev, 0x74);
-	me_base <<= 32;
-	me_base |= pci_read_config32(dev, 0x70);
-
-	printk(BIOS_DEBUG, "MEBASE 0x%llx\n", me_base);
-
-	tomk = tolud >> 10;
-	if (me_base == tolud) {
-		/* ME is from MEBASE-TOM */
-		uma_size = (tom - me_base) >> 10;
-		/* Increment TOLUD to account for ME as RAM */
-		tolud += uma_size << 10;
-		/* UMA starts at old TOLUD */
-		uma_memory_base = tomk * 1024ULL;
-		uma_memory_size = uma_size * 1024ULL;
-		printk(BIOS_DEBUG, "ME UMA base 0x%llx size %uM\n",
-		       me_base, uma_size >> 10);
-	}
+	/* If not enabled don't report it. */
+	if (!(bar & 0x1))
+		return 0;
+
+	/* Knock down the enable bit. */
+	*base = bar & ~1;
 
-	/* Graphics memory comes next */
-	ggc = pci_read_config16(dev, GGC);
-	if (!(ggc & 2)) {
-		printk(BIOS_DEBUG, "IGD decoded, subtracting ");
-
-		/* Graphics memory */
-		uma_size = ((ggc >> 3) & 0x1f) * 32 * 1024ULL;
-		printk(BIOS_DEBUG, "%uM UMA", uma_size >> 10);
-		tomk -= uma_size;
-		uma_memory_base = tomk * 1024ULL;
-		uma_memory_size += uma_size * 1024ULL;
-
-		/* GTT Graphics Stolen Memory Size (GGMS) */
-		uma_size = ((ggc >> 8) & 0x3) * 1024ULL;
-		tomk -= uma_size;
-		uma_memory_base = tomk * 1024ULL;
-		uma_memory_size += uma_size * 1024ULL;
-		printk(BIOS_DEBUG, " and %uM GTT\n", uma_size >> 10);
+	return 1;
+}
+
+struct fixed_mmio_descriptor {
+	unsigned int index;
+	u32 size;
+	int (*get_resource)(device_t dev, unsigned int index,
+	                    u32 *base, u32 *size);
+	const char *description;
+};
+
+#define SIZE_KB(x) ((x)*1024)
+struct fixed_mmio_descriptor mc_fixed_resources[] = {
+	{ PCIEXBAR, SIZE_KB(0),  get_pcie_bar,      "PCIEXBAR" },
+	{ MCHBAR,   SIZE_KB(32), get_bar,           "MCHBAR"   },
+	{ DMIBAR,   SIZE_KB(4),  get_bar,           "DMIBAR"   },
+	{ EPBAR,    SIZE_KB(4),  get_bar,           "EPBAR"    },
+	{ 0x5420,   SIZE_KB(4),  get_bar_in_mchbar, "GDXCBAR"  },
+	{ 0x5408,   SIZE_KB(16), get_bar_in_mchbar, "EDRAMBAR" },
+};
+#undef SIZE_KB
+
+/*
+ * Add all known fixed MMIO ranges that hang off the host bridge/memory
+ * controller device.
+ */
+static void mc_add_fixed_mmio_resources(device_t dev)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mc_fixed_resources); i++) {
+		u32 base;
+		u32 size;
+		struct resource *resource;
+		unsigned int index;
+
+		size = mc_fixed_resources[i].size;
+		index = mc_fixed_resources[i].index;
+		if (!mc_fixed_resources[i].get_resource(dev, index,
+		                                        &base, &size))
+			continue;
+
+		resource = new_resource(dev, mc_fixed_resources[i].index);
+		resource->flags = IORESOURCE_MEM | IORESOURCE_FIXED |
+		                  IORESOURCE_STORED | IORESOURCE_RESERVE |
+		                  IORESOURCE_ASSIGNED;
+		resource->base = base;
+		resource->size = size;
+		printk(BIOS_DEBUG, "%s: Adding %s @ %x 0x%08lx-0x%08lx.\n",
+		       __func__, mc_fixed_resources[i].description, index,
+		       (unsigned long)base, (unsigned long)(base + size - 1));
 	}
+}
 
-	/* Calculate TSEG size from its base which must be below GTT */
-	tseg_base = pci_read_config32(dev, 0xb8);
-	uma_size = (uma_memory_base - tseg_base) >> 10;
-	tomk -= uma_size;
-	uma_memory_base = tomk * 1024ULL;
-	uma_memory_size += uma_size * 1024ULL;
-	printk(BIOS_DEBUG, "TSEG base 0x%08x size %uM\n",
-	       tseg_base, uma_size >> 10);
+/* Host Memory Map:
+ *
+ * +--------------------------+ TOUUD
+ * |                          |
+ * +--------------------------+ 4GiB
+ * |     PCI Address Space    |
+ * +--------------------------+ TOLUD (also maps into MC address space)
+ * |     iGD                  |
+ * +--------------------------+ BDSM
+ * |     GTT                  |
+ * +--------------------------+ BGSM
+ * |     TSEG                 |
+ * +--------------------------+ TSEGMB
+ * |     Usage DRAM           |
+ * +--------------------------+ 0
+ *
+ * Some of the base registers above can be equal making the size of those
+ * regions 0. The reason is because the memory controller internally subtracts
+ * the base registers from each other to determine sizes of the regions. In
+ * other words, the memory map is in a fixed order no matter what.
+ */
 
-	printk(BIOS_INFO, "Available memory below 4GB: %lluM\n", tomk >> 10);
+struct map_entry {
+	int reg;
+	int is_64_bit;
+	int is_limit;
+	const char *description;
+};
 
-	/* Report the memory regions */
-	ram_resource(dev, 3, 0, legacy_hole_base_k);
-	ram_resource(dev, 4, legacy_hole_base_k + legacy_hole_size_k,
-	     (tomk - (legacy_hole_base_k + legacy_hole_size_k)));
+static void read_map_entry(device_t dev, struct map_entry *entry,
+                           uint64_t *result)
+{
+	uint64_t value;
+	uint64_t mask;
 
-	/*
-	 * If >= 4GB installed then memory from TOLUD to 4GB
-	 * is remapped above TOM, TOUUD will account for both
-	 */
-	touud >>= 10; /* Convert to KB */
-	if (touud > 4096 * 1024) {
-		ram_resource(dev, 5, 4096 * 1024, touud - (4096 * 1024));
-		printk(BIOS_INFO, "Available memory above 4GB: %lluM\n",
-		       (touud >> 10) - 4096);
+	/* All registers are on a 1MiB granularity. */
+	mask = ((1ULL<<20)-1);
+	mask = ~mask;
+
+	value = 0;
+
+	if (entry->is_64_bit) {
+		value = pci_read_config32(dev, entry->reg + 4);
+		value <<= 32;
 	}
 
-	add_fixed_resources(dev, 6);
+	value |= pci_read_config32(dev, entry->reg);
+	value &= mask;
 
-	assign_resources(dev->link_list);
+	if (entry->is_limit)
+		value |= ~mask;
 
-	/* Leave some space for ACPI, PIRQ and MP tables */
-	high_tables_base = (tomk * 1024) - HIGH_MEMORY_SIZE;
-	high_tables_size = HIGH_MEMORY_SIZE;
+	*result = value;
 }
 
-	/* TODO We could determine how many PCIe busses we need in
-	 * the bar. For now that number is hardcoded to a max of 64.
-	 * See e7525/northbridge.c for an example.
-	 */
-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,
-#if CONFIG_MMCONF_SUPPORT_DEFAULT
-	.ops_pci_bus	  = &pci_ops_mmconf,
-#else
-	.ops_pci_bus	  = &pci_cf8_conf1,
-#endif
+#define MAP_ENTRY(reg_, is_64_, is_limit_, desc_) \
+	{ \
+		.reg = reg_,           \
+		.is_64_bit = is_64_,   \
+		.is_limit = is_limit_, \
+		.description = desc_,  \
+	}
+
+#define MAP_ENTRY_BASE_64(reg_, desc_) \
+	MAP_ENTRY(reg_, 1, 0, desc_)
+#define MAP_ENTRY_LIMIT_64(reg_, desc_) \
+	MAP_ENTRY(reg_, 1, 1, desc_)
+#define MAP_ENTRY_BASE_32(reg_, desc_) \
+	MAP_ENTRY(reg_, 0, 0, desc_)
+
+enum {
+	TOM_REG,
+	TOUUD_REG,
+	MESEG_BASE_REG,
+	MESEG_LIMIT_REG,
+	REMAP_BASE_REG,
+	REMAP_LIMIT_REG,
+	TOLUD_REG,
+	BGSM_REG,
+	BDSM_REG,
+	TSEG_REG,
+	// Must be last.
+	NUM_MAP_ENTRIES
 };
 
-static void mc_read_resources(device_t dev)
+static struct map_entry memory_map[NUM_MAP_ENTRIES] = {
+	[TOM_REG] = MAP_ENTRY_BASE_64(TOM, "TOM"),
+	[TOUUD_REG] = MAP_ENTRY_BASE_64(TOUUD, "TOUUD"),
+	[MESEG_BASE_REG] = MAP_ENTRY_BASE_64(MESEG_BASE, "MESEG_BASE"),
+	[MESEG_LIMIT_REG] = MAP_ENTRY_LIMIT_64(MESEG_LIMIT, "MESEG_LIMIT"),
+	[REMAP_BASE_REG] = MAP_ENTRY_BASE_64(REMAPBASE, "REMAP_BASE"),
+	[REMAP_LIMIT_REG] = MAP_ENTRY_LIMIT_64(REMAPLIMIT, "REMAP_LIMIT"),
+	[TOLUD_REG] = MAP_ENTRY_BASE_32(TOLUD, "TOLUD"),
+	[BGSM_REG] = MAP_ENTRY_BASE_32(BDSM, "BDSM"),
+	[BDSM_REG] = MAP_ENTRY_BASE_32(BGSM, "BGSM"),
+	[TSEG_REG] = MAP_ENTRY_BASE_32(TSEG, "TESGMB"),
+};
+
+static void mc_read_map_entries(device_t dev, uint64_t *values)
 {
+	int i;
+	for (i = 0; i < NUM_MAP_ENTRIES; i++) {
+		read_map_entry(dev, &memory_map[i], &values[i]);
+	}
+}
+
+static void mc_report_map_entries(device_t dev, uint64_t *values)
+{
+	int i;
+	for (i = 0; i < NUM_MAP_ENTRIES; i++) {
+		printk(BIOS_DEBUG, "MC MAP: %s: 0x%llx\n",
+		       memory_map[i].description, values[i]);
+	}
+	/* One can validate the BDSM and BGSM against the GGC. */
+	printk(BIOS_DEBUG, "MC MAP: GGC: 0x%x\n", pci_read_config16(dev, GGC));
+}
+
+static void mc_add_dram_resources(device_t dev)
+{
+	unsigned long base_k, size_k;
+	unsigned long index;
 	struct resource *resource;
+	uint64_t mc_values[NUM_MAP_ENTRIES];
 
-	pci_dev_read_resources(dev);
+	/* Read in the MAP registers and report their values. */
+	mc_read_map_entries(dev, &mc_values[0]);
+	mc_report_map_entries(dev, &mc_values[0]);
 
-	/* So, this is one of the big mysteries in the coreboot resource
-	 * allocator. This resource should make sure that the address space
-	 * of the PCIe memory mapped config space bar. But it does not.
+	/*
+	 * There are 4 host memory ranges that should be added:
+	 * - 0 -> 0xa0000 : cacheable
+	 * - 0xc0000 -> TSEG : cacheable
+	 * - TESG -> TOLUD: not cacheable with standard MTRRs and reserved
+	 * - 4GiB -> TOUUD: cacheable
+	 *
+	 * The range 0xa0000 -> 0xc0000 does not have any resources
+	 * associated with it to handle legacy VGA memory. If this range
+	 * is not omitted the mtrr code will setup the area as cacheable
+	 * causing VGA access to not work.
+	 *
+	 * The resource index starts low and should not meet or exceed
+	 * PCI_BASE_ADDRESS_0. In this case there are only 3 entries so there
+	 * are no conflicts in the index space.
 	 */
+	index = 0;
+
+	/* 0 - > 0xa0000 */
+	base_k = 0;
+	size_k = 0xa0000 >> 10;
+	ram_resource(dev, index++, base_k, size_k);
+
+	/* 0xa0000 -> TSEG */
+	base_k = 0xc0000 >> 10;
+	size_k = (unsigned long)(mc_values[TSEG_REG] >> 10) - base_k;
+	ram_resource(dev, index++, base_k, size_k);
+
+	/* TSEG -> TOLUD */
+	resource = new_resource(dev, index++);
+	resource->base = mc_values[TSEG_REG];
+	resource->size = mc_values[TOLUD_REG] - resource->base;
+	resource->flags = IORESOURCE_MEM | IORESOURCE_FIXED |
+	                  IORESOURCE_STORED | IORESOURCE_RESERVE |
+	                  IORESOURCE_ASSIGNED;
+
+	/* 4GiB -> TOUUD */
+	base_k = 4096 * 1024; /* 4GiB */
+	size_k = (unsigned long)(mc_values[TOUUD_REG] >> 10) - base_k;
+	ram_resource(dev, index++, base_k, size_k);
+
+	mmio_resource(dev, index++, legacy_hole_base_k, legacy_hole_size_k);
+#if CONFIG_CHROMEOS_RAMOOPS
+	mmio_resource(dev, index++, CONFIG_CHROMEOS_RAMOOPS_RAM_START >> 10,
+			CONFIG_CHROMEOS_RAMOOPS_RAM_SIZE >> 10);
+#endif
 
-	/* We use 0xcf as an unused index for our PCIe bar so that we find it again */
-	resource = new_resource(dev, 0xcf);
-	resource->base = DEFAULT_PCIEXBAR;
-	resource->size = 64 * 1024 * 1024;	/* 64MB hard coded PCIe config space */
-	resource->flags =
-	    IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_STORED |
-	    IORESOURCE_ASSIGNED;
-	printk(BIOS_DEBUG, "Adding PCIe enhanced config space BAR 0x%08lx-0x%08lx.\n",
-		     (unsigned long)(resource->base), (unsigned long)(resource->base + resource->size));
+	/* Leave some space for ACPI, PIRQ and MP tables */
+	high_tables_size = HIGH_MEMORY_SIZE;
+	high_tables_base = mc_values[TSEG_REG] - high_tables_size;
 }
 
-static void mc_set_resources(device_t dev)
+static void mc_read_resources(device_t dev)
 {
-	struct resource *resource;
+	/* Read standard PCI resources. */
+	pci_dev_read_resources(dev);
 
-	/* Report the PCIe BAR */
-	resource = find_resource(dev, 0xcf);
-	if (resource) {
-		report_resource_stored(dev, resource, "<mmconfig>");
-	}
+	/* Add all fixed MMIO resources. */
+	mc_add_fixed_mmio_resources(dev);
 
-	/* And call the normal set_resources */
-	pci_dev_set_resources(dev);
+	/* Calculate and add DRAM resources. */
+	mc_add_dram_resources(dev);
 }
 
 static void intel_set_subsystem(device_t dev, unsigned vendor, unsigned device)
@@ -453,7 +532,7 @@ static struct pci_operations intel_pci_ops = {
 
 static struct device_operations mc_ops = {
 	.read_resources   = mc_read_resources,
-	.set_resources    = mc_set_resources,
+	.set_resources    = pci_dev_set_resources,
 	.enable_resources = pci_dev_enable_resources,
 	.init             = northbridge_init,
 	.enable           = northbridge_enable,



More information about the coreboot mailing list