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

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

Merge "msm: npu: Add support to get/set property"

parents b643f6b4 17e21308
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -17,8 +17,9 @@
		reg = <0x9900000 0x20000>,
			<0x99f0000 0x10000>,
			<0x9980000 0x10000>,
			<0x17c00000 0x10000>;
		reg-names = "tcm", "core", "cc", "apss_shared";
			<0x17c00000 0x10000>,
			<0x01f40000 0x40000>;
		reg-names = "tcm", "core", "cc", "apss_shared", "tcsr";
		interrupts = <GIC_SPI 583 IRQ_TYPE_LEVEL_HIGH>,
			<GIC_SPI 585 IRQ_TYPE_EDGE_RISING>,
			<GIC_SPI 588 IRQ_TYPE_EDGE_RISING>,
@@ -75,8 +76,8 @@
					100000000
					200000000
					200000000
					120000000
					40000000
					150000000
					30000000
					200000000
					19200000
					50000000
@@ -94,7 +95,7 @@
					400000000
					400000000
					200000000
					40000000
					37500000
					300000000
					19200000
					50000000
@@ -112,8 +113,8 @@
					515000000
					515000000
					300000000
					75000000
					400000000
					37500000
					403000000
					19200000
					50000000
					19200000
@@ -135,7 +136,7 @@
					19200000
					100000000
					19200000
					515000000
					650000000
					19200000
					660000000>;
			};
@@ -153,7 +154,7 @@
					19200000
					100000000
					19200000
					650000000
					800000000
					19200000
					800000000>;
			};
+10 −3
Original line number Diff line number Diff line
@@ -52,8 +52,11 @@
#define NPU_MAX_DT_NAME_LEN		21
#define NPU_MAX_PWRLEVELS		8
#define NPU_MAX_STATS_BUF_SIZE	16384
#define NPU_MAX_PATCH_NUM		160
#define NPU_MAX_BW_DEVS			4

#define PERF_MODE_DEFAULT 0

