diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/cnss/cnss_sdio.c | 145 |
1 files changed, 142 insertions, 3 deletions
diff --git a/drivers/net/wireless/cnss/cnss_sdio.c b/drivers/net/wireless/cnss/cnss_sdio.c index f9402e7a165f..8510699b2702 100644 --- a/drivers/net/wireless/cnss/cnss_sdio.c +++ b/drivers/net/wireless/cnss/cnss_sdio.c @@ -29,6 +29,8 @@ #include <net/cnss.h> #include <net/cnss_common.h> #include <linux/pm_qos.h> +#include <linux/msm-bus.h> +#include <linux/msm-bus-board.h> #define WLAN_VREG_NAME "vdd-wlan" #define WLAN_VREG_DSRC_NAME "vdd-wlan-dsrc" @@ -83,6 +85,12 @@ struct cnss_wlan_pinctrl_info { struct pinctrl_state *active; }; +struct cnss_sdio_bus_bandwidth { + struct msm_bus_scale_pdata *bus_scale_table; + u32 bus_client; + int current_bandwidth_vote; +}; + static struct cnss_sdio_data { struct cnss_sdio_regulator regulator; struct platform_device *pdev; @@ -90,6 +98,7 @@ static struct cnss_sdio_data { struct cnss_ssr_info ssr_info; struct pm_qos_request qos_request; struct cnss_wlan_pinctrl_info pinctrl_info; + struct cnss_sdio_bus_bandwidth bus_bandwidth; } *cnss_pdata; #define WLAN_RECOVERY_DELAY 1 @@ -150,7 +159,37 @@ EXPORT_SYMBOL(cnss_sdio_request_pm_qos_type); int cnss_sdio_request_bus_bandwidth(int bandwidth) { - return 0; + int ret; + struct cnss_sdio_bus_bandwidth *bus_bandwidth; + + if (!cnss_pdata) + return -ENODEV; + + bus_bandwidth = &cnss_pdata->bus_bandwidth; + if (!bus_bandwidth->bus_client) + return -ENODEV; + + switch (bandwidth) { + case CNSS_BUS_WIDTH_NONE: + case CNSS_BUS_WIDTH_LOW: + case CNSS_BUS_WIDTH_MEDIUM: + case CNSS_BUS_WIDTH_HIGH: + ret = msm_bus_scale_client_update_request( + bus_bandwidth->bus_client, bandwidth); + if (!ret) { + bus_bandwidth->current_bandwidth_vote = bandwidth; + } else { + pr_debug( + "%s: could not set bus bandwidth %d, ret = %d\n", + __func__, bandwidth, ret); + } + break; + default: + pr_debug("%s: Invalid request %d", __func__, bandwidth); + ret = -EINVAL; + } + + return ret; } void cnss_sdio_request_pm_qos(u32 qos_val) @@ -177,7 +216,37 @@ EXPORT_SYMBOL(cnss_sdio_remove_pm_qos); int cnss_request_bus_bandwidth(int bandwidth) { - return 0; + int ret; + struct cnss_sdio_bus_bandwidth *bus_bandwidth; + + if (!cnss_pdata) + return -ENODEV; + + bus_bandwidth = &cnss_pdata->bus_bandwidth; + if (!bus_bandwidth->bus_client) + return -ENODEV; + + switch (bandwidth) { + case CNSS_BUS_WIDTH_NONE: + case CNSS_BUS_WIDTH_LOW: + case CNSS_BUS_WIDTH_MEDIUM: + case CNSS_BUS_WIDTH_HIGH: + ret = msm_bus_scale_client_update_request( + bus_bandwidth->bus_client, bandwidth); + if (!ret) { + bus_bandwidth->current_bandwidth_vote = bandwidth; + } else { + pr_debug( + "%s: could not set bus bandwidth %d, ret = %d\n", + __func__, bandwidth, ret); + } + break; + default: + pr_debug("%s: Invalid request %d", __func__, bandwidth); + ret = -EINVAL; + } + + return ret; } EXPORT_SYMBOL(cnss_request_bus_bandwidth); @@ -616,11 +685,18 @@ static void cnss_sdio_wlan_removed(struct sdio_func *func) static int cnss_sdio_wlan_suspend(struct device *dev) { struct cnss_sdio_wlan_driver *wdrv; + struct cnss_sdio_bus_bandwidth *bus_bandwidth; int error = 0; if (!cnss_pdata) return -ENODEV; + bus_bandwidth = &cnss_pdata->bus_bandwidth; + if (bus_bandwidth->bus_client) { + msm_bus_scale_client_update_request( + bus_bandwidth->bus_client, CNSS_BUS_WIDTH_NONE); + } + wdrv = cnss_pdata->cnss_sdio_info.wdrv; if (!wdrv) { /* This can happen when no wlan driver loaded (no register to @@ -641,11 +717,19 @@ static int cnss_sdio_wlan_suspend(struct device *dev) static int cnss_sdio_wlan_resume(struct device *dev) { struct cnss_sdio_wlan_driver *wdrv; + struct cnss_sdio_bus_bandwidth *bus_bandwidth; int error = 0; if (!cnss_pdata) return -ENODEV; + bus_bandwidth = &cnss_pdata->bus_bandwidth; + if (bus_bandwidth->bus_client) { + msm_bus_scale_client_update_request( + bus_bandwidth->bus_client, + bus_bandwidth->current_bandwidth_vote); + } + wdrv = cnss_pdata->cnss_sdio_info.wdrv; if (!wdrv) { /* This can happen when no wlan driver loaded (no register to @@ -746,10 +830,17 @@ void cnss_sdio_wlan_unregister_driver(struct cnss_sdio_wlan_driver *driver) { struct cnss_sdio_info *cnss_info; + struct cnss_sdio_bus_bandwidth *bus_bandwidth; if (!cnss_pdata) return; + bus_bandwidth = &cnss_pdata->bus_bandwidth; + if (bus_bandwidth->bus_client) { + msm_bus_scale_client_update_request( + bus_bandwidth->bus_client, CNSS_BUS_WIDTH_NONE); + } + cnss_info = &cnss_pdata->cnss_sdio_info; if (!cnss_info->wdrv) { pr_err("%s: driver not registered\n", __func__); @@ -827,6 +918,18 @@ static void cnss_sdio_wlan_exit(void) sdio_unregister_driver(&cnss_ar6k_driver); } +static void cnss_sdio_deinit_bus_bandwidth(void) +{ + struct cnss_sdio_bus_bandwidth *bus_bandwidth; + + bus_bandwidth = &cnss_pdata->bus_bandwidth; + if (bus_bandwidth->bus_client) { + msm_bus_scale_client_update_request( + bus_bandwidth->bus_client, CNSS_BUS_WIDTH_NONE); + msm_bus_scale_unregister_client(bus_bandwidth->bus_client); + } +} + static int cnss_sdio_configure_wlan_enable_regulator(void) { int error; @@ -1022,6 +1125,29 @@ release_pinctrl: return ret; } +static int cnss_sdio_init_bus_bandwidth(void) +{ + int ret = 0; + struct cnss_sdio_bus_bandwidth *bus_bandwidth; + struct device *dev = &cnss_pdata->pdev->dev; + + bus_bandwidth = &cnss_pdata->bus_bandwidth; + bus_bandwidth->bus_scale_table = msm_bus_cl_get_pdata(cnss_pdata->pdev); + if (!bus_bandwidth->bus_scale_table) { + dev_err(dev, "Failed to get the bus scale platform data\n"); + ret = -EINVAL; + } + + bus_bandwidth->bus_client = msm_bus_scale_register_client( + bus_bandwidth->bus_scale_table); + if (!bus_bandwidth->bus_client) { + dev_err(dev, "Failed to register with bus_scale client\n"); + ret = -EINVAL; + } + + return ret; +} + static int cnss_sdio_probe(struct platform_device *pdev) { int error; @@ -1097,8 +1223,20 @@ static int cnss_sdio_probe(struct platform_device *pdev) goto err_subsys_init; } + if (of_property_read_bool( + pdev->dev.of_node, "qcom,cnss-enable-bus-bandwidth")) { + error = cnss_sdio_init_bus_bandwidth(); + if (error) { + dev_err(&pdev->dev, "Failed to init bus bandwidth\n"); + goto err_bus_bandwidth_init; + } + } + dev_info(&pdev->dev, "CNSS SDIO Driver registered"); return 0; + +err_bus_bandwidth_init: + cnss_subsys_exit(); err_subsys_init: cnss_ramdump_cleanup(); err_ramdump_create: @@ -1117,11 +1255,12 @@ static int cnss_sdio_remove(struct platform_device *pdev) if (!cnss_pdata) return -ENODEV; + cnss_sdio_deinit_bus_bandwidth(); cnss_sdio_wlan_exit(); - cnss_subsys_exit(); cnss_ramdump_cleanup(); cnss_sdio_release_resource(); + return 0; } |