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

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

Merge "icnss2: Add open loop CPR support"

parents 9a451790 c8abb129
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3267,6 +3267,7 @@ static int icnss_probe(struct platform_device *pdev)
			icnss_pr_err("ICNSS genl init failed %d\n", ret);

		icnss_runtime_pm_init(priv);
		icnss_get_cpr_info(priv);
	}

	INIT_LIST_HEAD(&priv->icnss_tcdev_list);
+12 −0
Original line number Diff line number Diff line
@@ -133,6 +133,15 @@ struct icnss_vreg_info {
	u32 enabled;
};

struct icnss_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;
};

enum icnss_vreg_type {
	ICNSS_VREG_PRIM,
};
@@ -307,6 +316,7 @@ struct icnss_priv {
	struct ce_irq_list ce_irq_list[ICNSS_MAX_IRQ_REGISTRATIONS];
	struct list_head vreg_list;
	struct list_head clk_list;
	struct icnss_cpr_info cpr_info;
	unsigned long device_id;
	struct icnss_msi_config *msi_config;
	u32 msi_base_data;
@@ -419,5 +429,7 @@ int icnss_soc_wake_event_post(struct icnss_priv *priv,
			      u32 flags, void *data);
int icnss_get_iova(struct icnss_priv *priv, u64 *addr, u64 *size);
int icnss_get_iova_ipa(struct icnss_priv *priv, u64 *addr, u64 *size);
int icnss_get_cpr_info(struct icnss_priv *priv);
int icnss_update_cpr_info(struct icnss_priv *priv);
#endif
+126 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include <linux/pinctrl/consumer.h>
#include <linux/regulator/consumer.h>
#include <soc/qcom/cmd-db.h>
#include <linux/io.h>
#include "main.h"
#include "qmi.h"
#include "debug.h"
@@ -45,6 +46,13 @@ static struct icnss_clk_cfg icnss_adrestea_clk_list[] = {
#define ICNSS_THRESHOLD_LOW				3450000
#define ICNSS_THRESHOLD_GUARD				20000

#define TCS_CMD_DATA_ADDR_OFFSET	0x4
#define TCS_OFFSET			0xC8
#define TCS_CMD_OFFSET			0x10
#define MAX_TCS_NUM			8
#define MAX_TCS_CMD_NUM			5
#define BT_CXMX_VOLTAGE_MV		950

static int icnss_get_vreg_single(struct icnss_priv *priv,
				 struct icnss_vreg_info *vreg)
{
@@ -801,3 +809,121 @@ int icnss_init_vph_monitor(struct icnss_priv *priv)
out:
	return ret;
}

int icnss_get_cpr_info(struct icnss_priv *priv)
{
	struct platform_device *plat_dev = priv->pdev;
	struct icnss_cpr_info *cpr_info = &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");
	if (!res) {
		icnss_pr_dbg("TCS CMD address is not present for CPR\n");
		goto out;
	}

	ret = of_property_read_string(plat_dev->dev.of_node,
				      "qcom,cmd_db_name", &cmd_db_name);
	if (ret) {
		icnss_pr_dbg("CommandDB name is not present for CPR\n");
		goto out;
	}

	cpr_pmic_addr = cmd_db_read_addr(cmd_db_name);
	if (cpr_pmic_addr > 0) {
		cpr_info->cpr_pmic_addr = cpr_pmic_addr;
		icnss_pr_dbg("Get CPR PMIC address 0x%x from %s\n",
			     cpr_info->cpr_pmic_addr, cmd_db_name);
	} else {
		icnss_pr_err("CPR PMIC address is not available for %s\n",
			     cmd_db_name);
		ret = -EINVAL;
		goto out;
	}

	cpr_info->tcs_cmd_base_addr = res->start;
	addr_len = resource_size(res);
	icnss_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);
		icnss_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;
}

int icnss_update_cpr_info(struct icnss_priv *priv)
{
	struct icnss_cpr_info *cpr_info = &priv->cpr_info;
	u32 pmic_addr, voltage = 0, voltage_tmp, offset;
	void __iomem *tcs_cmd_addr, *tcs_cmd_data_addr;
	int i, j;

	if (cpr_info->tcs_cmd_base_addr == 0) {
		icnss_pr_dbg("CPR is not enabled\n");
		return 0;
	}

	if (cpr_info->voltage == 0 || cpr_info->cpr_pmic_addr == 0) {
		icnss_pr_err("Voltage %dmV or PMIC address 0x%x is not valid\n",
			     cpr_info->voltage, cpr_info->cpr_pmic_addr);
		return -EINVAL;
	}

	if (cpr_info->tcs_cmd_data_addr_io)
		goto update_cpr;

	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;
			pmic_addr = readl_relaxed(tcs_cmd_addr);
			if (pmic_addr == cpr_info->cpr_pmic_addr) {
				tcs_cmd_data_addr = tcs_cmd_addr +
					TCS_CMD_DATA_ADDR_OFFSET;
				voltage_tmp = readl_relaxed(tcs_cmd_data_addr);
				icnss_pr_dbg("Got voltage %dmV from i: %d, j: %d\n",
					     voltage_tmp, i, j);

				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;
					cpr_info->tcs_cmd_data_addr_io =
						tcs_cmd_data_addr;
				}
			}
		}
	}

	if (!cpr_info->tcs_cmd_data_addr_io) {
		icnss_pr_err("Failed to find proper TCS CMD data address\n");
		return -EINVAL;
	}

update_cpr:
	cpr_info->voltage = cpr_info->voltage > BT_CXMX_VOLTAGE_MV ?
		cpr_info->voltage : BT_CXMX_VOLTAGE_MV;
	icnss_pr_dbg("Update TCS CMD data address %pa with voltage %dmV\n",
		     &cpr_info->tcs_cmd_data_addr, cpr_info->voltage);
	writel_relaxed(cpr_info->voltage, cpr_info->tcs_cmd_data_addr_io);

	return 0;
}
+8 −0
Original line number Diff line number Diff line
@@ -674,6 +674,14 @@ int wlfw_cap_send_sync_msg(struct icnss_priv *priv)
				resp->fw_version_info.fw_build_timestamp,
				WLFW_MAX_TIMESTAMP_LEN + 1);
	}

	if (resp->voltage_mv_valid) {
		priv->cpr_info.voltage = resp->voltage_mv;
		icnss_pr_dbg("Voltage for CPR: %dmV\n",
			    priv->cpr_info.voltage);
		icnss_update_cpr_info(priv);
	}

	if (resp->fw_build_id_valid)
		strlcpy(priv->fw_build_id, resp->fw_build_id,
			QMI_WLFW_MAX_BUILD_ID_LEN_V01 + 1);