x86_64: fake apicid_to_node mapping for fake numa
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / i386 / pci / mmconfig-shared.c
CommitLineData
b7867394
OG
1/*
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:
9358c693 6 * - known chipset handling
b7867394
OG
7 * - 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
b7867394
OG
25DECLARE_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. */
429d512e 33static void __init unreachable_devices(void)
b7867394 34{
429d512e 35 int i, bus;
b7867394 36 /* Use the max bus number from ACPI here? */
429d512e 37 for (bus = 0; bus < PCI_MMCFG_MAX_CHECK_BUS; bus++) {
b7867394 38 for (i = 0; i < 32; i++) {
429d512e 39 unsigned int devfn = PCI_DEVFN(i, 0);
b7867394
OG
40 u32 val1, val2;
41
429d512e 42 pci_conf1_read(0, bus, devfn, 0, 4, &val1);
b7867394
OG
43 if (val1 == 0xffffffff)
44 continue;
45
56829d19
OH
46 if (pci_mmcfg_arch_reachable(0, bus, devfn)) {
47 raw_pci_ops->read(0, bus, devfn, 0, 4, &val2);
48 if (val1 == val2)
49 continue;
b7867394 50 }
56829d19
OH
51 set_bit(i + 32 * bus, pci_mmcfg_fallback_slots);
52 printk(KERN_NOTICE "PCI: No mmconfig possible on device"
53 " %02x:%02x\n", bus, i);
b7867394
OG
54 }
55 }
56}
57
429d512e 58static const char __init *pci_mmcfg_e7520(void)
9358c693
OG
59{
60 u32 win;
61 pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win);
62
b5229dbb
OG
63 win = win & 0xf000;
64 if(win == 0x0000 || win == 0xf000)
65 pci_mmcfg_config_num = 0;
66 else {
67 pci_mmcfg_config_num = 1;
68 pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
69 if (!pci_mmcfg_config)
70 return NULL;
71 pci_mmcfg_config[0].address = win << 16;
72 pci_mmcfg_config[0].pci_segment = 0;
73 pci_mmcfg_config[0].start_bus_number = 0;
74 pci_mmcfg_config[0].end_bus_number = 255;
75 }
9358c693
OG
76
77 return "Intel Corporation E7520 Memory Controller Hub";
78}
79
429d512e 80static const char __init *pci_mmcfg_intel_945(void)
9358c693
OG
81{
82 u32 pciexbar, mask = 0, len = 0;
83
84 pci_mmcfg_config_num = 1;
85
86 pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0x48, 4, &pciexbar);
87
88 /* Enable bit */
89 if (!(pciexbar & 1))
90 pci_mmcfg_config_num = 0;
91
92 /* Size bits */
93 switch ((pciexbar >> 1) & 3) {
94 case 0:
95 mask = 0xf0000000U;
96 len = 0x10000000U;
97 break;
98 case 1:
99 mask = 0xf8000000U;
100 len = 0x08000000U;
101 break;
102 case 2:
103 mask = 0xfc000000U;
104 len = 0x04000000U;
105 break;
106 default:
107 pci_mmcfg_config_num = 0;
108 }
109
110 /* Errata #2, things break when not aligned on a 256Mb boundary */
111 /* Can only happen in 64M/128M mode */
112
113 if ((pciexbar & mask) & 0x0fffffffU)
114 pci_mmcfg_config_num = 0;
115
b5229dbb
OG
116 /* Don't hit the APIC registers and their friends */
117 if ((pciexbar & mask) >= 0xf0000000U)
118 pci_mmcfg_config_num = 0;
119
9358c693
OG
120 if (pci_mmcfg_config_num) {
121 pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
122 if (!pci_mmcfg_config)
123 return NULL;
124 pci_mmcfg_config[0].address = pciexbar & mask;
125 pci_mmcfg_config[0].pci_segment = 0;
126 pci_mmcfg_config[0].start_bus_number = 0;
127 pci_mmcfg_config[0].end_bus_number = (len >> 20) - 1;
128 }
129
130 return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
131}
132
133struct pci_mmcfg_hostbridge_probe {
134 u32 vendor;
135 u32 device;
136 const char *(*probe)(void);
137};
138
429d512e 139static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = {
9358c693
OG
140 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
141 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
142};
143
144static int __init pci_mmcfg_check_hostbridge(void)
145{
146 u32 l;
147 u16 vendor, device;
148 int i;
149 const char *name;
150
151 pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0, 4, &l);
152 vendor = l & 0xffff;
153 device = (l >> 16) & 0xffff;
154
155 pci_mmcfg_config_num = 0;
156 pci_mmcfg_config = NULL;
157 name = NULL;
158
429d512e
OH
159 for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) {
160 if (pci_mmcfg_probes[i].vendor == vendor &&
161 pci_mmcfg_probes[i].device == device)
9358c693 162 name = pci_mmcfg_probes[i].probe();
429d512e 163 }
9358c693
OG
164
165 if (name) {
429d512e
OH
166 printk(KERN_INFO "PCI: Found %s %s MMCONFIG support.\n",
167 name, pci_mmcfg_config_num ? "with" : "without");
9358c693
OG
168 }
169
170 return name != NULL;
171}
172
429d512e 173static void __init pci_mmcfg_insert_resources(void)
6a0668fc
OG
174{
175#define PCI_MMCFG_RESOURCE_NAME_LEN 19
176 int i;
177 struct resource *res;
178 char *names;
179 unsigned num_buses;
180
181 res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res),
182 pci_mmcfg_config_num, GFP_KERNEL);
6a0668fc
OG
183 if (!res) {
184 printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n");
185 return;
186 }
187
188 names = (void *)&res[pci_mmcfg_config_num];
189 for (i = 0; i < pci_mmcfg_config_num; i++, res++) {
429d512e
OH
190 struct acpi_mcfg_allocation *cfg = &pci_mmcfg_config[i];
191 num_buses = cfg->end_bus_number - cfg->start_bus_number + 1;
6a0668fc
OG
192 res->name = names;
193 snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u",
429d512e
OH
194 cfg->pci_segment);
195 res->start = cfg->address;
6a0668fc
OG
196 res->end = res->start + (num_buses << 20) - 1;
197 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
198 insert_resource(&iomem_resource, res);
199 names += PCI_MMCFG_RESOURCE_NAME_LEN;
200 }
201}
202
26054ed0 203static void __init pci_mmcfg_reject_broken(int type)
44de0203 204{
26054ed0
OH
205 typeof(pci_mmcfg_config[0]) *cfg;
206
207 if ((pci_mmcfg_config_num == 0) ||
208 (pci_mmcfg_config == NULL) ||
209 (pci_mmcfg_config[0].address == 0))
210 return;
211
212 cfg = &pci_mmcfg_config[0];
44de0203
OH
213
214 /*
215 * Handle more broken MCFG tables on Asus etc.
216 * They only contain a single entry for bus 0-0.
217 */
218 if (pci_mmcfg_config_num == 1 &&
219 cfg->pci_segment == 0 &&
220 (cfg->start_bus_number | cfg->end_bus_number) == 0) {
44de0203 221 printk(KERN_ERR "PCI: start and end of bus number is 0. "
26054ed0
OH
222 "Rejected as broken MCFG.\n");
223 goto reject;
224 }
225
226 /*
227 * Only do this check when type 1 works. If it doesn't work
228 * assume we run on a Mac and always use MCFG
229 */
230 if (type == 1 && !e820_all_mapped(cfg->address,
231 cfg->address + MMCONFIG_APER_MIN,
232 E820_RESERVED)) {
233 printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not"
234 " E820-reserved\n", cfg->address);
235 goto reject;
44de0203 236 }
26054ed0
OH
237 return;
238
239reject:
240 printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
241 kfree(pci_mmcfg_config);
242 pci_mmcfg_config = NULL;
243 pci_mmcfg_config_num = 0;
44de0203
OH
244}
245
b7867394
OG
246void __init pci_mmcfg_init(int type)
247{
9358c693
OG
248 int known_bridge = 0;
249
b7867394
OG
250 if ((pci_probe & PCI_PROBE_MMCONF) == 0)
251 return;
252
9358c693
OG
253 if (type == 1 && pci_mmcfg_check_hostbridge())
254 known_bridge = 1;
255
44de0203 256 if (!known_bridge) {
9358c693 257 acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
26054ed0 258 pci_mmcfg_reject_broken(type);
44de0203 259 }
b7867394
OG
260
261 if ((pci_mmcfg_config_num == 0) ||
262 (pci_mmcfg_config == NULL) ||
263 (pci_mmcfg_config[0].address == 0))
264 return;
265
b7867394 266 if (pci_mmcfg_arch_init()) {
5f027387
OG
267 if (type == 1)
268 unreachable_devices();
6a0668fc
OG
269 if (known_bridge)
270 pci_mmcfg_insert_resources();
b7867394
OG
271 pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
272 }
273}