summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2011-01-29 20:58:38 +0000
committermarcel <marcel@FreeBSD.org>2011-01-29 20:58:38 +0000
commitd129fb0e44db1f4eba2f03627ac099e40f08122d (patch)
treefec042adbb304ebfd29a4edbd235c9e905009e06
parentf9d6eb1e7555188ea1354e0096c8c5ba13fd5676 (diff)
downloadFreeBSD-src-d129fb0e44db1f4eba2f03627ac099e40f08122d.zip
FreeBSD-src-d129fb0e44db1f4eba2f03627ac099e40f08122d.tar.gz
Fix the interrupt code, broken 7 months ago. The interrupt framework
already supported nested PICs, but was limited to having a nested AT-PIC only. With G5 support the need for nested OpenPIC controllers needed to be added. This was done the wrong way and broke the MPC8555 eval system in the process. OFW, as well as FDT, describe the interrupt routing in terms of a controller and an interrupt pin on it. This needs to be mapped to a flat and global resource: the IRQ. The IRQ is the same as the PCI intline and as such needs to be representable in 8 bits. Secondly, ISA support pretty much dictates that IRQ 0-15 should be reserved for ISA interrupts, because of the internal workins of south bridges. Both were broken. This change reverts revision 209298 for a big part and re-implements it simpler. In particular: o The id() method of the PIC I/F is removed again. It's not needed. o The openpic_attach() function has been changed to take the OFW or FDT phandle of the controller as a second argument. All bus attachments that previously used openpic_attach() as the attach method of the device I/F now implement as bus-specific method and pass the phandle_t to the renamed openpic_attach(). o Change powerpc_register_pic() to take a few more arguments. In particular: - Pass the number of IPIs specificly. The number of IRQs carved out for a PIC is the sum of the number of int. pins and IPIs. - Pass a flag indicating whether the PIC is an AT-PIC or not. This tells the interrupt framework whether to assign IRQ 0-15 or some other range. o Until we implement proper multi-pass bus enumeration, we have to handle the case where we need to map from PIC+pin to IRQ *before* the PIC gets registered. This is done in a similar way as before, but rather than carving out 256 IRQs per PIC, we carve out 128 IRQs (124 pins + 4 IPIs). This is supposed to handle the G5 case, but should really be fixed properly using multiple passes. o Have the interrupt framework set root_pic in most cases and not put that burden in PIC drivers (for the most part). o Remove powerpc_ign_lookup() and replace it with powerpc_get_irq(). Remove IGN_SHIFT, INTR_INTLINE and INTR_IGN. Related to the above, fix the Freescale PCI controller driver, broken by the FDT code. Besides not attaching properly, bus numbers were assigned improperly and enumeration was broken in general. This prevented the AT PIC from being discovered and interrupt routing to work properly. Consequently, the ata(4) controller stopped functioning. Fix the driver, and FDT PCI support, enough to get the MPC8555CDS going again. The FDT PCI code needs a whole lot more work. No breakages are expected, but lackiong G5 hardware, it's possible that there are unpleasant side-effects. At least MPC85xx support is back to where it was 7 months ago -- it's amazing how badly support can be broken in just 7 months... Sponsored by: Juniper Networks
-rw-r--r--sys/powerpc/include/intr_machdep.h12
-rw-r--r--sys/powerpc/include/openpicvar.h2
-rw-r--r--sys/powerpc/mambo/mambo_openpic.c21
-rw-r--r--sys/powerpc/mpc85xx/atpic.c15
-rw-r--r--sys/powerpc/mpc85xx/isa.c8
-rw-r--r--sys/powerpc/mpc85xx/openpic_fdt.c11
-rw-r--r--sys/powerpc/mpc85xx/pci_fdt.c109
-rw-r--r--sys/powerpc/powermac/cpcht.c16
-rw-r--r--sys/powerpc/powermac/hrowpic.c13
-rw-r--r--sys/powerpc/powermac/openpic_macio.c13
-rw-r--r--sys/powerpc/powerpc/intr_machdep.c112
-rw-r--r--sys/powerpc/powerpc/openpic.c5
-rw-r--r--sys/powerpc/powerpc/pic_if.m4
-rw-r--r--sys/powerpc/ps3/ps3pic.c13
-rw-r--r--sys/powerpc/psim/openpic_iobus.c10
15 files changed, 162 insertions, 202 deletions
diff --git a/sys/powerpc/include/intr_machdep.h b/sys/powerpc/include/intr_machdep.h
index 67d7e79..d0c6c1b 100644
--- a/sys/powerpc/include/intr_machdep.h
+++ b/sys/powerpc/include/intr_machdep.h
@@ -29,13 +29,9 @@
#define _MACHINE_INTR_MACHDEP_H_
#define INTR_VECTORS 256
-#define MAX_PICS 5
-#define IGN_SHIFT 8
-#define INTR_INTLINE(irq) (irq & ((1 << IGN_SHIFT) - 1))
-#define INTR_IGN(irq) (irq >> IGN_SHIFT)
-
-#define INTR_VEC(pic_id, irq) ((powerpc_ign_lookup(pic_id) << IGN_SHIFT) | (irq))
+#define MAX_PICS 5
+#define INTR_VEC(node, pin) powerpc_get_irq(node, pin)
/*
* Default base address for MSI messages on PowerPC
@@ -50,8 +46,8 @@ driver_filter_t powerpc_ipi_handler;
void intrcnt_add(const char *name, u_long **countp);
-void powerpc_register_pic(device_t, u_int);
-int powerpc_ign_lookup(uint32_t pic_id);
+void powerpc_register_pic(device_t, uint32_t, u_int, u_int, u_int);
+u_int powerpc_get_irq(uint32_t, u_int);
void powerpc_dispatch_intr(u_int, struct trapframe *);
int powerpc_enable_intr(void);
diff --git a/sys/powerpc/include/openpicvar.h b/sys/powerpc/include/openpicvar.h
index 5468542..4fb9aa7 100644
--- a/sys/powerpc/include/openpicvar.h
+++ b/sys/powerpc/include/openpicvar.h
@@ -52,7 +52,7 @@ extern devclass_t openpic_devclass;
/*
* Bus-independent attach i/f
*/
-int openpic_attach(device_t);
+int openpic_common_attach(device_t, uint32_t);
/*
* PIC interface.
diff --git a/sys/powerpc/mambo/mambo_openpic.c b/sys/powerpc/mambo/mambo_openpic.c
index 3edb027..883c9d7 100644
--- a/sys/powerpc/mambo/mambo_openpic.c
+++ b/sys/powerpc/mambo/mambo_openpic.c
@@ -56,12 +56,11 @@ __FBSDID("$FreeBSD$");
* Mambo interface
*/
static int openpic_mambo_probe(device_t);
-static uint32_t openpic_mambo_id(device_t dev);
+static int openpic_mambo_attach(device_t);
static int openpicbus_mambo_probe(device_t dev);
static int openpicbus_mambo_attach(device_t dev);
-static struct resource *openpicbus_alloc_resource(device_t bus, device_t dev,
- int type, int *rid, u_long start, u_long end, u_long count,
- u_int flags);
+static struct resource *openpicbus_alloc_resource(device_t bus, device_t dev,
+ int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
static device_method_t openpicbus_mambo_methods[] = {
/* Device interface */
@@ -87,7 +86,7 @@ static driver_t openpicbus_mambo_driver = {
static device_method_t openpic_mambo_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, openpic_mambo_probe),
- DEVMETHOD(device_attach, openpic_attach),
+ DEVMETHOD(device_attach, openpic_mambo_attach),
/* PIC interface */
DEVMETHOD(pic_config, openpic_config),
@@ -97,7 +96,6 @@ static device_method_t openpic_mambo_methods[] = {
DEVMETHOD(pic_ipi, openpic_ipi),
DEVMETHOD(pic_mask, openpic_mask),
DEVMETHOD(pic_unmask, openpic_unmask),
- DEVMETHOD(pic_id, openpic_mambo_id),
{ 0, 0 },
};
@@ -167,14 +165,15 @@ openpicbus_alloc_resource(device_t bus, device_t dev, int type, int *rid,
static int
openpic_mambo_probe(device_t dev)
{
+
device_set_desc(dev, OPENPIC_DEVSTR);
-
return (0);
}
-static uint32_t
-openpic_mambo_id(device_t dev)
+static int
+openpic_mambo_attach(device_t dev)
{
- return (ofw_bus_get_node(device_get_parent(dev)));
+
+ return (openpic_common_attach(dev,
+ ofw_bus_get_node(device_get_parent(dev))));
}
-
diff --git a/sys/powerpc/mpc85xx/atpic.c b/sys/powerpc/mpc85xx/atpic.c
index e903dbc..e1d0b39 100644
--- a/sys/powerpc/mpc85xx/atpic.c
+++ b/sys/powerpc/mpc85xx/atpic.c
@@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/intr_machdep.h>
-#include <machine/ocpbus.h>
#include <machine/pio.h>
#include <powerpc/mpc85xx/mpc85xx.h>
@@ -79,7 +78,6 @@ static void atpic_eoi(device_t, u_int);
static void atpic_ipi(device_t, u_int);
static void atpic_mask(device_t, u_int);
static void atpic_unmask(device_t, u_int);
-static uint32_t atpic_id (device_t dev);
static device_method_t atpic_isa_methods[] = {
/* Device interface */
@@ -95,7 +93,6 @@ static device_method_t atpic_isa_methods[] = {
DEVMETHOD(pic_ipi, atpic_ipi),
DEVMETHOD(pic_mask, atpic_mask),
DEVMETHOD(pic_unmask, atpic_unmask),
- DEVMETHOD(pic_id, atpic_id),
{ 0, 0 },
};
@@ -154,7 +151,7 @@ atpic_isa_identify(driver_t *drv, device_t parent)
bus_set_resource(child, SYS_RES_IOPORT, ATPIC_SLAVE, IO_ICU2, 2);
/* ISA interrupts are routed through external interrupt 0. */
- bus_set_resource(child, SYS_RES_IRQ, 0, PIC_IRQ_EXT(0), 1);
+ bus_set_resource(child, SYS_RES_IRQ, 0, 16, 1);
}
static int
@@ -221,7 +218,7 @@ atpic_isa_attach(device_t dev)
atpic_init(sc, ATPIC_SLAVE);
atpic_init(sc, ATPIC_MASTER);
- powerpc_register_pic(dev, 0x10);
+ powerpc_register_pic(dev, 0, 16, 0, TRUE);
return (0);
fail:
@@ -328,11 +325,3 @@ atpic_unmask(device_t dev, u_int irq)
atpic_write(sc, ATPIC_MASTER, 1, sc->sc_mask[ATPIC_MASTER]);
}
}
-
-static uint32_t
-atpic_id (device_t dev)
-{
-
- return (ATPIC_ID);
-}
-
diff --git a/sys/powerpc/mpc85xx/isa.c b/sys/powerpc/mpc85xx/isa.c
index eeffbfd..a1715ef 100644
--- a/sys/powerpc/mpc85xx/isa.c
+++ b/sys/powerpc/mpc85xx/isa.c
@@ -33,15 +33,12 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <machine/intr_machdep.h>
-#include <machine/ocpbus.h>
#include <machine/resource.h>
#include <isa/isareg.h>
#include <isa/isavar.h>
#include <isa/isa_common.h>
-#include "ocpbus.h"
-
void
isa_init(device_t dev)
{
@@ -62,10 +59,7 @@ isa_alloc_resource(device_t bus, device_t child, int type, int *rid,
resource_list_find(rl, type, *rid) == NULL) {
switch (type) {
case SYS_RES_IOPORT: rids = ISA_PNP_NPORT; break;
- case SYS_RES_IRQ:
- rids = ISA_PNP_NIRQ;
- start = ISA_IRQ(start);
- break;
+ case SYS_RES_IRQ: rids = ISA_PNP_NIRQ; break;
case SYS_RES_MEMORY: rids = ISA_PNP_NMEM; break;
default: rids = 0; break;
}
diff --git a/sys/powerpc/mpc85xx/openpic_fdt.c b/sys/powerpc/mpc85xx/openpic_fdt.c
index da70542..7cf18ea 100644
--- a/sys/powerpc/mpc85xx/openpic_fdt.c
+++ b/sys/powerpc/mpc85xx/openpic_fdt.c
@@ -45,12 +45,12 @@ __FBSDID("$FreeBSD$");
#include "pic_if.h"
static int openpic_fdt_probe(device_t);
-static uint32_t openpic_fdt_id(device_t);
+static int openpic_fdt_attach(device_t);
static device_method_t openpic_fdt_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, openpic_fdt_probe),
- DEVMETHOD(device_attach, openpic_attach),
+ DEVMETHOD(device_attach, openpic_fdt_attach),
/* PIC interface */
DEVMETHOD(pic_bind, openpic_bind),
@@ -61,7 +61,6 @@ static device_method_t openpic_fdt_methods[] = {
DEVMETHOD(pic_ipi, openpic_ipi),
DEVMETHOD(pic_mask, openpic_mask),
DEVMETHOD(pic_unmask, openpic_unmask),
- DEVMETHOD(pic_id, openpic_fdt_id),
{ 0, 0 },
};
@@ -85,9 +84,9 @@ openpic_fdt_probe(device_t dev)
return (BUS_PROBE_DEFAULT);
}
-static uint32_t
-openpic_fdt_id(device_t dev)
+static int
+openpic_fdt_attach(device_t dev)
{
- return (ofw_bus_get_node(dev));
+ return (openpic_common_attach(dev, ofw_bus_get_node(dev)));
}
diff --git a/sys/powerpc/mpc85xx/pci_fdt.c b/sys/powerpc/mpc85xx/pci_fdt.c
index 9d67aae..7965167 100644
--- a/sys/powerpc/mpc85xx/pci_fdt.c
+++ b/sys/powerpc/mpc85xx/pci_fdt.c
@@ -136,7 +136,7 @@ static int fsl_pcib_decode_win(phandle_t, struct fsl_pcib_softc *);
static void fsl_pcib_err_init(device_t);
static void fsl_pcib_inbound(struct fsl_pcib_softc *, int, int, u_long,
u_long, u_long);
-static int fsl_pcib_init(struct fsl_pcib_softc *, int, int, int);
+static int fsl_pcib_init(struct fsl_pcib_softc *, int, int);
static int fsl_pcib_intr_info(phandle_t, struct fsl_pcib_softc *);
static int fsl_pcib_set_range(struct fsl_pcib_softc *, int, int, u_long,
u_long);
@@ -160,8 +160,6 @@ static uint32_t fsl_pcib_read_config(device_t, u_int, u_int, u_int, u_int, int);
static void fsl_pcib_write_config(device_t, u_int, u_int, u_int, u_int,
uint32_t, int);
-static int next_busnr = 0;
-
/* Configuration r/w mutex. */
struct mtx pcicfg_mtx;
static int mtx_initialized = 0;
@@ -215,23 +213,17 @@ DRIVER_MODULE(pcib, fdtbus, fsl_pcib_driver, pcib_devclass, 0, 0);
static int
fsl_pcib_probe(device_t dev)
{
- phandle_t parnode;
+ phandle_t node;
- /*
- * The PCI subnode does not have the 'compatible' property, so we need
- * to check in the parent PCI node. However the parent is not
- * represented by a separate ofw_bus child, and therefore
- * ofw_bus_is_compatible() cannot be used, but direct fdt equivalent.
- */
- parnode = OF_parent(ofw_bus_get_node(dev));
- if (parnode == 0)
+ node = ofw_bus_get_node(dev);
+ if (!fdt_is_type(node, "pci"))
return (ENXIO);
- if (!(fdt_is_compatible(parnode, "fsl,mpc8548-pcie") ||
- fdt_is_compatible(parnode, "fsl,mpc8548-pcie")))
+
+ if (!(fdt_is_compatible(node, "fsl,mpc8540-pci") ||
+ fdt_is_compatible(node, "fsl,mpc8548-pcie")))
return (ENXIO);
device_set_desc(dev, "Freescale Integrated PCI/PCI-E Controller");
-
return (BUS_PROBE_DEFAULT);
}
@@ -241,7 +233,7 @@ fsl_pcib_attach(device_t dev)
struct fsl_pcib_softc *sc;
phandle_t node;
uint32_t cfgreg;
- int maxslot, subbus;
+ int maxslot;
uint8_t ltssm, capptr;
sc = device_get_softc(dev);
@@ -304,23 +296,13 @@ fsl_pcib_attach(device_t dev)
sc->sc_devfn_tundra = -1;
sc->sc_devfn_via_ide = -1;
- maxslot = (sc->sc_pcie) ? 1 : 31;
/*
- * Scan bus using firmware configured, 0 based bus numbering,
- * let fsl_pcib_init() shift bus number by next_busnr offset.
+ * Scan bus using firmware configured, 0 based bus numbering.
*/
- sc->sc_busnr = 1;
- subbus = fsl_pcib_init(sc, 0, next_busnr, maxslot);
-
- if (bootverbose)
- printf("PCI: domain %d, busnr = %d, next_busnr = %d\n",
- device_get_unit(dev), next_busnr + 1,
- next_busnr + subbus + 1);
-
- /* Set final busnr */
- sc->sc_busnr = next_busnr + 1;
- next_busnr += subbus + 1;
+ sc->sc_busnr = 0;
+ maxslot = (sc->sc_pcie) ? 0 : PCI_SLOTMAX;
+ fsl_pcib_init(sc, sc->sc_busnr, maxslot);
if (sc->sc_pcie) {
ltssm = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_LTSSM, 1);
@@ -455,7 +437,7 @@ fsl_pcib_maxslots(device_t dev)
{
struct fsl_pcib_softc *sc = device_get_softc(dev);
- return ((sc->sc_pcie) ? 1 : 31);
+ return ((sc->sc_pcie) ? 0 : PCI_SLOTMAX);
}
static uint32_t
@@ -572,14 +554,11 @@ fsl_pcib_route_int(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func,
devfn = DEVFN(bus, slot, func);
if (devfn == sc->sc_devfn_via_ide)
-#if 0
- intline = INTR_VEC(ATPIC_ID, 14);
+ intline = INTR_VEC(0, 14);
else if (devfn == sc->sc_devfn_via_ide + 1)
- intline = INTR_VEC(ATPIC_ID, 10);
+ intline = INTR_VEC(0, 10);
else if (devfn == sc->sc_devfn_via_ide + 2)
- intline = INTR_VEC(ATPIC_ID, 10);
-#endif
- ;
+ intline = INTR_VEC(0, 10);
else {
if (intpin != 0)
err = fdt_pci_route_intr(bus, slot, func, intpin,
@@ -596,10 +575,9 @@ fsl_pcib_route_int(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func,
}
static int
-fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int busnr_offset,
- int maxslot)
+fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int maxslot)
{
- int secbus, subbus;
+ int secbus;
int old_pribus, old_secbus, old_subbus;
int new_pribus, new_secbus, new_subbus;
int slot, func, maxfunc;
@@ -608,11 +586,10 @@ fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int busnr_offset,
uint8_t command, hdrtype, class, subclass;
uint8_t intline, intpin;
- subbus = bus;
+ secbus = bus;
for (slot = 0; slot <= maxslot; slot++) {
maxfunc = 0;
for (func = 0; func <= maxfunc; func++) {
-
hdrtype = fsl_pcib_read_config(sc->sc_dev, bus, slot,
func, PCIR_HDRTYPE, 1);
@@ -667,19 +644,14 @@ fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int busnr_offset,
func, PCIR_CLASS, 1);
subclass = fsl_pcib_read_config(sc->sc_dev, bus, slot,
func, PCIR_SUBCLASS, 1);
-#if 0
+
/* Allow only proper PCI-PCI briges */
if (class != PCIC_BRIDGE)
continue;
if (subclass != PCIS_BRIDGE_PCI)
continue;
-#endif
- /* Allow all DEVTYPE 1 devices */
- if (hdrtype != PCIM_HDRTYPE_BRIDGE)
- continue;
- subbus++;
- secbus = subbus;
+ secbus++;
/* Program I/O decoder. */
fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
@@ -718,31 +690,20 @@ fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int busnr_offset,
if (bootverbose)
printf("PCI: reading firmware bus numbers for "
"secbus = %d (bus/sec/sub) = (%d/%d/%d)\n",
- secbus + busnr_offset, old_pribus,
- old_secbus, old_subbus);
+ secbus, old_pribus, old_secbus, old_subbus);
- /* Skip unconfigured devices */
- if ((old_pribus == 0) &&
- (old_secbus == 0) && (old_subbus == 0))
- continue;
-
- subbus += fsl_pcib_init(sc, secbus, busnr_offset,
- (subclass == PCIS_BRIDGE_PCI) ? 31 : 1);
+ new_pribus = bus;
+ new_secbus = secbus;
- new_pribus = bus + busnr_offset;
- new_secbus = secbus + busnr_offset;
- new_subbus = subbus + busnr_offset;
+ secbus = fsl_pcib_init(sc, secbus,
+ (subclass == PCIS_BRIDGE_PCI) ? PCI_SLOTMAX : 0);
- /* Fixup pribus for MPC8572 PCIE controller */
- if ((vendor == 0x1957) && ((device = 0x0040) ||
- (device == 0x0041)))
- new_pribus = 0;
+ new_subbus = secbus;
if (bootverbose)
- printf("PCI: translate firmware bus numbers for "
- "secbus %d (%d/%d/%d) -> (%d/%d/%d)\n",
- secbus + busnr_offset,
- old_pribus, old_secbus, old_subbus,
+ printf("PCI: translate firmware bus numbers "
+ "for secbus %d (%d/%d/%d) -> (%d/%d/%d)\n",
+ secbus, old_pribus, old_secbus, old_subbus,
new_pribus, new_secbus, new_subbus);
fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
@@ -754,11 +715,7 @@ fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int busnr_offset,
}
}
- if (bootverbose)
- printf("PCI: bus %d, #subbus = %d\n",
- bus + busnr_offset, subbus - bus);
-
- return (subbus - bus);
+ return (secbus);
}
static void
@@ -938,12 +895,10 @@ fsl_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
va = sc->sc_iomem_va;
break;
case SYS_RES_IRQ:
-#if 0
- if (INTR_IGN(start) == powerpc_ign_lookup(ATPIC_ID)) {
+ if (start < 16) {
device_printf(dev, "%s requested ISA interrupt %lu\n",
device_get_nameunit(child), start);
}
-#endif
flags |= RF_SHAREABLE;
return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
type, rid, start, end, count, flags));
diff --git a/sys/powerpc/powermac/cpcht.c b/sys/powerpc/powermac/cpcht.c
index 4ee6aee..9359cd8 100644
--- a/sys/powerpc/powermac/cpcht.c
+++ b/sys/powerpc/powermac/cpcht.c
@@ -757,7 +757,6 @@ static void openpic_cpcht_config(device_t, u_int irq,
static void openpic_cpcht_enable(device_t, u_int irq, u_int vector);
static void openpic_cpcht_unmask(device_t, u_int irq);
static void openpic_cpcht_eoi(device_t, u_int irq);
-static uint32_t openpic_cpcht_id(device_t);
static device_method_t openpic_cpcht_methods[] = {
/* Device interface */
@@ -773,7 +772,6 @@ static device_method_t openpic_cpcht_methods[] = {
DEVMETHOD(pic_ipi, openpic_ipi),
DEVMETHOD(pic_mask, openpic_mask),
DEVMETHOD(pic_unmask, openpic_cpcht_unmask),
- DEVMETHOD(pic_id, openpic_cpcht_id),
{ 0, 0 },
};
@@ -808,9 +806,11 @@ static int
openpic_cpcht_attach(device_t dev)
{
struct openpic_cpcht_softc *sc;
+ phandle_t node;
int err, irq;
- err = openpic_attach(dev);
+ node = ofw_bus_get_node(dev);
+ err = openpic_common_attach(dev, node);
if (err != 0)
return (err);
@@ -839,9 +839,8 @@ openpic_cpcht_attach(device_t dev)
* be necessary, but Linux does it, and I cannot find any U3 machines
* with MSI devices to test.
*/
-
if (dev == root_pic)
- cpcht_msipic = PIC_ID(dev);
+ cpcht_msipic = node;
return (0);
}
@@ -981,10 +980,3 @@ openpic_cpcht_eoi(device_t dev, u_int irq)
openpic_eoi(dev, irq);
}
-
-static uint32_t
-openpic_cpcht_id(device_t dev)
-{
- return (ofw_bus_get_node(dev));
-}
-
diff --git a/sys/powerpc/powermac/hrowpic.c b/sys/powerpc/powermac/hrowpic.c
index 0e839d9..0142173 100644
--- a/sys/powerpc/powermac/hrowpic.c
+++ b/sys/powerpc/powermac/hrowpic.c
@@ -69,7 +69,6 @@ static void hrowpic_eoi(device_t, u_int);
static void hrowpic_ipi(device_t, u_int);
static void hrowpic_mask(device_t, u_int);
static void hrowpic_unmask(device_t, u_int);
-static uint32_t hrowpic_id(device_t dev);
static device_method_t hrowpic_methods[] = {
/* Device interface */
@@ -80,7 +79,6 @@ static device_method_t hrowpic_methods[] = {
DEVMETHOD(pic_dispatch, hrowpic_dispatch),
DEVMETHOD(pic_enable, hrowpic_enable),
DEVMETHOD(pic_eoi, hrowpic_eoi),
- DEVMETHOD(pic_id, hrowpic_id),
DEVMETHOD(pic_ipi, hrowpic_ipi),
DEVMETHOD(pic_mask, hrowpic_mask),
DEVMETHOD(pic_unmask, hrowpic_unmask),
@@ -169,9 +167,7 @@ hrowpic_attach(device_t dev)
hrowpic_write_reg(sc, HPIC_ENABLE, HPIC_SECONDARY, 0);
hrowpic_write_reg(sc, HPIC_CLEAR, HPIC_SECONDARY, 0xffffffff);
- powerpc_register_pic(dev, 64);
- root_pic = dev; /* Heathrow systems have only one PIC */
-
+ powerpc_register_pic(dev, ofw_bus_get_node(dev), 64, 0, FALSE);
return (0);
}
@@ -282,10 +278,3 @@ hrowpic_unmask(device_t dev, u_int irq)
sc = device_get_softc(dev);
hrowpic_toggle_irq(sc, irq, 1);
}
-
-static uint32_t
-hrowpic_id(device_t dev)
-{
- return (ofw_bus_get_node(dev));
-}
-
diff --git a/sys/powerpc/powermac/openpic_macio.c b/sys/powerpc/powermac/openpic_macio.c
index 880b8f7..e542ae3 100644
--- a/sys/powerpc/powermac/openpic_macio.c
+++ b/sys/powerpc/powermac/openpic_macio.c
@@ -58,12 +58,12 @@ __FBSDID("$FreeBSD$");
* MacIO interface
*/
static int openpic_macio_probe(device_t);
-static uint32_t openpic_macio_id(device_t);
+static int openpic_macio_attach(device_t);
static device_method_t openpic_macio_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, openpic_macio_probe),
- DEVMETHOD(device_attach, openpic_attach),
+ DEVMETHOD(device_attach, openpic_macio_attach),
/* PIC interface */
DEVMETHOD(pic_bind, openpic_bind),
@@ -74,7 +74,6 @@ static device_method_t openpic_macio_methods[] = {
DEVMETHOD(pic_ipi, openpic_ipi),
DEVMETHOD(pic_mask, openpic_mask),
DEVMETHOD(pic_unmask, openpic_unmask),
- DEVMETHOD(pic_id, openpic_macio_id),
{ 0, 0 },
};
@@ -99,9 +98,9 @@ openpic_macio_probe(device_t dev)
return (0);
}
-static uint32_t
-openpic_macio_id(device_t dev)
+static int
+openpic_macio_attach(device_t dev)
{
- return (ofw_bus_get_node(dev));
+
+ return (openpic_common_attach(dev, ofw_bus_get_node(dev)));
}
-
diff --git a/sys/powerpc/powerpc/intr_machdep.c b/sys/powerpc/powerpc/intr_machdep.c
index a33bddb..b8b703d 100644
--- a/sys/powerpc/powerpc/intr_machdep.c
+++ b/sys/powerpc/powerpc/intr_machdep.c
@@ -60,6 +60,8 @@
* $FreeBSD$
*/
+#include "opt_isa.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -102,9 +104,11 @@ struct powerpc_intr {
};
struct pic {
- device_t pic;
- uint32_t pic_id;
- int ipi_irq;
+ device_t dev;
+ uint32_t node;
+ u_int irqs;
+ u_int ipis;
+ int base;
};
static u_int intrcnt_index = 0;
@@ -113,6 +117,11 @@ static struct powerpc_intr *powerpc_intrs[INTR_VECTORS];
static struct pic piclist[MAX_PICS];
static u_int nvectors; /* Allocated vectors */
static u_int npics; /* PICs registered */
+#ifdef DEV_ISA
+static u_int nirqs = 16; /* Allocated IRQS (ISA pre-allocated). */
+#else
+static u_int nirqs = 0; /* Allocated IRQs. */
+#endif
static u_int stray_count;
device_t root_pic;
@@ -142,7 +151,6 @@ smp_intr_init(void *dummy __unused)
PIC_BIND(i->pic, i->intline, i->cpu);
}
}
-
SYSINIT(smp_intr_init, SI_SUB_SMP, SI_ORDER_ANY, smp_intr_init, NULL);
#endif
@@ -231,9 +239,21 @@ intr_lookup(u_int irq)
static int
powerpc_map_irq(struct powerpc_intr *i)
{
+ struct pic *p;
+ u_int cnt;
+ int idx;
- i->intline = INTR_INTLINE(i->irq);
- i->pic = piclist[INTR_IGN(i->irq)].pic;
+ for (idx = 0; idx < npics; idx++) {
+ p = &piclist[idx];
+ cnt = p->irqs + p->ipis;
+ if (i->irq >= p->base && i->irq < p->base + cnt)
+ break;
+ }
+ if (idx == npics)
+ return (EINVAL);
+
+ i->intline = i->irq - p->base;
+ i->pic = p->dev;
/* Try a best guess if that failed */
if (i->pic == NULL)
@@ -288,46 +308,76 @@ powerpc_assign_intr_cpu(void *arg, u_char cpu)
}
void
-powerpc_register_pic(device_t dev, u_int ipi)
+powerpc_register_pic(device_t dev, uint32_t node, u_int irqs, u_int ipis,
+ u_int atpic)
{
- int i;
+ struct pic *p;
+ u_int irq;
+ int idx;
mtx_lock(&intr_table_lock);
- for (i = 0; i < npics; i++) {
- if (piclist[i].pic_id == PIC_ID(dev))
+ /* XXX see powerpc_get_irq(). */
+ for (idx = 0; idx < npics; idx++) {
+ p = &piclist[idx];
+ if (p->node != node)
+ continue;
+ if (node != 0 || p->dev == dev)
break;
}
- piclist[i].pic = dev;
- piclist[i].pic_id = PIC_ID(dev);
- piclist[i].ipi_irq = ipi;
- if (i == npics)
+ p = &piclist[idx];
+
+ p->dev = dev;
+ p->node = node;
+ p->irqs = irqs;
+ p->ipis = ipis;
+ if (idx == npics) {
+#ifdef DEV_ISA
+ p->base = (atpic) ? 0 : nirqs;
+#else
+ p->base = nirqs;
+#endif
+ irq = p->base + irqs + ipis;
+ nirqs = MAX(nirqs, irq);
npics++;
+ }
mtx_unlock(&intr_table_lock);
}
-int
-powerpc_ign_lookup(uint32_t pic_id)
+u_int
+powerpc_get_irq(uint32_t node, u_int pin)
{
- int i;
+ int idx;
- mtx_lock(&intr_table_lock);
+ if (node == 0)
+ return (pin);
- for (i = 0; i < npics; i++) {
- if (piclist[i].pic_id == pic_id) {
+ mtx_lock(&intr_table_lock);
+ for (idx = 0; idx < npics; idx++) {
+ if (piclist[idx].node == node) {
mtx_unlock(&intr_table_lock);
- return (i);
+ return (piclist[idx].base + pin);
}
}
- piclist[i].pic = NULL;
- piclist[i].pic_id = pic_id;
- piclist[i].ipi_irq = 0;
+
+ /*
+ * XXX we should never encounter an unregistered PIC, but that
+ * can only be done when we properly support bus enumeration
+ * using multiple passes. Until then, fake an entry and give it
+ * some adhoc maximum number of IRQs and IPIs.
+ */
+ piclist[idx].dev = NULL;
+ piclist[idx].node = node;
+ piclist[idx].irqs = 124;
+ piclist[idx].ipis = 4;
+ piclist[idx].base = nirqs;
+ nirqs += 128;
npics++;
mtx_unlock(&intr_table_lock);
- return (i);
+ return (piclist[idx].base + pin);
}
int
@@ -342,15 +392,18 @@ powerpc_enable_intr(void)
if (npics == 0)
panic("no PIC detected\n");
+ if (root_pic == NULL)
+ root_pic = piclist[0].dev;
+
#ifdef SMP
/* Install an IPI handler. */
-
for (n = 0; n < npics; n++) {
- if (piclist[n].pic != root_pic)
+ if (piclist[n].dev != root_pic)
continue;
+ KASSERT(piclist[n].ipis != 0, ("%s", __func__));
error = powerpc_setup_intr("IPI",
- INTR_VEC(piclist[n].pic_id, piclist[n].ipi_irq),
+ INTR_VEC(piclist[n].node, piclist[n].irqs),
powerpc_ipi_handler, NULL, NULL,
INTR_TYPE_MISC | INTR_EXCL, &ipi_cookie);
if (error) {
@@ -373,6 +426,9 @@ powerpc_enable_intr(void)
i->pol != INTR_POLARITY_CONFORM)
PIC_CONFIG(i->pic, i->intline, i->trig, i->pol);
+ if (i != NULL && i->pic == root_pic)
+ PIC_BIND(i->pic, i->intline, i->cpu);
+
if (i->event != NULL)
PIC_ENABLE(i->pic, i->intline, vector);
}
diff --git a/sys/powerpc/powerpc/openpic.c b/sys/powerpc/powerpc/openpic.c
index 7668f77..042f8b8 100644
--- a/sys/powerpc/powerpc/openpic.c
+++ b/sys/powerpc/powerpc/openpic.c
@@ -83,7 +83,7 @@ openpic_set_priority(struct openpic_softc *sc, int pri)
}
int
-openpic_attach(device_t dev)
+openpic_common_attach(device_t dev, uint32_t node)
{
struct openpic_softc *sc;
u_int cpu, ipi, irq;
@@ -217,7 +217,7 @@ openpic_attach(device_t dev)
for (cpu = 0; cpu < sc->sc_ncpu; cpu++)
openpic_write(sc, OPENPIC_PCPU_TPR(cpu), 0);
- powerpc_register_pic(dev, sc->sc_nirq);
+ powerpc_register_pic(dev, node, sc->sc_nirq, 4, FALSE);
/* If this is not a cascaded PIC, it must be the root PIC */
if (sc->sc_intr == NULL)
@@ -285,7 +285,6 @@ openpic_dispatch(device_t dev, struct trapframe *tf)
cpuid = (dev == root_pic) ? PCPU_GET(cpuid) : 0;
sc = device_get_softc(dev);
-
while (1) {
vector = openpic_read(sc, OPENPIC_PCPU_IACK(cpuid));
vector &= OPENPIC_VECTOR_MASK;
diff --git a/sys/powerpc/powerpc/pic_if.m b/sys/powerpc/powerpc/pic_if.m
index 04f1c1e..185cc08 100644
--- a/sys/powerpc/powerpc/pic_if.m
+++ b/sys/powerpc/powerpc/pic_if.m
@@ -66,10 +66,6 @@ METHOD void ipi {
u_int cpu;
};
-METHOD uint32_t id {
- device_t dev;
-};
-
METHOD void mask {
device_t dev;
u_int irq;
diff --git a/sys/powerpc/ps3/ps3pic.c b/sys/powerpc/ps3/ps3pic.c
index 5d56d3e..c00585b 100644
--- a/sys/powerpc/ps3/ps3pic.c
+++ b/sys/powerpc/ps3/ps3pic.c
@@ -54,7 +54,6 @@ static void ps3pic_eoi(device_t, u_int);
static void ps3pic_ipi(device_t, u_int);
static void ps3pic_mask(device_t, u_int);
static void ps3pic_unmask(device_t, u_int);
-static uint32_t ps3pic_id(device_t dev);
struct ps3pic_softc {
uint64_t *bitmap_thread0;
@@ -76,7 +75,6 @@ static device_method_t ps3pic_methods[] = {
DEVMETHOD(pic_dispatch, ps3pic_dispatch),
DEVMETHOD(pic_enable, ps3pic_enable),
DEVMETHOD(pic_eoi, ps3pic_eoi),
- DEVMETHOD(pic_id, ps3pic_id),
DEVMETHOD(pic_ipi, ps3pic_ipi),
DEVMETHOD(pic_mask, ps3pic_mask),
DEVMETHOD(pic_unmask, ps3pic_unmask),
@@ -146,9 +144,7 @@ ps3pic_attach(device_t dev)
sc->sc_ipi_outlet[1], 0);
#endif
- powerpc_register_pic(dev, sc->sc_ipi_outlet[0]);
- root_pic = dev; /* PS3s have only one PIC */
-
+ powerpc_register_pic(dev, 0, sc->sc_ipi_outlet[0], 1, FALSE);
return (0);
}
@@ -245,10 +241,3 @@ ps3pic_unmask(device_t dev, u_int irq)
lv1_did_update_interrupt_mask(ppe, 0);
lv1_did_update_interrupt_mask(ppe, 1);
}
-
-static uint32_t
-ps3pic_id(device_t dev)
-{
- return (0);
-}
-
diff --git a/sys/powerpc/psim/openpic_iobus.c b/sys/powerpc/psim/openpic_iobus.c
index 6522985..f2e7cdb 100644
--- a/sys/powerpc/psim/openpic_iobus.c
+++ b/sys/powerpc/psim/openpic_iobus.c
@@ -62,11 +62,12 @@ __FBSDID("$FreeBSD$");
* PSIM IOBus interface
*/
static int openpic_iobus_probe(device_t);
+static int openpic_iobus_attach(device_t);
static device_method_t openpic_iobus_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, openpic_iobus_probe),
- DEVMETHOD(device_attach, openpic_attach),
+ DEVMETHOD(device_attach, openpic_iobus_attach),
/* PIC interface */
DEVMETHOD(pic_config, openpic_config),
@@ -109,3 +110,10 @@ openpic_iobus_probe(device_t dev)
return (0);
}
+
+static int
+openpic_iobus_attach(device_t dev)
+{
+
+ return (openpic_common_attach(dev, 0));
+}
OpenPOWER on IntegriCloud