Commit 92cadedd authored by Ulf Hansson's avatar Ulf Hansson Committed by Kalle Valo

brcmfmac: Avoid keeping power to SDIO card unless WOWL is used

Keeping the power to the SDIO card during system wide suspend, consumes
energy. Especially on battery driven embedded systems, this can be a
problem. Therefore, let's change the behaviour into allowing the SDIO card
to be powered off, unless WOWL is supported and enabled.

Note that, the downside from this change, is that during system resume the
SDIO card needs to be re-initialized and the FW must be re-programmed. Even
if this may take some time to complete, it should we worth it, rather than
draining the battery.
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Tested-by: default avatarChristophe Roullier <christophe.roullier@foss.st.com>
Reviewed-by: default avatarYann Gautier <yann.gautier@foss.st.com>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20220323083950.414783-1-ulf.hansson@linaro.org
parent 3e12968f
......@@ -1119,9 +1119,21 @@ void brcmf_sdio_wowl_config(struct device *dev, bool enabled)
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
mmc_pm_flag_t pm_caps = sdio_get_host_pm_caps(sdiodev->func1);
brcmf_dbg(SDIO, "Configuring WOWL, enabled=%d\n", enabled);
/* Power must be preserved to be able to support WOWL. */
if (!(pm_caps & MMC_PM_KEEP_POWER))
goto notsup;
if (sdiodev->settings->bus.sdio.oob_irq_supported ||
pm_caps & MMC_PM_WAKE_SDIO_IRQ) {
sdiodev->wowl_enabled = enabled;
brcmf_dbg(SDIO, "Configuring WOWL, enabled=%d\n", enabled);
return;
}
notsup:
brcmf_dbg(SDIO, "WOWL not supported\n");
}
#ifdef CONFIG_PM_SLEEP
......@@ -1130,7 +1142,7 @@ static int brcmf_ops_sdio_suspend(struct device *dev)
struct sdio_func *func;
struct brcmf_bus *bus_if;
struct brcmf_sdio_dev *sdiodev;
mmc_pm_flag_t pm_caps, sdio_flags;
mmc_pm_flag_t sdio_flags;
int ret = 0;
func = container_of(dev, struct sdio_func, dev);
......@@ -1142,20 +1154,15 @@ static int brcmf_ops_sdio_suspend(struct device *dev)
bus_if = dev_get_drvdata(dev);
sdiodev = bus_if->bus_priv.sdio;
pm_caps = sdio_get_host_pm_caps(func);
if (pm_caps & MMC_PM_KEEP_POWER) {
/* preserve card power during suspend */
if (sdiodev->wowl_enabled) {
brcmf_sdiod_freezer_on(sdiodev);
brcmf_sdio_wd_timer(sdiodev->bus, 0);
sdio_flags = MMC_PM_KEEP_POWER;
if (sdiodev->wowl_enabled) {
if (sdiodev->settings->bus.sdio.oob_irq_supported)
enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);
else
sdio_flags |= MMC_PM_WAKE_SDIO_IRQ;
}
if (sdio_set_host_pm_flags(sdiodev->func1, sdio_flags))
brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
......@@ -1176,21 +1183,19 @@ static int brcmf_ops_sdio_resume(struct device *dev)
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
struct sdio_func *func = container_of(dev, struct sdio_func, dev);
mmc_pm_flag_t pm_caps = sdio_get_host_pm_caps(func);
int ret = 0;
brcmf_dbg(SDIO, "Enter: F%d\n", func->num);
if (func->num != 2)
return 0;
if (!(pm_caps & MMC_PM_KEEP_POWER)) {
if (!sdiodev->wowl_enabled) {
/* bus was powered off and device removed, probe again */
ret = brcmf_sdiod_probe(sdiodev);
if (ret)
brcmf_err("Failed to probe device on resume\n");
} else {
if (sdiodev->wowl_enabled &&
sdiodev->settings->bus.sdio.oob_irq_supported)
if (sdiodev->settings->bus.sdio.oob_irq_supported)
disable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);
brcmf_sdiod_freezer_off(sdiodev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment