blob: 4d88e3609d2c8a466a365254631408ba89c03b45 [file] [log] [blame]
Angel Pons4b429832020-04-02 23:48:50 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Patrick Georgi2efc8802012-11-06 11:03:53 +01003
4#include <stdint.h>
5#include <string.h>
6
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02007#include <device/pci_ops.h>
Patrick Georgi2efc8802012-11-06 11:03:53 +01008#include <device/pci_def.h>
Patrick Georgi2efc8802012-11-06 11:03:53 +01009
10#include "gm45.h"
11
12void init_iommu()
13{
14 /* FIXME: proper test? */
15 int me_active = pci_read_config8(PCI_DEV(0, 3, 0), PCI_CLASS_REVISION) != 0xff;
16 int stepping = pci_read_config8(PCI_DEV(0, 0, 0), PCI_CLASS_REVISION);
17
18 MCHBAR32(0x28) = IOMMU_BASE1 | 1; /* HDA @ 0:1b.0 */
19 if (stepping != STEPPING_B2) {
20 /* The official workaround is to run SMM every 64ms.
21 The only winning move is not to play. */
22 MCHBAR32(0x18) = IOMMU_BASE2 | 1; /* IGD @ 0:2.0-1 */
23 } else {
24 /* write-once, so lock it down */
25 MCHBAR32(0x18) = 0; /* disable IOMMU for IGD @ 0:2.0-1 */
26 }
27 if (me_active) {
28 MCHBAR32(0x10) = IOMMU_BASE3 | 1; /* ME @ 0:3.0-3 */
Damien Zammit88af3722016-08-27 00:35:48 +100029 } else {
30 MCHBAR32(0x10) = 0; /* disable IOMMU for ME */
Patrick Georgi2efc8802012-11-06 11:03:53 +010031 }
32 MCHBAR32(0x20) = IOMMU_BASE4 | 1; /* all other DMA sources */
33
34 /* clear GTT */
Elyes HAOUASef20ecc2018-10-04 13:50:14 +020035 u16 gtt = pci_read_config16(PCI_DEV(0, 0, 0), D0F0_GGC);
Patrick Georgi2efc8802012-11-06 11:03:53 +010036 if (gtt & 0x400) { /* VT mode */
Furquan Shaikh25f75b22016-08-29 22:51:41 -070037 pci_devfn_t igd = PCI_DEV(0, 2, 0);
Patrick Georgi2efc8802012-11-06 11:03:53 +010038
39 /* setup somewhere */
40 u8 cmd = pci_read_config8(igd, PCI_COMMAND);
41 cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
42 pci_write_config8(igd, PCI_COMMAND, cmd);
Elyes HAOUASfd051dc2018-07-08 12:39:34 +020043 void *bar = (void *)pci_read_config32(igd, PCI_BASE_ADDRESS_0);
Patrick Georgi2efc8802012-11-06 11:03:53 +010044
45 /* clear GTT, 2MB is enough (and should be safe) */
46 memset(bar, 0, 2<<20);
47
48 /* and now disable again */
49 cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
50 pci_write_config8(igd, PCI_COMMAND, cmd);
51 pci_write_config32(igd, PCI_BASE_ADDRESS_0, 0);
52 }
53
54 if (stepping == STEPPING_B3) {
55 MCHBAR8(0xffc) |= 1 << 4;
Furquan Shaikh25f75b22016-08-29 22:51:41 -070056 pci_devfn_t peg = PCI_DEV(0, 1, 0);
Patrick Georgi2efc8802012-11-06 11:03:53 +010057 /* FIXME: proper test? */
58 if (pci_read_config8(peg, PCI_CLASS_REVISION) != 0xff) {
59 int val = pci_read_config32(peg, 0xfc) | (1 << 15);
60 pci_write_config32(peg, 0xfc, val);
61 }
62 }
63
64 /* final */
65 MCHBAR8(0x94) |= 1 << 3;
66}