summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/cnss/cnss_sdio.c145
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;
}