blob: 4ea0852487a4e0db8207bed16f749aacb7da542e [file] [log] [blame]
Olivier Galibertb7867392007-02-13 13:26:20 +01001/*
2 * mmconfig-shared.c - Low-level direct PCI config space access via
3 * MMCONFIG - common code between i386 and x86-64.
4 *
5 * This code does:
Olivier Galibert9358c692007-02-13 13:26:20 +01006 * - known chipset handling
Olivier Galibertb7867392007-02-13 13:26:20 +01007 * - ACPI decoding and validation
8 *
9 * Per-architecture code takes care of the mappings and accesses
10 * themselves.
11 */
12
13#include <linux/pci.h>
14#include <linux/init.h>
15#include <linux/acpi.h>
16#include <linux/bitmap.h>
17#include <asm/e820.h>
18
19#include "pci.h"
20
21/* aperture is up to 256MB but BIOS may reserve less */
22#define MMCONFIG_APER_MIN (2 * 1024*1024)
23#define MMCONFIG_APER_MAX (256 * 1024*1024)
24
Olivier Galibertb7867392007-02-13 13:26:20 +010025DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
26
27/* K8 systems have some devices (typically in the builtin northbridge)
28 that are only accessible using type1
29 Normally this can be expressed in the MCFG by not listing them
30 and assigning suitable _SEGs, but this isn't implemented in some BIOS.
31 Instead try to discover all devices on bus 0 that are unreachable using MM
32 and fallback for them. */
OGAWA Hirofumi429d5122007-02-13 13:26:20 +010033static void __init unreachable_devices(void)
Olivier Galibertb7867392007-02-13 13:26:20 +010034{
OGAWA Hirofumi429d5122007-02-13 13:26:20 +010035 int i, bus;
Olivier Galibertb7867392007-02-13 13:26:20 +010036 /* Use the max bus number from ACPI here? */
OGAWA Hirofumi429d5122007-02-13 13:26:20 +010037 for (bus = 0; bus < PCI_MMCFG_MAX_CHECK_BUS; bus++) {
Olivier Galibertb7867392007-02-13 13:26:20 +010038 for (i = 0; i < 32; i++) {
OGAWA Hirofumi429d5122007-02-13 13:26:20 +010039 unsigned int devfn = PCI_DEVFN(i, 0);
Olivier Galibertb7867392007-02-13 13:26:20 +010040 u32 val1, val2;
41
OGAWA Hirofumi429d5122007-02-13 13:26:20 +010042 pci_conf1_read(0, bus, devfn, 0, 4, &val1);
Olivier Galibertb7867392007-02-13 13:26:20 +010043 if (val1 == 0xffffffff)
44 continue;
45
OGAWA Hirofumi429d5122007-02-13 13:26:20 +010046 raw_pci_ops->read(0, bus, devfn, 0, 4, &val2);
Olivier Galibertb7867392007-02-13 13:26:20 +010047 if (val1 != val2) {
OGAWA Hirofumi429d5122007-02-13 13:26:20 +010048 set_bit(i + 32 * bus, pci_mmcfg_fallback_slots);
Olivier Galibertb7867392007-02-13 13:26:20 +010049 printk(KERN_NOTICE "PCI: No mmconfig possible"
OGAWA Hirofumi429d5122007-02-13 13:26:20 +010050 " on device %02x:%02x\n", bus, i);
Olivier Galibertb7867392007-02-13 13:26:20 +010051 }
52 }
53 }
54}
55
OGAWA Hirofumi429d5122007-02-13 13:26:20 +010056static const char __init *pci_mmcfg_e7520(void)
Olivier Galibert9358c692007-02-13 13:26:20 +010057{
58 u32 win;
59 pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win);
60
61 pci_mmcfg_config_num = 1;
62 pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
63 if (!pci_mmcfg_config)
64 return NULL;
65 pci_mmcfg_config[0].address = (win & 0xf000) << 16;
66 pci_mmcfg_config[0].pci_segment = 0;
67 pci_mmcfg_config[0].start_bus_number = 0;
68 pci_mmcfg_config[0].end_bus_number = 255;
69
70 return "Intel Corporation E7520 Memory Controller Hub";
71}
72
OGAWA Hirofumi429d5122007-02-13 13:26:20 +010073static const char __init *pci_mmcfg_intel_945(void)
Olivier Galibert9358c692007-02-13 13:26:20 +010074{
75 u32 pciexbar, mask = 0, len = 0;
76
77 pci_mmcfg_config_num = 1;
78
79 pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0x48, 4, &pciexbar);
80
81 /* Enable bit */
82 if (!(pciexbar & 1))
83 pci_mmcfg_config_num = 0;
84
85 /* Size bits */
86 switch ((pciexbar >> 1) & 3) {
87 case 0:
88 mask = 0xf0000000U;
89 len = 0x10000000U;
90 break;
91 case 1:
92 mask = 0xf8000000U;
93 len = 0x08000000U;
94 break;
95 case 2:
96 mask = 0xfc000000U;
97 len = 0x04000000U;
98 break;
99 default:
100 pci_mmcfg_config_num = 0;
101 }
102
103 /* Errata #2, things break when not aligned on a 256Mb boundary */
104 /* Can only happen in 64M/128M mode */
105
106 if ((pciexbar & mask) & 0x0fffffffU)
107 pci_mmcfg_config_num = 0;
108
109 if (pci_mmcfg_config_num) {
110 pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
111 if (!pci_mmcfg_config)
112 return NULL;
113 pci_mmcfg_config[0].address = pciexbar & mask;
114 pci_mmcfg_config[0].pci_segment = 0;
115 pci_mmcfg_config[0].start_bus_number = 0;
116 pci_mmcfg_config[0].end_bus_number = (len >> 20) - 1;
117 }
118
119 return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
120}
121
122struct pci_mmcfg_hostbridge_probe {
123 u32 vendor;
124 u32 device;
125 const char *(*probe)(void);
126};
127
OGAWA Hirofumi429d5122007-02-13 13:26:20 +0100128static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = {
Olivier Galibert9358c692007-02-13 13:26:20 +0100129 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
130 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
131};
132
133static int __init pci_mmcfg_check_hostbridge(void)
134{
135 u32 l;
136 u16 vendor, device;
137 int i;
138 const char *name;
139
140 pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0, 4, &l);
141 vendor = l & 0xffff;
142 device = (l >> 16) & 0xffff;
143
144 pci_mmcfg_config_num = 0;
145 pci_mmcfg_config = NULL;
146 name = NULL;
147
OGAWA Hirofumi429d5122007-02-13 13:26:20 +0100148 for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) {
149 if (pci_mmcfg_probes[i].vendor == vendor &&
150 pci_mmcfg_probes[i].device == device)
Olivier Galibert9358c692007-02-13 13:26:20 +0100151 name = pci_mmcfg_probes[i].probe();
OGAWA Hirofumi429d5122007-02-13 13:26:20 +0100152 }
Olivier Galibert9358c692007-02-13 13:26:20 +0100153
154 if (name) {
OGAWA Hirofumi429d5122007-02-13 13:26:20 +0100155 printk(KERN_INFO "PCI: Found %s %s MMCONFIG support.\n",
156 name, pci_mmcfg_config_num ? "with" : "without");
Olivier Galibert9358c692007-02-13 13:26:20 +0100157 }
158
159 return name != NULL;
160}
161
OGAWA Hirofumi429d5122007-02-13 13:26:20 +0100162static void __init pci_mmcfg_insert_resources(void)
Olivier Galibert6a0668f2007-02-13 13:26:20 +0100163{
164#define PCI_MMCFG_RESOURCE_NAME_LEN 19
165 int i;
166 struct resource *res;
167 char *names;
168 unsigned num_buses;
169
170 res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res),
171 pci_mmcfg_config_num, GFP_KERNEL);
Olivier Galibert6a0668f2007-02-13 13:26:20 +0100172 if (!res) {
173 printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n");
174 return;
175 }
176
177 names = (void *)&res[pci_mmcfg_config_num];
178 for (i = 0; i < pci_mmcfg_config_num; i++, res++) {
OGAWA Hirofumi429d5122007-02-13 13:26:20 +0100179 struct acpi_mcfg_allocation *cfg = &pci_mmcfg_config[i];
180 num_buses = cfg->end_bus_number - cfg->start_bus_number + 1;
Olivier Galibert6a0668f2007-02-13 13:26:20 +0100181 res->name = names;
182 snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u",
OGAWA Hirofumi429d5122007-02-13 13:26:20 +0100183 cfg->pci_segment);
184 res->start = cfg->address;
Olivier Galibert6a0668f2007-02-13 13:26:20 +0100185 res->end = res->start + (num_buses << 20) - 1;
186 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
187 insert_resource(&iomem_resource, res);
188 names += PCI_MMCFG_RESOURCE_NAME_LEN;
189 }
190}
191
OGAWA Hirofumi44de0202007-02-13 13:26:20 +0100192static void __init pci_mmcfg_reject_broken(void)
193{
194 typeof(pci_mmcfg_config[0]) *cfg = &pci_mmcfg_config[0];
195
196 /*
197 * Handle more broken MCFG tables on Asus etc.
198 * They only contain a single entry for bus 0-0.
199 */
200 if (pci_mmcfg_config_num == 1 &&
201 cfg->pci_segment == 0 &&
202 (cfg->start_bus_number | cfg->end_bus_number) == 0) {
203 kfree(pci_mmcfg_config);
204 pci_mmcfg_config = NULL;
205 pci_mmcfg_config_num = 0;
206
207 printk(KERN_ERR "PCI: start and end of bus number is 0. "
208 "Rejected as broken MCFG.");
209 }
210}
211
Olivier Galibertb7867392007-02-13 13:26:20 +0100212void __init pci_mmcfg_init(int type)
213{
Olivier Galibert9358c692007-02-13 13:26:20 +0100214 int known_bridge = 0;
215
Olivier Galibertb7867392007-02-13 13:26:20 +0100216 if ((pci_probe & PCI_PROBE_MMCONF) == 0)
217 return;
218
Olivier Galibert9358c692007-02-13 13:26:20 +0100219 if (type == 1 && pci_mmcfg_check_hostbridge())
220 known_bridge = 1;
221
OGAWA Hirofumi44de0202007-02-13 13:26:20 +0100222 if (!known_bridge) {
Olivier Galibert9358c692007-02-13 13:26:20 +0100223 acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
OGAWA Hirofumi44de0202007-02-13 13:26:20 +0100224 pci_mmcfg_reject_broken();
225 }
Olivier Galibertb7867392007-02-13 13:26:20 +0100226
227 if ((pci_mmcfg_config_num == 0) ||
228 (pci_mmcfg_config == NULL) ||
229 (pci_mmcfg_config[0].address == 0))
230 return;
231
232 /* Only do this check when type 1 works. If it doesn't work
233 assume we run on a Mac and always use MCFG */
Olivier Galibert9358c692007-02-13 13:26:20 +0100234 if (type == 1 && !known_bridge &&
Olivier Galibertb7867392007-02-13 13:26:20 +0100235 !e820_all_mapped(pci_mmcfg_config[0].address,
236 pci_mmcfg_config[0].address + MMCONFIG_APER_MIN,
237 E820_RESERVED)) {
238 printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not E820-reserved\n",
239 pci_mmcfg_config[0].address);
240 printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
241 return;
242 }
243
244 if (pci_mmcfg_arch_init()) {
Olivier Galibert5f027382007-02-13 13:26:20 +0100245 if (type == 1)
246 unreachable_devices();
Olivier Galibert6a0668f2007-02-13 13:26:20 +0100247 if (known_bridge)
248 pci_mmcfg_insert_resources();
Olivier Galibertb7867392007-02-13 13:26:20 +0100249 pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
250 }
251}