Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 76855ba7 authored by Glen Lee's avatar Glen Lee Committed by Greg Kroah-Hartman
Browse files

staging: wilc1000: add sdio resume/suspend



This patch introduces sdio device suspend and resume functionality. sdio_reset
function is added to reset sdio. Remove static inline keyword from
chip_allow_sleep and chip_wakeup, and export symbols.

Signed-off-by: default avatarGlen Lee <glen.lee@atmel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent fdc2ac1a
Loading
Loading
Loading
Loading
+72 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ static wilc_sdio_t g_sdio;

static int sdio_write_reg(struct wilc *wilc, u32 addr, u32 data);
static int sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data);
static int sdio_init(struct wilc *wilc);

static void wilc_sdio_interrupt(struct sdio_func *func)
{
@@ -142,11 +143,82 @@ static void linux_sdio_remove(struct sdio_func *func)
	wilc_netdev_cleanup(sdio_get_drvdata(func));
}

static int sdio_reset(struct wilc *wilc)
{
	sdio_cmd52_t cmd;
	int ret;
	struct sdio_func *func = dev_to_sdio_func(wilc->dev);

	cmd.read_write = 1;
	cmd.function = 0;
	cmd.raw = 0;
	cmd.address = 0x6;
	cmd.data = 0x8;
	ret = wilc_sdio_cmd52(wilc, &cmd);
	if (ret) {
		dev_err(&func->dev, "Fail cmd 52, reset cmd ...\n");
		return ret;
	}
	return 0;
}

static int wilc_sdio_suspend(struct device *dev)
{
	struct sdio_func *func = dev_to_sdio_func(dev);
	struct wilc *wilc = sdio_get_drvdata(func);
	int ret;

	dev_info(dev, "sdio suspend\n");
	chip_wakeup(wilc);

	if (!wilc->suspend_event) {
		wilc_chip_sleep_manually(wilc);
	} else {
		host_sleep_notify(wilc);
		chip_allow_sleep(wilc);
	}

	ret = sdio_reset(wilc);
	if (ret) {
		dev_err(&func->dev, "Fail reset sdio\n");
		return ret;
	}
	sdio_claim_host(func);

	return 0;
}

static int wilc_sdio_resume(struct device *dev)
{
	struct sdio_func *func = dev_to_sdio_func(dev);
	struct wilc *wilc = sdio_get_drvdata(func);

	dev_info(dev, "sdio resume\n");
	sdio_release_host(func);
	chip_wakeup(wilc);
	sdio_init(wilc);

	if (wilc->suspend_event)
		host_wakeup_notify(wilc);

	chip_allow_sleep(wilc);

	return 0;
}

static const struct dev_pm_ops wilc_sdio_pm_ops = {
	.suspend = wilc_sdio_suspend,
	.resume = wilc_sdio_resume,
};

static struct sdio_driver wilc1000_sdio_driver = {
	.name		= SDIO_MODALIAS,
	.id_table	= wilc_sdio_ids,
	.probe		= linux_sdio_probe,
	.remove		= linux_sdio_remove,
	.drv = {
		.pm = &wilc_sdio_pm_ops,
	}
};
module_driver(wilc1000_sdio_driver,
	      sdio_register_driver,
+1 −0
Original line number Diff line number Diff line
@@ -215,6 +215,7 @@ struct wilc {
	const struct firmware *firmware;

	struct device *dev;
	bool suspend_event;
};

struct WILC_WFI_mon_priv {
+7 −4
Original line number Diff line number Diff line
@@ -3,8 +3,6 @@
#include "wilc_wfi_netdevice.h"
#include "wilc_wlan_cfg.h"

static inline void chip_allow_sleep(struct wilc *wilc);
static inline void chip_wakeup(struct wilc *wilc);
static u32 dbgflag = N_INIT | N_ERR | N_INTR | N_TXQ | N_RXQ;

/* FIXME: replace with dev_debug() */
@@ -515,7 +513,7 @@ static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc)
	return NULL;
}

static inline void chip_allow_sleep(struct wilc *wilc)
void chip_allow_sleep(struct wilc *wilc)
{
	u32 reg = 0;

@@ -524,8 +522,9 @@ static inline void chip_allow_sleep(struct wilc *wilc)
	wilc->hif_func->hif_write_reg(wilc, 0xf0, reg & ~BIT(0));
	wilc->hif_func->hif_write_reg(wilc, 0xfa, 0);
}
EXPORT_SYMBOL_GPL(chip_allow_sleep);

static inline void chip_wakeup(struct wilc *wilc)
void chip_wakeup(struct wilc *wilc)
{
	u32 reg, clk_status_reg, trials = 0;

@@ -584,6 +583,7 @@ static inline void chip_wakeup(struct wilc *wilc)
	}
	chip_ps_state = CHIP_WAKEDUP;
}
EXPORT_SYMBOL_GPL(chip_wakeup);

void wilc_chip_sleep_manually(struct wilc *wilc)
{
@@ -597,6 +597,7 @@ void wilc_chip_sleep_manually(struct wilc *wilc)
	chip_ps_state = CHIP_SLEEPING_MANUAL;
	release_bus(wilc, RELEASE_ONLY);
}
EXPORT_SYMBOL_GPL(wilc_chip_sleep_manually);

void host_wakeup_notify(struct wilc *wilc)
{
@@ -604,6 +605,7 @@ void host_wakeup_notify(struct wilc *wilc)
	wilc->hif_func->hif_write_reg(wilc, 0x10b0, 1);
	release_bus(wilc, RELEASE_ONLY);
}
EXPORT_SYMBOL_GPL(host_wakeup_notify);

void host_sleep_notify(struct wilc *wilc)
{
@@ -611,6 +613,7 @@ void host_sleep_notify(struct wilc *wilc)
	wilc->hif_func->hif_write_reg(wilc, 0x10ac, 1);
	release_bus(wilc, RELEASE_ONLY);
}
EXPORT_SYMBOL_GPL(host_sleep_notify);

int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
{
+2 −1
Original line number Diff line number Diff line
@@ -298,5 +298,6 @@ void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size);
void host_wakeup_notify(struct wilc *wilc);
void host_sleep_notify(struct wilc *wilc);
extern bool wilc_enable_ps;

void chip_allow_sleep(struct wilc *wilc);
void chip_wakeup(struct wilc *wilc);
#endif