Home | History | Annotate | Line # | Download | only in smumgr
      1 /*	$NetBSD: amdgpu_smu10_smumgr.c,v 1.2 2021/12/18 23:45:27 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright 2016 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_smu10_smumgr.c,v 1.2 2021/12/18 23:45:27 riastradh Exp $");
     28 
     29 #include <linux/pci.h>
     30 
     31 #include "smumgr.h"
     32 #include "smu10_inc.h"
     33 #include "soc15_common.h"
     34 #include "smu10_smumgr.h"
     35 #include "ppatomctrl.h"
     36 #include "rv_ppsmc.h"
     37 #include "smu10_driver_if.h"
     38 #include "smu10.h"
     39 #include "pp_debug.h"
     40 
     41 
     42 #define BUFFER_SIZE                 80000
     43 #define MAX_STRING_SIZE             15
     44 #define BUFFER_SIZETWO              131072
     45 
     46 #define MP0_Public                  0x03800000
     47 #define MP0_SRAM                    0x03900000
     48 #define MP1_Public                  0x03b00000
     49 #define MP1_SRAM                    0x03c00004
     50 
     51 #define smnMP1_FIRMWARE_FLAGS       0x3010028
     52 
     53 
     54 static uint32_t smu10_wait_for_response(struct pp_hwmgr *hwmgr)
     55 {
     56 	struct amdgpu_device *adev = hwmgr->adev;
     57 	uint32_t reg;
     58 
     59 	reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_90);
     60 
     61 	phm_wait_for_register_unequal(hwmgr, reg,
     62 			0, MP1_C2PMSG_90__CONTENT_MASK);
     63 
     64 	return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90);
     65 }
     66 
     67 static int smu10_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr,
     68 		uint16_t msg)
     69 {
     70 	struct amdgpu_device *adev = hwmgr->adev;
     71 
     72 	WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66, msg);
     73 
     74 	return 0;
     75 }
     76 
     77 static uint32_t smu10_read_arg_from_smc(struct pp_hwmgr *hwmgr)
     78 {
     79 	struct amdgpu_device *adev = hwmgr->adev;
     80 
     81 	return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82);
     82 }
     83 
     84 static int smu10_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
     85 {
     86 	struct amdgpu_device *adev = hwmgr->adev;
     87 
     88 	smu10_wait_for_response(hwmgr);
     89 
     90 	WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0);
     91 
     92 	smu10_send_msg_to_smc_without_waiting(hwmgr, msg);
     93 
     94 	if (smu10_wait_for_response(hwmgr) == 0)
     95 		printk("Failed to send Message %x.\n", msg);
     96 
     97 	return 0;
     98 }
     99 
    100 
    101 static int smu10_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
    102 		uint16_t msg, uint32_t parameter)
    103 {
    104 	struct amdgpu_device *adev = hwmgr->adev;
    105 
    106 	smu10_wait_for_response(hwmgr);
    107 
    108 	WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0);
    109 
    110 	WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82, parameter);
    111 
    112 	smu10_send_msg_to_smc_without_waiting(hwmgr, msg);
    113 
    114 
    115 	if (smu10_wait_for_response(hwmgr) == 0)
    116 		printk("Failed to send Message %x.\n", msg);
    117 
    118 	return 0;
    119 }
    120 
    121 static int smu10_copy_table_from_smc(struct pp_hwmgr *hwmgr,
    122 		uint8_t *table, int16_t table_id)
    123 {
    124 	struct smu10_smumgr *priv =
    125 			(struct smu10_smumgr *)(hwmgr->smu_backend);
    126 	struct amdgpu_device *adev = hwmgr->adev;
    127 
    128 	PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
    129 			"Invalid SMU Table ID!", return -EINVAL;);
    130 	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
    131 			"Invalid SMU Table version!", return -EINVAL;);
    132 	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
    133 			"Invalid SMU Table Length!", return -EINVAL;);
    134 	smu10_send_msg_to_smc_with_parameter(hwmgr,
    135 			PPSMC_MSG_SetDriverDramAddrHigh,
    136 			upper_32_bits(priv->smu_tables.entry[table_id].mc_addr));
    137 	smu10_send_msg_to_smc_with_parameter(hwmgr,
    138 			PPSMC_MSG_SetDriverDramAddrLow,
    139 			lower_32_bits(priv->smu_tables.entry[table_id].mc_addr));
    140 	smu10_send_msg_to_smc_with_parameter(hwmgr,
    141 			PPSMC_MSG_TransferTableSmu2Dram,
    142 			priv->smu_tables.entry[table_id].table_id);
    143 
    144 	/* flush hdp cache */
    145 	amdgpu_asic_flush_hdp(adev, NULL);
    146 
    147 	memcpy(table, (uint8_t *)priv->smu_tables.entry[table_id].table,
    148 			priv->smu_tables.entry[table_id].size);
    149 
    150 	return 0;
    151 }
    152 
    153 static int smu10_copy_table_to_smc(struct pp_hwmgr *hwmgr,
    154 		uint8_t *table, int16_t table_id)
    155 {
    156 	struct smu10_smumgr *priv =
    157 			(struct smu10_smumgr *)(hwmgr->smu_backend);
    158 	struct amdgpu_device *adev = hwmgr->adev;
    159 
    160 	PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
    161 			"Invalid SMU Table ID!", return -EINVAL;);
    162 	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
    163 			"Invalid SMU Table version!", return -EINVAL;);
    164 	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
    165 			"Invalid SMU Table Length!", return -EINVAL;);
    166 
    167 	memcpy(priv->smu_tables.entry[table_id].table, table,
    168 			priv->smu_tables.entry[table_id].size);
    169 
    170 	amdgpu_asic_flush_hdp(adev, NULL);
    171 
    172 	smu10_send_msg_to_smc_with_parameter(hwmgr,
    173 			PPSMC_MSG_SetDriverDramAddrHigh,
    174 			upper_32_bits(priv->smu_tables.entry[table_id].mc_addr));
    175 	smu10_send_msg_to_smc_with_parameter(hwmgr,
    176 			PPSMC_MSG_SetDriverDramAddrLow,
    177 			lower_32_bits(priv->smu_tables.entry[table_id].mc_addr));
    178 	smu10_send_msg_to_smc_with_parameter(hwmgr,
    179 			PPSMC_MSG_TransferTableDram2Smu,
    180 			priv->smu_tables.entry[table_id].table_id);
    181 
    182 	return 0;
    183 }
    184 
    185 static int smu10_verify_smc_interface(struct pp_hwmgr *hwmgr)
    186 {
    187 	uint32_t smc_driver_if_version;
    188 
    189 	smu10_send_msg_to_smc(hwmgr,
    190 			PPSMC_MSG_GetDriverIfVersion);
    191 	smc_driver_if_version = smu10_read_arg_from_smc(hwmgr);
    192 
    193 	if ((smc_driver_if_version != SMU10_DRIVER_IF_VERSION) &&
    194 	    (smc_driver_if_version != SMU10_DRIVER_IF_VERSION + 1)) {
    195 		pr_err("Attempt to read SMC IF Version Number Failed!\n");
    196 		return -EINVAL;
    197 	}
    198 
    199 	return 0;
    200 }
    201 
    202 static int smu10_smu_fini(struct pp_hwmgr *hwmgr)
    203 {
    204 	struct smu10_smumgr *priv =
    205 			(struct smu10_smumgr *)(hwmgr->smu_backend);
    206 
    207 	if (priv) {
    208 		amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle,
    209 					&priv->smu_tables.entry[SMU10_WMTABLE].mc_addr,
    210 					&priv->smu_tables.entry[SMU10_WMTABLE].table);
    211 		amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_CLOCKTABLE].handle,
    212 					&priv->smu_tables.entry[SMU10_CLOCKTABLE].mc_addr,
    213 					&priv->smu_tables.entry[SMU10_CLOCKTABLE].table);
    214 		kfree(hwmgr->smu_backend);
    215 		hwmgr->smu_backend = NULL;
    216 	}
    217 
    218 	return 0;
    219 }
    220 
    221 static int smu10_start_smu(struct pp_hwmgr *hwmgr)
    222 {
    223 	struct amdgpu_device *adev = hwmgr->adev;
    224 
    225 	smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion);
    226 	hwmgr->smu_version = smu10_read_arg_from_smc(hwmgr);
    227 	adev->pm.fw_version = hwmgr->smu_version >> 8;
    228 
    229 	if (adev->rev_id < 0x8 && adev->pdev->device != 0x15d8 &&
    230 	    adev->pm.fw_version < 0x1e45)
    231 		adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
    232 
    233 	if (smu10_verify_smc_interface(hwmgr))
    234 		return -EINVAL;
    235 
    236 	return 0;
    237 }
    238 
    239 static int smu10_smu_init(struct pp_hwmgr *hwmgr)
    240 {
    241 	struct smu10_smumgr *priv;
    242 	int r;
    243 
    244 	priv = kzalloc(sizeof(struct smu10_smumgr), GFP_KERNEL);
    245 
    246 	if (!priv)
    247 		return -ENOMEM;
    248 
    249 	hwmgr->smu_backend = priv;
    250 
    251 	/* allocate space for watermarks table */
    252 	r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
    253 			sizeof(Watermarks_t),
    254 			PAGE_SIZE,
    255 			AMDGPU_GEM_DOMAIN_VRAM,
    256 			&priv->smu_tables.entry[SMU10_WMTABLE].handle,
    257 			&priv->smu_tables.entry[SMU10_WMTABLE].mc_addr,
    258 			&priv->smu_tables.entry[SMU10_WMTABLE].table);
    259 
    260 	if (r)
    261 		goto err0;
    262 
    263 	priv->smu_tables.entry[SMU10_WMTABLE].version = 0x01;
    264 	priv->smu_tables.entry[SMU10_WMTABLE].size = sizeof(Watermarks_t);
    265 	priv->smu_tables.entry[SMU10_WMTABLE].table_id = TABLE_WATERMARKS;
    266 
    267 	/* allocate space for watermarks table */
    268 	r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
    269 			sizeof(DpmClocks_t),
    270 			PAGE_SIZE,
    271 			AMDGPU_GEM_DOMAIN_VRAM,
    272 			&priv->smu_tables.entry[SMU10_CLOCKTABLE].handle,
    273 			&priv->smu_tables.entry[SMU10_CLOCKTABLE].mc_addr,
    274 			&priv->smu_tables.entry[SMU10_CLOCKTABLE].table);
    275 
    276 	if (r)
    277 		goto err1;
    278 
    279 	priv->smu_tables.entry[SMU10_CLOCKTABLE].version = 0x01;
    280 	priv->smu_tables.entry[SMU10_CLOCKTABLE].size = sizeof(DpmClocks_t);
    281 	priv->smu_tables.entry[SMU10_CLOCKTABLE].table_id = TABLE_DPMCLOCKS;
    282 
    283 	return 0;
    284 
    285 err1:
    286 	amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle,
    287 				&priv->smu_tables.entry[SMU10_WMTABLE].mc_addr,
    288 				&priv->smu_tables.entry[SMU10_WMTABLE].table);
    289 err0:
    290 	kfree(priv);
    291 	return -EINVAL;
    292 }
    293 
    294 static int smu10_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw)
    295 {
    296 	int ret;
    297 
    298 	if (rw)
    299 		ret = smu10_copy_table_from_smc(hwmgr, table, table_id);
    300 	else
    301 		ret = smu10_copy_table_to_smc(hwmgr, table, table_id);
    302 
    303 	return ret;
    304 }
    305 
    306 
    307 const struct pp_smumgr_func smu10_smu_funcs = {
    308 	.name = "smu10_smu",
    309 	.smu_init = &smu10_smu_init,
    310 	.smu_fini = &smu10_smu_fini,
    311 	.start_smu = &smu10_start_smu,
    312 	.request_smu_load_specific_fw = NULL,
    313 	.send_msg_to_smc = &smu10_send_msg_to_smc,
    314 	.send_msg_to_smc_with_parameter = &smu10_send_msg_to_smc_with_parameter,
    315 	.download_pptable_settings = NULL,
    316 	.upload_pptable_settings = NULL,
    317 	.get_argument = smu10_read_arg_from_smc,
    318 	.smc_table_manager = smu10_smc_table_manager,
    319 };
    320 
    321 
    322