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

Commit 49b1b0e8 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "cnss2: Add support of runtime Vreg enable for QCA6490"

parents 10a538a0 852e8b2f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2344,6 +2344,7 @@ static int cnss_probe(struct platform_device *plat_dev)
	INIT_LIST_HEAD(&plat_priv->clk_list);

	cnss_get_wlaon_pwr_ctrl_info(plat_priv);
	cnss_get_tcs_info(plat_priv);
	cnss_get_cpr_info(plat_priv);
	cnss_init_control_params(plat_priv);

+8 −2
Original line number Diff line number Diff line
@@ -307,10 +307,13 @@ struct cnss_control_params {
	unsigned int time_sync_period;
};

struct cnss_tcs_info {
	resource_size_t cmd_base_addr;
	void __iomem *cmd_base_addr_io;
};

struct cnss_cpr_info {
	resource_size_t tcs_cmd_base_addr;
	resource_size_t tcs_cmd_data_addr;
	void __iomem *tcs_cmd_base_addr_io;
	void __iomem *tcs_cmd_data_addr_io;
	u32 cpr_pmic_addr;
	u32 voltage;
@@ -403,6 +406,7 @@ struct cnss_plat_data {
	bool cbc_enabled;
	u8 use_nv_mac;
	u8 set_wlaon_pwr_ctrl;
	struct cnss_tcs_info tcs_info;
};

#ifdef CONFIG_ARCH_QCOM
@@ -460,5 +464,7 @@ int cnss_minidump_add_region(struct cnss_plat_data *plat_priv,
int cnss_minidump_remove_region(struct cnss_plat_data *plat_priv,
				enum cnss_fw_dump_type type, int seg_no,
				void *va, phys_addr_t pa, size_t size);
int cnss_enable_int_pow_amp_vreg(struct cnss_plat_data *plat_priv);
int cnss_get_tcs_info(struct cnss_plat_data *plat_priv);

#endif /* _CNSS_MAIN_H */
+74 −28
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */
/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */

#include <linux/clk.h>
#include <linux/delay.h>
@@ -10,6 +10,7 @@

#include "main.h"
#include "debug.h"
#include "bus.h"

static struct cnss_vreg_cfg cnss_vreg_list[] = {
	{"vdd-wlan-core", 1300000, 1300000, 0, 0, 0},
@@ -832,15 +833,12 @@ void cnss_set_pin_connect_status(struct cnss_plat_data *plat_priv)
	plat_priv->pin_result.host_pin_result = pin_status;
}

int cnss_get_cpr_info(struct cnss_plat_data *plat_priv)
int cnss_get_tcs_info(struct cnss_plat_data *plat_priv)
{
	struct platform_device *plat_dev = plat_priv->plat_dev;
	struct cnss_cpr_info *cpr_info = &plat_priv->cpr_info;
	struct resource *res;
	resource_size_t addr_len;
	void __iomem *tcs_cmd_base_addr;
	const char *cmd_db_name;
	u32 cpr_pmic_addr = 0;
	int ret = 0;

	res = platform_get_resource_byname(plat_dev, IORESOURCE_MEM, "tcs_cmd");
@@ -849,6 +847,37 @@ int cnss_get_cpr_info(struct cnss_plat_data *plat_priv)
		goto out;
	}

	plat_priv->tcs_info.cmd_base_addr = res->start;
	addr_len = resource_size(res);
	cnss_pr_dbg("TCS CMD base address is %pa with length %pa\n",
		    &plat_priv->tcs_info.cmd_base_addr, &addr_len);

	tcs_cmd_base_addr = devm_ioremap_resource(&plat_dev->dev, res);
	if (IS_ERR(tcs_cmd_base_addr)) {
		ret = PTR_ERR(tcs_cmd_base_addr);
		cnss_pr_err("Failed to map TCS CMD address, err = %d\n",
			    ret);
		goto out;
	}
	plat_priv->tcs_info.cmd_base_addr_io = tcs_cmd_base_addr;
	return 0;
out:
	return ret;
}

int cnss_get_cpr_info(struct cnss_plat_data *plat_priv)
{
	struct platform_device *plat_dev = plat_priv->plat_dev;
	struct cnss_cpr_info *cpr_info = &plat_priv->cpr_info;
	const char *cmd_db_name;
	u32 cpr_pmic_addr = 0;
	int ret = 0;

	if (plat_priv->tcs_info.cmd_base_addr == 0) {
		cnss_pr_dbg("TCS CMD not configured\n");
		return 0;
	}

	ret = of_property_read_string(plat_dev->dev.of_node,
				      "qcom,cmd_db_name", &cmd_db_name);
	if (ret) {
@@ -873,24 +902,7 @@ int cnss_get_cpr_info(struct cnss_plat_data *plat_priv)
		ret = -EINVAL;
		goto out;
	}

	cpr_info->tcs_cmd_base_addr = res->start;
	addr_len = resource_size(res);
	cnss_pr_dbg("TCS CMD base address is %pa with length %pa\n",
		    &cpr_info->tcs_cmd_base_addr, &addr_len);

	tcs_cmd_base_addr = devm_ioremap_resource(&plat_dev->dev, res);
	if (IS_ERR(tcs_cmd_base_addr)) {
		ret = PTR_ERR(tcs_cmd_base_addr);
		cnss_pr_err("Failed to map TCS CMD address, err = %d\n",
			    ret);
		goto out;
	}

	cpr_info->tcs_cmd_base_addr_io = tcs_cmd_base_addr;

	return 0;

out:
	return ret;
}
@@ -902,8 +914,8 @@ int cnss_update_cpr_info(struct cnss_plat_data *plat_priv)
	void __iomem *tcs_cmd_addr, *tcs_cmd_data_addr;
	int i, j;

