On Sat, Feb 13, 2016 at 10:56:40AM +0100, Ludovic Desroches wrote: > When suspending the sdhci host, the only hardware event that could wake > up the host is a sdio irq if they are enabled. If we want to wakeup on > card detect events, a gpio as to be used. > If we don't want to use a gpio but the card detect pio of the controller > then we need to keep enabled the clock of the controller interface to > get the interrupt and to not set the host in a suspended state to have the > interrupt handled. > How can I move forward on this topic? I have several issues related to runtime PM (card detection, wifi module which doesn't like to get clocks disabled) but I am not in favour to get rid of it. Regards Ludovic > Signed-off-by: Ludovic Desroches <ludovic.desroches@xxxxxxxxx> > --- > drivers/mmc/host/sdhci-of-at91.c | 46 ++++++++++++++++++++++++++++++---------- > 1 file changed, 35 insertions(+), 11 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-of-at91.c b/drivers/mmc/host/sdhci-of-at91.c > index efec736..2159c6e 100644 > --- a/drivers/mmc/host/sdhci-of-at91.c > +++ b/drivers/mmc/host/sdhci-of-at91.c > @@ -18,6 +18,7 @@ > #include <linux/err.h> > #include <linux/io.h> > #include <linux/mmc/host.h> > +#include <linux/mmc/slot-gpio.h> > #include <linux/module.h> > #include <linux/of.h> > #include <linux/of_device.h> > @@ -45,7 +46,6 @@ static const struct sdhci_ops sdhci_at91_sama5d2_ops = { > > static const struct sdhci_pltfm_data soc_data_sama5d2 = { > .ops = &sdhci_at91_sama5d2_ops, > - .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION, > .quirks2 = SDHCI_QUIRK2_NEED_DELAY_AFTER_INT_CLK_RST, > }; > > @@ -55,17 +55,37 @@ static const struct of_device_id sdhci_at91_dt_match[] = { > }; > > #ifdef CONFIG_PM > +static bool sdhci_at91_use_sdhci_runtime(struct sdhci_host *host) > +{ > + u32 caps = host->mmc->caps; > + > + return (caps & MMC_CAP_NONREMOVABLE) || > + (!IS_ERR_VALUE(mmc_gpio_get_cd(host->mmc))); > +} > + > static int sdhci_at91_runtime_suspend(struct device *dev) > { > struct sdhci_host *host = dev_get_drvdata(dev); > struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); > struct sdhci_at91_priv *priv = pltfm_host->priv; > - int ret; > + int ret = 0; > > - ret = sdhci_runtime_suspend_host(host); > + /* > + * If we call sdhci_runtime_suspend(), we could wakeup only if sdio > + * irqs are enabled. If we want to wakeup on a card detect event there > + * are two options: > + * - do not call sdhci_runtime_suspend() but save power by disabling > + * all clocks excepting the one for the controller interface. > + * - call sdhci_runtime_suspend(), save maximum power by disabling > + * all clocks but use a gpio for the card detect signal to have a way > + * to wakeup. > + */ > + if (sdhci_at91_use_sdhci_runtime(host)) { > + ret = sdhci_runtime_suspend_host(host); > + clk_disable_unprepare(priv->hclock); > + } > > clk_disable_unprepare(priv->gck); > - clk_disable_unprepare(priv->hclock); > clk_disable_unprepare(priv->mainck); > > return ret; > @@ -84,19 +104,23 @@ static int sdhci_at91_runtime_resume(struct device *dev) > return ret; > } > > - ret = clk_prepare_enable(priv->hclock); > - if (ret) { > - dev_err(dev, "can't enable hclock\n"); > - return ret; > - } > - > ret = clk_prepare_enable(priv->gck); > if (ret) { > dev_err(dev, "can't enable gck\n"); > return ret; > } > > - return sdhci_runtime_resume_host(host); > + if (sdhci_at91_use_sdhci_runtime(host)) { > + ret = clk_prepare_enable(priv->hclock); > + if (ret) { > + dev_err(dev, "can't enable hclock\n"); > + return ret; > + } > + > + ret = sdhci_runtime_resume_host(host); > + } > + > + return ret; > } > #endif /* CONFIG_PM */ > > -- > 2.7.0 > -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html