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

Commit 67732f97 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: VPU: Add feature to write csr registers through debugfs"

parents 3819e9d0 87bc1446
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -2440,6 +2440,19 @@ size_t vpu_hw_print_queues(char *buf, size_t buf_size)
	return vpu_hfi_print_queues(buf, buf_size);
}

int vpu_hw_write_csr_reg(u32 off, u32 val)
{
	int rc;
	struct vpu_channel_hal *ch_hal = &g_vpu_ch_hal;

	if (VPU_IS_UP(ch_hal->mode))
		rc = vpu_hfi_write_csr_reg(off, val);
	else
		rc = -EIO; /* firmware down */

	return rc;
}

int vpu_hw_dump_csr_regs(char *buf, size_t buf_size)
{
	int rc = 0;
+9 −0
Original line number Diff line number Diff line
@@ -354,6 +354,15 @@ void vpu_hw_debug_off(void);
 */
size_t vpu_hw_print_queues(char *buf, size_t buf_size);

/**
 * vpu_hw_write_csr_reg() - write a value to a CSR register
 * @off:	offset (from base) to write
 * @val:	value to write
 *
 * Return: 0 on success, -ve on failure
 */
int vpu_hw_write_csr_reg(u32 off, u32 val);

/**
 * vpu_hw_dump_csr_regs() - dump the contents of the VPU CSR registers into buf
 * @buf:	debug buffer to write into
+35 −1
Original line number Diff line number Diff line
@@ -254,9 +254,43 @@ static ssize_t read_csr_regs(struct file *file, char __user *user_buf,
	return ret;
}

int write_csr_reg(struct file *file, const char __user *user_buf,
	size_t count, loff_t *ppos)
{
	int ret;
	int len;
	char buf[24];
	char *sptr, *token;
	u32 reg_off;
	u32 reg_val;

	len = min(count, sizeof(buf) - 1);
	if (copy_from_user(buf, user_buf, len))
		return -EFAULT;
	buf[len] = '\0';

	sptr = buf;
	token = strsep(&sptr, ":");
	if (!token)
		return -EINVAL;

	if (kstrtou32(token, 0, &reg_off))
		return -EINVAL;

	if (kstrtou32(sptr, 0, &reg_val))
		return -EINVAL;

	ret = vpu_hw_write_csr_reg(reg_off, reg_val);
	if (ret)
		return ret;

	return count;
}

static const struct file_operations csr_regs_ops = {
	.open = simple_open,
	.read = read_csr_regs,
	.write = write_csr_reg,
};

static void debug_on(void)
@@ -582,7 +616,7 @@ struct dentry *init_vpu_debugfs(struct vpu_dev_core *core)
	}

	/* create csr regs file */
	attr = debugfs_create_file("csr_regs", S_IRUGO, root, NULL,
	attr = debugfs_create_file("csr_regs", RW_MODE, root, NULL,
			&csr_regs_ops);
	if (IS_ERR_OR_NULL(attr)) {
		pr_err("Failed to create csr regs attribute\n");
+69 −12
Original line number Diff line number Diff line
@@ -131,11 +131,6 @@ struct vpu_hfi_device {
	struct vpu_platform_resources	*platform_resouce;
};

struct addr_range {
	u32 start;
	u32 end;
};

/* global */
static struct vpu_hfi_device g_hfi_device;

@@ -1202,22 +1197,84 @@ size_t vpu_hfi_print_queues(char *buf, size_t buf_size)
	return strlcat(buf, "", buf_size);
}

static struct addr_range csr_skip_addrs[] = {
struct addr_range {
	u32 start;
	u32 end;
};

static struct addr_range restricted_csr_addrs[] = {
	/* start and end offsets of inaccessible address ranges */
	{ 0x0000, 0x000F },
	{ 0x0018, 0x001B },
	{ 0x0020, 0x0037 },
	{ 0x00C0, 0x00DF },
	{ 0x01A0, 0x01AF },
	{ 0x01A0, 0x0FFF },
};

/* registers which should not be written through debugfs
 * (may interfere with the normal operation of the driver
 * which makes use of these registers)
 */
static u32 no_write_csr_regs[] = {
	VPU_CSR_APPS_SGI_STS,
	VPU_CSR_APPS_SGI_CLR,
	VPU_CSR_FW_SGI_EN_SET,
	VPU_CSR_FW_SGI_EN_CLR,
	VPU_CSR_FW_SGI_FORCELEVEL,
	VPU_CSR_FW_SGI_STS,
	VPU_CSR_FW_SGI_CLR,
	VPU_CSR_FW_SGI_TRIG,
	VPU_CSR_SW_SCRATCH0_STS,
	VPU_CSR_SW_SCRATCH1_QTBL_INFO,
	VPU_CSR_SW_SCRATCH2_QTBL_ADDR,
};

int vpu_hfi_write_csr_reg(u32 off, u32 val)
{
	struct vpu_hfi_device *hdevice = &g_hfi_device;
	u32 v_base = (u32)(hdevice->reg_base);
	u32 p_base = (u32)(hdevice->platform_resouce->register_base_phy);
	u32 write_addr = v_base + off;
	u32 last_addr = v_base + VPU_CSR_LAST_REG;
	int i;

	if (write_addr > last_addr || write_addr < v_base) {
		pr_err("attempting to write outside of addr range\n");
		return -EFAULT;
	}

	if (off % 4) {
		pr_err("addr must be 32-bit word-aligned\n");
		return -EFAULT;
	}

	for (i = 0; i < ARRAY_SIZE(no_write_csr_regs); i++) {
		if (off == no_write_csr_regs[i]) {
			pr_err("not allowed write this reg through debugfs\n");
			return -EFAULT;
		}
	}

	for (i = 0; i < ARRAY_SIZE(restricted_csr_addrs); i++) {
		if (off >= restricted_csr_addrs[i].start
			&& off <= restricted_csr_addrs[i].end) {
			pr_err("attempting to write restricted addr range\n");
			return -EFAULT;
		}
	}

	raw_hfi_reg_write(write_addr, val);

	pr_debug("wrote val: 0x%08x at addr: 0x%08x\n", val, p_base + off);
	return 0;
}

int vpu_hfi_dump_csr_regs(char *buf, size_t buf_size)
{
	struct vpu_hfi_device *hdevice = &g_hfi_device;
	u32 v_base = (u32)(hdevice->reg_base);
	u32 p_base = (u32)(hdevice->platform_resouce->register_base_phy);
	u32 last_addr = v_base +
			csr_skip_addrs[ARRAY_SIZE(csr_skip_addrs) - 1].end;
	u32 last_addr = v_base + VPU_CSR_LAST_REG;
	u32 addr;
	char temp[32];
	int i = 0, skip = 0, temp_size = 32;
@@ -1232,8 +1289,8 @@ int vpu_hfi_dump_csr_regs(char *buf, size_t buf_size)
			strlcat(buf, temp, buf_size);
		}

		if ((addr - v_base) >= csr_skip_addrs[i].start &&
				(addr - v_base) <= csr_skip_addrs[i].end) {
		if ((addr - v_base) >= restricted_csr_addrs[i].start &&
			(addr - v_base) <= restricted_csr_addrs[i].end) {
			skip = 1;
			snprintf(temp, temp_size, " xxxxxxxxxx");
			strlcat(buf, temp, buf_size);
@@ -1244,7 +1301,7 @@ int vpu_hfi_dump_csr_regs(char *buf, size_t buf_size)
			}

			snprintf(temp, temp_size, " 0x%08x",
					readl_relaxed(addr + 0 * sizeof(u32)));
					raw_hfi_reg_read(addr));
			strlcat(buf, temp, buf_size);
		}

+8 −0
Original line number Diff line number Diff line
@@ -119,6 +119,14 @@ void vpu_hfi_set_pil_timeout(u32 pil_timeout);
 */
size_t vpu_hfi_print_queues(char *buf, size_t buf_size);

/**
 * vpu_hfi_write_csr_reg() - write a value into a CSR register
 * @off:	offset (from base) to write
 * @val:	value to write
 *
 * Return: 0 on success, -ve on failure
 */
int vpu_hfi_write_csr_reg(u32 off, u32 val);

/**
 * vpu_hfi_dump_csr_regs() - dump the contents of the VPU CSR registers
Loading