File Index
Files and directories
Sign in
FILE

vega12_smumgr.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c C
  1/*
  2 * Copyright 2017 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 "smumgr.h"
 25#include "vega12_inc.h"
 26#include "soc15_common.h"
 27#include "smu9_smumgr.h"
 28#include "vega12_smumgr.h"
 29#include "vega12_ppsmc.h"
 30#include "vega12/smu9_driver_if.h"
 31#include "ppatomctrl.h"
 32#include "pp_debug.h"
 33
 34
 35/*
 36 * Copy table from SMC into driver FB
 37 * @param   hwmgr    the address of the HW manager
 38 * @param   table_id    the driver's table ID to copy from
 39 */
 40static int vega12_copy_table_from_smc(struct pp_hwmgr *hwmgr,
 41				      uint8_t *table, int16_t table_id)
 42{
 43	struct vega12_smumgr *priv =
 44			(struct vega12_smumgr *)(hwmgr->smu_backend);
 45	struct amdgpu_device *adev = hwmgr->adev;
 46
 47	PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT,
 48			"Invalid SMU Table ID!", return -EINVAL);
 49	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
 50			"Invalid SMU Table version!", return -EINVAL);
 51	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
 52			"Invalid SMU Table Length!", return -EINVAL);
 53	PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
 54			PPSMC_MSG_SetDriverDramAddrHigh,
 55			upper_32_bits(priv->smu_tables.entry[table_id].mc_addr),
 56			NULL) == 0,
 57			"[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL);
 58	PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
 59			PPSMC_MSG_SetDriverDramAddrLow,
 60			lower_32_bits(priv->smu_tables.entry[table_id].mc_addr),
 61			NULL) == 0,
 62			"[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!",
 63			return -EINVAL);
 64	PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
 65			PPSMC_MSG_TransferTableSmu2Dram,
 66			table_id,
 67			NULL) == 0,
 68			"[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!",
 69			return -EINVAL);
 70
 71	amdgpu_hdp_invalidate(adev, NULL);
 72
 73	memcpy(table, priv->smu_tables.entry[table_id].table,
 74			priv->smu_tables.entry[table_id].size);
 75
 76	return 0;
 77}
 78
 79/*
 80 * Copy table from Driver FB into SMC
 81 * @param   hwmgr    the address of the HW manager
 82 * @param   table_id    the table to copy from
 83 */
 84static int vega12_copy_table_to_smc(struct pp_hwmgr *hwmgr,
 85				    uint8_t *table, int16_t table_id)
 86{
 87	struct vega12_smumgr *priv =
 88			(struct vega12_smumgr *)(hwmgr->smu_backend);
 89	struct amdgpu_device *adev = hwmgr->adev;
 90
 91	PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT,
 92			"Invalid SMU Table ID!", return -EINVAL);
 93	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
 94			"Invalid SMU Table version!", return -EINVAL);
 95	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
 96			"Invalid SMU Table Length!", return -EINVAL);
 97
 98	memcpy(priv->smu_tables.entry[table_id].table, table,
 99			priv->smu_tables.entry[table_id].size);
