Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5883338f authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "wcnss: modularize wcnss power up sequence and debug logs"

parents d3b34dae 5eebfeaa
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -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>;
+145 −32
Original line number Diff line number Diff line
@@ -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)))
		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:
+29 −120
Original line number Diff line number Diff line
@@ -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");
@@ -2673,51 +2688,16 @@ static struct miscdevice wcnss_usr_ctrl = {
	.fops = &wcnss_ctrl_fops,
};

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) {
+2 −1
Original line number Diff line number Diff line
@@ -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);