]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/MAI/bios_emulator/glue.c
b765ed54c98f46b951d53dbf127895dd5db3e307
[karo-tx-uboot.git] / board / MAI / bios_emulator / glue.c
1 #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
16 static pci_dev_t to_pci(int bus, int devfn)
17 {
18     return PCI_BDF(bus, (devfn>>3), devfn&3);
19 }
20
21 int mypci_find_device(int vendor, int product, int index)
22 {
23     return pci_find_device(vendor, product, index);
24 }
25
26 int mypci_bus(int device)
27 {
28     return PCI_BUS(device);
29 }
30
31 int mypci_devfn(int device)
32 {
33     return (PCI_DEV(device)<<3) | PCI_FUNC(device);
34 }
35
36
37 #define mypci_read_func(type, size)                             \
38 type 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)                            \
46 void 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
51 mypci_read_func(u8,byte);
52 mypci_read_func(u16,word);
53
54 mypci_write_func(u8,byte);
55 mypci_write_func(u16,word);
56
57 u32 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
64 void 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
69 void _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
81 char *_getenv(char *name)
82 {
83     return getenv(name);
84 }
85
86 unsigned 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
114 void 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
125 void 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
136 void 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
141 void unmap_rom(pci_dev_t dev)
142 {
143     pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
144 }
145
146 void 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
175 int find_image(u32 rom_address, u32 rom_size, void **image, u32 *image_size);
176
177 int 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
274     /*  FIXME: */
275     bat_map(2, 0x80000000, 256*1024*1024);
276     show_bat_mapping();
277
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
400 int 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;
404     /* if (*rom != 0x55 || *(rom+1) != 0xAA) return 0; // No bios rom this is, yes. */
405
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
437 void show_bat_mapping(void)
438 {
439 #ifdef DEBUG
440     u32 dbat0u, dbat0l, ibat0u, ibat0l;
441     u32 dbat1u, dbat1l, ibat1u, ibat1l;
442     u32 dbat2u, dbat2l, ibat2u, ibat2l;
443     u32 dbat3u, dbat3l, ibat3u, ibat3l;
444     u32 msr, hid0, l2cr_reg;
445
446     __asm volatile ("mfdbatu %0,0" : "=r" (dbat0u));
447     __asm volatile ("mfdbatl %0,0" : "=r" (dbat0l));
448     __asm volatile ("mfibatu %0,0" : "=r" (ibat0u));
449     __asm volatile ("mfibatl %0,0" : "=r" (ibat0l));
450
451     __asm volatile ("mfdbatu %0,1" : "=r" (dbat1u));
452     __asm volatile ("mfdbatl %0,1" : "=r" (dbat1l));
453     __asm volatile ("mfibatu %0,1" : "=r" (ibat1u));
454     __asm volatile ("mfibatl %0,1" : "=r" (ibat1l));
455
456     __asm volatile ("mfdbatu %0,2" : "=r" (dbat2u));
457     __asm volatile ("mfdbatl %0,2" : "=r" (dbat2l));
458     __asm volatile ("mfibatu %0,2" : "=r" (ibat2u));
459     __asm volatile ("mfibatl %0,2" : "=r" (ibat2l));
460
461     __asm volatile ("mfdbatu %0,3" : "=r" (dbat3u));
462     __asm volatile ("mfdbatl %0,3" : "=r" (dbat3l));
463     __asm volatile ("mfibatu %0,3" : "=r" (ibat3u));
464     __asm volatile ("mfibatl %0,3" : "=r" (ibat3l));
465
466     __asm volatile ("mfmsr %0"     : "=r" (msr));
467     __asm volatile ("mfspr %0,1008": "=r" (hid0));
468     __asm volatile ("mfspr %0,1017": "=r" (l2cr_reg));
469
470     printf("dbat0u: %08x dbat0l: %08x ibat0u: %08x ibat0l: %08x\n",
471            dbat0u, dbat0l, ibat0u, ibat0l);
472     printf("dbat1u: %08x dbat1l: %08x ibat1u: %08x ibat1l: %08x\n",
473            dbat1u, dbat1l, ibat1u, ibat1l);
474     printf("dbat2u: %08x dbat2l: %08x ibat2u: %08x ibat2l: %08x\n",
475            dbat2u, dbat2l, ibat2u, ibat2l);
476     printf("dbat3u: %08x dbat3l: %08x ibat3u: %08x ibat3l: %08x\n",
477            dbat3u, dbat3l, ibat3u, ibat3l);
478
479     printf("\nMSR: %08x   HID0: %08x   L2CR: %08x \n", msr,hid0, l2cr_reg);
480 #endif
481 }
482
483
484
485 void remove_init_data(void)
486 {
487     char *s;
488     u32 batl = ((CFG_SDRAM_BASE+0x100000) | BATL_PP_RW);
489     u32 batu =((CFG_SDRAM_BASE+0x100000) | BATU_BL_256M | BATU_VS | BATU_VP);
490 #if 0   /* already done in board_init_r() */
491     void *data = (void *)(CFG_INIT_RAM_ADDR+CFG_INIT_DATA_OFFSET);
492     unsigned char data2[CFG_INIT_DATA_SIZE];
493
494     /*  Make a copy of the data */
495     memcpy(data2, data, CFG_INIT_DATA_SIZE);
496 #endif /* 0 */
497
498     /*  Invalidate and disable data cache */
499     invalidate_l1_data_cache();
500     dcache_disable();
501
502 #if 0
503     /*  Copy to the real RAM address */
504     memcpy(data, data2, CFG_INIT_DATA_SIZE);
505 #endif
506
507     /*printf("Before ICache enable\n");
508       show_bat_mapping();*/
509
510     __asm volatile ("isync        \n"
511                     "mtdbatu 2,%2 \n"
512                     "mtdbatl 2,%2 \n"
513                     "mtdbatu 1,%0 \n"
514                     "mtdbatl 1,%1 \n"
515                     "sync         \n"
516                     "isync        \n"
517                     : : "r" (batu), "r" (batl), "r" (0));
518
519     /* show_bat_mapping(); */
520     s = getenv("x86_cache");
521
522     if (!s || (s && strcmp(s, "on")==0))
523     {
524         icache_enable();
525         dcache_enable();
526     }
527
528 }