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

Commit 41ddc62e authored by Jilai Wang's avatar Jilai Wang
Browse files

msm: npu: Vote minimum bandwidth to enable Turing GDSCR



Turing GDSCR needs to be enabled before NPU AXI clock is turned
on and it can be turned on by voting minimum bandwidth.

Change-Id: Idc338164b6c66694b1dee4170b068de25552fd1d
Signed-off-by: default avatarJilai Wang <jilaiw@codeaurora.org>
parent 8d774dde
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/mailbox/qmp.h>
#include <linux/msm-bus.h>

#include "npu_mgr.h"

@@ -201,6 +202,21 @@ struct npu_io_data {
	void __iomem *base;
};

#define MAX_PATHS	2
#define DBL_BUF	2
#define MBYTE (1ULL << 20)

struct npu_bwctrl {
	struct msm_bus_vectors vectors[MAX_PATHS * DBL_BUF];
	struct msm_bus_paths bw_levels[DBL_BUF];
	struct msm_bus_scale_pdata bw_data;
	uint32_t bus_client;
	int cur_ab;
	int cur_ib;
	int cur_idx;
	uint32_t num_paths;
};

struct npu_device {
	struct mutex dev_lock;

@@ -238,6 +254,7 @@ struct npu_device {
	struct thermal_cooling_device *tcdev;
	struct npu_pwrctrl pwrctrl;
	struct npu_thermalctrl thermalctrl;
	struct npu_bwctrl bwctrl;

	struct llcc_slice_desc *sys_cache;
	uint32_t execute_v2_flag;
@@ -285,5 +302,6 @@ int enable_fw(struct npu_device *npu_dev);
void disable_fw(struct npu_device *npu_dev);
int load_fw(struct npu_device *npu_dev);
int unload_fw(struct npu_device *npu_dev);
int npu_set_bw(struct npu_device *npu_dev, int new_ib, int new_ab);

#endif /* _NPU_COMMON_H */
+93 −0
Original line number Diff line number Diff line
@@ -91,6 +91,7 @@ static long npu_ioctl(struct file *file, unsigned int cmd,
static unsigned int npu_poll(struct file *filp, struct poll_table_struct *p);
static int npu_parse_dt_clock(struct npu_device *npu_dev);
static int npu_parse_dt_regulator(struct npu_device *npu_dev);
static int npu_parse_dt_bw(struct npu_device *npu_dev);
static int npu_of_parse_pwrlevels(struct npu_device *npu_dev,
		struct device_node *node);
static int npu_pwrctrl_init(struct npu_device *npu_dev);
@@ -1460,6 +1461,91 @@ static int npu_parse_dt_regulator(struct npu_device *npu_dev)
	return rc;
}

static int npu_parse_dt_bw(struct npu_device *npu_dev)
{
	int ret, len;
	uint32_t ports[2];
	struct platform_device *pdev = npu_dev->pdev;
	struct npu_bwctrl *bwctrl = &npu_dev->bwctrl;

	if (of_find_property(pdev->dev.of_node, "qcom,src-dst-ports", &len)) {
		len /= sizeof(ports[0]);
		if (len != 2) {
			NPU_ERR("Unexpected number of ports\n");
			return -EINVAL;
		}

		ret = of_property_read_u32_array(pdev->dev.of_node,
			"qcom,src-dst-ports", ports, len);
		if (ret) {
			NPU_ERR("Failed to read bw property\n");
			return ret;
		}
	} else {
		NPU_ERR("can't find bw property\n");
		return -EINVAL;
	}

	bwctrl->bw_levels[0].vectors = &bwctrl->vectors[0];
	bwctrl->bw_levels[1].vectors = &bwctrl->vectors[MAX_PATHS];
	bwctrl->bw_data.usecase = bwctrl->bw_levels;
	bwctrl->bw_data.num_usecases = ARRAY_SIZE(bwctrl->bw_levels);
	bwctrl->bw_data.name = dev_name(&pdev->dev);
	bwctrl->bw_data.active_only = false;

	bwctrl->bw_levels[0].vectors[0].src = ports[0];
	bwctrl->bw_levels[0].vectors[0].dst = ports[1];
	bwctrl->bw_levels[1].vectors[0].src = ports[0];
	bwctrl->bw_levels[1].vectors[0].dst = ports[1];
	bwctrl->bw_levels[0].num_paths = 1;
	bwctrl->bw_levels[1].num_paths = 1;
	bwctrl->num_paths = 1;

	bwctrl->bus_client = msm_bus_scale_register_client(&bwctrl->bw_data);
	if (!bwctrl->bus_client) {
		NPU_ERR("Unable to register bus client\n");
		return -ENODEV;
	}

	NPU_INFO("NPU BW client sets up successfully\n");

	return 0;
}

int npu_set_bw(struct npu_device *npu_dev, int new_ib, int new_ab)
{
	int i, ret;
	struct npu_bwctrl *bwctrl = &npu_dev->bwctrl;

	if (!bwctrl->bus_client) {
		NPU_DBG("bus client doesn't exist\n");
		return 0;
	}

	if (bwctrl->cur_ib == new_ib && bwctrl->cur_ab == new_ab)
		return 0;

	i = (bwctrl->cur_idx + 1) % DBL_BUF;

	bwctrl->bw_levels[i].vectors[0].ib = new_ib * MBYTE;
	bwctrl->bw_levels[i].vectors[0].ab = new_ab / bwctrl->num_paths * MBYTE;
	bwctrl->bw_levels[i].vectors[1].ib = new_ib * MBYTE;
	bwctrl->bw_levels[i].vectors[1].ab = new_ab / bwctrl->num_paths * MBYTE;

	NPU_INFO("BW MBps: AB: %d IB: %d\n", new_ab, new_ib);

	ret = msm_bus_scale_client_update_request(bwctrl->bus_client, i);
	if (ret) {
		NPU_ERR("bandwidth request failed (%d)\n", ret);
	} else {
		bwctrl->cur_idx = i;
		bwctrl->cur_ib = new_ib;
		bwctrl->cur_ab = new_ab;
	}

	return ret;
}

static int npu_of_parse_pwrlevels(struct npu_device *npu_dev,
		struct device_node *node)
{
@@ -1674,6 +1760,7 @@ static int npu_hw_info_init(struct npu_device *npu_dev)
{
	int rc = 0;

	npu_set_bw(npu_dev, 100, 100);
	rc = npu_enable_core_power(npu_dev);
	if (rc) {
		NPU_ERR("Failed to enable power\n");
@@ -1683,6 +1770,7 @@ static int npu_hw_info_init(struct npu_device *npu_dev)
	npu_dev->hw_version = REGR(npu_dev, NPU_HW_VERSION);
	NPU_DBG("NPU_HW_VERSION 0x%x\n", npu_dev->hw_version);
	npu_disable_core_power(npu_dev);
	npu_set_bw(npu_dev, 0, 0);

	return rc;
}
@@ -1827,6 +1915,10 @@ static int npu_probe(struct platform_device *pdev)
	if (rc)
		goto error_get_dev_num;

	rc = npu_parse_dt_bw(npu_dev);
	if (rc)
		NPU_WARN("Parse bw info failed\n");

	rc = npu_hw_info_init(npu_dev);
	if (rc)
		goto error_get_dev_num;
@@ -1947,6 +2039,7 @@ static int npu_remove(struct platform_device *pdev)
	unregister_chrdev_region(npu_dev->dev_num, 1);
	platform_set_drvdata(pdev, NULL);
	npu_mbox_deinit(npu_dev);
	msm_bus_scale_unregister_client(npu_dev->bwctrl.bus_client);

	g_npu_dev = NULL;

+11 −1
Original line number Diff line number Diff line
@@ -77,6 +77,12 @@ static int load_fw_nolock(struct npu_device *npu_dev, bool enable)
		return 0;
	}

	ret = npu_set_bw(npu_dev, 100, 100);
	if (ret) {
		NPU_ERR("Vote bandwidth failed\n");
		return ret;
	}

	/* Boot the NPU subsystem */
	host_ctx->subsystem_handle = subsystem_get_local("npu");
	if (IS_ERR_OR_NULL(host_ctx->subsystem_handle)) {
@@ -132,8 +138,10 @@ static int load_fw_nolock(struct npu_device *npu_dev, bool enable)
	if (!ret) {
		host_ctx->fw_state = FW_LOADED;
	} else {
		if (!IS_ERR_OR_NULL(host_ctx->subsystem_handle))
		if (!IS_ERR_OR_NULL(host_ctx->subsystem_handle)) {
			subsystem_put_local(host_ctx->subsystem_handle);
			npu_set_bw(npu_dev, 0, 0);
		}
		host_ctx->fw_state = FW_UNLOADED;
	}

@@ -177,6 +185,7 @@ int unload_fw(struct npu_device *npu_dev)
	}

	subsystem_put_local(host_ctx->subsystem_handle);
	npu_set_bw(npu_dev, 0, 0);
	host_ctx->fw_state = FW_UNLOADED;
	NPU_DBG("fw is unloaded\n");
	mutex_unlock(&host_ctx->lock);
@@ -335,6 +344,7 @@ static void disable_fw_nolock(struct npu_device *npu_dev)
		subsystem_put_local(host_ctx->subsystem_handle);
		host_ctx->fw_state = FW_UNLOADED;
		NPU_DBG("fw is unloaded\n");
		npu_set_bw(npu_dev, 0, 0);
	}
}