Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/arch/arm/mach-integrator/pci_v3.c | |
3 | * | |
4 | * PCI functions for V3 host PCI bridge | |
5 | * | |
6 | * Copyright (C) 1999 ARM Limited | |
7 | * Copyright (C) 2000-2001 Deep Blue Solutions Ltd | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License as published by | |
11 | * the Free Software Foundation; either version 2 of the License, or | |
12 | * (at your option) any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with this program; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
22 | */ | |
1da177e4 LT |
23 | #include <linux/kernel.h> |
24 | #include <linux/pci.h> | |
1da177e4 LT |
25 | #include <linux/ioport.h> |
26 | #include <linux/interrupt.h> | |
27 | #include <linux/spinlock.h> | |
28 | #include <linux/init.h> | |
fced80c7 | 29 | #include <linux/io.h> |
86adc39f | 30 | #include <linux/platform_device.h> |
f55b2b56 LW |
31 | #include <linux/of.h> |
32 | #include <linux/of_address.h> | |
33 | #include <linux/of_irq.h> | |
34 | #include <linux/of_pci.h> | |
01ef3105 | 35 | #include <video/vga.h> |
1da177e4 | 36 | |
ae9daf2d | 37 | #include <asm/mach/map.h> |
d43c36dc | 38 | #include <asm/signal.h> |
1da177e4 | 39 | #include <asm/mach/pci.h> |
c6af66b9 | 40 | #include <asm/irq_regs.h> |
1da177e4 | 41 | |
ae9daf2d | 42 | #include "pci_v3.h" |
1b1ef755 | 43 | #include "hardware.h" |
ae9daf2d LW |
44 | |
45 | /* | |
46 | * Where in the memory map does PCI live? | |
47 | * | |
48 | * This represents a fairly liberal usage of address space. Even though | |
49 | * the V3 only has two windows (therefore we need to map stuff on the fly), | |
50 | * we maintain the same addresses, even if they're not mapped. | |
51 | */ | |
1eb92b24 LW |
52 | #define PHYS_PCI_MEM_BASE 0x40000000 /* 256M */ |
53 | #define PHYS_PCI_PRE_BASE 0x50000000 /* 256M */ | |
ae9daf2d LW |
54 | #define PHYS_PCI_IO_BASE 0x60000000 /* 16M */ |
55 | #define PHYS_PCI_CONFIG_BASE 0x61000000 /* 16M */ | |
56 | #define PHYS_PCI_V3_BASE 0x62000000 /* 64K */ | |
57 | ||
58 | #define PCI_MEMORY_VADDR IOMEM(0xe8000000) | |
59 | #define PCI_CONFIG_VADDR IOMEM(0xec000000) | |
60 | ||
207bcf45 LW |
61 | /* |
62 | * V3 Local Bus to PCI Bridge definitions | |
63 | * | |
64 | * Registers (these are taken from page 129 of the EPC User's Manual Rev 1.04 | |
65 | * All V3 register names are prefaced by V3_ to avoid clashing with any other | |
66 | * PCI definitions. Their names match the user's manual. | |
67 | * | |
68 | * I'm assuming that I20 is disabled. | |
69 | * | |
70 | */ | |
71 | #define V3_PCI_VENDOR 0x00000000 | |
72 | #define V3_PCI_DEVICE 0x00000002 | |
73 | #define V3_PCI_CMD 0x00000004 | |
74 | #define V3_PCI_STAT 0x00000006 | |
75 | #define V3_PCI_CC_REV 0x00000008 | |
76 | #define V3_PCI_HDR_CFG 0x0000000C | |
77 | #define V3_PCI_IO_BASE 0x00000010 | |
78 | #define V3_PCI_BASE0 0x00000014 | |
79 | #define V3_PCI_BASE1 0x00000018 | |
80 | #define V3_PCI_SUB_VENDOR 0x0000002C | |
81 | #define V3_PCI_SUB_ID 0x0000002E | |
82 | #define V3_PCI_ROM 0x00000030 | |
83 | #define V3_PCI_BPARAM 0x0000003C | |
84 | #define V3_PCI_MAP0 0x00000040 | |
85 | #define V3_PCI_MAP1 0x00000044 | |
86 | #define V3_PCI_INT_STAT 0x00000048 | |
87 | #define V3_PCI_INT_CFG 0x0000004C | |
88 | #define V3_LB_BASE0 0x00000054 | |
89 | #define V3_LB_BASE1 0x00000058 | |
90 | #define V3_LB_MAP0 0x0000005E | |
91 | #define V3_LB_MAP1 0x00000062 | |
92 | #define V3_LB_BASE2 0x00000064 | |
93 | #define V3_LB_MAP2 0x00000066 | |
94 | #define V3_LB_SIZE 0x00000068 | |
95 | #define V3_LB_IO_BASE 0x0000006E | |
96 | #define V3_FIFO_CFG 0x00000070 | |
97 | #define V3_FIFO_PRIORITY 0x00000072 | |
98 | #define V3_FIFO_STAT 0x00000074 | |
99 | #define V3_LB_ISTAT 0x00000076 | |
100 | #define V3_LB_IMASK 0x00000077 | |
101 | #define V3_SYSTEM 0x00000078 | |
102 | #define V3_LB_CFG 0x0000007A | |
103 | #define V3_PCI_CFG 0x0000007C | |
104 | #define V3_DMA_PCI_ADR0 0x00000080 | |
105 | #define V3_DMA_PCI_ADR1 0x00000090 | |
106 | #define V3_DMA_LOCAL_ADR0 0x00000084 | |
107 | #define V3_DMA_LOCAL_ADR1 0x00000094 | |
108 | #define V3_DMA_LENGTH0 0x00000088 | |
109 | #define V3_DMA_LENGTH1 0x00000098 | |
110 | #define V3_DMA_CSR0 0x0000008B | |
111 | #define V3_DMA_CSR1 0x0000009B | |
112 | #define V3_DMA_CTLB_ADR0 0x0000008C | |
113 | #define V3_DMA_CTLB_ADR1 0x0000009C | |
114 | #define V3_DMA_DELAY 0x000000E0 | |
115 | #define V3_MAIL_DATA 0x000000C0 | |
116 | #define V3_PCI_MAIL_IEWR 0x000000D0 | |
117 | #define V3_PCI_MAIL_IERD 0x000000D2 | |
118 | #define V3_LB_MAIL_IEWR 0x000000D4 | |
119 | #define V3_LB_MAIL_IERD 0x000000D6 | |
120 | #define V3_MAIL_WR_STAT 0x000000D8 | |
121 | #define V3_MAIL_RD_STAT 0x000000DA | |
122 | #define V3_QBA_MAP 0x000000DC | |
123 | ||
124 | /* PCI COMMAND REGISTER bits | |
125 | */ | |
126 | #define V3_COMMAND_M_FBB_EN (1 << 9) | |
127 | #define V3_COMMAND_M_SERR_EN (1 << 8) | |
128 | #define V3_COMMAND_M_PAR_EN (1 << 6) | |
129 | #define V3_COMMAND_M_MASTER_EN (1 << 2) | |
130 | #define V3_COMMAND_M_MEM_EN (1 << 1) | |
131 | #define V3_COMMAND_M_IO_EN (1 << 0) | |
132 | ||
133 | /* SYSTEM REGISTER bits | |
134 | */ | |
135 | #define V3_SYSTEM_M_RST_OUT (1 << 15) | |
136 | #define V3_SYSTEM_M_LOCK (1 << 14) | |
137 | ||
138 | /* PCI_CFG bits | |
139 | */ | |
140 | #define V3_PCI_CFG_M_I2O_EN (1 << 15) | |
141 | #define V3_PCI_CFG_M_IO_REG_DIS (1 << 14) | |
142 | #define V3_PCI_CFG_M_IO_DIS (1 << 13) | |
143 | #define V3_PCI_CFG_M_EN3V (1 << 12) | |
144 | #define V3_PCI_CFG_M_RETRY_EN (1 << 10) | |
145 | #define V3_PCI_CFG_M_AD_LOW1 (1 << 9) | |
146 | #define V3_PCI_CFG_M_AD_LOW0 (1 << 8) | |
147 | ||
148 | /* PCI_BASE register bits (PCI -> Local Bus) | |
149 | */ | |
150 | #define V3_PCI_BASE_M_ADR_BASE 0xFFF00000 | |
151 | #define V3_PCI_BASE_M_ADR_BASEL 0x000FFF00 | |
152 | #define V3_PCI_BASE_M_PREFETCH (1 << 3) | |
153 | #define V3_PCI_BASE_M_TYPE (3 << 1) | |
154 | #define V3_PCI_BASE_M_IO (1 << 0) | |
155 | ||
156 | /* PCI MAP register bits (PCI -> Local bus) | |
157 | */ | |
158 | #define V3_PCI_MAP_M_MAP_ADR 0xFFF00000 | |
159 | #define V3_PCI_MAP_M_RD_POST_INH (1 << 15) | |
160 | #define V3_PCI_MAP_M_ROM_SIZE (3 << 10) | |
161 | #define V3_PCI_MAP_M_SWAP (3 << 8) | |
162 | #define V3_PCI_MAP_M_ADR_SIZE 0x000000F0 | |
163 | #define V3_PCI_MAP_M_REG_EN (1 << 1) | |
164 | #define V3_PCI_MAP_M_ENABLE (1 << 0) | |
165 | ||
166 | /* | |
167 | * LB_BASE0,1 register bits (Local bus -> PCI) | |
168 | */ | |
169 | #define V3_LB_BASE_ADR_BASE 0xfff00000 | |
170 | #define V3_LB_BASE_SWAP (3 << 8) | |
171 | #define V3_LB_BASE_ADR_SIZE (15 << 4) | |
172 | #define V3_LB_BASE_PREFETCH (1 << 3) | |
173 | #define V3_LB_BASE_ENABLE (1 << 0) | |
174 | ||
175 | #define V3_LB_BASE_ADR_SIZE_1MB (0 << 4) | |
176 | #define V3_LB_BASE_ADR_SIZE_2MB (1 << 4) | |
177 | #define V3_LB_BASE_ADR_SIZE_4MB (2 << 4) | |
178 | #define V3_LB_BASE_ADR_SIZE_8MB (3 << 4) | |
179 | #define V3_LB_BASE_ADR_SIZE_16MB (4 << 4) | |
180 | #define V3_LB_BASE_ADR_SIZE_32MB (5 << 4) | |
181 | #define V3_LB_BASE_ADR_SIZE_64MB (6 << 4) | |
182 | #define V3_LB_BASE_ADR_SIZE_128MB (7 << 4) | |
183 | #define V3_LB_BASE_ADR_SIZE_256MB (8 << 4) | |
184 | #define V3_LB_BASE_ADR_SIZE_512MB (9 << 4) | |
185 | #define V3_LB_BASE_ADR_SIZE_1GB (10 << 4) | |
186 | #define V3_LB_BASE_ADR_SIZE_2GB (11 << 4) | |
187 | ||
188 | #define v3_addr_to_lb_base(a) ((a) & V3_LB_BASE_ADR_BASE) | |
189 | ||
190 | /* | |
191 | * LB_MAP0,1 register bits (Local bus -> PCI) | |
192 | */ | |
193 | #define V3_LB_MAP_MAP_ADR 0xfff0 | |
194 | #define V3_LB_MAP_TYPE (7 << 1) | |
195 | #define V3_LB_MAP_AD_LOW_EN (1 << 0) | |
196 | ||
197 | #define V3_LB_MAP_TYPE_IACK (0 << 1) | |
198 | #define V3_LB_MAP_TYPE_IO (1 << 1) | |
199 | #define V3_LB_MAP_TYPE_MEM (3 << 1) | |
200 | #define V3_LB_MAP_TYPE_CONFIG (5 << 1) | |
201 | #define V3_LB_MAP_TYPE_MEM_MULTIPLE (6 << 1) | |
202 | ||
203 | #define v3_addr_to_lb_map(a) (((a) >> 16) & V3_LB_MAP_MAP_ADR) | |
204 | ||
205 | /* | |
206 | * LB_BASE2 register bits (Local bus -> PCI IO) | |
207 | */ | |
208 | #define V3_LB_BASE2_ADR_BASE 0xff00 | |
209 | #define V3_LB_BASE2_SWAP (3 << 6) | |
210 | #define V3_LB_BASE2_ENABLE (1 << 0) | |
211 | ||
212 | #define v3_addr_to_lb_base2(a) (((a) >> 16) & V3_LB_BASE2_ADR_BASE) | |
213 | ||
214 | /* | |
215 | * LB_MAP2 register bits (Local bus -> PCI IO) | |
216 | */ | |
217 | #define V3_LB_MAP2_MAP_ADR 0xff00 | |
218 | ||
219 | #define v3_addr_to_lb_map2(a) (((a) >> 16) & V3_LB_MAP2_MAP_ADR) | |
1da177e4 LT |
220 | |
221 | /* | |
222 | * The V3 PCI interface chip in Integrator provides several windows from | |
223 | * local bus memory into the PCI memory areas. Unfortunately, there | |
29d39604 | 224 | * are not really enough windows for our usage, therefore we reuse |
1da177e4 LT |
225 | * one of the windows for access to PCI configuration space. The |
226 | * memory map is as follows: | |
29d39604 | 227 | * |
1da177e4 | 228 | * Local Bus Memory Usage |
29d39604 | 229 | * |
1da177e4 LT |
230 | * 40000000 - 4FFFFFFF PCI memory. 256M non-prefetchable |
231 | * 50000000 - 5FFFFFFF PCI memory. 256M prefetchable | |
232 | * 60000000 - 60FFFFFF PCI IO. 16M | |
233 | * 61000000 - 61FFFFFF PCI Configuration. 16M | |
29d39604 | 234 | * |
1da177e4 LT |
235 | * There are three V3 windows, each described by a pair of V3 registers. |
236 | * These are LB_BASE0/LB_MAP0, LB_BASE1/LB_MAP1 and LB_BASE2/LB_MAP2. | |
237 | * Base0 and Base1 can be used for any type of PCI memory access. Base2 | |
238 | * can be used either for PCI I/O or for I20 accesses. By default, uHAL | |
239 | * uses this only for PCI IO space. | |
29d39604 | 240 | * |
1da177e4 | 241 | * Normally these spaces are mapped using the following base registers: |
29d39604 | 242 | * |
1da177e4 | 243 | * Usage Local Bus Memory Base/Map registers used |
29d39604 | 244 | * |
1da177e4 LT |
245 | * Mem 40000000 - 4FFFFFFF LB_BASE0/LB_MAP0 |
246 | * Mem 50000000 - 5FFFFFFF LB_BASE1/LB_MAP1 | |
247 | * IO 60000000 - 60FFFFFF LB_BASE2/LB_MAP2 | |
248 | * Cfg 61000000 - 61FFFFFF | |
29d39604 | 249 | * |
1da177e4 | 250 | * This means that I20 and PCI configuration space accesses will fail. |
29d39604 | 251 | * When PCI configuration accesses are needed (via the uHAL PCI |
1da177e4 | 252 | * configuration space primitives) we must remap the spaces as follows: |
29d39604 | 253 | * |
1da177e4 | 254 | * Usage Local Bus Memory Base/Map registers used |
29d39604 | 255 | * |
1da177e4 LT |
256 | * Mem 40000000 - 4FFFFFFF LB_BASE0/LB_MAP0 |
257 | * Mem 50000000 - 5FFFFFFF LB_BASE0/LB_MAP0 | |
258 | * IO 60000000 - 60FFFFFF LB_BASE2/LB_MAP2 | |
259 | * Cfg 61000000 - 61FFFFFF LB_BASE1/LB_MAP1 | |
29d39604 | 260 | * |
1da177e4 | 261 | * To make this work, the code depends on overlapping windows working. |
29d39604 | 262 | * The V3 chip translates an address by checking its range within |
1da177e4 LT |
263 | * each of the BASE/MAP pairs in turn (in ascending register number |
264 | * order). It will use the first matching pair. So, for example, | |
265 | * if the same address is mapped by both LB_BASE0/LB_MAP0 and | |
29d39604 | 266 | * LB_BASE1/LB_MAP1, the V3 will use the translation from |
1da177e4 | 267 | * LB_BASE0/LB_MAP0. |
29d39604 | 268 | * |
1da177e4 LT |
269 | * To allow PCI Configuration space access, the code enlarges the |
270 | * window mapped by LB_BASE0/LB_MAP0 from 256M to 512M. This occludes | |
271 | * the windows currently mapped by LB_BASE1/LB_MAP1 so that it can | |
272 | * be remapped for use by configuration cycles. | |
29d39604 RH |
273 | * |
274 | * At the end of the PCI Configuration space accesses, | |
1da177e4 LT |
275 | * LB_BASE1/LB_MAP1 is reset to map PCI Memory. Finally the window |
276 | * mapped by LB_BASE0/LB_MAP0 is reduced in size from 512M to 256M to | |
277 | * reveal the now restored LB_BASE1/LB_MAP1 window. | |
29d39604 | 278 | * |
1da177e4 LT |
279 | * NOTE: We do not set up I2O mapping. I suspect that this is only |
280 | * for an intelligent (target) device. Using I2O disables most of | |
281 | * the mappings into PCI memory. | |
282 | */ | |
283 | ||
f55b2b56 | 284 | /* Filled in by probe */ |
a5ecbab7 | 285 | static void __iomem *pci_v3_base; |
1eb92b24 | 286 | /* CPU side memory ranges */ |
f55b2b56 LW |
287 | static struct resource conf_mem; /* FIXME: remap this instead of static map */ |
288 | static struct resource io_mem; | |
289 | static struct resource non_mem; | |
290 | static struct resource pre_mem; | |
1eb92b24 LW |
291 | /* PCI side memory ranges */ |
292 | static u64 non_mem_pci; | |
293 | static u64 non_mem_pci_sz; | |
294 | static u64 pre_mem_pci; | |
295 | static u64 pre_mem_pci_sz; | |
a5ecbab7 | 296 | |
1da177e4 | 297 | // V3 access routines |
a5ecbab7 LW |
298 | #define v3_writeb(o,v) __raw_writeb(v, pci_v3_base + (unsigned int)(o)) |
299 | #define v3_readb(o) (__raw_readb(pci_v3_base + (unsigned int)(o))) | |
1da177e4 | 300 | |
a5ecbab7 LW |
301 | #define v3_writew(o,v) __raw_writew(v, pci_v3_base + (unsigned int)(o)) |
302 | #define v3_readw(o) (__raw_readw(pci_v3_base + (unsigned int)(o))) | |
1da177e4 | 303 | |
a5ecbab7 LW |
304 | #define v3_writel(o,v) __raw_writel(v, pci_v3_base + (unsigned int)(o)) |
305 | #define v3_readl(o) (__raw_readl(pci_v3_base + (unsigned int)(o))) | |
1da177e4 LT |
306 | |
307 | /*============================================================================ | |
308 | * | |
309 | * routine: uHALir_PCIMakeConfigAddress() | |
310 | * | |
311 | * parameters: bus = which bus | |
312 | * device = which device | |
313 | * function = which function | |
314 | * offset = configuration space register we are interested in | |
315 | * | |
316 | * description: this routine will generate a platform dependent config | |
317 | * address. | |
318 | * | |
319 | * calls: none | |
320 | * | |
321 | * returns: configuration address to play on the PCI bus | |
322 | * | |
29d39604 RH |
323 | * To generate the appropriate PCI configuration cycles in the PCI |
324 | * configuration address space, you present the V3 with the following pattern | |
1da177e4 LT |
325 | * (which is very nearly a type 1 (except that the lower two bits are 00 and |
326 | * not 01). In order for this mapping to work you need to set up one of | |
327 | * the local to PCI aperatures to 16Mbytes in length translating to | |
328 | * PCI configuration space starting at 0x0000.0000. | |
329 | * | |
330 | * PCI configuration cycles look like this: | |
331 | * | |
332 | * Type 0: | |
333 | * | |
29d39604 | 334 | * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 |
1da177e4 LT |
335 | * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 |
336 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
337 | * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0| | |
338 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
339 | * | |
340 | * 31:11 Device select bit. | |
341 | * 10:8 Function number | |
342 | * 7:2 Register number | |
343 | * | |
344 | * Type 1: | |
345 | * | |
29d39604 | 346 | * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 |
1da177e4 LT |
347 | * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 |
348 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
349 | * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1| | |
350 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
351 | * | |
352 | * 31:24 reserved | |
353 | * 23:16 bus number (8 bits = 128 possible buses) | |
354 | * 15:11 Device number (5 bits) | |
355 | * 10:8 function number | |
356 | * 7:2 register number | |
29d39604 | 357 | * |
1da177e4 | 358 | */ |
1da177e4 | 359 | |
1da177e4 LT |
360 | #undef V3_LB_BASE_PREFETCH |
361 | #define V3_LB_BASE_PREFETCH 0 | |
362 | ||
b7a3f8db | 363 | static void __iomem *v3_open_config_window(struct pci_bus *bus, |
1da177e4 LT |
364 | unsigned int devfn, int offset) |
365 | { | |
366 | unsigned int address, mapaddress, busnr; | |
367 | ||
368 | busnr = bus->number; | |
369 | ||
370 | /* | |
371 | * Trap out illegal values | |
372 | */ | |
f7a9b365 SL |
373 | BUG_ON(offset > 255); |
374 | BUG_ON(busnr > 255); | |
375 | BUG_ON(devfn > 255); | |
1da177e4 LT |
376 | |
377 | if (busnr == 0) { | |
378 | int slot = PCI_SLOT(devfn); | |
379 | ||
380 | /* | |
381 | * local bus segment so need a type 0 config cycle | |
382 | * | |
383 | * build the PCI configuration "address" with one-hot in | |
384 | * A31-A11 | |
385 | * | |
386 | * mapaddress: | |
387 | * 3:1 = config cycle (101) | |
388 | * 0 = PCI A1 & A0 are 0 (0) | |
389 | */ | |
390 | address = PCI_FUNC(devfn) << 8; | |
391 | mapaddress = V3_LB_MAP_TYPE_CONFIG; | |
392 | ||
393 | if (slot > 12) | |
394 | /* | |
395 | * high order bits are handled by the MAP register | |
396 | */ | |
397 | mapaddress |= 1 << (slot - 5); | |
398 | else | |
399 | /* | |
400 | * low order bits handled directly in the address | |
401 | */ | |
402 | address |= 1 << (slot + 11); | |
403 | } else { | |
404 | /* | |
405 | * not the local bus segment so need a type 1 config cycle | |
406 | * | |
407 | * address: | |
408 | * 23:16 = bus number | |
409 | * 15:11 = slot number (7:3 of devfn) | |
410 | * 10:8 = func number (2:0 of devfn) | |
411 | * | |
412 | * mapaddress: | |
413 | * 3:1 = config cycle (101) | |
414 | * 0 = PCI A1 & A0 from host bus (1) | |
415 | */ | |
416 | mapaddress = V3_LB_MAP_TYPE_CONFIG | V3_LB_MAP_AD_LOW_EN; | |
417 | address = (busnr << 16) | (devfn << 8); | |
418 | } | |
419 | ||
420 | /* | |
421 | * Set up base0 to see all 512Mbytes of memory space (not | |
422 | * prefetchable), this frees up base1 for re-use by | |
423 | * configuration memory | |
424 | */ | |
f55b2b56 | 425 | v3_writel(V3_LB_BASE0, v3_addr_to_lb_base(non_mem.start) | |
1da177e4 LT |
426 | V3_LB_BASE_ADR_SIZE_512MB | V3_LB_BASE_ENABLE); |
427 | ||
428 | /* | |
429 | * Set up base1/map1 to point into configuration space. | |
430 | */ | |
f55b2b56 | 431 | v3_writel(V3_LB_BASE1, v3_addr_to_lb_base(conf_mem.start) | |
1da177e4 LT |
432 | V3_LB_BASE_ADR_SIZE_16MB | V3_LB_BASE_ENABLE); |
433 | v3_writew(V3_LB_MAP1, mapaddress); | |
434 | ||
435 | return PCI_CONFIG_VADDR + address + offset; | |
436 | } | |
437 | ||
438 | static void v3_close_config_window(void) | |
439 | { | |
440 | /* | |
441 | * Reassign base1 for use by prefetchable PCI memory | |
442 | */ | |
f55b2b56 | 443 | v3_writel(V3_LB_BASE1, v3_addr_to_lb_base(pre_mem.start) | |
1da177e4 LT |
444 | V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_PREFETCH | |
445 | V3_LB_BASE_ENABLE); | |
1eb92b24 | 446 | v3_writew(V3_LB_MAP1, v3_addr_to_lb_map(pre_mem_pci) | |
1da177e4 LT |
447 | V3_LB_MAP_TYPE_MEM_MULTIPLE); |
448 | ||
449 | /* | |
450 | * And shrink base0 back to a 256M window (NOTE: MAP0 already correct) | |
451 | */ | |
f55b2b56 | 452 | v3_writel(V3_LB_BASE0, v3_addr_to_lb_base(non_mem.start) | |
1da177e4 LT |
453 | V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_ENABLE); |
454 | } | |
455 | ||
456 | static int v3_read_config(struct pci_bus *bus, unsigned int devfn, int where, | |
457 | int size, u32 *val) | |
458 | { | |
61dc485b | 459 | int ret = pci_generic_config_read(bus, devfn, where, size, val); |
1da177e4 | 460 | v3_close_config_window(); |
61dc485b | 461 | return ret; |
1da177e4 LT |
462 | } |
463 | ||
464 | static int v3_write_config(struct pci_bus *bus, unsigned int devfn, int where, | |
465 | int size, u32 val) | |
466 | { | |
61dc485b | 467 | int ret = pci_generic_config_write(bus, devfn, where, size, val); |
1da177e4 | 468 | v3_close_config_window(); |
61dc485b | 469 | return ret; |
1da177e4 LT |
470 | } |
471 | ||
f4bc4f0a | 472 | static struct pci_ops pci_v3_ops = { |
61dc485b | 473 | .map_bus = v3_open_config_window, |
1da177e4 LT |
474 | .read = v3_read_config, |
475 | .write = v3_write_config, | |
476 | }; | |
477 | ||
37d15909 | 478 | static int __init pci_v3_setup_resources(struct pci_sys_data *sys) |
1da177e4 LT |
479 | { |
480 | if (request_resource(&iomem_resource, &non_mem)) { | |
481 | printk(KERN_ERR "PCI: unable to allocate non-prefetchable " | |
482 | "memory region\n"); | |
483 | return -EBUSY; | |
484 | } | |
485 | if (request_resource(&iomem_resource, &pre_mem)) { | |
486 | release_resource(&non_mem); | |
487 | printk(KERN_ERR "PCI: unable to allocate prefetchable " | |
488 | "memory region\n"); | |
489 | return -EBUSY; | |
490 | } | |
491 | ||
492 | /* | |
37d15909 BH |
493 | * the mem resource for this bus |
494 | * the prefetch mem resource for this bus | |
1da177e4 | 495 | */ |
9f786d03 BH |
496 | pci_add_resource_offset(&sys->resources, &non_mem, sys->mem_offset); |
497 | pci_add_resource_offset(&sys->resources, &pre_mem, sys->mem_offset); | |
1da177e4 LT |
498 | |
499 | return 1; | |
500 | } | |
501 | ||
502 | /* | |
503 | * These don't seem to be implemented on the Integrator I have, which | |
504 | * means I can't get additional information on the reason for the pm2fb | |
505 | * problems. I suppose I'll just have to mind-meld with the machine. ;) | |
506 | */ | |
379df279 LW |
507 | static void __iomem *ap_syscon_base; |
508 | #define INTEGRATOR_SC_PCIENABLE_OFFSET 0x18 | |
509 | #define INTEGRATOR_SC_LBFADDR_OFFSET 0x20 | |
510 | #define INTEGRATOR_SC_LBFCODE_OFFSET 0x24 | |
1da177e4 LT |
511 | |
512 | static int | |
513 | v3_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | |
514 | { | |
515 | unsigned long pc = instruction_pointer(regs); | |
516 | unsigned long instr = *(unsigned long *)pc; | |
517 | #if 0 | |
518 | char buf[128]; | |
519 | ||
520 | sprintf(buf, "V3 fault: addr 0x%08lx, FSR 0x%03x, PC 0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x ISTAT=%02x\n", | |
379df279 | 521 | addr, fsr, pc, instr, __raw_readl(ap_syscon_base + INTEGRATOR_SC_LBFADDR_OFFSET), __raw_readl(ap_syscon_base + INTEGRATOR_SC_LBFCODE_OFFSET) & 255, |
1da177e4 LT |
522 | v3_readb(V3_LB_ISTAT)); |
523 | printk(KERN_DEBUG "%s", buf); | |
1da177e4 LT |
524 | #endif |
525 | ||
526 | v3_writeb(V3_LB_ISTAT, 0); | |
379df279 | 527 | __raw_writel(3, ap_syscon_base + INTEGRATOR_SC_PCIENABLE_OFFSET); |
1da177e4 LT |
528 | |
529 | /* | |
530 | * If the instruction being executed was a read, | |
531 | * make it look like it read all-ones. | |
532 | */ | |
533 | if ((instr & 0x0c100000) == 0x04100000) { | |
534 | int reg = (instr >> 12) & 15; | |
535 | unsigned long val; | |
536 | ||
537 | if (instr & 0x00400000) | |
538 | val = 255; | |
539 | else | |
540 | val = -1; | |
541 | ||
542 | regs->uregs[reg] = val; | |
543 | regs->ARM_pc += 4; | |
544 | return 0; | |
545 | } | |
546 | ||
547 | if ((instr & 0x0e100090) == 0x00100090) { | |
548 | int reg = (instr >> 12) & 15; | |
549 | ||
550 | regs->uregs[reg] = -1; | |
551 | regs->ARM_pc += 4; | |
552 | return 0; | |
553 | } | |
554 | ||
555 | return 1; | |
556 | } | |
557 | ||
50564a79 | 558 | static irqreturn_t v3_irq(int irq, void *devid) |
1da177e4 LT |
559 | { |
560 | #ifdef CONFIG_DEBUG_LL | |
0cd61b68 | 561 | struct pt_regs *regs = get_irq_regs(); |
1da177e4 LT |
562 | unsigned long pc = instruction_pointer(regs); |
563 | unsigned long instr = *(unsigned long *)pc; | |
564 | char buf[128]; | |
7c28472a | 565 | extern void printascii(const char *); |
1da177e4 | 566 | |
e8f2af17 | 567 | sprintf(buf, "V3 int %d: pc=0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x " |
50564a79 | 568 | "ISTAT=%02x\n", irq, pc, instr, |
379df279 LW |
569 | __raw_readl(ap_syscon_base + INTEGRATOR_SC_LBFADDR_OFFSET), |
570 | __raw_readl(ap_syscon_base + INTEGRATOR_SC_LBFCODE_OFFSET) & 255, | |
1da177e4 LT |
571 | v3_readb(V3_LB_ISTAT)); |
572 | printascii(buf); | |
573 | #endif | |
574 | ||
575 | v3_writew(V3_PCI_STAT, 0xf000); | |
576 | v3_writeb(V3_LB_ISTAT, 0); | |
379df279 | 577 | __raw_writel(3, ap_syscon_base + INTEGRATOR_SC_PCIENABLE_OFFSET); |
1da177e4 LT |
578 | |
579 | #ifdef CONFIG_DEBUG_LL | |
580 | /* | |
581 | * If the instruction being executed was a read, | |
582 | * make it look like it read all-ones. | |
583 | */ | |
584 | if ((instr & 0x0c100000) == 0x04100000) { | |
585 | int reg = (instr >> 16) & 15; | |
586 | sprintf(buf, " reg%d = %08lx\n", reg, regs->uregs[reg]); | |
587 | printascii(buf); | |
588 | } | |
589 | #endif | |
590 | return IRQ_HANDLED; | |
591 | } | |
592 | ||
f4bc4f0a | 593 | static int __init pci_v3_setup(int nr, struct pci_sys_data *sys) |
1da177e4 LT |
594 | { |
595 | int ret = 0; | |
596 | ||
67c6b2ef LW |
597 | if (!ap_syscon_base) |
598 | return -EINVAL; | |
599 | ||
1da177e4 | 600 | if (nr == 0) { |
f55b2b56 | 601 | sys->mem_offset = non_mem.start; |
37d15909 | 602 | ret = pci_v3_setup_resources(sys); |
1da177e4 LT |
603 | } |
604 | ||
605 | return ret; | |
606 | } | |
607 | ||
1da177e4 LT |
608 | /* |
609 | * V3_LB_BASE? - local bus address | |
610 | * V3_LB_MAP? - pci bus address | |
611 | */ | |
f4bc4f0a | 612 | static void __init pci_v3_preinit(void) |
1da177e4 | 613 | { |
1da177e4 | 614 | unsigned int temp; |
0b0b0893 | 615 | phys_addr_t io_address = pci_pio_to_address(io_mem.start); |
1da177e4 | 616 | |
c9d95fbe RH |
617 | pcibios_min_mem = 0x00100000; |
618 | ||
1da177e4 LT |
619 | /* |
620 | * Hook in our fault handler for PCI errors | |
621 | */ | |
6338a6aa KS |
622 | hook_fault_code(4, v3_pci_fault, SIGBUS, 0, "external abort on linefetch"); |
623 | hook_fault_code(6, v3_pci_fault, SIGBUS, 0, "external abort on linefetch"); | |
624 | hook_fault_code(8, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch"); | |
625 | hook_fault_code(10, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch"); | |
1da177e4 | 626 | |
1da177e4 LT |
627 | /* |
628 | * Unlock V3 registers, but only if they were previously locked. | |
629 | */ | |
630 | if (v3_readw(V3_SYSTEM) & V3_SYSTEM_M_LOCK) | |
631 | v3_writew(V3_SYSTEM, 0xa05f); | |
632 | ||
633 | /* | |
634 | * Setup window 0 - PCI non-prefetchable memory | |
635 | * Local: 0x40000000 Bus: 0x00000000 Size: 256MB | |
636 | */ | |
f55b2b56 | 637 | v3_writel(V3_LB_BASE0, v3_addr_to_lb_base(non_mem.start) | |
1da177e4 | 638 | V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_ENABLE); |
1eb92b24 | 639 | v3_writew(V3_LB_MAP0, v3_addr_to_lb_map(non_mem_pci) | |
1da177e4 LT |
640 | V3_LB_MAP_TYPE_MEM); |
641 | ||
642 | /* | |
643 | * Setup window 1 - PCI prefetchable memory | |
644 | * Local: 0x50000000 Bus: 0x10000000 Size: 256MB | |
645 | */ | |
f55b2b56 | 646 | v3_writel(V3_LB_BASE1, v3_addr_to_lb_base(pre_mem.start) | |
1da177e4 LT |
647 | V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_PREFETCH | |
648 | V3_LB_BASE_ENABLE); | |
1eb92b24 | 649 | v3_writew(V3_LB_MAP1, v3_addr_to_lb_map(pre_mem_pci) | |
1da177e4 LT |
650 | V3_LB_MAP_TYPE_MEM_MULTIPLE); |
651 | ||
652 | /* | |
653 | * Setup window 2 - PCI IO | |
654 | */ | |
0b0b0893 | 655 | v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_address) | |
1da177e4 LT |
656 | V3_LB_BASE_ENABLE); |
657 | v3_writew(V3_LB_MAP2, v3_addr_to_lb_map2(0)); | |
658 | ||
659 | /* | |
660 | * Disable PCI to host IO cycles | |
661 | */ | |
662 | temp = v3_readw(V3_PCI_CFG) & ~V3_PCI_CFG_M_I2O_EN; | |
663 | temp |= V3_PCI_CFG_M_IO_REG_DIS | V3_PCI_CFG_M_IO_DIS; | |
664 | v3_writew(V3_PCI_CFG, temp); | |
665 | ||
666 | printk(KERN_DEBUG "FIFO_CFG: %04x FIFO_PRIO: %04x\n", | |
667 | v3_readw(V3_FIFO_CFG), v3_readw(V3_FIFO_PRIORITY)); | |
668 | ||
669 | /* | |
670 | * Set the V3 FIFO such that writes have higher priority than | |
671 | * reads, and local bus write causes local bus read fifo flush. | |
672 | * Same for PCI. | |
673 | */ | |
674 | v3_writew(V3_FIFO_PRIORITY, 0x0a0a); | |
675 | ||
676 | /* | |
677 | * Re-lock the system register. | |
678 | */ | |
679 | temp = v3_readw(V3_SYSTEM) | V3_SYSTEM_M_LOCK; | |
680 | v3_writew(V3_SYSTEM, temp); | |
681 | ||
682 | /* | |
683 | * Clear any error conditions, and enable write errors. | |
684 | */ | |
685 | v3_writeb(V3_LB_ISTAT, 0); | |
686 | v3_writew(V3_LB_CFG, v3_readw(V3_LB_CFG) | (1 << 10)); | |
687 | v3_writeb(V3_LB_IMASK, 0x28); | |
379df279 | 688 | __raw_writel(3, ap_syscon_base + INTEGRATOR_SC_PCIENABLE_OFFSET); |
1da177e4 LT |
689 | } |
690 | ||
f4bc4f0a | 691 | static void __init pci_v3_postinit(void) |
1da177e4 LT |
692 | { |
693 | unsigned int pci_cmd; | |
0b0b0893 | 694 | phys_addr_t io_address = pci_pio_to_address(io_mem.start); |
1da177e4 LT |
695 | |
696 | pci_cmd = PCI_COMMAND_MEMORY | | |
697 | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE; | |
698 | ||
699 | v3_writew(V3_PCI_CMD, pci_cmd); | |
700 | ||
701 | v3_writeb(V3_LB_ISTAT, ~0x40); | |
702 | v3_writeb(V3_LB_IMASK, 0x68); | |
703 | ||
704 | #if 0 | |
705 | ret = request_irq(IRQ_AP_LBUSTIMEOUT, lb_timeout, 0, "bus timeout", NULL); | |
706 | if (ret) | |
707 | printk(KERN_ERR "PCI: unable to grab local bus timeout " | |
708 | "interrupt: %d\n", ret); | |
709 | #endif | |
863dab45 | 710 | |
0b0b0893 | 711 | register_isa_ports(non_mem.start, io_address, 0); |
1da177e4 | 712 | } |
f4bc4f0a LW |
713 | |
714 | /* | |
715 | * A small note about bridges and interrupts. The DECchip 21050 (and | |
716 | * later) adheres to the PCI-PCI bridge specification. This says that | |
717 | * the interrupts on the other side of a bridge are swizzled in the | |
718 | * following manner: | |
719 | * | |
720 | * Dev Interrupt Interrupt | |
721 | * Pin on Pin on | |
722 | * Device Connector | |
723 | * | |
724 | * 4 A A | |
725 | * B B | |
726 | * C C | |
727 | * D D | |
728 | * | |
729 | * 5 A B | |
730 | * B C | |
731 | * C D | |
732 | * D A | |
733 | * | |
734 | * 6 A C | |
735 | * B D | |
736 | * C A | |
737 | * D B | |
738 | * | |
739 | * 7 A D | |
740 | * B A | |
741 | * C B | |
742 | * D C | |
743 | * | |
744 | * Where A = pin 1, B = pin 2 and so on and pin=0 = default = A. | |
745 | * Thus, each swizzle is ((pin-1) + (device#-4)) % 4 | |
746 | */ | |
747 | ||
748 | /* | |
749 | * This routine handles multiple bridges. | |
750 | */ | |
86adc39f | 751 | static u8 __init pci_v3_swizzle(struct pci_dev *dev, u8 *pinp) |
f4bc4f0a LW |
752 | { |
753 | if (*pinp == 0) | |
754 | *pinp = 1; | |
755 | ||
756 | return pci_common_swizzle(dev, pinp); | |
757 | } | |
758 | ||
d7057e1d LW |
759 | static struct hw_pci pci_v3 __initdata = { |
760 | .swizzle = pci_v3_swizzle, | |
761 | .setup = pci_v3_setup, | |
762 | .nr_controllers = 1, | |
763 | .ops = &pci_v3_ops, | |
764 | .preinit = pci_v3_preinit, | |
765 | .postinit = pci_v3_postinit, | |
766 | }; | |
767 | ||
768 | static int __init pci_v3_probe(struct platform_device *pdev) | |
f55b2b56 | 769 | { |
d7057e1d | 770 | struct device_node *np = pdev->dev.of_node; |
f55b2b56 LW |
771 | struct of_pci_range_parser parser; |
772 | struct of_pci_range range; | |
773 | struct resource *res; | |
774 | int irq, ret; | |
775 | ||
d7057e1d | 776 | /* Remap the Integrator system controller */ |
99d14a1d | 777 | ap_syscon_base = devm_ioremap(&pdev->dev, INTEGRATOR_SC_BASE, 0x100); |
d7057e1d LW |
778 | if (!ap_syscon_base) { |
779 | dev_err(&pdev->dev, "unable to remap the AP syscon for PCIv3\n"); | |
780 | return -ENODEV; | |
781 | } | |
782 | ||
783 | /* Device tree probe path */ | |
784 | if (!np) { | |
785 | dev_err(&pdev->dev, "no device tree node for PCIv3\n"); | |
786 | return -ENODEV; | |
787 | } | |
788 | ||
f55b2b56 LW |
789 | if (of_pci_range_parser_init(&parser, np)) |
790 | return -EINVAL; | |
791 | ||
792 | /* Get base for bridge registers */ | |
793 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
794 | if (!res) { | |
795 | dev_err(&pdev->dev, "unable to obtain PCIv3 base\n"); | |
796 | return -ENODEV; | |
797 | } | |
798 | pci_v3_base = devm_ioremap(&pdev->dev, res->start, | |
799 | resource_size(res)); | |
800 | if (!pci_v3_base) { | |
801 | dev_err(&pdev->dev, "unable to remap PCIv3 base\n"); | |
802 | return -ENODEV; | |
803 | } | |
804 | ||
805 | /* Get and request error IRQ resource */ | |
806 | irq = platform_get_irq(pdev, 0); | |
807 | if (irq <= 0) { | |
808 | dev_err(&pdev->dev, "unable to obtain PCIv3 error IRQ\n"); | |
809 | return -ENODEV; | |
810 | } | |
811 | ret = devm_request_irq(&pdev->dev, irq, v3_irq, 0, | |
812 | "PCIv3 error", NULL); | |
813 | if (ret < 0) { | |
814 | dev_err(&pdev->dev, "unable to request PCIv3 error IRQ %d (%d)\n", irq, ret); | |
815 | return ret; | |
816 | } | |
817 | ||
818 | for_each_of_pci_range(&parser, &range) { | |
819 | if (!range.flags) { | |
0b0b0893 | 820 | ret = of_pci_range_to_resource(&range, np, &conf_mem); |
f55b2b56 LW |
821 | conf_mem.name = "PCIv3 config"; |
822 | } | |
823 | if (range.flags & IORESOURCE_IO) { | |
0b0b0893 | 824 | ret = of_pci_range_to_resource(&range, np, &io_mem); |
f55b2b56 LW |
825 | io_mem.name = "PCIv3 I/O"; |
826 | } | |
827 | if ((range.flags & IORESOURCE_MEM) && | |
828 | !(range.flags & IORESOURCE_PREFETCH)) { | |
1eb92b24 LW |
829 | non_mem_pci = range.pci_addr; |
830 | non_mem_pci_sz = range.size; | |
0b0b0893 | 831 | ret = of_pci_range_to_resource(&range, np, &non_mem); |
f55b2b56 LW |
832 | non_mem.name = "PCIv3 non-prefetched mem"; |
833 | } | |
834 | if ((range.flags & IORESOURCE_MEM) && | |
835 | (range.flags & IORESOURCE_PREFETCH)) { | |
1eb92b24 LW |
836 | pre_mem_pci = range.pci_addr; |
837 | pre_mem_pci_sz = range.size; | |
0b0b0893 | 838 | ret = of_pci_range_to_resource(&range, np, &pre_mem); |
f55b2b56 LW |
839 | pre_mem.name = "PCIv3 prefetched mem"; |
840 | } | |
f55b2b56 | 841 | |
0b0b0893 LD |
842 | if (ret < 0) { |
843 | dev_err(&pdev->dev, "missing ranges in device node\n"); | |
844 | return ret; | |
845 | } | |
f55b2b56 LW |
846 | } |
847 | ||
16b84e5a | 848 | pci_v3.map_irq = of_irq_parse_and_map_pci; |
f55b2b56 LW |
849 | pci_common_init_dev(&pdev->dev, &pci_v3); |
850 | ||
851 | return 0; | |
852 | } | |
853 | ||
f55b2b56 LW |
854 | static const struct of_device_id pci_ids[] = { |
855 | { .compatible = "v3,v360epc-pci", }, | |
856 | {}, | |
857 | }; | |
858 | ||
86adc39f LW |
859 | static struct platform_driver pci_v3_driver = { |
860 | .driver = { | |
861 | .name = "pci-v3", | |
f55b2b56 | 862 | .of_match_table = pci_ids, |
86adc39f LW |
863 | }, |
864 | }; | |
865 | ||
866 | static int __init pci_v3_init(void) | |
867 | { | |
868 | return platform_driver_probe(&pci_v3_driver, pci_v3_probe); | |
869 | } | |
870 | ||
871 | subsys_initcall(pci_v3_init); | |
ae9daf2d LW |
872 | |
873 | /* | |
874 | * Static mappings for the PCIv3 bridge | |
875 | * | |
876 | * e8000000 40000000 PCI memory PHYS_PCI_MEM_BASE (max 512M) | |
877 | * ec000000 61000000 PCI config space PHYS_PCI_CONFIG_BASE (max 16M) | |
878 | * fee00000 60000000 PCI IO PHYS_PCI_IO_BASE (max 16M) | |
879 | */ | |
880 | static struct map_desc pci_v3_io_desc[] __initdata __maybe_unused = { | |
881 | { | |
882 | .virtual = (unsigned long)PCI_MEMORY_VADDR, | |
883 | .pfn = __phys_to_pfn(PHYS_PCI_MEM_BASE), | |
884 | .length = SZ_16M, | |
885 | .type = MT_DEVICE | |
886 | }, { | |
887 | .virtual = (unsigned long)PCI_CONFIG_VADDR, | |
888 | .pfn = __phys_to_pfn(PHYS_PCI_CONFIG_BASE), | |
889 | .length = SZ_16M, | |
890 | .type = MT_DEVICE | |
891 | } | |
892 | }; | |
893 | ||
894 | int __init pci_v3_early_init(void) | |
895 | { | |
896 | iotable_init(pci_v3_io_desc, ARRAY_SIZE(pci_v3_io_desc)); | |
897 | vga_base = (unsigned long)PCI_MEMORY_VADDR; | |
898 | pci_map_io_early(__phys_to_pfn(PHYS_PCI_IO_BASE)); | |
899 | return 0; | |
900 | } |