blob: a7ad03ee98cf5e3fb6c5e8f072ac17c75f20e7b9 [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>
Andi Kleenca8642f2006-01-11 22:44:27 +010026#include <asm/dma.h>
Andi Kleena32073b2006-06-26 13:56:40 +020027#include <asm/k8.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
29int iommu_aperture;
30int iommu_aperture_disabled __initdata = 0;
31int iommu_aperture_allowed __initdata = 0;
32
33int fallback_aper_order __initdata = 1; /* 64MB */
34int fallback_aper_force __initdata = 0;
35
36int fix_aperture __initdata = 1;
37
Andrew Morton42442ed2005-06-08 15:49:25 -070038/* This code runs before the PCI subsystem is initialized, so just
39 access the northbridge directly. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
41static u32 __init allocate_aperture(void)
42{
Linus Torvalds1da177e2005-04-16 15:20:36 -070043 pg_data_t *nd0 = NODE_DATA(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 u32 aper_size;
45 void *p;
46
47 if (fallback_aper_order > 7)
48 fallback_aper_order = 7;
49 aper_size = (32 * 1024 * 1024) << fallback_aper_order;
50
51 /*
Andrew Morton42442ed2005-06-08 15:49:25 -070052 * Aperture has to be naturally aligned. This means an 2GB aperture won't
53 * have much chances to find a place in the lower 4GB of memory.
54 * Unfortunately we cannot move it up because that would make the
55 * IOMMU useless.
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 */
57 p = __alloc_bootmem_node(nd0, aper_size, aper_size, 0);
58 if (!p || __pa(p)+aper_size > 0xffffffff) {
59 printk("Cannot allocate aperture memory hole (%p,%uK)\n",
60 p, aper_size>>10);
61 if (p)
Jon Masonc912c2d2006-03-25 16:31:19 +010062 free_bootmem_node(nd0, __pa(p), aper_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 return 0;
64 }
Andrew Morton42442ed2005-06-08 15:49:25 -070065 printk("Mapping aperture over %d KB of RAM @ %lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 aper_size >> 10, __pa(p));
67 return (u32)__pa(p);
68}
69
Andi Kleena32073b2006-06-26 13:56:40 +020070static int __init aperture_valid(u64 aper_base, u32 aper_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -070071{
72 if (!aper_base)
73 return 0;
74 if (aper_size < 64*1024*1024) {
Andi Kleena32073b2006-06-26 13:56:40 +020075 printk("Aperture too small (%d MB)\n", aper_size>>20);
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 return 0;
77 }
78 if (aper_base + aper_size >= 0xffffffff) {
Andi Kleena32073b2006-06-26 13:56:40 +020079 printk("Aperture beyond 4GB. Ignoring.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 return 0;
81 }
Arjan van de Veneee5a9f2006-04-07 19:49:24 +020082 if (e820_any_mapped(aper_base, aper_base + aper_size, E820_RAM)) {
Andi Kleena32073b2006-06-26 13:56:40 +020083 printk("Aperture pointing to e820 RAM. Ignoring.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 return 0;
85 }
86 return 1;
87}
88
Andrew Morton42442ed2005-06-08 15:49:25 -070089/* Find a PCI capability */
Linus Torvalds1da177e2005-04-16 15:20:36 -070090static __u32 __init find_cap(int num, int slot, int func, int cap)
91{
92 u8 pos;
93 int bytes;
94 if (!(read_pci_config_16(num,slot,func,PCI_STATUS) & PCI_STATUS_CAP_LIST))
95 return 0;
96 pos = read_pci_config_byte(num,slot,func,PCI_CAPABILITY_LIST);
97 for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) {
98 u8 id;
99 pos &= ~3;
100 id = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_ID);
101 if (id == 0xff)
102 break;
103 if (id == cap)
104 return pos;
105 pos = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_NEXT);
106 }
107 return 0;
108}
109
110/* Read a standard AGPv3 bridge header */
111static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order)
112{
113 u32 apsize;
114 u32 apsizereg;
115 int nbits;
116 u32 aper_low, aper_hi;
117 u64 aper;
118
119 printk("AGP bridge at %02x:%02x:%02x\n", num, slot, func);
120 apsizereg = read_pci_config_16(num,slot,func, cap + 0x14);
121 if (apsizereg == 0xffffffff) {
122 printk("APSIZE in AGP bridge unreadable\n");
123 return 0;
124 }
125
126 apsize = apsizereg & 0xfff;
127 /* Some BIOS use weird encodings not in the AGPv3 table. */
128 if (apsize & 0xff)
129 apsize |= 0xf00;
130 nbits = hweight16(apsize);
131 *order = 7 - nbits;
132 if ((int)*order < 0) /* < 32MB */
133 *order = 0;
134
135 aper_low = read_pci_config(num,slot,func, 0x10);
136 aper_hi = read_pci_config(num,slot,func,0x14);
137 aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32);
138
139 printk("Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n",
140 aper, 32 << *order, apsizereg);
141
Andi Kleena32073b2006-06-26 13:56:40 +0200142 if (!aperture_valid(aper, (32*1024*1024) << *order))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143 return 0;
144 return (u32)aper;
145}
146
147/* Look for an AGP bridge. Windows only expects the aperture in the
148 AGP bridge and some BIOS forget to initialize the Northbridge too.
149 Work around this here.
150
151 Do an PCI bus scan by hand because we're running before the PCI
152 subsystem.
153
154 All K8 AGP bridges are AGPv3 compliant, so we can do this scan
155 generically. It's probably overkill to always scan all slots because
156 the AGP bridges should be always an own bus on the HT hierarchy,
157 but do it here for future safety. */
158static __u32 __init search_agp_bridge(u32 *order, int *valid_agp)
159{
160 int num, slot, func;
161
162 /* Poor man's PCI discovery */
Navin Boppuri9c01dda2006-03-25 16:31:40 +0100163 for (num = 0; num < 256; num++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 for (slot = 0; slot < 32; slot++) {
165 for (func = 0; func < 8; func++) {
166 u32 class, cap;
167 u8 type;
168 class = read_pci_config(num,slot,func,
169 PCI_CLASS_REVISION);
170 if (class == 0xffffffff)
171 break;
172
173 switch (class >> 16) {
174 case PCI_CLASS_BRIDGE_HOST:
175 case PCI_CLASS_BRIDGE_OTHER: /* needed? */
176 /* AGP bridge? */
177 cap = find_cap(num,slot,func,PCI_CAP_ID_AGP);
178 if (!cap)
179 break;
180 *valid_agp = 1;
181 return read_agp(num,slot,func,cap,order);
182 }
183
184 /* No multi-function device? */
185 type = read_pci_config_byte(num,slot,func,
186 PCI_HEADER_TYPE);
187 if (!(type & 0x80))
188 break;
189 }
190 }
191 }
192 printk("No AGP bridge found\n");
193 return 0;
194}
195
196void __init iommu_hole_init(void)
197{
198 int fix, num;
Andi Kleen50895c52005-11-05 17:25:53 +0100199 u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 u64 aper_base, last_aper_base = 0;
201 int valid_agp = 0;
202
203 if (iommu_aperture_disabled || !fix_aperture)
204 return;
205
206 printk("Checking aperture...\n");
207
208 fix = 0;
209 for (num = 24; num < 32; num++) {
Andi Kleena32073b2006-06-26 13:56:40 +0200210 if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00)))
211 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212
213 iommu_aperture = 1;
214
215 aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7;
216 aper_size = (32 * 1024 * 1024) << aper_order;
217 aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff;
218 aper_base <<= 25;
219
220 printk("CPU %d: aperture @ %Lx size %u MB\n", num-24,
221 aper_base, aper_size>>20);
222
Andi Kleena32073b2006-06-26 13:56:40 +0200223 if (!aperture_valid(aper_base, aper_size)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 fix = 1;
225 break;
226 }
227
228 if ((last_aper_order && aper_order != last_aper_order) ||
229 (last_aper_base && aper_base != last_aper_base)) {
230 fix = 1;
231 break;
232 }
233 last_aper_order = aper_order;
234 last_aper_base = aper_base;
235 }
236
237 if (!fix && !fallback_aper_force)
238 return;
239
240 if (!fallback_aper_force)
241 aper_alloc = search_agp_bridge(&aper_order, &valid_agp);
242
243 if (aper_alloc) {
244 /* Got the aperture from the AGP bridge */
Andi Kleen63f02fd2005-09-12 18:49:24 +0200245 } else if (swiotlb && !valid_agp) {
246 /* Do nothing */
Jon Mason60b08c62006-02-26 04:18:22 +0100247 } else if ((!no_iommu && end_pfn > MAX_DMA32_PFN) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 force_iommu ||
249 valid_agp ||
250 fallback_aper_force) {
251 printk("Your BIOS doesn't leave a aperture memory hole\n");
252 printk("Please enable the IOMMU option in the BIOS setup\n");
Andrew Morton42442ed2005-06-08 15:49:25 -0700253 printk("This costs you %d MB of RAM\n",
254 32 << fallback_aper_order);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255
256 aper_order = fallback_aper_order;
257 aper_alloc = allocate_aperture();
258 if (!aper_alloc) {
259 /* Could disable AGP and IOMMU here, but it's probably
260 not worth it. But the later users cannot deal with
261 bad apertures and turning on the aperture over memory
262 causes very strange problems, so it's better to
263 panic early. */
264 panic("Not enough memory for aperture");
265 }
266 } else {
267 return;
268 }
269
270 /* Fix up the north bridges */
271 for (num = 24; num < 32; num++) {
Andi Kleena32073b2006-06-26 13:56:40 +0200272 if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 continue;
274
275 /* Don't enable translation yet. That is done later.
276 Assume this BIOS didn't initialise the GART so
277 just overwrite all previous bits */
278 write_pci_config(0, num, 3, 0x90, aper_order<<1);
279 write_pci_config(0, num, 3, 0x94, aper_alloc>>25);
280 }
281}