brcmfmac: Add wowl support for SDIO devices.
This patch adds wowl support for SDIO bus devices. This feature requires FW which has support for wowl built in. Reviewed-by: Arend Van Spriel <arend@broadcom.com> Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Signed-off-by: Hante Meuleman <meuleman@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Родитель
244b124c6a
Коммит
330b4e4be9
|
@ -1064,6 +1064,16 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
|
|||
if (!sdiodev->pdata)
|
||||
brcmf_of_probe(sdiodev);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
/* wowl can be supported when KEEP_POWER is true and (WAKE_SDIO_IRQ
|
||||
* is true or when platform data OOB irq is true).
|
||||
*/
|
||||
if ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_KEEP_POWER) &&
|
||||
((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_WAKE_SDIO_IRQ) ||
|
||||
(sdiodev->pdata->oob_irq_supported)))
|
||||
bus_if->wowl_supported = true;
|
||||
#endif
|
||||
|
||||
atomic_set(&sdiodev->suspend, false);
|
||||
init_waitqueue_head(&sdiodev->request_word_wait);
|
||||
init_waitqueue_head(&sdiodev->request_buffer_wait);
|
||||
|
@ -1116,34 +1126,39 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func)
|
|||
brcmf_dbg(SDIO, "Exit\n");
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
brcmf_dbg(SDIO, "Configuring WOWL, enabled=%d\n", enabled);
|
||||
sdiodev->wowl_enabled = enabled;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int brcmf_ops_sdio_suspend(struct device *dev)
|
||||
{
|
||||
mmc_pm_flag_t sdio_flags;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
|
||||
int ret = 0;
|
||||
mmc_pm_flag_t sdio_flags;
|
||||
|
||||
brcmf_dbg(SDIO, "Enter\n");
|
||||
|
||||
sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]);
|
||||
if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
|
||||
brcmf_err("Host can't keep power while suspended\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
atomic_set(&sdiodev->suspend, true);
|
||||
|
||||
ret = sdio_set_host_pm_flags(sdiodev->func[1], MMC_PM_KEEP_POWER);
|
||||
if (ret) {
|
||||
brcmf_err("Failed to set pm_flags\n");
|
||||
atomic_set(&sdiodev->suspend, false);
|
||||
return ret;
|
||||
if (sdiodev->wowl_enabled) {
|
||||
sdio_flags = MMC_PM_KEEP_POWER;
|
||||
if (sdiodev->pdata->oob_irq_supported)
|
||||
enable_irq_wake(sdiodev->pdata->oob_irq_nr);
|
||||
else
|
||||
sdio_flags = MMC_PM_WAKE_SDIO_IRQ;
|
||||
if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags))
|
||||
brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
|
||||
}
|
||||
|
||||
brcmf_sdio_wd_timer(sdiodev->bus, 0);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int brcmf_ops_sdio_resume(struct device *dev)
|
||||
|
@ -1152,6 +1167,8 @@ static int brcmf_ops_sdio_resume(struct device *dev)
|
|||
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
|
||||
|
||||
brcmf_dbg(SDIO, "Enter\n");
|
||||
if (sdiodev->pdata->oob_irq_supported)
|
||||
disable_irq_wake(sdiodev->pdata->oob_irq_nr);
|
||||
brcmf_sdio_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS);
|
||||
atomic_set(&sdiodev->suspend, false);
|
||||
return 0;
|
||||
|
|
|
@ -3949,6 +3949,7 @@ static struct brcmf_bus_ops brcmf_sdio_bus_ops = {
|
|||
.txctl = brcmf_sdio_bus_txctl,
|
||||
.rxctl = brcmf_sdio_bus_rxctl,
|
||||
.gettxq = brcmf_sdio_bus_gettxq,
|
||||
.wowl_config = brcmf_sdio_wowl_config
|
||||
};
|
||||
|
||||
static void brcmf_sdio_firmware_callback(struct device *dev,
|
||||
|
|
|
@ -186,6 +186,7 @@ struct brcmf_sdio_dev {
|
|||
struct sg_table sgtable;
|
||||
char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
|
||||
char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
|
||||
bool wowl_enabled;
|
||||
};
|
||||
|
||||
/* sdio core registers */
|
||||
|
@ -334,5 +335,6 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus);
|
|||
void brcmf_sdio_isr(struct brcmf_sdio *bus);
|
||||
|
||||
void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick);
|
||||
void brcmf_sdio_wowl_config(struct device *dev, bool enabled);
|
||||
|
||||
#endif /* _BRCM_SDH_H_ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче