Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F170804983
D203.id440.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
39 KB
Referenced Files
None
Subscribers
None
D203.id440.diff
View Options
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 <dev/ofw/ofw_bus.h>
#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,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Sep 7, 6:08 PM (5 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38479594
Default Alt Text
D203.id440.diff (39 KB)
Attached To
Mode
D203: Multipass suspend/resume
Attached
Detach File
Event Timeline
Log In to Comment