blob: 658000aa87f33a7562477bd53357198913eba35c [file] [log] [blame]
Stefan Reinauer00636b02012-04-04 00:08:51 +02001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2007-2009 coresystems GmbH
Stefan Reinauere5a0a5d2012-09-19 10:51:48 -07005 * Copyright (C) 2012 The Chromium OS Authors
Stefan Reinauer00636b02012-04-04 00:08:51 +02006 *
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.
Stefan Reinauer00636b02012-04-04 00:08:51 +020016 */
17
18#include <types.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020019#include <console/console.h>
20#include <arch/acpi.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020021#include <device/device.h>
22#include <device/pci.h>
23#include <device/pci_ids.h>
24#include "sandybridge.h"
Nico Huber9d9ce0d2015-10-26 12:59:49 +010025#include <southbridge/intel/bd82x6x/pch.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020026
27unsigned long acpi_fill_mcfg(unsigned long current)
28{
29 device_t dev;
30 u32 pciexbar = 0;
31 u32 pciexbar_reg;
32 int max_buses;
33
Stefan Reinauer6097e192012-06-11 15:38:15 -070034 dev = dev_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_SB, 0);
35 if (!dev)
36 dev = dev_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_IB, 0);
Stefan Reinauer00636b02012-04-04 00:08:51 +020037 if (!dev)
38 return current;
39
40 pciexbar_reg=pci_read_config32(dev, PCIEXBAR);
41
42 // MMCFG not supported or not enabled.
43 if (!(pciexbar_reg & (1 << 0)))
44 return current;
45
46 switch ((pciexbar_reg >> 1) & 3) {
47 case 0: // 256MB
48 pciexbar = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28));
49 max_buses = 256;
50 break;
51 case 1: // 128M
52 pciexbar = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)|(1 << 27));
53 max_buses = 128;
54 break;
55 case 2: // 64M
56 pciexbar = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)|(1 << 27)|(1 << 26));
57 max_buses = 64;
58 break;
59 default: // RSVD
60 return current;
61 }
62
63 if (!pciexbar)
64 return current;
65
66 current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *) current,
67 pciexbar, 0x0, 0x0, max_buses - 1);
68
69 return current;
70}
71
Nico Huber9d9ce0d2015-10-26 12:59:49 +010072static unsigned long acpi_fill_dmar(unsigned long current)
73{
74 const struct device *const igfx = dev_find_slot(0, PCI_DEVFN(2, 0));
75
76 if (igfx && igfx->enabled) {
77 const unsigned long tmp = current;
78 current += acpi_create_dmar_drhd(current, 0, 0, IOMMU_BASE1);
79 current += acpi_create_dmar_drhd_ds_pci(current, 0, 2, 0);
80 current += acpi_create_dmar_drhd_ds_pci(current, 0, 2, 1);
81 acpi_dmar_drhd_fixup(tmp, current);
82 }
83
84 const unsigned long tmp = current;
85 current += acpi_create_dmar_drhd(current,
86 DRHD_INCLUDE_PCI_ALL, 0, IOMMU_BASE2);
87 current += acpi_create_dmar_drhd_ds_ioapic(current,
88 2, PCH_IOAPIC_PCI_BUS, PCH_IOAPIC_PCI_SLOT, 0);
89 size_t i;
90 for (i = 0; i < 8; ++i)
91 current += acpi_create_dmar_drhd_ds_msi_hpet(current,
92 0, PCH_HPET_PCI_BUS, PCH_HPET_PCI_SLOT, i);
93 acpi_dmar_drhd_fixup(tmp, current);
94
95 return current;
96}
97
Nico Huber9d9ce0d2015-10-26 12:59:49 +010098unsigned long northbridge_write_acpi_tables(struct device *const dev,
99 unsigned long current,
100 struct acpi_rsdp *const rsdp)
101{
102 const u32 capid0_a = pci_read_config32(dev, 0xe4);
103 if (capid0_a & (1 << 23))
104 return current;
105
106 printk(BIOS_DEBUG, "ACPI: * DMAR\n");
107 acpi_dmar_t *const dmar = (acpi_dmar_t *)current;
108 acpi_create_dmar(dmar, DMAR_INTR_REMAP, acpi_fill_dmar);
109 current += dmar->header.length;
Aaron Durbin07a1b282015-12-10 17:07:38 -0600110 current = acpi_align_current(current);
Nico Huber9d9ce0d2015-10-26 12:59:49 +0100111 acpi_add_table(rsdp, dmar);
112
Aaron Durbin07a1b282015-12-10 17:07:38 -0600113 current = acpi_align_current(current);
Nico Huber9d9ce0d2015-10-26 12:59:49 +0100114
115 printk(BIOS_DEBUG, "current = %lx\n", current);
116
117 return current;
118}