/* * This file is part of the coreboot project. * * Copyright (C) 2013 Google Inc. * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. * * 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 #include #include #include #include static const int legacy_hole_base_k = 0xa0000 / 1024; static const int legacy_hole_size_k = 384; /* Host Memory Map: * * +--------------------------+ BMBOUND_HI * | Usable DRAM | * +--------------------------+ 4GiB * | PCI Address Space | * +--------------------------+ BMBOUND * | TPM | * +--------------------------+ IMR2 * | TXE | * +--------------------------+ IMR1 * | iGD | * +--------------------------+ * | GTT | * +--------------------------+ SMMRRH, IRM0 * | TSEG | * +--------------------------+ SMMRRL * | FSP | * +--------------------------+ SMMRRL - 2MB * | Usable DRAM | * +--------------------------+ FFFFF * | ROM Area | * +--------------------------+ A0000 * | Usable DRAM | * +--------------------------+ 0 * * Note that there are really only a few regions that need to enumerated w.r.t. * coreboot's resource model: * * +--------------------------+ BMBOUND_HI * | Cacheable/Usable | * +--------------------------+ 4GiB * * +--------------------------+ BMBOUND * | Uncacheable/Reserved | * +--------------------------+ SMMRRH * | Cacheable/Reserved | * +--------------------------+ SMMRRL - 2MB * | Cacheable/Usable | * +--------------------------+ 0 */ /* * Get the top of low memory for use by ACPI */ uint32_t nc_read_top_of_low_memory(void) { uint32_t fsp_mem_base = 0; GetLowMemorySize(&fsp_mem_base); return fsp_mem_base; } static int get_pcie_bar(u32 *base) { struct device *dev; u32 pciexbar_reg; *base = 0; dev = dev_find_slot(0, PCI_DEVFN(0, 0)); if (!dev) return 0; pciexbar_reg = iosf_bunit_read(BUNIT_MMCONF_REG); if (!(pciexbar_reg & (1 << 0))) return 0; *base = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) | (1 << 28)); return 256; } static int add_fixed_resources(struct device *dev, int index) { struct resource *resource; resource = new_resource(dev, index++); /* Local APIC */ resource->base = LAPIC_DEFAULT_BASE; resource->size = 0x00001000; resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE | IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED; mmio_resource(dev, index++, legacy_hole_base_k, legacy_hole_size_k); return index; } static void mc_add_dram_resources(struct device *dev) { u32 bmbound, bsmmrrl; int index = 0; uint64_t highmem_size = 0; uint32_t fsp_mem_base = 0; GetHighMemorySize(&highmem_size); fsp_mem_base=(uint32_t)cbmem_top(); bmbound = iosf_bunit_read(BUNIT_BMBOUND); bsmmrrl = iosf_bunit_read(BUNIT_SMRRL) << 20; if (bsmmrrl){ printk(BIOS_DEBUG, "UMA, GTT & SMM memory location: 0x%x\n" "UMA, GTT & SMM memory size: %dM\n", bsmmrrl, (bmbound - bsmmrrl) >> 20); printk(BIOS_DEBUG, "FSP memory location: 0x%x\nFSP memory size: %dM\n", fsp_mem_base, (bsmmrrl - fsp_mem_base) >> 20); } printk(BIOS_INFO, "Available memory below 4GB: 0x%08x (%dM)\n", fsp_mem_base, fsp_mem_base >> 20); /* Report the memory regions. */ ram_resource(dev, index++, 0, legacy_hole_base_k); ram_resource(dev, index++, legacy_hole_base_k + legacy_hole_size_k, ((fsp_mem_base >> 10) - (legacy_hole_base_k + legacy_hole_size_k))); /* Mark SMM & FSP regions reserved */ mmio_resource(dev, index++, fsp_mem_base >> 10, (bmbound - fsp_mem_base) >> 10); if (highmem_size) { ram_resource(dev, index++, 0x100000000 >> 10, highmem_size >> 10); } printk(BIOS_INFO, "Available memory above 4GB: %lluM\n", highmem_size >> 20); index = add_fixed_resources(dev, index); } static void nc_read_resources(struct device *dev) { u32 pcie_config_base; int buses; /* Call the normal read_resources */ pci_dev_read_resources(dev); /* We use 0xcf as an unused index for our PCIe bar so that we find it again */ buses = get_pcie_bar(&pcie_config_base); if (buses) { struct resource *resource = new_resource(dev, 0xcf); mmconf_resource_init(resource, pcie_config_base, buses); } /* Calculate and add DRAM resources. */ mc_add_dram_resources(dev); } static void nc_enable(struct device *dev) { print_fsp_info(); } static struct device_operations nc_ops = { .read_resources = nc_read_resources, .acpi_fill_ssdt_generator = generate_cpu_entries, .set_resources = DEVICE_NOOP, .enable_resources = NULL, .init = NULL, .enable = &nc_enable, .scan_bus = NULL, .ops_pci = &soc_pci_ops, }; static const struct pci_driver nc_driver __pci_driver = { .ops = &nc_ops, .vendor = PCI_VENDOR_ID_INTEL, .device = SOC_DEVID, };