Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Jan 2014 04:25:54 +0000 (UTC)
From:      Justin Hibbits <jhibbits@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r260668 - in projects/pmac_pmu/sys: dev/pci kern powerpc/ofw powerpc/powermac sys
Message-ID:  <201401150425.s0F4Ps8m038406@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhibbits
Date: Wed Jan 15 04:25:54 2014
New Revision: 260668
URL: http://svnweb.freebsd.org/changeset/base/260668

Log:
  Various updates that I had made against head:
  
  * Add the 'Buffer A with handshake update' #define for PMU, for completeness.
  * Mark OpenPIC as BUS_PASS_INTERRUPT, so it's suspended later and resumed
    earlier.
  * Add two new bus methods: bus_suspend_child()/bus_resume_child(), and use
    those in the bus_generic_suspend()/bus_generic_resume() implementation.
    * This, in turn, allows us to move all bus recursion logic into the generic
      functions, allowing the drivers to suspend/resume _only_ themselves.
    * Make use of these in the PCI driver.

Modified:
  projects/pmac_pmu/sys/dev/pci/pci.c
  projects/pmac_pmu/sys/dev/pci/pci_private.h
  projects/pmac_pmu/sys/kern/bus_if.m
  projects/pmac_pmu/sys/kern/subr_bus.c
  projects/pmac_pmu/sys/powerpc/ofw/openpic_ofw.c
  projects/pmac_pmu/sys/powerpc/powermac/maciovar.h
  projects/pmac_pmu/sys/powerpc/powermac/pmu.c
  projects/pmac_pmu/sys/powerpc/powermac/viareg.h
  projects/pmac_pmu/sys/sys/bus.h

Modified: projects/pmac_pmu/sys/dev/pci/pci.c
==============================================================================
--- projects/pmac_pmu/sys/dev/pci/pci.c	Wed Jan 15 04:16:45 2014	(r260667)
+++ projects/pmac_pmu/sys/dev/pci/pci.c	Wed Jan 15 04:25:54 2014	(r260668)
@@ -127,8 +127,6 @@ static device_method_t pci_methods[] = {
 	DEVMETHOD(device_attach,	pci_attach),
 	DEVMETHOD(device_detach,	bus_generic_detach),
 	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),
@@ -138,6 +136,8 @@ static device_method_t pci_methods[] = {
 	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),
@@ -3364,12 +3364,11 @@ pci_attach(device_t dev)
 }
 
 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
@@ -3379,101 +3378,46 @@ pci_set_power_children(device_t dev, dev
 	 * 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)
-		return (error);
-	for (i = 0; i < numdevs; i++) {
-		child = devlist[i];
-		dinfo = device_get_ivars(child);
-		pci_cfg_save(child, dinfo, 0);
-	}
+	dinfo = device_get_ivars(child);
+	pci_cfg_save(child, dinfo, 0);
+
+	error = DEVICE_SUSPEND(child);
 
-	/* Suspend devices before potentially powering them down. */
-	error = bus_generic_suspend(dev);
-	if (error) {
-		free(devlist, M_TEMP);
+	if (error)
 		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);
-
-	/* Now the device is powered up, restore its config space. */
-	for (i = 0; i < numdevs; i++) {
-		child = devlist[i];
-		dinfo = device_get_ivars(child);
+		pci_set_power_child(dev, child, PCI_POWERSTATE_D0);
+	error = DEVICE_RESUME(child);
 
-		pci_cfg_restore(child, dinfo);
-		if (!device_is_attached(child))
-			pci_cfg_save(child, dinfo, 1);
-	}
+	dinfo = device_get_ivars(child);
+	pci_cfg_restore(child, dinfo);
 
-	/*
-	 * 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:
-			error = 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:
-			error = DEVICE_RESUME(child);
-		}
-	}
-	free(devlist, M_TEMP);
 	return (error);
 }
 

Modified: projects/pmac_pmu/sys/dev/pci/pci_private.h
==============================================================================
--- projects/pmac_pmu/sys/dev/pci/pci_private.h	Wed Jan 15 04:16:45 2014	(r260667)
+++ projects/pmac_pmu/sys/dev/pci/pci_private.h	Wed Jan 15 04:25:54 2014	(r260668)
@@ -114,8 +114,8 @@ int		pci_child_location_str_method(devic
 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

Modified: projects/pmac_pmu/sys/kern/bus_if.m
==============================================================================
--- projects/pmac_pmu/sys/kern/bus_if.m	Wed Jan 15 04:16:45 2014	(r260667)
+++ projects/pmac_pmu/sys/kern/bus_if.m	Wed Jan 15 04:25:54 2014	(r260668)
@@ -670,3 +670,25 @@ METHOD int remap_intr {
 	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;

Modified: projects/pmac_pmu/sys/kern/subr_bus.c
==============================================================================
--- projects/pmac_pmu/sys/kern/subr_bus.c	Wed Jan 15 04:16:45 2014	(r260667)
+++ projects/pmac_pmu/sys/kern/subr_bus.c	Wed Jan 15 04:25:54 2014	(r260668)
@@ -91,7 +91,6 @@ struct devclass {
 	device_t	*devices;	/* array of devices indexed by unit */
 	int		maxunit;	/* size of devices array */
 	int		flags;
