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