blob: 3ae44b8b3654e0e850c1086c323221d792866196 [file] [log] [blame]
Angel Pons6e5aabd2020-03-23 23:44:42 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Stefan Reinauer00636b02012-04-04 00:08:51 +02003
4#include <types.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +02005#include <console/console.h>
Nico Huberb3234742018-11-17 14:09:25 +01006#include <commonlib/helpers.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -07007#include <acpi/acpi.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +02008#include <device/device.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02009#include <device/pci_ops.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020010#include "sandybridge.h"
Nico Huber9d9ce0d2015-10-26 12:59:49 +010011#include <southbridge/intel/bd82x6x/pch.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020012
13unsigned long acpi_fill_mcfg(unsigned long current)
14{
Stefan Reinauer00636b02012-04-04 00:08:51 +020015 u32 pciexbar = 0;
16 u32 pciexbar_reg;
17 int max_buses;
18
Kyösti Mälkkic70eed12018-05-22 02:18:00 +030019 struct device *const dev = pcidev_on_root(0, 0);
Vagiz Trakhanove200c1c2017-09-28 15:01:06 +000020
Stefan Reinauer00636b02012-04-04 00:08:51 +020021 if (!dev)
22 return current;
23
Angel Pons7c49cb82020-03-16 23:17:32 +010024 pciexbar_reg = pci_read_config32(dev, PCIEXBAR);
Stefan Reinauer00636b02012-04-04 00:08:51 +020025
Angel Pons7c49cb82020-03-16 23:17:32 +010026 /* MMCFG not supported or not enabled */
Stefan Reinauer00636b02012-04-04 00:08:51 +020027 if (!(pciexbar_reg & (1 << 0)))
28 return current;
29
30 switch ((pciexbar_reg >> 1) & 3) {
Angel Pons7c49cb82020-03-16 23:17:32 +010031 case 0: /* 256MB */
32 pciexbar = pciexbar_reg & (0xffffffffULL << 28);
Stefan Reinauer00636b02012-04-04 00:08:51 +020033 max_buses = 256;
34 break;
Angel Pons7c49cb82020-03-16 23:17:32 +010035 case 1: /* 128M */
36 pciexbar = pciexbar_reg & (0xffffffffULL << 27);
Stefan Reinauer00636b02012-04-04 00:08:51 +020037 max_buses = 128;
38 break;
Angel Pons7c49cb82020-03-16 23:17:32 +010039 case 2: /* 64M */
40 pciexbar = pciexbar_reg & (0xffffffffULL << 26);
Stefan Reinauer00636b02012-04-04 00:08:51 +020041 max_buses = 64;
42 break;
Angel Pons7c49cb82020-03-16 23:17:32 +010043 default: /* RSVD */
Stefan Reinauer00636b02012-04-04 00:08:51 +020044 return current;
45 }
46
47 if (!pciexbar)
48 return current;
49
Angel Pons7c49cb82020-03-16 23:17:32 +010050 current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *) current, pciexbar, 0, 0,
51 max_buses - 1);
Stefan Reinauer00636b02012-04-04 00:08:51 +020052
53 return current;
54}
55
Angel Pons7c49cb82020-03-16 23:17:32 +010056
Nico Huberb3234742018-11-17 14:09:25 +010057static unsigned long acpi_create_igfx_rmrr(const unsigned long current)
58{
59 const u32 base_mask = ~(u32)(MiB - 1);
60
Kyösti Mälkki19bad302019-02-08 18:42:19 +020061 struct device *const host = pcidev_on_root(0, 0);
Nico Huberb3234742018-11-17 14:09:25 +010062 if (!host)
63 return 0;
64
Angel Pons7c49cb82020-03-16 23:17:32 +010065 const u32 bgsm = pci_read_config32(host, BGSM) & base_mask;
Nico Huberb3234742018-11-17 14:09:25 +010066 const u32 tolud = pci_read_config32(host, TOLUD) & base_mask;
67 if (!bgsm || !tolud)
68 return 0;
69
70 return acpi_create_dmar_rmrr(current, 0, bgsm, tolud - 1);
71}
72
Nico Huber9d9ce0d2015-10-26 12:59:49 +010073static unsigned long acpi_fill_dmar(unsigned long current)
74{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +030075 const struct device *const igfx = pcidev_on_root(2, 0);
Nico Huber9d9ce0d2015-10-26 12:59:49 +010076
77 if (igfx && igfx->enabled) {
Nico Huberb3234742018-11-17 14:09:25 +010078 unsigned long tmp;
79
80 tmp = current;
Angel Pons7c49cb82020-03-16 23:17:32 +010081 current += acpi_create_dmar_drhd(current, 0, 0, GFXVT_BASE);
Matt DeVillier7866d492018-03-29 14:59:57 +020082 current += acpi_create_dmar_ds_pci(current, 0, 2, 0);
83 current += acpi_create_dmar_ds_pci(current, 0, 2, 1);
Nico Huber9d9ce0d2015-10-26 12:59:49 +010084 acpi_dmar_drhd_fixup(tmp, current);
Nico Huberb3234742018-11-17 14:09:25 +010085
86 tmp = current;
87 current += acpi_create_igfx_rmrr(current);
88 if (current != tmp) {
89 current += acpi_create_dmar_ds_pci(current, 0, 2, 0);
90 current += acpi_create_dmar_ds_pci(current, 0, 2, 1);
91 acpi_dmar_rmrr_fixup(tmp, current);
92 }
Nico Huber9d9ce0d2015-10-26 12:59:49 +010093 }
94
95 const unsigned long tmp = current;
Angel Pons7c49cb82020-03-16 23:17:32 +010096 current += acpi_create_dmar_drhd(current, DRHD_INCLUDE_PCI_ALL, 0, VTVC0_BASE);
97
98 current += acpi_create_dmar_ds_ioapic(current, 2, PCH_IOAPIC_PCI_BUS,
99 PCH_IOAPIC_PCI_SLOT, 0);
100
Nico Huber9d9ce0d2015-10-26 12:59:49 +0100101 size_t i;
102 for (i = 0; i < 8; ++i)
Angel Pons7c49cb82020-03-16 23:17:32 +0100103 current += acpi_create_dmar_ds_msi_hpet(current, 0, PCH_HPET_PCI_BUS,
104 PCH_HPET_PCI_SLOT, i);
105
Nico Huber9d9ce0d2015-10-26 12:59:49 +0100106 acpi_dmar_drhd_fixup(tmp, current);
107
108 return current;
109}
110
Furquan Shaikh0f007d82020-04-24 06:41:18 -0700111unsigned long northbridge_write_acpi_tables(const struct device *const dev,
112 unsigned long current,
Nico Huber9d9ce0d2015-10-26 12:59:49 +0100113 struct acpi_rsdp *const rsdp)
114{
Angel Pons7c49cb82020-03-16 23:17:32 +0100115 const u32 capid0_a = pci_read_config32(dev, CAPID0_A);
Nico Huber9d9ce0d2015-10-26 12:59:49 +0100116 if (capid0_a & (1 << 23))
117 return current;
118
119 printk(BIOS_DEBUG, "ACPI: * DMAR\n");
Angel Pons7c49cb82020-03-16 23:17:32 +0100120
Nico Huber9d9ce0d2015-10-26 12:59:49 +0100121 acpi_dmar_t *const dmar = (acpi_dmar_t *)current;
Angel Pons7c49cb82020-03-16 23:17:32 +0100122
Nico Huber9d9ce0d2015-10-26 12:59:49 +0100123 acpi_create_dmar(dmar, DMAR_INTR_REMAP, acpi_fill_dmar);
124 current += dmar->header.length;
Aaron Durbin07a1b282015-12-10 17:07:38 -0600125 current = acpi_align_current(current);
Nico Huber9d9ce0d2015-10-26 12:59:49 +0100126
Angel Pons7c49cb82020-03-16 23:17:32 +0100127 acpi_add_table(rsdp, dmar);
Aaron Durbin07a1b282015-12-10 17:07:38 -0600128 current = acpi_align_current(current);
Nico Huber9d9ce0d2015-10-26 12:59:49 +0100129
130 printk(BIOS_DEBUG, "current = %lx\n", current);
131
132 return current;
133}