On Thu, Jun 09, 2005 at 09:14:52PM -0700, David Brownell wrote:
> On Thursday 09 June 2005 8:39 pm, Todd Poynor wrote:
...
> > So far as I thought I knew, pm_message_t will eventually become a struct
> > with fields that can be used to properly describe what sort of driver
> > behavior is needed at suspend and resume...
> 
> That's one theory; I can't see it checking out though...

OK, I know a cell phone vendor or two that want more info on system
suspend/resume behaviors available to drivers, so I'll pitch in to try
to turn this parameter into something useful.

> It was only swsusp that forced "3"; the other 2.6 code, now deleted,
> was doing PM_SUSPEND_MEM (3) or PM_SUSPEND_DISK (4).

Ah I see, I meant that both "standby" and "mem" suspends (which we can
map to two different sleep modes on the PXA27x that have different power
cycling behavior for I/O devices) both suspend devices to state 3, was
forgetting about the suspend-to-disk option.

> This patch reads fine to me except that you're not setting the
> dev->power.power_state to (bleech) PMSG_SUSPEND or PMSG_ON,
> which means that operations through sysfs power/state files will
> be more borked than usual ... not all paths through the driver
> core will maintain that field, so drivers need to.  At least,
> so long as the field exists.  It's mostly just trouble.  :)

Ugh, at one point in the not-too-distant past both system suspend/resume
and individual device "runtime" suspend/resume managed that field on
behalf of drivers, but I see system suspend/resume no longer does so.
Here's a new patch that assigns a "message" to the "state" field (may
this simply be a passing phase).

Thanks -- Todd

Power Management for the Intel XScale PXA27x OHCI USB host controller

Signed-off-by: Todd Poynor <[EMAIL PROTECTED]>

Index: linux-2.6.12-rc4/drivers/usb/host/ohci-pxa27x.c
===================================================================
--- linux-2.6.12-rc4.orig/drivers/usb/host/ohci-pxa27x.c        2005-06-09 
02:56:43.000000000 +0000
+++ linux-2.6.12-rc4/drivers/usb/host/ohci-pxa27x.c     2005-06-10 
20:27:04.000000000 +0000
@@ -310,6 +310,7 @@
        .hub_suspend =          ohci_hub_suspend,
        .hub_resume =           ohci_hub_resume,
 #endif
+       .start_port_reset =     ohci_start_port_reset,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -337,32 +338,69 @@
        return 0;
 }
 
-static int ohci_hcd_pxa27x_drv_suspend(struct device *dev, pm_message_t state, 
u32 level)
+
+#ifdef CONFIG_PM
+
+static int ohci_hcd_pxa27x_drv_suspend(struct device *dev, pm_message_t 
message, u32 level)
 {
-//     struct platform_device *pdev = to_platform_device(dev);
-//     struct usb_hcd *hcd = dev_get_drvdata(dev);
-       printk("%s: not implemented yet\n", __FUNCTION__);
+       struct platform_device *pdev = to_platform_device(dev);
+       struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev));
+       int status = -EINVAL;
 
-       return 0;
+       if (level != SUSPEND_POWER_DOWN)
+               return 0;
+
+       down(&ohci_to_hcd(ohci)->self.root_hub->serialize);
+       status = ohci_hub_suspend(ohci_to_hcd(ohci));
+       if (status == 0) {
+               pxa27x_stop_hc(pdev);
+               ohci_to_hcd(ohci)->self.root_hub->state =
+                       USB_STATE_SUSPENDED;
+               ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
+               dev->power.power_state = PMSG_SUSPEND;
+       }
+       up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
+       return status;
 }
 
 static int ohci_hcd_pxa27x_drv_resume(struct device *dev, u32 level)
 {
-//     struct platform_device *pdev = to_platform_device(dev);
-//     struct usb_hcd *hcd = dev_get_drvdata(dev);
-       printk("%s: not implemented yet\n", __FUNCTION__);
+       struct platform_device *pdev = to_platform_device(dev);
+       struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev));
+       int             status = 0;
 
-       return 0;
+       if (level != RESUME_POWER_ON)
+               return 0;
+
+       if (time_before(jiffies, ohci->next_statechange))
+               msleep(5);
+       ohci->next_statechange = jiffies;
+       pxa27x_start_hc(pdev);
+#ifdef CONFIG_USB_SUSPEND
+       /* get extra cleanup even if remote wakeup isn't in use */
+       status = usb_resume_device(ohci_to_hcd(ohci)->self.root_hub);
+#else
+       down(&ohci_to_hcd(ohci)->self.root_hub->serialize);
+       status = ohci_hub_resume(ohci_to_hcd(ohci));
+       up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
+#endif
+       if (status == 0)
+               dev->power.power_state = PMSG_ON;
+
+       return status;
 }
 
+#endif
 
 static struct device_driver ohci_hcd_pxa27x_driver = {
        .name           = "pxa27x-ohci",
        .bus            = &platform_bus_type,
        .probe          = ohci_hcd_pxa27x_drv_probe,
        .remove         = ohci_hcd_pxa27x_drv_remove,
+#ifdef CONFIG_PM
        .suspend        = ohci_hcd_pxa27x_drv_suspend, 
-       .resume         = ohci_hcd_pxa27x_drv_resume, 
+       .resume         = ohci_hcd_pxa27x_drv_resume,
+#endif 
 };
 
 static int __init ohci_hcd_pxa27x_init (void)



-------------------------------------------------------
This SF.Net email is sponsored by: NEC IT Guy Games.  How far can you shotput
a projector? How fast can you ride your desk chair down the office luge track?
If you want to score the big prize, get to know the little guy.  
Play to win an NEC 61" plasma display: http://www.necitguy.com/?r=20
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to