100
101	amdgpu_hdp_flush(adev, NULL);
102
103	PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
104			PPSMC_MSG_SetDriverDramAddrHigh,
105			upper_32_bits(priv->smu_tables.entry[table_id].mc_addr),
106			NULL) == 0,
107			"[CopyTableToSMC] Attempt to Set Dram Addr High Failed!",
108			return -EINVAL;);
109	PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
110			PPSMC_MSG_SetDriverDramAddrLow,
111			lower_32_bits(priv->smu_tables.entry[table_id].mc_addr),
112			NULL) == 0,
113			"[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!",
114			return -EINVAL);
115	PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
116			PPSMC_MSG_TransferTableDram2Smu,
117			table_id,
118			NULL) == 0,
119			"[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!",
120			return -EINVAL);
121
122	return 0;
123}
124
125int vega12_enable_smc_features(struct pp_hwmgr *hwmgr,
126		bool enable, uint64_t feature_mask)
127{
128	uint32_t smu_features_low, smu_features_high;
129
130	smu_features_low = (uint32_t)((feature_mask & SMU_FEATURES_LOW_MASK) >> SMU_FEATURES_LOW_SHIFT);
131	smu_features_high = (uint32_t)((feature_mask & SMU_FEATURES_HIGH_MASK) >> SMU_FEATURES_HIGH_SHIFT);
132
133	if (enable) {
134		PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
135				PPSMC_MSG_EnableSmuFeaturesLow, smu_features_low, NULL) == 0,
136				"[EnableDisableSMCFeatures] Attempt to enable SMU features Low failed!",
137				return -EINVAL);
138		PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
139				PPSMC_MSG_EnableSmuFeaturesHigh, smu_features_high, NULL) == 0,
140				"[EnableDisableSMCFeatures] Attempt to enable SMU features High failed!",
141				return -EINVAL);
142	} else {
143		PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
144				PPSMC_MSG_DisableSmuFeaturesLow, smu_features_low, NULL) == 0,
145				"[EnableDisableSMCFeatures] Attempt to disable SMU features Low failed!",
146				return -EINVAL);
147		PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
148				PPSMC_MSG_DisableSmuFeaturesHigh, smu_features_high, NULL) == 0,
149				"[EnableDisableSMCFeatures] Attempt to disable SMU features High failed!",
150				return -EINVAL);
151	}
152
153	return 0;
154}
155
156int vega12_get_enabled_smc_features(struct pp_hwmgr *hwmgr,
157		uint64_t *features_enabled)
158{
159	uint32_t smc_features_low, smc_features_high;
160
161	if (features_enabled == NULL)
162		return -EINVAL;
163
164	PP_ASSERT_WITH_CODE(smum_send_msg_to_smc(hwmgr,
165			PPSMC_MSG_GetEnabledSmuFeaturesLow,
166			&smc_features_low) == 0,
167			"[GetEnabledSMCFeatures] Attempt to get SMU features Low failed!",
168			return -EINVAL);
169
170	PP_ASSERT_WITH_CODE(smum_send_msg_to_smc(hwmgr,
171			PPSMC_MSG_GetEnabledSmuFeaturesHigh,
172			&smc_features_high) == 0,
173			"[GetEnabledSMCFeatures] Attempt to get SMU features High failed!",
174			return -EINVAL);
175
176	*features_enabled = ((((uint64_t)smc_features_low << SMU_FEATURES_LOW_SHIFT) & SMU_FEATURES_LOW_MASK) |
177			(((uint64_t)smc_features_high << SMU_FEATURES_HIGH_SHIFT) & SMU_FEATURES_HIGH_MASK));
178
179	return 0;
180}
181
182static bool vega12_is_dpm_running(struct pp_hwmgr *hwmgr)
183{
184	uint64_t features_enabled = 0;
185
186	vega12_get_enabled_smc_features(hwmgr, &features_enabled);
187
188	if (features_enabled & SMC_DPM_FEATURES)
189		return true;
190	else
191		return false;
192}
193
194static int vega12_set_tools_address(struct pp_hwmgr *hwmgr)
195{
196	struct vega12_smumgr *priv =
197			(struct vega12_smumgr *)(hwmgr->smu_backend);
198
199	if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr) {
200		if (!smum_send_msg_to_smc_with_parameter(hwmgr,
201				PPSMC_MSG_SetToolsDramAddrHigh,
202				upper_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr),
203				NULL))
204			smum_send_msg_to_smc_with_parameter(hwmgr,
205					PPSMC_MSG_SetToolsDramAddrLow,
206					lower_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr),
207					NULL);
208	}
209	return 0;
210}
211
212static int vega12_smu_init(struct pp_hwmgr *hwmgr)
213{
214	struct vega12_smumgr *priv;
215	unsigned long tools_size;
216	struct cgs_firmware_info info = {0};
217	int ret;
218
219	ret = cgs_get_firmware_info(hwmgr->device, CGS_UCODE_ID_SMU,
220				&info);
221	if (ret || !info.kptr)
222		return -EINVAL;
223
224	priv = kzalloc(sizeof(struct vega12_smumgr), GFP_KERNEL);
225	if (!priv)
226		return -ENOMEM;
227
228	hwmgr->smu_backend = priv;
229
230	/* allocate space for pptable */
231	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
232			sizeof(PPTable_t),
233			PAGE_SIZE,
234			AMDGPU_GEM_DOMAIN_VRAM,
235			&priv->smu_tables.entry[TABLE_PPTABLE].handle,
236			&priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
237			&priv->smu_tables.entry[TABLE_PPTABLE].table);
238	if (ret)
239		goto free_backend;
240
241	priv->smu_tables.entry[TABLE_PPTABLE].version = 0x01;
242	priv->smu_tables.entry[TABLE_PPTABLE].size = sizeof(PPTable_t);
243
244	/* allocate space for watermarks table */
245	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
246				      sizeof(Watermarks_t),
247				      PAGE_SIZE,
248				      AMDGPU_GEM_DOMAIN_VRAM,
249				      &priv->smu_tables.entry[TABLE_WATERMARKS].handle,
250				      &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
251				      &priv->smu_tables.entry[TABLE_WATERMARKS].table);
252
253	if (ret)
254		goto err0;
255
256	priv->smu_tables.entry[TABLE_WATERMARKS].version = 0x01;
257	priv->smu_tables.entry[TABLE_WATERMARKS].size = sizeof(Watermarks_t);
258
259	tools_size = 0x19000;
260	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
261				      tools_size,
262				      PAGE_SIZE,
263				      AMDGPU_GEM_DOMAIN_VRAM,
264				      &priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
265				      &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
266				      &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
267	if (ret)
268		goto err1;
269
270	priv->smu_tables.entry[TABLE_PMSTATUSLOG].version = 0x01;
271	priv->smu_tables.entry[TABLE_PMSTATUSLOG].size = tools_size;
272
273	/* allocate space for AVFS Fuse table */
274	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
275				      sizeof(AvfsFuseOverride_t),
276				      PAGE_SIZE,
277				      AMDGPU_GEM_DOMAIN_VRAM,
278				      &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle,
279				      &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr,
280				      &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table);
281
282	if (ret)
283		goto err2;
284
285	priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].version = 0x01;
286	priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].size = sizeof(AvfsFuseOverride_t);
287
288	/* allocate space for OverDrive table */
289	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
290				      sizeof(OverDriveTable_t),
291				      PAGE_SIZE,
292				      AMDGPU_GEM_DOMAIN_VRAM,
293				      &priv->smu_tables.entry[TABLE_OVERDRIVE].handle,
294				      &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr,
295				      &priv->smu_tables.entry[TABLE_OVERDRIVE].table);
296	if (ret)
297		goto err3;
298
299	priv->smu_tables.entry[TABLE_OVERDRIVE].version = 0x01;
300	priv->smu_tables.entry[TABLE_OVERDRIVE].size = sizeof(OverDriveTable_t);
301
302	/* allocate space for SMU_METRICS table */
303	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
304				      sizeof(SmuMetrics_t),
305				      PAGE_SIZE,
306				      AMDGPU_GEM_DOMAIN_VRAM,
307				      &priv->smu_tables.entry[TABLE_SMU_METRICS].handle,
308				      &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr,
309				      &priv->smu_tables.entry[TABLE_SMU_METRICS].table);
310	if (ret)
311		goto err4;
312
313	priv->smu_tables.entry[TABLE_SMU_METRICS].version = 0x01;
314	priv->smu_tables.entry[TABLE_SMU_METRICS].size = sizeof(SmuMetrics_t);
315
316	return 0;
317
318err4:
319	amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle,
320				&priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr,
321				&priv->smu_tables.entry[TABLE_OVERDRIVE].table);
322err3:
323	amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle,
324				&priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr,
325				&priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table);
326err2:
327	if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].table)
328		amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
329				&priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
330				&priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
331err1:
332	amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle,
333				&priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
334				&priv->smu_tables.entry[TABLE_WATERMARKS].table);
335err0:
336	amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle,
337			&priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
338			&priv->smu_tables.entry[TABLE_PPTABLE].table);
339free_backend:
340	kfree(hwmgr->smu_backend);
341
342	return -EINVAL;
343}
344
345static int vega12_smu_fini(struct pp_hwmgr *hwmgr)
346{
347	struct vega12_smumgr *priv =
348			(struct vega12_smumgr *)(hwmgr->smu_backend);
349
350	if (priv) {
351		amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle,
352				      &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
353				      &priv->smu_tables.entry[TABLE_PPTABLE].table);
354		amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle,
355				      &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
356				      &priv->smu_tables.entry[TABLE_WATERMARKS].table);
357		if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].table)
358			amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
359					      &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
360					      &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
361		amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle,
362				      &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr,
363				      &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table);
364		amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle,
365				      &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr,
366				      &priv->smu_tables.entry[TABLE_OVERDRIVE].table);
367		amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_SMU_METRICS].handle,
368				      &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr,
369				      &priv->smu_tables.entry[TABLE_SMU_METRICS].table);
370		kfree(hwmgr->smu_backend);
371		hwmgr->smu_backend = NULL;
372	}
373	return 0;
374}
375
376static int vega12_start_smu(struct pp_hwmgr *hwmgr)
377{
378	PP_ASSERT_WITH_CODE(smu9_is_smc_ram_running(hwmgr),
379			"SMC is not running!",
380			return -EINVAL);
381
382	vega12_set_tools_address(hwmgr);
383
384	return 0;
385}
386
387static int vega12_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table,
388				    uint16_t table_id, bool rw)
389{
390	int ret;
391
392	if (rw)
393		ret = vega12_copy_table_from_smc(hwmgr, table, table_id);
394	else
395		ret = vega12_copy_table_to_smc(hwmgr, table, table_id);
396
397	return ret;
398}
399
400const struct pp_smumgr_func vega12_smu_funcs = {
401	.name = "vega12_smu",
402	.smu_init = &vega12_smu_init,
403	.smu_fini = &vega12_smu_fini,
404	.start_smu = &vega12_start_smu,
405	.request_smu_load_specific_fw = NULL,
406	.send_msg_to_smc = &smu9_send_msg_to_smc,
407	.send_msg_to_smc_with_parameter = &smu9_send_msg_to_smc_with_parameter,
408	.download_pptable_settings = NULL,
409	.upload_pptable_settings = NULL,
410	.is_dpm_running = vega12_is_dpm_running,
411	.get_argument = smu9_get_argument,
412	.smc_table_manager = vega12_smc_table_manager,
413};
~/ Read-only file preview.