// SPDX-License-Identifier: GPL-2.0-only /* * This file is part of wl1271 * * Copyright (C) 2009-2010 Nokia Corporation * * Contact: Luciano Coelho <luciano.coelho@nokia.com>
*/
ret = pm_runtime_resume_and_get(&card->dev); if (ret < 0) {
dev_err(glue->dev, "%s: failed to get_sync(%d)\n",
__func__, ret);
return ret;
}
sdio_claim_host(func); /* * To guarantee that the SDIO card is power cycled, as required to make * the FW programming to succeed, let's do a brute force HW reset.
*/
mmc_hw_reset(card);
return 0;
} #else staticint wlcore_probe_of(struct device *dev, int *irq, int *wakeirq, struct wlcore_platdev_data *pdev_data)
{ return -ENODATA;
} #endif
staticint wl1271_probe(struct sdio_func *func, conststruct sdio_device_id *id)
{ struct wlcore_platdev_data *pdev_data; struct wl12xx_sdio_glue *glue; struct resource res[2];
mmc_pm_flag_t mmcflags; int ret = -ENOMEM; int irq, wakeirq, num_irqs; constchar *chip_family;
/* We are only able to handle the wlan function */ if (func->num != 0x02) return -ENODEV;
pdev_data = devm_kzalloc(&func->dev, sizeof(*pdev_data), GFP_KERNEL); if (!pdev_data) return -ENOMEM;
pdev_data->if_ops = &sdio_ops;
glue = devm_kzalloc(&func->dev, sizeof(*glue), GFP_KERNEL); if (!glue) return -ENOMEM;
glue->dev = &func->dev;
/* Grab access to FN0 for ELP reg. */
func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
/* Use block mode for transferring over one block size of data */
func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
ret = wlcore_probe_of(&func->dev, &irq, &wakeirq, pdev_data); if (ret) goto out;
/* if sdio can keep power while host is suspended, enable wow */
mmcflags = sdio_get_host_pm_caps(func);
dev_dbg(glue->dev, "sdio PM caps = 0x%x\n", mmcflags);
if (mmcflags & MMC_PM_KEEP_POWER)
pdev_data->pwr_in_suspend = true;
sdio_set_drvdata(func, glue);
/* Tell PM core that we don't need the card to be powered now */
pm_runtime_put_noidle(&func->dev);
/* * Due to a hardware bug, we can't differentiate wl18xx from * wl12xx, because both report the same device ID. The only * way to differentiate is by checking the SDIO revision, * which is 3.00 on the wl18xx chips.
*/ if (func->card->cccr.sdio_vsn == SDIO_SDIO_REV_3_00)
chip_family = "wl18xx"; else
chip_family = "wl12xx";
glue->core = platform_device_alloc(chip_family, PLATFORM_DEVID_AUTO); if (!glue->core) {
dev_err(glue->dev, "can't allocate platform_device");
ret = -ENOMEM; goto out;
}
/* Undo decrement done above in wl1271_probe */
pm_runtime_get_noresume(&func->dev);
platform_device_unregister(glue->core);
}
#ifdef CONFIG_PM staticint wl1271_suspend(struct device *dev)
{ /* Tell MMC/SDIO core it's OK to power down the card
* (if it isn't already), but not to remove it completely */ struct sdio_func *func = dev_to_sdio_func(dev); struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func); struct wl1271 *wl = platform_get_drvdata(glue->core);
mmc_pm_flag_t sdio_flags; int ret = 0;
if (!wl) {
dev_err(dev, "no wilink module was probed\n"); goto out;
}
/* check whether sdio should keep power */ if (wl->wow_enabled) {
sdio_flags = sdio_get_host_pm_caps(func);
if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
dev_err(dev, "can't keep power while host " "is suspended\n");
ret = -EINVAL; goto out;
}
/* keep power while host suspended */
ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); if (ret) {
dev_err(dev, "error while trying to keep power\n"); goto out;
}
}
out: return ret;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.