blob: 82b622113ac504e36a9ea9d767eb3701b9514fec [file] [log] [blame]
Patrick Georgi2efc8802012-11-06 11:03:53 +01001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2007-2009 coresystems GmbH
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; version 2 of
9 * the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Patrick Georgi2efc8802012-11-06 11:03:53 +010015 */
16
17#include <types.h>
Patrick Georgi2efc8802012-11-06 11:03:53 +010018#include <console/console.h>
19#include <arch/acpi.h>
20#include <arch/acpigen.h>
21#include <device/device.h>
22#include <device/pci.h>
Elyes HAOUAS748caed2019-12-19 17:02:08 +010023#include <device/pci_def.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020024#include <device/pci_ops.h>
Elyes HAOUASa1e22b82019-03-18 22:49:36 +010025
Patrick Georgi2efc8802012-11-06 11:03:53 +010026#include "gm45.h"
27
28unsigned long acpi_fill_mcfg(unsigned long current)
29{
Elyes HAOUAS6dcdaaf2018-02-09 07:44:31 +010030 struct device *dev;
Patrick Georgi2efc8802012-11-06 11:03:53 +010031 u32 pciexbar = 0;
32 u32 pciexbar_reg;
33 int max_buses;
34
35 dev = dev_find_device(0x8086, 0x2a40, 0);
36 if (!dev)
37 return current;
38
39 pciexbar_reg = pci_read_config32(dev, D0F0_PCIEXBAR_LO);
40
41 // MMCFG not supported or not enabled.
42 if (!(pciexbar_reg & (1 << 0)))
43 return current;
44
45 switch ((pciexbar_reg >> 1) & 3) {
46 case 0: // 256MB
47 pciexbar = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28));
48 max_buses = 256;
49 break;
50 case 1: // 128M
51 pciexbar = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)|(1 << 27));
52 max_buses = 128;
53 break;
54 case 2: // 64M
55 pciexbar = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)|(1 << 27)|(1 << 26));
56 max_buses = 64;
57 break;
58 default: // RSVD
59 return current;
60 }
61
62 if (!pciexbar)
63 return current;
64
65 current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *) current,
66 pciexbar, 0x0, 0x0, max_buses - 1);
67
68 return current;
69}
70
Vladimir Serbinenko8d70e942014-11-09 13:22:27 +010071static unsigned long acpi_fill_dmar(unsigned long current)
Patrick Georgi2efc8802012-11-06 11:03:53 +010072{
Arthur Heymans15063e82019-08-12 09:41:42 +020073 const struct device *dev;
74
75 dev = pcidev_on_root(3, 0);
76 int me_active = dev && dev->enabled;
77
Arthur Heymans08456362019-08-12 09:21:30 +020078 dev = pcidev_on_root(2, 0);
79 int igd_active = dev && dev->enabled;
80
Kyösti Mälkkic70eed12018-05-22 02:18:00 +030081 int stepping = pci_read_config8(pcidev_on_root(0, 0),
82 PCI_CLASS_REVISION);
Patrick Georgi2efc8802012-11-06 11:03:53 +010083
84 unsigned long tmp = current;
85 current += acpi_create_dmar_drhd(current, 0, 0, IOMMU_BASE1);
Matt DeVillier7866d492018-03-29 14:59:57 +020086 current += acpi_create_dmar_ds_pci(current, 0, 0x1b, 0);
Patrick Georgi2efc8802012-11-06 11:03:53 +010087 acpi_dmar_drhd_fixup(tmp, current);
88
Arthur Heymans08456362019-08-12 09:21:30 +020089 if (stepping != STEPPING_B2 && igd_active) {
Patrick Georgi2efc8802012-11-06 11:03:53 +010090 tmp = current;
91 current += acpi_create_dmar_drhd(current, 0, 0, IOMMU_BASE2);
Matt DeVillier7866d492018-03-29 14:59:57 +020092 current += acpi_create_dmar_ds_pci(current, 0, 0x2, 0);
93 current += acpi_create_dmar_ds_pci(current, 0, 0x2, 1);
Patrick Georgi2efc8802012-11-06 11:03:53 +010094 acpi_dmar_drhd_fixup(tmp, current);
95 }
96
97 if (me_active) {
98 tmp = current;
99 current += acpi_create_dmar_drhd(current, 0, 0, IOMMU_BASE3);
Matt DeVillier7866d492018-03-29 14:59:57 +0200100 current += acpi_create_dmar_ds_pci(current, 0, 0x3, 0);
101 current += acpi_create_dmar_ds_pci(current, 0, 0x3, 1);
102 current += acpi_create_dmar_ds_pci(current, 0, 0x3, 2);
103 current += acpi_create_dmar_ds_pci(current, 0, 0x3, 3);
Patrick Georgi2efc8802012-11-06 11:03:53 +0100104 acpi_dmar_drhd_fixup(tmp, current);
105 }
106
107 current += acpi_create_dmar_drhd(current, DRHD_INCLUDE_PCI_ALL, 0, IOMMU_BASE4);
108
109 /* TODO: reserve GTT for 0.2.0 and 0.2.1? */
110 return current;
111}
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200112
Elyes HAOUAS6dcdaaf2018-02-09 07:44:31 +0100113unsigned long northbridge_write_acpi_tables(struct device *device,
Alexander Couzens83fc32f2015-04-12 22:28:37 +0200114 unsigned long start,
115 struct acpi_rsdp *rsdp)
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200116{
117 unsigned long current;
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200118 acpi_dmar_t *dmar;
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200119
120 current = start;
121
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200122 printk(BIOS_DEBUG, "ACPI: * DMAR\n");
123 dmar = (acpi_dmar_t *) current;
Nico Hubere561f352015-10-26 11:51:25 +0100124 acpi_create_dmar(dmar, 0, acpi_fill_dmar);
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200125 current += dmar->header.length;
Aaron Durbin07a1b282015-12-10 17:07:38 -0600126 current = acpi_align_current(current);
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200127 acpi_add_table(rsdp, dmar);
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200128
Aaron Durbin07a1b282015-12-10 17:07:38 -0600129 current = acpi_align_current(current);
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200130
131 printk(BIOS_DEBUG, "current = %lx\n", current);
132
133 return current;
134}