1bd687ebfSPeter Grehan /* 2bd687ebfSPeter Grehan * Copyright 2003 by Peter Grehan. All rights reserved. 3bd687ebfSPeter Grehan * 4bd687ebfSPeter Grehan * Redistribution and use in source and binary forms, with or without 5bd687ebfSPeter Grehan * modification, are permitted provided that the following conditions 6bd687ebfSPeter Grehan * are met: 7bd687ebfSPeter Grehan * 1. Redistributions of source code must retain the above copyright 8bd687ebfSPeter Grehan * notice, this list of conditions and the following disclaimer. 9bd687ebfSPeter Grehan * 2. Redistributions in binary form must reproduce the above copyright 10bd687ebfSPeter Grehan * notice, this list of conditions and the following disclaimer in the 11bd687ebfSPeter Grehan * documentation and/or other materials provided with the distribution. 12bd687ebfSPeter Grehan * 3. The name of the author may not be used to endorse or promote products 13bd687ebfSPeter Grehan * derived from this software without specific prior written permission. 14bd687ebfSPeter Grehan * 15bd687ebfSPeter Grehan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16bd687ebfSPeter Grehan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17bd687ebfSPeter Grehan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18bd687ebfSPeter Grehan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19bd687ebfSPeter Grehan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20bd687ebfSPeter Grehan * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21bd687ebfSPeter Grehan * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22bd687ebfSPeter Grehan * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23bd687ebfSPeter Grehan * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24bd687ebfSPeter Grehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25bd687ebfSPeter Grehan * SUCH DAMAGE. 26bd687ebfSPeter Grehan * 27bd687ebfSPeter Grehan * $FreeBSD$ 28bd687ebfSPeter Grehan */ 29bd687ebfSPeter Grehan 30bd687ebfSPeter Grehan /* 31bd687ebfSPeter Grehan * A driver for the PIC found in the Heathrow/Paddington MacIO chips. 32bd687ebfSPeter Grehan * This was superseded by an OpenPIC in the Keylargo and beyond 33bd687ebfSPeter Grehan * MacIO versions. 34bd687ebfSPeter Grehan * 35bd687ebfSPeter Grehan * The device is initially located in the OpenFirmware device tree 36bd687ebfSPeter Grehan * in the earliest stage of the nexus probe. However, no device registers 37bd687ebfSPeter Grehan * are touched until the actual h/w is probed later on during the 38bd687ebfSPeter Grehan * MacIO probe. At that point, any interrupt sources that were allocated 39bd687ebfSPeter Grehan * prior to this are activated. 40bd687ebfSPeter Grehan */ 41bd687ebfSPeter Grehan 42bd687ebfSPeter Grehan #include <sys/param.h> 43bd687ebfSPeter Grehan #include <sys/systm.h> 4440cdee9dSPeter Grehan #include <sys/module.h> 45bd687ebfSPeter Grehan #include <sys/bus.h> 46bd687ebfSPeter Grehan #include <sys/conf.h> 47bd687ebfSPeter Grehan #include <sys/kernel.h> 48bd687ebfSPeter Grehan 49bd687ebfSPeter Grehan #include <dev/ofw/openfirm.h> 50bd687ebfSPeter Grehan 51bd687ebfSPeter Grehan #include <machine/bus.h> 52bd687ebfSPeter Grehan #include <machine/intr.h> 53bd687ebfSPeter Grehan #include <machine/intr_machdep.h> 54bd687ebfSPeter Grehan #include <machine/md_var.h> 55bd687ebfSPeter Grehan #include <machine/nexusvar.h> 56bd687ebfSPeter Grehan #include <machine/pio.h> 57bd687ebfSPeter Grehan #include <machine/resource.h> 58bd687ebfSPeter Grehan 59bd687ebfSPeter Grehan #include <vm/vm.h> 60bd687ebfSPeter Grehan #include <vm/pmap.h> 61bd687ebfSPeter Grehan 62bd687ebfSPeter Grehan #include <sys/rman.h> 63bd687ebfSPeter Grehan 64bd687ebfSPeter Grehan #include <powerpc/powermac/maciovar.h> 65bd687ebfSPeter Grehan #include <powerpc/powermac/hrowpicvar.h> 66bd687ebfSPeter Grehan 67bd687ebfSPeter Grehan #include "pic_if.h" 68bd687ebfSPeter Grehan 69bd687ebfSPeter Grehan /* 70bd687ebfSPeter Grehan * Device interface. 71bd687ebfSPeter Grehan */ 7273cb337cSPeter Grehan static void hrowpic_identify(driver_t *, device_t); 73bd687ebfSPeter Grehan static int hrowpic_probe(device_t); 74bd687ebfSPeter Grehan static int hrowpic_attach(device_t); 75bd687ebfSPeter Grehan 76bd687ebfSPeter Grehan /* 77bd687ebfSPeter Grehan * PIC interface. 78bd687ebfSPeter Grehan */ 79bd687ebfSPeter Grehan static struct resource *hrowpic_allocate_intr(device_t, device_t, int *, 80bd687ebfSPeter Grehan u_long, u_int); 81bd687ebfSPeter Grehan static int hrowpic_setup_intr(device_t, device_t, 82bd687ebfSPeter Grehan struct resource *, int, driver_intr_t, void *, 83bd687ebfSPeter Grehan void **); 84bd687ebfSPeter Grehan static int hrowpic_teardown_intr(device_t, device_t, 85bd687ebfSPeter Grehan struct resource *, void *); 86bd687ebfSPeter Grehan static int hrowpic_release_intr(device_t dev, device_t, int, 87bd687ebfSPeter Grehan struct resource *res); 88bd687ebfSPeter Grehan 89bd687ebfSPeter Grehan /* 90bd687ebfSPeter Grehan * MacIO interface 91bd687ebfSPeter Grehan */ 92bd687ebfSPeter Grehan static int hrowpic_macio_probe(device_t); 93bd687ebfSPeter Grehan static int hrowpic_macio_attach(device_t); 94bd687ebfSPeter Grehan 95bd687ebfSPeter Grehan /* 96bd687ebfSPeter Grehan * Local routines 97bd687ebfSPeter Grehan */ 98bd687ebfSPeter Grehan static void hrowpic_intr(void); 990bfbe7b9SPeter Wemm static void hrowpic_ext_enable_irq(uintptr_t); 1000bfbe7b9SPeter Wemm static void hrowpic_ext_disable_irq(uintptr_t); 101bd687ebfSPeter Grehan static void hrowpic_toggle_irq(struct hrowpic_softc *sc, int, int); 102bd687ebfSPeter Grehan 103bd687ebfSPeter Grehan /* 104bd687ebfSPeter Grehan * Interrupt controller softc. There should only be one. 105bd687ebfSPeter Grehan */ 106bd687ebfSPeter Grehan static struct hrowpic_softc *hpicsoftc; 107bd687ebfSPeter Grehan 108bd687ebfSPeter Grehan /* 109bd687ebfSPeter Grehan * Driver methods. 110bd687ebfSPeter Grehan */ 111bd687ebfSPeter Grehan static device_method_t hrowpic_methods[] = { 112bd687ebfSPeter Grehan /* Device interface */ 11373cb337cSPeter Grehan DEVMETHOD(device_identify, hrowpic_identify), 114bd687ebfSPeter Grehan DEVMETHOD(device_probe, hrowpic_probe), 115bd687ebfSPeter Grehan DEVMETHOD(device_attach, hrowpic_attach), 116bd687ebfSPeter Grehan 117bd687ebfSPeter Grehan /* PIC interface */ 118bd687ebfSPeter Grehan DEVMETHOD(pic_allocate_intr, hrowpic_allocate_intr), 119bd687ebfSPeter Grehan DEVMETHOD(pic_setup_intr, hrowpic_setup_intr), 120bd687ebfSPeter Grehan DEVMETHOD(pic_teardown_intr, hrowpic_teardown_intr), 121bd687ebfSPeter Grehan DEVMETHOD(pic_release_intr, hrowpic_release_intr), 122bd687ebfSPeter Grehan 123bd687ebfSPeter Grehan { 0, 0 } 124bd687ebfSPeter Grehan }; 125bd687ebfSPeter Grehan 126bd687ebfSPeter Grehan static driver_t hrowpic_driver = { 127bd687ebfSPeter Grehan "hrowpic", 128bd687ebfSPeter Grehan hrowpic_methods, 129bd687ebfSPeter Grehan sizeof(struct hrowpic_softc) 130bd687ebfSPeter Grehan }; 131bd687ebfSPeter Grehan 132bd687ebfSPeter Grehan static devclass_t hrowpic_devclass; 133bd687ebfSPeter Grehan 134bd687ebfSPeter Grehan DRIVER_MODULE(hrowpic, nexus, hrowpic_driver, hrowpic_devclass, 0, 0); 135bd687ebfSPeter Grehan 13673cb337cSPeter Grehan static void 13773cb337cSPeter Grehan hrowpic_identify(driver_t *driver, device_t parent) 13873cb337cSPeter Grehan { 13973cb337cSPeter Grehan phandle_t chosen, pic; 14073cb337cSPeter Grehan char type[40]; 14173cb337cSPeter Grehan 14273cb337cSPeter Grehan chosen = OF_finddevice("/chosen"); 14373cb337cSPeter Grehan if (chosen == -1) 14473cb337cSPeter Grehan return; 14573cb337cSPeter Grehan 14673cb337cSPeter Grehan if (OF_getprop(chosen, "interrupt-controller", &pic, 4) != 4) 14773cb337cSPeter Grehan return; 14873cb337cSPeter Grehan 14973cb337cSPeter Grehan OF_getprop(pic, "compatible", type, sizeof(type)); 15073cb337cSPeter Grehan if (strcmp(type, "heathrow")) 15173cb337cSPeter Grehan return; 15273cb337cSPeter Grehan 15373cb337cSPeter Grehan BUS_ADD_CHILD(parent, 0, "hrowpic", 0); 15473cb337cSPeter Grehan } 15573cb337cSPeter Grehan 156bd687ebfSPeter Grehan static int 157bd687ebfSPeter Grehan hrowpic_probe(device_t dev) 158bd687ebfSPeter Grehan { 15973cb337cSPeter Grehan char *name; 160bd687ebfSPeter Grehan 16173cb337cSPeter Grehan name = nexus_get_name(dev); 162bd687ebfSPeter Grehan 16373cb337cSPeter Grehan if (strcmp(name, "hrowpic")) 164bd687ebfSPeter Grehan return (ENXIO); 165bd687ebfSPeter Grehan 166bd687ebfSPeter Grehan device_set_desc(dev, "Heathrow interrupt controller"); 167bd687ebfSPeter Grehan return (0); 168bd687ebfSPeter Grehan } 169bd687ebfSPeter Grehan 170bd687ebfSPeter Grehan static int 171bd687ebfSPeter Grehan hrowpic_attach(device_t dev) 172bd687ebfSPeter Grehan { 173bd687ebfSPeter Grehan struct hrowpic_softc *sc; 174bd687ebfSPeter Grehan 175bd687ebfSPeter Grehan sc = device_get_softc(dev); 176bd687ebfSPeter Grehan 177bd687ebfSPeter Grehan sc->sc_rman.rm_type = RMAN_ARRAY; 178bd687ebfSPeter Grehan sc->sc_rman.rm_descr = device_get_nameunit(dev); 179bd687ebfSPeter Grehan 180bd687ebfSPeter Grehan if (rman_init(&sc->sc_rman) != 0 || 181bd687ebfSPeter Grehan rman_manage_region(&sc->sc_rman, 0, HROWPIC_IRQMAX-1) != 0) { 182bd687ebfSPeter Grehan device_printf(dev, "could not set up resource management"); 183bd687ebfSPeter Grehan return (ENXIO); 184bd687ebfSPeter Grehan } 185bd687ebfSPeter Grehan 18673cb337cSPeter Grehan nexus_install_intcntlr(dev); 187bd687ebfSPeter Grehan intr_init(hrowpic_intr, HROWPIC_IRQMAX, hrowpic_ext_enable_irq, 188bd687ebfSPeter Grehan hrowpic_ext_disable_irq); 189bd687ebfSPeter Grehan 190bd687ebfSPeter Grehan KASSERT(hpicsoftc == NULL, ("hrowpic: h/w already probed")); 191bd687ebfSPeter Grehan hpicsoftc = sc; 192bd687ebfSPeter Grehan 193bd687ebfSPeter Grehan return (0); 194bd687ebfSPeter Grehan } 195bd687ebfSPeter Grehan 196bd687ebfSPeter Grehan /* 197bd687ebfSPeter Grehan * PIC interface 198bd687ebfSPeter Grehan */ 199bd687ebfSPeter Grehan static struct resource * 200bd687ebfSPeter Grehan hrowpic_allocate_intr(device_t picdev, device_t child, int *rid, u_long intr, 201bd687ebfSPeter Grehan u_int flags) 202bd687ebfSPeter Grehan { 203bd687ebfSPeter Grehan struct hrowpic_softc *sc; 204bd687ebfSPeter Grehan struct resource *rv; 205bd687ebfSPeter Grehan int needactivate; 206bd687ebfSPeter Grehan 207bd687ebfSPeter Grehan sc = device_get_softc(picdev); 208bd687ebfSPeter Grehan needactivate = flags & RF_ACTIVE; 209bd687ebfSPeter Grehan flags &= ~RF_ACTIVE; 210bd687ebfSPeter Grehan 211bd687ebfSPeter Grehan rv = rman_reserve_resource(&sc->sc_rman, intr, intr, 1, flags, child); 212bd687ebfSPeter Grehan if (rv == NULL) { 213bd687ebfSPeter Grehan device_printf(picdev, "interrupt reservation failed for %s\n", 214bd687ebfSPeter Grehan device_get_nameunit(child)); 215bd687ebfSPeter Grehan return (NULL); 216bd687ebfSPeter Grehan } 217bd687ebfSPeter Grehan 218bd687ebfSPeter Grehan return (rv); 219bd687ebfSPeter Grehan } 220bd687ebfSPeter Grehan 221bd687ebfSPeter Grehan static int 222bd687ebfSPeter Grehan hrowpic_setup_intr(device_t picdev, device_t child, struct resource *res, 223bd687ebfSPeter Grehan int flags, driver_intr_t *intr, void *arg, void **cookiep) 224bd687ebfSPeter Grehan { 225bd687ebfSPeter Grehan struct hrowpic_softc *sc; 226bd687ebfSPeter Grehan int error; 227bd687ebfSPeter Grehan 228bd687ebfSPeter Grehan sc = device_get_softc(picdev); 229bd687ebfSPeter Grehan 230bd687ebfSPeter Grehan if ((res->r_flags & RF_SHAREABLE) == 0) 231bd687ebfSPeter Grehan flags |= INTR_EXCL; 232bd687ebfSPeter Grehan 233bd687ebfSPeter Grehan /* 234bd687ebfSPeter Grehan * We depend here on rman_activate_resource() being idempotent. 235bd687ebfSPeter Grehan */ 236bd687ebfSPeter Grehan error = rman_activate_resource(res); 237bd687ebfSPeter Grehan if (error) 238bd687ebfSPeter Grehan return (error); 239bd687ebfSPeter Grehan 240bd687ebfSPeter Grehan error = inthand_add(device_get_nameunit(child), res->r_start, intr, 241bd687ebfSPeter Grehan arg, flags, cookiep); 242bd687ebfSPeter Grehan 243bd687ebfSPeter Grehan if (!error) { 244bd687ebfSPeter Grehan /* 245bd687ebfSPeter Grehan * Record irq request, and enable if h/w has been probed 246bd687ebfSPeter Grehan */ 247bd687ebfSPeter Grehan sc->sc_irq[res->r_start] = 1; 248bd687ebfSPeter Grehan if (sc->sc_memr) { 249bd687ebfSPeter Grehan hrowpic_toggle_irq(sc, res->r_start, 1); 250bd687ebfSPeter Grehan } 251bd687ebfSPeter Grehan } 252bd687ebfSPeter Grehan 253bd687ebfSPeter Grehan return (error); 254bd687ebfSPeter Grehan } 255bd687ebfSPeter Grehan 256bd687ebfSPeter Grehan static int 257bd687ebfSPeter Grehan hrowpic_teardown_intr(device_t picdev, device_t child, struct resource *res, 258bd687ebfSPeter Grehan void *ih) 259bd687ebfSPeter Grehan { 260bd687ebfSPeter Grehan int error; 261bd687ebfSPeter Grehan 262bd687ebfSPeter Grehan error = rman_deactivate_resource(res); 263bd687ebfSPeter Grehan if (error) 264bd687ebfSPeter Grehan return (error); 265bd687ebfSPeter Grehan 266bd687ebfSPeter Grehan error = inthand_remove(res->r_start, ih); 267bd687ebfSPeter Grehan 268bd687ebfSPeter Grehan return (error); 269bd687ebfSPeter Grehan } 270bd687ebfSPeter Grehan 271bd687ebfSPeter Grehan static int 272bd687ebfSPeter Grehan hrowpic_release_intr(device_t picdev, device_t child, int rid, 273bd687ebfSPeter Grehan struct resource *res) 274bd687ebfSPeter Grehan { 275bd687ebfSPeter Grehan int error; 276bd687ebfSPeter Grehan 277bd687ebfSPeter Grehan if (rman_get_flags(res) & RF_ACTIVE) { 278bd687ebfSPeter Grehan error = bus_deactivate_resource(child, SYS_RES_IRQ, rid, res); 279bd687ebfSPeter Grehan if (error) 280bd687ebfSPeter Grehan return (error); 281bd687ebfSPeter Grehan } 282bd687ebfSPeter Grehan 283bd687ebfSPeter Grehan return (rman_release_resource(res)); 284bd687ebfSPeter Grehan } 285bd687ebfSPeter Grehan 286bd687ebfSPeter Grehan /* 287bd687ebfSPeter Grehan * Interrupt interface 288bd687ebfSPeter Grehan */ 289bd687ebfSPeter Grehan static void 290bd687ebfSPeter Grehan hrowpic_write_reg(struct hrowpic_softc *sc, u_int reg, u_int bank, 291bd687ebfSPeter Grehan u_int32_t val) 292bd687ebfSPeter Grehan { 293bd687ebfSPeter Grehan if (bank == HPIC_PRIMARY) 294bd687ebfSPeter Grehan reg += HPIC_1ST_OFFSET; 295bd687ebfSPeter Grehan 296bd687ebfSPeter Grehan bus_space_write_4(sc->sc_bt, sc->sc_bh, reg, val); 297bd687ebfSPeter Grehan 298bd687ebfSPeter Grehan /* 299bd687ebfSPeter Grehan * XXX Issue a read to force the write to complete 300bd687ebfSPeter Grehan */ 301bd687ebfSPeter Grehan bus_space_read_4(sc->sc_bt, sc->sc_bh, reg); 302bd687ebfSPeter Grehan } 303bd687ebfSPeter Grehan 304bd687ebfSPeter Grehan static u_int32_t 305bd687ebfSPeter Grehan hrowpic_read_reg(struct hrowpic_softc *sc, u_int reg, u_int bank) 306bd687ebfSPeter Grehan { 307bd687ebfSPeter Grehan if (bank == HPIC_PRIMARY) 308bd687ebfSPeter Grehan reg += HPIC_1ST_OFFSET; 309bd687ebfSPeter Grehan 310bd687ebfSPeter Grehan return (bus_space_read_4(sc->sc_bt, sc->sc_bh, reg)); 311bd687ebfSPeter Grehan } 312bd687ebfSPeter Grehan 313bd687ebfSPeter Grehan static void 314bd687ebfSPeter Grehan hrowpic_clear_all(struct hrowpic_softc *sc) 315bd687ebfSPeter Grehan { 316bd687ebfSPeter Grehan /* 317bd687ebfSPeter Grehan * Disable all interrupt sources and clear outstanding interrupts 318bd687ebfSPeter Grehan */ 319bd687ebfSPeter Grehan hrowpic_write_reg(sc, HPIC_ENABLE, HPIC_PRIMARY, 0); 320bd687ebfSPeter Grehan hrowpic_write_reg(sc, HPIC_CLEAR, HPIC_PRIMARY, 0xffffffff); 321bd687ebfSPeter Grehan hrowpic_write_reg(sc, HPIC_ENABLE, HPIC_SECONDARY, 0); 322bd687ebfSPeter Grehan hrowpic_write_reg(sc, HPIC_CLEAR, HPIC_SECONDARY, 0xffffffff); 323bd687ebfSPeter Grehan } 324bd687ebfSPeter Grehan 325bd687ebfSPeter Grehan static void 326bd687ebfSPeter Grehan hrowpic_toggle_irq(struct hrowpic_softc *sc, int irq, int enable) 327bd687ebfSPeter Grehan { 328bd687ebfSPeter Grehan u_int roffset; 329bd687ebfSPeter Grehan u_int rbit; 330bd687ebfSPeter Grehan 331bd687ebfSPeter Grehan KASSERT((irq > 0) && (irq < HROWPIC_IRQMAX), ("en irq out of range")); 332bd687ebfSPeter Grehan 333bd687ebfSPeter Grehan /* 334bd687ebfSPeter Grehan * Calculate prim/sec register bank for the IRQ, update soft copy, 335bd687ebfSPeter Grehan * and enable the IRQ as an interrupt source 336bd687ebfSPeter Grehan */ 337bd687ebfSPeter Grehan roffset = HPIC_INT_TO_BANK(irq); 338bd687ebfSPeter Grehan rbit = HPIC_INT_TO_REGBIT(irq); 339bd687ebfSPeter Grehan 340bd687ebfSPeter Grehan if (enable) 341bd687ebfSPeter Grehan sc->sc_softreg[roffset] |= (1 << rbit); 342bd687ebfSPeter Grehan else 343bd687ebfSPeter Grehan sc->sc_softreg[roffset] &= ~(1 << rbit); 344bd687ebfSPeter Grehan 345bd687ebfSPeter Grehan hrowpic_write_reg(sc, HPIC_ENABLE, roffset, sc->sc_softreg[roffset]); 346bd687ebfSPeter Grehan } 347bd687ebfSPeter Grehan 348bd687ebfSPeter Grehan static void 349bd687ebfSPeter Grehan hrowpic_intr(void) 350bd687ebfSPeter Grehan { 351bd687ebfSPeter Grehan int irq_lo, irq_hi; 352bd687ebfSPeter Grehan int i; 353bd687ebfSPeter Grehan struct hrowpic_softc *sc; 354bd687ebfSPeter Grehan 355bd687ebfSPeter Grehan sc = hpicsoftc; 356bd687ebfSPeter Grehan 357bd687ebfSPeter Grehan /* 358bd687ebfSPeter Grehan * Loop through both interrupt sources until they are empty. 359bd687ebfSPeter Grehan * XXX simplistic code, far from optimal. 360bd687ebfSPeter Grehan */ 361bd687ebfSPeter Grehan do { 362bd687ebfSPeter Grehan irq_lo = hrowpic_read_reg(sc, HPIC_STATUS, HPIC_PRIMARY); 363bd687ebfSPeter Grehan if (irq_lo) { 364bd687ebfSPeter Grehan hrowpic_write_reg(sc, HPIC_CLEAR, HPIC_PRIMARY, 365bd687ebfSPeter Grehan irq_lo); 366bd687ebfSPeter Grehan for (i = 0; i < HROWPIC_IRQ_REGNUM; i++) { 367bd687ebfSPeter Grehan if (irq_lo & (1 << i)) { 368bd687ebfSPeter Grehan /* 369bd687ebfSPeter Grehan * Disable IRQ and call handler 370bd687ebfSPeter Grehan */ 371bd687ebfSPeter Grehan hrowpic_toggle_irq(sc, i, 0); 372bd687ebfSPeter Grehan intr_handle(i); 373bd687ebfSPeter Grehan } 374bd687ebfSPeter Grehan } 375bd687ebfSPeter Grehan 376bd687ebfSPeter Grehan } 377bd687ebfSPeter Grehan 378bd687ebfSPeter Grehan irq_hi = hrowpic_read_reg(sc, HPIC_STATUS, HPIC_SECONDARY); 379bd687ebfSPeter Grehan if (irq_hi) { 380bd687ebfSPeter Grehan hrowpic_write_reg(sc, HPIC_CLEAR, HPIC_SECONDARY, 381bd687ebfSPeter Grehan irq_hi); 382bd687ebfSPeter Grehan for (i = 0; i < HROWPIC_IRQ_REGNUM; i++) { 383bd687ebfSPeter Grehan if (irq_hi & (1 << i)) { 384bd687ebfSPeter Grehan /* 385bd687ebfSPeter Grehan * Disable IRQ and call handler 386bd687ebfSPeter Grehan */ 387bd687ebfSPeter Grehan hrowpic_toggle_irq(sc, 388bd687ebfSPeter Grehan i + HROWPIC_IRQ_REGNUM, 0); 389bd687ebfSPeter Grehan intr_handle(i + HROWPIC_IRQ_REGNUM); 390bd687ebfSPeter Grehan } 391bd687ebfSPeter Grehan } 392bd687ebfSPeter Grehan } 393bd687ebfSPeter Grehan } while (irq_lo && irq_hi); 394bd687ebfSPeter Grehan } 395bd687ebfSPeter Grehan 396bd687ebfSPeter Grehan static void 3970bfbe7b9SPeter Wemm hrowpic_ext_enable_irq(uintptr_t irq) 398bd687ebfSPeter Grehan { 399bd687ebfSPeter Grehan hrowpic_toggle_irq(hpicsoftc, irq, 1); 400bd687ebfSPeter Grehan } 401bd687ebfSPeter Grehan 402bd687ebfSPeter Grehan static void 4030bfbe7b9SPeter Wemm hrowpic_ext_disable_irq(uintptr_t irq) 404bd687ebfSPeter Grehan { 405bd687ebfSPeter Grehan hrowpic_toggle_irq(hpicsoftc, irq, 0); 406bd687ebfSPeter Grehan } 407bd687ebfSPeter Grehan 408bd687ebfSPeter Grehan 409bd687ebfSPeter Grehan /* 410bd687ebfSPeter Grehan * MacIO interface 411bd687ebfSPeter Grehan */ 412bd687ebfSPeter Grehan 413bd687ebfSPeter Grehan static device_method_t hrowpic_macio_methods[] = { 414bd687ebfSPeter Grehan /* Device interface */ 415bd687ebfSPeter Grehan DEVMETHOD(device_probe, hrowpic_macio_probe), 416bd687ebfSPeter Grehan DEVMETHOD(device_attach, hrowpic_macio_attach), 417bd687ebfSPeter Grehan 418bd687ebfSPeter Grehan { 0, 0 }, 419bd687ebfSPeter Grehan }; 420bd687ebfSPeter Grehan 421bd687ebfSPeter Grehan static driver_t hrowpic_macio_driver = { 422bd687ebfSPeter Grehan "hrowpicmacio", 423bd687ebfSPeter Grehan hrowpic_macio_methods, 424bd687ebfSPeter Grehan 0 425bd687ebfSPeter Grehan }; 426bd687ebfSPeter Grehan 427bd687ebfSPeter Grehan static devclass_t hrowpic_macio_devclass; 428bd687ebfSPeter Grehan 429bd687ebfSPeter Grehan DRIVER_MODULE(hrowpicmacio, macio, hrowpic_macio_driver, 430bd687ebfSPeter Grehan hrowpic_macio_devclass, 0, 0); 431bd687ebfSPeter Grehan 432bd687ebfSPeter Grehan static int 433bd687ebfSPeter Grehan hrowpic_macio_probe(device_t dev) 434bd687ebfSPeter Grehan { 435bd687ebfSPeter Grehan char *type = macio_get_devtype(dev); 436bd687ebfSPeter Grehan 437bd687ebfSPeter Grehan /* 438bd687ebfSPeter Grehan * OpenPIC cells have a type of "open-pic", so this 439bd687ebfSPeter Grehan * is sufficient to identify a Heathrow cell 440bd687ebfSPeter Grehan */ 441bd687ebfSPeter Grehan if (strcmp(type, "interrupt-controller") != 0) 442bd687ebfSPeter Grehan return (ENXIO); 443bd687ebfSPeter Grehan 444bd687ebfSPeter Grehan /* 445bd687ebfSPeter Grehan * The description was already printed out in the nexus 446bd687ebfSPeter Grehan * probe, so don't do it again here 447bd687ebfSPeter Grehan */ 448bd687ebfSPeter Grehan device_set_desc(dev, "Heathrow MacIO interrupt cell"); 449bd687ebfSPeter Grehan device_quiet(dev); 450bd687ebfSPeter Grehan return (0); 451bd687ebfSPeter Grehan } 452bd687ebfSPeter Grehan 453bd687ebfSPeter Grehan static int 454bd687ebfSPeter Grehan hrowpic_macio_attach(device_t dev) 455bd687ebfSPeter Grehan { 456bd687ebfSPeter Grehan struct hrowpic_softc *sc = hpicsoftc; 457bd687ebfSPeter Grehan int rid; 458bd687ebfSPeter Grehan int i; 459bd687ebfSPeter Grehan 460bd687ebfSPeter Grehan KASSERT(sc != NULL, ("pic not nexus-probed\n")); 461bd687ebfSPeter Grehan sc->sc_maciodev = dev; 462bd687ebfSPeter Grehan 463bd687ebfSPeter Grehan rid = 0; 4645f96beb9SNate Lawson sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 465bd687ebfSPeter Grehan RF_ACTIVE); 466bd687ebfSPeter Grehan 467bd687ebfSPeter Grehan if (sc->sc_memr == NULL) { 468bd687ebfSPeter Grehan device_printf(dev, "Could not alloc mem resource!\n"); 469bd687ebfSPeter Grehan return (ENXIO); 470bd687ebfSPeter Grehan } 471bd687ebfSPeter Grehan 472bd687ebfSPeter Grehan sc->sc_bt = rman_get_bustag(sc->sc_memr); 473bd687ebfSPeter Grehan sc->sc_bh = rman_get_bushandle(sc->sc_memr); 474bd687ebfSPeter Grehan 475bd687ebfSPeter Grehan hrowpic_clear_all(sc); 476bd687ebfSPeter Grehan 477bd687ebfSPeter Grehan /* 478bd687ebfSPeter Grehan * Enable all IRQs that were requested before the h/w 479bd687ebfSPeter Grehan * was probed 480bd687ebfSPeter Grehan */ 481bd687ebfSPeter Grehan for (i = 0; i < HROWPIC_IRQMAX; i++) 482bd687ebfSPeter Grehan if (sc->sc_irq[i]) { 483bd687ebfSPeter Grehan hrowpic_toggle_irq(sc, i, 1); 484bd687ebfSPeter Grehan } 485bd687ebfSPeter Grehan 486bd687ebfSPeter Grehan return (0); 487bd687ebfSPeter Grehan } 488