]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/i386/pci/mmconfig-shared.c
[PATCH] mmconfig: minor cleanup in mmconfig code
[linux-2.6-omap-h63xx.git] / arch / i386 / pci / mmconfig-shared.c
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:
6  * - known chipset handling
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
25 DECLARE_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. */
33 static void __init unreachable_devices(void)
34 {
35         int i, bus;
36         /* Use the max bus number from ACPI here? */
37         for (bus = 0; bus < PCI_MMCFG_MAX_CHECK_BUS; bus++) {
38                 for (i = 0; i < 32; i++) {
39                         unsigned int devfn = PCI_DEVFN(i, 0);
40                         u32 val1, val2;
41
42                         pci_conf1_read(0, bus, devfn, 0, 4, &val1);
43                         if (val1 == 0xffffffff)
44                                 continue;
45
46                         raw_pci_ops->read(0, bus, devfn, 0, 4, &val2);
47                         if (val1 != val2) {
48                                 set_bit(i + 32 * bus, pci_mmcfg_fallback_slots);
49                                 printk(KERN_NOTICE "PCI: No mmconfig possible"
50                                        " on device %02x:%02x\n", bus, i);
51                         }
52                 }
53         }
54 }
55
56 static const char __init *pci_mmcfg_e7520(void)
57 {
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
73 static const char __init *pci_mmcfg_intel_945(void)
74 {
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
122 struct pci_mmcfg_hostbridge_probe {
123         u32 vendor;
124         u32 device;
125         const char *(*probe)(void);
126 };
127
128 static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = {
129         { 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
133 static 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
148         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)
151                         name = pci_mmcfg_probes[i].probe();
152         }
153
154         if (name) {
155                 printk(KERN_INFO "PCI: Found %s %s MMCONFIG support.\n",
156                        name, pci_mmcfg_config_num ? "with" : "without");
157         }
158
159         return name != NULL;
160 }
161
162 static void __init pci_mmcfg_insert_resources(void)
163 {
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);
172         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++) {
179                 struct acpi_mcfg_allocation *cfg = &pci_mmcfg_config[i];
180                 num_buses = cfg->end_bus_number - cfg->start_bus_number + 1;
181                 res->name = names;
182                 snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u",
183                          cfg->pci_segment);
184                 res->start = cfg->address;
185                 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
192 static 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
212 void __init pci_mmcfg_init(int type)
213 {
214         int known_bridge = 0;
215
216         if ((pci_probe & PCI_PROBE_MMCONF) == 0)
217                 return;
218
219         if (type == 1 && pci_mmcfg_check_hostbridge())
220                 known_bridge = 1;
221
222         if (!known_bridge) {
223                 acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
224                 pci_mmcfg_reject_broken();
225         }
226
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 */
234         if (type == 1 && !known_bridge &&
235             !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()) {
245                 if (type == 1)
246                         unreachable_devices();
247                 if (known_bridge)
248                         pci_mmcfg_insert_resources();
249                 pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
250         }
251 }