From owner-svn-src-all@FreeBSD.ORG Fri Jun 18 14:06:28 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3D2241065673; Fri, 18 Jun 2010 14:06:28 +0000 (UTC) (envelope-from nwhitehorn@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 27ED68FC18; Fri, 18 Jun 2010 14:06:28 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o5IE6SvD077956; Fri, 18 Jun 2010 14:06:28 GMT (envelope-from nwhitehorn@svn.freebsd.org) Received: (from nwhitehorn@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o5IE6R2A077930; Fri, 18 Jun 2010 14:06:27 GMT (envelope-from nwhitehorn@svn.freebsd.org) Message-Id: <201006181406.o5IE6R2A077930@svn.freebsd.org> From: Nathan Whitehorn Date: Fri, 18 Jun 2010 14:06:27 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r209298 - in head/sys: dev/iicbus dev/ofw powerpc/aim powerpc/booke powerpc/include powerpc/mpc85xx powerpc/ofw powerpc/powermac powerpc/powerpc sparc64/ebus sparc64/isa sparc64/pci X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 18 Jun 2010 14:06:28 -0000 Author: nwhitehorn Date: Fri Jun 18 14:06:27 2010 New Revision: 209298 URL: http://svn.freebsd.org/changeset/base/209298 Log: Provide for multiple, cascaded PICs on PowerPC systems, and extend the OFW interrupt map interface to also return the device's interrupt parent. MFC after: 8.1-RELEASE Modified: head/sys/dev/iicbus/iiconf.c head/sys/dev/ofw/ofw_bus_subr.c head/sys/dev/ofw/ofw_bus_subr.h head/sys/powerpc/aim/interrupt.c head/sys/powerpc/aim/nexus.c head/sys/powerpc/booke/interrupt.c head/sys/powerpc/include/intr_machdep.h head/sys/powerpc/include/ocpbus.h head/sys/powerpc/include/openpicvar.h head/sys/powerpc/mpc85xx/atpic.c head/sys/powerpc/mpc85xx/isa.c head/sys/powerpc/mpc85xx/ocpbus.c head/sys/powerpc/mpc85xx/ocpbus.h head/sys/powerpc/mpc85xx/opic.c head/sys/powerpc/mpc85xx/pci_ocp.c head/sys/powerpc/ofw/ofw_pcib_pci.c head/sys/powerpc/ofw/ofw_pcibus.c head/sys/powerpc/powermac/cpcht.c head/sys/powerpc/powermac/grackle.c head/sys/powerpc/powermac/hrowpic.c head/sys/powerpc/powermac/macgpio.c head/sys/powerpc/powermac/macio.c head/sys/powerpc/powermac/openpic_macio.c head/sys/powerpc/powermac/uninorth.c head/sys/powerpc/powermac/uninorthpci.c head/sys/powerpc/powerpc/intr_machdep.c head/sys/powerpc/powerpc/mp_machdep.c head/sys/powerpc/powerpc/openpic.c head/sys/powerpc/powerpc/pic_if.m head/sys/sparc64/ebus/ebus.c head/sys/sparc64/isa/ofw_isa.c head/sys/sparc64/pci/fire.c head/sys/sparc64/pci/ofw_pcib_subr.c head/sys/sparc64/pci/psycho.c head/sys/sparc64/pci/schizo.c Modified: head/sys/dev/iicbus/iiconf.c ============================================================================== --- head/sys/dev/iicbus/iiconf.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/dev/iicbus/iiconf.c Fri Jun 18 14:06:27 2010 (r209298) @@ -363,7 +363,7 @@ iicbus_transfer(device_t bus, struct iic int iicbus_transfer_gen(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) { - int i, error, lenread, lenwrote, nkid; + int i, error, lenread, lenwrote, nkid, rpstart, addr; device_t *children, bus; if ((error = device_get_children(dev, &children, &nkid)) != 0) @@ -373,14 +373,38 @@ iicbus_transfer_gen(device_t dev, struct return (EIO); } bus = children[0]; + rpstart = 0; free(children, M_TEMP); for (i = 0, error = 0; i < nmsgs && error == 0; i++) { + addr = msgs[i].slave; if (msgs[i].flags & IIC_M_RD) - error = iicbus_block_read(bus, msgs[i].slave, - msgs[i].buf, msgs[i].len, &lenread); + addr |= LSB; else - error = iicbus_block_write(bus, msgs[i].slave, - msgs[i].buf, msgs[i].len, &lenwrote); + addr &= ~LSB; + + if (!(msgs[i].flags & IIC_M_NOSTART)) { + if (rpstart) + error = iicbus_repeated_start(bus, addr, 0); + else + error = iicbus_start(bus, addr, 0); + } + + if (error) + break; + + if (msgs[i].flags & IIC_M_RD) + error = iicbus_read(bus, msgs[i].buf, msgs[i].len, + &lenread, IIC_LAST_READ, 0); + else + error = iicbus_write(bus, msgs[i].buf, msgs[i].len, + &lenwrote, 0); + + if (!(msgs[i].flags & IIC_M_NOSTOP)) { + rpstart = 0; + iicbus_stop(bus); + } else { + rpstart = 1; /* Next message gets repeated start */ + } } return (error); } Modified: head/sys/dev/ofw/ofw_bus_subr.c ============================================================================== --- head/sys/dev/ofw/ofw_bus_subr.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/dev/ofw/ofw_bus_subr.c Fri Jun 18 14:06:27 2010 (r209298) @@ -222,7 +222,7 @@ ofw_bus_setup_iinfo(phandle_t node, stru int ofw_bus_lookup_imap(phandle_t node, struct ofw_bus_iinfo *ii, void *reg, int regsz, void *pintr, int pintrsz, void *mintr, int mintrsz, - void *maskbuf) + phandle_t *iparent, void *maskbuf) { int rv; @@ -236,7 +236,7 @@ ofw_bus_lookup_imap(phandle_t node, stru panic("ofw_bus_lookup_imap: could not get reg property"); return (ofw_bus_search_intrmap(pintr, pintrsz, reg, ii->opi_addrc, ii->opi_imap, ii->opi_imapsz, ii->opi_imapmsk, maskbuf, mintr, - mintrsz)); + mintrsz, iparent)); } /* @@ -259,7 +259,7 @@ ofw_bus_lookup_imap(phandle_t node, stru int ofw_bus_search_intrmap(void *intr, int intrsz, void *regs, int physsz, void *imap, int imapsz, void *imapmsk, void *maskbuf, void *result, - int rintrsz) + int rintrsz, phandle_t *iparent) { phandle_t parent; uint8_t *ref = maskbuf; @@ -303,6 +303,9 @@ ofw_bus_search_intrmap(void *intr, int i if (bcmp(ref, mptr, physsz + intrsz) == 0) { bcopy(mptr + physsz + intrsz + sizeof(parent), result, rintrsz); + + if (iparent != NULL) + *iparent = parent; return (1); } mptr += tsz; Modified: head/sys/dev/ofw/ofw_bus_subr.h ============================================================================== --- head/sys/dev/ofw/ofw_bus_subr.h Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/dev/ofw/ofw_bus_subr.h Fri Jun 18 14:06:27 2010 (r209298) @@ -63,9 +63,12 @@ bus_child_pnpinfo_str_t ofw_bus_gen_chil /* Routines for processing firmware interrupt maps */ void ofw_bus_setup_iinfo(phandle_t, struct ofw_bus_iinfo *, int); int ofw_bus_lookup_imap(phandle_t, struct ofw_bus_iinfo *, void *, int, - void *, int, void *, int, void *); + void *, int, void *, int, phandle_t *, void *); int ofw_bus_search_intrmap(void *, int, void *, int, void *, int, void *, - void *, void *, int); + void *, void *, int, phandle_t *); + +/* Helper to get node's interrupt parent */ +void ofw_bus_find_iparent(phandle_t); /* Helper routine for checking compat prop */ int ofw_bus_is_compatible(device_t, const char *); Modified: head/sys/powerpc/aim/interrupt.c ============================================================================== --- head/sys/powerpc/aim/interrupt.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/aim/interrupt.c Fri Jun 18 14:06:27 2010 (r209298) @@ -81,7 +81,7 @@ powerpc_interrupt(struct trapframe *fram switch (framep->exc) { case EXC_EXI: critical_enter(); - PIC_DISPATCH(pic, framep); + PIC_DISPATCH(root_pic, framep); critical_exit(); break; Modified: head/sys/powerpc/aim/nexus.c ============================================================================== --- head/sys/powerpc/aim/nexus.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/aim/nexus.c Fri Jun 18 14:06:27 2010 (r209298) @@ -208,7 +208,7 @@ nexus_attach(device_t dev) sc = device_get_softc(dev); start = 0; - end = INTR_VECTORS - 1; + end = MAX_PICS*INTR_VECTORS - 1; sc->sc_rman.rm_start = start; sc->sc_rman.rm_end = end; Modified: head/sys/powerpc/booke/interrupt.c ============================================================================== --- head/sys/powerpc/booke/interrupt.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/booke/interrupt.c Fri Jun 18 14:06:27 2010 (r209298) @@ -134,7 +134,7 @@ powerpc_extr_interrupt(struct trapframe { critical_enter(); - PIC_DISPATCH(pic, framep); + PIC_DISPATCH(root_pic, framep); critical_exit(); framep->srr1 &= ~PSL_WE; } Modified: head/sys/powerpc/include/intr_machdep.h ============================================================================== --- head/sys/powerpc/include/intr_machdep.h Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/include/intr_machdep.h Fri Jun 18 14:06:27 2010 (r209298) @@ -29,26 +29,32 @@ #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) /* * Default base address for MSI messages on PowerPC */ #define MSI_INTEL_ADDR_BASE 0xfee00000 -extern device_t pic; -extern device_t pic8259; +extern device_t root_pic; struct trapframe; driver_filter_t powerpc_ipi_handler; void powerpc_register_pic(device_t, u_int); -void powerpc_register_8259(device_t); +int powerpc_ign_lookup(uint32_t pic_id); void powerpc_dispatch_intr(u_int, struct trapframe *); int powerpc_enable_intr(void); -int powerpc_setup_intr(const char *, u_int, driver_filter_t, - driver_intr_t, void *, enum intr_type, void **); +int powerpc_setup_intr(const char *, u_int, driver_filter_t, driver_intr_t, + void *, enum intr_type, void **); int powerpc_teardown_intr(void *); int powerpc_config_intr(int, enum intr_trigger, enum intr_polarity); Modified: head/sys/powerpc/include/ocpbus.h ============================================================================== --- head/sys/powerpc/include/ocpbus.h Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/include/ocpbus.h Fri Jun 18 14:06:27 2010 (r209298) @@ -44,4 +44,8 @@ #define OCPBUS_DEVTYPE_I2C 7 #define OCPBUS_DEVTYPE_SEC 8 +/* PIC IDs */ +#define OPIC_ID 0 +#define ATPIC_ID 1 + #endif /* _MACHINE_OCPBUS_H_ */ Modified: head/sys/powerpc/include/openpicvar.h ============================================================================== --- head/sys/powerpc/include/openpicvar.h Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/include/openpicvar.h Fri Jun 18 14:06:27 2010 (r209298) @@ -35,10 +35,13 @@ struct openpic_softc { device_t sc_dev; struct resource *sc_memr; + struct resource *sc_intr; bus_space_tag_t sc_bt; bus_space_handle_t sc_bh; char *sc_version; int sc_rid; + int sc_irq; + void *sc_icookie; u_int sc_ncpu; u_int sc_nirq; int sc_psim; Modified: head/sys/powerpc/mpc85xx/atpic.c ============================================================================== --- head/sys/powerpc/mpc85xx/atpic.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/mpc85xx/atpic.c Fri Jun 18 14:06:27 2010 (r209298) @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -79,6 +80,9 @@ 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_t pic8259; static device_method_t atpic_isa_methods[] = { /* Device interface */ @@ -94,6 +98,7 @@ 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 }, }; @@ -219,7 +224,8 @@ atpic_isa_attach(device_t dev) atpic_init(sc, ATPIC_SLAVE); atpic_init(sc, ATPIC_MASTER); - powerpc_register_8259(dev); + powerpc_register_pic(dev, 0x10); + pic8259 = dev; return (0); fail: @@ -328,3 +334,11 @@ 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); +} + Modified: head/sys/powerpc/mpc85xx/isa.c ============================================================================== --- head/sys/powerpc/mpc85xx/isa.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/mpc85xx/isa.c Fri Jun 18 14:06:27 2010 (r209298) @@ -32,12 +32,16 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include #include #include #include #include +#include "ocpbus.h" + void isa_init(device_t dev) { @@ -58,7 +62,10 @@ isa_alloc_resource(device_t bus, device_ 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; break; + case SYS_RES_IRQ: + rids = ISA_PNP_NIRQ; + start = ISA_IRQ(start); + break; case SYS_RES_MEMORY: rids = ISA_PNP_NMEM; break; default: rids = 0; break; } Modified: head/sys/powerpc/mpc85xx/ocpbus.c ============================================================================== --- head/sys/powerpc/mpc85xx/ocpbus.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/mpc85xx/ocpbus.c Fri Jun 18 14:06:27 2010 (r209298) @@ -277,7 +277,7 @@ ocpbus_attach(device_t dev) ccsr_read4(OCP85XX_PORDEVSR), ccsr_read4(OCP85XX_PORDEVSR2)); - for (i = PIC_IRQ_START; i < PIC_IRQ_START + 4; i++) + for (i = INTR_VEC(OPIC_ID, 0); i < INTR_VEC(OPIC_ID, 4); i++) powerpc_config_intr(i, INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW); return (bus_generic_attach(dev)); @@ -305,35 +305,35 @@ const struct ocp_resource mpc8555_resour {OCPBUS_DEVTYPE_QUICC, 0, SYS_RES_MEMORY, 0, OCP85XX_QUICC_OFF, OCP85XX_QUICC_SIZE}, - {OCPBUS_DEVTYPE_QUICC, 0, SYS_RES_IRQ, 0, PIC_IRQ_INT(30), 1}, + {OCPBUS_DEVTYPE_QUICC, 0, SYS_RES_IRQ, 0, 30, 1}, {OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_MEMORY, 0, OCP85XX_TSEC0_OFF, OCP85XX_TSEC_SIZE}, - {OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 0, PIC_IRQ_INT(13), 1}, - {OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 1, PIC_IRQ_INT(14), 1}, - {OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 2, PIC_IRQ_INT(18), 1}, + {OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 0, 13, 1}, + {OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 1, 14, 1}, + {OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 2, 18, 1}, {OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_MEMORY, 0, OCP85XX_TSEC1_OFF, OCP85XX_TSEC_SIZE}, - {OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 0, PIC_IRQ_INT(19), 1}, - {OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 1, PIC_IRQ_INT(20), 1}, - {OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 2, PIC_IRQ_INT(24), 1}, + {OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 0, 19, 1}, + {OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 1, 20, 1}, + {OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 2, 24, 1}, {OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_MEMORY, 0, OCP85XX_TSEC2_OFF, OCP85XX_TSEC_SIZE}, - {OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 0, PIC_IRQ_INT(15), 1}, - {OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 1, PIC_IRQ_INT(16), 1}, - {OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 2, PIC_IRQ_INT(17), 1}, + {OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 0, 15, 1}, + {OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 1, 16, 1}, + {OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 2, 17, 1}, {OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_MEMORY, 0, OCP85XX_TSEC3_OFF, OCP85XX_TSEC_SIZE}, - {OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 0, PIC_IRQ_INT(21), 1}, - {OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 1, PIC_IRQ_INT(22), 1}, - {OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 2, PIC_IRQ_INT(23), 1}, + {OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 0, 21, 1}, + {OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 1, 22, 1}, + {OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 2, 23, 1}, {OCPBUS_DEVTYPE_UART, 0, SYS_RES_MEMORY, 0, OCP85XX_UART0_OFF, OCP85XX_UART_SIZE}, - {OCPBUS_DEVTYPE_UART, 0, SYS_RES_IRQ, 0, PIC_IRQ_INT(26), 1}, + {OCPBUS_DEVTYPE_UART, 0, SYS_RES_IRQ, 0, 26, 1}, {OCPBUS_DEVTYPE_UART, 1, SYS_RES_MEMORY, 0, OCP85XX_UART1_OFF, OCP85XX_UART_SIZE}, - {OCPBUS_DEVTYPE_UART, 1, SYS_RES_IRQ, 0, PIC_IRQ_INT(26), 1}, + {OCPBUS_DEVTYPE_UART, 1, SYS_RES_IRQ, 0, 26, 1}, {OCPBUS_DEVTYPE_PCIB, 0, SYS_RES_MEMORY, 0, OCP85XX_PCI0_OFF, OCP85XX_PCI_SIZE}, @@ -357,15 +357,15 @@ const struct ocp_resource mpc8555_resour {OCPBUS_DEVTYPE_I2C, 0, SYS_RES_MEMORY, 0, OCP85XX_I2C0_OFF, OCP85XX_I2C_SIZE}, - {OCPBUS_DEVTYPE_I2C, 0, SYS_RES_IRQ, 0, PIC_IRQ_INT(27), 1}, + {OCPBUS_DEVTYPE_I2C, 0, SYS_RES_IRQ, 0, 27, 1}, {OCPBUS_DEVTYPE_I2C, 1, SYS_RES_MEMORY, 0, OCP85XX_I2C1_OFF, OCP85XX_I2C_SIZE}, - {OCPBUS_DEVTYPE_I2C, 1, SYS_RES_IRQ, 0, PIC_IRQ_INT(27), 1}, + {OCPBUS_DEVTYPE_I2C, 1, SYS_RES_IRQ, 0, 27, 1}, {OCPBUS_DEVTYPE_SEC, 0, SYS_RES_MEMORY, 0, OCP85XX_SEC_OFF, OCP85XX_SEC_SIZE}, - {OCPBUS_DEVTYPE_SEC, 0, SYS_RES_IRQ, 0, PIC_IRQ_INT(29), 1}, - {OCPBUS_DEVTYPE_SEC, 0, SYS_RES_IRQ, 1, PIC_IRQ_INT(42), 1}, + {OCPBUS_DEVTYPE_SEC, 0, SYS_RES_IRQ, 0, 29, 1}, + {OCPBUS_DEVTYPE_SEC, 0, SYS_RES_IRQ, 1, 42, 1}, {0} }; @@ -402,7 +402,7 @@ ocpbus_get_resource(device_t dev, device start = res->sr_offset + CCSRBAR_VA; break; case SYS_RES_IRQ: - start = res->sr_offset; + start = PIC_IRQ_INT(res->sr_offset); break; default: error = EINVAL; Modified: head/sys/powerpc/mpc85xx/ocpbus.h ============================================================================== --- head/sys/powerpc/mpc85xx/ocpbus.h Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/mpc85xx/ocpbus.h Fri Jun 18 14:06:27 2010 (r209298) @@ -104,11 +104,9 @@ /* * PIC definitions */ -#define ISA_IRQ_START 0 -#define PIC_IRQ_START (ISA_IRQ_START + 16) -#define ISA_IRQ(n) (ISA_IRQ_START + (n)) -#define PIC_IRQ_EXT(n) (PIC_IRQ_START + (n)) -#define PIC_IRQ_INT(n) (PIC_IRQ_START + 16 + (n)) +#define ISA_IRQ(n) (INTR_VEC(ATPIC_ID, n)) +#define PIC_IRQ_EXT(n) (INTR_VEC(OPIC_ID, (n))) +#define PIC_IRQ_INT(n) (INTR_VEC(OPIC_ID, (16 + (n)))) #endif /* _MACHINE_OCP85XX_H */ Modified: head/sys/powerpc/mpc85xx/opic.c ============================================================================== --- head/sys/powerpc/mpc85xx/opic.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/mpc85xx/opic.c Fri Jun 18 14:06:27 2010 (r209298) @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); * OpenPIC attachment to ocpbus */ static int openpic_ocpbus_probe(device_t); +static uint32_t openpic_ocpbus_id(device_t); static device_method_t openpic_ocpbus_methods[] = { /* Device interface */ @@ -63,6 +64,7 @@ static device_method_t openpic_ocpbus_m DEVMETHOD(pic_ipi, openpic_ipi), DEVMETHOD(pic_mask, openpic_mask), DEVMETHOD(pic_unmask, openpic_unmask), + DEVMETHOD(pic_id, openpic_ocpbus_id), { 0, 0 }, }; @@ -93,3 +95,11 @@ openpic_ocpbus_probe (device_t dev) device_set_desc(dev, OPENPIC_DEVSTR); return (BUS_PROBE_DEFAULT); } + +static uint32_t +openpic_ocpbus_id (device_t dev) +{ + return (OPIC_ID); +} + + Modified: head/sys/powerpc/mpc85xx/pci_ocp.c ============================================================================== --- head/sys/powerpc/mpc85xx/pci_ocp.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/mpc85xx/pci_ocp.c Fri Jun 18 14:06:27 2010 (r209298) @@ -792,7 +792,7 @@ pci_ocp_alloc_resource(device_t dev, dev va = sc->sc_iomem_va; break; case SYS_RES_IRQ: - if (start < PIC_IRQ_START) { + if (INTR_IGN(start) == powerpc_ign_lookup(ATPIC_ID)) { device_printf(dev, "%s requested ISA interrupt %lu\n", device_get_nameunit(child), start); } Modified: head/sys/powerpc/ofw/ofw_pcib_pci.c ============================================================================== --- head/sys/powerpc/ofw/ofw_pcib_pci.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/ofw/ofw_pcib_pci.c Fri Jun 18 14:06:27 2010 (r209298) @@ -42,6 +42,8 @@ #include #include +#include + #include "pcib_if.h" static int ofw_pcib_pci_probe(device_t bus); @@ -149,6 +151,7 @@ ofw_pcib_pci_route_interrupt(device_t br struct ofw_bus_iinfo *ii; struct ofw_pci_register reg; cell_t pintr, mintr; + phandle_t iparent; uint8_t maskbuf[sizeof(reg) + sizeof(pintr)]; sc = device_get_softc(bridge); @@ -157,13 +160,13 @@ ofw_pcib_pci_route_interrupt(device_t br pintr = intpin; if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), ii, ®, sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), - maskbuf)) { + &iparent, maskbuf)) { /* * If we've found a mapping, return it and don't map * it again on higher levels - that causes problems * in some cases, and never seems to be required. */ - return (mintr); + return (INTR_VEC(iparent, mintr)); } } else if (intpin >= 1 && intpin <= 4) { /* Modified: head/sys/powerpc/ofw/ofw_pcibus.c ============================================================================== --- head/sys/powerpc/ofw/ofw_pcibus.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/ofw/ofw_pcibus.c Fri Jun 18 14:06:27 2010 (r209298) @@ -212,13 +212,16 @@ ofw_pcibus_enum_devtree(device_t dev, u_ OF_getprop(iparent, "#interrupt-cells", &icells, sizeof(icells)); + if (iparent != 0) + intr[0] = INTR_VEC(iparent, intr[0]); + if (iparent != 0 && icells > 1) { powerpc_config_intr(intr[0], (intr[1] & 1) ? INTR_TRIGGER_LEVEL : INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH); } - + resource_list_add(&dinfo->opd_dinfo.resources, SYS_RES_IRQ, 0, intr[0], intr[0], 1); } @@ -293,7 +296,7 @@ static int ofw_pcibus_assign_interrupt(device_t dev, device_t child) { ofw_pci_intr_t intr; - phandle_t node; + phandle_t node, iparent; int isz; node = ofw_bus_get_node(child); @@ -303,8 +306,8 @@ ofw_pcibus_assign_interrupt(device_t dev /* * XXX: Right now we don't have anything sensible to do here, - * since the ofw_imap stuff relies on nodes have a reg - * property. There exists ways around this, so the ePAPR + * since the ofw_imap stuff relies on nodes having a reg + * property. There exist ways around this, so the ePAPR * spec will need to be studied. */ @@ -318,18 +321,29 @@ ofw_pcibus_assign_interrupt(device_t dev } /* + * Try to determine the node's interrupt parent so we know which + * PIC to use. + */ + + iparent = -1; + if (OF_getprop(node, "interrupt-parent", &iparent, sizeof(iparent)) < 0) + iparent = -1; + + /* * Any AAPL,interrupts property gets priority and is * fully specified (i.e. does not need routing) */ isz = OF_getprop(node, "AAPL,interrupts", &intr, sizeof(intr)); - if (isz == sizeof(intr)) { - return (intr); - } + if (isz == sizeof(intr)) + return ((iparent == -1) ? intr : INTR_VEC(iparent, intr)); isz = OF_getprop(node, "interrupts", &intr, sizeof(intr)); - if (isz != sizeof(intr)) { - /* No property; our best guess is the intpin. */ + if (isz == sizeof(intr)) { + if (iparent != -1) + intr = INTR_VEC(iparent, intr); + } else { + /* No property: our best guess is the intpin. */ intr = pci_get_intpin(child); } Modified: head/sys/powerpc/powermac/cpcht.c ============================================================================== --- head/sys/powerpc/powermac/cpcht.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/powermac/cpcht.c Fri Jun 18 14:06:27 2010 (r209298) @@ -595,6 +595,7 @@ static void openpic_cpcht_config(device_ 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 */ @@ -609,6 +610,7 @@ static device_method_t openpic_cpcht_me 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,3 +810,9 @@ openpic_cpcht_eoi(device_t dev, u_int ir openpic_eoi(dev, irq); } +static uint32_t +openpic_cpcht_id(device_t dev) +{ + return (ofw_bus_get_node(dev)); +} + Modified: head/sys/powerpc/powermac/grackle.c ============================================================================== --- head/sys/powerpc/powermac/grackle.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/powermac/grackle.c Fri Jun 18 14:06:27 2010 (r209298) @@ -43,6 +43,7 @@ #include #include +#include #include #include #include @@ -341,13 +342,15 @@ grackle_route_interrupt(device_t bus, de struct grackle_softc *sc; struct ofw_pci_register reg; uint32_t pintr, mintr; + phandle_t iparent; uint8_t maskbuf[sizeof(reg) + sizeof(pintr)]; sc = device_get_softc(bus); pintr = pin; if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, ®, - sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), maskbuf)) - return (mintr); + sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), + &iparent, maskbuf)) + return (INTR_VEC(iparent, mintr)); /* Maybe it's a real interrupt, not an intpin */ if (pin > 4) Modified: head/sys/powerpc/powermac/hrowpic.c ============================================================================== --- head/sys/powerpc/powermac/hrowpic.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/powermac/hrowpic.c Fri Jun 18 14:06:27 2010 (r209298) @@ -70,6 +70,7 @@ 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,6 +81,7 @@ 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,6 +171,8 @@ hrowpic_attach(device_t dev) hrowpic_write_reg(sc, HPIC_CLEAR, HPIC_SECONDARY, 0xffffffff); powerpc_register_pic(dev, 64); + root_pic = dev; /* Heathrow systems have only one PIC */ + return (0); } @@ -282,3 +286,10 @@ 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)); +} + Modified: head/sys/powerpc/powermac/macgpio.c ============================================================================== --- head/sys/powerpc/powermac/macgpio.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/powermac/macgpio.c Fri Jun 18 14:06:27 2010 (r209298) @@ -35,15 +35,16 @@ #include #include #include -#include #include -#include #include #include -#include +#include +#include +#include #include +#include #include #include @@ -150,8 +151,7 @@ macgpio_attach(device_t dev) { struct macgpio_softc *sc; struct macgpio_devinfo *dinfo; - phandle_t root; - phandle_t child; + phandle_t root, child, iparent; device_t cdev; uint32_t irq; @@ -186,10 +186,13 @@ macgpio_attach(device_t dev) resource_list_init(&dinfo->mdi_resources); - if (OF_getprop(child,"interrupts",&irq, sizeof(irq)) == + if (OF_getprop(child, "interrupts", &irq, sizeof(irq)) == sizeof(irq)) { + OF_searchprop(child, "interrupt-parent", &iparent, + sizeof(iparent)); resource_list_add(&dinfo->mdi_resources, SYS_RES_IRQ, - 0, irq, irq, 1); + 0, INTR_VEC(iparent, irq), INTR_VEC(iparent, irq), + 1); } /* Fix messed-up offsets */ Modified: head/sys/powerpc/powermac/macio.c ============================================================================== --- head/sys/powerpc/powermac/macio.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/powermac/macio.c Fri Jun 18 14:06:27 2010 (r209298) @@ -37,15 +37,16 @@ #include #include #include -#include #include -#include #include #include -#include +#include +#include +#include #include +#include #include #include @@ -186,6 +187,7 @@ macio_get_quirks(const char *name) static void macio_add_intr(phandle_t devnode, struct macio_devinfo *dinfo) { + phandle_t iparent; int *intr; int i, nintr; int icells; @@ -211,11 +213,17 @@ macio_add_intr(phandle_t devnode, struct if (intr[0] == -1) return; + if (OF_getprop(devnode, "interrupt-parent", &iparent, sizeof(iparent)) + <= 0) + panic("Interrupt but no interrupt parent!\n"); + for (i = 0; i < nintr; i+=icells) { resource_list_add(&dinfo->mdi_resources, SYS_RES_IRQ, - dinfo->mdi_ninterrupts, intr[i], intr[i], 1); + dinfo->mdi_ninterrupts, INTR_VEC(iparent, intr[i]), + INTR_VEC(iparent, intr[i]), 1); - dinfo->mdi_interrupts[dinfo->mdi_ninterrupts] = intr[i]; + dinfo->mdi_interrupts[dinfo->mdi_ninterrupts] = + INTR_VEC(iparent, intr[i]); dinfo->mdi_ninterrupts++; } } Modified: head/sys/powerpc/powermac/openpic_macio.c ============================================================================== --- head/sys/powerpc/powermac/openpic_macio.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/powermac/openpic_macio.c Fri Jun 18 14:06:27 2010 (r209298) @@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$"); * MacIO interface */ static int openpic_macio_probe(device_t); +static uint32_t openpic_macio_id(device_t); static device_method_t openpic_macio_methods[] = { /* Device interface */ @@ -73,6 +74,7 @@ static device_method_t openpic_macio_me DEVMETHOD(pic_ipi, openpic_ipi), DEVMETHOD(pic_mask, openpic_mask), DEVMETHOD(pic_unmask, openpic_unmask), + DEVMETHOD(pic_id, openpic_macio_id), { 0, 0 }, }; @@ -96,3 +98,10 @@ openpic_macio_probe(device_t dev) device_set_desc(dev, OPENPIC_DEVSTR); return (0); } + +static uint32_t +openpic_macio_id(device_t dev) +{ + return (ofw_bus_get_node(dev)); +} + Modified: head/sys/powerpc/powermac/uninorth.c ============================================================================== --- head/sys/powerpc/powermac/uninorth.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/powermac/uninorth.c Fri Jun 18 14:06:27 2010 (r209298) @@ -144,9 +144,9 @@ DRIVER_MODULE(unin, nexus, unin_chip_dri static void unin_chip_add_intr(phandle_t devnode, struct unin_chip_devinfo *dinfo) { + phandle_t iparent; int *intr; int i, nintr; - phandle_t iparent; int icells; if (dinfo->udi_ninterrupts >= 6) { @@ -176,9 +176,17 @@ unin_chip_add_intr(phandle_t devnode, st for (i = 0; i < nintr; i+=icells) { resource_list_add(&dinfo->udi_resources, SYS_RES_IRQ, - dinfo->udi_ninterrupts, intr[i], intr[i], 1); + dinfo->udi_ninterrupts, INTR_VEC(iparent, intr[i]), + INTR_VEC(iparent, intr[i]), 1); + + if (icells > 1) { + powerpc_config_intr(INTR_VEC(iparent, intr[i]), + (intr[i+1] & 1) ? INTR_TRIGGER_LEVEL : + INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH); + } - dinfo->udi_interrupts[dinfo->udi_ninterrupts] = intr[i]; + dinfo->udi_interrupts[dinfo->udi_ninterrupts] = + INTR_VEC(iparent, intr[i]); dinfo->udi_ninterrupts++; } } Modified: head/sys/powerpc/powermac/uninorthpci.c ============================================================================== --- head/sys/powerpc/powermac/uninorthpci.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/powermac/uninorthpci.c Fri Jun 18 14:06:27 2010 (r209298) @@ -356,14 +356,15 @@ uninorth_route_interrupt(device_t bus, d struct uninorth_softc *sc; struct ofw_pci_register reg; uint32_t pintr, mintr; + phandle_t iparent; uint8_t maskbuf[sizeof(reg) + sizeof(pintr)]; sc = device_get_softc(bus); pintr = pin; if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, ®, sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), - maskbuf)) - return (mintr); + &iparent, maskbuf)) + return (INTR_VEC(iparent, mintr)); /* Maybe it's a real interrupt, not an intpin */ if (pin > 4) Modified: head/sys/powerpc/powerpc/intr_machdep.c ============================================================================== --- head/sys/powerpc/powerpc/intr_machdep.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/powerpc/intr_machdep.c Fri Jun 18 14:06:27 2010 (r209298) @@ -85,14 +85,6 @@ #include "pic_if.h" -#ifdef MPC85XX -#define ISA_IRQ_COUNT 16 -#endif - -#ifndef ISA_IRQ_COUNT -#define ISA_IRQ_COUNT 0 -#endif - #define MAX_STRAY_LOG 5 MALLOC_DEFINE(M_INTR, "intr", "interrupt handler data"); @@ -108,20 +100,25 @@ struct powerpc_intr { enum intr_polarity pol; }; +struct pic { + device_t pic; + uint32_t pic_id; + int ipi_irq; +}; + static struct mtx intr_table_lock; 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 */ static u_int stray_count; +device_t root_pic; + #ifdef SMP static void *ipi_cookie; #endif -static u_int ipi_irq; - -device_t pic; -device_t pic8259; - static void intr_init(void *dummy __unused) { @@ -198,21 +195,13 @@ static int powerpc_map_irq(struct powerpc_intr *i) { -#if ISA_IRQ_COUNT > 0 - if (i->irq < ISA_IRQ_COUNT) { - if (pic8259 == NULL) { - i->pic = pic; - i->intline = 0; - return (ENXIO); - } - i->pic = pic8259; - i->intline = i->irq; - return (0); - } -#endif + i->intline = INTR_INTLINE(i->irq); + i->pic = piclist[INTR_IGN(i->irq)].pic; + + /* Try a best guess if that failed */ + if (i->pic == NULL) + i->pic = root_pic; - i->pic = pic; - i->intline = i->irq - ISA_IRQ_COUNT; return (0); } @@ -243,16 +232,44 @@ powerpc_intr_unmask(void *arg) void powerpc_register_pic(device_t dev, u_int ipi) { + int i; + + mtx_lock(&intr_table_lock); - pic = dev; - ipi_irq = ipi + ISA_IRQ_COUNT; + for (i = 0; i < npics; i++) { + if (piclist[i].pic_id == PIC_ID(dev)) + break; + } + piclist[i].pic = dev; + piclist[i].pic_id = PIC_ID(dev); + piclist[i].ipi_irq = ipi; + if (i == npics) + npics++; + + mtx_unlock(&intr_table_lock); } -void -powerpc_register_8259(device_t dev) +int +powerpc_ign_lookup(uint32_t pic_id) { + int i; + + mtx_lock(&intr_table_lock); + + for (i = 0; i < npics; i++) { + if (piclist[i].pic_id == pic_id) { + mtx_unlock(&intr_table_lock); + return (i); + } + } + piclist[i].pic = NULL; + piclist[i].pic_id = pic_id; + piclist[i].ipi_irq = 0; + npics++; - pic8259 = dev; + mtx_unlock(&intr_table_lock); + + return (i); } int @@ -260,17 +277,28 @@ powerpc_enable_intr(void) { struct powerpc_intr *i; int error, vector; +#ifdef SMP + int n; +#endif - if (pic == NULL) + if (npics == 0) panic("no PIC detected\n"); #ifdef SMP /* Install an IPI handler. */ - error = powerpc_setup_intr("IPI", ipi_irq, powerpc_ipi_handler, - NULL, NULL, INTR_TYPE_MISC | INTR_EXCL | INTR_FAST, &ipi_cookie); - if (error) { - printf("unable to setup IPI handler\n"); - return (error); + + for (n = 0; n < npics; n++) { + if (piclist[n].pic != root_pic) + continue; + + error = powerpc_setup_intr("IPI", + INTR_VEC(piclist[n].pic_id, piclist[n].ipi_irq), + powerpc_ipi_handler, NULL, NULL, + INTR_TYPE_MISC | INTR_EXCL | INTR_FAST, &ipi_cookie); + if (error) { + printf("unable to setup IPI handler\n"); + return (error); + } } #endif @@ -295,7 +323,7 @@ powerpc_enable_intr(void) } int -powerpc_setup_intr(const char *name, u_int irq, driver_filter_t filter, +powerpc_setup_intr(const char *name, u_int irq, driver_filter_t filter, driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep) { struct powerpc_intr *i; Modified: head/sys/powerpc/powerpc/mp_machdep.c ============================================================================== --- head/sys/powerpc/powerpc/mp_machdep.c Fri Jun 18 11:36:55 2010 (r209297) +++ head/sys/powerpc/powerpc/mp_machdep.c Fri Jun 18 14:06:27 2010 (r209298) @@ -319,7 +319,7 @@ ipi_send(struct pcpu *pc, int ipi) pc, pc->pc_cpuid, ipi); atomic_set_32(&pc->pc_ipimask, (1 << ipi)); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***