Merge "cnss: Reset QCA Card during WLAN SubSystem Recovery"
This commit is contained in:
commit
40b4ea195d
3 changed files with 214 additions and 46 deletions
|
@ -29,7 +29,8 @@ Optional properties:
|
||||||
- qcom,msm-bus,num-cases: number of cases for bus scaling.
|
- qcom,msm-bus,num-cases: number of cases for bus scaling.
|
||||||
- qcom,msm-bus,num-paths: number of paths for bus scale vector.
|
- qcom,msm-bus,num-paths: number of paths for bus scale vector.
|
||||||
- qcom,msm-bus,vectors-KBps: bus scale vector table.
|
- qcom,msm-bus,vectors-KBps: bus scale vector table.
|
||||||
|
- qcom,skip-wlan-en-toggle: Boolean property to be enabled for platforms where
|
||||||
|
wlan_en toggling is not supported.
|
||||||
Example:
|
Example:
|
||||||
qcom,cnss-sdio {
|
qcom,cnss-sdio {
|
||||||
compatible = "qcom,cnss_sdio";
|
compatible = "qcom,cnss_sdio";
|
||||||
|
|
|
@ -2761,14 +2761,8 @@ static void cnss_crash_shutdown(const struct subsys_desc *subsys)
|
||||||
wdrv = penv->driver;
|
wdrv = penv->driver;
|
||||||
pdev = penv->pdev;
|
pdev = penv->pdev;
|
||||||
|
|
||||||
penv->dump_data.version = CNSS_DUMP_FORMAT_VER;
|
|
||||||
strlcpy(penv->dump_data.name, CNSS_DUMP_NAME,
|
|
||||||
sizeof(penv->dump_data.name));
|
|
||||||
|
|
||||||
if (pdev && wdrv && wdrv->crash_shutdown)
|
if (pdev && wdrv && wdrv->crash_shutdown)
|
||||||
wdrv->crash_shutdown(pdev);
|
wdrv->crash_shutdown(pdev);
|
||||||
|
|
||||||
penv->dump_data.magic = CNSS_DUMP_MAGIC_VER_V2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cnss_device_self_recovery(void)
|
void cnss_device_self_recovery(void)
|
||||||
|
@ -2829,6 +2823,28 @@ static struct notifier_block mnb = {
|
||||||
.notifier_call = cnss_modem_notifier_nb,
|
.notifier_call = cnss_modem_notifier_nb,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int cnss_init_dump_entry(void)
|
||||||
|
{
|
||||||
|
struct msm_dump_entry dump_entry;
|
||||||
|
|
||||||
|
if (!penv)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (!penv->ramdump_dynamic)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
penv->dump_data.addr = penv->ramdump_phys;
|
||||||
|
penv->dump_data.len = penv->ramdump_size;
|
||||||
|
penv->dump_data.version = CNSS_DUMP_FORMAT_VER;
|
||||||
|
penv->dump_data.magic = CNSS_DUMP_MAGIC_VER_V2;
|
||||||
|
strlcpy(penv->dump_data.name, CNSS_DUMP_NAME,
|
||||||
|
sizeof(penv->dump_data.name));
|
||||||
|
dump_entry.id = MSM_DUMP_DATA_CNSS_WLAN;
|
||||||
|
dump_entry.addr = virt_to_phys(&penv->dump_data);
|
||||||
|
|
||||||
|
return msm_dump_data_register(MSM_DUMP_TABLE_APPS, &dump_entry);
|
||||||
|
}
|
||||||
|
|
||||||
static int cnss_probe(struct platform_device *pdev)
|
static int cnss_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
@ -2836,7 +2852,6 @@ static int cnss_probe(struct platform_device *pdev)
|
||||||
const char *client_desc;
|
const char *client_desc;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
u32 rc_num;
|
u32 rc_num;
|
||||||
struct msm_dump_entry dump_entry;
|
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
u32 ramdump_size = 0;
|
u32 ramdump_size = 0;
|
||||||
u32 smmu_iova_address[2];
|
u32 smmu_iova_address[2];
|
||||||
|
@ -2952,18 +2967,10 @@ static int cnss_probe(struct platform_device *pdev)
|
||||||
goto skip_ramdump;
|
goto skip_ramdump;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (penv->ramdump_dynamic) {
|
ret = cnss_init_dump_entry();
|
||||||
penv->dump_data.addr = penv->ramdump_phys;
|
if (ret) {
|
||||||
penv->dump_data.len = penv->ramdump_size;
|
pr_err("%s: Dump table setup failed: %d\n", __func__, ret);
|
||||||
dump_entry.id = MSM_DUMP_DATA_CNSS_WLAN;
|
goto err_ramdump_create;
|
||||||
dump_entry.addr = virt_to_phys(&penv->dump_data);
|
|
||||||
|
|
||||||
ret = msm_dump_data_register(MSM_DUMP_TABLE_APPS, &dump_entry);
|
|
||||||
if (ret) {
|
|
||||||
pr_err("%s: Dump table setup failed: %d\n",
|
|
||||||
__func__, ret);
|
|
||||||
goto err_ramdump_create;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
penv->ramdump_dev = create_ramdump_device(penv->subsysdesc.name,
|
penv->ramdump_dev = create_ramdump_device(penv->subsysdesc.name,
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/mmc/sdio_func.h>
|
#include <linux/mmc/sdio_func.h>
|
||||||
#include <linux/mmc/sdio_ids.h>
|
#include <linux/mmc/sdio_ids.h>
|
||||||
|
#include <linux/mmc/card.h>
|
||||||
|
#include <linux/mmc/host.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <soc/qcom/subsystem_restart.h>
|
#include <soc/qcom/subsystem_restart.h>
|
||||||
#include <soc/qcom/subsystem_notif.h>
|
#include <soc/qcom/subsystem_notif.h>
|
||||||
|
@ -46,7 +48,7 @@
|
||||||
/* Values for Dynamic Ramdump Collection*/
|
/* Values for Dynamic Ramdump Collection*/
|
||||||
#define CNSS_DUMP_FORMAT_VER 0x11
|
#define CNSS_DUMP_FORMAT_VER 0x11
|
||||||
#define CNSS_DUMP_MAGIC_VER_V2 0x42445953
|
#define CNSS_DUMP_MAGIC_VER_V2 0x42445953
|
||||||
#define CNSS_DUMP_NAME "CNSS_WLAN"
|
#define CNSS_DUMP_NAME "CNSS_WLAN_SDIO"
|
||||||
#define CNSS_PINCTRL_SLEEP_STATE "sleep"
|
#define CNSS_PINCTRL_SLEEP_STATE "sleep"
|
||||||
#define CNSS_PINCTRL_ACTIVE_STATE "active"
|
#define CNSS_PINCTRL_ACTIVE_STATE "active"
|
||||||
|
|
||||||
|
@ -60,7 +62,11 @@ struct cnss_sdio_regulator {
|
||||||
struct cnss_sdio_info {
|
struct cnss_sdio_info {
|
||||||
struct cnss_sdio_wlan_driver *wdrv;
|
struct cnss_sdio_wlan_driver *wdrv;
|
||||||
struct sdio_func *func;
|
struct sdio_func *func;
|
||||||
|
struct mmc_card *card;
|
||||||
|
struct mmc_host *host;
|
||||||
|
struct device *dev;
|
||||||
const struct sdio_device_id *id;
|
const struct sdio_device_id *id;
|
||||||
|
bool skip_wlan_en_toggle;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cnss_ssr_info {
|
struct cnss_ssr_info {
|
||||||
|
@ -212,19 +218,103 @@ void cnss_sdio_remove_pm_qos(void)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cnss_sdio_remove_pm_qos);
|
EXPORT_SYMBOL(cnss_sdio_remove_pm_qos);
|
||||||
|
|
||||||
|
static int cnss_put_hw_resources(struct device *dev)
|
||||||
|
{
|
||||||
|
int ret = -EINVAL;
|
||||||
|
struct cnss_sdio_info *info;
|
||||||
|
struct mmc_host *host;
|
||||||
|
|
||||||
|
if (!cnss_pdata)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
info = &cnss_pdata->cnss_sdio_info;
|
||||||
|
|
||||||
|
if (info->skip_wlan_en_toggle) {
|
||||||
|
pr_debug("%s: HW doesn't support wlan toggling\n", __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
host = info->host;
|
||||||
|
|
||||||
|
if (!host) {
|
||||||
|
pr_err("%s: MMC host is invalid\n", __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mmc_power_save_host(host);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("%s: Failed to Power Save Host err:%d\n", __func__,
|
||||||
|
ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cnss_pdata->regulator.wlan_vreg) {
|
||||||
|
pr_debug("%s: wlan_vreg regulator is invalid\n", __func__);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
regulator_disable(cnss_pdata->regulator.wlan_vreg);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cnss_get_hw_resources(struct device *dev)
|
||||||
|
{
|
||||||
|
int ret = -EINVAL;
|
||||||
|
struct mmc_host *host;
|
||||||
|
struct cnss_sdio_info *info;
|
||||||
|
|
||||||
|
if (!cnss_pdata)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
info = &cnss_pdata->cnss_sdio_info;
|
||||||
|
|
||||||
|
if (info->skip_wlan_en_toggle) {
|
||||||
|
pr_debug("%s: HW doesn't support wlan toggling\n", __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
host = info->host;
|
||||||
|
|
||||||
|
ret = regulator_enable(cnss_pdata->regulator.wlan_vreg);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("%s: Failed to enable wlan vreg\n", __func__);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mmc_power_restore_host(host);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("%s: Failed to restore host power ret:%d\n", __func__,
|
||||||
|
ret);
|
||||||
|
regulator_disable(cnss_pdata->regulator.wlan_vreg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int cnss_sdio_shutdown(const struct subsys_desc *subsys, bool force_stop)
|
static int cnss_sdio_shutdown(const struct subsys_desc *subsys, bool force_stop)
|
||||||
{
|
{
|
||||||
struct cnss_sdio_info *cnss_info;
|
struct cnss_sdio_info *cnss_info;
|
||||||
struct cnss_sdio_wlan_driver *wdrv;
|
struct cnss_sdio_wlan_driver *wdrv;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (!cnss_pdata)
|
if (!cnss_pdata)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
cnss_info = &cnss_pdata->cnss_sdio_info;
|
cnss_info = &cnss_pdata->cnss_sdio_info;
|
||||||
wdrv = cnss_info->wdrv;
|
wdrv = cnss_info->wdrv;
|
||||||
if (wdrv && wdrv->shutdown)
|
if (!wdrv)
|
||||||
wdrv->shutdown(cnss_info->func);
|
return 0;
|
||||||
return 0;
|
if (!wdrv->shutdown)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
wdrv->shutdown(cnss_info->func);
|
||||||
|
ret = cnss_put_hw_resources(cnss_info->dev);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
pr_err("%s: Failed to put hw resources\n", __func__);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cnss_sdio_powerup(const struct subsys_desc *subsys)
|
static int cnss_sdio_powerup(const struct subsys_desc *subsys)
|
||||||
|
@ -238,11 +328,23 @@ static int cnss_sdio_powerup(const struct subsys_desc *subsys)
|
||||||
|
|
||||||
cnss_info = &cnss_pdata->cnss_sdio_info;
|
cnss_info = &cnss_pdata->cnss_sdio_info;
|
||||||
wdrv = cnss_info->wdrv;
|
wdrv = cnss_info->wdrv;
|
||||||
if (wdrv && wdrv->reinit) {
|
|
||||||
ret = wdrv->reinit(cnss_info->func, cnss_info->id);
|
if (!wdrv)
|
||||||
if (ret)
|
return 0;
|
||||||
pr_err("%s: wlan reinit error=%d\n", __func__, ret);
|
|
||||||
|
if (!wdrv->reinit)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = cnss_get_hw_resources(cnss_info->dev);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("%s: Failed to power up HW\n", __func__);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = wdrv->reinit(cnss_info->func, cnss_info->id);
|
||||||
|
if (ret)
|
||||||
|
pr_err("%s: wlan reinit error=%d\n", __func__, ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -551,25 +653,41 @@ int cnss_get_restart_level(void)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cnss_get_restart_level);
|
EXPORT_SYMBOL(cnss_get_restart_level);
|
||||||
|
|
||||||
static int cnss_sdio_wlan_inserted(
|
static int cnss_sdio_wlan_inserted(struct sdio_func *func,
|
||||||
struct sdio_func *func,
|
const struct sdio_device_id *id)
|
||||||
const struct sdio_device_id *id)
|
|
||||||
{
|
{
|
||||||
|
struct cnss_sdio_info *info;
|
||||||
|
|
||||||
if (!cnss_pdata)
|
if (!cnss_pdata)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
cnss_pdata->cnss_sdio_info.func = func;
|
info = &cnss_pdata->cnss_sdio_info;
|
||||||
cnss_pdata->cnss_sdio_info.id = id;
|
|
||||||
|
info->func = func;
|
||||||
|
info->card = func->card;
|
||||||
|
info->host = func->card->host;
|
||||||
|
info->id = id;
|
||||||
|
info->dev = &func->dev;
|
||||||
|
|
||||||
|
cnss_put_hw_resources(cnss_pdata->cnss_sdio_info.dev);
|
||||||
|
|
||||||
|
pr_info("%s: SDIO Device is Probed\n", __func__);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cnss_sdio_wlan_removed(struct sdio_func *func)
|
static void cnss_sdio_wlan_removed(struct sdio_func *func)
|
||||||
{
|
{
|
||||||
|
struct cnss_sdio_info *info;
|
||||||
|
|
||||||
if (!cnss_pdata)
|
if (!cnss_pdata)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cnss_pdata->cnss_sdio_info.func = NULL;
|
info = &cnss_pdata->cnss_sdio_info;
|
||||||
cnss_pdata->cnss_sdio_info.id = NULL;
|
|
||||||
|
info->host = NULL;
|
||||||
|
info->card = NULL;
|
||||||
|
info->func = NULL;
|
||||||
|
info->id = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_PM)
|
#if defined(CONFIG_PM)
|
||||||
|
@ -577,6 +695,8 @@ static int cnss_sdio_wlan_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct cnss_sdio_wlan_driver *wdrv;
|
struct cnss_sdio_wlan_driver *wdrv;
|
||||||
struct cnss_sdio_bus_bandwidth *bus_bandwidth;
|
struct cnss_sdio_bus_bandwidth *bus_bandwidth;
|
||||||
|
struct sdio_func *func;
|
||||||
|
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
if (!cnss_pdata)
|
if (!cnss_pdata)
|
||||||
|
@ -588,11 +708,13 @@ static int cnss_sdio_wlan_suspend(struct device *dev)
|
||||||
bus_bandwidth->bus_client, CNSS_BUS_WIDTH_NONE);
|
bus_bandwidth->bus_client, CNSS_BUS_WIDTH_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func = cnss_pdata->cnss_sdio_info.func;
|
||||||
wdrv = cnss_pdata->cnss_sdio_info.wdrv;
|
wdrv = cnss_pdata->cnss_sdio_info.wdrv;
|
||||||
if (!wdrv) {
|
if (!wdrv) {
|
||||||
/* This can happen when no wlan driver loaded (no register to
|
/* This can happen when no wlan driver loaded (no register to
|
||||||
* platform driver).
|
* platform driver).
|
||||||
*/
|
*/
|
||||||
|
sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
|
||||||
pr_debug("wlan driver not registered\n");
|
pr_debug("wlan driver not registered\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -692,29 +814,49 @@ EXPORT_SYMBOL(cnss_sdio_configure_spdt);
|
||||||
int cnss_sdio_wlan_register_driver(struct cnss_sdio_wlan_driver *driver)
|
int cnss_sdio_wlan_register_driver(struct cnss_sdio_wlan_driver *driver)
|
||||||
{
|
{
|
||||||
struct cnss_sdio_info *cnss_info;
|
struct cnss_sdio_info *cnss_info;
|
||||||
int error = 0;
|
struct device *dev;
|
||||||
|
int error = -EINVAL;
|
||||||
|
|
||||||
if (!cnss_pdata)
|
if (!cnss_pdata)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
cnss_info = &cnss_pdata->cnss_sdio_info;
|
cnss_info = &cnss_pdata->cnss_sdio_info;
|
||||||
|
dev = cnss_info->dev;
|
||||||
|
|
||||||
if (cnss_info->wdrv)
|
if (cnss_info->wdrv)
|
||||||
pr_debug("%s:wdrv already exists wdrv(%p)\n", __func__,
|
pr_debug("%s:wdrv already exists wdrv(%p)\n", __func__,
|
||||||
cnss_info->wdrv);
|
cnss_info->wdrv);
|
||||||
|
|
||||||
|
cnss_info->wdrv = driver;
|
||||||
|
|
||||||
|
if (!driver)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
error = cnss_get_hw_resources(dev);
|
||||||
|
if (error) {
|
||||||
|
pr_err("%s: Failed to restore power err:%d\n", __func__, error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
error = cnss_set_pinctrl_state(cnss_pdata, PINCTRL_ACTIVE);
|
error = cnss_set_pinctrl_state(cnss_pdata, PINCTRL_ACTIVE);
|
||||||
if (error) {
|
if (error) {
|
||||||
pr_err("%s: Fail to set pinctrl to active state\n", __func__);
|
pr_err("%s: Fail to set pinctrl to active state\n", __func__);
|
||||||
return -EFAULT;
|
goto put_hw;
|
||||||
}
|
}
|
||||||
|
|
||||||
cnss_info->wdrv = driver;
|
error = driver->probe ? driver->probe(cnss_info->func,
|
||||||
if (driver->probe) {
|
cnss_info->id) : error;
|
||||||
error = driver->probe(cnss_info->func, cnss_info->id);
|
if (error) {
|
||||||
if (error)
|
pr_err("%s: wlan probe failed error=%d\n", __func__, error);
|
||||||
pr_err("%s: wlan probe failed error=%d\n", __func__,
|
goto pinctrl_sleep;
|
||||||
error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
|
||||||
|
pinctrl_sleep:
|
||||||
|
cnss_set_pinctrl_state(cnss_pdata, PINCTRL_SLEEP);
|
||||||
|
put_hw:
|
||||||
|
cnss_put_hw_resources(dev);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cnss_sdio_wlan_register_driver);
|
EXPORT_SYMBOL(cnss_sdio_wlan_register_driver);
|
||||||
|
@ -746,10 +888,17 @@ cnss_sdio_wlan_unregister_driver(struct cnss_sdio_wlan_driver *driver)
|
||||||
pr_err("%s: driver not registered\n", __func__);
|
pr_err("%s: driver not registered\n", __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cnss_info->wdrv->remove)
|
|
||||||
cnss_info->wdrv->remove(cnss_info->func);
|
if (!driver)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!driver->remove)
|
||||||
|
return;
|
||||||
|
|
||||||
|
driver->remove(cnss_info->func);
|
||||||
cnss_info->wdrv = NULL;
|
cnss_info->wdrv = NULL;
|
||||||
cnss_set_pinctrl_state(cnss_pdata, PINCTRL_SLEEP);
|
cnss_set_pinctrl_state(cnss_pdata, PINCTRL_SLEEP);
|
||||||
|
cnss_put_hw_resources(cnss_info->dev);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cnss_sdio_wlan_unregister_driver);
|
EXPORT_SYMBOL(cnss_sdio_wlan_unregister_driver);
|
||||||
|
|
||||||
|
@ -1051,6 +1200,8 @@ static int cnss_sdio_init_bus_bandwidth(void)
|
||||||
static int cnss_sdio_probe(struct platform_device *pdev)
|
static int cnss_sdio_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct cnss_sdio_info *info;
|
||||||
|
|
||||||
if (pdev->dev.of_node) {
|
if (pdev->dev.of_node) {
|
||||||
cnss_pdata = devm_kzalloc(
|
cnss_pdata = devm_kzalloc(
|
||||||
|
@ -1065,6 +1216,7 @@ static int cnss_sdio_probe(struct platform_device *pdev)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
cnss_pdata->pdev = pdev;
|
cnss_pdata->pdev = pdev;
|
||||||
|
info = &cnss_pdata->cnss_sdio_info;
|
||||||
|
|
||||||
error = cnss_sdio_pinctrl_init(cnss_pdata, pdev);
|
error = cnss_sdio_pinctrl_init(cnss_pdata, pdev);
|
||||||
if (error) {
|
if (error) {
|
||||||
|
@ -1103,6 +1255,9 @@ static int cnss_sdio_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info->skip_wlan_en_toggle = of_property_read_bool(dev->of_node,
|
||||||
|
"qcom,skip-wlan-en-toggle");
|
||||||
|
|
||||||
error = cnss_sdio_wlan_init();
|
error = cnss_sdio_wlan_init();
|
||||||
if (error) {
|
if (error) {
|
||||||
dev_err(&pdev->dev, "cnss wlan init failed error=%d\n", error);
|
dev_err(&pdev->dev, "cnss wlan init failed error=%d\n", error);
|
||||||
|
@ -1152,15 +1307,20 @@ err_wlan_enable_regulator:
|
||||||
|
|
||||||
static int cnss_sdio_remove(struct platform_device *pdev)
|
static int cnss_sdio_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
struct cnss_sdio_info *info;
|
||||||
|
|
||||||
if (!cnss_pdata)
|
if (!cnss_pdata)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
info = &cnss_pdata->cnss_sdio_info;
|
||||||
|
|
||||||
cnss_sdio_deinit_bus_bandwidth();
|
cnss_sdio_deinit_bus_bandwidth();
|
||||||
cnss_sdio_wlan_exit();
|
cnss_sdio_wlan_exit();
|
||||||
cnss_subsys_exit();
|
cnss_subsys_exit();
|
||||||
cnss_ramdump_cleanup();
|
cnss_ramdump_cleanup();
|
||||||
|
cnss_put_hw_resources(info->dev);
|
||||||
cnss_sdio_release_resource();
|
cnss_sdio_release_resource();
|
||||||
|
cnss_pdata = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue