blob: a491f72cc96663a79bf26a5e8f642cbab55dac26 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Firmware replacement code.
3 *
4 * Work around broken BIOSes that don't set an aperture or only set the
5 * aperture in the AGP bridge.
6 * If all fails map the aperture over some low memory. This is cheaper than
7 * doing bounce buffering. The memory is lost. This is done at early boot
8 * because only the bootmem allocator can allocate 32+MB.
9 *
10 * Copyright 2002 Andi Kleen, SuSE Labs.
11 * $Id: aperture.c,v 1.7 2003/08/01 03:36:18 ak Exp $
12 */
13#include <linux/config.h>
14#include <linux/kernel.h>
15#include <linux/types.h>
16#include <linux/init.h>
17#include <linux/bootmem.h>
18#include <linux/mmzone.h>
19#include <linux/pci_ids.h>
20#include <linux/pci.h>
21#include <linux/bitops.h>
22#include <asm/e820.h>
23#include <asm/io.h>
24#include <asm/proto.h>
25#include <asm/pci-direct.h>
26
27int iommu_aperture;
28int iommu_aperture_disabled __initdata = 0;
29int iommu_aperture_allowed __initdata = 0;
30
31int fallback_aper_order __initdata = 1; /* 64MB */
32int fallback_aper_force __initdata = 0;
33
34int fix_aperture __initdata = 1;
35
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#define NB_ID_3 (PCI_VENDOR_ID_AMD | (0x1103<<16))
37
Andi Kleenece90302005-04-16 15:25:13 -070038static struct resource aper_res = {
39 .name = "Aperture",
40 .flags = IORESOURCE_MEM,
41};
42
Linus Torvalds1da177e2005-04-16 15:20:36 -070043static u32 __init allocate_aperture(void)
44{
45#ifdef CONFIG_DISCONTIGMEM
46 pg_data_t *nd0 = NODE_DATA(0);
47#else
48 pg_data_t *nd0 = &contig_page_data;
49#endif
50 u32 aper_size;
51 void *p;
52
53 if (fallback_aper_order > 7)
54 fallback_aper_order = 7;
55 aper_size = (32 * 1024 * 1024) << fallback_aper_order;
56
57 /*
Andi Kleenece90302005-04-16 15:25:13 -070058 * Aperture has to be naturally aligned. This means an 2GB
59 * aperture won't have much chances to find a place in the
60 * lower 4GB of memory. Unfortunately we cannot move it up
61 * because that would make the IOMMU useless.
Linus Torvalds1da177e2005-04-16 15:20:36 -070062 */
Andi Kleenece90302005-04-16 15:25:13 -070063
64 /* First try to find some free unused space */
65 if (!allocate_resource(&iomem_resource, &aper_res,
66 aper_size,
67 0, 0xffffffff,
68 aper_size,
69 NULL, NULL)) {
70 printk(KERN_INFO "Putting aperture at %lx-%lx\n",
71 aper_res.start, aper_res.end);
72 return aper_res.start;
73 }
74
75 /* No free space found. Go on to waste some memory... */
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 p = __alloc_bootmem_node(nd0, aper_size, aper_size, 0);
77 if (!p || __pa(p)+aper_size > 0xffffffff) {
78 printk("Cannot allocate aperture memory hole (%p,%uK)\n",
79 p, aper_size>>10);
80 if (p)
81 free_bootmem_node(nd0, (unsigned long)p, aper_size);
82 return 0;
83 }
Andi Kleenece90302005-04-16 15:25:13 -070084 printk("Mapping aperture over %d KB of precious RAM @ %lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 aper_size >> 10, __pa(p));
86 return (u32)__pa(p);
87}
88
89static int __init aperture_valid(char *name, u64 aper_base, u32 aper_size)
90{
91 if (!aper_base)
92 return 0;
93 if (aper_size < 64*1024*1024) {
94 printk("Aperture from %s too small (%d MB)\n", name, aper_size>>20);
95 return 0;
96 }
97 if (aper_base + aper_size >= 0xffffffff) {
98 printk("Aperture from %s beyond 4GB. Ignoring.\n",name);
99 return 0;
100 }
101 if (e820_mapped(aper_base, aper_base + aper_size, E820_RAM)) {
102 printk("Aperture from %s pointing to e820 RAM. Ignoring.\n",name);
103 return 0;
104 }
Andi Kleenece90302005-04-16 15:25:13 -0700105 /* Don't check the resource here because the aperture is usually
106 in an e820 reserved area, and we allocated these earlier. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 return 1;
108}
109
Andi Kleenece90302005-04-16 15:25:13 -0700110/*
111 * Find a PCI capability.
112 * This code runs before the PCI subsystem is initialized, so just
113 * access the northbridge directly.
114 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115static __u32 __init find_cap(int num, int slot, int func, int cap)
116{
117 u8 pos;
118 int bytes;
119 if (!(read_pci_config_16(num,slot,func,PCI_STATUS) & PCI_STATUS_CAP_LIST))
120 return 0;
121 pos = read_pci_config_byte(num,slot,func,PCI_CAPABILITY_LIST);
122 for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) {
123 u8 id;
124 pos &= ~3;
125 id = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_ID);
126 if (id == 0xff)
127 break;
128 if (id == cap)
129 return pos;
130 pos = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_NEXT);
131 }
132 return 0;
133}
134
135/* Read a standard AGPv3 bridge header */
136static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order)
137{
138 u32 apsize;
139 u32 apsizereg;
140 int nbits;
141 u32 aper_low, aper_hi;
142 u64 aper;
143
144 printk("AGP bridge at %02x:%02x:%02x\n", num, slot, func);
145 apsizereg = read_pci_config_16(num,slot,func, cap + 0x14);
146 if (apsizereg == 0xffffffff) {
147 printk("APSIZE in AGP bridge unreadable\n");
148 return 0;
149 }
150
151 apsize = apsizereg & 0xfff;
152 /* Some BIOS use weird encodings not in the AGPv3 table. */
153 if (apsize & 0xff)
154 apsize |= 0xf00;
155 nbits = hweight16(apsize);
156 *order = 7 - nbits;
157 if ((int)*order < 0) /* < 32MB */
158 *order = 0;
159
160 aper_low = read_pci_config(num,slot,func, 0x10);
161 aper_hi = read_pci_config(num,slot,func,0x14);
162 aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32);
163
164 printk("Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n",
165 aper, 32 << *order, apsizereg);
166
167 if (!aperture_valid("AGP bridge", aper, (32*1024*1024) << *order))
168 return 0;
169 return (u32)aper;
170}
171
172/* Look for an AGP bridge. Windows only expects the aperture in the
173 AGP bridge and some BIOS forget to initialize the Northbridge too.
174 Work around this here.
175
176 Do an PCI bus scan by hand because we're running before the PCI
177 subsystem.
178
179 All K8 AGP bridges are AGPv3 compliant, so we can do this scan
180 generically. It's probably overkill to always scan all slots because
181 the AGP bridges should be always an own bus on the HT hierarchy,
182 but do it here for future safety. */
183static __u32 __init search_agp_bridge(u32 *order, int *valid_agp)
184{
185 int num, slot, func;
186
187 /* Poor man's PCI discovery */
188 for (num = 0; num < 32; num++) {
189 for (slot = 0; slot < 32; slot++) {
190 for (func = 0; func < 8; func++) {
191 u32 class, cap;
192 u8 type;
193 class = read_pci_config(num,slot,func,
194 PCI_CLASS_REVISION);
195 if (class == 0xffffffff)
196 break;
197
198 switch (class >> 16) {
199 case PCI_CLASS_BRIDGE_HOST:
200 case PCI_CLASS_BRIDGE_OTHER: /* needed? */
201 /* AGP bridge? */
202 cap = find_cap(num,slot,func,PCI_CAP_ID_AGP);
203 if (!cap)
204 break;
205 *valid_agp = 1;
206 return read_agp(num,slot,func,cap,order);
207 }
208
209 /* No multi-function device? */
210 type = read_pci_config_byte(num,slot,func,
211 PCI_HEADER_TYPE);
212 if (!(type & 0x80))
213 break;
214 }
215 }
216 }
217 printk("No AGP bridge found\n");
218 return 0;
219}
220
221void __init iommu_hole_init(void)
222{
223 int fix, num;
224 u32 aper_size, aper_alloc = 0, aper_order, last_aper_order = 0;
225 u64 aper_base, last_aper_base = 0;
226 int valid_agp = 0;
227
228 if (iommu_aperture_disabled || !fix_aperture)
229 return;
230
231 printk("Checking aperture...\n");
232
233 fix = 0;
234 for (num = 24; num < 32; num++) {
235 char name[30];
236 if (read_pci_config(0, num, 3, 0x00) != NB_ID_3)
237 continue;
238
239 iommu_aperture = 1;
240
241 aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7;
242 aper_size = (32 * 1024 * 1024) << aper_order;
243 aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff;
244 aper_base <<= 25;
245
246 printk("CPU %d: aperture @ %Lx size %u MB\n", num-24,
247 aper_base, aper_size>>20);
248
249 sprintf(name, "northbridge cpu %d", num-24);
250
251 if (!aperture_valid(name, aper_base, aper_size)) {
252 fix = 1;
253 break;
254 }
255
256 if ((last_aper_order && aper_order != last_aper_order) ||
257 (last_aper_base && aper_base != last_aper_base)) {
258 fix = 1;
259 break;
260 }
261 last_aper_order = aper_order;
262 last_aper_base = aper_base;
263 }
264
265 if (!fix && !fallback_aper_force)
266 return;
267
268 if (!fallback_aper_force)
269 aper_alloc = search_agp_bridge(&aper_order, &valid_agp);
270
271 if (aper_alloc) {
272 /* Got the aperture from the AGP bridge */
273 } else if ((!no_iommu && end_pfn >= 0xffffffff>>PAGE_SHIFT) ||
274 force_iommu ||
275 valid_agp ||
276 fallback_aper_force) {
277 printk("Your BIOS doesn't leave a aperture memory hole\n");
278 printk("Please enable the IOMMU option in the BIOS setup\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
280 aper_order = fallback_aper_order;
281 aper_alloc = allocate_aperture();
282 if (!aper_alloc) {
283 /* Could disable AGP and IOMMU here, but it's probably
284 not worth it. But the later users cannot deal with
285 bad apertures and turning on the aperture over memory
286 causes very strange problems, so it's better to
287 panic early. */
288 panic("Not enough memory for aperture");
289 }
290 } else {
291 return;
292 }
293
294 /* Fix up the north bridges */
295 for (num = 24; num < 32; num++) {
296 if (read_pci_config(0, num, 3, 0x00) != NB_ID_3)
297 continue;
298
299 /* Don't enable translation yet. That is done later.
300 Assume this BIOS didn't initialise the GART so
301 just overwrite all previous bits */
302 write_pci_config(0, num, 3, 0x90, aper_order<<1);
303 write_pci_config(0, num, 3, 0x94, aper_alloc>>25);
304 }
305}