1f6ffbd4fSLucas Stach // SPDX-License-Identifier: GPL-2.0
29e2c2e27SChristian Gmeiner /*
39e2c2e27SChristian Gmeiner  * Copyright (C) 2017 Etnaviv Project
49e2c2e27SChristian Gmeiner  * Copyright (C) 2017 Zodiac Inflight Innovations
59e2c2e27SChristian Gmeiner  */
69e2c2e27SChristian Gmeiner 
715ff4a7bSChristian Gmeiner #include "common.xml.h"
89e2c2e27SChristian Gmeiner #include "etnaviv_gpu.h"
9249300c7SChristian Gmeiner #include "etnaviv_perfmon.h"
1033deff0aSChristian Gmeiner #include "state_hi.xml.h"
119e2c2e27SChristian Gmeiner 
129e2c2e27SChristian Gmeiner struct etnaviv_pm_domain;
139e2c2e27SChristian Gmeiner 
149e2c2e27SChristian Gmeiner struct etnaviv_pm_signal {
159e2c2e27SChristian Gmeiner 	char name[64];
169e2c2e27SChristian Gmeiner 	u32 data;
179e2c2e27SChristian Gmeiner 
189e2c2e27SChristian Gmeiner 	u32 (*sample)(struct etnaviv_gpu *gpu,
199e2c2e27SChristian Gmeiner 		      const struct etnaviv_pm_domain *domain,
209e2c2e27SChristian Gmeiner 		      const struct etnaviv_pm_signal *signal);
219e2c2e27SChristian Gmeiner };
229e2c2e27SChristian Gmeiner 
239e2c2e27SChristian Gmeiner struct etnaviv_pm_domain {
249e2c2e27SChristian Gmeiner 	char name[64];
2533deff0aSChristian Gmeiner 
2633deff0aSChristian Gmeiner 	/* profile register */
2733deff0aSChristian Gmeiner 	u32 profile_read;
2833deff0aSChristian Gmeiner 	u32 profile_config;
2933deff0aSChristian Gmeiner 
309e2c2e27SChristian Gmeiner 	u8 nr_signals;
319e2c2e27SChristian Gmeiner 	const struct etnaviv_pm_signal *signal;
329e2c2e27SChristian Gmeiner };
339e2c2e27SChristian Gmeiner 
349e2c2e27SChristian Gmeiner struct etnaviv_pm_domain_meta {
35ed1dd899SChristian Gmeiner 	unsigned int feature;
369e2c2e27SChristian Gmeiner 	const struct etnaviv_pm_domain *domains;
379e2c2e27SChristian Gmeiner 	u32 nr_domains;
389e2c2e27SChristian Gmeiner };
399e2c2e27SChristian Gmeiner 
perf_reg_read(struct etnaviv_gpu * gpu,const struct etnaviv_pm_domain * domain,const struct etnaviv_pm_signal * signal)4033deff0aSChristian Gmeiner static u32 perf_reg_read(struct etnaviv_gpu *gpu,
4133deff0aSChristian Gmeiner 	const struct etnaviv_pm_domain *domain,
4233deff0aSChristian Gmeiner 	const struct etnaviv_pm_signal *signal)
4333deff0aSChristian Gmeiner {
4433deff0aSChristian Gmeiner 	gpu_write(gpu, domain->profile_config, signal->data);
4533deff0aSChristian Gmeiner 
4633deff0aSChristian Gmeiner 	return gpu_read(gpu, domain->profile_read);
4733deff0aSChristian Gmeiner }
4833deff0aSChristian Gmeiner 
pipe_select(struct etnaviv_gpu * gpu,u32 clock,unsigned pipe)49*a5cafb90SChristian Gmeiner static inline void pipe_select(struct etnaviv_gpu *gpu, u32 clock, unsigned pipe)
50*a5cafb90SChristian Gmeiner {
51*a5cafb90SChristian Gmeiner 	clock &= ~(VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK);
52*a5cafb90SChristian Gmeiner 	clock |= VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE(pipe);
53*a5cafb90SChristian Gmeiner 
54*a5cafb90SChristian Gmeiner 	gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, clock);
55*a5cafb90SChristian Gmeiner }
56*a5cafb90SChristian Gmeiner 
pipe_perf_reg_read(struct etnaviv_gpu * gpu,const struct etnaviv_pm_domain * domain,const struct etnaviv_pm_signal * signal)5777dfb36aSChristian Gmeiner static u32 pipe_perf_reg_read(struct etnaviv_gpu *gpu,
58a3d0c390SChristian Gmeiner 	const struct etnaviv_pm_domain *domain,
59a3d0c390SChristian Gmeiner 	const struct etnaviv_pm_signal *signal)
60a3d0c390SChristian Gmeiner {
61a3d0c390SChristian Gmeiner 	u32 clock = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
62a3d0c390SChristian Gmeiner 	u32 value = 0;
63a3d0c390SChristian Gmeiner 	unsigned i;
64a3d0c390SChristian Gmeiner 
65a3d0c390SChristian Gmeiner 	for (i = 0; i < gpu->identity.pixel_pipes; i++) {
66*a5cafb90SChristian Gmeiner 		pipe_select(gpu, clock, i);
67658690d8SChristian Gmeiner 		value += perf_reg_read(gpu, domain, signal);
68a3d0c390SChristian Gmeiner 	}
69a3d0c390SChristian Gmeiner 
70a3d0c390SChristian Gmeiner 	/* switch back to pixel pipe 0 to prevent GPU hang */
71*a5cafb90SChristian Gmeiner 	pipe_select(gpu, clock, 0);
72a3d0c390SChristian Gmeiner 
73a3d0c390SChristian Gmeiner 	return value;
74a3d0c390SChristian Gmeiner }
75a3d0c390SChristian Gmeiner 
pipe_reg_read(struct etnaviv_gpu * gpu,const struct etnaviv_pm_domain * domain,const struct etnaviv_pm_signal * signal)76bbab2be7SChristian Gmeiner static u32 pipe_reg_read(struct etnaviv_gpu *gpu,
77bbab2be7SChristian Gmeiner 	const struct etnaviv_pm_domain *domain,
78bbab2be7SChristian Gmeiner 	const struct etnaviv_pm_signal *signal)
79bbab2be7SChristian Gmeiner {
80bbab2be7SChristian Gmeiner 	u32 clock = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
81bbab2be7SChristian Gmeiner 	u32 value = 0;
82bbab2be7SChristian Gmeiner 	unsigned i;
83bbab2be7SChristian Gmeiner 
84bbab2be7SChristian Gmeiner 	for (i = 0; i < gpu->identity.pixel_pipes; i++) {
85*a5cafb90SChristian Gmeiner 		pipe_select(gpu, clock, i);
86bbab2be7SChristian Gmeiner 		value += gpu_read(gpu, signal->data);
87bbab2be7SChristian Gmeiner 	}
88bbab2be7SChristian Gmeiner 
89bbab2be7SChristian Gmeiner 	/* switch back to pixel pipe 0 to prevent GPU hang */
90*a5cafb90SChristian Gmeiner 	pipe_select(gpu, clock, 0);
91bbab2be7SChristian Gmeiner 
92bbab2be7SChristian Gmeiner 	return value;
93bbab2be7SChristian Gmeiner }
94bbab2be7SChristian Gmeiner 
hi_total_cycle_read(struct etnaviv_gpu * gpu,const struct etnaviv_pm_domain * domain,const struct etnaviv_pm_signal * signal)9515ff4a7bSChristian Gmeiner static u32 hi_total_cycle_read(struct etnaviv_gpu *gpu,
9615ff4a7bSChristian Gmeiner 	const struct etnaviv_pm_domain *domain,
9715ff4a7bSChristian Gmeiner 	const struct etnaviv_pm_signal *signal)
9815ff4a7bSChristian Gmeiner {
9915ff4a7bSChristian Gmeiner 	u32 reg = VIVS_HI_PROFILE_TOTAL_CYCLES;
10015ff4a7bSChristian Gmeiner 
10115ff4a7bSChristian Gmeiner 	if (gpu->identity.model == chipModel_GC880 ||
10215ff4a7bSChristian Gmeiner 		gpu->identity.model == chipModel_GC2000 ||
10315ff4a7bSChristian Gmeiner 		gpu->identity.model == chipModel_GC2100)
10415ff4a7bSChristian Gmeiner 		reg = VIVS_MC_PROFILE_CYCLE_COUNTER;
10515ff4a7bSChristian Gmeiner 
10615ff4a7bSChristian Gmeiner 	return gpu_read(gpu, reg);
10715ff4a7bSChristian Gmeiner }
10815ff4a7bSChristian Gmeiner 
hi_total_idle_cycle_read(struct etnaviv_gpu * gpu,const struct etnaviv_pm_domain * domain,const struct etnaviv_pm_signal * signal)10915ff4a7bSChristian Gmeiner static u32 hi_total_idle_cycle_read(struct etnaviv_gpu *gpu,
11015ff4a7bSChristian Gmeiner 	const struct etnaviv_pm_domain *domain,
11115ff4a7bSChristian Gmeiner 	const struct etnaviv_pm_signal *signal)
11215ff4a7bSChristian Gmeiner {
11315ff4a7bSChristian Gmeiner 	u32 reg = VIVS_HI_PROFILE_IDLE_CYCLES;
11415ff4a7bSChristian Gmeiner 
11515ff4a7bSChristian Gmeiner 	if (gpu->identity.model == chipModel_GC880 ||
11615ff4a7bSChristian Gmeiner 		gpu->identity.model == chipModel_GC2000 ||
11715ff4a7bSChristian Gmeiner 		gpu->identity.model == chipModel_GC2100)
11815ff4a7bSChristian Gmeiner 		reg = VIVS_HI_PROFILE_TOTAL_CYCLES;
11915ff4a7bSChristian Gmeiner 
12015ff4a7bSChristian Gmeiner 	return gpu_read(gpu, reg);
12115ff4a7bSChristian Gmeiner }
12215ff4a7bSChristian Gmeiner 
1239e2c2e27SChristian Gmeiner static const struct etnaviv_pm_domain doms_3d[] = {
12433deff0aSChristian Gmeiner 	{
12533deff0aSChristian Gmeiner 		.name = "HI",
12633deff0aSChristian Gmeiner 		.profile_read = VIVS_MC_PROFILE_HI_READ,
12733deff0aSChristian Gmeiner 		.profile_config = VIVS_MC_PROFILE_CONFIG2,
128bbab2be7SChristian Gmeiner 		.nr_signals = 7,
12933deff0aSChristian Gmeiner 		.signal = (const struct etnaviv_pm_signal[]) {
13033deff0aSChristian Gmeiner 			{
131bbab2be7SChristian Gmeiner 				"TOTAL_READ_BYTES8",
132bbab2be7SChristian Gmeiner 				VIVS_HI_PROFILE_READ_BYTES8,
133bbab2be7SChristian Gmeiner 				&pipe_reg_read,
134bbab2be7SChristian Gmeiner 			},
135bbab2be7SChristian Gmeiner 			{
136bbab2be7SChristian Gmeiner 				"TOTAL_WRITE_BYTES8",
137bbab2be7SChristian Gmeiner 				VIVS_HI_PROFILE_WRITE_BYTES8,
138bbab2be7SChristian Gmeiner 				&pipe_reg_read,
139bbab2be7SChristian Gmeiner 			},
140bbab2be7SChristian Gmeiner 			{
14133deff0aSChristian Gmeiner 				"TOTAL_CYCLES",
14215ff4a7bSChristian Gmeiner 				0,
14315ff4a7bSChristian Gmeiner 				&hi_total_cycle_read
14433deff0aSChristian Gmeiner 			},
14533deff0aSChristian Gmeiner 			{
14633deff0aSChristian Gmeiner 				"IDLE_CYCLES",
14715ff4a7bSChristian Gmeiner 				0,
14815ff4a7bSChristian Gmeiner 				&hi_total_idle_cycle_read
14933deff0aSChristian Gmeiner 			},
15033deff0aSChristian Gmeiner 			{
15133deff0aSChristian Gmeiner 				"AXI_CYCLES_READ_REQUEST_STALLED",
15233deff0aSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_READ_REQUEST_STALLED,
15333deff0aSChristian Gmeiner 				&perf_reg_read
15433deff0aSChristian Gmeiner 			},
15533deff0aSChristian Gmeiner 			{
15633deff0aSChristian Gmeiner 				"AXI_CYCLES_WRITE_REQUEST_STALLED",
15733deff0aSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_REQUEST_STALLED,
15833deff0aSChristian Gmeiner 				&perf_reg_read
15933deff0aSChristian Gmeiner 			},
16033deff0aSChristian Gmeiner 			{
16133deff0aSChristian Gmeiner 				"AXI_CYCLES_WRITE_DATA_STALLED",
16233deff0aSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_DATA_STALLED,
16333deff0aSChristian Gmeiner 				&perf_reg_read
16433deff0aSChristian Gmeiner 			}
16533deff0aSChristian Gmeiner 		}
166a3d0c390SChristian Gmeiner 	},
167a3d0c390SChristian Gmeiner 	{
168a3d0c390SChristian Gmeiner 		.name = "PE",
169a3d0c390SChristian Gmeiner 		.profile_read = VIVS_MC_PROFILE_PE_READ,
170a3d0c390SChristian Gmeiner 		.profile_config = VIVS_MC_PROFILE_CONFIG0,
171f5fd9fd4SDan Carpenter 		.nr_signals = 4,
172a3d0c390SChristian Gmeiner 		.signal = (const struct etnaviv_pm_signal[]) {
173a3d0c390SChristian Gmeiner 			{
174a3d0c390SChristian Gmeiner 				"PIXEL_COUNT_KILLED_BY_COLOR_PIPE",
175a3d0c390SChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_COLOR_PIPE,
17677dfb36aSChristian Gmeiner 				&pipe_perf_reg_read
177a3d0c390SChristian Gmeiner 			},
178a3d0c390SChristian Gmeiner 			{
179a3d0c390SChristian Gmeiner 				"PIXEL_COUNT_KILLED_BY_DEPTH_PIPE",
180a3d0c390SChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_DEPTH_PIPE,
18177dfb36aSChristian Gmeiner 				&pipe_perf_reg_read
182a3d0c390SChristian Gmeiner 			},
183a3d0c390SChristian Gmeiner 			{
184a3d0c390SChristian Gmeiner 				"PIXEL_COUNT_DRAWN_BY_COLOR_PIPE",
185a3d0c390SChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_COLOR_PIPE,
18677dfb36aSChristian Gmeiner 				&pipe_perf_reg_read
187a3d0c390SChristian Gmeiner 			},
188a3d0c390SChristian Gmeiner 			{
189a3d0c390SChristian Gmeiner 				"PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE",
190a3d0c390SChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE,
19177dfb36aSChristian Gmeiner 				&pipe_perf_reg_read
192a3d0c390SChristian Gmeiner 			}
193a3d0c390SChristian Gmeiner 		}
19498b2482eSChristian Gmeiner 	},
19598b2482eSChristian Gmeiner 	{
19698b2482eSChristian Gmeiner 		.name = "SH",
19798b2482eSChristian Gmeiner 		.profile_read = VIVS_MC_PROFILE_SH_READ,
19898b2482eSChristian Gmeiner 		.profile_config = VIVS_MC_PROFILE_CONFIG0,
19998b2482eSChristian Gmeiner 		.nr_signals = 9,
20098b2482eSChristian Gmeiner 		.signal = (const struct etnaviv_pm_signal[]) {
20198b2482eSChristian Gmeiner 			{
20298b2482eSChristian Gmeiner 				"SHADER_CYCLES",
20398b2482eSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG0_SH_SHADER_CYCLES,
20498b2482eSChristian Gmeiner 				&perf_reg_read
20598b2482eSChristian Gmeiner 			},
20698b2482eSChristian Gmeiner 			{
20798b2482eSChristian Gmeiner 				"PS_INST_COUNTER",
20898b2482eSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG0_SH_PS_INST_COUNTER,
20998b2482eSChristian Gmeiner 				&perf_reg_read
21098b2482eSChristian Gmeiner 			},
21198b2482eSChristian Gmeiner 			{
21298b2482eSChristian Gmeiner 				"RENDERED_PIXEL_COUNTER",
21398b2482eSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_PIXEL_COUNTER,
21498b2482eSChristian Gmeiner 				&perf_reg_read
21598b2482eSChristian Gmeiner 			},
21698b2482eSChristian Gmeiner 			{
21798b2482eSChristian Gmeiner 				"VS_INST_COUNTER",
21898b2482eSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG0_SH_VS_INST_COUNTER,
21977dfb36aSChristian Gmeiner 				&pipe_perf_reg_read
22098b2482eSChristian Gmeiner 			},
22198b2482eSChristian Gmeiner 			{
22298b2482eSChristian Gmeiner 				"RENDERED_VERTICE_COUNTER",
22398b2482eSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_VERTICE_COUNTER,
22477dfb36aSChristian Gmeiner 				&pipe_perf_reg_read
22598b2482eSChristian Gmeiner 			},
22698b2482eSChristian Gmeiner 			{
22798b2482eSChristian Gmeiner 				"VTX_BRANCH_INST_COUNTER",
22898b2482eSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG0_SH_VTX_BRANCH_INST_COUNTER,
22977dfb36aSChristian Gmeiner 				&pipe_perf_reg_read
23098b2482eSChristian Gmeiner 			},
23198b2482eSChristian Gmeiner 			{
23298b2482eSChristian Gmeiner 				"VTX_TEXLD_INST_COUNTER",
23398b2482eSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG0_SH_VTX_TEXLD_INST_COUNTER,
23477dfb36aSChristian Gmeiner 				&pipe_perf_reg_read
23598b2482eSChristian Gmeiner 			},
23698b2482eSChristian Gmeiner 			{
23798b2482eSChristian Gmeiner 				"PXL_BRANCH_INST_COUNTER",
23898b2482eSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG0_SH_PXL_BRANCH_INST_COUNTER,
23977dfb36aSChristian Gmeiner 				&pipe_perf_reg_read
24098b2482eSChristian Gmeiner 			},
24198b2482eSChristian Gmeiner 			{
24298b2482eSChristian Gmeiner 				"PXL_TEXLD_INST_COUNTER",
24398b2482eSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG0_SH_PXL_TEXLD_INST_COUNTER,
24477dfb36aSChristian Gmeiner 				&pipe_perf_reg_read
24598b2482eSChristian Gmeiner 			}
24698b2482eSChristian Gmeiner 		}
247c3787ff6SChristian Gmeiner 	},
248c3787ff6SChristian Gmeiner 	{
249c3787ff6SChristian Gmeiner 		.name = "PA",
250c3787ff6SChristian Gmeiner 		.profile_read = VIVS_MC_PROFILE_PA_READ,
251c3787ff6SChristian Gmeiner 		.profile_config = VIVS_MC_PROFILE_CONFIG1,
252c3787ff6SChristian Gmeiner 		.nr_signals = 6,
253c3787ff6SChristian Gmeiner 		.signal = (const struct etnaviv_pm_signal[]) {
254c3787ff6SChristian Gmeiner 			{
255c3787ff6SChristian Gmeiner 				"INPUT_VTX_COUNTER",
256c3787ff6SChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_PA_INPUT_VTX_COUNTER,
257c3787ff6SChristian Gmeiner 				&perf_reg_read
258c3787ff6SChristian Gmeiner 			},
259c3787ff6SChristian Gmeiner 			{
260c3787ff6SChristian Gmeiner 				"INPUT_PRIM_COUNTER",
261c3787ff6SChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_PA_INPUT_PRIM_COUNTER,
262c3787ff6SChristian Gmeiner 				&perf_reg_read
263c3787ff6SChristian Gmeiner 			},
264c3787ff6SChristian Gmeiner 			{
265c3787ff6SChristian Gmeiner 				"OUTPUT_PRIM_COUNTER",
266c3787ff6SChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_PA_OUTPUT_PRIM_COUNTER,
267c3787ff6SChristian Gmeiner 				&perf_reg_read
268c3787ff6SChristian Gmeiner 			},
269c3787ff6SChristian Gmeiner 			{
270c3787ff6SChristian Gmeiner 				"DEPTH_CLIPPED_COUNTER",
271c3787ff6SChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_PA_DEPTH_CLIPPED_COUNTER,
27277dfb36aSChristian Gmeiner 				&pipe_perf_reg_read
273c3787ff6SChristian Gmeiner 			},
274c3787ff6SChristian Gmeiner 			{
275c3787ff6SChristian Gmeiner 				"TRIVIAL_REJECTED_COUNTER",
276c3787ff6SChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_PA_TRIVIAL_REJECTED_COUNTER,
27777dfb36aSChristian Gmeiner 				&pipe_perf_reg_read
278c3787ff6SChristian Gmeiner 			},
279c3787ff6SChristian Gmeiner 			{
280c3787ff6SChristian Gmeiner 				"CULLED_COUNTER",
281c3787ff6SChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_PA_CULLED_COUNTER,
28277dfb36aSChristian Gmeiner 				&pipe_perf_reg_read
283c3787ff6SChristian Gmeiner 			}
284c3787ff6SChristian Gmeiner 		}
285a515264cSChristian Gmeiner 	},
286a515264cSChristian Gmeiner 	{
287a515264cSChristian Gmeiner 		.name = "SE",
288a515264cSChristian Gmeiner 		.profile_read = VIVS_MC_PROFILE_SE_READ,
289a515264cSChristian Gmeiner 		.profile_config = VIVS_MC_PROFILE_CONFIG1,
290a515264cSChristian Gmeiner 		.nr_signals = 2,
291a515264cSChristian Gmeiner 		.signal = (const struct etnaviv_pm_signal[]) {
292a515264cSChristian Gmeiner 			{
293a515264cSChristian Gmeiner 				"CULLED_TRIANGLE_COUNT",
294a515264cSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_SE_CULLED_TRIANGLE_COUNT,
295a515264cSChristian Gmeiner 				&perf_reg_read
296a515264cSChristian Gmeiner 			},
297a515264cSChristian Gmeiner 			{
298a515264cSChristian Gmeiner 				"CULLED_LINES_COUNT",
299a515264cSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_SE_CULLED_LINES_COUNT,
300a515264cSChristian Gmeiner 				&perf_reg_read
301a515264cSChristian Gmeiner 			}
302a515264cSChristian Gmeiner 		}
30391a9a17bSChristian Gmeiner 	},
30491a9a17bSChristian Gmeiner 	{
30591a9a17bSChristian Gmeiner 		.name = "RA",
30691a9a17bSChristian Gmeiner 		.profile_read = VIVS_MC_PROFILE_RA_READ,
30791a9a17bSChristian Gmeiner 		.profile_config = VIVS_MC_PROFILE_CONFIG1,
30891a9a17bSChristian Gmeiner 		.nr_signals = 7,
30991a9a17bSChristian Gmeiner 		.signal = (const struct etnaviv_pm_signal[]) {
31091a9a17bSChristian Gmeiner 			{
31191a9a17bSChristian Gmeiner 				"VALID_PIXEL_COUNT",
31291a9a17bSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_RA_VALID_PIXEL_COUNT,
31391a9a17bSChristian Gmeiner 				&perf_reg_read
31491a9a17bSChristian Gmeiner 			},
31591a9a17bSChristian Gmeiner 			{
31691a9a17bSChristian Gmeiner 				"TOTAL_QUAD_COUNT",
31791a9a17bSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_QUAD_COUNT,
31891a9a17bSChristian Gmeiner 				&perf_reg_read
31991a9a17bSChristian Gmeiner 			},
32091a9a17bSChristian Gmeiner 			{
32191a9a17bSChristian Gmeiner 				"VALID_QUAD_COUNT_AFTER_EARLY_Z",
32291a9a17bSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_RA_VALID_QUAD_COUNT_AFTER_EARLY_Z,
32391a9a17bSChristian Gmeiner 				&perf_reg_read
32491a9a17bSChristian Gmeiner 			},
32591a9a17bSChristian Gmeiner 			{
32691a9a17bSChristian Gmeiner 				"TOTAL_PRIMITIVE_COUNT",
32791a9a17bSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_PRIMITIVE_COUNT,
32891a9a17bSChristian Gmeiner 				&perf_reg_read
32991a9a17bSChristian Gmeiner 			},
33091a9a17bSChristian Gmeiner 			{
33191a9a17bSChristian Gmeiner 				"PIPE_CACHE_MISS_COUNTER",
33291a9a17bSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_RA_PIPE_CACHE_MISS_COUNTER,
33391a9a17bSChristian Gmeiner 				&perf_reg_read
33491a9a17bSChristian Gmeiner 			},
33591a9a17bSChristian Gmeiner 			{
33691a9a17bSChristian Gmeiner 				"PREFETCH_CACHE_MISS_COUNTER",
33791a9a17bSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_RA_PREFETCH_CACHE_MISS_COUNTER,
33891a9a17bSChristian Gmeiner 				&perf_reg_read
33991a9a17bSChristian Gmeiner 			},
34091a9a17bSChristian Gmeiner 			{
34191a9a17bSChristian Gmeiner 				"CULLED_QUAD_COUNT",
34291a9a17bSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_RA_CULLED_QUAD_COUNT,
34391a9a17bSChristian Gmeiner 				&perf_reg_read
34491a9a17bSChristian Gmeiner 			}
34591a9a17bSChristian Gmeiner 		}
3469646025eSChristian Gmeiner 	},
3479646025eSChristian Gmeiner 	{
3489646025eSChristian Gmeiner 		.name = "TX",
3499646025eSChristian Gmeiner 		.profile_read = VIVS_MC_PROFILE_TX_READ,
3509646025eSChristian Gmeiner 		.profile_config = VIVS_MC_PROFILE_CONFIG1,
3519646025eSChristian Gmeiner 		.nr_signals = 9,
3529646025eSChristian Gmeiner 		.signal = (const struct etnaviv_pm_signal[]) {
3539646025eSChristian Gmeiner 			{
3549646025eSChristian Gmeiner 				"TOTAL_BILINEAR_REQUESTS",
3559646025eSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_BILINEAR_REQUESTS,
3569646025eSChristian Gmeiner 				&perf_reg_read
3579646025eSChristian Gmeiner 			},
3589646025eSChristian Gmeiner 			{
3599646025eSChristian Gmeiner 				"TOTAL_TRILINEAR_REQUESTS",
3609646025eSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TRILINEAR_REQUESTS,
3619646025eSChristian Gmeiner 				&perf_reg_read
3629646025eSChristian Gmeiner 			},
3639646025eSChristian Gmeiner 			{
3649646025eSChristian Gmeiner 				"TOTAL_DISCARDED_TEXTURE_REQUESTS",
3659646025eSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_DISCARDED_TEXTURE_REQUESTS,
3669646025eSChristian Gmeiner 				&perf_reg_read
3679646025eSChristian Gmeiner 			},
3689646025eSChristian Gmeiner 			{
3699646025eSChristian Gmeiner 				"TOTAL_TEXTURE_REQUESTS",
3709646025eSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TEXTURE_REQUESTS,
3719646025eSChristian Gmeiner 				&perf_reg_read
3729646025eSChristian Gmeiner 			},
3739646025eSChristian Gmeiner 			{
3749646025eSChristian Gmeiner 				"MEM_READ_COUNT",
3759646025eSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_COUNT,
3769646025eSChristian Gmeiner 				&perf_reg_read
3779646025eSChristian Gmeiner 			},
3789646025eSChristian Gmeiner 			{
3799646025eSChristian Gmeiner 				"MEM_READ_IN_8B_COUNT",
3809646025eSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_IN_8B_COUNT,
3819646025eSChristian Gmeiner 				&perf_reg_read
3829646025eSChristian Gmeiner 			},
3839646025eSChristian Gmeiner 			{
3849646025eSChristian Gmeiner 				"CACHE_MISS_COUNT",
3859646025eSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_COUNT,
3869646025eSChristian Gmeiner 				&perf_reg_read
3879646025eSChristian Gmeiner 			},
3889646025eSChristian Gmeiner 			{
3899646025eSChristian Gmeiner 				"CACHE_HIT_TEXEL_COUNT",
3909646025eSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_TX_CACHE_HIT_TEXEL_COUNT,
3919646025eSChristian Gmeiner 				&perf_reg_read
3929646025eSChristian Gmeiner 			},
3939646025eSChristian Gmeiner 			{
3949646025eSChristian Gmeiner 				"CACHE_MISS_TEXEL_COUNT",
3959646025eSChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_TEXEL_COUNT,
3969646025eSChristian Gmeiner 				&perf_reg_read
3979646025eSChristian Gmeiner 			}
3989646025eSChristian Gmeiner 		}
39949168ee9SChristian Gmeiner 	},
40049168ee9SChristian Gmeiner 	{
40149168ee9SChristian Gmeiner 		.name = "MC",
40249168ee9SChristian Gmeiner 		.profile_read = VIVS_MC_PROFILE_MC_READ,
40349168ee9SChristian Gmeiner 		.profile_config = VIVS_MC_PROFILE_CONFIG2,
40449168ee9SChristian Gmeiner 		.nr_signals = 3,
40549168ee9SChristian Gmeiner 		.signal = (const struct etnaviv_pm_signal[]) {
40649168ee9SChristian Gmeiner 			{
40749168ee9SChristian Gmeiner 				"TOTAL_READ_REQ_8B_FROM_PIPELINE",
40849168ee9SChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_PIPELINE,
40949168ee9SChristian Gmeiner 				&perf_reg_read
41049168ee9SChristian Gmeiner 			},
41149168ee9SChristian Gmeiner 			{
41249168ee9SChristian Gmeiner 				"TOTAL_READ_REQ_8B_FROM_IP",
41349168ee9SChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_IP,
41449168ee9SChristian Gmeiner 				&perf_reg_read
41549168ee9SChristian Gmeiner 			},
41649168ee9SChristian Gmeiner 			{
41749168ee9SChristian Gmeiner 				"TOTAL_WRITE_REQ_8B_FROM_PIPELINE",
41849168ee9SChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_WRITE_REQ_8B_FROM_PIPELINE,
41949168ee9SChristian Gmeiner 				&perf_reg_read
42049168ee9SChristian Gmeiner 			}
42149168ee9SChristian Gmeiner 		}
42233deff0aSChristian Gmeiner 	}
4239e2c2e27SChristian Gmeiner };
4249e2c2e27SChristian Gmeiner 
4259e2c2e27SChristian Gmeiner static const struct etnaviv_pm_domain doms_2d[] = {
426a3d0c390SChristian Gmeiner 	{
427a3d0c390SChristian Gmeiner 		.name = "PE",
428a3d0c390SChristian Gmeiner 		.profile_read = VIVS_MC_PROFILE_PE_READ,
429a3d0c390SChristian Gmeiner 		.profile_config = VIVS_MC_PROFILE_CONFIG0,
430a3d0c390SChristian Gmeiner 		.nr_signals = 1,
431a3d0c390SChristian Gmeiner 		.signal = (const struct etnaviv_pm_signal[]) {
432a3d0c390SChristian Gmeiner 			{
433a3d0c390SChristian Gmeiner 				"PIXELS_RENDERED_2D",
434a3d0c390SChristian Gmeiner 				VIVS_MC_PROFILE_CONFIG0_PE_PIXELS_RENDERED_2D,
43577dfb36aSChristian Gmeiner 				&pipe_perf_reg_read
436a3d0c390SChristian Gmeiner 			}
437a3d0c390SChristian Gmeiner 		}
438a3d0c390SChristian Gmeiner 	}
4399e2c2e27SChristian Gmeiner };
4409e2c2e27SChristian Gmeiner 
4419e2c2e27SChristian Gmeiner static const struct etnaviv_pm_domain doms_vg[] = {
4429e2c2e27SChristian Gmeiner };
4439e2c2e27SChristian Gmeiner 
4449e2c2e27SChristian Gmeiner static const struct etnaviv_pm_domain_meta doms_meta[] = {
4459e2c2e27SChristian Gmeiner 	{
446ed1dd899SChristian Gmeiner 		.feature = chipFeatures_PIPE_3D,
4479e2c2e27SChristian Gmeiner 		.nr_domains = ARRAY_SIZE(doms_3d),
4489e2c2e27SChristian Gmeiner 		.domains = &doms_3d[0]
4499e2c2e27SChristian Gmeiner 	},
4509e2c2e27SChristian Gmeiner 	{
451ed1dd899SChristian Gmeiner 		.feature = chipFeatures_PIPE_2D,
4529e2c2e27SChristian Gmeiner 		.nr_domains = ARRAY_SIZE(doms_2d),
4539e2c2e27SChristian Gmeiner 		.domains = &doms_2d[0]
4549e2c2e27SChristian Gmeiner 	},
4559e2c2e27SChristian Gmeiner 	{
456ed1dd899SChristian Gmeiner 		.feature = chipFeatures_PIPE_VG,
4579e2c2e27SChristian Gmeiner 		.nr_domains = ARRAY_SIZE(doms_vg),
4589e2c2e27SChristian Gmeiner 		.domains = &doms_vg[0]
4599e2c2e27SChristian Gmeiner 	}
4609e2c2e27SChristian Gmeiner };
4619e2c2e27SChristian Gmeiner 
num_pm_domains(const struct etnaviv_gpu * gpu)462ed1dd899SChristian Gmeiner static unsigned int num_pm_domains(const struct etnaviv_gpu *gpu)
463ed1dd899SChristian Gmeiner {
464ed1dd899SChristian Gmeiner 	unsigned int num = 0, i;
465ed1dd899SChristian Gmeiner 
466ed1dd899SChristian Gmeiner 	for (i = 0; i < ARRAY_SIZE(doms_meta); i++) {
467ed1dd899SChristian Gmeiner 		const struct etnaviv_pm_domain_meta *meta = &doms_meta[i];
468ed1dd899SChristian Gmeiner 
469ed1dd899SChristian Gmeiner 		if (gpu->identity.features & meta->feature)
470ed1dd899SChristian Gmeiner 			num += meta->nr_domains;
471ed1dd899SChristian Gmeiner 	}
472ed1dd899SChristian Gmeiner 
473ed1dd899SChristian Gmeiner 	return num;
474ed1dd899SChristian Gmeiner }
475ed1dd899SChristian Gmeiner 
pm_domain(const struct etnaviv_gpu * gpu,unsigned int index)476ed1dd899SChristian Gmeiner static const struct etnaviv_pm_domain *pm_domain(const struct etnaviv_gpu *gpu,
477ed1dd899SChristian Gmeiner 	unsigned int index)
478ed1dd899SChristian Gmeiner {
479ed1dd899SChristian Gmeiner 	const struct etnaviv_pm_domain *domain = NULL;
480ed1dd899SChristian Gmeiner 	unsigned int offset = 0, i;
481ed1dd899SChristian Gmeiner 
482ed1dd899SChristian Gmeiner 	for (i = 0; i < ARRAY_SIZE(doms_meta); i++) {
483ed1dd899SChristian Gmeiner 		const struct etnaviv_pm_domain_meta *meta = &doms_meta[i];
484ed1dd899SChristian Gmeiner 
485ed1dd899SChristian Gmeiner 		if (!(gpu->identity.features & meta->feature))
486ed1dd899SChristian Gmeiner 			continue;
487ed1dd899SChristian Gmeiner 
48840b697e2SChristian Gmeiner 		if (index - offset >= meta->nr_domains) {
489ed1dd899SChristian Gmeiner 			offset += meta->nr_domains;
490ed1dd899SChristian Gmeiner 			continue;
491ed1dd899SChristian Gmeiner 		}
492ed1dd899SChristian Gmeiner 
493ed1dd899SChristian Gmeiner 		domain = meta->domains + (index - offset);
494ed1dd899SChristian Gmeiner 	}
495ed1dd899SChristian Gmeiner 
496ed1dd899SChristian Gmeiner 	return domain;
497ed1dd899SChristian Gmeiner }
498ed1dd899SChristian Gmeiner 
etnaviv_pm_query_dom(struct etnaviv_gpu * gpu,struct drm_etnaviv_pm_domain * domain)4999e2c2e27SChristian Gmeiner int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu,
5009e2c2e27SChristian Gmeiner 	struct drm_etnaviv_pm_domain *domain)
5019e2c2e27SChristian Gmeiner {
502ed1dd899SChristian Gmeiner 	const unsigned int nr_domains = num_pm_domains(gpu);
5039e2c2e27SChristian Gmeiner 	const struct etnaviv_pm_domain *dom;
5049e2c2e27SChristian Gmeiner 
505ed1dd899SChristian Gmeiner 	if (domain->iter >= nr_domains)
5069e2c2e27SChristian Gmeiner 		return -EINVAL;
5079e2c2e27SChristian Gmeiner 
508ed1dd899SChristian Gmeiner 	dom = pm_domain(gpu, domain->iter);
509ed1dd899SChristian Gmeiner 	if (!dom)
510ed1dd899SChristian Gmeiner 		return -EINVAL;
5119e2c2e27SChristian Gmeiner 
5129e2c2e27SChristian Gmeiner 	domain->id = domain->iter;
5139e2c2e27SChristian Gmeiner 	domain->nr_signals = dom->nr_signals;
5149e2c2e27SChristian Gmeiner 	strncpy(domain->name, dom->name, sizeof(domain->name));
5159e2c2e27SChristian Gmeiner 
5169e2c2e27SChristian Gmeiner 	domain->iter++;
517ed1dd899SChristian Gmeiner 	if (domain->iter == nr_domains)
5189e2c2e27SChristian Gmeiner 		domain->iter = 0xff;
5199e2c2e27SChristian Gmeiner 
5209e2c2e27SChristian Gmeiner 	return 0;
5219e2c2e27SChristian Gmeiner }
5229e2c2e27SChristian Gmeiner 
etnaviv_pm_query_sig(struct etnaviv_gpu * gpu,struct drm_etnaviv_pm_signal * signal)5239e2c2e27SChristian Gmeiner int etnaviv_pm_query_sig(struct etnaviv_gpu *gpu,
5249e2c2e27SChristian Gmeiner 	struct drm_etnaviv_pm_signal *signal)
5259e2c2e27SChristian Gmeiner {
526ed1dd899SChristian Gmeiner 	const unsigned int nr_domains = num_pm_domains(gpu);
5279e2c2e27SChristian Gmeiner 	const struct etnaviv_pm_domain *dom;
5289e2c2e27SChristian Gmeiner 	const struct etnaviv_pm_signal *sig;
5299e2c2e27SChristian Gmeiner 
530ed1dd899SChristian Gmeiner 	if (signal->domain >= nr_domains)
5319e2c2e27SChristian Gmeiner 		return -EINVAL;
5329e2c2e27SChristian Gmeiner 
533ed1dd899SChristian Gmeiner 	dom = pm_domain(gpu, signal->domain);
534ed1dd899SChristian Gmeiner 	if (!dom)
535ed1dd899SChristian Gmeiner 		return -EINVAL;
5369e2c2e27SChristian Gmeiner 
537f5fd9fd4SDan Carpenter 	if (signal->iter >= dom->nr_signals)
5389e2c2e27SChristian Gmeiner 		return -EINVAL;
5399e2c2e27SChristian Gmeiner 
5409e2c2e27SChristian Gmeiner 	sig = &dom->signal[signal->iter];
5419e2c2e27SChristian Gmeiner 
5429e2c2e27SChristian Gmeiner 	signal->id = signal->iter;
5439e2c2e27SChristian Gmeiner 	strncpy(signal->name, sig->name, sizeof(signal->name));
5449e2c2e27SChristian Gmeiner 
5459e2c2e27SChristian Gmeiner 	signal->iter++;
5469e2c2e27SChristian Gmeiner 	if (signal->iter == dom->nr_signals)
5479e2c2e27SChristian Gmeiner 		signal->iter = 0xffff;
5489e2c2e27SChristian Gmeiner 
5499e2c2e27SChristian Gmeiner 	return 0;
5509e2c2e27SChristian Gmeiner }
55146df52cdSChristian Gmeiner 
etnaviv_pm_req_validate(const struct drm_etnaviv_gem_submit_pmr * r,u32 exec_state)55246df52cdSChristian Gmeiner int etnaviv_pm_req_validate(const struct drm_etnaviv_gem_submit_pmr *r,
55346df52cdSChristian Gmeiner 	u32 exec_state)
55446df52cdSChristian Gmeiner {
55546df52cdSChristian Gmeiner 	const struct etnaviv_pm_domain_meta *meta = &doms_meta[exec_state];
55646df52cdSChristian Gmeiner 	const struct etnaviv_pm_domain *dom;
55746df52cdSChristian Gmeiner 
55846df52cdSChristian Gmeiner 	if (r->domain >= meta->nr_domains)
55946df52cdSChristian Gmeiner 		return -EINVAL;
56046df52cdSChristian Gmeiner 
56146df52cdSChristian Gmeiner 	dom = meta->domains + r->domain;
56246df52cdSChristian Gmeiner 
563f5fd9fd4SDan Carpenter 	if (r->signal >= dom->nr_signals)
56446df52cdSChristian Gmeiner 		return -EINVAL;
56546df52cdSChristian Gmeiner 
56646df52cdSChristian Gmeiner 	return 0;
56746df52cdSChristian Gmeiner }
568249300c7SChristian Gmeiner 
etnaviv_perfmon_process(struct etnaviv_gpu * gpu,const struct etnaviv_perfmon_request * pmr,u32 exec_state)569249300c7SChristian Gmeiner void etnaviv_perfmon_process(struct etnaviv_gpu *gpu,
5707a9c0fe2SLucas Stach 	const struct etnaviv_perfmon_request *pmr, u32 exec_state)
571249300c7SChristian Gmeiner {
5727a9c0fe2SLucas Stach 	const struct etnaviv_pm_domain_meta *meta = &doms_meta[exec_state];
573249300c7SChristian Gmeiner 	const struct etnaviv_pm_domain *dom;
574249300c7SChristian Gmeiner 	const struct etnaviv_pm_signal *sig;
575249300c7SChristian Gmeiner 	u32 *bo = pmr->bo_vma;
576249300c7SChristian Gmeiner 	u32 val;
577249300c7SChristian Gmeiner 
578249300c7SChristian Gmeiner 	dom = meta->domains + pmr->domain;
579249300c7SChristian Gmeiner 	sig = &dom->signal[pmr->signal];
580249300c7SChristian Gmeiner 	val = sig->sample(gpu, dom, sig);
581249300c7SChristian Gmeiner 
582249300c7SChristian Gmeiner 	*(bo + pmr->offset) = val;
583249300c7SChristian Gmeiner }
584