Index: sys/powerpc/powermac/smu.c =================================================================== --- sys/powerpc/powermac/smu.c +++ sys/powerpc/powermac/smu.c @@ -108,6 +108,7 @@ struct smu_softc { device_t sc_dev; + device_t sc_doorbell; struct mtx sc_mtx; struct resource *sc_memr; @@ -181,8 +182,6 @@ /* where to find the doorbell GPIO */ -static device_t smu_doorbell = NULL; - static device_method_t smu_methods[] = { /* Device interface */ DEVMETHOD(device_probe, smu_probe), @@ -278,6 +277,49 @@ sc->sc_cmd_phys = segs[0].ds_addr; } +static void +smu_setup_intr(device_t smu, device_t doorbell) +{ + struct smu_softc *sc; + static device_t doorbell_dev = NULL; + static device_t smu_dev = NULL; + + /* + * Defer establishing the interrupt until both devices are ready. + */ + if (smu != NULL) + smu_dev = smu; + if (doorbell != NULL) + doorbell_dev = doorbell; + if (smu_dev == NULL || doorbell_dev == NULL) + return; + + /* + * Set up doorbell interrupt. + */ + sc = device_get_softc(smu); + sc->sc_doorbell = doorbell_dev; + sc->sc_doorbellirqid = 0; + sc->sc_doorbellirq = bus_alloc_resource_any(doorbell_dev, SYS_RES_IRQ, + &sc->sc_doorbellirqid, RF_ACTIVE); + bus_setup_intr(doorbell, sc->sc_doorbellirq, + INTR_TYPE_MISC | INTR_MPSAFE, NULL, smu_doorbell_intr, smu_dev, + &sc->sc_doorbellirqcookie); + powerpc_config_intr(rman_get_start(sc->sc_doorbellirq), + INTR_TRIGGER_EDGE, INTR_POLARITY_LOW); + + /* + * Connect RTC interface. + */ + clock_register(smu_dev, 1000); + + /* + * Learn about shutdown events + */ + EVENTHANDLER_REGISTER(shutdown_final, smu_shutdown, smu_dev, + SHUTDOWN_PRI_LAST); +} + static int smu_attach(device_t dev) { @@ -379,28 +421,7 @@ "server_mode", CTLTYPE_INT | CTLFLAG_RW, dev, 0, smu_server_mode, "I", "Enable reboot after power failure"); - /* - * Set up doorbell interrupt. - */ - sc->sc_doorbellirqid = 0; - sc->sc_doorbellirq = bus_alloc_resource_any(smu_doorbell, SYS_RES_IRQ, - &sc->sc_doorbellirqid, RF_ACTIVE); - bus_setup_intr(smu_doorbell, sc->sc_doorbellirq, - INTR_TYPE_MISC | INTR_MPSAFE, NULL, smu_doorbell_intr, dev, - &sc->sc_doorbellirqcookie); - powerpc_config_intr(rman_get_start(sc->sc_doorbellirq), - INTR_TRIGGER_EDGE, INTR_POLARITY_LOW); - - /* - * Connect RTC interface. - */ - clock_register(dev, 1000); - - /* - * Learn about shutdown events - */ - EVENTHANDLER_REGISTER(shutdown_final, smu_shutdown, dev, - SHUTDOWN_PRI_LAST); + smu_setup_intr(dev, NULL); return (bus_generic_attach(dev)); } @@ -420,6 +441,8 @@ sc = device_get_softc(dev); mtx_assert(&sc->sc_mtx, MA_OWNED); + /* Should always have a doorbell dev to get here */ + KASSERT(sc->sc_doorbell != NULL, "Missing doorbell device"); if (sc->sc_u3) powerpc_pow_enabled = 0; /* SMU cannot work if we go to NAP */ @@ -437,7 +460,7 @@ __asm __volatile("sync; dcbf 0,%0; sync" :: "r"(sc->sc_cmd): "memory"); /* Ring SMU doorbell */ - macgpio_write(smu_doorbell, GPIO_DDR_OUTPUT); + macgpio_write(sc->sc_doorbell, GPIO_DDR_OUTPUT); } static void @@ -448,8 +471,8 @@ int doorbell_ack; smu = xdev; - doorbell_ack = macgpio_read(smu_doorbell); sc = device_get_softc(smu); + doorbell_ack = macgpio_read(sc->sc_doorbell); if (doorbell_ack != (GPIO_DDR_OUTPUT | GPIO_LEVEL_RO | GPIO_DATA)) return; @@ -648,7 +671,7 @@ static int doorbell_attach(device_t dev) { - smu_doorbell = dev; + smu_setup_intr(NULL, dev); return (0); }