-	int		pass;
 #define DC_HAS_CHILDREN		1
 
 	struct sysctl_ctx_list sysctl_ctx;
@@ -125,6 +124,7 @@ struct device {
 	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  */
@@ -136,7 +136,6 @@ struct device {
 #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 suspended. */
 	u_int	order;			/**< order from device_add_child_ordered() */
 	void	*ivars;			/**< instance variables  */
 	void	*softc;			/**< current driver's variables  */
@@ -1086,7 +1085,6 @@ devclass_add_driver(devclass_t dc, drive
 	TAILQ_INSERT_TAIL(&dc->drivers, dl, link);
 	driver->refs++;		/* XXX: kobj_mtx */
 	dl->pass = pass;
-	(*dcp)->pass = pass;	/* Used in suspend/resume. */
 	driver_register_pass(dl);
 
 	devclass_driver_added(dc, driver);
@@ -2815,6 +2813,7 @@ device_attach(device_t dev)
 	else
 		dev->state = DS_ATTACHED;
 	dev->flags &= ~DF_DONENOMATCH;
+	dev->pass = bus_current_pass;
 	devadded(dev);
 	return (0);
 }
@@ -3587,6 +3586,38 @@ bus_generic_shutdown(device_t dev)
 }
 
 /**
+ * @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);
+
+	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);
+
+	return (error);
+}
+
+/**
  * @brief Helper function for implementing DEVICE_SUSPEND()
  *
  * This function can be used to help implement the DEVICE_SUSPEND()
@@ -3598,30 +3629,41 @@ bus_generic_shutdown(device_t dev)
 int
 bus_generic_suspend(device_t dev)
 {
-	int		error;
-	int		again = 0;
+	int		error = 0;
 	device_t	child, child2;
 
+	if (dev->state == DS_SUSPENDED)
+		return (0);
+
 	TAILQ_FOREACH(child, &dev->children, link) {
-		if (!(child->flags & DF_SUSPENDED)) {
-			error = DEVICE_SUSPEND(child);
-			if (error && error != EAGAIN) {
-				for (child2 = TAILQ_FIRST(&dev->children);
-				     child2 && child2 != child;
-				     child2 = TAILQ_NEXT(child2, link)) {
-					DEVICE_RESUME(child2);
-					child2->flags &= ~DF_SUSPENDED;
-				}
-				return (error);
+		if (child->state != DS_SUSPENDED)
+			error = bus_generic_suspend(child);
+		if (error == 0) {
+			/* We won't busy ourselves with busy devices. */
+			if (child->state == DS_BUSY)
+				error = (EBUSY);
+			else if (child->pass >= bus_current_pass && child->state == DS_ATTACHED) {
+				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 == 0)
+					child->state = DS_SUSPENDED;
 			}
-			if (error == EAGAIN) {
-				again = EAGAIN;
-				continue;
+		}
+
+		if (error) {
+			for (child2 = TAILQ_FIRST(&dev->children);
+				 child2 && child2 != child;
+				 child2 = TAILQ_NEXT(child2, link)) {
+				BUS_RESUME_CHILD(dev, child2);
+				bus_generic_resume(child2);
 			}
-			child->flags |= DF_SUSPENDED;
+			return (error);
 		}
 	}
-	return (again);
+
+	return (error);
 }
 
 /**
@@ -3634,31 +3676,23 @@ int
 bus_generic_resume(device_t dev)
 {
 	device_t	child;
-	int		error = 0;
 
 	TAILQ_FOREACH(child, &dev->children, link) {
-		if (child->flags & DF_SUSPENDED) {
-			if (child->devclass->pass > bus_current_pass) {
-				if (bootverbose)
-					printf("Skipping: %s: %d, %d\n",
-					    child->nameunit,
-					    child->devclass->pass,
-					    bus_current_pass);
-				error = EAGAIN;
-				continue;
-			}
-			if (DEVICE_RESUME(child) == EAGAIN) {
-				error = EAGAIN;
-				continue;
-			}
+		if (child->pass == bus_current_pass && child->state == DS_SUSPENDED) {
+			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... */
-			child->flags &= ~DF_SUSPENDED;
+			/* Re-mark the child as attached. */
+			child->state = DS_ATTACHED;
+		}
+
+		/* Recurse through the child, resuming all its children. */
+		if (child->pass <= bus_current_pass) {
+			bus_generic_resume(child);
 		}
