[PATCH] x86_64: Don't sanity check Type 1 PCI bus access on newer systems
[linux-drm-fsl-dcu.git] / arch / i386 / pci / direct.c
1 /*
2  * direct.c - Low-level direct PCI config space access
3  */
4
5 #include <linux/pci.h>
6 #include <linux/init.h>
7 #include <linux/dmi.h>
8 #include "pci.h"
9
10 /*
11  * Functions for accessing PCI configuration space with type 1 accesses
12  */
13
14 #define PCI_CONF1_ADDRESS(bus, devfn, reg) \
15         (0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3))
16
17 int pci_conf1_read(unsigned int seg, unsigned int bus,
18                           unsigned int devfn, int reg, int len, u32 *value)
19 {
20         unsigned long flags;
21
22         if (!value || (bus > 255) || (devfn > 255) || (reg > 255))
23                 return -EINVAL;
24
25         spin_lock_irqsave(&pci_config_lock, flags);
26
27         outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
28
29         switch (len) {
30         case 1:
31                 *value = inb(0xCFC + (reg & 3));
32                 break;
33         case 2:
34                 *value = inw(0xCFC + (reg & 2));
35                 break;
36         case 4:
37                 *value = inl(0xCFC);
38                 break;
39         }
40
41         spin_unlock_irqrestore(&pci_config_lock, flags);
42
43         return 0;
44 }
45
46 int pci_conf1_write(unsigned int seg, unsigned int bus,
47                            unsigned int devfn, int reg, int len, u32 value)
48 {
49         unsigned long flags;
50
51         if ((bus > 255) || (devfn > 255) || (reg > 255)) 
52                 return -EINVAL;
53
54         spin_lock_irqsave(&pci_config_lock, flags);
55
56         outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
57
58         switch (len) {
59         case 1:
60                 outb((u8)value, 0xCFC + (reg & 3));
61                 break;
62         case 2:
63                 outw((u16)value, 0xCFC + (reg & 2));
64                 break;
65         case 4:
66                 outl((u32)value, 0xCFC);
67                 break;
68         }
69
70         spin_unlock_irqrestore(&pci_config_lock, flags);
71
72         return 0;
73 }
74
75 #undef PCI_CONF1_ADDRESS
76
77 struct pci_raw_ops pci_direct_conf1 = {
78         .read =         pci_conf1_read,
79         .write =        pci_conf1_write,
80 };
81
82
83 /*
84  * Functions for accessing PCI configuration space with type 2 accesses
85  */
86
87 #define PCI_CONF2_ADDRESS(dev, reg)     (u16)(0xC000 | (dev << 8) | reg)
88
89 static int pci_conf2_read(unsigned int seg, unsigned int bus,
90                           unsigned int devfn, int reg, int len, u32 *value)
91 {
92         unsigned long flags;
93         int dev, fn;
94
95         if (!value || (bus > 255) || (devfn > 255) || (reg > 255))
96                 return -EINVAL;
97
98         dev = PCI_SLOT(devfn);
99         fn = PCI_FUNC(devfn);
100
101         if (dev & 0x10) 
102                 return PCIBIOS_DEVICE_NOT_FOUND;
103
104         spin_lock_irqsave(&pci_config_lock, flags);
105
106         outb((u8)(0xF0 | (fn << 1)), 0xCF8);
107         outb((u8)bus, 0xCFA);
108
109         switch (len) {
110         case 1:
111                 *value = inb(PCI_CONF2_ADDRESS(dev, reg));
112                 break;
113         case 2:
114                 *value = inw(PCI_CONF2_ADDRESS(dev, reg));
115                 break;
116         case 4:
117                 *value = inl(PCI_CONF2_ADDRESS(dev, reg));
118                 break;
119         }
120
121         outb(0, 0xCF8);
122
123         spin_unlock_irqrestore(&pci_config_lock, flags);
124
125         return 0;
126 }
127
128 static int pci_conf2_write(unsigned int seg, unsigned int bus,
129                            unsigned int devfn, int reg, int len, u32 value)
130 {
131         unsigned long flags;
132         int dev, fn;
133
134         if ((bus > 255) || (devfn > 255) || (reg > 255)) 
135                 return -EINVAL;
136
137         dev = PCI_SLOT(devfn);
138         fn = PCI_FUNC(devfn);
139
140         if (dev & 0x10) 
141                 return PCIBIOS_DEVICE_NOT_FOUND;
142
143         spin_lock_irqsave(&pci_config_lock, flags);
144
145         outb((u8)(0xF0 | (fn << 1)), 0xCF8);
146         outb((u8)bus, 0xCFA);
147
148         switch (len) {
149         case 1:
150                 outb((u8)value, PCI_CONF2_ADDRESS(dev, reg));
151                 break;
152         case 2:
153                 outw((u16)value, PCI_CONF2_ADDRESS(dev, reg));
154                 break;
155         case 4:
156                 outl((u32)value, PCI_CONF2_ADDRESS(dev, reg));
157                 break;
158         }
159
160         outb(0, 0xCF8);    
161
162         spin_unlock_irqrestore(&pci_config_lock, flags);
163
164         return 0;
165 }
166
167 #undef PCI_CONF2_ADDRESS
168
169 static struct pci_raw_ops pci_direct_conf2 = {
170         .read =         pci_conf2_read,
171         .write =        pci_conf2_write,
172 };
173
174
175 /*
176  * Before we decide to use direct hardware access mechanisms, we try to do some
177  * trivial checks to ensure it at least _seems_ to be working -- we just test
178  * whether bus 00 contains a host bridge (this is similar to checking
179  * techniques used in XFree86, but ours should be more reliable since we
180  * attempt to make use of direct access hints provided by the PCI BIOS).
181  *
182  * This should be close to trivial, but it isn't, because there are buggy
183  * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
184  */
185 static int __init pci_sanity_check(struct pci_raw_ops *o)
186 {
187         u32 x = 0;
188         int devfn;
189
190         if (pci_probe & PCI_NO_CHECKS)
191                 return 1;
192         /* Assume Type 1 works for newer systems.
193            This handles machines that don't have anything on PCI Bus 0. */
194         if (dmi_get_year(DMI_BIOS_DATE) >= 2001)
195                 return 1;
196
197         for (devfn = 0; devfn < 0x100; devfn++) {
198                 if (o->read(0, 0, devfn, PCI_CLASS_DEVICE, 2, &x))
199                         continue;
200                 if (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)
201                         return 1;
202
203                 if (o->read(0, 0, devfn, PCI_VENDOR_ID, 2, &x))
204                         continue;
205                 if (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ)
206                         return 1;
207         }
208
209         DBG(KERN_WARNING "PCI: Sanity check failed\n");
210         return 0;
211 }
212
213 static int __init pci_check_type1(void)
214 {
215         unsigned long flags;
216         unsigned int tmp;
217         int works = 0;
218
219         local_irq_save(flags);
220
221         outb(0x01, 0xCFB);
222         tmp = inl(0xCF8);
223         outl(0x80000000, 0xCF8);
224         if (inl(0xCF8) == 0x80000000 && pci_sanity_check(&pci_direct_conf1)) {
225                 works = 1;
226         }
227         outl(tmp, 0xCF8);
228         local_irq_restore(flags);
229
230         return works;
231 }
232
233 static int __init pci_check_type2(void)
234 {
235         unsigned long flags;
236         int works = 0;
237
238         local_irq_save(flags);
239
240         outb(0x00, 0xCFB);
241         outb(0x00, 0xCF8);
242         outb(0x00, 0xCFA);
243         if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00 &&
244             pci_sanity_check(&pci_direct_conf2)) {
245                 works = 1;
246         }
247
248         local_irq_restore(flags);
249
250         return works;
251 }
252
253 void __init pci_direct_init(void)
254 {
255         struct resource *region, *region2;
256
257         if ((pci_probe & PCI_PROBE_CONF1) == 0)
258                 goto type2;
259         region = request_region(0xCF8, 8, "PCI conf1");
260         if (!region)
261                 goto type2;
262
263         if (pci_check_type1()) {
264                 printk(KERN_INFO "PCI: Using configuration type 1\n");
265                 raw_pci_ops = &pci_direct_conf1;
266                 return;
267         }
268         release_resource(region);
269
270  type2:
271         if ((pci_probe & PCI_PROBE_CONF2) == 0)
272                 return;
273         region = request_region(0xCF8, 4, "PCI conf2");
274         if (!region)
275                 return;
276         region2 = request_region(0xC000, 0x1000, "PCI conf2");
277         if (!region2)
278                 goto fail2;
279
280         if (pci_check_type2()) {
281                 printk(KERN_INFO "PCI: Using configuration type 2\n");
282                 raw_pci_ops = &pci_direct_conf2;
283                 return;
284         }
285
286         release_resource(region2);
287  fail2:
288         release_resource(region);
289 }