enum npu_power_level {
	NPU_PWRLEVEL_MINSVS = 0,
	NPU_PWRLEVEL_LOWSVS,
@@ -170,6 +173,8 @@ struct npu_reg {
 * @uc_pwrlevel - power level from user driver setting
 * @perf_mode_override - perf mode from sysfs to override perf mode
 *                       settings from user driver
 * @dcvs_mode - dcvs mode from sysfs to turn on dcvs mode
 *              settings from user driver
 * @devbw - bw device
 */
struct npu_pwrctrl {
@@ -189,6 +194,8 @@ struct npu_pwrctrl {
	uint32_t cdsprm_pwrlevel;
	uint32_t fmax_pwrlevel;
	uint32_t perf_mode_override;
	uint32_t dcvs_mode;
	uint32_t cur_dcvs_activity;
};

/**
@@ -252,7 +259,7 @@ struct npu_device {
	struct npu_io_data core_io;
	struct npu_io_data tcm_io;
	struct npu_io_data cc_io;
	struct npu_io_data qdsp_io;
	struct npu_io_data tcsr_io;
	struct npu_io_data apss_shared_io;
	struct npu_io_data qfprom_io;

+23 −82
Original line number Diff line number Diff line
@@ -32,8 +32,7 @@
 */
static int npu_debug_open(struct inode *inode, struct file *file);
static int npu_debug_release(struct inode *inode, struct file *file);
static ssize_t npu_debug_reg_write(struct file *file,
		const char __user *user_buf, size_t count, loff_t *ppos);
static int npu_debug_reg_release(struct inode *inode, struct file *file);
static ssize_t npu_debug_reg_read(struct file *file,
		char __user *user_buf, size_t count, loff_t *ppos);
static ssize_t npu_debug_off_write(struct file *file,
@@ -49,13 +48,12 @@ static ssize_t npu_debug_ctrl_write(struct file *file,
 * Variables
 * -------------------------------------------------------------------------
 */
struct npu_device *g_npu_dev;
static struct npu_device *g_npu_dev;

static const struct file_operations npu_reg_fops = {
	.open = npu_debug_open,
	.release = npu_debug_release,
	.release = npu_debug_reg_release,
	.read = npu_debug_reg_read,
	.write = npu_debug_reg_write,
};

static const struct file_operations npu_off_fops = {
@@ -92,6 +90,11 @@ static int npu_debug_open(struct inode *inode, struct file *file)
}

static int npu_debug_release(struct inode *inode, struct file *file)
{
	return 0;
}

static int npu_debug_reg_release(struct inode *inode, struct file *file)
{
	struct npu_device *npu_dev = file->private_data;
	struct npu_debugfs_ctx *debugfs;
@@ -108,41 +111,6 @@ static int npu_debug_release(struct inode *inode, struct file *file)
 * Function Implementations - Reg Read/Write
 * -------------------------------------------------------------------------
 */
static ssize_t npu_debug_reg_write(struct file *file,
		const char __user *user_buf, size_t count, loff_t *ppos)
{
	size_t off;
	uint32_t data, cnt;
	struct npu_device *npu_dev = file->private_data;
	char buf[24];

	if (count >= sizeof(buf))
		return -EINVAL;

	if (copy_from_user(buf, user_buf, count))
		return -EFAULT;

	buf[count] = 0;	/* end of string */

	cnt = sscanf(buf, "%zx %x", &off, &data);
	NPU_DBG("%s 0x%zx, 0x%08x\n", buf, off, data);

	return count;
	if (cnt < 2)
		return -EINVAL;

	if (npu_enable_core_power(npu_dev))
		return -EPERM;

	REGW(npu_dev, off, data);

	npu_disable_core_power(npu_dev);

	NPU_DBG("write: addr=%zx data=%x\n", off, data);

	return count;
}

static ssize_t npu_debug_reg_read(struct file *file,
			char __user *user_buf, size_t count, loff_t *ppos)
{
@@ -262,6 +230,7 @@ static ssize_t npu_debug_off_read(struct file *file,

	len = scnprintf(buf, sizeof(buf), "offset=0x%08x cnt=%d\n",
		debugfs->reg_off, debugfs->reg_cnt);
	len = min(len, count);

	if (copy_to_user(user_buf, buf, len)) {
		NPU_ERR("failed to copy to user\n");
@@ -291,49 +260,21 @@ static ssize_t npu_debug_log_read(struct file *file,
	mutex_lock(&debugfs->log_lock);

	if (debugfs->log_num_bytes_buffered != 0) {
		if ((debugfs->log_read_index +
			debugfs->log_num_bytes_buffered) >
			debugfs->log_buf_size) {
			/* Wrap around case */
			uint32_t remaining_to_end = debugfs->log_buf_size -
				debugfs->log_read_index;
			uint8_t *src_addr = debugfs->log_buf +
				debugfs->log_read_index;
			void __user *dst_addr = (void __user *) user_buf;

			if (copy_to_user(dst_addr, src_addr,
				remaining_to_end)) {
				NPU_ERR("failed to copy to user\n");
				mutex_unlock(&debugfs->log_lock);
				return -EFAULT;
			}
			src_addr = debugfs->log_buf;
			dst_addr = (void __user *)(user_buf + remaining_to_end);
			if (copy_to_user(dst_addr, src_addr,
				debugfs->log_num_bytes_buffered -
				remaining_to_end)) {
				NPU_ERR("failed to copy to user\n");
				mutex_unlock(&debugfs->log_lock);
				return -EFAULT;
			}
			debugfs->log_read_index =
				debugfs->log_num_bytes_buffered -
				remaining_to_end;
		} else {
		len = min(debugfs->log_num_bytes_buffered,
			debugfs->log_buf_size - debugfs->log_read_index);
		len = min(count, len);
		if (copy_to_user(user_buf, (debugfs->log_buf +
				debugfs->log_read_index),
				debugfs->log_num_bytes_buffered)) {
			debugfs->log_read_index), len)) {
			NPU_ERR("failed to copy to user\n");
			mutex_unlock(&debugfs->log_lock);
			return -EFAULT;
		}
			debugfs->log_read_index +=
				debugfs->log_num_bytes_buffered;
		debugfs->log_read_index += len;
		if (debugfs->log_read_index == debugfs->log_buf_size)
			debugfs->log_read_index = 0;
		}
		len = debugfs->log_num_bytes_buffered;
		debugfs->log_num_bytes_buffered = 0;

		debugfs->log_num_bytes_buffered -= len;
		*ppos += len;
	}

	/* mutex log unlock */
+151 −31
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@
#define DDR_MAPPED_START_ADDR   0x80000000
#define DDR_MAPPED_SIZE         0x60000000

#define PERF_MODE_DEFAULT 0
#define MBOX_OP_TIMEOUTMS 1000

/* -------------------------------------------------------------------------
@@ -65,6 +64,12 @@ static ssize_t perf_mode_override_show(struct device *dev,
static ssize_t perf_mode_override_store(struct device *dev,
					  struct device_attribute *attr,
					  const char *buf, size_t count);
static ssize_t dcvs_mode_show(struct device *dev,
					 struct device_attribute *attr,
					 char *buf);
static ssize_t dcvs_mode_store(struct device *dev,
					  struct device_attribute *attr,
					  const char *buf, size_t count);
static ssize_t boot_store(struct device *dev,
					  struct device_attribute *attr,
					  const char *buf, size_t count);
@@ -92,6 +97,11 @@ static int npu_exec_network_v2(struct npu_client *client,
	unsigned long arg);
static int npu_receive_event(struct npu_client *client,
	unsigned long arg);
static int npu_set_fw_state(struct npu_client *client, uint32_t enable);
static int npu_set_property(struct npu_client *client,
	unsigned long arg);
static int npu_get_property(struct npu_client *client,
	unsigned long arg);
static long npu_ioctl(struct file *file, unsigned int cmd,
					unsigned long arg);
static unsigned int npu_poll(struct file *filp, struct poll_table_struct *p);
@@ -162,11 +172,13 @@ static DEVICE_ATTR_RO(caps);
static DEVICE_ATTR_RW(pwr);
static DEVICE_ATTR_RW(perf_mode_override);
static DEVICE_ATTR_WO(boot);
static DEVICE_ATTR_RW(dcvs_mode);

static struct attribute *npu_fs_attrs[] = {
	&dev_attr_caps.attr,
	&dev_attr_pwr.attr,
	&dev_attr_perf_mode_override.attr,
	&dev_attr_dcvs_mode.attr,
	&dev_attr_boot.attr,
	NULL
};
@@ -285,8 +297,8 @@ static ssize_t perf_mode_override_store(struct device *dev,
					  struct device_attribute *attr,
					  const char *buf, size_t count)
{
	struct npu_client client;
	struct npu_device *npu_dev = dev_get_drvdata(dev);
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
	uint32_t val;
	int rc;

@@ -297,15 +309,56 @@ static ssize_t perf_mode_override_store(struct device *dev,
	}

	val = min(val, npu_dev->pwrctrl.num_pwrlevels);
	mutex_lock(&host_ctx->lock);
	npu_dev->pwrctrl.perf_mode_override = val;
	NPU_INFO("setting uc_pwrlevel_override to %d\n", val);
	npu_set_power_level(npu_dev, true);
	mutex_unlock(&host_ctx->lock);
	NPU_INFO("setting perf mode to %d\n", val);
	client.npu_dev = npu_dev;
	npu_host_set_perf_mode(&client, 0, val);

	return count;
}

static ssize_t dcvs_mode_show(struct device *dev,
					 struct device_attribute *attr,
					 char *buf)
{
	struct npu_device *npu_dev = dev_get_drvdata(dev);
	struct npu_pwrctrl *pwr = &npu_dev->pwrctrl;

	return scnprintf(buf, PAGE_SIZE, "%d\n", pwr->dcvs_mode);
}

static ssize_t dcvs_mode_store(struct device *dev,
					  struct device_attribute *attr,
					  const char *buf, size_t count)
{
	struct npu_device *npu_dev = dev_get_drvdata(dev);
	struct msm_npu_property prop;
	uint32_t val;
	int ret = 0;

	ret = kstrtou32(buf, 10, &val);
	if (ret) {
		NPU_ERR("Invalid input for dcvs mode setting\n");
		return -EINVAL;
	}

	val = min(val, (uint32_t)(npu_dev->pwrctrl.num_pwrlevels - 1));
	NPU_DBG("sysfs: setting dcvs_mode to %d\n", val);

	prop.prop_id = MSM_NPU_PROP_ID_DCVS_MODE;
	prop.num_of_params = 1;
	prop.network_hdl = 0;
	prop.prop_param[0] = val;

	ret = npu_host_set_fw_property(npu_dev, &prop);
	if (ret) {
		NPU_ERR("npu_host_set_fw_property failed %d\n", ret);
		return ret;
	}

	npu_dev->pwrctrl.dcvs_mode = val;

	return count;
}
/* -------------------------------------------------------------------------
 * SysFS - npu_boot
 * -------------------------------------------------------------------------
@@ -393,6 +446,7 @@ void npu_disable_core_power(struct npu_device *npu_dev)
		pwr->active_pwrlevel = pwr->default_pwrlevel;
		pwr->uc_pwrlevel = pwr->max_pwrlevel;
		pwr->cdsprm_pwrlevel = pwr->max_pwrlevel;
		pwr->cur_dcvs_activity = pwr->num_pwrlevels;
		NPU_DBG("setting back to power level=%d\n",
			pwr->active_pwrlevel);
	}
@@ -452,14 +506,6 @@ static uint32_t npu_calc_power_level(struct npu_device *npu_dev)
	uint32_t active_pwr_level = npu_dev->pwrctrl.active_pwrlevel;
	uint32_t uc_pwr_level = npu_dev->pwrctrl.uc_pwrlevel;

	/*
	 * if perf_mode_override is not 0, use it to override
	 * uc_pwrlevel
	 */
	if (npu_dev->pwrctrl.perf_mode_override > 0)
		uc_pwr_level = npu_power_level_from_index(npu_dev,
			npu_dev->pwrctrl.perf_mode_override - 1);

	/*
	 * pick the lowese power level between thermal power and usecase power
	 * settings
@@ -566,9 +612,6 @@ int npu_set_uc_power_level(struct npu_device *npu_dev,
	struct npu_pwrctrl *pwr = &npu_dev->pwrctrl;
	uint32_t uc_pwrlevel_to_set;

	if (perf_mode == PERF_MODE_DEFAULT)
		uc_pwrlevel_to_set = pwr->default_pwrlevel;
	else
	uc_pwrlevel_to_set = npu_power_level_from_index(npu_dev,
		perf_mode - 1);

@@ -853,6 +896,7 @@ static void npu_disable_regulators(struct npu_device *npu_dev)
	if (host_ctx->power_vote_num > 0) {
		for (i = 0; i < npu_dev->regulator_num; i++)
			regulator_disable(regulators[i].regulator);

		host_ctx->power_vote_num--;
	}
}
@@ -1148,9 +1192,10 @@ static int npu_load_network_v2(struct npu_client *client,
		return -EFAULT;
	}

	if (req.patch_info_num > MSM_NPU_MAX_PATCH_LAYER_NUM) {
	if ((req.patch_info_num > NPU_MAX_PATCH_NUM) ||
		(req.patch_info_num == 0)) {
		NPU_ERR("Invalid patch info num %d[max:%d]\n",
			req.patch_info_num, MSM_NPU_MAX_PATCH_LAYER_NUM);
			req.patch_info_num, NPU_MAX_PATCH_NUM);
		return -EINVAL;
	}

@@ -1235,9 +1280,10 @@ static int npu_exec_network_v2(struct npu_client *client,
		return -EFAULT;
	}

	if (req.patch_buf_info_num > MSM_NPU_MAX_PATCH_LAYER_NUM) {
	if ((req.patch_buf_info_num > NPU_MAX_PATCH_NUM) ||
		(req.patch_buf_info_num == 0)) {
		NPU_ERR("Invalid patch buf info num %d[max:%d]\n",
			req.patch_buf_info_num, MSM_NPU_MAX_PATCH_LAYER_NUM);
			req.patch_buf_info_num, NPU_MAX_PATCH_NUM);
		return -EINVAL;
	}

@@ -1331,6 +1377,43 @@ static int npu_receive_event(struct npu_client *client,
	return ret;
}

static int npu_set_fw_state(struct npu_client *client, uint32_t enable)
{
	struct npu_device *npu_dev = client->npu_dev;
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
	int rc = 0;

	if (host_ctx->network_num > 0) {
		NPU_ERR("Need to unload network first\n");
		mutex_unlock(&npu_dev->dev_lock);
		return -EINVAL;
	}

	if (enable) {
		NPU_DBG("enable fw\n");
		rc = enable_fw(npu_dev);
		if (rc) {
			NPU_ERR("enable fw failed\n");
		} else {
			host_ctx->npu_init_cnt++;
			NPU_DBG("npu_init_cnt %d\n",
				host_ctx->npu_init_cnt);
			/* set npu to lowest power level */
			if (npu_set_uc_power_level(npu_dev, 1))
				NPU_WARN("Failed to set uc power level\n");
		}
	} else if (host_ctx->npu_init_cnt > 0) {
		NPU_DBG("disable fw\n");
		disable_fw(npu_dev);
		host_ctx->npu_init_cnt--;
		NPU_DBG("npu_init_cnt %d\n", host_ctx->npu_init_cnt);
	} else {
		NPU_ERR("can't disable fw %d\n", host_ctx->npu_init_cnt);
	}

	return rc;
}

static int npu_set_property(struct npu_client *client,
	unsigned long arg)
{
@@ -1345,9 +1428,19 @@ static int npu_set_property(struct npu_client *client,
	}

	switch (prop.prop_id) {
	case MSM_NPU_PROP_ID_FW_STATE:
		ret = npu_set_fw_state(client,
			(uint32_t)prop.prop_param[0]);
		break;
	case MSM_NPU_PROP_ID_PERF_MODE:
		ret = npu_host_set_perf_mode(client,
			(uint32_t)prop.network_hdl,
			(uint32_t)prop.prop_param[0]);
		break;
	default:
		NPU_ERR("Not supported property %d\n", prop.prop_id);
		ret = -EINVAL;
		ret = npu_host_set_fw_property(client->npu_dev, &prop);
		if (ret)
			NPU_ERR("npu_host_set_fw_property failed\n");
		break;
	}

@@ -1373,6 +1466,10 @@ static int npu_get_property(struct npu_client *client,
	case MSM_NPU_PROP_ID_FW_STATE:
		prop.prop_param[0] = host_ctx->fw_state;
		break;
	case MSM_NPU_PROP_ID_PERF_MODE:
		prop.prop_param[0] = npu_host_get_perf_mode(client,
			(uint32_t)prop.network_hdl);
		break;
	case MSM_NPU_PROP_ID_PERF_MODE_MAX:
		prop.prop_param[0] = npu_dev->pwrctrl.num_pwrlevels;
		break;
@@ -1383,13 +1480,17 @@ static int npu_get_property(struct npu_client *client,
		prop.prop_param[0] = npu_dev->hw_version;
		break;
	default:
		NPU_ERR("Not supported property %d\n", prop.prop_id);
		return -EINVAL;
		ret = npu_host_get_fw_property(client->npu_dev, &prop);
		if (ret) {
			NPU_ERR("npu_host_set_fw_property failed\n");
			return ret;
		}
		break;
	}

	ret = copy_to_user(argp, &prop, sizeof(prop));
	if (ret) {
		pr_err("fail to copy to user\n");
		NPU_ERR("fail to copy to user\n");
		return -EFAULT;
	}

@@ -1749,6 +1850,7 @@ static int npu_of_parse_pwrlevels(struct npu_device *npu_dev,
	pwr->uc_pwrlevel = pwr->max_pwrlevel;
	pwr->perf_mode_override = 0;
	pwr->cdsprm_pwrlevel = pwr->max_pwrlevel;
	pwr->cur_dcvs_activity = pwr->num_pwrlevels;

	return 0;
}
@@ -2119,6 +2221,7 @@ static int npu_probe(struct platform_device *pdev)
		return -EFAULT;

	npu_dev->pdev = pdev;
	mutex_init(&npu_dev->dev_lock);

	platform_set_drvdata(pdev, npu_dev);
	res = platform_get_resource_byname(pdev,
@@ -2178,6 +2281,25 @@ static int npu_probe(struct platform_device *pdev)
	NPU_DBG("cc_io phy address=0x%llx virt=%pK\n",
		res->start, npu_dev->cc_io.base);

	res = platform_get_resource_byname(pdev,
		IORESOURCE_MEM, "tcsr");
	if (!res) {
		NPU_ERR("unable to get tcsr_mutex resource\n");
		rc = -ENODEV;
		goto error_get_dev_num;
	}
	npu_dev->tcsr_io.size = resource_size(res);
	npu_dev->tcsr_io.phy_addr = res->start;
	npu_dev->tcsr_io.base = devm_ioremap(&pdev->dev, res->start,
					npu_dev->tcsr_io.size);
	if (unlikely(!npu_dev->tcsr_io.base)) {
		NPU_ERR("unable to map tcsr\n");
		rc = -ENOMEM;
		goto error_get_dev_num;
	}
	NPU_DBG("tcsr phy address=0x%llx virt=%pK\n",
		res->start, npu_dev->tcsr_io.base);

	res = platform_get_resource_byname(pdev,
		IORESOURCE_MEM, "apss_shared");
	if (!res) {
@@ -2288,8 +2410,6 @@ static int npu_probe(struct platform_device *pdev)
		goto error_driver_init;
	}

	mutex_init(&npu_dev->dev_lock);

	rc = npu_host_init(npu_dev);
	if (rc) {
		NPU_ERR("unable to init host\n");
+7 −0
Original line number Diff line number Diff line
@@ -243,6 +243,13 @@ static int ipc_queue_read(struct npu_device *npu_dev,
		status = -EPERM;
		goto exit;
	}

	if (packet_size > NPU_IPC_BUF_LENGTH) {
		NPU_ERR("Invalid packet size %d\n", packet_size);
		status = -EINVAL;
		goto exit;
	}

	new_read_idx = queue.qhdr_read_idx + packet_size;

	if (new_read_idx < (queue.qhdr_q_size)) {
Loading