1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2017 Etnaviv Project
4 * Copyright (C) 2017 Zodiac Inflight Innovations
7 #include "common.xml.h"
8 #include "etnaviv_gpu.h"
9 #include "etnaviv_perfmon.h"
10 #include "state_hi.xml.h"
12 struct etnaviv_pm_domain
;
14 struct etnaviv_pm_signal
{
18 u32 (*sample
)(struct etnaviv_gpu
*gpu
,
19 const struct etnaviv_pm_domain
*domain
,
20 const struct etnaviv_pm_signal
*signal
);
23 struct etnaviv_pm_domain
{
26 /* profile register */
31 const struct etnaviv_pm_signal
*signal
;
34 struct etnaviv_pm_domain_meta
{
36 const struct etnaviv_pm_domain
*domains
;
40 static u32
perf_reg_read(struct etnaviv_gpu
*gpu
,
41 const struct etnaviv_pm_domain
*domain
,
42 const struct etnaviv_pm_signal
*signal
)
44 gpu_write(gpu
, domain
->profile_config
, signal
->data
);
46 return gpu_read(gpu
, domain
->profile_read
);
49 static u32
pipe_reg_read(struct etnaviv_gpu
*gpu
,
50 const struct etnaviv_pm_domain
*domain
,
51 const struct etnaviv_pm_signal
*signal
)
53 u32 clock
= gpu_read(gpu
, VIVS_HI_CLOCK_CONTROL
);
57 for (i
= 0; i
< gpu
->identity
.pixel_pipes
; i
++) {
58 clock
&= ~(VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK
);
59 clock
|= VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE(i
);
60 gpu_write(gpu
, VIVS_HI_CLOCK_CONTROL
, clock
);
61 gpu_write(gpu
, domain
->profile_config
, signal
->data
);
62 value
+= gpu_read(gpu
, domain
->profile_read
);
65 /* switch back to pixel pipe 0 to prevent GPU hang */
66 clock
&= ~(VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK
);
67 clock
|= VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE(0);
68 gpu_write(gpu
, VIVS_HI_CLOCK_CONTROL
, clock
);
73 static u32
hi_total_cycle_read(struct etnaviv_gpu
*gpu
,
74 const struct etnaviv_pm_domain
*domain
,
75 const struct etnaviv_pm_signal
*signal
)
77 u32 reg
= VIVS_HI_PROFILE_TOTAL_CYCLES
;
79 if (gpu
->identity
.model
== chipModel_GC880
||
80 gpu
->identity
.model
== chipModel_GC2000
||
81 gpu
->identity
.model
== chipModel_GC2100
)
82 reg
= VIVS_MC_PROFILE_CYCLE_COUNTER
;
84 return gpu_read(gpu
, reg
);
87 static u32
hi_total_idle_cycle_read(struct etnaviv_gpu
*gpu
,
88 const struct etnaviv_pm_domain
*domain
,
89 const struct etnaviv_pm_signal
*signal
)
91 u32 reg
= VIVS_HI_PROFILE_IDLE_CYCLES
;
93 if (gpu
->identity
.model
== chipModel_GC880
||
94 gpu
->identity
.model
== chipModel_GC2000
||
95 gpu
->identity
.model
== chipModel_GC2100
)
96 reg
= VIVS_HI_PROFILE_TOTAL_CYCLES
;
98 return gpu_read(gpu
, reg
);
101 static const struct etnaviv_pm_domain doms_3d
[] = {
104 .profile_read
= VIVS_MC_PROFILE_HI_READ
,
105 .profile_config
= VIVS_MC_PROFILE_CONFIG2
,
107 .signal
= (const struct etnaviv_pm_signal
[]) {
116 &hi_total_idle_cycle_read
119 "AXI_CYCLES_READ_REQUEST_STALLED",
120 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_READ_REQUEST_STALLED
,
124 "AXI_CYCLES_WRITE_REQUEST_STALLED",
125 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_REQUEST_STALLED
,
129 "AXI_CYCLES_WRITE_DATA_STALLED",
130 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_DATA_STALLED
,
137 .profile_read
= VIVS_MC_PROFILE_PE_READ
,
138 .profile_config
= VIVS_MC_PROFILE_CONFIG0
,
140 .signal
= (const struct etnaviv_pm_signal
[]) {
142 "PIXEL_COUNT_KILLED_BY_COLOR_PIPE",
143 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_COLOR_PIPE
,
147 "PIXEL_COUNT_KILLED_BY_DEPTH_PIPE",
148 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_DEPTH_PIPE
,
152 "PIXEL_COUNT_DRAWN_BY_COLOR_PIPE",
153 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_COLOR_PIPE
,
157 "PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE",
158 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE
,
165 .profile_read
= VIVS_MC_PROFILE_SH_READ
,
166 .profile_config
= VIVS_MC_PROFILE_CONFIG0
,
168 .signal
= (const struct etnaviv_pm_signal
[]) {
171 VIVS_MC_PROFILE_CONFIG0_SH_SHADER_CYCLES
,
176 VIVS_MC_PROFILE_CONFIG0_SH_PS_INST_COUNTER
,
180 "RENDERED_PIXEL_COUNTER",
181 VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_PIXEL_COUNTER
,
186 VIVS_MC_PROFILE_CONFIG0_SH_VS_INST_COUNTER
,
190 "RENDERED_VERTICE_COUNTER",
191 VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_VERTICE_COUNTER
,
195 "VTX_BRANCH_INST_COUNTER",
196 VIVS_MC_PROFILE_CONFIG0_SH_VTX_BRANCH_INST_COUNTER
,
200 "VTX_TEXLD_INST_COUNTER",
201 VIVS_MC_PROFILE_CONFIG0_SH_VTX_TEXLD_INST_COUNTER
,
205 "PXL_BRANCH_INST_COUNTER",
206 VIVS_MC_PROFILE_CONFIG0_SH_PXL_BRANCH_INST_COUNTER
,
210 "PXL_TEXLD_INST_COUNTER",
211 VIVS_MC_PROFILE_CONFIG0_SH_PXL_TEXLD_INST_COUNTER
,
218 .profile_read
= VIVS_MC_PROFILE_PA_READ
,
219 .profile_config
= VIVS_MC_PROFILE_CONFIG1
,
221 .signal
= (const struct etnaviv_pm_signal
[]) {
224 VIVS_MC_PROFILE_CONFIG1_PA_INPUT_VTX_COUNTER
,
228 "INPUT_PRIM_COUNTER",
229 VIVS_MC_PROFILE_CONFIG1_PA_INPUT_PRIM_COUNTER
,
233 "OUTPUT_PRIM_COUNTER",
234 VIVS_MC_PROFILE_CONFIG1_PA_OUTPUT_PRIM_COUNTER
,
238 "DEPTH_CLIPPED_COUNTER",
239 VIVS_MC_PROFILE_CONFIG1_PA_DEPTH_CLIPPED_COUNTER
,
243 "TRIVIAL_REJECTED_COUNTER",
244 VIVS_MC_PROFILE_CONFIG1_PA_TRIVIAL_REJECTED_COUNTER
,
249 VIVS_MC_PROFILE_CONFIG1_PA_CULLED_COUNTER
,
256 .profile_read
= VIVS_MC_PROFILE_SE_READ
,
257 .profile_config
= VIVS_MC_PROFILE_CONFIG1
,
259 .signal
= (const struct etnaviv_pm_signal
[]) {
261 "CULLED_TRIANGLE_COUNT",
262 VIVS_MC_PROFILE_CONFIG1_SE_CULLED_TRIANGLE_COUNT
,
266 "CULLED_LINES_COUNT",
267 VIVS_MC_PROFILE_CONFIG1_SE_CULLED_LINES_COUNT
,
274 .profile_read
= VIVS_MC_PROFILE_RA_READ
,
275 .profile_config
= VIVS_MC_PROFILE_CONFIG1
,
277 .signal
= (const struct etnaviv_pm_signal
[]) {
280 VIVS_MC_PROFILE_CONFIG1_RA_VALID_PIXEL_COUNT
,
285 VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_QUAD_COUNT
,
289 "VALID_QUAD_COUNT_AFTER_EARLY_Z",
290 VIVS_MC_PROFILE_CONFIG1_RA_VALID_QUAD_COUNT_AFTER_EARLY_Z
,
294 "TOTAL_PRIMITIVE_COUNT",
295 VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_PRIMITIVE_COUNT
,
299 "PIPE_CACHE_MISS_COUNTER",
300 VIVS_MC_PROFILE_CONFIG1_RA_PIPE_CACHE_MISS_COUNTER
,
304 "PREFETCH_CACHE_MISS_COUNTER",
305 VIVS_MC_PROFILE_CONFIG1_RA_PREFETCH_CACHE_MISS_COUNTER
,
310 VIVS_MC_PROFILE_CONFIG1_RA_CULLED_QUAD_COUNT
,
317 .profile_read
= VIVS_MC_PROFILE_TX_READ
,
318 .profile_config
= VIVS_MC_PROFILE_CONFIG1
,
320 .signal
= (const struct etnaviv_pm_signal
[]) {
322 "TOTAL_BILINEAR_REQUESTS",
323 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_BILINEAR_REQUESTS
,
327 "TOTAL_TRILINEAR_REQUESTS",
328 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TRILINEAR_REQUESTS
,
332 "TOTAL_DISCARDED_TEXTURE_REQUESTS",
333 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_DISCARDED_TEXTURE_REQUESTS
,
337 "TOTAL_TEXTURE_REQUESTS",
338 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TEXTURE_REQUESTS
,
343 VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_COUNT
,
347 "MEM_READ_IN_8B_COUNT",
348 VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_IN_8B_COUNT
,
353 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_COUNT
,
357 "CACHE_HIT_TEXEL_COUNT",
358 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_HIT_TEXEL_COUNT
,
362 "CACHE_MISS_TEXEL_COUNT",
363 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_TEXEL_COUNT
,
370 .profile_read
= VIVS_MC_PROFILE_MC_READ
,
371 .profile_config
= VIVS_MC_PROFILE_CONFIG2
,
373 .signal
= (const struct etnaviv_pm_signal
[]) {
375 "TOTAL_READ_REQ_8B_FROM_PIPELINE",
376 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_PIPELINE
,
380 "TOTAL_READ_REQ_8B_FROM_IP",
381 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_IP
,
385 "TOTAL_WRITE_REQ_8B_FROM_PIPELINE",
386 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_WRITE_REQ_8B_FROM_PIPELINE
,
393 static const struct etnaviv_pm_domain doms_2d
[] = {
396 .profile_read
= VIVS_MC_PROFILE_PE_READ
,
397 .profile_config
= VIVS_MC_PROFILE_CONFIG0
,
399 .signal
= (const struct etnaviv_pm_signal
[]) {
401 "PIXELS_RENDERED_2D",
402 VIVS_MC_PROFILE_CONFIG0_PE_PIXELS_RENDERED_2D
,
409 static const struct etnaviv_pm_domain doms_vg
[] = {
412 static const struct etnaviv_pm_domain_meta doms_meta
[] = {
414 .feature
= chipFeatures_PIPE_3D
,
415 .nr_domains
= ARRAY_SIZE(doms_3d
),
416 .domains
= &doms_3d
[0]
419 .feature
= chipFeatures_PIPE_2D
,
420 .nr_domains
= ARRAY_SIZE(doms_2d
),
421 .domains
= &doms_2d
[0]
424 .feature
= chipFeatures_PIPE_VG
,
425 .nr_domains
= ARRAY_SIZE(doms_vg
),
426 .domains
= &doms_vg
[0]
430 static unsigned int num_pm_domains(const struct etnaviv_gpu
*gpu
)
432 unsigned int num
= 0, i
;
434 for (i
= 0; i
< ARRAY_SIZE(doms_meta
); i
++) {
435 const struct etnaviv_pm_domain_meta
*meta
= &doms_meta
[i
];
437 if (gpu
->identity
.features
& meta
->feature
)
438 num
+= meta
->nr_domains
;
444 static const struct etnaviv_pm_domain
*pm_domain(const struct etnaviv_gpu
*gpu
,
447 const struct etnaviv_pm_domain
*domain
= NULL
;
448 unsigned int offset
= 0, i
;
450 for (i
= 0; i
< ARRAY_SIZE(doms_meta
); i
++) {
451 const struct etnaviv_pm_domain_meta
*meta
= &doms_meta
[i
];
453 if (!(gpu
->identity
.features
& meta
->feature
))
456 if (index
- offset
>= meta
->nr_domains
) {
457 offset
+= meta
->nr_domains
;
461 domain
= meta
->domains
+ (index
- offset
);
467 int etnaviv_pm_query_dom(struct etnaviv_gpu
*gpu
,
468 struct drm_etnaviv_pm_domain
*domain
)
470 const unsigned int nr_domains
= num_pm_domains(gpu
);
471 const struct etnaviv_pm_domain
*dom
;
473 if (domain
->iter
>= nr_domains
)
476 dom
= pm_domain(gpu
, domain
->iter
);
480 domain
->id
= domain
->iter
;
481 domain
->nr_signals
= dom
->nr_signals
;
482 strncpy(domain
->name
, dom
->name
, sizeof(domain
->name
));
485 if (domain
->iter
== nr_domains
)
491 int etnaviv_pm_query_sig(struct etnaviv_gpu
*gpu
,
492 struct drm_etnaviv_pm_signal
*signal
)
494 const unsigned int nr_domains
= num_pm_domains(gpu
);
495 const struct etnaviv_pm_domain
*dom
;
496 const struct etnaviv_pm_signal
*sig
;
498 if (signal
->domain
>= nr_domains
)
501 dom
= pm_domain(gpu
, signal
->domain
);
505 if (signal
->iter
>= dom
->nr_signals
)
508 sig
= &dom
->signal
[signal
->iter
];
510 signal
->id
= signal
->iter
;
511 strncpy(signal
->name
, sig
->name
, sizeof(signal
->name
));
514 if (signal
->iter
== dom
->nr_signals
)
515 signal
->iter
= 0xffff;
520 int etnaviv_pm_req_validate(const struct drm_etnaviv_gem_submit_pmr
*r
,
523 const struct etnaviv_pm_domain_meta
*meta
= &doms_meta
[exec_state
];
524 const struct etnaviv_pm_domain
*dom
;
526 if (r
->domain
>= meta
->nr_domains
)
529 dom
= meta
->domains
+ r
->domain
;
531 if (r
->signal
>= dom
->nr_signals
)
537 void etnaviv_perfmon_process(struct etnaviv_gpu
*gpu
,
538 const struct etnaviv_perfmon_request
*pmr
, u32 exec_state
)
540 const struct etnaviv_pm_domain_meta
*meta
= &doms_meta
[exec_state
];
541 const struct etnaviv_pm_domain
*dom
;
542 const struct etnaviv_pm_signal
*sig
;
543 u32
*bo
= pmr
->bo_vma
;
546 dom
= meta
->domains
+ pmr
->domain
;
547 sig
= &dom
->signal
[pmr
->signal
];
548 val
= sig
->sample(gpu
, dom
, sig
);
550 *(bo
+ pmr
->offset
) = val
;