Merge branch 'merge'
[pandora-kernel.git] / arch / i386 / pci / mmconfig.c
1 /*
2  * Copyright (C) 2004 Matthew Wilcox <matthew@wil.cx>
3  * Copyright (C) 2004 Intel Corp.
4  *
5  * This code is released under the GNU General Public License version 2.
6  */
7
8 /*
9  * mmconfig.c - Low-level direct PCI config space access via MMCONFIG
10  */
11
12 #include <linux/pci.h>
13 #include <linux/init.h>
14 #include <linux/acpi.h>
15 #include <linux/dmi.h>
16 #include <asm/e820.h>
17 #include "pci.h"
18
19 /* aperture is up to 256MB but BIOS may reserve less */
20 #define MMCONFIG_APER_MIN       (2 * 1024*1024)
21 #define MMCONFIG_APER_MAX       (256 * 1024*1024)
22
23 /* Assume systems with more busses have correct MCFG */
24 #define MAX_CHECK_BUS 16
25
26 #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
27
28 /* The base address of the last MMCONFIG device accessed */
29 static u32 mmcfg_last_accessed_device;
30
31 static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32);
32
33 /*
34  * Functions for accessing PCI configuration space with MMCONFIG accesses
35  */
36 static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
37 {
38         int cfg_num = -1;
39         struct acpi_table_mcfg_config *cfg;
40
41         if (seg == 0 && bus < MAX_CHECK_BUS &&
42             test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots))
43                 return 0;
44
45         while (1) {
46                 ++cfg_num;
47                 if (cfg_num >= pci_mmcfg_config_num) {
48                         break;
49                 }
50                 cfg = &pci_mmcfg_config[cfg_num];
51                 if (cfg->pci_segment_group_number != seg)
52                         continue;
53                 if ((cfg->start_bus_number <= bus) &&
54                     (cfg->end_bus_number >= bus))
55                         return cfg->base_address;
56         }
57
58         /* Handle more broken MCFG tables on Asus etc.
59            They only contain a single entry for bus 0-0. Assume
60            this applies to all busses. */
61         cfg = &pci_mmcfg_config[0];
62         if (pci_mmcfg_config_num == 1 &&
63                 cfg->pci_segment_group_number == 0 &&
64                 (cfg->start_bus_number | cfg->end_bus_number) == 0)
65                 return cfg->base_address;
66
67         /* Fall back to type 0 */
68         return 0;
69 }
70
71 static inline void pci_exp_set_dev_base(unsigned int base, int bus, int devfn)
72 {
73         u32 dev_base = base | (bus << 20) | (devfn << 12);
74         if (dev_base != mmcfg_last_accessed_device) {
75                 mmcfg_last_accessed_device = dev_base;
76                 set_fixmap_nocache(FIX_PCIE_MCFG, dev_base);
77         }
78 }
79
80 static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
81                           unsigned int devfn, int reg, int len, u32 *value)
82 {
83         unsigned long flags;
84         u32 base;
85
86         if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
87                 *value = -1;
88                 return -EINVAL;
89         }
90
91         base = get_base_addr(seg, bus, devfn);
92         if (!base)
93                 return pci_conf1_read(seg,bus,devfn,reg,len,value);
94
95         spin_lock_irqsave(&pci_config_lock, flags);
96
97         pci_exp_set_dev_base(base, bus, devfn);
98
99         switch (len) {
100         case 1:
101                 *value = readb(mmcfg_virt_addr + reg);
102                 break;
103         case 2:
104                 *value = readw(mmcfg_virt_addr + reg);
105                 break;
106         case 4:
107                 *value = readl(mmcfg_virt_addr + reg);
108                 break;
109         }
110
111         spin_unlock_irqrestore(&pci_config_lock, flags);
112
113         return 0;
114 }
115
116 static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
117                            unsigned int devfn, int reg, int len, u32 value)
118 {
119         unsigned long flags;
120         u32 base;
121
122         if ((bus > 255) || (devfn > 255) || (reg > 4095)) 
123                 return -EINVAL;
124
125         base = get_base_addr(seg, bus, devfn);
126         if (!base)
127                 return pci_conf1_write(seg,bus,devfn,reg,len,value);
128
129         spin_lock_irqsave(&pci_config_lock, flags);
130
131         pci_exp_set_dev_base(base, bus, devfn);
132
133         switch (len) {
134         case 1:
135                 writeb(value, mmcfg_virt_addr + reg);
136                 break;
137         case 2:
138                 writew(value, mmcfg_virt_addr + reg);
139                 break;
140         case 4:
141                 writel(value, mmcfg_virt_addr + reg);
142                 break;
143         }
144
145         spin_unlock_irqrestore(&pci_config_lock, flags);
146
147         return 0;
148 }
149
150 static struct pci_raw_ops pci_mmcfg = {
151         .read =         pci_mmcfg_read,
152         .write =        pci_mmcfg_write,
153 };
154
155 /* K8 systems have some devices (typically in the builtin northbridge)
156    that are only accessible using type1
157    Normally this can be expressed in the MCFG by not listing them
158    and assigning suitable _SEGs, but this isn't implemented in some BIOS.
159    Instead try to discover all devices on bus 0 that are unreachable using MM
160    and fallback for them. */
161 static __init void unreachable_devices(void)
162 {
163         int i, k;
164         unsigned long flags;
165
166         for (k = 0; k < MAX_CHECK_BUS; k++) {
167                 for (i = 0; i < 32; i++) {
168                         u32 val1;
169                         u32 addr;
170
171                         pci_conf1_read(0, k, PCI_DEVFN(i, 0), 0, 4, &val1);
172                         if (val1 == 0xffffffff)
173                                 continue;
174
175                         /* Locking probably not needed, but safer */
176                         spin_lock_irqsave(&pci_config_lock, flags);
177                         addr = get_base_addr(0, k, PCI_DEVFN(i, 0));
178                         if (addr != 0)
179                                 pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0));
180                         if (addr == 0 ||
181                             readl((u32 __iomem *)mmcfg_virt_addr) != val1) {
182                                 set_bit(i + 32*k, fallback_slots);
183                                 printk(KERN_NOTICE
184                         "PCI: No mmconfig possible on %x:%x\n", k, i);
185                         }
186                         spin_unlock_irqrestore(&pci_config_lock, flags);
187                 }
188         }
189 }
190
191 static int disable_mcfg(struct dmi_system_id *d)
192 {
193         printk("PCI: %s detected. Disabling MCFG.\n", d->ident);
194         pci_probe &= ~PCI_PROBE_MMCONF;
195         return 0;
196 }
197
198 static struct dmi_system_id __initdata dmi_bad_mcfg[] = {
199         /* Has broken MCFG table that makes the system hang when used */
200         {
201          .callback = disable_mcfg,
202          .ident = "Intel D3C5105 SDV",
203          .matches = {
204                      DMI_MATCH(DMI_BIOS_VENDOR, "Intel"),
205                      DMI_MATCH(DMI_BOARD_NAME, "D26928"),
206                      },
207          },
208          {}
209 };
210
211 void __init pci_mmcfg_init(void)
212 {
213         dmi_check_system(dmi_bad_mcfg);
214
215         if ((pci_probe & (PCI_PROBE_MMCONF_FORCE|PCI_PROBE_MMCONF)) == 0)
216                 return;
217
218         acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
219         if ((pci_mmcfg_config_num == 0) ||
220             (pci_mmcfg_config == NULL) ||
221             (pci_mmcfg_config[0].base_address == 0))
222                 return;
223
224         printk(KERN_INFO "PCI: Using MMCONFIG\n");
225         raw_pci_ops = &pci_mmcfg;
226         pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
227
228         unreachable_devices();
229 }