blob: b380f0dfe87986df3b6348f1218c34b3f0219bc7 [file] [log] [blame]
wdenkc7de8292002-11-19 11:04:11 +00001#include <common.h>
2#include <pci.h>
3#include <74xx_7xx.h>
4
5
6#ifdef DEBUG
7#undef DEBUG
8#endif
9
10#ifdef DEBUG
11#define PRINTF(format, args...) _printf(format , ## args)
12#else
13#define PRINTF(format, argc...)
14#endif
15
16static pci_dev_t to_pci(int bus, int devfn)
17{
18 return PCI_BDF(bus, (devfn>>3), devfn&3);
19}
20
21int mypci_find_device(int vendor, int product, int index)
22{
23 return pci_find_device(vendor, product, index);
24}
25
26int mypci_bus(int device)
27{
28 return PCI_BUS(device);
29}
30
31int mypci_devfn(int device)
32{
33 return (PCI_DEV(device)<<3) | PCI_FUNC(device);
34}
35
36
37#define mypci_read_func(type, size) \
38type mypci_read_cfg_##size##(int bus, int devfn, int offset) \
39{ \
40 type c; \
41 pci_read_config_##size##(to_pci(bus, devfn), offset, &c); \
42 return c; \
43}
44
45#define mypci_write_func(type, size) \
46void mypci_write_cfg_##size##(int bus, int devfn, int offset, int value) \
47{ \
48 pci_write_config_##size##(to_pci(bus, devfn), offset, value); \
49}
50
51mypci_read_func(u8,byte);
52mypci_read_func(u16,word);
53
54mypci_write_func(u8,byte);
55mypci_write_func(u16,word);
56
57u32 mypci_read_cfg_long(int bus, int devfn, int offset)
58{
59 u32 c;
60 pci_read_config_dword(to_pci(bus, devfn), offset, &c);
61 return c;
62}
63
64void mypci_write_cfg_long(int bus, int devfn, int offset, int value)
65{
66 pci_write_config_dword(to_pci(bus, devfn), offset, value);
67}
68
69void _printf(const char *fmt, ...)
70{
71 va_list args;
72 char buf[CFG_PBSIZE];
73
74 va_start(args, fmt);
75 (void)vsprintf(buf, fmt, args);
76 va_end(args);
77
78 printf(buf);
79}
80
81char *_getenv(char *name)
82{
83 return getenv(name);
84}
85
86unsigned long get_bar_size(pci_dev_t dev, int offset)
87{
88 u32 bar_back, bar_value;
89
90 /* Save old BAR value */
91 pci_read_config_dword(dev, offset, &bar_back);
92
93 /* Write all 1's. */
94 pci_write_config_dword(dev, offset, ~0);
95
96 /* Now read back the relevant bits */
97 pci_read_config_dword(dev, offset, &bar_value);
98
99 /* Restore original value */
100 pci_write_config_dword(dev, offset, bar_back);
101
102 if (bar_value == 0) return 0xFFFFFFFF; /* This BAR is disabled */
103
104 if ((bar_value & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY)
105 {
106 /* This is a memory space BAR. Mask it out so we get the size of it */
107 return ~(bar_value & PCI_BASE_ADDRESS_MEM_MASK) + 1;
108 }
109
110 /* Not suitable */
111 return 0xFFFFFFFF;
112}
113
114void enable_compatibility_hole(void)
115{
116 u8 cfg;
117 pci_dev_t art = PCI_BDF(0,0,0);
118
119 pci_read_config_byte(art, 0x54, &cfg);
120 /* cfg |= 0x08; */
121 cfg |= 0x20;
122 pci_write_config_byte(art, 0x54, cfg);
123}
124
125void disable_compatibility_hole(void)
126{
127 u8 cfg;
128 pci_dev_t art = PCI_BDF(0,0,0);
129
130 pci_read_config_byte(art, 0x54, &cfg);
131 /* cfg &= ~0x08; */
132 cfg &= ~0x20;
133 pci_write_config_byte(art, 0x54, cfg);
134}
135
136void map_rom(pci_dev_t dev, u32 address)
137{
138 pci_write_config_dword(dev, PCI_ROM_ADDRESS, address|PCI_ROM_ADDRESS_ENABLE);
139}
140
141void unmap_rom(pci_dev_t dev)
142{
143 pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
144}
145
146void bat_map(u8 batnum, u32 address, u32 length)
147{
148 u32 temp = address;
149 address &= 0xFFFE0000;
150 temp &= 0x0001FFFF;
151 length = (length - 1 ) >> 17;
152 length <<= 2;
153
154 switch (batnum)
155 {
156 case 0:
157 __asm volatile ("mtdbatu 0, %0" : : "r" (address | length | 3));
158 __asm volatile ("mtdbatl 0, %0" : : "r" (address | 0x22));
159 break;
160 case 1:
161 __asm volatile ("mtdbatu 1, %0" : : "r" (address | length | 3));
162 __asm volatile ("mtdbatl 1, %0" : : "r" (address | 0x22));
163 break;
164 case 2:
165 __asm volatile ("mtdbatu 2, %0" : : "r" (address | length | 3));
166 __asm volatile ("mtdbatl 2, %0" : : "r" (address | 0x22));
167 break;
168 case 3:
169 __asm volatile ("mtdbatu 3, %0" : : "r" (address | length | 3));
170 __asm volatile ("mtdbatl 3, %0" : : "r" (address | 0x22));
171 break;
172 }
173}
174
175int find_image(u32 rom_address, u32 rom_size, void **image, u32 *image_size);
176
177int attempt_map_rom(pci_dev_t dev, void *copy_address)
178{
179 u32 rom_size = 0;
180 u32 rom_address = 0;
181 u32 bar_size = 0;
182 u32 bar_backup = 0;
183 int i,j;
184 void *image = 0;
185 u32 image_size = 0;
186 int did_correct = 0;
187 u32 prefetch_addr = 0;
188 u32 prefetch_size = 0;
189 u32 prefetch_idx = 0;
190
191 /* Get the size of the expansion rom */
192 pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0xFFFFFFFF);
193 pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_size);
194 if ((rom_size & 0x01) == 0)
195 {
196 PRINTF("No ROM\n");
197 return 0;
198 }
199
200 rom_size &= 0xFFFFF800;
201 rom_size = (~rom_size)+1;
202
203 PRINTF("ROM Size is %dK\n", rom_size/1024);
204
205 /*
206 * Try to find a place for the ROM. We always attempt to use
207 * one of the card's bases for this, as this will be in any
208 * bridge's resource range as well as being free of conflicts
209 * with other cards. In a graphics card it is very unlikely
210 * that there won't be any base address that is large enough to
211 * hold the rom.
212 *
213 * FIXME: To work around this, theoretically the largest base
214 * could be used if none is found in the loop below.
215 */
216
217 for (i = PCI_BASE_ADDRESS_0; i <= PCI_BASE_ADDRESS_5; i += 4)
218 {
219 bar_size = get_bar_size(dev, i);
220 PRINTF("PCI_BASE_ADDRESS_%d is %dK large\n",
221 (i - PCI_BASE_ADDRESS_0)/4,
222 bar_size/1024);
223 if (bar_size != 0xFFFFFFFF && bar_size >= rom_size)
224 {
225 PRINTF("Found a match for rom size\n");
226 pci_read_config_dword(dev, i, &rom_address);
227 rom_address &= 0xFFFFFFF0;
228 if (rom_address != 0 && rom_address != 0xFFFFFFF0) break;
229 }
230 }
231
232 if (rom_address == 0 || rom_address == 0xFFFFFFF0)
233 {
234 PRINTF("No suitable rom address found\n");
235 return 0;
236 }
237
238 /* Disable the BAR */
239 pci_read_config_dword(dev, i, &bar_backup);
240 pci_write_config_dword(dev, i, 0);
241
242 /* Map ROM */
243 pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address | PCI_ROM_ADDRESS_ENABLE);
244
245 /* Copy the rom to a place in the emulator space */
246 PRINTF("Claiming BAT 2\n");
247 bat_map(2, rom_address, rom_size);
248 /* show_bat_mapping(); */
249
250 if (0 == find_image(rom_address, rom_size, &image, &image_size))
251 {
252 PRINTF("No x86 BIOS image found\n");
253 return 0;
254 }
255
256 PRINTF("Copying %ld bytes from 0x%lx to 0x%lx\n", (long)image_size, (long)image, (long)copy_address);
257
258 /* memcpy(copy_address, rom_address, rom_size); */
259 {
260 unsigned char *from = (unsigned char *)image; /* rom_address; */
261 unsigned char *to = (unsigned char *)copy_address;
262 for (j=0; j<image_size /*rom_size*/; j++)
263 {
264 *to++ = *from++;
265 }
266 }
267
268 PRINTF("Copy is done\n");
269
270 /* Unmap the ROM and restore the BAR */
271 pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
272 pci_write_config_dword(dev, i, bar_backup);
273
wdenk7c7a23b2002-12-07 00:20:59 +0000274 /* FIXME: Shouldn't be needed anymore*/
275 /* bat_map(2, 0x80000000, 256*1024*1024);
276 show_bat_mapping(); */
wdenkc7de8292002-11-19 11:04:11 +0000277
278 /*
279 * Since most cards can probably only do 16 bit IO addressing, we
280 * correct their IO base into an appropriate value.
281 * This should do for most.
282 */
283 for (i = PCI_BASE_ADDRESS_0; i <= PCI_BASE_ADDRESS_5; i += 4)
284 {
285 unsigned long value;
286 pci_read_config_dword(dev, i, &value);
287 if (value & 0x01) /* IO */
288 {
289 did_correct = 1;
290 pci_write_config_dword(dev, i, 0x1001);
291 break;
292 }
293
294 if (value & PCI_BASE_ADDRESS_MEM_PREFETCH)
295 {
296 prefetch_idx = i;
297 prefetch_addr = value & PCI_BASE_ADDRESS_MEM_MASK;
298 prefetch_size = get_bar_size(dev, i);
299 }
300 }
301
302 if (1) /* did_correct) */
303 {
304 extern pci_dev_t pci_find_bridge_for_bus(struct pci_controller *hose, int busnr);
305 int busnr = PCI_BUS(dev);
306 if (busnr)
307 {
308 pci_dev_t bridge;
309 PRINTF("Need to correct bridge device for IO range change\n");
310 bridge = pci_find_bridge_for_bus(NULL, busnr);
311 if (bridge == PCI_ANY_ID)
312 {
313 PRINTF("Didn't find bridge. Hope that's OK\n");
314 }
315 else
316 {
317 /*
318 * Set upper I/O base/limit to 0
319 */
320 pci_write_config_byte(bridge, 0x30, 0x00);
321 pci_write_config_byte(bridge, 0x31, 0x00);
322 pci_write_config_byte(bridge, 0x32, 0x00);
323 pci_write_config_byte(bridge, 0x33, 0x00);
324 if (did_correct)
325 {
326 /*
327 * set lower I/O base to 1000
328 * That is, bits 0:3 are set to 0001 by default.
329 * bits 7:4 contain I/O address bits 15:12
330 * all others are assumed 0.
331 */
332 pci_write_config_byte(bridge, 0x1C, 0x11);
333 /*
334 * Set lower I/O limit to 1FFF
335 * That is, bits 0:3 are reserved and always 0000
336 * Bits 7:4 contain I/O address bits 15:12
337 * All others are assumed F.
338 */
339 pci_write_config_byte(bridge, 0x1D, 0x10);
340 pci_write_config_byte(bridge, 0x0D, 0x20);
341 PRINTF("Corrected bridge resource range of bridge at %02x:%02x:%02x\n",
342 PCI_BUS(bridge), PCI_DEV(bridge), PCI_FUNC(bridge));
343
344 }
345 else
346 {
347 /*
348 * This card doesn't have I/O, we disable I/O forwarding
349 */
350 pci_write_config_byte(bridge, 0x1C, 0x11);
351 pci_write_config_byte(bridge, 0x1D, 0x00);
352 pci_write_config_byte(bridge, PCI_INTERRUPT_LINE, 0);
353 pci_write_config_byte(bridge, PCI_INTERRUPT_PIN, 0);
354 pci_write_config_dword(bridge, PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_IO);
355 PRINTF("Disabled bridge resource range of bridge at %02x:%02x:%02x\n",
356 PCI_BUS(bridge), PCI_DEV(bridge), PCI_FUNC(bridge));
357
358 }
359 }
360 /*
361 * Correct the prefetchable memory base, which is not set correctly by
362 * the U-Boot autoconfig stuff
363 */
364 if (prefetch_idx)
365 {
366/* PRINTF("Setting prefetchable range to %x, %x (%x and %x)\n", */
367/* prefetch_addr, prefetch_addr+prefetch_size, */
368/* prefetch_addr>>16, (prefetch_addr+prefetch_size)>>16); */
369/* pci_write_config_word(bridge, PCI_PREF_MEMORY_BASE, (prefetch_addr>>16)); */
370/* pci_write_config_word(bridge, PCI_PREF_MEMORY_LIMIT, (prefetch_addr+prefetch_size)>>16); */
371 }
372
373 pci_write_config_word(bridge, PCI_PREF_MEMORY_BASE, 0x1000);
374 pci_write_config_word(bridge, PCI_PREF_MEMORY_LIMIT, 0x0000);
375
376 pci_write_config_byte(bridge, 0xD0, 0x0A);
377 pci_write_config_byte(bridge, 0xD3, 0x04);
378
379 /*
380 * Set the interrupt pin to 0
381 */
382#if 0
383 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 0);
384 pci_write_config_byte(dev, PCI_INTERRUPT_PIN, 0);
385#endif
386 pci_write_config_byte(bridge, PCI_INTERRUPT_LINE, 0);
387 pci_write_config_byte(bridge, PCI_INTERRUPT_PIN, 0);
388
389 }
390 }
391
392 /* Finally, enable the card's IO and memory response */
393 pci_write_config_dword(dev, PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
394 pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0);
395 pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0);
396
397 return 1;
398}
399
400int find_image(u32 rom_address, u32 rom_size, void **image, u32 *image_size)
401{
402 int i = 0;
403 unsigned char *rom = (unsigned char *)rom_address;
wdenk8bde7f72003-06-27 21:31:46 +0000404 /* if (*rom != 0x55 || *(rom+1) != 0xAA) return 0; /* No bios rom this is, yes. */ */
wdenkc7de8292002-11-19 11:04:11 +0000405
406 for (;;)
407 {
408 unsigned short pci_data_offset = *(rom+0x18) + 256 * *(rom+0x19);
409 unsigned short pci_image_length = (*(rom+pci_data_offset+0x10) + 256 * *(rom+pci_data_offset+0x11)) * 512;
410 unsigned char pci_image_type = *(rom+pci_data_offset+0x14);
411 if (*rom != 0x55 || *(rom+1) != 0xAA)
412 {
413 PRINTF("Invalid header this is\n");
414 return 0;
415 }
416 PRINTF("Image %i: Type %d (%s)\n", i++, pci_image_type,
417 pci_image_type==0 ? "x86" :
418 pci_image_type==1 ? "OpenFirmware" :
419 "Unknown");
420 if (pci_image_type == 0)
421 {
422 *image = rom;
423 *image_size = pci_image_length;
424 return 1;
425 }
426
427 if (*(rom+pci_data_offset+0x15) & 0x80)
428 {
429 PRINTF("LAST image encountered, no image found\n");
430 return 0;
431 }
432
433 rom += pci_image_length;
434 }
435}
436
437void show_bat_mapping(void)
438{
wdenkc7de8292002-11-19 11:04:11 +0000439 u32 dbat0u, dbat0l, ibat0u, ibat0l;
440 u32 dbat1u, dbat1l, ibat1u, ibat1l;
441 u32 dbat2u, dbat2l, ibat2u, ibat2l;
442 u32 dbat3u, dbat3l, ibat3u, ibat3l;
443 u32 msr, hid0, l2cr_reg;
444
445 __asm volatile ("mfdbatu %0,0" : "=r" (dbat0u));
446 __asm volatile ("mfdbatl %0,0" : "=r" (dbat0l));
447 __asm volatile ("mfibatu %0,0" : "=r" (ibat0u));
448 __asm volatile ("mfibatl %0,0" : "=r" (ibat0l));
449
450 __asm volatile ("mfdbatu %0,1" : "=r" (dbat1u));
451 __asm volatile ("mfdbatl %0,1" : "=r" (dbat1l));
452 __asm volatile ("mfibatu %0,1" : "=r" (ibat1u));
453 __asm volatile ("mfibatl %0,1" : "=r" (ibat1l));
454
455 __asm volatile ("mfdbatu %0,2" : "=r" (dbat2u));
456 __asm volatile ("mfdbatl %0,2" : "=r" (dbat2l));
457 __asm volatile ("mfibatu %0,2" : "=r" (ibat2u));
458 __asm volatile ("mfibatl %0,2" : "=r" (ibat2l));
459
460 __asm volatile ("mfdbatu %0,3" : "=r" (dbat3u));
461 __asm volatile ("mfdbatl %0,3" : "=r" (dbat3l));
462 __asm volatile ("mfibatu %0,3" : "=r" (ibat3u));
463 __asm volatile ("mfibatl %0,3" : "=r" (ibat3l));
464
465 __asm volatile ("mfmsr %0" : "=r" (msr));
466 __asm volatile ("mfspr %0,1008": "=r" (hid0));
467 __asm volatile ("mfspr %0,1017": "=r" (l2cr_reg));
468
469 printf("dbat0u: %08x dbat0l: %08x ibat0u: %08x ibat0l: %08x\n",
470 dbat0u, dbat0l, ibat0u, ibat0l);
471 printf("dbat1u: %08x dbat1l: %08x ibat1u: %08x ibat1l: %08x\n",
472 dbat1u, dbat1l, ibat1u, ibat1l);
473 printf("dbat2u: %08x dbat2l: %08x ibat2u: %08x ibat2l: %08x\n",
474 dbat2u, dbat2l, ibat2u, ibat2l);
475 printf("dbat3u: %08x dbat3l: %08x ibat3u: %08x ibat3l: %08x\n",
476 dbat3u, dbat3l, ibat3u, ibat3l);
477
478 printf("\nMSR: %08x HID0: %08x L2CR: %08x \n", msr,hid0, l2cr_reg);
wdenkc7de8292002-11-19 11:04:11 +0000479}
480
481
wdenkc7de8292002-11-19 11:04:11 +0000482void remove_init_data(void)
483{
484 char *s;
wdenkc7de8292002-11-19 11:04:11 +0000485
486 /* Invalidate and disable data cache */
487 invalidate_l1_data_cache();
488 dcache_disable();
489
wdenkc7de8292002-11-19 11:04:11 +0000490 s = getenv("x86_cache");
491
wdenk7c7a23b2002-12-07 00:20:59 +0000492 if (!s)
wdenkc7de8292002-11-19 11:04:11 +0000493 {
494 icache_enable();
495 dcache_enable();
496 }
wdenk7c7a23b2002-12-07 00:20:59 +0000497 else if (s)
498 {
wdenk8bde7f72003-06-27 21:31:46 +0000499 if (strcmp(s, "dcache")==0)
500 {
501 dcache_enable();
502 }
503 else if (strcmp(s, "icache") == 0)
504 {
505 icache_enable();
506 }
507 else if (strcmp(s, "on")== 0 || strcmp(s, "both") == 0)
508 {
509 dcache_enable();
510 icache_enable();
511 }
wdenk7c7a23b2002-12-07 00:20:59 +0000512 }
wdenkc7de8292002-11-19 11:04:11 +0000513
wdenk7c7a23b2002-12-07 00:20:59 +0000514 /* show_bat_mapping();*/
wdenkc7de8292002-11-19 11:04:11 +0000515}