mb/system76/cml-u/dt: Make use of chipset devicetree
[coreboot.git] / src / soc / intel / xeon_sp / uncore.c
blob2e5023d04ed624d67fd916a7bbe79625346d58c2
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <arch/vga.h>
4 #include <cbmem.h>
5 #include <console/console.h>
6 #include <cpu/x86/lapic_def.h>
7 #include <device/pci.h>
8 #include <device/pci_ids.h>
9 #include <soc/acpi.h>
10 #include <soc/chip_common.h>
11 #include <soc/iomap.h>
12 #include <soc/pci_devs.h>
13 #include <soc/ramstage.h>
14 #include <soc/util.h>
15 #include <fsp/util.h>
16 #include <security/intel/txt/txt_platform.h>
17 #include <security/intel/txt/txt.h>
18 #include <soc/config.h>
19 #include <soc/numa.h>
20 #include <soc/soc_util.h>
21 #include <stdint.h>
23 struct proximity_domains pds = {
24 .num_pds = 0,
25 .pds = NULL,
28 struct map_entry {
29 uint32_t reg;
30 int is_64_bit;
31 int is_limit;
32 int mask_bits;
33 const char *description;
36 enum {
37 TOHM_REG,
38 MMIOL_REG,
39 MMCFG_BASE_REG,
40 MMCFG_LIMIT_REG,
41 TOLM_REG,
42 /* NCMEM and ME ranges are mutually exclusive */
43 NCMEM_BASE_REG,
44 NCMEM_LIMIT_REG,
45 ME_BASE_REG,
46 ME_LIMIT_REG,
47 TSEG_BASE_REG,
48 TSEG_LIMIT_REG,
49 VTDBAR_REG,
50 /* Must be last. */
51 NUM_MAP_ENTRIES
54 size_t vtd_probe_bar_size(struct device *dev)
56 uint32_t id = pci_read_config32(dev, PCI_VENDOR_ID);
57 assert(id == (PCI_VID_INTEL | (MMAP_VTD_CFG_REG_DEVID << 16)));
59 uint32_t val = pci_read_config32(dev, VTD_BAR_CSR);
60 pci_write_config32(dev, VTD_BAR_CSR, (uint32_t)(-4 * KiB));
61 size_t size = (~(pci_read_config32(dev, VTD_BAR_CSR) & ((uint32_t)(-4 * KiB)))) + 1;
62 assert(size != 0);
63 pci_write_config32(dev, VTD_BAR_CSR, val);
65 return size;
68 static struct map_entry memory_map[NUM_MAP_ENTRIES] = {
69 [TOHM_REG] = MAP_ENTRY_LIMIT_64(VTD_TOHM_CSR, 26, "TOHM"),
70 [MMIOL_REG] = MAP_ENTRY_BASE_32(VTD_MMIOL_CSR, "MMIOL"),
71 [MMCFG_BASE_REG] = MAP_ENTRY_BASE_64(VTD_MMCFG_BASE_CSR, "MMCFG_BASE"),
72 [MMCFG_LIMIT_REG] = MAP_ENTRY_LIMIT_64(VTD_MMCFG_LIMIT_CSR, 26, "MMCFG_LIMIT"),
73 [TOLM_REG] = MAP_ENTRY_LIMIT_32(VTD_TOLM_CSR, 26, "TOLM"),
74 #if CONFIG(SOC_INTEL_HAS_NCMEM)
75 [NCMEM_BASE_REG] = MAP_ENTRY_BASE_64(VTD_NCMEM_BASE_CSR, "NCMEM_BASE"),
76 [NCMEM_LIMIT_REG] = MAP_ENTRY_LIMIT_64(VTD_NCMEM_LIMIT_CSR, 19, "NCMEM_LIMIT"),
77 #else
78 [ME_BASE_REG] = MAP_ENTRY_BASE_64(VTD_ME_BASE_CSR, "ME_BASE"),
79 [ME_LIMIT_REG] = MAP_ENTRY_LIMIT_64(VTD_ME_LIMIT_CSR, 19, "ME_LIMIT"),
80 #endif
81 [TSEG_BASE_REG] = MAP_ENTRY_BASE_32(VTD_TSEG_BASE_CSR, "TSEGMB_BASE"),
82 [TSEG_LIMIT_REG] = MAP_ENTRY_LIMIT_32(VTD_TSEG_LIMIT_CSR, 20, "TSEGMB_LIMIT"),
83 [VTDBAR_REG] = MAP_ENTRY_BASE_32(VTD_BAR_CSR, "VTD_BAR"),
86 static void read_map_entry(struct device *dev, struct map_entry *entry,
87 uint64_t *result)
89 uint64_t value;
90 uint64_t mask;
92 if (!entry->reg) {
93 *result = 0;
94 return;
96 if (entry->reg == VTD_BAR_CSR && !(pci_read_config32(dev, entry->reg) & 1)) {
97 /* VTDBAR is not enabled */
98 *result = 0;
99 return;
102 mask = ((1ULL << entry->mask_bits) - 1);
103 mask = ~mask;
105 value = 0;
107 if (entry->is_64_bit) {
108 value = pci_read_config32(dev, entry->reg + sizeof(uint32_t));
109 value <<= 32;
112 value |= (uint64_t)pci_read_config32(dev, entry->reg);
113 value &= mask;
115 if (entry->is_limit)
116 value |= ~mask;
118 *result = value;
121 static void mc_read_map_entries(struct device *dev, uint64_t *values)
123 int i;
124 for (i = 0; i < NUM_MAP_ENTRIES; i++)
125 read_map_entry(dev, &memory_map[i], &values[i]);
128 static void mc_report_map_entries(struct device *dev, uint64_t *values)
130 int i;
131 for (i = 0; i < NUM_MAP_ENTRIES; i++) {
132 if (!memory_map[i].description)
133 continue;
135 printk(BIOS_DEBUG, "%s: MC MAP: %s: 0x%llx\n",
136 dev_path(dev), memory_map[i].description, values[i]);
140 static void configure_dpr(struct device *dev)
142 const uintptr_t cbmem_top_mb = ALIGN_UP(cbmem_top(), MiB) / MiB;
143 union dpr_register dpr = { .raw = pci_read_config32(dev, VTD_LTDPR) };
145 /* The DPR lock bit has to be set sufficiently early. It looks like
146 * it cannot be set anymore after FSP-S.
148 dpr.lock = 1;
149 dpr.epm = 1;
150 dpr.size = dpr.top - cbmem_top_mb;
151 pci_write_config32(dev, VTD_LTDPR, dpr.raw);
155 * Host Memory Map:
157 * +--------------------------+ TOCM (2 pow 46 - 1)
158 * | Reserved |
159 * +--------------------------+
160 * | MMIOH (relocatable) |
161 * +--------------------------+
162 * | PCISeg |
163 * +--------------------------+ TOHM
164 * | High DRAM Memory |
165 * +--------------------------+ 4GiB (0x100000000)
166 * +--------------------------+ 0xFFFF_FFFF
167 * | Firmware |
168 * +--------------------------+ 0xFF00_0000
169 * | Reserved |
170 * +--------------------------+ 0xFEF0_0000
171 * | Local xAPIC |
172 * +--------------------------+ 0xFEE0_0000
173 * | HPET/LT/TPM/Others |
174 * +--------------------------+ 0xFED0_0000
175 * | I/O xAPIC |
176 * +--------------------------+ 0xFEC0_0000
177 * | Reserved |
178 * +--------------------------+ 0xFEB8_0000
179 * | Reserved |
180 * +--------------------------+ 0xFEB0_0000
181 * | Reserved |
182 * +--------------------------+ 0xFE00_0000
183 * | MMIOL (relocatable) |
184 * | P2SB PCR cfg BAR | (0xfd000000 - 0xfdffffff
185 * | BAR space | [mem 0x90000000-0xfcffffff] available for PCI devices
186 * +--------------------------+ 0x9000_0000
187 * |PCIe MMCFG (relocatable) | CONFIG_ECAM_MMCONF_BASE_ADDRESS 64 or 256MB
188 * | | (0x80000000 - 0x8fffffff, 0x40000)
189 * +--------------------------+ TOLM
190 * | MEseg (relocatable) | 32, 64, 128 or 256 MB (0x78000000 - 0x7fffffff, 0x20000)
191 * +--------------------------+
192 * | Tseg (relocatable) | N x 8MB (0x70000000 - 0x77ffffff, 0x20000)
193 * +--------------------------+
194 * | DPR |
195 * +--------------------------+ 1M aligned DPR base
196 * | Unused memory |
197 * +--------------------------+ cbmem_top
198 * | Reserved - CBMEM | (0x6fffe000 - 0x6fffffff, 0x2000)
199 * +--------------------------+
200 * | Reserved - FSP | (0x6fbfe000 - 0x6fffdfff, 0x400000)
201 * +--------------------------+ top_of_ram (0x6fbfdfff)
202 * | Low DRAM Memory |
203 * +--------------------------+ FFFFF (1MB)
204 * | E & F segments |
205 * +--------------------------+ E0000
206 * | C & D segments |
207 * +--------------------------+ C0000
208 * | VGA & SMM Memory |
209 * +--------------------------+ A0000
210 * | Conventional Memory |
211 * | (DOS Range) |
212 * +--------------------------+ 0
215 static void mc_add_dram_resources(struct device *dev, int *res_count)
217 const struct resource *res;
218 uint64_t mc_values[NUM_MAP_ENTRIES];
219 uint64_t top_of_ram;
220 int index = *res_count;
221 struct range_entry fsp_mem;
223 /* Read in the MAP registers and report their values. */
224 mc_read_map_entries(dev, &mc_values[0]);
225 mc_report_map_entries(dev, &mc_values[0]);
227 if (mc_values[VTDBAR_REG]) {
228 res = mmio_range(dev, VTD_BAR_CSR, mc_values[VTDBAR_REG],
229 vtd_probe_bar_size(dev));
230 LOG_RESOURCE("vtd_bar", dev, res);
233 /* Only add dram resources once. */
234 if (dev->upstream->secondary != 0 || dev->upstream->segment_group != 0)
235 return;
237 /* Conventional Memory (DOS region, 0x0 to 0x9FFFF) */
238 res = ram_from_to(dev, index++, 0, 0xa0000);
239 LOG_RESOURCE("legacy_ram", dev, res);
241 /* 1MB -> top_of_ram */
242 fsp_find_reserved_memory(&fsp_mem);
243 top_of_ram = range_entry_base(&fsp_mem) - 1;
244 res = ram_from_to(dev, index++, 1 * MiB, top_of_ram);
245 LOG_RESOURCE("low_ram", dev, res);
247 /* top_of_ram -> cbmem_top */
248 res = ram_from_to(dev, index++, top_of_ram, cbmem_top());
249 LOG_RESOURCE("cbmem_ram", dev, res);
251 /* Mark TSEG/SMM region as reserved */
252 res = reserved_ram_from_to(dev, index++, mc_values[TSEG_BASE_REG],
253 mc_values[TSEG_LIMIT_REG] + 1);
254 LOG_RESOURCE("mmio_tseg", dev, res);
256 /* Reserve DPR region */
257 union dpr_register dpr = { .raw = pci_read_config32(dev, VTD_LTDPR) };
258 if (dpr.size) {
260 * cbmem_top -> DPR base:
261 * DPR has a 1M granularity so it's possible if cbmem_top is not 1M
262 * aligned that some memory does not get marked as assigned.
264 res = reserved_ram_from_to(dev, index++, cbmem_top(),
265 (dpr.top - dpr.size) * MiB);
266 LOG_RESOURCE("unused_dram", dev, res);
268 /* DPR base -> DPR top */
269 res = reserved_ram_from_to(dev, index++, (dpr.top - dpr.size) * MiB,
270 dpr.top * MiB);
271 LOG_RESOURCE("dpr", dev, res);
274 /* Mark TSEG/SMM region as reserved */
275 res = reserved_ram_from_to(dev, index++, mc_values[TSEG_BASE_REG],
276 mc_values[TSEG_LIMIT_REG] + 1);
277 LOG_RESOURCE("mmio_tseg", dev, res);
279 /* Mark region between TSEG - TOLM (eg. MESEG) as reserved */
280 res = reserved_ram_from_to(dev, index++, mc_values[TSEG_LIMIT_REG] + 1,
281 mc_values[TOLM_REG]);
282 LOG_RESOURCE("mmio_tolm", dev, res);
284 if (CONFIG(SOC_INTEL_HAS_CXL)) {
285 /* 4GiB -> CXL Memory */
286 uint32_t gi_mem_size;
287 gi_mem_size = get_generic_initiator_mem_size(); /* unit: 64MB */
289 * Memory layout when there is CXL HDM (Host-managed Device Memory):
290 * -------------- <- TOHM
291 * CXL memory regions (pds global variable records the base/size of them)
292 * Processor attached high memory
293 * -------------- <- 0x100000000 (4GB)
295 res = upper_ram_end(dev, index++,
296 mc_values[TOHM_REG] - ((uint64_t)gi_mem_size << 26) + 1);
297 LOG_RESOURCE("high_ram", dev, res);
299 /* CXL Memory */
300 uint8_t i;
301 for (i = 0; i < pds.num_pds; i++) {
302 if (pds.pds[i].pd_type != PD_TYPE_GENERIC_INITIATOR)
303 continue;
305 unsigned long flags = IORESOURCE_CACHEABLE;
306 int cxl_mode = get_cxl_mode();
307 if (cxl_mode == XEONSP_CXL_SP_MEM)
308 flags |= IORESOURCE_SOFT_RESERVE;
309 else
310 flags |= IORESOURCE_STORED;
312 res = fixed_mem_range_flags(dev, index++,
313 (uint64_t)pds.pds[i].base << 26,
314 (uint64_t)pds.pds[i].size << 26, flags);
315 if (cxl_mode == XEONSP_CXL_SP_MEM)
316 LOG_RESOURCE("specific_purpose_memory", dev, res);
317 else
318 LOG_RESOURCE("CXL_memory", dev, res);
320 } else {
321 /* 4GiB -> TOHM */
322 res = upper_ram_end(dev, index++, mc_values[TOHM_REG] + 1);
323 LOG_RESOURCE("high_ram", dev, res);
326 /* add MMIO CFG resource */
327 res = mmio_from_to(dev, index++, mc_values[MMCFG_BASE_REG],
328 mc_values[MMCFG_LIMIT_REG] + 1);
329 LOG_RESOURCE("mmiocfg_res", dev, res);
331 /* add Local APIC resource */
332 res = mmio_range(dev, index++, LAPIC_DEFAULT_BASE, 0x00001000);
333 LOG_RESOURCE("apic_res", dev, res);
336 * Add legacy region as reserved - 0xa000 - 1MB
337 * Reserve everything between A segment and 1MB:
339 * 0xa0000 - 0xbffff: legacy VGA
340 * 0xc0000 - 0xfffff: RAM
342 res = mmio_range(dev, index++, VGA_MMIO_BASE, VGA_MMIO_SIZE);
343 LOG_RESOURCE("legacy_mmio", dev, res);
345 res = reserved_ram_from_to(dev, index++, 0xc0000, 1 * MiB);
346 LOG_RESOURCE("legacy_write_protect", dev, res);
348 *res_count = index;
351 static void mmapvtd_read_resources(struct device *dev)
353 int index = 0;
355 /* Read standard PCI resources. */
356 pci_dev_read_resources(dev);
358 /* set up DPR */
359 configure_dpr(dev);
361 /* Calculate and add DRAM resources. */
362 mc_add_dram_resources(dev, &index);
365 static void mmapvtd_init(struct device *dev)
369 static struct device_operations mmapvtd_ops = {
370 .read_resources = mmapvtd_read_resources,
371 .set_resources = pci_dev_set_resources,
372 .enable_resources = pci_dev_enable_resources,
373 .init = mmapvtd_init,
374 .ops_pci = &soc_pci_ops,
377 static const unsigned short mmapvtd_ids[] = {
378 MMAP_VTD_CFG_REG_DEVID, /* Memory Map/IntelĀ® VT-d Configuration Registers */
382 static const struct pci_driver mmapvtd_driver __pci_driver = {
383 .ops = &mmapvtd_ops,
384 .vendor = PCI_VID_INTEL,
385 .devices = mmapvtd_ids
388 #if !CONFIG(SOC_INTEL_MMAPVTD_ONLY_FOR_DPR)
389 static void vtd_read_resources(struct device *dev)
391 pci_dev_read_resources(dev);
393 configure_dpr(dev);
396 static struct device_operations vtd_ops = {
397 .read_resources = vtd_read_resources,
398 .set_resources = pci_dev_set_resources,
399 .enable_resources = pci_dev_enable_resources,
400 .ops_pci = &soc_pci_ops,
403 /* VTD devices on other stacks */
404 static const struct pci_driver vtd_driver __pci_driver = {
405 .ops = &vtd_ops,
406 .vendor = PCI_VID_INTEL,
407 .device = MMAP_VTD_STACK_CFG_REG_DEVID,
409 #endif
411 static void dmi3_init(struct device *dev)
413 if (CONFIG(INTEL_TXT) && skip_intel_txt_lockdown())
414 return;
415 /* Disable error injection */
416 pci_or_config16(dev, ERRINJCON, 1 << 0);
419 * DMIRCBAR registers are not TXT lockable, but the BAR enable
420 * bit is. TXT requires that DMIRCBAR be disabled for security.
422 pci_and_config32(dev, DMIRCBAR, ~(1 << 0));
425 static struct device_operations dmi3_ops = {
426 .read_resources = pci_dev_read_resources,
427 .set_resources = pci_dev_set_resources,
428 .enable_resources = pci_dev_enable_resources,
429 .init = dmi3_init,
430 .ops_pci = &soc_pci_ops,
433 static const struct pci_driver dmi3_driver __pci_driver = {
434 .ops = &dmi3_ops,
435 .vendor = PCI_VID_INTEL,
436 .device = DMI3_DEVID,
439 static void iio_dfx_global_init(struct device *dev)
441 if (CONFIG(INTEL_TXT) && skip_intel_txt_lockdown())
442 return;
444 uint16_t reg16;
445 pci_or_config16(dev, IIO_DFX_LCK_CTL, 0x3ff);
446 reg16 = pci_read_config16(dev, IIO_DFX_TSWCTL0);
447 reg16 &= ~(1 << 4); // allow ib mmio cfg
448 reg16 &= ~(1 << 5); // ignore acs p2p ma lpbk
449 reg16 |= (1 << 3); // me disable
450 pci_write_config16(dev, IIO_DFX_TSWCTL0, reg16);
453 static const unsigned short iio_dfx_global_ids[] = {
454 0x202d,
455 0x203d,
459 static struct device_operations iio_dfx_global_ops = {
460 .read_resources = pci_dev_read_resources,
461 .set_resources = pci_dev_set_resources,
462 .enable_resources = pci_dev_enable_resources,
463 .init = iio_dfx_global_init,
464 .ops_pci = &soc_pci_ops,
467 static const struct pci_driver iio_dfx_global_driver __pci_driver = {
468 .ops = &iio_dfx_global_ops,
469 .vendor = PCI_VID_INTEL,
470 .devices = iio_dfx_global_ids,