static int __init hdpu_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) { struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); if (hose->index == 0) { static char pci_irq_table[][4] = { {HDPU_PCI_0_IRQ, 0, 0, 0}, {HDPU_PCI_0_IRQ, 0, 0, 0}, }; const long min_idsel = 1, max_idsel = 2, irqs_per_slot = 4; return PCI_IRQ_TABLE_LOOKUP; } else { static char pci_irq_table[][4] = { {HDPU_PCI_1_IRQ, 0, 0, 0}, }; const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4; return PCI_IRQ_TABLE_LOOKUP; } }
int fdtdec_get_pci_bar32(const void *blob, int node, struct fdt_pci_addr *addr, u32 *bar) { pci_dev_t bdf; int barnum; int ret; /* get pci devices's bdf */ ret = fdtdec_get_pci_bdf(blob, node, addr, &bdf); if (ret) return ret; /* extract the bar number from fdt_pci_addr */ barnum = addr->phys_hi & 0xff; if ((barnum < PCI_BASE_ADDRESS_0) || (barnum > PCI_CARDBUS_CIS)) return -EINVAL; barnum = (barnum - PCI_BASE_ADDRESS_0) / 4; *bar = pci_read_bar32(pci_bus_to_hose(PCI_BUS(bdf)), bdf, barnum); return 0; }
/* * Subroutine: pciinfo * * Description: Show information about devices on PCI bus. * Depending on the define CONFIG_SYS_SHORT_PCI_LISTING * the output will be more or less exhaustive. * * Inputs: bus_no the number of the bus to be scanned. * * Return: None * */ void pciinfo(int BusNum, int ShortPCIListing) { struct pci_controller *hose = pci_bus_to_hose(BusNum); int Device; int Function; unsigned char HeaderType; unsigned short VendorID; pci_dev_t dev; int ret; if (!hose) return; printf("Scanning PCI devices on bus %d\n", BusNum); if (ShortPCIListing) { printf("BusDevFun VendorId DeviceId Device Class Sub-Class\n"); printf("_____________________________________________________________\n"); } for (Device = 0; Device < PCI_MAX_PCI_DEVICES; Device++) { HeaderType = 0; VendorID = 0; for (Function = 0; Function < PCI_MAX_PCI_FUNCTIONS; Function++) { /* * If this is not a multi-function device, we skip the rest. */ if (Function && !(HeaderType & 0x80)) break; dev = PCI_BDF(BusNum, Device, Function); if (pci_skip_dev(hose, dev)) continue; ret = pci_read_config_word(dev, PCI_VENDOR_ID, &VendorID); if (ret) goto error; if ((VendorID == 0xFFFF) || (VendorID == 0x0000)) continue; if (!Function) pci_read_config_byte(dev, PCI_HEADER_TYPE, &HeaderType); if (ShortPCIListing) { printf("%02x.%02x.%02x ", BusNum, Device, Function); pci_header_show_brief(dev); } else { printf("\nFound PCI device %02x.%02x.%02x:\n", BusNum, Device, Function); pci_header_show(dev); } } } return; error: printf("Cannot read bus configuration: %d\n", ret); }
static void __init pplus_setup_arch(void) { struct pci_controller *hose; if (ppc_md.progress) ppc_md.progress("pplus_setup_arch: enter", 0); /* init to some ~sane value until calibrate_delay() runs */ loops_per_jiffy = 50000000; if (ppc_md.progress) ppc_md.progress("pplus_setup_arch: find_bridges", 0); /* Setup PCI host bridge */ pplus_find_bridges(); hose = pci_bus_to_hose(0); isa_io_base = (ulong) hose->io_base_virt; if (ppc_md.progress) ppc_md.progress("pplus_setup_arch: set_board_type", 0); pplus_set_board_type(); /* Enable L2. Assume we don't need to flush -- Cort */ *(unsigned char *)(PPLUS_L2_CONTROL_REG) |= 3; #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start) ROOT_DEV = Root_RAM0; else #endif #ifdef CONFIG_ROOT_NFS ROOT_DEV = Root_NFS; #else ROOT_DEV = Root_SDA2; #endif printk(KERN_INFO "Motorola PowerPlus Platform\n"); printk(KERN_INFO "Port by MontaVista Software, Inc. ([email protected])\n"); #ifdef CONFIG_VGA_CONSOLE /* remap the VGA memory */ vgacon_remap_base = (unsigned long)ioremap(PPLUS_ISA_MEM_BASE, 0x08000000); conswitchp = &vga_con; #endif #ifdef CONFIG_PPCBUG_NVRAM /* Read in NVRAM data */ init_prep_nvram(); /* if no bootargs, look in NVRAM */ if (cmd_line[0] == '\0') { char *bootargs; bootargs = prep_nvram_get_var("bootargs"); if (bootargs != NULL) { strcpy(cmd_line, bootargs); /* again.. */ strcpy(saved_command_line, cmd_line); } } #endif if (ppc_md.progress) ppc_md.progress("pplus_setup_arch: exit", 0); }
static inline int __init adir_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) { #define PCIIRQ(a,b,c,d) {ADIR_IRQ_##a,ADIR_IRQ_##b,ADIR_IRQ_##c,ADIR_IRQ_##d}, struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); /* * The three PCI devices on the motherboard have dedicated lines to the * CPLD interrupt controller, bypassing the standard PCI INTA-D and the * PC interrupt controller. All other PCI devices (slots) have usual * staggered INTA-D lines, resulting in 8 lines total (PCI0 INTA-D and * PCI1 INTA-D). All 8 go to the CPLD interrupt controller. PCI0 INTA-D * also go to the south bridge, so we have the option of taking them * via the CPLD interrupt controller or via the south bridge 8259 * 8258 thingy. PCI1 INTA-D can only be taken via the CPLD interrupt * controller. We take all PCI interrupts via the CPLD interrupt * controller as recommended by SBS. * * We also have some monkey business with the PCI devices within the * VT82C686B south bridge itself. This chip actually has 7 functions on * its IDSEL. Function 0 is the actual south bridge, function 1 is IDE, * and function 4 is some special stuff. The other 4 functions are just * regular PCI devices bundled in the chip. 2 and 3 are USB UHCIs and 5 * and 6 are audio (not supported on the Adirondack). * * This is where the monkey business begins. PCI devices are supposed * to signal normal PCI interrupts. But the 4 functions in question are * located in the south bridge chip, which is designed with the * assumption that it will be fielding PCI INTA-D interrupts rather * than generating them. Here's what it does. Each of the functions in * question routes its interrupt to one of the IRQs on the 8259 thingy. * Which one? It looks at the Interrupt Line register in the PCI config * space, even though the PCI spec says it's for BIOS/OS interaction * only. * * How do we deal with this? We take these interrupts via 8259 IRQs as * we have to. We return the desired IRQ numbers from this routine when * called for the functions in question. The PCI scan code will then * stick our return value into the Interrupt Line register in the PCI * config space, and the interrupt will actually go there. We identify * these functions within the south bridge IDSEL by their interrupt pin * numbers, as the VT82C686B has 04 in the Interrupt Pin register for * USB and 03 for audio. */ if (!hose->index) { static char pci_irq_table[][4] = /* * PCI IDSEL/INTPIN->INTLINE * A B C D */ { /* south bridge */ PCIIRQ(IDE0, NONE, VIA_AUDIO, VIA_USB) /* Ethernet 0 */ PCIIRQ(MBETH0, MBETH0, MBETH0, MBETH0) /* PCI0 slot 1 */ PCIIRQ(PCI0_INTB, PCI0_INTC, PCI0_INTD, PCI0_INTA) /* PCI0 slot 2 */ PCIIRQ(PCI0_INTC, PCI0_INTD, PCI0_INTA, PCI0_INTB) /* PCI0 slot 3 */ PCIIRQ(PCI0_INTD, PCI0_INTA, PCI0_INTB, PCI0_INTC) }; const long min_idsel = 3, max_idsel = 7, irqs_per_slot = 4; return PCI_IRQ_TABLE_LOOKUP; } else { static char pci_irq_table[][4] = /* * PCI IDSEL/INTPIN->INTLINE * A B C D */ { /* Ethernet 1 */ PCIIRQ(MBETH1, MBETH1, MBETH1, MBETH1) /* SCSI */ PCIIRQ(MBSCSI, MBSCSI, MBSCSI, MBSCSI) /* PCI1 slot 1 */ PCIIRQ(PCI1_INTB, PCI1_INTC, PCI1_INTD, PCI1_INTA) /* PCI1 slot 2 */ PCIIRQ(PCI1_INTC, PCI1_INTD, PCI1_INTA, PCI1_INTB) /* PCI1 slot 3 */ PCIIRQ(PCI1_INTD, PCI1_INTA, PCI1_INTB, PCI1_INTC) }; const long min_idsel = 3, max_idsel = 7, irqs_per_slot = 4; return PCI_IRQ_TABLE_LOOKUP; } #undef PCIIRQ }