1 /*
2  * Copyright 2019 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23 
24 #include "amdgpu.h"
25 #include "amdgpu_smu.h"
26 #include "soc15_common.h"
27 #include "smu_v12_0_ppsmc.h"
28 #include "smu12_driver_if.h"
29 #include "smu_v12_0.h"
30 #include "renoir_ppt.h"
31 
32 
33 #define MSG_MAP(msg, index) \
34 	[SMU_MSG_##msg] = {1, (index)}
35 
36 #define TAB_MAP_VALID(tab) \
37 	[SMU_TABLE_##tab] = {1, TABLE_##tab}
38 
39 #define TAB_MAP_INVALID(tab) \
40 	[SMU_TABLE_##tab] = {0, TABLE_##tab}
41 
42 static struct smu_12_0_cmn2aisc_mapping renoir_message_map[SMU_MSG_MAX_COUNT] = {
43 	MSG_MAP(TestMessage,                    PPSMC_MSG_TestMessage),
44 	MSG_MAP(GetSmuVersion,                  PPSMC_MSG_GetSmuVersion),
45 	MSG_MAP(GetDriverIfVersion,             PPSMC_MSG_GetDriverIfVersion),
46 	MSG_MAP(PowerUpGfx,                     PPSMC_MSG_PowerUpGfx),
47 	MSG_MAP(AllowGfxOff,                    PPSMC_MSG_EnableGfxOff),
48 	MSG_MAP(DisallowGfxOff,                 PPSMC_MSG_DisableGfxOff),
49 	MSG_MAP(PowerDownIspByTile,             PPSMC_MSG_PowerDownIspByTile),
50 	MSG_MAP(PowerUpIspByTile,               PPSMC_MSG_PowerUpIspByTile),
51 	MSG_MAP(PowerDownVcn,                   PPSMC_MSG_PowerDownVcn),
52 	MSG_MAP(PowerUpVcn,                     PPSMC_MSG_PowerUpVcn),
53 	MSG_MAP(PowerDownSdma,                  PPSMC_MSG_PowerDownSdma),
54 	MSG_MAP(PowerUpSdma,                    PPSMC_MSG_PowerUpSdma),
55 	MSG_MAP(SetHardMinIspclkByFreq,         PPSMC_MSG_SetHardMinIspclkByFreq),
56 	MSG_MAP(SetHardMinVcn,                  PPSMC_MSG_SetHardMinVcn),
57 	MSG_MAP(Spare1,                         PPSMC_MSG_spare1),
58 	MSG_MAP(Spare2,                         PPSMC_MSG_spare2),
59 	MSG_MAP(SetAllowFclkSwitch,             PPSMC_MSG_SetAllowFclkSwitch),
60 	MSG_MAP(SetMinVideoGfxclkFreq,          PPSMC_MSG_SetMinVideoGfxclkFreq),
61 	MSG_MAP(ActiveProcessNotify,            PPSMC_MSG_ActiveProcessNotify),
62 	MSG_MAP(SetCustomPolicy,                PPSMC_MSG_SetCustomPolicy),
63 	MSG_MAP(SetVideoFps,                    PPSMC_MSG_SetVideoFps),
64 	MSG_MAP(NumOfDisplays,                  PPSMC_MSG_SetDisplayCount),
65 	MSG_MAP(QueryPowerLimit,                PPSMC_MSG_QueryPowerLimit),
66 	MSG_MAP(SetDriverDramAddrHigh,          PPSMC_MSG_SetDriverDramAddrHigh),
67 	MSG_MAP(SetDriverDramAddrLow,           PPSMC_MSG_SetDriverDramAddrLow),
68 	MSG_MAP(TransferTableSmu2Dram,          PPSMC_MSG_TransferTableSmu2Dram),
69 	MSG_MAP(TransferTableDram2Smu,          PPSMC_MSG_TransferTableDram2Smu),
70 	MSG_MAP(GfxDeviceDriverReset,           PPSMC_MSG_GfxDeviceDriverReset),
71 	MSG_MAP(SetGfxclkOverdriveByFreqVid,    PPSMC_MSG_SetGfxclkOverdriveByFreqVid),
72 	MSG_MAP(SetHardMinDcfclkByFreq,         PPSMC_MSG_SetHardMinDcfclkByFreq),
73 	MSG_MAP(SetHardMinSocclkByFreq,         PPSMC_MSG_SetHardMinSocclkByFreq),
74 	MSG_MAP(ControlIgpuATS,                 PPSMC_MSG_ControlIgpuATS),
75 	MSG_MAP(SetMinVideoFclkFreq,            PPSMC_MSG_SetMinVideoFclkFreq),
76 	MSG_MAP(SetMinDeepSleepDcfclk,          PPSMC_MSG_SetMinDeepSleepDcfclk),
77 	MSG_MAP(ForcePowerDownGfx,              PPSMC_MSG_ForcePowerDownGfx),
78 	MSG_MAP(SetPhyclkVoltageByFreq,         PPSMC_MSG_SetPhyclkVoltageByFreq),
79 	MSG_MAP(SetDppclkVoltageByFreq,         PPSMC_MSG_SetDppclkVoltageByFreq),
80 	MSG_MAP(SetSoftMinVcn,                  PPSMC_MSG_SetSoftMinVcn),
81 	MSG_MAP(EnablePostCode,                 PPSMC_MSG_EnablePostCode),
82 	MSG_MAP(GetGfxclkFrequency,             PPSMC_MSG_GetGfxclkFrequency),
83 	MSG_MAP(GetFclkFrequency,               PPSMC_MSG_GetFclkFrequency),
84 	MSG_MAP(GetMinGfxclkFrequency,          PPSMC_MSG_GetMinGfxclkFrequency),
85 	MSG_MAP(GetMaxGfxclkFrequency,          PPSMC_MSG_GetMaxGfxclkFrequency),
86 	MSG_MAP(SoftReset,                      PPSMC_MSG_SoftReset),
87 	MSG_MAP(SetGfxCGPG,                     PPSMC_MSG_SetGfxCGPG),
88 	MSG_MAP(SetSoftMaxGfxClk,               PPSMC_MSG_SetSoftMaxGfxClk),
89 	MSG_MAP(SetHardMinGfxClk,               PPSMC_MSG_SetHardMinGfxClk),
90 	MSG_MAP(SetSoftMaxSocclkByFreq,         PPSMC_MSG_SetSoftMaxSocclkByFreq),
91 	MSG_MAP(SetSoftMaxFclkByFreq,           PPSMC_MSG_SetSoftMaxFclkByFreq),
92 	MSG_MAP(SetSoftMaxVcn,                  PPSMC_MSG_SetSoftMaxVcn),
93 	MSG_MAP(PowerGateMmHub,                 PPSMC_MSG_PowerGateMmHub),
94 	MSG_MAP(UpdatePmeRestore,               PPSMC_MSG_UpdatePmeRestore),
95 	MSG_MAP(GpuChangeState,                 PPSMC_MSG_GpuChangeState),
96 	MSG_MAP(SetPowerLimitPercentage,        PPSMC_MSG_SetPowerLimitPercentage),
97 	MSG_MAP(ForceGfxContentSave,            PPSMC_MSG_ForceGfxContentSave),
98 	MSG_MAP(EnableTmdp48MHzRefclkPwrDown,   PPSMC_MSG_EnableTmdp48MHzRefclkPwrDown),
99 	MSG_MAP(PowerDownJpeg,                  PPSMC_MSG_PowerDownJpeg),
100 	MSG_MAP(PowerUpJpeg,                    PPSMC_MSG_PowerUpJpeg),
101 	MSG_MAP(PowerGateAtHub,                 PPSMC_MSG_PowerGateAtHub),
102 	MSG_MAP(SetSoftMinJpeg,                 PPSMC_MSG_SetSoftMinJpeg),
103 	MSG_MAP(SetHardMinFclkByFreq,           PPSMC_MSG_SetHardMinFclkByFreq),
104 };
105 
106 static struct smu_12_0_cmn2aisc_mapping renoir_table_map[SMU_TABLE_COUNT] = {
107 	TAB_MAP_VALID(WATERMARKS),
108 	TAB_MAP_INVALID(CUSTOM_DPM),
109 	TAB_MAP_VALID(DPMCLOCKS),
110 	TAB_MAP_VALID(SMU_METRICS),
111 };
112 
renoir_get_smu_msg_index(struct smu_context * smc,uint32_t index)113 static int renoir_get_smu_msg_index(struct smu_context *smc, uint32_t index)
114 {
115 	struct smu_12_0_cmn2aisc_mapping mapping;
116 
117 	if (index >= SMU_MSG_MAX_COUNT)
118 		return -EINVAL;
119 
120 	mapping = renoir_message_map[index];
121 	if (!(mapping.valid_mapping))
122 		return -EINVAL;
123 
124 	return mapping.map_to;
125 }
126 
renoir_get_smu_table_index(struct smu_context * smc,uint32_t index)127 static int renoir_get_smu_table_index(struct smu_context *smc, uint32_t index)
128 {
129 	struct smu_12_0_cmn2aisc_mapping mapping;
130 
131 	if (index >= SMU_TABLE_COUNT)
132 		return -EINVAL;
133 
134 	mapping = renoir_table_map[index];
135 	if (!(mapping.valid_mapping))
136 		return -EINVAL;
137 
138 	return mapping.map_to;
139 }
140 
renoir_tables_init(struct smu_context * smu,struct smu_table * tables)141 static int renoir_tables_init(struct smu_context *smu, struct smu_table *tables)
142 {
143 	struct smu_table_context *smu_table = &smu->smu_table;
144 
145 	SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
146 		PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
147 	SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t),
148 		PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
149 	SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
150 		PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
151 
152 	smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL);
153 	if (!smu_table->clocks_table)
154 		return -ENOMEM;
155 
156 	return 0;
157 }
158 
159 /**
160  * This interface just for getting uclk ultimate freq and should't introduce
161  * other likewise function result in overmuch callback.
162  */
renoir_get_dpm_uclk_limited(struct smu_context * smu,uint32_t * clock,bool max)163 static int renoir_get_dpm_uclk_limited(struct smu_context *smu, uint32_t *clock, bool max)
164 {
165 
166 	DpmClocks_t *table = smu->smu_table.clocks_table;
167 
168 	if (!clock || !table)
169 		return -EINVAL;
170 
171 	if (max)
172 		*clock = table->FClocks[NUM_FCLK_DPM_LEVELS-1].Freq;
173 	else
174 		*clock = table->FClocks[0].Freq;
175 
176 	return 0;
177 
178 }
179 
renoir_print_clk_levels(struct smu_context * smu,enum smu_clk_type clk_type,char * buf)180 static int renoir_print_clk_levels(struct smu_context *smu,
181 			enum smu_clk_type clk_type, char *buf)
182 {
183 	int i, size = 0, ret = 0;
184 	uint32_t cur_value = 0, value = 0, count = 0, min = 0, max = 0;
185 	DpmClocks_t *clk_table = smu->smu_table.clocks_table;
186 	SmuMetrics_t metrics = {0};
187 
188 	if (!clk_table || clk_type >= SMU_CLK_COUNT)
189 		return -EINVAL;
190 
191 	ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
192 			       (void *)&metrics, false);
193 	if (ret)
194 		return ret;
195 
196 	switch (clk_type) {
197 	case SMU_GFXCLK:
198 	case SMU_SCLK:
199 		/* retirve table returned paramters unit is MHz */
200 		cur_value = metrics.ClockFrequency[CLOCK_GFXCLK];
201 		ret = smu_get_dpm_freq_range(smu, SMU_GFXCLK, &min, &max);
202 		if (!ret) {
203 			/* driver only know min/max gfx_clk, Add level 1 for all other gfx clks */
204 			if (cur_value  == max)
205 				i = 2;
206 			else if (cur_value == min)
207 				i = 0;
208 			else
209 				i = 1;
210 
211 			size += sprintf(buf + size, "0: %uMhz %s\n", min,
212 					i == 0 ? "*" : "");
213 			size += sprintf(buf + size, "1: %uMhz %s\n",
214 					i == 1 ? cur_value : RENOIR_UMD_PSTATE_GFXCLK,
215 					i == 1 ? "*" : "");
216 			size += sprintf(buf + size, "2: %uMhz %s\n", max,
217 					i == 2 ? "*" : "");
218 		}
219 		return size;
220 	case SMU_SOCCLK:
221 		count = NUM_SOCCLK_DPM_LEVELS;
222 		cur_value = metrics.ClockFrequency[CLOCK_SOCCLK];
223 		break;
224 	case SMU_MCLK:
225 		count = NUM_MEMCLK_DPM_LEVELS;
226 		cur_value = metrics.ClockFrequency[CLOCK_UMCCLK];
227 		break;
228 	case SMU_DCEFCLK:
229 		count = NUM_DCFCLK_DPM_LEVELS;
230 		cur_value = metrics.ClockFrequency[CLOCK_DCFCLK];
231 		break;
232 	case SMU_FCLK:
233 		count = NUM_FCLK_DPM_LEVELS;
234 		cur_value = metrics.ClockFrequency[CLOCK_FCLK];
235 		break;
236 	default:
237 		return -EINVAL;
238 	}
239 
240 	for (i = 0; i < count; i++) {
241 		GET_DPM_CUR_FREQ(clk_table, clk_type, i, value);
242 		size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
243 				cur_value == value ? "*" : "");
244 	}
245 
246 	return size;
247 }
248 
249 static const struct pptable_funcs renoir_ppt_funcs = {
250 	.get_smu_msg_index = renoir_get_smu_msg_index,
251 	.get_smu_table_index = renoir_get_smu_table_index,
252 	.tables_init = renoir_tables_init,
253 	.set_power_state = NULL,
254 	.get_dpm_uclk_limited = renoir_get_dpm_uclk_limited,
255 	.print_clk_levels = renoir_print_clk_levels,
256 };
257 
renoir_set_ppt_funcs(struct smu_context * smu)258 void renoir_set_ppt_funcs(struct smu_context *smu)
259 {
260 	struct smu_table_context *smu_table = &smu->smu_table;
261 
262 	smu->ppt_funcs = &renoir_ppt_funcs;
263 	smu->smc_if_version = SMU12_DRIVER_IF_VERSION;
264 	smu_table->table_count = TABLE_COUNT;
265 }
266