xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/bifrost/mali_kbase_pbha_debugfs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
2 /*
3  *
4  * (C) COPYRIGHT 2021-2022 ARM Limited. All rights reserved.
5  *
6  * This program is free software and is provided to you under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation, and any use by you of this program is subject to the terms
9  * of such GNU license.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you can access it online at
18  * http://www.gnu.org/licenses/gpl-2.0.html.
19  *
20  */
21 
22 #include "mali_kbase_pbha_debugfs.h"
23 #include "mali_kbase_pbha.h"
24 #include <device/mali_kbase_device.h>
25 #include <mali_kbase_reset_gpu.h>
26 #include <mali_kbase.h>
27 
28 #if MALI_USE_CSF
29 #include "backend/gpu/mali_kbase_pm_internal.h"
30 #endif
31 
int_id_overrides_show(struct seq_file * sfile,void * data)32 static int int_id_overrides_show(struct seq_file *sfile, void *data)
33 {
34 	struct kbase_device *kbdev = sfile->private;
35 	int i;
36 
37 	kbase_pm_context_active(kbdev);
38 
39 	/* Minimal header for readability */
40 	seq_puts(sfile, "// R   W\n");
41 	for (i = 0; i < SYSC_ALLOC_COUNT; ++i) {
42 		int j;
43 		u32 reg = kbase_reg_read(kbdev, GPU_CONTROL_REG(SYSC_ALLOC(i)));
44 
45 		for (j = 0; j < sizeof(u32); ++j) {
46 			u8 r_val;
47 			u8 w_val;
48 
49 			switch (j) {
50 			case 0:
51 				r_val = SYSC_ALLOC_R_SYSC_ALLOC0_GET(reg);
52 				w_val = SYSC_ALLOC_W_SYSC_ALLOC0_GET(reg);
53 				break;
54 			case 1:
55 				r_val = SYSC_ALLOC_R_SYSC_ALLOC1_GET(reg);
56 				w_val = SYSC_ALLOC_W_SYSC_ALLOC1_GET(reg);
57 				break;
58 			case 2:
59 				r_val = SYSC_ALLOC_R_SYSC_ALLOC2_GET(reg);
60 				w_val = SYSC_ALLOC_W_SYSC_ALLOC2_GET(reg);
61 				break;
62 			case 3:
63 				r_val = SYSC_ALLOC_R_SYSC_ALLOC3_GET(reg);
64 				w_val = SYSC_ALLOC_W_SYSC_ALLOC3_GET(reg);
65 				break;
66 			}
67 			seq_printf(sfile, "%2zu 0x%x 0x%x\n",
68 				   (i * sizeof(u32)) + j, r_val, w_val);
69 		}
70 	}
71 	kbase_pm_context_idle(kbdev);
72 
73 	return 0;
74 }
75 
int_id_overrides_write(struct file * file,const char __user * ubuf,size_t count,loff_t * ppos)76 static ssize_t int_id_overrides_write(struct file *file,
77 				      const char __user *ubuf, size_t count,
78 				      loff_t *ppos)
79 {
80 	struct seq_file *sfile = file->private_data;
81 	struct kbase_device *kbdev = sfile->private;
82 	char raw_str[128];
83 	unsigned int id;
84 	unsigned int r_val;
85 	unsigned int w_val;
86 
87 	if (count >= sizeof(raw_str))
88 		return -E2BIG;
89 	if (copy_from_user(raw_str, ubuf, count))
90 		return -EINVAL;
91 	raw_str[count] = '\0';
92 
93 	if (sscanf(raw_str, "%u %x %x", &id, &r_val, &w_val) != 3)
94 		return -EINVAL;
95 
96 	if (kbase_pbha_record_settings(kbdev, true, id, r_val, w_val))
97 		return -EINVAL;
98 
99 	/* This is a debugfs config write, so reset GPU such that changes take effect ASAP */
100 	kbase_pm_context_active(kbdev);
101 	if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_NONE))
102 		kbase_reset_gpu(kbdev);
103 	kbase_pm_context_idle(kbdev);
104 
105 	return count;
106 }
107 
int_id_overrides_open(struct inode * in,struct file * file)108 static int int_id_overrides_open(struct inode *in, struct file *file)
109 {
110 	return single_open(file, int_id_overrides_show, in->i_private);
111 }
112 
113 #if MALI_USE_CSF
114 /**
115  * propagate_bits_show - Read PBHA bits from L2_CONFIG out to debugfs.
116  *
117  * @sfile: The debugfs entry.
118  * @data: Data associated with the entry.
119  *
120  * Return: 0 in all cases.
121  */
propagate_bits_show(struct seq_file * sfile,void * data)122 static int propagate_bits_show(struct seq_file *sfile, void *data)
123 {
124 	struct kbase_device *kbdev = sfile->private;
125 	u32 l2_config_val;
126 
127 	kbase_csf_scheduler_pm_active(kbdev);
128 	kbase_pm_wait_for_l2_powered(kbdev);
129 	l2_config_val = L2_CONFIG_PBHA_HWU_GET(kbase_reg_read(kbdev, GPU_CONTROL_REG(L2_CONFIG)));
130 	kbase_csf_scheduler_pm_idle(kbdev);
131 
132 	seq_printf(sfile, "PBHA Propagate Bits: 0x%x\n", l2_config_val);
133 	return 0;
134 }
135 
propagate_bits_open(struct inode * in,struct file * file)136 static int propagate_bits_open(struct inode *in, struct file *file)
137 {
138 	return single_open(file, propagate_bits_show, in->i_private);
139 }
140 
141 /**
142  * propagate_bits_write - Write input value from debugfs to PBHA bits of L2_CONFIG register.
143  *
144  * @file:     Pointer to file struct of debugfs node.
145  * @ubuf:     Pointer to user buffer with value to be written.
146  * @count:    Size of user buffer.
147  * @ppos:     Not used.
148  *
149  * Return: Size of buffer passed in when successful, but error code E2BIG/EINVAL otherwise.
150  */
propagate_bits_write(struct file * file,const char __user * ubuf,size_t count,loff_t * ppos)151 static ssize_t propagate_bits_write(struct file *file, const char __user *ubuf, size_t count,
152 				    loff_t *ppos)
153 {
154 	struct seq_file *sfile = file->private_data;
155 	struct kbase_device *kbdev = sfile->private;
156 	/* 32 characters should be enough for the input string in any base */
157 	char raw_str[32];
158 	unsigned long propagate_bits;
159 
160 	if (count >= sizeof(raw_str))
161 		return -E2BIG;
162 	if (copy_from_user(raw_str, ubuf, count))
163 		return -EINVAL;
164 	raw_str[count] = '\0';
165 	if (kstrtoul(raw_str, 0, &propagate_bits))
166 		return -EINVAL;
167 
168 	/* Check propagate_bits input argument does not
169 	 * exceed the maximum size of the propagate_bits mask.
170 	 */
171 	if (propagate_bits > (L2_CONFIG_PBHA_HWU_MASK >> L2_CONFIG_PBHA_HWU_SHIFT))
172 		return -EINVAL;
173 	/* Cast to u8 is safe as check is done already to ensure size is within
174 	 * correct limits.
175 	 */
176 	kbdev->pbha_propagate_bits = (u8)propagate_bits;
177 
178 	/* GPU Reset will set new values in L2 config */
179 	if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_NONE)) {
180 		kbase_reset_gpu(kbdev);
181 		kbase_reset_gpu_wait(kbdev);
182 	}
183 
184 	return count;
185 }
186 
187 static const struct file_operations pbha_propagate_bits_fops = {
188 	.owner = THIS_MODULE,
189 	.open = propagate_bits_open,
190 	.read = seq_read,
191 	.write = propagate_bits_write,
192 	.llseek = seq_lseek,
193 	.release = single_release,
194 };
195 #endif /* MALI_USE_CSF */
196 
197 static const struct file_operations pbha_int_id_overrides_fops = {
198 	.owner = THIS_MODULE,
199 	.open = int_id_overrides_open,
200 	.read = seq_read,
201 	.write = int_id_overrides_write,
202 	.llseek = seq_lseek,
203 	.release = single_release,
204 };
205 
kbase_pbha_debugfs_init(struct kbase_device * kbdev)206 void kbase_pbha_debugfs_init(struct kbase_device *kbdev)
207 {
208 	if (kbasep_pbha_supported(kbdev)) {
209 		const mode_t mode = 0644;
210 		struct dentry *debugfs_pbha_dir = debugfs_create_dir(
211 			"pbha", kbdev->mali_debugfs_directory);
212 
213 		if (IS_ERR_OR_NULL(debugfs_pbha_dir)) {
214 			dev_err(kbdev->dev,
215 				"Couldn't create mali debugfs page-based hardware attributes directory\n");
216 			return;
217 		}
218 
219 		debugfs_create_file("int_id_overrides", mode, debugfs_pbha_dir,
220 				    kbdev, &pbha_int_id_overrides_fops);
221 #if MALI_USE_CSF
222 		if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PBHA_HWU))
223 			debugfs_create_file("propagate_bits", mode, debugfs_pbha_dir, kbdev,
224 					    &pbha_propagate_bits_fops);
225 #endif /* MALI_USE_CSF */
226 	}
227 }
228