blob: 02bc1bf2a7a766fe5ce45e5256f5aa9a4ffc8eda [file] [log] [blame]
Aaron Durbin76c37002012-10-30 09:03:43 -05001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2007-2009 coresystems GmbH
5 * Copyright (C) 2012 The Chromium OS Authors
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; version 2 of
10 * the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
Aaron Durbin76c37002012-10-30 09:03:43 -050016 */
17
18#include <types.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050019#include <console/console.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050020#include <arch/acpi.h>
21#include <device/device.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020022#include <device/pci_ops.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050023#include "haswell.h"
Matt DeVillier85d98d92018-03-04 01:41:23 -060024#include <southbridge/intel/lynxpoint/pch.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050025
26unsigned long acpi_fill_mcfg(unsigned long current)
27{
Elyes HAOUAS77f7a6e2018-05-09 17:47:59 +020028 struct device *dev;
Aaron Durbin76c37002012-10-30 09:03:43 -050029 u32 pciexbar = 0;
30 u32 pciexbar_reg;
31 int max_buses;
Ryan Salsamendib9bc2572017-07-04 13:35:06 -070032 u32 mask;
Aaron Durbin76c37002012-10-30 09:03:43 -050033
Kyösti Mälkkic70eed12018-05-22 02:18:00 +030034 dev = pcidev_on_root(0, 0);
Aaron Durbin76c37002012-10-30 09:03:43 -050035 if (!dev)
36 return current;
37
Elyes HAOUAS69d658f2016-09-17 20:32:07 +020038 pciexbar_reg = pci_read_config32(dev, PCIEXBAR);
Aaron Durbin76c37002012-10-30 09:03:43 -050039
Angel Pons1db5bc72020-01-15 00:49:03 +010040 /* MMCFG not supported or not enabled. */
Aaron Durbin76c37002012-10-30 09:03:43 -050041 if (!(pciexbar_reg & (1 << 0)))
42 return current;
43
Ryan Salsamendib9bc2572017-07-04 13:35:06 -070044 mask = (1UL << 31) | (1 << 30) | (1 << 29) | (1 << 28);
Aaron Durbin76c37002012-10-30 09:03:43 -050045 switch ((pciexbar_reg >> 1) & 3) {
Angel Pons1db5bc72020-01-15 00:49:03 +010046 case 0: /* 256MB */
Ryan Salsamendib9bc2572017-07-04 13:35:06 -070047 pciexbar = pciexbar_reg & mask;
Aaron Durbin76c37002012-10-30 09:03:43 -050048 max_buses = 256;
49 break;
Angel Pons1db5bc72020-01-15 00:49:03 +010050 case 1: /* 128M */
Ryan Salsamendib9bc2572017-07-04 13:35:06 -070051 mask |= (1 << 27);
52 pciexbar = pciexbar_reg & mask;
Aaron Durbin76c37002012-10-30 09:03:43 -050053 max_buses = 128;
54 break;
Angel Pons1db5bc72020-01-15 00:49:03 +010055 case 2: /* 64M */
Ryan Salsamendib9bc2572017-07-04 13:35:06 -070056 mask |= (1 << 27) | (1 << 26);
57 pciexbar = pciexbar_reg & mask;
Aaron Durbin76c37002012-10-30 09:03:43 -050058 max_buses = 64;
59 break;
Angel Pons1db5bc72020-01-15 00:49:03 +010060 default: /* RSVD */
Aaron Durbin76c37002012-10-30 09:03:43 -050061 return current;
62 }
63
64 if (!pciexbar)
65 return current;
66
Angel Pons1db5bc72020-01-15 00:49:03 +010067 current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *) current, pciexbar, 0, 0,
68 max_buses - 1);
Aaron Durbin76c37002012-10-30 09:03:43 -050069
70 return current;
71}
Matt DeVillier85d98d92018-03-04 01:41:23 -060072
73static unsigned long acpi_fill_dmar(unsigned long current)
74{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +030075 struct device *const igfx_dev = pcidev_on_root(2, 0);
Matt DeVillier85d98d92018-03-04 01:41:23 -060076 const u32 gfxvtbar = MCHBAR32(GFXVTBAR) & ~0xfff;
77 const u32 vtvc0bar = MCHBAR32(VTVC0BAR) & ~0xfff;
78 const bool gfxvten = MCHBAR32(GFXVTBAR) & 0x1;
79 const bool vtvc0en = MCHBAR32(VTVC0BAR) & 0x1;
80
81 /* iGFX has to be enabled; GFXVTBAR set, enabled, in 32-bit space */
Angel Pons1db5bc72020-01-15 00:49:03 +010082 if (igfx_dev && igfx_dev->enabled && gfxvtbar && gfxvten && !MCHBAR32(GFXVTBAR + 4)) {
83
Matt DeVillier85d98d92018-03-04 01:41:23 -060084 const unsigned long tmp = current;
85
86 current += acpi_create_dmar_drhd(current, 0, 0, gfxvtbar);
Matt DeVillier7866d492018-03-29 14:59:57 +020087 current += acpi_create_dmar_ds_pci(current, 0, 2, 0);
Matt DeVillier85d98d92018-03-04 01:41:23 -060088
89 acpi_dmar_drhd_fixup(tmp, current);
90 }
91
92 /* VTVC0BAR has to be set, enabled, and in 32-bit space */
93 if (vtvc0bar && vtvc0en && !MCHBAR32(VTVC0BAR + 4)) {
Angel Pons1db5bc72020-01-15 00:49:03 +010094
Matt DeVillier85d98d92018-03-04 01:41:23 -060095 const unsigned long tmp = current;
Angel Pons1db5bc72020-01-15 00:49:03 +010096 current += acpi_create_dmar_drhd(current, DRHD_INCLUDE_PCI_ALL, 0, vtvc0bar);
97 current += acpi_create_dmar_ds_ioapic(current, 2, PCH_IOAPIC_PCI_BUS,
98 PCH_IOAPIC_PCI_SLOT, 0);
99
Matt DeVillier85d98d92018-03-04 01:41:23 -0600100 size_t i;
101 for (i = 0; i < 8; ++i)
Angel Pons1db5bc72020-01-15 00:49:03 +0100102 current += acpi_create_dmar_ds_msi_hpet(current, 0, PCH_HPET_PCI_BUS,
103 PCH_HPET_PCI_SLOT, i);
Matt DeVillier85d98d92018-03-04 01:41:23 -0600104 acpi_dmar_drhd_fixup(tmp, current);
105 }
106
107 return current;
108}
109
Angel Pons1db5bc72020-01-15 00:49:03 +0100110unsigned long northbridge_write_acpi_tables(struct device *const dev, unsigned long current,
Matt DeVillier85d98d92018-03-04 01:41:23 -0600111 struct acpi_rsdp *const rsdp)
112{
113 /* Create DMAR table only if we have VT-d capability. */
114 const u32 capid0_a = pci_read_config32(dev, CAPID0_A);
115 if (capid0_a & VTD_DISABLE)
116 return current;
117
118 acpi_dmar_t *const dmar = (acpi_dmar_t *)current;
119 printk(BIOS_DEBUG, "ACPI: * DMAR\n");
120 acpi_create_dmar(dmar, DMAR_INTR_REMAP, acpi_fill_dmar);
121 current += dmar->header.length;
122 current = acpi_align_current(current);
123 acpi_add_table(rsdp, dmar);
124
125 return current;
126}