On Tue, Nov 16, 2010 at 7:17 PM, Arnd Hannemann <hannemann@xxxxxxxxxxxxxxxxxxx> >> > Its an AP4 (SH7372) evaluation board from renesas. It has an SD-Slot, > where you plug the SDIO card into it. No special wiring or something > like this. So I doubt some external GPIOs are involved. > I have no idea how the wifi card gets its power, but I hope its over > some well defined pins within the SD slot... Can you please specify what was the wlan card you used ? is it a commercial card or an evaluation board of some sort ? You said it, but just to be sure - I assume there is no external power supply involved with that card, right ? it's just plugged into the SD slot with no extra wire whatsoever ? Thanks! Ohad. > I was able to work with 2.6.35 and .36 plus some out-of-tree patches > for the sh_mobile_sdhi mfd, which are now in mainline: > mmc: Allow 2 byte requests in 4-bit mode for tmio_mmc > tmio_mmc: don't clear unhandled pending interrupts > tmio_mmc: don't clear unhandled pending interrupts > >>> From 6b5691bdd8184cc0876d209c69d38844ea10f678 Mon Sep 17 00:00:00 2001 >>> From: Ohad Ben-Cohen <ohad@xxxxxxxxxx> >>> Date: Mon, 1 Nov 2010 09:41:44 +0200 >>> Subject: [PATCH] mmc: add MMC_CAP_RUNTIME_PM >>> >>> Some board/card/host configurations are not capable of powering off/on >>> on the card during runtime. >>> >>> To support such configurations, and to allow smoother transition to >>> runtime PM behavior, MMC_CAP_RUNTIME_PM is added, so hosts need to >>> explicitly indicate that it's OK to power off their cards after boot. >>> >>> This will prevent sdio_bus_probe() from failing to power on the card >>> when the driver is loaded on such setups. >>> >>> Signed-off-by: Ohad Ben-Cohen <ohad@xxxxxxxxxx> >>> --- >>> drivers/mmc/core/sdio.c | 37 +++++++++++++++++++++++-------------- >>> drivers/mmc/core/sdio_bus.c | 33 ++++++++++++++++++++++----------- >>> include/linux/mmc/host.h | 1 + >>> 3 files changed, 46 insertions(+), 25 deletions(-) >>> >>> diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c >>> index 6a9ad40..373d56d 100644 >>> --- a/drivers/mmc/core/sdio.c >>> +++ b/drivers/mmc/core/sdio.c >>> @@ -547,9 +547,11 @@ static void mmc_sdio_detect(struct mmc_host *host) >>> BUG_ON(!host->card); >>> >>> /* Make sure card is powered before detecting it */ >>> - err = pm_runtime_get_sync(&host->card->dev); >>> - if (err < 0) >>> - goto out; >>> + if (host->caps & MMC_CAP_RUNTIME_PM) { >>> + err = pm_runtime_get_sync(&host->card->dev); >>> + if (err < 0) >>> + goto out; >>> + } >>> >>> mmc_claim_host(host); >>> >>> @@ -570,7 +572,8 @@ out: >>> } >>> >>> /* Tell PM core that we're done */ >>> - pm_runtime_put(&host->card->dev); >>> + if (host->caps & MMC_CAP_RUNTIME_PM) >>> + pm_runtime_put(&host->card->dev); >>> } >>> >>> /* >>> @@ -720,16 +723,21 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) >>> card = host->card; >>> >>> /* >>> - * Let runtime PM core know our card is active >>> + * Enable runtime PM only if supported by host+card+board >>> */ >>> - err = pm_runtime_set_active(&card->dev); >>> - if (err) >>> - goto remove; >>> + if (host->caps & MMC_CAP_RUNTIME_PM) { >>> + /* >>> + * Let runtime PM core know our card is active >>> + */ >>> + err = pm_runtime_set_active(&card->dev); >>> + if (err) >>> + goto remove; >>> >>> - /* >>> - * Enable runtime PM for this card >>> - */ >>> - pm_runtime_enable(&card->dev); >>> + /* >>> + * Enable runtime PM for this card >>> + */ >>> + pm_runtime_enable(&card->dev); >>> + } >>> >>> /* >>> * The number of functions on the card is encoded inside >>> @@ -747,9 +755,10 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) >>> goto remove; >>> >>> /* >>> - * Enable Runtime PM for this func >>> + * Enable Runtime PM for this func (if supported) >>> */ >>> - pm_runtime_enable(&card->sdio_func[i]->dev); >>> + if (host->caps & MMC_CAP_RUNTIME_PM) >>> + pm_runtime_enable(&card->sdio_func[i]->dev); >>> } >>> >>> mmc_release_host(host); >>> diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c >>> index 2716c7a..f3ce21b 100644 >>> --- a/drivers/mmc/core/sdio_bus.c >>> +++ b/drivers/mmc/core/sdio_bus.c >>> @@ -17,6 +17,7 @@ >>> #include <linux/pm_runtime.h> >>> >>> #include <linux/mmc/card.h> >>> +#include <linux/mmc/host.h> >>> #include <linux/mmc/sdio_func.h> >>> >>> #include "sdio_cis.h" >>> @@ -132,9 +133,11 @@ static int sdio_bus_probe(struct device *dev) >>> * it should call pm_runtime_put_noidle() in its probe routine and >>> * pm_runtime_get_noresume() in its remove routine. >>> */ >>> - ret = pm_runtime_get_sync(dev); >>> - if (ret < 0) >>> - goto out; >>> + if (func->card->host->caps & MMC_CAP_RUNTIME_PM) { >>> + ret = pm_runtime_get_sync(dev); >>> + if (ret < 0) >>> + goto out; >>> + } >>> >>> /* Set the default block size so the driver is sure it's something >>> * sensible. */ >>> @@ -151,7 +154,8 @@ static int sdio_bus_probe(struct device *dev) >>> return 0; >>> >>> disable_runtimepm: >>> - pm_runtime_put_noidle(dev); >>> + if (func->card->host->caps & MMC_CAP_RUNTIME_PM) >>> + pm_runtime_put_noidle(dev); >>> out: >>> return ret; >>> } >>> @@ -160,12 +164,14 @@ static int sdio_bus_remove(struct device *dev) >>> { >>> struct sdio_driver *drv = to_sdio_driver(dev->driver); >>> struct sdio_func *func = dev_to_sdio_func(dev); >>> - int ret; >>> + int ret = 0; >>> >>> /* Make sure card is powered before invoking ->remove() */ >>> - ret = pm_runtime_get_sync(dev); >>> - if (ret < 0) >>> - goto out; >>> + if (func->card->host->caps & MMC_CAP_RUNTIME_PM) { >>> + ret = pm_runtime_get_sync(dev); >>> + if (ret < 0) >>> + goto out; >>> + } >>> >>> drv->remove(func); >>> >>> @@ -178,10 +184,12 @@ static int sdio_bus_remove(struct device *dev) >>> } >>> >>> /* First, undo the increment made directly above */ >>> - pm_runtime_put_noidle(dev); >>> + if (func->card->host->caps & MMC_CAP_RUNTIME_PM) >>> + pm_runtime_put_noidle(dev); >>> >>> /* Then undo the runtime PM settings in sdio_bus_probe() */ >>> - pm_runtime_put_noidle(dev); >>> + if (func->card->host->caps & MMC_CAP_RUNTIME_PM) >>> + pm_runtime_put_noidle(dev); >>> >>> out: >>> return ret; >>> @@ -191,6 +199,8 @@ out: >>> >>> static int sdio_bus_pm_prepare(struct device *dev) >>> { >>> + struct sdio_func *func = dev_to_sdio_func(dev); >>> + >>> /* >>> * Resume an SDIO device which was suspended at run time at this >>> * point, in order to allow standard SDIO suspend/resume paths >>> @@ -212,7 +222,8 @@ static int sdio_bus_pm_prepare(struct device *dev) >>> * since there is little point in failing system suspend if a >>> * device can't be resumed. >>> */ >>> - pm_runtime_resume(dev); >>> + if (func->card->host->caps & MMC_CAP_RUNTIME_PM) >>> + pm_runtime_resume(dev); >>> >>> return 0; >>> } >>> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h >>> index c3ffad8..e5eee0e 100644 >>> --- a/include/linux/mmc/host.h >>> +++ b/include/linux/mmc/host.h >>> @@ -167,6 +167,7 @@ struct mmc_host { >>> /* DDR mode at 1.8V */ >>> #define MMC_CAP_1_2V_DDR (1 << 12) /* can support */ >>> /* DDR mode at 1.2V */ >>> +#define MMC_CAP_RUNTIME_PM (1 << 13) /* Can power off/on in runtime */ >>> >>> mmc_pm_flag_t pm_caps; /* supported pm features */ >>> >>> -- >>> 1.7.0.4 >>> >>> > > -- 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