summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt3
-rw-r--r--drivers/net/wireless/wcnss/wcnss_vreg.c177
-rw-r--r--drivers/net/wireless/wcnss/wcnss_wlan.c149
-rw-r--r--include/linux/wcnss_wlan.h3
4 files changed, 176 insertions, 156 deletions
diff --git a/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt b/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
index 77d6bf06ee26..d0855115b6d1 100644
--- a/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
+++ b/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
@@ -64,8 +64,6 @@ support for pronto hardware.
to use for VBATT feature.
- qcom,has-a2xb-split-reg: boolean flag to determine A2xb split timeout limit
register is available or not.
-- qcom,wcn-external-gpio-support: boolean flag to determine 3.3v gpio support
-for pronto hardware for a target.
Example:
@@ -87,7 +85,6 @@ Example:
gpios = <&msmgpio 36 0>, <&msmgpio 37 0>, <&msmgpio 38 0>,
<&msmgpio 39 0>, <&msmgpio 40 0>;
- qcom,wcn-external-gpio-support;
qcom,has-48mhz-xo;
qcom,is-pronto-vt;
qcom,wlan-rx-buff-count = <512>;
diff --git a/drivers/net/wireless/wcnss/wcnss_vreg.c b/drivers/net/wireless/wcnss/wcnss_vreg.c
index d0a74744f70a..d94bd90f64da 100644
--- a/drivers/net/wireless/wcnss/wcnss_vreg.c
+++ b/drivers/net/wireless/wcnss/wcnss_vreg.c
@@ -71,23 +71,33 @@ static int is_power_on;
struct vregs_info {
const char * const name;
+ const char * const curr;
+ const char * const volt;
int state;
+ bool required;
struct regulator *regulator;
};
/* IRIS regulators for Pronto hardware */
-static struct vregs_info iris_vregs_pronto[] = {
- {"qcom,iris-vddxo", VREG_NULL_CONFIG, NULL},
- {"qcom,iris-vddrfa", VREG_NULL_CONFIG, NULL},
- {"qcom,iris-vddpa", VREG_NULL_CONFIG, NULL},
- {"qcom,iris-vdddig", VREG_NULL_CONFIG, NULL},
+static struct vregs_info iris_vregs[] = {
+ {"qcom,iris-vddxo", "qcom,iris-vddxo-current",
+ "qcom,iris-vddxo-voltage-level", VREG_NULL_CONFIG, true, NULL},
+ {"qcom,iris-vddrfa", "qcom,iris-vddrfa-current",
+ "qcom,iris-vddrfa-voltage-level", VREG_NULL_CONFIG, true, NULL},
+ {"qcom,iris-vddpa", "qcom,iris-vddpa-current",
+ "qcom,iris-vddpa-voltage-level", VREG_NULL_CONFIG, false, NULL},
+ {"qcom,iris-vdddig", "qcom,iris-vdddig-current",
+ "qcom,iris-vdddig-voltage-level", VREG_NULL_CONFIG, true, NULL},
};
/* WCNSS regulators for Pronto hardware */
static struct vregs_info pronto_vregs[] = {
- {"qcom,pronto-vddmx", VREG_NULL_CONFIG, NULL},
- {"qcom,pronto-vddcx", VREG_NULL_CONFIG, NULL},
- {"qcom,pronto-vddpx", VREG_NULL_CONFIG, NULL},
+ {"qcom,pronto-vddmx", "qcom,pronto-vddmx-current",
+ "qcom,vddmx-voltage-level", VREG_NULL_CONFIG, true, NULL},
+ {"qcom,pronto-vddcx", "qcom,pronto-vddcx-current",
+ "qcom,vddcx-voltage-level", VREG_NULL_CONFIG, true, NULL},
+ {"qcom,pronto-vddpx", "qcom,pronto-vddpx-current",
+ "qcom,vddpx-voltage-level", VREG_NULL_CONFIG, true, NULL},
};
struct host_driver {
@@ -184,6 +194,129 @@ int validate_iris_chip_id(u32 reg)
}
}
+static void wcnss_free_regulator(void)
+{
+ int vreg_i;
+
+ /* Free pronto voltage regulators from device node */
+ for (vreg_i = 0; vreg_i < PRONTO_REGULATORS; vreg_i++) {
+ if (pronto_vregs[vreg_i].state) {
+ regulator_put(pronto_vregs[vreg_i].regulator);
+ pronto_vregs[vreg_i].state = VREG_NULL_CONFIG;
+ }
+ }
+
+ /* Free IRIS voltage regulators from device node */
+ for (vreg_i = 0; vreg_i < IRIS_REGULATORS; vreg_i++) {
+ if (iris_vregs[vreg_i].state) {
+ regulator_put(iris_vregs[vreg_i].regulator);
+ iris_vregs[vreg_i].state = VREG_NULL_CONFIG;
+ }
+ }
+}
+
+static int
+wcnss_dt_parse_vreg_level(struct device *dev, int index,
+ const char *current_vreg_name, const char *vreg_name,
+ struct vregs_level *vlevel)
+{
+ int ret = 0;
+ /* array used to store nominal, low and high voltage values */
+ u32 voltage_levels[3], current_vreg;
+
+ ret = of_property_read_u32_array(dev->of_node, vreg_name,
+ voltage_levels,
+ ARRAY_SIZE(voltage_levels));
+ if (ret) {
+ dev_err(dev, "error reading %s property\n", vreg_name);
+ return ret;
+ }
+
+ vlevel[index].nominal_min = voltage_levels[0];
+ vlevel[index].low_power_min = voltage_levels[1];
+ vlevel[index].max_voltage = voltage_levels[2];
+
+ ret = of_property_read_u32(dev->of_node, current_vreg_name,
+ &current_vreg);
+ if (ret) {
+ dev_err(dev, "error reading %s property\n", current_vreg_name);
+ return ret;
+ }
+
+ vlevel[index].uA_load = current_vreg;
+
+ return ret;
+}
+
+int
+wcnss_parse_voltage_regulator(struct wcnss_wlan_config *wlan_config,
+ struct device *dev)
+{
+ int rc, vreg_i;
+
+ /* Parse pronto voltage regulators from device node */
+ for (vreg_i = 0; vreg_i < PRONTO_REGULATORS; vreg_i++) {
+ pronto_vregs[vreg_i].regulator =
+ regulator_get(dev, pronto_vregs[vreg_i].name);
+ if (IS_ERR(pronto_vregs[vreg_i].regulator)) {
+ if (pronto_vregs[vreg_i].required) {
+ rc = PTR_ERR(pronto_vregs[vreg_i].regulator);
+ dev_err(dev, "regulator get of %s failed (%d)\n",
+ pronto_vregs[vreg_i].name, rc);
+ goto wcnss_vreg_get_err;
+ } else {
+ dev_dbg(dev, "Skip optional regulator configuration: %s\n",
+ pronto_vregs[vreg_i].name);
+ continue;
+ }
+ }
+
+ pronto_vregs[vreg_i].state |= VREG_GET_REGULATOR_MASK;
+ rc = wcnss_dt_parse_vreg_level(dev, vreg_i,
+ pronto_vregs[vreg_i].curr,
+ pronto_vregs[vreg_i].volt,
+ wlan_config->pronto_vlevel);
+ if (rc) {
+ dev_err(dev, "error reading voltage-level property\n");
+ goto wcnss_vreg_get_err;
+ }
+ }
+
+ /* Parse iris voltage regulators from device node */
+ for (vreg_i = 0; vreg_i < IRIS_REGULATORS; vreg_i++) {
+ iris_vregs[vreg_i].regulator =
+ regulator_get(dev, iris_vregs[vreg_i].name);
+ if (IS_ERR(iris_vregs[vreg_i].regulator)) {
+ if (iris_vregs[vreg_i].required) {
+ rc = PTR_ERR(iris_vregs[vreg_i].regulator);
+ dev_err(dev, "regulator get of %s failed (%d)\n",
+ iris_vregs[vreg_i].name, rc);
+ goto wcnss_vreg_get_err;
+ } else {
+ dev_dbg(dev, "Skip optional regulator configuration: %s\n",
+ iris_vregs[vreg_i].name);
+ continue;
+ }
+ }
+
+ iris_vregs[vreg_i].state |= VREG_GET_REGULATOR_MASK;
+ rc = wcnss_dt_parse_vreg_level(dev, vreg_i,
+ iris_vregs[vreg_i].curr,
+ iris_vregs[vreg_i].volt,
+ wlan_config->iris_vlevel);
+ if (rc) {
+ dev_err(dev, "error reading voltage-level property\n");
+ goto wcnss_vreg_get_err;
+ }
+ }
+
+ return 0;
+
+wcnss_vreg_get_err:
+ wcnss_free_regulator();
+ return rc;
+}
+
void wcnss_iris_reset(u32 reg, void __iomem *pmu_conf_reg)
{
/* Reset IRIS */
@@ -417,11 +550,6 @@ static void wcnss_vregs_off(struct vregs_info regulators[], uint size,
if (regulators[i].state == VREG_NULL_CONFIG)
continue;
- if (cfg->wcn_external_gpio_support) {
- if (!memcmp(regulators[i].name, VDD_PA, sizeof(VDD_PA)))
- continue;
- }
-
/* Remove PWM mode */
if (regulators[i].state & VREG_OPTIMUM_MODE_MASK) {
rc = regulator_set_load(regulators[i].regulator, 0);
@@ -483,23 +611,10 @@ static int wcnss_vregs_on(struct device *dev,
}
for (i = 0; i < size; i++) {
- if (cfg->wcn_external_gpio_support) {
- if (!memcmp(regulators[i].name, VDD_PA, sizeof(VDD_PA)))
- continue;
- }
+ if (regulators[i].state == VREG_NULL_CONFIG)
+ continue;
- /* Get regulator source */
- regulators[i].regulator =
- regulator_get(dev, regulators[i].name);
- if (IS_ERR(regulators[i].regulator)) {
- rc = PTR_ERR(regulators[i].regulator);
- pr_err("regulator get of %s failed (%d)\n",
- regulators[i].name, rc);
- goto fail;
- }
- regulators[i].state |= VREG_GET_REGULATOR_MASK;
reg_cnt = regulator_count_voltages(regulators[i].regulator);
-
/* Set voltage to nominal. Exclude swtiches e.g. LVS */
if ((voltage_level[i].nominal_min ||
voltage_level[i].max_voltage) && (reg_cnt > 0)) {
@@ -561,8 +676,7 @@ static void wcnss_iris_vregs_off(enum wcnss_hw_type hw_type,
{
switch (hw_type) {
case WCNSS_PRONTO_HW:
- wcnss_vregs_off(iris_vregs_pronto,
- ARRAY_SIZE(iris_vregs_pronto),
+ wcnss_vregs_off(iris_vregs, ARRAY_SIZE(iris_vregs),
cfg->iris_vlevel);
break;
default:
@@ -579,8 +693,7 @@ static int wcnss_iris_vregs_on(struct device *dev,
switch (hw_type) {
case WCNSS_PRONTO_HW:
- ret = wcnss_vregs_on(dev, iris_vregs_pronto,
- ARRAY_SIZE(iris_vregs_pronto),
+ ret = wcnss_vregs_on(dev, iris_vregs, ARRAY_SIZE(iris_vregs),
cfg->iris_vlevel);
break;
default:
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index ed56943733de..b604f61e1a05 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -64,6 +64,21 @@
#define WCNSS_CONFIG_UNSPECIFIED (-1)
#define UINT32_MAX (0xFFFFFFFFU)
+#define SUBSYS_NOTIF_MIN_INDEX 0
+#define SUBSYS_NOTIF_MAX_INDEX 9
+char *wcnss_subsys_notif_type[] = {
+ "SUBSYS_BEFORE_SHUTDOWN",
+ "SUBSYS_AFTER_SHUTDOWN",
+ "SUBSYS_BEFORE_POWERUP",
+ "SUBSYS_AFTER_POWERUP",
+ "SUBSYS_RAMDUMP_NOTIFICATION",
+ "SUBSYS_POWERUP_FAILURE",
+ "SUBSYS_PROXY_VOTE",
+ "SUBSYS_PROXY_UNVOTE",
+ "SUBSYS_SOC_RESET",
+ "SUBSYS_NOTIF_TYPE_COUNT"
+};
+
static int has_48mhz_xo = WCNSS_CONFIG_UNSPECIFIED;
module_param(has_48mhz_xo, int, S_IWUSR | S_IRUGO);
MODULE_PARM_DESC(has_48mhz_xo, "Is an external 48 MHz XO present");
@@ -2674,50 +2689,15 @@ static struct miscdevice wcnss_usr_ctrl = {
};
static int
-wcnss_dt_parse_vreg_level(struct device *dev, int index,
- const char *current_vreg_name, const char *vreg_name,
- struct vregs_level *vlevel)
-{
- int ret = 0;
- /* array used to store nominal, low and high voltage values
- */
- u32 voltage_levels[3], current_vreg;
-
- ret = of_property_read_u32_array(dev->of_node, vreg_name,
- voltage_levels,
- ARRAY_SIZE(voltage_levels));
- if (ret) {
- dev_err(dev, "error reading %s property\n", vreg_name);
- return ret;
- }
-
- vlevel[index].nominal_min = voltage_levels[0];
- vlevel[index].low_power_min = voltage_levels[1];
- vlevel[index].max_voltage = voltage_levels[2];
-
- ret = of_property_read_u32(dev->of_node, current_vreg_name,
- &current_vreg);
- if (ret) {
- dev_err(dev, "error reading %s property\n", current_vreg_name);
- return ret;
- }
-
- vlevel[index].uA_load = current_vreg;
-
- return ret;
-}
-
-static int
wcnss_trigger_config(struct platform_device *pdev)
{
int ret;
- int rc, index = 0;
+ int rc;
struct qcom_wcnss_opts *pdata;
struct resource *res;
int is_pronto_vadc;
int is_pronto_v3;
int pil_retry = 0;
- struct wcnss_wlan_config *wlan_cfg = &penv->wlan_config;
struct device_node *node = (&pdev->dev)->of_node;
int has_pronto_hw = of_property_read_bool(node, "qcom,has-pronto-hw");
@@ -2729,93 +2709,14 @@ wcnss_trigger_config(struct platform_device *pdev)
penv->is_a2xb_split_reg =
of_property_read_bool(node, "qcom,has-a2xb-split-reg");
- wlan_cfg->wcn_external_gpio_support =
- of_property_read_bool(node, "qcom,wcn-external-gpio-support");
-
if (of_property_read_u32(node, "qcom,wlan-rx-buff-count",
&penv->wlan_rx_buff_count)) {
penv->wlan_rx_buff_count = WCNSS_DEF_WLAN_RX_BUFF_COUNT;
}
- ret = wcnss_dt_parse_vreg_level(&pdev->dev, index,
- "qcom,pronto-vddmx-current",
- "qcom,vddmx-voltage-level",
- penv->wlan_config.pronto_vlevel);
-
- if (ret) {
- dev_err(&pdev->dev, "error reading voltage-level property\n");
- goto fail;
- }
-
- index++;
- ret = wcnss_dt_parse_vreg_level(&pdev->dev, index,
- "qcom,pronto-vddcx-current",
- "qcom,vddcx-voltage-level",
- penv->wlan_config.pronto_vlevel);
-
- if (ret) {
- dev_err(&pdev->dev, "error reading voltage-level property\n");
- goto fail;
- }
-
- index++;
- ret = wcnss_dt_parse_vreg_level(&pdev->dev, index,
- "qcom,pronto-vddpx-current",
- "qcom,vddpx-voltage-level",
- penv->wlan_config.pronto_vlevel);
-
- if (ret) {
- dev_err(&pdev->dev, "error reading voltage-level property\n");
- goto fail;
- }
-
- /* assign 0 to index now onwards, index variable re used to
- * represent iris regulator index
- */
- index = 0;
- ret = wcnss_dt_parse_vreg_level(&pdev->dev, index,
- "qcom,iris-vddxo-current",
- "qcom,iris-vddxo-voltage-level",
- penv->wlan_config.iris_vlevel);
-
- if (ret) {
- dev_err(&pdev->dev, "error reading voltage-level property\n");
- goto fail;
- }
-
- index++;
- ret = wcnss_dt_parse_vreg_level(&pdev->dev, index,
- "qcom,iris-vddrfa-current",
- "qcom,iris-vddrfa-voltage-level",
- penv->wlan_config.iris_vlevel);
-
- if (ret) {
- dev_err(&pdev->dev, "error reading voltage-level property\n");
- goto fail;
- }
-
- if (!wlan_cfg->wcn_external_gpio_support) {
- index++;
- ret = wcnss_dt_parse_vreg_level(
- &pdev->dev, index,
- "qcom,iris-vddpa-current",
- "qcom,iris-vddpa-voltage-level",
- penv->wlan_config.iris_vlevel);
- if (ret) {
- dev_err(&pdev->dev,
- "error reading voltage-level property\n");
- goto fail;
- }
- }
-
- index++;
- ret = wcnss_dt_parse_vreg_level(&pdev->dev, index,
- "qcom,iris-vdddig-current",
- "qcom,iris-vdddig-voltage-level",
- penv->wlan_config.iris_vlevel);
-
- if (ret) {
- dev_err(&pdev->dev, "error reading voltage-level property\n");
+ rc = wcnss_parse_voltage_regulator(&penv->wlan_config, &pdev->dev);
+ if (rc) {
+ dev_err(&pdev->dev, "Failed to parse voltage regulators\n");
goto fail;
}
@@ -3161,7 +3062,7 @@ wcnss_trigger_config(struct platform_device *pdev)
penv->vadc_dev = qpnp_get_vadc(&penv->pdev->dev, "wcnss");
if (IS_ERR(penv->vadc_dev)) {
- pr_err("%s: vadc get failed\n", __func__);
+ pr_debug("%s: vadc get failed\n", __func__);
penv->vadc_dev = NULL;
} else {
rc = wcnss_get_battery_volt(&penv->wlan_config.vbatt);
@@ -3437,7 +3338,15 @@ static int wcnss_notif_cb(struct notifier_block *this, unsigned long code,
struct notif_data *data = (struct notif_data *)ss_handle;
int ret, xo_mode;
- pr_info("%s: wcnss notification event: %lu\n", __func__, code);
+ if (!(code >= SUBSYS_NOTIF_MIN_INDEX) &&
+ (code <= SUBSYS_NOTIF_MAX_INDEX)) {
+ pr_debug("%s: Invaild subsystem notification code: %lu\n",
+ __func__, code);
+ return NOTIFY_DONE;
+ }
+
+ pr_debug("%s: wcnss notification event: %lu : %s\n",
+ __func__, code, wcnss_subsys_notif_type[code]);
if (code == SUBSYS_PROXY_VOTE) {
if (pdev && pwlanconfig) {
diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h
index e0c47f8b06bf..bc838936d2c9 100644
--- a/include/linux/wcnss_wlan.h
+++ b/include/linux/wcnss_wlan.h
@@ -38,7 +38,6 @@ struct vregs_level {
};
struct wcnss_wlan_config {
- bool wcn_external_gpio_support;
int use_48mhz_xo;
int is_pronto_vadc;
int is_pronto_v3;
@@ -143,6 +142,8 @@ void wcnss_init_delayed_work(struct delayed_work *dwork , void *callbackptr);
int wcnss_get_iris_name(char *iris_version);
void wcnss_dump_stack(struct task_struct *task);
void wcnss_snoc_vote(bool clk_chk_en);
+int wcnss_parse_voltage_regulator(struct wcnss_wlan_config *wlan_config,
+ struct device *dev);
#ifdef CONFIG_WCNSS_REGISTER_DUMP_ON_BITE
void wcnss_log_debug_regs_on_bite(void);