-		else
-			if (bootverbose)
-				printf("Skipping %s: already resumed\n", child->nameunit);
 	}
-	return (error);
+	return (0);
 }
 
 /**
@@ -4465,18 +4499,22 @@ root_resume(device_t dev)
 {
 	struct driverlink *dl;
 	int error = 0;
+	int rv = 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 != EAGAIN)
-			break;
+		if (error != 0)
+			rv = error;
 	}
 
-	if (error == 0)
+	if (rv == 0)
 		devctl_notify("kern", "power", "resume", NULL);
-	return (error);
+	return (rv);
 }
 
 static int
@@ -4487,11 +4525,25 @@ root_suspend(device_t dev)
 
 	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 != EAGAIN)
+		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);
 }
 

Modified: projects/pmac_pmu/sys/powerpc/ofw/openpic_ofw.c
==============================================================================
--- projects/pmac_pmu/sys/powerpc/ofw/openpic_ofw.c	Wed Jan 15 04:16:45 2014	(r260667)
+++ projects/pmac_pmu/sys/powerpc/ofw/openpic_ofw.c	Wed Jan 15 04:25:54 2014	(r260668)
@@ -95,7 +95,7 @@ static driver_t openpic_ofw_driver = {
 
 DRIVER_MODULE(openpic, nexus, 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)

Modified: projects/pmac_pmu/sys/powerpc/powermac/maciovar.h
==============================================================================
--- projects/pmac_pmu/sys/powerpc/powermac/maciovar.h	Wed Jan 15 04:16:45 2014	(r260667)
+++ projects/pmac_pmu/sys/powerpc/powermac/maciovar.h	Wed Jan 15 04:25:54 2014	(r260668)
@@ -48,6 +48,12 @@
 #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
 
@@ -112,6 +118,230 @@
 #define FCR3_I2S0_CLK18_ENABLE	0x00004000
 #define FCR3_VIA_CLK16_ENABLE	0x00008000
 
+#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
+
+/*
+ * 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
+
 /*
  * Format of a macio reg property entry.
  */

