blob: 8f91b2af81052c7c87d4dc3b813f0d860a8864c9 [file] [log] [blame]
Felix Held3c44c622022-01-10 20:57:29 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2
3/* TODO: Check if this is still correct */
4
5#include <acpi/acpigen.h>
6#include <amdblocks/acpi.h>
7#include <amdblocks/alib.h>
8#include <amdblocks/ioapic.h>
9#include <amdblocks/memmap.h>
10#include <arch/ioapic.h>
11#include <cbmem.h>
12#include <console/console.h>
13#include <cpu/amd/msr.h>
14#include <device/device.h>
15#include <device/pci.h>
16#include <device/pci_ids.h>
17#include <fsp/util.h>
18#include <soc/iomap.h>
19#include <stdint.h>
20#include "chip.h"
21
22#define DPTC_TOTAL_UPDATE_PARAMS 4
23
24struct dptc_input {
25 uint16_t size;
26 struct alib_dptc_param params[DPTC_TOTAL_UPDATE_PARAMS];
27} __packed;
28
29#define DPTC_INPUTS(_thermctllmit, _sustained, _fast, _slow) \
30 { \
31 .size = sizeof(struct dptc_input), \
32 .params = { \
33 { \
34 .id = ALIB_DPTC_THERMAL_CONTROL_LIMIT_ID, \
35 .value = _thermctllmit, \
36 }, \
37 { \
38 .id = ALIB_DPTC_SUSTAINED_POWER_LIMIT_ID, \
39 .value = _sustained, \
40 }, \
41 { \
42 .id = ALIB_DPTC_FAST_PPT_LIMIT_ID, \
43 .value = _fast, \
44 }, \
45 { \
46 .id = ALIB_DPTC_SLOW_PPT_LIMIT_ID, \
47 .value = _slow, \
48 }, \
49 }, \
50 }
51
52/*
53 *
54 * +--------------------------------+
55 * | |
56 * | |
57 * | |
58 * | |
59 * | |
60 * | |
61 * | |
62 * reserved_dram_end +--------------------------------+
63 * | |
64 * | verstage (if reqd) |
65 * | (VERSTAGE_SIZE) |
66 * +--------------------------------+ VERSTAGE_ADDR
67 * | |
68 * | FSP-M |
69 * | (FSP_M_SIZE) |
70 * +--------------------------------+ FSP_M_ADDR
71 * | romstage |
72 * | (ROMSTAGE_SIZE) |
73 * +--------------------------------+ ROMSTAGE_ADDR = BOOTBLOCK_END
74 * | | X86_RESET_VECTOR = BOOTBLOCK_END - 0x10
75 * | bootblock |
76 * | (C_ENV_BOOTBLOCK_SIZE) |
77 * +--------------------------------+ BOOTBLOCK_ADDR = BOOTBLOCK_END - C_ENV_BOOTBLOCK_SIZE
78 * | Unused hole |
79 * | (86KiB) |
80 * +--------------------------------+
81 * | FMAP cache (FMAP_SIZE) |
82 * +--------------------------------+ PSP_SHAREDMEM_BASE + PSP_SHAREDMEM_SIZE + PRERAM_CBMEM_CONSOLE_SIZE + 0x200
83 * | Early Timestamp region (512B) |
84 * +--------------------------------+ PSP_SHAREDMEM_BASE + PSP_SHAREDMEM_SIZE + PRERAM_CBMEM_CONSOLE_SIZE
85 * | Preram CBMEM console |
86 * | (PRERAM_CBMEM_CONSOLE_SIZE) |
87 * +--------------------------------+ PSP_SHAREDMEM_BASE + PSP_SHAREDMEM_SIZE
88 * | PSP shared (vboot workbuf) |
89 * | (PSP_SHAREDMEM_SIZE) |
90 * +--------------------------------+ PSP_SHAREDMEM_BASE
91 * | APOB (64KiB) |
92 * +--------------------------------+ PSP_APOB_DRAM_ADDRESS
93 * | Early BSP stack |
94 * | (EARLYRAM_BSP_STACK_SIZE) |
95 * reserved_dram_start +--------------------------------+ EARLY_RESERVED_DRAM_BASE
96 * | DRAM |
97 * +--------------------------------+ 0x100000
98 * | Option ROM |
99 * +--------------------------------+ 0xc0000
100 * | Legacy VGA |
101 * +--------------------------------+ 0xa0000
102 * | DRAM |
103 * +--------------------------------+ 0x0
104 */
105static void read_resources(struct device *dev)
106{
107 uint32_t mem_usable = (uintptr_t)cbmem_top();
108 unsigned int idx = 0;
109 const struct hob_header *hob = fsp_get_hob_list();
110 const struct hob_resource *res;
111 struct resource *gnb_apic;
112
113 uintptr_t early_reserved_dram_start, early_reserved_dram_end;
114 const struct memmap_early_dram *e = memmap_get_early_dram_usage();
115
116 early_reserved_dram_start = e->base;
117 early_reserved_dram_end = e->base + e->size;
118
Felix Heldaf17f0b2022-03-02 23:36:55 +0100119 /* The root complex has no PCI BARs implemented, so there's no need to call
120 pci_dev_read_resources for it */
121
Felix Held3c44c622022-01-10 20:57:29 +0100122 /* 0x0 - 0x9ffff */
123 ram_resource(dev, idx++, 0, 0xa0000 / KiB);
124
125 /* 0xa0000 - 0xbffff: legacy VGA */
126 mmio_resource(dev, idx++, 0xa0000 / KiB, 0x20000 / KiB);
127
128 /* 0xc0000 - 0xfffff: Option ROM */
129 reserved_ram_resource(dev, idx++, 0xc0000 / KiB, 0x40000 / KiB);
130
131 /* 1MiB - bottom of DRAM reserved for early coreboot usage */
132 ram_resource(dev, idx++, (1 * MiB) / KiB,
133 (early_reserved_dram_start - (1 * MiB)) / KiB);
134
135 /* DRAM reserved for early coreboot usage */
136 reserved_ram_resource(dev, idx++, early_reserved_dram_start / KiB,
137 (early_reserved_dram_end - early_reserved_dram_start) / KiB);
138
139 /*
140 * top of DRAM consumed early - low top usable RAM
141 * cbmem_top() accounts for low UMA and TSEG if they are used.
142 */
143 ram_resource(dev, idx++, early_reserved_dram_end / KiB,
144 (mem_usable - early_reserved_dram_end) / KiB);
145
Felix Held56b037b2022-03-02 22:57:01 +0100146 mmconf_resource(dev, idx++);
Felix Held3c44c622022-01-10 20:57:29 +0100147
148 if (!hob) {
149 printk(BIOS_ERR, "Error: %s incomplete because no HOB list was found\n",
150 __func__);
151 return;
152 }
153
154 for (; hob->type != HOB_TYPE_END_OF_HOB_LIST; hob = fsp_next_hob(hob)) {
155
156 if (hob->type != HOB_TYPE_RESOURCE_DESCRIPTOR)
157 continue;
158
159 res = fsp_hob_header_to_resource(hob);
160
161 if (res->type == EFI_RESOURCE_SYSTEM_MEMORY && res->addr < mem_usable)
162 continue; /* 0 through low usable was set above */
163 if (res->type == EFI_RESOURCE_MEMORY_MAPPED_IO)
164 continue; /* Done separately */
165
166 if (res->type == EFI_RESOURCE_SYSTEM_MEMORY)
167 ram_resource(dev, idx++, res->addr / KiB, res->length / KiB);
168 else if (res->type == EFI_RESOURCE_MEMORY_RESERVED)
169 reserved_ram_resource(dev, idx++, res->addr / KiB, res->length / KiB);
170 else
171 printk(BIOS_ERR, "Error: failed to set resources for type %d\n",
172 res->type);
173 }
174
175 /* GNB IOAPIC resource */
Felix Heldb1197af2022-03-02 23:02:31 +0100176 gnb_apic = new_resource(dev, idx++);
Felix Held3c44c622022-01-10 20:57:29 +0100177 gnb_apic->base = GNB_IO_APIC_ADDR;
178 gnb_apic->size = 0x00001000;
179 gnb_apic->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
180}
181
182static void root_complex_init(struct device *dev)
183{
184 setup_ioapic((u8 *)GNB_IO_APIC_ADDR, GNB_IOAPIC_ID);
185}
186
187static void acipgen_dptci(void)
188{
189 const struct soc_amd_sabrina_config *config = config_of_soc();
190
191 if (!config->dptc_enable)
192 return;
193
194 struct dptc_input default_input = DPTC_INPUTS(config->thermctl_limit_degreeC,
195 config->sustained_power_limit_mW,
196 config->fast_ppt_limit_mW,
197 config->slow_ppt_limit_mW);
198 struct dptc_input tablet_mode_input = DPTC_INPUTS(
199 config->thermctl_limit_tablet_mode_degreeC,
200 config->sustained_power_limit_tablet_mode_mW,
201 config->fast_ppt_limit_tablet_mode_mW,
202 config->slow_ppt_limit_tablet_mode_mW);
203
204 acpigen_write_alib_dptc((uint8_t *)&default_input, sizeof(default_input),
205 (uint8_t *)&tablet_mode_input, sizeof(tablet_mode_input));
206}
207
208static void root_complex_fill_ssdt(const struct device *device)
209{
210 acpi_fill_root_complex_tom(device);
211 acipgen_dptci();
212}
213
214static const char *gnb_acpi_name(const struct device *dev)
215{
216 return "GNB";
217}
218
219static struct device_operations root_complex_operations = {
220 .read_resources = read_resources,
221 .set_resources = noop_set_resources,
222 .enable_resources = pci_dev_enable_resources,
223 .init = root_complex_init,
224 .acpi_name = gnb_acpi_name,
225 .acpi_fill_ssdt = root_complex_fill_ssdt,
226};
227
228static const struct pci_driver family17_root_complex __pci_driver = {
229 .ops = &root_complex_operations,
Felix Singer43b7f412022-03-07 04:34:52 +0100230 .vendor = PCI_VID_AMD,
231 .device = PCI_DID_AMD_17H_MODEL_A0AF_NB,
Felix Held3c44c622022-01-10 20:57:29 +0100232};