pending = readl(®s->sio_ir);
mask = readl(®s->sio_ies);
pending &= mask; /* Mask off not enabled interrupts */
if (pending)
generic_handle_domain_irq(domain, __ffs(pending)); else
spurious_interrupt();
}
/* * System boards/BaseIOs use more interrupt pins of the bridge ASIC * to which the IOC3 is connected. Since the IOC3 MFD driver * knows wiring of these extra pins, we use the map_irq function * to get interrupts activated
*/ staticint ioc3_map_irq(struct pci_dev *pdev, int slot, int pin)
{ struct pci_host_bridge *hbrg = pci_find_host_bridge(pdev->bus);
staticint ioc3_led_setup(struct ioc3_priv_data *ipd)
{ int ret;
ret = mfd_add_devices(&ipd->pdev->dev, 0, ioc3_led_cells,
ARRAY_SIZE(ioc3_led_cells),
&ipd->pdev->resource[0], 0, ipd->domain); if (ret)
dev_err(&ipd->pdev->dev, "Failed to add LED subdev\n");
return ret;
}
staticint ip27_baseio_setup(struct ioc3_priv_data *ipd)
{ int ret, io_irq;
io_irq = ioc3_map_irq(ipd->pdev, PCI_SLOT(ipd->pdev->devfn),
PCI_INTERRUPT_INTB);
ret = ioc3_irq_domain_setup(ipd, io_irq); if (ret) return ret;
ret = ioc3_eth_setup(ipd); if (ret) return ret;
ret = ioc3_serial_setup(ipd); if (ret) return ret;
return ioc3_m48t35_setup(ipd);
}
staticint ip27_baseio6g_setup(struct ioc3_priv_data *ipd)
{ int ret, io_irq;
io_irq = ioc3_map_irq(ipd->pdev, PCI_SLOT(ipd->pdev->devfn),
PCI_INTERRUPT_INTB);
ret = ioc3_irq_domain_setup(ipd, io_irq); if (ret) return ret;
ret = ioc3_eth_setup(ipd); if (ret) return ret;
ret = ioc3_serial_setup(ipd); if (ret) return ret;
ret = ioc3_m48t35_setup(ipd); if (ret) return ret;
return ioc3_kbd_setup(ipd);
}
staticint ip27_mio_setup(struct ioc3_priv_data *ipd)
{ int ret;
ret = ioc3_irq_domain_setup(ipd, ipd->pdev->irq); if (ret) return ret;
ret = ioc3_serial_setup(ipd); if (ret) return ret;
return ioc3_kbd_setup(ipd);
}
staticint ip30_sysboard_setup(struct ioc3_priv_data *ipd)
{ int ret, io_irq;
io_irq = ioc3_map_irq(ipd->pdev, PCI_SLOT(ipd->pdev->devfn),
PCI_INTERRUPT_INTB);
ret = ioc3_irq_domain_setup(ipd, io_irq); if (ret) return ret;
ret = ioc3_eth_setup(ipd); if (ret) return ret;
ret = ioc3_serial_setup(ipd); if (ret) return ret;
ret = ioc3_kbd_setup(ipd); if (ret) return ret;
ret = ioc3_ds1685_setup(ipd); if (ret) return ret;
return ioc3_led_setup(ipd);
}
staticint ioc3_menet_setup(struct ioc3_priv_data *ipd)
{ int ret, io_irq;
io_irq = ioc3_map_irq(ipd->pdev, PCI_SLOT(ipd->pdev->devfn),
PCI_INTERRUPT_INTB);
ret = ioc3_irq_domain_setup(ipd, io_irq); if (ret) return ret;
/* Read subsystem vendor id and subsystem id */
pci_read_config_dword(ipd->pdev, PCI_SUBSYSTEM_VENDOR_ID, &sid);
for (i = 0; i < ARRAY_SIZE(ioc3_infos); i++) if (sid == ioc3_infos[i].sid) {
pr_info("ioc3: %s\n", ioc3_infos[i].name); return ioc3_infos[i].setup(ipd);
}
/* Treat everything not identified by PCI subid as CAD DUO */
pr_info("ioc3: CAD DUO\n"); return ioc3_cad_duo_setup(ipd);
}
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); if (ret) {
pr_err("%s: No usable DMA configuration, aborting.\n",
pci_name(pdev)); goto out_disable_device;
}
/* Set up per-IOC3 data */
ipd = devm_kzalloc(&pdev->dev, sizeof(struct ioc3_priv_data),
GFP_KERNEL); if (!ipd) {
ret = -ENOMEM; goto out_disable_device;
}
ipd->pdev = pdev;
/* * Map all IOC3 registers. These are shared between subdevices * so the main IOC3 module manages them.
*/
regs = pci_ioremap_bar(pdev, 0); if (!regs) {
dev_warn(&pdev->dev, "ioc3: Unable to remap PCI BAR for %s.\n",
pci_name(pdev));
ret = -ENOMEM; goto out_disable_device;
}
ipd->regs = regs;
/* Track PCI-device specific data */
pci_set_drvdata(pdev, ipd);
ret = ioc3_setup(ipd); if (ret) { /* Remove all already added MFD devices */
mfd_remove_devices(&ipd->pdev->dev); if (ipd->domain) { struct fwnode_handle *fn = ipd->domain->fwnode;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.