Power management support for OHCI on au1x00
Subsystems (3)
PATCH 1/1 Power management support for OHCI on au1x00
Hello,
here:
http://ftp.enneenne.com/pub/misc/au1100-patches/linux/patch-ohci_au1xxx_pm_support
and attached my patch for power management support for OHCI on au1x00.
Ciao,
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems [email protected] UNIX programming phone: +39 349 2432127
drivers/usb/host/ohci-au1xxx.c +108 -14
@@ -14,6 +14,8 @@* by Durgesh Pattamatta <[email protected]> * Modified for AMD Alchemy Au1xxx * by Matt Porter <[email protected]> +* Modified to add PM support +* by Rodolfo Giometti <[email protected]> on May 2006 * * This file is licenced under the GPL. */
@@ -229,6 +231,15 @@ static void usb_ohci_au1xxx_remove(struc/*-------------------------------------------------------------------------*/ +static int +ohci_au1xxx_reset (struct usb_hcd *hcd) +{ +struct ohci_hcd *ohci =hcd_to_ohci (hcd); + +ohci_hcd_init (ohci); +return ohci_init (ohci); +} +static int __devinit ohci_au1xxx_start (struct usb_hcd *hcd) {
@@ -249,6 +260,37 @@ ohci_au1xxx_start (struct usb_hcd *hcd)return 0 ; } +#ifdef CONFIG_PM +static int ohci_au1xxx_suspend (struct usb_hcd *hcd,pm_message_t message) +{ +struct ohci_hcd *ohci =hcd_to_ohci (hcd); +unsigned long flags; +int rc =0 ; + +spin_lock_irqsave (&ohci->lock, flags); +if (hcd->state !=HC_STATE_SUSPENDED ) { + rc = -EINVAL ; + goto exit; + } +ohci_writel (ohci,OHCI_INTR_MIE , &ohci->regs->intrdisable); + (void )ohci_readl (ohci, &ohci->regs->intrdisable); +clear_bit (HCD_FLAG_HW_ACCESSIBLE , &hcd->flags); + +exit: +spin_unlock_irqrestore (&ohci->lock, flags); + +return rc; +} + +static int ohci_au1xxx_resume (struct usb_hcd *hcd) +{ +set_bit (HCD_FLAG_HW_ACCESSIBLE , &hcd->flags); +usb_hcd_resume_root_hub (hcd); +return 0 ; +} +#endif /* CONFIG_PM */ + +/*-------------------------------------------------------------------------*/ static const struct hc_driver ohci_au1xxx_hc_driver = {
@@ -265,11 +307,12 @@ static const struct hc_driver ohci_au1xx/* * basic lifecycle operations */ + .reset = ohci_au1xxx_reset, .start = ohci_au1xxx_start, -#ifdef CONFIG_PM -/* suspend: ohci_au1xxx_suspend, -- tbd */ -/* resume: ohci_au1xxx_resume, -- tbd */ -#endif /*CONFIG_PM*/ +#ifdef CONFIG_PM + .suspend = ohci_au1xxx_suspend, + .resume = ohci_au1xxx_resume, +#endif .stop = ohci_stop,/*
@@ -318,26 +361,77 @@ static int ohci_hcd_au1xxx_drv_remove(stusb_ohci_au1xxx_remove (hcd, pdev);return 0 ; } -/*TBD*/ -/*static int ohci_hcd_au1xxx_drv_suspend(struct platform_device *dev) + +#ifdef CONFIG_PM +static int ohci_hcd_au1xxx_drv_suspend (struct platform_device *pdev,pm_message_t state) { -struct usb_hcd *hcd = platform_get_drvdata(dev); +struct usb_hcd *hcd =platform_get_drvdata (pdev); +int ret =0 ; -return 0; +if (hcd->self.root_hub->dev.power.power_state.event ==PM_EVENT_ON ) +return -EBUSY ; + +if (hcd->driver->suspend) { + ret = hcd->driver->suspend (hcd, state); +suspend_report_result (hcd->driver->suspend, ret); +if (ret) + goto done; + } +synchronize_irq (dev->irq); + +if (hcd->state ==HC_STATE_SUSPENDED ) +au1xxx_stop_ohc (pdev); +else { +dev_dbg (hcd->self.controller,"hcd state %d; not suspended\n" , + hcd->state); +WARN_ON (1 ); + ret = -EINVAL ; + } + +done: +if (ret ==0 ) + pdev->dev.power.power_state =PMSG_SUSPEND ; + +return ret; } -static int ohci_hcd_au1xxx_drv_resume(struct platform_device *dev) + +static int ohci_hcd_au1xxx_drv_resume (struct platform_device *pdev) { -struct usb_hcd *hcd = platform_get_drvdata(dev); +struct usb_hcd *hcd =platform_get_drvdata (pdev); +int ret =0 ; -return 0; +if (hcd->state !=HC_STATE_SUSPENDED ) { +dev_dbg (hcd->self.controller, +"can't resume, not suspended!\n" ); +return 0 ; + } + +au1xxx_start_ohc (pdev); + + pdev->dev.power.power_state =PMSG_ON ; + +clear_bit (HCD_FLAG_SAW_IRQ , &hcd->flags); + +if (hcd->driver->resume) { + ret = hcd->driver->resume (hcd); +if (ret) { +dev_err (hcd->self.controller, +"hcd post-resume error %d!\n" , ret); +usb_hc_died (hcd); + } + } + +return ret; } -*/ +#endif static struct platform_driver ohci_hcd_au1xxx_driver = { .probe = ohci_hcd_au1xxx_drv_probe, .remove = ohci_hcd_au1xxx_drv_remove, -/*.suspend = ohci_hcd_au1xxx_drv_suspend, */ -/*.resume = ohci_hcd_au1xxx_drv_resume, */ +#ifdef CONFIG_PM + .suspend = ohci_hcd_au1xxx_drv_suspend, + .resume = ohci_hcd_au1xxx_drv_resume, +#endif .driver = { .name ="au1xxx-ohci" , .owner =THIS_MODULE ,