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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [sh/] [kernel/] [pci_st40.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
3
 *
4
 * May be copied or modified under the terms of the GNU General Public
5
 * License.  See linux/COPYING for more information.
6
 *
7
 * Support functions for the ST40 PCI hardware.
8
 */
9
 
10
#include <linux/config.h>
11
#include <linux/kernel.h>
12
#include <linux/smp.h>
13
#include <linux/smp_lock.h>
14
#include <linux/init.h>
15
#include <linux/errno.h>
16
#include <linux/pci.h>
17
#include <linux/delay.h>
18
#include <linux/types.h>
19
#include <asm/pci.h>
20
#include <linux/irq.h>
21
 
22
#include "pci_st40.h"
23
 
24
static struct resource pci_io_space, pci_mem_space;
25
 
26
/* This is in P2 of course */
27
#define ST40PCI_BASE_ADDRESS     (0xb0000000)
28
#define ST40PCI_MEM_ADDRESS      (ST40PCI_BASE_ADDRESS+0x0)
29
#define ST40PCI_IO_ADDRESS       (ST40PCI_BASE_ADDRESS+0x06000000)
30
#define ST40PCI_REG_ADDRESS      (ST40PCI_BASE_ADDRESS+0x07000000)
31
 
32
#define ST40PCI_REG(x) (ST40PCI_REG_ADDRESS+(ST40PCI_##x))
33
#define ST40PCI_REG_INDEXED(reg, index)                                 \
34
        (ST40PCI_REG(reg##0) +                                  \
35
          ((ST40PCI_REG(reg##1) - ST40PCI_REG(reg##0))*index))
36
 
37
#define ST40PCI_WRITE(reg,val) writel((val),ST40PCI_REG(reg));udelay(2);
38
#define ST40PCI_WRITE_SHORT(reg,val) writew((val),ST40PCI_REG(reg));udelay(2);
39
#define ST40PCI_WRITE_BYTE(reg,val) writeb((val),ST40PCI_REG(reg));udelay(2);
40
#define ST40PCI_WRITE_INDEXED(reg, index, val)                          \
41
         writel((val), ST40PCI_REG_INDEXED(reg, index)); udelay(2);
42
 
43
#define ST40PCI_READ(reg) readl(ST40PCI_REG(reg))
44
#define ST40PCI_READ_SHORT(reg) readw(ST40PCI_REG(reg))
45
#define ST40PCI_READ_BYTE(reg) readb(ST40PCI_REG(reg))
46
#define ST40PCI_READ_INDEXED(reg, index) readl(ST40PCI_REG_INDEXED(reg, index))
47
 
48
#define ST40PCI_SERR_IRQ        64
49
#define ST40PCI_ERR_IRQ        65
50
#define ST40PCI_AD_INT                  66
51
#define ST40PCI_PWR_DWN_INT             67
52
 
53
#define PLLPCICR (0xbb040000+0x10)      // CLKGENA.PLL2CR
54
 
55
/* From ST's include/asm-sh/st40_clock.h */
56
/* Macros to extract PLL params */
57
#define PLL_MDIV(reg)  ( ((unsigned)reg) & 0xff )
58
#define PLL_NDIV(reg) ( (((unsigned)reg)>>8) & 0xff )
59
#define PLL_PDIV(reg) ( (((unsigned)reg)>>16) & 0x7 )
60
#define PLL_SETUP(reg) ( (((unsigned)reg)>>19) & 0x1ff )
61
 
62
/*
63
 * The pcibios_map_platform_irq function is defined in the appropraite
64
 * board specific code and referenced here
65
 */
66
extern int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin);
67
 
68
static void __init pcibios_assign_resources(void);
69
 
70
static __init void SetPCIPLL(void)
71
{
72
        {
73
                /* Lets play with the PLL values */
74
                unsigned long pll1cr1;
75
                unsigned long mdiv, ndiv, pdiv;
76
                unsigned long muxcr;
77
                unsigned int muxcr_ratios[4] = { 8, 16, 21, 1 };
78
                unsigned int freq;
79
 
80
#define CLKGENA            0xbb040000
81
#define CLKGENA_PLL2_MUXCR CLKGENA + 0x48
82
                pll1cr1 = ctrl_inl(PLLPCICR);
83
                printk("PLL1CR1 %08x\n", pll1cr1);
84
                mdiv = PLL_MDIV(pll1cr1);
85
                ndiv = PLL_NDIV(pll1cr1);
86
                pdiv = PLL_PDIV(pll1cr1);
87
                printk("mdiv %02x ndiv %02x pdiv %02x\n", mdiv, ndiv, pdiv);
88
                freq = ((2*27*ndiv)/mdiv) / (1 << pdiv);
89
                printk("PLL freq %dMHz\n", freq);
90
                muxcr = ctrl_inl(CLKGENA_PLL2_MUXCR);
91
                printk("PCI freq %dMhz\n", freq / muxcr_ratios[muxcr & 3]);
92
        }
93
}
94
 
95
 
96
struct pci_err {
97
  unsigned mask;
98
  const char *error_string;
99
};
100
 
101
 
102
static struct pci_err int_error[]={
103
  { INT_MNLTDIM,"MNLTDIM: Master non-lock transfer"},
104
  { INT_TTADI,  "TTADI: Illegal byte enable in I/O transfer"},
105
  { INT_TMTO,   "TMTO: Target memory read/write timeout"},
106
  { INT_MDEI,   "MDEI: Master function disable error"},
107
  { INT_APEDI,  "APEDI: Address parity error"},
108
  { INT_SDI,    "SDI: SERR detected"},
109
  { INT_DPEITW, "DPEITW: Data parity error target write"},
110
  { INT_PEDITR, "PEDITR: PERR detected"},
111
  { INT_TADIM,  "TADIM: Target abort detected"},
112
  { INT_MADIM,  "MADIM: Master abort detected"},
113
  { INT_MWPDI,  "MWPDI: PERR from target at data write"},
114
  { INT_MRDPEI, "MRDPEI: Master read data parity error"}
115
};
116
#define NUM_PCI_INT_ERRS (sizeof(int_error)/sizeof(struct pci_err))
117
 
118
static struct pci_err aint_error[]={
119
  { AINT_MBI,   "MBI: Master broken"},
120
  { AINT_TBTOI, "TBTOI: Target bus timeout"},
121
  { AINT_MBTOI, "MBTOI: Master bus timeout"},
122
  { AINT_TAI,   "TAI: Target abort"},
123
  { AINT_MAI,   "MAI: Master abort"},
124
  { AINT_RDPEI, "RDPEI: Read data parity"},
125
  { AINT_WDPE,  "WDPE: Write data parity"}
126
};
127
 
128
 
129
#define NUM_PCI_AINT_ERRS (sizeof(aint_error)/sizeof(struct pci_err))
130
 
131
static void print_pci_errors(unsigned reg,struct pci_err *error,int num_errors)
132
{
133
  int i;
134
 
135
  for(i=0;i<num_errors;i++) {
136
    if(reg & error[i].mask) {
137
      printk("%s\n",error[i].error_string);
138
    }
139
  }
140
 
141
}
142
 
143
 
144
static char * pci_commands[16]={
145
        "Int Ack",
146
        "Special Cycle",
147
        "I/O Read",
148
        "I/O Write",
149
        "Reserved",
150
        "Reserved",
151
        "Memory Read",
152
        "Memory Write",
153
        "Reserved",
154
        "Reserved",
155
        "Configuration Read",
156
        "Configuration Write",
157
        "Memory Read Multiple",
158
        "Dual Address Cycle",
159
        "Memory Read Line",
160
        "Memory Write-and-Invalidate"
161
};
162
 
163
 
164
static void st40_pci_irq(int irq, void *dev_instance, struct pt_regs *regs)
165
{
166
 
167
        unsigned pci_int, pci_air, pci_cir, pci_aint;
168
        static int count=0;
169
 
170
 
171
        pci_int = ST40PCI_READ(INT);pci_aint = ST40PCI_READ(AINT);
172
        pci_cir = ST40PCI_READ(CIR);pci_air = ST40PCI_READ(AIR);
173
 
174
        /* Reset state to stop multiple interrupts */
175
        ST40PCI_WRITE(INT, ~0); ST40PCI_WRITE(AINT, ~0);
176
 
177
 
178
        if(++count>1) return;
179
 
180
        printk("** PCI ERROR **\n");
181
 
182
        if(pci_int) {
183
                printk("** INT register status\n");
184
                print_pci_errors(pci_int,int_error,NUM_PCI_INT_ERRS);
185
        }
186
 
187
        if(pci_aint) {
188
                printk("** AINT register status\n");
189
                print_pci_errors(pci_aint,aint_error,NUM_PCI_AINT_ERRS);
190
        }
191
 
192
        printk("** Address and command info\n");
193
 
194
        printk("** Command  %s : Address 0x%x\n",
195
               pci_commands[pci_cir&0xf],pci_air);
196
 
197
        if(pci_cir&CIR_PIOTEM) {
198
                printk("CIR_PIOTEM:PIO transfer error for master\n");
199
        }
200
        if(pci_cir&CIR_RWTET) {
201
                printk("CIR_RWTET:Read/Write transfer error for target\n");
202
        }
203
}
204
 
205
 
206
/* Rounds a number UP to the nearest power of two. Used for
207
 * sizing the PCI window.
208
 */
209
static u32 r2p2(u32 num)
210
{
211
        int i = 31;
212
        u32 tmp = num;
213
 
214
        if (num == 0)
215
                return 0;
216
 
217
        do {
218
                if (tmp & (1 << 31))
219
                        break;
220
                i--;
221
                tmp <<= 1;
222
        } while (i >= 0);
223
 
224
        tmp = 1 << i;
225
        /* If the original number isn't a power of 2, round it up */
226
        if (tmp != num)
227
                tmp <<= 1;
228
 
229
        return tmp;
230
}
231
 
232
static void __init pci_fixup_ide_bases(struct pci_dev *d)
233
{
234
        int i;
235
 
236
        /*
237
         * PCI IDE controllers use non-standard I/O port decoding, respect it.
238
         */
239
        if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
240
                return;
241
        printk("PCI: IDE base address fixup for %s\n", d->slot_name);
242
        for(i=0; i<4; i++) {
243
                struct resource *r = &d->resource[i];
244
                if ((r->start & ~0x80) == 0x374) {
245
                        r->start |= 2;
246
                        r->end = r->start;
247
                }
248
        }
249
}
250
 
251
 
252
static void __init pci_fixup_cache_line(struct pci_dev *d)
253
{
254
        pci_write_config_byte(d,PCI_CACHE_LINE_SIZE,0);
255
}
256
 
257
 
258
/* Add future fixups here... */
259
struct pci_fixup pcibios_fixups[] = {
260
        { PCI_FIXUP_HEADER,     PCI_ANY_ID,     PCI_ANY_ID,     pci_fixup_ide_bases },
261
        { PCI_FIXUP_FINAL,      PCI_ANY_ID,     PCI_ANY_ID,     pci_fixup_cache_line },
262
        { 0 }
263
};
264
 
265
char * __init pcibios_setup(char *str)
266
{
267
        return str;
268
}
269
 
270
static void __init st40pci_init_resources(void)
271
{
272
        pci_io_space.start = PCIBIOS_MIN_IO;
273
        pci_io_space.end   = 64*1024 - PCIBIOS_MIN_IO - 1;
274
        pci_io_space.name = "ST40 PCI";
275
        pci_io_space.flags = IORESOURCE_IO;
276
 
277
        request_resource(&ioport_resource, &pci_io_space);
278
 
279
        pci_mem_space.start = PCIBIOS_MIN_MEM;
280
        pci_mem_space.end   = PCIBIOS_MIN_MEM + (96*1024*1024) -1;
281
        pci_mem_space.name = "ST40 PCI";
282
        pci_mem_space.flags = IORESOURCE_MEM;
283
 
284
        request_resource(&iomem_resource, &pci_mem_space);
285
}
286
 
287
int __init st40pci_init(unsigned memStart, unsigned memSize)
288
{
289
        u32 lsr0;
290
 
291
        printk("PCI version register reads 0x%x\n",ST40PCI_READ(VCR_VERSION));
292
 
293
        SetPCIPLL();
294
        st40pci_init_resources();
295
 
296
        /* Initialises the ST40 pci subsystem, performing a reset, then programming
297
         * up the address space decoders appropriately
298
         */
299
 
300
        /* Should reset core here as well methink */
301
 
302
        ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_SOFT_RESET);
303
 
304
        /* Loop while core resets */
305
        while (ST40PCI_READ(CR) & CR_SOFT_RESET);
306
 
307
        /* Switch off interrupts */
308
        ST40PCI_WRITE(INTM, 0);
309
        ST40PCI_WRITE(AINT, 0);
310
 
311
        /* Now, lets reset all the cards on the bus with extreme prejudice */
312
        ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_RSTCTL);
313
        udelay(250);
314
 
315
        /* Set bus active, take it out of reset */
316
        ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_BMAM | CR_CFINT | CR_PFCS | CR_PFE);
317
 
318
        /* The PCI spec says that no access must be made to the bus until 1 second
319
         * after reset. This seem ludicrously long, but some delay is needed here
320
         */
321
        mdelay(1000);
322
 
323
 
324
        /* Allow it to be a master */
325
 
326
        ST40PCI_WRITE_SHORT(CSR_CMD,
327
                            PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
328
                            PCI_COMMAND_IO);
329
 
330
        /* Accesse to the 0xb0000000 -> 0xb6000000 area will go through to 0x10000000 -> 0x16000000
331
         * on the PCI bus. This allows a nice 1-1 bus to phys mapping.
332
         */
333
 
334
 
335
        ST40PCI_WRITE(MBR, 0x10000000);
336
        /* Always set the max size 128M (actually, it is only 96MB wide) */
337
        ST40PCI_WRITE(MBMR, 0x07ff0000);
338
 
339
        /* I/O addresses are mapped at 0xb6000000 -> 0xb7000000. These are changed to 0, to
340
         * allow cards that have legacy io such as vga to function correctly. This gives a
341
         * maximum of 64K of io/space as only the bottom 16 bits of the address are copied
342
         * over to the bus  when the transaction is made. 64K of io space is more than enough
343
         */
344
        ST40PCI_WRITE(IOBR, 0x0);
345
        /* Set up the 64K window */
346
        ST40PCI_WRITE(IOBMR, 0x0);
347
 
348
        /* Now we set up the mbars so the PCI bus can see the local memory */
349
        /* Expose a 256M window starting at PCI address 0... */
350
        ST40PCI_WRITE(CSR_MBAR0, 0);
351
        ST40PCI_WRITE(LSR0, 0x0fff0001);
352
 
353
        /* ... and set up the initial incomming window to expose all of RAM */
354
        pci_set_rbar_region(7, memStart, memStart, memSize);
355
 
356
        /* Maximise timeout values */
357
        ST40PCI_WRITE_BYTE(CSR_TRDY, 0xff);
358
        ST40PCI_WRITE_BYTE(CSR_RETRY, 0xff);
359
        ST40PCI_WRITE_BYTE(CSR_MIT, 0xff);
360
 
361
        ST40PCI_WRITE_BYTE(PERF,PERF_MASTER_WRITE_POSTING);
362
 
363
        return 1;
364
}
365
 
366
#define SET_CONFIG_BITS(bus,devfn,where)\
367
  (((bus) << 16) | ((devfn) << 8) | ((where) & ~3) | (bus!=0))
368
 
369
#define CONFIG_CMD(dev, where) SET_CONFIG_BITS((dev)->bus->number,(dev)->devfn,where)
370
 
371
 
372
static int CheckForMasterAbort(void)
373
{
374
        if (ST40PCI_READ(INT) & INT_MADIM) {
375
                /* Should we clear config space version as well ??? */
376
                ST40PCI_WRITE(INT, INT_MADIM);
377
                ST40PCI_WRITE_SHORT(CSR_STATUS, PCI_RMA);
378
                return 1;
379
        }
380
 
381
        return 0;
382
}
383
 
384
/* Write to config register */
385
static int st40pci_read_config_byte(struct pci_dev *dev, int where,
386
                                    u8 * val)
387
{
388
        CheckForMasterAbort();
389
 
390
        ST40PCI_WRITE(PAR, CONFIG_CMD(dev, where));
391
 
392
        *val = ST40PCI_READ_BYTE(PDR + (where & 3));
393
 
394
        if (CheckForMasterAbort())
395
                *val = 0xff;
396
 
397
 
398
        return PCIBIOS_SUCCESSFUL;
399
}
400
 
401
static int st40pci_read_config_word(struct pci_dev *dev, int where,
402
                                    u16 * val)
403
{
404
        CheckForMasterAbort();
405
 
406
        ST40PCI_WRITE(PAR, CONFIG_CMD(dev, where));
407
 
408
        *val = ST40PCI_READ_SHORT(PDR + (where & 2));
409
 
410
        if (CheckForMasterAbort())
411
                *val = 0xffff;
412
 
413
        return PCIBIOS_SUCCESSFUL;
414
}
415
 
416
 
417
static int st40pci_read_config_dword(struct pci_dev *dev, int where,
418
                                     u32 * val)
419
{
420
        CheckForMasterAbort();
421
 
422
        ST40PCI_WRITE(PAR, CONFIG_CMD(dev, where));
423
 
424
        *val = ST40PCI_READ(PDR);
425
 
426
        if (CheckForMasterAbort()) {
427
                *val = 0xffffffff;
428
        }
429
 
430
        return PCIBIOS_SUCCESSFUL;
431
}
432
 
433
static int st40pci_write_config_byte(struct pci_dev *dev, int where,
434
                                     u8 val)
435
{
436
        ST40PCI_WRITE(PAR, CONFIG_CMD(dev, where));
437
 
438
        ST40PCI_WRITE_BYTE(PDR + (where & 3), val);
439
 
440
        CheckForMasterAbort();
441
 
442
        return PCIBIOS_SUCCESSFUL;
443
}
444
 
445
 
446
static int st40pci_write_config_word(struct pci_dev *dev, int where,
447
                                     u16 val)
448
{
449
        ST40PCI_WRITE(PAR, CONFIG_CMD(dev, where));
450
 
451
        ST40PCI_WRITE_SHORT(PDR + (where & 2), val);
452
 
453
        CheckForMasterAbort();
454
 
455
        return PCIBIOS_SUCCESSFUL;
456
}
457
 
458
static int st40pci_write_config_dword(struct pci_dev *dev, int where,
459
                                      u32 val)
460
{
461
        ST40PCI_WRITE(PAR, CONFIG_CMD(dev, where));
462
 
463
        ST40PCI_WRITE(PDR, val);
464
 
465
        CheckForMasterAbort();
466
 
467
        return PCIBIOS_SUCCESSFUL;
468
}
469
 
470
static struct pci_ops pci_config_ops = {
471
        st40pci_read_config_byte,
472
        st40pci_read_config_word,
473
        st40pci_read_config_dword,
474
        st40pci_write_config_byte,
475
        st40pci_write_config_word,
476
        st40pci_write_config_dword
477
};
478
 
479
 
480
/* Everything hangs off this */
481
static struct pci_bus *pci_root_bus;
482
 
483
 
484
static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
485
{
486
        printk("swizzle for dev %d on bus %d slot %d pin is %d\n",
487
               dev->devfn,dev->bus->number, PCI_SLOT(dev->devfn),*pin);
488
        return PCI_SLOT(dev->devfn);
489
}
490
 
491
static inline u8 bridge_swizzle(u8 pin, u8 slot)
492
{
493
        return (((pin-1) + slot) % 4) + 1;
494
}
495
 
496
u8 __init common_swizzle(struct pci_dev *dev, u8 *pinp)
497
{
498
        if (dev->bus->number != 0) {
499
                u8 pin = *pinp;
500
                do {
501
                        pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
502
                        /* Move up the chain of bridges. */
503
                        dev = dev->bus->self;
504
                } while (dev->bus->self);
505
                *pinp = pin;
506
 
507
                /* The slot is the slot of the last bridge. */
508
        }
509
 
510
        return PCI_SLOT(dev->devfn);
511
}
512
 
513
void __init
514
pcibios_fixup_pbus_ranges(struct pci_bus *bus,
515
                          struct pbus_set_ranges_data *ranges)
516
{
517
}
518
 
519
void __init pcibios_init(void)
520
{
521
        extern unsigned long memory_start, memory_end;
522
 
523
        if (sh_mv.mv_init_pci != NULL) {
524
                sh_mv.mv_init_pci();
525
        }
526
 
527
        /* The pci subsytem needs to know where memory is and how much
528
         * of it there is. I've simply made these globals. A better mechanism
529
         * is probably needed.
530
         */
531
        st40pci_init(PHYSADDR(memory_start),
532
                     PHYSADDR(memory_end) - PHYSADDR(memory_start));
533
 
534
        if (request_irq(ST40PCI_SERR_IRQ, st40_pci_irq,
535
                        SA_INTERRUPT, "st40pci", NULL)) {
536
                printk(KERN_ERR "st40pci: Cannot hook interrupt\n");
537
                return;
538
        }
539
 
540
        if (request_irq(ST40PCI_ERR_IRQ, st40_pci_irq,
541
                        SA_INTERRUPT, "st40pci", NULL)) {
542
                printk(KERN_ERR "st40pci: Cannot hook interrupt\n");
543
                return;
544
        }
545
 
546
        /* Reset state just in case any outstanding (usually SERR) */
547
        ST40PCI_WRITE(INT, ~0); ST40PCI_WRITE(AINT, ~0);
548
        /* Enable the PCI interrupts on the device */
549
        ST40PCI_WRITE(INTM, ~0);
550
        ST40PCI_WRITE(AINT, ~0);
551
 
552
        /* Map the io address apprioately */
553
#ifdef CONFIG_HD64465
554
        hd64465_port_map(PCIBIOS_MIN_IO, (64 * 1024) - PCIBIOS_MIN_IO + 1,
555
                         ST40_IO_ADDR + PCIBIOS_MIN_IO, 0);
556
#endif
557
 
558
        /* ok, do the scan man */
559
        pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL);
560
        pci_assign_unassigned_resources();
561
        pci_fixup_irqs(no_swizzle, pcibios_map_platform_irq);
562
 
563
}
564
 
565
void __init
566
pcibios_fixup_resource(struct resource *res, struct resource *root)
567
{
568
        res->start += root->start;
569
        res->end += root->start;
570
}
571
 
572
void __init
573
pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus)
574
{
575
        /* Update device resources.  */
576
        int i;
577
 
578
        for (i = 0; i < PCI_NUM_RESOURCES; i++) {
579
                if (!dev->resource[i].start)
580
                        continue;
581
                if (dev->resource[i].flags & IORESOURCE_IO)
582
                        pcibios_fixup_resource(&dev->resource[i],
583
                                               &pci_io_space);
584
                else if (dev->resource[i].flags & IORESOURCE_MEM)
585
                        pcibios_fixup_resource(&dev->resource[i],
586
                                               &pci_mem_space);
587
        }
588
}
589
 
