2 * arch/ppc/platforms/adir_pci.c
4 * PCI support for SBS Adirondack
6 * By Michael Sokolov <msokolov@ivan.Harhan.ORG>
7 * based on the K2 version by Matt Porter <mporter@mvista.com>
10 #include <linux/kernel.h>
11 #include <linux/init.h>
12 #include <linux/pci.h>
13 #include <linux/slab.h>
15 #include <asm/byteorder.h>
17 #include <asm/uaccess.h>
18 #include <asm/machdep.h>
19 #include <asm/pci-bridge.h>
21 #include <syslib/cpc710.h>
26 #define DBG(x...) printk(x)
31 static inline int __init
32 adir_map_irq(struct pci_dev
*dev
, unsigned char idsel
, unsigned char pin
)
34 #define PCIIRQ(a,b,c,d) {ADIR_IRQ_##a,ADIR_IRQ_##b,ADIR_IRQ_##c,ADIR_IRQ_##d},
35 struct pci_controller
*hose
= pci_bus_to_hose(dev
->bus
->number
);
37 * The three PCI devices on the motherboard have dedicated lines to the
38 * CPLD interrupt controller, bypassing the standard PCI INTA-D and the
39 * PC interrupt controller. All other PCI devices (slots) have usual
40 * staggered INTA-D lines, resulting in 8 lines total (PCI0 INTA-D and
41 * PCI1 INTA-D). All 8 go to the CPLD interrupt controller. PCI0 INTA-D
42 * also go to the south bridge, so we have the option of taking them
43 * via the CPLD interrupt controller or via the south bridge 8259
44 * 8258 thingy. PCI1 INTA-D can only be taken via the CPLD interrupt
45 * controller. We take all PCI interrupts via the CPLD interrupt
46 * controller as recommended by SBS.
48 * We also have some monkey business with the PCI devices within the
49 * VT82C686B south bridge itself. This chip actually has 7 functions on
50 * its IDSEL. Function 0 is the actual south bridge, function 1 is IDE,
51 * and function 4 is some special stuff. The other 4 functions are just
52 * regular PCI devices bundled in the chip. 2 and 3 are USB UHCIs and 5
53 * and 6 are audio (not supported on the Adirondack).
55 * This is where the monkey business begins. PCI devices are supposed
56 * to signal normal PCI interrupts. But the 4 functions in question are
57 * located in the south bridge chip, which is designed with the
58 * assumption that it will be fielding PCI INTA-D interrupts rather
59 * than generating them. Here's what it does. Each of the functions in
60 * question routes its interrupt to one of the IRQs on the 8259 thingy.
61 * Which one? It looks at the Interrupt Line register in the PCI config
62 * space, even though the PCI spec says it's for BIOS/OS interaction
65 * How do we deal with this? We take these interrupts via 8259 IRQs as
66 * we have to. We return the desired IRQ numbers from this routine when
67 * called for the functions in question. The PCI scan code will then
68 * stick our return value into the Interrupt Line register in the PCI
69 * config space, and the interrupt will actually go there. We identify
70 * these functions within the south bridge IDSEL by their interrupt pin
71 * numbers, as the VT82C686B has 04 in the Interrupt Pin register for
72 * USB and 03 for audio.
75 static char pci_irq_table
[][4] =
77 * PCI IDSEL/INTPIN->INTLINE
81 /* south bridge */ PCIIRQ(IDE0
, NONE
, VIA_AUDIO
, VIA_USB
)
82 /* Ethernet 0 */ PCIIRQ(MBETH0
, MBETH0
, MBETH0
, MBETH0
)
83 /* PCI0 slot 1 */ PCIIRQ(PCI0_INTB
, PCI0_INTC
, PCI0_INTD
, PCI0_INTA
)
84 /* PCI0 slot 2 */ PCIIRQ(PCI0_INTC
, PCI0_INTD
, PCI0_INTA
, PCI0_INTB
)
85 /* PCI0 slot 3 */ PCIIRQ(PCI0_INTD
, PCI0_INTA
, PCI0_INTB
, PCI0_INTC
)
87 const long min_idsel
= 3, max_idsel
= 7, irqs_per_slot
= 4;
88 return PCI_IRQ_TABLE_LOOKUP
;
90 static char pci_irq_table
[][4] =
92 * PCI IDSEL/INTPIN->INTLINE
96 /* Ethernet 1 */ PCIIRQ(MBETH1
, MBETH1
, MBETH1
, MBETH1
)
97 /* SCSI */ PCIIRQ(MBSCSI
, MBSCSI
, MBSCSI
, MBSCSI
)
98 /* PCI1 slot 1 */ PCIIRQ(PCI1_INTB
, PCI1_INTC
, PCI1_INTD
, PCI1_INTA
)
99 /* PCI1 slot 2 */ PCIIRQ(PCI1_INTC
, PCI1_INTD
, PCI1_INTA
, PCI1_INTB
)
100 /* PCI1 slot 3 */ PCIIRQ(PCI1_INTD
, PCI1_INTA
, PCI1_INTB
, PCI1_INTC
)
102 const long min_idsel
= 3, max_idsel
= 7, irqs_per_slot
= 4;
103 return PCI_IRQ_TABLE_LOOKUP
;
109 adir_pcibios_fixup_resources(struct pci_dev
*dev
)
113 if ((dev
->vendor
== PCI_VENDOR_ID_IBM
) &&
114 (dev
->device
== PCI_DEVICE_ID_IBM_CPC710_PCI64
))
116 DBG("Fixup CPC710 resources\n");
117 for (i
=0; i
<DEVICE_COUNT_RESOURCE
; i
++)
119 dev
->resource
[i
].start
= 0;
120 dev
->resource
[i
].end
= 0;
126 * CPC710 DD3 has an errata causing it to hang the system if a type 0 config
127 * cycle is attempted on its PCI32 interface with a device number > 21.
128 * CPC710's PCI bridges map device numbers 1 through 21 to AD11 through AD31.
129 * Per the PCI spec it MUST accept all other device numbers and do nothing, and
130 * software MUST scan all device numbers without assuming how IDSELs are
131 * mapped. However, as the CPC710 DD3's errata causes such correct scanning
132 * procedure to hang the system, we have no choice but to introduce this hack
133 * of knowingly avoiding device numbers > 21 on PCI0,
136 adir_exclude_device(u_char bus
, u_char devfn
)
138 if ((bus
== 0) && (PCI_SLOT(devfn
) > 21))
139 return PCIBIOS_DEVICE_NOT_FOUND
;
141 return PCIBIOS_SUCCESSFUL
;
144 void adir_find_bridges(void)
146 struct pci_controller
*hose_a
, *hose_b
;
148 /* Setup PCI32 hose */
149 hose_a
= pcibios_alloc_controller();
153 hose_a
->first_busno
= 0;
154 hose_a
->last_busno
= 0xff;
155 hose_a
->pci_mem_offset
= ADIR_PCI32_MEM_BASE
;
156 hose_a
->io_space
.start
= 0;
157 hose_a
->io_space
.end
= ADIR_PCI32_VIRT_IO_SIZE
- 1;
158 hose_a
->mem_space
.start
= 0;
159 hose_a
->mem_space
.end
= ADIR_PCI32_MEM_SIZE
- 1;
160 hose_a
->io_resource
.start
= 0;
161 hose_a
->io_resource
.end
= ADIR_PCI32_VIRT_IO_SIZE
- 1;
162 hose_a
->io_resource
.flags
= IORESOURCE_IO
;
163 hose_a
->mem_resources
[0].start
= ADIR_PCI32_MEM_BASE
;
164 hose_a
->mem_resources
[0].end
= ADIR_PCI32_MEM_BASE
+
165 ADIR_PCI32_MEM_SIZE
- 1;
166 hose_a
->mem_resources
[0].flags
= IORESOURCE_MEM
;
167 hose_a
->io_base_phys
= ADIR_PCI32_IO_BASE
;
168 hose_a
->io_base_virt
= (void *) ADIR_PCI32_VIRT_IO_BASE
;
170 ppc_md
.pci_exclude_device
= adir_exclude_device
;
171 setup_indirect_pci(hose_a
, ADIR_PCI32_CONFIG_ADDR
,
172 ADIR_PCI32_CONFIG_DATA
);
174 /* Initialize PCI32 bus registers */
175 early_write_config_byte(hose_a
,
179 hose_a
->first_busno
);
180 early_write_config_byte(hose_a
,
183 CPC710_SUB_BUS_NUMBER
,
186 hose_a
->last_busno
= pciauto_bus_scan(hose_a
, hose_a
->first_busno
);
188 /* Write out correct max subordinate bus number for hose A */
189 early_write_config_byte(hose_a
,
192 CPC710_SUB_BUS_NUMBER
,
195 /* Setup PCI64 hose */
196 hose_b
= pcibios_alloc_controller();
200 hose_b
->first_busno
= hose_a
->last_busno
+ 1;
201 hose_b
->last_busno
= 0xff;
202 hose_b
->pci_mem_offset
= ADIR_PCI64_MEM_BASE
;
203 hose_b
->io_space
.start
= 0;
204 hose_b
->io_space
.end
= ADIR_PCI64_VIRT_IO_SIZE
- 1;
205 hose_b
->mem_space
.start
= 0;
206 hose_b
->mem_space
.end
= ADIR_PCI64_MEM_SIZE
- 1;
207 hose_b
->io_resource
.start
= 0;
208 hose_b
->io_resource
.end
= ADIR_PCI64_VIRT_IO_SIZE
- 1;
209 hose_b
->io_resource
.flags
= IORESOURCE_IO
;
210 hose_b
->mem_resources
[0].start
= ADIR_PCI64_MEM_BASE
;
211 hose_b
->mem_resources
[0].end
= ADIR_PCI64_MEM_BASE
+
212 ADIR_PCI64_MEM_SIZE
- 1;
213 hose_b
->mem_resources
[0].flags
= IORESOURCE_MEM
;
214 hose_b
->io_base_phys
= ADIR_PCI64_IO_BASE
;
215 hose_b
->io_base_virt
= (void *) ADIR_PCI64_VIRT_IO_BASE
;
217 setup_indirect_pci(hose_b
, ADIR_PCI64_CONFIG_ADDR
,
218 ADIR_PCI64_CONFIG_DATA
);
220 /* Initialize PCI64 bus registers */
221 early_write_config_byte(hose_b
,
224 CPC710_SUB_BUS_NUMBER
,
227 early_write_config_byte(hose_b
,
231 hose_b
->first_busno
);
233 hose_b
->last_busno
= pciauto_bus_scan(hose_b
,
234 hose_b
->first_busno
);
236 /* Write out correct max subordinate bus number for hose B */
237 early_write_config_byte(hose_b
,
240 CPC710_SUB_BUS_NUMBER
,
243 ppc_md
.pcibios_fixup
= NULL
;
244 ppc_md
.pcibios_fixup_resources
= adir_pcibios_fixup_resources
;
245 ppc_md
.pci_swizzle
= common_swizzle
;
246 ppc_md
.pci_map_irq
= adir_map_irq
;