mirror of
https://github.com/torvalds/linux.git
synced 2026-05-24 23:22:31 +02:00
wifi: wfx: allow SDIO device to wake up the host
If the device is connected with SDIO bus, it can wake up the host using either the SDIO controller (that requires MMC_PM_WAKE_SDIO_IRQ capability) or the out-of-bound IRQ. This patch allows both. Obviously, the SDIO controller must be able to keep the SDIO device powered on. Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com> Link: https://patch.msgid.link/20250304153224.39083-5-jerome.pouiller@silabs.com Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
32bd7f4b39
commit
75516809af
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/of_irq.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/align.h>
|
||||
#include <linux/pm.h>
|
||||
|
||||
#include "bus.h"
|
||||
#include "wfx.h"
|
||||
|
|
@ -191,9 +192,48 @@ static const struct of_device_id wfx_sdio_of_match[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(of, wfx_sdio_of_match);
|
||||
|
||||
static int wfx_sdio_suspend(struct device *dev)
|
||||
{
|
||||
struct sdio_func *func = dev_to_sdio_func(dev);
|
||||
struct wfx_sdio_priv *bus = sdio_get_drvdata(func);
|
||||
int ret;
|
||||
|
||||
if (!device_may_wakeup(dev))
|
||||
return 0;
|
||||
|
||||
flush_work(&bus->core->hif.bh);
|
||||
/* Either "wakeup-source" attribute or out-of-band IRQ is required for
|
||||
* WoWLAN
|
||||
*/
|
||||
if (bus->of_irq) {
|
||||
ret = enable_irq_wake(bus->of_irq);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
ret = sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
|
||||
}
|
||||
|
||||
static int wfx_sdio_resume(struct device *dev)
|
||||
{
|
||||
struct sdio_func *func = dev_to_sdio_func(dev);
|
||||
struct wfx_sdio_priv *bus = sdio_get_drvdata(func);
|
||||
|
||||
if (!device_may_wakeup(dev))
|
||||
return 0;
|
||||
if (bus->of_irq)
|
||||
return disable_irq_wake(bus->of_irq);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wfx_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
|
||||
{
|
||||
const struct wfx_platform_data *pdata = of_device_get_match_data(&func->dev);
|
||||
mmc_pm_flag_t pm_flag = sdio_get_host_pm_caps(func);
|
||||
struct device_node *np = func->dev.of_node;
|
||||
struct wfx_sdio_priv *bus;
|
||||
int ret;
|
||||
|
|
@ -235,6 +275,9 @@ static int wfx_sdio_probe(struct sdio_func *func, const struct sdio_device_id *i
|
|||
if (ret)
|
||||
goto sdio_release;
|
||||
|
||||
if (pm_flag & MMC_PM_KEEP_POWER)
|
||||
device_set_wakeup_capable(&func->dev, true);
|
||||
|
||||
return 0;
|
||||
|
||||
sdio_release:
|
||||
|
|
@ -261,6 +304,8 @@ static const struct sdio_device_id wfx_sdio_ids[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(sdio, wfx_sdio_ids);
|
||||
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(wfx_sdio_pm_ops, wfx_sdio_suspend, wfx_sdio_resume);
|
||||
|
||||
struct sdio_driver wfx_sdio_driver = {
|
||||
.name = "wfx-sdio",
|
||||
.id_table = wfx_sdio_ids,
|
||||
|
|
@ -268,5 +313,6 @@ struct sdio_driver wfx_sdio_driver = {
|
|||
.remove = wfx_sdio_remove,
|
||||
.drv = {
|
||||
.of_match_table = wfx_sdio_of_match,
|
||||
.pm = &wfx_sdio_pm_ops,
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user