590
void __init pcibios_fixup_bus(struct pci_bus *bus)
591
{
592
        /* Propogate hose info into the subordinate devices.  */
593
        struct list_head *ln;
594
        struct pci_dev *dev = bus->self;
595
 
596
        if (!dev) {
597
                bus->resource[0] = &pci_io_space;
598
                bus->resource[1] = &pci_mem_space;
599
        }
600
 
601
        for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
602
                struct pci_dev *dev = pci_dev_b(ln);
603
                if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
604
                        pcibios_fixup_device_resources(dev, bus);
605
        }
606
}
607
 
608
static void __init pcibios_assign_resources(void)
609
{
610
        struct pci_dev *dev;
611
        int idx;
612
        struct resource *r;
613
        pci_for_each_dev(dev) {
614
                int class = dev->class >> 8;
615
 
616
                /* Don't touch classless devices and host bridges */
617
                if (!class || class == PCI_CLASS_BRIDGE_HOST)
618
                        continue;
619
 
620
                for(idx=0; idx<6; idx++) {
621
                        r = &dev->resource[idx];
622
 
623
                        /*
624
                         *  Don't touch IDE controllers and I/O ports of video cards!
625
                         */
626
                        if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) ||
627
                            (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))
628
                                continue;
629
 
630
                        /*
631
                         *  We shall assign a new address to this resource, either because
632
                         *  the BIOS forgot to do so or because we have decided the old
633
                         *  address was unusable for some reason.
634
                         */
635
                        if (!r->start && r->end)
636
                        {
637
                                pci_assign_resource(dev, idx);
638
                         }
639
                }
