Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
 *
 * (C) COPYRIGHT 2021-2022 ARM Limited. All rights reserved.
 *
 * This program is free software and is provided to you under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation, and any use by you of this program is subject to the terms
 * of such GNU license.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you can access it online at
 * http://www.gnu.org/licenses/gpl-2.0.html.
 *
 */

#include "mali_kbase_pbha_debugfs.h"

#include "mali_kbase_pbha.h"

#include <device/mali_kbase_device.h>
#include <mali_kbase_reset_gpu.h>
#include <mali_kbase.h>

static int int_id_overrides_show(struct seq_file *sfile, void *data)
{
	struct kbase_device *kbdev = sfile->private;
	int i;

	kbase_pm_context_active(kbdev);

	/* Minimal header for readability */
	seq_puts(sfile, "// R   W\n");
	for (i = 0; i < SYSC_ALLOC_COUNT; ++i) {
		int j;
		u32 reg = kbase_reg_read(kbdev, GPU_CONTROL_REG(SYSC_ALLOC(i)));

		for (j = 0; j < sizeof(u32); ++j) {
			u8 r_val;
			u8 w_val;

			switch (j) {
			case 0:
				r_val = SYSC_ALLOC_R_SYSC_ALLOC0_GET(reg);
				w_val = SYSC_ALLOC_W_SYSC_ALLOC0_GET(reg);
				break;
			case 1:
				r_val = SYSC_ALLOC_R_SYSC_ALLOC1_GET(reg);
				w_val = SYSC_ALLOC_W_SYSC_ALLOC1_GET(reg);
				break;
			case 2:
				r_val = SYSC_ALLOC_R_SYSC_ALLOC2_GET(reg);
				w_val = SYSC_ALLOC_W_SYSC_ALLOC2_GET(reg);
				break;
			case 3:
				r_val = SYSC_ALLOC_R_SYSC_ALLOC3_GET(reg);
				w_val = SYSC_ALLOC_W_SYSC_ALLOC3_GET(reg);
				break;
			}
			seq_printf(sfile, "%2zu 0x%x 0x%x\n",
				   (i * sizeof(u32)) + j, r_val, w_val);
		}
	}
	kbase_pm_context_idle(kbdev);

	return 0;
}

static ssize_t int_id_overrides_write(struct file *file,
				      const char __user *ubuf, size_t count,
				      loff_t *ppos)
{
	struct seq_file *sfile = file->private_data;
	struct kbase_device *kbdev = sfile->private;
	char raw_str[128];
	unsigned int id;
	unsigned int r_val;
	unsigned int w_val;

	if (count >= sizeof(raw_str))
		return -E2BIG;
	if (copy_from_user(raw_str, ubuf, count))
		return -EINVAL;
	raw_str[count] = '\0';

	if (sscanf(raw_str, "%u %x %x", &id, &r_val, &w_val) != 3)
		return -EINVAL;

	if (kbase_pbha_record_settings(kbdev, true, id, r_val, w_val))
		return -EINVAL;

	/* This is a debugfs config write, so reset GPU such that changes take effect ASAP */
	kbase_pm_context_active(kbdev);
	if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_NONE))
		kbase_reset_gpu(kbdev);
	kbase_pm_context_idle(kbdev);

	return count;
}

static int int_id_overrides_open(struct inode *in, struct file *file)
{
	return single_open(file, int_id_overrides_show, in->i_private);
}

static const struct file_operations pbha_int_id_overrides_fops = {
	.owner = THIS_MODULE,
	.open = int_id_overrides_open,
	.read = seq_read,
	.write = int_id_overrides_write,
	.llseek = seq_lseek,
	.release = single_release,
};

void kbase_pbha_debugfs_init(struct kbase_device *kbdev)
{
	if (kbasep_pbha_supported(kbdev)) {
		const mode_t mode = 0644;
		struct dentry *debugfs_pbha_dir = debugfs_create_dir(
			"pbha", kbdev->mali_debugfs_directory);

		if (IS_ERR_OR_NULL(debugfs_pbha_dir)) {
			dev_err(kbdev->dev,
				"Couldn't create mali debugfs page-based hardware attributes directory\n");
			return;
		}

		debugfs_create_file("int_id_overrides", mode, debugfs_pbha_dir,
				    kbdev, &pbha_int_id_overrides_fops);
	}
}