blob: 58af8e73738bd5cf51dc9b0a7884bb0fbb66d154 [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.
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012#include <linux/kernel.h>
13#include <linux/types.h>
14#include <linux/init.h>
15#include <linux/bootmem.h>
16#include <linux/mmzone.h>
17#include <linux/pci_ids.h>
18#include <linux/pci.h>
19#include <linux/bitops.h>
20#include <asm/e820.h>
21#include <asm/io.h>
22#include <asm/proto.h>
23#include <asm/pci-direct.h>
Andi Kleenca8642f2006-01-11 22:44:27 +010024#include <asm/dma.h>
Andi Kleena32073b2006-06-26 13:56:40 +020025#include <asm/k8.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026
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
Andrew Morton42442ed2005-06-08 15:49:25 -070036/* This code runs before the PCI subsystem is initialized, so just
37 access the northbridge directly. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070038
39static u32 __init allocate_aperture(void)
40{
Linus Torvalds1da177e2005-04-16 15:20:36 -070041 pg_data_t *nd0 = NODE_DATA(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070042 u32 aper_size;
43 void *p;
44
45 if (fallback_aper_order > 7)
46 fallback_aper_order = 7;
47 aper_size = (32 * 1024 * 1024) << fallback_aper_order;
48
49 /*
Andrew Morton42442ed2005-06-08 15:49:25 -070050 * Aperture has to be naturally aligned. This means an 2GB aperture won't
51 * have much chances to find a place in the lower 4GB of memory.
52 * Unfortunately we cannot move it up because that would make the
53 * IOMMU useless.
Linus Torvalds1da177e2005-04-16 15:20:36 -070054 */
55 p = __alloc_bootmem_node(nd0, aper_size, aper_size, 0);
56 if (!p || __pa(p)+aper_size > 0xffffffff) {
57 printk("Cannot allocate aperture memory hole (%p,%uK)\n",
58 p, aper_size>>10);
59 if (p)
Jon Masonc912c2d2006-03-25 16:31:19 +010060 free_bootmem_node(nd0, __pa(p), aper_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 return 0;
62 }
Andrew Morton42442ed2005-06-08 15:49:25 -070063 printk("Mapping aperture over %d KB of RAM @ %lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 aper_size >> 10, __pa(p));
65 return (u32)__pa(p);
66}
67
Andi Kleena32073b2006-06-26 13:56:40 +020068static int __init aperture_valid(u64 aper_base, u32 aper_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -070069{
70 if (!aper_base)
71 return 0;
72 if (aper_size < 64*1024*1024) {
Andi Kleena32073b2006-06-26 13:56:40 +020073 printk("Aperture too small (%d MB)\n", aper_size>>20);
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 return 0;
75 }
76 if (aper_base + aper_size >= 0xffffffff) {
Andi Kleena32073b2006-06-26 13:56:40 +020077 printk("Aperture beyond 4GB. Ignoring.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -070078 return 0;
79 }
Arjan van de Veneee5a9f2006-04-07 19:49:24 +020080 if (e820_any_mapped(aper_base, aper_base + aper_size, E820_RAM)) {
Andi Kleena32073b2006-06-26 13:56:40 +020081 printk("Aperture pointing to e820 RAM. Ignoring.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -070082 return 0;
83 }
84 return 1;
85}
86
Andrew Morton42442ed2005-06-08 15:49:25 -070087/* Find a PCI capability */
Linus Torvalds1da177e2005-04-16 15:20:36 -070088static __u32 __init find_cap(int num, int slot, int func, int cap)
89{
90 u8 pos;
91 int bytes;
92 if (!(read_pci_config_16(num,slot,func,PCI_STATUS) & PCI_STATUS_CAP_LIST))
93 return 0;
94 pos = read_pci_config_byte(num,slot,func,PCI_CAPABILITY_LIST);
95 for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) {
96 u8 id;
97 pos &= ~3;
98 id = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_ID);
99 if (id == 0xff)
100 break;
101 if (id == cap)
102 return pos;
103 pos = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_NEXT);
104 }
105 return 0;
106}
107
108/* Read a standard AGPv3 bridge header */
109static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order)
110{
111 u32 apsize;
112 u32 apsizereg;
113 int nbits;
114 u32 aper_low, aper_hi;
115 u64 aper;
116
117 printk("AGP bridge at %02x:%02x:%02x\n", num, slot, func);
118 apsizereg = read_pci_config_16(num,slot,func, cap + 0x14);
119 if (apsizereg == 0xffffffff) {
120 printk("APSIZE in AGP bridge unreadable\n");
121 return 0;
122 }
123
124 apsize = apsizereg & 0xfff;
125 /* Some BIOS use weird encodings not in the AGPv3 table. */
126 if (apsize & 0xff)
127 apsize |= 0xf00;
128 nbits = hweight16(apsize);
129 *order = 7 - nbits;
130 if ((int)*order < 0) /* < 32MB */
131 *order = 0;
132
133 aper_low = read_pci_config(num,slot,func, 0x10);
134 aper_hi = read_pci_config(num,slot,func,0x14);
135 aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32);
136
137 printk("Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n",
138 aper, 32 << *order, apsizereg);
139
Andi Kleena32073b2006-06-26 13:56:40 +0200140 if (!aperture_valid(aper, (32*1024*1024) << *order))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 return 0;
142 return (u32)aper;
143}
144
145/* Look for an AGP bridge. Windows only expects the aperture in the
146 AGP bridge and some BIOS forget to initialize the Northbridge too.
147 Work around this here.
148
149 Do an PCI bus scan by hand because we're running before the PCI
150 subsystem.
151
152 All K8 AGP bridges are AGPv3 compliant, so we can do this scan
153 generically. It's probably overkill to always scan all slots because
154 the AGP bridges should be always an own bus on the HT hierarchy,
155 but do it here for future safety. */
156static __u32 __init search_agp_bridge(u32 *order, int *valid_agp)
157{
158 int num, slot, func;
159
160 /* Poor man's PCI discovery */
Navin Boppuri9c01dda2006-03-25 16:31:40 +0100161 for (num = 0; num < 256; num++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 for (slot = 0; slot < 32; slot++) {
163 for (func = 0; func < 8; func++) {
164 u32 class, cap;
165 u8 type;
166 class = read_pci_config(num,slot,func,
167 PCI_CLASS_REVISION);
168 if (class == 0xffffffff)
169 break;
170
171 switch (class >> 16) {
172 case PCI_CLASS_BRIDGE_HOST:
173 case PCI_CLASS_BRIDGE_OTHER: /* needed? */
174 /* AGP bridge? */
175 cap = find_cap(num,slot,func,PCI_CAP_ID_AGP);
176 if (!cap)
177 break;
178 *valid_agp = 1;
179 return read_agp(num,slot,func,cap,order);
180 }
181
182 /* No multi-function device? */
183 type = read_pci_config_byte(num,slot,func,
184 PCI_HEADER_TYPE);
185 if (!(type & 0x80))
186 break;
187 }
188 }
189 }
190 printk("No AGP bridge found\n");
191 return 0;
192}
193
194void __init iommu_hole_init(void)
195{
196 int fix, num;
Andi Kleen50895c52005-11-05 17:25:53 +0100197 u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 u64 aper_base, last_aper_base = 0;
199 int valid_agp = 0;
200
201 if (iommu_aperture_disabled || !fix_aperture)
202 return;
203
204 printk("Checking aperture...\n");
205
206 fix = 0;
207 for (num = 24; num < 32; num++) {
Andi Kleena32073b2006-06-26 13:56:40 +0200208 if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00)))
209 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210
Jon Mason8d4f6b92006-06-26 13:58:05 +0200211 iommu_detected = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 iommu_aperture = 1;
213
214 aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7;
215 aper_size = (32 * 1024 * 1024) << aper_order;
216 aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff;
217 aper_base <<= 25;
218
219 printk("CPU %d: aperture @ %Lx size %u MB\n", num-24,
220 aper_base, aper_size>>20);
221
Andi Kleena32073b2006-06-26 13:56:40 +0200222 if (!aperture_valid(aper_base, aper_size)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 fix = 1;
224 break;
225 }
226
227 if ((last_aper_order && aper_order != last_aper_order) ||
228 (last_aper_base && aper_base != last_aper_base)) {
229 fix = 1;
230 break;
231 }
232 last_aper_order = aper_order;
233 last_aper_base = aper_base;
234 }
235
236 if (!fix && !fallback_aper_force)
237 return;
238
239 if (!fallback_aper_force)
240 aper_alloc = search_agp_bridge(&aper_order, &valid_agp);
241
242 if (aper_alloc) {
243 /* Got the aperture from the AGP bridge */
Andi Kleen63f02fd2005-09-12 18:49:24 +0200244 } else if (swiotlb && !valid_agp) {
245 /* Do nothing */
Jon Mason60b08c62006-02-26 04:18:22 +0100246 } else if ((!no_iommu && end_pfn > MAX_DMA32_PFN) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 force_iommu ||
248 valid_agp ||
249 fallback_aper_force) {
250 printk("Your BIOS doesn't leave a aperture memory hole\n");
251 printk("Please enable the IOMMU option in the BIOS setup\n");
Andrew Morton42442ed2005-06-08 15:49:25 -0700252 printk("This costs you %d MB of RAM\n",
253 32 << fallback_aper_order);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
255 aper_order = fallback_aper_order;
256 aper_alloc = allocate_aperture();
257 if (!aper_alloc) {
258 /* Could disable AGP and IOMMU here, but it's probably
259 not worth it. But the later users cannot deal with
260 bad apertures and turning on the aperture over memory
261 causes very strange problems, so it's better to
262 panic early. */
263 panic("Not enough memory for aperture");
264 }
265 } else {
266 return;
267 }
268
269 /* Fix up the north bridges */
270 for (num = 24; num < 32; num++) {
Andi Kleena32073b2006-06-26 13:56:40 +0200271 if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 continue;
273
274 /* Don't enable translation yet. That is done later.
275 Assume this BIOS didn't initialise the GART so
276 just overwrite all previous bits */
277 write_pci_config(0, num, 3, 0x90, aper_order<<1);
278 write_pci_config(0, num, 3, 0x94, aper_alloc>>25);
279 }
280}