640
#if 0 /* don't assign ROMs */
641
                if (pci_probe & PCI_ASSIGN_ROMS) {
642
                        r = &dev->resource[PCI_ROM_RESOURCE];
643
                        r->end -= r->start;
644
                        r->start = 0;
645
                        if (r->end)
646
                                pci_assign_resource(dev, PCI_ROM_RESOURCE);
647
                }
648
#endif
649
        }
650
}
651
 
652
/*
653
 * Publish a region of local address space over the PCI bus
654
 * to other devices.
655
 */
656
void pci_set_rbar_region(unsigned int region,     unsigned long localAddr,
657
                         unsigned long pciOffset, unsigned long regionSize)
658
{
659
        unsigned long mask;
660
 
661
        if (region > 7)
662
                return;
663
 
664
        if (regionSize > (512 * 1024 * 1024))
665
                return;
666
 
667
        mask = r2p2(regionSize) - 0x10000;
668
 
669
        /* Diable the region (in case currently in use, should never happen) */
670
        ST40PCI_WRITE_INDEXED(RSR, region, 0);
671
 
672
        /* Start of local address space to publish */
673
        ST40PCI_WRITE_INDEXED(RLAR, region, PHYSADDR(localAddr) );
674
 
675
        /* Start of region in PCI address space as an offset from MBAR0 */
676
        ST40PCI_WRITE_INDEXED(RBAR, region, pciOffset);
677
 
678
        /* Size of region */
679
        ST40PCI_WRITE_INDEXED(RSR, region, mask | 1);
680
}
681
 
682
/*
683
 * Make a previously published region of local address space
684
 * inaccessible to other PCI devices.
685
 */
686
void pci_clear_rbar_region(unsigned int region)
687
{
688
        if (region > 7)
689
                return;
690
 
691
        ST40PCI_WRITE_INDEXED(RSR, region, 0);
692
        ST40PCI_WRITE_INDEXED(RBAR, region, 0);
693
        ST40PCI_WRITE_INDEXED(RLAR, region, 0);
694
}

powered by: WebSVN 2.1.0

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