Modified: projects/pmac_pmu/sys/powerpc/powermac/pmu.c
==============================================================================
--- projects/pmac_pmu/sys/powerpc/powermac/pmu.c	Wed Jan 15 04:16:45 2014	(r260667)
+++ projects/pmac_pmu/sys/powerpc/powermac/pmu.c	Wed Jan 15 04:25:54 2014	(r260668)
@@ -132,10 +132,10 @@ static device_method_t  pmu_methods[] = 
 	/* 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_suspend,       pmu_suspend),
-        DEVMETHOD(device_resume,        pmu_resume),
+	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),
@@ -157,7 +157,7 @@ static driver_t pmu_driver = {
 
 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);
@@ -431,6 +431,10 @@ pmu_attach(device_t dev)
 	    "sleep", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
 	    pmu_sleep, "I", "Put the machine to sleep");
 
+	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];
@@ -540,43 +544,6 @@ pmu_write_reg(struct pmu_softc *sc, u_in
 	bus_write_1(sc->sc_memr, offset, value);
 }
 
-static void
-pmu_save_state(struct pmu_softc *sc)
-{
-	sc->saved_regs[0] = pmu_read_reg(sc, vBufA);
-	sc->saved_regs[1] = pmu_read_reg(sc, vDirA);
-	sc->saved_regs[2] = pmu_read_reg(sc, vBufB);
-	sc->saved_regs[3] = pmu_read_reg(sc, vDirB);
-	sc->saved_regs[4] = pmu_read_reg(sc, vPCR);
-	sc->saved_regs[5] = pmu_read_reg(sc, vACR);
-	sc->saved_regs[6] = pmu_read_reg(sc, vIER);
-	sc->saved_regs[7] = pmu_read_reg(sc, vT1C);
-	sc->saved_regs[8] = pmu_read_reg(sc, vT1CH);
-}
-
-static void
-pmu_restore_state(struct pmu_softc *sc)
-{
-	pmu_write_reg(sc, vBufA, sc->saved_regs[0]);
-	eieio();
-	pmu_write_reg(sc, vDirA, sc->saved_regs[1]);
-	eieio();
-	pmu_write_reg(sc, vBufB, sc->saved_regs[2]);
-	eieio();
-	pmu_write_reg(sc, vDirB, sc->saved_regs[3]);
-	eieio();
-	pmu_write_reg(sc, vPCR, sc->saved_regs[4]);
-	eieio();
-	pmu_write_reg(sc, vACR, sc->saved_regs[5]);
-	eieio();
-	pmu_write_reg(sc, vIER, sc->saved_regs[6]);
-	eieio();
-	pmu_write_reg(sc, vT1C, sc->saved_regs[7]);
-	eieio();
-	pmu_write_reg(sc, vT1CH, sc->saved_regs[8]);
-	eieio();
-}
-
 static int
 pmu_send_byte(struct pmu_softc *sc, uint8_t data)
 {
@@ -1079,6 +1046,34 @@ pmu_settime(device_t dev, struct timespe
 
 	return (0);
 }
+ 
+static void
+pmu_save_state(struct pmu_softc *sc)
+{
+	sc->saved_regs[0] = pmu_read_reg(sc, vBufA);
+	sc->saved_regs[1] = pmu_read_reg(sc, vDirA);
+	sc->saved_regs[2] = pmu_read_reg(sc, vBufB);
+	sc->saved_regs[3] = pmu_read_reg(sc, vDirB);
+	sc->saved_regs[4] = pmu_read_reg(sc, vPCR);
+	sc->saved_regs[5] = pmu_read_reg(sc, vACR);
+	sc->saved_regs[6] = pmu_read_reg(sc, vIER);
+	sc->saved_regs[7] = pmu_read_reg(sc, vT1C);
+	sc->saved_regs[8] = pmu_read_reg(sc, vT1CH);
+}
+
+static void
+pmu_restore_state(struct pmu_softc *sc)
+{
+	pmu_write_reg(sc, vBufA, sc->saved_regs[0]);
+	pmu_write_reg(sc, vDirA, sc->saved_regs[1]);
+	pmu_write_reg(sc, vBufB, sc->saved_regs[2]);
+	pmu_write_reg(sc, vDirB, sc->saved_regs[3]);
+	pmu_write_reg(sc, vPCR, sc->saved_regs[4]);
+	pmu_write_reg(sc, vACR, sc->saved_regs[5]);
+	pmu_write_reg(sc, vIER, sc->saved_regs[6]);
+	pmu_write_reg(sc, vT1C, sc->saved_regs[7]);
+	pmu_write_reg(sc, vT1CH, sc->saved_regs[8]);
+}
 
 static int
 pmu_suspend(device_t dev)
@@ -1189,31 +1184,6 @@ void pmu_sleep_int(void)
 	powerpc_sync();
 }
 
-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);
-
-	mtx_lock(&Giant);
-	error = DEVICE_SUSPEND(root_bus);
-	if (error == 0) {
-		spinlock_enter();
-		pmu_sleep_int();
-
-		spinlock_exit();
-		DEVICE_RESUME(root_bus);
-	}
-	mtx_unlock(&Giant);
-
-	return (error);
-}
-
 int
 pmu_set_speed(int low_speed)
 {
@@ -1240,3 +1210,29 @@ pmu_set_speed(int low_speed)
 
 	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);
+
+	mtx_lock(&Giant);
+	error = DEVICE_SUSPEND(root_bus);
+	if (error == 0) {
+		spinlock_enter();
+		pmu_sleep_int();
+
+		spinlock_exit();
+		DEVICE_RESUME(root_bus);
+	}
+	mtx_unlock(&Giant);
+	printf("Fully resumed.\n");
+
+	return (error);
+}

Modified: projects/pmac_pmu/sys/powerpc/powermac/viareg.h
==============================================================================
--- projects/pmac_pmu/sys/powerpc/powermac/viareg.h	Wed Jan 15 04:16:45 2014	(r260667)
+++ projects/pmac_pmu/sys/powerpc/powermac/viareg.h	Wed Jan 15 04:25:54 2014	(r260668)
@@ -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 */

Modified: projects/pmac_pmu/sys/sys/bus.h
==============================================================================
--- projects/pmac_pmu/sys/sys/bus.h	Wed Jan 15 04:16:45 2014	(r260667)
+++ projects/pmac_pmu/sys/sys/bus.h	Wed Jan 15 04:25:54 2014	(r260668)
@@ -54,7 +54,8 @@ typedef enum device_state {
 	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;
 
 /**
@@ -340,6 +341,7 @@ int	bus_generic_read_ivar(device_t dev, 
 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, 
@@ -358,6 +360,7 @@ int	bus_generic_rl_release_resource (dev
 
 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,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201401150425.s0F4Ps8m038406>