1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <asm/ddb5xxx/ddb5xxx.h>
#include <asm/ddb5xxx/debug.h>
#include <asm/ddb5xxx/pci.h>
static struct resource extpci_io_resource = {
"ext pci IO space",
DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE,
DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI0_IO_SIZE -1,
IORESOURCE_IO};
static struct resource extpci_mem_resource = {
"ext pci memory space",
DDB_PCI0_MEM_BASE,
DDB_PCI0_MEM_BASE + DDB_PCI0_MEM_SIZE -1,
IORESOURCE_MEM};
static struct resource iopci_io_resource = {
"io pci IO space",
DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE,
DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI1_IO_SIZE -1,
IORESOURCE_IO};
static struct resource iopci_mem_resource = {
"ext pci memory space",
DDB_PCI1_MEM_BASE,
DDB_PCI1_MEM_BASE + DDB_PCI1_MEM_SIZE -1,
IORESOURCE_MEM};
extern struct pci_ops ddb5477_ext_pci_ops;
extern struct pci_ops ddb5477_io_pci_ops;
struct pci_channel mips_pci_channels[] = {
{ &ddb5477_ext_pci_ops, &extpci_io_resource, &extpci_mem_resource },
{ &ddb5477_io_pci_ops, &iopci_io_resource, &iopci_mem_resource },
{ NULL, NULL, NULL}
};
/*
* we fix up irqs based on the slot number.
* The first entry is at AD:11.
* Fortunately this works because, although we have two pci buses,
* they all have different slot numbers.
*
* This does not work for devices on sub-buses.
*
* Note that the irq number in the array is relative number in vrc5477.
* We need to translate it to global irq number.
*/
/*
* irq mapping : PCI int # -> vrc5477 irq #
* based on vrc5477 manual page 46
*/
#define PCI_EXT_INTA 8
#define PCI_EXT_INTB 9
#define PCI_EXT_INTC 10
#define PCI_EXT_INTD 11
#define PCI_EXT_INTE 12
#define PCI_IO_INTA 16
#define PCI_IO_INTB 17
#define PCI_IO_INTC 18
#define PCI_IO_INTD 19
/*
* irq mapping : device -> pci int #,
* ddb5477 board manual page 4 and vrc5477 manual page 46
*/
#define INT_ONBOARD_TULIP PCI_EXT_INTA
#define INT_SLOT1 PCI_EXT_INTB
#define INT_SLOT2 PCI_EXT_INTC
#define INT_SLOT3 PCI_EXT_INTD
#define INT_SLOT4 PCI_EXT_INTE
#define INT_USB_HOST PCI_IO_INTA
#define INT_USB_PERI PCI_IO_INTB
#define INT_AC97 PCI_IO_INTC
/*
* based on ddb5477 manual page 11
*/
#define MAX_SLOT_NUM 21
static unsigned char irq_map[MAX_SLOT_NUM] = {
/* AD:11 */ 0xff, 0xff, 0xff, 0xff,
/* AD:15 */ INT_ONBOARD_TULIP, INT_SLOT1, INT_SLOT2, INT_SLOT3,
/* AD:19 */ INT_SLOT4, 0xff, 0xff, 0xff,
/* AD:23 */ 0xff, 0xff, 0xff, 0xff,
/* AD:27 */ 0xff, 0xff, INT_AC97, INT_USB_PERI,
/* AD:31 */ INT_USB_HOST
};
extern int vrc5477_irq_to_irq(int irq);
void __init pcibios_fixup_irqs(void)
{
struct pci_dev *dev;
int slot_num;
pci_for_each_dev(dev) {
slot_num = PCI_SLOT(dev->devfn);
MIPS_ASSERT(slot_num < MAX_SLOT_NUM);
MIPS_ASSERT(irq_map[slot_num] != 0xff);
pci_write_config_byte(dev,
PCI_INTERRUPT_LINE,
irq_map[slot_num]);
dev->irq = vrc5477_irq_to_irq(irq_map[slot_num]);
}
}
#if defined(CONFIG_LL_DEBUG)
extern void jsun_scan_pci_bus(void);
extern void jsun_assign_pci_resource(void);
#endif
void __init ddb_pci_reset_bus(void)
{
u32 temp;
/*
* I am not sure about the "official" procedure, the following
* steps work as far as I know:
* We first set PCI cold reset bit (bit 31) in PCICTRL-H.
* Then we clear the PCI warm reset bit (bit 30) to 0 in PCICTRL-H.
* The same is true for both PCI channels.
*/
temp = ddb_in32(DDB_PCICTL0_H);
temp |= 0x80000000;
ddb_out32(DDB_PCICTL0_H, temp);
temp &= ~0xc0000000;
ddb_out32(DDB_PCICTL0_H, temp);
temp = ddb_in32(DDB_PCICTL1_H);
temp |= 0x80000000;
ddb_out32(DDB_PCICTL1_H, temp);
temp &= ~0xc0000000;
ddb_out32(DDB_PCICTL1_H, temp);
}
|