Page MenuHomeFreeBSD

D203.id440.diff
No OneTemporary

D203.id440.diff

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, &reg, 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, &reg, 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

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)

Event Timeline