OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [x86/] [kernel/] [aperture_64.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
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
 */
12
#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 <linux/ioport.h>
21
#include <asm/e820.h>
22
#include <asm/io.h>
23
#include <asm/gart.h>
24
#include <asm/pci-direct.h>
25
#include <asm/dma.h>
26
#include <asm/k8.h>
27
 
28
int gart_iommu_aperture;
29
int gart_iommu_aperture_disabled __initdata = 0;
30
int gart_iommu_aperture_allowed __initdata = 0;
31
 
32
int fallback_aper_order __initdata = 1; /* 64MB */
33
int fallback_aper_force __initdata = 0;
34
 
35
int fix_aperture __initdata = 1;
36
 
37
static struct resource gart_resource = {
38
        .name   = "GART",
39
        .flags  = IORESOURCE_MEM,
40
};
41
 
42
static void __init insert_aperture_resource(u32 aper_base, u32 aper_size)
43
{
44
        gart_resource.start = aper_base;
45
        gart_resource.end = aper_base + aper_size - 1;
46
        insert_resource(&iomem_resource, &gart_resource);
47
}
48
 
49
/* This code runs before the PCI subsystem is initialized, so just
50
   access the northbridge directly. */
51
 
52
static u32 __init allocate_aperture(void)
53
{
54
        u32 aper_size;
55
        void *p;
56
 
57
        if (fallback_aper_order > 7)
58
                fallback_aper_order = 7;
59
        aper_size = (32 * 1024 * 1024) << fallback_aper_order;
60
 
61
        /*
62
         * Aperture has to be naturally aligned. This means an 2GB aperture won't
63
         * have much chance of finding a place in the lower 4GB of memory.
64
         * Unfortunately we cannot move it up because that would make the
65
         * IOMMU useless.
66
         */
67
        p = __alloc_bootmem_nopanic(aper_size, aper_size, 0);
68
        if (!p || __pa(p)+aper_size > 0xffffffff) {
69
                printk("Cannot allocate aperture memory hole (%p,%uK)\n",
70
                       p, aper_size>>10);
71
                if (p)
72
                        free_bootmem(__pa(p), aper_size);
73
                return 0;
74
        }
75
        printk("Mapping aperture over %d KB of RAM @ %lx\n",
76
               aper_size >> 10, __pa(p));
77
        insert_aperture_resource((u32)__pa(p), aper_size);
78
        return (u32)__pa(p);
79
}
80
 
81
static int __init aperture_valid(u64 aper_base, u32 aper_size)
82
{
83
        if (!aper_base)
84
                return 0;
85
        if (aper_size < 64*1024*1024) {
86
                printk("Aperture too small (%d MB)\n", aper_size>>20);
87
                return 0;
88
        }
89
        if (aper_base + aper_size > 0x100000000UL) {
90
                printk("Aperture beyond 4GB. Ignoring.\n");
91
                return 0;
92
        }
93
        if (e820_any_mapped(aper_base, aper_base + aper_size, E820_RAM)) {
94
                printk("Aperture pointing to e820 RAM. Ignoring.\n");
95
                return 0;
96
        }
97
        return 1;
98
}
99
 
100
/* Find a PCI capability */
101
static __u32 __init find_cap(int num, int slot, int func, int cap)
102
{
103
        u8 pos;
104
        int bytes;
105
        if (!(read_pci_config_16(num,slot,func,PCI_STATUS) & PCI_STATUS_CAP_LIST))
106
                return 0;
107
        pos = read_pci_config_byte(num,slot,func,PCI_CAPABILITY_LIST);
108
        for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) {
109
                u8 id;
110
                pos &= ~3;
111
                id = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_ID);
112
                if (id == 0xff)
113
                        break;
114
                if (id == cap)
115
                        return pos;
116
                pos = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_NEXT);
117
        }
118
        return 0;
119
}
120
 
121
/* Read a standard AGPv3 bridge header */
122
static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order)
123
{
124
        u32 apsize;
125
        u32 apsizereg;
126
        int nbits;
127
        u32 aper_low, aper_hi;
128
        u64 aper;
129
 
130
        printk("AGP bridge at %02x:%02x:%02x\n", num, slot, func);
131
        apsizereg = read_pci_config_16(num,slot,func, cap + 0x14);
132
        if (apsizereg == 0xffffffff) {
133
                printk("APSIZE in AGP bridge unreadable\n");
134
                return 0;
135
        }
136
 
137
        apsize = apsizereg & 0xfff;
138
        /* Some BIOS use weird encodings not in the AGPv3 table. */
139
        if (apsize & 0xff)
140
                apsize |= 0xf00;
141
        nbits = hweight16(apsize);
142
        *order = 7 - nbits;
143
        if ((int)*order < 0) /* < 32MB */
144
                *order = 0;
145
 
146
        aper_low = read_pci_config(num,slot,func, 0x10);
147
        aper_hi = read_pci_config(num,slot,func,0x14);
148
        aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32);
149
 
150
        printk("Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n",
151
               aper, 32 << *order, apsizereg);
152
 
153
        if (!aperture_valid(aper, (32*1024*1024) << *order))
154
            return 0;
155
        return (u32)aper;
156
}
157
 
