Home | History | Annotate | Line # | Download | only in smumgr
      1 /*	$NetBSD: amdgpu_vega12_smumgr.c,v 1.2 2021/12/18 23:45:27 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright 2017 Advanced Micro Devices, Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  */
     25 
     26 #include <sys/cdefs.h>
     27 __KERNEL_RCSID(0, "$NetBSD: amdgpu_vega12_smumgr.c,v 1.2 2021/12/18 23:45:27 riastradh Exp $");
     28 
     29 #include "smumgr.h"
     30 #include "vega12_inc.h"
     31 #include "soc15_common.h"
     32 #include "smu9_smumgr.h"
     33 #include "vega12_smumgr.h"
     34 #include "vega12_ppsmc.h"
     35 #include "vega12/smu9_driver_if.h"
     36 #include "ppatomctrl.h"
     37 #include "pp_debug.h"
     38 
     39 
     40 /*
     41  * Copy table from SMC into driver FB
     42  * @param   hwmgr    the address of the HW manager
     43  * @param   table_id    the driver's table ID to copy from
     44  */
     45 static int vega12_copy_table_from_smc(struct pp_hwmgr *hwmgr,
     46 				      uint8_t *table, int16_t table_id)
     47 {
     48 	struct vega12_smumgr *priv =
     49 			(struct vega12_smumgr *)(hwmgr->smu_backend);
     50 	struct amdgpu_device *adev = hwmgr->adev;
     51 
     52 	PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT,
     53 			"Invalid SMU Table ID!", return -EINVAL);
     54 	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
     55 			"Invalid SMU Table version!", return -EINVAL);
     56 	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
     57 			"Invalid SMU Table Length!", return -EINVAL);
     58 	PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr,
     59 			PPSMC_MSG_SetDriverDramAddrHigh,
     60 			upper_32_bits(priv->smu_tables.entry[table_id].mc_addr)) == 0,
     61 			"[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL);
     62 	PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr,
     63 			PPSMC_MSG_SetDriverDramAddrLow,
     64 			lower_32_bits(priv->smu_tables.entry[table_id].mc_addr)) == 0,
     65 			"[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!",
     66 			return -EINVAL);
     67 	PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr,
     68 			PPSMC_MSG_TransferTableSmu2Dram,
     69 			table_id) == 0,
     70 			"[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!",
     71 			return -EINVAL);
     72 
     73 	/* flush hdp cache */
     74 	amdgpu_asic_flush_hdp(adev, NULL);
     75 
     76 	memcpy(table, priv->smu_tables.entry[table_id].table,
     77 			priv->smu_tables.entry[table_id].size);
     78 
     79 	return 0;
     80 }
     81 
     82 /*
     83  * Copy table from Driver FB into SMC
     84  * @param   hwmgr    the address of the HW manager
     85  * @param   table_id    the table to copy from
     86  */
     87 static int vega12_copy_table_to_smc(struct pp_hwmgr *hwmgr,
     88 				    uint8_t *table, int16_t table_id)
     89 {
     90 	struct vega12_smumgr *priv =
     91 			(struct vega12_smumgr *)(hwmgr->smu_backend);
     92 	struct amdgpu_device *adev = hwmgr->adev;
     93 
     94 	PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT,
     95 			"Invalid SMU Table ID!", return -EINVAL);
     96 	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
     97 			"Invalid SMU Table version!", return -EINVAL);
     98 	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
     99 			"Invalid SMU Table Length!", return -EINVAL);
    100 
    101 	memcpy(priv->smu_tables.entry[table_id].table, table,
    102 			priv->smu_tables.entry[table_id].size);
    103 
    104 	amdgpu_asic_flush_hdp(adev, NULL);
    105 
    106 	PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr,
    107 			PPSMC_MSG_SetDriverDramAddrHigh,
    108 			upper_32_bits(priv->smu_tables.entry[table_id].mc_addr)) == 0,
    109 			"[CopyTableToSMC] Attempt to Set Dram Addr High Failed!",
    110 			return -EINVAL;);
    111 	PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr,
    112 			PPSMC_MSG_SetDriverDramAddrLow,
    113 			lower_32_bits(priv->smu_tables.entry[table_id].mc_addr)) == 0,
    114 			"[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!",
    115 			return -EINVAL);
    116 	PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr,
    117 			PPSMC_MSG_TransferTableDram2Smu,
    118 			table_id) == 0,
    119 			"[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!",
    120 			return -EINVAL);
    121 
    122 	return 0;
    123 }
    124 
    125 int 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(smu9_send_msg_to_smc_with_parameter(hwmgr,
    135 				PPSMC_MSG_EnableSmuFeaturesLow, smu_features_low) == 0,
    136 				"[EnableDisableSMCFeatures] Attempt to enable SMU features Low failed!",
    137 				return -EINVAL);
    138 		PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr,
    139 				PPSMC_MSG_EnableSmuFeaturesHigh, smu_features_high) == 0,
    140 				"[EnableDisableSMCFeatures] Attempt to enable SMU features High failed!",
    141 				return -EINVAL);
    142 	} else {
    143 		PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr,
    144 				PPSMC_MSG_DisableSmuFeaturesLow, smu_features_low) == 0,
    145 				"[EnableDisableSMCFeatures] Attempt to disable SMU features Low failed!",
    146 				return -EINVAL);
    147 		PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr,
    148 				PPSMC_MSG_DisableSmuFeaturesHigh, smu_features_high) == 0,
    149 				"[EnableDisableSMCFeatures] Attempt to disable SMU features High failed!",
    150 				return -EINVAL);
    151 	}
    152 
    153 	return 0;
    154 }
    155 
    156 int 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(smu9_send_msg_to_smc(hwmgr,
    165 			PPSMC_MSG_GetEnabledSmuFeaturesLow) == 0,
    166 			"[GetEnabledSMCFeatures] Attempt to get SMU features Low failed!",
    167 			return -EINVAL);
    168 	smc_features_low = smu9_get_argument(hwmgr);
    169 
    170 	PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc(hwmgr,
    171 			PPSMC_MSG_GetEnabledSmuFeaturesHigh) == 0,
    172 			"[GetEnabledSMCFeatures] Attempt to get SMU features High failed!",
    173 			return -EINVAL);
    174 	smc_features_high = smu9_get_argument(hwmgr);
    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 
    182 static 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 
    194 static 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 (!smu9_send_msg_to_smc_with_parameter(hwmgr,
    201 				PPSMC_MSG_SetToolsDramAddrHigh,
    202 				upper_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr)))
    203 			smu9_send_msg_to_smc_with_parameter(hwmgr,
    204 					PPSMC_MSG_SetToolsDramAddrLow,
    205 					lower_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr));
    206 	}
    207 	return 0;
    208 }
    209 
    210 static int vega12_smu_init(struct pp_hwmgr *hwmgr)
    211 {
    212 	struct vega12_smumgr *priv;
    213 	unsigned long tools_size;
    214 	struct cgs_firmware_info info = {0};
    215 	int ret;
    216 
    217 	ret = cgs_get_firmware_info(hwmgr->device, CGS_UCODE_ID_SMU,
    218 				&info);
    219 	if (ret || !info.kptr)
    220 		return -EINVAL;
    221 
    222 	priv = kzalloc(sizeof(struct vega12_smumgr), GFP_KERNEL);
    223 	if (!priv)
    224 		return -ENOMEM;
    225 
    226 	hwmgr->smu_backend = priv;
    227 
    228 	/* allocate space for pptable */
    229 	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
    230 			sizeof(PPTable_t),
    231 			PAGE_SIZE,
    232 			AMDGPU_GEM_DOMAIN_VRAM,
    233 			&priv->smu_tables.entry[TABLE_PPTABLE].handle,
    234 			&priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
    235 			&priv->smu_tables.entry[TABLE_PPTABLE].table);
    236 	if (ret)
    237 		goto free_backend;
    238 
    239 	priv->smu_tables.entry[TABLE_PPTABLE].version = 0x01;
    240 	priv->smu_tables.entry[TABLE_PPTABLE].size = sizeof(PPTable_t);
    241 
    242 	/* allocate space for watermarks table */
    243 	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
    244 				      sizeof(Watermarks_t),
    245 				      PAGE_SIZE,
    246 				      AMDGPU_GEM_DOMAIN_VRAM,
    247 				      &priv->smu_tables.entry[TABLE_WATERMARKS].handle,
    248 				      &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
    249 				      &priv->smu_tables.entry[TABLE_WATERMARKS].table);
    250 
    251 	if (ret)
    252 		goto err0;
    253 
    254 	priv->smu_tables.entry[TABLE_WATERMARKS].version = 0x01;
    255 	priv->smu_tables.entry[TABLE_WATERMARKS].size = sizeof(Watermarks_t);
    256 
    257 	tools_size = 0x19000;
    258 	if (tools_size) {
    259 		ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
    260 					      tools_size,
    261 					      PAGE_SIZE,
    262 					      AMDGPU_GEM_DOMAIN_VRAM,
    263 					      &priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
    264 					      &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
    265 					      &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
    266 		if (ret)
    267 			goto err1;
    268 
    269 		priv->smu_tables.entry[TABLE_PMSTATUSLOG].version = 0x01;
    270 		priv->smu_tables.entry[TABLE_PMSTATUSLOG].size = tools_size;
    271 	}
    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 
    318 err4:
    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);
    322 err3:
    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);
    326 err2:
    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);
    331 err1:
    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);
    335 err0:
    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);
    339 free_backend:
    340 	kfree(hwmgr->smu_backend);
    341 
    342 	return -EINVAL;
    343 }
    344 
    345 static 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 
    376 static 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 
    387 static 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 
    400 const 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 };
    414