Author: agraf Date: Mon Feb 22 19:52:26 2010 New Revision: 679 URL: http://tracker.coreboot.org/trac/openbios/changeset/679
Log: PPC: Create interrupt map for PCI
There is a draft spec that defines how interrupts are supposed to be mapped from one bus to another, down to the PIC and CPU interrupt line.
So far we don't implement that spec. But PPC64 Linux requires us to for PCI devices. So let's create a map here.
Draft: http://playground.sun.com/1275/practice/imap/imap0_9d.pdf
Signed-off-by: Alexander Graf agraf@suse.de
Modified: trunk/openbios-devel/drivers/macio.c trunk/openbios-devel/drivers/pci.c trunk/openbios-devel/include/openbios/pci.h
Modified: trunk/openbios-devel/drivers/macio.c ============================================================================== --- trunk/openbios-devel/drivers/macio.c Mon Feb 22 19:52:25 2010 (r678) +++ trunk/openbios-devel/drivers/macio.c Mon Feb 22 19:52:26 2010 (r679) @@ -18,6 +18,7 @@ #include "macio.h" #include "cuda.h" #include "escc.h" +#include "openbios/pci.h"
#define OW_IO_NVRAM_SIZE 0x00020000 #define OW_IO_NVRAM_OFFSET 0x00060000 @@ -172,9 +173,13 @@ fword("finish-device");
if (is_newworld()) { + u32 *interrupt_map; + int len, i; + /* patch in interrupt parent */ dnode = find_dev(buf); - target_node = find_dev("/pci"); + + target_node = find_dev("/pci/mac-io"); set_int_property(target_node, "interrupt-parent", dnode);
target_node = find_dev("/pci/mac-io/escc/ch-a"); @@ -182,6 +187,15 @@
target_node = find_dev("/pci/mac-io/escc/ch-b"); set_int_property(target_node, "interrupt-parent", dnode); + + 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 < 4; i++) { + interrupt_map[(i * 7) + PCI_INT_MAP_PIC_HANDLE] = (u32)dnode; + } + set_property(target_node, "interrupt-map", (char *)interrupt_map, len); } }
Modified: trunk/openbios-devel/drivers/pci.c ============================================================================== --- trunk/openbios-devel/drivers/pci.c Mon Feb 22 19:52:25 2010 (r678) +++ trunk/openbios-devel/drivers/pci.c Mon Feb 22 19:52:26 2010 (r679) @@ -278,6 +278,47 @@ set_property(dev, "bus-range", (char *)props, 2 * sizeof(props[0])); }
+static void pci_host_set_interrupt_map(const pci_config_t *config) +{ +/* 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) + phandle_t dev = get_cur_dev(); + u32 props[7 * 4]; + int i; + +#if defined(CONFIG_PPC) + /* Oldworld macs do interrupt maps differently */ + if(!is_newworld()) + return; +#endif + + for (i = 0; i < (7*4); 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 * 4 * 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])); +#endif +} + static void pci_host_set_reg(const pci_config_t *config) { phandle_t dev = get_cur_dev(); @@ -344,6 +385,7 @@ pci_host_set_reg(config); pci_host_set_ranges(config); pci_set_bus_range(config); + pci_host_set_interrupt_map(config);
return 0; }
Modified: trunk/openbios-devel/include/openbios/pci.h ============================================================================== --- trunk/openbios-devel/include/openbios/pci.h Mon Feb 22 19:52:25 2010 (r678) +++ trunk/openbios-devel/include/openbios/pci.h Mon Feb 22 19:52:26 2010 (r679) @@ -24,6 +24,16 @@
extern const pci_arch_t *arch;
+/* Device tree offsets */ + +#define PCI_INT_MAP_PCI0 0 +#define PCI_INT_MAP_PCI1 1 +#define PCI_INT_MAP_PCI2 2 +#define PCI_INT_MAP_PCI_INT 3 +#define PCI_INT_MAP_PIC_HANDLE 4 +#define PCI_INT_MAP_PIC_INT 5 +#define PCI_INT_MAP_PIC_POL 6 + /* Device classes and subclasses */
#define PCI_BASE_CLASS_STORAGE 0x01