Index: dev/ofw/ofwbus.c =================================================================== --- dev/ofw/ofwbus.c +++ dev/ofw/ofwbus.c @@ -136,7 +136,7 @@ sizeof(struct ofwbus_softc) }; static devclass_t ofwbus_devclass; -DRIVER_MODULE(ofwbus, nexus, ofwbus_driver, ofwbus_devclass, 0, 0); +EARLY_DRIVER_MODULE(ofwbus, nexus, ofwbus_driver, ofwbus_devclass, 0, 0, BUS_PASS_BUS); MODULE_VERSION(ofwbus, 1); static const char *const ofwbus_excl_name[] = { Index: dev/pci/hostb_pci.c =================================================================== --- dev/pci/hostb_pci.c +++ dev/pci/hostb_pci.c @@ -264,4 +264,4 @@ static devclass_t pci_hostb_devclass; -DRIVER_MODULE(hostb, pci, pci_hostb_driver, pci_hostb_devclass, 0, 0); +EARLY_DRIVER_MODULE(hostb, pci, pci_hostb_driver, pci_hostb_devclass, 0, 0, BUS_PASS_BUS); Index: dev/pci/pci.c =================================================================== --- dev/pci/pci.c +++ dev/pci/pci.c @@ -136,8 +136,6 @@ DEVMETHOD(device_detach, bus_generic_detach), #endif DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, pci_suspend), - DEVMETHOD(device_resume, pci_resume), /* Bus interface */ DEVMETHOD(bus_print_child, pci_print_child), @@ -147,6 +145,8 @@ DEVMETHOD(bus_driver_added, pci_driver_added), DEVMETHOD(bus_setup_intr, pci_setup_intr), DEVMETHOD(bus_teardown_intr, pci_teardown_intr), + DEVMETHOD(bus_suspend_child, pci_suspend_child), + DEVMETHOD(bus_resume_child, pci_resume_child), DEVMETHOD(bus_get_dma_tag, pci_get_dma_tag), DEVMETHOD(bus_get_resource_list,pci_get_resource_list), @@ -192,7 +192,7 @@ DEFINE_CLASS_0(pci, pci_driver, pci_methods, sizeof(struct pci_softc)); static devclass_t pci_devclass; -DRIVER_MODULE(pci, pcib, pci_driver, pci_devclass, pci_modevent, NULL); +EARLY_DRIVER_MODULE(pci, pcib, pci_driver, pci_devclass, pci_modevent, NULL, BUS_PASS_BUS); MODULE_VERSION(pci, 1); static char *pci_vendordata; @@ -3625,12 +3625,11 @@ #endif static void -pci_set_power_children(device_t dev, device_t *devlist, int numdevs, - int state) +pci_set_power_child(device_t dev, device_t child, int state) { - device_t child, pcib; + device_t pcib; struct pci_devinfo *dinfo; - int dstate, i; + int dstate; /* * Set the device to the given state. If the firmware suggests @@ -3640,102 +3639,47 @@ * are handled separately. */ pcib = device_get_parent(dev); - for (i = 0; i < numdevs; i++) { - child = devlist[i]; - dinfo = device_get_ivars(child); - dstate = state; - if (device_is_attached(child) && - PCIB_POWER_FOR_SLEEP(pcib, dev, &dstate) == 0) - pci_set_powerstate(child, dstate); - } + dinfo = device_get_ivars(child); + dstate = state; + if (device_is_attached(child) && + PCIB_POWER_FOR_SLEEP(pcib, dev, &dstate) == 0) + pci_set_powerstate(child, dstate); } int -pci_suspend(device_t dev) +pci_suspend_child(device_t dev, device_t child) { - device_t child, *devlist; struct pci_devinfo *dinfo; - int error, i, numdevs; + int error; - /* - * Save the PCI configuration space for each child and set the - * device in the appropriate power state for this sleep state. - */ - if ((error = device_get_children(dev, &devlist, &numdevs)) != 0) + dinfo = device_get_ivars(child); + pci_cfg_save(child, dinfo, 0); + + error = bus_generic_suspend_child(dev, child); + + if (error) return (error); - for (i = 0; i < numdevs; i++) { - child = devlist[i]; - dinfo = device_get_ivars(child); - pci_cfg_save(child, dinfo, 0); - } - /* Suspend devices before potentially powering them down. */ - error = bus_generic_suspend(dev); - if (error) { - free(devlist, M_TEMP); - return (error); - } if (pci_do_power_suspend) - pci_set_power_children(dev, devlist, numdevs, - PCI_POWERSTATE_D3); - free(devlist, M_TEMP); + pci_set_power_child(dev, child, PCI_POWERSTATE_D3); + return (0); } int -pci_resume(device_t dev) +pci_resume_child(device_t dev, device_t child) { - device_t child, *devlist; struct pci_devinfo *dinfo; - int error, i, numdevs; + int error; - /* - * Set each child to D0 and restore its PCI configuration space. - */ - if ((error = device_get_children(dev, &devlist, &numdevs)) != 0) - return (error); if (pci_do_power_resume) - pci_set_power_children(dev, devlist, numdevs, - PCI_POWERSTATE_D0); + pci_set_power_child(dev, child, PCI_POWERSTATE_D0); + error = bus_generic_resume_child(dev, child); - /* Now the device is powered up, restore its config space. */ - for (i = 0; i < numdevs; i++) { - child = devlist[i]; - dinfo = device_get_ivars(child); + dinfo = device_get_ivars(child); + pci_cfg_restore(child, dinfo); - pci_cfg_restore(child, dinfo); - if (!device_is_attached(child)) - pci_cfg_save(child, dinfo, 1); - } - - /* - * Resume critical devices first, then everything else later. - */ - for (i = 0; i < numdevs; i++) { - child = devlist[i]; - switch (pci_get_class(child)) { - case PCIC_DISPLAY: - case PCIC_MEMORY: - case PCIC_BRIDGE: - case PCIC_BASEPERIPH: - DEVICE_RESUME(child); - break; - } - } - for (i = 0; i < numdevs; i++) { - child = devlist[i]; - switch (pci_get_class(child)) { - case PCIC_DISPLAY: - case PCIC_MEMORY: - case PCIC_BRIDGE: - case PCIC_BASEPERIPH: - break; - default: - DEVICE_RESUME(child); - } - } - free(devlist, M_TEMP); - return (0); + return (error); } static void Index: dev/pci/pci_private.h =================================================================== --- dev/pci/pci_private.h +++ dev/pci/pci_private.h @@ -117,8 +117,8 @@ int pci_child_pnpinfo_str_method(device_t cbdev, device_t child, char *buf, size_t buflen); int pci_assign_interrupt_method(device_t dev, device_t child); -int pci_resume(device_t dev); -int pci_suspend(device_t dev); +int pci_resume_child(device_t dev, device_t child); +int pci_suspend_child(device_t dev, device_t child); bus_dma_tag_t pci_get_dma_tag(device_t bus, device_t dev); /** Restore the config register state. The state must be previously Index: kern/bus_if.m =================================================================== --- kern/bus_if.m +++ kern/bus_if.m @@ -670,3 +670,25 @@ device_t _child; u_int _irq; } DEFAULT null_remap_intr; + +/** + * @brief Resume a child of the bus + * + * @param _dev the bus device + * @param _child the child device + */ +METHOD int resume_child { + device_t _dev; + device_t _child; +} DEFAULT bus_generic_resume_child; + +/** + * @brief Suspend a child of the bus + * + * @param _dev the bus device + * @param _child the child device + */ +METHOD int suspend_child { + device_t _dev; + device_t _child; +} DEFAULT bus_generic_suspend_child; Index: kern/subr_bus.c =================================================================== --- kern/subr_bus.c +++ kern/subr_bus.c @@ -124,6 +124,7 @@ char* nameunit; /**< name+unit e.g. foodev0 */ char* desc; /**< driver specific description */ int busy; /**< count of calls to device_busy() */ + int pass; /**< pass number this device was attached at */ device_state_t state; /**< current device state */ uint32_t devflags; /**< api level flags for device_get_flags() */ u_int flags; /**< internal device flags */ @@ -135,6 +136,7 @@ #define DF_DONENOMATCH 0x20 /* don't execute DEVICE_NOMATCH again */ #define DF_EXTERNALSOFTC 0x40 /* softc not allocated by us */ #define DF_REBID 0x80 /* Can rebid after attach */ +#define DF_SUSPENDED 0x100 /* Device is currently suspended. */ u_int order; /**< order from device_add_child_ordered() */ void *ivars; /**< instance variables */ void *softc; /**< current driver's variables */ @@ -1774,6 +1776,7 @@ dev->devflags = 0; dev->flags = DF_ENABLED; dev->order = 0; + dev->pass = parent ? parent->pass : BUS_PASS_ROOT; if (unit == -1) dev->flags |= DF_WILDCARD; if (name) { @@ -2858,6 +2861,7 @@ else dev->state = DS_ATTACHED; dev->flags &= ~DF_DONENOMATCH; + dev->pass = bus_current_pass; devadded(dev); return (0); } @@ -3630,6 +3634,45 @@ } /** + * @brief Helper function for implementing DEVICE_SUSPEND_CHILD() + * + * This function can be used to help implement the DEVICE_SUSPEND_CHILD() + * for a bus. It calls DEVICE_SUSPEND() for the given child. + */ +int +bus_generic_suspend_child(device_t dev, device_t child) +{ + int error; + + error = DEVICE_SUSPEND(child); + if (!error) + child->flags |= DF_SUSPENDED; + + return (error); +} + +/** + * @brief Helper function for implementing DEVICE_RESUME_CHILD() + * + * This function can be used to help implement the DEVICE_RESUME_CHILD() + * for a bus. It calls DEVICE_RESUME() for the given child. + */ +int +bus_generic_resume_child(device_t dev, device_t child) +{ + int error; + + error = DEVICE_RESUME(child); + /* + * Regardless of resume state, there's nothing we can do, so mark it + * attached again. + */ + child->flags &= ~DF_SUSPENDED; + + return (error); +} + +/** * @brief Helper function for implementing DEVICE_SUSPEND() * * This function can be used to help implement the DEVICE_SUSPEND() @@ -3641,20 +3684,37 @@ int bus_generic_suspend(device_t dev) { - int error; + int error = 0; device_t child, child2; + if (dev->flags & DF_SUSPENDED) + return (0); + TAILQ_FOREACH(child, &dev->children, link) { - error = DEVICE_SUSPEND(child); + if (!(child->state & DF_SUSPENDED)) + error = bus_generic_suspend(child); + if (error == 0) { + if (child->pass >= bus_current_pass && child->state == DS_ATTACHED) { + if (bootverbose) + printf("Suspending %s, child of %s\n", child->nameunit, dev->nameunit); + error = BUS_SUSPEND_CHILD(dev, child); + if (error != 0) + printf("Error suspending child %s: %d\n", child->nameunit, error); + } + } + if (error) { for (child2 = TAILQ_FIRST(&dev->children); - child2 && child2 != child; - child2 = TAILQ_NEXT(child2, link)) - DEVICE_RESUME(child2); + child2 && child2 != child; + child2 = TAILQ_NEXT(child2, link)) { + BUS_RESUME_CHILD(dev, child2); + bus_generic_resume(child2); + } return (error); } } - return (0); + + return (error); } /** @@ -3669,8 +3729,18 @@ device_t child; TAILQ_FOREACH(child, &dev->children, link) { - DEVICE_RESUME(child); - /* if resume fails, there's nothing we can usefully do... */ + if (child->pass == bus_current_pass && (child->flags & DF_SUSPENDED)) { + if (bootverbose) + printf("Resuming %s, child of %s\n", child->nameunit, dev->nameunit); + BUS_RESUME_CHILD(dev, child); + + /* if resume fails, there's nothing we can usefully do... */ + } + + /* Recurse through the child, resuming all its children. */ + if (child->pass <= bus_current_pass) { + bus_generic_resume(child); + } } return (0); } @@ -4477,11 +4547,53 @@ static int root_resume(device_t dev) { - int error; + struct driverlink *dl; + int error = 0; + int rv = 0; - error = bus_generic_resume(dev); - if (error == 0) + TAILQ_FOREACH(dl, &passes, passlink) { + /* + * Raise the pass level to the next level and rescan + * the tree. + */ + bus_current_pass = dl->pass; + error = bus_generic_resume(dev); + if (error != 0) + rv = error; + } + + if (rv == 0) devctl_notify("kern", "power", "resume", NULL); + return (rv); +} + +static int +root_suspend(device_t dev) +{ + struct driverlink *dl; + int error = 0; + + TAILQ_FOREACH_REVERSE(dl, &passes, driver_list, passlink) { + bus_current_pass = dl->pass; + printf("New pass: %d\n", bus_current_pass); + error = bus_generic_suspend(dev); + if (error != 0) + break; + } + + if (error != 0) { + printf("Error %d\n", error); + TAILQ_FOREACH_FROM(dl, &passes, passlink) { + if (dl->pass <= bus_current_pass) + continue; + + bus_current_pass = dl->pass; + error = bus_generic_resume(dev); + if (error != 0) + break; + } + } + return (error); } @@ -4522,7 +4634,7 @@ static kobj_method_t root_methods[] = { /* Device interface */ KOBJMETHOD(device_shutdown, bus_generic_shutdown), - KOBJMETHOD(device_suspend, bus_generic_suspend), + KOBJMETHOD(device_suspend, root_suspend), KOBJMETHOD(device_resume, root_resume), /* Bus interface */ @@ -4700,7 +4812,7 @@ if (!dev) return; - indentprintf(("device %d: <%s> %sparent,%schildren,%s%s%s%s%s,%sivars,%ssoftc,busy=%d\n", + indentprintf(("device %d: <%s> %sparent,%schildren,%s%s%s%s%s%s,%sivars,%ssoftc,busy=%d\n", dev->unit, dev->desc, (dev->parent? "":"no "), (TAILQ_EMPTY(&dev->children)? "no ":""), @@ -4709,6 +4821,7 @@ (dev->flags&DF_WILDCARD? "wildcard,":""), (dev->flags&DF_DESCMALLOCED? "descmalloced,":""), (dev->flags&DF_REBID? "rebiddable,":""), + (dev->flags&DF_SUSPENDED? "suspended,":""), (dev->ivars? "":"no "), (dev->softc? "":"no "), dev->busy)); Index: powerpc/ofw/ofw_pcib_pci.c =================================================================== --- powerpc/ofw/ofw_pcib_pci.c +++ powerpc/ofw/ofw_pcib_pci.c @@ -83,7 +83,7 @@ DEFINE_CLASS_1(pcib, ofw_pcib_pci_driver, ofw_pcib_pci_methods, sizeof(struct ofw_pcib_softc), pcib_driver); -DRIVER_MODULE(ofw_pcib, pci, ofw_pcib_pci_driver, pcib_devclass, 0, 0); +EARLY_DRIVER_MODULE(ofw_pcib, pci, ofw_pcib_pci_driver, pcib_devclass, 0, 0, BUS_PASS_BUS); static int ofw_pcib_pci_probe(device_t dev) Index: powerpc/ofw/ofw_pcibus.c =================================================================== --- powerpc/ofw/ofw_pcibus.c +++ powerpc/ofw/ofw_pcibus.c @@ -93,7 +93,7 @@ DEFINE_CLASS_1(pci, ofw_pcibus_driver, ofw_pcibus_methods, sizeof(struct pci_softc), pci_driver); -DRIVER_MODULE(ofw_pcibus, pcib, ofw_pcibus_driver, pci_devclass, 0, 0); +EARLY_DRIVER_MODULE(ofw_pcibus, pcib, ofw_pcibus_driver, pci_devclass, 0, 0, BUS_PASS_BUS); MODULE_VERSION(ofw_pcibus, 1); MODULE_DEPEND(ofw_pcibus, pci, 1, 1, 1); Index: powerpc/ofw/openpic_ofw.c =================================================================== --- powerpc/ofw/openpic_ofw.c +++ powerpc/ofw/openpic_ofw.c @@ -95,7 +95,7 @@ DRIVER_MODULE(openpic, ofwbus, openpic_ofw_driver, openpic_devclass, 0, 0); DRIVER_MODULE(openpic, simplebus, openpic_ofw_driver, openpic_devclass, 0, 0); -DRIVER_MODULE(openpic, macio, openpic_ofw_driver, openpic_devclass, 0, 0); +EARLY_DRIVER_MODULE(openpic, macio, openpic_ofw_driver, openpic_devclass, 0, 0, BUS_PASS_INTERRUPT); static int openpic_ofw_probe(device_t dev) Index: powerpc/powermac/ata_macio.c =================================================================== --- powerpc/powermac/ata_macio.c +++ powerpc/powermac/ata_macio.c @@ -51,6 +51,7 @@ #include #include "ata_dbdma.h" +#include "maciovar.h" /* * Offset to control registers from base @@ -116,6 +117,7 @@ static int ata_macio_begin_transaction(struct ata_request *request); static int ata_macio_suspend(device_t dev); static int ata_macio_resume(device_t dev); +static void ata_macio_chreset(device_t dev); static device_method_t ata_macio_methods[] = { /* Device interface */ @@ -126,6 +128,7 @@ /* ATA interface */ DEVMETHOD(ata_setmode, ata_macio_setmode), + DEVMETHOD(ata_reset, ata_macio_chreset), DEVMETHOD_END }; @@ -356,6 +359,17 @@ return (error); } +static void +ata_macio_chreset(device_t dev) +{ + struct ata_channel *ch = device_get_softc(dev); + + if (ch->dma.reset) + ch->dma.reset(dev); + macio_reset_ata(dev); + ata_generic_reset(dev); +} + static int ata_macio_resume(device_t dev) { Index: powerpc/powermac/macgpio.c =================================================================== --- powerpc/powermac/macgpio.c +++ powerpc/powermac/macgpio.c @@ -124,7 +124,7 @@ devclass_t macgpio_devclass; -DRIVER_MODULE(macgpio, macio, macgpio_pci_driver, macgpio_devclass, 0, 0); +EARLY_DRIVER_MODULE(macgpio, macio, macgpio_pci_driver, macgpio_devclass, 0, 0, BUS_PASS_BUS); struct macgpio_devinfo { struct ofw_bus_devinfo mdi_obdinfo; Index: powerpc/powermac/maciovar.h =================================================================== --- powerpc/powermac/maciovar.h +++ powerpc/powermac/maciovar.h @@ -44,18 +44,329 @@ #define KEYLARGO_FCR0 0x38 #define KEYLARGO_FCR1 0x3c #define KEYLARGO_FCR2 0x40 +#define KEYLARGO_FCR3 0x44 +#define KEYLARGO_FCR4 0x48 +#define KEYLARGO_FCR5 0x4c +#define K2_FCR10 0x24 +#define K2_FCR9 0x28 +#define K2_FCR8 0x2c +#define K2_FCR7 0x30 +#define K2_FCR6 0x34 + #define FCR_ENET_ENABLE 0x60000000 #define FCR_ENET_RESET 0x80000000 -#define FCR1_I2S0_CLK_ENABLE 0x00001000 -#define FCR1_I2S0_ENABLE 0x00002000 - /* Used only by macio_enable_wireless() for now. */ #define KEYLARGO_GPIO_BASE 0x6a #define KEYLARGO_EXTINT_GPIO_REG_BASE 0x58 +#define KEYLARGO_MEDIABAY 0x34 +#define KEYLARGO_MB0_DEV_ENABLE 0x00001000 +#define KEYLARGO_MB0_DEV_POWER 0x00000400 +#define KEYLARGO_MB0_DEV_RESET 0x00000200 +#define KEYLARGO_MB0_ENABLE 0x00000100 +#define KEYLARGO_MB1_DEV_ENABLE 0x10000000 +#define KEYLARGO_MB1_DEV_POWER 0x04000000 +#define KEYLARGO_MB1_DEV_RESET 0x02000000 +#define KEYLARGO_MB1_ENABLE 0x01000000 + +#define FCR0_CHOOSE_SCCB 0x00000001 +#define FCR0_CHOOSE_SCCA 0x00000002 +#define FCR0_SLOW_SCC_PCLK 0x00000004 +#define FCR0_RESET_SCC 0x00000008 +#define FCR0_SCCA_ENABLE 0x00000010 +#define FCR0_SCCB_ENABLE 0x00000020 +#define FCR0_SCC_CELL_ENABLE 0x00000040 +#define FCR0_CHOOSE_VIA 0x00000080 +#define FCR0_HIGH_BAND_FOR_1MB 0x00000080 +#define FCR0_USE_IR_SOURCE_2 0x00000200 /* KeyLargo */ +#define FCR0_USE_IR_SOURCE_1 0x00000400 /* KeyLargo */ +#define FCR0_USB0_PMI_ENABLE 0x00000400 /* Pangea and Intrepid */ +#define FCR0_IRDA_SWRESET 0x00000800 /* KeyLargo */ +#define FCR0_USB0_REF_SUSPEND_SEL 0x00000800 /* Pangea and Intrepid */ +#define FCR0_IRDA_DEFAULT1 0x00001000 /* KeyLargo */ +#define FCR0_USB0_REF_SUSPEND 0x00001000 /* Pangea and Intrepid */ +#define FCR0_IRDA_DEFAULT0 0x00002000 /* KeyLargo */ +#define FCR0_USB0_PAD_SUSPEND_SEL 0x00002000 /* Pangea and Intrepid */ +#define FCR0_IRDA_FAST_CON 0x00004000 /* KeyLargo */ +#define FCR0_USB1_PMI_ENABLE 0x00004000 /* Pangea and Intrepid */ +#define FCR0_IRDA_ENABLE 0x00008000 +#define FCR0_USB1_REF_SUSPEND_SEL 0x00008000 +#define FCR0_IRDA_CLK32_ENABLE 0x00010000 +#define FCR0_USB1_REF_SUSPEND 0x00010000 +#define FCR0_IRDA_CLK19_ENABLE 0x00020000 +#define FCR0_USB1_PAD_SUSPEND_SEL 0x00020000 +#define FCR0_USB0_PAD_SUSPEND_0 0x00040000 +#define FCR0_USB0_PAD_SUSPEND_1 0x00080000 +#define FCR0_USB0_CELL_ENABLE 0x00100000 +#define FCR0_USB1_PAD_SUSPEND_0 0x00400000 +#define FCR0_USB1_PAD_SUSPEND_1 0x00800000 +#define FCR0_USB1_CELL_ENABLE 0x01000000 +#define FCR0_USB_REF_SUSPEND 0x10000000 + +#define FCR1_USB2_PMI_ENABLE 0x00000001 +#define FCR1_AUDIO_SEL_22MCLK 0x00000002 +#define FCR1_USB2_REF_SUSPEND_SEL 0x00000002 +#define FCR1_USB2_REF_SUSPEND 0x00000002 +#define FCR1_AUDIO_CLK_ENABLE 0x00000008 +#define FCR1_USB2_PAD_SUSPEND_SEL 0x00000008 +#define FCR1_USB2_PAD_SUSPEND0 0x00000010 +#define FCR1_AUDIO_CLKOUT_ENABLE 0x00000020 +#define FCR1_USB2_PAD_SUSPEND1 0x00000020 +#define FCR1_AUDIO_CELL_ENABLE 0x00000040 +#define FCR1_USB2_CELL_ENABLE 0x00000040 +#define FCR1_CHOOSE_AUDIO 0x00000080 +#define FCR1_CHOOSE_I2S0 0x00000400 +#define FCR1_I2S0_CELL_ENABLE 0x00000400 +#define FCR1_I2S0_CLK_ENABLE 0x00001000 +#define FCR1_I2S0_ENABLE 0x00002000 +#define FCR1_I2S1_CELL_ENABLE 0x00020000 +#define FCR1_I2S1_CLK_ENABLE 0x00080000 +#define FCR1_I2S1_ENABLE 0x00100000 +#define FCR1_EIDE0_ENABLE 0x00800000 +#define FCR1_EIDE0_RESET 0x01000000 +#define FCR1_EIDE1_ENABLE 0x04000000 +#define FCR1_EIDE1_RESET 0x08000000 +#define FCR1_UIDE_ENABLE 0x20000000 +#define FCR1_UIDE_RESET 0x40000000 + +#define FCR2_IOBUS_ENABLE 0x00000002 +#define FCR2_SLEEP_STATE 0x00000100 +#define FCR2_STOP_ALL_KL_CLOCKS 0x00000100 +#define FCR2_MPIC_ENABLE 0x00020000 +#define FCR2_CARD_SLOT_RESET 0x00040000 +#define FCR2_ALT_DATA_OUT 0x02000000 + +#define FCR3_SHUTDOWN_PLL_TOTAL 0x00000001 +#define FCR3_SHUTDOWN_PLL_KW6 0x00000002 +#define FCR3_SHUTDOWN_PLL3 0x00000002 +#define FCR3_SHUTDOWN_PLL_KW4 0x00000004 +#define FCR3_SHUTDOWN_PLL2 0x00000004 +#define FCR3_SHUTDOWN_PLL_KW35 0x00000008 +#define FCR3_SHUTDOWN_PLL1 0x00000008 +#define FCR3_SHUTDOWN_PLL_KW12 0x00000010 +#define FCR3_ENABLE_PLL3_SHUTDOWN 0x00000010 +#define FCR3_ENABLE_PLL2_SHUTDOWN 0x00000020 +#define FCR3_ENABLE_PLL1_SHUTDOWN 0x00000040 +#define FCR3_SHUTDOWN_PLL_2X 0x00000080 +#define FCR3_CLK_66_ENABLE 0x00000100 +#define FCR3_CLK_49_ENABLE 0x00000200 +#define FCR3_CLK_45_ENABLE 0x00000400 +#define FCR3_CLK_31_ENABLE 0x00000800 +#define FCR3_TMR_CLK18_ENABLE 0x00001000 +#define FCR3_I2S1_CLK18_ENABLE 0x00002000 +#define FCR3_I2S0_CLK18_ENABLE 0x00004000 +#define FCR3_VIA_CLK16_ENABLE 0x00008000 +#define FCR3_VIA_CLK32_ENABLE 0x00008000 +#define FCR3_PORT5_DISCONNECT_SELECT 0x00010000 +#define FCR3_PORT5_CONNECT_SELECT 0x00020000 +#define FCR3_PORT5_RESUME_SELECT 0x00040000 +#define FCR3_PORT5_ENABLE 0x00080000 +#define FCR3_STOPPING_33_ENABLED 0x00080000 +#define FCR3_PLL_ENABLE_TEST 0x00080000 +#define FCR3_PORT5_DISCONNECT 0x00100000 +#define FCR3_PORT5_CONNECT 0x00200000 +#define FCR3_PORT5_RESUME 0x00400000 +#define FCR3_PORT6_DISCONNECT_SELECT 0x00800000 +#define FCR3_PORT6_CONNECT_SELECT 0x02000000 +#define FCR3_PORT6_RESUME_SELECT 0x04000000 +#define FCR3_PORT6_ENABLE 0x08000000 +#define FCR3_PORT6_DISCONNECT 0x10000000 +#define FCR3_PORT6_CONNECT 0x20000000 +#define FCR3_PORT6_RESUME 0x40000000 + +#define FCR4_PORT1_DISCONNECT_SELECT 0x00000001 +#define FCR4_PORT1_CONNECT_SELECT 0x00000002 +#define FCR4_PORT1_RESUME_SELECT 0x00000004 +#define FCR4_PORT1_ENABLE 0x00000008 +#define FCR4_PORT1_DISCONNECT 0x00000010 +#define FCR4_PORT1_CONNECT 0x00000020 +#define FCR4_PORT1_RESUME 0x00000040 +#define FCR4_PORT2_DISCONNECT_SELECT 0x00000100 +#define FCR4_PORT2_CONNECT_SELECT 0x00000200 +#define FCR4_PORT2_RESUME_SELECT 0x00000400 +#define FCR4_PORT2_ENABLE 0x00000800 +#define FCR4_PORT2_DISCONNECT 0x00001000 +#define FCR4_PORT2_CONNECT 0x00002000 +#define FCR4_PORT2_RESUME 0x00004000 +#define FCR4_PORT3_DISCONNECT_SELECT 0x00010000 +#define FCR4_PORT3_CONNECT_SELECT 0x00020000 +#define FCR4_PORT3_RESUME_SELECT 0x00040000 +#define FCR4_PORT3_ENABLE 0x00080000 +#define FCR4_PORT3_DISCONNECT 0x00100000 +#define FCR4_PORT3_CONNECT 0x00200000 +#define FCR4_PORT3_RESUME 0x00400000 +#define FCR4_PORT4_DISCONNECT_SELECT 0x01000000 +#define FCR4_PORT4_CONNECT_SELECT 0x02000000 +#define FCR4_PORT4_RESUME_SELECT 0x04000000 +#define FCR4_PORT4_ENABLE 0x08000000 +#define FCR4_PORT4_DISCONNECT 0x10000000 +#define FCR4_PORT4_CONNECT 0x20000000 +#define FCR4_PORT4_RESUME 0x40000000 + +#define FCR5_VIA_USE_CLK31 0x00000001 +#define FCR5_SCC_USE_CLK31 0x00000002 +#define FCR5_PWM_CLK32_ENABLE 0x00000004 +#define FCR5_CLK3_68_ENABLE 0x00000010 +#define FCR5_CLK32_ENABLE 0x00000020 + +/* KeyLargo sleep bits */ +#define KEYLARGO_FCR0_SLEEP_SET FCR0_USB_REF_SUSPEND +#define KEYLARGO_FCR0_SLEEP_CLR (FCR0_SCCA_ENABLE | FCR0_SCCB_ENABLE | \ + FCR0_SCC_CELL_ENABLE | FCR0_IRDA_ENABLE | FCR0_IRDA_CLK32_ENABLE | \ + FCR0_IRDA_CLK19_ENABLE) + +#define KEYLARGO_FCR1_SLEEP_SET 0 +#define KEYLARGO_FCR1_SLEEP_CLR (FCR1_AUDIO_SEL_22MCLK | FCR1_AUDIO_CLK_ENABLE | \ + FCR1_AUDIO_CLKOUT_ENABLE | FCR1_AUDIO_CELL_ENABLE | \ + FCR1_I2S0_CELL_ENABLE | FCR1_I2S0_CLK_ENABLE | FCR1_I2S0_ENABLE | \ + FCR1_I2S1_CELL_ENABLE | FCR1_I2S1_CLK_ENABLE | FCR1_I2S1_ENABLE | \ + FCR1_EIDE0_ENABLE | FCR1_EIDE1_ENABLE | FCR1_UIDE_ENABLE | \ + FCR1_EIDE0_RESET | FCR1_EIDE1_RESET) + +#define KEYLARGO_FCR2_SLEEP_SET 0 +#define KEYLARGO_FCR2_SLEEP_CLR FCR2_IOBUS_ENABLE + +#define KEYLARGO_FCR3_SLEEP_SET (FCR3_SHUTDOWN_PLL_KW6 | FCR3_SHUTDOWN_PLL_KW4 | \ + FCR3_SHUTDOWN_PLL_KW35 | FCR3_SHUTDOWN_PLL_KW12) +#define KEYLARGO_FCR3_SLEEP_CLR (FCR3_CLK_66_ENABLE | FCR3_CLK_49_ENABLE | \ + FCR3_CLK_45_ENABLE | FCR3_CLK_31_ENABLE | FCR3_TMR_CLK18_ENABLE | \ + FCR3_I2S1_CLK18_ENABLE | FCR3_I2S0_CLK18_ENABLE | FCR3_VIA_CLK32_ENABLE) + +/* Pangea sleep bits */ +#define PANGEA_FCR0_SLEEP_SET 0 +#define PANGEA_FCR0_SLEEP_CLR (FCR0_USB1_CELL_ENABLE | FCR0_USB0_CELL_ENABLE | \ + FCR0_SCC_CELL_ENABLE | FCR0_SCCB_ENABLE | FCR0_SCCA_ENABLE) + +#define PANGEA_FCR1_SLEEP_SET 0 +#define PANGEA_FCR1_SLEEP_CLR (FCR1_AUDIO_SEL_22MCLK | FCR1_AUDIO_CLK_ENABLE | \ + FCR1_AUDIO_CLKOUT_ENABLE | FCR1_AUDIO_CELL_ENABLE | \ + FCR1_I2S0_CELL_ENABLE | FCR1_I2S0_CLK_ENABLE | FCR1_I2S0_ENABLE | \ + FCR1_I2S1_CELL_ENABLE | FCR1_I2S1_CLK_ENABLE | FCR1_I2S1_ENABLE | \ + FCR1_UIDE_ENABLE) + +#define PANGEA_FCR2_SLEEP_SET FCR2_ALT_DATA_OUT +#define PANGEA_FCR2_SLEEP_CLR 0 + +#define PANGEEA_FCR3_SLEEP_SET (FCR3_SHUTDOWN_PLL_KW35 | \ + FCR3_SHUTDOWN_PLL_KW4 | FCR3_SHUTDOWN_PLL_KW6) +#define PANGEA_FCR3_SLEEP_CLR (FCR3_CLK_49_ENABLE | FCR3_CLK_45_ENABLE | \ + FCR3_CLK_31_ENABLE | FCR3_TMR_CLK18_ENABLE | \ + FCR3_I2S1_CLK18_ENABLE | FCR3_I2S0_CLK18_ENABLE | FCR3_VIA_CLK16_ENABLE) + +/* Intrepid sleep bits */ +#define INTREPID_FCR0_SLEEP_SET 0 +#define INTREPID_FCR0_SLEEP_CLR (FCR0_SCCA_ENABLE | FCR0_SCCB_ENABLE | \ + FCR0_SCC_CELL_ENABLE) + +#define INTREPID_FCR1_SLEEP_SET 0 +#define INTREPID_FCR1_SLEEP_CLR ( FCR1_I2S0_CELL_ENABLE | \ + FCR1_I2S0_CLK_ENABLE | FCR1_I2S0_ENABLE | \ + FCR1_I2S1_CELL_ENABLE | FCR1_I2S1_CLK_ENABLE | \ + FCR1_I2S1_ENABLE | FCR1_UIDE_ENABLE) + +#define INTREPID_FCR2_SLEEP_SET 0 +#define INTREPID_FCR2_SLEEP_CLR 0 + +#define INTREPID_FCR3_SLEEP_SET 0 +#define INTREPID_FCR3_SLEEP_CLR (FCR3_CLK_49_ENABLE | FCR3_CLK_45_ENABLE | \ + FCR3_TMR_CLK18_ENABLE | \ + FCR3_I2S1_CLK18_ENABLE | FCR3_I2S0_CLK18_ENABLE | FCR3_VIA_CLK16_ENABLE) + + /* + * K2 FCRs. + */ +#define FCR0_K2_USB0_SWRESET 0x00200000 +#define FCR0_K2_USB1_SWRESET 0x02000000 +#define FCR0_K2_RING_PME_DISABLE 0x08000000 + +#define FCR1_K2_I2S2_CELL_ENABLE 0x00000010 +#define FCR1_K2_I2S2_CLK_ENABLE 0x00000040 +#define FCR1_K2_I2S2_ENABLE 0x00000080 +#define FCR1_K2_PCI1_BUS_RESET 0x00000100 +#define FCR1_K2_PCI1_SLEEP_RESET_EN 0x00000200 +#define FCR1_K2_PCI1_CLK_ENABLE 0x00004000 +#define FCR1_K2_FW_CLK_ENABLE 0x00008000 +#define FCR1_K2_FW_RESET 0x00010000 +#define FCR1_K2_I2S1_SWRESET 0x00040000 +#define FCR1_K2_GB_CLK_ENABLE 0x00400000 +#define FCR1_GB_PWR_DOWN 0x00800000 +#define FCR1_K2_GB_RESET 0x01000000 +#define FCR1_K2_SATA_CLK_ENABLE 0x02000000 +#define FCR1_K2_SATA_PWR_DOWN 0x04000000 +#define FCR1_K2_SATA_RESET 0x08000000 +#define FCR1_K2_UATA_CLK_ENABLE 0x10000000 +#define FCR1_K2_UATA_RESET 0x40000000 +#define FCR1_K2_UATA_CHOOSE_CLK66 0x80000000 + +#define FCR2_K2_PWM0_AUTO_STOP_EN 0x00000010 +#define FCR2_K2_PWM1_AUTO_STOP_EN 0x00000020 +#define FCR2_K2_PWM2_AUTO_STOP_EN 0x00000040 +#define FCR2_K2_PWM3_AUTO_STOP_EN 0x00000080 +#define FCR2_K2_PWM0_OVER_TEMP_EN 0x00000100 +#define FCR2_K2_PWM1_OVER_TEMP_EN 0x00000200 +#define FCR2_K2_PWM2_OVER_TEMP_EN 0x00000400 +#define FCR2_K2_PWM3_OVER_TEMP_EN 0x00000800 +#define FCR2_K2_HT_ENABLE_INTERRUPTS 0x00008000 +#define FCR2_K2_SB_MPIC_ENABLE_OUTPUTS 0x00010000 +#define FCR2_K2_SB_MPIC_RESET 0x00010000 +#define FCR2_K2_FW_LINK_ON_INT_EN 0x00040000 +#define FCR2_K2_FW_ALT_LINK_ON_SEL 0x00080000 +#define FCR2_K2_PWMS_EN 0x00100000 +#define FCR2_K2_GB_WAKE_INT_EN 0x00200000 +#define FCR2_K2_GB_ENERGY_INT_EN 0x00400000 +#define FCR2_K2_BLOCK_EXT_GPIO1 0x00800000 +#define FCR2_K2_PCI0_BRIDGE_INT 0x01000000 +#define FCR2_K2_PCI1_BRIDGE_INT 0x02000000 +#define FCR2_K2_PCI2_BRIDGE_INT 0x04000000 +#define FCR2_K2_PCI3_BRIDGE_INT 0x08000000 +#define FCR2_K2_PCI4_BRIDGE_INT 0x10000000 +#define FCR2_K2_HT_NONFATAL_ERROR 0x40000000 +#define FCR2_K2_HT_FATAL_ERROR 0x80000000 + +#define FCR3_K2_ENABLE_OSC25_SHUTDOWN 0x00000001 +#define FCR3_K2_ENABLE_FW_PAD_PWRDOWN 0x00000002 +#define FCR3_K2_ENABLE_GBPAD_PWRDOWN 0x00000004 +#define FCR3_K2_ENABLE_PLL0_SHUTDOWN 0x00000080 +#define FCR3_K2_ENABLE_PLL6_SHUTDOWN 0x00000100 +#define FCR3_K2_DYN_CLK_STOP_ENABLE 0x00000800 +#define FCR3_K2_I2S2_CLK18_ENABLE 0x00008000 + +#define FCR9_K2_PCI1_CLK66_IS_STOPPED 0x00000001 +#define FCR9_K2_PCI2_CLK66_IS_STOPPED 0x00000002 +#define FCR9_K2_FW_CLK66_IS_STOPPED 0x00000004 +#define FCR9_K2_UATA_CLK66_IS_STOPPED 0x00000008 +#define FCR9_K2_UATA_CLK100_IS_STOPPED 0x00000010 +#define FCR9_K2_PCI3_CLK66_IS_STOPPED 0x00000020 +#define FCR9_K2_GB_CLK66_IS_STOPPED 0x00000040 +#define FCR9_K2_PCI4_CLK66_IS_STOPPED 0x00000080 +#define FCR9_K2_SATA_CLK66_IS_STOPPED 0x00000100 +#define FCR9_K2_USB0_CLK48_IS_STOPPED 0x00000200 +#define FCR9_K2_USB1_CLK48_IS_STOPPED 0x00000400 +#define FCR9_K2_CLK45_IS_STOPPED 0x00000800 +#define FCR9_K2_CLK49_IS_STOPPED 0x00001000 +#define FCR9_K2_OSC25_SHUTDOWN 0x00008000 + +/* K2 sleep bits */ +#define K2_FCR0_SLEEP_SET 0 +#define K2_FCR0_SLEEP_CLR (FCR0_USB1_CELL_ENABLE | FCR0_USB0_CELL_ENABLE | \ + FCR0_SCC_CELL_ENABLE | FCR0_SCCB_ENABLE | FCR0_SCCA_ENABLE) + +#define K2_FCR1_SLEEP_SET 0 +#define K2_FCR1_SLEEP_CLR ( FCR1_I2S0_CELL_ENABLE | \ + FCR1_I2S0_CLK_ENABLE | FCR1_I2S0_ENABLE | \ + FCR1_I2S1_CELL_ENABLE | FCR1_I2S1_CLK_ENABLE | FCR1_I2S1_ENABLE | \ + FCR1_K2_SATA_RESET | FCR1_K2_UATA_RESET | FCR1_K2_GB_CLK_ENABLE) + +#define K2_FCR2_SLEEP_SET 0 +#define K2_FCR2_SLEEP_CLR FCR2_K2_SB_MPIC_ENABLE_OUTPUTS + +#define K2_FCR3_SLEEP_SET 0 +#define K2_FCR3_SLEEP_CLR FCR3_K2_ENABLE_OSC25_SHUTDOWN + +/* * Format of a macio reg property entry. */ struct macio_reg { @@ -70,10 +381,12 @@ int mdi_interrupts[6]; int mdi_ninterrupts; int mdi_base; + int mdi_aapl_busid; struct ofw_bus_devinfo mdi_obdinfo; struct resource_list mdi_resources; }; extern int macio_enable_wireless(device_t dev, bool enable); +extern int macio_reset_ata(device_t atadev); #endif /* _MACIO_MACIOVAR_H_ */ Index: powerpc/powermac/pmu.c =================================================================== --- powerpc/powermac/pmu.c +++ powerpc/powermac/pmu.c @@ -99,10 +99,15 @@ static void pmu_shutdown(void *xsc, int howto); static void pmu_set_sleepled(void *xsc, int onoff); static int pmu_server_mode(SYSCTL_HANDLER_ARGS); +static int pmu_sleep(SYSCTL_HANDLER_ARGS); static int pmu_acline_state(SYSCTL_HANDLER_ARGS); static int pmu_query_battery(struct pmu_softc *sc, int batt, struct pmu_battstate *info); static int pmu_battquery_sysctl(SYSCTL_HANDLER_ARGS); +static void pmu_restore_state(struct pmu_softc *sc); +static void pmu_save_state(struct pmu_softc *sc); +static int pmu_suspend(device_t); +static int pmu_resume(device_t); /* * List of battery-related sysctls we might ask for @@ -123,8 +128,10 @@ /* Device interface */ DEVMETHOD(device_probe, pmu_probe), DEVMETHOD(device_attach, pmu_attach), - DEVMETHOD(device_detach, pmu_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_detach, pmu_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, pmu_suspend), + DEVMETHOD(device_resume, pmu_resume), /* ADB bus interface */ DEVMETHOD(adb_hb_send_raw_packet, pmu_adb_send), @@ -146,7 +153,7 @@ static devclass_t pmu_devclass; -DRIVER_MODULE(pmu, macio, pmu_driver, pmu_devclass, 0, 0); +EARLY_DRIVER_MODULE(pmu, macio, pmu_driver, pmu_devclass, 0, 0, BUS_PASS_RESOURCE); DRIVER_MODULE(adb, pmu, adb_driver, adb_devclass, 0, 0); static int pmuextint_probe(device_t); @@ -168,7 +175,7 @@ static devclass_t pmuextint_devclass; -DRIVER_MODULE(pmuextint, macgpio, pmuextint_driver, pmuextint_devclass, 0, 0); +EARLY_DRIVER_MODULE(pmuextint, macgpio, pmuextint_driver, pmuextint_devclass, 0, 0, BUS_PASS_RESOURCE); /* Make sure uhid is loaded, as it turns off some of the ADB emulation */ MODULE_DEPEND(pmu, usb, 1, 1, 1); @@ -416,6 +423,10 @@ "server_mode", CTLTYPE_INT | CTLFLAG_RW, sc, 0, pmu_server_mode, "I", "Enable reboot after power failure"); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "sleep", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + pmu_sleep, "I", "Put the machine to sleep"); + if (sc->sc_batteries > 0) { struct sysctl_oid *oid, *battroot; char battnum[2]; @@ -712,16 +723,14 @@ } if (resp[1] & PMU_INT_ENVIRONMENT) { /* if the lid was just closed, notify devd. */ - if ((resp[2] & PMU_ENV_LID_CLOSED) && (!sc->lid_closed)) { - sc->lid_closed = 1; - if (devctl_process_running()) - devctl_notify("PMU", "lid", "close", NULL); + if ((resp[2] & PMU_ENV_LID_CLOSED) && (!sc->sc_lid_closed)) { + sc->sc_lid_closed = 1; + devctl_notify("PMU", "lid", "close", NULL); } - else if (!(resp[2] & PMU_ENV_LID_CLOSED) && (sc->lid_closed)) { + else if (!(resp[2] & PMU_ENV_LID_CLOSED) && (sc->sc_lid_closed)) { /* if the lid was just opened, notify devd. */ - if (devctl_process_running()) - devctl_notify("PMU", "lid", "open", NULL); - sc->lid_closed = 0; + devctl_notify("PMU", "lid", "open", NULL); + sc->sc_lid_closed = 0; } } } @@ -1026,7 +1035,78 @@ return (0); } + +static void +pmu_save_state(struct pmu_softc *sc) +{ + sc->sc_saved_regs[0] = pmu_read_reg(sc, vBufA); + sc->sc_saved_regs[1] = pmu_read_reg(sc, vDirA); + sc->sc_saved_regs[2] = pmu_read_reg(sc, vBufB); + sc->sc_saved_regs[3] = pmu_read_reg(sc, vDirB); + sc->sc_saved_regs[4] = pmu_read_reg(sc, vPCR); + sc->sc_saved_regs[5] = pmu_read_reg(sc, vACR); + sc->sc_saved_regs[6] = pmu_read_reg(sc, vIER); + sc->sc_saved_regs[7] = pmu_read_reg(sc, vT1C); + sc->sc_saved_regs[8] = pmu_read_reg(sc, vT1CH); +} +static void +pmu_restore_state(struct pmu_softc *sc) +{ + pmu_write_reg(sc, vBufA, sc->sc_saved_regs[0]); + pmu_write_reg(sc, vDirA, sc->sc_saved_regs[1]); + pmu_write_reg(sc, vBufB, sc->sc_saved_regs[2]); + pmu_write_reg(sc, vDirB, sc->sc_saved_regs[3]); + pmu_write_reg(sc, vPCR, sc->sc_saved_regs[4]); + pmu_write_reg(sc, vACR, sc->sc_saved_regs[5]); + pmu_write_reg(sc, vIER, sc->sc_saved_regs[6]); + pmu_write_reg(sc, vT1C, sc->sc_saved_regs[7]); + pmu_write_reg(sc, vT1CH, sc->sc_saved_regs[8]); +} + +static int +pmu_suspend(device_t dev) +{ + uint8_t resp[16]; + uint8_t clrcmd[] = {PMU_PWR_CLR_POWERUP_EVENTS, 0xff, 0xff}; + uint8_t setcmd[] = {PMU_PWR_SET_POWERUP_EVENTS, 0, + PMU_PWR_WAKEUP_LID_OPEN|PMU_PWR_WAKEUP_KEY}; + uint8_t sleepcmd[] = {'M', 'A', 'T', 'T'}; + uint8_t reg = 0; + struct pmu_softc *sc; + + sc = device_get_softc(dev); + mtx_lock(&sc->sc_mutex); + pmu_send(sc, PMU_SET_IMASK, 1, ®, 16, resp); + pmu_send(sc, PMU_POWER_EVENTS, 3, clrcmd, 16, resp); + pmu_send(sc, PMU_POWER_EVENTS, 3, setcmd, 2, resp); + + pmu_send(sc, PMU_SLEEP, 4, sleepcmd, 16, resp); + pmu_save_state(sc); + mtx_unlock(&sc->sc_mutex); + + return (0); +} + +static int +pmu_resume(device_t dev) +{ + uint8_t resp[16]; + uint8_t cmd[2] = {2, 0}; + struct pmu_softc *sc; + uint8_t reg; + + sc = device_get_softc(dev); + mtx_lock(&sc->sc_mutex); + pmu_restore_state(sc); + pmu_send(sc, PMU_SYSTEM_READY, 1, cmd, 16, resp); + reg = PMU_DEFAULTS; + pmu_send(sc, PMU_SET_IMASK, 1, ®, 16, resp); + mtx_unlock(&sc->sc_mutex); + + return (0); +} + int pmu_set_speed(int low_speed) { @@ -1053,3 +1133,31 @@ return (0); } + +static int +pmu_sleep(SYSCTL_HANDLER_ARGS) +{ + u_int sleep = 0; + int error; + + error = sysctl_handle_int(oidp, &sleep, 0, req); + + if (error || !req->newptr) + return (error); + + EVENTHANDLER_INVOKE(power_suspend); + mtx_lock(&Giant); + error = DEVICE_SUSPEND(root_bus); + if (error == 0) { + spinlock_enter(); + platform_sleep(); + + spinlock_exit(); + DEVICE_RESUME(root_bus); + } + mtx_unlock(&Giant); + EVENTHANDLER_INVOKE(power_resume); + printf("Fully resumed.\n"); + + return (error); +} Index: powerpc/powermac/pmuvar.h =================================================================== --- powerpc/powermac/pmuvar.h +++ powerpc/powermac/pmuvar.h @@ -160,8 +160,8 @@ volatile int sc_autopoll; int sc_batteries; struct cdev *sc_leddev; - int lid_closed; - uint8_t saved_regs[9]; + int sc_lid_closed; + uint8_t sc_saved_regs[9]; }; struct pmu_battstate { Index: powerpc/powermac/uninorth.c =================================================================== --- powerpc/powermac/uninorth.c +++ powerpc/powermac/uninorth.c @@ -65,6 +65,8 @@ static int unin_chip_probe(device_t); static int unin_chip_attach(device_t); +static int unin_chip_suspend(device_t); +static int unin_chip_resume(device_t); /* * Bus interface. @@ -102,6 +104,8 @@ /* Device interface */ DEVMETHOD(device_probe, unin_chip_probe), DEVMETHOD(device_attach, unin_chip_attach), + DEVMETHOD(device_suspend, unin_chip_suspend), + DEVMETHOD(device_resume, unin_chip_resume), /* Bus interface */ DEVMETHOD(bus_print_child, unin_chip_print_child), @@ -143,7 +147,7 @@ */ static device_t unin_chip; -DRIVER_MODULE(unin, ofwbus, unin_chip_driver, unin_chip_devclass, 0, 0); +EARLY_DRIVER_MODULE(unin, ofwbus, unin_chip_driver, unin_chip_devclass, 0, 0, BUS_PASS_BUS); /* * Add an interrupt to the dev's resource list if present @@ -640,6 +644,25 @@ return (&dinfo->udi_obdinfo); } +static int +unin_chip_suspend(device_t dev) +{ + int error; + + error = unin_chip_sleep(dev, 0); + + return (error); +} + +static int +unin_chip_resume(device_t dev) +{ + + unin_chip_wake(dev); + + return (0); +} + int unin_chip_wake(device_t dev) { Index: powerpc/powermac/uninorthpci.c =================================================================== --- powerpc/powermac/uninorthpci.c +++ powerpc/powermac/uninorthpci.c @@ -86,6 +86,8 @@ /* Device interface */ DEVMETHOD(device_probe, uninorth_probe), DEVMETHOD(device_attach, uninorth_attach), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), /* pcib interface */ DEVMETHOD(pcib_read_config, uninorth_read_config), @@ -98,7 +100,7 @@ DEFINE_CLASS_1(pcib, uninorth_driver, uninorth_methods, sizeof(struct uninorth_softc), ofw_pci_driver); -DRIVER_MODULE(uninorth, ofwbus, uninorth_driver, uninorth_devclass, 0, 0); +EARLY_DRIVER_MODULE(uninorth, ofwbus, uninorth_driver, uninorth_devclass, 0, 0, BUS_PASS_BUS); static int uninorth_probe(device_t dev) Index: powerpc/powermac/viareg.h =================================================================== --- powerpc/powermac/viareg.h +++ powerpc/powermac/viareg.h @@ -30,6 +30,7 @@ /* VIA interface registers */ #define vBufB 0x0000 /* register B */ +#define vBufAH 0x0200 /* register A (handshake) */ #define vDirB 0x0400 /* data direction register */ #define vDirA 0x0600 /* data direction register */ #define vT1C 0x0800 /* Timer 1 counter Lo */ @@ -46,6 +47,10 @@ #define vPB4 0x10 #define vPB5 0x20 #define vSR_INT 0x04 +#define vCB2_INT 0x08 +#define vCB1_INT 0x10 #define vSR_OUT 0x10 +#define vIER_SET 0x80 +#define vIER_CLR 0x00 #endif /* _POWERPC_VIAREG_H_ */ Index: sys/bus.h =================================================================== --- sys/bus.h +++ sys/bus.h @@ -54,7 +54,8 @@ DS_ALIVE = 20, /**< @brief probe succeeded */ DS_ATTACHING = 25, /**< @brief currently attaching */ DS_ATTACHED = 30, /**< @brief attach method called */ - DS_BUSY = 40 /**< @brief device is open */ + DS_BUSY = 40, /**< @brief device is open */ + DS_SUSPENDED = 50, /**< @brief device is suspended */ } device_state_t; /** @@ -339,6 +340,7 @@ int bus_generic_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r); int bus_generic_resume(device_t dev); +int bus_generic_resume_child(device_t dev, device_t child); int bus_generic_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, driver_filter_t *filter, driver_intr_t *intr, @@ -357,6 +359,7 @@ int bus_generic_shutdown(device_t dev); int bus_generic_suspend(device_t dev); +int bus_generic_suspend_child(device_t dev, device_t child); int bus_generic_teardown_intr(device_t dev, device_t child, struct resource *irq, void *cookie); int bus_generic_write_ivar(device_t dev, device_t child, int which,