	if (cpr_info->tcs_cmd_base_addr == 0) {
		cnss_pr_dbg("CPR is not enabled\n");
	if (plat_priv->tcs_info.cmd_base_addr == 0) {
		cnss_pr_dbg("TCS CMD not configured\n");
		return 0;
	}

@@ -919,7 +931,8 @@ int cnss_update_cpr_info(struct cnss_plat_data *plat_priv)
	for (i = 0; i < MAX_TCS_NUM; i++) {
		for (j = 0; j < MAX_TCS_CMD_NUM; j++) {
			offset = i * TCS_OFFSET + j * TCS_CMD_OFFSET;
			tcs_cmd_addr = cpr_info->tcs_cmd_base_addr_io + offset;
			tcs_cmd_addr = plat_priv->tcs_info.cmd_base_addr_io +
									offset;
			pmic_addr = readl_relaxed(tcs_cmd_addr);
			if (pmic_addr == cpr_info->cpr_pmic_addr) {
				tcs_cmd_data_addr = tcs_cmd_addr +
@@ -931,9 +944,8 @@ int cnss_update_cpr_info(struct cnss_plat_data *plat_priv)
				if (voltage_tmp > voltage) {
					voltage = voltage_tmp;
					cpr_info->tcs_cmd_data_addr =
						cpr_info->tcs_cmd_base_addr +
						offset +
						TCS_CMD_DATA_ADDR_OFFSET;
					plat_priv->tcs_info.cmd_base_addr +
					offset + TCS_CMD_DATA_ADDR_OFFSET;
					cpr_info->tcs_cmd_data_addr_io =
						tcs_cmd_data_addr;
				}
@@ -955,3 +967,37 @@ int cnss_update_cpr_info(struct cnss_plat_data *plat_priv)

	return 0;
}

int cnss_enable_int_pow_amp_vreg(struct cnss_plat_data *plat_priv)
{
	struct platform_device *plat_dev = plat_priv->plat_dev;
	u32 offset, addr_val, data_val;
	void __iomem *tcs_cmd;
	int ret;

	if (!plat_priv->tcs_info.cmd_base_addr_io) {
		cnss_pr_err("TCS CMD not configured\n");
		return -EINVAL;
	}

	if (plat_priv->device_id != QCA6490_DEVICE_ID)
		return -EINVAL;

	ret = of_property_read_u32(plat_dev->dev.of_node,
				   "qcom,tcs_offset_int_pow_amp_vreg",
				   &offset);
	if (ret) {
		cnss_pr_dbg("Internal Power Amp Vreg not configured\n");
		return -EINVAL;
	}
	tcs_cmd = plat_priv->tcs_info.cmd_base_addr_io + offset;
	addr_val = readl_relaxed(tcs_cmd);
	tcs_cmd += TCS_CMD_DATA_ADDR_OFFSET;

	/* 1 = enable Vreg */
	writel_relaxed(1, tcs_cmd);

	data_val = readl_relaxed(tcs_cmd);
	cnss_pr_dbg("Setup S3E TCS Addr: %x Data: %d\n", addr_val, data_val);
	return 0;
}
+6 −0
Original line number Diff line number Diff line
@@ -632,6 +632,12 @@ int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv,
	if (bdf_type != CNSS_BDF_DUMMY)
		release_firmware(fw_entry);

	/* QCA6490 enable S3E regulator for IPA configuration only */
	if (resp->host_bdf_data_valid) {
		if (!(resp->host_bdf_data & QMI_WLFW_HW_XPA_V01))
			cnss_enable_int_pow_amp_vreg(plat_priv);
	}

	kfree(req);
	kfree(resp);
	return 0;