91f87568274120309e53997c7b6c980568f52148
[openwrt/staging/linusw.git] /
1 From 7b5e845f3243afd393ede5ca0e5de310115ccf30 Mon Sep 17 00:00:00 2001
2 From: Dom Cobley <popcornmix@gmail.com>
3 Date: Thu, 8 Jun 2023 11:33:08 +0100
4 Subject: [PATCH 0910/1085] perf/raspberry: Add support for 2712 axi
5 performance monitors
6
7 Also handle 2711 correctly which has a different configuration
8 from 2835.
9
10 Signed-off-by: Dom Cobley <popcornmix@gmail.com>
11 ---
12 drivers/perf/raspberrypi_axi_monitor.c | 257 ++++++++++++++++++++++---
13 1 file changed, 225 insertions(+), 32 deletions(-)
14
15 --- a/drivers/perf/raspberrypi_axi_monitor.c
16 +++ b/drivers/perf/raspberrypi_axi_monitor.c
17 @@ -33,7 +33,7 @@
18 #define MAX_BUSES 16
19 #define DEFAULT_SAMPLE_TIME 100
20
21 -#define NUM_BUS_WATCHER_RESULTS 9
22 +#define NUM_BUS_WATCHER_RESULTS 11
23
24 struct bus_watcher_data {
25 union {
26 @@ -48,6 +48,8 @@ struct bus_watcher_data {
27 u32 rtrans;
28 u32 rtwait;
29 u32 rmax;
30 + u32 rpend;
31 + u32 ratrans;
32 };
33 };
34 };
35 @@ -65,6 +67,9 @@ struct rpi_axiperf {
36 /* Sample time spent on for each bus */
37 int sample_time;
38
39 + /* chip specific bus config */
40 + const struct bwconfig_config *config;
41 +
42 /* Now storage for the per monitor settings and the resulting
43 * performance figures
44 */
45 @@ -107,6 +112,7 @@ const int GEN_CTRL;
46
47 const int GEN_CTL_ENABLE_BIT = BIT(0);
48 const int GEN_CTL_RESET_BIT = BIT(1);
49 +const int GEN_CTL_WATCH_BIT = BIT(2);
50
51 /* Bus watcher registers */
52 const int BW_PITCH = 0x40;
53 @@ -136,7 +142,7 @@ const int BW_CTRL_BUS_WATCH_SHIFT;
54 const int BW_CTRL_BUS_WATCH_MASK = GENMASK(5, 0); // 6 bits
55 const int BW_CTRL_BUS_FILTER_SHIFT = 8;
56
57 -const static char *bus_filter_strings[] = {
58 +static const char *bus_filter_strings[] = {
59 "",
60 "CORE0_V",
61 "ICACHE0",
62 @@ -171,9 +177,96 @@ const static char *bus_filter_strings[]
63 "M30"
64 };
65
66 -const int num_bus_filters = ARRAY_SIZE(bus_filter_strings);
67 +static const char * const bus_filter_strings_2711[] = {
68 + "AIO",
69 + "CORE0_V",
70 + "ICACHE0",
71 + "DCACHE0",
72 + "CORE1_V",
73 + "ICACHE1",
74 + "DCACHE1",
75 + "L2_MAIN",
76 + "ARGON",
77 + "PCIE",
78 + "HVS",
79 + "ISP",
80 + "VIDEO_DCT",
81 + "VIDEO_SD2AXI",
82 + "CAM0",
83 + "CAM1",
84 + "DMA0",
85 + "DMA1",
86 + "DMA2",
87 + "JPEG",
88 + "VIDEO_CME",
89 + "TRANSPOSER",
90 + "VIDEO_FME",
91 + "GIGE",
92 + "USB",
93 + "V3D0",
94 + "V3D1",
95 + "V3D2",
96 + "GISB_AXI",
97 + "DEBUG",
98 + "ARM",
99 + "EMMCSTB",
100 +};
101
102 -const static char *system_bus_string[] = {
103 +static const char * const bus_filter_strings_2712[] = {
104 + "",
105 + "VPU_UC0",
106 + "VPU_IC0",
107 + "VPU_DC0",
108 + "VPU_UC1",
109 + "VPU_IC1",
110 + "VPU_DC1",
111 + "VPU_L2",
112 + "DMA2",
113 + "VPU_DEBUG",
114 + "ARM",
115 + "DMA0",
116 + "DMA1",
117 + "RAAGA",
118 + "BBSI",
119 + "PCIE0",
120 + "PCIE1",
121 + "PCIE2",
122 + "UMR",
123 + "SAGE",
124 + "HVDP",
125 + "BSP",
126 + "HVS",
127 + "HVS_WMK",
128 + "MOP0",
129 + "MOP1",
130 + "MBVN",
131 + "DSI",
132 + "XPT",
133 + "EMMC0",
134 + "GENET",
135 + "USB",
136 + "ARGON",
137 + "UNICAM",
138 + "PISP",
139 + "PISPFE",
140 + "JPEG",
141 + "EMMC1",
142 + "EMMC2",
143 + "TRC",
144 + "BSTM0",
145 + "BSTM1",
146 + "BSTM0_SEC",
147 + "BSTM1_SEC",
148 + "AIO",
149 + "MAP",
150 + "SYS_DMA",
151 + "MMUCACHE0",
152 + "MMUCACHE1",
153 + "MPUCACHE0",
154 + "MPUCACHE1",
155 +};
156 +
157 +static const char *system_bus_string[] = {
158 "DMA_L2",
159 "TRANS",
160 "JPEG",
161 @@ -192,9 +285,38 @@ const static char *system_bus_string[] =
162 "CPU_L2"
163 };
164
165 -const int num_system_buses = ARRAY_SIZE(system_bus_string);
166 +static const char * const system_bus_string_2711[] = {
167 + "DMA_L2",
168 + "TRANS",
169 + "JPEG",
170 + "VPU_UC",
171 + "DMA_UC",
172 + "SYSTEM_L2",
173 + "HVS",
174 + "ARGON",
175 + "H264",
176 + "PERIPHERAL",
177 + "ARM_UC",
178 + "ARM_L2",
179 +};
180 +
181 +static const char * const system_bus_string_2712[] = {
182 + "VPU_UC",
183 + "DISPLAY_TOP",
184 + "V3D",
185 + "ARM",
186 + "XPT",
187 + "BSTM_TOP",
188 + "PCIE_01",
189 + "ARGON_TOP",
190 + "ARB3",
191 + "SRC",
192 + "HVDP",
193 + "PER",
194 + "SYSTEM_L2",
195 +};
196
197 -const static char *vpu_bus_string[] = {
198 +static const char *vpu_bus_string[] = {
199 "VPU1_D_L2",
200 "VPU0_D_L2",
201 "VPU1_I_L2",
202 @@ -213,7 +335,66 @@ const static char *vpu_bus_string[] = {
203 "L2_IN"
204 };
205
206 -const int num_vpu_buses = ARRAY_SIZE(vpu_bus_string);
207 +static const char * const vpu_bus_string_2711[] = {
208 + "VPU1_D_L2",
209 + "VPU0_D_L2",
210 + "VPU1_I_L2",
211 + "VPU0_I_L2",
212 + "SYSTEM_L2",
213 + "DMA_L2",
214 + "VPU1_D_UC",
215 + "VPU0_D_UC",
216 + "VPU1_I_UC",
217 + "VPU0_I_UC",
218 + "VPU_UC",
219 + "L2_OUT",
220 + "DMA_UC",
221 + "L2_IN"
222 +};
223 +
224 +static const char * const vpu_bus_string_2712[] = {
225 + "VPU1_D_L2",
226 + "VPU0_D_L2",
227 + "VPU1_I_L2",
228 + "VPU0_I_L2",
229 + "SYSTEM_L2",
230 + "DMA_L2",
231 + "VPU1_D_UC",
232 + "VPU0_D_UC",
233 + "VPU1_I_UC",
234 + "VPU0_I_UC",
235 + "VPU_UC",
236 + "L2_OUT",
237 + "DMA_UC",
238 + "L2_IN"
239 +};
240 +
241 +struct bwconfig_config {
242 + const char * const *bus_filter_strings;
243 + const int num_bus_filters;
244 + const char * const *system_bus_string;
245 + const int num_system_buses;
246 + const char * const *vpu_bus_string;
247 + const int num_vpu_buses;
248 +};
249 +
250 +static const struct bwconfig_config config_2835 = {
251 + bus_filter_strings, ARRAY_SIZE(bus_filter_strings),
252 + system_bus_string, ARRAY_SIZE(system_bus_string),
253 + vpu_bus_string, ARRAY_SIZE(vpu_bus_string),
254 +};
255 +
256 +static const struct bwconfig_config config_2711 = {
257 + bus_filter_strings_2711, ARRAY_SIZE(bus_filter_strings_2711),
258 + system_bus_string_2711, ARRAY_SIZE(system_bus_string_2711),
259 + vpu_bus_string_2711, ARRAY_SIZE(vpu_bus_string_2711),
260 +};
261 +
262 +static const struct bwconfig_config config_2712 = {
263 + bus_filter_strings_2712, ARRAY_SIZE(bus_filter_strings_2712),
264 + system_bus_string_2712, ARRAY_SIZE(system_bus_string_2712),
265 + vpu_bus_string_2712, ARRAY_SIZE(vpu_bus_string_2712),
266 +};
267
268 const static char *monitor_name[] = {
269 "System",
270 @@ -233,10 +414,10 @@ static inline u32 read_reg(int monitor,
271 static void read_bus_watcher(int monitor, int watcher, u32 *results)
272 {
273 if (state->monitor[monitor].use_mailbox_interface) {
274 - /* We have 9 results, plus the overheads of start address and
275 - * length So 11 u32 to define
276 + /* We have NUM_BUS_WATCHER_RESULTS results, plus the overheads
277 + * of start address and length
278 */
279 - u32 tmp[11];
280 + u32 tmp[NUM_BUS_WATCHER_RESULTS+2];
281 int err;
282
283 tmp[0] = (u32)(uintptr_t)(state->monitor[monitor].base_address + watcher
284 @@ -352,7 +533,7 @@ static void monitor(struct rpi_axiperf *
285 }
286
287 /* start monitoring */
288 - set_monitor_control(monitor, GEN_CTL_ENABLE_BIT);
289 + set_monitor_control(monitor, GEN_CTL_ENABLE_BIT | GEN_CTL_WATCH_BIT);
290 }
291
292 mutex_unlock(&state->lock);
293 @@ -409,11 +590,12 @@ static ssize_t myreader(struct file *fp,
294 int buff_size = INIT_BUFF_SIZE;
295 char *p;
296 typeof(state->monitor[0]) *mon = &(state->monitor[idx]);
297 + const struct bwconfig_config *config = state->config;
298
299 if (idx < 0 || idx > NUM_MONITORS)
300 idx = 0;
301
302 - num_buses = idx == SYSTEM_MONITOR ? num_system_buses : num_vpu_buses;
303 + num_buses = idx == SYSTEM_MONITOR ? config->num_system_buses : config->num_vpu_buses;
304
305 string_buffer = kmalloc(buff_size, GFP_KERNEL);
306
307 @@ -428,17 +610,17 @@ static ssize_t myreader(struct file *fp,
308 mutex_lock(&state->lock);
309
310 if (mon->bus_filter) {
311 - int filt = min(mon->bus_filter & 0x1f, num_bus_filters);
312 + int filt = min(mon->bus_filter & 0x1f, config->num_bus_filters);
313
314 cnt = snprintf(p, buff_size,
315 "\nMonitoring transactions from %s only\n",
316 - bus_filter_strings[filt]);
317 + config->bus_filter_strings[filt]);
318 p += cnt;
319 buff_size -= cnt;
320 }
321
322 - cnt = snprintf(p, buff_size, " Bus | Atrans Atwait AMax Wtrans Wtwait WMax Rtrans Rtwait RMax\n"
323 - "======================================================================================================\n");
324 + cnt = snprintf(p, buff_size, " Bus | Atrans Atwait AMax Wtrans Wtwait WMax Rtrans Rtwait RMax RPend RAtrans\n"
325 + "===========================================================================================================================\n");
326
327 if (cnt >= buff_size)
328 goto done;
329 @@ -446,25 +628,29 @@ static ssize_t myreader(struct file *fp,
330 p += cnt;
331 buff_size -= cnt;
332
333 +#define M(x) ((x) >= 1000000000 ? (x)/1000000 : (x) >= 1000 ? (x)/1000 : (x))
334 +#define N(x) ((x) >= 1000000000 ? 'M' : (x) >= 1000 ? 'K' : ' ')
335 +
336 for (i = 0; i < num_buses; i++) {
337 if (mon->bus_enabled & (1 << i)) {
338 -#define DIVIDER (1024)
339 typeof(mon->results[0]) *res = &(mon->results[i]);
340
341 cnt = snprintf(p, buff_size,
342 - "%10s | %8uK %8uK %8uK %8uK %8uK %8uK %8uK %8uK %8uK\n",
343 + "%11s | %8u%c %8u%c %8u%c %8u%c %8u%c %8u%c %8u%c %8u%c %8u%c %8u%c %8u%c\n",
344 idx == SYSTEM_MONITOR ?
345 - system_bus_string[i] :
346 - vpu_bus_string[i],
347 - res->atrans/DIVIDER,
348 - res->atwait/DIVIDER,
349 - res->amax/DIVIDER,
350 - res->wtrans/DIVIDER,
351 - res->wtwait/DIVIDER,
352 - res->wmax/DIVIDER,
353 - res->rtrans/DIVIDER,
354 - res->rtwait/DIVIDER,
355 - res->rmax/DIVIDER
356 + config->system_bus_string[i] :
357 + config->vpu_bus_string[i],
358 + M(res->atrans), N(res->atrans),
359 + M(res->atwait), N(res->atwait),
360 + M(res->amax), N(res->amax),
361 + M(res->wtrans), N(res->wtrans),
362 + M(res->wtwait), N(res->wtwait),
363 + M(res->wmax), N(res->wmax),
364 + M(res->rtrans), N(res->rtrans),
365 + M(res->rtwait), N(res->rtwait),
366 + M(res->rmax), N(res->rmax),
367 + M(res->rpend), N(res->rpend),
368 + M(res->ratrans), N(res->ratrans)
369 );
370 if (cnt >= buff_size)
371 goto done;
372 @@ -526,6 +712,10 @@ static int rpi_axiperf_probe(struct plat
373 if (!state)
374 return -ENOMEM;
375
376 + state->config = of_device_get_match_data(dev);
377 + if (!state->config)
378 + return -EINVAL;
379 +
380 /* Get the firmware handle for future rpi-firmware-xxx calls */
381 fw_node = of_parse_phandle(np, "firmware", 0);
382 if (!fw_node) {
383 @@ -612,9 +802,12 @@ static int rpi_axiperf_remove(struct pla
384 }
385
386 static const struct of_device_id rpi_axiperf_match[] = {
387 - {
388 - .compatible = "brcm,bcm2835-axiperf",
389 - },
390 + { .compatible = "brcm,bcm2835-axiperf",
391 + .data = &config_2835 },
392 + { .compatible = "brcm,bcm2711-axiperf",
393 + .data = &config_2711 },
394 + { .compatible = "brcm,bcm2712-axiperf",
395 + .data = &config_2712 },
396 {},
397 };
398 MODULE_DEVICE_TABLE(of, rpi_axiperf_match);