Net: CNSS_SDIO: add sdio wlan driver registration
Move sdio wlan func driver interface(includes Suspend and Resume)registration from wlan cld driver to cnss_sdio driver. wlan cld driver provides callback functions to cnss_sdio driver by cnss_sdio_wlan_register_driver API. CRs-Fixed: 944931 Change-Id: If9cec25024c5840e043fc652a7f0c7df4d83f4e9 Signed-off-by: Liangwei Dong <liangwei@codeaurora.org>
This commit is contained in:
parent
1b10409872
commit
fa7db29c1f
2 changed files with 258 additions and 8 deletions
|
@ -19,6 +19,9 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include <linux/mmc/sdio_ids.h>
|
||||
#include <net/cnss.h>
|
||||
|
||||
#define WLAN_VREG_NAME "vdd-wlan"
|
||||
#define WLAN_VREG_DSRC_NAME "vdd-wlan-dsrc"
|
||||
|
@ -31,8 +34,6 @@
|
|||
#define WLAN_VREG_XTAL_MIN 1800000
|
||||
#define POWER_ON_DELAY 4
|
||||
|
||||
#define CNSS_MAX_CH_NUM 100
|
||||
|
||||
struct cnss_unsafe_channel_list {
|
||||
u16 unsafe_ch_count;
|
||||
u16 unsafe_ch_list[CNSS_MAX_CH_NUM];
|
||||
|
@ -50,13 +51,62 @@ struct cnss_sdio_regulator {
|
|||
struct regulator *wlan_vreg_dsrc;
|
||||
};
|
||||
|
||||
struct cnss_sdio_info {
|
||||
struct cnss_sdio_wlan_driver *wdrv;
|
||||
struct sdio_func *func;
|
||||
const struct sdio_device_id *id;
|
||||
};
|
||||
|
||||
static struct cnss_sdio_data {
|
||||
struct cnss_sdio_regulator regulator;
|
||||
struct platform_device *pdev;
|
||||
struct cnss_dfs_nol_info dfs_info;
|
||||
struct cnss_unsafe_channel_list unsafe_list;
|
||||
struct cnss_sdio_info cnss_sdio_info;
|
||||
} *cnss_pdata;
|
||||
|
||||
/* SDIO manufacturer ID and Codes */
|
||||
#define MANUFACTURER_ID_AR6320_BASE 0x500
|
||||
#define MANUFACTURER_ID_QCA9377_BASE 0x700
|
||||
#define MANUFACTURER_CODE 0x271
|
||||
|
||||
static const struct sdio_device_id ar6k_id_table[] = {
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x0))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x1))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x2))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x3))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x4))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x5))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x6))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x7))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x8))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x9))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xA))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xB))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xC))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xD))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xE))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xF))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x0))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x1))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x2))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x3))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x4))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x5))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x6))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x7))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x8))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x9))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xA))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xB))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xC))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xD))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xE))},
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xF))},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(sdio, ar6k_id_table);
|
||||
|
||||
int cnss_set_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 ch_count)
|
||||
{
|
||||
struct cnss_unsafe_channel_list *unsafe_list;
|
||||
|
@ -103,7 +153,7 @@ int cnss_get_wlan_unsafe_channel(
|
|||
}
|
||||
EXPORT_SYMBOL(cnss_get_wlan_unsafe_channel);
|
||||
|
||||
int cnss_wlan_set_dfs_nol(void *info, u16 info_len)
|
||||
int cnss_wlan_set_dfs_nol(const void *info, u16 info_len)
|
||||
{
|
||||
void *temp;
|
||||
struct cnss_dfs_nol_info *dfs_info;
|
||||
|
@ -153,6 +203,176 @@ int cnss_wlan_get_dfs_nol(void *info, u16 info_len)
|
|||
}
|
||||
EXPORT_SYMBOL(cnss_wlan_get_dfs_nol);
|
||||
|
||||
static int cnss_sdio_wlan_inserted(
|
||||
struct sdio_func *func,
|
||||
const struct sdio_device_id *id)
|
||||
{
|
||||
if (!cnss_pdata)
|
||||
return -ENODEV;
|
||||
|
||||
cnss_pdata->cnss_sdio_info.func = func;
|
||||
cnss_pdata->cnss_sdio_info.id = id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cnss_sdio_wlan_removed(struct sdio_func *func)
|
||||
{
|
||||
if (!cnss_pdata)
|
||||
return;
|
||||
|
||||
cnss_pdata->cnss_sdio_info.func = NULL;
|
||||
cnss_pdata->cnss_sdio_info.id = NULL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PM)
|
||||
static int cnss_sdio_wlan_suspend(struct device *dev)
|
||||
{
|
||||
struct cnss_sdio_wlan_driver *wdrv;
|
||||
int error = 0;
|
||||
|
||||
if (!cnss_pdata)
|
||||
return -ENODEV;
|
||||
|
||||
wdrv = cnss_pdata->cnss_sdio_info.wdrv;
|
||||
if (!wdrv) {
|
||||
/* This can happen when no wlan driver loaded (no register to
|
||||
* platform driver).
|
||||
*/
|
||||
pr_debug("wlan driver not registered\n");
|
||||
return 0;
|
||||
}
|
||||
if (wdrv->suspend) {
|
||||
error = wdrv->suspend(dev);
|
||||
if (error)
|
||||
pr_err("wlan suspend failed error=%d\n", error);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int cnss_sdio_wlan_resume(struct device *dev)
|
||||
{
|
||||
struct cnss_sdio_wlan_driver *wdrv;
|
||||
int error = 0;
|
||||
|
||||
if (!cnss_pdata)
|
||||
return -ENODEV;
|
||||
|
||||
wdrv = cnss_pdata->cnss_sdio_info.wdrv;
|
||||
if (!wdrv) {
|
||||
/* This can happen when no wlan driver loaded (no register to
|
||||
* platform driver).
|
||||
*/
|
||||
pr_debug("wlan driver not registered\n");
|
||||
return 0;
|
||||
}
|
||||
if (wdrv->resume) {
|
||||
error = wdrv->resume(dev);
|
||||
if (error)
|
||||
pr_err("wlan resume failed error=%d\n", error);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PM)
|
||||
static const struct dev_pm_ops cnss_ar6k_device_pm_ops = {
|
||||
.suspend = cnss_sdio_wlan_suspend,
|
||||
.resume = cnss_sdio_wlan_resume,
|
||||
};
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static const struct sdio_driver cnss_ar6k_driver = {
|
||||
.name = "cnss_ar6k_wlan",
|
||||
.id_table = ar6k_id_table,
|
||||
.probe = cnss_sdio_wlan_inserted,
|
||||
.remove = cnss_sdio_wlan_removed,
|
||||
#if defined(CONFIG_PM)
|
||||
.drv = {
|
||||
.pm = &cnss_ar6k_device_pm_ops,
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* cnss_sdio_wlan_register_driver() - cnss wlan register API
|
||||
* @driver: sdio wlan driver interface from wlan driver.
|
||||
*
|
||||
* wlan sdio function driver uses this API to register callback
|
||||
* functions to cnss_sido platform driver. The callback will
|
||||
* be invoked by corresponding wrapper function of this cnss
|
||||
* platform driver.
|
||||
*/
|
||||
int cnss_sdio_wlan_register_driver(struct cnss_sdio_wlan_driver *driver)
|
||||
{
|
||||
struct cnss_sdio_info *cnss_info;
|
||||
int error = 0;
|
||||
|
||||
if (!cnss_pdata)
|
||||
return -ENODEV;
|
||||
|
||||
cnss_info = &cnss_pdata->cnss_sdio_info;
|
||||
if (cnss_info->wdrv)
|
||||
pr_debug("%s:wdrv already exists wdrv(%p)\n", __func__,
|
||||
cnss_info->wdrv);
|
||||
|
||||
cnss_info->wdrv = driver;
|
||||
if (driver->probe) {
|
||||
error = driver->probe(cnss_info->func, cnss_info->id);
|
||||
if (error)
|
||||
pr_err("%s: wlan probe failed error=%d\n", __func__,
|
||||
error);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_sdio_wlan_register_driver);
|
||||
|
||||
/**
|
||||
* cnss_sdio_wlan_unregister_driver() - cnss wlan unregister API
|
||||
* @driver: sdio wlan driver interface from wlan driver.
|
||||
*
|
||||
* wlan sdio function driver uses this API to detach it from cnss_sido
|
||||
* platform driver.
|
||||
*/
|
||||
void
|
||||
cnss_sdio_wlan_unregister_driver(struct cnss_sdio_wlan_driver *driver)
|
||||
{
|
||||
struct cnss_sdio_info *cnss_info;
|
||||
|
||||
if (!cnss_pdata)
|
||||
return;
|
||||
|
||||
cnss_info = &cnss_pdata->cnss_sdio_info;
|
||||
if (!cnss_info->wdrv) {
|
||||
pr_err("%s: driver not registered\n", __func__);
|
||||
return;
|
||||
}
|
||||
if (cnss_info->wdrv->remove)
|
||||
cnss_info->wdrv->remove(cnss_info->func);
|
||||
cnss_info->wdrv = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_sdio_wlan_unregister_driver);
|
||||
|
||||
static int cnss_sdio_wlan_init(void)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
error = sdio_register_driver(&cnss_ar6k_driver);
|
||||
if (error)
|
||||
pr_err("%s: registered fail error=%d\n", __func__, error);
|
||||
else
|
||||
pr_debug("%s: registered succ\n", __func__);
|
||||
return error;
|
||||
}
|
||||
|
||||
static void cnss_sdio_wlan_exit(void)
|
||||
{
|
||||
if (!cnss_pdata)
|
||||
return;
|
||||
|
||||
sdio_unregister_driver(&cnss_ar6k_driver);
|
||||
}
|
||||
|
||||
static int cnss_sdio_configure_wlan_enable_regulator(void)
|
||||
{
|
||||
int error;
|
||||
|
@ -318,7 +538,8 @@ static int cnss_sdio_probe(struct platform_device *pdev)
|
|||
cnss_pdata->pdev = pdev;
|
||||
error = cnss_sdio_configure_regulator();
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "Failed to config voltage regulator\n");
|
||||
dev_err(&pdev->dev, "Failed to configure voltage regulator error=%d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -328,7 +549,8 @@ static int cnss_sdio_probe(struct platform_device *pdev)
|
|||
error = cnss_sdio_configure_wlan_enable_regulator();
|
||||
if (error) {
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to enable wlan enable regulator\n");
|
||||
"Failed to enable wlan enable regulator error=%d\n",
|
||||
error);
|
||||
goto err_wlan_enable_regulator;
|
||||
}
|
||||
}
|
||||
|
@ -344,6 +566,12 @@ static int cnss_sdio_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
error = cnss_sdio_wlan_init();
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "cnss wlan init failed error=%d\n", error);
|
||||
goto err_wlan_dsrc_enable_regulator;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "CNSS SDIO Driver registered");
|
||||
return 0;
|
||||
|
||||
|
@ -352,6 +580,7 @@ err_wlan_dsrc_enable_regulator:
|
|||
err_wlan_enable_regulator:
|
||||
regulator_put(cnss_pdata->regulator.wlan_xtal);
|
||||
regulator_put(cnss_pdata->regulator.wlan_io);
|
||||
cnss_pdata = NULL;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -362,6 +591,8 @@ static int cnss_sdio_remove(struct platform_device *pdev)
|
|||
if (!cnss_pdata)
|
||||
return -ENODEV;
|
||||
|
||||
cnss_sdio_wlan_exit();
|
||||
|
||||
dfs_info = &cnss_pdata->dfs_info;
|
||||
kfree(dfs_info->dfs_nol_info);
|
||||
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/pci.h>
|
||||
#ifdef CONFIG_CNSS_SDIO
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CNSS
|
||||
/* max 20mhz channel count */
|
||||
#define CNSS_MAX_CH_NUM 45
|
||||
|
||||
#define CNSS_MAX_FILE_NAME 20
|
||||
|
||||
#define MAX_FIRMWARE_SIZE (1 * 1024 * 1024)
|
||||
|
@ -165,6 +165,9 @@ extern int cnss_is_auto_suspend_allowed(const char *caller_func);
|
|||
extern int cnss_pm_runtime_request(struct device *dev, enum
|
||||
cnss_runtime_request request);
|
||||
#endif
|
||||
/* max 20mhz channel count */
|
||||
#define CNSS_MAX_CH_NUM 45
|
||||
|
||||
extern void cnss_init_work(struct work_struct *work, work_func_t func);
|
||||
extern void cnss_flush_work(void *work);
|
||||
extern void cnss_flush_delayed_work(void *dwork);
|
||||
|
@ -185,4 +188,20 @@ extern int cnss_get_wlan_unsafe_channel(u16 *unsafe_ch_list,
|
|||
u16 *ch_count, u16 buf_len);
|
||||
extern int cnss_wlan_set_dfs_nol(const void *info, u16 info_len);
|
||||
extern int cnss_wlan_get_dfs_nol(void *info, u16 info_len);
|
||||
|
||||
#ifdef CONFIG_CNSS_SDIO
|
||||
struct cnss_sdio_wlan_driver {
|
||||
const char *name;
|
||||
const struct sdio_device_id *id_table;
|
||||
int (*probe)(struct sdio_func *, const struct sdio_device_id *);
|
||||
void (*remove)(struct sdio_func *);
|
||||
int (*suspend)(struct device *);
|
||||
int (*resume)(struct device *);
|
||||
};
|
||||
|
||||
extern int cnss_sdio_wlan_register_driver(
|
||||
struct cnss_sdio_wlan_driver *driver);
|
||||
extern void cnss_sdio_wlan_unregister_driver(
|
||||
struct cnss_sdio_wlan_driver *driver);
|
||||
#endif
|
||||
#endif /* _NET_CNSS_H_ */
|
||||
|
|
Loading…
Add table
Reference in a new issue