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

Commit bb16c367 authored by Jilai Wang's avatar Jilai Wang
Browse files

msm: npu: Add bandwidth monitor support



This change is to add bandwidth monitor support to notify bwmon
when NPU activity starts and ends.

Change-Id: I2a1277d3dd8eadc20ea1bcbc84b70fe52d7eca59
Signed-off-by: default avatarJilai Wang <jilaiw@codeaurora.org>
parent 524c5e31
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@
#define NPU_MAX_DT_NAME_LEN	    21
#define NPU_MAX_PWRLEVELS		8
#define NPU_MAX_STATS_BUF_SIZE 16384
#define NPU_MAX_BW_DEVS			4

enum npu_power_level {
	NPU_PWRLEVEL_MINSVS = 0,
@@ -174,7 +175,9 @@ struct npu_pwrctrl {
	uint32_t min_pwrlevel;
	uint32_t num_pwrlevels;

	struct device *devbw;
	struct device *devbw[NPU_MAX_BW_DEVS];
	uint32_t devbw_num;
	uint32_t bwmon_enabled;
	uint32_t uc_pwrlevel;
	uint32_t cdsprm_pwrlevel;
	uint32_t fmax_pwrlevel;
+87 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <linux/regulator/consumer.h>
#include <linux/thermal.h>
#include <linux/soc/qcom/llcc-qcom.h>
#include <soc/qcom/devfreq_devbw.h>

#include "npu_common.h"
#include "npu_hw.h"
@@ -60,6 +61,8 @@ static ssize_t perf_mode_override_store(struct device *dev,
static ssize_t boot_store(struct device *dev,
					  struct device_attribute *attr,
					  const char *buf, size_t count);
static void npu_suspend_devbw(struct npu_device *npu_dev);
static void npu_resume_devbw(struct npu_device *npu_dev);
static bool npu_is_post_clock(const char *clk_name);
static bool npu_is_exclude_rate_clock(const char *clk_name);
static int npu_get_max_state(struct thermal_cooling_device *cdev,
@@ -353,6 +356,7 @@ int npu_enable_core_power(struct npu_device *npu_dev)
			npu_disable_regulators(npu_dev);
			goto fail;
		}
		npu_resume_devbw(npu_dev);
	}
	pwr->pwr_vote_num++;
fail:
@@ -373,6 +377,7 @@ void npu_disable_core_power(struct npu_device *npu_dev)

	pwr->pwr_vote_num--;
	if (!pwr->pwr_vote_num) {
		npu_suspend_devbw(npu_dev);
		npu_disable_core_clocks(npu_dev);
		npu_set_bw(npu_dev, 0, 0);
		npu_disable_regulators(npu_dev);
@@ -565,6 +570,44 @@ int npu_set_uc_power_level(struct npu_device *npu_dev,
	return npu_set_power_level(npu_dev, true);
}

/* -------------------------------------------------------------------------
 * Bandwidth Monitor Related
 * -------------------------------------------------------------------------
 */
static void npu_suspend_devbw(struct npu_device *npu_dev)
{
	struct npu_pwrctrl *pwr = &npu_dev->pwrctrl;
	int ret, i;

	if (pwr->bwmon_enabled && (pwr->devbw_num > 0)) {
		for (i = 0; i < pwr->devbw_num; i++) {
			NPU_DBG("Suspend devbw%d\n", i);
			ret = devfreq_suspend_devbw(pwr->devbw[i]);
			if (ret)
				NPU_ERR("devfreq_suspend_devbw failed rc:%d\n",
					ret);
		}
		pwr->bwmon_enabled = 0;
	}
}

static void npu_resume_devbw(struct npu_device *npu_dev)
{
	struct npu_pwrctrl *pwr = &npu_dev->pwrctrl;
	int ret, i;

	if (!pwr->bwmon_enabled && (pwr->devbw_num > 0)) {
		for (i = 0; i < pwr->devbw_num; i++) {
			NPU_DBG("Resume devbw%d\n", i);
			ret = devfreq_resume_devbw(pwr->devbw[i]);
			if (ret)
				NPU_ERR("devfreq_resume_devbw failed rc:%d\n",
					ret);
		}
		pwr->bwmon_enabled = 1;
	}
}

/* -------------------------------------------------------------------------
 * Clocks Related
 * -------------------------------------------------------------------------
@@ -1729,7 +1772,9 @@ static int npu_pwrctrl_init(struct npu_device *npu_dev)
{
	struct platform_device *pdev = npu_dev->pdev;
	struct device_node *node;
	int ret = 0;
	int ret = 0, i;
	struct platform_device *p2dev;
	struct npu_pwrctrl *pwr = &npu_dev->pwrctrl;

	/* Power levels */
	node = of_find_node_by_name(pdev->dev.of_node, "qcom,npu-pwrlevels");
@@ -1743,6 +1788,47 @@ static int npu_pwrctrl_init(struct npu_device *npu_dev)
	if (ret)
		return ret;

	/* Parse Bandwidth Monitor */
	pwr->devbw_num = of_property_count_strings(pdev->dev.of_node,
			"qcom,npubw-dev-names");
	if (pwr->devbw_num <= 0) {
		NPU_INFO("npubw-dev-names are not defined\n");
		return 0;
	} else if (pwr->devbw_num > NPU_MAX_BW_DEVS) {
		NPU_ERR("number of devbw %d exceeds limit\n", pwr->devbw_num);
		return -EINVAL;
	}

	for (i = 0; i < pwr->devbw_num; i++) {
		node = of_parse_phandle(pdev->dev.of_node,
				"qcom,npubw-devs", i);

		if (node) {
			p2dev = of_find_device_by_node(node);
			of_node_put(node);
			if (p2dev) {
				pwr->devbw[i] = &p2dev->dev;
			} else {
				NPU_ERR("can't find devbw%d\n", i);
				ret = -EINVAL;
				break;
			}
		} else {
			NPU_ERR("can't find devbw node\n");
			ret = -EINVAL;
			break;
		}
	}

	if (ret) {
		/* Allow npu work without bwmon */
		pwr->devbw_num = 0;
		ret = 0;
	} else {
		/* Set to 1 initially - we assume bwmon is on */
		pwr->bwmon_enabled = 1;
	}

	return ret;
}