|
@@ -73,6 +73,66 @@ static struct memory_type_mapping mem_type_mapping_tbl[] = {
|
|
|
{"EXTLAST", NULL, 0, 0xFE},
|
|
|
};
|
|
|
|
|
|
+static const struct of_device_id mwifiex_sdio_of_match_table[] = {
|
|
|
+ { .compatible = "marvell,sd8897" },
|
|
|
+ { .compatible = "marvell,sd8997" },
|
|
|
+ { }
|
|
|
+};
|
|
|
+
|
|
|
+static irqreturn_t mwifiex_wake_irq_wifi(int irq, void *priv)
|
|
|
+{
|
|
|
+ struct mwifiex_plt_wake_cfg *cfg = priv;
|
|
|
+
|
|
|
+ if (cfg->irq_wifi >= 0) {
|
|
|
+ pr_info("%s: wake by wifi", __func__);
|
|
|
+ cfg->wake_by_wifi = true;
|
|
|
+ disable_irq_nosync(irq);
|
|
|
+ }
|
|
|
+
|
|
|
+ return IRQ_HANDLED;
|
|
|
+}
|
|
|
+
|
|
|
+/* This function parse device tree node using mmc subnode devicetree API.
|
|
|
+ * The device node is saved in card->plt_of_node.
|
|
|
+ * if the device tree node exist and include interrupts attributes, this
|
|
|
+ * function will also request platform specific wakeup interrupt.
|
|
|
+ */
|
|
|
+static int mwifiex_sdio_probe_of(struct device *dev, struct sdio_mmc_card *card)
|
|
|
+{
|
|
|
+ struct mwifiex_plt_wake_cfg *cfg;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (!dev->of_node ||
|
|
|
+ !of_match_node(mwifiex_sdio_of_match_table, dev->of_node)) {
|
|
|
+ pr_err("sdio platform data not available");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ card->plt_of_node = dev->of_node;
|
|
|
+ card->plt_wake_cfg = devm_kzalloc(dev, sizeof(*card->plt_wake_cfg),
|
|
|
+ GFP_KERNEL);
|
|
|
+ cfg = card->plt_wake_cfg;
|
|
|
+ if (cfg && card->plt_of_node) {
|
|
|
+ cfg->irq_wifi = irq_of_parse_and_map(card->plt_of_node, 0);
|
|
|
+ if (!cfg->irq_wifi) {
|
|
|
+ dev_err(dev, "fail to parse irq_wifi from device tree");
|
|
|
+ } else {
|
|
|
+ ret = devm_request_irq(dev, cfg->irq_wifi,
|
|
|
+ mwifiex_wake_irq_wifi,
|
|
|
+ IRQF_TRIGGER_LOW,
|
|
|
+ "wifi_wake", cfg);
|
|
|
+ if (ret) {
|
|
|
+ dev_err(dev,
|
|
|
+ "Failed to request irq_wifi %d (%d)\n",
|
|
|
+ cfg->irq_wifi, ret);
|
|
|
+ }
|
|
|
+ disable_irq(cfg->irq_wifi);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* SDIO probe.
|
|
|
*
|
|
@@ -127,6 +187,9 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
|
|
|
return -EIO;
|
|
|
}
|
|
|
|
|
|
+ /* device tree node parsing and platform specific configuration*/
|
|
|
+ mwifiex_sdio_probe_of(&func->dev, card);
|
|
|
+
|
|
|
if (mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops,
|
|
|
MWIFIEX_SDIO)) {
|
|
|
pr_err("%s: add card failed\n", __func__);
|
|
@@ -183,6 +246,13 @@ static int mwifiex_sdio_resume(struct device *dev)
|
|
|
mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
|
|
|
MWIFIEX_SYNC_CMD);
|
|
|
|
|
|
+ /* Disable platform specific wakeup interrupt */
|
|
|
+ if (card->plt_wake_cfg && card->plt_wake_cfg->irq_wifi >= 0) {
|
|
|
+ disable_irq_wake(card->plt_wake_cfg->irq_wifi);
|
|
|
+ if (!card->plt_wake_cfg->wake_by_wifi)
|
|
|
+ disable_irq(card->plt_wake_cfg->irq_wifi);
|
|
|
+ }
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -262,6 +332,13 @@ static int mwifiex_sdio_suspend(struct device *dev)
|
|
|
|
|
|
adapter = card->adapter;
|
|
|
|
|
|
+ /* Enable platform specific wakeup interrupt */
|
|
|
+ if (card->plt_wake_cfg && card->plt_wake_cfg->irq_wifi >= 0) {
|
|
|
+ card->plt_wake_cfg->wake_by_wifi = false;
|
|
|
+ enable_irq(card->plt_wake_cfg->irq_wifi);
|
|
|
+ enable_irq_wake(card->plt_wake_cfg->irq_wifi);
|
|
|
+ }
|
|
|
+
|
|
|
/* Enable the Host Sleep */
|
|
|
if (!mwifiex_enable_hs(adapter)) {
|
|
|
mwifiex_dbg(adapter, ERROR,
|