|
@@ -42,6 +42,7 @@ struct ohci_at91_priv {
|
|
struct clk *uclk;
|
|
struct clk *uclk;
|
|
struct clk *hclk;
|
|
struct clk *hclk;
|
|
bool clocked;
|
|
bool clocked;
|
|
|
|
+ bool wakeup; /* Saved wake-up state for resume */
|
|
};
|
|
};
|
|
/* interface and function clocks; sometimes also an AHB clock */
|
|
/* interface and function clocks; sometimes also an AHB clock */
|
|
|
|
|
|
@@ -61,6 +62,8 @@ extern int usb_disabled(void);
|
|
|
|
|
|
static void at91_start_clock(struct ohci_at91_priv *ohci_at91)
|
|
static void at91_start_clock(struct ohci_at91_priv *ohci_at91)
|
|
{
|
|
{
|
|
|
|
+ if (ohci_at91->clocked)
|
|
|
|
+ return;
|
|
if (IS_ENABLED(CONFIG_COMMON_CLK)) {
|
|
if (IS_ENABLED(CONFIG_COMMON_CLK)) {
|
|
clk_set_rate(ohci_at91->uclk, 48000000);
|
|
clk_set_rate(ohci_at91->uclk, 48000000);
|
|
clk_prepare_enable(ohci_at91->uclk);
|
|
clk_prepare_enable(ohci_at91->uclk);
|
|
@@ -73,6 +76,8 @@ static void at91_start_clock(struct ohci_at91_priv *ohci_at91)
|
|
|
|
|
|
static void at91_stop_clock(struct ohci_at91_priv *ohci_at91)
|
|
static void at91_stop_clock(struct ohci_at91_priv *ohci_at91)
|
|
{
|
|
{
|
|
|
|
+ if (!ohci_at91->clocked)
|
|
|
|
+ return;
|
|
clk_disable_unprepare(ohci_at91->fclk);
|
|
clk_disable_unprepare(ohci_at91->fclk);
|
|
clk_disable_unprepare(ohci_at91->iclk);
|
|
clk_disable_unprepare(ohci_at91->iclk);
|
|
clk_disable_unprepare(ohci_at91->hclk);
|
|
clk_disable_unprepare(ohci_at91->hclk);
|
|
@@ -616,15 +621,22 @@ ohci_hcd_at91_drv_suspend(struct device *dev)
|
|
struct usb_hcd *hcd = dev_get_drvdata(dev);
|
|
struct usb_hcd *hcd = dev_get_drvdata(dev);
|
|
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
|
|
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
|
|
struct ohci_at91_priv *ohci_at91 = hcd_to_ohci_at91_priv(hcd);
|
|
struct ohci_at91_priv *ohci_at91 = hcd_to_ohci_at91_priv(hcd);
|
|
- bool do_wakeup = device_may_wakeup(dev);
|
|
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
- if (do_wakeup)
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Disable wakeup if we are going to sleep with slow clock mode
|
|
|
|
+ * enabled.
|
|
|
|
+ */
|
|
|
|
+ ohci_at91->wakeup = device_may_wakeup(dev)
|
|
|
|
+ && !at91_suspend_entering_slow_clock();
|
|
|
|
+
|
|
|
|
+ if (ohci_at91->wakeup)
|
|
enable_irq_wake(hcd->irq);
|
|
enable_irq_wake(hcd->irq);
|
|
|
|
|
|
- ret = ohci_suspend(hcd, do_wakeup);
|
|
|
|
|
|
+ ret = ohci_suspend(hcd, ohci_at91->wakeup);
|
|
if (ret) {
|
|
if (ret) {
|
|
- disable_irq_wake(hcd->irq);
|
|
|
|
|
|
+ if (ohci_at91->wakeup)
|
|
|
|
+ disable_irq_wake(hcd->irq);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
/*
|
|
/*
|
|
@@ -634,7 +646,7 @@ ohci_hcd_at91_drv_suspend(struct device *dev)
|
|
*
|
|
*
|
|
* REVISIT: some boards will be able to turn VBUS off...
|
|
* REVISIT: some boards will be able to turn VBUS off...
|
|
*/
|
|
*/
|
|
- if (at91_suspend_entering_slow_clock()) {
|
|
|
|
|
|
+ if (!ohci_at91->wakeup) {
|
|
ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
|
|
ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
|
|
ohci->hc_control &= OHCI_CTRL_RWC;
|
|
ohci->hc_control &= OHCI_CTRL_RWC;
|
|
ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
|
|
ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
|
|
@@ -653,11 +665,10 @@ static int ohci_hcd_at91_drv_resume(struct device *dev)
|
|
struct usb_hcd *hcd = dev_get_drvdata(dev);
|
|
struct usb_hcd *hcd = dev_get_drvdata(dev);
|
|
struct ohci_at91_priv *ohci_at91 = hcd_to_ohci_at91_priv(hcd);
|
|
struct ohci_at91_priv *ohci_at91 = hcd_to_ohci_at91_priv(hcd);
|
|
|
|
|
|
- if (device_may_wakeup(dev))
|
|
|
|
|
|
+ if (ohci_at91->wakeup)
|
|
disable_irq_wake(hcd->irq);
|
|
disable_irq_wake(hcd->irq);
|
|
|
|
|
|
- if (!ohci_at91->clocked)
|
|
|
|
- at91_start_clock(ohci_at91);
|
|
|
|
|
|
+ at91_start_clock(ohci_at91);
|
|
|
|
|
|
ohci_resume(hcd, false);
|
|
ohci_resume(hcd, false);
|
|
return 0;
|
|
return 0;
|