// SPDX-License-Identifier: GPL-2.0-or-later /* * Routines for tracking a legacy ISA bridge * * Copyrigh 2007 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp. * * Some bits and pieces moved over from pci_64.c * * Copyrigh 2003 Anton Blanchard <anton@au.ibm.com>, IBM Corp.
*/
inval_range: if (phb_io_base_phys) {
pr_err("no ISA IO ranges or unexpected isa range, mapping 64k\n");
remap_isa_base(phb_io_base_phys, 0x10000); return 0;
} return -EINVAL;
}
/** * isa_bridge_find_early - Find and map the ISA IO space early before * main PCI discovery. This is optionally called by * the arch code when adding PCI PHBs to get early * access to ISA IO ports
*/ void __init isa_bridge_find_early(struct pci_controller *hose)
{ struct device_node *np, *parent = NULL, *tmp;
/* If we already have an ISA bridge, bail off */ if (isa_bridge_devnode != NULL) return;
/* For each "isa" node in the system. Note : we do a search by * type and not by name. It might be better to do by name but that's * what the code used to do and I don't want to break too much at * once. We can look into changing that separately
*/
for_each_node_by_type(np, "isa") { /* Look for our hose being a parent */ for (parent = of_get_parent(np); parent;) { if (parent == hose->dn) {
of_node_put(parent); break;
}
tmp = parent;
parent = of_get_parent(parent);
of_node_put(tmp);
} if (parent != NULL) break;
} if (np == NULL) return;
isa_bridge_devnode = np;
/* Now parse the "ranges" property and setup the ISA mapping */
process_ISA_OF_ranges(np, hose->io_base_phys);
/* Set the global ISA io base to indicate we have an ISA bridge */
isa_io_base = ISA_IO_BASE;
pr_debug("ISA bridge (early) is %pOF\n", np);
}
/** * isa_bridge_find_early - Find and map the ISA IO space early before * main PCI discovery. This is optionally called by * the arch code when adding PCI PHBs to get early * access to ISA IO ports
*/ void __init isa_bridge_init_non_pci(struct device_node *np)
{ int ret;
/* If we already have an ISA bridge, bail off */ if (isa_bridge_devnode != NULL) return;
ret = process_ISA_OF_ranges(np, 0); if (ret) return;
/* Got it */
isa_bridge_devnode = np;
/* Set the global ISA io base to indicate we have an ISA bridge * and map it
*/
isa_io_base = ISA_IO_BASE;
pr_debug("ISA: Non-PCI bridge is %pOF\n", np);
}
/** * isa_bridge_find_late - Find and map the ISA IO space upon discovery of * a new ISA bridge
*/ staticvoid isa_bridge_find_late(struct pci_dev *pdev, struct device_node *devnode)
{ struct pci_controller *hose = pci_bus_to_host(pdev->bus);
/* Store ISA device node and PCI device */
isa_bridge_devnode = of_node_get(devnode);
isa_bridge_pcidev = pdev;
/* Now parse the "ranges" property and setup the ISA mapping */
process_ISA_OF_ranges(devnode, hose->io_base_phys);
/* Set the global ISA io base to indicate we have an ISA bridge */
isa_io_base = ISA_IO_BASE;
pr_debug("ISA bridge (late) is %pOF on %s\n",
devnode, pci_name(pdev));
}
/** * isa_bridge_remove - Remove/unmap an ISA bridge
*/ staticvoid isa_bridge_remove(void)
{
pr_debug("ISA bridge removed !\n");
/* Clear the global ISA io base to indicate that we have no more * ISA bridge. Note that drivers don't quite handle that, though * we should probably do something about it. But do we ever really * have ISA bridges being removed on machines using legacy devices ?
*/
isa_io_base = ISA_IO_BASE;
/* Clear references to the bridge */
of_node_put(isa_bridge_devnode);
isa_bridge_devnode = NULL;
isa_bridge_pcidev = NULL;
/* Unmap the ISA area */
vunmap_range(ISA_IO_BASE, ISA_IO_BASE + 0x10000);
}
switch(action) { case BUS_NOTIFY_ADD_DEVICE: /* Check if we have an early ISA device, without PCI dev */ if (isa_bridge_devnode && isa_bridge_devnode == devnode &&
!isa_bridge_pcidev) {
pr_debug("ISA bridge PCI attached: %s\n",
pci_name(pdev));
isa_bridge_pcidev = pdev;
}
/* Check if we have no ISA device, and this happens to be one, * register it as such if it has an OF device
*/ if (!isa_bridge_devnode && of_node_is_type(devnode, "isa"))
isa_bridge_find_late(pdev, devnode);
return 0; case BUS_NOTIFY_DEL_DEVICE: /* Check if this our existing ISA device */ if (pdev == isa_bridge_pcidev ||
(devnode && devnode == isa_bridge_devnode))
isa_bridge_remove(); return 0;
} return 0;
}
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.