158
/* Look for an AGP bridge. Windows only expects the aperture in the
159
   AGP bridge and some BIOS forget to initialize the Northbridge too.
160
   Work around this here.
161
 
162
   Do an PCI bus scan by hand because we're running before the PCI
163
   subsystem.
164
 
165
   All K8 AGP bridges are AGPv3 compliant, so we can do this scan
166
   generically. It's probably overkill to always scan all slots because
167
   the AGP bridges should be always an own bus on the HT hierarchy,
168
   but do it here for future safety. */
169
static __u32 __init search_agp_bridge(u32 *order, int *valid_agp)
170
{
171
        int num, slot, func;
172
 
173
        /* Poor man's PCI discovery */
174
        for (num = 0; num < 256; num++) {
175
                for (slot = 0; slot < 32; slot++) {
176
                        for (func = 0; func < 8; func++) {
177
                                u32 class, cap;
178
                                u8 type;
179
                                class = read_pci_config(num,slot,func,
180
                                                        PCI_CLASS_REVISION);
181
                                if (class == 0xffffffff)
182
                                        break;
183
 
184
                                switch (class >> 16) {
185
                                case PCI_CLASS_BRIDGE_HOST:
186
                                case PCI_CLASS_BRIDGE_OTHER: /* needed? */
187
                                        /* AGP bridge? */
188
                                        cap = find_cap(num,slot,func,PCI_CAP_ID_AGP);
189
                                        if (!cap)
190
                                                break;
191
                                        *valid_agp = 1;
192
                                        return read_agp(num,slot,func,cap,order);
193
                                }
194
 
195
                                /* No multi-function device? */
196
                                type = read_pci_config_byte(num,slot,func,
197
                                                               PCI_HEADER_TYPE);
198
                                if (!(type & 0x80))
199
                                        break;
200
                        }
201
                }
202
        }
203
        printk("No AGP bridge found\n");
204
        return 0;
205
}
206
 
207
void __init gart_iommu_hole_init(void)
208
{
209
        int fix, num;
210
        u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0;
211
        u64 aper_base, last_aper_base = 0;
212
        int valid_agp = 0;
213
 
214
        if (gart_iommu_aperture_disabled || !fix_aperture ||
215
            !early_pci_allowed())
216
                return;
217
 
218
        printk(KERN_INFO  "Checking aperture...\n");
219
 
220
        fix = 0;
221
        for (num = 24; num < 32; num++) {
222
                if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00)))
223
                        continue;
224
 
225
                iommu_detected = 1;
226
                gart_iommu_aperture = 1;
227
 
228
                aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7;
229
                aper_size = (32 * 1024 * 1024) << aper_order;
230
                aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff;
231
                aper_base <<= 25;
232
 
233
                printk("CPU %d: aperture @ %Lx size %u MB\n", num-24,
234
                       aper_base, aper_size>>20);
235
 
236
                if (!aperture_valid(aper_base, aper_size)) {
237
                        fix = 1;
238
                        break;
239
                }
240
 
241
                if ((last_aper_order && aper_order != last_aper_order) ||
242
                    (last_aper_base && aper_base != last_aper_base)) {
243
                        fix = 1;
244
                        break;
245
                }
246
                last_aper_order = aper_order;
247
                last_aper_base = aper_base;
248
        }
249
 
250
        if (!fix && !fallback_aper_force) {
251
                if (last_aper_base) {
252
                        unsigned long n = (32 * 1024 * 1024) << last_aper_order;
253
                        insert_aperture_resource((u32)last_aper_base, n);
254
                }
255
                return;
256
        }
257
 
258
        if (!fallback_aper_force)
259
                aper_alloc = search_agp_bridge(&aper_order, &valid_agp);
260
 
261
        if (aper_alloc) {
262
                /* Got the aperture from the AGP bridge */
263
        } else if (swiotlb && !valid_agp) {
264
                /* Do nothing */
265
        } else if ((!no_iommu && end_pfn > MAX_DMA32_PFN) ||
266
                   force_iommu ||
267
                   valid_agp ||
268
                   fallback_aper_force) {
269
                printk("Your BIOS doesn't leave a aperture memory hole\n");
270
                printk("Please enable the IOMMU option in the BIOS setup\n");
271
                printk("This costs you %d MB of RAM\n",
272
                       32 << fallback_aper_order);
273
 
274
                aper_order = fallback_aper_order;
275
                aper_alloc = allocate_aperture();
276
                if (!aper_alloc) {
277
                        /* Could disable AGP and IOMMU here, but it's probably
278
                           not worth it. But the later users cannot deal with
279
                           bad apertures and turning on the aperture over memory
280
                           causes very strange problems, so it's better to
281
                           panic early. */
282
                        panic("Not enough memory for aperture");
283
                }
284
        } else {
285
                return;
286
        }
287
 
288
        /* Fix up the north bridges */
289
        for (num = 24; num < 32; num++) {
290
                if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00)))
291
                        continue;
292
 
293
                /* Don't enable translation yet. That is done later.
294
                   Assume this BIOS didn't initialise the GART so
295
                   just overwrite all previous bits */
296
                write_pci_config(0, num, 3, 0x90, aper_order<<1);
297
                write_pci_config(0, num, 3, 0x94, aper_alloc>>25);
298
        }
299
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.