[OpenBIOS] [PATCH 4/4] pci.c: move openpic interrupt mapping to post-PCI-bus scan
Mark Cave-Ayland
mark.cave-ayland at ilande.co.uk
Thu Nov 13 13:19:54 CET 2014
Move the interrupt mapping from the pre-scan pci_host_set_interrupt_map()
to the post-scan ob_pci_host_set_interrupt_map() function.
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland at ilande.co.uk>
---
openbios-devel/drivers/pci.c | 146 +++++++++++++++++++++---------------------
1 file changed, 72 insertions(+), 74 deletions(-)
diff --git a/openbios-devel/drivers/pci.c b/openbios-devel/drivers/pci.c
index 09e601c..629a652 100644
--- a/openbios-devel/drivers/pci.c
+++ b/openbios-devel/drivers/pci.c
@@ -417,70 +417,6 @@ static void pci_set_bus_range(const pci_config_t *config)
set_property(dev, "bus-range", (char *)props, 2 * sizeof(props[0]));
}
-/* Convert device/irq pin to interrupt property */
-#define SUN4U_INTERRUPT(dev, irq_pin) \
- ((((dev >> 11) << 2) + irq_pin - 1) & 0x1f)
-
-static void pci_host_set_interrupt_map(phandle_t dev)
-{
-/* XXX We currently have a hook in the MPIC init code to fill in its handle.
- * If you want to have interrupt maps for your PCI host bus, add your
- * architecture to the #if and make your bridge detect code fill in its
- * handle too.
- *
- * It would be great if someone clever could come up with a more universal
- * mechanism here.
- */
-#if defined(CONFIG_PPC)
- u32 props[7 * 8];
- int i;
-
- /* Oldworld macs do interrupt maps differently */
- if(!is_newworld())
- return;
-
- for (i = 0; i < (7*8); i+=7) {
- props[i+PCI_INT_MAP_PCI0] = 0;
- props[i+PCI_INT_MAP_PCI1] = 0;
- props[i+PCI_INT_MAP_PCI2] = 0;
- props[i+PCI_INT_MAP_PCI_INT] = (i / 7) + 1; // starts at PINA=1
- props[i+PCI_INT_MAP_PIC_HANDLE] = 0; // gets patched in later
- props[i+PCI_INT_MAP_PIC_INT] = arch->irqs[i / 7];
- props[i+PCI_INT_MAP_PIC_POL] = 3;
- }
- set_property(dev, "interrupt-map", (char *)props, 7 * 8 * sizeof(props[0]));
-
- props[PCI_INT_MAP_PCI0] = 0;
- props[PCI_INT_MAP_PCI1] = 0;
- props[PCI_INT_MAP_PCI2] = 0;
- props[PCI_INT_MAP_PCI_INT] = 0x7;
-
- set_property(dev, "interrupt-map-mask", (char *)props, 4 * sizeof(props[0]));
-#elif defined(CONFIG_SPARC64)
- uint32_t props[12];
- int ncells, device, i;
-
- /* Set interrupt-map for devices 4 (NE2000) and 5 (CMD646) */
- ncells = 0;
- for (i = 4; i <= 5; i++) {
- device = i << 11;
-
- ncells += pci_encode_phys_addr(props + ncells, 0, 0, device, 0, 0);
- props[ncells++] = 1;
- props[ncells++] = dev;
- props[ncells++] = SUN4U_INTERRUPT(device, 1);
- }
-
- set_property(dev, "interrupt-map", (char *)props, ncells * sizeof(props[0]));
-
- props[0] = 0x0000f800;
- props[1] = 0x0;
- props[2] = 0x0;
- props[3] = 7;
- set_property(dev, "interrupt-map-mask", (char *)props, 4 * sizeof(props[0]));
-#endif
-}
-
static void pci_host_set_reg(phandle_t phandle)
{
phandle_t dev = phandle;
@@ -547,7 +483,6 @@ int host_config_cb(const pci_config_t *config)
//XXX this overrides "reg" property
pci_host_set_reg(get_cur_dev());
pci_host_set_ranges(config);
- pci_host_set_interrupt_map(get_cur_dev());
return 0;
}
@@ -1436,20 +1371,26 @@ static void ob_pci_set_available(phandle_t host, unsigned long mem_base, unsigne
set_property(host, "available", (char *)props, ncells * sizeof(props[0]));
}
+/* Convert device/irq pin to interrupt property */
+#define SUN4U_INTERRUPT(dev, irq_pin) \
+ ((((dev >> 11) << 2) + irq_pin - 1) & 0x1f)
+
static void ob_pci_host_set_interrupt_map(phandle_t host)
{
-#if defined(CONFIG_PPC)
phandle_t dnode = 0;
+ u32 props[128];
+ int i;
+
+#if defined(CONFIG_PPC)
phandle_t target_node;
- u32 *interrupt_map;
- int len, i;
/* Oldworld macs do interrupt maps differently */
if (!is_newworld())
return;
- /* patch in interrupt parent */
- while ((dnode = dt_iterate_type(dnode, "open-pic"))) {
+ dnode = dt_iterate_type(0, "open-pic");
+ if (dnode) {
+ /* patch in openpic interrupt-parent properties */
target_node = find_dev("/pci/mac-io");
set_int_property(target_node, "interrupt-parent", dnode);
@@ -1477,12 +1418,69 @@ static void ob_pci_host_set_interrupt_map(phandle_t host)
target_node = find_dev("/pci");
set_int_property(target_node, "interrupt-parent", dnode);
- interrupt_map = (u32 *)get_property(target_node, "interrupt-map", &len);
- for (i = 0; i < 8; i++) {
- interrupt_map[(i * 7) + PCI_INT_MAP_PIC_HANDLE] = (u32)dnode;
+ /* openpic interrupt mapping */
+ for (i = 0; i < (7*8); i += 7) {
+ props[i + PCI_INT_MAP_PCI0] = 0;
+ props[i + PCI_INT_MAP_PCI1] = 0;
+ props[i + PCI_INT_MAP_PCI2] = 0;
+ props[i + PCI_INT_MAP_PCI_INT] = (i / 7) + 1; // starts at PINA=1
+ props[i + PCI_INT_MAP_PIC_HANDLE] = dnode;
+ props[i + PCI_INT_MAP_PIC_INT] = arch->irqs[i / 7];
+ props[i + PCI_INT_MAP_PIC_POL] = 3;
+ }
+ set_property(host, "interrupt-map", (char *)props, 7 * 8 * sizeof(props[0]));
+
+ props[PCI_INT_MAP_PCI0] = 0;
+ props[PCI_INT_MAP_PCI1] = 0;
+ props[PCI_INT_MAP_PCI2] = 0;
+ props[PCI_INT_MAP_PCI_INT] = 0x7;
+
+ set_property(host, "interrupt-map-mask", (char *)props, 4 * sizeof(props[0]));
+ }
+
+#elif defined(CONFIG_SPARC64)
+ int ncells, len;
+ u32 *val, addr;
+ char *reg;
+
+ /* Set interrupt-map for devices 4 (NE2000) and 5 (CMD646) */
+ ncells = 0;
+
+ PUSH(host);
+ fword("child");
+ dnode = POP();
+ while (dnode) {
+ if (get_int_property(dnode, "interrupts", &len)) {
+ reg = get_property(dnode, "reg", &len);
+ if (reg) {
+ val = (u32 *)reg;
+
+ for (i = 0; i < (len / sizeof(u32)); i += 5) {
+ addr = val[i];
+
+ /* Device address is in 1st 32-bit word of encoded PCI address for config space */
+ if (!(addr & 0x03000000)) {
+ ncells += pci_encode_phys_addr(props + ncells, 0, 0, addr, 0, 0);
+ props[ncells++] = 1; /* always interrupt pin 1 for QEMU */
+ props[ncells++] = host;
+ props[ncells++] = SUN4U_INTERRUPT(addr, 1);
+ }
+ }
+ }
}
- set_property(target_node, "interrupt-map", (char *)interrupt_map, len);
+
+ PUSH(dnode);
+ fword("peer");
+ dnode = POP();
}
+ set_property(host, "interrupt-map", (char *)props, ncells * sizeof(props[0]));
+
+ props[0] = 0x0000f800;
+ props[1] = 0x0;
+ props[2] = 0x0;
+ props[3] = 7;
+ set_property(host, "interrupt-map-mask", (char *)props, 4 * sizeof(props[0]));
+
#endif
}
--
1.7.10.4
More information about the OpenBIOS
mailing list