2 * arch/ppc/platforms/pplus_pci.c
4 * PCI setup for MCG PowerPlus
6 * Author: Randy Vinson <rvinson@mvista.com>
8 * Derived from original PowerPlus PReP work by
9 * Cort Dougan, Johnnie Peters, Matt Porter, and
12 * Copyright 2001 MontaVista Software Inc.
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include <linux/config.h>
25 #include <linux/types.h>
26 #include <linux/pci.h>
27 #include <linux/kernel.h>
28 #include <linux/init.h>
30 #include <asm/sections.h>
31 #include <asm/byteorder.h>
33 #include <asm/ptrace.h>
34 #include <asm/pci-bridge.h>
35 #include <asm/residual.h>
36 #include <asm/processor.h>
38 #include <asm/machdep.h>
40 #include <asm/open_pic.h>
41 #include <asm/pplus.h>
43 unsigned char *Motherboard_map_name;
45 /* Tables for known hardware */
47 /* Motorola Mesquite */
49 mesquite_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
51 static char pci_irq_table[][4] =
53 * MPIC interrupts for various IDSEL values (MPIC IRQ0 =
54 * Linux IRQ16 (to leave room for ISA IRQs at 0-15).
55 * PCI IDSEL/INTPIN->INTLINE
59 { 18, 0, 0, 0 }, /* IDSEL 14 - Enet 0 */
60 { 0, 0, 0, 0 }, /* IDSEL 15 - unused */
61 { 19, 19, 19, 19 }, /* IDSEL 16 - PMC Slot 1 */
62 { 0, 0, 0, 0 }, /* IDSEL 17 - unused */
63 { 0, 0, 0, 0 }, /* IDSEL 18 - unused */
64 { 0, 0, 0, 0 }, /* IDSEL 19 - unused */
65 { 24, 25, 26, 27 }, /* IDSEL 20 - P2P bridge (to cPCI 1) */
66 { 0, 0, 0, 0 }, /* IDSEL 21 - unused */
67 { 28, 29, 30, 31 } /* IDSEL 22 - P2P bridge (to cPCI 2) */
70 const long min_idsel = 14, max_idsel = 22, irqs_per_slot = 4;
71 return PCI_IRQ_TABLE_LOOKUP;
76 sitka_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
78 static char pci_irq_table[][4] =
80 * MPIC interrupts for various IDSEL values (MPIC IRQ0 =
81 * Linux IRQ16 (to leave room for ISA IRQs at 0-15).
82 * PCI IDSEL/INTPIN->INTLINE
86 { 18, 0, 0, 0 }, /* IDSEL 14 - Enet 0 */
87 { 0, 0, 0, 0 }, /* IDSEL 15 - unused */
88 { 25, 26, 27, 28 }, /* IDSEL 16 - PMC Slot 1 */
89 { 28, 25, 26, 27 }, /* IDSEL 17 - PMC Slot 2 */
90 { 0, 0, 0, 0 }, /* IDSEL 18 - unused */
91 { 0, 0, 0, 0 }, /* IDSEL 19 - unused */
92 { 20, 0, 0, 0 } /* IDSEL 20 - P2P bridge (to cPCI) */
95 const long min_idsel = 14, max_idsel = 20, irqs_per_slot = 4;
96 return PCI_IRQ_TABLE_LOOKUP;
101 MTX_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
103 static char pci_irq_table[][4] =
105 * MPIC interrupts for various IDSEL values (MPIC IRQ0 =
106 * Linux IRQ16 (to leave room for ISA IRQs at 0-15).
107 * PCI IDSEL/INTPIN->INTLINE
111 { 19, 0, 0, 0 }, /* IDSEL 12 - SCSI */
112 { 0, 0, 0, 0 }, /* IDSEL 13 - unused */
113 { 18, 0, 0, 0 }, /* IDSEL 14 - Enet */
114 { 0, 0, 0, 0 }, /* IDSEL 15 - unused */
115 { 25, 26, 27, 28 }, /* IDSEL 16 - PMC Slot 1 */
116 { 26, 27, 28, 25 }, /* IDSEL 17 - PMC Slot 2 */
117 { 27, 28, 25, 26 } /* IDSEL 18 - PCI Slot 3 */
120 const long min_idsel = 12, max_idsel = 18, irqs_per_slot = 4;
121 return PCI_IRQ_TABLE_LOOKUP;
124 /* Motorola MTX Plus */
125 /* Secondary bus interrupt routing is not supported yet */
127 MTXplus_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
129 static char pci_irq_table[][4] =
131 * MPIC interrupts for various IDSEL values (MPIC IRQ0 =
132 * Linux IRQ16 (to leave room for ISA IRQs at 0-15).
133 * PCI IDSEL/INTPIN->INTLINE
137 { 19, 0, 0, 0 }, /* IDSEL 12 - SCSI */
138 { 0, 0, 0, 0 }, /* IDSEL 13 - unused */
139 { 18, 0, 0, 0 }, /* IDSEL 14 - Enet 1 */
140 { 0, 0, 0, 0 }, /* IDSEL 15 - unused */
141 { 25, 26, 27, 28 }, /* IDSEL 16 - PCI Slot 1P */
142 { 26, 27, 28, 25 }, /* IDSEL 17 - PCI Slot 2P */
143 { 27, 28, 25, 26 }, /* IDSEL 18 - PCI Slot 3P */
144 { 26, 0, 0, 0 }, /* IDSEL 19 - Enet 2 */
145 { 0, 0, 0, 0 } /* IDSEL 20 - P2P Bridge */
148 const long min_idsel = 12, max_idsel = 20, irqs_per_slot = 4;
149 return PCI_IRQ_TABLE_LOOKUP;
153 Genesis2_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
162 * PMC1 16 - IRQ9,10,11,12 = PMC1 A-D
163 * PMC2 17 - IRQ12,9,10,11 = A-D
166 * PCIX 20 - IRQ9,10,11,12 = PCI A-D
174 * PMC1 16 - IRQ9,10,11,12 = PMC A-D
175 * PMC2 17 - IRQ12,9,10,11 = PMC A-D
176 * PCIX 20 - IRQ9,10,11,12 = PMC A-D
184 * PMC1 16 - 9,10,11,12 = A-D
185 * PMC2 17 - 9,10,11,12 = B,C,D,A
188 static char pci_irq_table[][4] =
190 * MPIC interrupts for various IDSEL values (MPIC IRQ0 =
191 * Linux IRQ16 (to leave room for ISA IRQs at 0-15).
192 * PCI IDSEL/INTPIN->INTLINE
196 { 19, 0, 0, 0 }, /* IDSEL 12 - SCSI */
197 { 0, 0, 0, 0 }, /* IDSEL 13 - Universe PCI - VME */
198 { 18, 0, 0, 0 }, /* IDSEL 14 - Enet 1 */
199 { 0, 0, 0, 0 }, /* IDSEL 15 - unused */
200 { 25, 26, 27, 28 }, /* IDSEL 16 - PCI/PMC Slot 1P */
201 { 28, 25, 26, 27 }, /* IDSEL 17 - PCI/PMC Slot 2P */
202 { 27, 28, 25, 26 }, /* IDSEL 18 - PCI Slot 3P */
203 { 26, 0, 0, 0 }, /* IDSEL 19 - Enet 2 */
204 { 25, 26, 27, 28 } /* IDSEL 20 - P2P Bridge */
207 const long min_idsel = 12, max_idsel = 20, irqs_per_slot = 4;
208 return PCI_IRQ_TABLE_LOOKUP;
211 #define MOTOROLA_CPUTYPE_REG 0x800
212 #define MOTOROLA_BASETYPE_REG 0x803
213 #define MPIC_RAVEN_ID 0x48010000
214 #define MPIC_HAWK_ID 0x48030000
215 #define MOT_PROC2_BIT 0x800
217 static u_char pplus_openpic_initsenses[] __initdata = {
218 (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),/* MVME2600_INT_SIO */
219 (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE),/*MVME2600_INT_FALCN_ECC_ERR*/
220 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/*MVME2600_INT_PCI_ETHERNET */
221 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* MVME2600_INT_PCI_SCSI */
222 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* MVME2600_INT_PCI_GRAPHICS*/
223 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* MVME2600_INT_PCI_VME0 */
224 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* MVME2600_INT_PCI_VME1 */
225 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* MVME2600_INT_PCI_VME2 */
226 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* MVME2600_INT_PCI_VME3 */
227 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* MVME2600_INT_PCI_INTA */
228 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* MVME2600_INT_PCI_INTB */
229 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* MVME2600_INT_PCI_INTC */
230 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* MVME2600_INT_PCI_INTD */
231 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* MVME2600_INT_LM_SIG0 */
232 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* MVME2600_INT_LM_SIG1 */
233 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),
237 int prep_keybd_present = 1;
240 int __init raven_init(void)
242 unsigned short devid;
243 unsigned char base_mod;
245 /* set the MPIC base address */
246 early_write_config_dword(0, 0, 0, PCI_BASE_ADDRESS_1, 0x3cfc0000);
248 pplus_mpic_init(PREP_ISA_MEM_BASE);
250 OpenPIC_InitSenses = pplus_openpic_initsenses;
251 OpenPIC_NumInitSenses = sizeof(pplus_openpic_initsenses);
253 ppc_md.get_irq = openpic_get_irq;
255 /* This is a hack. If this is a 2300 or 2400 mot board then there is
256 * no keyboard controller and we have to indicate that.
259 early_read_config_word(0, 0, 0, PCI_VENDOR_ID, &devid);
260 base_mod = inb(MOTOROLA_BASETYPE_REG);
261 if ((devid == PCI_DEVICE_ID_MOTOROLA_HAWK) ||
262 (base_mod == 0xF9) ||
263 (base_mod == 0xFA) || (base_mod == 0xE1))
264 prep_keybd_present = 0;
270 int cpu_type; /* 0x100 mask assumes for Raven and Hawk boards that the level/edge are set */
271 /* 0x200 if this board has a Hawk chip. */
273 int max_cpu; /* ored with 0x80 if this board should be checked for multi CPU */
275 int (*map_irq)(struct pci_dev *,
279 struct brd_info mot_info[] = {
280 {0x300, 0x00, 0x00, "MVME 2400", Genesis2_map_irq},
281 {0x1E0, 0xE0, 0x00, "Mesquite cPCI (MCP750)", mesquite_map_irq},
282 {0x1E0, 0xE1, 0x00, "Sitka cPCI (MCPN750)", sitka_map_irq},
283 {0x1E0, 0xE2, 0x00, "Mesquite cPCI (MCP750) w/ HAC", mesquite_map_irq},
284 {0x1E0, 0xF6, 0x80, "MTX Plus", MTXplus_map_irq},
285 {0x1E0, 0xF6, 0x81, "Dual MTX Plus", MTXplus_map_irq},
286 {0x1E0, 0xF7, 0x80, "MTX wo/ Parallel Port", MTX_map_irq},
287 {0x1E0, 0xF7, 0x81, "Dual MTX wo/ Parallel Port", MTX_map_irq},
288 {0x1E0, 0xF8, 0x80, "MTX w/ Parallel Port", MTX_map_irq},
289 {0x1E0, 0xF8, 0x81, "Dual MTX w/ Parallel Port", MTX_map_irq},
290 {0x1E0, 0xF9, 0x00, "MVME 2300", Genesis2_map_irq},
291 {0x1E0, 0xFA, 0x00, "MVME 2300SC/2600", Genesis2_map_irq},
292 {0x1E0, 0xFB, 0x00, "MVME 2600 with MVME712M", Genesis2_map_irq},
293 {0x1E0, 0xFC, 0x00, "MVME 2600/2700 with MVME761", Genesis2_map_irq},
294 {0x1E0, 0xFD, 0x80, "MVME 3600 with MVME712M", Genesis2_map_irq},
295 {0x1E0, 0xFD, 0x81, "MVME 4600 with MVME712M", Genesis2_map_irq},
296 {0x1E0, 0xFE, 0x80, "MVME 3600 with MVME761", Genesis2_map_irq},
297 {0x1E0, 0xFE, 0x81, "MVME 4600 with MVME761", Genesis2_map_irq},
298 {0x000, 0x00, 0x00, "", NULL}
301 void __init pplus_set_board_type(void)
303 unsigned char cpu_type;
304 unsigned char base_mod;
306 unsigned short devid;
307 unsigned long *ProcInfo = NULL;
309 cpu_type = inb(MOTOROLA_CPUTYPE_REG) & 0xF0;
310 base_mod = inb(MOTOROLA_BASETYPE_REG);
311 early_read_config_word(0, 0, 0, PCI_VENDOR_ID, &devid);
313 for (entry = 0; mot_info[entry].cpu_type != 0; entry++) {
315 /* Check for Hawk chip */
316 if (mot_info[entry].cpu_type & 0x200) {
317 if (devid != PCI_DEVICE_ID_MOTOROLA_HAWK)
320 /* store the system config register for later use. */
321 ProcInfo = (unsigned long *)ioremap(0xfef80400, 4);
323 /* Check non hawk boards */
324 if ((mot_info[entry].cpu_type & 0xff) != cpu_type)
327 if (mot_info[entry].base_type == 0) {
332 if (mot_info[entry].base_type != base_mod)
336 if (!(mot_info[entry].max_cpu & 0x80)) {
341 /* processor 1 not present and max processor zero indicated */
342 if ((*ProcInfo & MOT_PROC2_BIT) && !(mot_info[entry].max_cpu & 0x7f)) {
347 /* processor 1 present and max processor zero indicated */
348 if (!(*ProcInfo & MOT_PROC2_BIT) && (mot_info[entry].max_cpu & 0x7f)) {
353 /* Indicate to system if this is a multiprocessor board */
354 if (!(*ProcInfo & MOT_PROC2_BIT)) {
361 /* No particular cpu type found - assume Mesquite (MCP750) */
364 Motherboard_map_name = (unsigned char *)mot_info[mot_entry].name;
365 ppc_md.pci_map_irq = mot_info[mot_entry].map_irq;
371 unsigned short short_reg;
373 struct pci_dev *dev = NULL;
376 * Perform specific configuration for the Via Tech or
377 * or Winbond PCI-ISA-Bridge part.
379 if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
380 PCI_DEVICE_ID_VIA_82C586_1, dev))) {
382 * PPCBUG does not set the enable bits
383 * for the IDE device. Force them on here.
385 pci_read_config_byte(dev, 0x40, ®);
387 reg |= 0x03; /* IDE: Chip Enable Bits */
388 pci_write_config_byte(dev, 0x40, reg);
390 if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
391 PCI_DEVICE_ID_VIA_82C586_2,
392 dev)) && (dev->devfn = 0x5a)) {
393 /* Force correct USB interrupt */
395 pci_write_config_byte(dev,
399 if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND,
400 PCI_DEVICE_ID_WINBOND_83C553, dev))) {
401 /* Clear PCI Interrupt Routing Control Register. */
403 pci_write_config_word(dev, 0x44, short_reg);
404 /* Route IDE interrupts to IRQ 14 */
406 pci_write_config_byte(dev, 0x43, reg);
409 if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND,
410 PCI_DEVICE_ID_WINBOND_82C105, dev))){
412 * Disable LEGIRQ mode so PCI INTS are routed
413 * directly to the 8259 and enable both channels
415 pci_write_config_dword(dev, 0x40, 0x10ff0033);
417 /* Force correct IDE interrupt */
419 pci_write_config_byte(dev,
426 pplus_set_VIA_IDE_legacy(void)
428 unsigned short vend, dev;
430 early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_VENDOR_ID, &vend);
431 early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_DEVICE_ID, &dev);
433 if ((vend == PCI_VENDOR_ID_VIA) &&
434 (dev == PCI_DEVICE_ID_VIA_82C586_1)) {
438 /* put back original "standard" port base addresses */
439 early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
440 PCI_BASE_ADDRESS_0, 0x1f1);
441 early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
442 PCI_BASE_ADDRESS_1, 0x3f5);
443 early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
444 PCI_BASE_ADDRESS_2, 0x171);
445 early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
446 PCI_BASE_ADDRESS_3, 0x375);
447 early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
448 PCI_BASE_ADDRESS_4, 0xcc01);
450 /* put into legacy mode */
451 early_read_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
454 early_write_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
460 pplus_set_VIA_IDE_native(void)
462 unsigned short vend, dev;
464 early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_VENDOR_ID, &vend);
465 early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_DEVICE_ID, &dev);
467 if ((vend == PCI_VENDOR_ID_VIA) &&
468 (dev == PCI_DEVICE_ID_VIA_82C586_1)) {
472 /* put into native mode */
473 early_read_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
476 early_write_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
482 pplus_pcibios_fixup(void)
485 printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name);
487 /* Setup the Winbond or Via PIB */
492 pplus_init_resource(struct resource *res, unsigned long start,
493 unsigned long end, int flags)
498 res->name = "PCI host bridge";
505 pplus_setup_hose(void)
507 struct pci_controller* hose;
509 hose = pcibios_alloc_controller();
513 hose->first_busno = 0;
514 hose->last_busno = 0xff;
516 hose->pci_mem_offset = PREP_ISA_MEM_BASE;
517 hose->io_base_virt = (void *)PREP_ISA_IO_BASE;
519 pplus_init_resource(&hose->io_resource, 0x00000000, 0x0fffffff,
521 pplus_init_resource(&hose->mem_resources[0], 0xc0000000, 0xfdffffff,
524 hose->io_space.start = 0x00000000;
525 hose->io_space.end = 0x0fffffff;
526 hose->mem_space.start = 0x00000000;
527 hose->mem_space.end = 0x3cfbffff; /* MPIC at 0x3cfc0000-0x3dffffff */
529 setup_indirect_pci(hose, 0x80000cf8, 0x80000cfc);
531 pplus_set_VIA_IDE_legacy();
533 hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
535 ppc_md.pcibios_fixup = pplus_pcibios_fixup;
536 ppc_md.pci_swizzle = common_swizzle;
537 pplus_set_board_type();