blob: f621eeaf31d87747a2eb43454eac6b4fd46d437d [file] [log] [blame]
Marshall Dawsoneb724872019-07-16 15:46:35 -06001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <acpi/acpigen.h>
4#include <cbmem.h>
5#include <console/console.h>
6#include <cpu/amd/msr.h>
7#include <cpu/amd/mtrr.h>
8#include <device/device.h>
9#include <device/pci.h>
10#include <device/pci_ids.h>
11#include <fsp/util.h>
12#include <stdint.h>
13
14static void read_resources(struct device *dev)
15{
16 uint32_t mem_usable = (uintptr_t)cbmem_top();
17 unsigned int idx = 0;
18 const struct hob_header *hob = fsp_get_hob_list();
19 const struct hob_resource *res;
20
21 /* 0x0 - 0x9ffff */
22 ram_resource(dev, idx++, 0, 0xa0000 / KiB);
23
24 /* 0xa0000 - 0xbffff: legacy VGA */
25 mmio_resource(dev, idx++, 0xa0000 / KiB, 0x20000 / KiB);
26
27 /* 0xc0000 - 0xfffff: Option ROM */
28 reserved_ram_resource(dev, idx++, 0xc0000 / KiB, 0x40000 / KiB);
29
30 /* 1MB to top of low usable RAM */
31 ram_resource(dev, idx++, 1 * MiB / KiB, (mem_usable - 1 * MiB) / KiB);
32
33 mmconf_resource(dev, MMIO_CONF_BASE);
34
35 if (!hob) {
36 printk(BIOS_ERR, "Error: %s incomplete because no HOB list was found\n",
37 __func__);
38 return;
39 }
40
41 for (; hob->type != HOB_TYPE_END_OF_HOB_LIST; hob = fsp_next_hob(hob)) {
42
43 if (hob->type != HOB_TYPE_RESOURCE_DESCRIPTOR)
44 continue;
45
46 res = fsp_hob_header_to_resource(hob);
47
48 if (res->type == EFI_RESOURCE_SYSTEM_MEMORY && res->addr < mem_usable)
49 continue; /* 0 through low usable was set above */
50 if (res->type == EFI_RESOURCE_MEMORY_MAPPED_IO)
51 continue; /* Done separately */
52
53 if (res->type == EFI_RESOURCE_SYSTEM_MEMORY)
54 ram_resource(dev, idx++, res->addr / KiB, res->length / KiB);
55 else if (res->type == EFI_RESOURCE_MEMORY_RESERVED)
56 reserved_ram_resource(dev, idx++, res->addr / KiB, res->length / KiB);
57 else
58 printk(BIOS_ERR, "Error: failed to set resources for type %d\n",
59 res->type);
60 }
61}
62
63/* Used by \_SB.PCI0._CRS */
64static void root_complex_fill_ssdt(const struct device *device)
65{
66 msr_t msr;
67
68 acpigen_write_scope(acpi_device_scope(device));
69
70 msr = rdmsr(TOP_MEM);
71 acpigen_write_name_dword("TOM1", msr.lo);
72 msr = rdmsr(TOP_MEM2);
73 /*
74 * Since XP only implements parts of ACPI 2.0, we can't use a qword
75 * here.
76 * See http://www.acpi.info/presentations/S01USMOBS169_OS%2520new.ppt
77 * slide 22ff.
78 * Shift value right by 20 bit to make it fit into 32bit,
79 * giving us 1MB granularity and a limit of almost 4Exabyte of memory.
80 */
81 acpigen_write_name_dword("TOM2", (msr.hi << 12) | msr.lo >> 20);
82 acpigen_pop_len();
83}
84
85static struct device_operations root_complex_operations = {
86 .read_resources = read_resources,
87 .enable_resources = pci_dev_enable_resources,
88 .acpi_fill_ssdt = root_complex_fill_ssdt,
89};
90
91static const struct pci_driver family17_root_complex __pci_driver = {
92 .ops = &root_complex_operations,
93 .vendor = PCI_VENDOR_ID_AMD,
94 .device = PCI_DEVICE_ID_AMD_17H_MODEL_101F_NB,
95};